ホームページ データベース 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衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Win11 ヒントの共有: ワン トリックで Microsoft アカウントのログインをスキップする Win11 ヒントの共有: ワン トリックで Microsoft アカウントのログインをスキップする Mar 27, 2024 pm 02:57 PM

Win11 のヒントの共有: Microsoft アカウントのログインをスキップする 1 つのトリック Windows 11 は、新しいデザイン スタイルと多くの実用的な機能を備えた、Microsoft によって発売された最新のオペレーティング システムです。ただし、一部のユーザーにとっては、システムを起動するたびに Microsoft アカウントにログインしなければならないのが少し煩わしい場合があります。あなたがそのような人であれば、次のヒントを試してみるとよいでしょう。これにより、Microsoft アカウントでのログインをスキップして、デスクトップ インターフェイスに直接入ることができるようになります。まず、Microsoft アカウントの代わりにログインするためのローカル アカウントをシステムに作成する必要があります。これを行う利点は、

初心者がフォームを作成するためのヒントは何ですか? 初心者がフォームを作成するためのヒントは何ですか? Mar 21, 2024 am 09:11 AM

私たちは Excel で表を作成したり編集したりすることがよくありますが、ソフトウェアに触れたばかりの初心者にとって、Excel を使用して表を作成する方法は私たちほど簡単ではありません。以下では、初心者、つまり初心者がマスターする必要があるテーブル作成のいくつかの手順について演習を行います。初心者向けのサンプルフォームを以下に示します。入力方法を見てみましょう。 1. Excel ドキュメントを新規作成するには 2 つの方法があります。 [デスクトップ]-[新規作成]-[xls]ファイル上の何もない場所でマウスを右クリックします。 [スタート]-[すべてのプログラム]-[Microsoft Office]-[Microsoft Excel 20**] を実行することもできます。 2. 新しい ex ファイルをダブルクリックします。

VSCode 入門ガイド: 初心者が使い方のスキルをすぐにマスターするための必読の書です。 VSCode 入門ガイド: 初心者が使い方のスキルをすぐにマスターするための必読の書です。 Mar 26, 2024 am 08:21 AM

VSCode (Visual Studio Code) は、Microsoft によって開発されたオープン ソース コード エディターであり、強力な機能と豊富なプラグイン サポートを備えており、開発者にとって推奨されるツールの 1 つです。この記事では、初心者が VSCode の使用スキルをすぐに習得できるようにするための入門ガイドを提供します。この記事では、VSCode のインストール方法、基本的な編集操作、ショートカット キー、プラグインのインストールなどを紹介し、具体的なコード例を読者に提供します。 1. まず VSCode をインストールします。

ベテラン必携:C言語の*と&のヒントと注意点 ベテラン必携:C言語の*と&のヒントと注意点 Apr 04, 2024 am 08:21 AM

C 言語では、他の変数のアドレスを格納するポインタを表し、& は変数のメモリ アドレスを返すアドレス演算子を表します。ポインタの使用に関するヒントには、ポインタの定義、ポインタの逆参照、ポインタが有効なアドレスを指していることの確認が含まれます。アドレス演算子の使用に関するヒントには、変数アドレスの取得、配列要素のアドレスを取得するときに配列の最初の要素のアドレスを返すことなどが含まれます。 。ポインター演算子とアドレス演算子を使用して文字列を反転する実際の例。

PHP プログラミング スキル: 3 秒以内に Web ページにジャンプする方法 PHP プログラミング スキル: 3 秒以内に Web ページにジャンプする方法 Mar 24, 2024 am 09:18 AM

タイトル: PHP プログラミングのヒント: 3 秒以内に Web ページにジャンプする方法 Web 開発では、一定時間内に別のページに自動的にジャンプする必要がある状況によく遭遇します。この記事では、PHP を使用して 3 秒以内にページにジャンプするプログラミング手法を実装する方法と、具体的なコード例を紹介します。まず、ページ ジャンプの基本原理は、HTTP 応答ヘッダーの Location フィールドを通じて実現されます。このフィールドを設定すると、ブラウザは指定されたページに自動的にジャンプできます。以下は、P の使用方法を示す簡単な例です。

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

フォームは、Web サイトまたはアプリケーションの作成に不可欠な部分です。 Laravel は人気のある PHP フレームワークとして、豊富で強力なフォーム クラスを提供し、フォーム処理をより簡単かつ効率的にします。この記事では、Laravel フォームクラスを使用して開発効率を向上させるためのヒントをいくつか紹介します。以下、具体的なコード例を挙げて詳しく説明します。フォームの作成 Laravel でフォームを作成するには、まずビューに対応する HTML フォームを記述する必要があります。フォームを操作するときは、Laravel を使用できます

ワードボックスの√記号の使い方を詳しく解説 ワードボックスの√記号の使い方を詳しく解説 Mar 25, 2024 pm 10:30 PM

Wordボックスで√記号を使うコツを詳しく解説. 日々の仕事や勉強の中で、文書の編集や組版などでWordを使用することが多くなります。その中でも√記号はよく使われる記号で、通常は「正しい」を意味します。 Word ボックスで √ 記号を使用すると、情報をより明確に表現し、文書の専門性と美しさを向上させることができます。次に、ワードボックスで√記号を使用するスキルを詳しく紹介します。皆さんのお役に立てれば幸いです。 1. √ 記号を挿入する Word では、√ 記号を挿入する方法がいくつかあります。 1つ

See all articles