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

来源:互联网 发布:人工智能四大开放平台 编辑:程序博客网 时间:2024/05/21 08:59

1.静态调用MyCEDLL

    在本章的第2节中介绍了调用DLL的两种方式:静态调用和动态调用,在下面的示例中

就来演示使用静态方法调用上面创建的MyCEDLL.dll的步骤。

    (1)使用VS2008智能设备MFC智能设备应用程序向导创建一个基于对话框的应

用程序CallDLLByStatic,编译环境设置为yincheng_OS

    (2)将MyCEDLL工程中的MyCEDLL.dll和MyCEDLL.1ib两个文件拷贝到本工程目录

下,然后选择VS2008主菜单中的“项目ICalIDLLByStatic属性”项打开项目属性设置窗口,

右边导航栏选择“配置属性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.

原创粉丝点击