使用 C++ MFC,并有一个所有者绘制的 CListBox,我在每个列表框项目中都有文本和 CLinkCtrl。我的问题是 CLinkCtrl 并不总是我希望在上下滚动时看到的控件,而所有者绘制的文本总是正确的。
存在另一个错误,底部的列表项之一几乎总是不显示链接控件。
以下是部分截图:
// 这是在滚动之后,其中列表链接项 的顺序不正确
当我选择一个控件时,UI 有时会更新为正确的控件值。
我会尝试添加尽可能多的信息,希望能够看到错误。
分为三部分:
1: ListBox Configuration, 自己绘制
2:填充 ListBox,这会将“项目”添加到 CListBox:
std::thread t([=]() {
myMutex.lock(); // acquire the mutex
// Disable redrawing of the control...
calListBox.EnableWindow(FALSE);
calListBox.SetRedraw(FALSE);
// clear all the items
for (int i = 0; i < calListBox.GetCount(); i++)
{
LPARAM lpData = calListBox.GetItemData(i);
CalListBoxItem* item = reinterpret_cast<CalListBoxItem*>(lpData);
delete item;
}
calListBox.ResetContent();
// for loop
int index = calListBox.SendMessage(LB_ADDSTRING, 0, 0);
if (index == LB_ERR) {
DWORD dwError = GetLastError();
}
else {
CalListBoxItem* pItem = new CalListBoxItem(description, htmllink, index);
calListBox.SendMessage(LB_SETITEMDATA, index, reinterpret_cast<DWORD_PTR>(pItem));
calListBox.SendMessage(LB_SETITEMHEIGHT, index, 100);
}
// end for loop
calListBox.SetRedraw(TRUE); // Re-enable redrawing of the control
calListBox.EnableWindow(TRUE);
myMutex.unlock(); // release the mutex
});
t.detach();
// here is the CalListBoxItem, it just holds the description, index and the htmllink control
public:
~CalListBoxItem();
CalListBoxItem(const std::string& desc, const std::string& link, int index)
: m_desc(desc), m_link(link), originalIndex(index)
{
linkCtrl = new CCustLinkCtrl();
}
public:
int originalIndex;
CCustLinkCtrl* linkCtrl;
std::string m_desc;
std::string m_link;
3:有一个CListBox,大部分是绘制列表项, 其中一些绘制文本,100% 有效,只是我添加的控件具有一些随机性。
这里是扩展 CListBox 的 Custom CalListBox 的一些位
// The AddLinkCtrl function
void CalListBox::AddLinkControl(CLinkCtrl* linkCtrl, CRect& rect, int nItemIndex, CString text, CString htmlLink) {
if (!linkCtrl) {
return;
}
if (::IsWindow(linkCtrl->m_hWnd)) {
CString strIndex;
strIndex.Format(_T(" u:%d"), nItemIndex); // convert nItemIndex to CString
CString strText = text + strIndex; // concatenate text and strIndex
linkCtrl->SetWindowTextW(strText);
linkCtrl->Invalidate();
linkCtrl->UpdateWindow();
return; // the control has already been created
}
// Create the control as a child of the list box
linkCtrl->Create(_T(""), WS_CHILD | WS_VISIBLE | DT_VCENTER | SS_NOTIFY, rect, this, IDC_LINK_CTRL_LIST_ITEM + nItemIndex);
CString strIndex;
strIndex.Format(_T(" %d"), nItemIndex); // convert nItemIndex to CString
CString strText = text + strIndex; // concatenate text and strIndex
linkCtrl->SetWindowTextW(strText);
//linkCtrl->SetWindowTextW(text + nItemIndex);
linkCtrl->SetItemUrl(0, htmlLink); // must be after text is set, else the link does not work
linkCtrl->SetFont(linkFont);
linkCtrl->Invalidate();
linkCtrl->UpdateWindow();
}
这里是 DrawItem,显示了部分位
void CalListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (lpDrawItemStruct->itemData == 0) {
return;
}
/*
CalListBoxItem* pItem = reinterpret_cast<CalListBoxItem*>(GetItemData(lpDrawItemStruct->itemID));
if (pItem == nullptr) {
return;
}
*/
CalListBoxItem* pItem = reinterpret_cast<CalListBoxItem*>(lpDrawItemStruct->itemData);
if (pItem == nullptr) {
return;
}
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
if (pDC == nullptr) {
return;
}
// Clip the region, not to draw outside of the boundary
/*
CRgn clipRgn;
clipRgn.CreateRectRgnIndirect(&lpDrawItemStruct->rcItem);
pDC->SelectClipRgn(&clipRgn);
*/
CRect rect(lpDrawItemStruct->rcItem);
// snip
AddLinkControl(pItem->linkCtrl, leftRect2, pItem->originalIndex, L"<a>Link</a>", leftText2);