DefWindowProc() issue - c++

VS2008, c++, mfc
I have to handle messages from the child windows in the parent window. In fact i want to handle only ON_BN_CLICKED messages and then make some ather actions.
As i understood i have to redefine WindowProc():
LRESULT CDLauncherDlg::WindowProc(UINT mes, WPARAM wp, LPARAM lp)
{
HWND hWnd = this->m_hWnd;
switch (mes){
case WM_COMMAND:
if((LOWORD(wp)==IDC_BUTTON4)&& (HIWORD(wp) == BN_CLICKED))
{
MessageBox("Button pressed.", "", 0);
}
break;
}
return DefWindowProc(mes, wp, lp);
}
Unfortunatelly, after pressing Cancel button DefWindowProc() does nothing and i can't close the application.
What's the problem?

The final answer was to replace
return DefWindowProc(mes, wp, lp);
with
return CDialog::WindowProc(mes, wp, lp);

Your code snippet doesn't indicate you're handling a WM_CLOSE message, or that you're explicitly calling DestroyWindow() when IDC_BUTTON4 is clicked. If this is a child window, and you want to terminate the application, you could call DestroyWindow() and then somewhere later PostQuitMessage().
If your snippet here is the windowproc for your parent window, and the handling of IDC_BUTTON4 is the parent window receiving the original message that you handled in the child and passed to the parent, simply call PostQuitMessage() where you've put the call to MessageBox().

Related

How to ignore injected input in only one window?

I have two devices that create keyboard input, one of them is a real keyboard and the other uses SendInput() to send Injected keyboard input. I am modifying an existing program that uses a hook to send the keyboard message only to its own window and blocks the input globally to other programs. However I do not want the Injected input to be blocked, and I also don't want the program to process the Injected input.
I used a WH_KEYBOARD_LL hook to determine if the input is Injected, Then I used a global WH_KEYBOARD hook to send the message only to the window if it is the real keyboard. What I am looking for is a way to sendMessage() to everything except the main window. I couldn't find a method in the documentation to do this though, so I decided to pass the hook farther down.
// WH_KEYBOARD
static LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
if (code < 0) {
return CallNextHookEx(hookHandle, code, wParam, lParam);
}
//Report the event to the main window, but do not pass it to the hook chain
if (realKeyboard) {
SendMessage(hwndServer, WM_HOOK, wParam, lParam);//only listen to real keyboard, block emulated one
}
else {
//what i want is to sendMessage to everythng except the main window
return CallNextHookEx(hookHandle, code, wParam, lParam); //let injected keyboard passthrough
//however we want to ignore injected inputs in the main window(keyboard program).
}
return 1;
}
I created a local WH_GETMESSAGE hook using GetCurrentThreadId(), to see if I could ignore the injected input there.
// WH_GETMESSAGE
static LRESULT CALLBACK GetMessageProc(int code, WPARAM wParam, LPARAM lParam) {
if (code < 0) {
return CallNextHookEx(hookHandle, code, wParam, lParam);
}
if (!realKeyboard) {
MSG * info = (MSG *)lParam;
info->message = WM_NULL;
}
return CallNextHookEx(hookHandle, code, wParam, lParam);
}
I read somewhere that info->message = WM_NULL; would work to block the message but it doesn't seem to have an effect. I also Tried creating a message loop something like this but it didn't work either.
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
if(IsRealKeyboard()){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Any ideas how I can ignore the injected message only in the main window and let it through to the rest of the system?
You could use RAW INPUT in the target window and process the WM_INPUT message, then get the Raw Input buffer via GetRawInputData.

Handling window messages in wndproc vs MSG, what's the difference?

I noticed that MSG from winuser.h (which is typedef'd to tagMSG) contains all the parameters from wndproc callback.
I was wondering if there's any real difference handling messages in wndproc vs handling the outside of wndproc by using MSG, along with the different use cases between the two
Basically something like the following
LRESULT WinApp::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
{
DestroyWindow(hwnd);
}
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
vs
MSG msg;
if ((PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
switch (msg.message)
{
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
{
DestroyWindow(hwnd);
}
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
Each window is associated with a WindowProc function. Both queued and non-queued messages that are dispatched to a window will arrive in its WindowProc. This is the preferred place to process messages that are specific to each window.
MSG is used when retrieving queued messages from a thread's message queue, before dispatching the messages to their target windows (see DispatchMessage()) . Processing messages directly in the message loop is the preferred way to handle messages that are specific to a thread but not necessarily to a specific window.
Basically it's the same, in terms of code processing and execution.
But, the main difference goes from the SendMessage function's family:
The SendMessage function calls the window procedure for the specified window...
Generally speaking, in Windows world each window has its own window's procedure, that can be called outside of the thread's message loop this window belongs to. As opposed to the PostMessage function, that:
Places (posts) a message in the message queue associated with the thread that created the specified window
So now it's clear, that messages might be handled in the main message loop, but in this case you are able to handle only the thread's messages. But you lose the ability to handle messages that was sent directly to your WndProc.
The difference is that using the normal message loop will handle cases involving multiple window classes, each with its own WndProc. What you show will only work if there is only going to be one set of message handlers for all windows (including popup menus).

Win32: C++: How do I re-focus on Parent Window after clicking in a child window?

In my Win32 CPP program, I have defined some Child Window to display various text strings using something like:
hnd_to_this_ch_window = CreateWindow(
L"EDIT",L"Some initial text", WS_VISIBLE | WS_CHILD | ES_LEFT,
position_of_this_window_X,
position_of_this_window_Y,
TEXTOUT_DEFAULT_WIDTH,
TEXTOUT_DEFAULT_HEIGHT,
handle_to_my_parent_window, NULL,
hinstance_variable_used_by_create_window,
NULL )
My problem is that if I click with my mouse to select the text in one of such child windows (to, say, copy it somewhere), the focus of the application goes to this child window and so any keypresses which used to be handled through my main windows CALLBACK (with case WM_KEYDOWN:) are now captured into the child window, where they appear as inputted characters. What magic function do I call to have the focus go back to the parent (so that my WM_KEYDOWN) can work again? I was hoping I could just click on the main Window's title bar and that would take it back to normal, but that isn't working (because, obviously, my program is lacking some extra logic).
Handle the WM_KILLFOCUS message in the window procedure of the window you want to focus, and restore the focus using the SetFocus function.
If you want to focus the window when it is clicked, handle the WM_LBUTTONDOWN message.
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
// Restore the focus when it was lost.
if (Msg == WM_KILLFOCUS) {
SetFocus(hWnd);
// Msg was handled, return zero.
return 0;
}
// Or when the window is clicked.
if (Msg == WM_LBUTTONDOWN) {
SetFocus(hWnd);
// Msg was handled, return zero.
return 0;
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
case WM_KEYDOWN:
SetFocus(Parent_Hwnd);
return SendMessage(Parent_Hwnd,WM_KEYDOWN,wParam,lParam);

C++ Modeless Dialog created from DLL doesn't process input properly

I am having issues with creating a modeless dialog from a DLL file. My dialog has nothing special on it, just an OK button and an edit box. I have looked at this Microsoft KB Article (http://support.microsoft.com/kb/233263) and have implemented its solution to create a window hook to grab and process messages.
The method provided by Microsoft solves the tab key problem, however, it creates another problem. When I type into the edit box on the dialog, whatever I press is duplicated 4 times. For example, if I press 'a' on the keyboard, 'aaaa' will show up in the edit box.
If I disable the Window Hook, then the edit box works correctly and only displays one 'a'.
What do I need to do to the Window Hook procedure to solve this problem?
Any help is greatly appreciated.
- - EDIT - -
As per request, my Window Hook Procedure Code: (It's the same as the KB article)
LRESULT FAR PASCAL GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) {
LPMSG lpMsg = (LPMSG) lParam;
if (nCode >= 0 && PM_REMOVE == wParam) {
// Don't translate non-input events.
if ((lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST)) {
if (IsDialogMessage(hwndDllDlg, lpMsg)) {
// The value returned from this hookproc is ignored,
// and it cannot be used to tell Windows the message has been handled.
// To avoid further processing, convert the message to WM_NULL
// before returning.
lpMsg->message = WM_NULL;
lpMsg->lParam = 0;
lpMsg->wParam = 0;
}
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
My Dialog Callback Procedure:
BOOL CALLBACK DllDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_INITDIALOG:
hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, GetCurrentThreadId());
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
DestroyWindow(hwndDlg);
hwndDllDlg = NULL;
}
return TRUE;
case WM_DESTROY:
UnhookWindowsHookEx(hHook);
return FALSE;
}
return FALSE;
}
}
Both hHook and hwndDllDlg are defined as HHOOK and HWND respectively.
HHOOK hHook;
HWND hwndDllDlg = CreateDialog(0, MAKEINTRESOURCE(DLG_MAIN), 0, DllDlgProc);
I looked at the KB article. It sounds reasonable. There is some point where you was not enough accurate while following the instructions from KB. Post your code. This may help.
If you have control over the message pump of the executable and can add IsDialogMessage there, then you do not need any hook. Code from the dll is part of the code of the process. Window handles are in the common space either.
Other approach is starting your own UI thread. If you create your dialog on this thread, then you will have your own message pump. The hook will not be needed in this case either.
Well, this is more of a question to author of the post..
I have the tab key issue and am trying to understand the microsoft article better.
So my dialog is shipped out as Dll and the application which I don't have access to is launching dialog from my dll.
HWND hwndDllDlg = CreateDialog(0, MAKEINTRESOURCE(DLG_MAIN), 0, DllDlgProc);
I don't understand what dialog the code refers to when they said hwndDllDlg in the article. Should I point my dialog creation to this variable ?

WM_PASTE hook not working

I want to detect everytime I paste something. It's just something to make some data entry work simpler.
I set a global hook and then "wait" for the wm_paste. This is part of the code I have:
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode < 0)//Do not process the message
return CallNextHookEx(msg_hook,nCode,wParam,lParam);
LPMSG m=(LPMSG)lParam;
if(m->message == WM_PASTE)
{
OutputString("Paste detected!\n");
}
if(m->message == WM_PASTE)
{
OutputString("Paste detected!\n");
}
return CallNextHookEx(msg_hook,nCode,wParam,lParam);
}
//DLL_ATTACH:
...
if(strstr(ProcName, LOADERNAME))
{
InitCommonControls();
if(!(msg_hook=SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, hinstDLL, 0)))
{
ErrorExit(TEXT("SetWindowsHookEx"));
//MessageBox(0, "WH_GETMESSAGE", 0, 0);
//return -1;
}
}
WM_PASTE debug string never gets printed. I'm aware that not all applications use WM_PASTE. But at least notepad should work.
Any suggestions?
Thanks!
In GetMsgProc, the wParam parameter is not the message being intercepted, but a flag that indicates whether or not the message in lParam and been removed from the message queue.
You should be using m->wParam instead.
Wm_paste message is fired only in combo box and edit control. There is no easy way to capture paste, but you can get copy message by creating a tiny window and adding this window to the chain of clipboard viewers.