调用CFileDlg打开文件选择对话框,默认是“列表”形式展示,而通常我们选择图片更好的查看方式是以“缩略图方式”来方便查看图片
这样就给我们带来麻烦,每次都需要选择“缩略图”方式来查看,所以需要重新继承一个新的类,来实现打开就显示缩略图的功能
通过用SPY++查看该列表控件是一个SHELLDLL_DefView包含的一个SysListView32控件,想到用枚举windows窗体来获得到
HWND TRACE_FindWindow(HWND parentHwnd,HWND hAfterChild) { HWND hWnd = FindWindowEx(parentHwnd,hAfterChild,NULL,NULL); if (hWnd) { CString str; str.Format("parentHwnd:0x%08X,hAfterChild:0x%08X,hWnd:0x%08X\r\n", parentHwnd, hAfterChild, hWnd); OutputDebugString(str); } return hWnd ; }
BOOL CMyFileDialog::OnInitDialog() { CFileDialog::OnInitDialog(); CWnd *parent = GetParent(); HWND hWnd1 = TRACE_FindWindow(parent->m_hWnd,NULL); //查找范围 hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //ComboBox hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //Static hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //ToolbarWindow32 hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //ListBox hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //SHELLDLL_DefView //找不到?? return TRUE; }
程序获得到的结果:
由此可知,可能在Initdialog函数中枚举这个控件时候,这个控件还没准备好,哪我们就自定义发送一个消息WM_POSTINITDLG,使用PostMessage,这样发送的消息会进入消息队列,windows执行完其他的消息后会执行该消息,我们在自定义消息中枚举窗体看看
BOOL CMyFileDialog::OnInitDialog() { CFileDialog::OnInitDialog(); //自定义消息 PostMessage(WM_POSTINITDLG,0,0); return TRUE; }
LRESULT CMyFileDialog::OnMYWM_POSTINIT(WPARAM wParam, LPARAM lParam) { //自定义消息 OutputDebugString("自定义消息中枚举窗口\r\n"); CWnd *parent = GetParent(); HWND hWnd1 = TRACE_FindWindow(parent->m_hWnd,NULL); //查找范围 hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //ComboBox hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //Static hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //ToolbarWindow32 hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //ListBox hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //SHELLDLL_DefView //找到 return 1; }
结果如下所示:
目前为止,我们获得到了SHELLDLL_DefView的hwnd, 可以对其发送显示缩略图消息,那我们该如何发送显示缩略图消息呢??继续我们的spy++探索,我们看看系统发送了什么消息,哪我们也相同发送一样的消息就可以了,如下图所示:
我们去掉我们不关心的消息,只留下我们关心的消息,
点击显示的模式”缩略图”,”平铺”,”图标”等会得到一下消息记录
所以我们可以尝试再自定义消息中发送WM_COMMAND 给SHELLDLL_DefView,
LRESULT CMyFileDialog::OnMYWM_POSTINIT(WPARAM wParam, LPARAM lParam) { //自定义消息 OutputDebugString("自定义消息中枚举窗口\r\n"); CWnd *parent = GetParent(); HWND hWnd1 = TRACE_FindWindow(parent->m_hWnd,NULL); //查找范围 hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //ComboBox hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //Static hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //ToolbarWindow32 hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //ListBox hWnd1 = TRACE_FindWindow(parent->m_hWnd,hWnd1); //SHELLDLL_DefView //找到 ::SendMessage(hWnd1 ,WM_COMMAND, 0x702d,0); //就可以实现缩略图等样式 //0x702d 对应的十进制就是28717 return 1; }
至此就可以以缩略图样式来显示
与思路1一致,我们可以直接获取到SHELLDLL_DefView信息,SHELLDLL_DefView的 ID 是 lst2 (值为 0x0461, 在 dlgs.h 中定义),但它不是列表框或列表控制。真正的 SysListView32 是 SHELLDLL_DefView 的 孩子,子 ID 为 1。 我们在自定义消息中获取到该控件发送消息
//enum LISTVIEWCMD //{ ODM_VIEW_ICONS = 0x7029, // ODM_VIEW_LIST = 0x702b, // ODM_VIEW_DETAIL= 0x702c, // ODM_VIEW_THUMBS= 0x702d, // ODM_VIEW_TILES = 0x702e, //}; BOOL CMyFileDialog::SetListView(LISTVIEWCMD cmd) { // Note real dialog is my parent, not me! CWnd* pshell = GetParent()->GetDlgItem(lst2); TRACE(_T("CMyFileDialog::SetListView: hwnd=%p\n"),pshell->GetSafeHwnd()); if (pshell) { // SHELLDLL_DefView window found: send it the command. pshell->SendMessage(WM_COMMAND, cmd); return TRUE; } return FALSE; }
http://www.vckbase.com/index.php/wv/761
Demo: