最近很多朋友喜歡上設計,但是大家卻不知道如何去做,別擔心有圖老師給你解答,史上最全最棒的詳細解說(shuō)讓你一看就懂。
第八章:使用ActiveX控件
1,ActiveX控件是一個(gè)直接插入到C++程序中的軟件模塊,以前常稱(chēng)OLE控件(OCX),是基于MS-COM技術(shù)。
2,ActiveX控件與普通Windows控件比較:
相同點(diǎn):ActiveX控件也可看成是一個(gè)子窗口(可以看成這樣的)。
如果想在對話(huà)框上加入ActiveX控件,則只要在對話(huà)框編輯器中,把ActiveX控件放在適當的位置上,并在資源模板中標識該控件。如果要在運行的過(guò)程中建立ActiveX控件,則可以調用響應控件類(lèi)的Create成員函數,而且通常在父窗口的WM_CREATE消息控制函數中調用。
不同點(diǎn):屬性和方法。
ActiveX控件不像普通控件那樣發(fā)送以WM_打頭的通知消息給它的包容器窗口,而是激發(fā)事件。事件實(shí)際上是由控件調用包容器函數。像普通的控件通知消息一樣,事件并沒(méi)有返回值傳給ActiveX控件。事件如lick,KeyDown。但對于客戶(hù)來(lái)說(shuō)時(shí)間與控件的通知消息是一樣的。
3,在MFC庫中,ActiveX控件就像子窗口一樣,但在控件窗口和包容器窗口之間有一層重要代碼。實(shí)際上,ActiveX控件可能沒(méi)有窗口。當調用Create函數時(shí),并不是直接建立控件窗口,而是把控件代碼載入進(jìn)來(lái),并激發(fā)一個(gè)“實(shí)地激活”(in-place activation)命令。然后ActiveX控件再建立它自己的窗口,通過(guò)MFC的CWnd類(lèi)指針我們可以訪(fǎng)問(wèn)該窗口。不過(guò)客戶(hù)程序最好不要使用ActiveX控件的hWnd句柄。
4,通常ActiveX控件會(huì )保存在擴展名為OCX的動(dòng)態(tài)連接庫中。包容器程序回根據Windows注冊表利用COM技術(shù)在需要的時(shí)候裝入動(dòng)態(tài)連接庫。
說(shuō)明:
1)暫時(shí)可以這樣認為,如果使用了ActiveX控件,那么在運行時(shí)候要裝入該ActiveX控件代碼。顯然在發(fā)布含有ActiveX控件的程序時(shí)候,必須要包含相應的OCX文件,而且還得提供一個(gè)合適的安裝程序。
5,安裝ActiveX控件:
1)把找到的ActiveX控件動(dòng)態(tài)連接庫拷到硬盤(pán)上。
2)在WINDOWS注冊表中登記注冊。(可使用Regsvr32命令行命令)
3)在使用該控件的項目中安裝該控件。(選擇Project菜單,再選擇Add To Project,再選擇Components And Controls,再選擇Registered ActiveX Controls,這時(shí)列表框列出系統已經(jīng)注冊所有的ActiveX控件,選擇需要的控件INSERT即可。)
6,ActiveX控件包容器編程:
1)不管ActiveX控件是作為對話(huà)框控件,還是做為“子窗口”,MFC和ClassWizard都支持。
2)ActiveX控件編寫(xiě)者設計了ActiveX控件屬性供使用者在設計時(shí)訪(fǎng)問(wèn)。所有的ActiveX控件屬性(包括設計時(shí)屬性),在運行時(shí)都是可以訪(fǎng)問(wèn)的,不過(guò)有些屬性可能被設計成只讀的。
3)當在項目中插入ActiveX控件時(shí),ClassWizard就會(huì )產(chǎn)生相應的CWnd的派生類(lèi)C++類(lèi),來(lái)滿(mǎn)足對空間的方法和屬性進(jìn)行訪(fǎng)問(wèn)要求??丶膶傩院头椒ǘ加邢鄳某蓡T函數,同時(shí)生成的類(lèi)還有一個(gè)構造函數可用以動(dòng)態(tài)創(chuàng )建ActiveX控件的事例。
4)當在項目中插入ActiveX控件ClassWizard生成的CWnd的派生類(lèi)C++類(lèi)中,可以看到其成員函數的代碼中都有對InvokeHelper函數的調用,InvokeHelper函數的第一個(gè)參數都和對應的屬性或方法在A(yíng)ctiveX控件中的分發(fā)(dispatch)ID(標識ActiveX控件的方法或屬性的)相對應。通過(guò)查看ActiveX控件hlp文件可以發(fā)現,ActiveX控件的方法在生存的C++類(lèi)中都有同名的成員函數與之對應,ActiveX控件的屬性都有一組Get和Set函數對其操作,其中ActiveX控件的方法和屬性操作與生成的C++類(lèi)成員函數相關(guān)聯(lián)都是通過(guò)InvokeHelper函數的調用來(lái)完成的,InvokeHelper函數的第一個(gè)參數是由Component Gallery(控件提供者)提供的。因為經(jīng)過(guò)這樣的處理,所以我們如果要調用ActiveX控件的方法或對其屬性進(jìn)行取和設置操作,只需調用生成的C++類(lèi)對應的成員函數便可。下面對InvokeHelper單獨說(shuō)明:
CWnd::InvokeHelper
void InvokeHelper( DISPID dwDispID, WORD wFlags, VARTYPE vtRet, void* pvRet, const BYTE* pbParamInfo, ... );
說(shuō)明:
Call this member function to invoke the OLE control method or property specified by dwDispID, in the context specified by wFlags.
其中參數:
dwDispID:
//Identifies the method or property to be invoked. This value is usually supplied by Component Gallery.
wFlags:可以為下面些值,指明調用InvokeHelper的目的。
//[ DISPATCH_METHOD ] The member is invoked as a method. If a property has the same name, both this and the DISPATCH_PROPERTYGET flag may be set.
[ DISPATCH_PROPERTYGET ] The member is retrieved as a property or data member.
[ DISPATCH_PROPERTYPUT ] The member is changed as a property or data member.
[ DISPATCH_PROPERTYPUTREF ] The member is changed by a reference assignment, rather than a value assignment. This flag is valid only when the property accepts a reference to an object.
vtRet:
//Specifies the type of the return value.
VT_EMPTY void
VT_I2 short
VT_I4 long
VT_R4 float
VT_R8 double
VT_CY CY
VT_DATE DATE
VT_BSTR BSTR
VT_DISPATCH LPDISPATCH
VT_ERROR SCODE
VT_BOOL BOOL
VT_VARIANT VARIANT
VT_UNKNOWN LPUNKNOWN
pvRet:
//Address of the variable that will that will receive the property value or return value. It must match the type specified by vtRet.
pbParamInfo:一般都設置為NULL
//Pointer to a null-terminated string of bytes specifying the types of the parameters following pbParamInfo.
specifies the types of the parameters passed to the method or property.
...:
//Variable List of parameters, of types specified in pbParamInfo.
5)AppWizard對ActiveX控件的支持是通過(guò)在生成的應用程序類(lèi)的成員函數InitInstance中插入(AfxEnableControlContainer();),同時(shí)在響應項目文件的StdAfx.h文件中插入(#includeafxdisp.h)(原因可參考書(shū)P38一些說(shuō)明)。
如果項目中不包含這兩行,而又要加入ActiveX控件,則只要手工加入上面兩行代碼即可。
6)可以對話(huà)框編輯器來(lái)生成對話(huà)框的模板中加入一個(gè)或多個(gè)ActiveX控件,這樣我們可以在對話(huà)框模板生成的類(lèi)中添加數據成員或事件控制函數來(lái)獲取ActiveX控件的屬性或對其控制。
注意:(詳細見(jiàn)書(shū)P159頁(yè)的[致WIN32程序員])
實(shí)際上,資源模板并不是在對話(huà)框編輯器中所看的那樣。函數CDialog::DoModal在把對話(huà)框模板交給WINDOWS內部的對話(huà)框過(guò)程之前,要先對模板進(jìn)行預處理,即:它先會(huì )去掉所有的ActiveX控件,有剩下的控件建立對話(huà)框窗口,然后再裝入ActiveX控件,激活它們并在正確的位置上創(chuàng )建它的窗口。
當模式對話(huà)框運行時(shí)候,MFC處理所有送給對話(huà)框消息時(shí),是不管是有普通控件發(fā)送的,還是ActiveX控件發(fā)送的。故ActiveX控件雖然不是對話(huà)框模板一部分,但用戶(hù)仍然可以用TAB鍵在所有的控件間切換。
7)調用UpdateData(FALSE)將會(huì )從所有的對話(huà)框控件中讀取所有屬性值。如果只需要得到ActiveX控件屬性的話(huà),可以調用ActiveX控件生成的C++類(lèi)中Get函數(同樣設置調用Set函數),這樣就提高了效率。
8)事例部分代碼對比說(shuō)明:
代碼一:
CDataExchange dx(this,TRUE);
DDX_Text(&dx,IDC_DAY,m_sDay);
DDX_Text(&dx,IDC_MONTH,m_sMonth);
DDX_Text(&dx,IDC_YEAR,m_sYear);
說(shuō)明一:
CDataExchange類(lèi)構造函數:(注,在MFC|SRC|AFXWIN.H中可以看到其構造函數聲明,在MFC|SRC|WINCORE.CPP文件中可以看到其構造函數的定義。)
(本文來(lái)源于圖老師網(wǎng)站,更多請訪(fǎng)問(wèn)http://www.tulaoshi.com/bianchengyuyan/)原型:CDataExchange::CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate);
定義:
CDataExchange::CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate)
{
ASSERT_VALID(pDlgWnd);
m_bSaveAndValidate = bSaveAndValidate;
m_pDlgWnd = pDlgWnd;
m_hWndLastControl = NULL;
}
//其中m_pDlgWnd和m_bSaveAndValidate是CDataExchange數據成員,可以通過(guò)這中方式給它們賦值。
m_pDlgWnd:The dialog box or window where the data exchange takes place.
m_bSaveAndValidate Flag for the direction of DDX and DDV. 詳見(jiàn)說(shuō)明二。
說(shuō)明二:
//CDataExchange does not have a base class.
//The CDataExchange class supports the dialog data exchange (DDX) and dialog data validation (DDV) routines used by the Microsoft Foundation classes. Use this class if you are writing data exchange routines for custom data types or controls, or if you are writing your own data validation routines.
//A CDataExchange object provides the context information needed for DDX and DDV to take place. The flag m_bSaveAndValidate is FALSE when DDX is used to fill the initial values of dialog controls from data members. The flag m_bSaveAndValidate is TRUE when DDX is used to set the current values of dialog controls into data members and when DDV is used to validate the data values. If the DDV validation fails, the DDV procedure will display a message box explaining the input error. The DDV procedure will then call Fail to reset the focus to the offending control and throw an exception to stop the validation process.
代碼二:(是為了比較代碼一做些說(shuō)明的)
(本文來(lái)源于圖老師網(wǎng)站,更多請訪(fǎng)問(wèn)http://www.tulaoshi.com/bianchengyuyan/)void CActiveXDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);//調用基類(lèi)的DoDataExchange
//{{AFX_DATA_MAP(CActiveXDialog)
DDX_Control(pDX, IDC_CALENDAR1, m_calendar);
DDX_Text(pDX, IDC_DAY, m_sDay);
DDX_Text(pDX, IDC_MONTH, m_sMonth);
DDX_Text(pDX, IDC_YEAR, m_sYear);
/
來(lái)源:http://www.tulaoshi.com/n/20160219/1611590.html 第二天:Microsoft基本類(lèi)庫應用程序框架
◎MFC是C++的Microsoft Windows API,如果想要開(kāi)發(fā)WINDOWS的應用程序當然VC/MFC是開(kāi)發(fā)環(huán)境的首選。
◎MFC產(chǎn)生的應用程序使用了標準化的結構。(我現在還體會(huì )不出這點(diǎn)的優(yōu)勢所在,請高手指點(diǎn))
◎MFC產(chǎn)生的應用程序短而運行速度快。這應該說(shuō)的是可以很容易的建立動(dòng)態(tài)連接,其實(shí)程序還是需要大量的DLL,不過(guò)由于WINDOWS上有很多可以用DLL所以應用程序很短,我是這樣想的不知對否。
◎VC++工具降低了編碼的復雜性。這點(diǎn)不容質(zhì)疑比起TC方便太多了。
◎MFC庫功能非常豐富。書(shū)上列出了MFC從1.0--4.21的一些特性,我就不廢話(huà)了,大家應該看看。
這一章節主要介紹了MFC庫的優(yōu)點(diǎn),其實(shí)我本人認為在某些特定環(huán)境下其實(shí)MFC不一定就象說(shuō)的那樣好。我想不會(huì )有人用純VC做MIS系統吧,太累了。我是這樣理解編程序的,如果把學(xué)編程看成學(xué)武的話(huà),C/C++語(yǔ)言及編程思想(OOP)是內功,API是基本功(編程思想是內功、API是基本功這適用于任何WIN32編程,不論Visual C++、Delphi、C++Builder、VB......),VC/MFC應該不同武功其中的一種,不同的學(xué)習方法效果不一樣,只要下工夫也都可以達到一定的境界。真正的高手是有著(zhù)深厚的內功,扎實(shí)的基本功,至于武功招數無(wú)所謂了,隨便一站不丁不八全無(wú)破綻,無(wú)招勝有招了。對不住扯遠了。
C++可以通過(guò)類(lèi)庫來(lái)進(jìn)行擴展,我們除了可以使用隨編譯器提供的類(lèi)庫外還可以很方便使用軟件公司銷(xiāo)售的類(lèi)庫產(chǎn)品,甚至可以自己開(kāi)發(fā)。而應用程序框架是一種類(lèi)庫的超集,它定義了程序的結構。
下面給出兩個(gè)示例程序(一個(gè)是書(shū)上的一個(gè)是我寫(xiě)的):
雷神建議: 雖然現在很多書(shū)都附CD,CD上有書(shū)中所有示例的源代碼,但還是應該親自在VC6用手敲進(jìn)去。這樣可以加深印象以及感受一下編譯除錯后程序正確運行時(shí)的樂(lè )趣,因為是純手工打造。自從我敲了近一百個(gè)代碼示例后,由于筆誤的BUG就很少了,打字速度也提高了。而且最好在原示例代碼的基礎上做些改動(dòng)例如別千篇一律的顯示HELLO WORLD!換點(diǎn)別的,這樣做也可以加深對示例程序的理解。
我的HELLO WORLD用AppWizard向導創(chuàng )建一個(gè)顯示一個(gè)字符串的單文檔程序,只需要敲入一行語(yǔ)句,主要是體驗MFC的強大功能。
1、打開(kāi)VC++6從菜單選擇NEW,給項目命名為”MyApp01“。
2、選擇MFC AppWizard[exe] 選項,除STEP 1選擇單文檔外其他STEP缺省。
3、在Class View選擇CMyApp01View類(lèi)的OnDraw()成員函數雙擊會(huì )在C++編譯器看到以下內容
void CMyApp01View::OnDraw(CDC* pDC)
{
CMyApp01Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
在 // TODO: add draw code for native data here的位置增加一行代碼
void CMyApp01View::OnDraw(CDC* pDC)
{
CMyApp01Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDC-TextOut(10,10,"雷神愿意和所有學(xué)VC的朋友共同進(jìn)步!"); //-----------增加的一行
// TODO: add draw code for native data here
}
完了,就這么簡(jiǎn)單。編譯運行??吹搅藛??這個(gè)程序具備WINDOWS程序的所有特性,例如有菜單、工具條、狀態(tài)欄、最大化、關(guān)閉、甚至還有關(guān)于對話(huà)框、打印預覽.....全了,這就是AppWizard通過(guò)MFC動(dòng)態(tài)創(chuàng )建的一個(gè)應用程序。從這個(gè)小例子可以看出用VC/MFC設計WINDOWS程序多么方便。下面我們看看書(shū)上的例子,以便更進(jìn)一步了解應用程序框架。
書(shū)上的例子:
1、先建立一個(gè)Win32 Application的應用程序。
2、選擇Project-Add to project-Files,分別創(chuàng )建一個(gè)名為MyApp.h和一個(gè)名為MyApp.cpp的文件。
3、添加代碼:(最好照敲以下代碼到編譯器,別用Ctrl+C/Ctrl+V)
//***********************************************
// MyApp.h
//
class CMyApp:public CWinApp //見(jiàn)下②
{
public:
virtual BOOL InitInstance();
};
class CMyFrame:public CFrameWnd
{
public:
CMyFrame();
protected:
afx_msg void OnLButtonDown(UINT nFlags,CPoint point);
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
};
//*****************************************************
// MyApp.cpp
//
#include "afxwin.h"
#include "myapp.h"
CMyApp theApp;//建立一個(gè)CMyAPP對象見(jiàn)下②
BOOL CMyApp::InitInstance ()
{
m_pMainWnd=new CMyFrame();
m_pMainWnd-ShowWindow (m_nCmdShow);
m_pMainWnd-UpdateWindow ();
return TRUE;
}
BEGIN_MESSAGE_MAP(CMyFrame,CFrameWnd)
ON_WM_LBUTTONDOWN()
ON_WM_PAINT()
END_MESSAGE_MAP()
CMyFrame::CMyFrame(){
Create(NULL,"MYAPP Application");
}
void CMyFrame::OnLButtonDown (UINT nFlags,CPoint point)
{
TRACE("Entering CMyFrame::OnLButtonDown - %lx,%d,%d",
(long)nFlags,point.x ,point.y);
}
void CMyFrame::OnPaint ()
{
CPaintDC dc(this);
dc.TextOut (0,0,"Hello World!");
}
4、編譯運行,報錯。為什么呢?原來(lái)還沒(méi)有添加MFC的支持,在Project Setting選項General屬性頁(yè)選擇”Use MFC in a Static Library"
5、再Ctrl+F5,哈成功了。
讓我們看看這個(gè)程序中的一些元素。
①WinMain函數:并非不存在只是已經(jīng)被隱藏在應用程序框架內部。
②CMyApp類(lèi):CMyApp類(lèi)的對象代表一個(gè)應用程序,CWinApp基類(lèi)決定它的大部分行為。
③應用程序的啟動(dòng):當開(kāi)始運行應用程序時(shí)WINDOWS會(huì )調用WinMain函數,WinMain會(huì )查找該應用程序的全局對象theApp。
④CMyApp::InitInstance成員函數:發(fā)現theApp后自動(dòng)調用重載的虛函數InitInstance來(lái)完成主窗口的構造和顯示工作。記住這個(gè)函數。
⑤CWinApp::Run成員函數:WinMain在調用InitInstance之后緊接著(zhù)調用Run函數,它被隱藏在基類(lèi)中負責傳遞應用程序的消息給相映的窗口。(我把它理解為好象SDK的窗口的過(guò)程函數不知對不對)
⑥CMyFrame類(lèi):此類(lèi)的對象代表著(zhù)應用程序的主窗口。它的構造函數調用基類(lèi)CFrameWnd的Create函數創(chuàng )建具體的窗口結構。
(本文來(lái)源于圖老師網(wǎng)站,更多請訪(fǎng)問(wèn)http://www.tulaoshi.com/bianchengyuyan/)⑦CMyFrame::OnLButtonDown函數:演示消息處理機制,當鼠標坐鍵被按下這一事件被映射到CMyFrame的OnLButtonDown函數上,如果你選擇F5進(jìn)行編譯運行的話(huà)可以在調試窗口看到TRACE宏顯示的類(lèi)似下面的信息
Entering CMyFrame::OnLButtonDown - 1,309,119
Entering CMyFrame::OnLButtonDown - 1,408,221
⑧CMyFrame::OnPaint函數:應用程序每次重新繪制窗口都需要調用此函數,將顯示"Hello World!"放在這里是因為每次窗口發(fā)生變化時(shí)保證"Hello World!"被顯示,你可以試著(zhù)將語(yǔ)句:
CPaintDC dc(this);
dc.TextOut (0,0,"Hello World!");
寫(xiě)在別出,例如寫(xiě)在
void CMyFrame::OnLButtonDown (UINT nFlags,CPoint point)
{
TRACE("Entering CMyFrame::OnLButtonDown - %lx,%d,%d",
(long)nFlags,point.x ,point.y);
CPaintDC dc(this);
dc.TextOut (0,0,"Hello World!");
}
運行后當點(diǎn)擊左鍵時(shí)顯示"Hello World!",但當窗口最小化再最大化時(shí)"Hello World!"不見(jiàn)了。
⑧關(guān)閉應用程序:用戶(hù)關(guān)閉應用程序時(shí)會(huì )有一系列事件發(fā)生。首先CMyFrame對象被刪除,然后退出Run,進(jìn)而退出WinMain,最后刪除CMyApp對象。
通過(guò)上面的示例我們看見(jiàn)程序的大部分功能包含在基類(lèi)CWinApp和CFrameWnd中,我們只寫(xiě)了很少的函數,便可以完成很復雜的功能。所以應用程序框架不僅僅是一種類(lèi)庫,它還定義了應用程序的結構,除了基類(lèi)外還包括WinMain函數,以及用來(lái)支持消息處理、診斷、DLL、等都包含在應用程序框架中。
來(lái)源:http://www.tulaoshi.com/n/20160219/1602452.html
聯(lián)系客服