|
Introduction
Yesterday, I was thinking the best way to solve a particular situation (specific actions derived logically from one) was a split button. Searching and searching on MSDN produced no results, so I was perplexed: no split button in .NET? No, there isn't. The strange thing is that a StripSplitButton (or something like that) exists, that is, the split button equivalent for the ToolStrip. Probably, not being a standard control for the system, they though not to include the control, because it was easy to simulate its functionality with images, and that's what I did.
Using the code
The control is very easy to use. Anyway, this is the step-by-step how-to-do:
- Include SplitButton.cs and SplitButton.designer.cs in your project.
- Load the assembly in the toolbox of Visual Studio, or just insert a
Button control in your form, and then change the type from Button to SplitButton.
[Updated: Oct '06] You can stop here, default images for split states will be used by the control, or you can follow next steps to customize split images.
Optional:
- Add an
ImageList to your form (or control or whatever) and set the ImageList property of the SplitButton to this ImageList.
- Add images you want to the
ImageList for the SplitButton splitter side statuses: Normal, Hover, Clicked, Disabled, Focused.
- Now, have a look at the property windows for the
SplitButton, go to "Split Button Images" category, and simply select an image for each status from the list box of images (the ones in the ImageList of the SplitButton).
- Now, you can set some suggested options:
TextAlign to MiddleLeft, ImageAlign to MiddleRight, and TextImageRelation to TextBeforeImage. You're done.
Now you can set some custom options for the SplitButton, a brief description follows:
bool DoubleClickedEnabled - Indicates whether the double click event is raised on the SplitButton.
bool AlwaysDropDown - Indicates whether the SplitButton always shows the drop down menu even if the button part is clicked.
bool AlwaysHoverChange - Indicates whether the SplitButton always shows the hover image status in the split part even if the button part is hovered.
bool CalculateSplitRect - Indicates whether the split rectangle must be calculated (based on the split image size).
bool FillSplitHeight - Indicates whether the split height must be filled to the button height even if the split image height is lower.
int SplitHeight - The split height (ignored if CalculateSplitRect is set to true).
int SplitWidth - The split width (ignored if CalculateSplitRect is set to true).
In addition to this, there are two events:
ButtonClick - Occurs when the button part of the SplitButton is clicked.
ButtonDoubleClick - Occurs when the button part of the SplitButton is double-clicked.
Conclusion
It's only a simple control, I know, but it could be useful in my opinion.
So, that's all, I think. I hope you'll find it useful, bye!
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 29 (Total in Forum: 29) (Refresh) | FirstPrevNext |
|
|
 |
|
|
 I think codeproject is the best web-Page for a coder or any IT-worker.Because there are many friends to help you when you need. At this place every body like a student.They study a lot of programming skill from many article.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
I was wondering what event I can put code in to be able to tell what subitem is being clicked?
If I'm populating the control like this:
this.splitButton1.ContextMenuStrip = new ContextMenuStrip(); this.splitButton1.ContextMenuStrip.Items.Add("one"); this.splitButton1.ContextMenuStrip.Items.Add("two"); this.splitButton1.ContextMenuStrip.Items.Add("three");
Is there a way to differentiate when someone clicks "one" or "two?" Also, can you populate the subitems on the control itself somehow (like a Collections property... but I don't see one)?
Thanks.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The easier (and the best in my opinion) way to populate menu items is to add a context menu (ContextMenuStrip class) to your form/UserControl through the designer and then add/remove/edit items or event handlers (ContextMenuStrip.ItemClicked is the one you need) through the designer itself. In such a way you can visually manage your context menu for the split button without the need to write any line of code (you need to do so only if menu items are dynamically determined, that is, created at run time). Then you simply have to select the ContextMenuStrip property of the SplitButton to your newly created context menu (using the drop down for the ContextMenuStrip property in the properties window). You should have a look at the demo project in the download section in this same article because in there I do exactly the things explained above.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
I already knew about the first solution, the problem is: that control doesn't allow you to use custom images for the split button states, it simply draws the triangle by himself and so I wrote this control to accomplish the task. In regard to the second solution, it has been published yesterday (June 24th, 2007) while mine has been published 10 months ago. In addition my article is also referenced in there as "# A buggy, but open source SplitButton designed by some anonymous guy. Pass.", and that is really funny because it says my control is bugged but it doesn't say what the bugs are and where. Strangely enough, that page has been published yesterday and isn't even indexed in google but you posted this comment at 21:43 which leaves you about 21 hours (probably less) to find the page, analyse the code in there and comment my article. That blog has a google pagerank of 3, which makes it just impossible to find through search engines, I wonder how did you find it so fast.
|
| Sign In·View Thread·PermaLink | 2.33/5 (3 votes) |
|
|
|
 |
|
|
I guess you're implying I'm that guy. Truth is, I use that guy's Panel2006 (a corny name, with just as many bugs). He's often mean, but this time I thought that he posted something useful.
My mistake for trying to relay information.
|
| Sign In·View Thread·PermaLink | 3.00/5 (2 votes) |
|
|
|
 |
|
|
 |
|
|
I tried using the second one (that fixes Microsoft guy's errors), and received an error when I clicked on a button that had no items in it... not sure what happened there, but I'm going back to Microsoft guy's control until it works properly. Thanks for providing links to both.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I noticed that when you right-click on the split button you still get the default context menu. If you override the context menu property like so:
private ContextMenuStrip _ContextMenu;
public override ContextMenuStrip ContextMenuStrip { get { return _ContextMenu; } set { _ContextMenu = value; } }
then the context menu will not appear when you right-click the split button.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Yes you're right. But i don't think that this is the best solution, infact in that way works because the base control uses directly the field of the context menu, and not the property, but you can't know if in the feature it will do so (even if it would be illogical not doing that). The real solution would be renaming also the property, and not only using a different field, or another (worse) solution would be overriding the (right) click event handler. Using the property you need also to change the OnMouseDown method override, from:
if (_AlwaysDropDown || MouseInSplit()) { if (Enabled) { ... To:
if (_AlwaysDropDown || MouseInSplit()) { if (Enabled && mevent.Button == MouseButtons.Left) { ...
Thanks anyway for the report.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I find your SplitButton very usefull. One thing though. When I disable the button, the background image stays enabled. Could you tell me how to fix that? Thanks, Golan Bar-Nov.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
You have to select the disabled image in the DisabledImage property of the SplitButton (under "Split Button Images" category), after setting the ImageList property to your ImageList, it's not automatically selected/grayed. I think I'm going to update this article/control in the near future, but I'm too busy at this time.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thank you for your quick reply. The disabled image under the "Split Button Images" refers to the arrow image on a disabled mode. There is another image in the button's base class called BackgroundImage which stays enabled when the control is disabled.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The control doesn't check the background image, and nor use that property, so is not a control fault if it remains enabled. So if you want to disable it you must do by yourself, and that shouldn't be difficult. Simply create a grayed-scale of your image, this routine should work:
public static Image CreateDisabledImage(Image normalImage) { ImageAttributes attributes1 = new ImageAttributes(); attributes1.ClearColorKey(); attributes1.SetColorMatrix(ToolStripRenderer.DisabledImageColorMatrix); Size size1 = normalImage.Size; Bitmap bitmap1 = new Bitmap(size1.Width, size1.Height); Graphics graphics1 = Graphics.FromImage(bitmap1); graphics1.DrawImage(normalImage, new Rectangle(0, 0, size1.Width, size1.Height), 0, 0, size1.Width, size1.Height, GraphicsUnit.Pixel, attributes1); graphics1.Dispose(); return bitmap1; }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Sorry, this is the complete code to disable an image (example program class):
static class Program { static ColorMatrix DisabledImageColorMatrix;
/// /// The main entry point for the application. /// [STAThread] static void Main() { float[][] singleArrayArray1 = new float[5][]; singleArrayArray1[0] = new float[] { 0.2125f, 0.2125f, 0.2125f, 0f, 0f }; singleArrayArray1[1] = new float[] { 0.2577f, 0.2577f, 0.2577f, 0f, 0f }; singleArrayArray1[2] = new float[] { 0.0361f, 0.0361f, 0.0361f, 0f, 0f }; float[] singleArray1 = new float[5]; singleArray1[3] = 1f; singleArrayArray1[3] = singleArray1; singleArrayArray1[4] = new float[] { 0.38f, 0.38f, 0.38f, 0f, 1f }; float[][] singleArrayArray2 = new float[5][]; float[] singleArray2 = new float[5]; singleArray2[0] = 1f; singleArrayArray2[0] = singleArray2; float[] singleArray3 = new float[5]; singleArray3[1] = 1f; singleArrayArray2[1] = singleArray3; float[] singleArray4 = new float[5]; singleArray4[2] = 1f; singleArrayArray2[2] = singleArray4; float[] singleArray5 = new float[5]; singleArray5[3] = 0.7f; singleArrayArray2[3] = singleArray5; singleArrayArray2[4] = new float[5];
DisabledImageColorMatrix = MultiplyColorMatrix(singleArrayArray2, singleArrayArray1);
Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); }
public static Image CreateDisabledImage(Image normalImage) { ImageAttributes attributes1 = new ImageAttributes(); attributes1.ClearColorKey(); attributes1.SetColorMatrix(Program.DisabledImageColorMatrix); Size size1 = normalImage.Size; Bitmap bitmap1 = new Bitmap(size1.Width, size1.Height); Graphics graphics1 = Graphics.FromImage(bitmap1); graphics1.DrawImage(normalImage, new Rectangle(0, 0, size1.Width, size1.Height), 0, 0, size1.Width, size1.Height, GraphicsUnit.Pixel, attributes1); graphics1.Dispose(); return bitmap1; }
static ColorMatrix MultiplyColorMatrix(float[][] matrix1, float[][] matrix2) { int num1 = 5; float[][] singleArrayArray1 = new float[num1][]; for (int num2 = 0; num2 < num1; num2++) { singleArrayArray1[num2] = new float[num1]; } float[] singleArray1 = new float[num1]; for (int num3 = 0; num3 < num1; num3++) { for (int num4 = 0; num4 < num1; num4++) { singleArray1[num4] = matrix1[num4][num3]; } for (int num5 = 0; num5 < num1; num5++) { float[] singleArray2 = matrix2[num5]; float single1 = 0f; for (int num6 = 0; num6 < num1; num6++) { single1 += singleArray2[num6] * singleArray1[num6]; } singleArrayArray1[num5][num3] = single1; } } return new ColorMatrix(singleArrayArray1); } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
In .Net 2.0 you can embedd a toolbar in a form completely invisibly. This way you can add the split buttons etc without need for coding...
Have a nice life!!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I don't agree, the "SplitButton" from a ToolBar will not look like a CommandButton (colors etc). But if you have found a solution for this, please let us know.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
I've tried, but had some troubles. It looks like a button when the button get focus, but not else. How did you get the ToolStrip to be invisible? What setting did you set in the ToolsStrip and on the ToolStipDownButton?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
why would you want to waste the resources of embedding a toolbar into your screen if you DO NOT need one?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
What I don't like about using ToolStripButton when I need the drop-down-like button is that it don't look like a conventional button. I once used ToolStripButton in a row of simple command buttons and this didn't look too elegant: the appearance of ToolStripButton differs distinctively from that of simple command buttons.
Back in 2005 I used the same approach as you did here to simulate drop-down button in .NET 1.1: conventional button with the image of an arrow facing down. The problem with this approach is that you cannot have another image on the button, besides the down-facing arrow, while ToolStripButton can.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|