I am resizing a image using DrawImage.
Graphics.DrawImage(SourceImage,0,0,200,200);
Here the source image starts with co ordinates 0.
Suppose i need to calculate the x and y coordinates dynamically how to do i go about it?
By default, the image should start with location 20(ie; x) and 20(ie y).
If i resize the form,it should proportionally calculate according to the resized imaged,that means,if for default it is 20 than for form resize how much?
Thanks
You can register to ResizeEnd event of the form and can redraw the image. Something like;
public Form1()
{
InitializeComponent();
this.ResizeEnd += new EventHandler(Form1_ResizeEnd);
}
void Form1_ResizeEnd(object sender, EventArgs e)
{
//draw the image again using the related calculation
}
From your question it is not clear how the size of the form relates to the desired coordinates.
A form has a ClientRectangle property that you can use to calculate the coordinates with. If you want to display the image in the bottom-right corner for example, you would:
protected override void OnPaint(PaintEventArgs e)
{
int x = this.ClientRectangle.Width - 200;
int y = this.ClientRectangle.Height - 200;
e.Graphics.DrawImage(SourceImage, x, y, 200, 200);
}
I assume the DrawImage code is in a Paint event handler, you could then either
use SetStyle(ControlStyles.ResizeRedraw, true); in the form constructor, so Paint is called when the form is resized
add an event handler for the Resize event and call Invalidate(); yourself
Related
I'm writing a game using c#'s winforms,
When creating a Scene (holding graphics, objects, etc...) I'm transfering the form so the c'tor looks something like that:
public Scene(Form form)
{
_g = form.CreateGraphics();
RegisterFormEvents(form);
_gameObjects = new List<GameObject>();
Width = form.Width;
Height = form.Height;
}
Now I'm trying to add an option to show the game on full screen,
but when i'm trying to maximize the window it only prints graphics to the original Width x Height,
how can I strecth those?
You just have to listen to the SizeChanged event of the form. Whenever the size has changed you set the Width and Height properties of the scene to match the new dimensions.
So, somewhere in your code you should have the following:
// I assume that this code is in the code-behind of the form, so "this" is the form
this.SizeChanged += new EventHandler(FormSizeChanged);
and
private void FormSizeChanged(object sender, EventArgs e)
{
yourScene.Width = this.Width;
yourScene.Height = this.Height;
}
I currently have a windows form app with a pictureBox in the middle of it which i am drawing various images too. The images are drawing fine except for the fact that they are all being scaled up by exactly 25%. I should also add that i am drawing everything inside a Paint method, using the PaintEventArgs to get the graphics device.
Ive made sure the SizeMode is set to Normal, ive checked over and over that the scale factor of the graphics object is 1 and all the image objects that i pass to the paint method are of the size they should be, but when they get drawn they are a different size.
I have until now just been calling g.drawImage(image, Rectangle) and passing the width and height of the image as the width and height of the Rectangle so that they are forced to be drawn at the correct size but i feel that this should be a short term fix and i am overlooking something simple.
Any help would be great, thanks in advance.
Code is as follows (only the important bits):
public class Level : PictureBox
{
...
private Image image;
...
public Level(TabPage parent, Panel propertiesPanel, ItemManager items, string levelName)
{
...
image = Image.FromFile(#"Levels/" + levelName);
Size = image.Size;
SizeMode = PictureBoxSizeMode.Normal;
MouseClick += new MouseEventHandler(level_MouseClick);
MouseMove += new MouseEventHandler(level_MouseMove);
Paint += new PaintEventHandler(level_Paint);
Invalidate();
}
private void level_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
//With the rectangle fix (drawing to correct size)
g.DrawImage(image, new Rectangle(0, 0, image.Size.Width, image.Size.Height));
////Without the fix (as i thought it should be be this is where it scales it)
//g.DrawImage(image, new Point(0, 0));
drawPlacedItems(g);
drawItemPreview(g);
}
This sounds like the HorizontalResolution and VerticalResolution properties of your image are being applied when you don't want them to, modify your code as per Jeremy's link to Image sizing issue in bitmap that ensures that HorizontalResolution and VerticalResolution are reset or ignored before calling DrawImage.
Hello it might be a silly question but i can't figure out the problem here.. here is my code to fill a form with a single block:
private void drawBackground()
{
Graphics g = genPan.CreateGraphics();
Image Block = Image.FromFile(#"C:\Users\Administrator\Desktop\movment V1\movment V1\images\BrownBlock.png");
float recWidth = Block.Width;
// rectangle width didnt change the name from previous code, it's picture width.
float recHeight = Block.Height;
// rectangle Heightdidnt change the name from previous code, it's picture Height.
float WinWidth = genPan.Width; // genPan is a panel that docked to the form
float WinHeight = genPan.Height;
float curWidth = 0; //indicates where the next block will be placed int the X axis
float curHeight = 0;//indicates where the next block will be placed int the Y axis
while ((curHeight + recHeight) <= WinHeight)
{
if (curWidth >= WinWidth / 3 || curWidth <= WinWidth / 1.5 ||
curHeight >= WinHeight / 3 || curHeight <= WinHeight / 1.5)
{
g.DrawImage(Block, curWidth, curHeight, recWidth , recHeight );
}
curWidth += recWidth;
if ((WinWidth - curWidth) < recWidth)
{
curWidth = 0;
curHeight += 50;
}
}
}
If I launch this func through a button it will work perfectly fine. But if I launch the func after the InitializeComponent(); method in the constructor OR in a FORM shown event, while the button is still on the form it will execute the func however the block backgroud wont be visible but the grey color will be. but if i remove the button the background will be visible. =\
I cant understand why is it happening, how to fix it and what am I doing wrong.. can anyone explain please..?
You can't really do that using your current logic. The problem is that the control (genPan panel in your case) has its own Paint event that when called, overwriting any graphics you used on it.
Even when you draw in button click it works only until the form is repainted e.g. try focus other window and focus your form again: you will lose what you have drawn.
Proper way to do such things is to write your own class that inherit from some basic control (Panel in your case) then overriding its OnPaint event and draw whatever you want there.
So first, have such class:
public class BlockBackgroundPanel : Panel
{
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
Image Block = Image.FromFile(#"C:\Users\Administrator\Desktop\movment V1\movment V1\images\BrownBlock.png");
float recWidth = Block.Width;
//rest of your code, replace "genPan" with "this" as you are inside the Panel
}
}
Then in your .Designer.cs file (you can open it in the Studio) change the code so that genPan will be of your new class instance:
private BlockBackgroundPanel genPan;
//...
this.genPan = new BlockBackgroundPanel ();
If you need to draw background only based on some condition/action/user interaction...
Put the call to this funciton into the forms OnPaint method and enable it only if some bollean variale equals true. And that boolean becomes true, only on button click.
Some hypothetical example:
protected override OnPaint(...) //FORMS ONPAINT OVERRIDE
{
if(needBackGround) //INITIAL VALUE AT STARTUP IS FALSE
drawBackground();
}
public void ButtonClickHandler(...)
{
needBackGround= !needBackGround; //INVERSE THE VALUE OF BOOLEAN
}
This is clearly just a sniplet to give you a hint and not a real code. There could be other problems you will need to face, like: flickering, handling resize, performance... but this is just a point to start.
I have a usercontrol that displays a gradient of colors which, once created will be constant.
The usercontrol doesn't contain any controls, not sure if i need to add a picturebox or dynamically add one.
Over that image, I'd like to display a line that will display what the current result is. I have no problem creating the gradient image on the map, however I'd like to somehow cache it so everytime I update the indicator (call CurrentValue from parent form), it will put the indicator line above the gradient image. This is updating about 30 times a second, thus, as of how the code below is working, it's repainting the gradient everytime, which is flickering.
Here's a code sample:
namespace Maps.UserControls
{
public partial class UserControlLegend : UserControl
{
private double m_CurrentValue;
public double CurrentValue
{
get
{
return m_CurrentValue;
}
set
{
m_CurrentValue = value;
RefreshValue();
}
}
public UserControlLegend()
{
InitializeComponent();
}
private void UserControlLegend_Paint(object sender, PaintEventArgs e)
{
if (b == null)
{
g = e.Graphics;
b = new System.Drawing.Bitmap(menuWidth, menuHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
// Code here that draws Menu
// Cache bitmap here?
g.Dispose();
}
}
private void RefreshValue()
{
this.Refresh();
g = this.CreateGraphics();
g.DrawImage(b, 0, 0);
//Code to Calcuate current Indicator Location
int x3 = 0;
// Draws current indicator correctly
g.DrawLine(new Pen(new SolidBrush(Color.Black)), this.Width / 2 - 15, x3, this.Width / 2 - 5, x3);
g.Dispose();
}
}
}
Explained above in comments, used a bitmap, and just set the x,y of the control.
First, I'd suggest you set your Control's property DoubleBuffered to True, so that flickering goes away. However, if you don't draw on the Control itself, that will be not useful at all. Drawing on a PictureBox is better, however, becuase it is automatically DoubleBuffered.
Second, you are painting into a new Bitmap every time, which is very bad in terms of memory, since the Bitmap is a few megabytes in size. I'd suggest you have a single Bitmap initialized in the constructor, and a single Graphics, created from that Bitmap in the constructor, too. Every time the paint accurs, just clear the old Graphics g and then draw onto it again and again. g Graphics and b Bitmap should be Disposed one time only, when the entire Control is Disposed.
This may inhance your code.
On a blank winform code can be added to show lines that intersect (crosshairs) at the mouse pointer. The problem is that the lines don't show (or are partially hidden) by controls on the form (ie listview, splitcontainer, buttons).
How would I modify the code below to show on-top (bring to front...) of all the controls present on the form?
int lastX = 0;
int lastY = 0;
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
Region r = new Region();
r.Union(new Rectangle(0, lastY, this.Width, 1));
r.Union(new Rectangle(lastX, 0, 1, this.Height));
this.Invalidate(r);
this.Update();
Graphics g = Graphics.FromHwnd(this.Handle);
g.DrawLine(Pens.Chocolate, 0, e.Y, this.Width, e.Y);
g.DrawLine(Pens.Chocolate, e.X, 0, e.X, this.Height);
lastX = e.X;
lastY = e.Y;
}
private void Form1_MouseLeave(object sender, EventArgs e)
{
this.Invalidate();
}
You need a transparent window that's on top of all the other controls. The only way to get one is by overlapping the form with another form, made transparent with its TranparencyKey property. You'll find sample code for this in my answer in this thread.
Please just try first sending to back(Control.SendToBack()) the controls on the form (ie listview, splitcontainer, buttons). Put this at the FormLoad event. I have experimented the same nightmare with a Windows MDI application.
Hope that helps,
Enumerate through the desired controls and call the .BringToFront(); function on them.
listBox1.BringToFront();
According to the documentation, the region object should be in world co-ordinates, you're passing in client co-ordinates. Use Control.PointToScreen to map the rectangles' top left coordinate to world space.
I'd also be tempted to defer the drawing to the OnPaint method.