HTML GUI (PB 4.10+)

Share your advanced PureBasic knowledge/code with the community.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

HTML GUI (PB 4.10+)

Post 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 ;)
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Interesting.

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

Thanks.
I may look like a mule, but I'm not a complete ass.
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post 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!
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

cool tip =)
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

Hi! I made this too a while ago. Let me find that old code and i'll post it here :).
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Fabulous, the possibilities get very cool indeed! Thanks for posting.
BERESHEIT
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post 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*)
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post 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
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post 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)
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post 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)
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post 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)
User avatar
fsw
Addict
Addict
Posts: 1603
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

Post 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.
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Post 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>
Pantcho!!
Enthusiast
Enthusiast
Posts: 538
Joined: Tue Feb 24, 2004 3:43 am
Location: Israel
Contact:

Post 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:
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post 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
Post Reply