CCombobox字符串插入会产生乱码

我通过扩展ccomboBox来实现DrawItem()函数来创建自定义CCustomCombo。这是它的代码。

void CCustomCombo::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
    ASSERT( lpDrawItemStruct->CtlType == ODT_COMBOBOX );
    LPCTSTR lpszText = ( LPCTSTR ) lpDrawItemStruct->itemData;
    ASSERT( lpszText != NULL );

    if ( lpDrawItemStruct->itemID == -1 || lpszText == NULL)
        return;

    CDC dc;
    dc.Attach( lpDrawItemStruct->hDC );

    // Save these value to restore them when done drawing. 
    COLORREF crOldTextColor = dc.GetTextColor();
    COLORREF crOldBkColor = dc.GetBkColor();

    // If this item is selected,set the background color  
    // and the text color to appropriate values. Erase 
    // the rect by filling it with the background color. 
    if ( ( lpDrawItemStruct->itemaction & ODA_SELECT ) &&
        ( lpDrawItemStruct->itemState  & ODS_SELECTED ) )
    {
        dc.SetTextColor( ::GetSysColor( COLOR_HIGHLIGHTTEXT ) );
        dc.SetBkColor( ::GetSysColor( COLOR_HIGHLIGHT ) );
        dc.FillSolidRect( &lpDrawItemStruct->rcItem,::GetSysColor( COLOR_HIGHLIGHT ) );
    }
    else
    {
        dc.FillSolidRect( &lpDrawItemStruct->rcItem,crOldBkColor );
    }

    // Draw the text. 
    dc.DrawText(
        lpszText,( int ) _tcslen( lpszText ),&lpDrawItemStruct->rcItem,DT_CENTER | DT_SINGLELINE | DT_VCENTER );

    // Reset the background color and the text color back to their 
    // original values. 
    dc.SetTextColor( crOldTextColor );
    dc.SetBkColor( crOldBkColor );

    dc.Detach();
}

创作部分-

m_selectionCombo.Create( WS_VSCROLL |
        CBS_DROPDOWNLIST | WS_VISIBLE | WS_TABSTOP| CBS_OWNERDRAWFIXED,rect,&m_wndSelectionBar,ID_TEMP_BTN))

现在问题在于将字符串项添加到组合框。当我使用字符串对象时,它总是显示一些乱码。

m_selectionCombo.InsertString(0,"One"); //works

char * one = "one"; 
m_selectionCombo.InsertString(0,one ); //works

CString one = "one"; 
m_selectionCombo.InsertString(0,one ); //shows gibberish

std::string one = "one";
char *cstr = &one[0];
m_wndSelectionBar.m_selectionCombo.InsertString(0,cstr ); //shows gibberish

对于AddString出现相同的结果。问题是我必须将一组双打插入组合框。而且我无法在不显示乱码的情况下将它们转换为字符串。我尝试了六种转换方法,但均无效果。我真是机智!

有趣的是,在我使用ccomboBox而不是我的CCustomCombo类/ CBS_OWNERDRAWFIXED之前,它能完美地工作。我尝试使用CBS_HASSTRINGS,但是它什么也没显示,甚至没有乱码,因此以某种方式,甚至连CBS_HASSTRINGS都没有添加字符串。

我需要自定义Draw方法,因为我计划突出显示某些下拉菜单项。我正在使用Windows 32和VS 2017。

任何帮助将不胜感激。 谢谢。

wyq_1234 回答:CCombobox字符串插入会产生乱码

LPCTSTR lpszText = (LPCTSTR)lpDrawItemStruct->itemData;

OwnerDraw函数正在查看itemDataitemData是使用CComboBox::SetItemData分配的。不能使用InsertString或其他文本函数来分配它。

char * one = "one"; 
m_selectionCombo.InsertString(0,one ); //works

未设置CBS_HASSTRINGS时,字符串和项目数据存储在相同的存储地址中。

另请参阅CB_SETITEMDATA的文档

  

如果指定的项目在创建的所有者绘制的组合框中,而没有   CBS_HASSTRINGS样式,此消息替换了   CB_ADDSTRING或CB_INSERTSTRING消息的lParam参数   将该项目添加到了组合框中。

因此,基本上itemData返回一个指针one,在这种情况下它可以正常工作。

CString one = "one"; 
m_selectionCombo.InsertString(0,one ); //shows gibberish

这一次在堆栈上创建字符串,该函数存在后销毁。 itemData指向无效的地址。


解决方案:

如果要使用InsertString/AddString设置文本,请确保已设置CBS_HASSTRINGS。并使用GetLBText读取字符串。示例:

//LPCTSTR lpszText = (LPCTSTR)lpDrawItemStruct->itemData; <- remove this

if(lpDrawItemStruct->itemID >= GetCount())
    return;

CString str;
GetLBText(lpDrawItemStruct->itemID,str);
LPCTSTR lpszText = str;

否则,请使用SetItemData来设置数据,然后使用itemData来读取。

本文链接:https://www.f2er.com/3152207.html

大家都在问