目前共有9篇帖子。
字体大小:较小 - 100% (默认)  内容转换:不转换
 
点击 回复
1580 8
【C语言程序】控件字体使用系统默认字体,并去掉背景颜色
巨大八爪鱼
武林盟主 二十一级
回复
1楼 发表于:2016-5-20 21:09
巨大八爪鱼
武林盟主 二十一级
回复
2楼 发表于:2016-5-20 21:10
【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;
}
巨大八爪鱼
武林盟主 二十一级
回复
3楼 发表于:2016-5-20 21:15
WM_CTLCOLORSTATIC消息返回FALSE可直接消除Static控件以及Read-only的Edit控件的背景颜色,但是会把滑块控件的背景颜色变为黑色,不过强行返回一个白色的画刷就能解决问题。
巨大八爪鱼
武林盟主 二十一级
回复
4楼 发表于:2016-5-20 21:22
使用特定字体输出文本的方法:先填写一个LOGFONT结构体,然后调用CreateFontIndirect得到HFONT对象,将这个对象选入hdc即可。
使用系统默认字体的方法:用SystemParametersInfo函数填充NONCLIENTMETRICS结构体,调用前一定要设置该结构体的cbSize成员,为了兼容XP系统最好减去sizeof(int)(根据所用的SDK版本决定减不减)。然后,通过ncm.lfCaptionFont成员创建字体,将其选入hdc或者用WM_SETFONT消息设置控件的字体。
巨大八爪鱼
武林盟主 二十一级
回复
5楼 发表于:2016-5-20 21:25
至于cbSize减不减sizeof(int)的问题,如果发现编译出来的程序在XP系统下运行时字体显示异常,就要减。如果减去后在Win7不能正常运行,那就不减。
一般VS2010以上都需要减。
巨大八爪鱼
武林盟主 二十一级
回复
6楼 发表于:2016-5-23 22:29

不过在XP下还是出错了。。。
巨大八爪鱼
武林盟主 二十一级
回复
7楼 发表于:2016-5-24 15:01
其实,在XP中直接用(HFONT)GetStockObject(DEFAULT_GUI_FONT)就行了
巨大八爪鱼
武林盟主 二十一级
回复
8楼 发表于:2016-5-24 15:03

回复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.

巨大八爪鱼
武林盟主 二十一级
回复
9楼 发表于:2016-5-24 20:15
【修正后的代码(兼容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;
}
回复帖子
内容:
用户名: 您目前是匿名发表。
验证码:
看不清?换一张
(快捷键:Ctrl+Enter)
本帖信息
点击数:1580 回复数:8
作者:巨大八爪鱼
最后回复:巨大八爪鱼
最后回复时间:2016-5-24 20:15
本吧精品帖子
公告板