How to change disabled Textbox Background colour in WPF to transparent - c#

I wanted to change the disabled background of my Textbox to a semitransparent Gradientbrush (one part transparent the other not).
I found this older post to a almost identical topic: this one
The accepted answer worked for my, as long as I did not wanted to add any transparency to it. Instead the transparent part of the background turns to some shade of gray.
How can I fix this a nice and clean way, the Template form the MS-Page might do the trick, but they always look so awfully giant for such small issues.

I have done something similar to a different control. I added my owncallback to the IsEnabled property like this
static IconPresenter()
{
IconPresenter.IsEnabledProperty.OverrideMetadata(typeof(IconPresenter), new UIPropertyMetadata(new PropertyChangedCallback(OnIsEnabledChanged)));
}
And then I added in the code that I wanted to happen when the IsEnabled is changed
private static void OnIsEnabledChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
IconPresenter iconPresenter = (IconPresenter)sender;
if ((bool)e.NewValue == false)
{
iconPresenter.Fill = Brushes.Transparent;
}
else
{
iconPresenter.Fill = Brushes.Black;
}
}

Related

Change the style color to custom color in Metro Framework?

I have implemented Metro Framework in my Windows Form Application. I want to change the style color to custom color. (As shown in the screenshot) How do I do this?
I know this is an old question but it might help others looking for answers in the future.
If you are using the nuget Metro Framework package for C# in Visual Studio then you need to set the "UseCustomBackColor" of the object to true:
metroTile_YourTile.UseCustomBackColor = true;
and then change the back color in the designer to "Custom" and pick the color, or set it programmatically:
metroTile_YourTile.UseCustomBackColor = Color.FromArgb(100,100,100);
This is true for a multitude of objects in the package, including buttons, dropdowns, etc. I hope that is helpful.
Short answer: You can't.
A workaround would be to override the OnPaint method of the MetroForm and draw it yourself. For example:
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
// custom draw the top border
using (Brush b = new SolidBrush(Color.White))
{
int borderWidth = 5; // MetroFramework source code
e.Graphics.FillRectangle(b, 0, 0, Width, borderWidth);
}
}
Long answer: I am using MetroModernUI from Nuget. And wanted to remove the top border.
Reading the source-code of the Framework, I found the method responsible for the draw of the top border, which is similar to the code above.
The method responsible for get the color for draw is MetroPaint.GetStyleBrush(Style), where Style is the Enum MetroColorStyle. It is a switch-case:
public static SolidBrush GetStyleBrush(MetroColorStyle style)
{
switch (style)
{
case MetroColorStyle.Black:
return MetroBrushes.Black;
case MetroColorStyle.White:
return MetroBrushes.White;
.
.
.
}
}
Basically you are limited to choose one of the colors available. (or fork the code and live the freedom!)
Reference: MetroModernUI (Github)
I realise this is an old question but this was driving me mad and I couldn't find answers anywhere. I did, however, figure it out so thought I'd share... As long as you don't mind editing the source code a little, there is a way to add custom colors.
1. Start with the MetroColors Class. Right at the bottom there is some code relating to a Custom option. Replace it with the following:
public static Color customColor = new Color();
public static Color Custom
{
get
{
return customColor;
}
}
2. Next, move onto the MetroPaint Class. Near the bottom, expand the Helper Methods region and add a case for Custom to GetStyleColor,
public static Color GetStyleColor(MetroColorStyle style)
{
switch (style)
{
case MetroColorStyle.Custom:
return MetroColors.Custom;
}
GetStyleBrushand
public static SolidBrush GetStyleBrush(MetroColorStyle style)
{
switch (style)
{
case MetroColorStyle.Custom:
return MetroBrushes.Custom;
}
GetStylePen. (Make sure to leave the defaults at the end)
public static Pen GetStylePen(MetroColorStyle style)
{
switch (style)
{
case MetroColorStyle.Custom:
return MetroPens.Custom;
}
}
3. Make sure that the MetroPens
public static Pen Custom
{
get
{
return GetSavePen("Custom", MetroColors.Yellow);
}
}
and MetroBrusheshave the Custom options at the end of them (I don't remember if they were already there or not)
public static SolidBrush Custom
{
get
{
return GetSaveBrush("Custom", MetroColors.Custom);
}
}
4. Save your changes and build it, then replace the MetroFramwork.dll in your project with the newly edited one.
5. I'll assume you already have a comboBox hooked up to the StyleManager. Add "Custom" to the end of the comboBox items (its index should be 15 as long as you haven't excluded any of the other colors) and add a colorDialog to the form.
6. Add a SelectedIndexChanged event handler to the comboBox and then add the following:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex == 15)
{
Color c = new Color();
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
c = colorDialog1.Color;
}
MetroColors.customColor = c;
metroStyleManager1.Style = MetroColorStyle.Custom;
}
else
{
metroStyleManager1.Style = (MetroFramework.MetroColorStyle)Convert.ToInt32(comboBox1.SelectedIndex);
}
Refresh();
}
Now when you select Custom from the combBox, the colorDialog will appear and you can choose any color you want. If you just wanted to change to a fixed custom color that you don't want to be changed, you can just specify the RGB and apply it on FormLoad instead:
private void Form1_Load(object sender, EventArgs e)
{
MetroColors.customColor = Color.FromArgb(0, 0, 0);
metroStyleManager1.Style = MetroColorStyle.Custom;
}
You can repeat these steps as many times as you want to add new colors (Custom1, Custom2 etc.). Just remember to add these to the list in the MetroColorStyle.cs as well.
Try to use:
this.Style={color};
You can use:
this.Style = MetroFramework.MetroColorStyle.<color>;
Possible colors:
Default
Black
White
Silver
Blue
Green
Lime
Teal
Orange
Brown
Pink
Magenta
Purple
Red
Yellow
So for example:
this.Style = MetroFramework.MetroColorStyle.Red;
You can use this on any MetroFramework control:
metroProgressBar1.Style = MetroFramework.MetroColorStyle.Blue;
You can also switch between light and dark theme:
this.Theme = MetroFramework.MetroThemeStyle.Light;
//or
this.Theme = MetroFramework.MetroThemeStyle.Dark;
As already stated before, a custom color is not possible. However, you can use the already defined colors. (See #SomeCoder's answer)
If you want to make a ComboBox to change the theme/style you don't have to make a big switch statement with all the themes/styles, you can simply do this:
private void ColorComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
Enum.TryParse(colorComboBox.Text, out MetroColorStyle color);
this.Style = color;
}
catch (ArgumentException)
{
this.Style = MetroColorStyle.Default;
}
Refresh();
}
I am not sure if this will work, but try to use
this.BackColor = (your colour)
Also please let me know if this is working or not.

C# ComboBox disable highlighting

I have custom ComboBox, where DropDownStyle = ComboBoxStyle.DropDown;.DropDown style is set because I want to set the Text property of the ComboBox to something outside the list of values. Everything works good, except that ComboBox is highlighting the text when it's left and when I click on the combobox editing is avaible. How can I cope with this?
To illustrate:
First Picture is where everything looks good, second is the highlight situation, third editing is on.
Try un-selecting the text after the DropDown closes:
void comboBox1_DropDownClosed(object sender, EventArgs e) {
this.BeginInvoke(new Action(() => { comboBox1.Select(0, 0); }));
}
If you are referring to disabling the highlighting and editing, then you might want to consider setting the DropdownStyle property to DropdownList.
yourComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
Tricky problem to solve. It seems to be from the Resize event. There are a lot of solutions that do something similar to this, but none that I've seen worked for me until I tried this. (This is a solution that does not require inheritance from ComboBox; inheriting is probably a much more straight forward solution, but requires you to always use your inherited class and never the actual ComboBox class.)
comboBox.Resize += (s, e) => {
if (!comboBox.IsHandleCreated)
return; // avoid possible exception
comboBox.BeginInvoke(new Action(() => comboBox.SelectionLength = 0));
};
Set the selection length to zero to get rid of the highlight, but when? Other examples do it in other places, but the problem seems to be specifically caused by Resize, so doing it after Resize fixes it consistently, at least for me. (Can still see it flicker when you resize the window though, but it always ends up ok.)
BeginInvoke ensures that it happens sufficiently after Resize to work, and the check for IsHandleCreated prevents it from being called before the handle is created, in which case BeginInvoke would throw an exception.
This slightly more complex version includes some checks to prevent a focused control from losing highlight, since it actually should have it. It also doesn't fire if the parent doesn't exist yet, or if the parent does not have an active control yet, both signs that things are too early.
comboBox.Resize += (s, e) => {
if (!comboBox.IsHandleCreated)
return;
comboBox.BeginInvoke(new Action(() => {
var parent = comboBox.FindForm();
if (parent == null)
return;
if (parent.ActiveControl == null)
return;
if (parent.ActiveControl == comboBox)
return;
comboBox.SelectionLength = 0;
}));
};
I tried to make a version that would 'preserve' the selection length rather than always set it to zero, but I couldn't get it to synchronize properly. Many Resize events can fire before the BeginInvoke delegates start to fire, so the preserved value will always be overwritten by the broken one. I tried saving them all in a Queue or Stack, but in both cases, I was unable to reverse the ordering (not really sure why, since that makes no sense).
To solve the same I have tried almost EVERYTHING:
setting the DropdownStyle property to DropdownList
this.BeginInvoke(new Action(() => { comboBox1.Select(0, 0); }));
combobox1.SelectionLength = 0;
changing comboBox.TabIndex
Not tried SendKeys.Send("{ESC}"); because it is not a reliable solution
Nothing helped.
The only stable and working solution was to move a focus on another Label control:
label.Focus();
You could also hide that label.
I know this post is old but recently I have the same problem with combobox.
Situation : I have an editable combobox which propose complete words when user write some letters.
But when I want to type a letter, combobox auto highlight the text and the next letter auto replace the previous.
Solution : I use a textbox to avoid any highlight like that:
<ComboBox IsTextSearchEnabled="False" IsEditable="True" x:Name="CMB_ClientName"/>
<TextBox Text="{Binding ElementName=CMB_ClientName, Path=Text}" TextChanged="ComboBoxChange" x:Name="TXT_ClientName"/>
And I generate the textbox TextChanged event :
private void ComboBoxChange(object sender, TextChangedEventArgs e)
{
//Clear ComboBox items
CMB_ClientName.Items.Clear();
//Auto Open DropDownList
CMB_ClientName.IsDropDownOpen = true;
//Get data from database (use entity framework 6.x)
dbEntity.Client.Load();
//Attribute Data to variable
var clients = dbEntity.Client.Local;
foreach (Client client in clients)
{
//If data begin with the texbox text, the data is add to the combobox items list.
if (client.Nom.ToLower().StartsWith(TXT_NomClient.Text.ToLower()))
{
CMB_ClientName.Items.Add(client.Nom);
}
}
}
I know this solution isn't realy beautifull, but it is for me the easiest solution to avoid highlight text and all the solutions in this post don't work for me.
I hope this solution will be helpfull, thanks for reading.
Math.
Ps: My apologies, my English is not very good. I hope you will understand me correctly.
Nothing worked for me ( I want the form to load with no highlighting in any combobox) until I set the combobox property TabStop to false. This meant that one of my buttons took the tab highlight which I didn't like so I set them all to false for start up and adjusted them programatically as needed.
I know this is an old thread, but my solution is similar to that of the others, but relies on the Form.ResizeEnd event. In its event handler, I iterate through the ComboBoxes and set ComboBox.SelectionLength to 0.
private void Form_ResizeEnd(object sender, EventArgs e)
{
foreach(ComboBox comboBox in parentControl.Controls.OfType<ComboBox>
{
comboBox.SelectionLength = 0;
}
}
This is what worked for me:
Set DrawMode to OwnerDrawFixed
Set cbxSubsystems.DrawItem event to the function below
private void cbxSubsystems_DrawItem(object sender, DrawItemEventArgs e)
{
Color BgClr;
Color TxClr;
if( (e.State & DrawItemState.ComboBoxEdit) == DrawItemState.ComboBoxEdit )
{
// Do not highlight main display
BgClr = cbxSubsystems.BackColor;
TxClr = cbxSubsystems.ForeColor;
}
else
{
BgClr = e.BackColor;
TxClr = e.ForeColor;
}
e.Graphics.FillRectangle(new SolidBrush(BgClr), e.Bounds);
TextRenderer.DrawText(e.Graphics, cbxSubsystems.Items[e.Index].ToString(), e.Font, e.Bounds,
TxClr, BgClr, TextFormatFlags.Left | TextFormatFlags.VerticalCenter );
}

Winforms Control Layout at Runtime

I've been working on developing a custom control which will be used in our CRM frontend. The control itself is nothing special, it simply wraps two labels, text edits, and a button into a single control. (The control is only acting as a wrapper, a bit long winded, but unfortunately our only option due to various restrictions)
I though it would be nice to give the control a Font and ForeColor property, that would change the Font and Color of the labels. Changing the font size means that the relative position of the text boxes be changed to keep everything in line. No problem.
I encapsulated the layout logic in an UpdateLayout method, which is called on the set accessor of the Font property and everything works beautifully at design time, however, at runtime, the Font of the labels is correct, but the layout of the text boxes and button are still in the default positions, hence, the labels overlap.
What am I missing in for updating the position of controls at the init stage in runtime? I've tried calling the UpdateLayout() method from both Initialize and the constructor of the control, alas to no avail.
Am i missing something obvious here?
EDIT:
As requested, I whipped up a quick test. My test control looks like so (Not including Designer code):
public partial class TestControl : UserControl
{
private Font _font;
[Browsable(true)]
public override Font Font
{
get
{
return this._font ?? SystemFonts.DefaultFont;
}
set
{
this._font = value;
this.DoLayout();
}
}
private void DoLayout()
{
this.label1.Font = this._font;
this.Size = new Size(label1.Width + textBox1.Width + 10,
label1.Height >= textBox1.Height ? label1.Height : textBox1.Height);
this.textBox1.Location = new Point(label1.Location.X + 5 + label1.Width, 1);
this.Update();
}
public TestControl()
{
InitializeComponent();
}
protected override void OnLayout(LayoutEventArgs e)
{
base.OnLayout(e);
DoLayout();
}
}
That works great at design time, but runtime, less so...
EDIT2:
So the above code doesn't entirely reflect the problem accurately, however, I have tried Jogy's suggestion of overriding the OnLayout method, and lo and behold, it works!
I'm relatively new to Custom Controls, so a rookie mistake on my part. This will definitely be committed to the long term memory.
Override OnLayout() method and call your UpdateLayout() there.
Thanks for supplying the code, I would provide the properties by reusing already available controls.
public override Font Font
{
get { return this.label1.Font; }
set
{
this.label1.Font = value;
// Additional code to update related controls.
}
}
Also be aware that the declaration of
private Font _font;
Delivers a non-initialized variable, and by using it in the "Do_Layout" might use a null value. Maybe change it to the following when using your code.
this.label1.Font = this.Font;

Get Aero Window Colour

I've made a pretty slick Windows 8-ish interface using WPF. It already turns out way better than I could wish for, but I was wondering the following:
Is it somehow possible to retrieve the current window colour set by the user? You know, you can set the Aero colour when you right-click the desktop... My plan is to use that colour for a couple of canvas elements on my GUI.
Thanks in advance!
The SystemColours class exists for this very purpose. You can bind directly to it like so
"{DynamicResource {x:Static SystemColors.WindowColorKey}}"
You can query the ColorizationColor registry key for this.
I've even went a step further and created a method to get the hexadecimal colour value, hope this helps you:
public void SomeMethod()
{
int argbColor = (int)Microsoft.Win32.Registry.GetValue(#"HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM","ColorizationColor", null);
var color = System.Drawing.Color.FromArgb(argbColor);
string hexadecimalColor = ConverterToHex(color);
}
private static String ConverterToHex(System.Drawing.Color c)
{
return String.Format("#{0}{1}{2}", c.R.ToString("X2"), c.G.ToString("X2"), c.B.ToString("X2"));
}
I managed to get the correct colour using the following code:
Little sidenote: It has a small correction in it to ignore the alpha bit of the hex number, so I get the full color rather than the less saturated one.
string colorizationValue = string.Format("{0:x}", Microsoft.Win32.Registry.GetValue(#"HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM", "ColorizationColor", "00000000"));
StringBuilder bl = new StringBuilder(colorizationValue);
bl[0] = 'd';
bl[1] = '9';
colorizationValue = bl.ToString();
BrushConverter bc = new BrushConverter();
Brush brush = (Brush)bc.ConvertFrom("#" + colorizationValue);
cvs_barColor.Background = brush;
I created an open-source library for this here which is also available on NuGet.
install-package aerocolor-wpf.AeroColor
After installing the package, you can refer to a DynamicResource called AeroColor and AeroBrush depending on what you need.
There's some setup code that's needed too, but it isn't much. Just put something in your Loaded event handler of the window, as seen below.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
AeroResourceInitializer.Initialize();
}
}
The neat thing about this library is that it installs a hook as well, which updates those resources as the actual Aero color changes in the system too. This means you don't have to handle that either, and if you use a DynamicResource to point to the color in your XAML instead of a StaticResource, WPF will automatically update the color in your UI as well.
Looks very cool when Windows 8 changes the Aero color transitionally and your color follows.

How do I reclaim the space from the "Grip"

I've got a StatusStrip with a single ToolStripStatusLabel, Spring=true and a background color for notifications.
The problem is that there's an ugly gray square on the right side of the status strip. After fiddling for a while, I realized this is the sizing grip (I had is set to SizingGrip=false, GripStyle=Hidden). Yet even with it hidden, it still hogs the space. I can't get any content on the status strip to extend all the way to the right.
How would you work around this? Note I can't just set the backcolor of the StatusStrip because the Status Label changes colors and has some fading effects.
The StatusStrip.Padding property is borked, it returns the wrong value for Padding.Right if the sizing grip is disabled. You can fix it in your form constructor, like this:
public Form1() {
InitializeComponent();
statusStrip1.Padding = new Padding(statusStrip1.Padding.Left,
statusStrip1.Padding.Top, statusStrip1.Padding.Left, statusStrip1.Padding.Bottom);
}
Using the Left property to specify Right is the fix. Don't bother submitting this bug to Connect, they won't fix it.
Have a look at this blog entry on MSDN. The question was about changing the size of the sizing grip manually, and I think using the ToolStrip Renderer as suggested could work for you also.
The problem I have so far, is that it removes the background color on a status label in the StatusStrip, so it's not a solution yet, but it's a start.
public MyForm()
{
InitializeComponent();
statusStrip1.Renderer = new MyRenderer();
}
private class MyRenderer : ToolStripProfessionalRenderer
{
protected override void OnRenderStatusStripSizingGrip(ToolStripRenderEventArgs e)
{
// don't draw at all
}
}
I had following problem: when I set tsslSeparator.Spring = true, my right label disappeared immediately after tsslSeparator lost focus. The issue appeared when sizing grip was enabled. When it was disabled, everything worked just fine.
The solution was to set right margin for right label to something different than 0.
tsslLogging.Margin = new Padding(0, 3, 2, 2); // this is necessary for right alignment of status bar label
Hope this helps somebody.
If Microsoft isn't interesting in fixing it, it seems like a proper fix should handle all orientations, and ideally fix all Status Strips (see my answer to Get All Children for definition of GetAllChildren)
public static StatusStrip FixPadding(this StatusStrip ss) {
if (!ss.SizingGrip) {
var fixpad = ss.Padding;
if (ss.Orientation == Orientation.Horizontal) {
if (ss.RightToLeft == RightToLeft.No)
fixpad.Right = fixpad.Left;
else
fixpad.Left = fixpad.Right;
}
else
fixpad.Bottom = fixpad.Top;
ss.Padding = fixpad;
}
return ss;
}
public static void FixStatusStripPadding(this Form f) {
foreach (var ss in f.GetAllChildren().OfType<StatusStrip>())
ss.FixPadding();
}

Categories

Resources