如何在运行时正确设置列表框的滚动条?

问题描述 投票:0回答:2

我这样创建了一个lsitbox:

HWND hLstBx = CreateWindowEx(WS_EX_CLIENTEDGE, "Listbox", NULL, WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL, 10, 10, 300, 500, hWnd, (HMENU)ID_LSTBX, (HINSTANCE)GetWindowLong(GWL_HINSTANCE, hWnd), NULL;


//SendMessage(hLstBx, LB_SETHORIZONTALEXTENT, (WPARAM)1000, 0);
  • 上面它成功创建了一个水平滚动条,但我想要的是:

如何在运行时根据长度最长的项设置值?

请不要像MFC中那样说,而只是

win32

提前谢谢您。

winapi visual-c++ listbox
2个回答
3
投票

天下没有免费的午餐,如果你想打电话给

LB_SETHORIZONTALEXTENT
LB_SETCOLUMNWIDTH
你必须自己测量每个项目的文本以找出正确的像素大小。

每次添加/删除项目或更改控件字体时,您都需要测量每个项目。将控件字体 (

WM_GETFONT
) 选择到 HDC 中,然后使用
GetTextExtentPoint32
DrawText(..., DT_CALCRECT)
测量文本。您可能还想添加一些填充,也许并考虑垂直滚动条(如果可见)。您可以通过使用
(2 * GetSystemMetrics(SM_CXEDGE))
/
LB_SETITEMDATA
缓存宽度来优化此功能,这样您只需在添加新项目时计算其大小。

一旦知道所有项目的宽度,您就可以设置最大项目的范围。

LB_GETITEMDATA

这里有一个 
MFC 示例

,它对控件进行子类化并为您完成所有操作,但没有任何 MFC 特定内容可以阻止您在普通 win32 中执行相同操作...


0
投票

UINT CalcLBItemWidth(HWND hLB, LPCTSTR Text) { RECT r; HDC hLBDC = GetDC(hLB); HDC hDC = CreateCompatibleDC(hLBDC); HFONT hFont = (HFONT) SendMessage(hLB, WM_GETFONT, 0, 0); HGDIOBJ hOrgFont = SelectObject(hDC, hFont); ZeroMemory(&r, sizeof(r)); DrawText(hDC, Text, -1, &r, DT_CALCRECT|DT_SINGLELINE|DT_NOCLIP); SelectObject(hDC, hOrgFont); DeleteDC(hDC); ReleaseDC(hLB, hLBDC); return (r.right - r.left) + (2 * GetSystemMetrics(SM_CXEDGE)); } static LRESULT CALLBACK MainWndProc(HWND hWnd, UINT Msg, WPARAM wp, LPARAM lp) { switch(Msg) { case WM_CREATE: { HWND hLB = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTBOX, NULL, WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|LBS_NOINTEGRALHEIGHT|LBS_DISABLENOSCROLL, 10, 10, 200, 100, hWnd, (HMENU)666, g_hInst, NULL); static const LPCTSTR strings[] = { TEXT("Foo"), TEXT("Foo bar"), TEXT("Foo bar baaaaaaaaaaaaaaaz") }; UINT largest = 0; for (UINT i = 0; i < 33; ++i) { UINT temp = CalcLBItemWidth(hLB, strings[i%3]); if (temp > largest) largest = temp; SendMessage(hLB, LB_ADDSTRING, 0, (LPARAM) strings[i%3]); } SendMessage(hLB, LB_SETHORIZONTALEXTENT, largest, 0); } break; ...

您应该在 wParam(第三个)参数中设置要滚动的像素数。
因此,如果您的列表框宽度为 600,并且您的数据需要大约 800 像素,则应将 wParam 设置为 800。

您可以使用 GetTextExtentPoint32A() 获取字符串的像素数量。例如:

SendMessage(scrollbarHWND, LB_SETHORIZONTALEXTENT, size in pixels, 0);

您将获得字符串在屏幕上显示的像素大小(以 lineSizeInPixels 表示)。对于水平滚动条,您可以通过以下方式获取它:

hdc = GetDC(0); string line = "Hello World"; SIZE lineSizeInPixels; GetTextExtentPoint32A(hdc, line.c_str(), line.size(), &lineSizeInPixels);

此消息有一个
说明

。以及 GetTextExtentPoint32A 的指令

© www.soinside.com 2019 - 2024. All rights reserved.