国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設(shè)計 > 正文

經(jīng)典與現(xiàn)代的結(jié)合:在MFC中集成RAD.NET框架

2019-11-17 05:02:08
字體:
供稿:網(wǎng)友
  MFC已經(jīng)有十幾年的歷史了,然而直到今天,他仍然是Visual C++的要害組成部分。從1996年的Visual C++ 4.2至今將近8年的時間,MFC的主體特征沒有出現(xiàn)明顯的變化,依舊是“古老”的面孔,因此關(guān)于這個類庫的種種評論自然是情理之中的事情了。從我個人的觀點上看,MFC功能依舊健壯、強大,而且是業(yè)界少有的、穩(wěn)定的、經(jīng)過足夠長歷史考驗的開發(fā)框架。深入研究這個類庫,你會找到酒越釀越醇的感覺。MFC的一個成功因素之一就是提供了一套完整的Document/View框架,然而這一點也是許多針對MFC批評的矛頭指向。也許是由于這個框架太經(jīng)典,使人們看上去MFC不再“婷婷玉立”,而是“人老珠黃”,以至于打開今天的Visual Studio IDE的時候,多少會有點不協(xié)調(diào)的感覺:比起其它基于.NET框架的開發(fā)語言,用MFC開發(fā)會顯得很“土氣”、“孤獨”——沒有RAD機制,明顯的缺乏與其它時髦對象的“互操作”能力,而且嚴格恪守自己的領(lǐng)地。每當生成一個基于文檔的MFC程序,我們總是看到一張滄桑的面孔,似乎劉姥姥進入大觀園,與四周時髦的C#、VB.NET等存在明顯的“代溝”與“不相容”。曾經(jīng)有很多人問我MFC還有前途嗎?是否已經(jīng)行將就木?關(guān)于是MFC還是.NET的討論時隱時現(xiàn),不絕于耳。CLR是個布滿魅力的世界,這種魅力,使得C#、VB.NET等變得光彩奪目。然而,MFC并沒有衰老,假如你深入的了解MFC,你會發(fā)現(xiàn),MFC完全可以與C#、VB.NET爭奇斗艷……  在MFC項目中使用托管擴展  支持托管擴展  .NET FrameWork提供的托管擴展支持確保了在MFC項目支持托管擴展(CLR),開發(fā)者可以使MFC工程(本文我們將使用Test作為工程名稱)通過打開項目的托管擴展屬性開關(guān),來增加編譯器的托管支持(如圖1)?! ?IMG height=274 alt="" src="http://www.knowsky.com/UploadFiles/20080308/200838144130077801.jpg" width=512>  (圖1:打開托管編譯支持開關(guān))
  對偶.NET對象  在打開托管擴展編譯開關(guān)以后,您就可以在MFC項目中使用托管對象了,通常的做法是:為每個重要的MFC對象匹配一個托管對象以形成一個對偶對,彼此匹配的對象包含指向?qū)Ψ降闹羔?,這樣,其他.NET對象可以通過對偶對中的.NET對象操作MFC對象;而其他MFC對象可以通過對偶對中的MFC對象操作.NET對象(如圖2)?! ?IMG height=360 alt="" src="http://www.knowsky.com/UploadFiles/20080308/2008381441306277802.jpg" width=480>  (圖2:對偶托管對象)  在Visual Studio .NET 中,沒有提供關(guān)于添加托管C++類對象的向?qū)?,因此,你可以先添加一個基于托管C++的Component對象(如圖3)。    (圖3. Add Class向?qū)В涸黾油泄蹸++ Component對象)  添加了該testDocObject托管組件對象之后,將該對象的基類改為Object,并刪除一些代碼得到一個最小托管類:
以下是引用片段:
namespace test
{
    __gc public class testDocObject
        : public Object
    {
    public:
        testDocObject(void)
        {
        }
    };
}
  經(jīng)過以上步驟,Visual Studio.NET生成的代碼被裝進了MFC程序,當然完全可以手動創(chuàng)建.h文件和.cpp文件,輸入相應(yīng)的代碼,然后把它們添加到當前工程。由于以上步驟在托管擴展編程中經(jīng)常碰到,因此,將上述過程自動化是必要的,有鑒于此,我們在附贈的光盤中提供了完整的添加.NET對象的Wizard。
  在MFC非托管類中定義托管成員變量  在MFC類中使用托管對象,提供對象的聲明和初始化方法與傳統(tǒng)的方法略有不同。以在文檔類CtestDoc中添加一個托管成員變量為例,聲明托管對象的代碼如下:
以下是引用片段:
public:
       gcroot<test::testDocObject*> m_ptestDocObj;
  gcroot類型安全包裝模板可以將托管參考類型指針作為成員變量嵌入到非托管類中,該變量就可以像其他類型的變量一樣使用了。在CtestDoc的成員函數(shù)InitialDocument中創(chuàng)建這個對象,代碼如下:
以下是引用片段:
BOOL CtestDoc::InitialDocument()
{
    #    #undef new
        m_ptestDocObj = new test::testDocObject();
    #pragma pop_macro("new")
}
  由于testDocObject是一個托管參考類型,它總被分配在CLR堆上,所以自然不能使用在afx.h中定義的new操作符來直接初始化該對象以避免該托管對象在非托管的本地C++堆上創(chuàng)建導致的錯誤。在托管對象中聲明MFC對象,與常規(guī)方法一致?! “盐樟松鲜龅幕就泄茴惡蛯ο笤趥鹘y(tǒng)MFC項目中的對偶使用方法,就可以保證您充分使用.NET框架所提供的豐富的類庫支持(引用相關(guān)的動態(tài)鏈接庫并聲明名稱空間是必要的)。假如希望更多地了解托管和非托管C++代碼混用的技術(shù),可以參考Tom Archer與Nishant Sivakumar合著,由Addison Wesley出版社出版的《Extending MFC applications with the .NET Framework》一書,相信會很有幫助。
  宿主.NET控件  宿主.NET控件的理論基礎(chǔ)  在.NET Framework的世界里,功能豐富的.NET控件無疑是光彩奪目的明珠,MFC程序自然想聯(lián)姻這些華麗的事物。由于MFC框架不提供對.NET控件的直接支持,從而導致MFC后天的失落(缺乏類似C#、VB.NET特有的可視化設(shè)計機制以及自由的控件組織功能),這一點多少成為MFC遠離.NET世界的一種合理的客觀原因。但是,我們注重到:.NET控件本質(zhì)上就是ActiveX控件,二者之間的重要區(qū)別是注冊方式不同——ActiveX控件是全局的,在系統(tǒng)注冊表中注冊;而.NET控件既可以在全局AssemblyCache中注冊,也可以放在局部的目錄中,相應(yīng)的,在程序中獲取它們相關(guān)信息的方式是不同的。但是,一旦.NET控件的基本信息被我們“捕捉”,我們就可以使用與創(chuàng)建ActiveX控件一致的方法將.NET控件創(chuàng)建到MFC項目中。    (圖4:MFC框架中ActiveX控件的創(chuàng)建)  我們知道,MFC是通過COleControlSite類創(chuàng)建ActiveX控件的,由于針對用于ActiveX控件的COleControlSite類不適用于.NET控件,因此必須重新派生一個新類CWFControlSite來提供必要的支持,通過一個CWFControlWrapper類將一個.NET控件包裝在一個CWnd窗體中,并將包裝后的窗體“安置”在CWFControlSite內(nèi)。CWFControlWrapper類代碼如下:
以下是引用片段:
class CWFControlWrapper : public CWnd
{
public:
    CWFControlWrapper();
    virtual ~CWFControlWrapper(void);
    IUnknown *pUnkControl;
    IUnknown *GetManagedControl()
    {
        return pUnkControl;
    }
    void SetControlSite(COleControlSite *pSite)
    {
        m_pCtrlSite = pSite;
    }
};
  下一步,要設(shè)計一個通用的CUserCtrlView類(從CView類派生),使得在CWFControlSite中指定的.NET控件可以像在COleControlSite中指定的ActiveX控件一樣顯示給用戶。正象每個ActiveX控件必需用一個CWnd對象進行創(chuàng)建一樣,一個支持.NET控件的CView類需要一個對應(yīng)的CWnd對象,CWFControlWrapper就是針對這個目的設(shè)計的,通過CWFControlWrapper對象,MFC程序可以得到.NET對象對應(yīng)的IUnknow、IDispatch。稍后我們介紹CUserCtrlView類的具體設(shè)計和使用方法?! ?IMG height=415 alt="" src="http://www.knowsky.com/UploadFiles/20080308/20083814413021877805.jpg" width=553>  (圖5:MFC框架中.NET控件的創(chuàng)建)
  NET控件的消息處理  一般而言,控件的對話框消息處理是一個極為要害的問題,在網(wǎng)上能找到的MFC中宿主控件的解決方法中,均沒有實現(xiàn).NET控件的對話框消息處理,一個明顯的特征是不能處理“Tab”鍵消息。為此,我們重載了CUserCtrlView的PreTranslateMessage函數(shù):
以下是引用片段:
BOOL CUserCtrlView::PreTranslateMessage(MSG *pMsg)
{
    BOOL bRet = FALSE;
    if(m_Control.pUnkControl != NULL)
    {
        CComQiptr<IOleInPlaceActiveObject>
            spInPlace(m_Control.pUnkControl);
        if(spInPlace)
            bRet =(S_OK == spInPlace->
                TranslateAccelerator(pMsg)) ?
                    TRUE : FALSE;
    }
    if(CView::PreTranslateMessage(pMsg))
        return TRUE;
    CFrameWnd *pFrameWnd = GetTopLevelFrame();
    if(pFrameWnd != NULL
    && pFrameWnd->m_bHelpMode)
        return FALSE;
    // start with first parent frame
    pFrameWnd = GetParentFrame();
    while(pFrameWnd != NULL)
    {
        if(pFrameWnd->PreTranslateMessage(pMsg))
            return TRUE;
        pFrameWnd = pFrameWnd->GetParentFrame();
    }
    return bRet;
}
  這樣可以使得CUserCtrlView可以正確的處理.NET Control的對話框消息。
  回歸RAD世界  接下來我們看看如何在工程中插入一個.NET用戶自定義控件。我們增加一個新的托管類testControl,代碼如下
以下是引用片段:
#pragma once

...

namespace test
{
    public __gc class testControl :
        public System::Windows::Forms::UserControl
    {
    public:
        testControl(void)
        {
            InitializeComponent();
        }
    protected:
        void Dispose(Boolean disposing)
        {
            if(disposing && components)
                components->Dispose();
            __super::Dispose(disposing);
        }
    private:
        System::Windows::Forms::Label *label1;
        System::ComponentModel::Container
            *components;
        void InitializeComponent(void)
        {
            this->label1 = new
                System::Windows::Forms::Label();
            this->SuspendLayout();
            this->label1->Location =
                System::Drawing::Point(16, 24);
            this->label1->Name = S"label1";
            this->label1->Size =
                System::Drawing::Size(208, 16);
            this->label1->TabIndex = 0;
            this->label1->Text =
                S"Welcome to TZ MFC.NET!";
            this->Controls->Add(this->label1);
            this->Name = S"testControl";
            this->Size =
                System::Drawing::Size(240, 160);
            this->ResumeLayout(false);
        }
    };
}
  注重,testControl類繼續(xù)自UserControl類,用戶控件是開發(fā)者創(chuàng)建的任何控件,您可以將多個.NET控件組織在一起,添加功能代碼,然后把它作為一個更綜合一些的控件來使用,使用每一個用戶控件和使用其他的.NET標準控件的步驟都是沒有區(qū)別的。在上面的代碼中,我們自定義的用戶控件僅包含了一個.NET Label控件。  到目前為止,我們已經(jīng)可以在原生MFC項目中成功插入.NET控件。然而,因為上面的.NET控件的插入是純手工方式的,不直觀且很難駕馭,一個聰明的辦法是實現(xiàn)一個集成在Visual Studio .NET IDE中的Wizard,以使得MFC工程中可以直接使用可視設(shè)計器,在隨機光盤中,我們提供了相關(guān)的Wizard,安裝后您就可以直接在MFC項目中插入并可視化設(shè)計.NET用戶控件了?! ⊥ㄟ^集成的Wizard,傳統(tǒng)的MFC可以與現(xiàn)代的.NET RAD機制完美的結(jié)合在一起,使得你既可以得到傳統(tǒng)C++的優(yōu)雅,又可以享有現(xiàn)代RAD機制的風韻,對資源的整合力度也極大地擴展了。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 鄱阳县| 沭阳县| 澄城县| 绵阳市| 安国市| 印江| 常德市| 西贡区| 南城县| 南溪县| 浑源县| 和龙市| 三门县| 会昌县| 宣恩县| 揭东县| 宜宾市| 会理县| 孟村| 永清县| 伊吾县| 洛阳市| 阳城县| 寿宁县| 大竹县| 洱源县| 崇礼县| 兰溪市| 绵竹市| 文化| 云霄县| 龙山县| 浠水县| 微山县| 永川市| 弋阳县| 林芝县| 仙居县| 扶绥县| 东辽县| 腾冲县|