Posts: 1,272
Threads: 119
Joined: Apr 2022
Reputation:
100
Since I've started diving into API calls I figured a dedicated thread for API related questions would be better.
Here is my first question.
In the Wiki here: https://qb64phoenix.com/qb64wiki/index.p...ndow_Focus
It's shown how to determine the foreground window (the one in focus).
The Microsoft docs for GetForegroundWindow are located here: https://learn.microsoft.com/en-us/window...oundwindow
I noticed in the Wiki example that GetForegroundWindow is declared as an _OFFSET (%&). How was this determined? Looking at the Microsoft docs there is no indication of the type of variable returned. With other window handle (hWnd) related functions I've noticed a variable type of LONG is used. Why was _OFFSET needed here instead of LONG?
This has me confused. Any clarification would be greatly appreciated.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Posts: 734
Threads: 30
Joined: Apr 2022
Reputation:
43
(08-18-2023, 07:35 PM)TerryRitchie Wrote: Since I've started diving into API calls I figured a dedicated thread for API related questions would be better.
Here is my first question.
In the Wiki here: https://qb64phoenix.com/qb64wiki/index.p...ndow_Focus
It's shown how to determine the foreground window (the one in focus).
The Microsoft docs for GetForegroundWindow are located here: https://learn.microsoft.com/en-us/window...oundwindow
I noticed in the Wiki example that GetForegroundWindow is declared as an _OFFSET (%&). How was this determined? Looking at the Microsoft docs there is no indication of the type of variable returned. With other window handle (hWnd) related functions I've noticed a variable type of LONG is used. Why was _OFFSET needed here instead of LONG?
This has me confused. Any clarification would be greatly appreciated. HWND is 4 bytes in 32 bit and 8 bytes in 64. The reason you probably see it often declared as a LONG is because many people use 32 bit QB64. Using OFFSET makes it automatically the right size for either system. From Microsoft, the declaration for GetForegroundWindow is: HWND GetForegroundWindow();
The HWND is a handle to the window. Most handles in Win32 are going to be translated best to OFFSET in QB64.
Tread on those who tread on you
Posts: 1,272
Threads: 119
Joined: Apr 2022
Reputation:
100
(08-18-2023, 07:51 PM)SpriggsySpriggs Wrote: (08-18-2023, 07:35 PM)TerryRitchie Wrote: Since I've started diving into API calls I figured a dedicated thread for API related questions would be better.
Here is my first question.
In the Wiki here: https://qb64phoenix.com/qb64wiki/index.p...ndow_Focus
It's shown how to determine the foreground window (the one in focus).
The Microsoft docs for GetForegroundWindow are located here: https://learn.microsoft.com/en-us/window...oundwindow
I noticed in the Wiki example that GetForegroundWindow is declared as an _OFFSET (%&). How was this determined? Looking at the Microsoft docs there is no indication of the type of variable returned. With other window handle (hWnd) related functions I've noticed a variable type of LONG is used. Why was _OFFSET needed here instead of LONG?
This has me confused. Any clarification would be greatly appreciated. HWND is 4 bytes in 32 bit and 8 bytes in 64. The reason you probably see it often declared as a LONG is because many people use 32 bit QB64. Using OFFSET makes it automatically the right size for either system. From Microsoft, the declaration for GetForegroundWindow is: HWND GetForegroundWindow();
The HWND is a handle to the window. Most handles in Win32 are going to be translated best to OFFSET in QB64. Ah, ok, so basically it's acting like an _INTEGER64 in this sense. So the rule of thumb is if a handle is returned best practice is to use _OFFSET.
Thank you for the quick reply and explanation.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Posts: 2,698
Threads: 327
Joined: Apr 2022
Reputation:
217
In a lot of cases, like in the wiki example you reference, the return type really isn't that important. Think of making a function like so:
FUNCTION Foo&&
'Stuff
END FUNCTION
Now that function returns a value which is an Integer64... Yet, you'll see folks write code like:
DIM whatever AS INTEGER
whatever = Foo
And, it works! Well, it works as long as the return value is less than 32536, otherwise you get overflow results as you can't put values larger than that in an INTEGER.
Since a lot of windows API calls just return simple error/success codes, it often doesn't matter what the return type is. Nearly any variable type can successfully receive a value of 1 for success, 0 for failure.
Posts: 2,698
Threads: 327
Joined: Apr 2022
Reputation:
217
Such as here:
DECLARE DYNAMIC LIBRARY "kernel32"
FUNCTION QueryDosDeviceA~& (BYVAL lpDeviceName AS _UNSIGNED _OFFSET, BYVAL lpTargetPath AS _UNSIGNED _OFFSET, BYVAL ucchMax AS _UNSIGNED LONG)
FUNCTION GetLastError~& ()
END DECLARE
DIM sizeofbuffer AS _UNSIGNED LONG
DIM buffer AS STRING
DIM i AS _UNSIGNED LONG
DIM x AS _UNSIGNED LONG
DIM n AS _UNSIGNED LONG
sizeofbuffer = 1024
buffer = SPACE$(sizeofbuffer)
DO
x = 0
IF QueryDosDeviceA~&(0, _OFFSET(buffer), sizeofbuffer) = 0 THEN
x = GetLastError~&
IF x = &H7A THEN
GetLastError is defined as an offset to return values, but x is defined as an Unsigned Long, and yet it works perfectly fine. Why? Because we only care if the return value in this case is &H7A -- which would fit properly in an Unsigned Byte!
(Snippet taken from wiki for Window Ports in the windows dll examples.)
It's not the *PROPER* return type, but it'll work a lot of times with any glitches.
Posts: 734
Threads: 30
Joined: Apr 2022
Reputation:
43
As our one-eyed friend put, it doesn't often matter about return types. However, it makes the most sense to do your best to match up sizes and types, for professionalism and consistency.
Tread on those who tread on you
Posts: 1,272
Threads: 119
Joined: Apr 2022
Reputation:
100
Can anyone figure out why the Windows Menu code here in the wiki: https://qb64phoenix.com/qb64wiki/index.p...ndows_Menu
does not work?
I went extensively through the Microsoft docs and found two things that may be a problem.
First, the UDT MENUITEMINFO:
TYPE MENUITEMINFO
cbSize AS LONG
fMask AS LONG
fType AS LONG
fState AS LONG
wID AS LONG
hSubMenu AS LONG
hbmpChecked AS LONG
hbmpUnchecked AS LONG
dwItemData AS _OFFSET
dwTypeData AS _OFFSET
cch AS LONG
'hbmpItem AS LONG <--- this not in original but specified in Microsoft docs.
END TYPE
seems to be missing hbmpItem (I added it above remmed out).
Second, the function DrawMenuBar is not used anywhere in the code to actually generate the menu. I'm wondering if somehow some of the code has been omitted during a copy/paste into this Wiki?
CreateMenu is returning a valid hMenu handle value. I believe the problem is with the first InsertMenuItemA function encountered, but according to what I've read in the docs it's structure appears fine.
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 LONG
hbmpChecked AS LONG
hbmpUnchecked AS LONG
dwItemData AS _OFFSET
dwTypeData AS _OFFSET
cch AS LONG
END TYPE
DECLARE LIBRARY
FUNCTION FindWindow& (BYVAL ClassName AS _OFFSET, WindowName$) ' To get hWnd handle
END DECLARE
DECLARE DYNAMIC LIBRARY "user32"
FUNCTION CreateMenu& ()
FUNCTION DrawMenuBar (BYVAL hWnd&)
FUNCTION SetMenu& (BYVAL hWnd&, BYVAL hMenu&)
FUNCTION InsertMenuItemA& (BYVAL hMenu&, BYVAL uItem&, BYVAL fByPosition&, BYVAL lpmii AS _OFFSET)
FUNCTION GetMenuItemCount& (BYVAL hMenu&)
FUNCTION GetMenuItemInfoA& (BYVAL hMenu&, BYVAL uItem&, BYVAL fByPosition&, BYVAL lpmii AS _OFFSET)
END DECLARE
DIM hWnd AS LONG
DIM hMenu AS LONG
DIM MenuItem AS MENUITEMINFO, BlankMenuItem AS MENUITEMINFO
DIM TypeData AS STRING * 1000
_TITLE "Menu bar API demo"
hWnd = _WINDOWHANDLE 'FindWindow(0, "Menu bar API demo" + CHR$(0))
hMenu = CreateMenu: BlankMenuItem.cbSize = LEN(BlankMenuItem)
COLOR 7, 1: CLS
'Add a separator bar
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
'Add a button
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$ = ""
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Posts: 734
Threads: 30
Joined: Apr 2022
Reputation:
43
I think this was due to the padding and such. I wrote code that worked for 64 bit a while back but I think I lost it. I'd need to look at it again to check the offsets of each member.
Tread on those who tread on you
Posts: 1,272
Threads: 119
Joined: Apr 2022
Reputation:
100
(08-19-2023, 04:32 AM)SpriggsySpriggs Wrote: I think this was due to the padding and such. I wrote code that worked for 64 bit a while back but I think I lost it. I'd need to look at it again to check the offsets of each member. I was going through my code archives and found a copy of the menu library I copied back in 2012 when version .954 of QB64 was still the latest. Aside from the change to using _WINDOWHANDLE in the version in the Wiki the code is identical. It appears a change in QB64 somewhere along the line broke the code.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Posts: 730
Threads: 120
Joined: Apr 2022
Reputation:
106
The wiki code is working for me as is. Im In windows 7 32-bit using the current version of QB64-PE.
- Dav
|