對CXListCtrl的項ComboBox顯示值改變的響應方法

kason.發表於2020-12-11


前言

在開發過程中,使用XListCtrl來豐富列表的使用,從而發現對項ComboBox的改變響應沒有好的方法入手,既有一下問題過程,現解決記錄互相分享,下拉到底直接檢視解決方法。


一、開發需求

在這裡插入圖片描述

如上圖所示,當資料型別改變時需要改變內容中的顯示方式(可選框或者輸入框)。

二、尋找解決方法

1.用ComboBox的CBN_SELCHANGE訊息進行嘗試

程式碼如下(示例):

//CXListCtrl列表的變數 CXListCtrl m_list;
DDX_Control(pDX, IDC_LIST2, m_list);

//訊息繫結函式 嘗試繫結在列表上
ON_CBN_SELCHANGE(IDC_LIST2, &CModelConfigDlg::OnSelchangeComboStyle)

//Combox控制元件的生成方式如下,所以沒有物件可以直接繫結
m_list.SetComboBox(nItem, 4,
		TRUE,		// enable combobox
		&(CStringArray),		// pointer to persistent CStringArray
		5,			// size of dropdown
		0,			// initial combo selection
		FALSE);		// sort CStringArray

結果:此方法沒有響應

2.考慮XListCtrl是否有自帶的響應訊息

A.獲得WM_XLISTCTRL_COMBO_SELECTION訊息

百度查詢到以下內容:
XListCtrl中自定義了訊息WM_XLISTCTRL_COMBO_SELECTION,寫個該訊息的響應函式就可以了。
來自此CSDN問答:如何獲取CXListCtrl中ComboBox的下拉事件

B.嘗試進行訊息繫結和獲取

//響應介面宣告
afx_msg LRESULT OnXlistCombo(WPARAM wParam, LPARAM lParam);
//訊息繫結
ON_MESSAGE(WM_XLISTCTRL_COMBO_SELECTION, &CModelConfigDlg::OnXlistCombo)

結果:此方法沒有響應

C.對CXListCtrl原始碼分析

上述步驟不能實現,考慮是否CListCtrl對此訊息有特殊處理,以下貼出部分原始碼追蹤過程

//在XListCtrl.cpp註冊了此訊息
XLISTCTRLLIBDLLEXPORT UINT WM_XLISTCTRL_COMBO_SELECTION  = ::RegisterWindowMessage(_T("WM_XLISTCTRL_COMBO_SELECTION"));

//查詢此訊息的傳送位置
void CXListCtrl::OnTimer(UINT nIDEvent)
{
 //忽略部分原始碼.......
 else if (nIDEvent == 3)		// get combo listbox selection, then close combo listbox
	{
		//忽略部分原始碼.......
		CWnd *pWnd = GetParent();
		if (!pWnd)
			pWnd = GetOwner();
		if (pWnd && ::IsWindow(pWnd->m_hWnd))
			pWnd->SendMessage(WM_XLISTCTRL_COMBO_SELECTION, 
						m_nComboItem, m_nComboSubItem);
	//忽略部分原始碼.......
}

//可知在定時器中 去當接收到3的觸發條件進行傳送訊息 接著檢視定時器啟動位置
// OnComboReturn
LRESULT CXListCtrl::OnComboComplete(WPARAM, LPARAM)
{
	XLISTCTRL_TRACE(_T("in CXListCtrl::OnComboComplete\n"));
	SetTimer(3, 50, NULL);
	return 0;
}
//查到一個訊號相應函式  繫結介面如下
ON_REGISTERED_MESSAGE(WM_XCOMBOLIST_COMPLETE, OnComboComplete)
//去查詢訊號WM_XCOMBOLIST_COMPLETE未有發現從而對ON_REGISTERED_MESSAGE這個不常見的繫結方法進行分析

D.ON_REGISTERED_MESSAGE自定義訊息繫結介面

通過百度查詢得到如下
注意事項:
  傳送訊息的-MyMessageDlg.cpp前也要定義
  static UINT WM_MY_MESSAGE=RegisterWindowMessage(“Message”);
  接受訊息的-MessageTestView.cpp前也要定義
  static UINT WM_MY_MESSAGE=RegisterWindowMessage(“Message”);
  RegisterWindowMessage(“Message”)中""的內容是什麼不重要,寫什麼都可以,單必須
  傳送者與接受者是一樣的內容,例如:“Message”
來自此部落格 傳送自定義訊息:ON_MESSAGE和ON_REGISTERED_MESSAGE的差別(轉)


解決方法

涉及程式碼如下

//先在接收訊息所在的CPP進行訊息註冊
static UINT WM_MY_MESSAGE = RegisterWindowMessage(_T("WM_XLISTCTRL_COMBO_SELECTION"));
//繫結訊息
ON_REGISTERED_MESSAGE(WM_MY_MESSAGE, OnXlistCombo)
//訊息響應函式
afx_msg LRESULT CModelConfigDlg::OnXlistCombo(WPARAM wParam, LPARAM lParam)
{
	CString strTittle;
	strTittle.Format(_T("自定義訊息引數:x=%d,y=%d"), wParam, lParam);
	SetWindowText(strTittle);
	return LRESULT();
}

至此,每次ComboBox的改變,都可以在響應函式中得到在XListCtrl上對應的行列位置,即可在響應函式中實現對應功能要求

相關文章