CCombobox 字符串插入给出乱码
CCombobox string insertion gives gibberish
我通过扩展 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))
现在的问题是将字符串项添加到组合框。当我使用字符串对象时,它总是显示一些 unicode 乱码。
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 出现相同的结果。问题是我有一组必须插入组合框的双打。而且我无法在不显示乱码的情况下将它们转换为字符串。我尝试了六种转换方法,none 成功了。我真是无计可施了!
有趣的是,在我使用 CComboBox 而不是我的 CCustomCombo class/CBS_OWNERDRAWFIXED 之前,它工作得很好。我尝试使用 CBS_HASSTRINGS,但它没有显示任何内容,甚至没有显示乱码,所以不知怎的,字符串甚至没有被添加到 CBS_HASSTRINGS 中。
我需要自定义 Draw 方法,因为我打算突出显示某些下拉项。我正在使用 windows 32,VS 2017。
如有任何帮助,我们将不胜感激。
谢谢
LPCTSTR lpszText = (LPCTSTR)lpDrawItemStruct->itemData;
OwnerDraw 函数正在查看 itemData
。 itemData
使用 CComboBox::SetItemData
赋值。它不是使用 InsertString
或其他文本函数分配的。
char * one = "one";
m_selectionCombo.InsertString(0, one ); //works
不设置CBS_HASSTRINGS
时,字符串和item数据存放在同一个内存地址。
另请参阅 CB_SETITEMDATA
的文档
If the specified item is in an owner-drawn combo box created without
the CBS_HASSTRINGS style, this message replaces the value in the
lParam parameter of the CB_ADDSTRING or CB_INSERTSTRING message that
added the item to the combo box.
所以基本上 itemData
returns 一个指针 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
读取。
我通过扩展 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))
现在的问题是将字符串项添加到组合框。当我使用字符串对象时,它总是显示一些 unicode 乱码。
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 出现相同的结果。问题是我有一组必须插入组合框的双打。而且我无法在不显示乱码的情况下将它们转换为字符串。我尝试了六种转换方法,none 成功了。我真是无计可施了!
有趣的是,在我使用 CComboBox 而不是我的 CCustomCombo class/CBS_OWNERDRAWFIXED 之前,它工作得很好。我尝试使用 CBS_HASSTRINGS,但它没有显示任何内容,甚至没有显示乱码,所以不知怎的,字符串甚至没有被添加到 CBS_HASSTRINGS 中。
我需要自定义 Draw 方法,因为我打算突出显示某些下拉项。我正在使用 windows 32,VS 2017。
如有任何帮助,我们将不胜感激。 谢谢
LPCTSTR lpszText = (LPCTSTR)lpDrawItemStruct->itemData;
OwnerDraw 函数正在查看 itemData
。 itemData
使用 CComboBox::SetItemData
赋值。它不是使用 InsertString
或其他文本函数分配的。
char * one = "one"; m_selectionCombo.InsertString(0, one ); //works
不设置CBS_HASSTRINGS
时,字符串和item数据存放在同一个内存地址。
另请参阅 CB_SETITEMDATA
If the specified item is in an owner-drawn combo box created without the CBS_HASSTRINGS style, this message replaces the value in the lParam parameter of the CB_ADDSTRING or CB_INSERTSTRING message that added the item to the combo box.
所以基本上 itemData
returns 一个指针 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
读取。