主頁 > 軟體工程 > NM_CUSTOMDRAW

NM_CUSTOMDRAW

2020-09-14 09:43:59 軟體工程

實作自定義繪制的三步曲
既然您已經了解了繪制控制元件可用的各種選項(包括使用自定義繪制的好處),那么,讓我們來看看實作一個自定義繪制控制元件需要的三個主要步驟。
' 執行一個 NM_CUSTOMDRAW 訊息處理程式。
' 指定處理所需的繪制階段。
' 篩選特定的繪制階段(在這些階段中,您需要加入自己的特定于控制元件的繪制代碼)。
執行一個NM_CUSTOMDRAW 訊息處理程式
當需要繪制一個公共控制元件時,MFC 會將控制元件的自定義繪制通知訊息(最初發送到控制元件的父視窗)以 NM_CUSTOMDRAW 訊息的形式反饋給控制元件。以下是一個 NM_CUSTOMDRAW 處理程式的示例。
void CMyCustomDrawControl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) { LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); ... }
正如您所見,NM_CUSTOMDRAW 處理程式將一個指標傳遞給 NMHDR 型別的結構。然而,該值不足以用于象 NMHDR 這樣只包含三個成員(hwndFrom、id From 和 code)的結構。
因此,您通常需要將該結構指標轉換為資訊量更大的結構 — LPNMCUSTOMDRAW。LPNMCUSTOMDRAW 指向 NMCUSTOMDRAW,它包含諸如 dwDrawStage、dwItemSpec 和 uItemState 這樣的成員 — 它們是決定當前繪制階段及確切繪制(例如,控制元件本身、或控制元件的一個專案或子項)所必需的。
這里值得注意的是,還可以將 NMHDR 指標指向特定于正在繪制控制元件的型別的結構。表 1 顯示控制元件的一個串列及其相關的自定義繪制結構型別名。
表 1:控制元件及其相關的自定義繪制結構
控制元件 結構(在 commctrl.h 中定義)
Rebar、Trackbar、AuthTicket、My.Resources、My.Settings、My.User 和 My.WebServices。
NMCUSTOMDRAW
List-view
NMLVCUSTOMDRAW
Toolbar
NMTBCUSTOMDRAW
Tooltip
NMTTCUSTOMDRAW
Tree-view
NMTVCUSTOMDRAW

指定處理所需的繪制階段
正如我在前面提到的,繪制一個控制元件存在一些“階段”。特別是,您可以將繪制程序理解為一系列階段,其中控制元件通知其父視窗需要繪制的內容。事實上,控制元件甚至會在繪制控制元件及其各項前后發送一個通知,從而讓編程人員更好地控制該程序。
在所有情況下,單一的 NM_CUSTOMDRAW 處理程式在每個繪制階段都進行呼叫。然而,謹記:自定義繪制允許您在自己的繪制中合并默認的控制元件繪制,您需要指定您將處理哪個繪制階段。這通過設定 NM_CUSTOMDRAW 處理程式的第二個引數 (pResult) 完成。事實上,如果您從未設定該值,則用初始階段的 CDDS_PREPAINT 呼叫函式后,您的函式將不再被呼叫!
從技術上講,只有兩個階段指定需要的繪制階段(CDDS_PREPAINT 和 CDDS_ITEMPREPAINT),它們影響發送通知訊息的內容。然而,通常只在處理程式的最后指定代碼將處理的繪制階段。表 2 列出用于指定所需繪制階段(代碼關注的)的值。
表 2:自定義繪制回傳標志
自定義繪制回傳標志 含義
CDRF_DEFAULT
指示控制元件自行繪制。該值為默認值,不應該將它與其他值組合在一起。
CDRF_SKIPDEFAULT
用于指定控制元件根本不進行任何繪制。
CDRF_NEWFONT
當代碼更改繪制項/子項的字體時使用。
CDRF_NOTIFYPOSTPAINT
使通知資訊在控制元件或每個項/子項繪制后發送。
CDRF_NOTIFYITEMDRAW
指出項(或子項)將進行繪制。注意,它下面的值與 CDRF_NOTIFYSUBITEMDRAW 相同。
CDRF_NOTIFYSUBITEMDRAW
指出子項(或項)將進行繪制。注意,它下面的值與 CDRF_NOTIFYITEMDRAW 相同。
CDRF_NOTIFYPOSTERASE
當洗掉控制元件后需要通知代碼時使用。

以下為一個示例,其中的代碼指定,當繪制控制元件的項 (CDRF_NOTIFYITEMDRAW) 及子項 (CDRF_NOTIFYPOSTPAINT),以及繪制完成時,應該呼叫 NM_CUSTOMDRAW 處理程式。
void CListCtrlWithCustomDraw::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult) { LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); ... *pResult = 0; // Initialize value *pResult |= CDRF_NOTIFYITEMDRAW; *pResult |= CDRF_NOTIFYSUBITEMDRAW; *pResult |= CDRF_NOTIFYPOSTPAINT; }
篩選指定的繪制階段
一旦指定要關注的階段后,您需要處理這些階段。因為繪制程序的每個階段只有一個訊息要發送,慣例是執行一個 switch 陳述句以決定準確的繪制階段。不同的繪制階段由以下標志定義:
CDDS_PREPAINT CDDS_ITEM CDDS_ITEMPREPAINT CDDS_ITEMPOSTPAINT CDDS_ITEMPREERASE CDDS_ITEMPOSTERASE CDDS_SUBITEM CDDS_POSTPAINT CDDS_PREERASE CDDS_POSTERASE
對于一個 CListCtrl 派生的類,有一個 NM_CUSTOMDRAW 處理程式的示例,其中您可以發現,代碼決定當前繪制階段的方式:
void CMyCustomDrawControl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) { LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); switch(pNMCD->dwDrawStage) { case CDDS_PREPAINT: ... break; case CDDS_ITEMPREPAINT: ... break; case CDDS_ITEMPREPAINT | CDDS_SUBITEM: ... break; ... } *pResult = 0; }
注意,為了決定子項(例如,串列視圖控制元件)繪制的階段,您必需使用按位 or 運算子,它有兩個值:其中一個為 CDDS_ITEMPREPAINT 或者 CDDS_ITEMPOSTPAINT,另一個為 CDDS_SUBITEM。
要說明它,我們假定您想在繪制串列視圖項之前進行一些處理。將撰寫 switch 陳述句來處理 CDDS_ITEMPREPAINT。
case CDDS_ITEMPREPAINT: ... break;
然而,如果是您所關注子項的預繪制階段,則將如下操作:
case CDDS_ITEMPREPAINT | CDDS_SUBITEM: ... break;
 回傳頁首回傳頁首
示例:創建一個串列視圖控制元件自定義繪制控制元件
如前面提到的,您可以完全控制控制元件及其項的繪制,或者僅執行一小部分特定于應用程式的繪制,并讓控制元件繼續進行。本文的焦點更多地偏重于控制元件繪制技術而非高級的繪制技術,我們將演練一個簡單的示例,其中串列視圖控制元件是一個自定義的繪制,因此項的文本將在創建拼接外觀的交替單元中顯示為不同的顏色。
' 創建一個基于 Visual C++ 2005 對話框的專案,名為 ListCtrlColor。
' 從 Class View 中選擇 Project 選單選項,并單擊 Add Class 呼叫 Add Class 對話框。
' 從分類串列中選擇 MFC,然后從模板串列中選擇 MFC Class。
' 單擊 Add 按鈕,呼叫 MFC Class Wizard 對話框。
' 對于 Class name,鍵入值 CListCtrlWithCustomDraw 并選擇 CListCtrl 的 Base class。
' 單擊 Finish 按鈕,生成類的標頭和執行檔案。
' 對于 Class View,右鍵單擊 CListCtrlWithCustomDraw 類,并選擇 Properties 背景關系選單選項。
' 顯示 Properties 視窗時,單擊頂部的 Messages 按鈕,顯示一個兩列的訊息串列,您可以為其實作處理程式。
' 在訊息串列中單擊 NM_CUSTOMDRAW 項,然后下拉第二列的組合框箭頭,并選擇值 OnNMCustomdraw。
' 現在,處理繪制代碼。這里,我們只簡單處理項和子項預繪制階段,指定基于當前行(項)和列(子項)的文本和背景色。要進行此操作,按如下所示修改 OnNMCustomdraw 函式:
void CListCtrlWithCustomDraw::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult) { LPNMLVCUSTOMDRAW lpLVCustomDraw = reinterpret_cast(pNMHDR); switch(lpLVCustomDraw->nmcd.dwDrawStage) { case CDDS_ITEMPREPAINT: case CDDS_ITEMPREPAINT | CDDS_SUBITEM: if (0 == ((lpLVCustomDraw->nmcd.dwItemSpec + lpLVCustomDraw->iSubItem) % 2)) { lpLVCustomDraw->clrText = RGB(255,255,255); // white text
lpLVCustomDraw->clrTextBk = RGB(0,0,0); // black background } else { lpLVCustomDraw->clrText = CLR_DEFAULT; lpLVCustomDraw->clrTextBk = CLR_DEFAULT; } break; default: break; } *pResult = 0; *pResult |= CDRF_NOTIFYPOSTPAINT; *pResult |= CDRF_NOTIFYITEMDRAW; *pResult |= CDRF_NOTIFYSUBITEMDRAW; }
現在,我們來測驗新控制元件。要進行此操作,您只需使用 CListCtrlWithCustomDraw 類將串列視圖控制元件放在對話框中,并對其進行子類派生。下面是完成該操作的步驟。
' 在 Resource 視圖中,打開應用程式的主對話框 (IDD_LISTCTRLCOLOR_DIALOG)。
' 從 Toolbox 中,將一個 List Control 拖放到該對話框。
' 右鍵單擊串列控制元件,并選擇 Properties 背景關系選單選項。
'
將 View 屬性設定為 Report。
' 右鍵單擊控制元件,并選擇 Add Variable 背景關系選單選項。
' 出現 Add Member Variable Wizard 對話框時,指定 m_lstBooks 的 Variable name,并單擊 Finish 按鈕。
' 這時,您就有了一個 CListCtrl 派生類 (m_lstBooks),它將對話框上的串列視圖控制元件進行子類派生。然而,m_lstBooks 需要從最新創建的 CListCtrlWithCustomDraw 派生,以便于呼叫您的繪制代碼。因此,打開對話框的標題檔案 (ListCtrlColorDlg.h),將 m_lstBooks 更改為 CListCtrlWithCustomDraw 型別。
' 在 CListCtrlColorDlg 類開始之前,添加以下指令。
#include 'ListCtrlWithCustomDraw.h'
' 將下面的代碼添加到對話框的 OnInitDialog 成員函式,這樣我們就能夠看到一些列
表視圖行。
// Insert the columns m_lstBooks.InsertColumn(0, _T('Author')); m_lstBooks.InsertColumn(1, _T('Book')); // Define the data static struct { TCHAR m_szAuthor[50]; TCHAR m_szTitle[100]; } BOOK_INFO[] = { _T('Tom Archer'), _T('Visual C++.NET Bible'), _T('Tom Archer'), _T('Extending MFC with the .NET Framework'), _T('Brian Johnson'), _T('XBox 360 For Dummies') }; // Insert the data int idx; for (int i = 0; i < sizeof BOOK_INFO / sizeof BOOK_INFO[0]; i++) { idx = m_lstBooks.InsertItem(i, BOOK_INFO[i].m_szAuthor); m_lstBooks.SetItemText(i, 1, BOOK_INFO[i].m_szTitle); }
' 現在,建立并運行應用程式。圖 1 為應用程式外觀的一個示例。

圖 1. 自定義繪制示例應用程式

uj5u.com熱心網友回復:

轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/33462.html

標籤:界面

上一篇:drawitem

下一篇:已經有了kalibr引數如何獲得立體相機校正后影像?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • Git本地庫既關聯GitHub又關聯Gitee

    創建代碼倉庫 使用gitee舉例(github和gitee差不多) 1.在gitee右上角點擊+,選擇新建倉庫 ? 2.選擇填寫倉庫資訊,然后進行創建 ? 3.服務端已經準備好了,本地開始作準備 (1)Git 全域設定 git config --global user.name "成鈺" git c ......

    uj5u.com 2020-09-10 05:04:14 more
  • CODING DevOps 代碼質量實戰系列第二課,相約周三

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。**《DevOps 代碼質量實戰(PHP 版)》**為 CODING DevOps 代碼質量實戰系列的第二課,同時也是本系列的 PHP ......

    uj5u.com 2020-09-10 05:07:43 more
  • 推薦Scrum書籍

    推薦Scrum書籍 直接上干貨,推薦書籍清單如下(推薦有順序的哦) Scrum指南 Scrum精髓 Scrum敏捷軟體開發 Scrum捷徑 硝煙中的Scrum和XP : 我們如何實施Scrum 敏捷軟體開發:Scrum實戰指南 Scrum要素 大規模Scrum:大規模敏捷組織的設計 用戶故事地圖 用 ......

    uj5u.com 2020-09-10 05:07:45 more
  • CODING DevOps 代碼質量實戰系列最后一課,周四發車

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。 **《DevOps 代碼質量實戰(Java 版)》**為 CODING DevOps 代碼質量實戰系列的最后一課,同時也是本系列的 ......

    uj5u.com 2020-09-10 05:07:52 more
  • 敏捷軟體工程實踐書籍

    Scrum轉型想要做好,第一步先了解并真正落實Scrum,那么我推薦的Scrum書籍是要看懂并實踐的。第二步是團隊的工程實踐要做扎實。 下面推薦工程實踐書單: 重構:改善既有代碼的設計 決議極限編程 : 擁抱變化 代碼整潔代碼 程式員的職業素養 修改代碼的藝術 撰寫可讀代碼的藝術 測驗驅動開發 : ......

    uj5u.com 2020-09-10 05:07:55 more
  • Jenkins+svn+nginx實作windows環境自動部署vue前端專案

    前面文章介紹了Jenkins+svn+tomcat實作自動化部署,現在終于有空抽時間出來寫下Jenkins+svn+nginx實作自動部署vue前端專案。 jenkins的安裝和配置已經在前面文章進行介紹,下面介紹實作vue前端專案需要進行的哪些額外的步驟。 注意:在安裝jenkins和nginx的 ......

    uj5u.com 2020-09-10 05:08:49 more
  • CODING DevOps 微服務專案實戰系列第一課,明天等你

    CODING DevOps 微服務專案實戰系列第一課**《DevOps 微服務專案實戰:DevOps 初體驗》**將由 CODING DevOps 開發工程師 王寬老師 向大家介紹 DevOps 的基本理念,并探討為什么現代開發活動需要 DevOps,同時將以 eShopOnContainers 項 ......

    uj5u.com 2020-09-10 05:09:14 more
  • CODING DevOps 微服務專案實戰系列第二課來啦!

    近年來,工程專案的結構越來越復雜,需要接入合適的持續集成流水線形式,才能滿足更多變的需求,那么如何優雅地使用 CI 能力提升生產效率呢?CODING DevOps 微服務專案實戰系列第二課 《DevOps 微服務專案實戰:CI 進階用法》 將由 CODING DevOps 全堆疊工程師 何晨哲老師 向 ......

    uj5u.com 2020-09-10 05:09:33 more
  • CODING DevOps 微服務專案實戰系列最后一課,周四開講!

    隨著軟體工程越來越復雜化,如何在 Kubernetes 集群進行灰度發布成為了生產部署的”必修課“,而如何實作安全可控、自動化的灰度發布也成為了持續部署重點關注的問題。CODING DevOps 微服務專案實戰系列最后一課:**《DevOps 微服務專案實戰:基于 Nginx-ingress 的自動 ......

    uj5u.com 2020-09-10 05:10:00 more
  • CODING 儀表盤功能正式推出,實作作業資料可視化!

    CODING 儀表盤功能現已正式推出!該功能旨在用一張張統計卡片的形式,統計并展示使用 CODING 中所產生的資料。這意味著無需額外的設定,就可以收集歸納寶貴的作業資料并予之量化分析。這些海量的資料皆會以圖表或串列的方式躍然紙上,方便團隊成員隨時查看各專案的進度、狀態和指標,云端協作迎來真正意義上 ......

    uj5u.com 2020-09-10 05:11:01 more
最新发布
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:41:12 more
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:35:34 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:05:44 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:00:18 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:20:31 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:55 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:18:51 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:00 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:17:55 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:12:06 more