VC/MFC 程序最小化后不能还原的原因与解决方法

winform中窗口最小化后还原窗口控件消失 现象:在有些机器上,winform的程序,最小化之后还原窗口,但是控件不在画面中。此时更改窗口的大小,控件又会出现。 初步怀疑是窗口最小化后,布局发生变化,控件位置挪到别的地方。但是还原过后,控件没有重新布局,所以控件会消失。 尚未找到解决办法。 ... 阅读详情

程序最小化后不能还原,一般原因是程序中至少存在一个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窗口进行隐藏与显示操作,代码如下:

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!!!

winfrom解决图片多导致闪烁,以及最小化后出现控件消失背景不全的问题 winfrom控件加载不全,闪烁 阅读详情

相关推荐

VC++ 实现 窗口最小化 MFC

所谓的“托盘”,在Windows系统界面中,指的就是下面任务条右侧,有系统时间等等的标志的那一部分。在程序最小化或挂起时,但有不希望占据任务栏的时候,就可以把程序放到托盘区。 一 、原理 1、最小化的原理:首先要将窗口隐藏,然后 在右下角绘制图标。 2、恢复的原理:将窗

7777

Winform窗体最小化后如何再次弹出

Winform窗体最小化后如何再次弹出,设置WindowState = FormWindowState.Normal即可。

路过 3107

VC 6 MFC 美化界面方法和技巧

前段时间一直在想怎么样能让窗口变得更漂亮一点,更加吸引人呢?在网上也看到了不少高手们的做法,但对于我这种不喜欢太复杂的人来说,我不是很喜欢那样写代码,GetSystemMetrics函数来得到各个边框的长度或宽度。。。。没几下,我的头就晕了,在查了许多资料以及实验后,我终于找到了一种比较简单的美化窗口的方法,现在就拿出来献丑一下,觉得不好的就请跳过去吧~~ 大家请看这张图:

mycaibo编程 5060

C# winform 子控件在窗体最小化再还原后滚动异常问题

子控件的AutoScroll=true,在窗体缩小到任务栏,再还原,滚动条会变得很长,而且是一个固定的数值4691(还是4961)

qq_36286345的博客 803

VC6.0 中如何实现最小化到托盘以及恢复?

(一)  原理1、最小化的原理:首先要将窗口隐藏,然后 在右下角绘制图标。2、恢复的原理:将窗口显示,再将托盘中的图片删除。(二)程序实现1、自定义消息WM_SHOWTASK: #define WM_SHOWTASK (WM_USER +1)2、在MFC的::OnSysCommand(UINT nID, LPARAM lParam)函数体中增加一个命令响应           

michaelli的专栏 2693

【WIN 32 报错】 Expression: ::IsWindow(m_hWnd)

WIN 32 报错问题: --------------------------- Microsoft Visual C++ Debug Library --------------------------- Debug Assertion Failed! Program: E:\HaoIE\bin\HaoIE_d.exe File: d:\program files\v

走向CTO的路上... 2786

Visual Studio MFC编程 程序调试时所遇到的问题及解决方法

本文中记录了笔者在基于Visual Studio MFC编程时,程序调试过程中所遇到的问题及解决方法。 1、Visual Studio MFC中的快捷方式 1.1、问题:Visual Studio MFC中修改好程序之后,怎样编译并建立可运行的exe Ctrl+F5两个按钮同时按下。 1.2、问题:Visual Studio的代码怎么快捷排版/自动排版? 在代码页面,Ctr...

dahailuoa6的博客 1万+

告别Qt Creator!VSCode + QMake + MinGW:从零搭建高效Qt开发环境

本文详细介绍了如何使用VSCode替代Qt Creator搭建高效的Qt开发环境,涵盖VSCode配置、QMake与MinGW集成、智能提示优化及构建调试技巧。通过实战案例展示如何提升开发效率30%以上,特别适合中大型Qt项目开发。

weixin_30466039的博客 243

VC最小化到托盘程序

<br /> 在实际操作电脑的过程中,我们常常可以看到一些应用程序可以最小化到桌面右下角的托盘中显示,如一些杀毒软件等开机就显示在托盘中,或是我们常用的QQ等聊天工具,都可以最小化在托盘中,如图-1。<br /><br />    在图-1中,可以看到第一个服务器样式的图标,那个就是我编写的服务器程序最小化在托盘中的显示。其实很简单,只要在程序中加几行代码就可以了。我主要就MFC中基于Dialog对话框的程序作一下简单的介绍。以下是基本步骤:<br /><br />1、首先建立一个基于对话框的MFC程序;<

mfc_winform_2011的专栏 581

如何入门强化学习

很多同学在入门强化学习的时候都会遇到困难,那我这里就简单介绍一下应该如何入门强化学习,并以开源代码为例详解强化学习实战。

seeksister的博客 3304

LaTeX参考文献格式apsrev4-1,增加文献标题

APS的LaTeX参考文献格式apsrev4-1是隐藏标题的,如果想要出现标题,需要更改apsrev4-1.bst文件内容 在apsrev4-1.bst文件靠后部分,定义不同类型文献格式的地方,将article类型的内容替换为, FUNCTION {article} { output.bibitem format.authors booktitle empty$ { "author" output.check }{ output } if$ author format.

loading1234567的博客 5031

VC中如何实现最小化到托盘以及恢复

VC6.0 中如何实现最小化到托盘以及恢复?function StorePage(){d=document;t=d.selection?(d.selection.type!=None?d.selection.createRange().text:):(d.getSelection?d.getSelection():);void(keyit=window.op

恋一种味 1267

android osmdroid 加载常用离线地图格式(开源的在线地图)

osmdroid是(几乎)完整/免费更换为Android MapView(v1 API)类。它还包括一个模块化的瓷砖供应商系统支持众多的在线和离线瓷砖来源和覆盖支持内置覆盖绘制图标,跟踪位置和形状。如果想在你项目中使用osmdroid,绝对是灵活度最高,不用申请百度,高德等的key。还有一堆规则要遵循。osmdroid可以支持多图层叠加,绘制自已的图层。离线加载常用地图格式zip,sqlite,.

mmsx990的博客 1万+

程序最小化到托盘

转自:http://zf0026.blog.163.com/blog/static/178262113201121711302641/ 对原文的补充,最为新手,需要知道如何定义消息,响应WM_SIZE消息 VC最小化到托盘程序   2011-03-17 11:30:26|  分类: c++|字号 订阅 在实际操作电脑的过程中,我们常常可以看到一些应用程序

u011365452的专栏 2833

dolphinscheduler服务注册中心源码解析(一)服务注册与发现整体设计

下一篇文章我们开始讲解dolphinscheduler基于Zookeeper实现注册中心的源码解析。

最爱嫣夜来 376

Windows 11 安装 JDK 21:下载、安装、配置环境变量、验证

本文详细介绍了在 Windows 11 系统中安装 JDK 21 的完整流程,包括从 Oracle 官网下载压缩包、解压至自定义目录、配置 JAVA_HOME 与 Path 环境变量,并验证安装是否成功。文章推荐使用 ZIP 压缩包而非安装程序,以实现绿色便携、多版本共存等优势,并通过一个包含 Java 21 新特性的示例程序进行功能验证,适合开发者快速上手。

寒水馨 · 轻量级技术文档 · hanshuixin.org 2519

vc 实现窗口最小化到任务栏

在VC /MFC中想点击一个窗体上的按钮后使窗体最小化到任务栏 中,怎么做 //定义theApp外部变量,即工程的Globals的theApp。 extern CXXXXXXApp theApp; theApp.GetMainWnd()->ShowWindow(SW_HIDE);//隐藏窗口 theApp.GetMainWnd()->ShowWindow(SW_MINIMIZE);//最小化窗口 theApp.GetMainWnd()->CloseWindow();//关闭窗口

vah101的专栏 5112

Python实战项目2:b站评论采集

本文不对数据采集的过程做探讨,直接上代码。

lyccomcn的博客 3199

【界面】VC 6 MFC让窗口轻而易举变漂亮

一、界面分析          主要是把数据放到合适的位置,并且获取窗口的pDC,用pDC—>StretchBlt()函数显示图片,这里面创建了一个兼容的dc,先把数据选择到这里面,再用StrtchBlt()拷贝兼容dc。          最后是一个一个数据块进行显示。 参考:1、VC 6 MFC让窗口轻而易举变漂亮 2、VC知识库—让窗口轻而易举变漂亮

此博客不更新很多年了,博客作废............ 4117

【WRF后处理】基于wrf-python处理wrf运行结果wrfout_d01

基于wrf-python处理wrf运行结果wrfout_d01

WW、forever的博客 5209

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

窗体最大化、最小化、隐藏、关闭功能及程序退出功能的按钮实现

1、在VC /MFC中点击一个窗体上的按钮后使窗体最小化到任务栏中!//定义theApp外部变量,即工程的Globals的theApp。extern CXXXXXXApp theApp;theApp.GetMainWnd()->ShowWindow(SW_HIDE);//隐藏窗口theApp.GetMainWnd()->ShowWindow(SW_MINIMIZE)

千愚千寻 3093

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

上一篇: ffmpeg参数中文详细解释
下一篇: ffplay的快捷键以及选项
FISH_LJZ
博客等级 码龄16年 16粉丝 4原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值