我主要来自.NET背景,但是我必须为Windows控件完成一项小任务,特别是ComboBox。
据我所知,ComboBox需要CBS_SORT消息来按字母顺序对项目进行排序。当我使用CB_ADDSTRING标志向组合框添加字符串时,这对我来说很好。
我试图让ComboBox使用反向(或其他自定义)排序顺序。
如果我使用CreateWindow
来制作我的组合框,有没有办法可以使用它返回的HWND并连接一个处理WM_COMPAREITEM消息的自定义方法?
这是Microsoft的文章,讨论了处理WM_COMPAREITEM消息的问题。 https://msdn.microsoft.com/en-us/library/windows/desktop/bb775791(v=vs.85).aspx
修改 我想一个解决方法是使用CB_INSERTSTRING标志进行自定义排序,但如果可以的话,我真的更喜欢用其他语言实现类似于CompareTo的东西。
修改 值得一提的是,调用CreateWindow的类(没有使用CBS_HASSTRINGS标志)有一个WM_COMMAND消息的消息处理程序。它在HIWORD中切换以处理CBN_SELCHANGE等通知。
我查看了Combo框的文档,发现CBN_SELCHANGE和WM_COMPAREITEM之间存在细微差别。
当用户更改组合框的列表框中的当前选择时,将发送CBN_SELCHANGE通知代码。用户可以通过单击列表框或使用箭头键来更改选择。组合框的父窗口以WM_COMMAND消息的形式接收此通知,并在wParam参数的高位字中使用CBN_SELCHANGE。
以下是关于WM_COMPAREITEM
的内容系统发送WM_COMPAREITEM消息以确定新项目在所有者绘制的组合框或列表框的排序列表中的相对位置。每当应用程序添加新项目时,系统都会将此消息发送给使用CBS_SORT或LBS_SORT样式创建的组合框或列表框的所有者。
据我所知,传递给CreateWindow方法的DWORD样式是WS_VISIBLE | WS_CHILD | WS_VSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWNLIST | CBS_SORT
也许问题在于创建的组合框不是"所有者绘制的"组合框? 如果是这种情况,我需要找到一种方法,但只处理WM_COMPAREITEM案例,而不是任何其他自定义绘画代码。
更新 我创建了没有CBS_HASSTRINGS的ComboBox和CB_OWNERDRAWFIXED(然后让我处理WM_COMPAREITEM消息)。
这是消息处理代码
LRESULT MyComboBoxParent::OnCompareItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
//umsg is always wm_compareitem
COMPAREITEMSTRUCT* pCompareItemStruct = (COMPAREITEMSTRUCT*)lParam;
ATLASSERT(pCompareItemStruct->CtlType == ODT_COMBOBOX); //this assert works
int iItemId1 = pCompareItemStruct->itemID1;
int iItemId2 = pCompareItemStruct->itemID2;
LPCTSTR item1 = (LPCTSTR)pCompareItemStruct ->itemData1;
ATLASSERT(item1 != NULL);
LPCTSTR item2 = (LPCTSTR)pCompareItemStruct->itemData2;
ATLASSERT(item2 != NULL);
int iStringCompareResult = _tcscmp(item1, item2);
//should reverse the sorting order
int iReturn = -1 * iStringCompareResult;
return iReturn;
}
//and the existing code snippet that adds the values to the combobox
::SendMessage(m_hwndCombo,CB_ADDSTRING,0,(LPARAM) ((wchar_t*)bstr_tDisplayedValue))
来自COMPAREITEMSTRUCT的数据真的很奇怪。 我按顺序将以下值添加到组合框中。
z,y和x都遵循相同的模式。我可能在互联网上找到了另一个有同样问题的人here。但很难说肯定。