flat assembler
Message board for the users of flat assembler.
Index
> Windows > How to keep one window on top of another |
Author |
|
cod3b453 25 May 2015, 18:09
Could subclass the other window and look for WM_SETFOCUS/ACTIVATE or similar to trigger your window to force it on top
|
|||
25 May 2015, 18:09 |
|
DergMoney 25 May 2015, 18:15
Thanks for the reply,
Can I subclass a window that wasn't created by me (i.e. a different application)? If 'yes' could you give me an example? Last edited by DergMoney on 25 May 2015, 18:19; edited 1 time in total |
|||
25 May 2015, 18:15 |
|
DergMoney 25 May 2015, 18:17
I was thinking that I'd have to set up a hook using WH_CALLWNDPROCRET but it would need to be running constantly and afaik that is hard on resources
|
|||
25 May 2015, 18:17 |
|
El Tangas 25 May 2015, 18:23
I suppose you can use the SetWindowLong function, since you have the handle to the target window, and use it to intercept the target WindowProc.
Or maybe you can create your window as owned by the target window, so it will always stay on top of it (but it will be destroyed if the target is closed). Never actually tried to do any of this stuff, but in theory, should work. |
|||
25 May 2015, 18:23 |
|
DergMoney 25 May 2015, 18:24
Ah! SetWindowLong() looks like it might do the trick, thanks cod3b453 and El Tangas
|
|||
25 May 2015, 18:24 |
|
DergMoney 25 May 2015, 19:10
Dang, I'm getting an 'Access is denied" error.
The error is being thrown at invoke SetWindowLong, [hWndPS], GWL_WNDPROC, psWndProc The full code is below, in this instance I'm trying it with the windows calculator... Code: format PE GUI 4.0 entry start include "%fasminc%\win32a.inc" section '.code' code readable executable start: invoke GetModuleHandle, 0 mov [wc.hInstance], eax invoke LoadIcon, 0, IDI_APPLICATION mov [wc.hIcon], eax invoke LoadCursor, 0, IDC_ARROW mov [wc.hCursor], eax invoke RegisterClass, wc or eax,eax jz error invoke CreateWindowEx, NULL, ClassMain, AppName, WS_OVERLAPPEDWINDOW or WS_VISIBLE, 100, 100, 600, 200, NULL, NULL, [wc.hInstance], NULL test eax,eax jz error mov [hWndMain], eax invoke EnumWindows, EnumWindowsProc, 0 msgLoop: invoke GetMessage, msg, NULL, 0, 0 or eax, eax jz endLoop invoke TranslateMessage, msg invoke DispatchMessage, msg jmp msgLoop error: invoke MessageBox, NULL, errorStr, NULL, MB_ICONERROR + MB_OK endLoop: invoke ExitProcess, [msg.wParam] proc WndProc hwnd, wmsg, wparam, lparam push ebx esi edi cmp [wmsg], WM_DESTROY je .wmDestroy .defWndProc: invoke DefWindowProc, [hwnd], [wmsg], [wparam], [lparam] jmp .finish .wmDestroy: invoke SetWindowLong, [hWndPS], GWL_WNDPROC, [psWndProcHnd] invoke PostQuitMessage, 0 xor eax, eax .finish: pop edi esi ebx ret endp proc EnumWindowsProc hwnd, lparam push ebx esi edi invoke GetWindowText, [hwnd], strBuff, 1000 or eax, eax jz .retTrue invoke lstrlen, strBuff mov ecx, eax mov al, "C" mov edi, strBuff repne scasb jne .retTrue mov esi, searchStr + 1 invoke lstrlen, searchStr dec eax mov ecx, eax rep cmpsb jne .retTrue invoke GetClassName, [hwnd], strBuff, 1000 invoke lstrlen, psClass mov ecx, eax mov esi, psClass mov edi, strBuff rep cmpsb jne .retTrue ; have found the calculator window push [hwnd] pop [hWndPS] invoke SetWindowLong, [hWndPS], GWL_WNDPROC, psWndProc or eax, eax jnz @f call showError jmp .retFalse @@: mov [psWndProcHnd], eax ; save address of the calculator WndProc .retFalse: mov eax, FALSE jmp .finish .retTrue: mov eax, TRUE .finish: pop edi esi ebx ret endp proc psWndProc, hwnd, wmsg, wparam, lparam push ebx edi esi invoke CallWindowProc, [psWndProcHnd], [hWndPS], [msg], [wparam], [lparam] pop esi edi ebx ret endp showError: pushad invoke GetLastError invoke FormatMessage, FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, eax, LANG_NEUTRAL, errStrBuff, 0, NULL invoke MessageBox, HWND_DESKTOP, [errStrBuff], NULL, MB_ICONERROR or MB_OK popad ret section '.data' data readable writeable ClassMain db "WinClass", 00 AppName db "My App", 00 errorStr db "oops!", 00 hWndMain dd ? hWndPS dd ? psWndProcHnd dd ? titlePS db 1002 dup ? strBuff db 1002 dup ? wordBuff db 40 dup ? space db " ", 00 errStrBuff dd ? wc WNDCLASS CS_HREDRAW or CS_VREDRAW, WndProc, 0, 0, NULL, NULL, NULL, COLOR_BTNFACE + 1, NULL, ClassMain msg MSG searchStr db "Calculator", 00 rect RECT numStr db "%i", 00 psClass db "CalcFrame", 00 section '.idata' import data readable writeable library kernel32,'KERNEL32.DLL',\ user32, 'USER32.DLL',\ gdi32, 'GDI32.DLL',\ comdlg32,'COMDLG32.DLL',\ advapi32,'ADVAPI32.DLL',\ comctl32,'COMCTL32.DLL',\ msvcrt, 'msvcrt.dll' include '%fasminc%\api\Kernel32.inc' include '%fasminc%\api\User32.inc' include '%fasminc%\api\Gdi32.inc' include '%fasminc%\api\Comdlg32.inc' include '%fasminc%\api\Advapi32.inc' include '%fasminc%\api\Comctl32.inc' import msvcrt,\ sprintf,'sprintf' |
|||
25 May 2015, 19:10 |
|
El Tangas 25 May 2015, 19:17
It's never as easy as we would like
Quote: An application can subclass a system class, but should not subclass a window class created by another process. Quote:
I'm sure there must be a way, so maybe someone more knowledgeable will have the answer. |
|||
25 May 2015, 19:17 |
|
DergMoney 25 May 2015, 19:28
El Tangas wrote: Or maybe you can create your window as owned by the target window, so it will always stay on top of it (but it will be destroyed if the target is closed). Haven't tried this yet. I'll let you know how it goes Thanks for your interest. |
|||
25 May 2015, 19:28 |
|
DergMoney 25 May 2015, 20:14
El Tangas, you're a star. Created my new window with calculator as owner and all is good
btw, closing the calculator doesn't close my new window because it has a separate WndProc Thanks |
|||
25 May 2015, 20:14 |
|
El Tangas 25 May 2015, 20:49
Cool
Can you post the code? Might be useful. |
|||
25 May 2015, 20:49 |
|
DergMoney 25 May 2015, 22:00
El Tangas wrote: Cool The extra WndProc in the code doesn't actually do anything as it is a test example to add to a bigger project but here ya go Code: format PE GUI 4.0 entry start include "%fasminc%\win32a.inc" section '.code' code readable executable start: invoke GetModuleHandle, 0 mov [wc.hInstance], eax mov [wcHUD.hInstance], eax invoke LoadIcon, 0, IDI_APPLICATION mov [wc.hIcon], eax mov [wcHUD.hIcon], eax invoke LoadCursor, 0, IDC_ARROW mov [wc.hCursor], eax mov [wcHUD.hCursor], eax invoke RegisterClass, wc invoke RegisterClass, wcHUD or eax,eax jz error invoke CreateWindowEx, NULL, ClassMain, AppName, WS_OVERLAPPEDWINDOW or WS_VISIBLE, 100, 100, 600, 200, NULL, NULL, [wc.hInstance], NULL test eax,eax jz error mov [hWndMain], eax invoke EnumWindows, EnumWindowsProc, 0 msgLoop: invoke GetMessage, msg, NULL, 0, 0 or eax, eax jz endLoop invoke TranslateMessage, msg invoke DispatchMessage, msg jmp msgLoop error: invoke MessageBox, NULL, errorStr, NULL, MB_ICONERROR + MB_OK endLoop: invoke ExitProcess, [msg.wParam] proc WndProc hwnd, wmsg, wparam, lparam push ebx esi edi cmp [wmsg], WM_DESTROY je .wmDestroy .defWndProc: invoke DefWindowProc, [hwnd], [wmsg], [wparam], [lparam] jmp .finish .wmDestroy: invoke DestroyWindow, [hWndHUD] invoke PostQuitMessage, 0 xor eax, eax .finish: pop edi esi ebx ret endp proc EnumWindowsProc hwnd, lparam push ebx esi edi invoke GetWindowText, [hwnd], strBuff, 1000 or eax, eax jz .retTrue invoke lstrlen, strBuff mov ecx, eax mov al, "C" mov edi, strBuff repne scasb jne .retTrue mov esi, searchStr + 1 invoke lstrlen, searchStr dec eax mov ecx, eax rep cmpsb jne .retTrue invoke GetClassName, [hwnd], strBuff, 1000 invoke lstrlen, psClass mov ecx, eax mov esi, psClass mov edi, strBuff rep cmpsb jne .retTrue ; have found the calculator window ; int3 push [hwnd] pop [hWndPS] invoke CreateWindowEx, WS_EX_LAYERED, ClassHUD, NULL, WS_POPUP or WS_VISIBLE, 800, 100, 150, 75, [hWndPS], NULL, [wcHUD.hInstance], NULL test eax,eax jz error mov [hWndHUD], eax invoke SetLayeredWindowAttributes, [hWndHUD], 0, 255, LWA_ALPHA invoke SetFocus, [hWndPS] .retFalse: mov eax, FALSE jmp .finish .retTrue: mov eax, TRUE .finish: pop edi esi ebx ret endp proc WndProcHUD hwnd, wmsg, wparam, lparam push ebx edi esi .defWndProc: invoke DefWindowProc, [hwnd], [wmsg], [wparam], [lparam] jmp .finish .finish: pop esi edi ebx ret endp showError: pushad invoke GetLastError invoke FormatMessage, FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, eax, LANG_NEUTRAL, errStrBuff, 0, NULL invoke MessageBox, HWND_DESKTOP, [errStrBuff], NULL, MB_ICONERROR or MB_OK popad ret section '.data' data readable writeable ClassMain db "WinClass", 00 ClassHUD db "hud", 00 hWndHUD dd ? AppName db "My App", 00 errorStr db "oops!", 00 hWndMain dd ? hWndPS dd ? psWndProcHnd dd ? titlePS db 1002 dup ? strBuff db 1002 dup ? wordBuff db 40 dup ? space db " ", 00 errStrBuff dd ? wc WNDCLASS CS_HREDRAW or CS_VREDRAW, WndProc, 0, 0, NULL, NULL, NULL, COLOR_BTNFACE + 1, NULL, ClassMain msg MSG searchStr db "Calculator", 00 rect RECT numStr db "%i", 00 psClass db "CalcFrame", 00 wcHUD WNDCLASS CS_HREDRAW or CS_VREDRAW, WndProcHUD, 0, 0, NULL, NULL, NULL, COLOR_BTNFACE + 4, NULL, ClassHUD section '.idata' import data readable writeable library kernel32,'KERNEL32.DLL',\ user32, 'USER32.DLL',\ gdi32, 'GDI32.DLL',\ comdlg32,'COMDLG32.DLL',\ advapi32,'ADVAPI32.DLL',\ comctl32,'COMCTL32.DLL',\ msvcrt, 'msvcrt.dll' include '%fasminc%\api\Kernel32.inc' include '%fasminc%\api\User32.inc' include '%fasminc%\api\Gdi32.inc' include '%fasminc%\api\Comdlg32.inc' include '%fasminc%\api\Advapi32.inc' include '%fasminc%\api\Comctl32.inc' import msvcrt,\ sprintf,'sprintf' |
|||
25 May 2015, 22:00 |
|
El Tangas 26 May 2015, 00:21
Tnx. It's just that I haven't programed in windows for some years, so I just enjoy looking at some code snippets to refresh my memory. Its ok if the code is not complete.
|
|||
26 May 2015, 00:21 |
|
DergMoney 26 May 2015, 01:12
El Tangas wrote: Tnx. It's just that I haven't programed in windows for some years, so I just enjoy looking at some code snippets to refresh my memory. Its ok if the code is not complete. The code given is complete. If you compile this and open the windows calculator program, the black box I create will stay above it in z-order but not any other unconnected apps. In case you have any problems compiling it here is the executable
|
|||||||||||
26 May 2015, 01:12 |
|
El Tangas 26 May 2015, 09:06
Tnx. No problem recompiling (reassembling, actually ), but I found a problem if you want to release your complete project later (some calculator add-on, I guess?). Since you search for "Calculator", it can't find my calc because my windows is not in english. I recompiled with the correct string in my language "Calculadora", works fine.
|
|||
26 May 2015, 09:06 |
|
DergMoney 26 May 2015, 09:21
Thanks for the heads-up on the language issue you encountered. I only aimed my example at the windows calculator since all viewers of this thread running windows will have it on their computer.
I probably won't make this into a commercial package but afaik the application it is aimed at always has its title bar in english anyway. Other language users get all the menus etc in their chosen language, just not the title bar. It is something I would check in more depth of course if I did decide to go further |
|||
26 May 2015, 09:21 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.