Reputation: 892
I want to add visible window titles to a combobox. Here is my source:
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);
}
but I get error:
error C2660: 'GetDlgItem' : function does not take 1 arguments 60
How I can correctly add titles to combo?
Upvotes: 3
Views: 850
Reputation: 18431
In addition to what user @mfc has provided, I would not do UI update from a different thread. I believe EnumWindows
does not create thread for enumeration. It would call the callbacks within the call-stack of current thread.
This, in turn, means that UI may freeze for a while. Thus, it is recommended to create a thread for enumeration. More over, I would not directly update UI from different thread. May be a vector
of string, or a PostMessage
(on each iteration) I would have used.
It is true that EnumWindows
may perform quite fast. But when you move to enumerate other (kernel) objects like file, printers, users etc - the UI is definitely going to freeze. So, better practice writing multithreaded code. Initially writing MT-code would be a pain, but later you'd love it, appreciate it, and cannot live without it.
Upvotes: 2
Reputation: 565
MFC objects are thread-sensitive, GetDlgItem
works well in the thread that created the object, probably the main UI thread. Function EnumWindows
probably creates a worker thread to access the callback function, and that is why GetDlgItem
failed to get a valid handle of the combobox.
To access the combobox properly in another thread, you have to use the static function: CWnd::FromHandle
with the raw handle of the combobox object as follows:
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);
Upvotes: 3
Reputation: 63210
Firstly, your GetDlgItem
has two parameters, and the first is a handle to the dialog box that contains the control.
So it expects a HWND
parameter of the dialog that contains this control, I would presume that will be the HWND
you pass as a parameter to your function.
CComboBox* pComboBox = (CComboBox*)GetDlgItem(hWnd,IDC_COMBO_PROCESS);
^^^^ added parameter
If you look at EnumWindows
in MSDN, you'll see you have to pass a callback and it has a HWND
parameter, if you look at what this parameter is for it says:
A handle to a top-level window.
This is exactly what you have to pass to GetDlgItem
.
Also, you should check the return value of GetWindowText
as this returns the number of characters written to the buff
you passed it.
int ret = GetWindowText(hWnd, buff, 254);
if (ret > 0) pComboBox->AddString(buff); // only add non-empty strings.
Upvotes: 2