在指定的矩形

时间:2015-06-13 18:43:19

标签: c++ winapi

我有需要在矩形内绘制的字符串。

问题在于,有时字符串可能太大而无法容纳在内部。

如何调整字体大小以使字符串适合内部?

我已阅读GDI的文档但未找到任何内容。我仍然在互联网上搜索,希望找到一些东西或者了解我自己...

GDI +也是一个选项......

发布以下代码以回应用户Jonathan Potter的评论:

#include <windows.h>
#include <windowsx.h>   
#include <CommCtrl.h>
#include <stdio.h>      // swprintf_s()
#include <math.h>
#include <gdiplus.h>
#include <string>
using namespace Gdiplus;

// enable Visual Styles
#pragma comment( linker, "/manifestdependency:\"type='win32' \
                         name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
                         processorArchitecture='*' publicKeyToken='6595b64144ccf1df' \
                         language='*'\"")

// link with Common Controls library
#pragma comment(lib, "comctl32.lib") 
#pragma comment(lib, "GdiPlus.lib")

//global variables
HINSTANCE hInst;

// main window procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_PAINT:
    {
        PAINTSTRUCT ps = { 0 };
        RECT rcClient = { 0 };
        HDC hdc = BeginPaint(hwnd, &ps);

        GetClientRect(hwnd, &rcClient);

        int pageWidth = rcClient.right - rcClient.left,
            pageHeight = rcClient.bottom - rcClient.top;

        HFONT font = NULL, oldFont = NULL;

        // target rectangle, text should fit inside
        Rectangle(hdc, 0, 0, pageWidth / 4, pageHeight / 10);

        SIZE sz;

        GetTextExtentPoint32(hdc, L"This is very long string that might not fit into specified rectangle",
            lstrlen(L"This is very long string that might not fit into specified rectangle"), &sz);

        if (sz.cx > (pageWidth / 4))
        {

            // get current font
            LOGFONT lf;
            GetObject(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);

            // scale it
            lf.lfHeight = MulDiv(lf.lfHeight, (pageWidth / 4), sz.cx);

            font = CreateFontIndirect(&lf);

            oldFont = SelectFont(hdc, font);
        }

        SetBkMode(hdc, TRANSPARENT);
        SetTextColor(hdc, RGB(255, 0, 0));

        // draw text in test rectangle 
        RECT rcText = { 0 };

        rcText.left = 0;
        rcText.top = 0;
        rcText.right = pageWidth / 4;
        rcText.bottom = pageHeight / 10;

        DrawTextEx(hdc,
            L"This is very long string that might not fit into specified rectangle",
            wcslen(L"This is very long string that might not fit into specified rectangle"),
            &rcText, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOCLIP, NULL);

        if (font != NULL)
        {
            SelectFont(hdc, oldFont);
            DeleteFont(font);
        }

        EndPaint(hwnd, &ps);
    }
        return 0L;
    case WM_SIZE:
    {
        InvalidateRect(hwnd, NULL, TRUE);
    }
        return 0L;
    case WM_CLOSE:
        ::DestroyWindow(hwnd);
        return 0L;
    case WM_DESTROY:
    {
        ::PostQuitMessage(0);
    }
        return 0L;
    default:
        return ::DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

// WinMain
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
    int nCmdShow)
{
    // store hInstance in global variable for later use
    hInst = hInstance;

    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    // register main window class
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInst;
    wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = L"Main_Window";
    wc.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);

    if (!RegisterClassEx(&wc))
    {
        MessageBox(NULL, L"Window Registration Failed!", L"Error!",
            MB_ICONEXCLAMATION | MB_OK);

        return 0;
    }

    // initialize common controls
    INITCOMMONCONTROLSEX iccex;
    iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    iccex.dwICC = ICC_LISTVIEW_CLASSES | ICC_STANDARD_CLASSES;
    InitCommonControlsEx(&iccex);

    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    // create main window
    hwnd = CreateWindowEx(0, L"Main_Window", L"Autofit text inside rectangle",
        WS_OVERLAPPEDWINDOW, 50, 50, 200, 200, NULL, NULL, hInstance, 0);

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }

    GdiplusShutdown(gdiplusToken);
    return Msg.wParam;
}

2 个答案:

答案 0 :(得分:1)

您正在寻找DrawText

int DrawText(_In_     HDC     hDC,
             _Inout_  LPCTSTR lpchText,
             _In_     int     nCount,
             _Inout_  LPRECT  lpRect,
             _In_     UINT    uFormat
            );

指定矩形,确保文本不会在该矩形之外绘制。如果您需要根据文本和当前选定的字体计算矩形,它还有一个DT_CALCRECT标志。或者,您可以使用DT_END_ELLIPSISDT_PATH_ELLIPSISDT_WORD_ELLIPSIS标记截断添加了省略号的文本绘图,以便用户可以查看文本何时长于矩形。

答案 1 :(得分:0)

从理论上讲,这样的事情应该有效,但我还没有对它进行过测试。添加适当的错误检查等。

SIZE sz;
GetTextExtentPoint32(hDC, pszMyString, lstrlen(pszMyString), &sz);

if (sz.cx > iMyMaximumWidth)
{
    // get current font
    LOGFONT lf;
    GetObject(GetCurrentObject(hDC, OBJ_FONT), sizeof(lf), &lf);

    // scale it
    lf.lfHeight = MulDiv(lf.lfHeight, iMyMaximumWidth, sz.cx);
    HFONT hNewFont = CreateFontIndirect(&lf);

    .. use hNewFont to render string, remember to delete it when done
}