|
Gidday, I have been using this for a while now but the current project I am working on a lot of the PC's do not have visual styles activated. I can't change this. I added the following code (below the error), however I occasionally get this error:
Exception:System.ArgumentException: Parameter is not valid.
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height)
at System.Windows.Forms.ControlPaint.DrawFrameControl(Graphics graphics, Int32 x, Int32 y, Int32 width, Int32 height, Int32 kind, Int32 state, Color foreColor, Color backColor)
at System.Windows.Forms.ControlPaint.DrawComboButton(Graphics graphics, Int32 x, Int32 y, Int32 width, Int32 height, ButtonState state)
at System.Windows.Forms.ControlPaint.DrawComboButton(Graphics graphics, Rectangle rectangle, ButtonState state)
Protected Class DblPanel
Inherits Panel
Protected Overloads Overrides Sub OnPaint(ByVal e As PaintEventArgs)
If Me.Visible = True Then
If ComboBoxRenderer.IsSupported Then
ComboBoxRenderer.DrawDropDownButton(e.Graphics, e.ClipRectangle, System.Windows.Forms.VisualStyles.ComboBoxState.Disabled)
Else
If Me.Enabled Then
ControlPaint.DrawComboButton(e.Graphics, e.ClipRectangle, ButtonState.Normal)
Else
ControlPaint.DrawComboButton(e.Graphics, e.ClipRectangle, ButtonState.Inactive)
End If
End If
End If
End Sub
End Class
Any ideas on how to prevent the error?
|
|
|
|
|
You say occasionally you get the error? What kind of situation triggers it?
What I can notice from your code is that this part is unecessary (unless you changed some more of the behaviour):
Else
If Me.Enabled Then
ControlPaint.DrawComboButton(e.Graphics, e.ClipRectangle, ButtonState.Normal)
Else
ControlPaint.DrawComboButton(e.Graphics, e.ClipRectangle, ButtonState.Inactive)
End If
You only need to draw if Visible = True. If it's not, then no draw is needed, as the ButtonState.Normal is already drawn by the original control itself as the panel will not be visible.
What you want is Check if the ComboBoxRender.IsSupported. If it is, use the VisualStyles, if its not, use the ButtonSatate.Inactive.
In any case, ControlPaint's Draw method is causing problems, and I don't know what could be the cause as I'm not familiar with its implementation. To solve the problem I'd recommend you use custom drawing for when the visual styles are disabled, as explained in the article.
I'm sorry if I can't help you further.
Regards,
Fábio
|
|
|
|
|
Exactly what I'd been looking for. Big thank you.
|
|
|
|
|
I'm glad to be of help.
Thanks for your vote.
Regards,
Fábio
|
|
|
|
|
Hi
You added a panel to your ComboBox control, what r u trying to do there?
r u using the panel to "mask" the control in order to support "ReadOnly"? Correct me if I am wrong.
TIA
modified on Thursday, April 30, 2009 7:51 AM
|
|
|
|
|
Hi, I inserted a panel in the inherited control, so it will be on top of the original DropDown button.
The size of the panel is just big enough to cover the whole DropDown button.
Then I draw on this panel to look like a disabled DropDown Button.
I hope this answers your question.
Regards,
Fábio
|
|
|
|
|
Thanks Fabio for your reply.
So the trick is with the "OnKeyPress" and "OnKeyDown" methods?
TIA
|
|
|
|
|
That too.
But there are events that "OnKeyPress" and "OnKeyDown" won't handle.
MouseWheel for example. the MouseWheel also changes the selected item, so to handle it. I need to override the WndProc method, that catches all messages sent to the control, I check if it is a mousewheel message and handle it if it is.
There are also the Tab and Arrow keys, that I handle overriding the ProcessCmdKey method.
Regards,
Fábio
|
|
|
|
|
Nice article Fabio. As someone who is very meticulous on data presentation and validation in winforms, this control is valuable to me. I really wanted to create something like this before but I just couldn't get myself started. I would always resort to the cumbersome combobox-textbox swapping technique.
|
|
|
|
|
Oh that approach has alway irked me something fierce. I was thrilled to see that someone actually had done it right with this article.
--
Thomas Due
"Insanity in individuals is something rare - but in groups, parties, nations and epochs, it is the rule."
-- Friedrich Nietzsche
|
|
|
|
|
Gio Bejarasco wrote: Nice article Fabio. As someone who is very meticulous on data presentation and validation in winforms, this control is valuable to me. I really wanted to create something like this before but I just couldn't get myself started. I would always resort to the cumbersome combobox-textbox swapping technique.
Hi Gio, I'm glad it worked for you. I'm too very meticulous on data presentation and validation and I mean it and this just didn't work for the guys who asked for this, it worked for me as well.
Thanks for your feedback.
Regards,
Fábio
|
|
|
|
|
First of, I'd like to say that it is the greatest and simplest solution I have come across yet in my search for a ReadOnly ComboBox.
Kudos to you.
I have a couple of suggestions for (I think) improvement:
1. Make the background grey when ReadOnly, like a TextBox. I do this by adding a line to the setter for ReadOnly:
this.BackColor = (m_Unselectable) ? SystemColors.Control : SystemColors.Window;
2. Replace all that code in the Paint for your DblPanel with this:
protected override void OnPaint(PaintEventArgs e)
{
if (this.Visible == true)
{
ComboBoxRenderer.DrawDropDownButton(e.Graphics, e.ClipRectangle,
System.Windows.Forms.VisualStyles.ComboBoxState.Disabled);
}
}
But these are only suggestions. The control is still great, and I will definitely be using this in my projects.
--
Thomas Due
"Insanity in individuals is something rare - but in groups, parties, nations and epochs, it is the rule."
-- Friedrich Nietzsche
|
|
|
|
|
Hi DotDue, I'm glad you found it useful and I appreciate your feedback.
As for your suggestions:
DotDue wrote: 1. Make the background grey when ReadOnly, like a TextBox. I do this by adding a line to the setter for ReadOnly:
this.BackColor = (m_Unselectable) ? SystemColors.Control : SystemColors.Window;
I actually prefer not to limit the user to the colors that are set, I leave it to the user so he can do as he pleases. It is easier for someone that would like this feature to do it manually when he handles the EnabledChanged event than the other way around.
And I think this approach would also involve remembering the last back color set, as the way it is now, when the user changes back from ReadOnly state, the back color he had before would be lost.
DotDue wrote: 2. Replace all that code in the Paint for your DblPanel with this:
protected override void OnPaint(PaintEventArgs e)
{
if (this.Visible == true)
{
ComboBoxRenderer.DrawDropDownButton(e.Graphics, e.ClipRectangle,
System.Windows.Forms.VisualStyles.ComboBoxState.Disabled);
}
}
Indeed a much better approach than the one I provided, I will make the changes and update the article. I will leave the older paint code commented, in case someone wishes to give the dropdown button a different color.
Thanks again for your feedback.
Regards,
Fábio
|
|
|
|
|
Fabio Franco wrote: I actually prefer not to limit the user to the colors that are set, I leave it to the user so he can do as he pleases. It is easier for someone that would like this feature to do it manually when he handles the EnabledChanged event than the other way around.
And I think this approach would also involve remembering the last back color set, as the way it is now, when the user changes back from ReadOnly state, the back color he had before would be lost.
Oh that is of course true. It is a matter of taste of course. I hadn't thought about the changed background color. It would have to be stored somewhere of course.
--
Thomas Due
"Insanity in individuals is something rare - but in groups, parties, nations and epochs, it is the rule."
-- Friedrich Nietzsche
|
|
|
|
|
you don't appreciate this but in reality, this helps us guys, setting a combobox's property enabled is hard to read. with this, article, it's up to you how you can handle a read-only combo box. Simple as it is....
You've got 5
darkmaster35
|
|
|
|
|
Thank you Joseph, it is always good to hear that I could be of help to someone.
I did this because I heard from several developers about this reading problem on disabled comboBoxes.
Thanks again for your feedback.
Regards,
Fábio
|
|
|
|
|
But on your screenshot above, the control shows a gray backcolor when set to readonly. If I try to use your control, the backcolor is white...?!?!?
Plus - even if you can't select a new item from the drop down, you can still highlight the text and delete it or change it if the style is dropdown. So it appears that it is not truly readonly...
Cheers,
Johnny J.
|
|
|
|
|
Hi, the gray backcolor in this case it is because it is selected and that is the selection color configured in my Test app. About the being able to highlight and delete the text I will check it here.
Thanks for the feedback.
Regards,
Fábio
|
|
|
|
|
Ok, I think I let that pass by unoticed. But now you are not able to edit the text when ReadOnly is set to true. Updated link on the top of the page.
Regards,
Fábio
|
|
|
|
|
Why not just using DropDownStyle property to DropDownList value ???
|
|
|
|
|
Using the dropdownstyle as dropdownlist won't prevent the user from changing the selected index of the combobox. Perhaps you misunderstood the ReadOnly concept for the ComboBox.
|
|
|
|
|
The you can just set the Enabled property to false.
Regards,
Thomas Stockwell
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning.
Visit my homepage Oracle Studios[ ^]
|
|
|
|
|
That is exactly why I made this feature, disabling the combobox makes the text in it hard to read and many complained about that, also with this ReadOnly feature you are also able to select the text, customize the colors and more... Things you can't do while it is disabled.
You should understand the purpose of this article as stated in its introduction.
Regards,
Fábio
modified on Tuesday, December 9, 2008 6:25 AM
|
|
|
|
|