unit uMonitors;

interface

  uses Forms;

  // *** CURRENT MONITOR FUNCTIONS ***
  function CMTop( C: tForm ): integer; // CurrentMonitorTop
  function CMWidth( C: tForm ): integer; // CurrentMonitorWidth
  function CMHeight( C: tForm ): integer; // CurrentMonitorHeight
  function CMLeft( C: tForm ): integer; // CurrentMonitorLeft
  function CMXCen( C: tForm ): integer;
  function CMYCen( C: tForm ): integer;
  function CMBottom( C: tForm ): integer;
  function CMRight( C: tForm ): integer;

  // *** PRIMARY MONITOR FUNCTION ***
  function PMWidth: integer; // PrimaryMonitorWidth
  function PMHeight: integer; // PrimaryMonitorHeight
  function PMLeft: integer; // PrimaryMonitorLeft
  function PMRight: integer; // PrimaryMonitorRight
  function PMTop: integer; // PrimaryMonitorTop
  function PMBottom: integer; // PrimaryMonitorRight
  function PMXCen: integer; // Center X coordinate of Primary Monitor
  function PMYCen: integer; // Center Y coordinate of Primary Monitor

  // Make sure the form C is on the system's workspace
  procedure InsureOnScreen( C: tForm );

implementation
  uses uUtility, Types;

  // *** CURRENT MONITOR FUNCTIONS ***
  function CMWidth( C: tForm ): integer; // CurrentMonitorWidth
  // return the width of the monitor that holds the upper left corner of form C
  var
    i,Current,Primary: integer;
  begin
    Current := -1;
    Primary := -1;
    for i:=0 to Screen.MonitorCount-1 do
    begin
      if iInRange( C.Left, Screen.Monitors[i].BoundsRect.Left, Screen.Monitors[i].BoundsRect.Right ) AND
         iInRange( C.Top,  Screen.Monitors[i].BoundsRect.Top, Screen.Monitors[i].BoundsRect.Bottom ) then
      begin
        Current := i;
      end;
      if Screen.Monitors[i].Primary then Primary := i;
    end;
    if Current >= 0 then
      result := Screen.Monitors[Current].WorkAreaRect.Right - Screen.Monitors[Current].WorkAreaRect.Left + 1
    else if Primary >= 0 then
      result := Screen.Monitors[Primary].WorkAreaRect.Right - Screen.Monitors[Primary].WorkAreaRect.Left + 1
    else
      result := Screen.WorkAreaRect.Right - Screen.WorkAreaRect.Left + 1;
  end;

  function CMHeight( C: tForm ): integer; // CurrentMonitorHeight
  // return the height of the monitor that holds the upper left corner of form C
  var
    i,Current,Primary: integer;
  begin
    Current := -1;
    Primary := -1;
    for i:=0 to Screen.MonitorCount-1 do
    begin
      if iInRange( C.Left, Screen.Monitors[i].BoundsRect.Left, Screen.Monitors[i].BoundsRect.Right ) AND
         iInRange( C.Top,  Screen.Monitors[i].BoundsRect.Top, Screen.Monitors[i].BoundsRect.Bottom ) then
      begin
        Current := i;
      end;
      if Screen.Monitors[i].Primary then Primary := i;
    end;
    if Current >= 0 then
      result := Screen.Monitors[Current].WorkAreaRect.Bottom - Screen.Monitors[Current].WorkAreaRect.Top + 1
    else if Primary >= 0 then
      result := Screen.Monitors[Primary].WorkAreaRect.Bottom - Screen.Monitors[Primary].WorkAreaRect.Top + 1
    else
      result := Screen.WorkAreaRect.Bottom - Screen.WorkAreaRect.Top + 1;
  end;

  function CMLeft( C: tForm ): integer; // CurrentMonitorLeft
  // return the left pixel of the monitor that holds the upper left corner of form C
  var
    i,Current,Primary: integer;
  begin
    Current := -1;
    Primary := -1;
    for i:=0 to Screen.MonitorCount-1 do
    begin
      if iInRange( C.Left, Screen.Monitors[i].BoundsRect.Left, Screen.Monitors[i].BoundsRect.Right ) AND
         iInRange( C.Top,  Screen.Monitors[i].BoundsRect.Top, Screen.Monitors[i].BoundsRect.Bottom ) then
      begin
        Current := i;
      end;
      if Screen.Monitors[i].Primary then Primary := i;
    end;
    if Current >= 0 then
      result := Screen.Monitors[Current].WorkAreaRect.Left
    else if Primary >= 0 then
      result := Screen.Monitors[Primary].WorkAreaRect.Left
    else
      result := Screen.WorkAreaRect.Left;
  end;

  function CMBottom( C: tForm ): integer;
  begin
    result := CMTop(C)+CMHeight(C);
  end;

  function CMRight( C: tForm ): integer;
  begin
    result := CMLeft(C)+CMWidth(C);
  end;

  function CMTop( C: tForm ): integer; // CurrentMonitorTop
  // return the top pixel of the monitor that holds the upper left corner of form C
  var
    i,Current,Primary: integer;
  begin
    Current := -1;
    Primary := -1;
    for i:=0 to Screen.MonitorCount-1 do
    begin
      if iInRange( C.Left, Screen.Monitors[i].BoundsRect.Left, Screen.Monitors[i].BoundsRect.Right ) AND
         iInRange( C.Top,  Screen.Monitors[i].BoundsRect.Top, Screen.Monitors[i].BoundsRect.Bottom ) then
      begin
        Current := i;
      end;
      if Screen.Monitors[i].Primary then Primary := i;
    end;
    if Current >= 0 then
      result := Screen.Monitors[Current].WorkAreaRect.Top
    else if Primary >= 0 then
      result := Screen.Monitors[Primary].WorkAreaRect.Top
    else
      result := Screen.WorkAreaRect.Top;
  end;

  function CMXCen( C: tForm ): integer;
  begin
    result := CMLeft(C) + CMWidth(C) DIV 2;
  end;

  function CMYCen( C: tForm ): integer;
  begin
    result := CMTop(C) + CMHeight(C) DIV 2;
  end;

  // *** PRIMARY MONITOR FUNCTION ***
  function PMWidth: integer; // PrimaryMonitorWidth
  // return the width of the monitor
  var
    i,Primary: integer;
  begin
    Primary := -1;
    for i:=0 to Screen.MonitorCount-1 do
    begin
      if Screen.Monitors[i].Primary then Primary := i;
    end;
    if Primary >= 0 then
      result := Screen.Monitors[Primary].WorkAreaRect.Right - Screen.Monitors[Primary].WorkAreaRect.Left + 1
    else
      result := Screen.WorkAreaRect.Right - Screen.WorkAreaRect.Left + 1;
  end;

  function PMHeight: integer; // PrimaryMonitorHeight
  // return the height of the primary monitor
  var
    i,Primary: integer;
  begin
    Primary := -1;
    for i:=0 to Screen.MonitorCount-1 do
    begin
      if Screen.Monitors[i].Primary then Primary := i;
    end;
    if Primary >= 0 then
      result := Screen.Monitors[Primary].WorkAreaRect.Bottom - Screen.Monitors[Primary].WorkAreaRect.Top + 1
    else
      result := Screen.WorkAreaRect.Bottom - Screen.WorkAreaRect.Top + 1;
  end;

  function PMLeft: integer; // PrimaryMonitorLeft
  // return the left pixel of the monitor that holds the upper left corner of form C
  var
    i,Primary: integer;
  begin
    Primary := -1;
    for i:=0 to Screen.MonitorCount-1 do
    begin
      if Screen.Monitors[i].Primary then Primary := i;
    end;
    if Primary >= 0 then
      result := Screen.Monitors[Primary].WorkAreaRect.Left
    else
      result := Screen.WorkAreaRect.Left;
  end;

  function PMRight: integer; // PrimaryMonitorRight
  // return the Right pixel of the monitor that holds the upper left corner of form C
  var
    i,Primary: integer;
  begin
    Primary := -1;
    for i:=0 to Screen.MonitorCount-1 do
    begin
      if Screen.Monitors[i].Primary then Primary := i;
    end;
    if Primary >= 0 then
      result := Screen.Monitors[Primary].WorkAreaRect.Right
    else
      result := Screen.WorkAreaRect.Right;
  end;

  function PMTop: integer; // PrimaryMonitorTop
  // return the Right pixel of the monitor that holds the upper left corner of form C
  var
    i,Primary: integer;
  begin
    Primary := -1;
    for i:=0 to Screen.MonitorCount-1 do
    begin
      if Screen.Monitors[i].Primary then Primary := i;
    end;
    if Primary >= 0 then
      result := Screen.Monitors[Primary].WorkAreaRect.Top
    else
      result := Screen.WorkAreaRect.Top;
  end;

  function PMBottom: integer; // PrimaryMonitorRight
  // return the Right pixel of the monitor that holds the upper left corner of form C
  var
    i,Primary: integer;
  begin
    Primary := -1;
    for i:=0 to Screen.MonitorCount-1 do
    begin
      if Screen.Monitors[i].Primary then Primary := i;
    end;
    if Primary >= 0 then
      result := Screen.Monitors[Primary].WorkAreaRect.Bottom
    else
      result := Screen.WorkAreaRect.Bottom;
  end;

  function PMYCen: integer; // Center Y coordinate of Primary Monitor
  begin
    result := PMTop + PMHeight DIV 2;
  end;

  function PMXCen: integer; // Center X coordinate of Primary Monitor
  begin
    result := PMLeft + PMWidth DIV 2;
  end;

  procedure InsureOnScreen( C: tForm );
  // Call from OnShow event to insure that a form is displayed on the screen, not
  // occluded by the taskbars, and fully on one screen.
  //    help links:  tScreen tMonitor tApplication
  var
    Bounds: tRect; 
  begin
    if C.WindowState = wsMinimized then C.WindowState := wsNormal;
    // if only one monitor, then force window to fit on the WorkArea
    if Screen.MonitorCount = 1 then
    begin
      // Single Monitor
      Bounds := Screen.WorkAreaRect;
    end else
    begin
      // Multi Monitor
      Bounds := Screen.DesktopRect;
    end;
    // Force height onto available size
    if C.Height > (Bounds.Bottom - Bounds.Top) then
      C.Height := Bounds.Bottom - Bounds.Top;
    // Force width onto available size
    if C.Width  > (Bounds.Right - Bounds.Left) then
      C.Width  := Bounds.Right - Bounds.Left;
    // Too Low?
    if (C.Top + C.Height) > Bounds.Bottom then
      C.Top := Bounds.Bottom - C.Height;
    // Too High?
    if C.Top < Bounds.Top then
      C.Top := Bounds.Top;
    // Too far right?
    if (C.Left + C.Width) > Bounds.Right then
      C.Left := Bounds.Right - C.Width;
    // Too far left?
    if C.Left < Bounds.Left then
      C.Left := Bounds.Left;
  end;

end.
