在使用VC6.0/5.0的AppWizard生成MDI应用的时候,我们发现MDI主窗口的客
户区背景千篇一律的是深灰的。VC6.0/5.0并没有提供修改其背景色的方法。甚 至使用SDK编程也没有好的方法修改背景色。以至于微软的产品如Office也是灰蒙 蒙的背景。那么,有没有办法将背景设置为自己喜欢的颜色呢? 笔者在学习过程中摸索出一套随意改变客户区窗口颜色的方法。利用这套方法, 可以将客户区窗口设为256色背景甚至设为BITMAP位图以至于动画等等。大大地增 强了程序的多媒体效果。 先介绍对MDI客户窗口编程的基本原理。 一、MDI客户窗口 一个MDI应用的主框架窗口包含一个特殊的子窗口称为MDICLIENT窗口。 MDICLIENT窗口负责管理主框架窗口的客户区。MDICLIENT窗口本身有自己的 子窗口即由CMDIChildWnd派生的文档窗口,也就是MDI子窗口。MDI主框架窗口 负责管理MDICLIENT子窗口。当控制条(菜单条,状态条等)发生变化时,MDI主 框架窗口重新配置MDICLIENT窗口。MDICLIENT子窗口负责管理全部的MDI子窗口。 父窗口负责将某些命令传递到子窗口。因此,消息队列发向MDI子窗口的消息 由MDICLIENT窗口负责传递,发向MDICLIENT窗口和MDI子窗口的消息由主框架窗 口负责传递。这样,我们可以在主框架窗口截获关于MDICLIENT窗口的重画消息 然后加入自己设计的代码。 二、MDI客户窗口编程方法 对MDI客户窗口编程有一定的难度。原因是MDIFrameWnd的客户区完全被 MDICLIENT窗口覆盖掉了。这样,MDI主窗口类MDIFrameWnd的背景色和光标都不 起作用。同时,微软并不支持将MDICLIENT窗口作为子类,MDICLIENT窗口只能使 用标准的背景色和光标。所以,对MDI客户窗口编程不能象对普通窗口那样简单 地重载WM_PAINT的消息处理函数。 改变MDI客户窗口背景的方法有两种。 使用CMDIFrameWnd::CreateClient 函数: CreateClient( LPCREATESTRUCT lpCreateStruct, CMenu* pWindowMenu ); 参数lpCreateStruct是指向CREATESTRUCT 结构的指针。在CREATESTRUCT 结构 中lpszClass项指向窗口类WNDCLASS结构。通过改变WNDCLASS结构中的 HbrBackground项和hCursor项可以更改MDICLIENT窗口的背景刷和光标。由于该 函数创建新的MDICLIENT窗口对象,必须在重载的主窗口的OnCreate成员函数中 调用。该方法比较复杂,必须手动创建MDI客户窗口,不能利用AppWizard自动 提供的功能。而且,只能使用Windows95有限的16色背景刷。本文采用第二种方法。 在主框架窗口的消息队列中截获发向MDI客户窗口的WM_PAINT消息并向主框架窗 口发送一条标志消息。在这条标志消息的处理函数中对MDI客户窗口进行操作。 该方法比较简捷,但有几点值得注意的地方。 首先,如何截获MDI客户窗口WM_PAINT消息。MFC提供 了PreTranslateMessage(MSG* pMsg) 函数。它在消息发送到TranslateMessage 和DispatchMessage 函数以前预先解释消息。可以重载该函数截获MDI客户窗 口WM_PAINT消息: BOOL PreTranslateMessage(MSG* pMsg) { if(pMsg->hwnd==m_hWndMDIClient && pMsg->message==WM_PAINT) PostMessage(WM_PAINT); return CMDIFrameWnd::PreTranslateMessage(pMsg); } 其次,为简单起见,这里将标志消息设为MDI主窗口的WM_PAINT。在MDI主窗 口WM_PAINT的消息处理函数中增加重画MDI客户窗口的代码。读者也可以自定义 消息,不过麻烦一点。 最后,由于对MDI客户窗口的操作都是在主窗口完成的。如何在主窗口中获得 MDI客户窗口的设备描述表呢。其实,在MDI主窗口类中有MDI客户窗口成员 m_hWndMDIClient。按如下方法得到客户窗口的设备描述表 dc.m_hDC=::GetDC(this->m_hWndMDIClient); 然后就可以对客户窗口进行操作了。 三、实例 将客户窗口设为256色背景。 使用AppWizard生成MDI应用TEST。 在TEST.CPP中的函数,增加如下代码: BOOL CTestApp::InitInstance() { AfxEnableControlContainer(); #ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif SetRegistryKey(_T("Local AppWizard-Generated Applications")); LoadStdProfileSettings(); // Load standard INI file options (including MRU) CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_TESTTYPE, RUNTIME_CLASS(CTestDoc), RUNTIME_CLASS(CChildFrame), // custom MDI child frame RUNTIME_CLASS(CTestView)); AddDocTemplate(pDocTemplate); // create main MDI Frame window CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; m_pMainWnd = pMainFrame; // Parse command line for standard shell commands, DDE, file open CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // Dispatch commands specified on the command line if (!ProcessShellCommand(cmdInfo)) return FALSE; // The main window has been initialized, so show and update it. pMainFrame->ShowWindow(m_nCmdShow); //******增加代码头****** AfxGetMainWnd()->PostMessage(WM_PAINT); //******增加代码尾****** pMainFrame->UpdateWindow(); return TRUE; } 保证程序一开始就更新客户窗口。 使用ClassWard在CmainFrame类中加入PreTranslateMessage消息处理函数入如下: BOOL PreTranslateMessage(MSG* pMsg) { //******增加代码头****** if(pMsg->hwnd==m_hWndMDIClient && pMsg->message==WM_PAINT) PostMessage(WM_PAINT); //******增加代码尾****** return CMDIFrameWnd::PreTranslateMessage(pMsg); } 在主窗口的WMPAINT消息处理函数中加入: void CMainFrame::OnPaint() { //******增加代码头****** CMDIFrameWnd::OnPaint(); CRect rc; CDC dc; dc.m_hDC=::GetDC(this->m_hWndMDIClient); CBrush br(RGB(120,200,40));//256色刷子 dc.SelectObject(&br); dc.GetClientRect(&rc); dc.PatBlt(rc.left,rc.top,rc.Width(),rc.Height(),PATCOPY); ReleaseDC(&dc); //******增加代码尾****** } 将客户窗口设为Bitmap位图。 1,2,3同例一。 4.在资源中加入自己喜欢的位图并设为IDB_BITMAP1。在主窗口类加入Cbitmap 类成员m_bmp。并在CMDIFrameWnd::OnCreate()函数末尾初始化: m_bmp.LoadBitmap(IDB_BITMAP1); 5.在主窗口的WM_PAINT消息处理函数中加入: void CMainFrame::OnPaint() { //******增加代码头****** CMDIFrameWnd::OnPaint(); CRect rc,memrc; CDC dc,memdc; dc.m_hDC=::GetDC(this->m_hWndMDIClient); memdc.CreateCompatibleDC(&dc); memdc.SelectObject(&m_bmp); GetClientRect(&rc) ; dc.BitBlt(rc.top,rc.left,rc.Width(),rc.Height() ,&memdc,rc.top,rc.left,SRCCOPY); ReleaseDC(&memdc); ReleaseDC(&dc); //******增加代码尾****** } |
MDI应用的主框架窗口背景设置
最新推荐文章于 2021-07-09 16:00:40 发布