i'm trying to put a red border around another application. I am trying to by using WinApi :
User32Methods.GetWindowRect(windowHandle, out var rectangle);
var g = System.Drawing.Graphics.FromHdc(User32Methods.GetDesktopWindow());
using (g)
{
//drawing borders
g.TranslateTransform(rectangle.Left, rectangle.Top);
g.DrawRectangle(new System.Drawing.Pen(System.Drawing.Color.Red, 10),
new System.Drawing.Rectangle(0, 0, rectangle.Width, rectangle.Height));
}
But if i put negative X/Y because the app is on left screen it didn't draw anything. I've try many methods but i'm blocked.
Thanks
Related
I am drawing rectangles for screen captures but when I draw it on mouse move it looks like it lacking and following mouse and not drawing smoothly.
But I want Drawing with smoothness
My code:
I have four rectangles and when I started drawing I give them margins between them and show our selected area in original color.
But when we remove outer four rectangles which make black area(outside of the rectangles) it works fast from before but I also want black outer areas as well.
My Code for outer rects:
rect_topleft.Visibility = Visibility.Visible;
rect_topleft.Margin = new Thickness(0, 0, 0, h - sY);
rect_bottomleft.Visibility = Visibility.Visible;
rect_bottomleft.Margin = new Thickness(0, startY, w - startX, -25);
rect_bottomright.Visibility = Visibility.Visible;
rect_bottomright.Margin = new Thickness(startX, endY, pictureBox2.Width - endX, 0); //Here picturebox2 is grid
rect_topright.Visibility = Visibility.Visible;
rect_topright.Margin = new Thickness(endX, startY, 0, -25);
EDIT:-
After Using Clemens Code :
it works fine on seperate project as shown in answer but it still lag in my code when i integrate it
Any solution for my code or any other method for doing this :
This question already has answers here:
Pixel behaviour of FillRectangle and DrawRectangle
(3 answers)
Closed 4 years ago.
I want to add a different bordercolor for every side of the element,
yet it's working pretty okay, the only problem I got is that my right side and bottom side of the border isn't visible.
public static void DrawBorder
(
Graphics graphics, Rectangle bounds,
Color leftColor, int leftWidth, ButtonBorderStyle leftStyle,
Color topColor, int topWidth, ButtonBorderStyle topStyle,
Color rightColor, int rightWidth, ButtonBorderStyle rightStyle,
Color bottomColor, int bottomWidth, ButtonBorderStyle bottomStyle
){}
Color leftColor = Color.FromArgb(65,0,0,0), rightColor = Color.FromArgb(150, 0, 0, 0), topColor = Color.FromArgb(65, 0, 0, 0), bottomColor = Color.FromArgb(150, 0, 0, 0);
int leftWidth = 3, rightWidth = 3, topWidth = 3, bottomWidth = 3;
ButtonBorderStyle leftStyle = ButtonBorderStyle.Solid, rightStyle = ButtonBorderStyle.Solid, topStyle = ButtonBorderStyle.Solid, bottomStyle = ButtonBorderStyle.Solid;
private void Paint_(object sender, PaintEventArgs e)
{
Rectangle borderRectangle = this.ClientRectangle;
borderRectangle.Inflate(0, 0);
ControlPaint.DrawBorder(e.Graphics, borderRectangle,
leftColor, leftWidth, leftStyle,
topColor, topWidth, topStyle,
rightColor, rightWidth, rightStyle,
bottomColor, bottomWidth, bottomStyle);
}
I'm using the "Paint_" function for every element you see here, so it's the same problem on every of these.
I'm pretty new to any of the "Draw" stuff, so I don't know anything which could be the problem.
The Draw... calls accepting a Pen instance seem (by default) to draw a rectangle bigger than 1 pixel to the right and bottom. So if you call something like DrawRectangle(Pens.Black, 0, 0, 100, 100), the rectangle on screen will look like as if it spans the coordinates 0, 0 to 101, 101.
The reasoning behind this is described here: Pixel behaviour of FillRectangle and DrawRectangle
To quickly fix your drawing, just pass coordinates smaller by 1 pixel to the right or bottom. E.g., to fix the above example, you'd call DrawRectangle(0, 0, 99, 99) to receive a rectangle spanning the coordinates 0, 0 to 100, 100 on the screen.
I personally resigned from using Pens and Draw calls for bordered rectangles and always use two FillRectangle calls (using Brush instances) as follows:
// Draws a white rectangle with black border
Rectangle rect = new Rectangle(0, 0, 100, 100);
gr.FillRectangle(Brushes.Black, rect); // Draw border
rect.Inflate(-1, -1); // Decrease the size of the rectangle by 1 pixel on all sides
gr.FillRectangle(Brushes.White, rect); // Draw background above it
I have read that FillRectangle is faster than DrawRectangle (as it can simply bitblit the area, unlike Draw which requires to draw for separate lines with all possible shenanigans internally).
I have following code to draw my border2.bmp in 4 direction
private void Form1_Paint(object sender, PaintEventArgs e)
{
Bitmap border = new Bitmap("border2.bmp");
int borderThick = border.Height;
Graphics g = e.Graphics;
Size region = g.VisibleClipBounds.Size.ToSize();
Rectangle desRectW = new Rectangle(0, 0, region.Width - borderThick, borderThick);
// 1. LEFT - RIGHT border
g.TranslateTransform(30, 30);
g.DrawImage(border, desRectW, desRectW, GraphicsUnit.Pixel);
// 2. UP - BUTTOM border
g.ResetTransform();
g.TranslateTransform(50, 50);
g.RotateTransform(90);
g.DrawImage(border, desRectW, desRectW, GraphicsUnit.Pixel);
// 3. RIGHT-LEFT border
g.ResetTransform();
g.TranslateTransform(100, 100);
g.RotateTransform(180);
g.DrawImage(border, desRectW, desRectW, GraphicsUnit.Pixel);
// 4. BOTTOM - UP border
g.ResetTransform();
g.TranslateTransform(150, 150);
g.RotateTransform(270);
g.DrawImage(border, desRectW, desRectW, GraphicsUnit.Pixel);
}
My original image is:
But the result of rotations are not exactly as I expected. 90 degrees is missing the first red line, 270 degrees is missing first black column, and 180 degrees is missing both.
Like image I attached:
PS: you can get border2.bmp at: http://i.imgur.com/pzonx3i.png
Edit:
I tried g.PixelOffsetMode = PixelOffsetMode.HighQuality; as #Peter Duniho comment, but I found it also does't draw correctly.
Example: 4 line is not starting at same position as we expect.
g.TranslateTransform(50, 50);
// LEFT - RIGHT border
g.DrawLine(Pens.Red, 0, 0, 100, 0);
// UP - BOTTOM border
g.RotateTransform(90);
g.DrawLine(new Pen(Color.FromArgb(128, Color.Blue)), 0, 0, 100, 0);
// RIGHT-LEFT border
g.RotateTransform(90);
g.DrawLine(new Pen(Color.FromArgb(128, Color.Green)), 0, 0, 100, 0);
// BOTTOM - UP border
g.RotateTransform(90);
g.DrawLine(new Pen(Color.FromArgb(128, Color.Gray)), 0, 0, 100, 0);
I can't really explain why this happens, except that any graphics API is necessarily going to include optimizations which may lead to imprecise behaviors at times and it seems that you are running into such a situation here.
In your particular example, the problem can be corrected by adding the following statement to the code, before you draw the images:
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
Setting it to Half will also work. It is equivalent to HighQuality (or technically, HighQuality is equivalent to it…but I find HighQuality more descriptive in the code :) ).
This will slow the rendering of the bitmap down somewhat, but probably not in a way that is perceptible to your users.
While the .NET documentation isn't very helpful in terms of describing this setting, the native Win32 docs for the same feature has slightly more detail:
PixelOffsetMode enumeration. From the description, one can infer that with the logical center of the pixel at (0,0), it's possible to lose a pixel on one edge when rotating (and/or gain a pixel on another edge). Switching to Half fixes this.
You need to account some things.
(1) RotateTransforms applies rotation at the current origin (as explained in the Matrix.Rotate documentation
(2) The default MatrixOrder (when not specified by using the overrides with the additional argument) is Prepend. Which means in your case the resulting transformation is rotate, then translate.
For instance, if you put this code inside the paint event:
var g = e.Graphics;
var loc = new Point(128, 128);
var rect = new Rectangle(0, 0, 64, 16);
g.ResetTransform();
g.TranslateTransform(loc.X, loc.Y);
g.FillRectangle(Brushes.Blue, rect);
g.ResetTransform();
g.TranslateTransform(loc.X, loc.Y);
g.RotateTransform(90);
g.FillRectangle(Brushes.Red, rect);
g.ResetTransform();
g.TranslateTransform(loc.X, loc.Y);
g.RotateTransform(180);
g.FillRectangle(Brushes.Green, rect);
g.ResetTransform();
g.TranslateTransform(loc.X, loc.Y);
g.RotateTransform(270);
g.FillRectangle(Brushes.Magenta, rect);
you'll get this
The blue rectangle is not rotated. Now pin virtually the origin (the upper left point) and start rotating clockwise. You'll see that it will exactly match the Red (90), Green (180) and Magenta (270) rectangles.
What all that means is that if you want to form a rectangle, you need to apply additional offset (translation) to the rotated rectangles. It depends how you want to handle the overlapping areas, but for the sample if we want to concat the Red rectangle right to the Blue one, we need to add the Blue rectangle Width + the original rectangle Height in the X direction. For other rotated rectangles you can apply similar additional offset to X, Y or both.
To complete the sample, if we modify the code like this
var g = e.Graphics;
var loc = new Point(128, 128);
var rect = new Rectangle(0, 0, 64, 16);
g.ResetTransform();
g.TranslateTransform(loc.X, loc.Y);
g.FillRectangle(Brushes.Blue, rect);
g.ResetTransform();
g.TranslateTransform(loc.X + rect.Width + rect.Height, loc.Y);
g.RotateTransform(90);
g.FillRectangle(Brushes.Red, rect);
g.ResetTransform();
g.TranslateTransform(loc.X + rect.Width + rect.Height, loc.Y + rect.Width + rect.Height);
g.RotateTransform(180);
g.FillRectangle(Brushes.Green, rect);
g.ResetTransform();
g.TranslateTransform(loc.X, loc.Y + rect.Width + rect.Height);
g.RotateTransform(270);
g.FillRectangle(Brushes.Magenta, rect);
the new result will be
Once you understand all that, hope you can apply the required corrections to your concrete code.
I'm currently trying to draw some lines in C# with the Graphics class.
My problem is, that sometimes (mostly on the repainting on resizing the form) some parts of the lines are missing.
This is how it looks like then:
This is my code where I draw the lines:
Graphics g = pnlGraph.CreateGraphics();
g.Clear(pnlGraph.BackColor);
Point p1 = new Point((mainNode.Left + (mainNode.Width / 2)), (mainNode.Top + (mainNode.Height / 2)));
Point p2 = new Point((pic.Left + (pic.Width / 2)), (pic.Top + (pic.Height / 2)));
g.DrawLine(new Pen(new SolidBrush(Color.Black), 2), p1, p2);
This code draws some lines from a mainNode in the middle of my panel to some nodes around it.
I'm calling the function to paint the lines on:
Load,
Resize,
Visible state changed
I also tried it in Paint of the form and the panel which didn't work.
Is there any way to fix it or another way of painting these lines?
Thanks for any answer!
Since the answer of #HansPassant has also made some problems we fixed the problem in another way:
We created an Image and filled it with an rectangle of the size of the panel.
After that we draw the lines in the image and draw the image on the panel.
Graphics g = pnlGraph.CreateGraphics();
Image img = new Bitmap(pnlGraph.Width, pnlGraph.Height);
Graphics gi = Graphics.FromImage(img);
gi.DrawRectangle(new Pen(new SolidBrush(pnlGraph.BackColor)), new Rectangle(0, 0, pnlGraph.Width, pnlGraph.Height));
// For every line:
gi.DrawLine(new Pen(new SolidBrush(Color.Black), 2), p1, p2);
// At the end:
g.DrawImage(img, 0, 0, img.Width, img.Height);
In Winforms application, i am doing 2D drawing.
for example, when i try fill a rectangle, that contains a circle. i want only region outside of circle should be filled with the specified color.
i tried but entire rectangle is getting filled.
Just try this to get the desired output. Open a windows forms and add a button. In the button click event, just add this code:
Region rgn = new Region(new Rectangle(50, 50, 200, 150));
System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
path.AddEllipse(60, 60, 100, 100);
rgn.Exclude(path);
Graphics g = this.CreateGraphics();
g.FillRegion(Brushes.Blue, rgn);
"rgn.Exclude(Path)" will help you to paint the rectangle excluding the circle inside it.