首页 > 解决方案 > Windows 类型不允许我的回调访问局部变量,有什么解决方法吗?

问题描述

我正在尝试使用该EnumWindows函数,该函数采用WNDENUMPROC带有 lambda 的 as 回调来访问局部变量。不幸的是,如果我尝试使用[&]编译器会告诉我类型不匹配。我正在尝试什么:

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;
    }

我能想出的唯一解决方案是使 wallpaper_hwnd 全局并用 定义 lambda [],但由于它仅在从该函数返回时才需要,而不是全局需要,我宁愿避免这种情况。

我比人们建议的更喜欢使用全局变量,但我只在全局变量与整个程序交互时才这样做,而事实并非如此。

我缺少任何更好的解决方案吗?

标签: c++windowswinapilambdascoping

解决方案


捕获外部变量的 Lambda 函数不能用作 Win32 回调。它们不能转换为原始函数指针。

在您的情况下,解决方案是将指针作为 EnumWindows() 的 LPARAM 参数传递给回调,该参数将传递给回调。

class A {...};
A a;
EnumWindows([](HWND   hwnd,LPARAM lParam) -> BOOL {
A* a = (A*)lParam;
...
},(LPARAM)&a);

大多数需要回调的 Windows 函数都支持传递用户定义的值,该值可以是指向结构的指针。编译器足够聪明,可以自动将非捕获 lambda 转换为 CALLBACK (=_stdcall) 调用约定。


推荐阅读