|
|
【C语言程序】控件字体使用系统默认字体,并去掉背景颜色 |
一派護法 十九級 |
|
一派護法 十九級 |
【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)就行了
|
一派護法 十九級 |
其实,在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; }
|
|
|
|