Page 1 of 2

HTML GUI (PB 4.10+)

Posted: Wed Jun 20, 2007 1:09 pm
by Rescator
This is a rather rough example but interesting anyway.
Quickly explained it acts almost like a About window/box but uses the webgadget,
the window can be closed normally or by clicking a inline close link.

Hopefully this gives you an idea on how to make a HTML GUI.
If your program is fully HTML GUI driven it would be best to have the window loop in the main program loop instead, this example was just a test.
This example also passes the html directly, it may be better to use local html gui files for GUI's with larger html "pages".

I also want to thank the PB Team for adding the callback as that is the key to making a HTML GUI as it allows custom things like "cmd:close"

Code: Select all

EnableExplicit

Procedure.l AboutHtml_NavigationCallback(gadget,url$)
 Protected window.l
 If url$="cmd:close"
  window=GetGadgetData(gadget)
  If IsWindow(window)
   CloseWindow(window)
  EndIf
  ProcedureReturn #False
 EndIf
 ProcedureReturn #True
EndProcedure

Procedure.l AboutHtml(title$,msg$,width.l=400,height.l=300,parent.l=#Null)
 Protected window.l,flags.l,web.l,button.l,result.l=#False,parentid.l=#Null,event.l
 flags=#PB_Window_SystemMenu|#PB_Window_TitleBar|#PB_Window_Invisible
 If parent
  flags|#PB_Window_WindowCentered
 Else
  flags|#PB_Window_ScreenCentered
 EndIf
 If parent
  parentid=WindowID(parent)
 EndIf
 window=OpenWindow(#PB_Any,#PB_Ignore,#PB_Ignore,width,height,title$,flags,parentid)
 If window
  If CreateGadgetList(WindowID(window))
   web=WebGadget(#PB_Any,0,0,WindowWidth(window),WindowHeight(window),"")
   If web
    SetGadgetItemText(web,#PB_Web_HtmlCode,msg$)
    SetGadgetData(web,window)
    SetGadgetAttribute(web,#PB_Web_NavigationCallback,@AboutHtml_NavigationCallback())
    HideWindow(window,#False)
    Repeat
     If IsWindow(window) ;We must check as it may have been closed in the callback
      event=WaitWindowEvent()
     Else
      event=#PB_Event_CloseWindow ;If window is gone we must quit the loop
     EndIf
    Until event=#PB_Event_CloseWindow
    result=#True
   EndIf
  EndIf
  If IsWindow(window)
   CloseWindow(window)
  EndIf
 EndIf
 ProcedureReturn result
EndProcedure

;A simple example
AboutHtml("Test","<a href="+#DQUOTE$+"cmd:close"+#DQUOTE$+">Close Window</a>")
PS! If others have alternative or improved examples please post those in this thread so it's easier for beginners to find them using the forum search ;)

Posted: Wed Jun 20, 2007 1:18 pm
by srod
Interesting.

I've never used a web gadget for much of anything really, but that's pretty cool and very instructive.

Thanks.

Posted: Wed Jun 20, 2007 1:18 pm
by Num3
Eheheh
I'm working on this too, using javascript and forms with data...

I'll clean up the code later and post a form example!

Posted: Wed Jun 20, 2007 1:19 pm
by dracflamloc
cool tip =)

Posted: Wed Jun 20, 2007 1:45 pm
by Inf0Byt3
Hi! I made this too a while ago. Let me find that old code and i'll post it here :).

Posted: Wed Jun 20, 2007 1:54 pm
by netmaestro
Fabulous, the possibilities get very cool indeed! Thanks for posting.

Posted: Wed Jun 20, 2007 2:09 pm
by Rescator
Looking forward to that Num3, as it seems the navigationcallback do not catch any GET forms? (intentional or a slip by the PB team? *looks at freak*)

Posted: Wed Jun 20, 2007 2:26 pm
by Inf0Byt3
Take a look here. Remember i made this code way back so it could be unusable.

Screenshot:
Image

Download here:
File:1->HTMLMenu.rar
Image

Posted: Wed Jun 20, 2007 2:36 pm
by Rescator
My apologies to the PB Team, GET forms work. (I've yet to test POST forms but I doubt they work)

I modified my previous example to display the form/GET query in a messagebox. Using normal PB string functions it should be easy to parse this.
HTML based GUI programs is now definably a possibility, and assuming that Linux and Mac will behave the same way, cross platform HTML GUI apps may get popular indeed ;)

Code: Select all

EnableExplicit

Procedure.l AboutHtml_NavigationCallback(gadget,url$)
 Protected window.l
 Debug url$
 If url$="cmd:close"
  window=GetGadgetData(gadget)
  If IsWindow(window)
   CloseWindow(window)
  EndIf
  ProcedureReturn #False
 ElseIf Left(url$,8)="cmd:data"
  MessageRequester("GET",Right(url$,Len(url$)-8))
  ProcedureReturn #False
 EndIf
 ProcedureReturn #True
EndProcedure

Procedure.l AboutHtml(title$,msg$,width.l=400,height.l=300,parent.l=#Null)
 Protected window.l,flags.l,web.l,button.l,result.l=#False,parentid.l=#Null,event.l
 flags=#PB_Window_SystemMenu|#PB_Window_TitleBar|#PB_Window_Invisible
 If parent
  flags|#PB_Window_WindowCentered
 Else
  flags|#PB_Window_ScreenCentered
 EndIf
 If parent
  parentid=WindowID(parent)
 EndIf
 window=OpenWindow(#PB_Any,#PB_Ignore,#PB_Ignore,width,height,title$,flags,parentid)
 If window
  If CreateGadgetList(WindowID(window))
   web=WebGadget(#PB_Any,0,0,WindowWidth(window),WindowHeight(window),"")
   If web
    SetGadgetItemText(web,#PB_Web_HtmlCode,msg$)
    SetGadgetData(web,window)
    SetGadgetAttribute(web,#PB_Web_NavigationCallback,@AboutHtml_NavigationCallback())
    HideWindow(window,#False)
    SetActiveGadget(web)
    Repeat
     If IsWindow(window) ;We must check as it may have been closed in the callback
      event=WaitWindowEvent()
     Else
      event=#PB_Event_CloseWindow ;If window is gone we must quit the loop
     EndIf
    Until event=#PB_Event_CloseWindow
    result=#True
   EndIf
  EndIf
  If IsWindow(window)
   CloseWindow(window)
  EndIf
 EndIf
 ProcedureReturn result
EndProcedure

AboutHtml("Test","<html><body><a href="+#DQUOTE$+"cmd:close"+#DQUOTE$+">Close Window</a> <form action="+#DQUOTE$+"cmd:data"+#DQUOTE$+" method="+#DQUOTE$+"get"+#DQUOTE$+"><textarea name="+#DQUOTE$+"message"+#DQUOTE$+" rows="+#DQUOTE$+"17"+#DQUOTE$+" cols="+#DQUOTE$+"77"+#DQUOTE$+" title="+#DQUOTE$+"Message"+#DQUOTE$+"></textarea><input class="+#DQUOTE$+"button"+#DQUOTE$+" type="+#DQUOTE$+"submit"+#DQUOTE$+" name="+#DQUOTE$+"submit"+#DQUOTE$+" value="+#DQUOTE$+"Submit"+#DQUOTE$+"></form></body></html>",800,600)

Posted: Wed Jun 20, 2007 2:49 pm
by Num3
Beat me to it rescator ;) nice job

Here's a slighty tweaker version with URL decode incorporated :D

Code: Select all

Procedure Hex2Dec(HexNumber.s)
  Structure OneByte
    a.b
  EndStructure
  *t.OneByte = @HexNumber
  result.l = 0
  While *t\a <> 0
    If *t\a >= '0' And *t\a <= '9'
      result = (result << 4) + (*t\a - 48)
    ElseIf *t\a >= 'A' And *t\a <= 'F'
      result = (result << 4) + (*t\a - 55)
    ElseIf *t\a >= 'a' And *t\a <= 'f'
      result = (result << 4) + (*t\a - 87)
    Else
      result = (result << 4) + (*t\a - 55)
    EndIf
    *t + 1
  Wend
  ProcedureReturn result
EndProcedure

Procedure.s URL_Decode(string.s)
  out.s=""
  For a=1 To Len(string.s)
    c$=Mid(string.s,a,1)
    If c$="%"
      k$=Mid(string.s,a+1,2)
      out.s+ Chr(Hex2Dec(k$))
      a+2
    ElseIf c$="+"
      out.s+" "
    Else
      out.s+c$
    EndIf
  Next
  ProcedureReturn out
EndProcedure


Procedure.l AboutHtml_NavigationCallback(Gadget,Url$)
  Protected window.l
  Debug Url$
  If Url$="cmd:close"
    window=GetGadgetData(Gadget)
    If IsWindow(window)
      CloseWindow(window)
      End
    EndIf
    ProcedureReturn #False
  ElseIf Left(Url$,8)="cmd:data"
    dat$=StringField(Url$,1,"&")
    MessageRequester("GET",URL_Decode(dat$))
    ProcedureReturn #False
  EndIf
  ProcedureReturn #True
EndProcedure

Procedure.l AboutHtml(title$,msg$,width.l=400,height.l=300,parent.l=#Null)
  Protected window.l,flags.l,web.l,button.l,result.l=#False,parentid.l=#Null,Event.l
  flags=#PB_Window_SystemMenu|#PB_Window_TitleBar|#PB_Window_Invisible
  If parent
    flags|#PB_Window_WindowCentered
  Else
    flags|#PB_Window_ScreenCentered
  EndIf
  If parent
    parentid=WindowID(parent)
  EndIf
  window=OpenWindow(#PB_Any,#PB_Ignore,#PB_Ignore,width,height,title$,flags,parentid)
  If window
    If CreateGadgetList(WindowID(window))
      web=WebGadget(#PB_Any,0,0,WindowWidth(window),WindowHeight(window),"")
      If web
        SetGadgetItemText(web,#PB_Web_HtmlCode,msg$)
        SetGadgetData(web,window)
        SetGadgetAttribute(web,#PB_Web_NavigationCallback,@AboutHtml_NavigationCallback())
        HideWindow(window,#False)
        SetActiveGadget(web)
        Repeat
          If IsWindow(window) ;We must check as it may have been closed in the callback
            Event=WaitWindowEvent()
          Else
            Event=#PB_Event_CloseWindow ;If window is gone we must quit the loop
          EndIf
        Until Event=#PB_Event_CloseWindow
        result=#True
      EndIf
    EndIf
    If IsWindow(window)
      CloseWindow(window)
    EndIf
  EndIf
  ProcedureReturn result
EndProcedure

AboutHtml("Test","<html><body><a href="+#DQUOTE$+"cmd:close"+#DQUOTE$+">Close Window</a> <form action="+#DQUOTE$+"cmd:data"+#DQUOTE$+" method="+#DQUOTE$+"get"+#DQUOTE$+"><textarea name="+#DQUOTE$+"message"+#DQUOTE$+" rows="+#DQUOTE$+"10"+#DQUOTE$+" cols="+#DQUOTE$+"40"+#DQUOTE$+" title="+#DQUOTE$+"Message"+#DQUOTE$+"></textarea><input class="+#DQUOTE$+"button"+#DQUOTE$+" type="+#DQUOTE$+"submit"+#DQUOTE$+" name="+#DQUOTE$+"submit"+#DQUOTE$+" value="+#DQUOTE$+"Submit"+#DQUOTE$+"></form></body></html>",800,600)

Posted: Wed Jun 20, 2007 6:10 pm
by Rescator
Nice, ironically I was fiddling away with my own code and did a urldecode as well, but I went a step further to something more practical.
(I love PHP so I took inspiration from that)

This example will take all form fields and put them into a associative list.
Allowing easy ForEach handling of the form fields.

I'm not entirely happy with the url decode and var/arg parsing,
it can probably be tightened up and optimized a bit.
And I probably forgot to check a few things so this GET handling code is not adviced for server use as it currently is.
But for HTML GUI apps it should be ok as those surf locally only so...

PS! This code should work ok with both Unicode and ANSI.

EDIT: forgot a ClearList()

Code: Select all

EnableExplicit

Structure _Form_List_Structure
 var$
 arg$
EndStructure
Global NewList FormResult._Form_List_Structure()

Procedure.l UrlDecodeToFormResultList(text$)
 Protected result$,len.l,*pos.character,a.l,b.l,v.l
 ClearList(FormResult())
 len=@text$+(Len(text$)*SizeOf(character))
 *pos=@text$
 v=#False
 While *pos<len
  If *pos\c=43 ;+
   result$+" "
  ElseIf (*pos\c=63) Or (*pos\c=38) ;? or &
   If v=#True
    FormResult()\arg$=result$
    result$=""
   EndIf
   AddElement(FormResult())
   v=#False
  ElseIf *pos\c=61 ;=
   If v=#False
    FormResult()\var$=result$
    result$=""
   EndIf
   v=#True
  ElseIf *pos\c=37 ;%
   *pos+SizeOf(character)
   If *pos\c<58 And *pos\c>47 ;0-9
    a=*pos\c-48
   ElseIf *pos\c<71 And *pos\c>64 ;A-F
    a=*pos\c-55
   ElseIf *pos\c<103 And *pos\c>96 ;a-f
    a=*pos\c-87
   Else
    a=0
   EndIf
   *pos+SizeOf(character)
   If *pos\c<58 And *pos\c>47 ;0-9
    b=*pos\c-48
   ElseIf *pos\c<71 And *pos\c>64 ;A-F
    b=*pos\c-55
   ElseIf *pos\c<103 And *pos\c>96 ;a-f
    b=*pos\c-87
   Else
    b=0
   EndIf
   result$+Chr((a<<4)+b)
  Else
   result$+Chr(*pos\c)
  EndIf
  *pos+SizeOf(character)
 Wend
 If Len(result$)>0
  If v=#True
   FormResult()\arg$=result$
  Else
   AddElement(FormResult())
   FormResult()\var$=result$
  EndIf
 EndIf
 a=CountList(FormResult())
 ProcedureReturn a
EndProcedure

Procedure.l AboutHtml_NavigationCallback(gadget,url$)
 Protected window.l,get$,msg$
 Debug url$
 If url$="cmd:close"
  window=GetGadgetData(gadget)
  If IsWindow(window)
   CloseWindow(window)
  EndIf
  ProcedureReturn #False
 ElseIf Left(url$,8)="cmd:data"
  get$=Right(url$,Len(url$)-8)
  If UrlDecodeToFormResultList(get$)
   ForEach FormResult()
    msg$+FormResult()\var$+"="+FormResult()\arg$+#LF$
   Next
   MessageRequester("GET",msg$)
  EndIf
  ProcedureReturn #False
 EndIf
 ProcedureReturn #True
EndProcedure

Procedure.l AboutHtml(title$,msg$,width.l=400,height.l=300,parent.l=#Null)
 Protected window.l,flags.l,web.l,button.l,result.l=#False,parentid.l=#Null,event.l
 flags=#PB_Window_SystemMenu|#PB_Window_TitleBar|#PB_Window_Invisible
 If parent
  flags|#PB_Window_WindowCentered
 Else
  flags|#PB_Window_ScreenCentered
 EndIf
 If parent
  parentid=WindowID(parent)
 EndIf
 window=OpenWindow(#PB_Any,#PB_Ignore,#PB_Ignore,width,height,title$,flags,parentid)
 If window
  If CreateGadgetList(WindowID(window))
   web=WebGadget(#PB_Any,0,0,WindowWidth(window),WindowHeight(window),"")
   If web
    SetGadgetItemText(web,#PB_Web_HtmlCode,msg$)
    SetGadgetData(web,window)
    SetGadgetAttribute(web,#PB_Web_NavigationCallback,@AboutHtml_NavigationCallback())
    HideWindow(window,#False)
    SetActiveGadget(web)
    Repeat
     If IsWindow(window) ;We must check as it may have been closed in the callback
      event=WaitWindowEvent()
     Else
      event=#PB_Event_CloseWindow ;If window is gone we must quit the loop
     EndIf
    Until event=#PB_Event_CloseWindow
    result=#True
   EndIf
  EndIf
  If IsWindow(window)
   CloseWindow(window)
  EndIf
 EndIf
 ProcedureReturn result
EndProcedure

AboutHtml("Test","<html><body><a href="+#DQUOTE$+"cmd:close"+#DQUOTE$+">Close Window</a> <form action="+#DQUOTE$+"cmd:data"+#DQUOTE$+" method="+#DQUOTE$+"get"+#DQUOTE$+" enctype="+#DQUOTE$+"application/x-www-form-urlencoded;charset=utf-8"+#DQUOTE$+"><textarea name="+#DQUOTE$+"message"+#DQUOTE$+" rows="+#DQUOTE$+"17"+#DQUOTE$+" cols="+#DQUOTE$+"77"+#DQUOTE$+" title="+#DQUOTE$+"Message"+#DQUOTE$+"></textarea><input class="+#DQUOTE$+"button"+#DQUOTE$+" type="+#DQUOTE$+"submit"+#DQUOTE$+" name="+#DQUOTE$+"submit"+#DQUOTE$+" value="+#DQUOTE$+"Submit"+#DQUOTE$+"></form></body></html>",800,600)

Posted: Thu Jun 21, 2007 6:15 am
by fsw
Can't test the code right now, just wanted to mention that long time ago I played with something similar. IIRC the name of the HTML GUI was HARMONIA.

Posted: Thu Jun 21, 2007 9:26 pm
by utopiomania
The possibility to do html based GUI's in PB has been talked about here for ages, and if 4.1 now
can trap a navigate event, get the url and cancel, its great news indeed :)

A bit off topic, but if you save the code below as a for example 'program.hta' to your
desktop and dblclick it, it will run as an app in the MS html application host (mshta.exe).

Means that you can develop apps using only Notepad and Windows (with IE >5.5) :)


Code: Select all

<head>
<title></title>
<meta http-equiv = "msThemeCompatible" content="yes">

<! html application: >
<hta:application
	applicationname = ""
	icon = "notepad.exe"
	border = "thin"
	scroll = "no"
	contextMenu = "no"
	innerBorder = "no"
	singleinstance = "yes"
	windowstate = "normal"
	navigable = "yes"
	selection = "no"
	version = ""
>

<! application functions: >
<script language = "vbscript">

sub window_onLoad
	window.resizeTo 600, 400
	window.moveTo 200, 100
end sub

sub button1_onClick
	self.close
end sub

sub button1_onMouseOver
	button1.value = "<< Prev"
	button1.style.cursor = "hand"
end sub

sub button1_onMouseOut
	button1.value = "Next >>"
end sub

sub button1_onFocus
	button1.value = "<< Prev"	
end sub

</script>
</head>

<! application user interface: >
<body style = "filter:progid:dxImageTransform.microsoft.gradient
	(gradientType = 0, startColorStr = '#ffffff', endColorStr = '#4080ff')">

<span style = "position:absolute; left:20; top:55">
	Type some important letters here:</span>

<input id = "text1" type = "text" title = "yes, type here"
	style = "position:absolute; left:20; top:80; width:555; height:22">

<hr style = "position:absolute; left:20; top:310; width:560; height:1; color:#c0c0c0">

<input id = "button1" type = "button" value = "Next >>"
	style = "position:absolute; left:480; top:330; width:100; height:25; cursor:hand">
</body>

Posted: Thu Jun 21, 2007 9:49 pm
by Pantcho!!
Ok this is weird.

I run the code i have a window with webgadget and a title and thats it.
And yes running PB 4.10 installed over a PB 4.02 directory.

:?: :roll:

Posted: Thu Jun 21, 2007 10:26 pm
by rsts
Pantcho!! wrote:Ok this is weird.

I run the code i have a window with webgadget and a title and thats it.
And yes running PB 4.10 installed over a PB 4.02 directory.

:?: :roll:
Me too. Thought maybe that was it :)

cheers