深入MDI客戶視窗編程

來源:互聯網
上載者:User
在使用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);

//******增加代碼尾******

}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.