精华内容
下载资源
问答
  • 演示了常见窗体和对话框的产生原理,演示了控件的WM_DRAWITEM消息重绘和使用窗体子类化控件重绘。 演示了常见窗体和对话框的产生原理,演示了控件的WM_DRAWITEM消息重绘和使用窗体子类化控件重绘。
  • DrawItem

    2015-07-16 10:11:00
    今天从CButton派生了一个类CUIButton,主要用于自绘,按照基本的流程,重写DrawItem方法。 步骤如下:点击CUIButton按钮,在右键弹出菜单中选择“add windows message Handler", 找到DrawItem,为其添加消息...

     

    原文链接: http://blog.csdn.net/jiftlixu/article/details/4893505

    今天从CButton派生了一个类CUIButton,主要用于自绘,按照基本的流程,重写DrawItem方法。

    步骤如下:点击CUIButton按钮,在右键弹出菜单中选择“add windows message Handler",

    找到DrawItem,为其添加消息映射,添加的代码如下:

    void CUIButton::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)

    结果在使用到CUIButton的地方用SubClassDlgItem就会出问题。

     

    后来调试发现,不应该按照上面的添加此消息的映射,而是为CUIButton类重写DrawItem函数,添

    加方法:

    在类CUIButton右键,在弹出菜单中选择"Add Virtual Function",弹出的添加虚函数框中选

    择"DrawItem",向导为我们生成的代码如下:

    void CUIButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)

     

    在这里添加所需的自绘代码就ok了

     

     

     

    附: how to implement control to self-draw

    1、从CButton类派生自己的CUIControl类

    2、借助于MFC向导生成工具,为期添加虚函数DrawItem()和OnEraseBkgnd()。

         注意:DrawItem()是控件重定义的函数,不是OnDrawItem()。

    3、在DrawItem()中近控件的自绘处理,这里给出一个实例代码,用于一个自定义Button,在

         Button上面绘图:

        void CUIButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
    {
     // TODO: Add your message handler code here and/or call default
     
     //CButton::OnDrawItem(nIDCtl, lpDrawItemStruct);

     int nCxIcon = ::GetSystemMetrics(SM_CXICON);
     int nCyIcon = ::GetSystemMetrics(SM_CYICON);
     CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
     CBitmap bitmap;
     bitmap.CreateCompatibleBitmap(pDC,nCxIcon,nCyIcon);
     CDC dcMem;
     dcMem.CreateCompatibleDC(pDC);
     CBitmap *pOldBitmap = (CBitmap *)dcMem.SelectObject(bitmap);
     ASSERT(pOldBitmap);

     HICON hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
     ASSERT(hIcon);

     CRect rcClient;
     GetClientRect(&rcClient); // get the button's rect
     dcMem.StretchBlt(0,0,nCxIcon,nCyIcon,pDC,2,2,rcClient.Width() - CX_SHADOW - 4, 
      rcClient.Height() - CY_SHADOW - 4,SRCCOPY);
     
     dcMem.DrawIcon(0,0,hIcon);

     // draw border around icon
     CPen pen;
     pen.CreateStockObject(BLACK_PEN);
     ASSERT(pDC != NULL);
     CPen* pPenOld = pDC->SelectObject(&pen);
     pDC->Rectangle(0, 0, rcClient.Width()-CX_SHADOW, rcClient.Height()-CY_SHADOW);
     if (pPenOld)
      pDC->SelectObject(pPenOld);

     //pDC->StretchBlt(0,0,80,80,&dcMem,0,0,nCxIcon,nCyIcon,SRCCOPY);
     pDC->StretchBlt(2,2,rcClient.Width() - CX_SHADOW - 4,rcClient.Height() - CY_SHADOW - 4,&dcMem,0,0,nCxIcon,nCyIcon,SRCCOPY);

    }

     

    4、为OnEraseBkGround()添加代码。这里很简单,直接返回True即可:

       BOOL CUIButton::OnEraseBkgnd(CDC* pDC) 
    {
     // TODO: Add your message handler code here and/or call default
     return TRUE;
     //return CButton::OnEraseBkgnd(pDC);
    }

    5、在你的对话框中使用CUIButton按钮,首先在dialog资源中添加一个按钮(CButton)。

    6、在对话框类的头文件中定义一个成员CUIButton m_CtlUIBtn;注意变量的类型是CUIButton而

        不是CButton

    7 、在OnInitDialog中用SubClass技术:

         BOOL CAboutDlg::OnInitDialog() 
    {
     CDialog::OnInitDialog(); 
     m_CtlUIButton.SubclassDlgItem(IDC_UI_BUTTON,this);
      return TRUE;  // return TRUE unless you set the focus to a control
                   // EXCEPTION: OCX Property Pages should return FALSE
    }

     

    that is OK!

     

    展开全文
  • C# Winform编程ListBox之DrawItem事件

    千次阅读 2019-11-25 21:07:49
    this.listBox1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.listBox1_DrawItem);  事件由ListBox触发. 下面,再举一反三下,实现交替颜色的列表框:     public ...

    新建一个winform项目,拖一个ListBox控件listBox1

     

     

     
    1. public Form1() 
    2.  
    3.  
    4.     InitializeComponent();             
    5.  
    6.     listBox1.DrawMode = DrawMode.OwnerDrawFixed; 
    7.  

    首先需要设置DrawMode为DrawMode.OwnerDrawFixed 或 DrawMode.OwnerDrawVariable 时,才触发该事件(DrawItem事件).,也可以通过设计器在属性面板里设置哈。

     

     
    1. private void listBox1_DrawItem(object sender, DrawItemEventArgs e) 
    2.     e.DrawBackground();//绘制背景 
    3.     Brush myBrush = Brushes.Black; 
    4.  
    5.     switch (e.Index) 
    6.     { 
    7.         case 0: 
    8.             myBrush = Brushes.Red; 
    9.             break; 
    10.         case 1: 
    11.             myBrush = Brushes.Orange; 
    12.             break; 
    13.         case 2: 
    14.             myBrush = Brushes.Purple; 
    15.             break; 
    16.     } 
    17.     e.DrawFocusRectangle();//焦点框 
    18.  
    19.     //文本 
    20.     e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), e.Font, myBrush, e.Bounds, StringFormat.GenericDefault); 

    这是采用附加委托的方式处理,可以查看设计器产生的代码:

     

     
    1. this.listBox1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.listBox1_DrawItem); 

    事件由ListBox触发.

    下面,再举一反三下,实现交替颜色的列表框:

     

     
    1. public partial class Form1 : Form 
    2.     private Color RowBackColorAlt=Color.FromArgb(200,200,200);//交替色 
    3.     private Color RowBackColorSel = Color.FromArgb(150, 200, 250);//选择项目颜色 
    4.  
    5.     public Form1() 
    6.     { 
    7.         InitializeComponent();             
    8.         listBox1.DrawMode = DrawMode.OwnerDrawFixed; 
    9.     } 
    10.  
    11.     private void listBox1_DrawItem(object sender, DrawItemEventArgs e) 
    12.     { 
    13.         Brush myBrush = Brushes.Black; 
    14.  
    15.         if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) 
    16.         { 
    17.             myBrush = new SolidBrush(RowBackColorSel); 
    18.         } 
    19.         else if (e.Index % 2 == 0) 
    20.         { 
    21.             myBrush = new SolidBrush(RowBackColorAlt); 
    22.         } 
    23.         else 
    24.         { 
    25.             myBrush = new SolidBrush(Color.White); 
    26.         } 
    27.         e.Graphics.FillRectangle(myBrush, e.Bounds); 
    28.         e.DrawFocusRectangle();//焦点框 
    29.  
    30.         //文本 
    31.         e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), e.Font, Brushes.Black, e.Bounds, StringFormat.GenericDefault); 
    32.     } 
    33.  

    上图:

     

     

     接下来,设置ItemHeight,每一项的高度:

     

     
    1. public Form1() 
    2.     InitializeComponent();             
    3.     listBox1.DrawMode = DrawMode.OwnerDrawFixed; 
    4.     listBox1.ItemHeight = 24; 

    文字,剧中:

     

     
    1. //文本 
    2. StringFormat strFormat = new StringFormat(); 
    3. strFormat.Alignment = StringAlignment.Center; 
    4. strFormat.LineAlignment = StringAlignment.Center; 
    5. e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), e.Font, Brushes.Black, e.Bounds,strFormat); 

    上图片:

     

     下面看看MeasureItem 事件:

    仅当 DrawMode 属性被设置为 OwnerDrawVariable 时,才引发该事件。

     
    1. public partial class Form1 : Form 
    2.     private Color RowBackColorAlt=Color.FromArgb(200,200,200);//交替色 
    3.     private Color RowBackColorSel = Color.FromArgb(150, 200, 250);//选择项目颜色 
    4.  
    5.     public Form1() 
    6.     { 
    7.         InitializeComponent();             
    8.         listBox1.DrawMode = DrawMode.OwnerDrawVariable; 
    9.     } 
    10.  
    11.     private void listBox1_DrawItem(object sender, DrawItemEventArgs e) 
    12.     { 
    13.         Brush myBrush = Brushes.Black; 
    14.  
    15.         if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) 
    16.         { 
    17.             myBrush = new SolidBrush(RowBackColorSel); 
    18.         } 
    19.         else if (e.Index % 2 == 0) 
    20.         { 
    21.             myBrush = new SolidBrush(RowBackColorAlt); 
    22.         } 
    23.         else 
    24.         { 
    25.             myBrush = new SolidBrush(Color.White); 
    26.         } 
    27.         e.Graphics.FillRectangle(myBrush, e.Bounds); 
    28.         e.DrawFocusRectangle();//焦点框 
    29.  
    30.         //文本 
    31.         StringFormat strFormat = new StringFormat(); 
    32.         strFormat.Alignment = StringAlignment.Center; 
    33.         strFormat.LineAlignment = StringAlignment.Center; 
    34.         e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), e.Font, new SolidBrush(e.ForeColor), e.Bounds,strFormat); 
    35.     } 
    36.  
    37.     private void listBox1_MeasureItem(object sender, MeasureItemEventArgs e) 
    38.     { 
    39.         e.ItemHeight = (1+e.Index)*12; 
    40.     } 
    41.  
    展开全文
  • MFC程序设计中经常需要在标准控件的基础上进行自绘以便获得更美观的界面。最近在自绘CStatic控件时发现程序不执行DrawItem函数,于是将解决的方法记录下来备用。本文的编程环境为VS2008。

    MFC程序设计中经常需要在标准控件的基础上进行自绘以便获得更美观的界面。最近在自绘CStatic控件时发现程序不执行DrawItem函数,于是将解决的方法记录下来备用。本文的编程环境为VS2008。

    问题描述

    首先通过VS2008的窗体编辑器在对话框中加入一个Picture Control控件,如下图所示。

    在对话框中加入Picture Control控件

    为了实现Picture Control控件的自绘,自定义一个CStatic的子类CMyStatic,CMyStatic包含头文件MyStatic.h和MyStatic.cpp两个文件。
    MyStatic.h源代码如下:

    #pragma once
    
    
    // CMyStatic
    
    class CMyStatic : public CStatic
    {
    	DECLARE_DYNAMIC(CMyStatic)
    
    public:
    	CMyStatic();
    	virtual ~CMyStatic();
    
    protected:
    	virtual void PreSubclassWindow();
    	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    
    	DECLARE_MESSAGE_MAP()
    };
    

    MyStatic.cpp源代码如下:

    // MyStatic.cpp : 实现文件
    //
    
    #include "stdafx.h"
    #include "MyStatic.h"
    
    
    // CMyStatic
    
    IMPLEMENT_DYNAMIC(CMyStatic, CStatic)
    
    CMyStatic::CMyStatic()
    {
    
    }
    
    CMyStatic::~CMyStatic()
    {
    }
    
    
    BEGIN_MESSAGE_MAP(CMyStatic, CStatic)
    END_MESSAGE_MAP()
    
    
    
    // CMyStatic 消息处理程序
    
    
    
    void CMyStatic::PreSubclassWindow()
    {
    	// TODO: 在此添加专用代码和/或调用基类
    	ModifyStyle(0, SS_OWNERDRAW);    // 使窗口自绘
    
    	CStatic::PreSubclassWindow();
    }
    
    void CMyStatic::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
    {
    	// TODO:  添加您的代码以绘制指定项
    	CRect rcClient;
    	GetClientRect(&rcClient);
    
    	// 绘制边框
    	CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    	pDC->DrawEdge(rcClient, EDGE_RAISED, BF_RECT);
    
    	// 绘制准星
    	int nLength = min(rcClient.right, rcClient.bottom) / 20;
    
    	pDC->MoveTo(rcClient.right / 2, rcClient.bottom / 2 - nLength);
    	pDC->LineTo(rcClient.right / 2, rcClient.bottom / 2 + nLength);
    
    	pDC->MoveTo(rcClient.right / 2 - nLength, rcClient.bottom / 2);
    	pDC->LineTo(rcClient.right / 2 + nLength, rcClient.bottom / 2);
    }
    

    自定义CMyStatic控件在PreSubclassWindow()函数中通过ModifyStyle()函数为控件增加SS_OWNERDRAW属性以便于控件在创建时进行自绘。然后在DrawItem()函数中增加了自绘代码。

    为了使刚才在主对话框中添加的Picture Control控件能够与CMyStatic相关联,需要在对话框对应的头文件中加入CMyStatic变量:

    CMyStatic m_wndTest;    // 在主对话框关联的类中添加CMyStatic成员变量
    

    同时在主对话框对应的源文件中将变量与控件进行关联:

    void CtestDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	DDX_Control(pDX, IDC_STATIC_TEST, m_wndTest);    // 关联成员变量和静态控件
    }
    

    接着运行程序发现主对话框中的Picture Control控件消失了。

    无法显示Picture Control控件

    解决方法

    解决方法是看了CButtonST的代码后找到的,这是一个比较有名的MFC第三方按钮控件。只需要将PreSubclassWindow()中的ModifyStyle()函数修改为如下即可:

    ModifyStyle(SS_TYPEMASK, SS_OWNERDRAW, SWP_FRAMECHANGED);
    

    重新运行程序,自绘成功。

    Picture Control自绘成功

    起作用的其实是第一个参数SS_TYPEMASK,第三个参数SWP_FRAMECHANGED可加可不加。具体原因也不清楚,如果有人知道的话欢迎交流哦。

    展开全文
  • WM_DRAWITEMDrawItem()的讨论

    千次阅读 2018-02-12 09:59:05
    学习中经常遇到要重写DrawItem()的情况,但又有一个WM_DRAWITEM消息,它们是什么样的关系呢。如果我们要重写一个CButton取名为CMyButton,我们可以重写CMyButton的DrawItem()函数来实现我们的需求,但CMyButton...

    学习中经常遇到要重写DrawItem()的情况,但又有一个WM_DRAWITEM消息,它们是什么样的关系呢。

    如果我们要重写一个CButton取名为CMyButton,我们可以重写CMyButton的DrawItem()函数来实现我们的

    需求,但CMyButton::DrawItem()是在什么时候调用呢?它是在它的宿主类的OnDrawItem()中被调用,

    OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct )正是对WM_DRAWiTEM的相应函数。

    宿主类可以根据nIDCtl来判定是哪个子控件。其实我们可以在OnDrawItem函数里对子控件进行绘制,但是有很多

    的子控件看起来不好,所以我们应该在子类的DrawItem对子类绘制,例如CMyButton::DrawItem。所以可以

    这样理解,OnDrawItem是画窗口中的子控件的,因为它的入口参数LPDRAWITEMSTRUCT带入不同子控件的相

    关参数,而且,你得把字控件设置成“自画”类型,才会调用到OnDrawItem。

        当自绘按钮(owner-draw button),下拉列表框(combo box),列表框(list box)视觉属性,或者菜单发生变化时,

    框架为他们的owner调用OnDrawItem(发送WM_DRAWITEM),在宿主类调用子类的DrawItem(发送WM_DRAWITEM消息)。

    我们可以重载子类的DrawItem可以绘制自己需要的控件,不是所有设置成自画类型的控件都会调用父窗口的OnDrawItem,

    例如ListBox的自画,你就必须重载CListBox的DrawItem方法和MeasureItem方法才可以,但象菜单,按钮等的自画则会调用

    OnDrawItem。在SDK中,子类是不可能受到WM_DRAWITEM,在MFC中可以,这是类的设计者设计的(反射),这的确不错。

        在学习中还有一个消息也是由宿主类被调用的,它就是WM_CTRCOLOR。这个消息是在子控件将要绘画时,向宿主

    类发送,宿主类利用发射机制让子类自己又一个处理的机会。OnCtlColor (CDC* pDC, CWnd* pWnd,  UINT  nCtlColor)

    pDC,pWnd都是于子类相关的,在这里可以设置,前景颜色,背景颜色,画刷类型,字体等等,但不能改变元素的界面框架,

    这是DrawItem 所能干的。

       如果同时有DrawItem(子类),OnDrawItem(宿主类),OnCtlColor(宿主类),它们的调用顺序是:

    OnCtlColor,OnDrawItem,DrawItem。

        如果我们同时又相应的子类的WM_PAINT消息,这也许OnPaint在内部进行了一些处理,判断是否自绘来决定是否向宿主类

    发送WM_DRAWITEM,所以如果响应了WM_PAINT子类就不会向宿主类发送WM_DRAWITEM消息,你要完成子类的全部绘

    制工作,如果子类是一个列表框,就很麻烦。这时调用顺序是OnCtlColor,OnPaint。

      在发送一个WM_PAINT消息前,总会先发送一个WM_ERASEBACK消息,我们在这里在一个背景图片。

       对于我们平时对控件的绘制,上面介绍的差不多了,还有一个CView的问题,也就是OnPaint和Ondraw的关系,

    其实这个很简单,CView::OnPaint()的源码如下:

    void CView::OnPaint()

    {

       CPaintDC dc(this);

       OnPrepareDC(&dc);

       OnDraw(&dc);

    }

    展开全文
  • 参考buttonST写的按钮控件drawitem函数,很简单,就是实现标准按钮的功能,适合需求简单的同学,比如想改字体颜色,直接在源码里该就可以,当然也可以使用buttonST,但是其功能太强大了,有时候用不着,而且源代码多...
  • 我在学习中经常遇到要重写DrawItem()的情况,但又有一个WM_DRAWITEM消息,它们是什么样的关系呢。 如果我们要重写一个CButton取名为CMyButton,我们可以重写CMyButton的DrawItem()函数来实现我们的 ...
  • 常见的有WM_DRAWITEM消息,DrawItem虚函数,还有一个NM_CUSTOMDRAW反射消息,NM_CUSTOMDRAW是通过WM_NOTIFY发送给父窗口的。我们可以在控件类里面反射调用次消息。 现在我们以CTListCtrl控件举例对比NM_CUSTOMDRAW...
  • DrawItem事件

    千次阅读 2013-09-27 10:11:16
    void CMyDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) DRAWITEMSTRUCT结构[1]为需要自绘的控件或者菜单项提供了必要的...该结构是由收到的WM_DRAWITEM消息的lParam参数提供的,这个参数是指向这
  • MFC CStatic控件在DrawItem中自绘

    千次阅读 2016-09-29 09:28:39
    转载自:也已时过境迁的MFC CStatic控件在DrawItem中自绘 实现PreSubclassWindow void CStaticHref::PreSubclassWindow() { // TODO: Add your specialized code here and/or call the base classDWORD dwStyle = ...
  • 只有DrawMode等于OwnerDrawFixed时,才会在绘制选项卡时发生DrawItem事件tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed; 转载于:https://www.cnblogs.com/wygm/p/5667404.html
  • 我在学习中经常遇到要重写DrawItem()的情况,但又有一个WM_DRAWITEM消息,它们是什么样的关系呢。 如果我们要重写一个CButton取名为CMyButton,我们可以重写CMyButton的DrawItem()函数来实现我们的 需求,...
  • 自绘控件之DrawItem(LPDRAWITEMSTRUCT )

    千次阅读 2015-09-16 09:13:24
    virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct ); Parameters lpDrawItemStruct A long pointer to a DRAWITEMSTRUCT structure. The structure contains infor
  • 控件自绘-DrawItem添加

    千次阅读 2019-01-21 15:41:36
    DrawItem是一个虚函数,在类向导中在虚函数下面添加,如图: 另外在消息里面也有一个DRAWITEM,如下图: 按钮设置重绘代码 ModifyStyle(0, BS_OWNERDRAW); 如果指定了重绘,但是没有实现重绘代码,程序运行就会...
  • WM_DRAWITEM通告消息

    千次阅读 2012-11-10 23:45:34
    参考文章: ... 当一个具有Owner-Draw风格的button control, combo-box control, list-box control, or menu需要显示外观时,会发送一条WM_DRAWITEM消息至它的隶属窗口。 前面讲的WM_ERASEBKGND, WM_CTL
  • 自绘CListCtrl时发现ON_WM_MEASUREITEM_REFLECT和DrawItem(LPDRAWITEMSTRUCT lpMeasureItemStruct) 无响应 一般情况下,我们都是在 dialog 里面 放一个 list 控件,然后 用自己的类绑定自己的自绘对象,如同下面: ...
  • 在需要绘制的控件或者菜单项对应的WM_DRAWITEM消息函数中得到一个指向 该结构的指针。 DRAWITEMSTRUCT结构的定义如下:  typedef struct tagDRAWITEMSTRUCT{  UINT CtlType;   UINT CtlID;   UINT ...
  • 控件重绘有三种方法: 1 设定界面属性 2 利用Windows的消息机制,通过...此方式涉及NM_CUSTOMDRAW和WM_DRAWITEM 3 利用虚函数机制,重载虚函数。即DrawItem虚函数。对于NM_CUSTOMDRAW,某些支持此消息的控件会发送
  • 我在学习中经常遇到要重写DrawItem()的情况,但又有一个WM_DRAWITEM消息,它们是什么样的关系呢。 如果我们要重写一个CButton取名为CMyButton,我们可以重写CMyButton的DrawItem()函数来实现我们的需求, 但...
  • 这几天一直为ClistCtrl重绘后图片空
  • 一般用于列表控件、组合框或树形控件,在控件的每个记录被重绘时调用的消息,第一个是用于响应重绘时单一记录的尺寸调整,第二个用于每个单一记录区域内的绘制。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,018
精华内容 2,807
关键字:

DrawItem