文章类型: VC&C++
关键词: VC,C++,CListCtrl,失去,焦点,仍然,显示,选中,高亮
内容摘要: CListCtrl 失去焦点仍然显示选中高亮

VC中的CListCtrl 失去焦点仍然显示选中高亮

2018/10/24 15:59:39    来源:apple    阅读:

CListCtrl中需要把选中的item高亮显示时只需要调用SetItemState传入LVIS_SELECTED就好。 

但是这样需要把焦点设置到CListCtrl上,一旦CListCtrl失去焦点高亮就会消失。

--------------------- 

最近工作中遇到一个需求,需要让CListCtrl在失去焦点的情况下依然显示高亮的item。 

总的来说有三种方法来实现这个功能。


继承CListCtrl然后重绘


太麻烦了不想用这个……


NM_CUSTOMDRAW事件


这个是一个类似于回调的处理过程,Windows在绘制List Ctrl的某个时间点上发送这个消息,可以选择忽略所有的通知,或者处理某部分的绘制,甚至绘制整个控件。用起来比较灵活方便,我只重绘被选中的那个item就好。 参考帖子

--------------------- 

void CMainFrame::OnNMCustomdrawRecQueryList(NMHDR *pNMHDR, LRESULT *pResult)
    {
        NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );

        *pResult = CDRF_DODEFAULT;

        if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
        {
            *pResult = CDRF_NOTIFYITEMDRAW;
        }
        else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
        {
            *pResult = CDRF_NOTIFYSUBITEMDRAW;
        }
        else if ( (CDDS_ITEMPREPAINT | CDDS_SUBITEM) == pLVCD->nmcd.dwDrawStage )
        {

            COLORREF clrNewTextColor, clrNewBkColor;

            int nItem = static_cast<int>( pLVCD->nmcd.dwItemSpec );

            POSITION pos = m_lstRecQueryRes.GetFirstSelectedItemPosition();
            int index = m_lstRecQueryRes.GetNextSelectedItem(pos);

            if (index == nItem)//如果要刷新的项为当前选择的项,则将文字设为白色,背景色设为蓝色
            {
                clrNewTextColor = RGB(255,255,255);        //Set the text to white
                clrNewBkColor = RGB(49,106,197);        //Set the background color to blue
            }
            else
            {
                clrNewTextColor = RGB(0,0,0);        //set the text black
                clrNewBkColor = RGB(255,255,255);    //leave the background color white
            }

            pLVCD->clrText = clrNewTextColor;
            pLVCD->clrTextBk = clrNewBkColor;

            *pResult = CDRF_DODEFAULT;
        }
    }

然而!我们代码里面用的BCG的list ctrl坑爹的自己把NM_CUSTOMDRAW处理了……用不了这个方法


--------------------- 

使用下面的方法肯定可以实现的,已经验证成功!

NM_KILLFOCUS

当控件失去焦点的时候就会发送这个消息,我们只要在这个消息的处理函数里面把需要高亮的item设置成LVIS_DROPHILITED,然后在NM_SETFOCUS的时候把状态取消就好了~

CTestDlg类的cpp文件主要代码如下:

//目的:小时列表与全览图切换后,恢复无模式对话框的选中项;事件映射方法如下

ON_NOTIFY(NM_KILLFOCUS, IDC_NOMODAL_LIST, OnNMKillfocusList)
//目的:小时列表与全览图切换后,恢复无模式对话框的选中项
ON_NOTIFY(NM_SETFOCUS, IDC_NOMODAL_LIST, OnNMSetfocusList)

void CTestDlg::OnNMKillfocusList(NMHDR *pNMHDR, LRESULT *pResult)
{
    // TODO: 在此添加控件通知处理程序代码
    m_nSelectedItemIndex = m_List.GetSelectionMark();
    m_List.SetItemState(m_nSelectedItemIndex, LVIS_DROPHILITED, LVIS_DROPHILITED);
    *pResult = 0;
}


void CTestDlg::OnNMSetfocusList(NMHDR *pNMHDR, LRESULT *pResult)
{
    // TODO: 在此添加控件通知处理程序代码
    m_List.SetItemState(m_nSelectedItemIndex, FALSE, LVIF_STATE);
    *pResult = 0;
}


CTestDlg类的h头文件主要代码如下:

class CTestDlg: public CDialog
{
public:
	// Construction
	CTestDlg(CWnd* pParent = NULL);   // standard constructor
	virtual ~CTestDlg();
public:
	CListCtrl	*m_pList;
private:
	//目的:保存小时列表中的无模式对话框的选中项的索引值
	int m_nSelectedItemIndex;
// Implementation
protected:
	// Generated message map functions
	//{{AFX_MSG(CUIRevNoModalDlg)
	//目的:小时列表与全览图切换后,恢复无模式对话框的选中项
	afx_msg void OnNMKillfocusList(NMHDR *pNMHDR, LRESULT *pResult);
	//目的:小时列表与全览图切换后,恢复无模式对话框的选中项
	afx_msg void OnNMSetfocusList(NMHDR *pNMHDR, LRESULT *pResult);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif

如下所示,图1与图2相互切换后选中项的焦点没有丢失。

image.png

图1

image.png

图2

↑ 上一篇文章:贝多芬交响曲全集(卡拉扬 60年代) 下载 关键词:贝多芬,交响曲,全集,卡拉扬,60年代,下载,西洋,古典.. 发布日期:2018/10/18 15:24:35
↓ 下一篇文章:CButtonST的用法详解 关键词:CButtonST,用法,详解,button,menu,.. 发布日期:2018/10/31 14:26:19
相关文章:
VC中CListCtrl获取当前选中行索引号 关键词:VC中CListCtrl获取当前选中行索引号,MFC 发布日期:2016-11-15 08:34
CListCtrl选中行恒保持其蓝色高亮状态 关键词:CListCtrl选中行恒保持其蓝色高亮状态 发布日期:2016-12-07 16:25
VC中CListCtrl获取当前选中行索引号 关键词:VC中CListCtrl获取当前选中行索引号 发布日期:2016-12-03 11:25
相关目录:.NETVC&C++软件开发
我要评论
正在加载评论信息......