MFC DLL資源動態切換

2021-06-08 12:29:51 字數 2446 閱讀 8806

在mfc使用過程中,遇到dll資源與主exe資源衝突問題。

出現這樣的bug,一時無從下手。

報錯位置在核心**中dlgcore.cpp。

bool afxapi _afxcheckdialogtemplate(lpctstr lpszresource, bool binvisiblechild)

......

return true;

}

afxfindresourcehandle查詢資源檔案時,本應在exe中的資源,結果返回了dll的控制代碼。

解決方法:

//記錄當前資源控制代碼

hinstance hcurinstance = afxgetresourcehandle();

//設定主模組資源控制代碼

create(ctestdlg::idd, getdesktopwindow());

showwindow(sw_hide);

showwindow(sw_shownoactivate);

//恢復當前模組控制代碼

afxsetresourcehandle(hcurinstance);

參照一篇文章,終於弄清楚了其中的來龍去脈。

afx_manage_state(afxgetstaticmodulestate())

先看乙個例子:

1、建立乙個動態鏈結到mfc dll的規則dll,其內部包含乙個對話方塊資源。指定該對話方塊id如下:

#define idd_dll_dialog 2000

2、建立乙個基於對話方塊的mfc應用程式,它包含兩個對話方塊資源,idd_ui_dialog和idd_exe_dialog。並將後者的id指定如下:

#define idd_exe_dialog 2000

其中前者是這個應用程式的使用者介面,單擊上面的按鈕,將彈出乙個對話方塊。部分**如下:

// in dll

void cdll::showdlg(void)

// in exe

void cexe::onbuttonclick()

3、單擊按鈕,彈出的不是期望的dll中的對話方塊idd_dll_dialog,而是應用程式中的對話方塊idd_exe_dialog。

解釋:

1、應用程式程序本身及其呼叫的每個dll模組都具有乙個全域性唯一的hinstance控制代碼,它們代表了exe或dll模組在程序虛擬空間中的起始位址。(程序本身的模組控制代碼一般為0x400000,而dll模組的預設控制代碼為0x10000000。如果程式同時載入了多個dll,則每個dll模組都會有不同的hinstance。應用程式在載入dll時對其進行了重定位)。

2、共享mfc dll(或mfc擴充套件dll)的規則dll涉及到hinstance控制代碼問題,

hinstance控制代碼對於載入資源特別重要

。exe和dll都有其自己的資源,而且這些

資源的id可能重複

,如果應用程式與規則dll共享mfc dll(或mfc擴充套件dll),那麼將總是

預設使用exe的資源

。3、因此應用程式需要通過資源模組的切換來找到正確的資源。如果應用程式需要來自於dll的資源,就應將資源模組控制代碼指定為dll的模組控制代碼;如果需要exe檔案中包含的資源,就應將資源模組控制代碼指定為exe的模組控制代碼。

解決辦法:

1、在dll中改進:

方法1。

// in dll

void cdll::showdlg(void)

注:afx_manage_state(afxgetstaticmodulestate());一定是作為介面函式的第一條語句。

其功能是在棧上(這意味著其作用域是區域性的)建立乙個afx_module_state類的例項,並將其指 

針pmodulestate返回。

afx_module_state類利用其建構函式和析構函式進行儲存模組狀態現場及恢復現場的工作。

該巨集用於將pmodulestate設定為當前的有效模組狀態。當離開該巨集的作用域時(也就離開了pmodulestate所指棧上物件的作用域),先前的模組狀態將由類afx_module_state的析構函式恢復。(即自動恢復)

方法2。

// in dll

void cdll::showdlg(void)

注:afxgetresourcehandle:獲取當前資源模組控制代碼;afxsetresourcehandle:設定程式目前要使用的資源模組控制代碼。

同方法1比較,方法2能夠靈活地設定程式的資源模組控制代碼,而方法1則只能在dll介面函式退出的時候才會恢復模組控制代碼。

2、在應用程式中改進:

// in exe

void cexe::onbuttonclick()

注:使用狀態切換的情況:當dll匯出函式包含mfc資源、類或者需要建立視窗時。

MFC資源切換

先看乙個例子 1 建立乙個動態鏈結到mfc dll的規則dll,其內部包含乙個對話方塊資源。指定該對話方塊id如下 define idd dll dialog 2000 2 建立乙個基於對話方塊的mfc應用程式,它包含兩個對話方塊資源,idd ui dialog和idd exe dialog。並將後...

解決擴充套件MFC DLL與主程式資源衝突問題

介紹這方面的文章不少,這裡僅僅簡明扼要提供 和一些說明。在要到處的mfc類加上afx ext class,比如 class afx ext class cmivptooldlg public cdialog 即可形成到處類,用dumpbin檢視發現幾乎匯出了所有的mfc函式,暫時不管他。在客戶端,也...

VC 動態鏈結庫程式設計之非MFC DLL

4.1乙個簡單的dll 第2節給出了以靜態鏈結庫方式提供add函式介面的方法,接下來我們來看看怎樣用動態鏈結庫實現乙個同樣功能的add函式。圖6 建立乙個非mfc dll 在建立的工程中新增lib.h及lib.cpp檔案,源 如下 檔名 lib.h ifndef lib h define lib h...