www.gusucode.com > VC++实现全屏功能演示代码-源码程序 > VC++实现全屏功能演示代码-源码程序/code/MainFrm.cpp
#include "stdafx.h" #include "FullView.h" #include "MainFrm.h" // Download by http://www.NewXing.com #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd) BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) //{{AFX_MSG_MAP(CMainFrame) ON_WM_CLOSE() ON_WM_CREATE() ON_WM_DESTROY() ON_WM_GETMINMAXINFO() ON_WM_SETTINGCHANGE() ON_COMMAND(ID_SET_SHOWMENU, OnSetShowmenu) ON_COMMAND(ID_SET_SHOWSCROLLBAR, OnSetShowscrollbar) ON_COMMAND(ID_VIEW_FULL_SCREEN, OnViewFullscreen) ON_COMMAND(ID_VIEW_TOGGLE_FULLSCREEN, OnViewToggleFullscreen) ON_COMMAND(ID_VIEW_TOOLBAR, OnViewToolbar) ON_COMMAND(ID_VIEW_STATUS_BAR, OnViewStatusBar) ON_UPDATE_COMMAND_UI(ID_SET_SHOWMENU, OnUpdateSetShowmenu) ON_UPDATE_COMMAND_UI(ID_SET_SHOWSCROLLBAR, OnUpdateSetShowscrollbar) ON_UPDATE_COMMAND_UI(ID_VIEW_FULL_SCREEN, OnUpdateViewFullscreen) ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, OnUpdateViewStatusBar) ON_UPDATE_COMMAND_UI(ID_VIEW_TOOLBAR, OnUpdateViewToolbar) //}}AFX_MSG_MAP ON_MESSAGE(WM_DISPLAYCHANGE, OnDisplayChange) ON_WM_SYSCOMMAND() END_MESSAGE_MAP() static UINT indicators[] = {ID_SEPARATOR,ID_INDICATOR_CAPS,ID_INDICATOR_NUM,ID_INDICATOR_SCRL}; BOOL CMainFrame::CalcFullScreenWndplChild() { //得到活动的子窗口的指针; CMDIChildWnd * pChildFrame=MDIGetActive(); if (!pChildFrame) return FALSE; else { CRect rectPotential; rectPotential.left=rectPotential.top=0; rectPotential.right = ::GetSystemMetrics(SM_CXSCREEN); rectPotential.bottom = ::GetSystemMetrics(SM_CYSCREEN); m_wndplFullScreenChild= *(m_mapHWndToWndpl[GetSafeHwnd()]); m_wndplFullScreenChild.showCmd = SW_SHOWMAXIMIZED; m_wndplFullScreenChild.rcNormalPosition = rectPotential; ::AdjustWindowRect(&(m_wndplFullScreenChild.rcNormalPosition), pChildFrame->GetStyle(), FALSE); m_wndplFullScreenChild.ptMaxPosition.x=m_wndplFullScreenChild.rcNormalPosition.left; m_wndplFullScreenChild.ptMaxPosition.y=m_wndplFullScreenChild.rcNormalPosition.top; m_bNeedToCalcWndplChild=FALSE; } return TRUE; } BOOL CMainFrame::CalcFullScreenWndplMain() { RECT rectPotential; if (!::SystemParametersInfo(SPI_GETWORKAREA, 0, &rectPotential, 0)) ::GetWindowRect(::GetDesktopWindow(), &rectPotential); else { rectPotential.right = ::GetSystemMetrics(SM_CXSCREEN); rectPotential.bottom = ::GetSystemMetrics(SM_CYSCREEN); rectPotential.right -= rectPotential.left; rectPotential.bottom -= rectPotential.top; rectPotential.left = -rectPotential.left; rectPotential.top = -rectPotential.top; } ::AdjustWindowRect(&rectPotential, GetStyle(), !m_bShowMenuBarInFullScreenMode); rectPotential.bottom += ::GetSystemMetrics(SM_CYBORDER); m_wndplFullScreenMain= *(m_mapHWndToWndpl[GetSafeHwnd()]); m_wndplFullScreenMain.showCmd = SW_SHOWNORMAL; m_wndplFullScreenMain.rcNormalPosition = rectPotential; m_wndplFullScreenMain.ptMaxPosition.x=m_wndplFullScreenMain.rcNormalPosition.left; m_wndplFullScreenMain.ptMaxPosition.y=m_wndplFullScreenMain.rcNormalPosition.top; return TRUE; } CMainFrame::CMainFrame() { m_bIsFullScreenMode=FALSE; m_bNeedToCalcWndplChild=TRUE;//需要计算; m_bShowStatusBarInFullScreenMode=FALSE;//显示状态栏? m_bShowMenuBarInFullScreenMode= AfxGetApp()->GetProfileInt("WindowStatus","ShowMenuBar",FALSE);//全屏时是否显示菜单栏; m_bShowStatusBarInFullScreenMode=AfxGetApp()->GetProfileInt("WindowStatus","ShowStatusBar",FALSE);//全屏时是否显示状态栏; m_bShowToolBarInFullScreenMode=AfxGetApp()->GetProfileInt("WindowStatus","ShowToolBar",FALSE); //全屏状态下显示工具栏? m_bShowScrollBar=AfxGetApp()->GetProfileInt("WindowStatus","ShowScrollBar",TRUE); //显示滚动条? //得到新的屏幕大小; WORD cxScreen = ::GetSystemMetrics(SM_CXSCREEN);//LOWORD WORD cyScreen = ::GetSystemMetrics(SM_CYSCREEN);//HIWORD m_dwOldScreenSize=MAKELPARAM(cxScreen,cyScreen); } CMainFrame::~CMainFrame() { } BOOL CMainFrame::ExpandToFullScreen() { //设置全屏标志; m_bIsFullScreenMode=TRUE; //计算大小; CalcFullScreenWndplMain(); m_bNeedToCalcWndplChild=!CalcFullScreenWndplChild(); //禁止“大小”和“最大化”系统菜单; ModifyStyle(WS_THICKFRAME|WS_MAXIMIZEBOX,0,0); //得到系统菜单的指针; CMenu * pMenu=GetSystemMenu(FALSE); //要加入的命令ID必需在系统命令范围之内; ASSERT((ID_GRAYEDMOVE & 0xFFF0) == ID_GRAYEDMOVE); ASSERT(ID_GRAYEDMOVE < 0xF000); //使“移动”菜单被禁用(替换掉原有的); CString strMove; pMenu->GetMenuString(SC_MOVE,strMove,MF_BYCOMMAND); pMenu->ModifyMenu(SC_MOVE,MF_BYCOMMAND|MF_STRING,ID_GRAYEDMOVE,strMove); pMenu->EnableMenuItem(ID_GRAYEDMOVE,MF_BYCOMMAND|MF_GRAYED); //锁住窗口不使之更新; LockWindowUpdate(); //默认在有菜单时不显示全屏工具栏; ShowControlBar(&m_tbFullScreen,!m_bShowMenuBarInFullScreenMode,TRUE);//用TRUE重画效果较好; //设置全屏大小的WindowPlacement; SetWindowPlacement(&m_wndplFullScreenMain); UnlockWindowUpdate(); return TRUE; } RECT CMainFrame::GetDesktopRect() { RECT rectDesktop; if (!::SystemParametersInfo(SPI_GETWORKAREA, 0, &rectDesktop, 0)) ::GetWindowRect(::GetDesktopWindow(), &rectDesktop); else { rectDesktop.right = ::GetSystemMetrics(SM_CXSCREEN); rectDesktop.bottom = ::GetSystemMetrics(SM_CYSCREEN); rectDesktop.right -= rectDesktop.left; rectDesktop.bottom -= rectDesktop.top; rectDesktop.left = -rectDesktop.left; rectDesktop.top = -rectDesktop.top; } return rectDesktop; } BOOL CMainFrame::GetFullScreenChildsMMI(MINMAXINFO *lpMMI) { if (!IsFullScreenMode()) return FALSE; else { POINT pt; pt.x=m_wndplFullScreenChild.rcNormalPosition.right-m_wndplFullScreenChild.rcNormalPosition.left; pt.y=m_wndplFullScreenChild.rcNormalPosition.bottom-m_wndplFullScreenChild.rcNormalPosition.top; lpMMI->ptMaxSize = pt; lpMMI->ptMaxTrackSize = pt; lpMMI->ptMaxPosition = m_wndplFullScreenChild.ptMaxPosition; return TRUE; } } void CMainFrame::OnClose() { //将窗口的大小和位置写入注册表; WINDOWPLACEMENT wndpl; if (IsFullScreenMode()) wndpl=*m_mapHWndToWndpl[GetSafeHwnd()]; else GetWindowPlacement(&wndpl); AfxGetApp()->WriteProfileInt("WindowPos","VertPos",wndpl.rcNormalPosition.top); AfxGetApp()->WriteProfileInt("WindowPos","HorizPos",wndpl.rcNormalPosition.left); AfxGetApp()->WriteProfileInt("WindowPos","Height",wndpl.rcNormalPosition.bottom - wndpl.rcNormalPosition.top); AfxGetApp()->WriteProfileInt("WindowPos","Width",wndpl.rcNormalPosition.right - wndpl.rcNormalPosition.left); AfxGetApp()->WriteProfileInt("WindowStatus","IsFullScreen",IsFullScreenMode()); AfxGetApp()->WriteProfileInt("WindowStatus","ShowMenuBar",m_bShowMenuBarInFullScreenMode); AfxGetApp()->WriteProfileInt("WindowStatus","ShowStatusBar",m_bShowStatusBarInFullScreenMode); AfxGetApp()->WriteProfileInt("WindowStatus","ShowToolBar",m_bShowToolBarInFullScreenMode); AfxGetApp()->WriteProfileInt("WindowStatus","ShowScrollBar",m_bShowScrollBar); CMDIFrameWnd::OnClose(); } int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { //若使用VC5,则可将CreateEX改为Create //并将有关ReBar工具栏的语句删掉或修改即可 if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.CreateEx(this) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("工具栏创建失败\n"); return -1; } m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle()|CBRS_TOOLTIPS | CBRS_FLYBY); if (!m_wndDlgBar.Create(this, IDR_MAINFRAME, CBRS_ALIGN_TOP, AFX_IDW_DIALOGBAR)) { TRACE0("对话栏创建失败\n"); return -1; } if (!m_wndReBar.Create(this) || !m_wndReBar.AddBar(&m_wndToolBar) ||!m_wndReBar.AddBar(&m_wndDlgBar)) { TRACE0("ReBar创建失败\n"); return -1; } if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT))) { TRACE0("状态栏创建失败\n"); return -1; } if (!m_tbFullScreen.CreateEx(this,TBSTYLE_FLAT, WS_CHILD | CBRS_ALIGN_TOP, CRect(0,0,0,0), IDR_FULLSCREEN) || !m_tbFullScreen.LoadToolBar(IDR_FULLSCREEN)) { TRACE0("全屏工具栏创建失败\n"); return -1; } m_tbFullScreen.SetBarStyle(m_tbFullScreen.GetBarStyle()|CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); //写工具栏的名称; m_tbFullScreen.SetWindowText("全屏幕"); //示例中不允许停靠; EnableDocking(CBRS_ALIGN_ANY); m_tbFullScreen.EnableDocking(0); //示例中任选位置显示,实际应用时应当 //随其它工具栏的状态一起存入注册表; FloatControlBar(&m_tbFullScreen,CPoint(9,14)); //取得主框架的WindowPlacement; WINDOWPLACEMENT * pWndpl=new WINDOWPLACEMENT; GetWindowPlacement(pWndpl); m_mapHWndToWndpl[GetSafeHwnd()]=pWndpl; //恢复上次的窗口状态; int y=AfxGetApp()->GetProfileInt("WindowPos","VertPos",lpCreateStruct->y); int x=AfxGetApp()->GetProfileInt("WindowPos","HorizPos",lpCreateStruct->x); int cy=AfxGetApp()->GetProfileInt("WindowPos","Height",pWndpl->rcNormalPosition.bottom-pWndpl->rcNormalPosition.top); int cx=AfxGetApp()->GetProfileInt("WindowPos","Width",pWndpl->rcNormalPosition.right-pWndpl->rcNormalPosition.left); SetWindowPos(NULL,x,y,cx,cy,SWP_NOZORDER); m_bIsFullScreenModeWhenLastShutDown=AfxGetApp()->GetProfileInt("WindowStatus","IsFullScreen",FALSE); if (m_bIsFullScreenModeWhenLastShutDown)//如果上次关闭程序时是全屏状态; OnViewFullscreen(); return 0; } void CMainFrame::OnDestroy() { //删除在CMap中的映射; WINDOWPLACEMENT * pWndpl=m_mapHWndToWndpl[GetSafeHwnd()]; delete pWndpl; m_mapHWndToWndpl.RemoveKey(GetSafeHwnd()); CMDIFrameWnd::OnDestroy(); } LRESULT CMainFrame::OnDisplayChange(WPARAM wParam, LPARAM lParam) { CMDIFrameWnd::OnDisplayChange(wParam, lParam); //若当前处于全屏状态,而且屏幕的大小改变; if(IsFullScreenMode() && m_dwOldScreenSize!=lParam) { //重新设置全屏状态; ExpandToFullScreen(); //保存屏幕大小; m_dwOldScreenSize=lParam; } return 0; } void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) { if (IsFullScreenMode()) { //在全屏状态下提供MINMAXINFO信息 POINT pt; pt.x=m_wndplFullScreenMain.rcNormalPosition.right-m_wndplFullScreenMain.rcNormalPosition.left; pt.y=m_wndplFullScreenMain.rcNormalPosition.bottom-m_wndplFullScreenMain.rcNormalPosition.top; lpMMI->ptMaxSize = lpMMI->ptMaxTrackSize = pt; lpMMI->ptMaxPosition.x = m_wndplFullScreenMain.ptMaxPosition.x; lpMMI->ptMaxPosition.y = m_wndplFullScreenMain.ptMaxPosition.y; } else CMDIFrameWnd::OnGetMinMaxInfo(lpMMI); } void CMainFrame::OnSetShowmenu() { m_bShowMenuBarInFullScreenMode=!m_bShowMenuBarInFullScreenMode; if (IsFullScreenMode()) { //重新扩展到全屏; ExpandToFullScreen(); } } void CMainFrame::OnSetShowscrollbar() { m_bShowScrollBar=!m_bShowScrollBar; HWND hWnd; WINDOWPLACEMENT * pWndpl; UINT uStyle; POSITION pos=m_mapHWndToWndpl.GetStartPosition(); while(pos) { m_mapHWndToWndpl.GetNextAssoc(pos,hWnd,pWndpl); if (hWnd!=GetSafeHwnd()) { //取得风格; uStyle=::GetWindowLong(hWnd,GWL_STYLE); //据情况取舍; if (m_bShowScrollBar) uStyle|=WS_HSCROLL|WS_VSCROLL; else uStyle&=~(WS_HSCROLL|WS_VSCROLL); //写回风格并刷新窗口; ::SetWindowLong(hWnd,GWL_STYLE,uStyle); ::SetWindowPos(hWnd,NULL,0,0,0,0,SWP_NOACTIVATE|SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); } } } void CMainFrame::OnSettingChange(UINT uFlags, LPCTSTR lpszSection) { CMDIFrameWnd::OnSettingChange(uFlags, lpszSection); //若当前处于全屏状态,而且界面元素的大小改变; if(IsFullScreenMode() && uFlags==SPI_SETNONCLIENTMETRICS) { //重新设置全屏状态; ExpandToFullScreen(); } } void CMainFrame::OnSysCommand(UINT nID, LONG lParam) { //取得项级窗口的指针; CFrameWnd* pFrameWnd = GetTopLevelFrame(); ASSERT_VALID(pFrameWnd); //在全屏和非帮助状态下; if (!pFrameWnd->m_bHelpMode && IsFullScreenMode()) { switch(nID) { case SC_SIZE: case SC_MAXIMIZE://加入对系统挂钩程序的支持; case SC_MOVE: case ID_GRAYEDMOVE://自行加入的命令; break;//什么也不做; default: CMDIFrameWnd::OnSysCommand(nID,lParam); break; } } else CMDIFrameWnd::OnSysCommand(nID, lParam); } void CMainFrame::OnUpdateSetShowmenu(CCmdUI* pCmdUI) { pCmdUI->SetCheck(m_bShowMenuBarInFullScreenMode); } void CMainFrame::OnUpdateSetShowscrollbar(CCmdUI* pCmdUI) { pCmdUI->SetCheck(ShowScrollBar()); } void CMainFrame::OnUpdateViewFullscreen(CCmdUI* pCmdUI) { pCmdUI->SetCheck(IsFullScreenMode()); } void CMainFrame::OnUpdateViewStatusBar(CCmdUI* pCmdUI) { CControlBar* pBar = GetControlBar(AFX_IDW_STATUS_BAR); if (pBar != NULL) { if(pBar->GetStyle() & WS_VISIBLE) pCmdUI->SetCheck(1); else pCmdUI->SetCheck(0); } } void CMainFrame::OnUpdateViewToolbar(CCmdUI* pCmdUI) { CControlBar* pBar = GetControlBar(AFX_IDW_REBAR); if (pBar != NULL) { if(pBar->GetStyle() & WS_VISIBLE) pCmdUI->SetCheck(1); else pCmdUI->SetCheck(0); } } void CMainFrame::OnViewFullscreen() { if(IsFullScreenMode()) { //退出全屏模式; RestoreToNormal(); } else //进入全屏模式; { //处理工具栏和状态栏的显示或隐藏; m_bHadToolBar = m_wndReBar.IsWindowVisible(); m_bHadStatusBar = m_wndStatusBar.IsWindowVisible(); ShowControlBar(&m_wndReBar, FALSE||m_bShowToolBarInFullScreenMode, FALSE); ShowControlBar(&m_wndStatusBar,FALSE||m_bShowStatusBarInFullScreenMode, FALSE); //重新取得各子框架的WindowPlacement; HWND hWnd; WINDOWPLACEMENT * pWndpl; POSITION pos=m_mapHWndToWndpl.GetStartPosition(); while(pos) { m_mapHWndToWndpl.GetNextAssoc(pos,hWnd,pWndpl); ::GetWindowPlacement(hWnd,pWndpl); } //扩大到全屏幕; ExpandToFullScreen(); } } void CMainFrame::OnViewStatusBar() { CControlBar* pBar = GetControlBar(AFX_IDW_STATUS_BAR); if (pBar != NULL) { ShowControlBar(pBar, (pBar->GetStyle() & WS_VISIBLE) == 0, FALSE); //如果用户在全屏状态下选择显示了状态栏,则下次进入全屏状态时就不隐藏它; if (IsFullScreenMode()) { if ( pBar->GetStyle() & WS_VISIBLE) m_bShowStatusBarInFullScreenMode=TRUE; else m_bShowStatusBarInFullScreenMode=FALSE; } } } void CMainFrame::OnViewToggleFullscreen() { //功能同OnViewFullscreen(),所以直接调用;这是一个单态的命令按钮,不保持被按下的状态; OnViewFullscreen(); } void CMainFrame::OnViewToolbar() { CControlBar* pBar = GetControlBar(AFX_IDW_REBAR); if (pBar != NULL) { ShowControlBar(pBar, (pBar->GetStyle() & WS_VISIBLE) == 0, FALSE); //如果用户在全屏状态下选择显示了工具栏,则下次进入全屏状态时就不隐藏它; if (IsFullScreenMode()) { if ( pBar->GetStyle() & WS_VISIBLE) m_bShowToolBarInFullScreenMode=TRUE; else m_bShowToolBarInFullScreenMode=FALSE; } } } BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) { if (pMsg->message==WM_KEYDOWN && IsFullScreenMode() && pMsg->wParam==VK_ESCAPE) { RestoreToNormal(); return TRUE; } else return CMDIFrameWnd::PreTranslateMessage(pMsg); } BOOL CMainFrame::RestoreToNormal() { //设置全屏标志 m_bIsFullScreenMode=FALSE; //设置需要计算的标志; m_bNeedToCalcWndplChild=TRUE; //取消禁止“大小”和“最大化”系统菜单; ModifyStyle(0,WS_THICKFRAME|WS_MAXIMIZEBOX,0); //得到系统菜单的指针; CMenu * pMenu=GetSystemMenu(FALSE); //复原“移动”菜单; pMenu->ModifyMenu(ID_GRAYEDMOVE,MF_BYCOMMAND|MF_STRING,SC_MOVE,"移动(&M)"); //锁住窗口不使之更新; LockWindowUpdate(); //处理工具栏和状态栏的显示或隐藏; ShowControlBar(&m_wndReBar, m_bHadToolBar, FALSE); ShowControlBar(&m_wndStatusBar, m_bHadStatusBar, FALSE); ShowControlBar(&m_tbFullScreen,FALSE,TRUE); //判断子窗口是否为最大化的; BOOL bChildMaximized=FALSE; CMDIChildWnd * pChildFrame=MDIGetActive(); if (pChildFrame && pChildFrame->GetStyle() & WS_MAXIMIZE) { bChildMaximized=TRUE; } //恢复所有窗口到普通状态; HWND hWnd; WINDOWPLACEMENT * pWndpl; POSITION pos=m_mapHWndToWndpl.GetStartPosition(); while(pos) { m_mapHWndToWndpl.GetNextAssoc(pos,hWnd,pWndpl); //设置所有的窗口的WindowPlacement为原先的值; ::SetWindowPlacement(hWnd,pWndpl); TRACE1("flags %d\n",pWndpl->flags); TRACE1("showCmd %d\n",pWndpl->showCmd); TRACE1("ptMinPosition.x %d\n",pWndpl->ptMinPosition.x); TRACE1("ptMinPosition.y %d\n",pWndpl->ptMinPosition.y); TRACE1("ptMaxPosition.x %d\n",pWndpl->ptMaxPosition.x); TRACE1("ptMaxPosition.y %d\n",pWndpl->ptMaxPosition.y); TRACE1("rcNormalPosition.left %d\n",pWndpl->rcNormalPosition.left); TRACE1("rcNormalPosition.top %d\n",pWndpl->rcNormalPosition.top); TRACE1("rcNormalPosition.right %d\n",pWndpl->rcNormalPosition.right); TRACE1("rcNormalPosition.bottom %d\n\n",pWndpl->rcNormalPosition.bottom); } //使窗口可更新; UnlockWindowUpdate(); return TRUE; }