如何实现全屏显示 全屏显示是一些应用软件程序必不可少的功能。比如在用VC++编辑工程源文件或编辑对话框等资源时,选择菜单“ViewFull Screen”,即可进入全屏显示状态,按“Esc”键后会退出全屏显示状态。
在VC++6.0中我们用AppWizard按默认方式生成单文档界面的应用程序框架。下面将先讨论点击菜单项“ViewFull Screen”实现全屏显示的方法,再讲述按“Esc”键后如何退出全屏显示状态。
1) 在CMainFrame类中,增加如下三个成员变量。
private: WINDOWPLACEMENT m_OldWndPlacement; //用来保存原窗口位置 BOOL m_bFullScreen; //全屏显示标志 CRect m_FullScreenRect; //表示全屏显示时的窗口位置 |
2)在资源编辑器中编辑菜单IDR_MAINFRAME。在“View”菜单栏下添加菜单项“Full Screen”。在其属性框中,ID设置为ID_FULL_SCREEN,Caption为“Full Screen”。还可以在工具栏中添加新的工具图标,并使之与菜单项“Full Screen”相关联,即将其ID值也设置为ID_FULL_SCREEN。
3)设计全屏显示处理函数,在CMainFrame类增加上述菜单项ID_FULL_SCREEN消息的响应函数。响应函数如下:
void CMainFrame::OnFullScreen() { GetWindowPlacement(&m_OldWndPlacement); CRect WindowRect; GetWindowRect(&WindowRect); CRect ClientRect; RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery, &ClientRect); ClientToScreen(&ClientRect); // 获取屏幕的分辨率 int nFullWidth=GetSystemMetrics(SM_CXSCREEN); int nFullHeight=GetSystemMetrics(SM_CYSCREEN); // 将除控制条外的客户区全屏显示到从(0,0)到(nFullWidth, nFullHeight)区域, 将(0,0)和(nFullWidth, nFullHeight)两个点外扩充原窗口和除控制条之外的 客户区位置间的差值, 就得到全屏显示的窗口位置 m_FullScreenRect.left=WindowRect.left-ClientRect.left; m_FullScreenRect.top=WindowRect.top-ClientRect.top; m_FullScreenRect.right=WindowRect.right-ClientRect.right+nFullWidth; m_FullScreenRect.bottom=WindowRect.bottom-ClientRect.bottom+nFullHeight; m_bFullScreen=TRUE; // 设置全屏显示标志为 TRUE // 进入全屏显示状态 WINDOWPLACEMENT wndpl; wndpl.length=sizeof(WINDOWPLACEMENT); wndpl.flags=0; wndpl.showCmd=SW_SHOWNORMAL; wndpl.rcNormalPosition=m_FullScreenRect; SetWindowPlacement(&wndpl); } |
4)重载CMainFrame类的OnGetMinMaxInfo函数,在全屏显示时提供全屏显示的位置信息。
void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) { if(m_bFullScreen) { lpMMI->ptMaxSize.x=m_FullScreenRect.Width(); lpMMI->ptMaxSize.y=m_FullScreenRect.Height(); lpMMI->ptMaxPosition.x=m_FullScreenRect.Width(); lpMMI->ptMaxPosition.y=m_FullScreenRect.Height(); //最大的Track尺寸也要改变 lpMMI->ptMaxTrackSize.x=m_FullScreenRect.Width(); lpMMI->ptMaxTrackSize.y=m_FullScreenRect.Height(); } CFrameWnd::OnGetMinMaxInfo(lpMMI) ; } |
完成上面的编程(www.cppentry.com)后,可以联编执行FullScreen.exe,选择菜单“ViewFull Screen”或点击与之关联的工具栏按钮即可进入全屏显示状态。但现在还需要增加用户退出全屏显示状态的操作接口,下面讲述如何编程(www.cppentry.com)实现按“Esc”键退出全屏显示状态。
1)在ClassView中选中CMainFrame并单击鼠标右键,选择“Add Member Function...”,添加public类型的成员函数EndFullScreen,该函数将完成退出全屏显示的操作。
void CMainFrame::EndFullScreen() { if(m_bFullScreen) {// 退出全屏显示, 恢复原窗口显示 ShowWindow(SW_HIDE); SetWindowPlacement(&m_OldWndPlacement); } } |
2)函数EndFullScreen可以退出全屏显示状态,问题是如何在“Esc”键被按下之后调用执行此函数。由于视图类可以处理键盘输入的有关消息(如WM_KEYDOWN表示用户按下了某一个键),我们将在视图类CFullScreenView中添加处理按键消息WM_KEYDOWN的响应函数OnKeyDown。判断如果按的键为“Esc”键,则调用CMainFrame类的函数EndFullScreen,便可退出全屏显示状态。
void CFullScreenView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { if(nChar==VK_ESCAPE) // 如果按的键为Esc键 {// 获取主框架窗口的指针 CMainFrame *pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd; // 调用主窗口类的自定义函数 EndFullScreen ,便可退出全屏显示状态 pFrame->EndFullScreen(); } CView::OnKeyDown(nChar, nRepCnt, nFlags); } |
更改窗口图标并将其显示在任务栏
以下两个函数可以为应用程序中的各子窗口显示一个任务条到任务栏并更改它们的图标。对那些象QQ一样隐藏主窗口的应用程序特别有用。
//函数用途:更改一个窗口的图标并将其显示在任务栏、任务切换条、任务管理器里 //参数说明: //hWnd 要改变图标的窗口句柄 //hLargeIcon 显示到任务切换条上的图标 32*32 //hSmallIcon 显示到除任务切换条之外的图标 16*16 //hIcon 显示的图标,32*32,在显示到任务切换条之外的其余地方时会被自动压缩成16*16的。 //注释: //此函数对于模式对话框无能为力。 //如果HICON 为NULL,函数不改变窗口图标,但是将原有图标显示到任务栏、 // 任务切换条、任务管理器里。 //此函数是通过将窗口的父窗口指针置空来实现将图标显示到任务栏、任务切换条、 // 任务管理器里的,所以调用完成后,其父窗口指针不再可用。 BOOL SendWndIconToTaskbar(HWND hWnd,HICON hLargeIcon,HICON hSmallIcon); BOOL SendWndIconToTaskbar(HWND hWnd,HICON hIcon); BOOL CUIApp::SendWndIconToTaskbar(HWND hWnd,HICON hLargeIcon,HICON hSmallIcon) { BOOL ret = TRUE; ASSERT(hWnd); if(!::IsWindow(hWnd)) return FALSE; //获取窗口指针 CWnd* pWnd; pWnd = pWnd->FromHandle(hWnd); ASSERT(pWnd); if(!pWnd) return FALSE; //将父窗口设为NULL if(pWnd->GetParent()) if(::SetWindowLong(hWnd,GWL_HWNDPARENT,NULL) == 0) return FALSE; if(!(pWnd->ModifyStyle(NULL,WS_OVERLAPPEDWINDOW))) ret = FALSE; //设置窗口图标 if(hLargeIcon && hSmallIcon) { pWnd->SetIcon(hSmallIcon,FALSE); pWnd->SetIcon(hLargeIcon,TRUE); } return ret; } BOOL CUIApp::SendWndIconToTaskbar(HWND hWnd,HICON hIcon) { BOOL ret = TRUE; ASSERT(hWnd); if(!::IsWindow(hWnd)) return FALSE; //获取窗口指针 CWnd* pWnd; pWnd = pWnd->FromHandle(hWnd); ASSERT(pWnd); if(!pWnd) return FALSE; //将父窗口设为NULL if(pWnd->GetParent()) if(::SetWindowLong(hWnd,GWL_HWNDPARENT,NULL) == 0) return FALSE; if(!(pWnd->ModifyStyle(NULL,WS_OVERLAPPEDWINDOW))) ret = FALSE; //设置窗口图标 pWnd->SetIcon(hIcon,TRUE); pWnd->SetIcon(hIcon,FALSE); return ret; } |
如何隐藏应用程序在任务栏上的显示
对于CFrameWnd可以在PreCreateWindow()函数中修改窗口的风格。
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { cs.style |=WS_POPUP;//使主窗口不可见 cs.dwExStyle |=WS_EX_TOOLWINDOW;//不显示任务按钮 return CFrameWnd::PreCreateWindow(cs); } |
对于其他窗口,可以在窗口被Create出来之后ShowWindow之前使用ModifyStyle()和ModifyStyleEx()来修改它的风格。
如何控制窗口框架的最大最小尺寸
要控制一个框架的的最大最小尺寸,你需要做两件事情。
第一步:在CFrameWnd的继承类中处理消息WM_GETMINMAXINFO,结构MINMAXINFO设置了整个窗口类的限制,因此记住要考虑工具条,滚动条等等的大小。
// 最大最小尺寸的象素点 - 示例 #define MINX 200 #define MINY 300 #define MAXX 300 #define MAXY 400 void CMyFrameWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) { CRect rectWindow; GetWindowRect(&rectWindow); CRect rectClient; GetClientRect(&rectClient); // get offset of toolbars, scrollbars, etc. int nWidthOffset = rectWindow.Width() - rectClient.Width(); int nHeightOffset = rectWindow.Height() - rectClient.Height(); lpMMI->ptMinTrackSize.x = MINX + nWidthOffset; lpMMI->ptMinTrackSize.y = MINY + nHeightOffset; lpMMI->ptMaxTrackSize.x = MAXX + nWidthOffset; lpMMI->ptMaxTrackSize.y = MAXY + nHeightOffset; }
|
第二步:在CFrameWnd的继承类的PreCreateWindow函数中去掉WS_MAXIMIZEBOX消息,否则在最大化时你将得不到预料的结果.
BOOL CMyFrameWnd::PreCreateWindow(CREATESTRUCT& cs) { cs.style &= ~WS_MAXIMIZEBOX; return CFrameWnd::PreCreateWindow(cs); } |
如何修改frame窗口的背景颜色?
MDI窗口的客户区是由frame窗口拥有的另一个窗口覆盖的。为了改变frame窗口背景的颜色,只需要这个客户区的背景颜色就可以了。你必须自己处理WM_ERASEBKND消息。下面是工作步骤:
创建一个从CWnd类继承的类,就叫它CMDIClient吧;
在CMDIFrameWnd中加入CMDIClient变量;(具体情况看下面的代码)
#include "MDIClient.h" class CMainFrame : public CMDIFrameWnd { ... protected: CMDIClient m_wndMDIClient; } |
重载CMDIFrameWnd::OnCreateClient,下面是这段代码,请注意其中的SubclassWindow();
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { if ( CMDIFrameWnd::OnCreateClient(lpcs, pContext) ) { m_wndMDIClient.SubclassWindow(m_hWndMDIClient); return TRUE; } else return FALSE; } |
最后要在CMDIClient中加入处理WM_ERASEBKGND的函数。
如何改变view的背景颜色?
若要改变CView,CFrameWnd或CWnd对象的背景颜色需要处理WM_ERASEBKGND消息,下面就是一个范例代码:
BOOL CSampleView::OnEraseBkgnd(CDC* pDC) { //设置brush为希望的背景颜色 CBrush backBrush(RGB(255, 128, 128)); //保存旧的brush CBrush* pOldBrush = pDC->SelectObject(&backBrush); CRect rect; pDC->GetClipBox(&rect); //画需要的区域 pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY); pDC->SelectObject(pOldBrush); return TRUE; } |
若要改变CFromView继承类的背景颜色,下面是一个范例代码:
HBRUSH CMyFormView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { switch (nCtlColor) { case CTLCOLOR_BTN: case CTLCOLOR_STATIC: { pDC->SetBkMode(TRANSPARENT); //不加任何处理或设置背景为透明 } case CTLCOLOR_DLG: { CBrush* back_brush; COLORREF color; color = (COLORREF) GetSysColor(COLOR_BTNFACE); back_brush = new CBrush(color); return (HBRUSH) (back_brush->m_hObject); } } return(CFormView::OnCtlColor(pDC, pWnd, nCtlColor)); } |