Simple non-modal custom dialog box closing automatically
Posted: Mon Sep 21, 2015 6:59 pm
:: coded in PB 5.10, updated for PB 5.31 ::
:: 99% cross-platform (1% : see line 109) ::
It is quite easy to create a
custom non-modal dialog box that closes automatically
when the user clicks outside of it
The secret is to simply watch for #WM_LBUTTONUP and #WM_RBUTTONUP events occuring in the parent window.
Below is a full example. Wordy, so things are clearly demontrated
, but still short 
Lines 109-118 of the source code is where the concept is applied.
This may be of interest to newcomers to PureBasic or to Windows programming.
I hope someone will find it useful.
[UpDate]
Changes made (colour constants and 2 events) to render code cross-platform
:: 99% cross-platform (1% : see line 109) ::
It is quite easy to create a
custom non-modal dialog box that closes automatically
when the user clicks outside of it
The secret is to simply watch for #WM_LBUTTONUP and #WM_RBUTTONUP events occuring in the parent window.
Below is a full example. Wordy, so things are clearly demontrated


Lines 109-118 of the source code is where the concept is applied.
This may be of interest to newcomers to PureBasic or to Windows programming.
Code: Select all
;- ***** ***** ***** ***** ***** ***** *****
;- Blue - September 2013
;- --- --- --- --- --- --- --- --- --- ---
;- Child Window that closes
;- ... when click detected outside of it
;- ***** ***** ***** ***** ***** ***** *****
; the child (technically correct : secondary) window has its own event loop
EnableExplicit
;{ constants
;- constants
;- .... for convenience
#enAttente = " Just waiting..."
#text = #PB_Gadget_FrontColor
#back = #PB_Gadget_BackColor
#colourF = $F4F7F9 ; child window background
#colourB = $FFFFFF ; text box background
#colourT = $FF0000 ; text
#colourL = $0779F8 ; labels
Enumeration ; fenĂȘtres
#main_WINDOW
#child_WINDOW
EndEnumeration
;- .... for gadgets
Enumeration
#cmdOK
#cmdANNULER
#infoLABEL
#infoBOX
#F2_cmdOK
#F2_cmd2
#F2_cmd3
#F2_cadre1
#F2_cadre2
#F2_cadreLABEL
EndEnumeration
;}
;- --- --- --- --- --- --- --- --- --- --- --- ---
Procedure Child_Window()
Define winH = 120
Define winW = WindowWidth(#main_WINDOW) * 0.66
If 0 = OpenWindow(#child_WINDOW, 0, 0, winW, winH, "Busy Body",
#PB_Window_BorderLess | #PB_Window_WindowCentered,
windowID(#main_WINDOW))
SetGadgetText(#infoBox, " Child window could not be created")
ProcedureReturn
EndIf
SetWindowColor(#child_WINDOW,#colourF)
SetGadgetText(#infoBox, " Click anywhere outside the child window to close it. ")
;{ gadgets hiding here
;- .... gadgets
Define gadget, gX,gY, gW,gH
gX = 1
gY = 1
gW = winW - (gX * 2)
gH = winH - (gY * 2)
FrameGadget(#F2_cadre1, gX, gY, gW,gH, "", #PB_Frame_Flat)
gX + 8
gY + 8
gW = winW - (gX * 2)
gH = winH - (gY * 2)
FrameGadget(#F2_cadre2, gX,gY, gW,gH, "")
gadget = #F2_cadreLABEL
gX + 8
gW = 80
gH = 18
TextGadget(gadget, gX,gY, gW,gH, "Child window",#PB_Text_Center)
SetGadgetColor(gadget, #back,#colourF)
SetGadgetColor(gadget, #text, #colourL)
#dX = 12
gW = 100
gX + #dX
gY + 24
gH = 25
ButtonGadget(#F2_cmd2, gX,gY, gW,gH, "Something")
gX + gW + #dX
ButtonGadget(#F2_cmd3, gX,gY, gW,gH, "Something else")
gW = 70
gH = 32
gX = GadgetWidth(#F2_cadre2) - gW
gY = GadgetHeight(#F2_cadre2) - gH
ButtonGadget(#F2_cmdOK, gX,gY, gW,gH, "OK", #PB_Button_Default)
;}
;- .... event loop
Define event, gadget, window
Repeat
event = WaitWindowEvent()
window = EventWindow()
If window <> #child_WINDOW ;- ... [109] >> catching outside events
; events occuring OUTSIDE our dialog box are intercepted here,
; therefore preempting actions tied to gadgets in the main window
SetActiveWindow(#child_WINDOW)
Select event
;Case #PB_Event_CloseWindow : Break ; uncomment to have the main close button close the child window
Case #WM_LBUTTONUP, #WM_RBUTTONUP : Break ; mouse clicked : the loop's work is done. (Windows OS only)
;Case #PB_Event_LeftClick, #PB_Event_RightClick : Break ; cross-platform : comment above line (won't catch clicks on buttons)
EndSelect
;Debug "event = "+ Str(event) + " gadget = "+ Str(gadget)
Continue ; disregard everything
EndIf
Select event
Case #PB_Event_Gadget
gadget = EventGadget()
Select gadget
Case #F2_cmd2 : SetGadgetText(#infoBox,"The child window is busy doing something...")
Case #F2_cmd3 : SetGadgetText(#infoBox,"The child window is doing something else...")
Case #F2_cmdOK : Break
Default : SetGadgetText(#infoBox,"gadget #" + Str(gadget))
EndSelect
EndSelect
ForEver
CloseWindow(#child_WINDOW)
SetGadgetText(#infoBox, #enAttente)
EndProcedure ; _Child_Window_
Procedure Main_Window()
Define winH = 280
Define winW = 400
If 0 = OpenWindow(#main_WINDOW, 0, 0, winW, winH, "Main Window",
#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
End
EndIf
;- .... gadgets
Define gadget, gX,gY, gW,gH
#marge = 10
gX = #marge
gY = #marge
gW = 130
gH = 25
ButtonGadget(#cmdOK, gX,gY, gW,gH, "Open child window", #PB_Button_Default)
gH = 36
gW = 90
gX = winW - gW - #marge
gY = winH - gH - #marge
ButtonGadget(#cmdANNULER, gX,gY, gW,gH, "Quit")
gadget = #infoLABEL
gX = #marge
gW = 90
gH = 22
gY - gH
TextGadget(gadget, gX,gY, gW,gH, "INFORMATION :")
SetGadgetColor(gadget, #text,#colourL)
gadget = #infoBOX
gX + gW
gW = winW - gX - #marge
gH = 24
gY - 5
TextGadget(gadget, gX,gY, gW,gH, "",#PB_Text_Border)
SetGadgetColor(gadget, #back, #colourB)
SetGadgetColor(gadget, #text, #colourT)
EndProcedure ; _Main_Window_
;- --- --- --- --- --- --- --- --- --- --- --- ---
;- main event loop
Define event, evType, gadget
Define fenetre
Main_Window()
SetGadgetText(#infoBox,#enAttente)
Repeat
event = WaitWindowEvent()
Select event
Case #PB_Event_CloseWindow : Break
Case #PB_Event_Gadget :
gadget = EventGadget()
Select gadget
Case #cmdANNULER : Break
Case #cmdOK : Child_Window()
EndSelect
EndSelect
ForEver
End
[UpDate]
Changes made (colour constants and 2 events) to render code cross-platform