原创技术文章 欢迎转载 但请注明出处
凌晨1:35,本人刚开通本博,感觉至少留下篇原创技术文章吧,在兄弟这,还不急着睡。
我原来的博客地址为 http://hi.baidu.com/zhongji
此博客会继续使用,但更多的技术文章将发布于博客园。
进入正题
最近学习DX,结合着MFC来使用,发现无法使用DX直接在创建设备的时候设置全屏
我尝试设置 D3DPRESENT_PARAMETERS中的Windowed参数,却发现之后的调用CreateDevice出错
所以未找到解决之道,在网上搜索了一些技术文章,直接用MFC设置全屏,说白了就是把窗口的位置设置为足够包含整个屏幕,依据自己的详细实现,完成了如下的类
头文件 ATMfcFullScreen.h
1 #pragma once 2 3 #include < assert.h > 4 5 class ATMfcFullScreen 6 { 7 public : 8 ATMfcFullScreen(); 9 10 void SetFrameView(CWnd * pFrame, CWnd * pView); 11 bool IsReady(); 12 13 void FullScreen(); 14 void Restore(); 15 bool IsFullScreen(); 16 CSize GetFullScreenSize(); 17 18 private : 19 CRect FullScreenRect(CRect & rcFrame, CRect & rcView, CRect & rcScreen); 20 CRect FullScreenRect(CWnd * pFrame, CWnd * pView); 21 22 void SetFrameViewPos(CRect rectPos); 23 24 private : 25 CRect m_rectRestore; 26 CWnd * m_pFrame; 27 CWnd * m_pView; 28 bool m_bFullScreen; 29 }; 实现文件 ATMfcFullScreen.cpp
1 #include " stdafx.h " 2 3 #include " ATMfcFullScreen.h " 4 5 6 ATMfcFullScreen::ATMfcFullScreen():m_rectRestore( 0 , 0 , 0 , 0 ) 7 { 8 m_pFrame = NULL; 9 m_pView = NULL; 10 m_bFullScreen = false ; 11 } 12 13 void ATMfcFullScreen::SetFrameView(CWnd * pFrame, CWnd * pView) 14 { 15 assert(pFrame != NULL && pView != NULL); 16 m_pFrame = pFrame; 17 m_pView = pView; 18 } 19 20 bool ATMfcFullScreen::IsReady() 21 { 22 return (m_pFrame != NULL && m_pView != NULL); 23 } 24 25 void ATMfcFullScreen::FullScreen() 26 { 27 if ( ! m_bFullScreen) 28 { 29 m_bFullScreen = true ; 30 m_pFrame -> GetWindowRect(m_rectRestore); 31 SetFrameViewPos(FullScreenRect(m_pFrame, m_pView)); 32 } 33 } 34 35 void ATMfcFullScreen::Restore() 36 { 37 if (m_bFullScreen) 38 { 39 m_bFullScreen = false ; 40 SetFrameViewPos(m_rectRestore); 41 } 42 } 43 44 bool ATMfcFullScreen::IsFullScreen() 45 { 46 return m_bFullScreen; 47 } 48 49 CSize ATMfcFullScreen::GetFullScreenSize() 50 { 51 CRect rectFullScreen = FullScreenRect(m_pFrame, m_pView); 52 return rectFullScreen.Size(); 53 } 54 55 CRect ATMfcFullScreen::FullScreenRect(CRect & rcFrame, CRect & rcView, CRect & rcScreen) 56 { 57 CRect rcMax; 58 rcMax.left = rcScreen.left + rcFrame.left - rcView.left; 59 rcMax.top = rcScreen.top + rcFrame.top - rcView.top; 60 rcMax.right = rcScreen.right + rcFrame.right - rcView.right; 61 rcMax.bottom = rcScreen.bottom + rcFrame.bottom - rcView.bottom; 62 return rcMax; 63 } 64 65 CRect ATMfcFullScreen::FullScreenRect(CWnd * pFrame, CWnd * pView) 66 { 67 assert(pFrame != NULL && pView != NULL); 68 69 CRect rectScreen( 0 , 0 , GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); 70 CRect rectFrame, rectView; 71 pFrame -> GetWindowRect(rectFrame); 72 pView -> GetClientRect(rectView); 73 pView -> ClientToScreen(rectView); 74 75 return FullScreenRect(rectFrame, rectView, rectScreen); 76 } 77 78 void ATMfcFullScreen::SetFrameViewPos(CRect rectPos) 79 { 80 // m_pFrame->SetWindowPos(NULL, rectPos.left, rectPos.top, rectPos.right, rectPos.bottom, 81 // SWP_NOZORDER); 82 83 m_pFrame -> MoveWindow(rectPos); 84 if (m_bFullScreen) 85 { 86 m_pFrame -> SetWindowPos( & CWnd::wndTopMost, rectPos.left, rectPos.top, 87 0 , 0 , SWP_NOSIZE); 88 } 89 else 90 { 91 m_pFrame -> SetWindowPos( & CWnd::wndNoTopMost, rectPos.left, rectPos.top, 92 0 , 0 , SWP_NOSIZE); 93 } 94 } 下面为使用方式
我之前写的个小程序是用来练习使用DX的,所以没有使用MFC的DOC/VIEW结构,我这里仅仅使用了MFC的单文档形式
具体实现方式
在CMainFrame中包含上面的头文件后,添加
private: //By 巨蚁 ATMfcFullScreen m_fullscreen;
在CMainFrame::OnCreate中添加
//初始化m_fullscreen m_fullscreen.SetFrameView(this, &m_wndView);
在CMainFram中添加WM_GETMINMAXINFO消息处理函数,函数实现如下所示,之所以添加一个检测m_fullscreen.IsReady(),原因在于此消息会先于WM_CREATE消息发出,而此时,我们在OnCreate中的m_fullscreen的初始化还没有进行。
void CMainFrame::OnGetMinMaxInfo(MINMAXINFO* lpMMI){ if (m_fullscreen.IsReady()) { CPoint point(m_fullscreen.GetFullScreenSize()); lpMMI->ptMaxSize = point; lpMMI->ptMaxTrackSize = point; } else { CFrameWnd::OnGetMinMaxInfo(lpMMI); }}
基本设置已经完成,下面就是设置全屏 和 还原 的命令了
为了方便测试,我定义了一个快捷键,当按下空格,产生 ID_AT_FULLSCREEN消息
我在CMainFrame中添加了消息处理函数,如下
void CMainFrame::OnAtFullscreen(){ if (m_fullscreen.IsFullScreen()) { m_fullscreen.Restore(); } else { m_fullscreen.FullScreen(); }}
编译完成,现在可以使用空格键来实现这个MFC程序从全屏与原大小之间的切换了
好,完成了,我就先飘过了~