??xml version="1.0" encoding="utf-8" standalone="yes"?>一级女性全黄久久生活片免费 ,久久久WWW成人免费精品,2020最新久久久视精品爱http://www.shnenglu.com/ivenher/articles/37002.html爱饭?/dc:creator>爱饭?/author>Tue, 20 Nov 2007 04:18:00 GMThttp://www.shnenglu.com/ivenher/articles/37002.htmlhttp://www.shnenglu.com/ivenher/comments/37002.htmlhttp://www.shnenglu.com/ivenher/articles/37002.html#Feedback0http://www.shnenglu.com/ivenher/comments/commentRss/37002.htmlhttp://www.shnenglu.com/ivenher/services/trackbacks/37002.html 

  一、在应用E序自定义消息方法:

        一般自定义消息有一定的范围Q虽然说自定义消息从WM_USER开始,但是׃我们的工E里面一般还有很多其他的控gQ他们也要占用一部分WM_USER消息范围Q所以我们必Mؓ他们留出一部分范围Q这里,我们保留100个消息,一般情况下Q这可以满我们的要求?/p>

  (1)    定义消息的倹{在我们要发生消息的地方(例如CMyView.cpp的开始部?或者stdafx..h文gQ进行如下定义:


#define WM_MSG  (WM_USER+101)

 

        接下来的工作其实很简单,我们在前面说了,消息正常工作?个部分必d调:消息声明、消息映、消息体。我们就一ơ进行手工加入?/p>

        (2)首先在AFX_MSG块中加入消息声明Q在CMyView.h中,扑ֈ如下部分Qƈ加入消息声明Q?/p>


         protected:       

            // {{AFX_MSGQCMyView)

            ......

            afx_msg LRESULT OnMyMsg(WPARAM wParam,LPARAM lParam);

            file://}}AFX_MSG

 

        (3)在MESSAGE_MAP块中dON_MESSAGE宏指令:


           BEGIN_MESSAGE_MAP(CMyView, CView)

              file://{{AFX_MSG_MAP(CMyView)

               .....

              ON_MESSAGE(WM_MSG, OnMyMsg)

             file://}}AFX_MSG_MAP

           END_MESSAGE_MAP()

 

        (4)d消息函数体:


      LPESULT CMyView::OnMyMsg(WPARAM wParam, LPARAM lParam)

          {

    


             AfxMessageBox("消息已经收到Q?);

             return 0;

          }

 

        消息x已l定义完毕,接下来我们就可以ȀzL息了Q就可以用我们前面所说的PostMessage/SendMessage来发送消息了?/p>

    如:::PostMessage(hwnd,WM_MSG,0,1);

       PostMessage:不用{消息返回?/p>

    SendMessage:需要等消息q回?/p>

  二、从DLL中传递消息到EXE

   在DLL中定义消息和上面的方法很怼Q有两点不同的地方:

  1?nbsp; 在DLL和应用程序中两个地方定义相同的消息?/p>

  2?nbsp; 应用E序调用DLLE序之后Q需要将应用E序的窗口句柄传递给DLLQ以便DLL中的消息q回?/p>

  在DLL工程中:

  Q?Q?nbsp;      在stdafx.h头文件中d消息定义Q?/p>


 #define WM_MSG WM_USER + 102

       

  Q?Q?nbsp;      d启动消息的输出函敎ͼ


       CMessageDLLApp theApp;

  //发送消?/p>

extern "C" _declspec(dllexport) void StartSendMessage(HWND hwnd)

{

                 theApp.SendMessage(hwnd);

}     

 

            其中hwnd是接收消息的H口句柄?/p>

  Q?Q?nbsp;      d启动消息的实现函敎ͼ

在头文g中添加函数声明:


  void SendMessage(HWND hwnd);

 

  在CPP文g中添加函数实?/p>

  //启动发送消?/p>


void CMessageDLLApp::SendMessage(HWND hwnd)

{

                   ::PostMessage(hwnd,WM_MSG,0,1);

}

  在应

用程序中Q?/p>

  Q?Q?nbsp;      在stdafx.h头文件中d消息定义Q?/p>


#define WM_MSG WM_USER + 102

       

  Q?Q?nbsp;      首先在AFX_MSG块中加入消息声明Q在CTestMessageDLLDlg.h中,扑ֈ如下部分Qƈ加入消息声明Q?/p>

。。。。。?/p>


        afx_msg LRESULT OnMyMsg(WPARAM wParam,LPARAM lParam);

                 DECLARE_MESSAGE_MAP()

 

  Q?Q?nbsp;      在MESSAGE_MAP块中dON_MESSAGE宏指令:


        BEGIN_MESSAGE_MAP(CTestMessageDLLDlg, CDialog)

          。。。。。?/p>

          ON_MESSAGE(WM_MSG, OnMyMsg)

          //}}AFX_MSG_MAP

          END_MESSAGE_MAP()

 

  Q?Q?nbsp;      d消息函数体:


       LRESULT CTestMessageDLLDlg::OnMyMsg(WPARAM wParam, LPARAM lParam)

 {

                AfxMessageBox("消息已经收到Q?);

                 return 0;

     }

 Q?Q?nbsp;      在对话框上添加一个按钮,在按钮事件中Q先调用DLL文gQ然后发送一个测试消息响应的命oQ?/p>


void CTestMessageDLLDlg::OnBnClickedButton1()

{

    // TODO: 在此d控g通知处理E序代码

    //定义函数

    typedef void (_cdecl*STARTSENDMESSAGE)(HWND hwnd);

    HMODULE hmessage = NULL;

    STARTSENDMESSAGE StartSendMessage = NULL;

  //导入DLL库文?/p>

    hmessage = LoadLibrary("MessageDLL.dll");

    if(hmessage==NULL)

    {

        FreeLibrary(hmessage);

        exit(0);

    }

  //导入DLL中测试消息函?/p>

    StartSendMessage = (STARTSENDMESSAGE)GetProcAddress(hmessage,"StartSendMessage");

    if(StartSendMessage==NULL)

    {

        FreeLibrary(hmessage);

        exit(1);

    }

    //获取对话框的H口句柄

    HWND hwnd = this-QGetSafeHwnd();

    //发送测试消息函?/p>

    (*StartSendMessage)(hwnd);

}

 

q行应用E序Q就可以看到试l果了?br> 











]]>
MFC规则DLL的调?/title><link>http://www.shnenglu.com/ivenher/articles/1322.html</link><dc:creator>爱饭?/dc:creator><author>爱饭?/author><pubDate>Fri, 25 Nov 2005 10:50:00 GMT</pubDate><guid>http://www.shnenglu.com/ivenher/articles/1322.html</guid><wfw:comment>http://www.shnenglu.com/ivenher/comments/1322.html</wfw:comment><comments>http://www.shnenglu.com/ivenher/articles/1322.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/ivenher/comments/commentRss/1322.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ivenher/services/trackbacks/1322.html</trackback:ping><description><![CDATA[W者编写了如图12的对话框MFCE序Q下载本工程<A >附g</A>Q来调用5.3节的MFC规则DLLQ在q个E序的对话框上点几Z调用DLL”按钮时弹出5.3节MFC规则DLL中的对话框?BR> <P align=center><IMG alt="" src="http://www.pconline.com.cn/pcedu/empolder/gj/vc/0509/pic/05-09-22-vc-12.jpg" border=0></P> <P align=center>?2 MFC规则DLL的调用例?/P> <P>  下面是“调用DLL”按钮单M件的消息处理函数Q?BR></P> <P class=code>void CRegularDllCallDlg::OnCalldllButton() <BR><BR>{<BR><BR>typedef void (*lpFun)(void);<BR><BR><BR>HINSTANCE hDll; //DLL句柄 <BR><BR>hDll = LoadLibrary("RegularDll.dll");<BR><BR>if (NULL==hDll)<BR><BR>{<BR><BR>MessageBox("DLL加蝲p|");<BR><BR>}<BR><BR><BR><BR>lpFun addFun; //函数指针<BR><BR>lpFun pShowDlg = (lpFun)GetProcAddress(hDll,"ShowDlg");<BR><BR>if (NULL==pShowDlg)<BR><BR>{<BR><BR>MessageBox("DLL中函数寻扑֤?); <BR><BR>}<BR><BR>pShowDlg();<BR><BR>}</P><BR>  上述例子中给出的是显C用的方式Q可以看出,其调用方式与W?节中非MFC DLL的调用方式没有什么不同?BR>我们照样可以在EXEE序中隐式调用MFC规则DLLQ只需要将DLL工程生成?lib文g?dll文g拷入当前工程所在的目录Qƈ在RegularDllCallDlg.cpp文gQ图12所C对话框cȝ实现文gQ的剙dQ?BR> <P class=code>#pragma comment(lib,"RegularDll.lib")<BR><BR>void ShowDlg(void); </P><BR>  q将void CRegularDllCallDlg::OnCalldllButton() 改ؓQ?BR> <P class=code>void CRegularDllCallDlg::OnCalldllButton() <BR><BR>{<BR><BR>ShowDlg();<BR><BR>}</P><img src ="http://www.shnenglu.com/ivenher/aggbug/1322.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ivenher/" target="_blank">爱饭?/a> 2005-11-25 18:50 <a href="http://www.shnenglu.com/ivenher/articles/1322.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MFC规则DLL 单的例子http://www.shnenglu.com/ivenher/articles/1321.html爱饭?/dc:creator>爱饭?/author>Fri, 25 Nov 2005 10:49:00 GMThttp://www.shnenglu.com/ivenher/articles/1321.htmlhttp://www.shnenglu.com/ivenher/comments/1321.htmlhttp://www.shnenglu.com/ivenher/articles/1321.html#Feedback2http://www.shnenglu.com/ivenher/comments/commentRss/1321.htmlhttp://www.shnenglu.com/ivenher/services/trackbacks/1321.htmlQ下载本工程附gQ:

?1 MFC规则DLL例子

  在DLL中添加对话框的方式与在MFC应用E序中是一L?BR>
  在图11所CDLL中的对话框的Hello按钮上点LMessageBox一个“Hello,pconline的网友”对话框Q下面是相关的文件及源代码,其中删除了MFC向导自动生成的绝大多数注释?BR>W一l文ӞCWinAppl承cȝ声明与实?BR>

// RegularDll.h : main header file for the REGULARDLL DLL



#if !defined(AFX_REGULARDLL_H__3E9CB22B_588B_4388_B778_B3416ADB79B3__INCLUDED_)

#define AFX_REGULARDLL_H__3E9CB22B_588B_4388_B778_B3416ADB79B3__INCLUDED_



#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000



#ifndef __AFXWIN_H__

#error include 'stdafx.h' before including this file for PCH

#endif

#include "resource.h" // main symbols



class CRegularDllApp : public CWinApp

{

public:

CRegularDllApp();



DECLARE_MESSAGE_MAP()

};

#endif



// RegularDll.cpp : Defines the initialization routines for the DLL.



#include "stdafx.h"

#include "RegularDll.h"



#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif



BEGIN_MESSAGE_MAP(CRegularDllApp, CWinApp)

END_MESSAGE_MAP()



/////////////////////////////////////////////////////////////////////////////

// CRegularDllApp construction



CRegularDllApp::CRegularDllApp()

{

}



/////////////////////////////////////////////////////////////////////////////

// The one and only CRegularDllApp object

CRegularDllApp theApp;


  分析Q?BR>
  在这一l文件中定义了一个承自CWinApp的类CRegularDllAppQƈ同时定义了其的一个实例theApp。乍一看,您会以ؓ它是一个MFC应用E序Q因为MFC应用E序也包含这L在工E名后添加“App”组成类名的c(q承自CWinAppc)Q也定义了这个类的一个全局实例theApp?BR>我们知道Q在MFC应用E序中CWinApp取代了SDKE序中WinMain的地位,SDKE序WinMain所完成的工作由CWinApp的三个函数完成:

virtual BOOL InitApplication( );

virtual BOOL InitInstance( );

virtual BOOL Run( ); //传说中MFCE序的“活水源头?/P>


  但是MFC规则DLLq不是MFC应用E序Q它所l承自CWinApp的类不包含消息@环。这是因为,MFC规则DLL不包含CWinApp::Run机制Q主消息泵仍然由应用E序拥有。如果DLL 生成无模式对话框或有自己的主框架H口Q则应用E序的主消息泵必调用从DLL 导出的函数来调用PreTranslateMessage成员函数?BR>
  另外QMFC规则DLL与MFC 应用E序中一P需要将所?DLL中元素的初始化放到InitInstance 成员函数中?BR>
  W二l文?自定义对话框cd明及实现(点击查看附g)

  分析Q?BR>
  q一部分的编E与一般的应用E序Ҏ没有什么不同,我们照样可以利用MFCcd导来自动为对话框上的控gd事g。MFCcd导照样会生成cMON_BN_CLICKED(IDC_HELLO_BUTTON, OnHelloButton)的消息映宏?BR>
  W三l文?DLL中的资源文g

//{{NO_DEPENDENCIES}}

// Microsoft Developer Studio generated include file.

// Used by RegularDll.rc

//

#define IDD_DLL_DIALOG 1000

#define IDC_HELLO_BUTTON 1000


  分析Q?BR>
  在MFC规则DLL中用资源也与在MFC应用E序中用资源没有什么不同,我们照样可以用Visual C++的资源编辑工兯行资源的d、删除和属性的更改?BR>
  W四l文?MFC规则DLL接口函数

#include "StdAfx.h"

#include "DllDialog.h"


extern "C" __declspec(dllexport) void ShowDlg(void)

{

CDllDialog dllDialog;

dllDialog.DoModal();

}


  分析Q?BR>
  q个接口q不使用MFCQ但是在其中却可以调用MFC扩展cCdllDialog的函敎ͼq体C“规则”的概类?BR>
  与非MFC DLL完全相同Q我们可以用__declspec(dllexport)声明或在.def中引出的方式导出MFC规则DLL中的接口?BR>



]]>
MFC规则DLL的创?/title><link>http://www.shnenglu.com/ivenher/articles/1320.html</link><dc:creator>爱饭?/dc:creator><author>爱饭?/author><pubDate>Fri, 25 Nov 2005 10:46:00 GMT</pubDate><guid>http://www.shnenglu.com/ivenher/articles/1320.html</guid><wfw:comment>http://www.shnenglu.com/ivenher/comments/1320.html</wfw:comment><comments>http://www.shnenglu.com/ivenher/articles/1320.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/ivenher/comments/commentRss/1320.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ivenher/services/trackbacks/1320.html</trackback:ping><description><![CDATA[<BR>  我们来一步步讲述使用MFC向导创徏MFC规则DLL的过E,首先新徏一个projectQ如?Q选择project的类型ؓMFC AppWizard(dll)。点击OKq入如图10所C的对话框?BR> <P align=center><IMG alt="" src="http://www.pconline.com.cn/pcedu/empolder/gj/vc/0509/pic/05-09-22-vc-9.jpg" border=0></P> <P align=center>? MFC DLL工程的创?/P> <P>  ?0所C对话框中的1区选择MFC DLL的类别?BR><BR>  2区选择是否支持automationQ自动化Q技术, automation 允许用户在一个应用程序中操纵另外一个应用程序或lg。例如,我们可以在应用程序中利用 Microsoft Word 或Microsoft Excel的工P而这U用对用户而言是透明的。自动化技术可以大大简化和加快应用E序的开发?BR><BR>  3区选择是否支持Windows SocketsQ当选择此项目时Q应用程序能?TCP/IP |络上进行通信?CWinAppzcȝInitInstance成员函数会初始化通讯端的支持Q同时工E中的StdAfx.h文g会自动include <AfxSock.h>头文件?BR>dsocket通讯支持后的InitInstance成员函数如下Q?BR></P> <P></P> <P class=code>BOOL CRegularDllSocketApp::InitInstance()<BR><BR>{<BR><BR>if (!AfxSocketInit())<BR><BR>{<BR><BR>AfxMessageBox(IDP_SOCKETS_INIT_FAILED);<BR><BR>return FALSE;<BR><BR>}<BR><BR><BR>return TRUE;<BR><BR>}</P> <P><BR>  4区选择是否由MFC向导自动在源代码中添加注释,一般我们选择“Yes,please”?BR></P> <P align=center><IMG alt="" src="http://www.pconline.com.cn/pcedu/empolder/gj/vc/0509/pic/05-09-22-vc-10.jpg" border=0></P> <P align=center>?0 MFC DLL的创建选项</P><img src ="http://www.shnenglu.com/ivenher/aggbug/1320.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ivenher/" target="_blank">爱饭?/a> 2005-11-25 18:46 <a href="http://www.shnenglu.com/ivenher/articles/1320.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MFC规则DLL 概述http://www.shnenglu.com/ivenher/articles/1319.html爱饭?/dc:creator>爱饭?/author>Fri, 25 Nov 2005 10:43:00 GMThttp://www.shnenglu.com/ivenher/articles/1319.htmlhttp://www.shnenglu.com/ivenher/comments/1319.htmlhttp://www.shnenglu.com/ivenher/articles/1319.html#Feedback0http://www.shnenglu.com/ivenher/comments/commentRss/1319.htmlhttp://www.shnenglu.com/ivenher/services/trackbacks/1319.html
  Q?Q?它是MFC?BR>
  “是MFC的”意味着可以在这UDLL的内部用MFCQ?BR>
  Q?Q?它是规则?BR>
  “是规则的”意味着它不同于MFC扩展DLLQ在MFC规则DLL的内部虽然可以用MFCQ但是其与应用程序的接口不能是MFC。而MFC扩展DLL与应用程序的接口可以是MFCQ可以从MFC扩展DLL中导Z个MFCcȝzcR?BR>
  Regular DLL能够被所有支持DLL技术的语言所~写的应用程序调用,当然也包括用MFC的应用程序。在q种动态连接库中,包含一个从CWinAppl承下来的类QDllMain函数则由MFC自动提供?BR>
  Regular DLL分ؓ两类Q?BR>
  Q?Q静态链接到MFC 的规则DLL

  静态链接到MFC的规则DLL与MFC库(包括MFC扩展 DLLQ静态链接,MFC库的代码直接生成?dll文g中。在调用q种DLL的接口时QMFC使用DLL的资源。因此,在静态链接到MFC 的规则DLL中不需要进行模块状态的切换?BR>
  使用q种Ҏ生成的规则DLL其程序较大,也可能包含重复的代码?BR>
  Q?Q动态链接到MFC 的规则DLL

  动态链接到MFC 的规则DLL 可以和用它的可执行文g同时动态链接到 MFC DLL 和Q何MFC扩展 DLL。在使用了MFC׃n库的时候,默认情况下,MFC使用d用程序的资源句柄来加载资源模ѝ这P当DLL和应用程序中存在相同ID的资源时Q即所谓的资源重复问题Q,pȝ可能不能获得正确的资源。因此,对于׃nMFC DLL的规则DLLQ我们必进行模块切换以使得MFC能够扑ֈ正确的资源模ѝ?BR>我们可以在Visual C++中设|MFC规则DLL是静态链接到MFC DLLq是动态链接到MFC DLL。如?Q依ơ选择Visual C++的project -> Settings -> General菜单或选项Q在Microsoft Foundation Classes中进行设|?BR>

]]>
DLL导出c?/title><link>http://www.shnenglu.com/ivenher/articles/1318.html</link><dc:creator>爱饭?/dc:creator><author>爱饭?/author><pubDate>Fri, 25 Nov 2005 10:26:00 GMT</pubDate><guid>http://www.shnenglu.com/ivenher/articles/1318.html</guid><wfw:comment>http://www.shnenglu.com/ivenher/comments/1318.html</wfw:comment><comments>http://www.shnenglu.com/ivenher/articles/1318.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/ivenher/comments/commentRss/1318.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ivenher/services/trackbacks/1318.html</trackback:ping><description><![CDATA[<STRONG>DLL导出c?BR><BR></STRONG>  DLL中定义的cd以在应用工程中用?BR><BR>  下面的例子里Q我们在DLL中定义了point和circle两个c,q在应用工程中引用了它们Q单L处下载本工程<A >附g</A>Q?BR> <P class=code>//文g名:point.hQpointcȝ声明<BR><BR>#ifndef POINT_H<BR><BR>#define POINT_H<BR><BR>#ifdef DLL_FILE<BR><BR>class _declspec(dllexport) point //导出cpoint<BR><BR>#else<BR><BR>class _declspec(dllimport) point //导入cpoint<BR><BR>#endif<BR><BR>{<BR><BR>public:<BR><BR>float y;<BR><BR>float x;<BR><BR>point();<BR><BR>point(float x_coordinate, float y_coordinate);<BR><BR>};<BR><BR>#endif<BR><BR><BR>//文g名:point.cppQpointcȝ实现<BR><BR>#ifndef DLL_FILE<BR><BR>#define DLL_FILE<BR><BR>#endif<BR><BR>#include "point.h"<BR><BR>//cpoint的缺省构造函?BR><BR>point::point()<BR><BR>{<BR><BR>x = 0.0;<BR><BR>y = 0.0;<BR><BR>}<BR><BR>//cpoint的构造函?BR><BR>point::point(float x_coordinate, float y_coordinate)<BR><BR>{<BR><BR>x = x_coordinate;<BR><BR>y = y_coordinate;<BR><BR>}<BR><BR><BR>//文g名:circle.hQcirclecȝ声明<BR><BR>#ifndef CIRCLE_H<BR><BR>#define CIRCLE_H<BR><BR>#include "point.h" <BR><BR>#ifdef DLL_FILE<BR><BR>class _declspec(dllexport)circle //导出ccircle<BR><BR>#else<BR><BR>class _declspec(dllimport)circle //导入ccircle<BR><BR>#endif<BR><BR>{<BR><BR>public:<BR><BR>void SetCentre(const point rePoint);<BR><BR>void SetRadius(float r);<BR><BR>float GetGirth();<BR><BR>float GetArea();<BR><BR>circle();<BR><BR>private:<BR><BR>float radius;<BR><BR>point centre;<BR><BR>};<BR><BR>#endif<BR><BR><BR>//文g名:circle.cppQcirclecȝ实现<BR><BR>#ifndef DLL_FILE<BR><BR>#define DLL_FILE<BR><BR>#endif<BR><BR>#include "circle.h"<BR><BR>#define PI 3.1415926<BR><BR>//circlecȝ构造函?BR><BR>circle::circle()<BR><BR>{<BR><BR>centre = point(0, 0);<BR><BR>radius = 0;<BR><BR>}<BR><BR>//得到圆的面积<BR><BR>float circle::GetArea()<BR><BR>{<BR><BR>return PI *radius * radius;<BR><BR>}<BR><BR>//得到圆的周长<BR><BR>float circle::GetGirth()<BR><BR>{<BR><BR>return 2 *PI * radius;<BR><BR>}<BR><BR>//讄圆心坐标<BR><BR>void circle::SetCentre(const point rePoint)<BR><BR>{<BR><BR>centre = centrePoint;<BR><BR>}<BR><BR>//讄圆的半径<BR><BR>void circle::SetRadius(float r)<BR><BR>{<BR><BR>radius = r;<BR><BR>}<BR><BR>cȝ引用Q?BR></P> <P class=code>#include "..\circle.h"  //包含cd明头文g<BR><BR>#pragma comment(lib,"dllTest.lib");<BR><BR><BR>int main(int argc, char *argv[])<BR><BR>{<BR><BR>circle c;<BR><BR>point p(2.0, 2.0);<BR><BR>c.SetCentre(p);<BR><BR>c.SetRadius(1.0);<BR><BR>printf("area:%f girth:%f", c.GetArea(), c.GetGirth());<BR><BR><BR>return 0;<BR><BR>}</P> <P class=code><BR>  从上q源代码可以看出Q由于在DLL的类实现代码中定义了宏DLL_FILEQ故在DLL的实C所包含的类声明实际上ؓQ?BR></P> <P class=code>class _declspec(dllexport) point //导出cpoint<BR><BR>{<BR><BR>?BR><BR>}</P> <P class=code><BR>  ?BR></P> <P class=code>class _declspec(dllexport) circle //导出ccircle<BR><BR>{<BR><BR>?BR><BR>}</P> <P class=code><BR>  而在应用工程中没有定义DLL_FILEQ故其包含point.h和circle.h后引入的cd明ؓQ?BR></P> <P class=code>class _declspec(dllimport) point //导入cpoint<BR><BR>{<BR><BR>?BR><BR>}</P> <P class=code><BR>  ?BR></P> <P class=code>class _declspec(dllimport) circle //导入ccircle<BR><BR>{<BR><BR>?BR><BR>}</P> <P class=code><BR clear=all></P><img src ="http://www.shnenglu.com/ivenher/aggbug/1318.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ivenher/" target="_blank">爱饭?/a> 2005-11-25 18:26 <a href="http://www.shnenglu.com/ivenher/articles/1318.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DLL导出变量http://www.shnenglu.com/ivenher/articles/1317.html爱饭?/dc:creator>爱饭?/author>Fri, 25 Nov 2005 10:21:00 GMThttp://www.shnenglu.com/ivenher/articles/1317.htmlhttp://www.shnenglu.com/ivenher/comments/1317.htmlhttp://www.shnenglu.com/ivenher/articles/1317.html#Feedback0http://www.shnenglu.com/ivenher/comments/commentRss/1317.htmlhttp://www.shnenglu.com/ivenher/services/trackbacks/1317.html附gQ?BR>

/* 文g名:lib.h */

#ifndef LIB_H

#define LIB_H

extern int dllGlobalVar;

#endif


/* 文g名:lib.cpp */

#include "lib.h"

#include <windows.h>


int dllGlobalVar;


BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)

{

switch (ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

dllGlobalVar = 100; //在dll被加载时Q赋全局变量?00

break;

case DLL_THREAD_ATTACH:

case DLL_THREAD_DETACH:

case DLL_PROCESS_DETACH:

break;

}

return TRUE;

}


;文g名:lib.def

;在DLL中导出变?BR>
LIBRARY "dllTest"

EXPORTS

dllGlobalVar CONSTANT

;或dllGlobalVar DATA

GetGlobalVar


  从lib.h和lib.cpp中可以看出,全局变量在DLL中的定义和用方法与一般的E序设计是一L。若要导出某全局变量Q我们需要在.def文g的EXPORTS后添加:

变量名 CONSTANT   //q时的方?/P>
  ?BR>

变量名 DATA     //VC++提示的新Ҏ

在主函数中引用DLL中定义的全局变量Q?BR>

#include <stdio.h>

#pragma comment(lib,"dllTest.lib")

extern int dllGlobalVar;

int main(int argc, char *argv[])

{

printf("%d ", *(int*)dllGlobalVar);

*(int*)dllGlobalVar = 1;

printf("%d ", *(int*)dllGlobalVar);


return 0;

}


  特别要注意的是用extern int dllGlobalVar声明所导入的ƈ不是DLL中全局变量本nQ而是其地址Q应用程序必通过强制指针转换来用DLL中的全局变量。这一点,?(int*)dllGlobalVar可以看出。因此在采用q种方式引用DLL全局变量Ӟ千万不要q行q样的赋值操作:

dllGlobalVar = 1;


  其结果是dllGlobalVar指针的内容发生变化,E序中以后再也引用不到DLL中的全局变量了?BR>
  在应用工E中引用DLL中全局变量的一个更好方法是Q?BR>

#include <stdio.h>

#pragma comment(lib,"dllTest.lib")

extern int _declspec(dllimport) dllGlobalVar; //用_declspec(dllimport)导入

int main(int argc, char *argv[])

{

printf("%d ", dllGlobalVar);

dllGlobalVar = 1; //q里可以直接? 无须q行强制指针转换

printf("%d ", dllGlobalVar);

return 0;

}


  通过_declspec(dllimport)方式导入的就是DLL中全局变量本n而不再是其地址了,W者徏议在一切可能的情况下都使用q种方式?BR>



]]>
__stdcallU定http://www.shnenglu.com/ivenher/articles/1316.html爱饭?/dc:creator>爱饭?/author>Fri, 25 Nov 2005 10:19:00 GMThttp://www.shnenglu.com/ivenher/articles/1316.htmlhttp://www.shnenglu.com/ivenher/comments/1316.htmlhttp://www.shnenglu.com/ivenher/articles/1316.html#Feedback0http://www.shnenglu.com/ivenher/comments/commentRss/1316.htmlhttp://www.shnenglu.com/ivenher/services/trackbacks/1316.html
  Windows~程中常见的几种函数cd声明宏都是与__stdcall和__cdecl有关的(节选自windef.hQ:

#define CALLBACK __stdcall //q就是传说中的回调函?BR>
#define WINAPI __stdcall //q就是传说中的WINAPI

#define WINAPIV __cdecl

#define APIENTRY WINAPI //DllMain的入口就在这?BR>
#define APIPRIVATE __stdcall

#define PASCAL __stdcall


  在lib.h中,应这样声明add函数Q?BR>

int __stdcall add(int x, int y);


  在应用工E中函数指针cd应定义ؓQ?BR>

typedef int(__stdcall *lpAddFun)(int, int);


  若在lib.h中将函数声明为__stdcall调用Q而应用工E中仍用typedef int (* lpAddFun)(int,int)Q运行时发生错误(因ؓcd不匹配,在应用工E中仍然是缺省的__cdecl调用Q,

]]>
DllMain函数http://www.shnenglu.com/ivenher/articles/1315.html爱饭?/dc:creator>爱饭?/author>Fri, 25 Nov 2005 10:12:00 GMThttp://www.shnenglu.com/ivenher/articles/1315.htmlhttp://www.shnenglu.com/ivenher/comments/1315.htmlhttp://www.shnenglu.com/ivenher/articles/1315.html#Feedback0http://www.shnenglu.com/ivenher/comments/commentRss/1315.htmlhttp://www.shnenglu.com/ivenher/services/trackbacks/1315.html
  Ҏ~写规范QWindows必须查找q执行DLL里的DllMain函数作ؓ加蝲DLL的依据,它得DLL得以保留在内存里。这个函数ƈ不属于导出函敎ͼ而是DLL的内部函数。这意味着不能直接在应用工E中引用DllMain函数QDllMain是自动被调用的?BR>
  我们来看一个DllMain函数的例子(单击此处下蝲本工E?A >附gQ?BR>

BOOL APIENTRY DllMain( HANDLE hModule,

DWORD ul_reason_for_call,

LPVOID lpReserved

)

{

switch (ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

printf("\nprocess attach of dll");

break;

case DLL_THREAD_ATTACH:

printf("\nthread attach of dll");

break;

case DLL_THREAD_DETACH:

printf("\nthread detach of dll");

break;

case DLL_PROCESS_DETACH:

printf("\nprocess detach of dll");

break;

}

return TRUE;

}


  DllMain函数在DLL被加载和卸蝲时被调用Q在单个U程启动和终止时QDLLMain函数也被调用Qul_reason_for_call指明了被调用的原因。原因共?U,即PROCESS_ATTACH、PROCESS_DETACH、THREAD_ATTACH和THREAD_DETACHQ以switch语句列出?BR>来仔l解M下DllMain的函数头BOOL APIENTRY DllMain( HANDLE hModule, WORD ul_reason_for_call, LPVOID lpReserved )?BR>
  APIENTRY被定义ؓ__stdcallQ它意味着q个函数以标准Pascal的方式进行调用,也就是WINAPI方式Q?BR>
  q程中的每个DLL模块被全局唯一?2字节的HINSTANCE句柄标识Q只有在特定的进E内部有效,句柄代表了DLL模块在进E虚拟空间中的v始地址。在Win32中,HINSTANCE和HMODULE的值是相同的,q两U类型可以替换用,q就是函数参数hModule的来历?BR>
  执行下列代码Q?BR>

hDll = LoadLibrary("..\\Debug\\dllTest.dll");

if (hDll != NULL)

{

addFun = (lpAddFun)GetProcAddress(hDll, MAKEINTRESOURCE(1));

//MAKEINTRESOURCE直接使用导出文g中的序号

if (addFun != NULL)

{

int result = addFun(2, 3);

printf("\ncall add in dll:%d", result);

}

FreeLibrary(hDll);

}



  我们看到输出序为:

  process attach of dll

  call add in dll:5

  process detach of dll

  q一输出序验证了DllMain被调用的时机?BR>
  代码中的GetProcAddress ( hDll, MAKEINTRESOURCE ( 1 ) )值得留意Q它直接通过.def文g中ؓadd函数指定的顺序号讉Kadd函数Q具体体现在MAKEINTRESOURCE ( 1 )QMAKEINTRESOURCE是一个通过序号获取函数名的宏,定义为(节选自winuser.hQ:

#define MAKEINTRESOURCEA(i) (LPSTR)((DWORD)((WORD)(i)))

#define MAKEINTRESOURCEW(i) (LPWSTR)((DWORD)((WORD)(i)))

#ifdef UNICODE

#define MAKEINTRESOURCE MAKEINTRESOURCEW

#else

#define MAKEINTRESOURCE MAKEINTRESOURCEA



]]>
非MFC DLL ?DLL的调用方?/title><link>http://www.shnenglu.com/ivenher/articles/1314.html</link><dc:creator>爱饭?/dc:creator><author>爱饭?/author><pubDate>Fri, 25 Nov 2005 10:10:00 GMT</pubDate><guid>http://www.shnenglu.com/ivenher/articles/1314.html</guid><wfw:comment>http://www.shnenglu.com/ivenher/comments/1314.html</wfw:comment><comments>http://www.shnenglu.com/ivenher/articles/1314.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/ivenher/comments/commentRss/1314.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ivenher/services/trackbacks/1314.html</trackback:ping><description><![CDATA[<FONT color=#ff0000><STRONG>动态调?/STRONG></FONT><BR>typedef int(*lpAddFun)(int, int); //宏定义函数指针类?BR><BR>int main(int argc, char *argv[])<BR><BR>{<BR><BR>HINSTANCE hDll; //DLL句柄 <BR><BR>lpAddFun addFun; //函数指针<BR><BR>hDll = LoadLibrary("..\\Debug\\dllTest.dll");<BR><BR>if (hDll != NULL)<BR><BR>{<BR><BR>addFun = (lpAddFun)GetProcAddress(hDll, "add");<BR><BR>if (addFun != NULL)<BR><BR>{<BR><BR>int result = addFun(2, 3);<BR><BR>printf("%d", result);<BR><BR>}<BR><BR>FreeLibrary(hDll);<BR><BR>}<BR><BR>return 0;<BR><BR>}<BR>  在上边的例子中我们看C由“LoadLibrary-GetProcAddress-FreeLibrary”系lApi提供的三位一体“DLL加蝲-DLL函数地址获取-DLL释放”方式,q种调用方式UCؓDLL?FONT color=#ff0000>动态调用?BR></FONT><BR>  动态调用方式的特点是完全由~程者用 API 函数加蝲和卸?DLLQ程序员可以军_ DLL 文g何时加蝲或不加蝲Q显式链接在q行时决定加载哪?DLL 文g?BR><BR>  与动态调用方式相对应的就是静态调用方式,“有动必有静”,q来源于物质世界的对立统一。“动与静”,其对立与l一竟无数次在技术领域里得到验证Q譬如静态IP与DHCP、静态\׃动态\q。从前文我们已经知道Q库也分为静态库与动态库DLLQ而想不到Q深入到DLL内部Q其调用方式也分为静态与动态。“动与静”,无处不在。《周易》已认识到有动必有静的动静^衡观Q《易Q系辞》曰Q“动静有常,刚柔断矣”。哲学意味着一U普遍的真理Q因此,我们l常可以在枯燥的技术领域看到哲学的影子?BR><BR>  静态调用方式的特点是由~译pȝ完成对DLL的加载和应用E序l束?DLL 的卸载。当调用某DLL的应用程序结束时Q若pȝ中还有其它程序用该 DLLQ则Windows对DLL的应用记录减1Q直到所有用该DLL的程序都l束时才释放它。静态调用方式简单实用,但不如动态调用方式灵zR?BR><BR>  下面我们来看?STRONG><FONT style="BACKGROUND-COLOR: #ffffff" color=#ff0000>静态调用的例子</FONT></STRONG>Q将~译dllTest工程所生成?lib?dll文g拷入dllCall工程所在的路径QdllCall执行下列代码Q?BR> <P class=code>#pragma comment(lib,"dllTest.lib") <BR><BR>//.lib文g中仅仅是关于其对应DLL文g中函数的重定位信?BR><BR>extern "C" __declspec(dllimport) add(int x,int y); <BR><BR>int main(int argc, char* argv[])<BR><BR>{<BR><BR>int result = add(2,3); <BR><BR>printf("%d",result);<BR><BR>return 0;<BR><BR>}</P><BR>  ׃qC码可以看出,静态调用方式的利q行需要完?STRONG><FONT color=#ff0000>两个动作</FONT></STRONG>Q?BR><BR>  (1)告诉~译器与DLL相对应的.lib文g所在的路径及文件名Q?pragma comment(lib,"dllTest.lib")是赯个作用?BR><BR>  E序员在建立一个DLL文gӞq接器会自动为其生成一个对应的.lib文gQ该文g包含了DLL 导出函数的符号名及序Pq不含有实际的代码)。在应用E序里,.lib文g作为DLL的替代文件参与编译?BR><BR>  (2)声明导入函数Qextern "C" __declspec(dllimport) add(int x,int y)语句中的__declspec(dllimport)发挥q个作用?BR><BR>  静态调用方式不再需要用系lAPI来加载、卸载DLL以及获取DLL中导出函数的地址。这是因为,当程序员通过静态链接方式编译生成应用程序时Q应用程序中调用的与.lib文g中导出符L匚w的函数符号将q入到生成的EXE 文g中,.lib文g中所包含的与之对应的DLL文g的文件名也被~译器存储在 EXE文g内部。当应用E序q行q程中需要加载DLL文gӞWindows根据这些信息发现ƈ加蝲DLLQ然后通过W号名实现对DLL 函数的动态链接。这PEXE能直接通过函数名调用DLL的输出函敎ͼp调用E序内部的其他函C栗?BR><img src ="http://www.shnenglu.com/ivenher/aggbug/1314.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ivenher/" target="_blank">爱饭?/a> 2005-11-25 18:10 <a href="http://www.shnenglu.com/ivenher/articles/1314.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>非MFC DLL ?声明导出函数http://www.shnenglu.com/ivenher/articles/1313.html爱饭?/dc:creator>爱饭?/author>Fri, 25 Nov 2005 09:59:00 GMThttp://www.shnenglu.com/ivenher/articles/1313.htmlhttp://www.shnenglu.com/ivenher/comments/1313.htmlhttp://www.shnenglu.com/ivenher/articles/1313.html#Feedback0http://www.shnenglu.com/ivenher/comments/commentRss/1313.htmlhttp://www.shnenglu.com/ivenher/services/trackbacks/1313.html  DLL中导出函数的声明有两U方式:一Uؓ4.1节例子中l出的在函数声明中加上__declspec(dllexport)Q这里不再D例说明;另外一U方式是采用模块定义(.def) 文g声明Q?def文g为链接器提供了有兌链接E序的导出、属性及其他斚w的信息?BR>
  下面的代码演CZ怎样?def文g函数add声明为DLL导出函数Q需在dllTest工程中添加lib.def文gQ:

; lib.def : 导出DLL函数

LIBRARY dllTest

EXPORTS

add @ 1


.def文g的规则ؓQ?BR>
  (1)LIBRARY语句说明.def文g相应的DLLQ?BR>
  (2)EXPORTS语句后列导出函数的名U。可以在.def文g中的导出函数名后加@nQ表C导出函数的序号ؓnQ在q行函数调用Ӟq个序号发挥其作用Q;

  (3).def 文g中的注释由每个注释行开始处的分?(;) 指定Q且注释不能与语句共享一行?BR>
  由此可以看出Q例子中lib.def文g的含义ؓ生成名ؓ“dllTest”的动态链接库Q导出其中的add函数Qƈ指定add函数的序号ؓ1?BR>

]]>
非MFC DLLhttp://www.shnenglu.com/ivenher/articles/dll_2.html爱饭?/dc:creator>爱饭?/author>Fri, 25 Nov 2005 09:58:00 GMThttp://www.shnenglu.com/ivenher/articles/dll_2.htmlhttp://www.shnenglu.com/ivenher/comments/1312.htmlhttp://www.shnenglu.com/ivenher/articles/dll_2.html#Feedback0http://www.shnenglu.com/ivenher/comments/commentRss/1312.htmlhttp://www.shnenglu.com/ivenher/services/trackbacks/1312.html

/* 文g名:lib.h */

#ifndef LIB_H

#define LIB_H

extern "C" int __declspec(dllexport)add(int x, int y);

#endif


/* 文g名:lib.cpp */

#include "lib.h"

int add(int x, int y)

{

return x + y;

}

分析上述代码QdllTest工程中的lib.cpp文g与第2节静态链接库版本完全相同Q不同在于lib.h对函数add的声明前面添加了__declspec(dllexport)语句。这个语句的含义是声明函数add为DLL的导出函数。DLL内的函数分ؓ两种Q?BR>
  (1)DLL导出函数Q可供应用程序调用;

  (2) DLL内部函数Q只能在DLLE序使用Q应用程序无法调用它们?BR>
与第2节对静态链接库的调用相|我们也徏立一个与DLL工程处于同一工作区的应用工程dllCallQ它调用DLL中的函数addQ其源代码如下:

#include <stdio.h>

#include <windows.h>

typedef int(*lpAddFun)(int, int); //宏定义函数指针类?BR>
int main(int argc, char *argv[])

{

HINSTANCE hDll; //DLL句柄

lpAddFun addFun; //函数指针

hDll = LoadLibrary("..\\Debug\\dllTest.dll");

if (hDll != NULL)

{

addFun = (lpAddFun)GetProcAddress(hDll, "add");

if (addFun != NULL)

{

int result = addFun(2, 3);

printf("%d", result);

}

FreeLibrary(hDll);

}

return 0;

}
而应用程序对本DLL的调用和对第2节静态链接库的调用却有较大差异,下面我们来逐一分析?BR>
  首先Q语句typedef int ( * lpAddFun)(int,int)定义了一个与add函数接受参数cd和返回值均相同的函数指针类型。随后,在main函数中定义了lpAddFun的实例addFunQ?BR>
  其次Q在函数main中定义了一个DLL HINSTANCE句柄实例hDllQ通过Win32 Api函数LoadLibrary动态加载了DLL模块q将DLL模块句柄赋给了hDllQ?BR>
  再次Q在函数main中通过Win32 Api函数GetProcAddress得到了所加蝲DLL模块中函数add的地址q赋l了addFun。经由函数指针addFunq行了对DLL中add函数的调用;

  最后,应用工程使用完DLL后,在函数main中通过Win32 Api函数FreeLibrary释放了已l加载的DLL模块?BR>
  通过q个单的例子Q我们获知DLL定义和调用的一般概念:

  (1)DLL中需以某U特定的方式声明导出函数Q或变量、类Q;

  (2)应用工程需以某U特定的方式调用DLL的导出函敎ͼ或变量、类Q?BR>



]]>
Lib 静态链接库http://www.shnenglu.com/ivenher/articles/1310.html爱饭?/dc:creator>爱饭?/author>Fri, 25 Nov 2005 09:24:00 GMThttp://www.shnenglu.com/ivenher/articles/1310.htmlhttp://www.shnenglu.com/ivenher/comments/1310.htmlhttp://www.shnenglu.com/ivenher/articles/1310.html#Feedback0http://www.shnenglu.com/ivenher/comments/commentRss/1310.htmlhttp://www.shnenglu.com/ivenher/services/trackbacks/1310.html  Visual C++支持三种DLLQ它们分别是Non-MFC DLLQ非MFC动态库Q、MFC Regular DLLQMFC规则DLLQ、MFC Extension DLLQMFC扩展DLLQ?BR>      非MFC动态库不采用MFCcdl构Q其导出函数为标准的C接口Q能被非MFC或MFC~写的应用程序所调用Q?BR>      MFC规则DLL 包含一个承自CWinApp的类Q但其无消息循环Q?BR>      MFC扩展DLL采用MFC的动态链接版本创建,它只能被用MFCcd所~写的应用程序所调用?BR>
静态链接库
在VC++6.0中new一个名UCؓlibTest的static library工程Qƈ新徏lib.h和lib.cpp两个文gQlib.h和lib.cpp的源代码如下Q?BR>

//文gQlib.h
#ifndef LIB_H
#define LIB_H
extern "C" int add(int x,int y);   //声明为C~译、连接方式的外部函数
#endif

//文gQlib.cpp
#include "lib.h"
int add(int x,int y)
{
return x + y;
}


  ~译q个工程得C一?lib文gQ这个文件就是一个函数库Q它提供了add的功能。将头文件和.lib文g提交l用户后Q用户就可以直接使用其中的add函数了?BR>
  标准Turbo C2.0中的C库函敎ͼ我们用来的scanf、printf、memcpy、strcpy{)来自这U静态库?BR>
下面来看看怎么使用q个库,在libTest工程所在的工作区内new一个libCall工程。libCall工程仅包含一个main.cpp文gQ它演示了静态链接库的调用方法,其源代码如下Q?BR>

#include <stdio.h>
#include "..\lib.h"
#pragma comment( lib, "..\\debug\\libTest.lib" )  //指定与静态库一赯?BR>int main(int argc, char* argv[])
{
printf( "2 + 3 = %d", add( 2, 3 ) );
}


  静态链接库的调用就是这么简单,或许我们每天都在用,可是我们没有明白q个概念。代码中#pragma comment( lib , "..\\debug\\libTest.lib" )的意思是指本文g生成?obj文g应与libTest.lib一赯接?BR>




]]>
޾þһ | þAVӰ| þ㽶97Ʒ| Ʒþþþþ | 99þ99þþƷƬ| ŷ޹Ʒþѿ | ۺϾþþþþĻ޹ۺһ | þ99Ʒþþþþþò| þҹ³˿Ƭϼ | 91Ʒ91þþþø| һaɫƬþٸһHƬѷ | þùѾƷ| 97Ʒ˾þþô߽97 | ŷ޾þþþƷ| þseƷһ| þԭƷ| ĻƷѾþ| þþƷӰԺ| þþƷ2020| ޷?Vþò| 91Ʒ91þþþþ| ƷŮþþþAV| ˾þۺ2020| һþۺ³³ŷһ | þþƷAVDz18| պƷþþþþ| þþþAVվ| 㽶þþƷۺ| պAVëƬƷþþ| ƷþþþþþĻ | Ʒžžžþþž| ŮþþŮ| ŷ޹Ʒþþþ| þþƷAV| ޹㽶ˬAVƬþ| Ʒþþþþþö| ҹƷþ| Ůaaaþþü| 99þۺϺݺۺϾþ| þþĻձ| ҹҹݺݾþö |