因為我的部門只有我一個人無奈之極,只有我一個做C++的,其他的都在做C#),所以我去跟技術顧問討論我們客戶端到底該怎麼呈現。他說按照以往上一套系統)的經驗,升級很頻繁,建議還是使用內嵌 HTML的方式來顯示界面,這樣以後只要升級HTML就可以了。我聽了之後,牙掉了一半,我拖了半個月的對話框就這麼給否了,心裡著實不是滋味。
然後就開始尋找MFC顯示HTML頁面的方法,找了一些自定義的HTML類,找了Webbrowser Control我到現在還沒找到這控件到底在哪裡),最終鎖定了CDHtmlDialog類。
這個類算是最近才開始大放異彩的吧,在vc6.0時代,用這玩意兒做出來的東西很難看,都是win2k風格。現在就可以使用什麼win7風格呀之類的,說不定在vs11裡還能使用Metro風格呢。。簡單試驗了一下,發現還是可以一用的,就決定下來要用這個了。
建立一個新的MFC Application工程,在這一步把HTML Dialog給勾上
可以看到如此一來,對話框就是從CDHtmlDialog類派生了。
建立完成後,觀察一下代碼跟以前的不同之處。發現了四點可能還有更多):
- class CTestHtmlDialogDlg : public CDHtmlDialog
表明此對話框類的確是繼承了CDHtmlDialog。
- // Dialog Data
- enum { IDD = IDD_TESTHTMLDIALOG_DIALOG, IDH = IDR_HTML_TESTHTMLDIALOG_DIALOG };
這兒的枚舉變成了兩個,也就是有一個普通對話框,還有一個HTML對話框。
- CTestHtmlDialogDlg::CTestHtmlDialogDlg(CWnd* pParent /*=NULL*/)
- : CDHtmlDialog(CTestHtmlDialogDlg::IDD, CTestHtmlDialogDlg::IDH, pParent)
在CTestHtmlDialogDlg的構造函數中,CDHtmlDialog的成員初始化列表中多了一個CTestHtmlDialogDlg::IDH。
- /////////////////////////////////////////////////////////////////////////////
- //
- // HTML
- //
- IDR_HTML_TESTHTMLDIALOG_DIALOG HTML "TestHtmlDialog.htm"
在resource文件中,多了這麼一行,用來指定HTML對話框的HTML文件資源,可以修改成自己喜歡的名字,比如index.html,當然在工程中的html文件也要修改成相應的名字。
我們來做個試驗。修改一下TestHtmlDialog.htm。
- <HTML>
- <HEAD>
- </HEAD>
- <BODY ID=CTestHtmlDialogDlg style="font-family:MS Shell Dlg;font-size:8">
- <h1>This is a test.</h1>
- <h2>I told you this is a test.</h2>
- <h3>Didn't hear me? This is a test!</h3>
- <img src="C:\\test.jpg">
- </BODY>
- </HTML>
顯示結果如下:
怎麼樣?比拖對話框、拖控件、加載資源、修改ID號、關聯變量、各種Load各種Show要簡單多了吧?
我這兒出了個問題,截止發文時尚未解決,如有大蝦指教煩請回復一下。我只能使用絕對路徑c:\test.jpg,而不能使用相對路徑,無論是test.jpg、..//test.jpg、..//Debug//test.jpg等等都不行,而且我把test.jpg在工程目錄裡放得到處都是,也不能加載,總是顯示一個小紅叉。。
-------------------------------我是華麗的分割線--------------------------------------
繼續我們的實驗。頁面不能光是顯示啊,總得有點什麼互動吧?那麼很高興這東西也支持Javascript。
利用VS2010自帶的HTML編輯器對TestHtmlDialog.htm進行編輯。這兒得贊一下VS2010的HTML編輯器,非常人性化,基本可以跟Dreamweaver媲美了,雙擊按鈕呀啥的都可以直接進入 onclick事件的編寫,默認Javascript。
我們拖一個按鈕在上面,改個名字,然後保存並雙擊按鈕編寫onclick事件
- function Button1_onclick() {
- alert("哈喽,擊這麼狠干啥");
- }
就彈出了剛才的alert信息。
-------------------------------我是華麗的分割線--------------------------------------
接下來我萌生了一個念頭,Javascript是不是可以調用本地對話框內的函數呢?去百度上Google了一會,發現當然是可以的。方法也比較簡單。
- // 1. 讓CTestHtmlDialog支持自動化
- // 在OnInitDialog()中添加
- EnableAutomation();
- // 2. 將自身暴露給Javascript
- // 在OnInitDialog()中添加
- SetExternalDispatch(GetIDispatch(TRUE)); //將浏覽器控件的擴展接口設置為對話框自身的IDispatch
- // 3. 聲明DISPATCH_MAP
- // 在TestHtmlDialog.h中
- DECLARE_DISPATCH_MAP()
- // 4. 定義DISPATCH_MAP
- // 在TestHtmlDialog.cpp中
- BEGIN_DISPATCH_MAP(CMyDHtmlDialog, CDHtmlDialog)
- DISP_FUNCTION(CMyDHTMLDialog, "SayHello", func, VT_EMPTY, VTS_NONE)
- END_DISPATCH_MAP()
應該看出來了,有點像MFC的消息映射機制。
接下來隨便寫個函數:
- MessageBox(_T("SayHello Func"), _T("Hello~~"));
修改一下剛才的按鈕單擊事件:
- function Button1_onclick() {
- //alert("哈喽,擊這麼狠干啥");
- external.SayHello();
- }
好,編譯運行。點擊按鈕,彈出個東西來:
因為要將程序內部暴露出來,Windows認為這可能是不安全的。點擊“是”之後,就看到了剛才寫的函數的效果。
但是我覺得很安全,我不想再看見剛才的這個東西。。該怎麼辦呢?一番尋找,便找到了解決方案。
在CTestHtmlDialog中,重載CanAccessExternal()函數。
- BOOL CWebbrowserDlg::CanAccessExternal()
- {
- return TRUE;
- }
這下,討厭的安全提示便不見啦~
-------------------------------我是華麗的分割線--------------------------------------
對話框可否訪問Javascript的函數呢?當然也可以,這樣就可以僅由Javascipt來判斷數據的合法性,讓C++來專心作邏輯運算了。
這個資料就相對少一些了,找了一個,還未吃透。仔細想一下,這方面的需要是比較少,所以資料也不太多。在codeproject上倒是找到了一個這方面的東西,感興趣的朋友就去觀望一下吧~ 時空穿梭傳送門
本文出自 “正面旺得福反面泰瑞寶” 博客,請務必保留此出處http://serious.blog.51cto.com/242085/864132