I'm working on a portability layer for OpenGL (abstracts the glX and wgl stuff for Linux and Windows)... Anyhow, it has a method for creating a Window... If you don't pass in a parent, you get a real window with a frame... If you pass in a parent, you get a borderless, frameless window...
This works fine, as long as I do it all on 1 thread... As soon as another thread tries to create a child window, the app deadlocks in the win32 call "CreateWindow()". Any ideas?
This is not a real answer, but since so many people seem to believe that Win32 forbids creating children in other threads than the parent, I feel obliged to post a demonstration to the contrary.
The code below demonstrates creation of a child window on a parent belonging to a different process. It accepts a window handle value as a command-line parameter and creates a child window on that parent.
// t.cpp
#include <windows.h>
#include <stdio.h>
#define CLASS_NAME L"fykshfksdafhafgsakr452"
static LRESULT CALLBACK WindowProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch ( msg )
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
break;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int main( int argc, char* argv[] )
{
HWND parent = (argc >= 2) ? (HWND)strtoul(argv[1], 0, 0) : (HWND)0;
printf("parent: 0x%x\n", parent);
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
wc.lpszClassName = CLASS_NAME;
wc.hbrBackground = (HBRUSH)(COLOR_ACTIVECAPTION + 1);
if ( !RegisterClass(&wc) )
{
printf("%d: error %d\n", __LINE__, GetLastError());
return 0;
}
const DWORD style = WS_CHILD | WS_VISIBLE;
HWND hwnd = CreateWindow(CLASS_NAME, L"Test", style, 50, 50, 100, 100,
parent, 0, wc.hInstance, 0);
if ( !hwnd )
{
printf("%d: error %d\n", __LINE__, GetLastError());
return 0;
}
MSG msg;
while ( GetMessage(&msg, 0, 0, 0) )
DispatchMessage(&msg);
return 0;
}
Compile this with the following command (using MSVC command line environment):
cl /EHsc /DUNICODE /D_UNICODE t.cpp user32.lib
Then use Spy++ or some other tool to obtain handle value of any window -- e.g. of Notepad or the browser you're viewing this site in. Let's assume it's 0x00001234. Then run the compiled sample with t.exe 0x1234. Use Ctrl-C to terminate t.exe (or just close the console window).
When a child window is created, it can interact with the parent window via SendMessage. But, note that SendMessage across thread boundary blocks threads unlike PostMessage. If the parent window's thread is waiting for the child thread, and the child thread is trying to create a window whose parent is in that thread, then it's a deadlock.
In general, I don't think it's a good idea to make child-parent relationship across the threads. It can very easily make deadlock.
There are a lot of replies here saying that you MUST NOT attempt to have child and parent windows on different threads, and rather emphatically stating that it will not work.
If that was so, Windows would put some safeguards in and simply fail out when you attempted to call CreateWindow.
Now, there definitely are thread coupling issues that can cause major issues, but, that said with those constraints, this is a supported scenario.
This is an interesting question: A lot of old school win32 guys have told me you CANNOT do this. In researching this, I found this forum: SendMessage(). My current theory is that CreateWindowEx() must send a message (via SendMessage(), so it blocks) to the parent window to ask for permission to exist (or at least to notify of its existence)... Anyhow, as long as that parent thread is free to process these messages, it all works...
A window is tied to the thread that creates it (more specifically, to that thread's message queue). A parent window cannot reside in a different thread than its child windows.
Related
For my college project I am developing a solution to distinguish between mouse user data from a person with Parkinson's compared to a healthy person. For which I need mouse data, ideally raw.
I presume I have misunderstood how to collect raw mouse input from the WM_INPUT message but I cannot figure it out.
I have been looking at the following thread: How to accurately measure mouse movement in inches or centimetres for a mouse with a known DPI
and Mouse input libraries on github all of which seem to easily catch a WM_INPUT message whose lParam is a handle to some RawInputData with something like this:
GetMessage(&msg, GetActiveWindow(), WM_INPUT, 0);
if (msg.message == WM_INPUT){ .....
And then retreiving the lParam from the message and collecting the data associated with that handle with:
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));
However when I call GetMessage in my main loop, the function never exits!
Consequently there is no way (that i know of) for me to get a handle to the RawInputData. Especially since the MSDN page just assumes you have the lParam already.
In summary I need a method of getting an lParam to pass to the GetRawInputData function which will remain active whether the program is running in the active window of not.
I'm running this code in a blank C++ CLR project in Visual Studio with the "winuser.h" library.
#include "stdafx.h"
#include "Windows.h"
#include "winuser.h"
#ifndef HID_USAGE_PAGE_GENERIC
#define HID_USAGE_PAGE_GENERIC ((USHORT) 0x01)
#endif
#ifndef HID_USAGE_GENERIC_MOUSE
#define HID_USAGE_GENERIC_MOUSE ((USHORT) 0x02)
#endif
int main(array<System::String ^> ^args)
{
RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE;
Rid[0].dwFlags = 0; //ideally RIDEV_INPUTSINK but that prevents registration
Rid[0].hwndTarget = GetActiveWindow(); //ideally this would be Null to be independent of the active window
if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) {
//registration failed. Call GetLastError for the cause of the error
Console::WriteLine("Registration Error");
}
MSG msg;
while (true) {
while (GetMessage(&msg, GetActiveWindow(), WM_INPUT, 0) != 0) { //this command is never completed
DispatchMessage(&msg); //this line is never ran
}
if (msg.message == WM_INPUT) {
Console::WriteLine("caught a message!!!");
}
}
}
Issue solved after much more research I found the winAPI walk through which I followed fixing the issue above by adding an:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE unused, PSTR cmd, int show) {.....}
Function to register devices and create a window then call GetMessage which calls LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {....} with the parameters occupied by the message ID,WParam and LParam corresponding the message event.
For anyone stuck with a similar issue follow this MSDN guide: https://msdn.microsoft.com/en-us/library/bb384843.aspx
As far as I understand, Windows makes a division of labor with regards to the (re)painting of a given window; the division into background erasure and foreground painting. The WM_ERASEBKGNDmessage is sent to prepare an invalidated portion of a given window for painting, and usually this preparation consists of erasing the background so the actual painting can commence of a clean canvas. It seems to me this message is always sent when Windows invalidates part of a given window (and so is basically always sent in conjunction with a WM_PAINT message being posted). Whenever the application itself invalidates (part of) a given window, the last argument to the InvalidateRect function specifies whether a WM_ERASEBKGNDis to be sent or not. So I wrote a small program to test my assumptions, but its behavior eludes me a little. This is said program:
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hwInstance, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = {0};
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Run the message loop.
MSG msg = {0};
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static int eb_count = 0; // counts number of WM_ERASEBKGND messages
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rect;
wchar_t text[40];
wsprintf(text, L"Number of WM_ERASEBKGND messages: %i\n", eb_count);
GetClientRect(hwnd, &rect);
DrawText(hdc, text, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps);
return 0;
case WM_RBUTTONDOWN: // repaint whenever RBUTTONDOWN
InvalidateRect(hwnd, NULL, FALSE);
UpdateWindow(hwnd);
return 0;
case WM_ERASEBKGND:
eb_count++;
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
I am handling WM_ERASEBKGND in the window procedure (it is a case in my switch), so it should not be passed to the default window procedure. However, I don't do any actual background erasing (I simply increment a static variable) and I return 0 to indicate that no erasing actually took place. It seems to me that in this program, the background should never get erased. This does, however, happen in two distinct instances.
Whenever I maximize the window, the background of the invalid portion does get erased with the class background brush. But how is this possible? The window procedure certainly does no such thing upon receiving a WM_ERASEBKGND message.
A similar thing happens whenever DrawText repaints its string. I would expect that the incrementing numbers would get painted on top of eachother (leading to an illegible mess, of course). So it seems the 'DrawText' function also somehow erases the background of the rectangle in which it paints its string.
My last question pertains to my assumption that a WM_ERASEBKGND message is sent whenever Windows invalidates part of a window. I noticed that whenever the window is covered by another window and subsequently uncovered, no WM_ERASEBKGND message seems to be sent. Does this mean my assumption is wrong?
Sorry for the long read, but any and all help in answering these questions would be greatly appreciated.
... my assumption that a WM_ERASEBKGND message is sent whenever Windows invalidates part of a window. I noticed that whenever the window is covered by another window and subsequently uncovered, no WM_ERASEBKGND message seems to be sent ...
That's because, as of Vista and later, we have the Desktop Window Manager (DWM) lurking away in the, erm, background. This buffers the contents of all the on-screen windows so that Windows doesn't need to issue WM_ERASEBKGND or WM_PAINT requests when part of one is uncovered - it can just copy the so-called back-buffer back to the screen.
[Parts of] windows do still get invalidated - either by you or the OS - but not as often as they used to be back in the XP days. Try minimising and restoring a window for example - then it has to be redrawn. When you do that, the DWM probably throws away the back-buffer to save memory while the window is minimised.
Apart from that, what the others said in the comments.
As per the answer by #Paul Sanders most recently the Desktop Window Manager is a process that does, actually, cache the contents of windows so it can perform a blend effects when composing the desktop, which means that your Window does not always get repainted in the way it did in earlier editions of Windows.
Prior to that, the move from a co-operatively multitasked to a multithreaded OS (This painting model was in the Windows 3.0 API) introduced some race conditions that, iirc, Windows would try and cover up by doing a pre-emptive background-brush fill in some cases when some process changed the visibility of another processes window. This is what you see when you maximise the window.
Your call to DrawText is working, because DrawText - by default - does its own background erase - you need to call SetBkMode passing in the TRANSPARENT flag to render just the font.
I'm working on a win32 c/cpp project involving openGL. I'm just starting and had a few basic questions regarding how a standard win32 program works. Following a tutorial, I made the winmain create a new window, enable openGL for the window, and then enter the main loop where if there are messages, the program handles them, and otherwise, the program moves onto drawing openGL animations. Following that, I simply shut down openGL and destroy the window. I'm not too confused about what's happening in here, but this is where I get lost:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message)
{
case WM_CREATE:
return 0;
case WM_CLOSE:
PostQuitMessage( 0 );
return 0;
case WM_DESTROY:
return 0;
case WM_KEYDOWN:
switch ( wParam )
{
case VK_ESCAPE:
PostQuitMessage(0);
return 0;
}
return 0;
default:
return DefWindowProc( hWnd, message, wParam, lParam );
}
though I do see in the winmain that I register this function to my window class via
wc.lpfnWndProc = WndProc;
How exactly does this process work? Can someone explain the pipeline to me - as the winmain method runs, it goes onto drawing the opengl animation, but as soon as a key is pressed, it enters message handling... and then what? How does my winmain method communicate with the WndProc method? What's actually happening from the machine's point of view?
In your WinMain there should be a pair of TranslateMessage / DispatchMessage calls. TranslateMessage is responsible for getting keystrokes being delivered correctly and DispatchMessage traverses the window hierachy to deliver the messages to the window that has the input focus, effectively calling the function which pointer was registered as default window message handler (Window Procedure) with the message as parameters.
I am writing a dll which is a COM wrapper for another dll (the inner dll) without COM support. The inner dll performs a lengthy computation and lets the outer dll know how progress is going via a callback function. The outer dll just makes the functions visible over COM.
However, I need the outer dll to pop up a progress bar dialog (the COM client I'm serving can't do this itself for various reasons). So how do I go about doing that? All examples I have seen so far revolve around Win32 apps which have a WinMain entry point; what can be done if we're already in a dll call when the dialog is needed?
I'm new to windows GUI programming, so quite out of my depth here. The existing code is included below - specific suggestions on what to call where would be appreciated. I'm guessing I may need to fire off a second thread to refresh the progress dialog.
Inner dll .h file (for implicit linking):
#define INNER_API extern "C" __declspec(dllimport)
//create calculation, passing callbacks for warning messages and progress bar
INNER_API Calculation* __stdcall calc_create(...blah...,
int (__cdecl *set_progressor_callback)(long),
int (__cdecl *print_warning_callback)(const char*));
INNER_API void __stdcall calc_run(Calculation *c);
Then in the outer dll, the com wrapper, ComWrapperObject.cpp:
int my_progressor_callback(long progress)
{
//set progressor to equal progress, but how?
return 0;
}
STDMETHODIMP ComWrapperObject::do_calculation()
{
//fire up progress bar and message window here, but how?
Calculation *calc = calc_create(...blah..., &my_progressor_callback);
calc_run(calc);
//wait for user to dismiss message window, but how?
return S_OK;
}
I'm posting a new answer which is more relevant to your updated question (and in order to be eligible for the bounty). Consider first this minimal source for a regular executable which contains a progress bar:
#include <Windows.h>
#include <CommCtrl.h>
#pragma comment(lib, "Comctl32.lib")
#include "resource.h"
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#define PROGRESSBAR_TIMER_ID 1
/*
* This callback is invoked each time the main window receives a message.
*/
INT_PTR CALLBACK DialogFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg) {
case WM_INITDIALOG: {
/*
* Fire a timer event each second.
*/
SetTimer(hwndDlg, PROGRESSBAR_TIMER_ID, 1000, NULL);
break;
}
case WM_TIMER: {
/*
* Catch the timer event that is fired each second. Increment the progress
* bar by 10% each time.
*/
HWND hwndProgressBar = GetDlgItem(hwndDlg, IDC_PROGRESS1);
UINT iPos = SendMessage(hwndProgressBar, PBM_GETPOS, 0, 0);
/*
* If the position is already full then kill the timer. Else increment the
* progress bar.
*/
if(iPos >= 100) {
KillTimer(hwndDlg, PROGRESSBAR_TIMER_ID);
} else {
SendMessage(hwndProgressBar, PBM_SETPOS, iPos + 10, 0);
}
break;
}
case WM_CLOSE:
EndDialog(hwndDlg, 0);
break;
default:
return FALSE;
}
return TRUE;
}
BOOL LaunchGUI(HINSTANCE hInstance)
{
return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogFunc) == 0;
}
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
/*
* Initialise the common controls DLL.
*/
INITCOMMONCONTROLSEX iccex;
iccex.dwSize = sizeof(iccex);
iccex.dwICC = ICC_PROGRESS_CLASS | ICC_STANDARD_CLASSES | ICC_WIN95_CLASSES;
if(!InitCommonControlsEx(&iccex)) {
MessageBox(NULL, L"Problem initialising common controls DLL.", NULL, MB_OK);
return -1;
}
/*
* Launches the main GUI window.
*/
LaunchGUI(hInstance);
return ERROR_SUCCESS;
}
If you like, I can post the relevant .rc resource file for this program although the code is mostly for you to gain the correct conceptual understanding. So to quickly summarise, this program:
Contains a single dialog containing a single progress bar
Sets a timer to fire each second
Each time the timer fires, the timer message triggers the progress bar to be updated
Graphically, it looks like this:
Your question is how to increment this bar from a DLL instead. What you need to do is to allow some way for the DLL to communicate with the window containing the progress bar. I'm not quite sure how you are loading the DLL, but this is the approach I would take assuming it is done through DLL injection:
Load/inject the DLL into the target
Have the DLL export some initialisation routine allowing it to receive information about the injector/client process.
Use GetProcAddress and CreateRemoteThread from the client to invoke this initialisation routine.
In the DLL, use the received information to get the HWND of the client.
Concretely, the intialisation routine would look like this:
HWND hwndClient = NULL;
BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lParam)
{
DWORD dwPID;
GetWindowThreadProcessId(hwnd, &dwPID);
if(dwPID == lParam) {
hwndClient = hwnd;
}
}
/*
* This code assumes the client has only one window. Given a PID, it populates
* a global to hold the window handle associated with the PID.
*/
DWORD WINAPI ReceiveClientPID(LPVOID dwPID)
{
EnumWindows(EnumProc, (LPARAM)dwPID);
}
The client code might be something like this:
/*
* Depending on your method of injection, you should have a handle to the
* target process as well as a HMODULE of the injected DLL.
*/
void InitDLL(HANDLE hProcess, HMODULE hModule)
{
FARPROC lpInit = GetProcAddress(hModule, "ReceiveClientPID");
HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL,
(LPTHREAD_START_ROUTINE)lpInit, (LPVOID)GetCurrentProcessId(), NULL, NULL);
if(hThread == NULL) {
MessageBox(NULL, L"Problem calling init routine in DLL", NULL, MB_OK);
} else {
CloseHandle(hThread);
}
}
So now you have the HWND of the client in the DLL and hence a way for you to do the communication. You can then specify a custom message in the client to change the progress bar:
/*
* The new progress position can be passed in wParam.
*/
#define WM_UPDATE_PROGRESS_BAR (WM_APP + 1)
Also add the corresponding case in the DialogFunc (we can remove the WM_TIMER code now because that was only there to demonstrate how to interact with progress bars):
case WM_UPDATE_PROGRESS_BAR:
SendMessage(GetDlgItem(hwndDlg, IDC_PROGRESS1), PBM_SETPOS, wParam, 0);
break;
And now to trigger changes in the progress bar of the client, the DLL simply has to do:
SendMessage(hwndClient, WM_UPDATE_PROGRESS_BAR, ..., 0);
Note that WM_UPDATE_PROGRESS_BAR needs to be redefined in the DLL as well.
To fit this all in with your current code:
/*
* Assumed progress is between 0 and 100. Otherwise it has to be
* normalised so this is the case (or the range of the progress bar
* in the client has to be changed).
*/
int my_progressor_callback(long progress)
{
SendMessage(hwndClient, WM_UPDATE_PROGRESS_BAR, progress, 0);
return 0;
}
Since you state that the DLL has no GUI and the client handles all the user interaction, why don't you send the progress information to the client instead and have it displayed there?
If you want to display the dialog in the DLL, you do so in exactly the same way as you would within a regular executable. There is absolutely no difference. If you want the DLL to continue working while it updates the progress bar, you can just kick off a new thread with CreateThread.
If you show some code, we'll be able to help you more directly.
Is it possible to find out to which process a MessageBox belongs? If yes, how?
You want to use GetWindowThreadProcessId. Here is an example.
#include <windows.h>
static const TCHAR g_cszClass = TEXT("#32770"); // dialog box class
// returned handle must be closed with CloseHandle() when no longer used
HANDLE GetMessageBoxProcess(__in_z LPCTSTR lpcszTitle, __in DWORD dwAccess)
{
HWND hWnd;
DWORD dwProcessId = 0;
HANDLE hRET;
hWnd = FindWindow(g_cszClass, lpcszTitle);
if (hWnd != NULL)
{
GetWindowThreadProcessId(hWnd, &dwProcessId);
if (dwProcessId != 0)
hRET = OpenProcess(dwAccess, FALSE, dwProcessId);
}
return hRET;
}
Not sure why you'd want the process though. Reasons I can think of:
terminating the message box completely
detecting a process
detecting a certain message box
all of which have superior & more optimal alternative solutions.
Another answer gives the programmatic solution. If this is a one-off thing for debugging, you can choose the window with Spy++, get the process ID from the properties window, and then look up the process in Task Manager.