VC6.0里ComboBox碰到的问题(续)

在上一篇文章里《VC6.0里ComboBox碰到的问题》里面提到了“如果有两个下拉列表项,其中一个是另外一个的前缀字符串(比如“A”是“ABCD”的前缀字符串)。那么把下拉列表的CString类型的成员变量设置为较短的那个下拉列表项后(比如“A”),在界面中显示的却是较长的列表项(显示为“ABCD”)”。上文中对于这种现象的处理方法是使用“使用CComboBox::FindStringExact,然后再使用CComboBox::SetCurSel”,实际上就是放弃使用ComboBox的成员变量。可是如果一定要使用成员变量那怎么办呢?可以有如下几种办法。

1.写一个子类继承自CComboBox,然后重载CB_SELECTSTRING消息的处理函数
ON_MESSAGE(CB_SELECTSTRING, OnCBSelectString)

LRESULT OnCBSelectString(WPARAM wParam, LPARAM lParam);

LRESULT CMyCmbBox::OnCBSelectString(WPARAM wParam,LPARAM lParam)
{
	int nSel = FindStringExact(-1,(LPCTSTR)lParam);
	if(nSel != CB_ERR)
	{
		SetCurSel(nSel);
	}
	return nSel;
}
这也是我原先使用的方法。

2.这种方法更为简单,而且是MFC已经提供给我们的方法。
首先我们来看一下,在使用ClassWizard为一个CComboBox添加成员变量的时候,MFC为我们加了什么。
第一、它声明了一个CString类型的变量
第二、它把这个变量和控件“绑定”在一起。
怎么绑定的?

最直观的就是在DoDataExchange函数里加上这样一行

DDX_CBString(pDX, XXXXX, XXXXX);
这样UpdateData调用DoDataExchange,DoDataExchange调用DDX_CBString,最后由DDX_CBString负责把控件信息传给成员变量,或者把成员变量传会给控件。

同时MFC还提供了DDX_CBStringExact函数,在调用UpdateData(TRUE);时,它做的工作和DDX_CBString一样(其实就是直接调用DDX_CBString)。但是在使用UpdateData(FALSE),把成员变量传回控件时,它做的任务就不一样了。

//DDX_CBString和DDX_CBStringExact的源码都在VC源码的DLGDATA.cpp里
void AFXAPI DDX_CBString(CDataExchange* pDX, int nIDC, CString& value)
{
	HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
	if (pDX->m_bSaveAndValidate)
	{
		// just get current edit item text (or drop list static)
		int nLen = ::GetWindowTextLength(hWndCtrl);
		if (nLen > 0)
		{
			// get known length
			::GetWindowText(hWndCtrl, value.GetBufferSetLength(nLen), nLen+1);
		}
		else
		{
			// for drop lists GetWindowTextLength does not work - assume
			//  max of 255 characters
			::GetWindowText(hWndCtrl, value.GetBuffer(255), 255+1);
		}
		value.ReleaseBuffer();
	}
	else
	{
		// set current selection based on model string
		if (::SendMessage(hWndCtrl, CB_SELECTSTRING, (WPARAM)-1,
			(LPARAM)(LPCTSTR)value) == CB_ERR)
		{
			// just set the edit text (will be ignored if DROPDOWNLIST)
			AfxSetWindowText(hWndCtrl, value);
		}
	}
}


void AFXAPI DDX_CBStringExact(CDataExchange* pDX, int nIDC, CString& value)
{
	HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
	if (pDX->m_bSaveAndValidate)
	{
		DDX_CBString(pDX, nIDC, value);
	}
	else
	{
		// set current selection based on data string
		int i = (int)::SendMessage(hWndCtrl, CB_FINDSTRINGEXACT, (WPARAM)-1,
		  (LPARAM)(LPCTSTR)value);
		if (i < 0)
		{
			// just set the edit text (will be ignored if DROPDOWNLIST)
			AfxSetWindowText(hWndCtrl, value);
		}
		else
		{
			// select it
			SendMessage(hWndCtrl, CB_SETCURSEL, i, 0L);
		}
	}
}
所以我们要做的就是使用DDX_CBStringExact代替DDX_CBString,就能够避免出现文章开头所提到的现象。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值