如何解决如何根据文本大小自动正确增长标签?
我确实在 WM_PAINT
中创建了一个新矩形,但为了更改文本,我还 SetWindowText()
,我需要一个 InvalidateRect()
所以它对我来说似乎很hacky。这样做的正确方法是什么?我不确定我是否正确计算了正确的高度和宽度。我曾尝试使用 WM_PAINT 中的 SetWindowPos()
进行增长,但它失败了,所以我切换到使用 Rectangle()
绘制它。我这样做是因为我想要文本 o 垂直居中,但静态控件不支持它,所以我自己去做了 paiting,这样我就可以使用 DrawText()
和 DT_CENTER | DT_SINGLELINE | DT_VCENTER
标志。以下是我处理 VM_PAINT
的方式:
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rt = {0};
GetClientRect(hwnd,&rt);
int height = rt.right - rt.left;
int width = rt.bottom - rt.top;
int len = GetwindowTextLength(hwnd);
wchar_t s[len+1];
GetwindowText(hwnd,s,len+1);
int flags = DT_CENTER | DT_SINGLELINE | DT_VCENTER;
HDC dc = BeginPaint(hwnd,&ps);
// calculate the width and height
DrawText(dc,-1,&rt,DT_CALCRECT | flags);
width += rt.right;
height += rt.bottom;
// update width and height
rt.right = width;
rt.bottom = height;
Rectangle(dc,rt.left,rt.top,rt.right,rt.bottom);
// this prevent from painting the border.
InflateRect(&rt,-1);
FillRect(dc,GetSysColorBrush(COLOR_BTNFACE));
SetBkMode(dc,TRANSPARENT);
DrawText(dc,flags);
EndPaint(hwnd,&ps);
return 0;
}
完整代码:
#pragma comment(lib,"user32.lib")
#pragma comment(lib,"Comctl32.lib")
#pragma comment(lib,"Gdi32.lib")
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <Commctrl.h>
#include <crtdbg.h>
#include <strsafe.h>
#include <string.h>
#include <assert.h>
LRESULT CALLBACK WndProc(HWND,UINT,WParaM,LParaM);
LRESULT CALLBACK ButtonProc(HWND hwnd,UINT uMsg,WParaM wParam,LParaM lParam);
WNDPROC oldButtonProc;
HINSTANCE ghInstance;
HWND hTab;
HFONT hdDfaultFont;
HWND btn;
enum
{
BTN_ID = 10,BTN2_ID,};
int WINAPI wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PWSTR pCmdLine,int nCmdshow)
{
MSG msg = {0};
HWND hwnd;
WNDCLASSW wc = {0};
wc.lpszClassName = L"Window";
wc.hInstance = hInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(0,IDC_ARROW);
//InitComControls();
if(!RegisterClass(&wc)) {
return -1;
}
int width = 540;
int height = 460;
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
int cx = (screenWidth - width) / 2;
int cy = (screenHeight - height) / 2;
hwnd = CreateWindowW(wc.lpszClassName,L"Window",WS_OVERLAPPEDWINDOW | WS_VISIBLE,cx,cy,width,height,NULL,hInstance,NULL);
ghInstance = hInstance;
while (GetMessage(&msg,0))
{
if (!IsDialogMessage(hwnd,&msg))
{
TranslateMessage(&msg);
dispatchMessage(&msg);
}
}
DeleteObject(hdDfaultFont);
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,LParaM lParam)
{
switch(msg)
{
case WM_CREATE:
{
btn =
CreateWindow(L"static",L"init text",SS_NOTIFY |
WS_VISIBLE | WS_CHILD | WS_TABSTOP,20,30,hwnd,(HMENU) BTN_ID,NULL);
oldButtonProc = (WNDPROC) SetwindowLongPtr(btn,GWLP_WNDPROC,(LONG_PTR) ButtonProc);
HWND btn2 =
CreateWindow(L"Button",L"Click me!",WS_VISIBLE | WS_CHILD | WS_TABSTOP,10,50,70,25,(HMENU) BTN2_ID,NULL);
SetDefaultFont(btn2);
}
break;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case BTN2_ID:
{
SetwindowText(btn,L"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0");
InvalidateRect(btn,TRUE);
}
break;
}
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}
LRESULT CALLBACK ButtonProc(HWND hwnd,LParaM lParam)
{
switch(msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rt = {0};
GetClientRect(hwnd,&rt);
int height = rt.right - rt.left;
int width = rt.bottom - rt.top;
int len = GetwindowTextLength(hwnd);
wchar_t s[len+1];
GetwindowText(hwnd,len+1);
int flags = DT_CENTER | DT_SINGLELINE | DT_VCENTER;
HDC dc = BeginPaint(hwnd,DT_CALCRECT | flags);
width += rt.right;
height += rt.bottom;
// update width and height
rt.right = width;
rt.bottom = height;
Rectangle(dc,rt.bottom);
InflateRect(&rt,&ps);
return 0;
}
break;
}
return CallWindowProc(oldButtonProc,lParam);
}
解决方法
您可以使用 GetTextExtentPoint32 来查找字符串长度,然后您无需进行计算。
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rt = { 0 };
GetClientRect(hwnd,&rt);
int len = GetWindowTextLength(hwnd);
wchar_t s[len + 1];
GetWindowText(hwnd,s,len + 1);
int flags = DT_CENTER | DT_SINGLELINE | DT_VCENTER;
HDC dc = BeginPaint(hwnd,&ps);
SIZE sz;
GetTextExtentPoint32(dc,len,&sz);
rt.right = sz.cx + 10; //I added 10 to make the display less crowded.
rt.bottom = sz.cy;
Rectangle(dc,rt.left,rt.top,rt.right,rt.bottom);
// this prevent from painting the border.
InflateRect(&rt,-1,-1);
FillRect(dc,&rt,GetSysColorBrush(COLOR_BTNFACE));
SetBkMode(dc,TRANSPARENT);
DrawText(dc,flags);
EndPaint(hwnd,&ps);
return 0;
}
,
为了回答 X
问题的 XY
部分,DT_VCENTER | DT_SINGLELINE
意味着单行文本,在这种情况下,具有 SS_CENTERIMAGE
样式的静态控件将使文本居中垂直文本。
SS_CENTERIMAGE
-
位图在包含它的静态控件中居中。控件未调整大小,因此对于控件来说太大的位图将被剪裁。 如果静态控件包含单行文本,则文本在客户区中垂直居中控制。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。