• 在DLL中产生对话框的方法一(Win32 DLL)


    什么是Dll?

         Stands for "Dynamic Link Library." A DLL (.dll) file contains a library of functions and other information that can be accessed by a Windows program. When a program is launched, links to the necessary .dll files are created. If a static link is created, the .dll files will be in use as long as the program is active. If a dynamic link is created, the .dll files will only be used when needed. Dynamic links help programs use resources, such as memory and hard drive space, more efficiently.

    对话框:
          对话框可以分为modal和modeless两种。
     
    在Win32 Dll中创建modal对话框。
           在一个Win32Dll中创建modal对话框非常简单,我们都知道,Win32函数DialogBox能够创建一个modal对话框,并且modal对话框的消息是独立于主程序消息循环的,所以可以直接在Dll内部建立对话框自己的窗口过程。下面就是一个在Win32 Dll中创建modal对话框的示例:
    //name: Modal_Dialog.cpp
    #include<windows.h>
    #include"resource.h"
    BOOL CALLBACK DlgProc(HWND hwnd,UINT Msg,WPARAM wParam,LPARAM lParam)
     {
         switch(Msg)
         {
         case WM_INITDIALOG:
             return TRUE;
     
         case WM_COMMAND:
             switch(wParam)
             {
             case IDOK:
                  MessageBox(NULL,"这是一个modal对话框的例子","提示",MB_OK);       
                  EndDialog(hwnd, 0);
                  return TRUE;
             }
             break;
         }
     
         return FALSE;
     }
     
    extern"C" __declspec(dllexport) void ShowDialog()
    {
         HINSTANCE hinst;
         hinst=LoadLibrary("Modal_Dialog.dll");     //获取库所在的实例句柄
         DialogBox(hinst,MAKEINTRESOURCE(IDD_DIALOG1),NULL,DlgProc);
         FreeLibrary(hinst);
    }
    //name: Test.cpp
    ……
         typedef void (*fp)();
         HINSTANCE hDll;
         fp Show;
         hDll = LoadLibrary("Modal_Dialog.dll");
         Show = (fp)GetProcAddress(hDll,"ShowDialog");
         (*Show)();
         FreeLibrary(hDll);
    ……
    在Win32 Dll 中创建modeless对话框。
           与modal对话框不同,modeless对话框的消息是要经过主程序消息循环的,这样一来,就必须在调用该Dll的主程序中处理对话框的消息循环,这就无法达到利用Dll来完成组件化开发的要求。其实我们可以人为的Modeless对话框创建一个窗口类,我们知道窗口过程是属于窗口类的,这样一来就有了主窗口的消息循环。
    //name: Modeless_Dialog.cpp
    #include <windows.h>
    #include"resource.h"
    LRESULT CALLBACK WndProc     (HWND, UINT, WPARAM, LPARAM) ;
    BOOL    CALLBACK DlgProc (HWND, UINT, WPARAM, LPARAM) ;
     
    extern"C" int __declspec(dllexport) ShowDialog()
    {
         static TCHAR szAppName[] = TEXT ("Modeless_Dialog") ;
         HWND         hwnd ;
         MSG          msg ;
         WNDCLASS     wndclass ;
          HINSTANCE hInstance;
          HWND hDialog;
     
        hInstance = LoadLibrary("Modeless_Dialog.dll");
        
     
          wndclass.style         = CS_HREDRAW | CS_VREDRAW;
         wndclass.lpfnWndProc   = WndProc ;
         wndclass.cbClsExtra    = 0 ;
         wndclass.cbWndExtra    = DLGWINDOWEXTRA ;    // Note!
         wndclass.hInstance     = hInstance ;
         wndclass.hIcon         = LoadIcon (hInstance, szAppName) ;
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
         wndclass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1) ;
         wndclass.lpszMenuName = NULL ;
         wndclass.lpszClassName = szAppName ;
         hwnd = CreateWindow (szAppName, TEXT ("Modeless_Dialog"),
                              WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              NULL, NULL, hInstance, NULL) ;
        
        // ShowWindow (hwnd, iCmdShow) ;       //并不在这里显示主窗口
        // UpdateWindow (hwnd) ;  
    hDialog = CreateDialog (hInstance, MAKEINTRESOURCE(IDD_DIALOG1), hwnd, DlgProc) ;
        
         while (GetMessage (&msg, NULL, 0, 0))
         {
              if(hDialog==0||!IsDialogMessage(hDialog,&msg))
              {
              TranslateMessage (&msg) ;
              DispatchMessage (&msg) ;
              }
         }
         return msg.wParam ;
     
    }
    BOOL CALLBACK DlgProc (HWND hDlg, UINT message,
                               WPARAM wParam, LPARAM lParam)
    {
         switch(message)
         {
             case WM_INITDIALOG :
                  return true;
             case WM_COMMAND:
                  switch(wParam)
                  {
                  case(IDOK):
                       MessageBox(NULL,"这是一个modeless对话框的例子","提示",MB_OK);
                       DestroyWindow(hDlg);
                       PostQuitMessage (0) ;
                       return TRUE;
                  }
         }
         return FALSE;
    }
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {   
         switch (message)
         { 
         case WM_DESTROY:
              PostQuitMessage (0) ;
              return 0 ;
         }
         return DefWindowProc (hwnd, message, wParam, lParam) ;
    }
          CreateDialog用来创建窗口,并且对话框模板要指定visible属性为True,只有这样才能显示对话框.
           if(hDialog==0||!IsDialogMessage(hDialog,&msg))这一句是起消息分流作用的,对于属于对话框的消息一律交给对话框过程DlgProc来处理。
            处理对话框的退出一定要使用DetroyWindow函数,并且要发送一个退出消息,使那个没有显示的主窗口也能够退出消息循环,不至于造成内存泄露。 
    在MFC Regular Dll 中创建modal对话框
        在MFC Regular Dll中创建modal对话框非常简单,Cdialog基类提供有一个方法DoModal(),能够创建一个modal对话框,因此在MFC Regular Dll中创建modal对话框,仅仅需要自己继承对话框基类,在导出函数中调用DoModal就可以了.
      在MFC Regular Dll 中创建modeless对话框.
        因为MFC应用程序框架仅仅是对Win32函数的封装,所以在MFC Regular Dll中创建modeless对话框其实与在DLL中产生对话框的方法一(Win32 DLL)介绍的产生modeless对话框的内部原理是一致的,差别仅仅是在MFC框架中还需要一点小技巧。
        我们知道在Win32 SDK编程中,有一个主窗口句柄hwnd,同样在MFC中,也有这样一个变量,只不过它现在被封装进了CwindThread中,我们可以在AFXWIN.H中看到这样的定义:
    ……
    CWnd* m_pMainWnd;   // main window (usually same AfxGetApp()->m_pMainWnd)
    ……
    并且我们知道CWinApp是继承于CWinThread的。
        我们再来看窗口过程的封装,在MFC中,CFrameWnd类别可以用来创建窗口,并在内部定义了窗口过程,具体地说,就是CreateWindow,MessageLoop这样的机制都是在该类别中实现的。
        有了上面地基础,再来看在DLL中产生对话框的方法一(Win32 DLL)这篇文章中产生modeless对话框的步骤:
    1:我们首先建立了一个主视窗,但是并不显示该视窗,我们真正需要的是窗口句柄hwnd.
    2: 建立对话框,将该对话框的owner句柄设置为hwnd。
    3:进行消息分流。
        在上面步骤后面其实隐藏了一个技巧在里面:我们可以抛弃hwnd,也就是说我们可以将对话框的句柄设置为hwnd,这样我们就可以省略第三步,不用在消息循环的地方做消息分流,
    那么我们的代码看上去是这个样子
    ……
         hwnd = CreateWindow (szAppName, TEXT ("Modeless_Dialog"),
                              WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              NULL, NULL, hInstance, NULL) ;
        
        // ShowWindow (hwnd, iCmdShow) ;       //并不在这里显示主窗口
        // UpdateWindow (hwnd) ;  
    hwnd = CreateDialog (hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc) ;
        
         while (GetMessage (&msg, NULL, 0, 0))
         {
              TranslateMessage (&msg) ;
              DispatchMessage (&msg) ;
         }
    ……
        OK这下我们可以按照上面的步骤来在MFC Regular DLL中产生对话框了
    1:利用AppWizard建立一个MFC Regular DLL.
    2: 从CFrameWnd派生出一个新的类CmyFrameWnd类,因为我们仅仅是需要产生一个不显示的窗口,所以一切动作采用默认的操作就可以了。
    class CMyFrame:public CFrameWnd
    {
    public:
        CMyFrame();
    DECLARE_MESSAGE_MAP()
    };
    3:从CDialog派生一个新的CMyDialog类。
    4:因为CWinApp的InitInstance()是用来对应用程序进行初始化动作的。所以我们在CMyWinApp的InitInstance方法中加入如下代码:
        m_pMainWnd = new CMyFrame();
        m_pMainWnd = pDlg;   //pDlg是一个指向CmyDialg对象的指针。
    5:写导出函数:
    extern"C" void __declspec(dllexport) Show()
    {
        pDlg->DoModal(); //显示对话框
    }
        从以上的步骤我们可以看出,在MFC Regular DLL中显示modeless对话框的方法还是遵从了Win32 DLL中的方法,当然因为MFC的面向对象的特性,只要遵从这种方法,我们可以有更多的办法实现,只是这里介绍的应该是最简单的也是最直接的方式。
    前面讲了MFC Regular Dll中产生对话框的方法,还有一种MFC Extention Dll,但是因为他本身有很多限制,已经有被淘汰的趋势,所以最好采用Win32 Dll或者MFC Regular Dll,当然最简单的方法还是接下来的C# Dll,因为所有的一切都已经被封装到.net framework中了,什么窗口过程,什么句柄,消息循环等等都不用我们操心了,唯一的缺点是需要在目标机器上装有.net FrameWork下面来看一下具体步骤:
    1: 在C#中新建一个class library。
    2: 新建一个form类(C#中,一切都是对象,所以直接添加一个窗体就行了)
    3: 在新建的class中添加一个method
    3: 调用form类的相关方法:
    //产生modal对话框的代码
    Form1 myModalDialog = new Form1();
    myModalDialog.ShowDialog();
    //产生modeless对话框的代码
    Form1 myModelessDialog =new Form1();
    myModelessDialog.Show();
    //使用也及其方便
    Modal_Dialog.CMyDialog test = new Modal_Dialog.CMyDialog();
    test.ShowModalDialog();
    test.ShowModelessDialog();
        当然除了上面的直接引用以外,也可以通过程序集(Assembly)的LoadFrom来加载.
  • 相关阅读:
    C#后台去除字符串最后一个字符
    C#后台验证含0的正整数
    jQuery提交表单的几种方式
    C#后台获取当前时间并格式化
    获取EasyUI日期输入框的值
    jQuery将字符串转换为数字
    JQ和JS获取span标签的内容
    正则
    json 拖拽
    event事件对象
  • 原文地址:https://www.cnblogs.com/chenbg2001/p/1373766.html
Copyright © 2020-2023  润新知