posts - 495,comments - 227,trackbacks - 0
            摘要: 本文對COM組件中的ActiveX控件的MFC開發(fā)方法進(jìn)行了介紹,講述了用戶自定義和庫存屬性、方法以及事件的添加方法和屬性頁的制作過程。使讀者能夠掌握基本的MFC ActiveX開發(fā)方法。

            關(guān)鍵詞: MFC;ActiveX控件;COM

            閱讀目錄:

            一、前言
            二、建立工程框架
            三、屬性、方法以及事件的添加
            四、實(shí)現(xiàn)屬性表
            五、在包容程序中使用ActiveX控件
            六、小結(jié)


            前言

            ActiveX控件是一種實(shí)現(xiàn)了一系列特定接口而使其在使用和外觀上更象一個(gè)控件的COM組件。ActiveX控件這種技術(shù)涉及到了幾乎所有的COM和OLE的技術(shù)精華,如可鏈接對象、統(tǒng)一數(shù)據(jù)傳輸、OLE文檔、屬性頁、永久存儲以及OLE自動化等。

            ActiveX控件作為基本的界面單元,必須擁有自己的屬性和方法以適合不同特點(diǎn)的程序和向包容器程序提供功能服務(wù),其屬性和方法均由自動化服務(wù)的IDispatch接口來支持。除了屬性和方法外,ActiveX控件還具有區(qū)別于自動化服務(wù)的一種特性--事件。事件指的是從控件發(fā)送給其包容程序的一種通知。與窗口控件通過發(fā)送消息通知其擁有者類似,ActiveX控件是通過觸發(fā)事件來通知其包容器的。事件的觸發(fā)通常是通過控件包容器提供的IDispatch接口來調(diào)用自動化對象的方法來實(shí)現(xiàn)的。在設(shè)計(jì)ActiveX控件時(shí)就應(yīng)當(dāng)考慮控件可能會發(fā)生哪些事件以及包容器程序?qū)ζ渲械哪男┦录信d趣并將這些事件包含進(jìn)來。與自動化服務(wù)不同,ActiveX控件的方法、屬性和事件均有自定義(custom)和庫存(stock)兩種不同的類型。自定義的方法和屬性也就是是普通的自動化方法和屬性,自定義事件則是自己選取名字和Dispatch ID的事件。而所謂的庫存方法、屬性和事件則是使用了ActiveX控件規(guī)定了名字和Dispatch ID的"標(biāo)準(zhǔn)"方法、屬性和事件。

            ActiveX控件可以使COM組件從外觀和使用上能與普通的窗口控件一樣,而且還提供了類似于設(shè)置Windows標(biāo)準(zhǔn)控件屬性的屬性頁,使其能夠在包容器程序的設(shè)計(jì)階段對ActiveX控件的屬性進(jìn)行可視化設(shè)置。ActiveX控件提供的這些功能使得對其的使用將是非常方便的。本文下面即以MFC為工具對ActiveX控件的開發(fā)進(jìn)行介紹。
            建立工程框架

            通過"MFC ActiveX ControlWizard"向?qū)Э梢苑浅H菀椎慕⒁粋€(gè)MFC ActiveX控件工程框架。按照默認(rèn)的選項(xiàng)將建立如圖1所示的工程結(jié)構(gòu):


          圖1 使用缺省選項(xiàng)建立的ActiveX控件工程結(jié)構(gòu)

            其中,_DSample68和_DSample68Events這兩個(gè)接口將為客戶程序提供本控件的屬性、方法以及可能響應(yīng)的事件。全局函數(shù)DllRegisterServer()和DllUnregisterServer()分別用于控件在注冊表的注冊和注銷,一般不需要對其進(jìn)行改動。

            應(yīng)用程序類從COleControlModule繼承。而COleControlModule有是從CWinApp派生,提供了初始化控件模塊的功能。CSample68PropPage的基類是COlePropertyPage,CDialog類的派生類,主要負(fù)責(zé)對屬性頁中對圖形界面下用戶控件屬性的顯示。控件類CSample68Ctrl類是這幾個(gè)類中比較重要的一個(gè)類,大部分實(shí)質(zhì)性工作都在該類完成,其基類為COleControl,從CWnd和CCmdTarget繼承,因此能夠?yàn)榭丶ο筇峁┡cMFC窗口對象相同的功能同時(shí)也提供了一系列事件觸發(fā)函數(shù)和一個(gè)分發(fā)映射表,使ActiveX控件能夠同包容器程序有效地進(jìn)行交互。該類的派生類將可以在滿足特定的條件時(shí)向控件的包容器發(fā)送消息或是觸發(fā)事件,以通知包容器程序在控件內(nèi)有一些重要的事件發(fā)生。分發(fā)映射表是其中很重要的一個(gè)部分,負(fù)責(zé)向包容器程序暴露控件提供的方法和屬性。圖2展示了COleControl類在控件與包容器通信中所起的作用。可以看出,ActiveX控件與其包容器之間的所有通信過程都是由COleControl來完成的:


          圖2 COleControl在ActiveX控件與包容器通信中的作用

            控件類對基類COleControl的OnDraw()函數(shù)進(jìn)行了重載,向?qū)闪巳缦氯笔〈a,其作用是在控件的客戶區(qū)繪制一個(gè)橢圓。在編程過程中通常要對其進(jìn)行替換:

          void CSample68Ctrl::OnDraw(
          CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
          {
           // TODO: Replace the following code with your own drawing code.
           pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
           pdc->Ellipse(rcBounds);
          }


          圖3 插入ActiveX控件


          圖4 插入的待測試控件

            對向?qū)傻拇a進(jìn)行編譯后,將產(chǎn)生擴(kuò)展名為ocx的ActiveX控件。ActiveX控件并不能獨(dú)立運(yùn)行,只能在包容器程序中才能夠運(yùn)行。通常,為了調(diào)試方便而多使用VC++附帶的ActiveX Control Test Container工具以在測試階段對ActiveX控件進(jìn)行調(diào)試。在測試工具的客戶區(qū)點(diǎn)擊鼠標(biāo)右鍵,并選中彈出菜單的"Insert New Control…"菜單項(xiàng),將彈出圖3所示的對話框,左側(cè)的列表框中列出了當(dāng)前系統(tǒng)中所有注冊的ActiveX控件,選中要測試的控件并將其插入到測試程序即可通過"Control"菜單下的各菜單項(xiàng)對控件的方法、屬性以及事件等進(jìn)行測試。在位于下方的分割視圖中將跟蹤顯示出調(diào)試記錄(參見圖4)。
            屬性、方法以及事件的添加


          圖5 屬性的添加


          圖6 方法的添加

            對ActiveX控件屬性、方法和事件的添加均有庫存和自定義兩種。其中對屬性和方法的添加在MFC ClassWizard對話框的Automation頁中通過按鈕"Add Property…"和"Add Method…"彈出如圖5和圖6所示的添加屬性和添加方法的對話框來完成。對于庫存屬性和方法,可以直接從External name組合框的下拉列表中選取,Implementation項(xiàng)將自動設(shè)置為Stock。對于自定義屬性和方法的添加與在自動化對象中為接口添加屬性和方法的過程一樣,ClassWizard將在.odl文件和控件類生成相應(yīng)的代碼,下面給出的是在控件類中實(shí)現(xiàn)的部分分發(fā)映射代碼:

          ……
          // Dispatch maps
          //{{AFX_DISPATCH(CSample68Ctrl)
          CString m_message;
          afx_msg void OnMessageChanged();
          afx_msg short GetXPos();
          afx_msg void SetXPos(short nNewValue);
          afx_msg short GetYPos();
          afx_msg void SetYPos(short nNewValue);
          afx_msg short MessageLen();
          //}}AFX_DISPATCH
          DECLARE_DISPATCH_MAP()
          // Dispatch and event IDs
          public:
          enum {
          //{{AFX_DISP_ID(CSample68Ctrl)
          dispidMessage = 1L,
          dispidXPos = 2L,
          dispidYPos = 3L,
          dispidMessageLen = 4L,
          //}}AFX_DISP_ID
          };
          ……
          BEGIN_DISPATCH_MAP(CSample68Ctrl, COleControl)
          //{{AFX_DISPATCH_MAP(CSample68Ctrl)
          DISP_PROPERTY_NOTIFY(CSample68Ctrl, "Message", m_message, OnMessageChanged, VT_BSTR)
          DISP_PROPERTY_EX(CSample68Ctrl, "XPos", GetXPos, SetXPos, VT_I2)
          DISP_PROPERTY_EX(CSample68Ctrl, "YPos", GetYPos, SetYPos, VT_I2)
          DISP_FUNCTION(CSample68Ctrl, "MessageLen", MessageLen, VT_I2, VTS_NONE)
          DISP_STOCKPROP_BACKCOLOR()
          DISP_STOCKPROP_CAPTION()
          DISP_STOCKPROP_FORECOLOR()
          //}}AFX_DISPATCH_MAP
          END_DISPATCH_MAP()
          ……

            在這里共添加了一個(gè)自定義方法MessageLen()和三種庫存屬性BackColor、Caption和ForeColor(分別表示控件的背景色、標(biāo)題和前臺色)、兩個(gè)以Get/Set方式獲取的自定義屬性XPos、YPos和一個(gè)以成員變量方式實(shí)現(xiàn)的自定義屬性Message。這幾個(gè)自定義屬性分別表示要顯示字符串的x、y坐標(biāo)和要顯示的內(nèi)容。對于采取Get/Set方式獲取的屬性,應(yīng)當(dāng)在控件類中為其添加相應(yīng)的成員函數(shù),并修改其Get、Set成員函數(shù)的實(shí)現(xiàn)過程:

          short m_nYPos;
          short m_nXPos;
          ……
          short CSample68Ctrl::GetXPos()
          {
           return m_nXPos;
          }
          void CSample68Ctrl::SetXPos(short nNewValue)
          {
           m_nXPos = nNewValue;
           SetModifiedFlag();
          }
          short CSample68Ctrl::GetYPos()
          {
           return m_nYPos;
          }
          void CSample68Ctrl::SetYPos(short nNewValue)
          {
           m_nYPos = nNewValue;
           SetModifiedFlag();
          }

            對于以成員變量方式創(chuàng)建的屬性Message,向?qū)н€為其生成了一個(gè)消息響應(yīng)函數(shù):

          void CSample68Ctrl::OnMessageChanged()
          {
          SetModifiedFlag();
          }

            只要該屬性的值被更改,OnMessageChanged()函數(shù)即會被調(diào)用。

            為了使上述屬性設(shè)置如背景色、前景色等能夠與控件實(shí)際聯(lián)系起來,需要替換控件類OnDraw()函數(shù)中由向?qū)傻哪遣糠执a。例如,下面這段代碼即以前面添加的屬性設(shè)置作為參數(shù)值,在控件中顯示一串字符:

          // 用背景色設(shè)置畫刷
          CBrush Brush(TranslateColor(GetBackColor()));
          // 用前臺色設(shè)置字體顏色
          pdc->SetTextColor(TranslateColor(GetForeColor()));
          // 繪制背景
          pdc->FillRect(rcBounds, &Brush);
          // 設(shè)置字體背景透明
          pdc->SetBkMode(TRANSPARENT);
          // 顯示字符
          pdc->TextOut(m_nXPos, m_nYPos, m_message);

            為了使屬性設(shè)置更改后,其效果能夠立即在控件上顯示出來,應(yīng)當(dāng)在與屬性設(shè)置相關(guān)的函數(shù)實(shí)現(xiàn)中調(diào)用InvalidateControl()以更新控件的顯示。

            可以編譯程序并在ActiveX Control Test Container工具中對其進(jìn)行測試。在插入控件后,通過"Invoke Methods…"菜單項(xiàng)彈出如圖7所示的對話框。在Method Name組合框中可以選擇要測試的屬性和方法。其中,對于屬性的測試分別有ProgGet和ProgSet的說明以指出是對屬性值的獲取與設(shè)置。在Parameter編輯框中輸入要設(shè)置的參數(shù)及其對應(yīng)的參數(shù)類型,點(diǎn)擊SetValue按鈕將把該參數(shù)值添加到參數(shù)列表框,最后點(diǎn)擊Invoke按鈕將在控件應(yīng)用設(shè)置的屬性并執(zhí)行指定的方法。對于有返回值的方法,其執(zhí)行結(jié)果將在Return編輯框中顯示。如果出現(xiàn)了異常操作,在Exception編輯框中將會顯示出相應(yīng)的異常錯(cuò)誤信息。圖8給出了經(jīng)過屬性設(shè)置的控件界面。


          圖7 對屬性、方法的測試


          圖8 設(shè)置了屬性后的控件

            對于控件屬性的添加,在MFC ClassWizard對話框的ActiveX Events頁中通過"Add Event…"按鈕彈出如圖9所示的"Add Event"事件添加對話框。與方法、屬性的添加類似,在External name組合框中可以輸入要添加的自定義事件名稱,也可以從下拉列表選擇庫存事件。Implementation項(xiàng)將根據(jù)所要添加的事件類型而自動設(shè)置Stock或Custom選項(xiàng)。ActiveX控件將通過添加的事件來通知容器程序有特定的事件發(fā)生,庫存事件多為鍵盤、鼠標(biāo)事件,將由COleControl自動進(jìn)行處理。對于自定義事件,則只是在.odl文件和控件類中添加了事件映射表等必要的代碼(代碼附下),至于應(yīng)當(dāng)在何種條件下觸發(fā)該事件須由開發(fā)人員自行編寫代碼。


          圖9 事件的添加

          dispinterface _DSample68Events
          {
           properties:
            // Event interface has no properties
           methods:
            // NOTE - ClassWizard will maintain event information here.
            // Use extreme caution when editing this section.
            //{{AFX_ODL_EVENT(CSample68Ctrl)
            [id(1)] void MsgOut();
            //}}AFX_ODL_EVENT
          };
          ……
          // Event maps
          //{{AFX_EVENT(CSample68Ctrl)
          void FireMsgOut()
          {FireEvent(eventidMsgOut,EVENT_PARAM(VTS_NONE));}
          //}}AFX_EVENT
          DECLARE_EVENT_MAP()
          // Dispatch and event IDs
          public:
          enum {
           //{{AFX_DISP_ID(CSample68Ctrl)
           ……
           eventidMsgOut = 1L,
           //}}AFX_DISP_ID
          };
          ……
          BEGIN_EVENT_MAP(CSample68Ctrl, COleControl)
          //{{AFX_EVENT_MAP(CSample68Ctrl)
          EVENT_CUSTOM("MsgOut", FireMsgOut, VTS_NONE)
          //}}AFX_EVENT_MAP
          END_EVENT_MAP()

            上述代碼添加了一個(gè)MsgOut的自定義事件,可以在通過調(diào)用FireMsgOut()來激發(fā)。下面對Message屬性的OnMessageChanged()消息響應(yīng)函數(shù)進(jìn)行修改,每當(dāng)Message屬性內(nèi)容被更改都會調(diào)用該函數(shù),在該函數(shù)中調(diào)用此前添加的MessageLen()方法以確定更改后的Message屬性的字符串長度,在長度大于10時(shí)調(diào)用FireMsgOut()觸發(fā)MsgOut事件:

          void CSample68Ctrl::OnMessageChanged()
          {
           InvalidateControl();
           if (MessageLen() >= 10)
            FireMsgOut();
            SetModifiedFlag();
          }


          圖10 選擇要記錄的事件

            在用ActiveX Control Test Container對剛添加的事件進(jìn)行測試時(shí),首先通過"Control"菜單下的"Logging…"菜單項(xiàng)彈出如圖10所示的對話框,并從"Events"屬性頁中選中要跟蹤記錄的事件。當(dāng)通過Invoke Methods對話框設(shè)置Message屬性的內(nèi)容超過10個(gè)字符后,位于程序框架下方的分割視圖將記錄控件所觸發(fā)的MsgOut事件(如圖11所示)。


          圖11 對事件的測試
            實(shí)現(xiàn)屬性表

            屬性表是ActiveX控件所特有的一種技術(shù),可以在包容器程序處于設(shè)計(jì)階段時(shí)為其提供一個(gè)可視化的人機(jī)交互界面,并可以通過其對控件的自定義屬性和庫存屬性進(jìn)行設(shè)置。在用向?qū)沙绦蚩蚣艿耐瑫r(shí)即已經(jīng)生成了一個(gè)空的用于管理自定義屬性的屬性頁。在代碼上通過控件類實(shí)現(xiàn)文件中的屬性頁ID表對其進(jìn)行維護(hù):

          BEGIN_PROPPAGEIDS(CSample68Ctrl, 1)
          PROPPAGEID(CSample68PropPage::guid)
          END_PROPPAGEIDS(CSample68Ctrl)

            這里的CSample68PropPage類是從COlePropertyPage派生出來的,而COlePropertyPage的基類又是CDialog,因此不難發(fā)現(xiàn)CSample68PropPage與通常的對話框類是比較相似的。可以象處理對話框一樣在資源視圖中為缺省的屬性頁添加與自定義屬性相關(guān)的交互用控件,并通過ClassWizard將這些控件與類成員變量建立綁定關(guān)系。但是有一點(diǎn)不同,就是在綁定成員變量時(shí)還要與控件中的相應(yīng)屬性建立起對應(yīng)關(guān)系。如圖12所示,在Optional property name組合框中輸入自定義屬性名或是直接從下拉列表選擇庫存屬性名,ClassWizard向?qū)⒃趯傩皂擃惖腄oDataExchange()函數(shù)中添加控件、變量和屬性的綁定代碼:

          void CSample68PropPage::DoDataExchange(CDataExchange* pDX)
          {
           //{{AFX_DATA_MAP(CSample68PropPage)
           DDP_Text(pDX, IDC_MESSAGE, m_sMessage, _T("Message") );
           DDX_Text(pDX, IDC_MESSAGE, m_sMessage);
           DDP_Text(pDX, IDC_TITLE, m_sCaption, _T("Caption") );
           DDX_Text(pDX, IDC_TITLE, m_sCaption);
           DDP_Text(pDX, IDC_XPOS, m_nXPos, _T("XPos") );
           DDX_Text(pDX, IDC_XPOS, m_nXPos);
           DDP_Text(pDX, IDC_YPOS, m_nYPos, _T("YPos") );
           DDX_Text(pDX, IDC_YPOS, m_nYPos);
          //}}AFX_DATA_MAP
          DDP_PostProcessing(pDX);
          }


          圖12 成員變量、控件與屬性的綁定

            這里只是在向?qū)傻娜笔傩皂撝袑?shí)現(xiàn)了自定義屬性的可視化設(shè)置。雖然也可以用相同的方法為庫存屬性進(jìn)行設(shè)置,但是更多的還是采用添加庫存屬性頁ID的方法來直接使用庫存屬性頁來對其進(jìn)行維護(hù)。例如,對于庫存屬性BackColor和ForeColor,可以通過ID號為CLSID_CcolorPropPage的庫存屬性頁來進(jìn)行設(shè)置,在將其添加到屬性頁ID表的同時(shí)一定要注意修改BEGIN_PROPPAGEIDS()宏的屬性頁計(jì)數(shù),否則將會引起系統(tǒng)的崩潰:

          BEGIN_PROPPAGEIDS(CSample68Ctrl, 2)
          PROPPAGEID(CSample68PropPage::guid)
          PROPPAGEID(CLSID_CColorPropPage)
          END_PROPPAGEIDS(CSample68Ctrl)

            繼續(xù)在ActiveX Control Test Container中測試控件,將其插入后選擇"Edit"菜單的"Properties…"菜單項(xiàng),將彈出入圖13所示的屬性表。該屬性表共有三個(gè)屬性頁,其中第一個(gè)屬性頁為剛才編輯的自定義屬性頁,第二個(gè)屬性頁(如圖14所示)即為CLSID_CcolorPropPage所指定的顏色屬性頁(為庫存屬性頁),最后一個(gè)屬性頁則是向?qū)ё詣犹砑拥臄U(kuò)展屬性頁。在屬性表中設(shè)置了相應(yīng)的屬性后,點(diǎn)擊"應(yīng)用"按鈕即可讓控件使用新的屬性。這與在"Invoke Methods"對話框中所完成的功能一樣,但顯然要方便的多。而且在包容器程序的設(shè)計(jì)階段,也是通過該屬性表來完成控件與客戶的屬性設(shè)置交互的。


          圖13 控件的屬性表


          圖14 顏色屬性頁
            在包容程序中使用ActiveX控件

            對于ActiveX控件的包容器程序,并不需要象使用OLE文檔服務(wù)器或ActiveX文檔服務(wù)器對象那樣編寫特定的包容器程序框架,直接將控件添加到工程并在對話框上創(chuàng)建即可對其進(jìn)行使用。

            通過"Project"菜單下的"Add To Project"菜單項(xiàng)彈出的"Components and Controls…"子菜單項(xiàng)打開一個(gè)"Components and Controls Gallery"對話框,進(jìn)入到Registered ActiveX Controls目錄下,選取前面創(chuàng)建的ActiveX控件,并將其添加到工程。向?qū)诠こ讨刑砑右粋€(gè)關(guān)于此ActiveX控件的包裝類,并在"Controls"工具欄中添加一個(gè)表示此控件的圖標(biāo)。可以象使用其他的標(biāo)準(zhǔn)控件一樣將其放置到對話框資源中,并修改其缺省屬性。除此之外,還可以在程序中通過對控件包裝類成員函數(shù)的使用來動態(tài)更改控件的屬性設(shè)置。例如,下面這段代碼通過包裝類對象m_ctrlTest在程序運(yùn)行期間動態(tài)設(shè)置了控件的XPos、YPos 以及Message屬性:

          // 更新顯示
          UpdateData();
          // 動態(tài)更改控件的Message屬性
          m_ctrlTest.SetMessage(m_sInput);
          // 設(shè)置顯示坐標(biāo)
          m_ctrlTest.SetXPos(10);
          m_ctrlTest.SetYPos(10);


          圖15 添加事件響應(yīng)函數(shù)

            在資源視圖中用鼠標(biāo)右鍵點(diǎn)擊放置于對話框上的ActiveX控件,并從彈出菜單中選擇"Events…"菜單項(xiàng),將彈出如圖15所示的對話框,在左邊的列表框中顯示了控件提供的事件,雙擊事件將在包容器程序中添加相應(yīng)的事件處理函數(shù)和事件映射表,并可以在響應(yīng)控件發(fā)出的事件后進(jìn)行相應(yīng)的處理:

          BEGIN_EVENTSINK_MAP(CSample69Dlg, CDialog)
          //{{AFX_EVENTSINK_MAP(CSample69Dlg)
          ON_EVENT(CSample69Dlg, IDC_SAMPLE68CTRL1, 1 /* MsgOut */, OnMsgOutSample68ctrl1, VTS_NONE)
          //}}AFX_EVENTSINK_MAP
          END_EVENTSINK_MAP()
          ……
          void CSample69Dlg::OnMsgOutSample68ctrl1()
          {
           // 得到輸入字符數(shù)
           int nNum = m_ctrlTest.MessageLen();
           // 回顯信息
           m_sInput.Format("輸入字符太多,共輸入了%d個(gè)字符", nNum);
           // 顯示信息
           UpdateData(FALSE);
          }

            從上述對ActiveX控件的使用過程可以看出其與標(biāo)準(zhǔn)控件的使用并沒有什么太大的區(qū)別,通過包裝類使得在客戶程序中對控件屬性、方法的使用可以象使用普通MFC類一樣簡單。另外,在控件的包裝類中還提供有Create()方法,使在程序運(yùn)行期間也能夠動態(tài)創(chuàng)建控件。

            小結(jié)

            盡管ActiveX控件從技術(shù)上集成了COM和OLE的許多精華技術(shù),但由于MFC對ActiveX控件提供了強(qiáng)大的支持,使得對ActiveX控件的開發(fā)成為一件非常容易的事情。但要深刻理解ActiveX控件技術(shù),還要對一些基礎(chǔ)技術(shù)有一個(gè)基本的概念,本文的目的并不在于介紹如何編寫一個(gè)ActiveX控件,而是通過對控件的創(chuàng)建過程的分析而使讀者能夠?qū)ctiveX控件的開發(fā)有一個(gè)新的認(rèn)識。本文所述代碼在Windows 2000 Professional下由Microsoft Visual C++ 6.0編譯通過。
          posted on 2007-02-28 15:33 SIMONE 閱讀(6068) 評論(3)  編輯  收藏 所屬分類: C++ActiveX控件

          FeedBack:
          # re: 使用MFC開發(fā)ActiveX控件[未登錄]
          2008-08-30 10:24 | tony
          太棒了!
          感謝  回復(fù)  更多評論
            
          # re: 使用MFC開發(fā)ActiveX控件
          2008-10-09 11:15 | hxbings
          謝謝版主,文章寫得真是很好!  回復(fù)  更多評論
            
          # re: 使用MFC開發(fā)ActiveX控件
          2009-06-12 15:17 | re
          太好了 早看到就好了 真好  回復(fù)  更多評論
            
          主站蜘蛛池模板: 道孚县| 苗栗市| 西充县| 乌拉特前旗| 剑川县| 紫阳县| 岳阳县| 江安县| 龙海市| 和静县| 永州市| 鄯善县| 门头沟区| 灵宝市| 平凉市| 星座| 阿尔山市| 龙山县| 自治县| 大石桥市| 榆树市| 宝坻区| 波密县| 盐边县| 星子县| 开原市| 聂拉木县| 景德镇市| 驻马店市| 凌源市| 桂东县| 贵南县| 云梦县| 滦南县| 江阴市| 大庆市| 阳朔县| 大港区| 塘沽区| 靖边县| 灵丘县|