데이터 베이스 MySQL 튜토리얼 MFC总结之CListCtrl用法及技巧(一)

MFC总结之CListCtrl用法及技巧(一)

Jun 07, 2016 pm 03:48 PM
mfc 요약 기능 용법

本文根据本人在项目中的应用,来谈谈CListCtrl的部分用法及技巧。当初学习时,查了很多资料,零零碎碎的作了些记录,现在主要是来做个总结,方便以后查阅。主要包括以下 十三点内容 :基本操作、获取选中行的行号、复选框操作、 动态设置选中行的字体颜色、



本文根据本人在项目中的应用,来谈谈CListCtrl的部分用法及技巧。当初学习时,查了很多资料,零零碎碎的作了些记录,现在主要是来做个总结,方便以后查阅。主要包括以下十三点内容:基本操作、获取选中行的行号、复选框操作、动态设置选中行的字体颜色、设置选中行的背景颜色、禁止拖动表头、让第一列居中显示、设置行高与字体、虚拟列表技术、点击表头时进行归类、向上与向下移动、动态调整大小问题、避免闪烁问题。

      分为两篇来进行总结。本篇重点总结:基本操作获取选中行的行号复选框操作动态设置选中行的字体颜色设置选中行的背景颜色


  1、基本操作

     分别从下面四点来介绍CListCtrl的基本操作:

     ①设置列表视图显示方式

      Ⅰ. CListCtrl有四种样式:LVS_ICON、LVS_SMALLICON、LVS_LIST、LSV_REPORT,可通过控件属性来设置。本文所述均为LSV_REPORT属性。

      Ⅱ. 扩展样式:

      常用的扩展样式有三种:LVS_EX_FULLROWSELECT、LVS_EX_GRIDLINES、LVS_EX_CHECKBOXES,分别对应作用 选中某行时使正行高亮、设置网格线、item前生成Ckeckbox控件。

      使用SetExtendedStyle(style)函数设置扩展样式,使用GetExtendedStyle()函数获取样式,如:

                       m_listInfo.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
       Ⅲ. 使用CListView时,需要在PreCreateWindow()函数中添加  cs.style | =  LVS_REPORT;

来将其设置为LVS_REPORT风格,否则插入无效。还用另一种方法来设置风格,即在OnInitialUpate()中获取CListCtrl控制权,然后修改风格,如下所示:

                      CListCtrl &theCtrl =GetListCtrl();

                      theCtrl.ModifyStyle(0, LVS_REPORT);

     ②插入操作

        先插入列:

                       int InsertColumn( int nCol, LPCTSTRlpszColumnHeading, int nFormat, int nWidth, int nSubItem)

插入列时,可指明列号、列名称、列名称显示样式,列宽等信息。对于列号为0的那一列,始终是靠左显示,后面会有修改使其剧中显示的方法,其他列通过设置nFormat属性可以居中显示。

        插入行:

                       int InsertItem( int nItem, LPCTSTRlpszItem )

直接插入一行,nItem指明行号,lpszItem指明该行第0列的信息。

       设置信息:

                       BOOL SetItemText(int nItem,  int nSubItem, LPCTSTR lpszText )

设置第nItem行nSubItem列的信息(nItem:0,1,2,3……; nSubItem:1,2,3……)

     ③删除操作

       有三个操作函数:

                       BOOL DeleteAllItems()  -------删除所有的行

                       BOOL DeleteItem(nItem) --------删除某一行

                       BOOL DeleteColumn(nCol) -----删除某一列

     ④获取/设置属性函数

      有很多函数了,就不一一介绍了。常用的有

                      int GetItemCount() -------- 获取已插入信息的行数

                      BOOL SetItemState(int iLink, UINTstate, UINTstateMask ) ---------设置行状态,如高亮显示等

等等


  2、获取选中行的行号

       获取选中行的行号,然后对该行进行相关处理,这点在编程中用的非常多。

       当鼠标单击item时,控件向父窗口发送NM_CLICK消息,其响应函数为OnNMClickXXXX(NMHDR *pNMHDR, LRESULT *pResult),在该函数下来编写代码获取鼠标点击的行号。

       有两种方法来获取行号:第一种是使用GetFirstSelectedItemPositionGetNextSelectedItem配合来获取;第二种是先获取鼠标位置信息,然后调用HitTest函数来找出行号。示例分别如下:

        第一种方法,该示例截自MSDN,可作修改后使用。

 

POSITION pos = pList->GetFirstSelectedItemPosition();
if (pos == NULL)
   TRACE0("No items were selected!\n");
else
{
   while (pos)
   {
      int nItem = pList->GetNextSelectedItem(pos);
      TRACE1("Item %d was selected!\n", nItem);
      // you could do your own processing on nItem here
   }
}
로그인 후 복사

        第二种方法,该示例来自我的项目,可作修改后使用。

 

//获取单击所在的行号
//找出鼠标位置
DWORD dwPos = GetMessagePos();
CPoint point( LOWORD(dwPos), HIWORD(dwPos) );
m_listCtrl.ScreenToClient(&point);

 //定义结构体
LVHITTESTINFO lvinfo;
lvinfo.pt = point;

 //获取行号信息
int nItem = m_listCtrl.HitTest(&lvinfo);
if(nItem != -1)
    m_itemSel = lvinfo.iItem;	//当前行号
로그인 후 복사

      对于LVHITTESTINFO 结构体,其有四个成员,在上述HitTest调用中,其第一个成员作为输入,另外三个作为输出。具体变量含义可查看MSDN。

typedef struct _LVHITTESTINFO {
    POINT pt;
    UINT flags;
    int iItem;
    int iSubItem;
} LVHITTESTINFO, *LPLVHITTESTINFO;
로그인 후 복사

  3复选框操作

       有时需要在item前面添加一个CheckBox,供用户选择,然后对所有选中项进行处理。

       这里涉及到两个问题:第一个,如何添加CheckBox风格;第二个,如何判断某一行的CheckBox状态是否发生改变。

       对于第一个问题,在基本操作里已经有所阐述了,即通过SetExtendedStyle函数添加LVS_EX_CHECKBOXES扩展风格。

      这里重点探讨第二个问题,首先,操作复选框状态的有两个函数:

                      BOOL GetCheck(int nItem)-------获取复选框状态

                      BOOL SetCheck( int nItem, BOOL fCheck = TRUE )-------设置复选框状态

其次,我们要搞清楚以下四点:

当列表的项item改变时,控件会向父窗口发送LVN_ITEMCHANGED消息,因此可以在LVN_ITEMCHANGED消息的响应函数中对复选框的状态进行处理(查询或设置)。

鼠标点击CheckBox时,消息的顺序是 NM_CLICK —> LVN_ITEMCHANGED,即CheckBox的状态是在 NM_CLICK消息函数结束后才会发生变化,在NM_CLICK中使用GetCheck无效。

鼠标点击Item(非CheckBox区域)时,消息的顺序是 LVN_ITEMCHANGED —> NM_CLICK。

调用InsertItem 函数时,也会产生LVN_ITEMCHANGED消息。鉴于此,通常会自定义一个BOOL型变量m_bHit 来判断是点击操作还是插入操作,该变量初始赋FALSE,当有鼠标点击item时赋TRUE, 检测完是否有CheckBox被点击后重新复位为FALSE。

        示例如下所示:

void CXXXX::OnNMClickXXXX(NMHDR *pNMHDR, LRESULT *pResult)
{
    //获取单击所在的行号
    //找出鼠标位置
    DWORD dwPos = GetMessagePos();
    CPoint point( LOWORD(dwPos), HIWORD(dwPos) );
    m_listCtrl.ScreenToClient(&point);
    //定义结构体
    LVHITTESTINFO lvinfo;
    lvinfo.pt = point;
    //获取行号信息
    int nItem = m_listCtrl.HitTest(&lvinfo);
    if(nItem != -1)
	m_itemSel = lvinfo.iItem;	//当前行号

     //判断是否点击在CheckBox上
     if(lvinfo.flags == LVHT_ONITEMSTATEICON)
          m_bHit = TRUE;

     *pResult = 0;
}

void CXXXX::OnLvnItemchangedXXXX(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLISTVIEW pNMLV = reinterpret_cast<lpnmlistview>(pNMHDR);
	//判断m_bHit,即是否点击了CheckBox
	if(m_bHit)
	{
	        m_bHit = FALSE;		//复位

		if(m_listCtrl.GetCheck(m_itemSel))
		{       //CheckBox被选中
			//do your own processing 
		}
		else
		{      //CheckBox取消选择
			//do your own processing 
		}
	}

	*pResult = 0;
}</lpnmlistview>
로그인 후 복사


  4、动态设置选中行的字体颜色

         有时可能需要设置某行的文字为特殊颜色,以表示某种特殊含义,比如正在下载的信息用绿色,暂停下载的用灰色。

         首先,给出一个CodeProject的链接,这篇文章讲的非常好,主要是利用Custom Draw。http://www.codeproject.com/Articles/79/Neat-Stuff-to-Do-in-List-Controls-Using-Custom-Dra    

         然后,来谈谈我的方法,这里主要谈对选中行的字体颜色进行动态修改,当然也是我通过上面文章和自己实践结合得出的。

        我们需要搞清楚以下几点(可以结合下面修改某一行的字体颜色的方法来看):

① 当控件绘制时,会发送NM_CUSTOMDRAW 消息,该消息的消息响应函数为

void CXXXX::OnNMCustomdrawXXXX(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLVCUSTOMDRAW pLVCD = reinterpret_cast<lpnmlvcustomdraw>(pNMHDR);
	// TODO: Add your control notification handler code here
	*pResult = CDRF_DODEFAULT;
       //………………
 }</lpnmlvcustomdraw>
로그인 후 복사
②其中,pNMHDR为输入参数,其指向NMLVCUSTOMDRAW结构体,该结构包含了很多信息,包括字体颜色、背景等等,特别是第一个成员,为NMCUSTOMDRAW结构体变量,其包含了Current drawing stage(不知道怎么编译比较好),其可能的值如下图(截自MSDN)所示

MFC总结之CListCtrl用法及技巧(一)

pResult为输出参数,该参数决定了接下来向windows发送什么消息(与绘制有关的),通过发送该消息我们可以进入下一步需要的处理阶段。具体输出哪个值取决于Current drawing stage,其可能的值如下图(截自MSDN)所示

MFC总结之CListCtrl用法及技巧(一)

④ 有一点必须注意(英文的,我觉得看起来比翻译过来更精确):

     One thing to keep in mind is you must always check the draw stage before doing anything else, because your handler will receive many messages, and the draw stage determines what action your code takes.

        下面我们来看看如何修改某一行的字体颜色:

①  首先,我们应该明白要修改字体颜色,应该在pre-paint 阶段来完成

② 因此,在消息响应函数中,我们首先判断是否处于pre-paint stage(即pLVCD->nmcd.dwDrawStage == CDDS_PREPAINT),然后通过修改输出值pResult 的值来通知windows我们需要处理每个item的消息(即设置 *pResult = CDRF_NOTIFYITEMDRAW)。

③ 再次进入消息响应函数时,我们判断是否处于Item的pre-paint stage(即pLVCD->nmcd.dwDrawStage == CDDS_ITEMPREPAINT),如果是则进行相关处理,即修改字体颜色等等。

④ 处理完了后重新设置 *pResult = CDRF_DODEFAULT,表示我们不再需要其他特殊的消息了,默认执行即可。

         示例如下:

void CXXXX::OnNMCustomdrawXXXX(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMLVCUSTOMDRAW pLVCD = reinterpret_cast<lpnmlvcustomdraw>(pNMHDR);
    *pResult = CDRF_DODEFAULT;

    // First thing - check the draw stage. If it's the control's pre-paint stage, 
    // then tell Windows we want messages for every item.
    if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
    {
        *pResult = CDRF_NOTIFYITEMDRAW;
    }
    else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
    {
        // This is the notification message for an item. 
	//处理,将item改变背景颜色
        if( /*符合条件*/ )
	    pLVCD->clrText = RGB(255,0,255);
		
           *pResult = CDRF_DODEFAULT;
    }
}</lpnmlvcustomdraw>
로그인 후 복사


        上面谈的方法主要用于设置静态字体颜色,当然,如果你的列表的信息在不断变化(即用SetItemText不断修改),那么也就实现了动态改变了,否则需要在合适的地方调用重绘函数:

                         BOOL RedrawItems( int nFirst, int nLast )

表示在nFirst和nLast之间的行需要进行重绘。


  5、设置选中行的背景颜色


         设置选中行的背景颜色,可以将选中行以特殊颜色显示,容易明白当前处理的是哪一行。尽管有高亮,但是高亮是基于焦点的,如果你选中了某一行,然后焦点转移了,这是就无法判断你选的是哪一行了。

        设置选中行的背景颜色的方法和第四节中讲的修改字体颜色的方法是相似的,都是利用Custom Draw。这里涉及到设置当前选中行为特殊颜色,同时要恢复前一次选中行的颜色,否则就乱了。因此需要记录前一次选中行、当前选中行的行号,相信通过前面的总结,这点并不难实现。然后在当前选中行和前一次选中行之间进行重绘即可。

       示例如下:

void CXXXX::OnNMClickXXXX(NMHDR *pNMHDR, LRESULT *pResult)
{
	//…………

	//重绘item,更改背景颜色
	int nFirst = min(m_itemSel,m_itemForeSel);
	int nLast = max(m_itemSel,m_itemForeSel);
	m_listCtrl.RedrawItems(nFirst, nLast);	//在前一次选中的item和当前选中的Item之间进行重绘

	*pResult = 0;
}
void CXXXX::OnNMCustomdrawXXXX(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLVCUSTOMDRAW pLVCD = reinterpret_cast<lpnmlvcustomdraw>(pNMHDR);
	*pResult = CDRF_DODEFAULT;

	// First thing - check the draw stage. If it's the control's prepaint
        // stage, then tell Windows we want messages for every item.
	if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
	{
             *pResult = CDRF_NOTIFYITEMDRAW;
	}
        else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
	{
                // This is the notification message for an item. 
		//处理,将item改变背景颜色
		if(m_itemSel == pLVCD->nmcd.dwItemSpec)		
		{	//当前选中的item
			pLVCD->clrTextBk = RGB(255,0,0);
		}
		else if(m_itemForeSel == pLVCD->nmcd.dwItemSpec)
		{	//前一次选中的item,恢复为白色
			pLVCD->clrTextBk = RGB(255,255,255);
		}

                *pResult = CDRF_DODEFAULT;
	}
}</lpnmlvcustomdraw>
로그인 후 복사


본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Win11 팁 공유: Microsoft 계정으로 로그인을 건너뛰는 한 가지 요령 Win11 팁 공유: Microsoft 계정으로 로그인을 건너뛰는 한 가지 요령 Mar 27, 2024 pm 02:57 PM

Win11 팁 공유: Microsoft 계정 로그인을 건너뛰는 한 가지 요령 Windows 11은 Microsoft가 출시한 최신 운영 체제로, 새로운 디자인 스타일과 많은 실용적인 기능을 갖추고 있습니다. 그러나 일부 사용자의 경우 시스템을 부팅할 때마다 Microsoft 계정에 로그인해야 하는 것이 다소 성가실 수 있습니다. 당신이 그들 중 하나라면, Microsoft 계정 로그인을 건너뛰고 데스크탑 인터페이스로 직접 들어갈 수 있는 다음 팁을 시도해 볼 수도 있습니다. 먼저 로그인하려면 Microsoft 계정 대신 시스템에 로컬 계정을 만들어야 합니다. 이렇게 하면 장점은

베테랑의 필수품: C 언어의 * 및 &에 대한 팁과 주의사항 베테랑의 필수품: C 언어의 * 및 &에 대한 팁과 주의사항 Apr 04, 2024 am 08:21 AM

C 언어에서는 다른 변수의 주소를 저장하는 포인터를 나타내고, &는 변수의 메모리 주소를 반환하는 주소 연산자를 나타냅니다. 포인터 사용에 대한 팁에는 포인터 정의, 포인터 역참조 및 포인터가 유효한 주소를 가리키는지 확인하는 것이 포함됩니다. 주소 연산자 사용에 대한 팁에는 변수 주소 가져오기 및 배열 요소의 주소를 가져올 때 배열의 첫 번째 요소 주소 반환이 포함됩니다. . 문자열을 반전시키기 위해 포인터 및 주소 연산자를 사용하는 방법을 보여주는 실제 예입니다.

초보자를 위한 양식 작성 요령은 무엇입니까? 초보자를 위한 양식 작성 요령은 무엇입니까? Mar 21, 2024 am 09:11 AM

우리는 엑셀로 표를 생성하고 편집하는 일이 많은데 이제 막 소프트웨어를 접한 초보자로서 엑셀을 이용해 표를 만드는 방법은 생각보다 쉽지 않습니다. 아래에서는 초보자, 즉 초보자가 마스터해야 할 테이블 생성의 몇 가지 단계에 대해 몇 가지 훈련을 수행합니다. 초보자를 위한 샘플 양식은 다음과 같습니다. 작성 방법을 살펴보겠습니다! 1. 새로운 엑셀 문서를 만드는 방법은 두 가지가 있습니다. [바탕화면] - [새로 만들기] - [xls] 파일의 빈 곳을 마우스 오른쪽 버튼으로 클릭하시면 됩니다. [시작]-[모든 프로그램]-[Microsoft Office]-[Microsoft Excel 20**]을 사용할 수도 있습니다. 2. 새 ex를 두 번 클릭합니다.

VSCode 시작 가이드: 초보자가 사용 기술을 빠르게 익히기 위해 꼭 읽어야 할 책입니다! VSCode 시작 가이드: 초보자가 사용 기술을 빠르게 익히기 위해 꼭 읽어야 할 책입니다! Mar 26, 2024 am 08:21 AM

VSCode(Visual Studio Code)는 Microsoft에서 개발한 오픈 소스 코드 편집기로, 강력한 기능과 풍부한 플러그인 지원을 갖추고 있어 개발자가 선호하는 도구 중 하나입니다. 이 기사에서는 초보자가 VSCode 사용 기술을 빠르게 익히는 데 도움이 되는 소개 가이드를 제공합니다. 이번 글에서는 VSCode 설치 방법, 기본적인 편집 작업, 단축키, 플러그인 설치 등을 소개하고, 독자들에게 구체적인 코드 예시를 제공하겠습니다. 1. 먼저 VSCode를 설치하세요.

PHP 프로그래밍 기술: 3초 안에 웹페이지로 이동하는 방법 PHP 프로그래밍 기술: 3초 안에 웹페이지로 이동하는 방법 Mar 24, 2024 am 09:18 AM

제목: PHP 프로그래밍 팁: 3초 안에 웹 페이지로 이동하는 방법 웹 개발을 하다 보면 일정 시간 내에 자동으로 다른 페이지로 이동해야 하는 상황이 자주 발생합니다. 이 기사에서는 PHP를 사용하여 3초 내에 페이지로 이동하는 프로그래밍 기술을 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 먼저, 페이지 점프의 기본 원리는 HTTP 응답 헤더의 Location 필드를 통해 구현됩니다. 이 필드를 설정하면 브라우저가 지정된 페이지로 자동으로 이동할 수 있습니다. 다음은 P를 사용하는 방법을 보여주는 간단한 예입니다.

Go 언어의 함수 리팩토링 기술에 대한 심층적인 이해 Go 언어의 함수 리팩토링 기술에 대한 심층적인 이해 Mar 28, 2024 pm 03:05 PM

Go 언어 프로그램 개발에 있어서 기능 재구성 능력은 매우 중요한 부분입니다. 기능을 최적화하고 리팩터링하면 코드 품질과 유지 관리 가능성을 향상시킬 수 있을 뿐만 아니라 프로그램 성능과 가독성도 향상시킬 수 있습니다. 이 기사에서는 독자가 이러한 기술을 더 잘 이해하고 적용할 수 있도록 특정 코드 예제와 결합된 Go 언어의 함수 재구성 기술을 탐구합니다. 1. 코드 예제 1: 중복된 코드 조각 추출 실제 개발에서는 재사용된 코드 조각을 자주 접하게 됩니다. 이때 반복되는 코드를 독립적인 함수로 추출하는 것을 고려해 볼 수 있습니다.

공개된 Win11 트릭: Microsoft 계정 로그인을 우회하는 방법 공개된 Win11 트릭: Microsoft 계정 로그인을 우회하는 방법 Mar 27, 2024 pm 07:57 PM

공개된 Win11 트릭: Microsoft 계정 로그인을 우회하는 방법 최근 Microsoft는 새로운 운영 체제인 Windows11을 출시하여 많은 관심을 받았습니다. 이전 버전에 비해 Windows 11은 인터페이스 디자인과 기능 개선 측면에서 많은 새로운 조정이 이루어졌지만 가장 눈길을 끄는 점은 사용자가 Microsoft 계정으로 시스템에 로그인하도록 강요한다는 것입니다. . 일부 사용자의 경우 로컬 계정으로 로그인하는 데 더 익숙하고 개인 정보를 Microsoft 계정에 바인딩하는 것을 꺼릴 수 있습니다.

Laravel 양식 클래스 사용 팁: 효율성을 높이는 방법 Laravel 양식 클래스 사용 팁: 효율성을 높이는 방법 Mar 11, 2024 pm 12:51 PM

양식은 웹 사이트나 응용 프로그램을 작성하는 데 있어 필수적인 부분입니다. 널리 사용되는 PHP 프레임워크인 Laravel은 풍부하고 강력한 양식 클래스를 제공하여 양식 처리를 보다 쉽고 효율적으로 만듭니다. 이 글에서는 개발 효율성을 향상시키는 데 도움이 되는 Laravel 폼 클래스 사용에 대한 몇 가지 팁을 소개합니다. 다음은 구체적인 코드 예시를 통해 자세히 설명합니다. 양식 생성하기 Laravel에서 양식을 생성하려면 먼저 뷰에 해당 HTML 양식을 작성해야 합니다. 양식 작업 시 Laravel을 사용할 수 있습니다.

See all articles