我想将可见的窗口标题添加到组合框中。这是我的来源:
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
如何正确添加标题到组合?
答案 0 :(得分: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);
答案 1 :(得分:2)
首先,您的GetDlgItem
有两个参数,第一个是包含控件的对话框的句柄。
因此它需要包含此控件的对话框的HWND
参数,我认为这将是您作为参数传递给函数的HWND
。
CComboBox* pComboBox = (CComboBox*)GetDlgItem(hWnd,IDC_COMBO_PROCESS);
^^^^ added parameter
如果您查看EnumWindows
in MSDN,您会看到必须传递一个回调且它有一个HWND
参数,如果您查看此参数的用途,则说:
顶级窗口的句柄。
这正是您必须传递给GetDlgItem
。
此外,您应该检查GetWindowText
的返回值,因为这会返回写入您传递给它的buff
的字符数。
int ret = GetWindowText(hWnd, buff, 254);
if (ret > 0) pComboBox->AddString(buff); // only add non-empty strings.
答案 2 :(得分:2)
除了@mfc提供的用户之外,我不会从其他线程进行UI更新。我相信EnumWindows
不为枚举创建线程。它会在当前线程的调用堆栈中调用回调。
反过来,这意味着UI可能会冻结一段时间。因此,建议为枚举创建一个线程。更重要的是,我不会直接从不同的线程更新UI。可能是vector
字符串,或者是PostMessage
(每次迭代)我会使用。
EnumWindows
确实表现得非常快。但是当您继续枚举其他(内核)对象(如文件,打印机,用户等)时,UI肯定会冻结。因此,更好地练习编写多线程代码。最初编写MT代码会很痛苦,但是后来你会喜欢它,欣赏它,并且不能没有它。