I'm working on a WinUI3 desktop application in C++. I'm trying to build a multiwindow application that will be still running and accepting events even when all the Windows are closed.
In WinUI3, the event loop(Application::Start()) will terminate when the last window is closed. I was not able to find any way to keep the WinUI3 event loop running when all the windows are closed.
But I was able to achieve it in one way, i.e I extracted the HWnd from the WinUI3 window and subclassed it, And handled WM_DESTROY message like this.
LRESULT CALLBACK
MyWindowClass::WindowSubClassProc(HWND hWnd, UINT messageCode, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (messageCode)
{
case WM_DESTROY:
// PostQuitMessage(0);
return 0;
This stopped the event loop to terminate as I didn't do PostQuitMessage(0);
Then when I actually needed the application to terminate, I called PostQuitMessage(0); to stop the event loop and close the application.
As this is one work around I could think of, is there any better way to achieve it?
I would be of great help if you could help me with this.
Thank you
Related
In case WM_KEYDOWN has a messagebox() in order to understand the functionality of this case.
somebody can help me why this case didn't response?
I'm trying to do debugging this while i insert some letter from keyboard and debugger not coming to WM_KEYDOWN case.
Thanks to all!
this is my code:
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_CREATE:
break;
case WM_COMMAND:
break;
case WM_KEYDOWN:
MessageBox(NULL,L"test",L"Information",MB_ICONINFORMATION);
break;
case WM_DESTROY:
// DESTROY WINDOW
break;
default:
return DefWindowProc( hwnd, msg, wParam, lParam );
}
return 0;
}
MessageBox() displays a popup dialog and then runs its own modal message loop to service messages for that dialog until it closes. While the dialog is active, your keystrokes are going to that dialog and not to the window that your WndProc() belongs to. That is why you are not getting more WM_KEYDOWN messages. You should not be using MessageBox() as a debugging tool for UI messages, because it changes the flow of UI messages. Use OutputDebugString() instead. That way, your debugger (or an external viewer like SysInternals DebugView) can display your debug messages without affecting your UI's behavior.
I am currently writing an application which allows scrolling, without focusing windows.
What I've done yet: I created a LowLevelMouseHook. If the LowLevelMouseProc recieves a MouseWheel-message I am searching for the handle at the cursor-position and send scroll-messages to that handle.
The hook looks like this:
LRESULT CALLBACK MouseHookCallback(int code, WPARAM wparam, LPARAM lparam)
{
if(code < 0)
return CallNextHookEx(mouseHookInstance, code, wparam, lparam);
if(UserMouseHookCallback != NULL)
{
UserMouseHookCallback(code, wparam, lparam);//scroll the hovered window here
if(wparam == WM_MOUSEWHEEL)
return -1;
}
return CallNextHookEx(mouseHookInstance, code, wparam, lparam);
}
As you can see, I am returing -1 if the message is a mousewheel-message. That should avoid scrolling the currently focused window(I don't want to scroll the focused window, I want to scroll the window which is hovered by the cursor). The problem is, that it does not cancel scrolling the focused window. So does anyone has an idea how to avoid scrolling the currently focused window? At the moment there are two windows which are getting scrolled. The one my mouse is hover and the one which is focused.
Please don't downvote my question and give me a chance. I am really doing my best but I am not able to find a solution.
I've found the solution. It is very, very, very simple. Set <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> in your manifest or start it as administrator manually and it works :)
If I have a console application with a handle to it set up like so;
HWND hWnd = GetConsoleWindow();
Then how do I set up a new wndProc for the window?
I tried using
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)conProc);
With conProc being defined as
LRESULT CALLBACK conProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_NCHITTEST:
return HTCAPTION;
}
return DefWindowProc(hWnd, msg, wParam, lParam );
}
But it doesn't work and says "Error code: 5 - Access is denied" on GetLastError()
I understand that it's pretty difficult to modify the console application like this, since it's a csrss.exe application and all, but I'd still like to try..
Thanks.
While the impression is that console window belongs to your process (like other window), it is in fact hosted by CSRSS system process and its WndProc is there. This makes you unable to subclass the window and provide your own WndProc living in your process.
Some related reading:
The process that is in charge of displaying the GUI windows in which consoles are presented is... CSRSS
SetWindowsHookEx with WH_KEYBOARD doesn't work for me, what do I wrong?
Subclassing XP Console Window
First of all SetWindowLong is superseded by SetWindowLongPtr, you should use that function.
Are you trying to change the WNDPROC of your own console window or another process?
From the MSDN docs :
GWL_WNDPROC
-4
Sets a new address for the window procedure.
You cannot change this attribute if the window does not belong to the same process as the calling thread.
Hello everyone I am new to windows32 programming and I have a couple of questions-:
When I use the following code in a program it works fine -:
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
But when I replace null of GetMessage to hwnd(the handle of the window just created) the doesn't seem to close it still remains running in the background. Why does this happen when I replace NULL with hwnd means I am receiving messages for only one window then why doesn't it work????
while(GetMessage(&msg,hwnd,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
By the way the windows function is-:
LRESULT CALLBACK WinProc(HWND hWnd, UINT message,
WPARAM wparam, LPARAM lparam){
switch(message){
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wparam, lparam);
}
return 0;
}
Secondly-:
Is there any way I can see all the messages sent to any particular window????
Thirdly-:
What is the reason behind writing __stdcall(WINAPI) when compiling my windows programs ????
A quick reply would be appreciated.Thank You.
GetMessage returns 0 (making the loop end) only when it receives a WM_QUIT, but a WM_QUIT is not associated to any particular window, so it is never received if you have a GetMessage that asks only messages for a certain hWnd.
If it's a window of yours, you already see them inside their window procedure; if you want to filter them before dispatching them to their window procedure, you can check the msg structure that is populated by GetMessage before calling DispatchMessage.
The whole Windows API uses the stdcall calling convention (I think because it is slightly faster/produces less boilerplate code than the usual cdecl), so also your callbacks must follow that calling convention. Notice that you must use WINAPI (i.e. stdcall) only on functions that are called by Windows API functions, for the other ones you are free to use whatever calling convention you like best.
PostQuitMessage generates WM_QUIT which is processed by the message queue, but not associated with a particular window. By filtering only hwnd messages in your call to GetMessage, you don't process WM_QUIT.
Regarding seeing all messages being sent to a window / thread / process, see https://stackoverflow.com/questions/4038730/i-am-looking-for-a-windows-spy-application
Finally, regarding __stdcall, see What does "WINAPI" in main function mean?
if i close my application via Alt-F4, or the corner "X" button, or by posting destroywindow(hwnd) myself, the application closes correctly, and everything works just as expected.
but recently i realized, on windows7, when i close the app by right klicking on the icon in the taskbar, and clicking "Close Window", the window closes, but my app is still running. when debugging, i don't get into either of the WM_QUIT/DESTROY/CLOSE events.
is there some special behavior when closing a window via taskbar? how can i detect that?
You should get WM_CLOSE. Maybe you're getting it on a different window that the one you're expecting? Although that shouldn't be able to happen unless you have multiple top-level windows.
via Alt-F4, or the corner "X" button, or by posting destroywindow(hwnd) myself
You can't post DestroyWindow(). Ensure that the window procedure of your main window resembles this:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
// Other cases
//...
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
The PostQuitMessage() function call ensures that your message loop exits, GetMessage() returns FALSE when it receives the WM_QUIT message. This makes your main window behave like the main window, closing it ends the process. You may have other top-level windows that don't, they shouldn't have this WM_DESTROY message handler. DestroyWindow() is already called automatically by DefWindowProc() when it processes the WM_CLOSE message.