新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 C/C++编程思想 』 → VC++动态链接库(DLL)编程深入浅出(连载) 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 20979 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: VC++动态链接库(DLL)编程深入浅出(连载) 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客11
    发贴心情 

    5.3 一个简单的MFC规则DLL
      这个DLL的例子(属于静态链接到MFC 的规则DLL)中提供了一个如图11所示的对话框。

    按此在新窗口浏览图片
      图11 MFC规则DLL例子

      在DLL中添加对话框的方式与在MFC应用程序中是一样的。

      在图11所示DLL中的对话框的Hello按钮上点击时将MessageBox一个“Hello,pconline的网友”对话框,下面是相关的文件及源代码,其中删除了MFC向导自动生成的绝大多数注释(下载本工程[URL=http://file.ddvip.com/2007_03/1173954594_ddvip_9149.zip]附件[/URL]):

      第一组文件:CWinApp继承类的声明与实现

    // 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;
      分析:

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/9/15 10:11:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客12
    发贴心情 
    在这一组文件中定义了一个继承自CWinApp的类CRegularDllApp,并同时定义了其的一个实例theApp。乍一看,您会以为它是一个MFC应用程序,因为MFC应用程序也包含这样的在工程名后添加“App”组成类名的类(并继承自CWinApp类),也定义了这个类的一个全局实例theApp。

      我们知道,在MFC应用程序中CWinApp取代了SDK程序中WinMain的地位,SDK程序WinMain所完成的工作由CWinApp的三个函数完成:

    virtual BOOL InitApplication( );
    virtual BOOL InitInstance( );
    virtual BOOL Run( ); //传说中MFC程序的“活水源头”
      但是MFC规则DLL并不是MFC应用程序,它所继承自CWinApp的类不包含消息循环。这是因为,MFC规则DLL不包含CWinApp::Run机制,主消息泵仍然由应用程序拥有。如果DLL 生成无模式对话框或有自己的主框架窗口,则应用程序的主消息泵必须调用从DLL 导出的函数来调用PreTranslateMessage成员函数。

      另外,MFC规则DLL与MFC 应用程序中一样,需要将所有 DLL中元素的初始化放到InitInstance 成员函数中。

      第二组文件 自定义对话框类声明及实现(点击查看附件)

      分析:

      这一部分的编程与一般的应用程序根本没有什么不同,我们照样可以利用MFC类向导来自动为对话框上的控件添加事件。MFC类向导照样会生成类似ON_BN_CLICKED(IDC_HELLO_BUTTON, OnHelloButton)的消息映射宏。

      第三组文件 DLL中的资源文件

    //{{NO_DEPENDENCIES}}
    // Microsoft Developer Studio generated include file.
    // Used by RegularDll.rc
    //
    #define IDD_DLL_DIALOG 1000
    #define IDC_HELLO_BUTTON 1000
      分析:

      在MFC规则DLL中使用资源也与在MFC应用程序中使用资源没有什么不同,我们照样可以用Visual C++的资源编辑工具进行资源的添加、删除和属性的更改。

      第四组文件 MFC规则DLL接口函数

    #include "StdAfx.h"
    #include "DllDialog.h"
    extern "C" __declspec(dllexport) void ShowDlg(void)
    {
    CDllDialog dllDialog;
    dllDialog.DoModal();
    }
      分析:

      这个接口并不使用MFC,但是在其中却可以调用MFC扩展类CdllDialog的函数,这体现了“规则”的概类。

      与非MFC DLL完全相同,我们可以使用__declspec(dllexport)声明或在.def中引出的方式导出MFC规则DLL中的接口。

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/9/15 10:12:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客13
    发贴心情 
    VC++动态链接库(DLL)编程深入浅出(四)
    这是《VC++动态链接库(DLL)编程深入浅出》的第四部分,阅读本文前,请先阅读前三部分:(一)、(二)、(三)。

      MFC扩展DLL的内涵为MFC的扩展,用户使用MFC扩展DLL就像使用MFC本身的DLL一样。除了可以在MFC扩展DLL的内部使用MFC以外,MFC扩展DLL与应用程序的接口部分也可以是MFC。我们一般使用MFC扩展DLL来包含一些MFC的增强功能,譬如扩展MFC的CStatic、CButton等类使之具备更强大的能力。

      使用Visual C++向导生产MFC扩展DLL时,MFC向导会自动增加DLL的入口函数DllMain:

    extern "C" int APIENTRY
    DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
    {
    // Remove this if you use lpReserved
    UNREFERENCED_PARAMETER(lpReserved);
    if (dwReason == DLL_PROCESS_ATTACH)
    {
      TRACE0("MFCEXPENDDLL.DLL Initializing! ");
      // Extension DLL one-time initialization
      if (!AfxInitExtensionModule(MfcexpenddllDLL, hInstance))
      return 0;
      // Insert this DLL into the resource chain
      // NOTE: If this Extension DLL is being implicitly linked to by
      // an MFC Regular DLL (such as an ActiveX Control)
      // instead of an MFC application, then you will want to
      // remove this line from DllMain and put it in a separate
      // function exported from this Extension DLL. The Regular DLL
      // that uses this Extension DLL should then explicitly call that
      // function to initialize this Extension DLL. Otherwise,
      // the CDynLinkLibrary object will not be attached to the
      // Regular DLL's resource chain, and serious problems will
      // result.
      new CDynLinkLibrary(MfcexpenddllDLL);
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {
      TRACE0("MFCEXPENDDLL.DLL Terminating! ");
      // Terminate the library before destructors are called
      AfxTermExtensionModule(MfcexpenddllDLL);
    }
    return 1;  // ok
    }
      上述代码完成MFC扩展DLL的初始化和终止处理。

      由于MFC扩展DLL导出函数和变量的方式与其它DLL没有什么区别,我们不再细致讲解。下面直接给出一个MFC扩展DLL的创建及在应用程序中调用它的例子。

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/9/15 10:13:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客14
    发贴心情 
    6.1 MFC扩展DLL的创建

      下面我们将在MFC扩展DLL中导出一个按钮类CSXButton(扩展自MFC的CButton类),类CSXButton是一个用以取代 CButton的类,它使你能在同一个按钮上显示位图和文字,而MFC的按钮仅可显示二者之一。类CSXbutton的源代码在Internet上广泛流传,有很好的“群众基础”,因此用这个类来讲解MFC扩展DLL有其特殊的功效。

      MFC中包含一些宏,这些宏在DLL和调用DLL的应用程序中被以不同的方式展开,这使得在DLL和应用程序中,使用统一的一个宏就可以表示出输出和输入的不同意思:

    // for data
    #ifndef AFX_DATA_EXPORT
    #define AFX_DATA_EXPORT __declspec(dllexport)
    #endif
    #ifndef AFX_DATA_IMPORT
    #define AFX_DATA_IMPORT __declspec(dllimport)
    #endif
    // for classes
    #ifndef AFX_CLASS_EXPORT
    #define AFX_CLASS_EXPORT __declspec(dllexport)
    #endif
    #ifndef AFX_CLASS_IMPORT
    #define AFX_CLASS_IMPORT __declspec(dllimport)
    #endif
    // for global APIs
    #ifndef AFX_API_EXPORT
    #define AFX_API_EXPORT __declspec(dllexport)
    #endif
    #ifndef AFX_API_IMPORT
    #define AFX_API_IMPORT __declspec(dllimport)
    #endif
    #ifndef AFX_EXT_DATA
    #ifdef _AFXEXT
      #define AFX_EXT_CLASS    AFX_CLASS_EXPORT
      #define AFX_EXT_API     AFX_API_EXPORT
      #define AFX_EXT_DATA    AFX_DATA_EXPORT
      #define AFX_EXT_DATADEF
    #else
      #define AFX_EXT_CLASS    AFX_CLASS_IMPORT
      #define AFX_EXT_API     AFX_API_IMPORT
      #define AFX_EXT_DATA    AFX_DATA_IMPORT
      #define AFX_EXT_DATADEF
    #endif
    #endif
      导出一个类,直接在类声明头文件中使用AFX_EXT_CLASS即可,以下是导出CSXButton类的例子:

    #ifndef _SXBUTTON_H
    #define _SXBUTTON_H
    #defineSXBUTTON_CENTER-1
    class AFX_EXT_CLASS CSXButton : public CButton
    {
    // Construction
    public:
    CSXButton();
    // Attributes
    private:
    //Positioning
    BOOL m_bUseOffset;  
    CPoint m_pointImage;
    CPoint m_pointText;
    int m_nImageOffsetFromBorder;
    int m_nTextOffsetFromImage;
    //Image
    HICON m_hIcon;  
    HBITMAP m_hBitmap;
    HBITMAP m_hBitmapDisabled;
    int m_nImageWidth, m_nImageHeight;
    //Color Tab
    char m_bColorTab;  
    COLORREFm_crColorTab;
    //State
    BOOL m_bDefault;
    UINT m_nOldAction;
    UINT m_nOldState;
    // Operations
    public:
    //Positioning
    int SetImageOffset( int nPixels );
    int SetTextOffset( int nPixels );
    CPointSetImagePos( CPoint p );
    CPointSetTextPos( CPoint p );
    //Image
    BOOLSetIcon( UINT nID, int nWidth, int nHeight );
    BOOLSetBitmap( UINT nID, int nWidth, int nHeight );
    BOOLSetMaskedBitmap( UINT nID, int nWidth, int nHeight, COLORREF crTransparentMask );
    BOOLHasImage() { return (BOOL)( m_hIcon != 0 | m_hBitmap != 0 ); }
    //Color Tab
    voidSetColorTab(COLORREF crTab);
    //State
    BOOLSetDefaultButton( BOOL bState = TRUE );
    private:
    BOOLSetBitmapCommon( UINT nID, int nWidth, int nHeight, COLORREF crTransparentMask, BOOL bUseMask );
    voidCheckPointForCentering( CPoint &p, int nWidth, int nHeight );
    voidRedraw();
    // Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CSXButton)
    public:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    //}}AFX_VIRTUAL
    // Implementation
    public:
    virtual ~CSXButton();
    // Generated message map functions
    protected:
    //{{AFX_MSG(CSXButton)
    afx_msg LRESULT OnGetText(WPARAM wParam, LPARAM lParam);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
    };
    #endif
      把SXBUTTON.CPP文件直接添加到工程,编译工程,得到“mfcexpenddll.lib”和“mfcexpenddll.dll”两个文件。我们用Visual Studio自带的Depends工具可以查看这个.dll,发现其导出了众多符号(见图15)。

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/9/15 10:14:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客15
    发贴心情 

      图15 导出类时导出的大量符号 (+放大该图片)

      这些都是类的构造函数、析构函数及其它成员函数和变量经编译器处理过的符号,我们直接用__declspec(dllexport)语句声明类就导出了这些符号。

      如果我们想用.lib文件导出这些符号,是非常困难的,我们需要在工程中生成.map文件,查询.map文件的符号,然后将其一一导出。如图16,打开DLL工程的settings选项,再选择Link,勾选其中的产生MAP文件(Generate mapfile)就可以产生.map文件了。

      打开mfcexpenddll工程生成的.map文件,我们发现其中包含了图15中所示的符号(symbol)

    0001:00000380 ?HasImage@CSXButton@@QAEHXZ 10001380 f i SXBUTTON.OBJ
    0001:000003d0 ??0CSXButton@@QAE@XZ    100013d0 f  SXBUTTON.OBJ
    0001:00000500 ??_GCSXButton@@UAEPAXI@Z  10001500 f i SXBUTTON.OBJ
    0001:00000570 ??_ECSXButton@@UAEPAXI@Z  10001570 f i SXBUTTON.OBJ
    0001:00000630 ??1CSXButton@@UAE@XZ    10001630 f  SXBUTTON.OBJ
    0001:00000700 ?_GetBaseMessageMap@CSXButton@@KGPBUAFX_MSGMAP@@XZ 10001700 f  SXBUTTON.OBJ
    0001:00000730 ?GetMessageMap@CSXButton@@MBEPBUAFX_MSGMAP@@XZ 10001730 f  SXBUTTON.OBJ
    0001:00000770  ?Redraw@CSXButton@@AAEXXZ 10001770 f i SXBUTTON.OBJ
    0001:000007d0  ?SetIcon@CSXButton@@QAEHIHH@Z 100017d0 f  SXBUTTON.OBJ
    ……………………………………………………………………..//省略
      图16 产生.map文件 (+放大该图片)

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/9/15 10:14:00
     
     poor_love 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:0
      积分:54
      门派:XML.ORG.CN
      注册:2007/10/11

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给poor_love发送一个短消息 把poor_love加入好友 查看poor_love的个人资料 搜索poor_love在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看poor_love的博客16
    发贴心情 
    高手,呵呵,佩服中
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/10/11 11:33:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2025/2/26 10:24:19

    本主题贴数16,分页: [1] [2]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    125.000ms