I'm trying to get the absolute position of a control on the screen. I'm using two monitors and the results aren't really that great...
What I'm doing is opening another form to capture an image, then passing this image to the main form and closing the capture form. I then want the main form to appear in the same place the picture was captured. To get a gist of what I'm trying to do as an example, open Snipping Tool on Windows and capture a snip. The window will then appear in the place that the image was taken.
This is the current code I am using to do this:
Location = new Point(Cursor.Position.X - CaptureBox.Width - CapturePanel.Location.X - CaptureBox.Location.X - 8, Cursor.Position.Y - CaptureBox.Height - CapturePanel.Location.Y - CaptureBox.Location.Y - 30);
CapturePanel contains the CaptureBox control which stores the picture. I'm also taking 8 from the X location and 30 from te Y location to compensate for the form's border and title bar, but the only problem with this is that some computers will be using a different window style, and these numbers will change.
If there is a method that can be used to grab the border and title width/height of windows, that would be great.
EDIT
A solution to this would be:
Location = new Point(
Cursor.Position.X -
CaptureBox.Width -
CapturePanel.Location.X -
CaptureBox.Location.X -
SystemInformation.HorizontalResizeBorderThickness,
Cursor.Position.Y -
CaptureBox.Height -
CapturePanel.Location.Y -
CaptureBox.Location.Y -
SystemInformation.CaptionHeight -
SystemInformation.VerticalResizeBorderThickness
);
With help from King King pointing out SystemInformation to me.
To get the Height of your Window caption, you can try this:
int captionHeight = yourForm.PointToScreen(Point.Empty).Y - yourForm.Top;
To get the Width of the form border, you can try this:
int borderWidth = yourForm.PointToScreen(Point.Empty).X - yourForm.Left;
Also you may want to look at the default caption height by SystemInformation.CaptionHeight.
If you want to get the location of the CaptureBox in screen coordinates, you can use the PointToScreen method:
Point loc = CaptureBox.PointToScreen(Point.Empty);
Related
Description Created a form in Winform C# app.
Added a panel (PBack) with dock type fill. (Scrollable)
Then added a picturebox(pbDraw) in panel(PBack) that height depends upon image size.
I want to add a control on the bottom left of the current screen view. (assume client scrolled down)
What i tried
Rectangle rect = Screen.GetWorkingArea(pbDraw);
ctrl.Top = rect.Top + rect.Height;
ctrl.Top = Screen.PrimaryScreen.WorkingArea.Top + Screen.PrimaryScreen.WorkingArea.Height;
ctrl.Top = Screen.FromControl(pbDraw).WorkingArea.Top+ Screen.FromControl(pbDraw).WorkingArea.Height;
Issue control is adding at top of pbDraw (0,0) and not on current screen bounds top.
As far as I understand, Control.Top takes the scrolled view into account all by itself.
Gets or sets the distance, in pixels, between the top edge of the control and the top edge of its container's client area.
So, you should be able to assign the coordinates relevant to the pBack and its client view:
ctrl.Top = pBack.Height - ctrl.Height;
Assuming that ctrl is a child of pBack this code should place it at the bottom of the current (scrolled) part of pBack
UPDATE:
As you said in the comments, ctrl is actually a child of pbDraw. In this case, you'll need to take the scrolling into account. For that, you can use Panel.VerticalScroll:
//scroll position + panel height - control height
ctrl.Top = pBack.VerticalScroll.Value + pBack.Height - ctrl.Height;
If I were you, I'd add ctrl to the panel, on top of the picture box. This will make it easier to calculate offsets relative to the panel.
If I create a Form, Size=(300,300),
then its .ClientRectangle property returns {X=0,Y=0,Width=292,Height=266}
From the Rectangle that we receive, it seems that we get the Size of the Client Area, but not the Location inwhich it starts relative to the form's Top-Left corner(above th title bar and border)..
The X and Y values are always 0,0,
yet we know that there is an offset between the Form's top-left corner, and its Client Area..
(because there is the Title Bar, and form Border)
So how can I get the actual starting point for it?
Going over Control's properties, I couldn't find one,
and as written above, the X,Y part of the .ClientRectangle property always returns 0,0..
The reason I ask this, is because If you want to use the Control.DrawToBitmap() method,
then you need to supply it with a Bitmap object with some size.
If you create a Bitmap in the size of Form.Size, then you can capture the whole form.
It will look like this:
Yet if you want to capture only the client area of the form,
then you can create a Bitmap object with size=Form.ClientRectangle,
but then you need to know at which point the client rectangle starts..
or else, your capture will look like this:
As can be seen, it's indeed in the size of the client area, but it doesn't start at the right location..
So when wanting to capture only the Client Area of the form, we need to know where the client area starts, relative to the Form's real starting point
(the top-left point, at which the border corner is, right above the title bar)
Are you looking for that:
// -8, -30 at my workstation
// so 30 is a size of caption and top border
// 8 is a left border size
Point leftTopShift = PointToClient(this.Location);
Just to take on a challenge, I decided to write an application to magnify only a particular section of the screen (under the mouse, following the mouse). The best way I can think to do this is to take a screenshot of the space under the form, enlarge, and paint on the form. I'm using this section of code to snap the picture inside a timer:
timer1.Stop();
//Reposition window
this.Left = Cursor.Position.X - this.Width / 2;
this.Top = Cursor.Position.Y - this.Height / 2;
//Bitmap to save image to
Bitmap bmpScreenshot = new Bitmap(this.Width, this.Height, PixelFormat.Format32bppArgb);
Graphics gfxScreenshot = Graphics.FromImage(bmpScreenshot);
//Grab section of screen shot
this.Opacity = 0.01;
gfxScreenshot.CopyFromScreen(this.Left, this.Top, 0, 0, this.Size, CopyPixelOperation.SourceCopy);
this.Opacity = 1;
//Save to class level so Paint can paint it
frame = bmpScreenshot;
//Make Double Buffered Panel repaint
dbPanel1.Invalidate();
timer1.Start();
In order to get the desktop (or whatever windows/contents are present) beneath the form, I set it's opacity to 0.01 (so that it's still clickable, which a click closes the app. Absolute 0 is not clickable) before taking the picture and then 1 after taking the snapshot... This creates a flicker. Is there a way I can get a bitmap of what's under the form without changing opacity or hiding/showing the form? I want a live image of what's under the form, not just a snapshot of when the app started.
I'm not looking for other apps that do this, I'm working on this so when I approach these problems I can learn a solution. I've tried changing the opacity (to all sorts of levels), using show and hide, SetVisibleCore(bool) on the window, but nothing lowers the flicker to an acceptable level. Any thoughts?
I would think you'd be better off displaying the magnified image offset from the cursor (look at the iPhone text selection/editing interface for example), and add some smart handling for the screen edges. That way you don't have to keep changing opacity, you just update the image and or placement of your form.
I use the function PointToScreen to get the screen related point of the control it gives proper value if I use this function for the toolstrip which is top on the form, but if there is menustrip on the top of the form and then under the menustrip, toolstrip is there then the function does not give proper value of screen point for the control toolstrip.
So,when I use this function for the toolstrip which is top on the form right now then it gives proper location like it gives Y position of 26 which is ok.
Now I am adding the menustrip top of the form and toolstrip is now under the menustrip and now if I use the function then it does not give proper value like,it gives y position of 74,which should be (26 + height of menustrip) = 50.
I would verify that you are calling PointToScreen on the correct control. If you want to find the location of a control in screen coordinates, call PointToScreen on its parent control.
For example:
control.Parent.PointToScreen(control.Location);
If you call PointToScreen on the control itself using a point relative to the parent control (such as Control.Location), you will get the wrong location.
For example:
Lets say control.Location = new Point(0, 20). If the parent is located at (100, 100) relative to the desktop, then the desktop position of the control is (100, 120). If you call PointToScreen on the parent control, then you will get (100, 120). If you call PointToScreen on the control itself, you will get the location of the point (0, 20) relative to the desktop location of the control, which would end up being (100, 140).
So if it's toolwindow or a minimizable form, I want to be able to get its height programmatically.
Is this possible? If so how?
You can determine titlebar height for both tool-windows and normal forms by using:
Rectangle screenRectangle = this.RectangleToScreen(this.ClientRectangle);
int titleHeight = screenRectangle.Top - this.Top;
Where 'this' is your form.
ClientRectangle returns the bounds of the client area of your form. RectangleToScreen converts this to screen coordinates which is the same coordinate system as the Form screen location.
There is an additional wrinkle in case your form is a view in an MDI application. In that case RectangleToScreen(this.ClientRectangle) returns coordinates relative not to Form itself (as one might expect) but with respect to MainForm which hosts MDIClient control hosting the Form.
You may to account for that by
Point pnt = new Point(0, 0);
Point corner = this.PointToScreen(pnt); // upper left in MainFrame coordinates
Point origin = this.Parent.PointToScreen(pnt); // MDIClient upperleft in MainFrame coordinates
int titleBarHeight = corner.Y - origin.Y - this.Location.Y;
This will get you the TitleBarsize:
form.ClientRectangle.Height - form.Height;
In my case, I had to change the height of the form so that it was just below one of the controls, I noticed that
int titleHeight = this.Height - screenRectangle.Height;
returns 39 while the accepted answer:
int titleHeight = screenRectangle.Top - this.Top;
returns 31
maybe because of form's bottom border.
To fix S. Norman's answer that simply has his minuend and subtrahend switched, the following is the simplest answer:
int HeightOfTheTitleBar_ofThis = this.Height - this.ClientRectangle.Height;
BTW, the standard hard coded title bar is 25dpi which is the minimum height and can be changed to a maximum of 50dpi.
OK OK,... yes, it is technically incorrect As stated by Cody Grey but it works and should get the same answer as the accepted answer. No need to create a rectangle.