c# WinForms - Programmatically disable the method Application.EnableVisualStyles()? - c#

Is is possible to disable Application.EnableVisualStyles(); programmatically? I wanted to turn off the visual styles for a certain part of my application where I could have a colored progress bar. I know you can use System.Drawing to draw it on, but this is much more simpler if I could turn it off temporarily. Is this possible or am I going to have to draw it?

Credits go to GreatJobBob for linking me the MSDN page, the following achieved what I was looking for.
using System.Windows.Forms.VisualStyles;
Application.VisualStyleState = VisualStyleState.NonClientAreaEnabled;
This let me change the color of my progress bar without changing the rest of my controls and form.

Create your own progress bar class. Disabling Application.EnableVisualStyles will cause problems in other UIs such as the MessageBox. Here's a basic class to get you started, just change the forecolor to what you want it to be.
using System;
using System.Drawing;
using System.Windows.Forms;
class MyProgressBar : Control
{
public MyProgressBar()
{
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, false);
Maximum = 100;
this.ForeColor = Color.Red; //This is where you choose your color
this.BackColor = Color.White;
}
public decimal Minimum { get; set; }
public decimal Maximum { get; set; }
private decimal mValue;
public decimal Value
{
get { return mValue; }
set { mValue = value; Invalidate(); }
}
protected override void OnPaint(PaintEventArgs e)
{
var rc = new RectangleF(0, 0, (float)(this.Width * (Value - Minimum) / Maximum), this.Height);
using (var br = new SolidBrush(this.ForeColor))
{
e.Graphics.FillRectangle(br, rc);
}
base.OnPaint(e);
}
}

Related

Draw progress bar into button background [duplicate]

I've made a class GradientButton which suppose to be a Button which is filled with gradient background.
I draw gradient filling in the OnPaintBackground() method. Unfortunately it is never invoked, of course I added a GradientButton to a Form via toolbox:
public class GradientButton : Button {
public Color Color1 { get; set; }
public Color Color2 { get; set; }
public float Angle { get; set; }
public GradientButton() {
Color1 = Color.YellowGreen;
Color2 = Color.LightGreen;
Angle = 30;
}
protected override void OnPaintBackground(PaintEventArgs e) {
base.OnPaintBackground(e);
Debug.WriteLine("This never prints");
using (LinearGradientBrush brush = new LinearGradientBrush(this.ClientRectangle,
Color1,
Color2,
Angle)) {
e.Graphics.FillRectangle(brush, this.ClientRectangle);
}
}
protected override void OnResize(EventArgs e) {
base.OnResize(e);
Invalidate();
}
}
Question: How fill the button's background with the gradient? Why OnPaintBackground is not invoked? As far as I know it should be calledbefore OnPaint method.
This is because the Button class has ControlStyles.Opaque flag set, which according to the documentation:
If true, the control is drawn opaque and the background is not painted.
You can turn it off in your class constructor
SetStyle(ControlStyles.Opaque, false);
and your OnPaintBackground override will be invoked.
However, it would not help a lot - there is a reason the flag to be set to true - the OnPaint draws both background and face of the button, so whatever you do in OnPaintBackground will not have any affect of the button appearance. Unfortunately there is no option to paint just the background, so you need to override the OnPaint and actually draw everything yourself.
You need to set the style of the form in the constructor ...
this.SetStyle(ControlStyles.UserPaint, true);
to ensure the OnPaint method is overridden. There are many settings for the ControlStyle which you can combine
I would do this instead.
Firstly, change your constructor to this:
public GradientButton()
{
Color1 = Color.YellowGreen;
Color2 = Color.LightGreen;
Angle = 30;
Paint += new PaintEventHandler(GradientButton_Paint);
}
And then add the below procedure:
private void GradientButton_Paint(object sender,PaintEventArgs e)
{
Debug.WriteLine("This never prints");
using (LinearGradientBrush brush = new LinearGradientBrush(this.ClientRectangle,Color1,Color2,Angle))
{
e.Graphics.FillRectangle(brush, this.ClientRectangle);
}
}
I'm not entirely sure why your code doesn't work, but the way I've described always works for me. Hope that's good enough.

Set CircularPictureBox Border Color

I'm creating a custom PictureBox.
As you can see, it's a PictureBox designed for profile photos
Well, this is the class of the CircularPictureBox
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Hector.Framework.Controls
{
public class CircularPictureBox : PictureBox
{
private Color _idlecolor = Color.White;
public CircularPictureBox()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);
this.DoubleBuffered = true;
this.BackColor = Color.White;
this.SizeMode = PictureBoxSizeMode.StretchImage;
this.Size = new Size(100, 100);
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
using (var gpath = new GraphicsPath())
{
var brush = new SolidBrush(this.IdleBorderColor);
var pen = new Pen(brush, 5);
var outrect = new Rectangle(-1, -1, this.Width + 5, this.Height + 5);
gpath.AddEllipse(outrect);
pe.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
pe.Graphics.DrawPath(pen, gpath);
brush.Dispose();
pen.Dispose();
gpath.Dispose();
}
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
using (var gpath = new GraphicsPath())
{
var rect = new Rectangle(1, 1, this.Width - 1, this.Height - 1);
gpath.AddEllipse(rect);
this.Region = new Region(gpath);
gpath.Dispose();
}
}
public Color IdleBorderColor
{
get => this._idlecolor;
set => this._idlecolor = value;
}
}
}
My problem is that since it is a control that can be used from the designer, I want it to have properties such as edge width or border color.
I started testing with the color, but it is that whenever I change the color,
Visual Studio shows me an error message saying that The value of the property is not valid
I made a few modifications to your code, to highlight some features that can be useful in the design of Custom Control.
The modifications I've made I think are self-explanatory.
However, take a look at the OnPaint event. The e.Graphics.Clip Region lets you hide all graphics parts that are not in the selected region. This implies that when you drag the control in Design Mode, the Image will be clipped and won't be seen outside the region area.
The PixelOffsetMode.HighQuality and SmoothingMode.AntiAlias contributes to the overall quality of the rendering (there are commented out options that can useful in other situations).
The calculation of the Border offset must reference the BorderSize width, and scaled accordingly. The Pen object draws starting from the middle of its size. If a Pen has a size of 3 pixels, 1 Pixel is drawn on the border, one outside the area and one inside (weird? Maybe).
The transparency settings is just a "fake" here.
It might be used effectively in other situations (it should read "Platforms").
public class CircularPictureBox : PictureBox
{
private Bitmap bitmap;
private Color borderColor;
private int penSize;
private Color alphaColor = Color.FromArgb(0, 255,255,255);
private bool enhancedBuffering;
public CircularPictureBox()
{
InitializeComponent();
this.SetStyle(ControlStyles.SupportsTransparentBackColor |
ControlStyles.ResizeRedraw |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.OptimizedDoubleBuffer, true);
}
private void InitializeComponent()
{
this.enhancedBuffering = true;
this.bitmap = null;
this.borderColor = Color.Silver;
this.penSize = 7;
this.BackColor = alphaColor;
this.SizeMode = PictureBoxSizeMode.StretchImage;
this.Size = new Size(100, 100);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.CompositingMode = CompositingMode.SourceOver;
//e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
//e.Graphics.InterpolationMode = InterpolationMode.Bicubic;
e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
if (this.Region != null) e.Graphics.Clip = this.Region;
var rect = this.ClientRectangle;
if (bitmap != null) {
e.Graphics.DrawImage(bitmap, rect);
}
rect.Inflate(-penSize / 2 + 1, -penSize / 2 + 1);
using (var pen = new Pen(borderColor, penSize)) {
e.Graphics.DrawEllipse(pen, rect);
}
}
protected override void OnResize(EventArgs e)
{
using (var path = new GraphicsPath()) {
path.AddEllipse(this.ClientRectangle);
path.CloseFigure();
using (Region region = new Region(path)) {
this.Region = region.Clone();
}
}
}
[Description("Gets or Sets the Image displayed by the control"), Category("Appearance")]
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
public Bitmap Bitmap
{
get { return bitmap; }
set { bitmap = value; Invalidate(); }
}
[Description("Gets or Sets the size of the Border"), Category("Behavior")]
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
public int BorderSize
{
get { return penSize; }
set { penSize = value; Invalidate(); }
}
[Description("Gets or Sets the Color of Border drawn around the Image.")]
[Category("Appearance")]
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
public Color BorderColor
{
get { return borderColor; }
set { borderColor = value; Invalidate(); }
}
[Description("Enables or disables the control OptimizedDoubleBuffering feature")]
[Category("Useful Features")] //<= "Useful feature" is a custom category
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
public bool EnhancedBuffering
{
get { return enhancedBuffering; }
set { enhancedBuffering = value;
SetStyle(ControlStyles.OptimizedDoubleBuffer, value);
UpdateStyles();
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
public new Image ErrorImage
{
get { return null; }
set { base.ErrorImage = null; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
public new Image InitialImage
{
get { return null; }
set { base.InitialImage = null; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
public new Image BackgroundImage
{
get { return null; }
set { base.BackgroundImage = null; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never), BrowsableAttribute(false)]
public new Image Image {
get { return null; }
set { base.Image = null; }
}
}
Some System.ComponentModel Attributes that can help shaping the Control.
For example, Description and Category attributes:
(These have been inserted in the custom Property BorderColor of your control).
[Description("Gets or Sets the Color of the Border drawn around the Image.")
[Category("Appearance")]
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
Description of course explains the user what the Property is for.
Category is used to give the Properties an organic disposition inside the PropertyGrid. You can use standard names (Appearance, Behavior etc.) or specify anything else.
Give the Category a custom name and it will be listed among the others, when the Categorized view is in use.
The Image property of the Custom Control has been hidden and substituted with a Bitmap Property:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never), BrowsableAttribute(false)]
The EditorBrowsable Attribute is a hint to Intellisense that lets you determine whether to show a property or method in the Popup menu. It can be Never, Always or Advanced (for those who know how to reach VS Options). Properties and Methods will be Hidden when the Custom Control is deployed (as a dll), not while you are designing it.
The BrowsableAttribute Attribute (or just [Browsable]) allows to specify whether that Property should be shown in the PropertyGrid.
The DesignerSerializationVisibility
With the DesignerSerializationVisibility Attribute, you can indicate
whether the value for a property is Visible, and should be persisted
in initialization code, Hidden, and should not be persisted in
initialization code, or consists of Content, which should have
initialization code generated for each public, not hidden property of
the object assigned to the property.
Also interesting:
TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))
With this Attribute, you can instruct to list the Public Properties of a Class Object in the PropertyGrid.
This Class Object can be an internal Class that serializes a complex Property of a Control.
The TypeConverter Class is very interesting itself.

How can I change the font size of all the screens in a windows forms application

I have a windows forms application in C#. I want to give facility to user to change the font size of all the screens.
Is there any way to do this in C# windows forms application?
You could create an event which you fire whenever you change the font size which takes the new value
public delegate void FontSize(int size);
public event FontSize OnFontSizeChanged;
public void WhereYouChangeFontSize()
{
// Change font size
OnFontSizeChanged(newFontSize)
}
And then hook up to it in all of your screens
SomeClass.OnFontSizeChanged += FontSizeChanged;
private void FontSizeChanged(int newValue)
{
controls.FontSize = newValue;
}
The elegant and acceptable way to do it is using a resource file. You should investigate in that way.
You can create BaseForm for all your Screens. This BaseForm subscribe to ChangeFontMessage. For messaging you can use any EventAggregator library. This example use MVVM Light Messenger.
public class BaseForm : Form
{
public BaseForm()
{
Messenger.Default.Register<ChangeFontMessage>(this, message =>
{
SetFont(message.FontSize);
});
}
private void SetFont(float fontSize)
{
Font = new Font(Font.FontFamily, fontSize);
//If you need to change font size of child controls
foreach (var control in Controls.OfType<Control>())
{
control.Font = new Font(control.Font.FontFamily, fontSize);
}
}
}
public class ChangeFontMessage
{
public float FontSize { get; set; }
}
Then you can raise this message in any place:
Messenger.Default.Send(new ChangeFontMessage { FontSize = 20 });

Alternate background color of rows in a CheckedListBox?

I need to alternate the color of the items in my CheckedListBox but "alternatingColors" is not a property of CheckedListBox.
How do I go about making the item's colors alternate?
The OnDrawItem event is inaccessible by default, but if you derive a new control based on CheckedListBox, then you can override the base event.
public class MyCheckedListBox : CheckedListBox
{
private SolidBrush primaryColor = new SolidBrush(Color.White);
private SolidBrush alternateColor = new SolidBrush(Color.LightGreen);
[Browsable(true)]
public Color PrimaryColor
{
get { return primaryColor.Color; }
set { primaryColor.Color = value; }
}
[Browsable(true)]
public Color AlternateColor
{
get { return alternateColor.Color; }
set { alternateColor.Color = value; }
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
base.OnDrawItem(e);
if (Items.Count <= 0)
return;
var contentRect = e.Bounds;
contentRect.X = 16;
e.Graphics.FillRectangle(e.Index%2 == 0 ? primaryColor : alternateColor, contentRect);
e.Graphics.DrawString(Convert.ToString(Items[e.Index]), e.Font, Brushes.Black, contentRect);
}
}
It'll alternate between white and green by default. Make adjustments in the Properties panel at design time, or during runtime.
I don't think this is even possible. You may want to consider using a different control for what you need. A DataGridView might be able to work for you better.

How can I remove a CheckBox's borders?

I'd like to create a CheckBox without borders. It should still display the checkmark when checked.
using System;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Linq;
using System.Text;
namespace WindowsFormsApplication1
{
public class RoundButton : Button
{
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
GraphicsPath grPath = new GraphicsPath();
grPath.AddEllipse(0, 0, ClientSize.Width, ClientSize.Height);
this.Region = new System.Drawing.Region(grPath);
base.OnPaint(e);
}
private void InitializeComponent()
{
this.SuspendLayout();
this.ResumeLayout(false);
}
}
}
this is a class that generate a customized round button, can be good starter for you to make your own customCheckbox by doing similarly
The verified answer on this question states:
You cannot remove just the border because the check box is drawn by windows and it's pretty much all or nothing.
This is because the System.Windows.CheckBox is a native control.
A workaround to this would be drawing you own CustomCheckBox, with no visible borders.
Hope this helps.
Following AndreiV advice, I created a CustomControl which inherited from Label. Next I override the OnPaint and OnClick events to make it look and behave like a CheckBox. In order to display the check box "checked image" I used a bit of paint for cropping it to what I needed.
Below is the full code:
public partial class FlatCheckBox : Label
{
public bool Checked { get; set; }
public FlatCheckBox()
{
InitializeComponent();
Checked = false;
}
protected override void OnClick(EventArgs e)
{
Checked = !Checked;
Invalidate();
}
protected override void OnPaint(PaintEventArgs pevent)
{
if (!DesignMode)
{
pevent.Graphics.Clear(Color.White);
var bigRectangle = new Rectangle(pevent.ClipRectangle.X, pevent.ClipRectangle.Y,
pevent.ClipRectangle.Width, pevent.ClipRectangle.Height);
var smallRectangle = new Rectangle(pevent.ClipRectangle.X + 1, pevent.ClipRectangle.Y + 1,
pevent.ClipRectangle.Width - 2, pevent.ClipRectangle.Height - 2);
var b = new SolidBrush(UllinkColors.NEWBLUE);
var b2 = new SolidBrush(Color.White);
pevent.Graphics.FillRectangle(b, bigRectangle);
pevent.Graphics.FillRectangle(b2, smallRectangle);
if (Checked)
{
pevent.Graphics.DrawImage(Resources.flatCheckedBox, new Point(3, 3));
}
}
}
}

Categories