I use the below code to set a gradient to a button in a windows form. It works but it's Text is not showing. What should I do to fix it?
Thank you.
private void Form1_Load(object sender, EventArgs e)
{
button2.Paint += new PaintEventHandler(this.Button2_Paint);
}
private void Button2_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.FillRectangle(new System.Drawing.Drawing2D.LinearGradientBrush(PointF.Empty, new PointF(button2.Width, button2.Height), Color.Pink, Color.Red), new RectangleF(PointF.Empty, button2.Size));
}
It's because you never actually drawing that text. Currently you only filling button's client rectangle with gradient, but there is no any text within. To show the string with button's text you need to add some more lines to Paint method:
private void Button2_Paint(object sender, PaintEventArgs e)
{
Button btn= (Button)sender;
Graphics g = e.Graphics;
g.FillRectangle(new System.Drawing.Drawing2D.LinearGradientBrush(PointF.Empty, new PointF(button2.Width, button2.Height), Color.Pink, Color.Red), new RectangleF(PointF.Empty, button2.Size));
SizeF size = g.MeasureString(btn.Text, btn.Font);
PointF topLeft = new PointF(btn.Width / 2 - size.Width / 2, btn.Height / 2 - size.Height / 2);
g.DrawString(btn.Text, btn.Font, Brushes.Black, topLeft);
}
Here Graphics.MeasureString gives you the width and height of a button's Text property, these values are used to position text right in the middle of a button. And Graphics.DrawString just draws the string with supplied color, font and position.
Related
I want to detect mouse click on my custom created region.
1) I ve tried this code with rectangle and it worked, but with string it doesnt
GraphicsPath gp = new GraphicsPath();
Region reg = new Region();
private void Form1_Load(object sender, EventArgs e)
{
gp.AddString("TEXT", new FontFamily("Arial"),0, 20.0f, new Point(300, 10), StringFormat.GenericDefault);
gp.Widen(Pens.AliceBlue);
reg = new Region(gp);
}
and here is the part2
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
if (reg.IsVisible(e.Location))
{
MessageBox.Show("aaaa");
}
}
It doesnt show the message box. :)
EDIT :here is my Paint event to see where my string is
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawString("TEXT", new Font("Arial", 20), Brushes.Yellow, 300,100 );
}
The most basic error is a typo: One time you draw at y = 10, the other time at y = 100.
But there is another issue which is not so obvious at all:
Add
e.Graphics.FillPath(Brushes.Firebrick, gp);
to the Paint event and you'll see it: The fonts have quite a different size.
That is because when adding text to a GraphicsPath it is using a different scale (called 'emSize') than Graphics.DrawString does, which uses 'Point'.
To adapt you can use this:
float fontsize = 20.0f;
using (Graphics g = panel1.CreateGraphics()) fontsize *= g.DpiY / 72f;
Now you can build the GraphicsPath, best with the correct coordinates..:
gp.AddString("TEXT", new FontFamily("Arial"), 0, fontsize,
new Point(300, 100), StringFormat.GenericDefault);
While trying to change the color of the tab based on button click event I came across this page:
Set TabPage Header Color
It appears to work, however I lost all the other formatting of my tabs and they now appear blank after I set the DrawMode=OwnerDrawFixed. How do I set the color of the tab of a specific page and still show the tabs as normal?
Code:
private void button3_Click(object sender, EventArgs e)
{
this.TabControlMain.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.TabControlMain_DrawItem);
SetTabHeader (tabDownload, System.Drawing.Color.Green);
}
private Dictionary<TabPage, Color> TabColors = new Dictionary<TabPage, Color>();
private void SetTabHeader(TabPage page, Color color)
{
TabColors[page] = color;
tabDownload.Invalidate();
}
private void TabControlMain_DrawItem(object sender, DrawItemEventArgs e)
{
//e.DrawBackground();
using (Brush br = new SolidBrush(TabColors[TabControlMain.TabPages[e.Index]]))
{
e.Graphics.FillRectangle(br, e.Bounds);
SizeF sz = e.Graphics.MeasureString(TabControlMain.TabPages[e.Index].Text, e.Font);
e.Graphics.DrawString(TabControlMain.TabPages[e.Index].Text, e.Font, Brushes.Black, e.Bounds.Left + (e.Bounds.Width - sz.Width) / 2, e.Bounds.Top + (e.Bounds.Height - sz.Height) / 2 + 1);
Rectangle rect = e.Bounds;
rect.Offset(0, 1);
rect.Inflate(0, -1);
e.Graphics.DrawRectangle(Pens.DarkGray, rect);
e.DrawFocusRectangle();
}
}
Below is a screenshot
Use Y(et)A(nother)TabControl
Gives you the possibly to draw own custom headers:
public override void DrawTab( Color foreColor,
Color backColor,
Color highlightColor,
Color shadowColor,
Color borderColor,
bool active,
bool mouseOver,
DockStyle dock,
Graphics graphics,
SizeF tabSize )
{
if( active )
{
Pen p = new Pen( borderColor );
graphics.DrawRectangle( p, 0, 0, tabSize.Width, tabSize.Height );
p.Dispose();
}
else
{
Brush b = Brushes.Peru;
float dif = tabSize.Height / 4.0f;
RectangleF r = new RectangleF( 0.0f, dif,
tabSize.Width, tabSize.Height - dif - dif );
graphics.FillRectangle( b, r );
}
}
In principle your code works, if not fine then at least sufficiently.
But you need to fix a few simple issues:
Of course, if your Tab is OwnerDrawn you need to do it from the start, not just after pressing the Button! So hook up the event right from the start, best in the Property-Event Tab so that it is placed in the Desgner.cs file where it belongs.
Now the Tabs are drawn and their Label texts show.
If you want to change a color you need to Invalidate the Tab Control, not the TabPage!
so change
tabDownload.Invalidate();
to
TabControlMain.Invalidate();
To make the example complete I have done only this:
private void Form1_Load(object sender, EventArgs e)
{
foreach (TabPage tp in TabControlMain.TabPages)
TabColors.Add(tp, tp.BackColor);
}
This sets all Tab colors in the Dictionary to the Colors of the Pages.
The code to draw the FocusRectangle could be improved.
First set the Padding like this:
this.TabControlMain.Padding = new System.Drawing.Point(10, 4);
This gives us enough room to draw a nice FocusRectangle..
Then change the code to draw it only on the selected Tab, maybe like this:
if (TabControlMain.SelectedIndex == e.Index)
using (Pen pen = new Pen(Color.Gray))
{
pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
Rectangle rect = e.Bounds;
rect.Offset(0, 1);
rect.Inflate(-3,-2);
e.Graphics.DrawRectangle(pen, rect);
}
Now it looks like this:
Of course managing the colors is up to you..
I'm using C# for developing a simple tool that has a picturebox inside a panel. The panel has property Autoscroll = true. If the Image of that picturebox is larger than the panel the panel has scrollbars
I could draw a rectangle on paint event of picturebox. But when i scroll, this rectangle disappears. I know it need to repaint it after moving the scrollbar but i don't know how to restore it again.
x, y, width, heigth, zoom is global variable and when use click in to treenode, it'll have data.
private void pictureBoxView_Paint(object sender, PaintEventArgs e)
{
if (choose == true)
{
Size newSize = new Size((int)(pictureBoxView.Image.Width * zoom),
(int)(pictureBoxView.Image.Height * zoom));
Graphics graphic = pictureBoxView.CreateGraphics();
Pen pen = new Pen(Color.Red, 3);
graphic.DrawRectangle(pen, x, y, width, height);
pen.Dispose();
}
}
private void treeViewTemplate_AfterSelect(object sender, TreeViewEventArgs e)
{
// refresh picturebox
pictureBoxView.Refresh();
// allow repaint
choose = true;
string[] value = treeViewTemplate.SelectedNode.Tag.ToString().Split(',');
x = Int32.Parse(value[0]);
y = Int32.Parse(value[1]);
width = Int32.Parse(value[2]);
height = Int32.Parse(value[3]);
zoom = Double.Parse(value[4]);
//MessageBox.Show("x = " + y + ", y = " + y + ", width = " + width + ", height = " + height + ", zoom = " + zoom);
// This call draw a rectangle again when I choose a value from TreeNode's Tag
pictureBoxView_Paint(this, null);
}
you also can use pictureBoxView.Refresh()
and define two local variable save the scroll offset through ScrollEventArgs.NewValue
if you do not want to paint when scrolling, you can use this
private void panel1_Paint(object sender, PaintEventArgs e)
{ pictureBox1.Refresh();}
In general you should use Invalidate method in order to redraw a surface of the control:
pictureBoxView.Invalidate();
Here is a sample of redrawing a PictureBox that is inside a Panel:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var rectangle = new Rectangle(10, 10, 100, 100);
e.Graphics.DrawRectangle(Pens.Red, rectangle);
}
private void panel1_Scroll(object sender, ScrollEventArgs e)
{
pictureBox1.Invalidate();
}
The fixed red rectangle is redrawed when panel is scrolled.
In this case (PictureBox in Panel control), you must create a method, which drawing on teh picture box. And you puts the drawing method in the Panel ScrollEvent.
private void panel1_Scroll(object sender, ScrollEventArgs e)
{
Drawing();
}
I found an article that does exactly what I need. It draws multiple colors on the same line on a text box. But the problem is that it was written in VB.NET and I'm writing my program in C#. Any good soul can convert this to C# if it is possible and if it isn't can you give me other options? Thanks.
This is the article: http://www.vbrad.com/article.aspx?id=34.
here is the conversion of what you posted Nicolas
if you need to change / get anything else working you will need to test it on your end..
Happy coding
private void MeasureItemHandler(object sender, MeasureItemEventArgs e)
{
Graphics g = Graphics.FromHwnd(lstColor.Handle);
StringFormat sf = new StringFormat(StringFormat.GenericTypographic);
SizeF size = default(SizeF);
float height = 0;
Font oFont = new Font("Arial", 10);
//measure the height of what you are about to draw
//and let the listbox know this
size = g.MeasureString(data(e.Index), oFont, 500, sf);
height = size.Height + 5;
e.ItemHeight = height;
}
private void DrawItemHandler(object sender, DrawItemEventArgs e)
{
Graphics g = Graphics.FromHwnd(lstColor.Handle);
StringFormat sf = new StringFormat(StringFormat.GenericTypographic);
SizeF size = default(SizeF);
float width = 0;
Font oFont = new Font("Arial", 10);
//get the width of the string you are about to write
//this info is needed so that we can offset the next
//string that will be drawn in a different color.
size = g.MeasureString(data(e.Index), oFont, 500, sf);
width = size.Width + 16;
//prepare the list for drawing
e.DrawBackground();
e.DrawFocusRectangle();
//draw the first string in a certain color
e.Graphics.DrawString(data(e.Index), oFont, new SolidBrush(color(e.Index)), e.Bounds.X, e.Bounds.Y);
//draw the second string in a different color
e.Graphics.DrawString(data(data.Length - 1 - e.Index), oFont, new SolidBrush(color(color.Length - 1 - e.Index)), width, e.Bounds.Y);
}
First of all, they aren't using a Textbox in this article, they are using a Listbox but what follows is a conversion of the code from VB.Net to C# like you asked. It needs tidied up a bit but it does the job.
Just create a new Windows Form, place a Listbox called lstColor onto this form, change the DrawMode property to OwnerDrawFixed inside the properties window, then add event handlers for DrawItem and MeasureItem (you can add event handlers by clicking on the lightning bolt in the Properties window, and double clicking the whitespace beside these two words in the list).
In the DrawItem event handler, add the following:
private void lstColor_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
{
var size = g.MeasureString(data[e.Index], oFont, 500, sf);
var width = size.Width + 16;
e.DrawBackground();
e.DrawFocusRectangle();
e.Graphics.DrawString(data[e.Index], oFont, new SolidBrush(color[e.Index]), e.Bounds.X, e.Bounds.Y);
e.Graphics.DrawString(data[data.Length - 1 - e.Index], oFont, new SolidBrush(color[color.Length - 1 - e.Index]), width, e.Bounds.Y);
}
In the MeasureItem event handler, add this:
private void lstColor_MeasureItem(object sender, MeasureItemEventArgs e)
{
var size = g.MeasureString(data[e.Index], oFont, 500, sf);
var height = size.Height;
e.ItemHeight = Convert.ToInt32(height);
}
Add five private fields outside the scope of any methods but inside your Form1 (or whatever you've called your form) class like so:
private string[] data;
private Color[] color;
private Font oFont;
private Graphics g;
private StringFormat sf;
Put the following three lines inside your Form1_Load event:
private void Form1_Load(object sender, EventArgs e)
{
oFont = new Font("Arial", 10);
data = new string[] { "This is Red", "This is Blue", "This is Green", "This is Yellow", "This is Black", "This is Aqua", "This is Brown", "This is Cyan", "This is Gray", "This is Pink" };
color = new Color[] {Color.Red, Color.Blue, Color.Green, Color.Yellow, Color.Black, Color.Aqua, Color.Brown, Color.Cyan, Color.Gray,Color.Pink};
lstColor.DataSource = data;
g = Graphics.FromHwnd(lstColor.Handle);
sf = new StringFormat(StringFormat.GenericTypographic);
}
And you are all set.
Hope this helps
Check out http://converter.telerik.com/ It converts code from VB.NET to C# and C# to VB.NET. It wont work on complex code, but could prove useful to you.
I'm very new in C#
I want a rectangle to appear wherever there's a mouseclick on a panel
Here's my code:
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
int x = e.Location.X;
int y = e.Location.Y;
if (radioButton1.Checked == false)
{
((Panel)sender).Invalidate(new Rectangle(x * 40, y * 40, 40, 40));
}
else if (radioButton2.Checked == true)
{
return;
}
}
I wonder how to change the color of the rectangle?
Please advise me if my code is wrong.
Thanks.
Your drawing should be performed in the panel's Paint event handler. When you click the panel, create the rectangle (in the MouseUp event of the panel) and store it in a collection of rectangles (such as a dictionary). Then refresh the panel. In the panel's Paint event, draw all the rectangles. Here is a simple example:
Dictionary<Color, List<Rectangle>> rectangles = new Dictionary<Color, List<Rectangle>>();
private void panel1_Paint(object sender, PaintEventArgs e)
{
//The key value for the dictionary is the color to use to paint with, so loop through all the keys (colors)
foreach (var rectKey in rectangles.Keys)
{
using (var pen = new Pen(rectKey)) //Create the pen used to draw the rectangle (using statement makes sure the pen is disposed)
{
//Draws all rectangles for the current color
//Note that we're using the Graphics object that is passed into the event handler.
e.Graphics.DrawRectangles(pen, rectangles[rectKey].ToArray());
}
}
}
//This method just adds the rectangle to the collection.
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
Color c = getSelectedColor(); //Gets a color for which to draw the rectangle
//Adds the rectangle using the color as the key for the dictionary
if (!rectangles.ContainsKey(c))
{
rectangles.Add(c, new List<Rectangle>());
}
rectangles[c].Add(new Rectangle(e.Location.X - 12, e.Location.Y - 12, 25, 25)); //Adds the rectangle to the collection
}
//Make the panel repaint itself.
panel1.Refresh();
}
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
Graphics g = panel1.CreateGraphics();
g.DrawRectangle(new Pen(Brushes.Black),
new Rectangle(new Point(e.X, e.Y), new
Size(100, 100)));
}
you can change the color in Brushes.Black part of code, change it as you desire