1. 程式人生 > >MFC對話方塊裡利用CHtmlView載入介面(四)————分層視窗設定

MFC對話方塊裡利用CHtmlView載入介面(四)————分層視窗設定


        在學會了 利用CHtmlView 在MFC對話方塊上顯示網頁,並支援JavaScript 和 MFC 之間的互相通訊後。 當然就想: 我們為什麼不能只用HTML 作為前端介面, 而底層用MFC實現邏輯呢? 這樣就完全不需要用到MFC對話方塊的介面風格了。


        本文就講告訴大家如何實現 用HTML代替MFC的對話方塊介面。

       首先解決的問題為: 如何使MFC對話方塊完全被HTML介面覆蓋?

        答案就在視窗風格設定上。 

        首先我們消除對話方塊上方的系統選單欄:ModifyStyle(WS_CAPTION , 0);

        這裡有必要解釋下ModifyStyle

函式。

BOOL ModifyStyle(
   DWORD dwRemove,
   DWORD dwAdd,
   UINT nFlags = 0
);

dwRemove指定在樣式修改時要移除的視窗樣式。 dwAdd 指定在樣式修改時要新增的視窗樣式。

ModifyStyle(WS_CAPTION , 0);相當於將WS_CAPTION風格移除。 此風格為:對話方塊上方的系統選單欄,包含了對話方塊的名稱、關閉、最大化、最小化等按鈕。

我們只需要上述設定,就可以移除整個系統選單欄。

  

這裡注意到:系統選單框 會佔據 對話方塊客戶區一定區域,具體為寬度 15,高度 20。

而我們的html介面的寬度為962, 高度632, 所以如果在有選單欄的風格中,要想將html全面顯示,則對話方塊寬度,高度至少應設定為977, 652.

  消除系統選單欄後,再用ModifyStyleEx( WS_EX_DLGMODALFRAME, 0) 消除對話方塊四邊的雙邊,即上圖的紅色標記部分。

消除後如圖:


這雙邊去除後,可以看到介面上多餘了一部分對話方塊,這是就需要我們設定對話方塊框的大小,剛好為html介面大小。

如下圖,這樣就將html完全覆蓋了對話方塊介面。


但是僅僅這樣做時,我們發現在將介面最小化後再次彈出時,介面會出現閃爍。我分析閃爍的根本原因為:MFC對話方塊要先繪製背景,然後再繪製html,這樣就會出現閃爍。

故,利用windows分層視窗( LayeredWindows)來將背景對話方塊透明化,這樣就能避免閃爍了。

具體的步驟如下:

一:設定視窗風格為分層視窗(WS_EX_LAYERED):

   有兩種方法可以設定視窗屬性:

   方法一:

ModifyStyleEx(0,WS_EX_LAYERED); //設定視窗擴充套件風格為:分層視窗

方法二:

SetWindowLong(GetSafeHwnd(),GWL_EXSTYLE,WS_EX_LAYERED);

當設定了視窗風格為分層視窗後, 如果你未呼叫SetLayeredWindowAttributesUpdateLayeredWindow為其設定透明情況,那麼預設將為全透明,不會彈出任何視窗。

二:設定背景透明屬性

::SetLayeredWindowAttributes(GetSafeHwnd(),RGB(255, 0, 255), 255,LWA_COLORKEY); //將背景顏色為RGB(255, 0, 255)透明化

或:

this->SetLayeredWindowAttributes(RGB(255, 0, 255), 255, LWA_COLORKEY );//將背景顏色為RGB(255, 0, 255)透明化

三:設定對話方塊背景顏色

SetLayeredWindowAttributes中,有一項為設定透明顏色, 表示在繪製對話方塊背景時,如果為透明顏色,則讓其透明。 這就需要我們在背景繪製時,將其繪製為透明顏色,使其透明。

設定對話方塊背景的方式:

在OnPaint函式中:

voidCMFCHtmlTest1Dlg::OnPaint()

{

if (IsIconic())

{

。。。

}

else

{

    CPaintDCdc(this);

RECTrect;

GetClientRect(&rect);

dc.FillSolidRect(&rect,RGB(255, 0, 255));  //設定對話方塊背景顏色

CDialogEx::OnPaint();

}

}


未透明 和 透明視窗 效果如圖:



利用分層視窗,我們就解決了彈出介面閃爍問題。

最終這些設定我都在OnInitDialog()完成:

BOOLCMFCHtmlTest1Dlg::OnInitDialog()

{

CDialogEx::OnInitDialog();

//將“關於...”選單項新增到系統選單中。

// IDM_ABOUTBOX必須在系統命令範圍內。

ASSERT((IDM_ABOUTBOX & 0xFFF0) ==IDM_ABOUTBOX);

ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu*pSysMenu = GetSystemMenu(FALSE);

if (pSysMenu !=NULL)

{

BOOLbNameValid;

CStringstrAboutMenu;

bNameValid =strAboutMenu.LoadString(IDS_ABOUTBOX);

ASSERT(bNameValid);

if (!strAboutMenu.IsEmpty())

{

pSysMenu->AppendMenu(MF_SEPARATOR);

pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);

}

}

//設定此對話方塊的圖示。  當應用程式主視窗不是對話方塊時,框架將自動

// 執行此操作

SetIcon(m_hIcon,TRUE);        // 設定大圖示

SetIcon(m_hIcon,FALSE);       // 設定小圖示

// TODO: 在此新增額外的初始化程式碼

ModifyStyle(WS_CAPTION , 0); //移除對話方塊 上方的系統選單欄

ModifyStyleEx(WS_EX_DLGMODALFRAME, 0);//分層視窗,並且不在工作列裡顯示,不帶雙邊

SetWindowLong(GetSafeHwnd(),GWL_EXSTYLE,WS_EX_LAYERED);

CRectrtDesk;

GetWindowRect(rtDesk);

MoveWindow(rtDesk.left,rtDesk.top,width, height);

this->SetLayeredWindowAttributes(RGB(255, 0, 255), 255, LWA_COLORKEY );

m_HtmlView.CreateFromStatic(IDC_STATIC1,this); //載入html

returnTRUE// 除非將焦點設定到控制元件,否則返回 TRUE

}