目前共有9篇帖子。 內容轉換:不轉換▼
 
點擊 回復
410 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)
 

本帖信息

點擊數:410 回複數:8
評論數: ?
作者:巨大八爪鱼
最後回復:巨大八爪鱼
最後回復時間:2016-5-24 20:15
 
©2010-2024 Arslanbar Ver2.0
除非另有聲明,本站採用創用CC姓名標示-相同方式分享 3.0 Unported許可協議進行許可。