VisualStyles color inconsistancy - c#

I'm just messing about with the Visual Styles offered by .NET using Winforms and I have a problem. I am simply executing this code, called from the OnPaint method of a custom Panel, nothing special.
private void DrawBox(PaintEventArgs e)
{
ComboBoxRenderer.DrawDropDownButton(e.Graphics, e.ClipRectangle, ComboBoxState.Normal);}
My problem is that the Background Color of the Button is grey while the Background Color of a true ComboBox is white (on my Computer anyway).
Two questions here, why the Color change and how do I make my Button render using the same Background Color as a true ComboBox?
Thanks
Danny

ClipRectangle is not what you want. Set the actual rectangle you want to draw. That being said, yeah, using VisualStyles is going to make you mad. This will get you close:
VisualStyleRenderer vsr = new VisualStyleRenderer("EDIT", 1, 1);
vsr.DrawBackground(e.Graphics, controlRectangle);
vsr.SetParameters("COMBOBOX", 7, 1);
vsr.DrawBackground(e.Graphics, arrowRectangle);

Related

Using image causes strange white frame around

Im trying to create a button in C# with the image as the button, I don't really want to use a picture box as i Require the "Label" bit of the button as the text for the buttons aren't in the image, This is what it looks like
If anyone can help me fix that white frame it would be much appreciated, Thanks!
EDIT: I found what was causing it but still no fix :( The BackColor on the actual form is where the white is coming from but you can't set the BackColor of a form to Transparent :/
Your image must have transparent background. Also see #IAbstract's suggestion.
As I answered here to remove the border you should set the FlatAppearance.BorderColor to transparent. The whole code to remove completely the border looks like:
customButton.TabStop = false;
//it's the best thing set flatstyle to flat when dealing with a custom button
customButton.FlatStyle = FlatStyle.Flat;
customButton.FlatAppearance.BorderSize = 0;
//set the border color to transparent by setting the alpha to 0 (it doesn't support Color.Transparent)
customButton.FlatAppearance.BorderColor = Color.FromArgb(0, 0, 0, 0);
I think a Background.Color = Transparent should fix it if WinForms.
Update
If you have set border and background properties to transparent, double check the white border to be transparent in the actual graphic?

How can I add transparency to a c# form while keeping controls visible?

UPDATE: I took a break from messing with the transparency stuff for a few days. I started messing with it again tonight. I got a new result using Hans Passant's solution:
http://img3.imageshack.us/img3/4265/icontransp.jpg
Passant's solution does solve the issue of the transparent background gradient. However, I'm still running into the problem with the transparent colors in my icon blending with the form's BackColor. You can see the fuchsia around various parts of the icon in the above image.
ORIGINAL CONTENT:
I've been going at this for several hours now, and I haven't had much luck. I've messed with Control.Region, Form.TransparencyKey, Form.Opacity, and a couple other random things with some funky effects.
Lately I've been trying to customize my desktop and decided to mess with Application Docks. After seeing what the Mac dock and a few third-party Windows implementations had to offer, I decided I wanted to build my own.
Eventually I want to move on to using the Win32 API. For now I just want to get something working using as much C# and .Net framework capabilities as possible.
There are a few things I want to be able to do in this application:
Display a form/menu with a gradient background.
Allow the form/menu to have transparency while keeping icons opaque.
Display icons that contain transparent backgrounds.
The Menu and Icons should be able to receive mouse-related events (hover, leave, click, dragover, dragdrop, and a few others).
This is the effect I'm shooting for:
http://img207.imageshack.us/img207/5716/desired.jpg
This image shows the visual effects I'm trying to achieve. This was a skin I made for a program called Rainmeter. The image shows Notepad++ behind the skin with a few of the skin's files open in the editor. The menu is transparent, but the icons remain opaque.
My Approach:
Using a Form to act as the menu seemed like a logical first choice to me. I have a basic understanding of events. I'm not quite sure how to create my own click events, so a form would make working with events a tad easier. I considered a few options for the icons. I decided I'd use PictureBoxes for the icons, since they can hold images and receive events.
Once I finished the code for all the structural logic of my menu, I started playing around with it to try to get the visual effect I wanted. Form.Opacity affected the transparency of everything on the form. Since I want the icons to be fully opaque, I left this property alone. I tried setting the BackColor to Color.Transparent, but that gives an error. I played around with a few combinations...
http://img204.imageshack.us/img204/757/effectsi.jpg
I drew the gradient with a Drawing2D.LinearGradientBrush into a Bitmap. This Bitmap was then placed as the Form.BackgroundImage or as a PictureBox.Image. If used, the PictureBox was sized to cover the entire Form and sent to the back.
I noticed that some of the Form.BackgroundColor would be mixed in with the outlines of my icons. The icons have transparency along the edges for a smoother appearance. Since the icons are picking up the Form's BackgroundColor, this makes me think that the PictureBoxes are creating new images when the icons are loaded into the form. The semi-transparent portions of the image are then merged with the Form's BackgroundColor when they should merge with whatever colors are behind the form.
http://img838.imageshack.us/img838/8299/whitedesktop.jpg
In this image you can see the Fuchsia existing in the icons even though the Form's Fuchsia color is now completely transparent. I forgot to point out that the same green to yellow gradient with an Alpha value of 150 was used in every case. In the images where the gradient doesn't look green, it's because the transparent colors are blending with the Fuchsia background.
I'm not really sure what to do from here. I feel like I could get what I want if I could somehow make the Form alone completely transparent. I was also thinking I may have better luck just drawing the icons instead of using PictureBoxes. The problem then would be setting up the icons to receive mouse events. (I've never made my own events, and I think it would involved some Win32 API calls.)
Is there something else I can do with the PictureBoxes to get the effect I want? Whichever the case, I'm open to any ideas or suggestions for the overall effect I'm trying to achieve.
This is pretty easy to do in Winforms. What you need is a sandwich of two forms. The bottom one should provide the transparent gradient background, the top one should draw the icons and handle mouse clicks. Some sample code:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.TransparencyKey = this.BackColor = Color.Fuchsia;
this.Opacity = 0.3;
var overlay = new Form();
overlay.FormBorderStyle = FormBorderStyle.None;
overlay.TransparencyKey = overlay.BackColor = Color.Fuchsia;
overlay.StartPosition = FormStartPosition.Manual;
overlay.Location = this.Location;
overlay.MouseDown += HandleIconClick;
this.Resize += delegate { overlay.Size = this.Size; };
this.LocationChanged += delegate { overlay.Location = this.Location; };
overlay.Paint += PaintIcons;
this.Paint += PaintBackground;
this.Load += delegate { overlay.Show(this); };
}
private void PaintBackground(object sender, PaintEventArgs e) {
var rc = new Rectangle(0, 0, this.ClientSize.Width, this.ClientSize.Height);
using (var br = new LinearGradientBrush(rc, Color.Gainsboro, Color.Yellow, 0f)) {
e.Graphics.FillRectangle(br, rc);
}
}
private void PaintIcons(object sender, PaintEventArgs e) {
e.Graphics.DrawIcon(Properties.Resources.ExampleIcon1, 50, 30);
// etc...
}
void HandleIconClick(object sender, MouseEventArgs e) {
// TODO
}
}
Which looks like this with the somewhat random colors and icon I selected:
OK, I got a bit lost in all that, but from the description in the original paragraph, I would make sure the background rectangle is NOT the visual parent of the pictureboxes. Make them overlapping siblings, with the pictureboxes in front using Panel.Zindex.
Then you can just change the opacity of the rectangle, without affecting the icons. Also make sure the icon source image files have a transparent background.
Should work I think.

Change Border of ToolStripComboBox with Flat Style

I would like to be able to change the border color of ToolStripComboBox controls in some of my toolstrips, since the default border color of ComboBoxes when used with flat styling is SystemColors.Window, which is basically invisible against the default control color of the toolstrip. After a lot of digging around in Reflector, I don't see any obvious way to do this, since all the infrastructure behind ComboBox rendering is highly protected behind internal and private interfaces.
Outside of ToolStrips, a common solution I've seen proposed for fixing border color on ComboBoxes is to subclass ComboBox, override WndProc, and manually paint the border. This can't work for ToolStripComboBox controls since the internal ComboBox control is its own private subclass of ComboBox, with no way that I can see to replace the instance of the control.
An alternative solution I'm considering is putting one of the extended ComboBox objects into a ToolStripControlHost, which allows me to draw a border, but then I have to give up some of the professional renderer tweaks. A secondary drawback I've noticed is that I get occasional flicker during mouseover.
Switching my design to WPF is not an acceptable solution. Wrapping controls in parent controls for drawing borders is also not acceptable, as this gains nothing over the ToolStripControlHost alternative.
Does anyone have a clever solution to defeat this problem, or is there an existing (permissively-licensed) re-implementation of the ComboBox flat-style rendering stack out in the wild, which fixes some of the shortcomings in the existing implementation?
Here's a way to make it work ... sort of :)
Create an event handler for the Paint event of the ToolStrip. Then loop through all of the ToolStripComboBoxes and paint a rectangle around them.
private Color cbBorderColor = Color.Gray;
private Pen cbBorderPen = new Pen(SystemColors.Window);
private void toolStrip1_Paint(object sender, PaintEventArgs e)
{
foreach (ToolStripComboBox cb in toolStrip1.Items)
{
Rectangle r = new Rectangle(
cb.ComboBox.Location.X - 1,
cb.ComboBox.Location.Y - 1,
cb.ComboBox.Size.Width + 1,
cb.ComboBox.Size.Height + 1);
cbBorderPen.Color = cbBorderColor;
e.Graphics.DrawRectangle(cbBorderPen, r);
}
}
Here's what it looks like (note that you may need to adjust the Height of the ToolStrip to prevent the painted border from being cut off):
improvement:
check the type of the toolstrip item,
so the program will not crush if it is toolstipLabel for example.
foreach (var item in toolStrip1.Items)
{
var asComboBox = item as ToolStripComboBox;
if (asComboBox != null)
{
var location = asComboBox.ComboBox.Location;
var size = asComboBox.ComboBox.Size;
Pen cbBorderPen = new Pen(Color.Gray);
Rectangle rect = new Rectangle(
location.X - 1,
location.Y - 1,
size.Width + 1,
size.Height + 1);
e.Graphics.DrawRectangle(cbBorderPen, rect);
}
}
toolStrip1.ComboBox.FlatStyle = FlatStyle.System;
This sets the default, OS-styled, border around the combo box. It is a light grey and thin border on Windows 10. Although, depending on the background, this may not show. In which case, you could try the other options like FlatStyle.Popup.
If the presets aren't what you are looking for, the other answers allow you to draw a custom border. However, since the rectangle is drawn with +1 pixel size around the combo box, the border is 1 pixel larger than the combo box. Removing the +1s and -1s doesn't work either.

Visual Studio C# Windows Forms... changing button color?

I have a form (see screenshot):
As you can see, its a pretty basic form, with a save button. I have programmed it so that if any of the text fields get changed, the "SAVE" button changes color so that its obvious that I haven't clicked save and don't forget to. Unfortunately, simply changing the BackColor of the button to red isn't enough, because its UGLY as sin.
What can I do to change the color of the button to red, but not as ugly. As you can see, the "BackColor" doesn't change the entire button, just the inner piece. The border is still the same old fashioned transparent grey.
A little bit of a LinearGradientBrush can go a long way to soften the harshness of a pure red button.
button1.ForeColor = Color.White;
Bitmap bmp = new Bitmap(button1.Width, button1.Height);
using (Graphics g = Graphics.FromImage(bmp)) {
Rectangle r = new Rectangle(0, 0, bmp.Width, bmp.Height);
using (LinearGradientBrush br = new LinearGradientBrush(
r,
Color.Red,
Color.DarkRed,
LinearGradientMode.Vertical)) {
g.FillRectangle(br, r);
}
}
then you can just assign the image to the button's BackgroundImage property:
button1.BackgroundImage = bmp;
Result:
Note: Assigning a background image will lose the mouse hover coloring of the button.
Another solution would be to add an Icon (e.g. exclamation mark) to the button instead to inform the user that the changes haven't been saved yet.
There are many tutorials online on how to create nice buttons with c#. For example this one allows you to create Vista like buttons. Have a look here: http://www.codeproject.com/Articles/19318/Vista-Style-Button-in-C
For basic colors visit this SO question:
C#: Changing Button BackColor has no effect
You can just use one of the button's properties, "FlatStyle". By default, it is standard. But if you switch it to "Popup", your background color will be extended to the area of the button. You can compare the followings:
left-standard, right-popup
This won't work in WinForms, but you might want to switch over to WPF.
It's much more convenient because you can configure EVERYTHING. (Even the color of a progressbar)
Edit: The OP doesn't have to entirely rewrite his application.
He just needs to redo the layout of it, the code can be C&P'd over to the new WPF project, fyi
Edit²: You don't even need to use code to change the color of a WPF button, you can just define a red overlay with 30% opacity in the XAML file. It's that easy, really.

C# UseVisualStyleBackColor

Is there a way in which I can change the button color and preserve the Windows VisualStyle? I want to create a button that looks like checkBox2 (color and style)
this.button2.BackColor = System.Drawing.SystemColors.GradientActiveCaption;
this.button2.UseVisualStyleBackColor = false; //if true, BackColor gets ignored
No, not really. This kind of button background is drawn by VisualStyleRenderer.DrawBackground(). Which in turns pinvokes DrawThemeBackground(). These methods don't take a color. None is needed because the color is already specified in the theme.
Simulating the appearance with a LinearGradientBrush is your only real hope. Note that custom drawing a button is quite difficult, all the code is internal and no owner-draw is provided.
Consider using an image.

Categories