unit my_monitor; //{$DEFINE _DEBUG} interface uses Windows, Messages, SysUtils, Classes, Controls, ExtCtrls, MultiMon, Forms; type //モニター座標 TMyMonitorPos = record MonitorNum: Integer; Position: TPoint; end; TMyScreenSize = class(TObject) private F_rcDesktopRect : TRect; //デスクトップ全体のRect F_rgDesktopRegion : HRGN; //各モニターのリージョンを足したもの F_rcMonitorsRect : array of TRect; //各モニターのRect F_hMonitorsHandle : array of HMONITOR; //各モニターのハンドル function F_GetMonitorCount : Integer; function F_GetMonitorsRect(iIndex: Integer) : TRect; function F_GetScreenLeft : Integer; function F_GetScreenTop : Integer; function F_GetScreenWidth : Integer; function F_GetScreenHeight : Integer; public constructor Create; destructor Destroy; override; procedure Reflesh; procedure SetBounds(AForm: TForm); function GetMonitorRect(AForm: TForm): TRect; function MonitorNum(hHandle: HMONITOR): Integer; function RectInDesktopRect(ARect: TRect): Boolean; property MonitorCount : Integer read F_GetMonitorCount; property DesktopRegion : HRGN read F_rgDesktopRegion; property DesktopRect : TRect read F_rcDesktopRect; property ScreenLeft : Integer read F_GetScreenLeft; property ScreenTop : Integer read F_GetScreenTop; property ScreenWidth : Integer read F_GetScreenWidth; property ScreenHeight : Integer read F_GetScreenHeight; property MonitorsRect[iIndex: Integer]: TRect read F_GetMonitorsRect; end; var MyScreenSize : TMyScreenSize; // MyCashDesktop : TMyScreenSize; function gfnrcMonitorRectGet(AScreenSize : TMyScreenSize; ptPos : TPoint) : TRect; overload; function gfnrcMonitorRectGet(ptPos : TPoint) : TRect; overload; function gfnrScreenToMonitor(AScreenSize : TMyScreenSize; ptPos: TPoint) : TMyMonitorPos; overload; function gfnrScreenToMonitor(ptPos : TPoint) : TMyMonitorPos; overload; //============================================================================== implementation uses {$IFDEF _DEBUG} myDebug, {$ENDIF} general; function gfnhMonitorFromRect(rcRect: TRect): HMONITOR; {2008-12-05: rcRectの領域があるモニターのモニターハンドルを返す。 } begin Result := MultiMon.MonitorFromRect(@rcRect, MONITOR_DEFAULTTONEAREST); end; function gfnrScreenToMonitor(AScreenSize : TMyScreenSize; ptPos: TPoint): TMyMonitorPos; {2008-07-08: スクリーン座標をモニター座標に変換して返す } var i: Integer; begin Result.MonitorNum := 0; Result.Position := Point(0, 0); for i := 0 to AScreenSize.MonitorCount -1 do begin if (PtInRect(AScreenSize.MonitorsRect[i], ptPos)) then begin Result.Position.X := ptPos.X - AScreenSize.MonitorsRect[i].Left; Result.Position.Y := ptPos.Y - AScreenSize.MonitorsRect[i].Top; Result.MonitorNum := i +1; //モニター番号なので+1; Break; end; end; end; function gfnrScreenToMonitor(ptPos: TPoint): TMyMonitorPos; begin Result := gfnrScreenToMonitor(MyScreenSize, ptPos); end; //------------------------------------------------------------------------------ { TMyScreenSize } constructor TMyScreenSize.Create; begin inherited; Reflesh; end; destructor TMyScreenSize.Destroy; begin DeleteObject(F_rgDesktopRegion); inherited; end; procedure TMyScreenSize.Reflesh; //デスクトップの大きさ(各モニターの領域の総和)とリージョンをセット。 function EnumMonitorsProc(hHandle: HMONITOR; dc: HDC; r: PRect; AScreenSize : TMyScreenSize): BOOL; stdcall; var li_Len, li_High : Integer; begin li_Len := Length(AScreenSize.F_rcMonitorsRect) +1; SetLength(AScreenSize.F_rcMonitorsRect, li_Len); li_High := High(AScreenSize.F_rcMonitorsRect); AScreenSize.F_rcMonitorsRect[li_High] := r^; SetLength(AScreenSize.F_hMonitorsHandle, li_Len); AScreenSize.F_hMonitorsHandle[li_High] := hHandle; Result := True; end; var lrc_Rect : TRect; lrg_Rgn : HRGN; i : Integer; // li_Ret : Integer; // lrc_Test : TRect; begin //FrcDesktopRectはユニットでの内グローバル変数。 F_rcDesktopRect := Rect(0, 0, 0, 0); F_rcMonitorsRect := nil; F_hMonitorsHandle := nil; DeleteObject(F_rgDesktopRegion); F_rgDesktopRegion := CreateRectRgnIndirect(Rect(0, 0, 0, 0)); EnumDisplayMonitors(0, nil, @EnumMonitorsProc, LPARAM(Self)); for i := 0 to High(F_rcMonitorsRect) do begin lrc_Rect := F_rcMonitorsRect[i]; F_rcDesktopRect.Left := gfniMin([F_rcDesktopRect.Left, lrc_Rect.Left]); F_rcDesktopRect.Top := gfniMin([F_rcDesktopRect.Top, lrc_Rect.Top]); F_rcDesktopRect.Right := gfniMax([F_rcDesktopRect.Right, lrc_Rect.Right]); F_rcDesktopRect.Bottom := gfniMax([F_rcDesktopRect.Bottom, lrc_Rect.Bottom]); lrg_Rgn := CreateRectRgnIndirect(lrc_Rect); try {li_Ret :=} CombineRgn(F_rgDesktopRegion, F_rgDesktopRegion, lrg_Rgn, RGN_OR); //myDebug.gpcDebug(['CombineRgn', li_Ret]); finally DeleteObject(lrg_Rgn); end; end; {li_Ret :=} OffsetRgn(F_rgDesktopRegion, -F_rcDesktopRect.Left, -F_rcDesktopRect.Top); //myDebug.gpcDebug(['OffsetRgn', li_Ret]); //li_Ret := GetRgnBox(F_rgDesktopRegion, lrc_Test); //myDebug.gpcDebug(['GetRgnBox', gfnsRectString(lrc_Test)]); end; procedure TMyScreenSize.SetBounds(AForm : TForm); begin if not(RectInRegion(F_rgDesktopRegion, gfnrcRectShift(AForm.BoundsRect, Point(-F_rcDesktopRect.Left, -F_rcDesktopRect.Top)))) then begin SetWindowPos(AForm.Handle, 0, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOZORDER or SWP_NOACTIVATE); end; end; function TMyScreenSize.GetMonitorRect(AForm : TForm) : TRect; var lh_Handle : HMONITOR; i : Integer; begin lh_Handle := gfnhMonitorFromRect(AForm.BoundsRect); for i := 0 to F_GetMonitorCount -1 do begin if (F_hMonitorsHandle[i] = lh_Handle) then begin Result := F_rcMonitorsRect[i]; Exit; end; end; Result := Rect(0, 0, 0, 0); end; function TMyScreenSize.MonitorNum(hHandle : HMONITOR) : Integer; var i : Integer; begin for i := 0 to F_GetMonitorCount -1 do begin if (F_hMonitorsHandle[i] = hHandle) then begin Result := i +1; //モニター番号なので+1 Exit; end; end; Result := -1; end; function TMyScreenSize.F_GetMonitorCount : Integer; begin Result := Length(F_rcMonitorsRect); end; function TMyScreenSize.F_GetMonitorsRect(iIndex : Integer) : TRect; //iIndexは0ベース。 //1ベースのモニター番号ではないことに注意。 begin Result := Rect(0, 0, 0, 0); if (iIndex < 0) or (iIndex >= F_GetMonitorCount) then begin Exit; end; Result := F_rcMonitorsRect[iIndex]; end; function TMyScreenSize.RectInDesktopRect(ARect: TRect): Boolean; var i : Integer; begin for i := 0 to F_GetMonitorCount -1 do begin if (gfnbRectInRect(ARect, F_GetMonitorsRect(i))) then begin Result := True; Exit; end; end; Result := False; end; function TMyScreenSize.F_GetScreenLeft : Integer; begin Result := F_rcDesktopRect.Left; end; function TMyScreenSize.F_GetScreenTop : Integer; begin Result := F_rcDesktopRect.Top; end; function TMyScreenSize.F_GetScreenWidth : Integer; begin Result := gfniRectWidth(F_rcDesktopRect); end; function TMyScreenSize.F_GetScreenHeight : Integer; begin Result := gfniRectHeight(F_rcDesktopRect); end; //------------------------------------------------------------------------------ function gfnrcMonitorRectGet(AScreenSize : TMyScreenSize; ptPos: TPoint): TRect; //モニター var i : Integer; lrc_Rect : TRect; begin for i := 0 to AScreenSize.MonitorCount -1 do begin lrc_Rect := AScreenSize.MonitorsRect[i]; if (PtInRect(lrc_Rect, ptPos)) then begin Result := lrc_Rect; Exit; end; end; Result := Rect(0, 0, 0, 0); //範囲外だった end; function gfnrcMonitorRectGet(ptPos: TPoint): TRect; begin Result := gfnrcMonitorRectGet(MyScreenSize, ptPos); end; //------------------------------------------------------------------------------ initialization MyScreenSize := TMyScreenSize.Create; // MyCashDesktop := TMyScreenSize.Create; finalization MyScreenSize.Free; MyScreenSize := nil; // MyCashDesktop.Free; // MyCashDesktop := nil; end.