Code archives/Miscellaneous/Simple Win32 GUI
This code has been declared by its author to be Public Domain code.
Download source code
| This is a work in progress and I'll be updating it as I go. Basically, this is a GUI I'm writing that uses an OO interface. Downside? It's Win32 only. Given that, Mac/Linux zealots/users may want to turn away right now. Complaining about how it doesn't support your OS is a waste of time because I won't be including them. For the sake of example, here's a simple window with a button (the only two controls currently implemented): Local wnd:IWindow = New IWindow ' Window caption wnd.Caption = "Blah foo" ' Set the position wnd.Position( 32, 32 ) ' Set the size wnd.Resize( 512, 384 ) ' When called before the window is built ' it sets it such that the window is ' visible when built wnd.Show( ) Local btn:IButton = New IButton ' Rinse btn.Caption = "Close Window" ' And btn.Position( 12, 12 ) ' Repeat btn.Resize( 128, 24 ) ' Set the parent of the button ' This only works BEFORE the control is built, ' so if you call IControl.Build on the control ' then its parent is set in stone, end of story btn.SetParent( wnd ) wnd.Build( ) ' Main loop While Not AppTerminate( ) ' Wait for an event WaitEvent( ) ' Process the event Select CurrentEvent.Id ' These are all fairly obvious event names Case WindowClosed Exit Case ButtonPressed If CurrentEvent.source = btn Then Exit EndIf Default End Select Wend ' Free the window (works for all controls) wnd.Dispose( ) |
Strict
Private
Global windows:TList = New TList
Global instance% = GetModuleHandleA(Null)
Global iwndclass$ = "IndigoWNDCLASS"
CreateWndClass( iwndclass, CS_VREDRAW|CS_HREDRAW, IWndProc )
Function GetControl:IControl( hwnd:Int )
For Local i:IControl = EachIn windows
If i.hwnd = hwnd Then Return i
Next
Return Null
End Function
Function IWndProc:Int( hwnd%, msg%, wparam%, lparam% )
Local ctl:IControl = GetControl( hwnd )
If ctl Then Return ctl.HandleMessage( msg, wparam, lparam )
Return DefWindowProcW( hwnd, msg, wparam, lparam )
End Function
Function CreateWndClass:TBank( name$, style%, wndProc@ Ptr )
Local c:TBank = TBank.Create( 40+name.Length*2+2 )
memset_(c.Buf( ), 0, 40)
c.PokeInt( 0, style )
c.PokeInt( 4, Int( wndProc ) )
c.PokeInt( 16, instance )
c.PokeInt( 20, LoadIconA( 0, Byte Ptr(32512) ) )
c.PokeInt( 24, LoadCursorA( 0, Byte Ptr(IDC_ARROW) ) )
c.PokeInt( 28, 16 )
Local mem@ Ptr = name.ToWString( )
MemCopy( c.Buf( )+40, mem, name.Length*2+2 )
MemFree( mem )
c.PokeInt( 36, Int( c.Buf( )+40 ) )
RegisterClassW( c.Buf( ) )
Return c
End Function
Public
' Generic events
Const ControlEnumStart =0
Const ControlMoved =ControlEnumStart+1
Const ControlResized =ControlMoved+1
Const ControlAction =ControlResized+1
Const ControlHidden =ControlAction+1
Const ControlShown =ControlHidden+1
Const ControlFocusGained =ControlShown+1
Const ControlFocusLost =ControlFocusGained+1
Const ControlEnumTop =32
Type IControl
Method New( )
_wndLink = windows.AddLast( Self )
End Method
Field child:TList = New TList
Field parent:IControl
Field hwnd%
Field x%, y%, w%, h%
Field link:TLink
Field _wndLink:TLink
' Internal function that really wouldn't be called from something like the main loop
Method HandleMessage%( msg%, wparam%, lparam% )
Select msg
Case WM_CREATE
For Local i:IControl = EachIn child
i.Build( )
Next
Return 0
Case WM_DESTROY
Dispose( )
Return 0
Case WM_COMMAND
If lparam <> 0 And lparam <> hwnd Then
Local ctl:IControl = GetControl( lparam )
If ctl Then Return ctl.HandleMessage( msg, wparam, lparam )
EndIf
End Select
Return DefWindowProcW( hwnd, msg, wparam, lparam )
End Method
' Abstract method to 'compile' the control with its initial values
Method Build( ) Abstract
' Frees the control and all children
Method Dispose( )
If Not hwnd Then Return
Hide( )
If child Then
For Local i:IControl = EachIn child
i.Dispose( )
Next
child.Clear( )
child = Null
EndIf
DestroyWindow( hwnd )
If link Then link.Remove( ) link = Null
If _wndLink Then _wndLink.Remove( ) _wndLink = Null
hwnd = 0
parent = Null
x = 0 y = 0 w = 0 h = 0
End Method
' Hides the control
Method Hide( )
If Not hwnd Then Return
ShowWindow( hwnd, SW_HIDE )
End Method
' Shows the control
Method Show( )
If Not hwnd Then Return
ShowWindow( hwnd, SW_SHOW )
End Method
' Resizes the control
Method Resize( rw%, rh% )
w = rw
h = rh
If Not hwnd Then Return
MoveWindow( hwnd, x, y, w, h, True )
End Method
' Positions the control
Method Position( px%, py% )
x = px
y = py
If Not hwnd Then Return
MoveWindow( hwnd, x, y, w, h, True )
End Method
' Sets the control's parent -- this is only useable before calling Build( )
Method SetParent( p:IControl )
If hwnd Then Return
If p = parent Then Return
If link Then link.Remove( ) link = Null
parent = p
If parent Then link = parent.child.AddLast( Self )
End Method
' Forces the control to be redrawn
' You may, optionally, specify a region to redraw with ax, ay, aw, & ah
Method Paint( ax%=-1,ay%=-1,aw%=-1,ah%=-1 )
If Not hwnd Then Return
If ax = -1 Or ay = -1 Or aw = -1 Or ah = -1 Then
InvalidateRect( hwnd, Null, 0 )
Else
Local rect:Int[] = [ax,ay,aw,ah]
InvalidateRect( hwnd, rect, 0 )
EndIf
End Method
End Type
' Window events
Const WindowClosed =ControlEnumTop+1
Const WindowMaximized =WindowClosed+1
Const WindowMinimized =WindowMaximized+1
Const WindowFocusGained =ControlFocusGained
Const WindowFocusLost =ControlFocusLost
Const WindowMoved =ControlMoved
Const WindowResized =ControlResized
Const WindowEnumTop =ControlEnumTop+32
Type IWindow Extends IControl
' Flags
' Misc.
Const Resizable%=%1
Const Titlebar%=%10
Const SystemMenu%=%100
Const ToolWindow%=%1000
Const Visible%=%10000
' Buttons
Const MinimizeButton%=%100000
Const MaximizeButton%=%1000000
Field caption$
Field flags% = Resizable|Titlebar|SystemMenu|MinimizeButton|MaximizeButton
Method Show( )
If hwnd Then Super.Show( ) Return
flags :| Visible
End Method
Method Hide( )
If hwnd Then Super.Hide( ) Return
flags = flags & (Not Visible)
End Method
Method HandleMessage%( msg%, wparam%, lparam% )
Select msg
Case WM_CLOSE
EmitEvent( CreateEvent( WindowClosed, Self ) )
Default
Return Super.HandleMessage( msg, wparam, lparam )
End Select
Return 0
End Method
Method Build( )
If Not hwnd Then
Local ph%=0
Local es% = WS_EX_CONTROLPARENT
Local st% = WS_CLIPCHILDREN
If parent Then
ph = parent.hwnd
st :| WS_CHILD
EndIf
If flags&Resizable Then st :| WS_SIZEBOX
If flags&Titlebar Then st :| WS_CAPTION
If flags&ToolWindow Then
es :| WS_EX_TOOLWINDOW
Else
st :| WS_SYSMENU|WS_CAPTION
EndIf
If flags&MinimizeButton Then st :| WS_MINIMIZEBOX
If flags&MaximizeButton Then st :| WS_MAXIMIZEBOX
If flags&Visible Then st :| WS_VISIBLE
hwnd = CreateWindowExW( es, iwndclass, caption, st, x, y, w, h, ph, 0, instance, Null )
EndIf
If Not hwnd Then Return
For Local i:IControl = EachIn child
i.Build( )
Next
End Method
End Type
Const ButtonPressed =ControlAction
Const ButtonEnumTop =WindowEnumTop+32
Type IButton Extends IControl
Field caption$
Method HandleMessage( msg%, wparam%, lparam% )
Select msg
Case WM_COMMAND
EmitEvent( CreateEvent( ButtonPressed, Self ) )
Default
Return Super.HandleMessage( msg, wparam, lparam )
End Select
Return 0
End Method
Method Build( )
If hwnd Then Return
If Not parent Then Return
hwnd = CreateWindowExW( 0, "Button", caption, WS_CHILD|WS_TABSTOP|BS_PUSHBUTTON, x, y, w, h, parent.hwnd, 0, instance, Null )
Show( )
End Method
End Type |