MFC 进行全屏显示并动态加载菜单进行还原

 

         首先说一下全屏的概念:大家应该都有过软件全屏的使用经历,无非就是让其客户区域显示在整个屏幕上,原先窗口上的工具栏和状态栏都隐藏了罢了。

下面我只说一下核心代码。(注:大家实验前,应该先建一个单文档工程,并添加一个菜单项:全屏:IDR_FULLSCREEN,点击这个菜单项就进行全屏显示,所以我们应该编写这个菜单项的事件代码,当然是再CMainFrame类中)。

    1:先说一下我们暂时(后边还需要其他的)需要的成员变量:因为我要进行全屏和还原工作,所以我们需要两个变量,一个用来保存全屏显示时的信息,另一个用来保存还原时的信息,所以,我们在CMainFrame类中增加个成员变量:m_wpOld,m_wpNew;这两个变量都是WINDOWPLACEMENT型的。

          再就是我们需要设置一个BOOL变量来记录是否已经全屏显示了 bool m_FullScreen=false;

          下面在菜单事件中写代码:

            RECT rectDeskTop;这个变量用来记录整个屏幕的大小信息。

            if(!m_FullScreen)  //如果不是全屏,那我们就要进行全屏显示

              {

                           m_wndStatusBar.ShowWindow(SW_HIDE);
                           m_wndToolBar.ShowWindow(SW_HIDE);            //先隐藏工具栏和状态栏

 

                           m_wpPrev.length=sizeof(m_wpOld);
                          GetWindowPlacement(&m_wpOld);         //获取当前窗口位置信息 (全屏显示前的,保存在m_wpOld中,以便于还原)

                            ::GetWindowRect(::GetDesktopWindow(),&rectDesktop);//得到整个桌面窗口的信息
                           AdjustWindowRectEx(&rectDesktop,GetStyle(),TRUE,GetExStyle());//根据传递进来的客户区域大小计算窗口的大小。因为,我们要进行全屏显示,所以我们要把整个屏幕设置为我们的客户区域,所以我们把上面获取到的rectDesktop作为我们的客户区域大小传递进去,函数返回后,rectDesktop里面就包含了我们进行全屏设置所需要的窗口大小(在这里要注意:客户区域和窗口的概念。我们设置全屏实质上是设置以整个屏幕为大小的客户区域的窗口。)

                           m_wpNew=m_wpOld;//把m_wpOld的一些信息(比如length,ptMinPosition,ptMaxPosition)来填充m_wpNew,(实际上在这里没什么用,因为m_wpNew需要的参数,在下边会设置)

                          m_wpNew.showCmd=SW_NORMAL/;

                           m_wpNew.rcNormalPosition=rectDesktop;//设置全屏显示时的窗口的正常显示的大小,对应上面的SW_NORMAL。上面为什么要设置wpNew.showCmd=SW_NORMAL/;呢?从GetWindowPlacement(&m_wpOld);         获取到的m_wpOld的showCmd参数实际上已经是SW_NORMAL了,执行这条语句m_wpNew=m_wpOld后,wpNew.showCmd就已经等于SW_NORMAL了,为什么我们这里还要设置一下呢,(1)因为当窗口刚创建出来的时候,当我们直接点击菜单项进行全屏时,GetWindowPlacement(&m_wpOld);   这个获取的m_wpOld的参数showCmd确实是SW_NORMAL,而当m_wpNew=m_wpOld后,m_wpNew的参数showCmd也是SW_NORMAL,因此,当进行全屏设置时(下面的SetWindowPlacement(&wpNew);)设置的确实是在m_wpNew.rcNormalPosition=rectDesktop 中设置的窗口的正常显示的大小。。(2)而当窗口创建出来的时候,这个时候如果我们点击最大化按钮,这个时候再点击全屏菜单项,GetWindowPlacement(&m_wpOld);   这个获取的m_wpOld的参数showCmd就不是SW_NORMAL了,而是SW_MAXIMIZE,这个时候当m_wpNew=m_wpOld后,m_wpNew的参数showCmd也是SW_MAXIMIZE,因此,当进行全屏设置时(下面的SetWindowPlacement(&wpNew);)设置的就不是在m_wpNew.rcNormalPosition=rectDesktop 中设置的窗口的正常显示的大小(即:不是我们想要的全屏效果),而是原先你的窗口最大化时的大小,只不过是状态栏和工具栏没有了。。(大家可以试一下,以加深理解)..(3)所以,为了窗口在任何状态下都能有我们想要的全屏显示效果,在这里要进行wpNew.showCmd=SW_NORMAL/;设置,(而当进行还原的时候我们就不必重新设置了,因为还原的就是全屏之前的大小,即:(如果之前是最大化显示,那还原之后还是最大化))

 

             m_FullScreen=TRUE;//全屏完了以后要设置状态

             

              }

            else //如果是全屏状态下,即进行还原操作

            {

                     m_wndStatusBar.ShowWindow(SW_NORMAL);
                      m_wndToolBar.ShowWindow(SW_NORMAL);//还原后要把之前隐藏的工具栏菜单栏给显示出来

                     m_wpNew=m_wpOld; //还原之后的窗口就是之前保存的那个
                      m_FullScreen=0;、//设置状态

            }

 

              SetWindowPlacement(&m_wpNew);//根据要全屏或要还原的窗口大小进行设置。。

 

        到这里实际上,全屏效果已经显示出来了,但是,我们要再全屏后进行还原,还需要动态加载一个下拉菜单,当需要还原的时候,我们只要按下一个键,动态菜单就显示出来了,然后点击进行还原操作。

       所以呢,我们还需要一个成员变量CMenu m_menu.来进行动态加载菜单。。这里假设当我们按下ALT+S组合键的时候菜单就在全屏中显示出来。。因为要ALT键的信息,普通的WM_KEYDOWN捕获不到,这个ALT的消息是WM_SYSKEYDOWN,所以我们要再CMainFrame类中重写BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) 函数,在PreTranslateMessage(MSG* pMsg)里面进行捕获。下面是动态加载弹出菜单代码:

BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class
	
	if(m_bFullScreen && pMsg->message==WM_SYSKEYDOWN)//只有在全屏模式下按ALT+S组合键才弹出菜单。  然后再检测是否为WM_SYSKEYDOWN消息,即是否按下了ALT键
	{
 		if(pMsg->wParam=='S')//这里检测当按下了ALT键后 是否又按下了“S”键。
		{
			m_menu.CreatePopupMenu(); //创建弹出菜单
			m_menu.AppendMenu(0,IDR_FULLSCREEN,"还原");//追加一个菜单项,这个菜单项就是我们之前设置的全屏:IDR_FULLSCREEN菜单,因为我们的还原代码也写到这个事件中去了,大家可以修改。
			
			CPoint Pos;
			Pos.x=0;
			Pos.y=0;//设置菜单弹出时的位置,假设我们要它在左上角弹出
        	m_menu.TrackPopupMenu(TPM_RIGHTBUTTON,Pos.x,Pos.y,this);//在指定位置弹出菜单
			m_menu.DestroyMenu();//设置完后销毁菜单
		}
	}
	return CFrameWnd::PreTranslateMessage(pMsg);//MFC生成的代码,不碍咱事
}
 
OK,大功告成了。。。。。
怎么样,实验了吗?是不是出问题了啊?哈哈。。。全屏是不是全的不彻底啊,屏幕底边还保留了桌面的状态栏。。没关系,我们来解决这个问题,解决之前,首先,让我们来看一个WINDOWS消息WM_GETMINMAXINFO。。(拷贝一段说明)在Windows中,无论什么时候以何种方式改变窗口的尺寸或大小,是拖拽窗口边缘也好,或是在代码中调用改变窗口尺寸的函数也好,总之不管你用什么方法,Windows都会首先发送WM_GETMINMAXINFO消息。这个消息的意思是说:“嘿,如果你要强迫我的尺寸变大或变小,就附上详细的MINMAXINFO结构信息,否则我用默认值处理。”大多数应用程序都不用显式处理这个 WM_GETMINMAXINFO消息(也就是说让DefWindowProc窗口过程进行缺省处理)(那我们什么时候需要自己处理呢?答案是:当我们要限制一个窗口的最大尺寸或最小尺寸时就需要自己处理),而Windows在进行缺省处理时是不会让一个窗口视图比屏幕还大的,所以我们会碰上前面那个问题。解决的方法是:不要让Windows对WM_GETMINMAXINFO消息进行缺省处理,而是由我们自己处理,方法如下:添加消息处理事件: 
void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) 
{
	// TODO: Add your message handler code here and/or call default
	if(m_FullScreen)//我们只在全屏的时候才处理这个消息,还原的时候不不要处理
	{
		//下面的m_FullScreenWindowRect是什么在后边介绍	
    	  lpMMI->ptMaxTrackSize.y=m_FullScreenWindowRect.Height();//设置窗口能用鼠标拖拽的最大尺寸y
    	  lpMMI->ptMaxTrackSize.x=m_FullScreenWindowRect.Width();//设置窗口能用鼠标拖拽的最大尺寸x

	}
	CFrameWnd::OnGetMinMaxInfo(lpMMI);
}

 

MINMAXINFO的结构体:
typedef struct {POINT ptReserved; //不用,系统保留
                POINT ptMaxSize; //窗口最大化显示时的大小
                POINT ptMaxPosition; //窗口最大化时的放置点
                POINT ptMinTrackSize; //当用鼠标拖动改变窗口大小时的最小拖动范围,也就是说你用鼠标拖动时,它会实时地跟着你的鼠标改变窗口大小,当达到一定值之后,你再拖它,它也不会变小,下面的同理         
               POINT ptMaxTrackSize; //当用鼠标拖动改变窗口大小时的最大拖动范围,(我们要设置的就是这个参数)
              } MINMAXINFO; 
 


 

既然有了上面的分析,那么我们应该再再CMainFrame类中添加一个成员变量m_FullScreenWindowRect,保存全屏时的RECT:CRect  m_FullScreenWindowRect ;(注意这里的类型为MFC封装类:CRect,而不是RECT)

添加完以后就要为它赋值,在哪里赋?赋什么值呢?对,就在当初次获取到要全屏显示的窗口的大小时那里:  AdjustWindowRectEx(&rectDesktop,GetStyle(),TRUE,GetExStyle());//就在这后面赋值:

                         m_FullScreenWindowRect=rectDesktop;

 

做完这项工作以后,再把上面WM_GETMINMAXINFO消息的处理代码加上!

 

OK,这回是真的大功告成啦。。。






  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
我的华为之路——销售工程师二面,周三,西苑1层。 从西苑回来好好休息,以为第二天不会又面试,很轻松的起床后发现,凌晨华为发了二面通知短信。我是9点,起床时已经8:20…… 既来之则安之的洗漱,穿衣,出门,打车过去。9:05到达西苑。第一批二面的已经出发了……于是无聊的等待。好几拨二面都已经出发,都没有我。10点,终于有我了。现在想来,也有可能是把我安排到有来自华赛的面试官的场次了吧……" 正好有一位之前认识的同是北邮的cx和我一场,于是决定共进退。进场后发现之前给我一面的A也在面试官的行列,呵呵,感觉很奇特~坐定,女生4人,平分坐,每组两人。对面一组(成为K组吧~)有来自清华,北大,外经贸的传统“侃”校的人。另外还有化工,北交,北语等几位分散在各组。流程: 1,自我介绍,每人1分钟左右。 首先根据之前各位分享的面经,了解到相互介绍的环节。于是记录。沉稳的介绍完自己。 自我介绍围绕基本情况,今后职业发展目标或者人生目标,自己的优缺点这三点来介绍。 2,相互介绍,换顺序 面试官提出由K组开始,依次倒序介绍我们组的成员。北大的哥们在自我介绍时候没有注意别人的发言,介绍的很不好,仅仅是名字和学校。后来的环节中,他也提到,这个环节对他的影响很大,导致总体没有发挥。同志们引以为戒~ 到我们组时候,改了顺序,并提出不要看之前自己记录的东西。 2.5,插曲,一位面试官对于之前自我介绍中个人所提的缺点逐个问询。 3,给你印象深刻的人,以及其优点 这个环节没按照顺序。由于视线的问题以及自我介绍时候的特色,我介绍了对面一位女生,其他人也分别介绍了印象较深的人。其中很多人提到我,第一次当面被如此多的人提到对自己印象深刻,有些意外和兴奋,呵呵~这个环节结束后,A问我别人认可你的感觉和原因。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值