I have a fun application written in Visual Studio (C#), and I'm wondering - What I do is I draw panels in certain ways on the form - if it's possible to render the form, without taking a screenshot?
Thanks
If by "taking a screenshot" you mean "sending PrtSc", then there's a better way, using System.Drawing.Graphics.CopyFromScreen:
using(Bitmap b = new Bitmap(this.ClientSize.Width, this.ClientSize.Height)) {
using(Graphics g = Graphics.FromImage(b)) {
g.CopyFromScreen(this.PointToClient(Point.Empty), Point.Empty, this.ClientSize);
}
// Your form is now rendered into b.
}
If you want to include the border, just use Size instead of ClientSize, and this.Location instead of this.PointToClient(Point.Empty).
Alternatively, you can use this.DrawToBitmap:
using(Bitmap b = new Bitmap(this.Width, this.Height)) {
this.DrawToBitmap(b, new Rectangle(0, 0, this.Width, this.Height));
// Your form is now rendered into b.
}
This will work even if your form doesn't have focus. However, it will draw the border and it will draw it in Windows Basic style if Aero is active.
No, it's not possible to capture the visual of the form as an image other than what is offered by some sort of screenshotting library (if that's what you're asking).
Related
I have been working on creating a program similar to MS Paint. I have several of the features it has down but the one which is currently giving me trouble is the rectangular selection tool. My program currently draws everything on the panel and saves it all in an ArrayList so each shape can be redrawn in Paint().
Like MS paint I would like the user to be able to select a section of the drawing on the panel and either copy it, move it, re-size it, or even delete it. I was thinking about having the user draw a rectangle & saving the information for it. Then taking that information for the rectangle, passing them to create a new Bitmap. I would then paint a new rectangle in the background color to give the appearance that the selected area was "removed" when the selected portion is moved. It sounded okay until I realized that I couldn't use the Graphics.FromImage() on the PaintEventArgs variable passed to Paint() which made my idea useless. Not sure if that makes sense so my apologies if it's a confusing mess.
I've been searching the internet for some assistance and I haven't found much to help so either this is very easy to do, very difficult, or "rectangle selection tool" is not the proper term. Any help or pointers would be greatly appreciated!!! Thank you for your time! :)
I understand that you actually have the Rectangle and now would like to copy an area from your painted Panel.
This is possible, assuming you have, as you should, placed all the painting in the Paint event of the Panel.
Then you can, use DrawToBitmap to ask the Panel to draw itself onto a new Bitmap; from there you can DrawImage the Rectangle onto your Panel.
Note: For this to integrate with your list of 'Paint-Actions' you will have to either now store that Bitmap or store the Rectangle and redo the whole operation.
using (Graphics G = panelCanvas.CreateGraphics() )
{
Rectangle R0 = new Rectangle(22,22,55,55); // your Rectangle!
using (Bitmap bmp = new
Bitmap(panelCanvas.ClientSize.Width, panelCanvas.ClientSize.Height))
{ panelCanvas.DrawToBitmap(bmp, panelCanvas.ClientRectangle);
G.DrawImage(bmp, 111f, 111f, R0, GraphicsUnit.Pixel);
}
}
Aside: Please do replace the ArrayList, which is depracated by the new List<T>, e.g. a List<PaintAction> or whatever name your class has!
If you simply want to extract a rectanglular area from the Panel Control you can use thsi function:
public Bitmap getAreaFrom(Control ctl, Rectangle area)
{
Bitmap bmp2 = new Bitmap(area.Width, area.Height);
using (Graphics G = ctl.CreateGraphics())
using (Bitmap bmp = new Bitmap(ctl.ClientSize.Width, ctl.ClientSize.Height))
{
ctl.DrawToBitmap(bmp, ctl.ClientRectangle);
using (Graphics G2 = Graphics.FromImage(bmp2))
G2.DrawImage(bmp, 0f, 0f, area, GraphicsUnit.Pixel);
}
return bmp2;
}
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.
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#.
I've put a BackgroundImage on my ListView in one of my windows forms.
Everything works as expected. But now I'd only like to position this image inside the ListView.
Like in CSS: background-position: top right; Would stick the image at the top right corner of the element.
Is there any way of doing so with a windows form?
Thanks a lot :)
It is possible, so yes, you can. Put on the resize or anywhere else if you don't resize listview
(need some optimize I guess, dont know)
Bitmap bmp = new Bitmap(listView1.Width, listView1.Height);
using (Graphics g = Graphics.FromImage(bmp))
{
SolidBrush br1 = new SolidBrush(Color.White);
g.FillRectangle(br1, 0, 0, listView1.Width, listView1.Height);
g.DrawImage(Image, listView1.Width - Image.Width, listView1.Height - pictureBox1.Image.Height);
}
listView1.BackgroundImage = bmp;
The short answer is: you can't.
This blog documents why LVM_SETBKIMAGE and intercepting WM_ERASEBKGROUND do not work with .NET ListViews.
The solution I found for this problem -- and which is used in the ObjectListView project -- is to use the low-level custom draw facilities of the native ListView control. It was complicated to implement, but is (now) easy to use.
the only way I know is to inherit from ListView and override the OnPaintBackground methode and draw the Image with Graphics.DrawImage() on your own. But you have to calculate the position on your own ;) You can also add a costum property for the aligment of the type System.Drawing.ContentAlignment.
otherwise you can tile the image , but it wont be stuck in one place .
listView1.BackgroundImageTiled = true;
I am using some custom controls one of which is a tooltip controller that can display images, so I am using th ebelow code to instantiate it:
Image newImage = Image.FromFile(imagePath);
e.ToolTipImage = newImage;
obviously could inline it but just testing at the moment. The trouble is the image is sometimes the wrong size, is there a way to set the display size. The only way I can currently see is editing the image using GDI+ or something like that. Seems like a lot of extra processing when I am only wanting to adjust display size not affect the actual image.
Once you have an image object loaded from its source, the Height and Width (and Size, and all ancillary properties) are read-only. Therefore, you are stuck with GDI+ methods for resizing it in RAM and then displaying it accordingly.
There are a lot of approaches you can take, but if you were to encapsulate that out to a library which you could reuse should this problem occur again, you'll be set to go. This isn't exactly optimized (IE, may have some bugs), but should give you an idea of how to approach it:
Image newImage = Image.FromFile(myFilePath);
Size outputSize = new Size(200, 200);
Bitmap backgroundBitmap = new Bitmap(outputSize.Width, outputSize.Height);
using (Bitmap tempBitmap = new Bitmap(newImage))
{
using (Graphics g = Graphics.FromImage(backgroundBitmap))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Get the set of points that determine our rectangle for resizing.
Point[] corners = {
new Point(0, 0),
new Point(backgroundBitmap.Width, 0),
new Point(0, backgroundBitmap.Height)
};
g.DrawImage(tempBitmap, corners);
}
}
this.BackgroundImage = backgroundBitmap;
I did test this, and it worked. (It created a 200x200 resized version of one of my desktop wallpapers, then set that as the background image of the main form in a scratch WinForms project. You'll need using statements for System.Drawing and System.Drawing.Drawing2D.
In Winforms, if you contain the image inside a PictureBox control, the PictureBox control can be set to zoom to a particular height/width, and the image should conform.
At least that's what happened in my Head First C# book when I did the exercise.