api - Win 32 API 设置窗口最小尺寸以保持文本完全可见

标签 api winapi window

我目前是 win 32 API 的初学者,正在制作一个示例程序。我面临的问题是我找不到正确的方法来设置窗口的最小尺寸,以便当窗口达到最小值时窗口内部的文本(居中)可见。在所有其他情况下,文本都是完全可见的,除非我达到某个“临界”大小,之后文本要么部分可见,要么根本不可见。

我找到了如何更改窗口的宽度和高度,如下所示:

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)        
{
    switch (message)                  
    {
        case WM_DESTROY:
            PostQuitMessage (0);      
            break;

        case WM_GETMINMAXINFO: 
            ((MINMAXINFO*)lParam)->ptMinTrackSize.x =100; //apply custom min width
            ((MINMAXINFO*)lParam)->ptMinTrackSize.y =100;  //apply custom min height
            break;

        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint (hwnd, &ps);

            GetClientRect(hwnd,&rc);

            DrawText (hdc, TEXT ("Sample text here"), -1, &rc,DT_SINGLELINE | DT_CENTER | DT_VCENTER ) ;


            EndPaint (hwnd, &ps);
        }
        break;

        default:                      
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

我认为这些行应该更改,但我不知道需要进行哪些更改。

((MINMAXINFO*)lParam)->ptMinTrackSize.x =100; //apply custom min width
((MINMAXINFO*)lParam)->ptMinTrackSize.y =100;  //apply custom min height

我的想法是,应该调用一个函数来确定文本的最小宽度和高度,而不是分配给 POINT 结构的 x 和 y 成员的显式浮点值。

如有任何帮助,我们将不胜感激。

以下是该程序的完整代码。

#if defined(UNICODE) && !defined(_UNICODE)
#define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif

#include <tchar.h>
#include <windows.h>
#include <stdio.h>


/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
TCHAR szClassName[ ] = _T("CodeBlocksWindowsApp");
RECT rc;
int WINAPI WinMain (HINSTANCE hThisInstance,
                 HINSTANCE hPrevInstance,
                 LPSTR lpszArgument,
                 int nCmdShow)
{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */

    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    if (!RegisterClassEx (&wincl))
        return 0;

    hwnd = CreateWindowEx (
       0,                   /* Extended possibilites for variation */
       szClassName,         /* Classname */
       _T("Code::Blocks Template Windows App"),
              /* Title Text */
       WS_OVERLAPPEDWINDOW, /* default window */
       CW_USEDEFAULT,       /* Windows decides the position */
       CW_USEDEFAULT,       /* where the window ends up on the screen */
       544,                 /* The programs width */
       375,                 /* and height in pixels */
       HWND_DESKTOP,        /* The window is a child-window to desktop */
       NULL,                /* No menu */
       hThisInstance,       /* Program Instance handler */
       NULL                 /* No Window Creation data */
       );

    ShowWindow (hwnd, nCmdShow);

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

    return messages.wParam;
}

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  
    {
        case WM_DESTROY:
            PostQuitMessage (0);       
            break;

        case WM_GETMINMAXINFO:
            //window size/position is going to change
            //apply custom min width/height 350,50

            SIZE sz;
            HDC hdc = GetDC( hwnd );
            TCHAR* myString = TEXT("Sample Text!");
            HFONT oldFont, myFont; //create your own font
            //select your font into device context
            oldFont = (HFONT)SelectObject( hdc, myFont );
            //get font dimensions
            GetTextExtentPoint32( hdc, myString, _tcslen( myString ), &sz );

            ((MINMAXINFO*)lParam)->ptMinTrackSize.x = sz.cx;
            ((MINMAXINFO*)lParam)->ptMinTrackSize.y = sz.cy;

            //cleanup
            SelectObject( hdc, oldFont );
            DeleteObject( myFont );
            ReleaseDC( hwnd, hdc );
            break;

        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint (hwnd, &ps);
                GetClientRect(hwnd,&rc);
                DrawText (hdc, TEXT("Sample Text!"), -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_WORDBREAK ) ;
                EndPaint (hwnd, &ps);
            }
            break;

        default:                      
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

对于糟糕的缩进,我深表歉意。

最佳答案

我认为GetTextExtentPoint32是您想要的,以便您可以计算文本大小和长度。 Here是展示如何使用它的示例。

以防万一您的文本尺寸大于屏幕尺寸,您可以将 DT_WORDBREAK 标志添加到 DrawText调用-查看文档。

您需要创建字体并在设备上下文中选择它,然后 CreateFontIndirect可以帮助您——关注LOGFONT structure成员(member)这样你就可以创建你想要的字体。 Here就是这样做的一个例子。

尝试这样的事情:

case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint (hwnd, &ps);

        //create your own font
        HFONT oldFont, myFont; 
        // create logical font for menu
        LOGFONT lf = { sizeof(lf) };
        _tcscpy_s( lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Microsoft Sans Serif" );
        lf.lfHeight = -MulDiv( 12, GetDeviceCaps( hdc, LOGPIXELSY), 72);
        lf.lfWeight = FW_HEAVY;
        lf.lfItalic = FALSE;
        lf.lfUnderline = FALSE;

        myFont = CreateFontIndirect(&lf);

        //select your font into device context
        oldFont = (HFONT)SelectObject( hdc, myFont );

        GetClientRect(hwnd,&rc);
        DrawText (hdc, TEXT("Sample Text!"), -1, &rc, 
            DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_WORDBREAK ) ;

        //cleanup
        SelectObject( hdc, oldFont );
        DeleteObject( myFont );

        EndPaint (hwnd, &ps);
    }
    return 0L;

case WM_GETMINMAXINFO: 
    {
        SIZE sz;
        HDC hdc = GetDC( hwnd );
        LPTSTR myString = TEXT( "Sample text here" );

        //create your own font 
        HFONT oldFont, myFont; 

        // create logical font for menu
        LOGFONT lf = { sizeof(lf) };
        _tcscpy_s( lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Microsoft Sans Serif" );
        lf.lfHeight = -MulDiv( 12, GetDeviceCaps( hdc, LOGPIXELSY), 72);
        lf.lfWeight = FW_HEAVY;
        lf.lfItalic = FALSE;
        lf.lfUnderline = FALSE;

        myFont = CreateFontIndirect(&lf);

        //select your font into device context
        oldFont = (HFONT)SelectObject( hdc, myFont );

        //get font dimensions
        GetTextExtentPoint32( hdc, myString, _tcslen( myString ), &sz );

        ((MINMAXINFO*)lParam)->ptMinTrackSize.x = sz.cx; 
        ((MINMAXINFO*)lParam)->ptMinTrackSize.y = sz.cy; 

        //cleanup
        SelectObject( hdc, oldFont );
        DeleteObject( myFont );
        ReleaseDC( hwnd, hdc );
    }
break;

如果您还有其他问题,请发表评论。

致以诚挚的问候。

关于api - Win 32 API 设置窗口最小尺寸以保持文本完全可见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21657447/

相关文章:

python - 如何在postman的Body中输入两个input

c - pthread_mutex_unlock 不是原子的

PHP 显示 CMD 命令提示符窗口 (Windows)

python - 更改 PyCharm 中的默认窗口位置

C++ 如何使用 CreateProcess 来处理进程?

javascript - 使用API​​停止YouTube视频时如何显示缩略图?

php - Infusionsoft 添加联系人时出错(isdk)

api - 使用 Evernote API 为新的 Evernote 网页编辑器生成开放链接

c++ - 热键控制键码困惑

c - 对话框不工作 - win32 api