relayman357
relayman357

Reputation: 855

Form position on screen (FMX, Win32)

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

enter image description here

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

Answers (2)

relayman357
relayman357

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.

enter image description here

thanks, russ

Upvotes: 0

Ted Lyngmo
Ted Lyngmo

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

Related Questions