Visual C++/MFC 開發中,有許多「查文件不如查筆記」的高頻技巧。本文整理 16 個實戰常用技巧,涵蓋應用程式控制、視窗操作、資源存取、進程管理、系統資訊取得等核心領域,附完整代碼片段,可直接複製應用。
| # | 需求 | 關鍵 API / 成員 | 核心代碼 |
|---|---|---|---|
| 1 | 取得應用程式實例句柄 | AfxGetInstanceHandle() | HINSTANCE hInst = AfxGetInstanceHandle(); |
| 2 | 取得主視窗指標 | AfxGetMainWnd() | AfxGetMainWnd()->ShowWindow(SW_SHOWMAXIMIZED); |
| 3 | 取得其他程式圖示 | SHGetFileInfo, ExtractIcon | SHFILEINFO info; SHGetFileInfo(_T("notepad.exe"), 0, &info, sizeof(info), SHGFI_ICON); pDC->DrawIcon(10,10,info.hIcon); |
| 4 | 程式結束 / 系統重啟 | WM_CLOSE, ExitWindowsEx | AfxGetMainWnd()->SendMessage(WM_CLOSE); ExitWindowsEx(EWX_REBOOT, 0); |
| 5 | 啟動其他應用程式 | WinExec, ShellExecute, CreateProcess | ShellExecute(NULL, NULL, _T("readme.txt"), NULL, _T("c:\\temp"), SW_SHOW); |
| 6 | 取得應用程式完整路徑 | GetModuleFileName | TCHAR path[MAX_PATH]; GetModuleFileName(NULL, path, MAX_PATH); |
| 7 | 取得系統特殊目錄 | GetWindowsDirectory, GetSystemDirectory, GetTempPath, GetCurrentDirectory | TCHAR winDir[MAX_PATH]; GetWindowsDirectory(winDir, MAX_PATH); |
| 8 | 自訂訊息 | #define WM_MY_MSG (WM_USER+100), ON_MESSAGE | LRESULT OnMyMsg(WPARAM, LPARAM); ON_MESSAGE(WM_MY_MSG, OnMyMsg) |
| 9 | 改變視窗圖示 | WM_SETICON | HICON hIcon = AfxGetApp()->LoadIcon(IDI_ICON); AfxGetMainWnd()->SendMessage(WM_SETICON, TRUE, (LPARAM)hIcon); |
| 10 | 修改視窗預設風格 | PreCreateWindow, CREATESTRUCT | cs.style &= ~WS_MAXIMIZEBOX; cs.x=cs.y=0; cs.cx=GetSystemMetrics(SM_CXSCREEN)/2; |
| 11 | 視窗置中顯示 | CenterWindow() | CenterWindow(); CenterWindow(GetDesktopWindow()); AfxGetMainWnd()->CenterWindow(); |
| 12 | 啟動時最大化/最小化 | m_nCmdShow, WS_MAXIMIZE | m_nCmdShow = SW_SHOWMAXIMIZED; // 在 InitInstance 設定 |
| 13 | 保持視窗最小化 (不可還原) | WM_QUERYOPEN | BOOL OnQueryOpen() { return FALSE; } // 在訊息映射加入 ON_WM_QUERYOPEN() |
| 14 | 限制視窗大小 (固定尺寸) | WM_GETMINMAXINFO | void OnGetMinMaxInfo(MINMAXINFO* p) { p->ptMaxTrackSize = p->ptMinTrackSize = CSize(400,300); } |
| 15 | 視窗隱藏/顯示 | ShowWindow(SW_HIDE/SW_SHOW) | pWnd->ShowWindow(SW_HIDE); // 配合 FindWindow 可控制其他程式視窗 |
| 16 | 視窗永遠置頂 | SetWindowPos, WS_EX_TOPMOST | pWnd->SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); // 取消用 &wndNoTopMost |
SHFILEINFO sfi = {0};
// 取得大圖示 (32x32)
SHGetFileInfo(_T("c:\\windows\\notepad.exe"), 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_LARGEICON);
pDC->DrawIcon(10, 10, sfi.hIcon);
// 取得小圖示 (16x16)
SHGetFileInfo(_T("c:\\windows\\notepad.exe"), 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_SMALLICON);
pDC->DrawIcon(50, 10, sfi.hIcon);
// 取得檔案類型描述
SHGetFileInfo(_T("test.txt"), 0, &sfi, sizeof(sfi), SHGFI_TYPENAME);
CString typeName = sfi.szTypeName; // "Text Document"
| 場景 | 推薦 API | 理由 |
|---|---|---|
| 開啟文件/網址/執行檔 (關聯程式) | ShellExecute | 自動處理檔案關聯、工作目錄、DDE、UAC 提權 |
| 需控制子進程 (標準輸入/輸出/錯誤、安全屬性、優先權) | CreateProcess | 完整進程控制、支援重導向、作業物件管理 |
| 簡單啟動 GUI 程式、無需等待 | WinExec (已棄用) | 僅相容舊碼,新碼請用 ShellExecute 或 CreateProcess |
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
// 移除最大化按鈕、邊框可調整大小
cs.style &= ~(WS_MAXIMIZEBOX | WS_THICKFRAME);
// 設定初始位置與大小 (螢幕座標)
cs.x = 100;
cs.y = 100;
cs.cx = 800;
cs.cy = 600;
// 擴充風格:工具視窗 (不在工作列顯示)、置頂
// cs.dwExStyle |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
return CFrameWnd::PreCreateWindow(cs);
}
void CMyDialog::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// 最小 400x300,最大 1200x900
lpMMI->ptMinTrackSize = CPoint(400, 300);
lpMMI->ptMaxTrackSize = CPoint(1200, 900);
// 最大化位置與大小 (螢幕座標)
lpMMI->ptMaxPosition = CPoint(0, 0);
lpMMI->ptMaxSize = CPoint(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
}
ExitWindowsEx 需 SE_SHUTDOWN_NAME 權限,現代應用建議改用 InitiateSystemShutdownEx。ShellExecuteEx 提供更豐富資訊回傳 (進程 ID、視窗句柄)。SHGetKnownFolderPath (Vista+) 取代 SHGetFolderPath,支援 KnownFolderID (如 FOLDERID_Documents)。SetWindowPos(&wndTopMost...) 可能被使用者關閉,重要視窗建議配合 WS_EX_TOPMOST 風格於 PreCreateWindow 設定。這 16 招涵蓋了 MFC 開發 80% 的高頻視窗/程式控制需求。建議將本文加入書籤,遇到對應需求時直接複製核心代碼並根據專案調整參數。記住:MSDN 文件是最終權威,使用前請確認參數型別、回傳值、錯誤碼定義,避免 64 位元移植或新版 Windows 相容性問題。