Some problems with the .net TabControl extension

I extended the TabControl to support the close button for individual tabs. See screenshot:

enter image description here

Problem 1

Hovering over the close button does not fire the MouseHover event. There is a slight delay of about 200ms resulting in a delayed image for the hover state. If I find quickly enough above the button, the event is not fired at all.

I am using the following code to place a button on a TabControl (making the Button a child of the TabControl):

[DllImport("User32", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndParent);

...

SetParent(closeButton.Handle, this.Handle);

      

By the way, this cannot be done:

closeButton.Parent = this; // this == instance of TabControl

      

This will throw an exception, so I'm using the API call.

Any idea why MouseHover is delaying?

Problem 2

It is not possible to use a transparent background image for the close button because the background will appear as the system control color. I read that a control with the BackColor set to transparency will accept the BackColor of the parent control. My parent control is a TabControl instance that doesn't have a BackColor property.

Is there a way to dynamically set the BackColor of the TabControl to transparent? Maybe with a winapi call?

Issue 3

As you can see in the screenshot, there is no padding in the tab text forcing the close button to overlap the text. How can I solve this without using a dirty hack, how do I add some spaces to the text?

To get the position of a tab header element, I use the winapi call:

WinApi.RECT myRect = new WinApi.RECT();
WinApi.SendMessage(this.Handle, WinApi.TCM_GETITEMRECT, (IntPtr)this.TabPages.IndexOf(tab), ref myRect);
Rectangle realRect = new Rectangle(myRect.Left, myRect.Top, myRect.Width, myRect.Height);

      

Maybe there is a way to set the size via api call? TCM_SETMINTABWIDTH can be set, but this will change the minimum width for all tabs.

Issue 4

To determine which tab is being closed I am currently using a native method:

ExtendedTabControl.SetTabCloseable(TabPage tab)

      

What should the implementation look like to make this work in DesignMode? Extending the TabPage class (adding a "Closeable" property) and then notifying VisualStudio (via annotations?) That my own TabPage class should be used in DesignMode?

+3


source to share


2 answers


Problem 1 It is probably much easier to pretend it is a button and not a button. Set the DrawMode of the tab control to OwnerDrawFixed and use the DrawItem event to draw the text and then the button. Since you are in full control of the drawing, you can crop text and draw transparent images, etc.

To emulate a button you will need to handle the MouseDown / MouseMove / MouseUp TabControl events

Since you will not have any real buttons, you will need to keep a list of rectangles that are the borders of the button you drew. This way, in mouse events, you can test if you are over the button and act accordingly.

My result (written in Delphi, so the code won't really help you) ends like this: Tab control with close button



The image for the button ultimately gets drawn across windows when called in a paint event.

Problem 2 This goes away when you don't use the real button.

Issue 3 The only way I know of this is to use the ItemSize property of the tab control to make the tabs wide enough to accommodate the text.

Problem 4 It becomes a boolean property of the tab itself, so yes. You will need to handle your own tabs if you want to do this independently for each tab. This is a bit of a topic on its own, so it might be better for another question rather than translating it all into one.

+2


source


protected override void OnHandleCreated(EventArgs e) {
  SendMessage(NativeMethods.TCM_SETPADDING, 0, 
              NativeMethods.Util.MAKELPARAM(padding.X, padding.Y));
}

      



0


source







All Articles