WM_KEYDOWN doesn't response - c++

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.

Related

How to show custom messages in a dialog box in Win32 API?

How to show custom messages using a dialog box in Win32 API rather than show them in a default MessageBox function?
I made a function as follows:
void DialogBox_Custom (HWND hWndParent, LPSTR contentToShow)
{
HWND hDialog = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), hWndParent, DialogProc);
if (!IsWindowVisible(hDialog))
{
ShowWindow(hDialog, SW_SHOW);
}
SetDlgItemText(hDialog, IDC_EDIT1, contentToShow);
}
But when I call this function, the dialog box is appearing like millions of times per second and never ending until I close the program by force.
Please kindly someone help me make a custom dialog box where I can show some content sent from the parent window to an EDIT control window in the dialog box.
Use the DialogBoxParam function to create the modal (suspend execution until the window is closed) dialog box.
DialogBoxParam(instance, MAKEINTRESOURCE(IDD_YOURDIALOG), hWndParent, YourWndProc, (LPARAM)contentToShow);
You then have to create a function YourWndProc to handle the messages to paint and offer a mechanism to close the window, to allow execution to continue after your DialogBox() call.
INT_PTR CALLBACK YourWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
SetDlgItemText(hDlg, IDC_EDIT1, (LPSTR)lParam);
return (INT_PTR)TRUE;
case WM_CLOSE:
EndDialog(hDlg, LOWORD(wParam));
break;
}
return DefWindowProc(hDlg, message, wParam, lParam);
}
Modal dialogs are similar to MessageBox: your code gets control back when the dialog is closed. API: DialogBox, DialogBoxIndirect.
Modeless dialogs are similar to windows: you create them with the help of dialog templates and you get the control back immediately, they live powered by message dispatch. This is what you do but you expect them to act as if they were modal. API: CreateDialog, CreateDialogIndirect.
With both modal and modeless dialog you control the dialog with your own DialogProc and you create the dialog with resource dialog template, which automatically creates controls (and you, of course, can add control in code).

C++: How to set a new wndProc for a console application?

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.

Close callback or WM_CLOSE from a HWND reference

I'm calling the HtmlHelpA winapi method to display the .chm of my app. This method returns a HWND immediatelly, and the help window is shown as a separate window.
Along with the window, I set a timer for this hwnd. My problem is that I need to know when this window gets closed to kill the timer.
My first approach was trying to register the WndProc callback, but I couldn't do that because I'm not creating the window, I only have a reference to the hwnd.
Then I tried with a hook (SetWindowsHookEx) but the HOOKPROC won't bring the HWND as a parameter to the callback. Besides, I need to know the thread for this hwnd.
Is there any way to register a callback when a HWND gets closed or having a WndProc to wait for the WM_CLOSE message?
If required you can register a new window procedure for an existing window. Check out the documentation on SetWindowLongPtr().
Invoking it like this:
SetWindowLongPtr(hwnd, GWLP_WNDPROC, &MyCustomHelpWindowProc);
Just remember that window subclassing is very delicate. You might want to store the old window procedure somewhere and invoke that rather than DefWindowProc() for messages you are not interested in.
You want to subclass the help window. Subclassing gives you a chance to spy on all the messages going to the window proc. You do whatever additional work you need when you see a message of interest, and then pass the message on to the original window procedure for normal processing.
LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
WNDPROC fnOldProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hwndHelp, GWLP_WNDPROC, &MyWndProc));
LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
if (msg == WM_CLOSE) {
// Kill your timer here.
}
return CallWindowProc(fnOldProc, hwnd, msg, wp, lp);
}

How to handle keyboard events in a winapi standard dialog?

i don't often work with winapi, i'm writing almost .NET code. But at this time I have to use the winapi to make a simple dialog. There i want to handle some keyevents. Therefore i watched for the corresponding callback message WM_KEYDOWN or WM_KEYUP at MSDN and added it to my callback function.
INT_PTR CALLBACK cbfunc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch(message) {
// ...
case WM_KEYUP:
MMsgBox("up"); // I never get here
return 0;
case WM_KEYDOWN:
MMsgBox("down"); // I never get here
return 0;
// ...
}
return 0;
}
But neither WM_KEYUP nor WM_KEYDOWN ever get triggered. Then I stated looking for a solution for this problem. I thought may my dialog eats this messages. So I added:
case WM_GETDLGCODE:
return DLGC_WANTALLKEYS;
With the result that it doesn't help.
Other solutions I've found were the following:
Alternatively using the WM_GETDLGCODE event to handle this keys as suggested on here.
I've found a lot of threads (like this one) talking about a method called PreTranslateMessage. But I don't even have got this class, because I simply create my dialog by using DialogBoxParam
So none of them worked for me. In the moment i have got no idea how to handle it. Something I've noticed, is that on key press a WM_COMMAND message seems to occur.
Regards Nem.
According to this link, certain messages are hard to trap with dialog boxes because Windows processes them internally and they never get to the DialogProc. Here are two of the options I can think of:
Use GetAsyncKeyState on a WM_COMMAND event
Create a custom dialog box, the DialogProc for which will handle WM_KEYDOWN etc. messages.
DialogProc doesn't receive WM_KEY events (and many others too). You can:
Subclass the dialog window (overwrite its WndProc) and process all
messages there, sample
Register hot key for the dialog window's HWND and then receive WM_HOTKEY in DlgProc (but registered key combinations will be system-wide)
Create your own message loop, link
Replace This
case WM_KEYUP:
MMsgBox("up"); // I never get here
return 0;
case WM_KEYDOWN:
MMsgBox("down"); // I never get here
return 0;
With This
case WM_KEYUP:
MMsgBox("up"); // I never get here
break;
case WM_KEYDOWN:
MMsgBox("down"); // I never get here
break;

not properly closing from taskbar closing event

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.