<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    MFC的dll中控制資源問題

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    有程序EXE和DLL,其中DLL中有1個函數用來顯示對話框,被EXE調用。
    當EXE和DLL都為Release或Debug時,沒有任何問題,但EXE為Release、
    DLL為Debug時,就會出錯。該DLL是用VC提供的MFC Extension DLL,
    函數的代碼如下:
    HINSTANCE hInstOld = AfxGetResourceHandle(); // 該句出錯
    HINSTANCE hInstNew = GetModuleHandle("T01Test.dll");
    AfxSetResourceHandle(hInstNew);

    CHahaDlg dlg;
    dlg.DoModal();

    AfxSetResourceHandle(hInstOld);

     

     

    長久以來,把界面的信息單獨存為一個DLL一直是很多商業軟件的作法,比如VC、InstallShield等等,這樣做的好處是,如果要做多語言版本,只要寫出不同的DLL來,在主程序中使用時調用不同的DLL就行,當然現在還有一種流行的方法是使用INI,讀存也非常方便。最近在網上轉了轉,發現竟沒有一篇關于如何讀取DLL中資源的文章,雖然Iczelion的Win32ASM教程中第26課"Splash Screen"講到了讀取DLL中的圖片,但不知是這種問題太簡單了還是其它什么原因,Iczelion沒有講解這段代碼的意思,于是乎決定寫一篇關于DLL資源讀取的文章,望大家不要$%@%@^%@%。
    我們看一下這些函數:
    HBITMAP LoadBitmap(HINSTANCE hInstance,LPCTSTR lpBitmapName)
    HICON LoadIcon(HINSTANCE hInstance,LPCTSTR lpIconName)
    HMENU LoadMenu(HINSTANCE hInstance,LPCTSTR lpMenuName)
    int LoadString(HINSTANCE hInstance,UINT uID,LPTSTR lpBuffer,int BufferMax)

    int DialogBoxParam(
    HINSTANCE hInstance, // handle to application instance
    LPCTSTR lpTemplateName, // identifies dialog box template
    HWND hWndParent, // handle to owner window
    DLGPROC lpDialogFunc, // pointer to dialog box procedure 
    LPARAM dwInitParam // initialization value
    );

    HWND CreateDialogParam(
    HINSTANCE hInstance, // handle to application instance
    LPCTSTR lpTemplateName, // identifies dialog box template
    HWND hWndParent, // handle to owner window
    DLGPROC lpDialogFunc, // pointer to dialog box procedure 
    LPARAM dwInitParam // initialization value
    );
    這些都是常用的讀取資源的函數,它們都有一個共同點:第一個參數需要的是要讀取的包含資源的程序的模塊句柄,那么,關鍵就在這個句柄,因為我們在讀取本身程序資源的時候,肯定是提供用GetModuleHandle函數獲得的句柄,這個句柄就是當前程序的實例句柄,如果要讀取DLL中的資源,很顯然的,我們需要提供DLL的句柄,那么這個DLL句柄怎么得到呢?很簡單,我們在使用LoadLibrary函數時,返回的值就是讀取的DLL的句柄,于是,我們讀取DLL中的資源,只需要這樣:
    invoke LoadLibrary,DLL_FILENAME
    mov DLL_HANDLE,eax
    invoke LoadBitmap,DLL_HANDLE,BITMAP_ID
    invoke LoadIcon,DLL_HANDLE,ICON_ID
    invoke LoadMenu,DLL_HANDLE,MENU_ID
    invoke LoadString,DLL_HANDLE,STRING_ID,StrBuffer,sizeof StrBuffer
    invoke DialogBoxParam,DLL_HANDLE,DLG_NAME,hParent,DlgProc,lParam
    其它的函數就不多說,著重講一下DialogBoxParam與CreateDialogParam,因為其它函數不需要回調函數,讀取之后句柄可以一直到程序結束才釋放。我們討論的就是DialogBoxParam與CreateDialogParam回調函數的方法。
    我曾上過當,把DialogBoxParam與CreateDialogParam的回調函數寫在主程序中,相信有很多的朋友也是寫在主程序中,然后直接把回調過程地址傳給DialogBoxParam與CreateDialogParam,其實,這是一種錯誤的方法,正確的方法是,我們必須把回調函數寫在對話框資源本身的DLL中,在主程序用DialogBoxParam與CreateDialogParam顯示對話框時提供DLL中的回調函數地址,當然,對純提供資源的DLL,它們不同的只是界面語言文字,這個把回調函數寫在主程序中更加好,如果是插件呢?如果主程序使用了很多的DLL呢?對于插件而言,回調函數是必須在DLL中的,主程序使用很多DLL時,把回調函數都寫在主程序中,就算能正常運行,但是DLL有變動,就算是一個小修改,也不得不重新更改主程序,所以,我的建議是:除了純資源DLL,編寫DLL時,對話框的回調函數一定要寫在DLL本身中。
    可是,如果在主程序中就這樣子使用DLL對話框,那么,DLL對話框的回調函數就必須引出,這樣主程序才能獲得回調函數地址,就像這樣:
    invoke GetProcAddress,DLL_HANDLE,DlgProcName
    invoke DialogBoxParam,DLL_HANDLE,DLG_NAME,hWnd,eax,NULL
    ;DlgProcName就是DLL中引出的回調函數
    這段代碼看起來非常簡潔,也完全能正常工作,可是想一想,如果在程序其它的地方要不停的使用DLL中的對話框,不僅上述工作很煩人,更煩的是,我們必須把所有的回調函數全部引出,其實我們完全可以這樣做:
    在DLL中編寫一個函數LoadDialog,如下:
    LoadDialog proc hInstance,hWnd,ID
    .if ID==100
    mov eax,offset DlgProc0
    .elseif ID==101
    mov eax,offset DlgProc1
    .elseif ID==102
    mov eax,offset DlgProc2
    .elseif ID==103
    mov eax,offset DlgProc3
    .end if
    invoke DialogBoxParam,hInstance,ID,hWnd,eax,NULL
    ret
    LoadDialog endp
    ;DlgProc0、DlgProc1、DlgProc2、DlgProc3都是DLL中的回調函數
    那么,我們在主程序中調用時就只需這樣:
    invoke GetProcAddress,DLL_HANDLE,DlgProcName ;DlgProcName="LoadDialog"
    mov LoadDialog,eax
    push ID
    push hWnd
    push DLL_HANDLE
    call [LoadDialog]
    只需在程序開頭獲取到LoadDialog的地址后,在任何地方調用不同的對話框只需要提供不同的ID即可,就像這樣:
    push 101
    push hWnd
    push DLL_HANDLE
    call [LoadDialog]
    這樣做,不僅DLL中的回調函數不需要引出,在主程序中使用時也比每次讀回調函數地址方便得多

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全