Movable Rectangle or Label - c#

I am writing a program in Visual C# 2010 that has several icons on the form. When the mouse is placed over the icon (which is just an image) I want the icon to b highlighted via a border around the icon. In visual basic i can make a transparent rectangle with a colored border and position it over the icon. In C#, i can do the same however until i call invalidate multiple borders appear. The problem with calling invalidate is that my program is doing something in the background every second so the border keeps flashing (re-drawing).
Anyone got any ideas how i can implement this?

You didn’t say how you draw the border but from your description you are creating a graphics context for this. Don’t do this, it’s wrong. Instead, draw inside the Paint element of either the control or the its parent container.
The Paint event handler could look as follows:
private void yourControl_Paint(object sender, PaintEventArgs e)
{
if (! HasFocus(yourControl))
return;
Graphics g = e.Graphics;
using (Pen p = new Pen(Color.FromArgb(128, 0, 0, 128)))
g.DrawRectangle(p, 0, 0, yourControl.Width -1, yourControl.Height - 1);
}
This uses a hypothetical HasFocus method to determine whether this control should have a focus rectangle.
By the way, this is identical in VB and C#.

Related

Scroll an image quickly and smoothly

When scrolling an image in a browser using the scrollbars - the image scrolls quickly and smoothly. On the other hand, making a tight loop with Graphics.DrawImage, incrementing the location's X-coordinate by 1 each iteration - returns a slow motion. (It's also somewhat jerky even after making the Control DoubleBuffered.)
How can I get fast rendering like a browser's?
EDIT
void DoNow()
{
Rectangle rec1 = new Rectangle(Point.Empty, panel1.BackgroundImage.Size);
Rectangle rec2 = new Rectangle(Point.Empty, panel1.BackgroundImage.Size);
using (Graphics g = Graphics.FromImage(panel1.BackgroundImage))
{
for (int i = 0; i < 100; i++)
{
rec2.Location = new Point(rec2.Location.X + 1, rec2.Location.Y);
g.DrawImage(image, rec1, rec2, GraphicsUnit.Pixel);
panel1.Refresh();
}
}
}
It seems from the comments like the answer to my question is that browsers use hardware acceleration which is unavailable to Winforms. (Please feel free to correct me if I'm wrong.)
The easiest solution is to use a Panel object with the scroll bars set to Auto. Place a picturebox as a child object with the size mode set to Auto. The picture box will expand to the size of the image that you assign to it. Since the picture box will expand to be larger than the panel, the panel's scroll bars will appear. When you scroll the image using the panel, it will be smooth.
If you still want to manually provide the drawing yourself, you are getting the "flicker" because the Invalidate method automatically performs background erasing which is not performed during the OnPaint event. You need to subclass the parent control that you are drawing on and override the OnPaintBackground event. Like below:
protected override void OnPaintBackground(PaintEventArgs pevent)
{
// base.OnPaintBackground(pevent);
}
Also, remember to perform ALL drawing during the OnPaint event and use the e.Graphics object.

Winforms: How to draw line over control without invalidating it

i have a class that draws waveforms of audio. I'm drawing it in OnPaint function. Now i need to draw a line that shows where on the waveform we are at current moment. I can calculate the position but when i try to draw it i need to call Invalidate() and that forces form to redraw all that waveform chart data (a lot of points).
So is there a way to put some transparent element over this one and then call Invalidate() only on that element? i was trying with picture box but no sucess...
//main form
private void timer100ms_Tick(object sender, EventArgs e)
{
customWaveViewer1.currentPosition = (int)((stream.Position / (float)stream.Length) * customWaveViewer1.Width);
customWaveViewer1.overlayLabel.Invalidate(false);
}
//drawing function in my class
private void overlayLabelInvalidate(object sender, PaintEventArgs e)
{
Pen pen = new Pen(Color.FromArgb(255, 0, 0, 0));
e.Graphics.DrawLine(pen, currentPosition, 0, currentPosition, this.Height);
}
//constructor
public CustomWaveViewer()
{
InitializeComponent();
this.DoubleBuffered = true;
this.PenColor = Color.DodgerBlue;
this.PenWidth = 1;
overlayLabel = new PictureBox();
overlayLabel.Size = new System.Drawing.Size(this.Width, this.Height);
overlayLabel.Location = new Point(this.Left, this.Top);
overlayLabel.Visible = true;
overlayLabel.BackColor=Color.FromArgb(0,0,0,0);
overlayLabel.Paint += new System.Windows.Forms.PaintEventHandler(this.overlayLabelInvalidate);
Controls.Add(overlayLabel);
}
Actually what you are saying is not exactly true.
In the painteventargs there is a rectangle indicating the small portion of the window that needs to be repainted.
Also when you invalidate, you don't necessarily need to invalidate the whole form.
In your case you might want to invalidate only the old and new position of the marker that indicates where you are in the waveform.
So in your algorithm of your paint method, it is really up to you to make it efficient and only paint that part of the window that really needs repainting and to skip the part that does not need repainting.
It really can make a huge difference.
To make it even more look professional, set double buffering on.
No need to hastle with bitmaps of the whole image you have yourself, that is just what double buffering is all about, and forms can do it for you.
I copied following excerpt from https://msdn.microsoft.com/en-us/library/windows/desktop/dd145137(v=vs.85).aspx
BeginPaint fills a PAINTSTRUCT structure with information such as the dimensions of the portion of the window to be updated and a flag indicating whether the window background has been drawn. The application can use this information to optimize drawing. For example, it can use the dimensions of the update region, specified by the rcPaint member, to limit drawing to only those portions of the window that need updating. If an application has very simple output, it can ignore the update region and draw in the entire window, relying on the system to discard (clip) any unneeded output. Because the system clips drawing that extends outside the clipping region, only drawing that is in the update region is visible.
In this case there is no simple output and taking this into account is adviced.
I am not saying that creating a bitmap will not work. I am saying that optimizing your drawing logic will solve it just as well.
The information above still stands as windows forms is built on top of the old win32 api.

how to draw rectangle by selecting four coordinate points by user in C# windows form and display the coordinate points in text box

In my c# windows form application I am trying to draw a rectangle by getting the coordinates from the user through 4 mouse click events in the windows form, one for each point.
Here is what I've tried so far.
private void Form1_Click(object sender, EventArgs e)
{
using (Graphics g = this.CreateGraphics())
{
Pen pen = new Pen(Color.Black, 2);
Brush brush = new SolidBrush(this.BackColor);
g.FillRectangle(brush, this.Bounds); // redraws background
g.DrawRectangle(pen,textBox1.Text,textBox2.Text,textBox3.Text,textBox4.Text);
pen.Dispose();
brush.Dispose();
}
}
Your first mistake is drawing in a Click handler. Don't use CreateGraphics. Anything you draw with that is volatile and unlikely to play well.
What you should do is collect the points you want to draw when the Click event fires. Add a handler for the form's Paint event and do your drawing there. The event args will provide a Graphics object for you to use.
A separate method for calculating the rectangle might also be useful to keep that work out of the Paint handler.

Disappearances of shapes on Windows Forms

I am trying to draw a series of rectangles on my Windows Form application in C#. I am using System.Drawing.Graphics to draw the Rectangles. They work fine, but once I switch to another application on my computer or minimize the form, they just disappear. Does anyone know why this is the case?
System.Drawing.Graphics graphics = this.CreateGraphics();
System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle(
25 + (32 * PASS_THROUGH), 190, 32, 32);
graphics.DrawRectangle(System.Drawing.Pens.Green, rectangle);
You're not going about painting the right way. Here's some basic information on how it works:
http://msdn.microsoft.com/en-us/library/kxys6ytf.aspx
You should have code that looks like this:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Rectangle = new Rectangle(25 + (32 * PASS_THROUGH), 190, 32, 32);
e.Graphics.DrawRectangle(Pens.Green, Rectangle);
}
Windows will call this method whenever it needs to repaint your window.
If you want to be able to change what is painted dynamically, you need to add logic to this method. Such as an if statement that writes, if (drawRectangle) ...
When you want to signal your control to repaint itself after changing a variable like my above example of drawRectangle, you just need to call the Control.Invalidate method on the control in question.
You can manage a lot of different variables and objects to control what is painted, such as a list of shapes. In your paint method you would then loop through those shapes and draw them one by one. I am not sure if this is what you're trying to do, or if you just want to customize the look of your form and you don't need it to change dynamically.

Simple rectangle box

How do put rectangular box around few controls on my winform? (i dont want the grouping thing).
If you don't want to use a GroupBox, you can put your controls in a Panel and set its BorderStyle property to BorderStyle.FixedSingle or BorderStyle.Fixed3D.
What's wrong with the GroupBox control? Grouping together a related set of controls is exactly what it's intended for. Your users have seen it in every other application they use, and throughout the Windows shell. They're much more likely to recognize what it means than your own custom-drawn rectangle. Deviating from standard platform conventions is rarely a good idea. I strongly recommend using the GroupBox control, even if it's not exactly the perfect look that you had in mind.
That being said, it's certainly possible to draw your own box around a group of controls on a form. To do so, you'll need to override your form's OnPaint method and write some code to draw a rectangle. Doing it this way gives you complete control over the color of your box, as well as the line thickness.
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
// Call the base class
base.OnPaint(e);
// Create your drawing pen
using (Pen p = new Pen(SystemColors.WindowText, 2.0))
{
// Calculate the position and dimensions of the box
Rectangle rect = new Rectangle(10, 10, 30, 30);
// Draw the rectangle
e.Graphics.DrawRectangle(p, rect);
}
}
The only thing you'll need to add is the code that calculates the dimensions of your rectangle, relative to the controls you want it to surround. Use the Location property of each control to get this information.
You can put your controls into a panel and set its BorderStyle from None to FixedSingle - it is the easiest way
http://msdn.microsoft.com/en-us/library/cyh3c8h8.aspx
Pen pen = new Pen(Color.FromArgb(255, 0, 0, 0));
e.Graphics.DrawLine(pen, 20, 10, 300, 100);
You can draw lines on a windows form this way. This would hook into the Paint method where e is PaintEventArgs

Categories

Resources