Reputation: 855
I want to know where my form is on the screen. I've looked at position properties (e.g. this->Top, this->Left etc.) but they don't seem to fit the bill. I want to be able to determine how far my form is from the top/bottom of screen, and from left/right side of screen.
I'm using C++ Builder and FMX building a Win32 app.
thanks, russ
UPDATE 1: Turns out that what i really need is to find that coordinate (X,Y) with respect to the entire Desktop, not just the primary monitor. The Desktop spans multiple monitors.
Upvotes: 0
Views: 1537
Reputation: 855
Based on input from Ted & David i put together the following code. It will popup a message if the left edge of the form is close (within errX pixels) to the left edge of the desktop. It will popup a message if the top edge of the forms client area is close (within errY pixels) to the top edge of the desktop. Not pretty, but shows the idea.
void __fastcall TForm1::Button4Click(TObject *Sender)
{
int dWidth = Screen->DesktopWidth;
int dLeft = Screen->DesktopLeft;
int dRight = dWidth + dRight; // deskLeft is 0 if primary monitor is most left monitor
int dTop = Screen->DesktopTop;
int errX = 10; // within 10 pixels is fine enough
int errY = 40; // remember 30 or so pixels for caption bar
TPointF cli(0.0, 0.0);
TPointF sp = ClientToScreen(cli); //sp holds the coordinates for top left of form client area
ShowMessage("X = " + FloatToStr(sp.x) + "\nY = " + FloatToStr(sp.y)); //show coordinates of top/left of form client area
if (dLeft < 0) { //negative value
if ((abs(dLeft)-abs(sp.x)) < errX) {
ShowMessage("Within " + IntToStr(errX) + " pixels of left edge."); // or further left of edge
}
}
else {
if ((dLeft + sp.x)< errX) {
ShowMessage("Within " + IntToStr(errX) + " pixels of left edge."); // or further left of edge
}
}
if (sp.x > 0) { // no need to test the negative case
if ((dRight-sp.x) < errX) {
ShowMessage("Within " + IntToStr(errX) + " pixels of right edge."); // or further right of edge
}
}
if ((dTop + sp.y)< errY) {
ShowMessage("Within " + IntToStr(errY) + " pixels of top edge.");
}
}
This code works regardless of which monitor is primary.
UPDATE 1: This code has problems when the monitors are not aligned along their top edge. In the pic below monitors 1 & 3 have their tops aligned. 2 does not. In this example DesktopTop returned -876. So it seems that David's tip toward "Monitors" is the way to go - in C++ it is "Displays". e.g. TRect myR = Screen->Displays[0].BoundsRect;
to get the rectangle of display 0 and then int theTop = myR.top;
to find the top of this particular display.
thanks, russ
Upvotes: 0
Reputation: 117298
Your forms Top
and Left
properties should give you the position relative to the active desktops top left position but you may need to use ClientToScreen
/ScreenToClient
too. Seems to be hard to get the precise offset in FMX.
void __fastcall TForm1::MoveToTopLeft()
{
TPointF cli(0.0, 0.0);
TPointF sp = ClientToScreen(cli);
Left -= sp.x;
Top = 0;
}
There's something very asymmetrical with that solution ...
Upvotes: 1