敬业的IT人 >> 编程开发 >> Visual C++/MFC >> 用DLL为应用程序预留待扩展功能接口

用DLL为应用程序预留待扩展功能接口

敬业的IT人 互联网 佚名 2008-1-4 18:59:36
动态链接函数库(Dynamic Link Library 简称DLL)是组成Windows系统的重要元素之一。Windows将构成其系统的大部分程序代码、数据以及经常用到的资源,以动态链接函数库(二进制文件)的形式存贮在磁盘里。本文主要介绍如何在应用程序中预留待扩展功能接口,以及利用DLL编写这类扩展功能代码的方法。

应用实例
  在开发应用程序的时候考虑到以后可能要添加某些新的功能,为避免修改源程序所带来的麻烦,我们可以在开发应用程序的过程中先预留一个扩展功能接口,以后需要扩展功能时,只要把扩展功能部分的代码单独编译成DLL即可。下面是一个示例程序,该示例程序分为应用程序和扩展功能两部分,当应用程序收到WM_CREATE消息时,检查是否有扩展功能,若有则装入;否则返回。该程序在Windows 95下,用Borland c 4.5调试通过。

  /*------PRAC.C 应用程序部分------*/

  #include <windows.h>

  #include "prac.h"

  int PASCAL WinMain(HANDLE, HANDLE, LPSTR, int);

  long FAR PASCAL MainWndProc(HWND, WORD, WORD, LONG);

  void MsgFilter(HWND , WPARAM );

  FARPROC LpExtProc ;

  /*------- WinMain() -------*/

  int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,

             LPSTR lpszCmdLine, int nCmdShow)

  {

   MSG   msg;

   HWND   hWnd;

   WNDCLASS wndclass;

   if ( ! hPrevInstance )

     {

      wndclass.style = CS_HREDRAW | CS_VREDRAW;

      wndclass.lpfnWndProc = MainWndProc;

      wndclass.cbClsExtra = 0;

      wndclass.cbWndExtra = 0;

      wndclass.hInstance = hInstance;

      wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);

      wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);

      wndclass.hbrBackground = GetStockObject (WHITE_BRUSH);

      wndclass.lpszMenuName = "OurOwnMenu"; //装入应用程序菜单

      wndclass.lpszClassName = "Application";

      if ( ! RegisterClass (&wndclass) )

       return FALSE;

     }

   hWnd = CreateWindow ( "Extend Function" ,

              "应用程序示例",

              WS_OVERLAPPEDWINDOW,

              CW_USEDEFAULT,

              CW_USEDEFAULT,

              CW_USEDEFAULT,

              CW_USEDEFAULT,

              NULL,

              NULL,

              hInstance,

              NULL);

   If (!hWnd )

     return FALSE;

   ShowWindow (hWnd, nCmdShow);

   UpdateWindow (hWnd);

   while ( GetMessage (&msg, NULL, 0, 0) )

     {

      TranslateMessage (&msg);

      DispatchMessage (&msg);

     }

   return msg.wParam;

  }

  /*---------- 主窗口函数 WndProc()-------------*/

  long FAR PASCAL MainWndProc(HWND hWnd, WORD message,

                    WORD wParam, LONG lParam)

  {

   static HANDLE hLibrary;

   char szBuf[80];

   switch(message)

   {

     case WM_CREATE:

     /*读应用程序的初始化文件prac.ini,检查是否有扩展功能的动态链接库,若没有则返回;若有则装入该动态链接函接数库,并取得接口函数的地址,对接口函数进行初始化*/

       GetPrivateProfileString("MyApp" , "AddMyapp" , "" ,

                 szBuf,sizeof(szBuf) , "prac.ini");

       if (szBuf[0] != '\0')

       if ((hLibrary = LoadLibrary(szBuf)) >= 32)

        {

         LpExtProc=(FARPROC)GetProcAddress(hLibrary,

                  MAKEINTRESOURCE(2));

         LpExtProc(hWnd , EXTPROC_LOAD);

        }

       else

        MessageBox(hWnd,"Load library failed!","Error",MB_OK);

       break;

     case WM_COMMAND:

       /*函数MsgFilter( )用来过滤菜单消息*/

       MsgFilter(hWnd , wParam);

       switch (wParam)

       {

         case IDM_COMMAND1: //处理应用程序

         case IDM_COMMAND2: //定义的菜单功

         case IDM_COMMAND3: //能,此处省略。

       }

       return 0;

     case WM_DESTROY:

       if(hLibrary != NULL)

       FreeLibrary(hLibrary);

       PostQuitMessage(0);

       break;

   }

   return DefWindowProc(hWnd, message, wParam, lParam);

  }

/*下面过滤函数,把菜单消息的来源分成两类,即应用程序本身的菜单消息和来自功能扩展部分的菜单消息。应用程序把值在MIN_FMT至MAX_FMT之间的菜单消息留给待扩展程序使用。如果有来自扩展程序的消息,就通过接口函数LpExtProc()把该消息传送给扩展程序,由扩展程序负责处理该消息*/

  void MsgFilter(HWND hWnd , WPARAM wParam)

  {

   if((wParam >= MIN_FMT)&&(wParam <= MAX_FMT))

    LpExtProc(hWnd , wParam);

   return;

  }

  /*---------------- End of PRAC.C-----------------*/

  /*----------- PRAC.H ----------*/

  #define MIN_FMT       100

  #define MAX_FMT      199

  #define EXTPROC_LOAD   200

  #define IDM_COMMAND1   201

  #define IDM_COMMAND2   202

  #define IDM_COMMAND3   203

  /*---End of PRAC.H ---*/

  ; 应用程序的模块定义文件PRAC.DEF

  NAME     PRAC

  DESCRIPTION  'demonstrate a different system menu'

  EXETYPE    WINDOWS

  STUB      'WINSTUB.EXE'

  CODE      PRELOAD MOVEABLE DISCARDABLE

  DATA     PRELOAD MOVEABLE MULTIPLE

  HEAPSIZE   1024

  STACKSIZE   8192

  EXPORTS    MainWndProc

  ; End of PRAC.DEF

  /*---资源定义文件PRAC.RC---*/

  #include "prac.h"

  OurOwnMenu MENU

  BEGIN

   MENUITEM "Command&1",   IDM_COMMAND1

   MENUITEM "Command&2",   IDM_COMMAND2

   MENUITEM "Command&3",   IDM_COMMAND3

  END

  /*---End of PRAC.RC---*/

  若要扩展上面应用程序的功能,在不改动上述程序的情况下,只需将功能扩展部分的代码编写成动态链接函数库,编译成.DLL文件,并在PRAC.INI文件中加入下面语句,即可达到扩展功能的目的。在PRAC.INI中加入:

  [AddApp]

  AddMyapp=c:\win95\system\extproc.dll

  扩展功能的动态链接函数库代码如下:

  /*-----EXTPROC_DLL.c-----*/

  #include <windows.h>

  #include <commdlg.h>

  #include "extproc_dll.h"

  HMENU hMenu , hExtMenu;

  HWND hWndExt = NULL;

  int FAR PASCAL LibMain(HANDLE hModule , WORD wDataSeg,

              WORD HeapSize , LPSTR lpszCmdLine)

  {

   if(HeapSize != 0)

    UnlockData(0);

   return 1;

  }

  int FAR PASCAL WEP(int SystemExit)

  {

   switch (SystemExit)

    {

     case WEP_SYSTEM_EXIT:

                 return 1;

     case WEP_FREE_DLL:

                 return 1;

     default:

         return 1;

    }

  }

  /*函数FMExtensionProc()即为扩展功能的处理函数,当过滤函数检索到有来自扩展功能的菜单消息时,就调用该函数进行处理。在此仅以设置打印机、选择字体来说明扩展功能的处理过程,读者可根据自己的需要修改*/

  void FAR PASCAL FMExtensionProc(HWND hWndFMExt , WORD wMessage)

  {

   PRINTDLG  pd;

   CHOOSEFONT fnt;

   LOGFONT lf;

   CHOOSECOLOR chclr;

   DWORD dwColor;

   DWORD dwCustClrs[16];

   int i;

   switch(wMessage)

     {

     /*处理FMEVENT_LOAD消息,加载用户扩展功能菜单FMExtMenu*/

      case EXTPROC_LOAD:

         hExtMenu = LoadMenu(FMExtInst,"FMExtMenu");

         hMenu = GetMenu(hWndFMExt);

         AppendMenu(hMenu,MF_POPUP,hExtMenu ,"扩展功能(&E)");

         SetMenu(hWndFMExt,hMenu);

         break;

     /*下面是用户可自定义的扩展功能代码*/

      case IDM_PRINTERSETUP: //设置打印机

        pd.lStructSize = sizeof(PRINTDLG);

        pd.hwndOwner = hWndFMExt;

        pd.hDevMode  = NULL;

        pd.hDevNames = NULL;

        pd.Flags = PD_RETURNDC|PD_SELECTION|PD_PRINTSETUP;

        pd.nCopies   = 1;

        PrintDlg((LPPRINTDLG)&pd);

        break;

      case IDM_SELECTFONT: //选择字体

        fnt.lStructSize = sizeof(CHOOSEFONT);

        fnt.hwndOwner = hWndFMExt;

        fnt.hDC     = NULL;

        fnt.lpLogFont = &lf;

        fnt.Flags   = CF_SCREENFONTS|CF_EFFECTS;

        fnt.rgbColors = RGB(0,255,255);

        fnt.lCustData = 0L;

        fnt.nFontType = SCREEN_FONTTYPE;

        fnt.nSizeMin  = 0;

        fnt.nSizeMax  = 0;

        ChooseFont(&fnt);

        break;

     }

   return;

  }

  /*------------End of EXTPROC_DLL.C------------*/

  /*----- EXTPROC_DLL.H -----*/

  #define IDM_PRINTERSETUP 101

  #define IDM_SELECTFONT  102

  #define EXTPROC_LOAD   200

  void FAR PASCAL _export FMExtensionProc(HWND,WORD);

  /*-----End of EXTPROC_DLL.H -----*/

  ;资源文件EXTPROC_dll.RC

  #include "windows.h"

  #include "extproc_dll.h"

  FMExtMenu MENU DISCARDABLE

  BEGIN

   MENUITEM "Printer&Setup" ,IDM_PRINTERSETUP

   MENUITEM "Select&Font"  ,IDM_SELECTFONT

  END

  ;End of EXTPROC_DLL.RC

  ;模块定义文件EXTPROC_DLL.DEF

  LIBRARY EXTPROC

  DESCRIPTION 'File Manager Extension DLL'

  EXETYPE WINDOWS

  CODE PRELOAD MOVEABLE DISCARDABLE

  DATA PRELOAD SINGLE SHARED

  HEAPSIZE 1024

  EXPORTS

   WEP @1 RESIDENTNAME

   FMExtensionProc @2

  ;End of EXTPROC_DLL.DEF

粤ICP备06119539号
Copyright CiscoSky.Org,Some Rights Reserved.
Email:me1228#tom.com