I'm trying to use the EnumWindows
function, which takes a WNDENUMPROC
as callback with a lambda in order to access local variables. Unfrotunately if i try to use [&]
the compiler will tell me types don't match.
What i'm trying:
HWND get_wallpaper_window()
{
HWND progman = FindWindow(L"ProgMan", NULL);
SendMessageTimeout(progman, 0x052C, 0, 0, SMTO_NORMAL, 1000, nullptr);
HWND wallpaper_hwnd;
EnumWindows(
// Error here
[&](HWND hwnd, LPARAM lParam) -> BOOL CALLBACK
{
HWND p = FindWindowEx(hwnd, NULL, L"SHELLDLL_DefView", NULL);
if (p) { wallpaper_hwnd = FindWindowEx(NULL, hwnd, L"WorkerW", NULL); }
}
, NULL);
return wallpaper_hwnd;
}
The only solution i could come up with is making wallpaper_hwnd global and defining the lambda with []
, but since it's only needed when returned from that function and not needed globally i'd rather avoid that.
I love using globals way more than people would advice, but i only do when the global variable is something that interacts with the whole program, and this is not the case.
Any better solution i'm missing?
Lambda functions that capture outside variables cannot be used as Win32 callbacks. They are not convertible to raw function pointers.
The solution in your case is to pass a pointer to something as the LPARAM parameter of EnumWindows(), which is passed to the callback.
class A {...};
A a;
EnumWindows([](HWND hwnd,LPARAM lParam) -> BOOL {
A* a = (A*)lParam;
...
},(LPARAM)&a);
Most windows functions that require a callback support passing a user-defined value which can be a pointer to a structure. The compiler is smart enough to convert a non-capturing lambda to CALLBACK (=_stdcall) calling convention automatically.