Windows Embedded Compact 7中的dll編程(下)

1.靜態調用MyCEDLLdom

    在本章的第2節中介紹了調用DLL的兩種方式:靜態調用和動態調用,在下面的示例中異步

就來演示使用靜態方法調用上面建立的MyCEDLL.dll的步驟。ide

    (1)使用VS2008智能設備MFC智能設備應用程序嚮導建立一個基於對話框的應函數

用程序CallDLLByStatic,編譯環境設置爲yincheng_OS測試

    (2)將MyCEDLL工程中的MyCEDLL.dll和MyCEDLL.1ib兩個文件拷貝到本工程目錄this

下,而後選擇VS2008主菜單中的「項目ICalIDLLByStatic屬性」項打開項目屬性設置窗口,spa

右邊導航欄選擇「配置屬性J連接器I輸入」,在該頁框中的「附加依賴項」輸入框中輸入線程

MyCEDll.1ib,實際頁面下圖所示。指針

    (3)將MyCEDLL工程的MyCEDLL.h頭文件拷貝到本工程目錄中,而且在對象

CaIlDLLByStaticDl9.cpp文件中引用MyCEDLL.h頭文件,代碼以下: #include」MyCEDLL.h」 如圖12-4

圖12-4配置DLL調用

   

(4)在對話框窗體上放置一個「調用」按鈕,經過單擊該按鈕來實現調用MyCEDLL中

TestDll方法的功能。「調用」按鈕的單擊事件代碼如程序

//演示靜態調用DLL

    void CCallDLLByStaticDlg::0nBnClickedBtnCall()

    {

    //TestDll數爲MyCEDLLdll中的一個輸出函數

TestDll()

}

(5)編譯並下載到yincheng.OS\RelDir\VirtualPC_x86_Release在虛擬機中運行,單擊「調用」按鈕後效果以下。效果如圖12-5

圖12-5程序效果圖

在上中介紹了以靜態方式調用DLL的示例,在下面的示例中將繼續介紹以動態

方式調用DLL的方法步驟,這裏仍是以MyCEDLL.dll文件爲例。

    (1)使用VS2008智能設備IMFC智能設備應用程序嚮導建立一個基於對話框的應

用程序CallDLLByDynamic,編譯環境設置爲yincheng_OS SDK)。

    (2)在CallDLLByDynamicDlg.h文件中添加MyCEDLL文件中的TestDll函數定義,代

碼以下:

    //定義MyCEDLL.dll中TestDll輸出函數原型

    typedef void(*pTestDII)(void);

    (3)在對話框上放置一個「調用」按鈕,用來調用MyCEDLL文件中的TestDll函數,

該按鈕的單擊事件代碼以下列所示。

    //動態調用DLL示例

void CCallDLLByDynamicDlg::OnBnClickedBtnCall()

{

//1、加載DLL

HINSTANCEhModule = LoadLibrary(_T("MyCEDLL.dll"));

    if (hModule == NULL)

{

AfxMessageBox(_T("加載DLL失敗"));

return;

}

   //獲得MyCEDLLTestDll函數地址

pTestDll pFun = (pTestDll)GetProcAddress(hModule,_T("TestDll"));

if ( pFun == NULL )

{

AfxMessageBox(_T("獲取TestDll函數失敗"));

}

else

{

//執行MyCEDLLTestDll函數

pFun();

}

    //3、釋放DLL;

FreeLibrary(hModule);

}

 (4)編譯並下載到模擬器中運行,其運行界面如圖l2-6所示。

圖12-6程序運行效果

12.3.2 基於mfcregular dll的建立

  基於MFC的Regular DLL是用MFC類庫編寫的,其明顯的特色就是在源文件裏有一個

繼承CWinApp的類。該類動態連接庫的輸出函數具備以下形式:

    extern  」C」  EXPORT YourExportedFunction()j

    若是沒有extern」C」修飾,輸出函數僅僅只能從C++代碼中調用。

    注意:全部從DLL輸出的函數都應該以以下語句開始:

    AFX—MANAGE—STATE(AfxGetStaticModuleState())

    以上語句用來正確地切換MFC模塊狀態。Regular DLL可以被全部支持DLL技術的語言

所編寫的應用程序調用。在這種動態鏈接庫中,它必須有一個從CwinApp類繼承下來的類,

DllMain函數被MFC所提供,不用顯式地寫出來。

    下面就來建立一個基於MFC的Regular DLL。這個DLL會提供一個異步處理方法,當方

法執行完成後,將提供回調函數通知用戶方法執行完成。該動態連接庫典型的用處就是,當用

戶執行一個查詢時,可能須要一段時間,若是採用同步的方式,用戶必須等待查詢結束後才能

執行其餘任務,可是若是將其改爲異步(經過單獨的線程)的方式,在執行完成後,將以回調

函數通知用戶,那麼在查詢的這段時間中,用戶還能夠執行其餘任務,提升了工做的效率。

    1.基於MFC的Regular DPLL的建立

    建立一個基於MFC的Regular DLL的具體步驟以下:

    (1)使用嚮導創建基於MFC的Regular Dll項目。

新建一個基於「MFC智能設備DLL」的項目,將項目名稱設爲AsynDll,如圖12-7所示。

選擇yinchengOS編譯環境如圖12-8

    單擊「肯定」按鈕,此時將出現「MFC智能設備DLL嚮導」對話框,如圖12-9所示。

    

單擊「完成」按鈕就完成了AsynDll工程的建立。

  

圖12-7設置項目模板

圖12-8,設置編譯環境

圖12-9定義動態函數連接庫類型

  (2)定義DLL輸出函數。

在AsynDll.h頭文件中添加Dll輸出函數定義,

//定義DLL函數導出類型

#define ASynDLL_EXPORT_API __declspec(dllexport)

//導出Dll函數

extern "C" 

{

//查詢數據,異步方法

long ASynDLL_EXPORT_API QueryData(void); 

//設置回調函數

    long ASynDLL_EXPORT_API SetCallbackProcAddr(long); 

}

//定義回調函數類型

typedef void (* TDataReadNotify)(long);

  在AsynDll.cpp文件中,添加DLL函數的實現代碼,具體位置是CASynDIIApp

語句的下面,代碼如程序所示。

//定義回調函數

TDataReadNotify DataReadNotify;

//線程處理函數

DWORD DoTheWork(LPVOID lpParameter)

{

  long lDBData;

  Sleep(5000);

  lDBData = Random();

  

  //通知用戶,函數執行完成

  if (DataReadNotify != NULL) 

  {

  //執行回調函數

  DataReadNotify(lDBData);

  }

  return 0;

};

//查詢數據

long ASynDLL_EXPORT_API QueryData(void)

{

    AFX_MANAGE_STATE(AfxGetStaticModuleState());

HANDLE hThread;

DWORD pThreadId;

long lProcAdr;

//設置線程函數

lProcAdr = (long)(&DoTheWork);

//建立線程,並執行線程

hThread = CreateThread(NULL, 

0,

(LPTHREAD_START_ROUTINE)lProcAdr,

NULL,

0,

&pThreadId);

return 0;

};

//設置回調函數指針

long ASynDLL_EXPORT_API SetCallbackProcAddr(long lProcAddress)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

long Result = 0;

//設置回調函數

DataReadNotify = (TDataReadNotify)lProcAddress;

if (DataReadNotify != NULL) 

{

Result = 1;

}

return Result;

};

ASynDIl就編寫完成了。此時就能夠把它編譯並下載到虛擬機中了。

    2.測試ASynDll.dll

    (1)使用Vs2008智能設備MFc智能設備應用程序嚮導建立一個基於對話框的應

用程序ASynDIITest,編譯環境設置爲yinchengOS. 

    (2)在ASynDllTestDlg.h文件中定義AsynDll.dll裏的兩個輸出函數類型。具體操做是將

以下代碼添加到CASynDllTestDlg類定義以前。

    //定義ASynDIl中的函數類型

    typedef long(*TQueryData)(void)

    typedef long(*TSetCallbackProcAddr)(long);

    (3)在ASynDllTestDlg.h文件中添加以下所示的引入函數定義。

   private:

//存儲Dll句柄

    HINSTANCEm_hModule;

//定義Dll中的輸入函數

TQueryData m_pQueryData;

    TSetCallbackProcAddr m_pSetCallbackProcAddr; 

(4)在ASynDllTestDlg.Cpp中,添加回調函數處理方法,代碼如程序

//回調函數,當DLLQueryData方法執行完畢時執行

void QueryReadNotify(long lDBData)

{

TCHAR sDBData[11];

TCHAR sMessage[64];

_ltow(lDBData, sDBData, 10);

wcscpy(sMessage, _T("DBData from DLL is: "));

wcscat(sMessage, sDBData);

::MessageBox(0, sMessage, 

_T("Sample App"), MB_OK + MB_ICONINFORMATION);

};

 (5)在cAsynDllTestDlg::0nInitDialog()方法中初始化DLL,代碼如

 //加載ASynDll

m_hModule = LoadLibrary(_T("ASynDll.dll"));

    if (m_hModule == NULL)

{

AfxMessageBox(_T("加載DLL失敗"));

return FALSE;

}

//獲得ASynDll中QueryData函數地址

m_pQueryData = (TQueryData)GetProcAddress(m_hModule,_T("QueryData"));

if ( m_pQueryData == NULL )

{

AfxMessageBox(_T("獲取QueryData函數失敗"));

FreeLibrary(m_hModule);

return FALSE;

}

//獲得ASynDll中SetCallbackProcAddr函數地址

m_pSetCallbackProcAddr = 

(TSetCallbackProcAddr)GetProcAddress(m_hModule,_T("SetCallbackProcAddr"));

if ( m_pSetCallbackProcAddr == NULL )

{

AfxMessageBox(_T("獲取SetCallbackProcAddr函數失敗"));

FreeLibrary(m_hModule);

return FALSE ;

}

    

    (6)在窗體釋放時,釋放ASynDll動態連接庫,代碼如程序所示。

  

     void CASynDllTestDlg::OnDestroy()

{

//釋放AsynDll

FreeLibrary(m_hModule);

CDialog::OnDestroy();

}       (7)在窗體上放置一個「調用」按鈕,用來調用DLL中的QueryData方法。

鈕的單擊事件代碼如程序所示。

      

//調用DLL

void CASynDllTestDlg::OnBnClickedBtnCall()

{

long lProcAdr;

   //設置回調函數地址

   lProcAdr = (long)(&QueryReadNotify);

   m_pSetCallbackProcAddr(lProcAdr);

   

   //執行異步查詢操做

   m_pQueryData();

}    以上操做完成後,就能夠編譯它並下載到虛擬機中運行了。用戶能夠屢次單擊「調用」

按鈕,此時的運行效果將如圖12-10所示。

圖12-10 程序運行效果

12.3.3 資源dll

     1.資源DLL的建立

    在這個小節中將介紹一個資源DLL的例子,該DLL將存儲位圖和圖標兩種資源,下面就

來介紹它的具體實現過程。

    (1)新建項目。

    新建一個基於「Win32智能設備DLL項目」的項目,將項目名稱設爲ResDll。將編譯

環境設置爲yinchengOS.

    (2)向DLL工程中添加資源。

    在資源視圖中,經過鼠標右擊快捷菜單「添加資源」,打開添加資源對話框,而後選擇

Bitmap,單擊「新建」按鈕,建立一個新的位圖。該位圖的默認名稱爲IDB—BITMAPl,將它

重命名爲IDB RESBMP。接着重複插入位圖的操做,添加一個圖標(ICON),命名爲

IDl—RESICON。

    最後編譯項目,就生成所需的資源DLL文件。

    下面接着講介紹如何使用DLL裏的資源。

    2.測試ResDll.dll

    (1)建立應用程序。

    使用VS2008智能設備MFC智能設備應用程序嚮導建立一個基於對話框的應用程

ResDllTest,編譯環境設置爲yinchengOS SDK.

    (2)測試程序界面設置。

    在對話框上放置4個按鈕,這些控件的基本屬性設置如表12.1所示。

12.1  測試程序界面控件屬性設置表

    標識

    屬性

IDCBLOAD

標題設爲「加載DLL

IDC——BTN——FREE

標題設爲釋放DLL

 IDC——BTN——BMP

標題設爲「顯示位圖」

IDCBTNjCON

標題設爲「顯示圖標」

此時應用程序界面如圖l211所示。

    圖1211測試程序界面

    (3)爲CResDllTestDlg類添加一個私有成員變量m_hDll,用於存儲資源DLL句柄,代

碼以下:

    private

    //DLL句柄

    HINSTANCE m_hDll

    注意:因爲這裏是經過資源ID調用了資源DLL裏的資源,所以應打開ResDll工程中的

Resource.h文件,將其中的資源定義拷貝到ResDllTestDl9.Cpp文件中,代碼片斷以下:

    //添加資源定義標識

    #define IDB_RESBMP    l01

    #define IDl_RESICON    l02

    (4)爲「加載DLL」、「釋放DLL」、「顯示圖片」、「顯示圖標」這4個按鈕添加單擊事件

代碼。其中「加載DLL」按鈕用於將DLL加載到應用程序中;「釋放DLL」按鈕用於從應用

程序中釋放DLL。這4個按鈕的單擊事件代碼如程序所示。

    //加載資源DLL

void CResDllTestDlg::OnBnClickedBtnLoad()

{

//加載DLL

m_hDll = LoadLibrary(_T("ResDll.dll"));

if (m_hDll == NULL)

{

AfxMessageBox(_T("加載Dll失敗"));

}

}

//釋放資源DLL

void CResDllTestDlg::OnBnClickedBtnFree()

{

//釋放DLL

if (m_hDll != NULL)

{

FreeLibrary(m_hDll);

}

}

//顯示資源裏的位圖

void CResDllTestDlg::OnBnClickedBtnBmp()

{

HBITMAP hOldBmp;

//DLL里加載指定的資源

HBITMAP bmp = LoadBitmap(m_hDll,MAKEINTRESOURCE(IDB_RESBMP));

if (bmp == NULL)

{

AfxMessageBox(_T("調用位圖資源失敗"));

return;

}

//得到繪圖環境資源

CDC memdc;

CDC *pDC = new CClientDC(this);

memdc.CreateCompatibleDC(pDC);

hOldBmp = (HBITMAP)memdc.SelectObject(bmp);

pDC->BitBlt(0,0,200,200,&memdc,0,0,SRCCOPY);

memdc.SelectObject(hOldBmp);

//釋放資源

DeleteObject(bmp);

//釋放DC

delete pDC;

pDC = NULL;

}

//顯示資源裏的圖標

void CResDllTestDlg::OnBnClickedBtnIcon()

{

//DLL里加載指定的資源

HICON icn = LoadIcon(m_hDll,MAKEINTRESOURCE(IDI_RESICON));

if (icn == NULL)

{

AfxMessageBox(_T("調用圖標資源失敗"));

return;

}

CDC *pDC = new CClientDC(this);

//繪製圖標

pDC->DrawIcon(CPoint(100,100),icn);

DeleteObject(icn);

//釋放CDC對象

delete pDC;

pDC = NULL;

}

    

    至此,資源DLL的測試程序就編寫完成了。在運行該應用程序時,單擊「加載DLL」按

鈕後,就可使用「顯示圖片」和「顯示圖標」按鈕了。使用結束後,應該單擊「釋放DLL」

按鈕以釋放DLL。測試程序的運行效果如圖12-12所示。

12-12程序運行效果

12.4小結

綜合簡介瞭如何在Windows Embedded Compact 7中開發各類Dll,請認真實踐,並在工做中根據需求開發本身的dll.

相關文章
相關標籤/搜索