计算带有图标的 CComboBoxEx 的最大下拉宽度
Working out the maximum drop-down width for a CComboBoxEx with icons
我在 CodeProject 上看过这篇关于动态设置 CComboBox
宽度的文章。
但是,我使用的是 CComboBoxEx
:
如您所见,最后一个条目已被裁剪。所以我想自动加宽下拉列表。
需要考虑的事实是,它们也是左侧图标的 space。所以这还不够好:
BOOL CMyComboBox::OnCbnDropdown()
{
// Reset the dropped width
CString str;
CRect rect;
int nWidth = 0;
int nNumEntries = GetCount();;
CClientDC dc(this);
int nSave = dc.SaveDC();
dc.SelectObject(GetFont());
for (int i = 0; i < nNumEntries; i++)
{
GetLBText(i, str);
int nLength = dc.GetTextExtent(str).cx;
if (nLength>nWidth)
nWidth = nLength;
}
nWidth += 2*::GetSystemMetrics(SM_CXEDGE) + 4;
// check if the current height is large enough for the items in the list
GetDroppedControlRect(&rect);
if (rect.Height() <= nNumEntries*GetItemHeight(0))
nWidth +=::GetSystemMetrics(SM_CXVSCROLL);
dc.RestoreDC(nSave);
SetDroppedWidth(nWidth);
return FALSE;
}
我们如何考虑左侧的图标?
这是有效的:
void CDatesComboBoxEx::OnCbnDropdown()
{
CString str;
CRect rect;
int nWidth = 0, nImageWidth = 0;
int nNumEntries = GetCount();
if (nNumEntries > 0)
{
// Get the width of an image list entry
auto pImageList = GetImageList();
if (pImageList != nullptr && pImageList->GetImageCount() > 0)
{
IMAGEINFO sInfo;
pImageList->GetImageInfo(0, &sInfo);
nImageWidth = sInfo.rcImage.right - sInfo.rcImage.left;
}
CClientDC dc(this);
int nSave = dc.SaveDC();
dc.SelectObject(GetFont());
for (int i = 0; i < nNumEntries; i++)
{
COMBOBOXEXITEM sItem;
TCHAR szBuffer[_MAX_PATH] = _T("");
sItem.mask = CBEIF_INDENT | CBEIF_TEXT;
sItem.iItem = i;
sItem.cchTextMax = _MAX_PATH;
sItem.pszText = szBuffer;
if (GetItem(&sItem))
{
int nLength = dc.GetTextExtent(szBuffer).cx + nImageWidth + (sItem.iIndent * 10);
if (nLength > nWidth)
nWidth = nLength;
}
}
nWidth += 2 * ::GetSystemMetrics(SM_CXEDGE) + 4;
// check if the current height is large enough for the items in the list
GetDroppedControlRect(&rect);
if (rect.Height() <= nNumEntries * GetItemHeight(0))
nWidth += ::GetSystemMetrics(SM_CXVSCROLL);
dc.RestoreDC(nSave);
SetDroppedWidth(nWidth);
}
}
结果:
我在 CodeProject 上看过这篇关于动态设置 CComboBox
宽度的文章。
但是,我使用的是 CComboBoxEx
:
如您所见,最后一个条目已被裁剪。所以我想自动加宽下拉列表。
需要考虑的事实是,它们也是左侧图标的 space。所以这还不够好:
BOOL CMyComboBox::OnCbnDropdown()
{
// Reset the dropped width
CString str;
CRect rect;
int nWidth = 0;
int nNumEntries = GetCount();;
CClientDC dc(this);
int nSave = dc.SaveDC();
dc.SelectObject(GetFont());
for (int i = 0; i < nNumEntries; i++)
{
GetLBText(i, str);
int nLength = dc.GetTextExtent(str).cx;
if (nLength>nWidth)
nWidth = nLength;
}
nWidth += 2*::GetSystemMetrics(SM_CXEDGE) + 4;
// check if the current height is large enough for the items in the list
GetDroppedControlRect(&rect);
if (rect.Height() <= nNumEntries*GetItemHeight(0))
nWidth +=::GetSystemMetrics(SM_CXVSCROLL);
dc.RestoreDC(nSave);
SetDroppedWidth(nWidth);
return FALSE;
}
我们如何考虑左侧的图标?
这是有效的:
void CDatesComboBoxEx::OnCbnDropdown()
{
CString str;
CRect rect;
int nWidth = 0, nImageWidth = 0;
int nNumEntries = GetCount();
if (nNumEntries > 0)
{
// Get the width of an image list entry
auto pImageList = GetImageList();
if (pImageList != nullptr && pImageList->GetImageCount() > 0)
{
IMAGEINFO sInfo;
pImageList->GetImageInfo(0, &sInfo);
nImageWidth = sInfo.rcImage.right - sInfo.rcImage.left;
}
CClientDC dc(this);
int nSave = dc.SaveDC();
dc.SelectObject(GetFont());
for (int i = 0; i < nNumEntries; i++)
{
COMBOBOXEXITEM sItem;
TCHAR szBuffer[_MAX_PATH] = _T("");
sItem.mask = CBEIF_INDENT | CBEIF_TEXT;
sItem.iItem = i;
sItem.cchTextMax = _MAX_PATH;
sItem.pszText = szBuffer;
if (GetItem(&sItem))
{
int nLength = dc.GetTextExtent(szBuffer).cx + nImageWidth + (sItem.iIndent * 10);
if (nLength > nWidth)
nWidth = nLength;
}
}
nWidth += 2 * ::GetSystemMetrics(SM_CXEDGE) + 4;
// check if the current height is large enough for the items in the list
GetDroppedControlRect(&rect);
if (rect.Height() <= nNumEntries * GetItemHeight(0))
nWidth += ::GetSystemMetrics(SM_CXVSCROLL);
dc.RestoreDC(nSave);
SetDroppedWidth(nWidth);
}
}
结果: