
目前共有9篇帖子。
![]() |
![]() |
![]() |
【main.c代碼】
#include <tchar.h> #include <time.h> #include <Windows.h> #include <windowsx.h> #include <CommCtrl.h> #pragma comment(lib, "comctl32.lib") #pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' language='*' publicKeyToken='6595b64144ccf1df'\"") HFONT hfontCustom, hfontCaption; HINSTANCE hInst; HWND hwndButton, hwndCheckbox, hwndCombo; HWND hwndEdit, hwndEdit2, hwndProgress, hwndRadio; HWND hwndTrackbar; NONCLIENTMETRICS ncm; // 創建自定義字體對象 void InitFont(void) { LOGFONT logfont; ZeroMemory(&logfont, sizeof(logfont)); logfont.lfCharSet = GB2312_CHARSET; // 字符集 lstrcpy(logfont.lfFaceName, TEXT("楷體")); // 字體名稱 logfont.lfHeight = 48; // 字體大小 logfont.lfQuality = ANTIALIASED_QUALITY; // 字體品質 logfont.lfWeight = FW_BOLD; // 是否為粗體 //logfont.lfItalic = TRUE; // 是否為斜體 hfontCustom = CreateFontIndirect(&logfont); } // 獲取系統默認字體 void InitNCM(void) { ncm.cbSize = sizeof(NONCLIENTMETRICS) - sizeof(int); // 減掉int的大小是為了兼容XP系統 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, (UINT)NULL); hfontCaption = CreateFontIndirect(&ncm.lfCaptionFont); } void AutoSelectSeason(void) { time_t t = time(NULL); struct tm lct; int season; localtime_s(&lct, &t); if (lct.tm_mon < 2) season = 3; else season = (lct.tm_mon - 2) / 3; ComboBox_SetCurSel(hwndCombo, season); } LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { HDC hdc; LPWSTR lpwstr; PAINTSTRUCT ps; switch (uMsg) { case WM_COMMAND: if ((HWND)lParam == hwndButton) { MessageBox(hWnd, TEXT("您點擊了這個按鈕!\n該按鈕將被禁用"), TEXT("提示"), MB_ICONWARNING); EnableWindow(hwndButton, FALSE); SetWindowText(hwndEdit, TEXT("按鈕已被禁用")); } break; case WM_CTLCOLORSTATIC: // 消除Static控件和只讀文本框的背景顏色 if ((HWND)lParam == hwndTrackbar) return (LRESULT)GetStockObject(WHITE_BRUSH); // 滑塊控件的背景顏色必須單獨指定 case WM_CTLCOLORBTN: // 消除按鈕背景顏色 break; // 直接返回FALSE, 不交給DefWindowProc處理 case WM_CREATE: InitNCM(); InitFont(); // 可選中文字一般用無邊框的文本框控件來做 hwndEdit = CreateWindow(WC_EDIT, TEXT("這是一段可用鼠標選中的文字..."), WS_CHILD | WS_VISIBLE | ES_READONLY, 10, 10, 300, ncm.iCaptionHeight, hWnd, NULL, hInst, NULL); SendMessage(hwndEdit, WM_SETFONT, (WPARAM)hfontCaption, TRUE); // 該消息的LPARAM參數決定是否立即重繪控件 // 按鈕控件 hwndButton = CreateWindow(WC_BUTTON, TEXT("確定"), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 10, 32, 75, 23, hWnd, NULL, hInst, NULL); SendMessage(hwndButton, WM_SETFONT, (WPARAM)hfontCaption, TRUE); // 注意: WS_BORDER是窗口的邊框(默認為灰色), WS_EX_CLIENTEDGE才是文本框的邊框 // 這個在Control Spy裏面可以看到 hwndEdit2 = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, TEXT("請輸入一些內容..."), WS_CHILD | WS_VISIBLE, 10, 124, 300, ncm.iCaptionHeight, hWnd, NULL, hInst, NULL); SendMessage(hwndEdit2, WM_SETFONT, (WPARAM)hfontCaption, TRUE); //下拉菜單框 hwndCombo = CreateWindow(WC_COMBOBOX, NULL, WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, 10, 160, 200, (int)NULL, hWnd, NULL, hInst, NULL); SendMessage(hwndCombo, WM_SETFONT, (WPARAM)hfontCaption, TRUE); ComboBox_AddString(hwndCombo, TEXT("Spring")); ComboBox_AddString(hwndCombo, TEXT("Summer")); ComboBox_AddString(hwndCombo, TEXT("Autumn")); ComboBox_AddString(hwndCombo, TEXT("Winter")); AutoSelectSeason(); // 單選框 hwndRadio = CreateWindow(WC_BUTTON, TEXT("單選框"), WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, 10, 196, 80, ncm.iCaptionHeight, hWnd, NULL, hInst, NULL); SendMessage(hwndRadio, WM_SETFONT, (WPARAM)hfontCaption, TRUE); Button_SetCheck(hwndRadio, BST_CHECKED); // 複選框 hwndCheckbox = CreateWindow(WC_BUTTON, TEXT("複選框"), WS_CHILD | WS_VISIBLE | BS_AUTO3STATE, 90, 196, 80, ncm.iCaptionHeight, hWnd, NULL, hInst, NULL); SendMessage(hwndCheckbox, WM_SETFONT, (WPARAM)hfontCaption, TRUE); Button_SetCheck(hwndCheckbox, BST_INDETERMINATE); // 進度條 hwndProgress = CreateWindow(PROGRESS_CLASS, NULL, WS_CHILD | WS_VISIBLE | PBS_MARQUEE, 10, 228, 400, 23, hWnd, NULL, hInst, NULL); SendMessage(hwndProgress, PBM_SETMARQUEE, TRUE, (LPARAM)NULL); // 滑塊 hwndTrackbar = CreateWindow(TRACKBAR_CLASS, NULL, WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS | TBS_ENABLESELRANGE, 10, 260, 400, 50, hWnd, NULL, hInst, NULL); SendMessage(hwndTrackbar, TBM_SETRANGE, TRUE, MAKELONG(0, 10)); // 第三個參數決定是否重繪 SendMessage(hwndTrackbar, TBM_SETPAGESIZE, (WPARAM)NULL, 1); SendMessage(hwndTrackbar, TBM_SETPOS, (WPARAM)TRUE, 6); break; case WM_DESTROY: // 關閉窗口時刪除字體 DeleteObject(hfontCustom); DeleteObject(hfontCaption); PostQuitMessage(0); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); SelectObject(hdc, hfontCustom); SetTextColor(hdc, RGB(122, 101, 197)); lpwstr = TEXT("這是一段不能選中的文字"); TextOut(hdc, 10, 64, lpwstr, lstrlen(lpwstr)); EndPaint(hWnd, &ps); break; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return FALSE; } int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; HWND hWnd; MSG msg; RECT rect; WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.cbClsExtra = wcex.cbWndExtra = 0; wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hIcon = wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); wcex.hInstance = hInst = hInstance; wcex.lpfnWndProc = WndProc; wcex.lpszClassName = TEXT("MainWindow"); wcex.lpszMenuName = NULL; wcex.style = (UINT)NULL; RegisterClassEx(&wcex); SetRect(&rect, 0, 0, 640, 480); AdjustWindowRect(&rect, dwStyle, FALSE); hWnd = CreateWindow(wcex.lpszClassName, TEXT("字體範例"), dwStyle, CW_USEDEFAULT, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } |
![]() |
WM_CTLCOLORSTATIC消息返回FALSE可直接消除Static控件以及Read-only的Edit控件的背景顏色,但是會把滑塊控件的背景顏色變為黑色,不過強行返回一個白色的畫刷就能解決問題。
|
![]() |
使用特定字體輸出文本的方法:先填寫一個LOGFONT結構體,然後調用CreateFontIndirect得到HFONT對象,將這個對象選入hdc即可。
使用系統默認字體的方法:用SystemParametersInfo函數填充NONCLIENTMETRICS結構體,調用前一定要設置該結構體的cbSize成員,為了兼容XP系統最好減去sizeof(int)(根據所用的SDK版本決定減不減)。然後,通過ncm.lfCaptionFont成員創建字體,將其選入hdc或者用WM_SETFONT消息設置控件的字體。 |
![]() |
至於cbSize減不減sizeof(int)的問題,如果發現編譯出來的程序在XP系統下運行時字體顯示異常,就要減。如果減去後在Win7不能正常運行,那就不減。
一般VS2010以上都需要減。 |
![]() |
![]() 不過在XP下還是出錯了。。。 |
![]() |
其實,在XP中直接用(HFONT)GetStockObject(DEFAULT_GUI_FONT)就行了
|
![]() |
回復7樓 @巨大八爪鱼 的內容:其實,在XP中直接用(HFONT)GetStockObject(DEFAULT_GUI_FONT)就行了
但是MSDN里寫着:
Remarks It is not recommended that you employ this method to obtain the current font used by dialogs and windows. Instead, use the SystemParametersInfo function with the SPI_GETNONCLIENTMETRICS parameter to retrieve the current font. SystemParametersInfo will take into account the current theme and provides font information for captions, menus, and message dialogs. |
![]() |
【修正後的代碼(兼容XP系統)】
#include <tchar.h> #include <time.h> #include <Windows.h> #include <windowsx.h> #include <CommCtrl.h> #pragma comment(lib, "comctl32.lib") #pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' language='*' publicKeyToken='6595b64144ccf1df'\"") HFONT hfontCustom, hfontCaption; HINSTANCE hInst; HWND hwndButton, hwndCheckbox, hwndCombo; HWND hwndEdit, hwndEdit2, hwndProgress, hwndRadio; HWND hwndTrackbar; NONCLIENTMETRICS ncm; int CALLBACK FontExistsProc(const LOGFONT *lpelfe, const TEXTMETRIC *lpntme, DWORD FontType, LPARAM lParam) { return 0; // 直接終止EnumFontFamiliesEx函數的運行 } // 判斷字體是否存在的函數 BOOL FontExists(LPLOGFONT lpFont) { HDC hdc = GetDC(NULL); BOOL bResult = (EnumFontFamiliesEx(hdc, lpFont, FontExistsProc, (LPARAM)NULL, (DWORD)NULL) == 0); ReleaseDC(NULL, hdc); return bResult; } // 創建自定義字體對象 void InitFont(void) { LOGFONT logfont; ZeroMemory(&logfont, sizeof(logfont)); logfont.lfCharSet = GB2312_CHARSET; // 字符集 lstrcpy(logfont.lfFaceName, TEXT("楷體")); // 字體名稱 logfont.lfHeight = 48; // 字體大小 logfont.lfQuality = ANTIALIASED_QUALITY; // 字體品質 logfont.lfWeight = FW_BOLD; // 是否為粗體 //logfont.lfItalic = TRUE; // 是否為斜體 // 如果字體不存在, 就更換名稱 if (!FontExists(&logfont)) lstrcpy(logfont.lfFaceName, TEXT("楷體_GB2312")); hfontCustom = CreateFontIndirect(&logfont); } // 獲取系統默認字體 void InitNCM(void) { ncm.cbSize = sizeof(NONCLIENTMETRICS) - sizeof(int); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, (UINT)NULL); hfontCaption = (HFONT)GetStockObject(DEFAULT_GUI_FONT); } void AutoSelectSeason(void) { time_t t = time(NULL); struct tm lct; int season; localtime_s(&lct, &t); if (lct.tm_mon < 2) season = 3; else season = (lct.tm_mon - 2) / 3; ComboBox_SetCurSel(hwndCombo, season); } LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { HDC hdc; LPWSTR lpwstr; PAINTSTRUCT ps; switch (uMsg) { case WM_COMMAND: if ((HWND)lParam == hwndButton) { MessageBox(hWnd, TEXT("您點擊了這個按鈕!\n該按鈕將被禁用"), TEXT("提示"), MB_ICONWARNING); EnableWindow(hwndButton, FALSE); SetWindowText(hwndEdit, TEXT("按鈕已被禁用")); } break; case WM_CTLCOLORSTATIC: // 消除Static控件、滑塊控件和只讀文本框的背景顏色 return (LRESULT)GetStockObject(WHITE_BRUSH); case WM_CTLCOLORBTN: // 消除按鈕背景顏色 break; // 直接返回FALSE, 不交給DefWindowProc處理 case WM_CREATE: InitNCM(); InitFont(); // 可選中文字一般用無邊框的文本框控件來做 hwndEdit = CreateWindow(WC_EDIT, TEXT("這是一段可用鼠標選中的文字..."), WS_CHILD | WS_VISIBLE | ES_READONLY, 10, 10, 300, ncm.iCaptionHeight, hWnd, NULL, hInst, NULL); SendMessage(hwndEdit, WM_SETFONT, (WPARAM)hfontCaption, TRUE); // 該消息的LPARAM參數決定是否立即重繪控件 // 按鈕控件 hwndButton = CreateWindow(WC_BUTTON, TEXT("確定"), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 10, 32, 75, 23, hWnd, NULL, hInst, NULL); SendMessage(hwndButton, WM_SETFONT, (WPARAM)hfontCaption, TRUE); // 注意: WS_BORDER是窗口的邊框(默認為灰色), WS_EX_CLIENTEDGE才是文本框的邊框 // 這個在Control Spy裏面可以看到 hwndEdit2 = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, TEXT("請輸入一些內容..."), WS_CHILD | WS_VISIBLE, 10, 124, 300, ncm.iCaptionHeight, hWnd, NULL, hInst, NULL); SendMessage(hwndEdit2, WM_SETFONT, (WPARAM)hfontCaption, TRUE); //下拉菜單框 hwndCombo = CreateWindow(WC_COMBOBOX, NULL, WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, 10, 160, 200, (int)NULL, hWnd, NULL, hInst, NULL); SendMessage(hwndCombo, WM_SETFONT, (WPARAM)hfontCaption, TRUE); ComboBox_AddString(hwndCombo, TEXT("Spring")); ComboBox_AddString(hwndCombo, TEXT("Summer")); ComboBox_AddString(hwndCombo, TEXT("Autumn")); ComboBox_AddString(hwndCombo, TEXT("Winter")); AutoSelectSeason(); // 單選框 hwndRadio = CreateWindow(WC_BUTTON, TEXT("單選框"), WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, 10, 196, 80, ncm.iCaptionHeight, hWnd, NULL, hInst, NULL); SendMessage(hwndRadio, WM_SETFONT, (WPARAM)hfontCaption, TRUE); Button_SetCheck(hwndRadio, BST_CHECKED); // 複選框 hwndCheckbox = CreateWindow(WC_BUTTON, TEXT("複選框"), WS_CHILD | WS_VISIBLE | BS_AUTO3STATE, 90, 196, 80, ncm.iCaptionHeight, hWnd, NULL, hInst, NULL); SendMessage(hwndCheckbox, WM_SETFONT, (WPARAM)hfontCaption, TRUE); Button_SetCheck(hwndCheckbox, BST_INDETERMINATE); // 進度條 hwndProgress = CreateWindow(PROGRESS_CLASS, NULL, WS_CHILD | WS_VISIBLE | PBS_MARQUEE, 10, 228, 400, 23, hWnd, NULL, hInst, NULL); SendMessage(hwndProgress, PBM_SETMARQUEE, TRUE, (LPARAM)NULL); // 滑塊 hwndTrackbar = CreateWindow(TRACKBAR_CLASS, NULL, WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS | TBS_ENABLESELRANGE, 10, 260, 400, 50, hWnd, NULL, hInst, NULL); SendMessage(hwndTrackbar, TBM_SETRANGE, TRUE, MAKELONG(0, 10)); // 第三個參數決定是否重繪 SendMessage(hwndTrackbar, TBM_SETPAGESIZE, (WPARAM)NULL, 1); SendMessage(hwndTrackbar, TBM_SETPOS, (WPARAM)TRUE, 6); break; case WM_DESTROY: // 關閉窗口時刪除字體 DeleteObject(hfontCustom); PostQuitMessage(0); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); SelectObject(hdc, hfontCaption); lpwstr = TEXT("這是TextOut函數輸出的文字"); TextOut(hdc, 10, 320, lpwstr, lstrlen(lpwstr)); SelectObject(hdc, hfontCustom); SetTextColor(hdc, RGB(122, 101, 197)); lpwstr = TEXT("這是一段不能選中的文字"); TextOut(hdc, 10, 64, lpwstr, lstrlen(lpwstr)); EndPaint(hWnd, &ps); break; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return FALSE; } int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; HWND hWnd; MSG msg; RECT rect; WNDCLASSEX wcex; InitCommonControls(); // 這句話必不可少, 防止在XP系統下運行時無法顯示控件 wcex.cbSize = sizeof(WNDCLASSEX); wcex.cbClsExtra = wcex.cbWndExtra = 0; wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hIcon = wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); wcex.hInstance = hInst = hInstance; wcex.lpfnWndProc = WndProc; wcex.lpszClassName = TEXT("MainWindow"); wcex.lpszMenuName = NULL; wcex.style = (UINT)NULL; RegisterClassEx(&wcex); SetRect(&rect, 0, 0, 640, 480); AdjustWindowRect(&rect, dwStyle, FALSE); hWnd = CreateWindow(wcex.lpszClassName, TEXT("字體範例"), dwStyle, CW_USEDEFAULT, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } |