如何在带有 C 的 WinAPI 中在像“Counts”这样的单词旁边画一条这样的线?

最佳答案

使用对话框资源

创建一个没有文本的静态文本控件,高度为 1 或 2 个像素,打开边框( WS_BORDER ),并将其样式设置为静态边缘( WS_EX_STATICEDGE )。然后创建一个静态文本控件,上面有“Counts”这个词。然后使用 CreateDialog() DialogBox() 来显示对话框。

IDD_DIALOG1 DIALOGEX 0, 0, 172, 63
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    LTEXT           "",IDC_STATIC,6,12,156,1,WS_BORDER,WS_EX_STATICEDGE
    LTEXT           "Counts ",IDC_STATIC,6,8,26,8
END

注意: 这是 Visual Studio 使用对话框设计器生成的逐字记录。

使用 CreateWindow() 创建静态控件(根据 Jonathan Potter 的建议)
LRESULT OnCreate( HWND hWnd, LPCREATESTRUCT lpCreateStruct )
{
    // Get default gui font
    NONCLIENTMETRICS metrics;
    metrics.cbSize = sizeof(NONCLIENTMETRICS);
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &metrics, NULL);
    HFONT hFont = CreateFontIndirect(&metrics.lfMessageFont);

    // Create the line
    CreateWindowEx(WS_EX_STATICEDGE, _T("STATIC"), NULL, WS_CHILD|WS_VISIBLE|WS_BORDER,
        10, 17, 280, 1, hWnd, NULL, lpCreateStruct->hInstance, NULL);

    // Create the Counts label
    HWND hwndCounts = CreateWindow(_T("STATIC"), _T("Counts "), WS_CHILD|WS_VISIBLE,
        10, 10, 50, 26, hWnd, NULL, lpCreateStruct->hInstance, NULL);

    // Apply the default gui font
    SendMessage(hwndCounts, WM_SETFONT, (WPARAM)hFont, TRUE);

    // Cleanup the font object
    DeleteObject(hFont);
}

WM_PAINT 事件 上手动绘制
void OnPaint( HWND hWnd )
{

    // Get the default font
    NONCLIENTMETRICS metrics;
    metrics.cbSize = sizeof(NONCLIENTMETRICS);
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &metrics, NULL);
    HFONT hFont = CreateFontIndirect(&metrics.lfMessageFont);

    // Setup HDC
    RECT rect;
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hWnd, &ps);

    // Select the default font
    SelectObject(hdc, hFont);

    // Draw the line using the button shadow
    SelectObject(hdc, GetStockObject(DC_PEN));
    SetDCPenColor(hdc, GetSysColor(COLOR_BTNSHADOW));
    MoveToEx(hdc, 10, 17, NULL);
    LineTo(hdc, 280, 17);

    // Draw the word Counts overtop of the line
    SetRect(&rect, 10, 10, 280, 22);
    SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));
    SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
    DrawText(hdc, TEXT("Counts "), -1, &rect, DT_NOCLIP);

    // Cleanup the font object
    DeleteObject(hFont);

    // Quit painting
    EndPaint(hWnd, &ps);
}

注意: 在这个例子中我没有考虑的是默认字体的高度。您将需要为此调整代码。

这是此方法输出的屏幕截图。

在您的示例中,它看起来像一条单像素线,所以这就是我绘制的,但是如果您想让该线看起来更像是“固定 3D”或“降低斜角线”(这就是组合框倾向于绘制它的边界线),然后您可以使用按钮高亮颜色在其下方绘制另一条线。
SetDCPenColor(hdc, GetSysColor(COLOR_BTNHIGHLIGHT));
MoveToEx(hdc, 10, 18, NULL);
LineTo(hdc, 280, 18);

正如 Ben Voigt 所指出的那样,尽管使用 DrawEdge 执行此操作可能会更好。
RECT line;
SetRect(&line, 10, 17, 280,17);
DrawEdge(hdc, &line, EDGE_ETCHED, BF_TOP );

创建分组框控件 (由 Hans Passant 建议)

Hans Passant 提出的使用 Group Box 执行此操作的建议在我测试时确实奏效。它 still drew a rectangle ,当您启用视觉样式时,它是 very difficult to see 。尽管如此,如果您想试一试,这应该可以帮助您入门。
HWND hwndGroup = CreateWindow(_T("Button"), _T("Counts "),
    WS_CHILD|WS_VISIBLE|BS_GROUPBOX, 10, 10, 280, 2, hWnd, NULL,
    lpCreateStruct->hInstance, NULL);
SendMessage(hwndGroup, WM_SETFONT, (WPARAM)hFont, TRUE);

附加说明

我想建议的另一件事是,您可以使用 Visual Studio 附带的 Spy++ 来分析您正在查看的窗口。这至少会告诉您它是否是子控件,或者他们是否正在手动绘制它。如果它是一个子控件,您还可以看到应用到它的矩形和样式,以及许多附加信息。

关于c - 在 WinAPI 中在单词旁边画一条线,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26830522/

10-11 22:37