VC/MFC 程序最小化后不能还原的原因与解决方法
2014-03-17 19:49
295 查看
程序最小化后不能还原,一般原因是程序中至少存在一个Popup类型的窗口引起的,因为Popup类型的子窗口即使由于父窗口的隐藏而隐藏,其WS_VISIBLE属性仍然是可见的,当用户再次点击任务栏的程序图标时,Popup窗口会拦截系统(还原)消息,使主程序框架无法接收到系统消息,从而导致主程序无法正常还原。如果将其修改为Child类型的窗口,那么主程序的最小化和还原的功能就可以正常了。不过在实际项目中,往往就需要一个Popup类型的窗口作为子窗口(Popup类型的窗口也可以有父窗口),那么这又如何解决程序最小化后不能还原的问题呢?根据以上分析的原理,只要在主程序最小化时,相应也隐藏掉Popup窗口(ShowWindow(SW_HIDE)),这样系统消息就能够正确传递了;当主程序还原时,再将隐藏的Popup窗口显示出来,这样就既不影响程序的显示效果,又能解决问题了!具体方法如下:
首先需要在主程序(如MainFrame)中拦截系统消息(响应最大化,最小化,还原,关闭等消息的地方)。其消息为WM_SYSCOMMAND.如在MainFrame.h头文件中加入afx_msg void OnSysCommand(UIND nID,LPARAM lParam);在MainFrame.cpp的BEGIN_MAP与END_MAP之间加入ON_WM_SYSCOMMAND,响应函数为
void CMainFrame::OnSysCommand(UIND nID,LPARAM lParam){}。
其次根据系统消息对Popup窗口进行隐藏与显示操作,代码如下:
方法二:拦截系统的还原消息,对其进行自定义的操作,如先设置为活动窗口,然后继续执行还原操作。
上半部分文档转至:http://blog.sina.com.cn/s/blog_4b44e1c00100mdkl.html
经测试:在XP上会出现点击任务栏无法还原窗体的情况,Win7上则不会出现。
但是我在程序中遇到这样的问题:
![](https://img-blog.csdn.net/20140317194229031)
本程序只准用户同时运行一个,肯定会对其加入控制,这种情况在Win7下会有这样的情况,当右击用户栏程序的时候,由于二次运行将不再启动程序,而是将原来最小化的程序显示出来,如上图所示。而这样的话,将不发送WM_SYSCOMMAND消息,也就意味着开始隐藏的Popup窗体在这种情况下将不再显示出来,并不能达到想要的要求,而上面的思路将进入死胡同。经过分析,这种情况是程序启动不成功导致,如果通过进程间通信去解决这个问题,将增加大量的工作,得不偿失啊。回过头来从源头出发重新分析问题,想到了在OnSize()函数上面做文章:
CWnd::OnSize
参数:
nType
指定请求的调整大小的类型。 此参数可以是下列值之一:
SIZE_MAXIMIZED 窗口最大化。
SIZE_MINIMIZED 窗口最小化。
SIZE_RESTORED 窗口已调整大小,但是,SIZE_MINIMIZED 和 SIZE_MAXIMIZED 不适用。
在某些其他窗口最大化时,SIZE_MAXHIDE 发送到所有弹出窗口。
在某些其他窗口将还原为其以前的大小时,SIZE_MAXSHOW 发送到所有弹出窗口。
cx
指定工作区的新的宽度。
cy
指定工作区的新的高度。
看来可行,解决步骤如下:
1.在主窗体中添加ON_WM_SIZE消息;
2.参照OnSysCommand函数修改OnSize()函数,代码如下:
运行效果很满意,一切OK!!!
首先需要在主程序(如MainFrame)中拦截系统消息(响应最大化,最小化,还原,关闭等消息的地方)。其消息为WM_SYSCOMMAND.如在MainFrame.h头文件中加入afx_msg void OnSysCommand(UIND nID,LPARAM lParam);在MainFrame.cpp的BEGIN_MAP与END_MAP之间加入ON_WM_SYSCOMMAND,响应函数为
void CMainFrame::OnSysCommand(UIND nID,LPARAM lParam){}。
其次根据系统消息对Popup窗口进行隐藏与显示操作,代码如下:
CWnd* m_pPopupWnd;/// Popup类型的窗口指针 void CMainFrame::OnSysCommand(UIND nID,LPARAM lParam) { static BOOL s_bDialogVisible = FALSE; /// 如果是最小化消息 if(SC_MINIMIZE == nID) { if(NULL != m_pPopupWnd && ::IsWindow(m_pPopupWnd->m_hWnd)) { if(::IsWindowVisible(m_pPopupWnd->m_hWnd)) { s_bDialogVisible = TRUE; /// 隐藏Popup类型窗口或具有Popup类型窗口的父窗口 m_pPopupWnd->ShowWindow(SW_HIDE); } } } else { if(NULL != m_pPopupWnd && ::IsWindow(m_pPopupWnd->m_hWnd)) { if(TRUE == s_bDialogVisible) { s_bDialogVisible = FALSE; /// 显示Popup类型窗口或具有Popup类型窗口的父窗口 m_pPopupWnd->ShowWindow(SW_SHOW); } } } CWnd::OnSyscommand(nID,lParam); }
方法二:拦截系统的还原消息,对其进行自定义的操作,如先设置为活动窗口,然后继续执行还原操作。
BOOL PreTranslateMessage(MSG* pMsg) { ASSERT(pMsg); /// 如果是激活窗口消息 if(pMsg->message == WS_APPACTIVE) { /// 如果是按下左键 if(pMsg->wParam == VK_LBUTTON) { ASSERT(AfxGetMainFrame()); /// 激活主窗口 SetActiveWindow(AfxGetMainFrame()->m_hWnd); } } /// 可继续向基类传递消息 return C**APP::PreTranslateMessage(pMsg); }
上半部分文档转至:http://blog.sina.com.cn/s/blog_4b44e1c00100mdkl.html
经测试:在XP上会出现点击任务栏无法还原窗体的情况,Win7上则不会出现。
但是我在程序中遇到这样的问题:
本程序只准用户同时运行一个,肯定会对其加入控制,这种情况在Win7下会有这样的情况,当右击用户栏程序的时候,由于二次运行将不再启动程序,而是将原来最小化的程序显示出来,如上图所示。而这样的话,将不发送WM_SYSCOMMAND消息,也就意味着开始隐藏的Popup窗体在这种情况下将不再显示出来,并不能达到想要的要求,而上面的思路将进入死胡同。经过分析,这种情况是程序启动不成功导致,如果通过进程间通信去解决这个问题,将增加大量的工作,得不偿失啊。回过头来从源头出发重新分析问题,想到了在OnSize()函数上面做文章:
CWnd::OnSize
afx_msg void OnSize( UINT nType, int cx, int cy );
参数:
nType
指定请求的调整大小的类型。 此参数可以是下列值之一:
SIZE_MAXIMIZED 窗口最大化。
SIZE_MINIMIZED 窗口最小化。
SIZE_RESTORED 窗口已调整大小,但是,SIZE_MINIMIZED 和 SIZE_MAXIMIZED 不适用。
在某些其他窗口最大化时,SIZE_MAXHIDE 发送到所有弹出窗口。
在某些其他窗口将还原为其以前的大小时,SIZE_MAXSHOW 发送到所有弹出窗口。
cx
指定工作区的新的宽度。
cy
指定工作区的新的高度。
看来可行,解决步骤如下:
1.在主窗体中添加ON_WM_SIZE消息;
2.参照OnSysCommand函数修改OnSize()函数,代码如下:
void CMainFrame::OnSize(UINT nType, int cx, int cy) { CDialog::OnSize(nType, cx, cy); // TODO: 在此处添加消息处理程序代码 static BOOL s_bDialogVisible = FALSE; if(SIZE_MINIMIZED == nType) { if(NULL != m_pPopupWnd && ::IsWindow(m_pPopupWnd.m_hWnd)) { if(::IsWindowVisible(m_pPopupWnd.m_hWnd)) { s_bDialogVisible = TRUE; /// 隐藏有Popup类型窗口或具有Popup类型窗口的父窗口 m_pPopupWnd.ShowWindow(SW_HIDE); } } } else if(SIZE_RESTORED == nType) { if(NULL != m_pPopupWnd && ::IsWindow(m_pPopupWnd.m_hWnd)) { if(TRUE == s_bDialogVisible) { s_bDialogVisible = FALSE; /// 显示有Popup类型窗口或具有Popup类型窗口的父窗口 m_pPopupWnd.ShowWindow(SW_SHOW); } } } }
运行效果很满意,一切OK!!!
相关文章推荐
- VC/MFC 程序最小化后不能还原的原因与解决方法
- VC/MFC 程序最小化后不能还原的原因与解决方法
- VC/MFC 程序最小化后不能还原的原因与解决方法
- VC2005编译的MFC程序提示“由于应用程序配置不正 确,应用程序未能启动”解决方法(转)
- VC6里改变对话框资源ID号后classwizard不能正常显示控件ID的原因及解决方法
- VS2008在WIN7 X64上不能编译VC++程序的解决方法
- VC的调试方式 + VC不能调试的原因及解决方法
- VC的调试方式 + VC不能调试的原因及解决方法
- STM32F407的简单LED点灯程序不能实现的原因及解决方法
- VC++ 6.0编写MFC程序经常出现的问题及解决方法
- 【转】 “由于应用程序配置不正确,程序未能启动”--原因及解决方法 vc2008, VC2005
- 不能从const char指针转换为LPCWSTR的原因及解决方法
- 【一个实体对象不能由多个 IEntityChangeTracker 实例引用】原因及解决方法
- 转载 本机运行x程序出现:Can't open display 原因及其解决方法
- vc2005编译过程中"没有找到MFC80UD.DLL,因此这个程序未能启动.重新安装应用程序可能会修复此问题"? 的彻底解决
- 实现VC程序启动时最小化到任务栏(完美解决闪烁问题)
- 局域网中文件服务器上的.Net程序不能被直接运行的解决方法
- 造成win2008 500内部错误不能显示详细错误的原因和解决方法
- CSDN 博客上不能插入一段SQL程序代码 解决方法
- 使用.NET Compact Framework开发Windows Mobile程序,不能触发OnKeyPress/OnKeyDown的原因及解决办法