【问题标题】:Override DrawItem of ComboBox覆盖 ComboBox 的 DrawItem
【发布时间】:2014-06-29 11:50:06
【问题描述】:

我更改了各种控件的突出显示颜色,并计划进行更多更改。因此,我最好创建自己的控件并重复使用它们,而不是为每个控件进行更改。

我创建了一个新的用户控件,并继承自System.Windows.Forms.ComboBox。 问题是我找不到像 onClick 那样覆盖 onDraw 的方法。

那么我将如何去覆盖它?这是我用于每个控件onDraw事件的代码

public void comboMasterUsers_DrawItem(object sender, DrawItemEventArgs e)
    {
        e.DrawBackground();

        Graphics g = e.Graphics;
        Brush brush = ((e.State & DrawItemState.Selected) == DrawItemState.Selected) ?
                      Brushes.LightSeaGreen : new SolidBrush(e.BackColor);

        g.FillRectangle(brush, e.Bounds);
        e.Graphics.DrawString(comboMasterUsers.Items[e.Index].ToString(), e.Font,
                 new SolidBrush(e.ForeColor), e.Bounds, StringFormat.GenericDefault);

        e.DrawFocusRectangle();
    }

谢谢!

【问题讨论】:

    标签: c# inheritance combobox controls ondraw


    【解决方案1】:

    给你:

    public class myCombo : ComboBox
    {
        // expose properties as needed
        public Color SelectedBackColor{ get; set; }
    
        // constructor
        public myCombo()
        {
            DrawItem += new DrawItemEventHandler(DrawCustomMenuItem);
            DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
            SelectedBackColor= Color.LightSeaGreen;
        }
    
        protected  void DrawCustomMenuItem(object sender, DrawItemEventArgs e)
        {
            e.DrawBackground();
             // a dropdownlist may initially have no item selected, so skip the highlighting:
            if (e.Index >= 0) 
            {  
              Graphics g = e.Graphics;
              Brush brush = ((e.State & DrawItemState.Selected) == DrawItemState.Selected) ?
                             new SolidBrush(SelectedBackColor) : new SolidBrush(e.BackColor);
              Brush tBrush = new SolidBrush(e.ForeColor);
    
              g.FillRectangle(brush, e.Bounds);
              e.Graphics.DrawString(this.Items[e.Index].ToString(), e.Font,
                         tBrush, e.Bounds, StringFormat.GenericDefault);
              brush.Dispose();
              tBrush.Dispose();
            }
            e.DrawFocusRectangle();
        }
    }
    

    您可以考虑在扩展自定义项时公开更多属性,以便您可以在需要时为每个实例更改它们..

    同时不要忘记处理您创建的 GDI 对象,例如画笔和钢笔!

    编辑:刚刚注意到BackColor 会隐藏原始属性。改成SelectedBackColor,居然说是什么!

    编辑 2: 正如 Simon 在 cmets 中指出的那样,有一个 HasFlag 方法,因此在 .Net 4.0 中也可以这样写:

          Brush brush = ((e.State.HasFlag(DrawItemState.Selected) ?
    

    更清晰、更简短。

    编辑 3: 实际上,对于在控件上绘图,建议使用 TextRenderer.DrawText 而不是 graphics.DrawString..

    【讨论】:

    • 谢谢,它有效。但是有一个问题。当我将 DropDownStyle 更改为 DropDownList 时,出现错误:InvalidArgument =value of -1 is not valid for index
    • 查看我的小修正 wrt tBrush! GDI 对象有一种可怕的无声泄漏趋势..
    • 还有一个小的更正 ;-) 我没有注意到警告,但现在看起来没问题..
    • 长话短说:画笔、钢笔和位图很特别。它们不是 GC 收集的普通 c# 对象;它们分开存放,您有责任处理它们。 90 年代的 GDI 遗产..
    • 哦,我明白了。谢谢您的信息!
    【解决方案2】:

    感谢这篇有用的帖子。我做了一个小改进,其他人可能会觉得有用。

    当 ComboBox 将其 DisplayMember 属性设置为访问所显示项目的特定属性时,ToString() 可能不会给出预期的文本。解决方法是使用:

        GetItemText(Items[e.Index])
    

    在对 DrawString() 的调用中检索所需的文本。

    【讨论】:

      【解决方案3】:

      这对寻找 VB.net 的人很有用

      公开课 myCombo

      Inherits ComboBox
      
      Public Property SelectedBackColor As Color
      
      Public Sub New()
          AddHandler DrawItem, New DrawItemEventHandler(AddressOf DrawCustomMenuItem)
          DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed
          DropDownStyle = ComboBoxStyle.DropDownList
      End Sub
      
      Protected Sub DrawCustomMenuItem(ByVal sender As Object, ByVal e As DrawItemEventArgs)
          If e.Index < 0 Then
              Return
          End If
          e.Graphics.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
          Dim Cb As ComboBox = TryCast(sender, ComboBox)
          If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
              e.Graphics.FillRectangle(New SolidBrush(Color.OrangeRed), e.Bounds) ' selected item background color
          Else
              e.Graphics.FillRectangle(New SolidBrush(Color.White), e.Bounds) ' background color
          End If
          e.Graphics.DrawString(Cb.Items(e.Index).ToString(), e.Font, New SolidBrush(e.ForeColor),
                                New Point(e.Bounds.X, e.Bounds.Y), StringFormat.GenericTypographic)
      End Sub
      

      结束类

      【讨论】:

        【解决方案4】:

        我尝试将 comboMasterUsers 固定到 comboBox1。 示例:

            public void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
            {
                e.DrawBackground();
        
                Graphics g = e.Graphics;
                Brush brush = ((e.State & DrawItemState.Selected) == DrawItemState.Selected) ?
                              Brushes.LightSeaGreen : new SolidBrush(e.BackColor);
        
                g.FillRectangle(brush, e.Bounds);
                e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), e.Font,
                         new SolidBrush(e.ForeColor), e.Bounds, StringFormat.GenericDefault);
        
                e.DrawFocusRectangle();
            }
        

        我看到了: The sample

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-12
          • 1970-01-01
          • 2021-12-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多