3

我想将可见的窗口标题添加到组合框。这是我的来源:

BOOL CALLBACK EnumWindowsProc(HWND hWnd, long lParam) 
{
     TCHAR buff[255];
     CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_PROCESS);
     if (IsWindowVisible(hWnd)) 
     {
         GetWindowText(hWnd, buff, 254);
         pComboBox->AddString(buff);
     }
     return TRUE;
}

void CFindProcess::OnDropdownComboProcess()
{
    EnumWindows(EnumWindowsProc, 0);
}

但我得到错误:

error C2660: 'GetDlgItem' : function does not take 1 arguments  60

如何正确添加标题到组合?

4

3 回答 3

3

MFC 对象是线程敏感的,GetDlgItem在创建对象的线程中运行良好,可能是主 UI 线程。函数EnumWindows可能会创建一个工作线程来访问回调函数,这就是为什么GetDlgItem无法获得组合框的有效句柄的原因。

要在另一个线程中正确访问组合框,您必须使用静态函数:CWnd::FromHandle使用组合框对象的原始句柄,如下所示:

BOOL CALLBACK EnumWindowsProc(HWND hWnd, long lParam) 
{
    if (IsWindowVisible(hWnd)) 
    {   TCHAR szBuffer[255];
        INT nLength = GetWindowText(hWnd, szBuffer, 254);
        if (nLength>0)
        {   // only add windows that has a caption
            CComboBox *pComboBox = (CComboBox*)CWnd::FromHandle((HWND)lParam);
            pComboBox->AddString(szBuffer);
        }
    }
    return TRUE;
}

// call EnumWindows --------------------
CComboBox *pComboBox = (CComboBox *)GetDlgItem(IDC_COMBO1);
// passing the raw handle of the combobox as parameter
EnumWindows(EnumWindowsProc, (LPARAM)pComboBox->m_hWnd);
于 2013-03-10T12:52:36.673 回答
2

首先,你GetDlgItem有两个参数,第一个是包含控件的对话框的句柄。

所以它需要一个HWND包含这个控件的对话框的参数,我认为这将是HWND你作为参数传递给你的函数。

 CComboBox* pComboBox = (CComboBox*)GetDlgItem(hWnd,IDC_COMBO_PROCESS);
                                                 ^^^^ added parameter

如果你EnumWindows在 MSDN中查看,你会看到你必须传递一个回调并且它有一个HWND参数,如果你看看这个参数是什么,它说:

顶级窗口的句柄。

这正是你必须传递给GetDlgItem.

此外,您应该检查返回值,GetWindowText因为这会返回写入buff您传递给它的字符数。

     int ret = GetWindowText(hWnd, buff, 254);
     if (ret > 0) pComboBox->AddString(buff); // only add non-empty strings.
于 2013-03-09T14:38:38.163 回答
2

除了用户 @mfc 提供的内容之外,我不会从不同的线程进行 UI 更新。相信EnumWindows不会为枚举创建线程。它将在当前线程的调用堆栈中调用回调。

反过来,这意味着 UI 可能会冻结一段时间。因此,建议创建一个线程进行枚举。此外,我不会直接从不同的线程更新 UI。可能是一个vector字符串,或者是PostMessage我会使用的(在每次迭代中)。

确实EnumWindows可以执行得相当快。但是,当您开始枚举其他(内核)对象,如文件、打印机、用户等时,UI 肯定会冻结。因此,更好地练习编写多线程代码。最初编写 MT 代码会很痛苦,但后来你会喜欢它,欣赏它,没有它就活不下去。

于 2013-03-10T13:06:23.900 回答