Strange EnumChildWindows issue
-
When I declare a LVFINDINFO object in the function body, EnumChildWindows fails to locate the control of SysListView32 type (a Windows class type). When I remove the LVFINDINFO object from the body, it works well. The code snippet is as the below.
void CMainDlg::OnBnClickedGetDolby()
{
// Kill any running window if any.
KillRunningApplet(_T("Sound"));// Launch it. if(!LaunchCplApplet(\_T("mmsys.cpl"), 0, 0)) { OutputDebugString(\_T("LaunchCplApplet fails. \\n")); return; } // Make sure the applet pops up. CWnd\* pWnd = NULL; int i = 0; while(!pWnd) { pWnd = FindWindow(NULL, \_T("Sound")); if(pWnd) { OutputDebugString(\_T("Found Sound window. \\n")); break; } Sleep(10); i++; if(i > 1000) { OutputDebugString(\_T("Sound window is not found. \\n")); return; } } // --- m\_pListView = NULL; EnumChildWindows(pWnd->m\_hWnd, DoSomethingHelper, (LPARAM)this); if(m\_pListView) { OutputDebugString(\_T("Got SysListView32")); } else { OutputDebugString(\_T("SysListView32 is not found.")); return; } m\_pListView->SendMessage(WM\_KEYDOWN, VK\_DOWN, 0); CListView\* pView = (CListView\*)m\_pListView; CListCtrl& Ctrl = pView->GetListCtrl(); LVFINDINFO info; // <--- This line fails SysListView32. int iIndex = 0; info.flags = LVFI\_PARTIAL | LVFI\_STRING; info.psz = \_T("Speaker");
/*
while ((iIndex = Ctrl.FindItem(&info)) != -1) { OutputDebugString(\_T("Speaker-like entry is found.")); CString s = Ctrl.GetItemText(iIndex, 0); OutputDebugString(s); }
*/
}
BOOL CALLBACK DoSomethingHelper(HWND hwnd, LPARAM lParam)
{
TCHAR sClassName[MAX_PATH] = {0};
GetClassName(hwnd, sClassName, MAX_PATH);
if(wcscmp(sClassName, _T("SysListView32")) == 0) {
CMainDlg* pMain = (CMainDlg*)lParam;
pMain->m_pListView = CWnd::FromHandle(hwnd);
}
OutputDebugString(sClassName);
return TRUE;
}Maxwell Chen
-
When I declare a LVFINDINFO object in the function body, EnumChildWindows fails to locate the control of SysListView32 type (a Windows class type). When I remove the LVFINDINFO object from the body, it works well. The code snippet is as the below.
void CMainDlg::OnBnClickedGetDolby()
{
// Kill any running window if any.
KillRunningApplet(_T("Sound"));// Launch it. if(!LaunchCplApplet(\_T("mmsys.cpl"), 0, 0)) { OutputDebugString(\_T("LaunchCplApplet fails. \\n")); return; } // Make sure the applet pops up. CWnd\* pWnd = NULL; int i = 0; while(!pWnd) { pWnd = FindWindow(NULL, \_T("Sound")); if(pWnd) { OutputDebugString(\_T("Found Sound window. \\n")); break; } Sleep(10); i++; if(i > 1000) { OutputDebugString(\_T("Sound window is not found. \\n")); return; } } // --- m\_pListView = NULL; EnumChildWindows(pWnd->m\_hWnd, DoSomethingHelper, (LPARAM)this); if(m\_pListView) { OutputDebugString(\_T("Got SysListView32")); } else { OutputDebugString(\_T("SysListView32 is not found.")); return; } m\_pListView->SendMessage(WM\_KEYDOWN, VK\_DOWN, 0); CListView\* pView = (CListView\*)m\_pListView; CListCtrl& Ctrl = pView->GetListCtrl(); LVFINDINFO info; // <--- This line fails SysListView32. int iIndex = 0; info.flags = LVFI\_PARTIAL | LVFI\_STRING; info.psz = \_T("Speaker");
/*
while ((iIndex = Ctrl.FindItem(&info)) != -1) { OutputDebugString(\_T("Speaker-like entry is found.")); CString s = Ctrl.GetItemText(iIndex, 0); OutputDebugString(s); }
*/
}
BOOL CALLBACK DoSomethingHelper(HWND hwnd, LPARAM lParam)
{
TCHAR sClassName[MAX_PATH] = {0};
GetClassName(hwnd, sClassName, MAX_PATH);
if(wcscmp(sClassName, _T("SysListView32")) == 0) {
CMainDlg* pMain = (CMainDlg*)lParam;
pMain->m_pListView = CWnd::FromHandle(hwnd);
}
OutputDebugString(sClassName);
return TRUE;
}Maxwell Chen
Okay, never mind. Constructing the
LVFINDINFO
object takes some time soEnumChildWindows
takes longer time to complete. So I added aSleep(10)
afterEnumChildWindows
call to make it happy.Maxwell Chen
-
When I declare a LVFINDINFO object in the function body, EnumChildWindows fails to locate the control of SysListView32 type (a Windows class type). When I remove the LVFINDINFO object from the body, it works well. The code snippet is as the below.
void CMainDlg::OnBnClickedGetDolby()
{
// Kill any running window if any.
KillRunningApplet(_T("Sound"));// Launch it. if(!LaunchCplApplet(\_T("mmsys.cpl"), 0, 0)) { OutputDebugString(\_T("LaunchCplApplet fails. \\n")); return; } // Make sure the applet pops up. CWnd\* pWnd = NULL; int i = 0; while(!pWnd) { pWnd = FindWindow(NULL, \_T("Sound")); if(pWnd) { OutputDebugString(\_T("Found Sound window. \\n")); break; } Sleep(10); i++; if(i > 1000) { OutputDebugString(\_T("Sound window is not found. \\n")); return; } } // --- m\_pListView = NULL; EnumChildWindows(pWnd->m\_hWnd, DoSomethingHelper, (LPARAM)this); if(m\_pListView) { OutputDebugString(\_T("Got SysListView32")); } else { OutputDebugString(\_T("SysListView32 is not found.")); return; } m\_pListView->SendMessage(WM\_KEYDOWN, VK\_DOWN, 0); CListView\* pView = (CListView\*)m\_pListView; CListCtrl& Ctrl = pView->GetListCtrl(); LVFINDINFO info; // <--- This line fails SysListView32. int iIndex = 0; info.flags = LVFI\_PARTIAL | LVFI\_STRING; info.psz = \_T("Speaker");
/*
while ((iIndex = Ctrl.FindItem(&info)) != -1) { OutputDebugString(\_T("Speaker-like entry is found.")); CString s = Ctrl.GetItemText(iIndex, 0); OutputDebugString(s); }
*/
}
BOOL CALLBACK DoSomethingHelper(HWND hwnd, LPARAM lParam)
{
TCHAR sClassName[MAX_PATH] = {0};
GetClassName(hwnd, sClassName, MAX_PATH);
if(wcscmp(sClassName, _T("SysListView32")) == 0) {
CMainDlg* pMain = (CMainDlg*)lParam;
pMain->m_pListView = CWnd::FromHandle(hwnd);
}
OutputDebugString(sClassName);
return TRUE;
}Maxwell Chen
Maxwell Chen wrote:
pMain->m_pListView = CWnd::FromHandle(hwnd);
Since
CWnd::FromHandle
documentation [^] states:The pointer may be temporary and should not be stored for later use.
I would use instead something like
pMain->m_hListView = hwnd;
and then obtain the
CWnd
pointer inside theCMainDlg::OnBnClickedGetDolby
body. Anyway I really don't know if it would help. :)If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles] -
Maxwell Chen wrote:
pMain->m_pListView = CWnd::FromHandle(hwnd);
Since
CWnd::FromHandle
documentation [^] states:The pointer may be temporary and should not be stored for later use.
I would use instead something like
pMain->m_hListView = hwnd;
and then obtain the
CWnd
pointer inside theCMainDlg::OnBnClickedGetDolby
body. Anyway I really don't know if it would help. :)If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles]CPallini wrote:
pMain->m_hListView = hwnd;
Thanks! It resolved the timing problem. :-D
Maxwell Chen