設置 | 登錄 | 註冊

目前共有9篇帖子。

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

內容轉換:

回覆帖子
內容:
用戶名: 您目前是匿名發表。
驗證碼:
看不清?換一張
©2010-2025 Purasbar Ver3.0 [手機版] [桌面版]
除非另有聲明,本站採用知識共享署名-相同方式共享 3.0 Unported許可協議進行許可。