|  | 
        
          |  | 【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;
 }
 
 |  |  |  |