I changed in the properties OwnerDraw to true.
and added the Draw event.
private void toolTip1_Draw(object sender, DrawToolTipEventArgs e)
{
using (StringFormat sf = new StringFormat())
{
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.None;
sf.FormatFlags = StringFormatFlags.NoWrap;
using (Font f = new Font("Tahoma", 12))
{
e.Graphics.DrawString(e.ToolTipText, f,
SystemBrushes.ActiveCaptionText, e.Bounds, sf);
}
}
}
First time i put the mouse over a control with a tooltip the text is bigger but then next on other controls the tooltip get black :
before using the Draw event it was working fine but i want to resize the text font size.
You need clear the graphics first.
e.Graphics.Clear(((Control)sender).BackColor);
Or just use the methods defined in DrawToolTipEventArgs
e.DrawBackground();
e.DrawBorder();
In the form1 constructor
listView1.Scrollable = true;
listView1.View = View.Details;
ColumnHeader header = new ColumnHeader();
header.Text = "Files are ready";
header.Name = "col1";
listView1.Columns.Add(header);
listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
I want to change the color of "Files are ready" to Red.
So I tried with this event:
private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
using (var sf = new StringFormat())
{
sf.Alignment = StringAlignment.Center;
using (var headerFont = new Font("Microsoft Sans Serif", 9, FontStyle.Bold))
{
e.Graphics.FillRectangle(Brushes.Pink, e.Bounds);
e.Graphics.DrawString(e.Header.Text, headerFont,
Brushes.Black, e.Bounds, sf);
}
}
}
Tried to change both Brushes to Red but it didn't change anything.
You probably misssed to set the OwnerDraw property of your listView1 to true.
This property indicates that you want to draw parts of the ListView by your own code instead of the original ListView methods. Without it events like DrawColumnHeader, DrawItem and DrawSubItem will not be raised by the ListView.
For the columns you do not want to draw by yourself set e.DrawDefault to true. And use e.DrawBackground() to draw the background of the header if you only want to change the text color:
private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
if (e.ColumnIndex != myColumnIndex)
{
e.DrawDefault = true; // tell the ListView to draw this header
return;
}
e.DrawBackground();
// draw your text as you did in your code
// except the FillRectangle since the background is
// now already drawn
}
But if you do set listView1.OwnerDraw to true, the ListView will ask you for everything: the headers, the items and the subitems. So you will need to subscribe to DrawItem and DrawSubItem events, too and tell the ListView explicitly that you want it to draw those things by itself:
listView1.DrawItem += (sender, e) => { e.DrawDefault = true; };
listView1.DrawSubItem += (sender, e) => { e.DrawDefault = true; };
I made custom combobox that have an integrated button to add new item and it works good in case when DropDownStyle = ComboBoxStyle.DropDownList but there is a problem when the combobox DropDownStyle = ComboBoxStyle.DropDown the text of the combobox is cover the button that I made.
Is there away to make space before text in case when the DropDownStyle for the combobox is set to DropDown? You can see the problem in image.
[Image showing the spacing issue on the combobox]1
public class ComboBoxButton3 : ComboBox
{
public ComboBoxButton3()
{
myButton = new Button();
this.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
this.DropDownStyle = ComboBoxStyle.DropDownList;
}
protected override void OnCreateControl()
{
this.myButton.Size = new Size(23, this.ClientSize.Height);
this.myButton.Location = new Point(0, 0);
this.myButton.Cursor = Cursors.Default;
this.Button.BackgroundImage = global::RibbonMenuControlTest.Properties.Resources.add1;
this.Button.BackgroundImageLayout = ImageLayout.Stretch;
this.Button.FlatStyle = FlatStyle.Flat;
this.Controls.Add(this.myButton);
base.OnCreateControl();
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
if (this != null)
{
e.DrawBackground();
if (e.Index >= 0)
{
StringFormat sf = new StringFormat();
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Center;
Brush brush = new SolidBrush(this.ForeColor);
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
brush = SystemBrushes.HighlightText;
e.Graphics.DrawString(this.Items[e.Index].ToString(), this.Font, brush, e.Bounds, sf);
}
}
base.OnDrawItem(e);
}
public Button myButton;
public Button Button
{
get
{
return myButton;
}
set
{
myButton = value;
}
}
}
Generally, if a control is not designed to do a certain function with ease, there is normally a reason for it.
I would suggest re-considering your design before going forward.
Regardless, if you insist and continue - then these threads should give you the desired result / point you in the right direction (at least with moving the text around).
Align Text in Combobox
http://blog.michaelgillson.org/2010/05/18/left-right-center-where-do-you-align/
Snippet:
How to set combobox item height? My combobox.size=new size(320,40) and I had set combobox.itemheight=18 but it didn't work. I want my itemheight or text height to be 18, and fixed size for the combobox which is 320x40. I used also drawmode property but nothing is happening.
Try changing Font Size of your combo box
Well, in order to prevent combobox resizing to its default height, you can declare it being manually drawing:
myComboBox.DrawMode = DrawMode.OwnerDrawFixed; // or DrawMode.OwnerDrawVariable;
myComboBox.Height = 18; // <- what ever you want
Then you have to implement DrawItem event:
private void myComboBox_DrawItem(object sender, DrawItemEventArgs e) {
ComboBox box = sender as ComboBox;
if (Object.ReferenceEquals(null, box))
return;
e.DrawBackground();
if (e.Index >= 0) {
Graphics g = e.Graphics;
using (Brush brush = ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
? new SolidBrush(SystemColors.Highlight)
: new SolidBrush(e.BackColor)) {
using (Brush textBrush = new SolidBrush(e.ForeColor)) {
g.FillRectangle(brush, e.Bounds);
g.DrawString(box.Items[e.Index].ToString(),
e.Font,
textBrush,
e.Bounds,
StringFormat.GenericDefault);
}
}
}
e.DrawFocusRectangle();
}
Edit: to have the combobox stretched, but not its dropdown list
myComboBox.DrawMode = DrawMode.OwnerDrawVariable;
myComboBox.Height = 18; // Combobox itself is 18 pixels in height
...
private void myComboBox_MeasureItem(object sender, MeasureItemEventArgs e) {
e.ItemHeight = 17; // while item is 17 pixels high only
}
How can I change the BorderColor of the Textbox when a user Clicks on it or focuses on it?
You can handle WM_NCPAINT message of TextBox and draw a border on the non-client area of control if the control has focus. You can use any color to draw border:
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class ExTextBox : TextBox
{
[DllImport("user32")]
private static extern IntPtr GetWindowDC(IntPtr hwnd);
private const int WM_NCPAINT = 0x85;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_NCPAINT && this.Focused)
{
var dc = GetWindowDC(Handle);
using (Graphics g = Graphics.FromHdc(dc))
{
g.DrawRectangle(Pens.Red, 0, 0, Width - 1, Height - 1);
}
}
}
}
Result
The painting of borders while the control is focused is completely flicker-free:
BorderColor property for TextBox
In the current post I just change the border color on focus. You can also add a BorderColor property to the control. Then you can change border-color based on your requirement at design-time or run-time. I've posted a more completed version of TextBox which has BorderColor property:
in the following post:
BorderColor property for TextBox
try this
bool focus = false;
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (focus)
{
textBox1.BorderStyle = BorderStyle.None;
Pen p = new Pen(Color.Red);
Graphics g = e.Graphics;
int variance = 3;
g.DrawRectangle(p, new Rectangle(textBox1.Location.X - variance, textBox1.Location.Y - variance, textBox1.Width + variance, textBox1.Height +variance ));
}
else
{
textBox1.BorderStyle = BorderStyle.FixedSingle;
}
}
private void textBox1_Enter(object sender, EventArgs e)
{
focus = true;
this.Refresh();
}
private void textBox1_Leave(object sender, EventArgs e)
{
focus = false;
this.Refresh();
}
This is an ultimate solution to set the border color of a TextBox:
public class BorderedTextBox : UserControl
{
TextBox textBox;
public BorderedTextBox()
{
textBox = new TextBox()
{
BorderStyle = BorderStyle.FixedSingle,
Location = new Point(-1, -1),
Anchor = AnchorStyles.Top | AnchorStyles.Bottom |
AnchorStyles.Left | AnchorStyles.Right
};
Control container = new ContainerControl()
{
Dock = DockStyle.Fill,
Padding = new Padding(-1)
};
container.Controls.Add(textBox);
this.Controls.Add(container);
DefaultBorderColor = SystemColors.ControlDark;
FocusedBorderColor = Color.Red;
BackColor = DefaultBorderColor;
Padding = new Padding(1);
Size = textBox.Size;
}
public Color DefaultBorderColor { get; set; }
public Color FocusedBorderColor { get; set; }
public override string Text
{
get { return textBox.Text; }
set { textBox.Text = value; }
}
protected override void OnEnter(EventArgs e)
{
BackColor = FocusedBorderColor;
base.OnEnter(e);
}
protected override void OnLeave(EventArgs e)
{
BackColor = DefaultBorderColor;
base.OnLeave(e);
}
protected override void SetBoundsCore(int x, int y,
int width, int height, BoundsSpecified specified)
{
base.SetBoundsCore(x, y, width, textBox.PreferredHeight, specified);
}
}
WinForms was never good at this and it's a bit of a pain.
One way you can try is by embedding a TextBox in a Panel and then manage the drawing based on focus from there:
public class BorderTextBox : Panel {
private Color _NormalBorderColor = Color.Gray;
private Color _FocusBorderColor = Color.Blue;
public TextBox EditBox;
public BorderTextBox() {
this.DoubleBuffered = true;
this.Padding = new Padding(2);
EditBox = new TextBox();
EditBox.AutoSize = false;
EditBox.BorderStyle = BorderStyle.None;
EditBox.Dock = DockStyle.Fill;
EditBox.Enter += new EventHandler(EditBox_Refresh);
EditBox.Leave += new EventHandler(EditBox_Refresh);
EditBox.Resize += new EventHandler(EditBox_Refresh);
this.Controls.Add(EditBox);
}
private void EditBox_Refresh(object sender, EventArgs e) {
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e) {
e.Graphics.Clear(SystemColors.Window);
using (Pen borderPen = new Pen(this.EditBox.Focused ? _FocusBorderColor : _NormalBorderColor)) {
e.Graphics.DrawRectangle(borderPen, new Rectangle(0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1));
}
base.OnPaint(e);
}
}
Using OnPaint to draw a custom border on your controls is fine. But know how to use OnPaint to keep efficiency up, and render time to a minimum. Read this if you are experiencing a laggy GUI while using custom paint routines: What is the right way to use OnPaint in .Net applications?
Because the accepted answer of PraVn may seem simple, but is actually inefficient. Using a custom control, like the ones posted in the answers above is way better.
Maybe the performance is not an issue in your application, because it is small, but for larger applications with a lot of custom OnPaint routines it is a wrong approach to use the way PraVn showed.
set Text box Border style to None
then write this code to container form "paint" event
private void Form1_Paint(object sender, PaintEventArgs e)
{
System.Drawing.Rectangle rect = new Rectangle(TextBox1.Location.X,
TextBox1.Location.Y, TextBox1.ClientSize.Width, TextBox1.ClientSize.Height);
rect.Inflate(1, 1); // border thickness
System.Windows.Forms.ControlPaint.DrawBorder(e.Graphics, rect,
Color.DeepSkyBlue, ButtonBorderStyle.Solid);
}
With PictureBox1
.Visible = False
.Width = TextBox1.Width + 4
.Height = TextBox1.Height + 4
.Left = TextBox1.Left - 2
.Top = TextBox1.Top - 2
.SendToBack()
.Visible = True
End With
Here is my complete Flat TextBox control that supports themes including custom border colors in normal and focused states.
The control uses the same concept mentioned by Reza Aghaei https://stackoverflow.com/a/38405319/5514131 ,however the FlatTextBox control is more customizable and flicker-free.
The control handles the WM_NCPAINT window message in a better way to help eliminate flicker.
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WindowMessage.WM_NCPAINT AndAlso _drawBorder AndAlso Not DesignMode Then 'Draw the control border
Dim w As Integer
Dim h As Integer
Dim clip As Rectangle
Dim hdc As IntPtr
Dim clientRect As RECT = Nothing
GetClientRect(Handle, clientRect)
Dim windowRect As RECT = Nothing
GetWindowRect(Handle, windowRect)
w = windowRect.Right - windowRect.Left
h = windowRect.Bottom - windowRect.Top
clip = New Rectangle(CInt((w - clientRect.Right) / 2), CInt((h - clientRect.Bottom) / 2), clientRect.Right, clientRect.Bottom)
hdc = GetWindowDC(Handle)
Using g As Graphics = Graphics.FromHdc(hdc)
g.SetClip(clip, CombineMode.Exclude)
Using sb = New SolidBrush(BackColor)
g.FillRectangle(sb, 0, 0, w, h)
End Using
Using p = New Pen(If(Focused, _borderActiveColor, _borderNormalColor), BORDER_WIDTH)
g.DrawRectangle(p, 0, 0, w - 1, h - 1)
End Using
End Using
ReleaseDC(Handle, hdc)
Return
End If
MyBase.WndProc(m)
End Sub
I have removed the default BorderStyle property and replaced it with a simple boolean DrawBorder property that controls whether to draw a border around the control or not.
Use the BorderNormalColor property to specify the border color when the TextBox has no focus, and the BorderActiveColor property to specify the border color when the control receives focus.
The FlatTextBox comes with two themes VS2019 Dark and VS2019 Light, use the Theme property to switch between them.
Complete FlatTextBox control code written in VB.NET
https://gist.github.com/ahmedosama007/37fe2004183a51a4ea0b4a6dcb554176