Posts: 593
Threads: 44
Joined: Apr 2022
Reputation:
43
08-19-2023, 03:53 PM
(This post was last modified: 08-19-2023, 04:09 PM by TerryRitchie.)
(08-19-2023, 03:48 PM)Dav Wrote: The wiki code is working for me as is. Im In windows 7 32-bit using the current version of QB64-PE.
- Dav Well now, that's interesting. I'm in Windows 7 64-bit using the current version of QB64-PE. I'll fire up a VM of 32bit and see if it run there.
Update: The code works fine in a virtual machine running Windows 7 32bit and the latest 32bit version of QB64-PE. Seems to be a 64bit related issue then.
Software and cathedrals are much the same — first we build them, then we pray.
QB64 Tutorial
Posts: 439
Threads: 17
Joined: Apr 2022
Reputation:
21
It's not really an "issue". What it is, is the person who wrote the sample didn't take into account any architecture other than 32 bit. I try to make sure all my types are sized for both systems when I can.
Ask me about Windows API and maybe some Linux stuff
Posts: 593
Threads: 44
Joined: Apr 2022
Reputation:
43
(08-19-2023, 09:10 PM)SpriggsySpriggs Wrote: It's not really an "issue". What it is, is the person who wrote the sample didn't take into account any architecture other than 32 bit. I try to make sure all my types are sized for both systems when I can. I was written by Galleon back in the 32bit .954 version of QB64.
What exactly would I need to do to bring the code to 64bit? I've studied the Microsoft docs pretty well and all but what I noted before seems in order. I've already tried changing the LONG values for handles to _OFFSETs and removing _OFFSETS as pointers to the UDT and instead passing the UDT directly but I get the same negative result.
Software and cathedrals are much the same — first we build them, then we pray.
QB64 Tutorial
Posts: 336
Threads: 24
Joined: Apr 2022
Reputation:
19
@ TerryRitchie
there were a number of places in your code that seemed to needed to be _offset instead of a long, plus you missed hbmpItem in the Type MENUITEMINFO
here is your altered code, it successfully adds the menu item and silently crashes or simply vanishes
Code: (Select All)
| | | DefLng A-Z | | | | Const MIIM_STATE = &H1 | | Const MIIM_ID = &H2 | | Const MIIM_TYPE = &H10 | | Const MFT_SEPARATOR = &H800 | | Const MFT_STRING = &H0 | | Const MFS_ENABLED = &H0 | | Const MFS_CHECKED = &H8 | | | | Const HWND_TOPMOST = -1 | | Const HWND_NOTOPMOST = -2 | | Const SWP_NOMOVE = &H2 | | Const SWP_NOSIZE = &H1 | | | | | | Type MENUITEMINFO | | cbSize As Long | | fMask As Long | | fType As Long | | fState As Long | | wID As Long | | hSubMenu As _Offset | | hbmpChecked As _Offset | | hbmpUnchecked As _Offset | | dwItemData As _Offset | | dwTypeData As _Offset | | cch As Long | | hbmpItem As _Offset | | End Type | | | | Declare Library | | Function FindWindow& (ByVal ClassName As _Offset, WindowName$) | | End Declare | | | | Declare Dynamic Library "user32" | | Function CreateMenu%& () | | Function DrawMenuBar (ByVal hWnd As _Offset) | | Function SetMenu& (ByVal hWnd As _Offset, Byval hMenu As _Offset) | | Function InsertMenuItemA& (ByVal hMenu As _Offset, Byval uItem As _Unsigned Long, Byval fByPosition&, Byval lpmii As _Offset) | | Function GetMenuItemCount& (ByVal hMenu As _Offset) | | Function GetMenuItemInfoA& (ByVal hMenu As _Offset, Byval uItem As _Unsigned Long, Byval fByPosition&, Byval lpmii As _Offset) | | End Declare | | | | Dim hWnd As _Offset | | Dim hMenu As _Offset | | Dim MenuItem As MENUITEMINFO, BlankMenuItem As MENUITEMINFO | | Dim TypeData As String * 1000 | | | | _Title "Menu bar API demo" | | hWnd = _WindowHandle | | | | hMenu = CreateMenu: BlankMenuItem.cbSize = Len(BlankMenuItem) | | | | Color 7, 1: Cls | | | | | | count = GetMenuItemCount(hMenu): Print "MenuItemCount:"; count | | MenuItem = BlankMenuItem | | MenuItem.fMask = MIIM_ID Or MIIM_TYPE | | MenuItem.fType = MFT_SEPARATOR | | MenuItem.wID = count | | If InsertMenuItemA(hMenu, count, 1, _Offset(MenuItem)) Then Print "Successfully added menu item!" Else Print "Failed to add menu item!": End | | | | | | MenuItem = BlankMenuItem | | count = GetMenuItemCount(hMenu): Print "MenuItemCount:"; count | | MenuItem.fMask = MIIM_STATE Or MIIM_ID Or MIIM_TYPE | | MenuItem.fType = MFT_STRING | | MenuItem.fState = MFS_ENABLED | | MenuItem.wID = count | | TypeData = "&Fire Laser!" + Chr$(0) | | MenuItem.dwTypeData = _Offset(TypeData) | | MenuItem.cch = Len(MenuItem.dwTypeData) | | MyButton = MenuItem.wID | | If InsertMenuItemA(hMenu, count, 1, _Offset(MenuItem)) Then Print "Successfully added menu item!" Else Print "Failed to add menu item!": End | | | | If SetMenu(hWnd, hMenu) Then Print "Successfully set menu!": Print "Menu handle is:"; hMenu Else Print "Failed to set menu!": End | | | | Do: _Limit 70 | | prev_state = new_state | | ok = GetMenuItemInfoA(hMenu, MyButton, 1, _Offset(MenuItem)) | | new_state = MenuItem.fState And 128 | | If prev_state = 0 And new_state <> 0 Then Print "Ouch! "; | | Loop While InKey$ = "" |
Posts: 593
Threads: 44
Joined: Apr 2022
Reputation:
43
(08-19-2023, 10:45 PM)Jack Wrote: @ TerryRitchie
there were a number of places in your code that seemed to needed to be _offset instead of a long, plus you missed hbmpItem in the Type MENUITEMINFO
here is your altered code, it successfully adds the menu item and silently crashes or simply vanishes Yeah, I pointed out that the original code was missing hbmpItem in an earlier post. The code is not mine, it's from the Wiki and was written by Galleon back around 2011.
As Dav pointed out, the code works correctly in 32bit versions of Windows and QB64.
Your code is closer than I have come to getting it to work. You got past the the first InsertMenuItemA, something I was unable to do. I'll study your changes to see if I can get it to work the rest of the way.
Thanks for changes.
Software and cathedrals are much the same — first we build them, then we pray.
QB64 Tutorial
Posts: 131
Threads: 7
Joined: May 2022
Reputation:
20
08-20-2023, 12:01 AM
(This post was last modified: 08-20-2023, 12:03 AM by a740g.)
Here. This should work on 64-bit compilers.
Code: (Select All)
| | | DEFLNG A-Z | | OPTION _EXPLICIT | | | | $IF 32BIT THEN | | $ERROR 32-bit compilers not supported! | | $END IF | | | | CONST NULL = 0 | | | | CONST MIIM_STATE = &H1 | | CONST MIIM_ID = &H2 | | CONST MIIM_TYPE = &H10 | | CONST MFT_SEPARATOR = &H800 | | CONST MFT_STRING = &H0 | | CONST MFS_ENABLED = &H0 | | CONST MFS_CHECKED = &H8 | | | | CONST HWND_TOPMOST = -1 | | CONST HWND_NOTOPMOST = -2 | | CONST SWP_NOMOVE = &H2 | | CONST SWP_NOSIZE = &H1 | | | | TYPE MENUITEMINFO | | AS _UNSIGNED LONG cbSize | | AS _UNSIGNED LONG fMask | | AS _UNSIGNED LONG fType | | AS _UNSIGNED LONG fState | | AS _UNSIGNED LONG wID | | AS STRING * 4 __padding1 | | AS _UNSIGNED _OFFSET hSubMenu | | AS _UNSIGNED _OFFSET hbmpChecked | | AS _UNSIGNED _OFFSET hbmpUnchecked | | AS _UNSIGNED _OFFSET dwItemData | | AS _UNSIGNED _OFFSET dwTypeData | | AS _UNSIGNED LONG cch | | AS STRING * 4 __padding2 | | AS _UNSIGNED _OFFSET hbmpItem | | END TYPE | | | | DECLARE DYNAMIC LIBRARY "user32" | | FUNCTION FindWindow~%& ALIAS FindWindowA (lpClassName AS STRING, lpWindowName AS STRING) | | FUNCTION CreateMenu~%& | | FUNCTION DrawMenuBar& (BYVAL hWnd AS _UNSIGNED _OFFSET) | | FUNCTION SetMenu& (BYVAL hWnd AS _UNSIGNED _OFFSET, BYVAL hMenu AS _UNSIGNED _OFFSET) | | FUNCTION InsertMenuItem& ALIAS InsertMenuItemA (BYVAL hMenu AS _UNSIGNED _OFFSET, BYVAL item AS _UNSIGNED LONG, BYVAL fByPosition AS LONG, BYVAL lpmi AS _UNSIGNED _OFFSET) | | FUNCTION GetMenuItemCount& (BYVAL hMenu AS _UNSIGNED _OFFSET) | | FUNCTION GetMenuItemInfo& ALIAS GetMenuItemInfoA (BYVAL hMenu AS _UNSIGNED _OFFSET, BYVAL item AS _UNSIGNED LONG, BYVAL fByPosition AS LONG, BYVAL lpmii AS _UNSIGNED _OFFSET) | | END DECLARE | | | | DIM MenuItem AS MENUITEMINFO, BlankMenuItem AS MENUITEMINFO | | DIM TypeData AS STRING * 1000 | | | | _TITLE "Menu bar API demo" | | | | DIM hWnd AS _UNSIGNED _OFFSET: hWnd = _WINDOWHANDLE | | | | DIM hMenu AS _UNSIGNED _OFFSET: hMenu = CreateMenu: BlankMenuItem.cbSize = LEN(BlankMenuItem) | | | | COLOR 7, 1 | | | | | | DIM count AS LONG: count = GetMenuItemCount(hMenu): PRINT "MenuItemCount:"; count | | MenuItem = BlankMenuItem | | MenuItem.fMask = MIIM_ID OR MIIM_TYPE | | MenuItem.fType = MFT_SEPARATOR | | MenuItem.wID = count | | IF InsertMenuItem(hMenu, count, 1, _OFFSET(MenuItem)) THEN PRINT "Successfully added menu item!" ELSE PRINT "Failed to add menu item!": END | | | | | | MenuItem = BlankMenuItem | | count = GetMenuItemCount(hMenu): PRINT "MenuItemCount:"; count | | MenuItem.fMask = MIIM_STATE OR MIIM_ID OR MIIM_TYPE | | MenuItem.fType = MFT_STRING | | MenuItem.fState = MFS_ENABLED | | MenuItem.wID = count | | TypeData = "&Fire Laser!" + CHR$(NULL) | | MenuItem.dwTypeData = _OFFSET(TypeData) | | MenuItem.cch = LEN(MenuItem.dwTypeData) | | | | DIM MyButton AS _UNSIGNED LONG: MyButton = MenuItem.wID | | IF InsertMenuItem(hMenu, count, 1, _OFFSET(MenuItem)) THEN PRINT "Successfully added menu item!" ELSE PRINT "Failed to add menu item!": END | | | | IF SetMenu(hWnd, hMenu) THEN PRINT "Successfully set menu!": PRINT "Menu handle is:"; hMenu ELSE PRINT "Failed to set menu!": END | | | | DIM AS LONG prev_state, new_state, ok | | | | DO | | _LIMIT 70 | | prev_state = new_state | | ok = GetMenuItemInfo(hMenu, MyButton, 1, _OFFSET(MenuItem)) | | new_state = MenuItem.fState AND 128 | | IF prev_state = 0 AND new_state <> 0 THEN PRINT "Ouch! "; | | LOOP WHILE INKEY$ = "" | | | | END |
Posts: 593
Threads: 44
Joined: Apr 2022
Reputation:
43
(08-20-2023, 12:01 AM)a740g Wrote: Here. This should work on 64-bit compilers.
Yes it does, thank you! This example should be added to the Windows Library examples in the Wiki.
Could you explain the changes you made and why they needed to be done so I can get a better understanding of your code and why 64-bit needs to be approached differently please?
Software and cathedrals are much the same — first we build them, then we pray.
QB64 Tutorial
Posts: 1,507
Threads: 160
Joined: Apr 2022
Reputation:
116
(08-20-2023, 05:47 PM)TerryRitchie Wrote: (08-20-2023, 12:01 AM)a740g Wrote: Here. This should work on 64-bit compilers.
Yes it does, thank you! This example should be added to the Windows Library examples in the Wiki.
Could you explain the changes you made and why they needed to be done so I can get a better understanding of your code and why 64-bit needs to be approached differently please?
The issue lies in data alignment and type packing. In 32 bit OSes, data is packed on a 4 byte alignment. In 64-bit OSes, it's packed on 8-byte alignments.
For example:
TYPE Foo
x AS INTEGER
y AS LONG
z AS STRING *3
END TYPE
The above type (as a windows type) would align on 4-byte break points. It'd actually use 12-bytes per record in memory as:
TRANSLATED TYPE Foo32
x AS INTEGER
buffer AS STRING *2 'complete that 4 byte block
y AS LONG 'already 4 bytes; no buffer is needed
z AS STRING * 3
buffer2 AS STRING * 1 'complete the other 4 byte block
END TYPE
On a 64-bit type, the breakpoints are 8-bytes, for 16-bytes per record in memory.
TRANSLATED TYPE Foo64
x AS INTEGER
y AS LONG
buffer AS STRING * 2 'complete the 8-byte block
z AS STRING * 3
buffer2 AS STRING * 5 'complete the second 8-byte block
END TYPE
For 32-bit windows API types, data is aligned in 4-byte segments. For 64-bit window API types, it's in 8-byte segments.
Posts: 1,507
Threads: 160
Joined: Apr 2022
Reputation:
116
TYPE MENUITEMINFO
AS _UNSIGNED LONG cbSize
AS _UNSIGNED LONG fMask << 8 bytes
AS _UNSIGNED LONG fType
AS _UNSIGNED LONG fState << 8 bytes
AS _UNSIGNED LONG wID
AS STRING * 4 __padding1 << 4 bytes + 4 bytes padding = 8 bytes
AS _UNSIGNED _OFFSET hSubMenu << *ALL* 64-bit OFFSET are 8 bytes
AS _UNSIGNED _OFFSET hbmpChecked
AS _UNSIGNED _OFFSET hbmpUnchecked
AS _UNSIGNED _OFFSET dwItemData
AS _UNSIGNED _OFFSET dwTypeData ' str ptr
AS _UNSIGNED LONG cch
AS STRING * 4 __padding2 << 4 bytes + 4 bytes padding = 8 bytes
AS _UNSIGNED _OFFSET hbmpItem
END TYPE
Posts: 336
Threads: 24
Joined: Apr 2022
Reputation:
19
with all due respect to a740g, I am not comfortable with the padding in MENUITEMINFO
this C code prints 80 as the size of MENUITEMINFO
Code: (Select All) #include <stdio.h>
#include <windows.h>
#include <winuser.h>
int main(void){
printf("%lld\n", sizeof(MENUITEMINFO));
return 0;
}
|