is there a way to determine the window handle of a menu, or scroll bar or caption bar, etc? I know that when you create most of these things you'll get a handle returned (like HMENU or something), but I'm thinking more like the handle returned by CreateWindowEx (HWND) so that I could pass it to other functions.

--Chorus
Posted on 2002-05-14 12:37:19 by chorus
well i can give you a solid answer for a menu. use the GetMenu api.

for a scrollbar i dont think you can actually get the handle unless it was actually created with the scrollbar api's. but to get and set info about the system defined scrollbars you can use the GetScrollBarInfo and SetScrollInfo api's. using those you dont need to know the handle to the scrollbar but only the window it belongs to.

as for the titlebar you can use the GetTitleBarInfo api. ive never really messed around with this one but to set the titlebar info you probably will need to use some gdi functions along with the info you get back from the GetTitleBarInfo api.
Posted on 2002-05-14 12:54:39 by smurf
Thanks smurf, but I think you got me backwards. GetMenu, for instance, returns the handle of a menu associated with a window. What I was looking for was to turn that menu handle into a *window* handle of the menu. For instance, I would like to grab the window handle of the title bar, subclass it and change the background brush to a different colour. As it stands, I believe the background colour is taken from the system default colours.

PS. Couldn't find the GetTitleBarInfo API in my API guide. Is this old or new??
Thanks again,

--Chorus
Posted on 2002-05-14 13:04:03 by chorus
I think for scrollbars (belonging to a listbox for example) the vertical bar has ID 1, the horizontal bar has id 2. So get the hwnd with GetDlgItem(hWndListBox,1).
I'm not sure if this is documented and if it works for other controls.

japheth
Posted on 2002-05-14 13:12:23 by japheth
japheth, this seems to be exactly what I'm looking for!
However, can't seem to make it work, heheh...

The WinAPI guide says

You can use the GetDlgItem function with any parent-child window pair, not just with dialog boxes. As long as the hDlg parameter specifies a parent window and the child window has a unique identifier (as specified by the hMenu parameter in the CreateWindow or CreateWindowEx function that created the child window), GetDlgItem returns a valid handle to the child window.


So, it seems that you can use it for pretty much anything you can get a handle for right? Anyways, what I wanted to do was change the background colour of the Menu bar, but it didn't work.

If anyone can spot any errors, here's what I did:



MenuWindow DD ?
OldWindowProc DD?

invoke GetMenu,ParentHwnd
invoke GetDlgItem,ParentHwnd,eax
mov MenuWindow,eax
invoke SetWindowLong,eax,GWL_WNDPROC,addr MenuSubProc
mov OldWindowProc,eax

invoke UpdateWindow,Parent.hwnd
....

MenuSubProc PROC hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
LOCAL rct:RECT
LOCAL bkbrush:DWORD
mov eax,uMsg
cmp eax,WM_ERASEBKGND
je @@EraseBkgnd
invoke CallWindowProc,OldWindowProc,hWin,uMsg,wParam,lParam
ret
@@EraseBkgnd: invoke GetClientRect,hWin,addr rct
invoke CreateSolidBrush,0ffffffh
mov bkbrush,eax
invoke FillRect,wParam,addr rct,bkbrush
invoke DeleteObject,bkbrush
xor eax,eax
ret
MenuSubProc ENDP





Thanks again for the pointer

--Chorus
Posted on 2002-05-14 13:49:03 by chorus
Hi chorus,

Menus are a system global class and Windows takes care of creating its window and handling all its messages. When you create menus using Win32 APIs you don't get any information at all about its WINDOW handle.
I use hooks to trap all windows messages that belonged to the same thread.
Microsoft describes hooks as "A point in the system message-handling mechanism where an application can install a subroutine to monitor the message traffic in the system and process certain types of messages before they reach the target window procedure".
In other words, a hook is a way of subclassing a whole thread. There are different hooks you can create, depending on the type of message you want to trap.
In order to detect when a menu-window is about to be created, you will use the WH_CALLWNDPROC hook. Here is a part of my program:


CreatePMHook: ;
mov eax, hWnd ;
push 0 ;
push eax ; eax->hWnd
call GetWindowThreadProcessId ; call API
push eax ; eax->hThreadID
push 0 ; handle to application instance
push offset pHookCallWndProc ; our hook proc
push WH_CALLWNDPROC ; hook type
call SetWindowsHookEx ; call API
mov hHookID, eax ; handle to hook procedure
ret ;
;..............................................................;
KillPMHook: ;
mov eax, hHookID ; eax-> handle to hook procedure
xor esi, esi ; esi = 0
push eax ; eax-> handle to hook procedure
call UnhookWindowsHookEx ; call API
mov hHookID, esi ; esi = 0
ret ;
;..............................................................;
pHookCallWndProc: ; our hook proc
pop ecx ; ecx->return address
mov eax, hHookID ;
push eax ; eax->hHookID
push ecx ; ecx->return address
mov edx, [esp+4+4] ; ncode
mov eax, [esp+12+4] ; lParam-> lp to CWPSTRUCT
cmp edx, HC_ACTION ; edx->ncode = HC_ACTION = 0
jnz EndClN ;
cmp [eax].CWPSTRUCT.message, WM_CREATE ; WM_CREATE = 1
jnz EndClN ;
;Get ClassName of the window ;
mov edi, offset buferClassName ;
mov esi, [eax].CWPSTRUCT.hwnd ; esi->CWPSTRUCT.hwnd
push sizeof buferClassName ; size of buferClassName = 16*4
push edi ; edi->buferClassName
push esi ; esi->CWPSTRUCT.hwnd
call GetClassName ; call API
mov eax, [edi+4] ; edi->bufer
mov edx, offset popMenuClassName ; edx-> string "#32768",0,0
mov ecx, [edi] ; edi->bufer
and eax, 0FFFFh ; need ax only
cmp ecx, [edx] ; edx->string "#32768",0,0
jnz EndClN ;
cmp eax, [edx+4] ; edx->string "#32768",0,0
jnz EndClN ; obtained with SI !!!
;ClassName of the window is #32768, and subclass it ; it is a POPUP MENU class name
push offset lpPopMenuSubclassWndProc ; new popMenuWndProc address
push GWL_WNDPROC ;
push esi ; esi->CWPSTRUCT.hwnd
call SetWindowLong ; call API
mov lpOldPopMenuWndProc, eax ; save original address
EndClN: ;
jmp CallNextHookEx ; call API
;..............................................................;
lpPopMenuSubclassWndProc: ;
;[esp] -> return address ;
;[esp+4] -> hwnd ;
;[esp+8] -> uMsg ;
;[esp+12] -> wParam ;
;[esp+16] -> lParam ;
mov eax, lpOldPopMenuWndProc ;
pop ecx ; ecx->return address
push eax ; eax->lpOldPopMenuWndProc
push ecx ; ecx->return address
mov eax, [esp+8+4] ; eax->uMsg
mov esi, [esp+4+4] ; esi->hwnd
cmp eax, WM_CREATE ; WM_CREATE = 1
jnz EndGlN2 ;
;..............................................................;
;WM_CREATE ;
invoke GetWindowLong, esi, GWL_STYLE ; Example for you
xor eax, WS_BORDER ;
invoke SetWindowLong, esi, GWL_STYLE, eax ;
invoke GetWindowLong, esi, GWL_EXSTYLE ;
xor eax, WS_EX_WINDOWEDGE or \ ;
WS_EX_DLGMODALFRAME ;
invoke SetWindowLong, esi, GWL_EXSTYLE, eax ;
;......................................................;
EndGlN2: ;
jmp CallWindowProc ; call API


:)
Posted on 2002-05-14 18:51:22 by buliaNaza
buliaNaza,
Thanks alot for the code! It's more than I expected. I haven't tried it yet, but I will at the earliest opportunity.
Just looking at it quickly, should I assume that the class name is actually "#32768"? If it is, do you think I could use FindWindow with this class name to get the window handle? I'll try it both ways...

Thanks again

--Chorus
Posted on 2002-05-15 14:17:56 by chorus
there may be an easier approach for access to a menu hwnd:

menu windows cannot be children of the window the menu belongs to. if they were, they would be clipped to the window/client area of their parent. So menu windows must be children of the desktop hwnd (sam as with tooltips). So it should be possible to find the menu window by searching "#32768" childrens of the desktop hwnd. One problem I see is that there may exist more than 1 window of this class so you have to find out which one is the right one.
Posted on 2002-05-15 16:50:38 by japheth
Chorus,
If ua Canadian don't be lazy...

japheth,
My code works fine for me...and where is your code?
Posted on 2002-05-15 19:58:42 by buliaNaza
for a scrollbar i dont think you can actually get the handle unless it was actually created with the scrollbar api's.
Surely the scrollbar would be a child window of the edit control, so you could EnumChildWindows to find its hWnd?
Posted on 2002-05-15 22:07:12 by sluggy
buliaNaza,

your code is fine :) .

I just doubted if to install hooks just for changing menu background color isn't a bit overstretched. But "my" approach isn't proofed to work and it most likely may be even larger than yours.

japheth
Posted on 2002-05-16 05:01:18 by japheth