Data in a window with global pointers repository this, protecting it with CRITICAL_SECTION, to make it thread safe (extracted from here ):
LRESULT CALLBACK WndProc2(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
Window *w = (Window *) GetWindowLong(hwnd, GWL_USERDATA);
_ASSERT(w);
return w->WndProc(hwnd, msg, wp, lp);
}
Window *g_pWindow;
CRITICAL_SECTION g_WindowCS;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
SetWindowLong(hwnd, GWL_USERDATA, (long) g_pWindow);
g_pWindow->HaveCSLock = false;
LeaveCriticalSection(&g_WindowCS);
SetWindowLong(hwnd, GWL_WNDPROC, (long) WndProc2);
return WndProc2(hwnd, msg, wp, lp);
}
Now we can create a window:
InitializeCriticalSection(&g_WindowCS);
EnterCriticalSection(&g_WindowCS);
g_pWindow = &w;
g_pWindow->HaveCSLock = true;
HWND hwnd = CreateWindow(TEXT("BaseWnd"), TEXT("Hello, World!"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hinst, 0);
if (g_pWindow->HaveCSLock)
LeaveCriticalSection(&g_WindowCS);
DeleteCriticalSection(&g_WindowCS);
Using the CBT hook procedure (extracted from here ):
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
Window *w = (Window *) GetWindowLong(hwnd, GWL_USERDATA);
_ASSERT(w);
return w->WndProc(hwnd, msg, wp, lp);
}
LRESULT CALLBACK CBTProc(int code, WPARAM wp, LPARAM lp)
{
if (code != HCBT_CREATEWND) {
return 0;
}
std::pair<Window *, HHOOK> *p = (std::pair<Window *, HHOOK> *) LPCBT_CREATEWND(lp)->lpcs->lpCreateParams;
if (p->first) {
SetWindowLong((HWND) wp, GWL_USERDATA, (long) p->first);
p->first = 0;
}
return CallNextHookEx(p->second, code, wp, lp);
}
Now we can create a window:
// Install the CBT hook
// Note: hook the thread immediately before, and unhook it immediately after CreateWindow call.
// The hook procedure can only process window creation nofitications, and it shouldn't be called for other types of notifications
// Additionally, calling hook for other events is wasteful since it won't do anything useful anyway
HHOOK hook = SetWindowsHookEx(WH_CBT, CBTProc, 0, GetCurrentThreadId());
_ASSERT(hook);
// Create window
// Pass a pair consisting of window object pointer and hook as lpParam
std::pair<Window *, HHOOK> p(&w, hook);
HWND hwnd = CreateWindow(TEXT("BaseWnd"), TEXT("Hello, World!"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hinst, &p);
// Unhook first
UnhookWindowsHookEx(hook);