unit my_monitor; interface uses Windows, Messages, SysUtils, Classes, Controls, Forms, MultiMon; //モニター --------------------------------------------------------------------- type TMyMonitorItem = class(TObject) private F_hHandle: HMONITOR; function F_GetLeft: Integer; function F_GetTop: Integer; function F_GetWidth: Integer; function F_GetHeight: Integer; function F_GetBoundsRect: TRect; function F_GetWorkareaLeft: Integer; function F_GetWorkareaTop: Integer; function F_GetWorkareaWidth: Integer; function F_GetWorkareaHeight: Integer; function F_GetWorkareaRect: TRect; function F_GetPrimary: Boolean; public constructor Create(hHandle: HMONITOR); destructor Destroy; override; property Handle: HMONITOR read F_hHandle; property Left: Integer read F_GetLeft; property Top: Integer read F_GetTop; property Height: Integer read F_GetHeight; property Width: Integer read F_GetWidth; property BoundsRect: TRect read F_GetBoundsRect; property WorkareaLeft: Integer read F_GetWorkareaLeft; property WorkareaTop: Integer read F_GetWorkareaTop; property WorkareaHeight: Integer read F_GetWorkareaHeight; property WorkareaWidth: Integer read F_GetWorkareaWidth; property WorkareaRect: TRect read F_GetWorkareaRect; property Primary: Boolean read F_GetPrimary; end; TMyMonitors = class(TObject) private F_MonitorList: array of TMyMonitorItem; F_iDesktopRegionCode: Integer; F_rgDesktopRegion: HRGN; //デスクトップのウィンドウリージョン。マルチモニタ時に点やRectがマルチモニタ内に収まっているかの判定用。 function Get(iIndex: Integer): TMyMonitorItem; procedure Put(iIndex: Integer; AMyMonitorItem: TMyMonitorItem); function F_GetCount: Integer; function F_GetPrimaryIndex: Integer; procedure F_ClearItems; procedure F_GetItems; function F_GetScreenLeft: Integer; function F_GetScreenTop: Integer; function F_GetScreenWidth: Integer; function F_GetScreenHeight: Integer; function F_GetScreenBoundsRect: TRect; public constructor Create; destructor Destroy; override; procedure Reflesh; procedure SetBounds(Form: TForm); reintroduce; overload; procedure SetBounds(Form: TForm; rcRect: TRect); reintroduce; overload; procedure SetBounds(Form: TForm; iLeft, iTop, iWidth, iHeight: Integer); reintroduce; overload; function MonitorIndex(hHandle: HMONITOR): Integer; overload; function MonitorIndex(hHandle: HWND): Integer; overload; function MonitorIndex(rcRect: TRect): Integer; overload; function MonitorIndex(ptPos: TPoint): Integer; overload; function MonitorNum (hHandle: HMONITOR): Integer; overload; function MonitorNum (hHandle: HWND): Integer; overload; 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 ScreenBoundsRect: TRect read F_GetScreenBoundsRect; property Count: Integer read F_GetCount; property DesktopRegionCode: Integer read F_iDesktopRegionCode; property DesktopRegion: HRGN read F_rgDesktopRegion; property MonitorCount: Integer read F_GetCount; property PrimaryIndex: Integer read F_GetPrimaryIndex; property Monitors[Index: Integer]: TMyMonitorItem read Get write Put; default; property Items[Index: Integer]: TMyMonitorItem read Get; end; type //モニター座標 TMyMonitorPos = record MonitorNum: Integer; Position: TPoint; end; function gfniMonitorCountGet: Integer; function gfnbGetMonitorInfo (hHandle: HMONITOR; var rInfo: TMonitorInfo): Boolean; function gfnhMonitorFromWindow(hHandle: HWND): HMONITOR; function gfnhMonitorFromRect (rcRect: TRect): HMONITOR; function gfnrMonitorInfoGet (hHandle: HMONITOR): TMonitorInfo; function gfnrcMonitorRectGet (hHandle: HMONITOR): TRect; function gfnrScreenToMonitor (ptPos: TPoint): TMyMonitorPos; //function gfnhMonitorGet (hHandle: HWND): HMonitor; function gfnrcMonitorWorkAreaRectGet(hHandle: HMONITOR): TRect; overload; function gfnrcMonitorWorkAreaRectGet(hHandle: HWND): TRect; overload; function gfnrcMonitorWorkAreaRectGet(rcRect: TRect): TRect; overload; function gfnrcMonitorWorkAreaRectGet(ptPos: TPoint): TRect; overload; var MyMonitors: TMyMonitors = nil; //============================================================================== implementation uses // myDebug, general; //モニター --------------------------------------------------------------------- {TMyMonitoItem} constructor TMyMonitorItem.Create(hHandle: HMONITOR); begin inherited Create; F_hHandle := hHandle; end; destructor TMyMonitorItem.Destroy; begin F_hHandle := 0; inherited; end; function TMyMonitorItem.F_GetLeft: Integer; begin Result := F_GetBoundsRect.Left; end; function TMyMonitorItem.F_GetTop: Integer; begin Result := F_GetBoundsRect.Top; end; function TMyMonitorItem.F_GetWidth: Integer; begin Result := gfniRectWidth(F_GetBoundsRect); end; function TMyMonitorItem.F_GetHeight: Integer; //2009-05-29:gfniRectWidthとしていた間違いを修正 begin Result := gfniRectHeight(F_GetBoundsRect); end; function TMyMonitorItem.F_GetBoundsRect: TRect; var lr_Info: TMonitorInfo; begin gfnbGetMonitorInfo(F_hHandle, lr_Info); Result := lr_Info.rcMonitor; end; function TMyMonitorItem.F_GetWorkareaLeft: Integer; begin Result := WorkareaRect.Left; end; function TMyMonitorItem.F_GetWorkareaTop: Integer; begin Result := WorkareaRect.Top; end; function TMyMonitorItem.F_GetWorkareaWidth: Integer; begin Result := gfniRectWidth(WorkareaRect); end; function TMyMonitorItem.F_GetWorkareaHeight: Integer; begin Result := gfniRectHeight(WorkareaRect); end; function TMyMonitorItem.F_GetWorkareaRect: TRect; var lr_Info: TMonitorInfo; begin gfnbGetMonitorInfo(F_hHandle, lr_Info); Result := lr_Info.rcWork; end; function TMyMonitorItem.F_GetPrimary: Boolean; begin Result := (F_GetLeft = 0) and (F_GetTop = 0); end; //------------------------------------------------------------------------------ {TMyMonitors} constructor TMyMonitors.Create; begin inherited; F_GetItems; end; destructor TMyMonitors.Destroy; begin F_ClearItems; F_MonitorList := nil; inherited; end; procedure TMyMonitors.F_ClearItems; var i: Integer; begin for i := 0 to High(F_MonitorList) do begin F_MonitorList[i].Free; end; F_MonitorList := nil; DeleteObject(F_rgDesktopRegion); end; function lfnbEnumMonitorsProc(hHandle: HMONITOR; dc: HDC; r: PRect; AMyMonitors: TMyMonitors): BOOL; stdcall; var l_Monitor: TMyMonitorItem; i: Integer; begin l_Monitor := TMyMonitorItem.Create(hHandle); for i := 0 to AMyMonitors.Count-1 do begin if (AMyMonitors.Monitors[i] = nil) then begin AMyMonitors.Monitors[i] := l_Monitor; Break; end; end; Result := True; end; procedure TMyMonitors.F_GetItems; var i: Integer; lrg_Rgn: HRGN; begin SetLength(F_MonitorList, gfniMonitorCountGet); for i := 0 to High(F_MonitorList) do begin F_MonitorList[i] := nil; end; EnumDisplayMonitors(0, nil, @lfnbEnumMonitorsProc, Longint(Self)); F_rgDesktopRegion := CreateRectRgnIndirect(Get(0).BoundsRect); for i := 1 to Count-1 do begin lrg_Rgn := CreateRectRgnIndirect(Get(i).BoundsRect); F_iDesktopRegionCode := CombineRgn(F_rgDesktopRegion, F_rgDesktopRegion, lrg_Rgn, RGN_OR); DeleteObject(lrg_Rgn); end; end; function TMyMonitors.Get(iIndex: Integer): TMyMonitorItem; begin iIndex := gfniNumLimit(iIndex, 0, F_GetCount -1); Result := F_MonitorList[iIndex]; end; procedure TMyMonitors.Put(iIndex: Integer; AMyMonitorItem: TMyMonitorItem); begin iIndex := gfniNumLimit(iIndex, 0, F_GetCount -1); F_MonitorList[iIndex] := AMyMonitorItem; end; function TMyMonitors.F_GetCount: Integer; begin Result := High(F_MonitorList) +1; end; procedure TMyMonitors.Reflesh; begin F_ClearItems; F_GetItems; end; //スクリーン(マルチモニター全体)の大きさを返す function TMyMonitors.F_GetScreenBoundsRect: TRect; var i: Integer; begin Reflesh; Result := Rect(0, 0, 0, 0); for i := 0 to F_GetCount -1 do begin if (Get(i).Left < Result.Left) then Result.Left := Get(i).Left; if (Get(i).Top < Result.Top) then Result.Top := Get(i).Top; if (Get(i).BoundsRect.Right > Result.Right) then Result.Right := Get(i).BoundsRect.Right; if (Get(i).BoundsRect.Bottom > Result.Bottom) then Result.Bottom := Get(i).BoundsRect.Bottom; end; end; function TMyMonitors.F_GetScreenLeft: Integer; var lrc_Rect: TRect; begin lrc_Rect := F_GetScreenBoundsRect; Result := lrc_Rect.Left; end; function TMyMonitors.F_GetScreenTop: Integer; var lrc_Rect: TRect; begin lrc_Rect := F_GetScreenBoundsRect; Result := lrc_Rect.Top; end; function TMyMonitors.F_GetScreenWidth: Integer; var lrc_Rect: TRect; begin lrc_Rect := F_GetScreenBoundsRect; Result := gfniRectWidth(lrc_Rect); end; function TMyMonitors.F_GetScreenHeight: Integer; var lrc_Rect: TRect; begin lrc_Rect := F_GetScreenBoundsRect; Result := gfniRectHeight(lrc_Rect); end; //モニター画面内に収まるようなSetBounds procedure TMyMonitors.SetBounds(Form: TForm); begin SetBounds(Form, Form.Left, Form.Top, Form.Width, Form.Height); end; procedure TMyMonitors.SetBounds(Form: TForm; rcRect: TRect); begin SetBounds(Form, rcRect.Left, rcRect.Top, gfniRectWidth(rcRect), gfniRectHeight(rcRect)); end; procedure TMyMonitors.SetBounds(Form: TForm; iLeft, iTop, iWidth, iHeight: Integer); var li_Index: Integer; l_MonitorItem: TMyMonitorItem; // li_Left, li_Top: Integer; begin li_Index := MonitorIndex(Rect(iLeft, iTop, iWidth, iHeight)); if (li_Index < 0) then li_Index := 0; //AIU l_MonitorItem := F_MonitorList[li_Index]; // li_Left := gfniNumLimit(iLeft, l_MonitorItem.WorkareaLeft, l_MonitorItem.WorkareaLeft + l_MonitorItem.WorkareaWidth - iWidth); // li_Top := gfniNumLimit(iTop, l_MonitorItem.WorkareaTop, l_MonitorItem.WorkareaTop + l_MonitorItem.WorkareaHeight - iHeight); Form.SetBounds( gfniNumLimit(iLeft, l_MonitorItem.WorkareaLeft, l_MonitorItem.WorkareaLeft + l_MonitorItem.WorkareaWidth - iWidth), gfniNumLimit(iTop, l_MonitorItem.WorkareaTop, l_MonitorItem.WorkareaTop + l_MonitorItem.WorkareaHeight - iHeight), iWidth, iHeight ); end; function TMyMonitors.F_GetPrimaryIndex: Integer; //プライマリーモニターの0ベースのインデックスを返す。 begin for Result := 0 to High(F_MonitorList) do begin if (F_MonitorList[Result].Primary) then begin Exit; end; end; Result := -1; end; function TMyMonitors.MonitorIndex(hHandle: HMONITOR): Integer; {2008-12-04: 0ベースのモニターのインデックスを返す。 } var i: Integer; begin Result := -1; if (hHandle <> 0) then begin for i := 0 to High(F_MonitorList) do begin if (F_MonitorList[i].Handle = hHandle) then begin Result := i; end; end; end; end; function TMyMonitors.MonitorIndex(hHandle: HWND): Integer; {2008-12-04: 0ベースのモニターのインデックスを返す。 } begin Result := MonitorIndex(gfnhMonitorFromWindow(hHandle)); end; function TMyMonitors.MonitorIndex(rcRect: TRect): Integer; {2008-12-05: 0ベースのモニターのインデックスを返す。 } begin Result := MonitorIndex(gfnhMonitorFromRect(rcRect)); end; function TMyMonitors.MonitorIndex(ptPos: TPoint): Integer; {2008-12-05: 0ベースのモニターのインデックスを返す。 } begin Result := MonitorIndex(Rect(ptPos.X, ptPos.Y, ptPos.X, ptPos.Y)); end; //モニター番号を返す function TMyMonitors.MonitorNum(hHandle: HMONITOR): Integer; begin Result := MonitorIndex(hHandle) + 1; end; function TMyMonitors.MonitorNum(hHandle: HWND): Integer; begin Result := MonitorNum(gfnhMonitorFromWindow(hHandle)); end; //------------------------------------------------------------------------------ //function gfnhMonitorGet(const hHandle: HWND): HMonitor; {2008-12-02: ウィンドウのあるモニターのモニターハンドルを返す。 } //begin // Result := MonitorFromWindow(hHandle, MONITOR_DEFAULTTONEAREST); //end; function gfnrcMonitorWorkAreaRectGet(hHandle: HMONITOR): TRect; {2008-12-02: モニターのワークエリアを返す。 } var lr_Info: TMonitorInfo; begin lr_Info.cbSize := SizeOf(lr_Info); GetMonitorInfo(hHandle, @lr_Info); Result := lr_Info.rcWork; end; function gfnrcMonitorWorkAreaRectGet(hHandle: HWND): TRect; {2008-12-02: ウィンドウのあるモニターのワークエリアを返す。 } begin Result := gfnrcMonitorWorkAreaRectGet(gfnhMonitorFromWindow(hHandle)); end; function gfnrcMonitorWorkAreaRectGet(rcRect: TRect): TRect; {2009-01-28: rcRectの領域のあるモニターのワークエリアを返す。 } begin Result := gfnrcMonitorWorkAreaRectGet(gfnhMonitorFromRect(rcRect)); end; function gfnrcMonitorWorkAreaRectGet(ptPos: TPoint): TRect; {2009-01-28: ptPos上のモニターのワークエリアを返す。 } begin Result := gfnrcMonitorWorkAreaRectGet(Rect(ptPos.X, ptPos.Y, ptPos.X, ptPos.Y)); end; function gfniMonitorCountGet: Integer; {2008-12-02: モニターの数を返す。 } begin Result := GetSystemMetrics(SM_CMONITORS); end; function gfnhMonitorFromWindow(hHandle: HWND): HMONITOR; {2008-12-02: hHandleのウィンドウがあるモニターのモニターハンドルを返す。 } begin Result := MultiMon.MonitorFromWindow(hHandle, MONITOR_DEFAULTTONEAREST); end; function gfnhMonitorFromRect(rcRect: TRect): HMONITOR; {2008-12-05: rcRectの領域があるモニターのモニターハンドルを返す。 } begin Result := MultiMon.MonitorFromRect(@rcRect, MONITOR_DEFAULTTONEAREST); end; function gfnbGetMonitorInfo(hHandle: HMONITOR; var rInfo: TMonitorInfo): Boolean; {2008-12-02: モニター情報を取得して成功ならTrueを返す。 } begin //初期化する FillChar(rInfo, SizeOf(rInfo), 0); if (hHandle <> 0) then begin rInfo.cbSize := SizeOf(rInfo); Result := MultiMon.GetMonitorInfo(hHandle, @rInfo); end else begin Result := False; end; end; function gfnrMonitorInfoGet(hHandle: HMONITOR): TMonitorInfo; {2008-12-02: モニター情報を返す。 } begin gfnbGetMonitorInfo(hHandle, Result); end; function gfnrcMonitorRectGet(hHandle: HMONITOR): TRect; {2008-12-02: モニターのRectを返す。 } var lr_Info: TMonitorInfo; begin Result := Rect(0, 0, 0, 0); if (hHandle <> 0) then begin FillChar(lr_Info, SizeOf(lr_Info), 0); lr_Info.cbSize := SizeOf(lr_Info); if (MultiMon.GetMonitorInfo(hHandle, @lr_Info)) then begin; Result := lr_Info.rcMonitor; end; end; { Result := Rect(0, 0, 0, 0); if (hHandle <> 0) then begin GetMem(lp_Info, SizeOf(lp_Info^)); try FillChar(lp_Info^, SizeOf(lp_Info^), 0); lp_Info.cbSize := SizeOf(lp_Info^); if (MultiMon.GetMonitorInfo(hHandle, lp_Info)) then begin; Result := lp_Info.rcMonitor; end; finally FreeMem(lp_Info); end; end; } end; //モニター座標 function gfnrScreenToMonitor(ptPos: TPoint): TMyMonitorPos; {2008-07-08: スクリーン座標をモニター座標に変換して返す } var i: Integer; l_Mon: TMyMonitors; begin Result.MonitorNum := 0; Result.Position := Point(0, 0); l_Mon := TMyMonitors.Create; try for i := 0 to l_Mon.MonitorCount -1 do begin if (PtInRect(l_Mon.Monitors[i].BoundsRect, ptPos)) then begin Result.Position.X := ptPos.X - l_Mon.Monitors[i].Left; Result.Position.Y := ptPos.Y - l_Mon.Monitors[i].Top; Result.MonitorNum := i + 1;; Break; end; end; finally l_Mon.Free; end; end; //------------------------------------------------------------------------------ initialization if (MyMonitors = nil) then begin MyMonitors := TMyMonitors.Create; end; finalization if (MyMonitors <> nil) then begin MyMonitors.Free; //MyMonitors := nil; end; end.