CComboBoxEx 调试断言失败:afxcmn2.inl 第 334 行
CComboBoxEx debug assert failure: afxcmn2.inl Line 334
请注意,我发现我需要添加 COMBOBOXEXITEM
值,就像 LVITEM
基于这本书:Image Lists and ComboBoxEx Controls | Programming Windows with MFC, Second Edition (flylib.com)
仅供参考,我在 SetImageList
调用中收到上述错误:
// Add color icons to combobox
for (int nCount = 0; nCount < m_colorBarTemplateFiles.GetCount(); nCount++) {
CBitmap colorTemplateBitmap;
const CString fname = colorBarTemplateDirectory + "\" + m_colorBarTemplateImageFileNames[nCount];
HANDLE colorTemplateImageHandle = LoadImage(0, fname, IMAGE_BITMAP, 16, 16, LR_LOADFROMFILE);
colorTemplateBitmap.FromHandle((HBITMAP)colorTemplateImageHandle);
m_colorBarTemplateImages.Add(&colorTemplateBitmap, (COLORREF)0xFFFFFF);
}
SetImageList(&m_colorBarTemplateImages);
在我 link 的书中,作者写了这段代码(顺便说一句,我已经购买了这本书,希望能附带 CD,但它要再过 3 周才能到):
m_il.Create (IDB_IMAGES, 16, 1, RGB (255, 0, 255));
SetImageList (&m_il);
但不幸的是,网站上的代码没有 *.rc 文件:
所以不知道他是怎么设置的IDB_IMAGES
。据我了解,IDB_IMAGES是一个很大的位图,被分成不同的图标,但不清楚如何在MFC中设置它。
这是afxcmn2.inl第334行:
_AFXCMN_INLINE CImageList* CComboBoxEx::SetImageList(_In_ CImageList* pImageList)
{ ASSERT(::IsWindow(m_hWnd)); return CImageList::FromHandle((HIMAGELIST) ::SendMessage(m_hWnd, CBEM_SETIMAGELIST, 0, (LPARAM)pImageList->GetSafeHandle())); }
所以我没有正确创建句柄。我还查看了其他帖子,例如:
visual c++ - How to add Images to CListCtrl in MFC - Stack Overflow
ccombobox - MFC CComboBoxEx icon update issue - Stack Overflow
CImageList Class | Microsoft Docs
CComboBoxEx Class | Microsoft Docs
你有什么建议吗? TIA.
更新:
请注意,我刚刚了解到我需要能够在运行时动态添加这些颜色,所以事实证明我将无法使用 *.rc
文件和 CBitmap
s .相反,我将不得不研究在 OnPaint
或 OnDraw
中的 ComboBoxEx
添加一个彩色区域,以某种方式使用类似这样的东西:
COLORREF itemColor = colorArray[subitem][item];
CRect rect;
GetSubItemRect(item, subitem, LVIR_LABEL, rect);
CDC* pDc = GetDC();
pDc->FillRect(rect, &CBrush(itemColor));
ReleaseDC(pDc);
所以我会及时通知您我的发现。
这就是我在不使用 *.rc 文件或 *.bmp 文件的情况下动态地将色样添加到组合框的方式。在父 windows class OnCreate
函数中,关键参数是 CBS_OWNERDRAWFIXED
,这会导致每次用户打开组合框时调用 DrawItem
函数:
int ParentToolbarWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// ...
CRect rect;
int toolbarButtonIndex = 0;
wndToolBar.GetItemRect(toolbarButtonIndex, &rect);
CSize colorSwatchSize = pDC->GetTextExtent("1234567");
rect.left = rect.right;
rect.right = rect.left + colorSwatchSize.cx + 60;
if (!wndToolBar.cmbColor.Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | WS_VSCROLL | CBS_HASSTRINGS | CBS_OWNERDRAWFIXED,
rect, &wndToolBar, IDC_COMBO_XLINE)) {
// error message...
return -1;
}
// ...
UpdateCombobox();
// ...
}
void ParentToolbarWindow::UpdateCombobox()
{
wndToolBar.cmbColor.ResetContent();
// Get input value CStringArray "colorSwatchNames" for combobox...
for (int i = 0; i < colorSwatchNames.GetCount(); i++) {
if (wndToolBar.cmbColor.AddString(colorSwatchNames[i]) == CB_ERR || wndToolBar.cmbColor.AddString(colorSwatchNames[i]) == CB_ERRSPACE) {
AfxMessageBox("Error setting up combo");
break;
}
}
wndToolBar.cmbColor.SetCurSel(0);
}
这里是我实际绘制色样和文本的地方:
void CColorCombo::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// ...
CRect itemRect(lpDrawItemStruct->rcItem);
CRect blockRect(itemRect);
// ... setup rect sizes and other setup steps
// Draw color swatch as columns, each one pixel wide where inputColors is CStringArray
for (int i = 0; i < inputColors.GetCount(); i++) {
CString inputColorLine = inputColors[i];
// read and tokenize inputColors into inputColorLine...
int red = atoi(inputColorLine[0]);
int green = atoi(inputColorLine[1]);
int blue = atoi(inputColorLine[2]);
COLORREF color = RGB(red, green, blue);
CPen* pen = new CPen(PS_SOLID, 1, color);
dc.SelectObject(pen);
dc.MoveTo(blockRect.left + i, blockRect.top);
dc.LineTo(blockRect.left + i, blockRect.bottom);
if (pen != NULL) delete pen;
}
}
请注意,我发现我需要添加 COMBOBOXEXITEM
值,就像 LVITEM
基于这本书:Image Lists and ComboBoxEx Controls | Programming Windows with MFC, Second Edition (flylib.com)
仅供参考,我在 SetImageList
调用中收到上述错误:
// Add color icons to combobox
for (int nCount = 0; nCount < m_colorBarTemplateFiles.GetCount(); nCount++) {
CBitmap colorTemplateBitmap;
const CString fname = colorBarTemplateDirectory + "\" + m_colorBarTemplateImageFileNames[nCount];
HANDLE colorTemplateImageHandle = LoadImage(0, fname, IMAGE_BITMAP, 16, 16, LR_LOADFROMFILE);
colorTemplateBitmap.FromHandle((HBITMAP)colorTemplateImageHandle);
m_colorBarTemplateImages.Add(&colorTemplateBitmap, (COLORREF)0xFFFFFF);
}
SetImageList(&m_colorBarTemplateImages);
在我 link 的书中,作者写了这段代码(顺便说一句,我已经购买了这本书,希望能附带 CD,但它要再过 3 周才能到):
m_il.Create (IDB_IMAGES, 16, 1, RGB (255, 0, 255));
SetImageList (&m_il);
但不幸的是,网站上的代码没有 *.rc 文件:
所以不知道他是怎么设置的IDB_IMAGES
。据我了解,IDB_IMAGES是一个很大的位图,被分成不同的图标,但不清楚如何在MFC中设置它。
这是afxcmn2.inl第334行:
_AFXCMN_INLINE CImageList* CComboBoxEx::SetImageList(_In_ CImageList* pImageList)
{ ASSERT(::IsWindow(m_hWnd)); return CImageList::FromHandle((HIMAGELIST) ::SendMessage(m_hWnd, CBEM_SETIMAGELIST, 0, (LPARAM)pImageList->GetSafeHandle())); }
所以我没有正确创建句柄。我还查看了其他帖子,例如:
visual c++ - How to add Images to CListCtrl in MFC - Stack Overflow
ccombobox - MFC CComboBoxEx icon update issue - Stack Overflow
CImageList Class | Microsoft Docs
CComboBoxEx Class | Microsoft Docs
你有什么建议吗? TIA.
更新:
请注意,我刚刚了解到我需要能够在运行时动态添加这些颜色,所以事实证明我将无法使用 *.rc
文件和 CBitmap
s .相反,我将不得不研究在 OnPaint
或 OnDraw
中的 ComboBoxEx
添加一个彩色区域,以某种方式使用类似这样的东西:
COLORREF itemColor = colorArray[subitem][item];
CRect rect;
GetSubItemRect(item, subitem, LVIR_LABEL, rect);
CDC* pDc = GetDC();
pDc->FillRect(rect, &CBrush(itemColor));
ReleaseDC(pDc);
所以我会及时通知您我的发现。
这就是我在不使用 *.rc 文件或 *.bmp 文件的情况下动态地将色样添加到组合框的方式。在父 windows class OnCreate
函数中,关键参数是 CBS_OWNERDRAWFIXED
,这会导致每次用户打开组合框时调用 DrawItem
函数:
int ParentToolbarWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// ...
CRect rect;
int toolbarButtonIndex = 0;
wndToolBar.GetItemRect(toolbarButtonIndex, &rect);
CSize colorSwatchSize = pDC->GetTextExtent("1234567");
rect.left = rect.right;
rect.right = rect.left + colorSwatchSize.cx + 60;
if (!wndToolBar.cmbColor.Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | WS_VSCROLL | CBS_HASSTRINGS | CBS_OWNERDRAWFIXED,
rect, &wndToolBar, IDC_COMBO_XLINE)) {
// error message...
return -1;
}
// ...
UpdateCombobox();
// ...
}
void ParentToolbarWindow::UpdateCombobox()
{
wndToolBar.cmbColor.ResetContent();
// Get input value CStringArray "colorSwatchNames" for combobox...
for (int i = 0; i < colorSwatchNames.GetCount(); i++) {
if (wndToolBar.cmbColor.AddString(colorSwatchNames[i]) == CB_ERR || wndToolBar.cmbColor.AddString(colorSwatchNames[i]) == CB_ERRSPACE) {
AfxMessageBox("Error setting up combo");
break;
}
}
wndToolBar.cmbColor.SetCurSel(0);
}
这里是我实际绘制色样和文本的地方:
void CColorCombo::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// ...
CRect itemRect(lpDrawItemStruct->rcItem);
CRect blockRect(itemRect);
// ... setup rect sizes and other setup steps
// Draw color swatch as columns, each one pixel wide where inputColors is CStringArray
for (int i = 0; i < inputColors.GetCount(); i++) {
CString inputColorLine = inputColors[i];
// read and tokenize inputColors into inputColorLine...
int red = atoi(inputColorLine[0]);
int green = atoi(inputColorLine[1]);
int blue = atoi(inputColorLine[2]);
COLORREF color = RGB(red, green, blue);
CPen* pen = new CPen(PS_SOLID, 1, color);
dc.SelectObject(pen);
dc.MoveTo(blockRect.left + i, blockRect.top);
dc.LineTo(blockRect.left + i, blockRect.bottom);
if (pen != NULL) delete pen;
}
}