How could I handle a Window's Message? - c++

I'm working on some CreateWindow things.
My work need I to insert a Button into one of an Application's Window, and when I click the button, my application can do something. That Application isn't my Application, so I think I need to do some "hook thing".
And I tried this:
HWND hwnd = FindWindowEx("className",NULL)
CreateWindowEx(...hwnd...)
Its worked. The Button successfully inserted into target application.
but when I try to handle that window's message
I failed.
This hwnd is belongs to my application hInstance, but my Application has its own message loop by CEF.
I tried SetWindowsHookEx,but its not working.
Whatever I do, it will not handled.
and if i use while(GetMessage (&messages, NULL, 0, 0)),it will block my application's thread
WNDCLASS xxx and RegisterClass(xxx)
or CreateWindow(className)
confused me.
I try to use LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) but the while() will block my application's thread
and in my application's wndProc, there is no WM_COMMAND message in.
HWND hwnd = FindWindowEx(0, 0, L"TCustomBaseForm" , NULL);
HWND hwndButton = CreateWindowEx(0L,_T("Button"), L"Btn", WS_CHILD|WS_VISIBLE| BS_PUSHBUTTON, 435, 45, 35, 45, hwnd, NULL, GetModuleHandle(0), 0);
DWORD dwProcId = 0;
DWORD dwThreadId = 0;
dwThreadId = GetWindowThreadProcessId(hwndButton, &dwProcId);
SetWindowsHookEx(WH_MOUSE, Hookproc, g_hInstance, dwProcId);
Until now, my "inserted button" never work.
So, is there any way to make this "inserted window" or button same as a MFC button that, when I click it, I can handle a message like WM_LBUTTONCLICK in my WndProc?

A button sends a WM_COMMAND message to its parent window when you click it.
There are at least two ways to deal with this without hooking:
Create the button as a child of a STATIC control (or a custom window) that you also create. You need to subclass the STATIC control to receive the message.
Subclass the button and catch the mouse up message and space/enter key-down messages.

Thank you all. I did it.
I create a Window that have a button. And I use SetParent(myWindowHwnd,myTargetWindowHwnd) and handle the button's click event in my window, it works.
No hook, no problems.
Thank you all very much.
And thanks for edit my question, for my poooooooooooor English.
I've learned a lot about Windows Hook.

Related

Determine which window the message was sent (SetWindowsHookEx & WH_KEYBOARD)

I need to be able to determine which window the message is intended for, but I don’t understand how to do it correctly. In WH_MOUSE has a special structure (MOUSEHOOKSTRUCT) that stores the hwnd of the window, but where to get the hwnd in WH_KEYBOARD?
LRESULT CALLBACK messageHandler(int nCode, WPARAM wParam, LPARAM lParam)
{
// ???
}
DWORD WINAPI messageDispatcher(LPVOID thread)
{
hookHandle = SetWindowsHookEx(WH_KEYBOARD, messageHandler, GetModuleHandle(nullptr), *reinterpret_cast<DWORD*>(thread));
if (!hookHandle)
{
return GetLastError();
}
MSG message{};
while (GetMessage(&message, 0, 0, 0) > 0)
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return 0;
}
In theory, I could use GetForegroundWindow, but it seems to me that this is a terrible option, because the window can receive a keyboard message from some other process (if another process sends a SendMessage to this window) and not the fact that the current window will be exactly the one for which the message was intended.
At the time a keyboard action is generated, the OS doesn't know yet which window will eventually receive the message. That is why the WH_KEYBOARD hook doesn't provide a target HWND, like a WH_MOUSE hook does (since a mouse message carries window-related coordinates).
When a keyboard message is being routed to a target, the message gets delivered to the window that currently has input focus.
Per About Keyboard Input:
The system posts keyboard messages to the message queue of the foreground thread that created the window with the keyboard focus. The keyboard focus is a temporary property of a window. The system shares the keyboard among all windows on the display by shifting the keyboard focus, at the user's direction, from one window to another. The window that has the keyboard focus receives (from the message queue of the thread that created it) all keyboard messages until the focus changes to a different window.
Since your hook runs inside of the message queue of the target thread, you can use GetFocus() to get the target HWND at that time:
Retrieves the handle to the window that has the keyboard focus, if the window is attached to the calling thread's message queue.
Otherwise, you can use a WH_CALLWNDPROC/RET hook instead, which gets called when the message is actually delivered to a window. However, you can't block messages with this hook (as you were asking about in your previous question).
I think what you might be looking for is a hook of type WH_JOURNALRECORD.
With this, the callback procedure that Windows will call in response to the various events that this hook intercepts is of type JournalRecordProc, and the lparam parameter passed to this function points to an EVENTMSG structure, which looks like this:
typedef struct tagEVENTMSG {
UINT message;
UINT paramL;
UINT paramH;
DWORD time;
HWND hwnd;
} EVENTMSG;
And there is your hwnd!

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).

How can I get a winMain's hInstance? windows32 programming

How can I get a winMain's HWND hwnd's hInstance application handle without using globals? I'm trying to make a dialog box to be sent to the LRESULT CALLBACK to have certain menu items make it show up.
Or is different way to set this up. I've done it with globals already but I can't seem to figure out how to set it up inside the LRESULT CALLBACK
I tried
HINSTANCE hInst = (HINSTANCE)GetWindowLongPtr(hwnd, GWL_HINSTANCE);
HWND hDlgbox = CreateDialog(hInst, MAKEINTRESOURCE(ID_TOOL_BOX_CREATE) ,hwnd, ToolProc);
in the wndproc but that only makes it show up once then never appears again when I try to open it using a popupmenu item and the buttons and items don't seem to receive messages in the dialog box when made this way in the wndproc.
So what I did was
in win main
HWND hdlg;
set wndextra to size of a hwnd.
then create your dlg box however you do it.
SetWindowLongPtr(hwnd, 0, (LONG_PTR)hdlg);
and in winproc
hwnd somenewDlg
somenewDlg = (HWND)GetWindowLongPtr(hwnd, 0);

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.

Create child window in WM_CREATE, relevance of same thread?

A typical pattern is to create a child window in the message callback (WndProc) at message WM_CREATE:
LRESULT APIENTRY WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
...
switch (message) {
case WM_CREATE:
....
hwndChild[i] = CreateWindow (szChildClass[i], NULL, WS_CHILDWINDOW | WS_BORDER ...
I perfectly understand this is a good opportunity, but is it a problem to do it any time later? One reason for doing so is that the child window is created within the same thread. But is there any other reason?
And how important is to create the child window in the same thread (as the parent)? As of " Can a child thread of parent GUI dialog thread create a child window? " this seems to be no general problem?
It's no problem to create your child window later, however, as you have mentioned, it should be created from the same thread.
For instance, you can create a child window inside a WM_COMMAND message handler (e.g. when a user clicks on a button) or as a response to WM_TIMER.
Creating a child window from another thread is a bad idea, as each thread has its own message queue. However, if you want another thread to initiate creating the window, you can work around it by sending a user-defined message to your window:
Define your message (e.g. #define WM_CREATEMYWINDOW WM_USER + 123)
From another thread post it to your window:
PostMessage(g_hWnd, WM_CREATEMYWINDOW, 0, 0);
In your window procedure create the child window:
if (message == WM_CREATEMYWINDOW)
hwndChild[i] = CreateWindow(...);