MFC中使用Create或CreateDialog創建對話框失敗,GetLastError錯誤碼為1813(找不到映像文件中指定的資源類型)

文章目錄

  • 創建對話框失敗示例、原因分析及解決方案
    • 示例代碼
    • 錯誤原因
    • 解決方案
  • AFX_MANAGE_STATE(AfxGetStaticModuleState())作用
    • 一、功能
      • 1. 模塊狀態切換
      • 2. 自動狀態恢復
    • 二、為什么要用該函數?
    • 三、必須使用該宏的典型場景
      • 1. MFC 擴展 DLL(Extension DLL)
      • 2. 多線程調用 MFC 功能
      • 3. COM 組件或 ActiveX 控件
      • 4. 靜態庫中的 MFC 代碼
    • 四、不需要使用的情況
    • 五、技術原理(偽代碼)
    • 六、常見問題與修復
      • 問題 1:對話框顯示空白
      • 問題 2:DYNAMIC_DOWNCAST 失敗
    • 七、最佳實踐
    • 總結
    • 在這里插入圖片描述

創建對話框失敗示例、原因分析及解決方案

示例代碼

void ShowDlg()
{//CreateDialogHWND hWnd = CreateDialog(NULL, MAKEINTRESOURCE(IDD_DLG_SHOW), NULL, NULL);if (NULL == hWnd){DWORD dErr = ::GetLastError();//dErr=1813 找不到映像文件中指定的資源類型。}::ShowWindow(hWnd, SW_SHOW);//CreatemyDlg mDlg;BOOL bRet = mDlg.Create(IDD_DLG_SHOW);if (!bRet){DWORD dErr = ::GetLastError();//dErr=1813 找不到映像文件中指定的資源類型。}mDlg.ShowWindow(SW_SHOW);
}

錯誤原因

在 DLL 中加載資源(如對話框、字符串)時,必須確保使用正確的模塊狀態,否則可能加載錯誤的資源或失敗。

解決方案

在創建對話框前增加:

AFX_MANAGE_STATE(AfxGetStaticModuleState()); 

那么AFX_MANAGE_STATE(AfxGetStaticModuleState())功能是什么呢,為什么要用該函數,哪些情況下需要使用?

AFX_MANAGE_STATE(AfxGetStaticModuleState())作用

AFX_MANAGE_STATE(AfxGetStaticModuleState()) 是 MFC(Microsoft Foundation Classes)中一個關鍵的模塊狀態管理宏,用于在多模塊應用程序(如涉及 DLL 的工程)中確保資源、消息映射和運行時類型信息的正確性。以下是詳細解答:


一、功能

1. 模塊狀態切換

  • MFC 使用模塊狀態AFX_MODULE_STATE)跟蹤當前代碼所屬的模塊(如 EXE 主程序、DLL、插件等)。
  • 模塊狀態包含:
    • 資源句柄(用于加載對話框、圖標、字符串等)
    • 運行時類型信息(RTTI)
    • 消息映射表
    • 線程上下文信息
  • 作用:在進入某個模塊的代碼時,臨時切換到該模塊的狀態,確保其資源、消息和類型信息能被正確訪問。

2. 自動狀態恢復

  • 該宏基于 RAII(資源獲取即初始化)機制:
    • 進入作用域時:將當前模塊狀態切換為目標模塊(如 DLL 的模塊狀態)。
    • 退出作用域時:自動恢復為之前的模塊狀態(如主程序的模塊狀態)。

二、為什么要用該函數?

在多模塊 MFC 應用中,如果不顯式管理模塊狀態,會導致以下問題:

  1. 資源加載錯誤

    • 例如:DLL 中的代碼嘗試加載對話框資源時,可能錯誤地從主程序(EXE)的資源中讀取,導致界面顯示異常或崩潰。
    • 示例:DLL 中定義的對話框資源 ID 與主程序沖突時,未切換狀態會加載主程序的資源。
  2. 運行時類型信息(RTTI)失效

    • MFC 的 DYNAMIC_DOWNCASTIsKindOf 可能因模塊狀態錯誤返回 NULL,導致類型轉換失敗。
  3. 線程上下文問題

    • 多線程環境下,若線程入口未設置模塊狀態,可能訪問錯誤的資源或消息映射。

三、必須使用該宏的典型場景

1. MFC 擴展 DLL(Extension DLL)

  • 場景:DLL 導出函數或類,且需要加載資源(如對話框、字符串)。
  • 示例
    // DLL 導出的函數
    void ShowDlgInDLL()
    {AFX_MANAGE_STATE(AfxGetStaticModuleState()); // 切換到 DLL 的模塊狀態CMyDialog dlg;dlg.DoModal(); // 正確加載 DLL 中的對話框資源
    }
    
  • 未使用的后果:對話框可能加載主程序的資源(導致布局錯亂),或直接崩潰。

2. 多線程調用 MFC 功能

  • 場景:線程由 DLL 創建,并在其中使用 MFC 類或資源。
  • 示例
    UINT MyThreadProc(LPVOID)
    {AFX_MANAGE_STATE(AfxGetStaticModuleState());CWinThread* pThread = AfxBeginThread(...); // 確保線程使用 DLL 的模塊狀態return 0;
    }
    

3. COM 組件或 ActiveX 控件

  • 場景:MFC 實現的 COM 對象被外部進程調用時,需確保內部代碼使用正確的模塊狀態。
  • 示例
    STDMETHODIMP CMyCOM::Method()
    {AFX_MANAGE_STATE(AfxGetStaticModuleState());CString str = _T("Hello"); // 正確使用 DLL 的字符串資源return S_OK;
    }
    

4. 靜態庫中的 MFC 代碼

  • 場景:靜態庫被多個模塊(EXE/DLL)調用時,需在調用入口切換狀態。

四、不需要使用的情況

  1. 純 EXE 項目:單模塊應用程序無需切換狀態。
  2. 非 MFC DLL:如純 Win32 DLL,不涉及 MFC 資源或類。
  3. 同一模塊內部調用:如 DLL 內部函數調用自身資源時,通常無需切換。

五、技術原理(偽代碼)

// AFX_MANAGE_STATE 的簡化實現
#define AFX_MANAGE_STATE(targetState) \AFX_MODULE_STATE* __prevState = AfxGetModuleState(); \ // 保存當前狀態AfxSetModuleState(targetState);                        // 切換新狀態// 作用域結束時自動調用析構函數恢復舊狀態

六、常見問題與修復

問題 1:對話框顯示空白

  • 現象:DLL 中的對話框未顯示預期內容。
  • 原因:未切換模塊狀態,資源從主程序加載。
  • 修復:在導出函數中添加 AFX_MANAGE_STATE

問題 2:DYNAMIC_DOWNCAST 失敗

  • 現象DYNAMIC_DOWNCAST(CMyClass, pObj) 返回 NULL
  • 原因:模塊狀態錯誤,導致 MFC 無法識別類信息。
  • 修復:在調用前切換模塊狀態。

七、最佳實踐

  1. 在 DLL 所有導出函數的入口處添加宏(除非明確不需要)。
  2. 避免在全局/靜態對象構造函數中使用:此時模塊狀態可能未初始化。
  3. 結合 CWinApp 派生類:若 DLL 有自己的 CWinApp,仍需顯式處理導出函數。

總結

  • 功能:確保跨模塊調用時,MFC 正確訪問資源、類型和消息映射。
  • 何時使用:涉及多模塊(DLL、COM、多線程)且使用 MFC 功能時。
  • 核心價值:避免資源錯亂、崩潰和邏輯錯誤,提升代碼健壯性。

上一篇:通過簡單示例來展示C/C++中是如何計算指針中字符串的長度


在這里插入圖片描述

技術世界如同浩瀚的海洋,每一處看似復雜的暗流,實則是通向更深理解的航道。
你探索的每一個 MFC 模塊狀態、每一行看似晦澀的代碼,都是在駕馭底層邏輯的力量。
也許今天的 AFX_MANAGE_STATE 曾讓你困惑,但當你跨越這道門檻,你會發現自己已悄然解鎖了構建健壯軟件的核心密鑰。
記住:
真正的開發者,從不畏懼細節的挑戰,而是將每一處“坑”化為成長的墊腳石。
當你能從容切換模塊狀態、馴服多線程的紛爭、甚至讓 COM 組件優雅協作時,那份“庖丁解牛”的成就感,便是技術之路上最美的風景。
保持好奇,持續深耕——因為你的每一份堅持,終將讓代碼煥發優雅與力量。
愿你在 MFC 的深海中,找到屬于自己的星辰大海!
🚀


(用這段文字為技術探索注入熱血與信念,讓學習不止于代碼,更是一場自我超越的旅程!)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/897816.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/897816.shtml
英文地址,請注明出處:http://en.pswp.cn/news/897816.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

php進程管理

php-fpm(fastcgi process manager)是PHP 的FastCGI管理器,管理PHP的FastCGI進程,提升PHP應用的性能和穩定性 php-fpm是一個高性能的php FastCGI管理器,提供了更好的php進程管理方式,可以有效的控制內存和進程,支持平滑…

《MySQL數據庫從零搭建到高效管理|表的增刪改查(基礎)》

目錄 引言: 一、表的操作 1.1 創建學生表 1.2 查看表結構 1.3 刪除表 1.4 修改表名 1.5 添加字段 1.6 修改字段 1.7 刪除字段 1.8 小結 二、CRUD 2.1 新增(Create)數據 2.2 查詢(Retrieve)數據 2.3 修改&…

建筑管理(2): 施工承包模式,工程監理,質量監督

文章目錄 一. 施工承包模式1. 施工總承包模式1.1 施工總承包的特點1.2 施工總承包模式中的承包方 2. 平行承包模式3. 聯合體與合作體承包模式 二. 工程監理1. 強制實行監理的工程范圍1.1 國家重點建設工程1.2 大中型公用事業工程(重點)1.3 成片開發建設的住宅小區工程1.4 必須實…

Spring Boot與Apache Ignite集成:構建高性能分布式緩存和計算平臺

1. 前言 1.1 什么是Apache Ignite Apache Ignite是一個高性能的分布式內存計算平臺,支持內存緩存、分布式計算、流處理和機器學習等功能。它提供了低延遲的數據訪問和強大的計算能力,適用于需要高性能和可擴展性的應用。 1.2 為什么選擇Apache Ignite 高性能:Ignite利用內…

REST 請求返回 Invalid Credentials

REST 請求返回 “Invalid Credentials”(無效憑據),通常表示身份驗證失敗。可能的原因和解決方案如下: 可能的原因 & 解決方案 用戶名或密碼錯誤 確保使用正確的用戶名和密碼。如果 API 需要 Base64 編碼的 Authorization 頭…

C++Primer學習(6.7 函數指針——難!)

6.7 函數指針 (這一章節比較難) 函數指針指向的是函數而非對象。和其他指針一樣,函數指針指向某種特定類型。函數的類型由它的返回類型和形參類型共同決定,與函數名無關。例如: //比較兩個 string 對象的長度 bool lengthCompare(const string &,co…

高級java每日一道面試題-2025年2月26日-框架篇[Mybatis篇]-Mybatis是如何將sql執行結果封裝為目標對象并返回的?都有哪些映射形式 ?

如果有遺漏,評論區告訴我進行補充 面試官: Mybatis是如何將sql執行結果封裝為目標對象并返回的?都有哪些映射形式 ? 我回答: 在Java高級面試中討論MyBatis如何將SQL執行結果封裝為目標對象并返回的過程時,我們可以從過程細節和映射形式兩個方面來綜合解答這個問…

react(一):特點-基本使用-JSX語法

初識React React是一個用于構建用戶界面的 JavaScript 庫,由 Facebook 開發和維護。 官網文檔:React 官方中文文檔 特點 1.聲明式編程 2.組件化開發 3.多平臺適配 開發依賴 開發React必須依賴三個庫: 1.react:包含react所必…

【Python+HTTP接口】POST請求不同請求頭構造

1、{‘Content-Type’: ‘application/json’} import requestsbody {"name1": "value1","name2": "value2"} requests.post(urlurl, databody)2、{“Content-Type”: “application/x-www-form-urlencoded; charsetUTF-8”} impor…

Java常用API:String與ArrayList的設計哲學與實踐應用

在Java編程中,API(應用程序編程接口)是開發者最強大的工具之一。它們封裝了復雜的底層邏輯,提供了簡潔的調用方式。本文將聚焦Java中兩個最常用的API——String和ArrayList,從底層原理到實際應用,結合深度思…

Python的字符串優雅優化策略:特定編碼 -> Unicode碼點 -> UTF-8(可自定義)

Python利用唯一uni-pot中介打理,任意制式輸出(首選uyf-8)。 筆記模板由python腳本于2025-03-14 23:37:04創建,本篇筆記適合喜歡探究字符串編碼細節的coder翻閱。 【學習的細節是歡悅的歷程】 博客的核心價值:在于輸出思…

linux 時間同步(阿里云ntp服務器)

1、安裝ntp服務 rootlocalhost ~]# yum -y install ntp 已加載插件:fastestmirror, langpacks Loading mirror speeds from cached hostfile* base: mirrors.nju.edu.cn* centos-sclo-rh: mirrors.nju.edu.cn* centos-sclo-sclo: mirrors.huaweicloud.com* epel: m…

虛擬化數據恢復—重裝系統服務器崩了的數據恢復過程

虛擬化數據恢復環境&故障: VMware虛擬化平臺 vmfs文件系統 工作人員誤操作重裝操作系統,服務器崩潰。 重裝系統會導致文件系統元文件被覆蓋。要恢復數據,必須找到&提取重裝系統前的文件系統殘留信息,通過提取出來的元文件…

微信開發者工具內建終端使用不了npm,但是cmd可以

下載cnpm并配置鏡像源 終端cmd: npm install -g cnpm --registryhttp://registry.npmmirror.com 打開微信開發者工具,找到方框的文件右擊選擇內建終端打開 初始化: npm init -y 發現npm沒有此命令 關閉微信開發工具,用管理…

vue/react/vite前端項目打包的時候加上時間最簡單版本,防止后端扯皮

如果你是vite項目,直接寫一個vite的插件,通過這個插件可以動態注入環境變量,然后當打包的時候,自動注入這個時間到環境變量中,然后在項目中App.vue中或者Main.tsx中打印出來,這就知道是什么時候編譯的項目了…

element-plus中Autocomplete自動補全輸入框組件的使用

目錄 1.基本使用 ①從官網賦值如下代碼 ②查看運行效果 ③代碼解讀 2.調用后端接口&#xff0c;動態獲取建議數據 結語 1.基本使用 ①從官網賦值如下代碼 <template> <div><!-- 自動補全輸入框 --><el-autocompletev-model"state":fetc…

DeFi開發的深度解析與展望

去中心化金融&#xff08;DeFi&#xff09;作為區塊鏈技術的一個重要應用&#xff0c;近年來在金融領域掀起了一股創新浪潮。它不僅為用戶提供了更加便捷、高效的金融服務&#xff0c;還重新定義了傳統金融的運作方式。本文將圍繞DeFi開發的核心要素、應用場景、面臨的問題以及…

思維鏈醫療編程方法論框架(Discuss V1版)

思維鏈醫療編程方法論框架 1. 方法論核心定義 思維鏈醫療編程方法論是一種結合結構化思維鏈(Chain of Thought)與醫療領域需求的系統化編程實踐框架,旨在通過分步邏輯推理、知識整合與動態反饋,提升醫療軟件/算法的開發效率、準確性與可解釋性。該方法論的關鍵在于通過清晰…

HarmonyOS第21天:解鎖分布式技術,開啟跨設備協同新體驗

一、HarmonyOS 分布式技術&#xff1a;開啟萬物互聯新時代 在物聯網蓬勃發展的今天&#xff0c;設備之間的互聯互通不再是遙不可及的夢想&#xff0c;而是真切融入日常生活的現實。從智能家居設備的聯動控制&#xff0c;到智能辦公場景中的高效協作&#xff0c;再到智能出行中的…

2025移動端軟件供應鏈安全開源治理方案最佳實踐

2025年3月13日&#xff0c;由中國軟件評測中心、CAPPVD漏洞庫聯合主辦的“第六期移動互聯網APP產品安全漏洞技術沙龍”在海口成功召開。懸鏡安全基于移動端數字供應鏈安全開源治理方案榮獲中國軟件評測中心“2024移動互聯網APP產品安全漏洞治理”優秀案例&#xff0c;并獲頒證書…