相信用电脑看过电影的人都会下意识的默认双击一个播放器就会得到全屏播放影片的效果,那这个是怎么做到的呢?其实本人也是不知道的。。当然这篇文章不是到这就完了,而是介绍一种在MFC上全屏显示窗口或者PICTURE控件的方法,用此方法能做到全屏显示图像的效果,当然好坏还是有待考证的。
首先从简单的着手,来看如何实现MFC窗口的全屏显示,废话不说上代码:
在对话框头文件中添加变量:
//对话框功能 private: BOOL bFullScreen; CRect rectFullScreen; WINDOWPLACEMENT m_struOldWndpl;//结构中包含了有关窗口在屏幕上位置的信息
添加对话框的鼠标左键双击处理函数,并添加如下代码:
if (!bFullScreen) { //获取系统屏幕宽高 int g_iCurScreenWidth = GetSystemMetrics(SM_CXSCREEN); int g_iCurScreenHeight = GetSystemMetrics(SM_CYSCREEN); //用m_struOldWndpl得到当前窗口的显示状态和窗体位置,以供退出全屏后使用 GetWindowPlacement(&m_struOldWndpl); //计算出窗口全屏显示客户端所应该设置的窗口大小,主要为了将不需要显示的窗体边框等部分排除在屏幕外 CRect rectWholeDlg; CRect rectClient; GetWindowRect(&rectWholeDlg);//得到当前窗体的总的相对于屏幕的坐标 RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery, &rectClient);//得到窗口客户区坐标 ClientToScreen(&rectClient);//将客户区相对窗体的坐标转为相对屏幕坐标 rectFullScreen.left = rectWholeDlg.left - rectClient.left; rectFullScreen.top = rectWholeDlg.top - rectClient.top; rectFullScreen.right = rectWholeDlg.right + g_iCurScreenWidth - rectClient.right; rectFullScreen.bottom = rectWholeDlg.bottom + g_iCurScreenHeight - rectClient.bottom; //设置窗口对象参数,为全屏做好准备并进入全屏状态 WINDOWPLACEMENT struWndpl; struWndpl.length = sizeof(WINDOWPLACEMENT); struWndpl.flags = 0; struWndpl.showCmd = SW_SHOWNORMAL; struWndpl.rcNormalPosition = rectFullScreen; SetWindowPlacement(&struWndpl);//该函数设置指定窗口的显示状态和显示大小位置等,是我们该程序最为重要的函数 bFullScreen = true; } else { SetWindowPlacement(&m_struOldWndpl); bFullScreen = false; }
OK,到处窗口客户区全屏显示就完成一大部分了,运行一下双击窗口就会全屏显示窗口客户区,再双击则返回之前的窗体。
为什么说只是完成一大部分呢?原因在于现在的全屏还不是真正意义上的全屏,在目前的情况下双击全屏会发现底部开始菜单栏和右边一部分屏幕并没有被覆盖,究其原因是因为当窗体做出调整大小之类的操作时Windows会首先发送WM_GETMINMAXINFO消息,该消息在默认的缺省处理中是不允许窗体大小大于屏幕大小的。为此,我们要修改这个消息的响应函数,即主动为窗体添加WM_GETMINMAXINFO消息的处理函数,实现如下:
void CShowPictureInFullScreenDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (bFullScreen) { lpMMI->ptMaxSize.x = rectFullScreen.Width(); lpMMI->ptMaxSize.y = rectFullScreen.Height(); lpMMI->ptMaxPosition.x = rectFullScreen.left; lpMMI->ptMaxPosition.y = rectFullScreen.top; lpMMI->ptMaxTrackSize.x = rectFullScreen.Width(); lpMMI->ptMaxTrackSize.y = rectFullScreen.Height(); } CDialogEx::OnGetMinMaxInfo(lpMMI); }
到此,全屏显示窗口客户区的功能就完成了。如果仔细观察了上面所写的代码,会轻易的发现其中最为关键的一句为
SetWindowPlacement(&struWndpl);//该函数设置指定窗口的显示状态和显示大小位置等,是我们该程序最为重要的函数
如果我们把窗口客户区变为全屏大小之后将PICTURE控件调整大小填满整个客户区并且隐藏掉其他的控件,则可以得到全屏显示的图片。实现如下:
添加一个类变量存储PICTURE控件原位置信息
WINDOWPLACEMENT m_struOldWndpPic;//PICTURE控件在屏幕上位置的信息修改对话框的鼠标左键双击处理函数
if (!bFullScreen) { bFullScreen = true; //获取系统屏幕宽高 int g_iCurScreenWidth = GetSystemMetrics(SM_CXSCREEN); int g_iCurScreenHeight = GetSystemMetrics(SM_CYSCREEN); //用m_struOldWndpl得到当前窗口的显示状态和窗体位置,以供退出全屏后使用 GetWindowPlacement(&m_struOldWndpl); GetDlgItem(IDC_STATIC_PICSHOW)->GetWindowPlacement(&m_struOldWndpPic); //计算出窗口全屏显示客户端所应该设置的窗口大小,主要为了将不需要显示的窗体边框等部分排除在屏幕外 CRect rectWholeDlg; CRect rectClient; GetWindowRect(&rectWholeDlg);//得到当前窗体的总的相对于屏幕的坐标 RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery, &rectClient);//得到客户区窗口坐标 ClientToScreen(&rectClient);//将客户区相对窗体的坐标转为相对屏幕坐标 //GetDlgItem(IDC_STATIC_PICSHOW)->GetWindowRect(rectClient);//得到PICTURE控件坐标 rectFullScreen.left = rectWholeDlg.left - rectClient.left; rectFullScreen.top = rectWholeDlg.top - rectClient.top; rectFullScreen.right = rectWholeDlg.right + g_iCurScreenWidth - rectClient.right; rectFullScreen.bottom = rectWholeDlg.bottom + g_iCurScreenHeight - rectClient.bottom; //设置窗口对象参数,为全屏做好准备并进入全屏状态 WINDOWPLACEMENT struWndpl; struWndpl.length = sizeof(WINDOWPLACEMENT); struWndpl.flags = 0; struWndpl.showCmd = SW_SHOWNORMAL; struWndpl.rcNormalPosition = rectFullScreen; SetWindowPlacement(&struWndpl);//该函数设置指定窗口的显示状态和显示大小位置等,是我们该程序最为重要的函数 //将PICTURE控件的坐标设为全屏大小 GetDlgItem(IDC_STATIC_PICSHOW)->MoveWindow(CRect(0, 0, g_iCurScreenWidth, g_iCurScreenHeight)); } else { GetDlgItem(IDC_STATIC_PICSHOW)->SetWindowPlacement(&m_struOldWndpPic); SetWindowPlacement(&m_struOldWndpl); bFullScreen = false; }到此本篇博客希望实现的内容就都完成了,效果如下:
可以在鼠标双击函数中加上鼠标位置判断来实现鼠标双击位置在PICTURE控件内才放大的效果。本篇博客的工程在博客最后的链接中,该工程基于VS2013+OpenCV2.4.9,如有需要可以下载,要自行配置OpenCV方可运行。
工程地址:点击打开链接