技術演進中的開發沉思-41 MFC系列:定制 AppWizard

MFC開發,最為重要的無非就是用“MFC AppWizard” 對話框做開發了,第一次使用感覺像拆收音機的孩子 —— 左邊是項目類型選擇,右邊是一堆打勾的選項,點完 “完成”,屏幕上就冒出了能直接編譯運行的窗口程序。那時還不知道,這個像 “自動包餃子機” 的工具,后來會被我們改成適配團隊需求的 “專屬模具”。

一、Custom AppWizard 基本操作

剛開始用 AppWizard 時,每次新建項目都要重復選 “單文檔”“支持數據庫”“帶狀態欄”,像每次包餃子都要重新調餡料比例。有次團隊趕一個環境監測軟件的項目,一周內要新建三個類似的子模塊,光是配置項目選項就耗了小半天。也就是從那時候起,我開始琢磨怎么把這些重復步驟 “固化” 成新模板,Custom AppWizard 就成了最佳選擇。

打開 VC++5.0,從 “File” 里選 “New”,在 “Projects” 標簽里找到 “Custom AppWizard”,給它起個名字 —— 比如我們當時給團隊做的 “科研數據工具模板”。這里有個小細節,名字最好帶上團隊或項目特征,后來我們建了好幾個模板,“水質監測專用”“大氣數據采集” 這樣的命名能讓大家一眼就找到對應模板。

下一步會讓你選基于哪個原始模板(就像選基礎面團),MFC 提供了單文檔、多文檔、對話框這幾種基礎類型。我們當時做的監測軟件大多是單文檔帶數據表格的,就選了 “Single Document” 作為基礎。接著彈出的配置頁和普通 AppWizard 一模一樣,從 “Database Support” 里勾選 “Database View Without File Support”,到 “User Interface Features” 里把 “Status Bar” 和 “Tool Bar” 都打上勾,每一個選項都對應著后續開發的基礎需求。

配置完成后,VC++ 會生成一個新的模板項目,里面包含了模板的配置信息和生成邏輯。我們需要把這個模板編譯一下,生成的.dll 文件會被自動放到 VC 的模板目錄里。等下次同事新建項目時,在 “Projects” 列表里就能看到我們做的 “科研數據工具模板”,一點擊,之前配置的選項全都是默認勾選狀態,原本要花 5 分鐘的配置過程,現在 10 秒鐘就能搞定。

這一步就像給自動售貨機裝固定貨道 —— 你提前把大家常買的飲料擺好,別人按一下就能拿到,不用再從一堆選項里翻找。而且這個貨道還能隨時調整,后來我們需要給軟件加打印功能,就在模板里把 “Printing and Print Preview” 勾選上,所有基于這個模板新建的項目,自動就有了打印相關的基礎代碼。

二、AppWizard Components 剖析

后來團隊需要在每個程序里加日志模塊,普通模板滿足不了。這時候就得拆開 AppWizard 的 “五臟六腑”,看看它是怎么生成代碼的。就像想在餃子里加新餡料,得先知道餃子機的餡料輸送管道在哪。

AppWizard 的核心是兩個部分:配置對話框代碼生成腳本。配置對話框就是我們選選項的那些窗口,它由一系列的對話框資源和對應的處理代碼組成。這些對話框就像點餐時勾選 “加辣”“少冰” 的菜單,每個勾選框背后都對應著一個變量,當我們點擊 “下一步” 時,這些變量的值就會被傳遞給代碼生成腳本。

代碼生成腳本則是根據勾選結果 “炒菜” 的菜譜,它用一種叫 “.awx” 的格式存儲。.awx 文件其實是一種特殊的資源文件,里面包含了代碼模板、條件判斷語句和資源模板。我當時用資源編輯器打開.awx 文件,看到里面像搭積木一樣排列著各種代碼片段 —— 有窗口類的定義、消息映射的實現,還有菜單和工具欄的資源描述。

比如它判斷你選了 “狀態欄”,就會在 MainFrame 類里加m_wndStatusBar的定義,同時在OnCreate函數里加入狀態欄的創建代碼:


if (!m_wndStatusBar.Create(this) ||!m_wndStatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT))){TRACE0("Failed to create status bar\n");return -1; // fail to create}

而如果選了 “數據庫支持”,它就會引入 ODBC 相關的頭文件,在文檔類里加入CDatabase和CRecordset的對象定義。

這些組件就像裝修時的 “水電預裝模塊”—— 你選了 “裝空調”,工人就會預留管線;選了 “智能家居”,就會提前布好網線。理解了這些,就知道該改哪里能加入我們自己的模塊。比如我們想加日志模塊,就得找到代碼生成腳本里初始化程序的部分,在那里加入日志初始化的代碼;同時在配置對話框里加一個勾選框,讓用戶可以選擇是否啟用日志功能。

當時為了搞清楚這些組件的工作流程,我特意找了個簡單的模板,每勾選一個選項就去看生成的代碼有什么變化,像偵探破案一樣一點點梳理出選項和代碼之間的對應關系。這個過程雖然花了兩天時間,但搞明白之后,后面修改模板就得心應手了。

三、動手修改 AppWizard

早期在開發項目時有這樣的需求,我們需要每個程序都帶 “數據加密” 功能。因為監測數據涉及到環境敏感信息,必須在程序啟動時初始化加密模塊,防止數據泄露。如果讓每個開發人員手動加這段代碼,不僅麻煩還容易出錯,所以我決定修改之前的 Custom AppWizard 模板,把加密初始化的代碼集成進去。

首先找到模板的.awx 文件(通常在 VC 安裝目錄的 Template 文件夾里,路徑大概是 “Microsoft Visual Studio\VC98\Template”),用 VC 打開這個模板項目。在工作區里能看到 “Resource Files” 下面有個 “Custom.awx” 文件,這就是我們要修改的代碼生成腳本。

雙擊打開.awx 文件,里面是按不同代碼模塊分類的腳本。我要找的是應用程序初始化的部分,對應著 CWinApp 派生類的 InitInstance 函數。在腳本里找到相關的代碼塊后,加入了一段判斷和加密初始化代碼(簡化版):


// 在生成CWinApp派生類時添加加密初始化if (m_bNeedEncrypt) // 我們新增的配置項{AddCode("BOOL CMyApp::InitInstance()");AddCode("{");AddCode(" // 初始化加密模塊");AddCode(" EncryptInit();"); // 我們的加密函數AddCode(" // 原有初始化代碼");AddCode(" CWinApp::InitInstance();");AddCode("}");}

這段腳本的意思是,如果用戶勾選了 “啟用數據加密”,生成的程序就會在初始化時調用 EncryptInit 函數。

光有腳本還不夠,得讓用戶能選擇是否啟用這個功能。所以我又在配置對話框里加了個 “啟用數據加密” 的復選框。在模板項目里找到對話框資源(通常是 IDD_STEP1 或者類似的 ID),用對話框編輯器拖了一個復選框進去,設置 ID 為 IDC_ENCRYPT,然后在對應的對話框類里添加了一個成員變量 m_bNeedEncrypt,用來存儲用戶的選擇。這樣當用戶在配置時勾選這個復選框,m_bNeedEncrypt 就會被設為 TRUE,上面的腳本就會生效。

改完這些后,我編譯了模板并測試了一下。新建項目時,配置頁面果然出現了 “啟用數據加密” 的復選框,勾選后生成的代碼里也有了 EncryptInit 的調用。但運行程序時卻崩潰了,調試后發現是沒在代碼里引入加密模塊的頭文件 “Encrypt.h”。就像包餃子時忘了放酵母,面發不起來,代碼缺少必要的頭文件,自然無法正常運行。于是我又回到腳本里,在添加加密初始化代碼的地方,加了一行#include "Encrypt.h",問題才得以解決。

這種 “踩坑” 的經歷反而讓我明白:工具再智能,也需要人懂它的 “脾氣”。每個看似簡單的功能背后,都有一連串的細節需要考慮,而這些細節正是從 “會用工具” 到 “駕馭工具” 的關鍵。

最后小結:

現在回頭看,Custom AppWizard 就像 MFC 時代的 “技術裁縫”。它不只是省時間的工具,更藏著早期程序員對 “復用” 的理解 —— 我們不重復寫代碼,也不重復做配置,把精力留給真正需要創新的地方。

后來到了 Web 時代,腳手架工具代替了 AppWizard,但道理沒變:好的工具永遠是 “可定制的”。就像當年我們在機房里改模板時想的:技術會變,但 “讓工具適應人” 的思路,大概是所有程序員的共同默契。而那些在修改模板時踩過的坑、總結的經驗,也成了后來面對新工具時的底氣 —— 無論工具怎么變,拆解它、理解它、改造它的邏輯,從來都沒有變過。未完待續.........

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

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

相關文章

Libevent(3)之使用教程(2)創建事件

Libevent(3)之使用教程(2)創建事件 Author: Once Day Date: 2025年6月29日 一位熱衷于Linux學習和開發的菜鳥,試圖譜寫一場冒險之旅,也許終點只是一場白日夢… 漫漫長路,有人對你微笑過嘛… 本文檔翻譯于:Fast portable non-bl…

Kotlin 作用域函數 let 的實現原理

Kotlin 中的 let 是一個 標準庫擴展函數,它廣泛用于作用域函數(Scope Functions)中,尤其適用于對可空對象(nullable)做非空判斷并執行代碼塊的場景。 示例代碼 val name: String? "123" name?…

從FDTD仿真到光學神經網絡:機器學習在光子器件設計中的前沿應用工坊

FDTD仿真與光學神經網絡的基礎概念 FDTD(時域有限差分)是一種數值方法,用于求解麥克斯韋方程組,廣泛應用于光子器件設計。光學神經網絡通過光波導、衍射元件等物理結構實現矩陣運算,具有低能耗、高并行的優勢。 機器學…

在Ubutu22系統上面離線安裝Go語言環境【教程】

0.引言 Go語言(又稱Golang)是Google開發的一種靜態強類型、編譯型、并發型編程語言,由Robert Griesemer、Rob Pike和Ken Thompson于2007年開始設計,2009年正式發布。 1.到官網下載壓縮包 2.從win10系統離線上傳壓縮包給ubuntu22…

CMake實踐:CMake3.30版本之前和之后鏈接boost的方式差異

目錄 1.背景 2.boost引入CMake時機 3.CMake 3.30 之前(含 3.29)鏈接 Boost 的方式 4.CMake 3.30 及之后鏈接 Boost 的方式 5.CMake3.30后引入Boost的步驟 6.遷移建議(3.30 之前 → 3.30 之后) 7.CMake 3.30 移除FindBoost的…

告別掛馬風險!PBootCMS完美替代方案BadouCMS

開發企業網站時一直比較喜歡用pbootcms,標簽套用很簡單,使用也方便。 但是pbootcms一直有被掛馬的問題,官方好像也不怎么更新了!換過好幾個cms,比如eyoucms、dedecms、帝國等等,感覺都不怎么能用得習慣,還…

開發者如何集成AI繪畫?智創聚合API簡化Midjourney接入

在 AI 繪畫領域,Midjourney 的大名如雷貫耳,其強大的圖像生成能力,能將我們腦海中的奇思妙想,迅速轉化為精美的視覺畫面,深受設計師、藝術家以及廣大創意愛好者的青睞。然而,使用 Midjourney 的過程中&…

pycharm回車、刪除、方向鍵和快捷鍵等不能使用原因

解決方法 :菜單欄中的Tools取消勾選Vim Emulator 原因 :新版的pycharm安裝中,默認安裝了vim擴展,一旦安裝了pycharm在編寫代碼時會默認使用Vim編輯器

修復ffmpeg.dll丟失錯誤|6種解決ffmpeg.dll方法詳細教程

看到電腦提示“ffmpeg.dll丟失”,很多人會懵。ffmpeg.dll 是個處理視頻、音頻的關鍵文件。它要是沒了或壞了,軟件就打不開或直接閃退。常見原因是軟件安裝不全、文件被刪、或者中病毒。下面說說它是干嘛的,再給解決辦法。一.ffmpeg.dll 到底是…

OkHttp 與 Stetho 結合使用:打造強大的 Android 網絡調試工具鏈

前言在 Android 應用開發過程中,網絡請求的調試一直是一個重要但具有挑戰性的環節。Facebook 開發的 Stetho 是一個強大的調試工具,當它與 OkHttp 結合使用時,可以為我們提供前所未有的網絡請求洞察能力。本文將詳細介紹如何將這兩者結合使用…

LangGraph教程10:LangGraph ReAct應用

文章目錄 ReAct 預構建的代理 向 ReAct 代理添加記憶 向 ReAct 代理添加系統提示 向 ReAct 代理添加人機交互 ReAct 官方文檔地址:https://langchain-ai.github.io/langgraph/how-tos/#prebuilt-react-agent 中文文檔地址:https://www.aidoczh.com/langgraph/how-tos/#react…

安卓第一個項目

測試所有攝像頭 安卓CameraX:https://developer.android.com/media/grow/spatial-audio?hlzh-cn 1、MainActivity.java // 定義包名 package com.mms.densenapplication;// 引入 AppCompatActivity,支持兼容性更強的 Activity import androidx.appcompa…

Google Gemini 體驗

文章中代碼倉庫 gemini 谷歌推出的 AI 只能模型 Gemini官網Gemini ChatGemini開發者文檔Gemini SDK 所有模型 模型變體輸入輸出優化目標Gemini 2.5 Pro gemini-2.5-pro音頻、圖片、視頻、文本和 PDF文本增強的思考和推理能力、多模態理解能力、高級編碼能力等Gemini 2.5 Fla…

Trae安裝指定版本的插件

前情 Trae是屬于國產的跟 Cursor類似的AI編程IDE,我也是第一時間體驗Trae的,雖然相比Cursor弱了一些,但是也絕對勝任了,前端因為排隊問題我轉戰了Cursor,等到Trae出收費模式前,我已經辦了Cursor會員了&…

【技術追蹤】用于醫學圖像合成和分割的噪聲一致孿生擴散模型(CVPR-2025)

孿生擴散模型,生成息肉圖像用于提升分割性能! 論文:Noise-Consistent Siamese-Diffusion for Medical Image Synthesis and Segmentation 代碼:https://github.com/Qiukunpeng/Siamese-Diffusion 0、摘要 深度學習已徹底革新醫學影…

Crontab詳解

crontab是Unix/Linux系統中用于設置周期性任務的工具,通過編輯配置文件實現定時執行命令或腳本。以下是其語法規則和核心要點: 一、基本格式 * * * * * command - - - - - | | | | | | | | | ----…

中國1km逐月潛在蒸散發數據集 - matlab按shp批量裁剪

中國1km逐月潛在蒸散發數據集 - matlab按shp批量裁剪 1. 數據概述 2 利用掩膜文件對數據進行裁剪 3 完整代碼 4 結語 本篇繼續處理氣象數據,中國1km逐月潛在蒸散發數據集同前節介紹的中國1km降水數據集一樣,都可以從國家青藏高原科學數據中心獲得,數據具有同樣的空間分辨率(…

Node.js鏈接MySql

前言: 在現代 Web 開發和后端服務中,Node.js 因其高性能和異步特性被廣泛使用。MySQL 作為流行的關系型數據庫之一,提供了穩定高效的數據存儲和管理能力。將 Node.js 與 MySQL 結合,可以構建強大的數據驅動型應用。 一、環境準備…

Charles 的 Windows proxy 對爬取瑞數6 網站接口數據的作用分析

其實本文還是源于上個月的這篇文章 ??▼ 耗時兩天半,利用 DrissionPage繞過瑞數6,爬取某藥*局數據經歷~ 不同點是,當時爬取的是列表頁(已爬完),后面爬取的是詳情頁!懂的都懂,差別還…

PHP 測驗

PHP 測驗 引言 PHP 作為一種流行的開源服務器端腳本語言,被廣泛應用于網頁開發、服務器端編程等領域。為了幫助大家更好地理解和掌握 PHP,我們特此推出本 PHP 測驗。通過以下問題,您可以檢驗自己的 PHP 知識水平,同時也能了解自己在哪些方面需要加強。 測驗內容 問題一…