整理自實戰開發中高頻遇到的 20 個典型問題,涵蓋視窗樣式控制、訊息傳遞、Shell 整合、檔案操作、程式庫知識等,附標準 API 呼叫與 MFC 封裝寫法,可直接複製套用。
方法一:Win32 API
// 隱藏
LONG style = ::GetWindowLong(m_hWnd, GWL_STYLE);
::SetWindowLong(m_hWnd, GWL_STYLE, style & ~WS_CAPTION);
::SetWindowPos(m_hWnd, NULL, 0,0,0,0,
SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED);
// 顯示
::SetWindowLong(m_hWnd, GWL_STYLE, style | WS_CAPTION);
::SetWindowPos(m_hWnd, NULL, 0,0,0,0,
SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED);
方法二:MFC 封裝 (推薦)
// 隱藏
ModifyStyle(WS_CAPTION, 0, SWP_FRAMECHANGED);
// 顯示
ModifyStyle(0, WS_CAPTION, SWP_FRAMECHANGED);
HWND hEdit = GetDlgItem(IDC_EDIT1)->GetSafeHwnd();
::SendMessage(hEdit, WM_SETTEXT, 0, (LPARAM)_T(""));
SHELLEXECUTEINFO sei = {0};
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_INVOKEIDLIST;
sei.lpVerb = _T("properties");
sei.lpFile = _T("C:\\"); // 或檔案路徑
sei.nShow = SW_SHOW;
ShellExecuteEx(&sei);
BOOL DeleteDirectory(LPCTSTR path) {
CFileFind finder;
CString pattern; pattern.Format(_T("%s\\*.*"), path);
BOOL found = finder.FindFile(pattern);
while (found) {
found = finder.FindNextFile();
if (finder.IsDots()) continue;
CString full = path + _T("\\") + finder.GetFileName();
if (finder.IsDirectory())
DeleteDirectory(full); // 遞迴
else
DeleteFile(full);
}
finder.Close();
return RemoveDirectory(path) ? TRUE : FALSE;
}
| 特性 | .lib (靜態庫) | .dll (動態庫) |
|---|---|---|
| 連結時機 | 編譯連結期 | 執行期載入 |
| 檔案大小 | 較大 (含代碼) | 較小 (僅匯出表) |
| 部署 | 無需額外檔案 | 需隨程式部署 DLL |
| 升級 | 需重新編譯 | 僅替換 DLL (介面不變) |
| 跨語言 | 困難 | 容易 (C 介面) |
關聯:DLL 專案產出 .dll + .lib (匯入庫),應用程式連結 .lib,執行期載入 .dll。若無 .lib,可用 LoadLibrary/GetProcAddress 顯式載入。
extern "C" {
#include "my_c_header.h"
}
防止 C++ 名稱修飾導致連結錯誤。
CString GetAppPath() {
TCHAR path[MAX_PATH];
GetModuleFileName(NULL, path, MAX_PATH);
PathRemoveFileSpec(path);
return CString(path);
}
BOOL PathExists(LPCTSTR path) {
return GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES;
}
BOOL RunAndWait(LPCTSTR cmd, LPCTSTR params = NULL) {
SHELLEXECUTEINFO sei = {sizeof(sei)};
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.lpFile = cmd; sei.lpParameters = params;
sei.nShow = SW_SHOW;
if (!ShellExecuteEx(&sei)) return FALSE;
WaitForSingleObject(sei.hProcess, INFINITE);
CloseHandle(sei.hProcess);
return TRUE;
}
CString GetSpecialFolder(int csidl) { // CSIDL_DESKTOP, CSIDL_PROGRAM_FILES 等
TCHAR path[MAX_PATH];
SHGetSpecialFolderPath(NULL, path, csidl, FALSE);
return CString(path);
}
BOOL IsWinNT() {
OSVERSIONINFO osvi = {sizeof(osvi)};
GetVersionEx(&osvi);
return osvi.dwPlatformId == VER_PLATFORM_WIN32_NT;
}
// 需配合 NOTIFYICONDATA、Shell_NotifyIcon、WM_SYSCOMMAND SC_MINIMIZE 處理
SetWindowPos(&wndTopMost, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE); // 置頂
SetWindowPos(&wndNoTopMost, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE); // 取消
CRect rect; GetDlgItem(IDC_xxx)->GetWindowRect(&rect); ScreenToClient(&rect);
HANDLE hMutex = CreateMutex(NULL, TRUE, _T("Global\\MyAppUniqueName"));
if (GetLastError() == ERROR_ALREADY_EXISTS) { /* 已執行,激活舊視窗並退出 */ }
CString str; str.Format(_T("Value: %d, Name: %s"), 123, _T("Test")); // MFC 安全
// 或 C++11: std::to_string, std::ostringstream
CByteArray arr; arr.Append(data, len);
CString str((LPCSTR)arr.GetData(), len); // ANSI
// Unicode 需留意編碼
TRACE(_T("File: %s, Line: %d, Value: %d\n"), _T(__FILE__), __LINE__, val);