Using Purebasic 32 bit Version 5.22 on Windows 7 Home Premium 64 bit version.
Some further information following on from Kukulkan's posting about Popup menus on Image
gadgets in the Mac OS forum on this site.
I've been using Purebasic for over 8 years now and have used Popup menus many times, usually
invoked with a right mouse button as a context sensitive menu and I have never noticed any
problems until a couple of weeks ago when I noticed that I could not reliably invoke the
Popup menu in one of my programs by using a right mouse button in the bottom area of the
window. The window uses a scroll bar gadget with an image gadget contained and as the main
window is moved down the screen towards the Task Bar there is a growing dead zone of perhaps
20-30 pixels within the scroll & image gadget where the Popup menu can no longer be invoked,
you can see the menu very quickly appear and then disappear.
I have overcome the above behavior by using the WIN32 function TrackPopupMenuEx to call the
Popup menu instead of using the Purebasic DisplayPopupMenu function and this works very well
with no dead zones regardless of where the main window is positioned.
I catch the mouse button events in the procedure associated with the window of interest, in
the above case the scroll bar gadget which I subclass and then wait for a #WM_PARENTNOTIFY
event from the Image gadget.
If you simply use a callback procedure to the main window to catch the mouse button then
there are some strange things happening similar to what Kukulkan has experienced. The
behaviours are as follows:
1. When you invoke a Popup menu using either the native Purebasic DisplayPopupMenu function
or the Win32 TrackPopupMenuEx function it takes three left button mouse clicks to close the
Popup menu.
2. Even though the mouse left button is being used the message sent is for the right button?
I have attached a simple program example that has a scroll bar gadget with an image gadget
contained within.
I have a call back procedure for the main window and I have sub classed the Scroll Bar and
Image gadgets to demonstrate the messages received.
There are two option/radio buttons that will allow the menu to be invoked either from the
main window callback procedure or the Scroll Bar procedure using the right mouse button.
The other two option/radio buttons allow the selection of either the native Purebasic
DisplayPopupMenu function or the Win32 TrackPopupMenuEx function to invoke the Popup menu.
Code: Select all
;{;Window Constants
#TPM_HORIZONTAL = $0000
#TPM_VERTICAL = $0040
#TPM_NONOTIFY = $0080
#TPM_RETURNCMD = $0100
#TPM_NOANIMATION = $4000
#TPM_BOTTOMALIGN = $0020
;}
Enumeration
#Window_0
EndEnumeration
Enumeration ;MENUS
#Main_Window_PopUpMenu_1
#Main_Window_PopUpMenu1_Item1
#Main_Window_PopUpMenu1_Item2
#Main_Window_PopUpMenu1_Item3
#Main_Window_PopUpMenu1_Item4
#Main_Window_PopUpMenu1_Item5
#Main_Window_PopUpMenu1_Item6
;EndEnumeration
;Enumeration
#Button_0
#Button_1
#Main_ScrollArea_0
#Main_Image_0
#Option_0
#Option_1
#Option_2
#Option_3
EndEnumeration
Global hWndScrollGadetProc.l
Global hWndImagelGadetProc.l
Procedure WinCallback(hwnd.l, uMsg.l, wParam.l, lParam.l)
result = #PB_ProcessPureBasicEvents
Select uMsg
Case #WM_LBUTTONDOWN
Debug "#WM_LBUTTONDOWN in Main Window Callback"
Case #WM_RBUTTONDOWN
Debug "#WM_RBUTTONDOWN in Main Window Callback"
Case #WM_COMMAND
;Debug " #WM_COMMAND "
Case #WM_PARENTNOTIFY
;Debug "#WM_PARENTNOTIFY"
If wParam & $0000FFFF = #WM_LBUTTONDOWN
x.l = lParam & $0000FFFF
y.l = (lParam >> 16) & $0000FFFF
Debug "Left Button captured in PARENTNOTIFY Main Window Proc"
Debug "x = "+Str(x)
Debug "y = "+Str(y)
EndIf
If wParam & $0000FFFF = #WM_RBUTTONDOWN ;edit the label
Debug "Right Button captured in PARENTNOTIFY Main Window Proc"
a.l = lParam & $0000FFFF
b.l = (lParam >> 16) & $0000FFFF
Debug "a = "+Str(a)
Debug "b = "+Str(b)
If GetGadgetState(#Option_0) ;Use Main Window Callback
Debug "Using Main Window Callback"
If GetGadgetState(#Option_2) ; Use PB or Win32
DisplayPopupMenu(#Main_Window_PopUpMenu_1, WindowID(#Window_0))
Debug "Using PB DisplayPopupMenu"
Else
TPParam.TPMPARAMS
TPParam\cbSize = SizeOf(TPMPARAMS)
TPParam\rcExclude\bottom = 0
TPParam\rcExclude\left = 0
TPParam\rcExclude\right = 0
TPParam\rcExclude\top = 0
Mask.l = #TPM_LEFTBUTTON | #TPM_LEFTALIGN |#TPM_HORIZONTAL
TrackPopupMenuEx_(MenuID(#Main_Window_PopUpMenu_1),Mask,a,b,WindowID(#Window_0),TPParam)
Debug "Using Win32 TrackPopupMenuEx"
EndIf
SetGadgetState(#Main_Image_0, ImageID(100))
EndIf
EndIf
EndSelect
ProcedureReturn result
EndProcedure
Procedure ScrollGadetProc(hWnd.l,uMsg.l,wParam.l,lParam.l)
Select uMsg
Case #WM_LBUTTONDOWN
Debug "#WM_LBUTTONDOWN in Scroll Gadget Proc"
Case #WM_RBUTTONDOWN
Debug "#WM_RBUTTONDOWN in Scroll Gadget Proc"
Case #WM_PARENTNOTIFY
;Debug "#WM_PARENTNOTIFY"
If wParam & $0000FFFF = #WM_LBUTTONDOWN ;select the label
Debug "Left Button captured in PARENTNOTIFY Scroll Window Proc"
x.l = lPAram & $0000FFFF
y.l = (lPAram >> 16) & $0000FFFF
EndIf
If wParam & $0000FFFF = #WM_RBUTTONDOWN ;edit the label
Debug "Right Button captured in PARENTNOTIFY Scroll Window Proc"
a.l = lPAram & $0000FFFF
b.l = (lPAram >> 16) & $0000FFFF
If GetGadgetState(#Option_1) ;Use Scroll Proc
Debug "Scroll Proc 1"
If GetGadgetState(#Option_2) ; Use PB DisplayPopupMenu
DisplayPopupMenu(#Main_Window_PopUpMenu_1, WindowID(#Window_0))
Debug "Using PB DisplayPopupMenu"
Else
;Use WIN32 TrackPopupMenuEx
TPParam.TPMPARAMS
TPParam\cbSize = SizeOf(TPMPARAMS)
TPParam\rcExclude\bottom = 0
TPParam\rcExclude\left = 0
TPParam\rcExclude\right = 0
TPParam\rcExclude\top = 0
Mask.l = #TPM_LEFTBUTTON | #TPM_LEFTALIGN |#TPM_HORIZONTAL
TrackPopupMenuEx_(MenuID(#Main_Window_PopUpMenu_1),Mask,a,b,WindowID(#Window_0),TPParam)
Debug "Using Win32 TrackPopupMenuEx"
EndIf
EndIf
SetGadgetState(#Main_Image_0, ImageID(100))
EndIf
EndSelect
ProcedureReturn CallWindowProc_(hWndScrollGadetProc,hWnd.l,uMsg.l,wParam.l,lParam.l)
EndProcedure
Procedure ImageGadgetProc(hWnd.l,uMsg.l,wParam.l,lParam.l)
Select uMsg
Case #WM_LBUTTONDOWN
Debug "#WM_LBUTTONDOWN in Image Gadget Proc"
Case #WM_RBUTTONDOWN
Debug "#WM_RBUTTONDOWN in Image Gadget Proc"
EndSelect
ProcedureReturn CallWindowProc_(hWndImagelGadetProc,hWnd.l,uMsg.l,wParam.l,lParam.l)
EndProcedure
Procedure Open_Window_0()
If OpenWindow(#Window_0, 100, 10, 700, 700, "Popu Behaviour Demonstration", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_TitleBar )
SetWindowCallback(@WinCallback());,#Window_0)
ButtonGadget(#Button_0, 480, 640, 70, 30, "")
OptionGadget(#Option_0, 20, 610, 250, 20, "Invoke Menu from Main Window Callback")
OptionGadget(#Option_1, 20, 640, 250, 20, "Invoke Menu from Scroll Gadget Proc")
SetGadgetState(#Option_0, 1)
ButtonGadget(#Button_1, 570, 640, 70, 30, "")
OptionGadget(#Option_2, 280, 610, 150, 20, "Use PB OpenPopup")
OptionGadget(#Option_3, 280, 640, 180, 20, "Use Win32 TrackPopupMenuEx")
SetGadgetState(#Option_2, 1)
If CreatePopupMenu(#Main_Window_PopUpMenu_1)
MenuItem(#Main_Window_PopUpMenu1_Item1,"Edit")
MenuItem(#Main_Window_PopUpMenu1_Item2,"Cancel")
MenuItem(#Main_Window_PopUpMenu1_Item3,"Accept Edit Changes & Close Edit Window")
MenuItem(#Main_Window_PopUpMenu1_Item4,"Delete Label")
MenuBar()
MenuItem(#Main_Window_PopUpMenu1_Item5,"Set First Label to print from")
MenuItem(#Main_Window_PopUpMenu1_Item6,"Set Last Label to print to")
EndIf
ScrollAreaGadget(#Main_ScrollArea_0, 0, 0, 640, 600, 3000, 4000, 10)
ImageGadget(#Main_Image_0, 10, 10, 400, 400, ImageID(100))
CloseGadgetList()
EndIf
EndProcedure
Procedure Draw()
StartDrawing(ImageOutput(100))
Box(50,50,800,800,RGB(142, 239, 243))
StopDrawing()
EndProcedure
CreateImage(100, 1000, 2000,24,RGB(255, 251, 158))
Open_Window_0()
hWndScrollGadetProc = SetWindowLongPtr_(GadgetID(#Main_ScrollArea_0),#GWL_WNDPROC,@ScrollGadetProc())
hWndImagelGadetProc = SetWindowLongPtr_(GadgetID(#Main_Image_0),#GWL_WNDPROC,@ImageGadgetProc())
Draw()
SetGadgetState(#Main_Image_0, ImageID(100))
Loop:
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Gadget
Select EventGadget()
Case #Button_0
DisplayPopupMenu(#Main_Window_PopUpMenu_1, WindowID(#Window_0))
Case #Button_1
EndSelect
EndSelect
Until Event = #PB_Event_CloseWindow
End