c++ - 不能通过回调永久改变类的状态

标签 c++ winapi callback state

这是我尝试使用此 WinAPI 函数执行的操作:

EnumWindows(
    _In_ WNDENUMPROC lpEnumFunc,
    _In_ LPARAM      lParam
);

它是从此类 WinFinderFeedWindowsHandlesList 函数中调用的(此处已简化)。

class WinFinder
{
    WinFinder();
    ~WinFinder();

    std::vector<HWND> winHandles;
    void FeedWindowsHandlesList();
};

FeedWinDowsHandlesList 函数调用 EnumWindows,这反过来会为找到的每个句柄触发回调。在那里,HWND 被添加到调用 WinFinder 实例的 winHandles 成员中。我面临的挑战是访问调用 WinFinder 实例的成员。我尝试了两种方法,它们都以同样的方式失败。


方法一:(灵感来源于此SO post)

调用函数:

void WinFinder::FeedWindowsHandlesList() {
    LPARAM param = reinterpret_cast<LPARAM>(this);
    EnumWindows(EnumWindowsProc, param);
}

回调(简化):

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
    WinFinder thisWF = *(reinterpret_cast<WinFinder*>(lParam));
    thisWF.winHandles.push_back(hWnd);
    return TRUE;
}

push_back 级别的断点让我看到添加发生,并且 vector 的大小达到 1。但是下次我进入回调时,vector 是空的。当 EnumWindows 完成时,vector 完全是空的。


我也试过这样

方法2:

调用函数:

void WinFinder::FeedWindowsHandlesList() {
    WinFinder * wf =this;
    EnumWindows(EnumWindowsProc,(LPARAM)wf);    
}

回调:

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
    WinFinder thisWF= *((WinFinder*)lParam);
    thisWF.winHandles.push_back(hWnd);  
 return TRUE;
}

那么,您认为我应该如何访问调用 EnumWindowsWinFinder 类的 vector 成员,而不丢失任何内容?

最佳答案

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
    // WinFinder thisWF = *(reinterpret_cast<WinFinder*>(lParam));
    // in the above line you're creating a copy of the object pointed to by lParam
    // what you want instead is just a pointer of type WinFinder to simplify access:
    WinFinder *thisWF = reinterpret_cast<WinFinder*>(lParam);
    // thisWF.winHandles.push_back(hWnd);
    // since thisWF is a pointer you have to use -> to access the members:
    thisWF->winHandles.push_back(hWnd);
    return TRUE;
}

B 计划:使用引用(如 @SoronelHaetir 所建议):

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
    WinFinder &thisWF = *reinterpret_cast<WinFinder*>(lParam);
    thisWF.winHandles.push_back(hWnd);
    return TRUE;
}

最小示例:

#include <iostream>
#include <vector>
#include <Windows.h>

struct WinFinder
{
    std::vector<HWND> winHandles;
    void FeedWindowsHandlesList();
};

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
    WinFinder *thisWF = reinterpret_cast<WinFinder*>(lParam);
    thisWF->winHandles.push_back(hWnd);
    return TRUE;
}

void WinFinder::FeedWindowsHandlesList()
{
    LPARAM param = reinterpret_cast<LPARAM>(this);
    EnumWindows(EnumWindowsProc, param);
}

int main()
{
    WinFinder wf;
    wf.FeedWindowsHandlesList();

    for (auto const & w : wf.winHandles)
        std::cout << w << '\n';
}

关于c++ - 不能通过回调永久改变类的状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51572485/

相关文章:

c++ - 检测(可能是抽象的)基类的 protected 构造函数

winapi - 如何在 Windows 文件对话框的 "save"按钮上设置文本?

objective-c - 注册显示重新配置回调

jquery - 链接和下拉选择器与 PreventDefault 相反?

c++ - getch() 和 scanf() 函数之间的区别

C++:在没有隐式默认构造函数的情况下初始化成员类的选择(问题主体中有更多约束)

c++ - 识别访问互联网的进程

javascript - 如何在高阶 javascript 函数中执行变量捕获?

C++:跨平台且安全的 system(...) 替代方案是什么?

c++ - 如何从虚拟键码中获取键文本?