Can I use a DrawItem event handler with a CheckedListBox?
Asked Answered
V

2

1

I would like to override the text displayed when an item is added to a checked list box. Right now it is using obj.ToString(), but I want to append some text, without changing the objects ToString method. I have seen examples of handling the DrawItem event for ListBoxs, but when I try to implement them, my event handler is not called. I have noted that the Winforms designer does not seem to allow me to assign a handler for the DrawItem event. Being stubborn, I just added the code myself

        listbox1.DrawMode = DrawMode.OwnerDrawVariable;
        listbox1.DrawItem += listbox1_DrawItem;

Am I trying to do the impossible?

Volumetric answered 10/9, 2013 at 17:15 Comment(1)
You might be interested in a better solution to this problem (and any other UI-specific problems you can think of)Eliott
U
4

Not impossible, but incredibly difficult. What you suggest will not work, note the meta-data in class CheckedListBox for method DrawItem:

// Summary:
//     Occurs when a visual aspect of an owner-drawn System.Windows.Forms.CheckedListBox
//     changes. This event is not relevant to this class.
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public event DrawItemEventHandler DrawItem;

Therefore, your only option is to derive your own class from CheckedListBox, and in my limited testing, this will be a long road. You can handle the drawing simply enough, as such:

public class CustomCheckedListBox : CheckedListBox
{
    protected override void OnDrawItem(DrawItemEventArgs e)
    {
        String s = Items[e.Index].ToString();
        s += "APPEND";  //do what you like to the text
        CheckBoxState state = GetCheckBoxState(e.State);  // <---problem
        Size glyphSize = CheckBoxRenderer.GetGlyphSize(e.Graphics, state);
        CheckBoxRenderer.DrawCheckBox(
            e.Graphics, 
            e.Bounds.Location, 
            new Rectangle(
                new Point(e.Bounds.X + glyphSize.Width, e.Bounds.Y), 
                new Size(e.Bounds.Width - glyphSize.Width, e.Bounds.Height)), 
            s, 
            this.Font, 
            false,
            state);
    }
}

Note the method GetCheckBoxState(). What you get in the DrawItemEventArgs is a DrawItemState, not the CheckBoxState you need, so you have to translate, and that's where things started to go downhill for me.

Soldier on, if you like, this should get you started. But I think it'll be a messy, long road.

Unalloyed answered 10/9, 2013 at 18:58 Comment(2)
+1 for your effort and coming up with a not-so-simple code. But I don't think that you (= the OP) should even consider the option of relying on drawing events if what he wants is affecting text. The statement "I don't want the modifications to be returned by the ToString() method" does not sounds as a reason to me (why not overriding the ToString() method?). I am not saying all this just for this specific case, but in general: better using draw/paint events to draw/paint (= colors, contours, etc.) and text ones to write. It would be easier and, most likely, much more reliable.As
@varocarbas I don't disagree. But given the restrictions OP placed, this is the only other course available.Unalloyed
H
0

I continued the work in DonBoitnotts answer.

The "GetCheckBoxState" is implemented using a very limited set with only two states.

var state = GetItemChecked(e.Index) ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal;

Vertically aligned the checkbox and left aligned the text.

var b = e.Bounds;
int checkPad = (b.Height - glyphSize.Height) / 2;
CheckBoxRenderer.DrawCheckBox(g, new Point(b.X + checkPad, b.Y + checkPad),
    new Rectangle(
        new Point(b.X + b.Height, b.Y),
        new Size(b.Width - b.Height, b.Height)),
    text, this.Font, TextFormatFlags.Left, false, state);
Hamate answered 20/11, 2014 at 16:10 Comment(1)
Important: to avoid strange effects in the text (visual like bold) the code must starts with e.DrawBackgroud();Subtype

© 2022 - 2024 — McMap. All rights reserved.