|
Post by pablosl on Jan 31, 2019 20:08:07 GMT -5
|
|
cundo
Full Member
Muchas Gracias!!
Posts: 146
|
Post by cundo on Feb 2, 2019 9:39:20 GMT -5
So, you want to move the popup menu to be exactly below the button? same x position, and y = button height?
|
|
|
Post by Brandon Parker on Feb 3, 2019 17:19:49 GMT -5
You will need to check out the TrackPopupMenu function. This will require you to create, fill, destroy your own menu, but it will allow you to have it pop up wherever you specify. Have a quick peak at the Microsoft reference material and try it on your own first. When you have further questions just post what you have tried and we can go from there. I do this in a program all the time for the users and it works well. I am more than willing to help guide you along the way.... {:0) Brandon Parker
|
|
cundo
Full Member
Muchas Gracias!!
Posts: 146
|
Post by cundo on Feb 5, 2019 20:43:09 GMT -5
Since the popup appears at the cursor position, what if we move the mouse cursor using API then show the popupmenu?... it's a workaround, not a nice solution but it works. The drawback is, we can't put the cursor back while the menu is on screen because the popup menu acts like a Wait statement.
|
|
|
Post by Brandon Parker on Feb 6, 2019 9:16:18 GMT -5
Since the popup appears at the cursor position, what if we move the mouse cursor using API then show the popupmenu?... it's a workaround, not a nice solution but it works. The drawback is, we can't put the cursor back while the menu is on screen because the popup menu acts like a Wait statement. That's why you use the TrackPopupMenu function. Not only do you have full control of what goes into it, but you can also specify where it opens on the screen. {:0) Brandon Parker
|
|
|
Post by alincon on Feb 6, 2019 10:12:56 GMT -5
Brandon, can you show us an LB program using the TrackPopUpMenu function? The Microsoft article I found seems geared to some other language.
r.m.
|
|
|
Post by Chris Iverson on Feb 6, 2019 11:20:52 GMT -5
Here's a quick example I created off the cuff.
open "needed window" for window as #test
hWnd = hwnd(#test)
dim items$(5) For x = 1 to 5 Input "Enter value for menu item ";x;": ";data$ items$(x) = data$ Next x
Print Print "Preparing menu..." Print
hMenu = CreatePopupMenu()
for x = 1 to 5 a = AppendMenuItemString(hMenu, x, items$(x)) next x
Input "Enter X coordinate to open menu at. ";x Input "Enter Y coordinate to open menu at. ";y
response = TrackPopupMenu(hMenu, _TPM_NONOTIFY or _TPM_RETURNCMD, x, y, hWnd)
Print Print "Menu item selected: ";items$(response)
a = DestroyMenu(hMenu)
close #test
Function CreatePopupMenu() CallDLL #user32, "CreatePopupMenu",_ CreatePopupMenu as ulong End Function
Function DestroyMenu(hMenu) CallDLL #user32, "DestroyMenu",_ hMenu as ulong,_ DestroyMenu as long End Function
Function AppendMenuItemString(hMenu, ID, data$) CallDLL #user32, "AppendMenuA",_ hMenu as ulong,_ _MF_STRING as long,_ ID as long,_ data$ as ptr,_ AppendMenuItemString as long End Function
Function TrackPopupMenu(hMenu, uFlags, x, y, hWnd) CallDLL #user32, "TrackPopupMenu",_ hMenu as ulong,_ uFlags as ulong,_ x as long,_ y as long,_ 0 as long,_ hWnd as ulong,_ 0 as long,_ TrackPopupMenu as long End Function
|
|
|
Post by pablosl on Feb 6, 2019 18:16:02 GMT -5
@brandon Parker: Thank you for the explanations.
@chris Iverson: What if I need to add a menu separator?. Can you show this in some code snippet?. Thank you in advance!.
-Pablo
|
|
|
Post by Chris Iverson on Feb 6, 2019 19:13:47 GMT -5
Add this new function to the group above:
Function AppendMenuItemSeparator(hMenu) CallDLL #user32, "AppendMenuA",_ hMenu as ulong,_ _MF_SEPARATOR as long,_ 0 as long,_ 0 as long,_ AppendMenuItemSeparator as long End Function
And call that function after you add the item that comes just before the separator. For example, if you want to add a separator between items 2 and 3, then call AddMenuItemSeparator() after you've added item 2.
As an example, modify the code above, to change the loop that adds all the menu items to the menu to this:
for x = 1 to 5 a = AppendMenuItemString(hMenu, x, items$(x)) if x = 2 then a = AppendMenuItemSeparator(hMenu) next x
|
|
|
Post by Brandon Parker on Feb 6, 2019 19:23:05 GMT -5
Here's another way of doing it - along with a couple extra functions that are handy, but not used here. This is how I normally do it which allows for easily creating the separator; shown as menu item 1 (second call to the InsertMenu() function).
There are different ways of doing things; this is just my way.
Dim myItems$(2)
'Create the struct for the screen coordinates 'I store coordinates from different functions so 'I have the need to have them available across 'said functions Struct point, x As long, _ y As long
Struct rect, left As long,_ top As long, _ right As long, _ bottom As long
Open "Test Window" For Window As #Test #Test "TrapClose quit"
For i = 0 to 2 Input "Enter value for menu item ";i;": ";data$ myItems$(i) = data$ Next i
hMenu = CreatePopupMenu()
result = InsertMenu(hMenu, 0, _MF_BYPOSITION Or _MF_STRING, 0, myItems$(0)) result = InsertMenu(hMenu, 1, _MF_BYPOSITION Or _MF_SEPARATOR, _NULL, "") result = InsertMenu(hMenu, 2, _MF_BYPOSITION Or _MF_STRING, 1, myItems$(1)) result = InsertMenu(hMenu, 3, _MF_BYPOSITION Or _MF_STRING, 2, myItems$(2))
Input "Enter X coordinate to open menu at. ";x Input "Enter Y coordinate to open menu at. ";y
'Get the position of the Window Rectangle result = GetWindowRect(Hwnd(#Test))
'Offset the Point x/ y by the window position plus the user's choice. point.x.struct = (rect.left.struct + x) point.y.struct = (rect.top.struct + y)
result = TrackPopupMenu(hMenu, _TPM_RETURNCMD Or _TPM_LEFTALIGN Or _TPM_TOPALIGN Or _TPM_LEFTBUTTON, Hwnd(#Test))
Print Print "Menu item selected: ";result
'You can use the result that is returned from TrackPopupMenu; it will be the number 'you sent via the fourth parameter in the InsertMenu function to track which 'menu item is selected and trigger something to happen accordingly. Select Case result Case 1 Print myItems$(1) Case 4 Print myItems$(4) Case 15 Print myItems$(15) End Select result = DestroyMenu(hMenu) Wait
Sub quit handle$ Close #handle$ End End Sub
'_____________________________________________________________________________________________________________
'_____________________________________________________________________________________________________________
Function CreatePopupMenu() CallDLL #user32, "CreatePopupMenu", CreatePopupMenu As ulong End Function
'_____________________________________________________________________________________________________________
'_____________________________________________________________________________________________________________
Function DestroyMenu(hMenu) CallDLL #user32, "DestroyMenu", hMenu As ulong, _ DestroyMenu As long End Function
'_____________________________________________________________________________________________________________ '_____________________________________________________________________________________________________________
Function DeleteMenu(hMenu, uPosition, uFlags) CallDLL #user32, "DeleteMenu", hMenu As ulong, _ uPosition As ulong, _ uFlags As ulong, _ DeleteMenu As long End Function
'_____________________________________________________________________________________________________________
'_____________________________________________________________________________________________________________
Function EndMenu() CallDLL #user32, "EndMenu", EndMenu As long End Function
'_____________________________________________________________________________________________________________
'_____________________________________________________________________________________________________________
Function InsertMenu(hMenu, uPosition, uFlags, uIDNewItem, lpNewItem$) lpNewItem$ = lpNewItem$ + chr$(0) CallDLL #user32, "InsertMenuA", hMenu As ulong, _ uPosition As ulong, _ uFlags As ulong, _ uIDNewItem As ulong, _ lpNewItem$ As ptr, _ InsertMenu As long End Function
'_____________________________________________________________________________________________________________
'_____________________________________________________________________________________________________________
Function TrackPopupMenu(hMenu, uFlags, hWnd) xPos = point.x.struct yPos = point.y.struct CallDLL #user32, "TrackPopupMenu", hMenu As ulong, _ uFlags As ulong, _ xPos As long, _ yPos As long, _ _NULL As long, _ hWnd As ulong, _ rect As struct, _ TrackPopupMenu As long End Function
'_____________________________________________________________________________________________________________
'_____________________________________________________________________________________________________________
Function GetWindowRect(hWnd) 'Get WindwRectangle CallDLL #user32, "GetWindowRect", hWnd As ulong, _ rect As struct, _ GetWindowRect As ulong End Function
'_____________________________________________________________________________________________________________
'_____________________________________________________________________________________________________________
{:0)
Brandon Parker
|
|
|
Post by pablosl on Feb 6, 2019 19:24:05 GMT -5
Chris & Brandon,
Thank you so much!!!.
-Pablo
|
|
|
Post by Brandon Parker on Feb 6, 2019 19:34:26 GMT -5
No problem... When you get really comfortable with it you can build whatever you want on the fly. The menu shown below (minus the green rectangles - redacted for legal purposes) is a menu that is built on the fly and displayed above whichever power plant (bitmap button on a map) the user right-clicks on. Menu items are included/ not included based off of many different things, but building them on the fly was a necessity for me. And yes...the program is written in Liberty BASIC; started it nine years ago and it has been running and constantly upgraded/ expanded ever since. {:0) Brandon Parker Attachments:
|
|
|
Post by alincon on Feb 7, 2019 12:11:46 GMT -5
Thanks Chris and Brandon. You are both amazing.
r.m.
|
|
|
Post by alincon on Feb 8, 2019 10:15:27 GMT -5
On second thought, if you need to call so many functions, should you be using another language? I like to use native LB code as much as possible, so I might have used just a small window containing only a list box to serve as a pop-up menu in this case.
r.m.
|
|
|
Post by Brandon Parker on Feb 8, 2019 22:07:55 GMT -5
Nope.... That's not actually "a lot" of function calls .... I find that Liberty BASIC suits my needs for the project so there's no reason to migrate it anywhere else. When you start leveraging the power that the operating system has to offer and Liberty BASIC has access to, you can do many more things than before. Once I have functions written for a certain task, all I have to do is call those functions as I have set them up. There's no real difference from that to other languages; when the language doesn't offer the abilities natively and the operating system does....there's no reason not to leverage that. I would much rather program in Liberty BASIC than some other languages; that's just me though. To each his own.... {:0) Brandon Parker
|
|