How to delete/remove/undo DrawString in C# WinForm - c#

My form has a background image. I have some pictureBoxes i am using as buttons. I am attempting to have a MouseEnter/MouseLeave event to display label or pictureBox.
I have been trying various approaches. I am getting similar results- The label or picturebox appears fine, but on MouseLeave, label1.Visible = false; causes a very temporary blank box over the background image of the form. While it is fully functional, it just seems like a very slight lag, but makes the program look bad.
I experimented with the DrawString method. This seems like it could be a good option, but i cannot figure out how to remove the object on a MouseLeave event.
Is this possible? If not, is there a better option to accomplish what i am trying to accomplish?
Here is how I am drawing my string (in buttonClick event for testing):
Graphics g = this.CreateGraphics();
string letter = "Yo Dawg!";
g.DrawString(letter, new Font(FontFamily.GenericSansSerif, 20, FontStyle.Regular),
new SolidBrush(Color.Black), 100, 100);

You would draw in the paint event, in MouseLeave set a flag, cause a paint with Invalidate() then within paint if the flag is not set don't draw anything.
public partial class TheForm : Form
{
private Font _font = new Font(FontFamily.GenericSansSerif, 20, FontStyle.Regular);
private bool _hovering = false;
public TheForm() {
InitializeComponent();
picBox.Paint += new PaintEventHandler(picBox_Paint);
picBox.MouseEnter += (sender, e) => UpdateText(true);
picBox.MouseLeave += (sender, e) => UpdateText(false);
}
private void picBox_Paint(object sender, PaintEventArgs e) {
if (_hovering)
e.Graphics.DrawString("Yo Dawg!", _font, Brushes.Black, 100, 100);
}
private void UpdateText(bool show) {
_hovering = show;
picBox.Invalidate();
}
}

Related

How to show kind of notification (toast message) within Winform?

Let's take an example from android. Assume you send a message to someone and after message was send you can see (for a few seconds) kind of notification on the screen like Your message was send.
That is exactly what I would like to find in Winform. In my Winform app user click on the button and I would like to make kind of UI response, show him a message for a few sec, like Button clicked.
How to do it?
P.S. Actually I tried to find out how to do it, but everything that I found is kind of notification on the screen at the right bottom corner. It is not actually what I am looking for. I need something like you can see on screenshot. This text should appear in the form, not on the corner of the screen.
P.S 2 Tooltip also not what I am looking for. Tooltip is something that binded close to the button(view). I need kind of general UI response. User click on buttons and instead to show him a dialog that force user to move his mouse and close the dialog, I need kind of softy message that disappear after a few sec.
I need kind of softy message that disappear after a few sec.
I think the tooltips are what you are looking for. The idea is you can programmatically control where to show a tooltip and when to hide it.
Please start a new WinForms project. Add three buttons, ToolTip and Timer to the form. Write the next event handlers (and bind them to the corresponding components):
private void button_Click(object sender, EventArgs e)
{
toolTip1.Show(((Button)sender).Text + " is pressed", this, 300, 300);
timer1.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Enabled = false;
toolTip1.Hide(this);
}
After demo starting you'll see a tooltip with certain text appearing at the same position for the 1 second.
#Miamy's solution not a bad one, however you have to center text in notification box, and you don't need to use timer. Here the custom tooltip class which centers the tooltip text location and you can see the output below:
Moreover I added some coloring features along with default timer implementation.
class CustomToolTip : ToolTip
{
public int SIZE_X = 500;
public int SIZE_Y = 50;
public CustomToolTip()
{
this.OwnerDraw = true;
this.Popup += new PopupEventHandler(this.OnPopup);
this.Draw += new DrawToolTipEventHandler(this.OnDraw);
}
string m_EndSpecialText;
Color m_EndSpecialTextColor = Color.Black;
public Color EndSpecialTextColor
{
get { return m_EndSpecialTextColor; }
set { m_EndSpecialTextColor = value; }
}
public string EndSpecialText
{
get { return m_EndSpecialText; }
set { m_EndSpecialText = value; }
}
private void OnPopup(object sender, PopupEventArgs e) // use this event to set the size of the tool tip
{
e.ToolTipSize = new Size(SIZE_X, SIZE_Y);
}
private void OnDraw(object sender, DrawToolTipEventArgs e) // use this event to customise the tool tip
{
Graphics g = e.Graphics;
LinearGradientBrush b = new LinearGradientBrush(e.Bounds,
Color.AntiqueWhite, Color.LightCyan, 45f);
g.FillRectangle(b, e.Bounds);
g.DrawRectangle(new Pen(Brushes.Black, 1), new Rectangle(e.Bounds.X, e.Bounds.Y,
e.Bounds.Width - 1, e.Bounds.Height - 1));
System.Drawing.Size toolTipTextSize = TextRenderer.MeasureText(e.ToolTipText, e.Font);
g.DrawString(e.ToolTipText, new Font(e.Font, FontStyle.Bold), Brushes.Black,
new PointF((SIZE_X - toolTipTextSize.Width)/2, (SIZE_Y - toolTipTextSize.Height) / 2));
b.Dispose();
}
}
You can call this tooltip as below code:
CustomToolTip notifyError = new CustomToolTip();
notifyError.Show("Please enter a number.", this, 100, 100, 2000);
Above code creates notification box at 100, 100 location for 2 seconds.

C# - Code in form constructor not executed

Relatively new to C#; hopefully I'm just overlooking something simple.
I have a form named 'Exercise1' which contains a picture box called 'drawingArea' and a few buttons. The code for the constructor of Exercise1 is as follows:
public Exercise1()
{
InitializeComponent();
paper = drawingArea.CreateGraphics();
balloon = new Balloon("redBalloon", Color.Red, drawingArea.Width / 2,
drawingArea.Height / 2, 30);
paper.Clear(Color.White);
balloon.Display(paper);
}
...
'paper' and 'balloon' are created as globals above the constructor for use in the other methods on the form. Both 'paper' and 'balloon' work as initialized in the constructor in the other methods defined on the form.
For whatever reason, the commands
paper.Clear(Color.White);
and
balloon.Display(paper);
Which should clear the picture box and show a red ellipse, don't execute (at least visibly). What gives?
UPDATE:
Think I'm going to like this website... You guys are quick!
#Nitesh: The constructor for Exercise1 is called from another form. Code is as follows:
private void button1_Click(object sender, EventArgs e)
{
int exSelector = (int)numericUpDown1.Value;
switch (exSelector)
{
case 1:
Exercise1 form1 = new Exercise1();
form1.Show();
break;
...
#Sean Dunford: Yes and yes it is.
#RBarryYoung: Was playing around with that a bit, but had no luck. What command triggers a Form_Load event for Exercise1?
UPDATE: This altered code works as expected:
public Exercise1()
{
InitializeComponent();
paper = drawingArea.CreateGraphics();
drawingArea.BackColor = Color.White;
drawingArea.Paint += new PaintEventHandler(this.drawingArea_Paint);
balloon = new Balloon("redBalloon", Color.Red, drawingArea.Width / 2, drawingArea.Height / 2, 30);
}
private void drawingArea_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.White);
balloon.Display(e.Graphics);
}
...
Thanks for all the help!
You cannot do drawing in the constructor. To do proper drawing, you need to have the form shown on the screen. You can try using the Shown event to do your rendering (this may get lost when the form is redrawn, though).
Usually the best way is to set whatever flags you need in the constructor and then use the Paint event of the form to do all painting. Later on, when you need to repaint something, set up whatever state needs to be rendered, invalidate your form (this results in a Paint event) and then you can repaint the new state.
If you try to do customized drawing (outside your Paint event) you'll run the risk of things randomly going blank or your drawing may disapper when you resize/minimize your form.
You use Graphics in a constructor, that means that you draw on the paper only once, any redraw for whatever reason that happens after constructor will draw the drawingArea in its original way. Try to add PaintEventHandler to drawingArea and then call inside balloon.Display(e.Graphics);
public Exercise1()
{
InitializeComponent();
balloon = new Balloon("redBalloon", Color.Red, drawingArea.Width / 2,
drawingArea.Height / 2, 30);
drawingArea.Paint += new PaintEventHandler(drawingArea_Paint);
}
void drawingArea_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.White);
baloon.Display(e.Graphics);
}
You should be overriding the forms OnPaint event handler. In doing so, you are able to get the graphics context which will redraw your paper and balloon areas.

How to draw on Control so drawing doesn't disappear?

I want to display graphic file in PictureBox I have:
private void btnLoad_Click(object sender, EventArgs e)
{
if (dgOpenFile.ShowDialog() == DialogResult.OK)
{
Bitmap img = new Bitmap(dgOpenFile.FileName);
picture.Width = img.Height;
picture.Height = img.Height;
g.DrawImage(img, 0f, 0f);
}
}
That's g
private void Form1_Load(object sender, EventArgs e)
{
g = picture.CreateGraphics();
}
But when I move my Form outside the window my picture disappears. How can I prevent that?
You should do any custom drawing in the OnPaint event of the control to make it persistent. This causes your drawing to be redrawn every time the control is painted.
However, in this case it would be easier to use the picture box as it was designed:
picture.Image = img;
Windows uses a Paint-on-Request principle.
So when it sends a WM_PAINT message to your Control, it's OnPaint() is called. You should be ready to draw the image (again) in an overridden OnPaint() or in a Paint event handler.
But a Picturebox will do all this for you.

drawing a string with a transparent background using C#?

The standard way of g.DrawString creates a gray background. So if overlay another string on the form, part of it appears gray.
My question is, is there any way to draw a string with a transparent background? i want to be able to overlay strings, but still be able to see them.
Are you sure?
Here's a tutorial, which might help:
http://www.switchonthecode.com/tutorials/csharp-snippet-tutorial-how-to-draw-text-on-an-image
(edit)
Try starting from basics: I just created a new forms application and changed the code in Form1 to this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Paint += new PaintEventHandler(Form1_Paint);
}
void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawString("hello", new Font("Arial", 36), new SolidBrush(Color.FromArgb(255,0,0)), new Point(20,20));
e.Graphics.DrawString("world", new Font("Arial", 36), new SolidBrush(Color.FromArgb(0,0,255)), new Point(30,30));
}
}
It works as expected, with a transparent background for the text.
This is impossible to diagnose without you posting code. By default, Graphics.DrawString does not paint the background. This sample form demonstrates this:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs e) {
e.Graphics.DrawString("Underneath", this.Font, Brushes.Black, 0, 0);
e.Graphics.DrawString("Overlap", this.Font, Brushes.Black, 25, 5);
base.OnPaint(e);
}
}
Note how the 'Overlap' string does not erase the 'Underneath' string.

Why does text drawn on a panel disappear?

I'm trying to draw a text on a panel(The panel has a background picture).
It works brilliant,but when I minimize and then maximize the application the text is gone.
My code:
using (Graphics gfx = Panel1.CreateGraphics())
{
gfx.DrawString("a", new Font("Tahoma", 5), Brushes.White, new PointF(1, 1));
}
How do I keep it static so it doesn't get lost?
Inherit from Panel, add a property that represents the text you need to write, and override the OnPaintMethod():
public class MyPanel : Panel
{
public string TextToRender
{
get;
set;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawString(this.TextToRender, new Font("Tahoma", 5), Brushes.White, new PointF(1, 1));
}
}
This way, each Panel will know what it needs to render, and will know how to paint itself.
Just add a handler for the Paint event:
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawString("a", new Font("Tahoma", 5), Brushes.White, new PointF(1, 1));
}
If you don't use a Paint event, you are just drawing on the screen where the control happens to be. The control is not aware of this, so it has no idea that you intended for the text to stay there...
If you put the value that you want drawn on the panel in it's Tag property, you can use the same paint event handler for all the panels.
Also, you need to dispose of the Font object properly, or you will be having a lot of them waiting to be finalized before they return their resources to the system.
private void panel1_Paint(object sender, PaintEventArgs e) {
Control c = sender as Control;
using (Font f = new Font("Tahoma", 5)) {
e.Graphics.DrawString(c.Tag.ToString(), f, Brushes.White, new PointF(1, 1));
}
}
When you draw something, it only remains until the next time the form is refreshed.
When the form is refreshed, the Paint event is called. So if you want to ensure your text doesn't disappear, you need to include the code that draws it in the Paint event.
You can trigger a repaint using Control.Invalidate, but you otherwise cannot predict when they will happen.

Categories

Resources