- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2022-10-25T12:12:26+09:00","default:ahyahya2","ahyahya2")
[[戻る>DoldoWorkz#delphi]]
*Delphiでウインドウの最大化時の大きさをコントロール(マルチモニタ対応) [#b6d19f99]
#hr
#contents
#hr
**参考にした情報 [#j0a87610]
この内容はDelphi-ML「[Delphi:90115] ウインドウを最大化したまま最大化サイズを調節する」で付いたレスを参考にしています。
教えてくださる皆様、感謝感謝です。
**GetMonitorInfoでモニタに関する情報を取得する [#q67f6944]
-[[MSDN Japan-GetMonitorInfo:http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/jpgdi/html/_win32_GetMonitorInfo.asp]]~
GetMonitorInfoの情報があります。~
-[[MONITORINFO構造体-WinAPI Database for VB Programmer:http://www.winapi-database.com/Struct/MONITORINFO.html]]~
MONITORINFO 構造体の情報があります。~
モニタの範囲を知るためにはWindows APIの「GetMonitorInfo」を使う。~
このAPIはマルチモニタ対応のAPIで、ディスプレイモニタのハンドルを渡してあげる事によって、そのディスプレイモニタに関する情報を取得する事が出来ます。~
~
情報はMONITORINFO 構造体によって返され、以下のような情報が帰ってきます。~
~
-&color(red){''モニタ全体の範囲''};~
|MonitorInfo.rcMonitor.Bottom|範囲の下側Y座標|
|MonitorInfo.rcMonitor.Top|範囲の上側Y座標|
|MonitorInfo.rcMonitor.Left|範囲の左側X座標|
|MonitorInfo.rcMonitor.Right|範囲の右側X座標|
~
-&color(Green){''モニタ有効面の範囲''};~
|MonitorInfo.rcWork.Bottom|範囲の下側Y座標|
|MonitorInfo.rcWork.Top|範囲の上側Y座標|
|MonitorInfo.rcWork.Left|範囲の左側X座標|
|MonitorInfo.rcWork.Right|範囲の右側X座標|
~
以下の例では赤い四角がモニタの範囲、緑色の範囲がモニタの有効面の範囲になってます。~
タスクバーの分が有効面から除外されていますが、これは~
ウインドウを最大化したときに使える範囲=有効面だからです。~
※「タスクバーを自動的に隠す」をしていない例です~
他のソフトで、デスクトップを占有するタイプのアプリケーションがある場合はその分も有効面から除外されます~
#ref(Monitor1_Bottom.jpg,around)
#ref(Monitor1_Top.jpg)
#img(,clear)
#clear
~
#ref(Monitor1_Left.jpg,around)
#ref(Monitor1_Right.jpg)
#img(,clear)
#clear
~
取得出来る値は、&color(red){''プライマリモニタの左上を原点''};として数値が決まります。~
2台目以降のモニタの位置はある程度好きなように置ける様です。~
#ref(Monitor2.jpg)
※ぜんぜん関係ない話ですが、上の図はExcelで作っている物を、セル範囲のコピーってそのままペイント等に画像として貼り付けしてます。~
知らなかったです…なんとなく「出来るかな?」と思ってやって出来てびっくり。~
~
Delphiのコードだとこんな感じです
var
FMonitorInfo: TMonitorInfo;
begin
ZeroMemory(@FMonitorInfo, sizeof(FMonitorInfo));
FMonitorInfo.cbSize := SizeOf(FMonitorInfo);
GetMonitorInfo(FTargetForm.Monitor.Handle, @FMonitorInfo);
**WMGetMinMaxInfoメッセージ [#dc8f5264]
最大化の時に、フォームの大きさと位置の制限をするにはWMGetMinMaxInfoメッセージを使います
procedure WMGetMinMaxInfo(var msg : TWMGetMinMaxInfo); message WM_GETMINMAXINFO;
~
設定できる値は、以下の通りです。
|msg.MinMaxInfo.ptMaxPosition.X|フォームの左上のX座標を指定します|
|msg.MinMaxInfo.ptMaxPosition.Y|フォームの左上のY座標を指定します|
|msg.MinMaxInfo.ptMaxSize.X|フォームの横幅を指定します|
|msg.MinMaxInfo.ptMaxSize.Y|フォームの縦幅を指定します|
~
「msg.MinMaxInfo.ptMaxPosition.X」「msg.MinMaxInfo.ptMaxPosition.Y」は&color(red){''各種モニタの左上を原点''};として数値が決まります。~
#ref(Monitor3.jpg)
さらに、フォームのBorderStyleによって、原点位置が変わります
|BGCOLOR(YELLOW):BorderStyle|BGCOLOR(YELLOW):座標の原点|
|bsDialog|モニタ全体の範囲から(0,0)|
|bsNone|モニタ全体の範囲から(0,0)|
|bsSingle|BGCOLOR(#FFA0A0):モニタ有効面の範囲から(0,0)|
|bsSizeable|BGCOLOR(#FFA0A0):モニタ有効面の範囲から(0,0)|
|bsSizeToolWin|モニタ全体の範囲から(0,0)|
|bsToolWindow|モニタ全体の範囲から(0,0)|
※2009/5/7の時点では「2000・XP」と「Vista・7」では原点位置が変わる様に書いていたのですが、いつの間にか「2000・XP」と同じ動作になる様に「Vista・7」が修正された様です。~
**作ってみたコード [#o031755d]
マルチディスプレイ対応です。~
この内容はDelphi-ML「[Delphi:90115] ウインドウを最大化したまま最大化サイズを調節する」で付いたレスを参考にしています。~
教えてくださる皆様、感謝感謝です。~
&color(red){''2008/1/24修正''}; ウインドウがbsSizeable・bsSingle以外のモードの場合が動きおかしかったのを修正~
&color(red){''2009/5/7修正''}; WMGetMinMaxInfo2関数で、ちらつきを抑えつつ変更されるように作っていましたが、~
色々な場面(OS・フォームBorderStyle・OSテーマ対応)で動作が不安定なので断念…~
&color(red){''2010/9/17修正''}; Vista・7だけ動作が違っていた部分があったが、いつの間にか修正されていた様なので2000・XPと同じ動作をする様に修正する
ダウンロード
#ref(MultiMonitorParam100917.zip)
[[&ref(http://i.creativecommons.org/l/by/2.1/jp/80x15.png);>http://creativecommons.org/licenses/by/2.1/jp/]]
この作品は[[クリエイティブ・コモンズ・ライセンス>http://creativecommons.org/licenses/by/2.1/jp/]]の下でライセンスされています。
{*****************************************************************************}
{ }
{ MultiMonitorParam }
{ }
{ Copyright (c) 2007 Moon Doldo }
{ }
{この内容はDelphi-ML }
{[Delphi:90115] ウインドウを最大化したまま最大化サイズを調節する }
{で付いたレスを参考にしています。 }
{ }
{*****************************************************************************}
unit MultiMonitorParam;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Math, MultiMon, UxTheme;
type
// TargetFormが指定されていないか存在しないエラー
ETargetFormIsNotFound = class(Exception);
// MonitorInfo保持クラス
TMonitorInfoParam = class(TComponent)
private
FMonitorInfo : TMonitorInfo;
FDisplayMonitorInfo: TMonitorInfo;
FTargetForm: TForm;
procedure SetTargetForm(const Value: TForm);
protected
// MonitorInfoの取得
procedure GetMonitorInfoParam;
public
//TComponent等 Owner付コンストラクタ定義
constructor Create(AOwner: TComponent); override;
// ディスプレイモニタに関する情報を取得
// プライマリモニタの左上を原点(0,0)として座標値を返す
function MonitorInfo: TMonitorInfo;
// ディスプレイモニタに関する情報を取得
// 各モニタの左上を原点(0,0)として座標値を返す
function DisplayMonitorInfo: TMonitorInfo;
// モニタの数を取得
function MonitorCount: Integer;
// モニタ番号の取得
function MonitorNum: Integer;
published
// 対象のウインドウを設定
property TargetForm: TForm read FTargetForm write SetTargetForm;
end;
// 最大化の管理クラス
TMultiMonitorMaxInfoCalc = class(TMonitorInfoParam)
private
FMaxSizeY: Integer;
FMaxSizeX: Integer;
FMaxPositionY: Integer;
FMaxPositionX: Integer;
FMaxAlign: TAlign;
procedure SetMaxSizeX(const Value: Integer);
procedure SetMaxSizeY(const Value: Integer);
procedure SetMaxPositionX(const Value: Integer);
procedure SetMaxPositionY(const Value: Integer);
procedure SetMaxAlign(const Value: TAlign);
protected
// フォームの大きさと位置の制限(WMGetMinMaxInfo)
procedure WMNoneGetMinMaxInfo(var msg : TWMGetMinMaxInfo);
procedure WMClientGetMinMaxInfo(var msg : TWMGetMinMaxInfo);
procedure WMCustomGetMinMaxInfo(var msg : TWMGetMinMaxInfo);
procedure WMTopGetMinMaxInfo(var msg : TWMGetMinMaxInfo);
procedure WMBottomGetMinMaxInfo(var msg : TWMGetMinMaxInfo);
procedure WMLeftGetMinMaxInfo(var msg : TWMGetMinMaxInfo);
procedure WMRightGetMinMaxInfo(var msg : TWMGetMinMaxInfo);
public
//TComponent等 Owner付コンストラクタ定義
constructor Create(AOwner: TComponent); override;
//デストラクタ定義
destructor Destroy; override;
// フォームの大きさと位置の制限
procedure WMGetMinMaxInfo(var msg : TWMGetMinMaxInfo);
// フォームの大きさと位置の制限(既に最大化している場合)
procedure WMGetMinMaxInfo2;
// 通常の状態のフォームを適切な位置へ移動する
procedure SetFormSafePosition;
published
// 設定したいウインドウサイズを指定する
// alLeft, alRight, alCustomの場合のみ実行される
property MaxSizeX: Integer read FMaxSizeX write SetMaxSizeX;
// alTop, alBottom, alCustomの場合のみ実行される
property MaxSizeY: Integer read FMaxSizeY write SetMaxSizeY;
// 設定したい位置を指定する(各種モニタの有効面の左上を原点(0,0))
// alCustomの場合のみ実行される
property MaxPositionX: Integer read FMaxPositionX write SetMaxPositionX;
property MaxPositionY: Integer read FMaxPositionY write SetMaxPositionY;
// 最大化の際に、モニタ内でコントロールを揃える方法を指定します。
property MaxAlign: TAlign read FMaxAlign write SetMaxAlign;
end;
// ウインドウハンドルからモニタ番号の取得
function GetHWNDToMonitorNum(hWnd: HWND): Integer;
// Windows XP/Server2003で
// なおかつ「Windows XP スタイル」が設定されているかチェック
function isWindowsXPUseThemes: Boolean;
implementation
function GetHWNDToMonitorNum(hWnd: HWND): Integer;
var
wHMonitor: HMonitor;
wHMonitorIndex: Integer;
wMonitor: TMonitor;
begin
Result := -1;
wHMonitor := MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
for wHMonitorIndex := 0 to Screen.MonitorCount - 1 do
begin
if Screen.Monitors[wHMonitorIndex].Handle = wHMonitor then
begin
wMonitor := Screen.Monitors[wHMonitorIndex];
result := wMonitor.MonitorNum;
Exit;
end;
end;
end;
function isWindowsXPUseThemes: Boolean;
var
WkMajor, WkMinor: LongInt;
WkInfo: TOSVersionInfo;
begin
WkInfo.dwOSVersionInfoSize := SizeOf(WkInfo);
GetVersionEx(WkInfo);
WkMajor := WkInfo.dwMajorVersion ;
WkMinor := WkInfo.dwMinorVersion ;
// dwMajorVersionが5は2000・XP・Server2003
if WkMajor = 5 then
begin
// dwMinorVersionが1はXP
// dwMinorVersionが2はServer2003
if (WkMinor = 1) or (WkMinor = 2) then
begin
// UxThemeのUseThemesは
// OSがテーマ対応かクラシックモードかを判別する
// アプリケーションは関係なし
result := UseThemes;
end
else begin
result := False;
end;
end
else begin
result := False;
end;
end;
{ TMultiMonitorMaxInfoCalc }
constructor TMultiMonitorMaxInfoCalc.Create(AOwner: TComponent);
begin
inherited; //上位のクリエイトを呼び出す(Create表記を省略)
//↓Createを呼出し後に別の処理を書くのが一般的
FMaxAlign := alCustom;
FMaxSizeY := 0;
FMaxSizeX := 0;
FMaxPositionY := 0;
FMaxPositionX := 0;
end;
destructor TMultiMonitorMaxInfoCalc.Destroy;
begin
inherited;
end;
procedure TMultiMonitorMaxInfoCalc.SetFormSafePosition;
var
WkMonitorInfo : TMonitorInfo;
WkMonitorInfoWidth, WkMonitorInfoHeight: Integer;
WkTargetFormRight, WkTargetFormBottom: Integer;
WkLeft, WkTop: Integer;
begin
// ウインドウが存在しない場合は例外を発生させる
if FTargetForm = nil then
begin
raise ETargetFormIsNotFound.Create('TargetFormが指定されていません');
end;
if IsWindow(FTargetForm.Handle) = False then
begin
raise ETargetFormIsNotFound.Create('TargetFormで指定したフォームが存在されていません');
end;
if FTargetForm.WindowState = wsNormal then
begin
// ディスプレイモニタに関する情報を取得
WkMonitorInfo := Self.MonitorInfo;
WkLeft := FTargetForm.Left;
WkTop := FTargetForm.Top;
// 左上が有効面からはみ出ていたら直す
if WkLeft < WkMonitorInfo.rcWork.Left then
begin
WkLeft := WkMonitorInfo.rcWork.Left;
end;
if WkTop < WkMonitorInfo.rcWork.Top then
begin
WkTop := WkMonitorInfo.rcWork.Top;
end;
// 右下が有効面からはみ出ていたら直す
// ただし、有効面のよりフォームが小さい場合のみ行う(左上を優先にするため)
WkMonitorInfoWidth :=
WkMonitorInfo.rcWork.Right - WkMonitorInfo.rcWork.Left;
if FTargetForm.Width <= WkMonitorInfoWidth then
begin
WkTargetFormRight := WkLeft + FTargetForm.Width;
if WkTargetFormRight > WkMonitorInfo.rcWork.Right then
begin
WkLeft := WkMonitorInfo.rcWork.Right - FTargetForm.Width;
end;
end;
WkMonitorInfoHeight :=
WkMonitorInfo.rcWork.Bottom - WkMonitorInfo.rcWork.Top;
if FTargetForm.Height <= WkMonitorInfoHeight then
begin
WkTargetFormBottom := WkTop + FTargetForm.Height;
if WkTargetFormBottom > WkMonitorInfo.rcWork.Bottom then
begin
WkTop := WkMonitorInfo.rcWork.Bottom - FTargetForm.Height;
end;
end;
FTargetForm.Left := WkLeft;
FTargetForm.Top := WkTop;
end;
end;
procedure TMultiMonitorMaxInfoCalc.SetMaxAlign(const Value: TAlign);
begin
FMaxAlign := Value;
WMGetMinMaxInfo2;
end;
procedure TMultiMonitorMaxInfoCalc.SetMaxPositionX(const Value: Integer);
begin
FMaxPositionX := Value;
end;
procedure TMultiMonitorMaxInfoCalc.SetMaxPositionY(const Value: Integer);
begin
FMaxPositionY := Value;
end;
procedure TMultiMonitorMaxInfoCalc.SetMaxSizeX(const Value: Integer);
begin
FMaxSizeX := Value;
end;
procedure TMultiMonitorMaxInfoCalc.SetMaxSizeY(const Value: Integer);
begin
FMaxSizeY := Value;
end;
procedure TMultiMonitorMaxInfoCalc.WMBottomGetMinMaxInfo(
var msg: TWMGetMinMaxInfo);
var
WkMonitorInfo : TMonitorInfo;
WkPositionX, WkPositionY: Integer;
WkBoundaryX, WkBoundaryY: Integer;
begin
// ディスプレイモニタに関する情報を取得
// プライマリモニタの左上を原点(0,0)とした値が帰ってくる
WkMonitorInfo := Self.MonitorInfo;
// フォームのサイズをmsg.MinMaxInfo.ptMaxSizeに指定
msg.MinMaxInfo.ptMaxSize.X :=
WkMonitorInfo.rcWork.Right - WkMonitorInfo.rcWork.Left;
msg.MinMaxInfo.ptMaxSize.Y :=
Min(FMaxSizeY,
WkMonitorInfo.rcWork.Bottom - WkMonitorInfo.rcWork.Top);
// フォームの位置を保持
WkPositionX := WkMonitorInfo.rcWork.Left;
WkPositionY := WkMonitorInfo.rcWork.Bottom - msg.MinMaxInfo.ptMaxSize.Y;
// フォームの位置をmsg.MinMaxInfo.ptMaxPositionに指定
// msg.MinMaxInfo.ptMaxPositionは
// BorderStyleがbsSizeableおよびbsSingleの場合は
// 各モニタの有効面の左上を原点(0,0)とした座標を指定する。
// それ以外のBorderStyleでは
// 各モニタの左上を原点(0,0)として座標値を返す
if (TargetForm.BorderStyle = bsSizeable) or
(TargetForm.BorderStyle = bsSingle) then
begin
msg.MinMaxInfo.ptMaxPosition.X :=
WkPositionX - WkMonitorInfo.rcWork.Left;
msg.MinMaxInfo.ptMaxPosition.Y :=
WkPositionY - WkMonitorInfo.rcWork.Top;
end
else begin
msg.MinMaxInfo.ptMaxPosition.X :=
WkPositionX - WkMonitorInfo.rcMonitor.Left;
msg.MinMaxInfo.ptMaxPosition.Y :=
WkPositionY - WkMonitorInfo.rcMonitor.Top;
end;
// WindowsXP・Server2003でOSがテーマ対応の場合
// BorderStyleがbsDialogが設定されると
// 境界線が表示されないので、その調整のために境界線の幅だけ調整する
if (isWindowsXPUseThemes = True) and
(TargetForm.BorderStyle = bsDialog) then
begin
// 立体効果付きのウィンドウの境界線の幅 +
// 立体効果のないウィンドウの境界の幅 を取得
WkBoundaryX := GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CXBORDER);
WkBoundaryY := GetSystemMetrics(SM_CYEDGE) + GetSystemMetrics(SM_CXBORDER);
msg.MinMaxInfo.ptMaxSize.X :=
msg.MinMaxInfo.ptMaxSize.X + (WkBoundaryX * 2);
msg.MinMaxInfo.ptMaxSize.Y :=
msg.MinMaxInfo.ptMaxSize.Y + (WkBoundaryY * 2);
msg.MinMaxInfo.ptMaxPosition.X :=
msg.MinMaxInfo.ptMaxPosition.X - WkBoundaryX;
msg.MinMaxInfo.ptMaxPosition.Y :=
msg.MinMaxInfo.ptMaxPosition.Y - WkBoundaryY;
end;
{
// デバッグ用
ShowMessage(
'msg.MinMaxInfo.ptMaxPosition.X:' + IntToStr(msg.MinMaxInfo.ptMaxPosition.X) + #13#10 +
'msg.MinMaxInfo.ptMaxPosition.Y:' + IntToStr(msg.MinMaxInfo.ptMaxPosition.Y) + #13#10 +
'msg.MinMaxInfo.ptMaxSize.X:' + IntToStr(msg.MinMaxInfo.ptMaxSize.X) + #13#10 +
'msg.MinMaxInfo.ptMaxSize.Y:' + IntToStr(msg.MinMaxInfo.ptMaxSize.Y)
);
}
end;
procedure TMultiMonitorMaxInfoCalc.WMCustomGetMinMaxInfo(
var msg: TWMGetMinMaxInfo);
var
WkMonitorInfo : TMonitorInfo;
WkPositionX, WkPositionY: Integer;
WkBoundaryX, WkBoundaryY: Integer;
begin
// ディスプレイモニタに関する情報を取得
// プライマリモニタの左上を原点(0,0)とした値が帰ってくる
WkMonitorInfo := Self.MonitorInfo;
// フォームの位置を保持
WkPositionX :=
FMaxPositionX + WkMonitorInfo.rcWork.Left;
WkPositionY :=
FMaxPositionY + WkMonitorInfo.rcWork.Top;
// 有効面から左上にはみ出ている場合は直す
if WkPositionX < WkMonitorInfo.rcWork.Left then
begin
WkPositionX := WkMonitorInfo.rcWork.Left;
end;
if WkPositionY < WkMonitorInfo.rcWork.Top then
begin
WkPositionY := WkMonitorInfo.rcWork.Top;
end;
// フォームのサイズをmsg.MinMaxInfo.ptMaxSizeに指定
// 有効面以上の大きさにならないように大きさを修正する
msg.MinMaxInfo.ptMaxSize.X :=
Min(FMaxSizeX,
WkMonitorInfo.rcWork.Right - WkMonitorInfo.rcWork.Left - FMaxPositionX);
msg.MinMaxInfo.ptMaxSize.Y :=
Min(FMaxSizeY,
WkMonitorInfo.rcWork.Bottom - WkMonitorInfo.rcWork.Top - FMaxPositionY);
// フォームの位置をmsg.MinMaxInfo.ptMaxPositionに指定
// msg.MinMaxInfo.ptMaxPositionは
// BorderStyleがbsSizeableおよびbsSingleの場合は
// 各モニタの有効面の左上を原点(0,0)とした座標を指定する。
// それ以外のBorderStyleでは
// 各モニタの左上を原点(0,0)として座標値を返す
if (TargetForm.BorderStyle = bsSizeable) or
(TargetForm.BorderStyle = bsSingle) then
begin
msg.MinMaxInfo.ptMaxPosition.X :=
WkPositionX - WkMonitorInfo.rcWork.Left;
msg.MinMaxInfo.ptMaxPosition.Y :=
WkPositionY - WkMonitorInfo.rcWork.Top;
end
else begin
msg.MinMaxInfo.ptMaxPosition.X :=
WkPositionX - WkMonitorInfo.rcMonitor.Left;
msg.MinMaxInfo.ptMaxPosition.Y :=
WkPositionY - WkMonitorInfo.rcMonitor.Top;
end;
// WindowsXP・Server2003でOSがテーマ対応の場合
// BorderStyleがbsDialogが設定されると
// 境界線が表示されないので、その調整のために境界線の幅だけ調整する
if (isWindowsXPUseThemes = True) and
(TargetForm.BorderStyle = bsDialog) then
begin
// 立体効果付きのウィンドウの境界線の幅 +
// 立体効果のないウィンドウの境界の幅 を取得
WkBoundaryX := GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CXBORDER);
WkBoundaryY := GetSystemMetrics(SM_CYEDGE) + GetSystemMetrics(SM_CXBORDER);
msg.MinMaxInfo.ptMaxSize.X :=
msg.MinMaxInfo.ptMaxSize.X + (WkBoundaryX * 2);
msg.MinMaxInfo.ptMaxSize.Y :=
msg.MinMaxInfo.ptMaxSize.Y + (WkBoundaryY * 2);
msg.MinMaxInfo.ptMaxPosition.X :=
msg.MinMaxInfo.ptMaxPosition.X - WkBoundaryX;
msg.MinMaxInfo.ptMaxPosition.Y :=
msg.MinMaxInfo.ptMaxPosition.Y - WkBoundaryY;
end;
{
// デバッグ用
ShowMessage(
'msg.MinMaxInfo.ptMaxPosition.X:' + IntToStr(msg.MinMaxInfo.ptMaxPosition.X) + #13#10 +
'msg.MinMaxInfo.ptMaxPosition.Y:' + IntToStr(msg.MinMaxInfo.ptMaxPosition.Y) + #13#10 +
'msg.MinMaxInfo.ptMaxSize.X:' + IntToStr(msg.MinMaxInfo.ptMaxSize.X) + #13#10 +
'msg.MinMaxInfo.ptMaxSize.Y:' + IntToStr(msg.MinMaxInfo.ptMaxSize.Y)
);
}
end;
procedure TMultiMonitorMaxInfoCalc.WMGetMinMaxInfo(
var msg: TWMGetMinMaxInfo);
begin
// ウインドウが存在しない場合は終了
if FTargetForm = nil then
begin
Exit;
end;
if IsWindow(FTargetForm.Handle) = False then
begin
Exit;
end;
case FMaxAlign of
alNone:
begin
WMNoneGetMinMaxInfo(msg);
end;
alClient:
begin
WMClientGetMinMaxInfo(msg);
end;
alCustom:
begin
WMCustomGetMinMaxInfo(msg);
end;
alTop:
begin
WMTopGetMinMaxInfo(msg);
end;
alBottom:
begin
WMBottomGetMinMaxInfo(msg);
end;
alLeft:
begin
WMLeftGetMinMaxInfo(msg);
end;
alRight:
begin
WMRightGetMinMaxInfo(msg);
end;
else
raise Exception.Create('MaxAlignのエラーです' + #13#10 +
'プログラミングエラーです、開発者にお問い合わせください');
end;
end;
procedure TMultiMonitorMaxInfoCalc.WMGetMinMaxInfo2;
begin
// ウインドウが存在しない場合は終了
if FTargetForm = nil then
begin
Exit;
end;
if IsWindow(FTargetForm.Handle) = False then
begin
Exit;
end;
// 最大化の時のみ実行される
if IsZoomed(FTargetForm.Handle) then
begin
// 最小化して最大化
ShowWindow(FTargetForm.Handle, SW_NORMAL);
ShowWindow(FTargetForm.Handle, SW_MAXIMIZE);
// 以前は、ちらつきを抑えつつ変更されるように作っていましたが、
// 色々な場面(OS・フォームBorderStyle・OSテーマ対応)
// で動作が不安定なので断念…
// Delphi-MLで教えていただいた方申し訳ありません。
end;
end;
procedure TMultiMonitorMaxInfoCalc.WMLeftGetMinMaxInfo(
var msg: TWMGetMinMaxInfo);
var
WkMonitorInfo : TMonitorInfo;
WkPositionX, WkPositionY: Integer;
WkBoundaryX, WkBoundaryY: Integer;
begin
// ディスプレイモニタに関する情報を取得
// プライマリモニタの左上を原点(0,0)とした値が帰ってくる
WkMonitorInfo := Self.MonitorInfo;
// フォームの位置を保持
WkPositionX := WkMonitorInfo.rcWork.Left;
WkPositionY := WkMonitorInfo.rcWork.Top;
// フォームのサイズをmsg.MinMaxInfo.ptMaxSizeに指定
msg.MinMaxInfo.ptMaxSize.X :=
Min(FMaxSizeX,
WkMonitorInfo.rcWork.Right - WkMonitorInfo.rcWork.Left);
msg.MinMaxInfo.ptMaxSize.Y :=
WkMonitorInfo.rcWork.Bottom - WkMonitorInfo.rcWork.Top;
// フォームの位置をmsg.MinMaxInfo.ptMaxPositionに指定
// msg.MinMaxInfo.ptMaxPositionは
// BorderStyleがbsSizeableおよびbsSingleの場合は
// 各モニタの有効面の左上を原点(0,0)とした座標を指定する。
// それ以外のBorderStyleでは
// 各モニタの左上を原点(0,0)として座標値を返す
if (TargetForm.BorderStyle = bsSizeable) or
(TargetForm.BorderStyle = bsSingle) then
begin
msg.MinMaxInfo.ptMaxPosition.X :=
WkPositionX - WkMonitorInfo.rcWork.Left;
msg.MinMaxInfo.ptMaxPosition.Y :=
WkPositionY - WkMonitorInfo.rcWork.Top;
end
else begin
msg.MinMaxInfo.ptMaxPosition.X :=
WkPositionX - WkMonitorInfo.rcMonitor.Left;
msg.MinMaxInfo.ptMaxPosition.Y :=
WkPositionY - WkMonitorInfo.rcMonitor.Top;
end;
// WindowsXP・Server2003でOSがテーマ対応の場合
// BorderStyleがbsDialogが設定されると
// 境界線が表示されないので、その調整のために境界線の幅だけ調整する
if (isWindowsXPUseThemes = True) and
(TargetForm.BorderStyle = bsDialog) then
begin
// 立体効果付きのウィンドウの境界線の幅 +
// 立体効果のないウィンドウの境界の幅 を取得
WkBoundaryX := GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CXBORDER);
WkBoundaryY := GetSystemMetrics(SM_CYEDGE) + GetSystemMetrics(SM_CXBORDER);
msg.MinMaxInfo.ptMaxSize.X :=
msg.MinMaxInfo.ptMaxSize.X + (WkBoundaryX * 2);
msg.MinMaxInfo.ptMaxSize.Y :=
msg.MinMaxInfo.ptMaxSize.Y + (WkBoundaryY * 2);
msg.MinMaxInfo.ptMaxPosition.X :=
msg.MinMaxInfo.ptMaxPosition.X - WkBoundaryX;
msg.MinMaxInfo.ptMaxPosition.Y :=
msg.MinMaxInfo.ptMaxPosition.Y - WkBoundaryY;
end;
{
// デバッグ用
ShowMessage(
'msg.MinMaxInfo.ptMaxPosition.X:' + IntToStr(msg.MinMaxInfo.ptMaxPosition.X) + #13#10 +
'msg.MinMaxInfo.ptMaxPosition.Y:' + IntToStr(msg.MinMaxInfo.ptMaxPosition.Y) + #13#10 +
'msg.MinMaxInfo.ptMaxSize.X:' + IntToStr(msg.MinMaxInfo.ptMaxSize.X) + #13#10 +
'msg.MinMaxInfo.ptMaxSize.Y:' + IntToStr(msg.MinMaxInfo.ptMaxSize.Y)
);
}
end;
procedure TMultiMonitorMaxInfoCalc.WMClientGetMinMaxInfo(
var msg: TWMGetMinMaxInfo);
var
WkMonitorInfo : TMonitorInfo;
WkPositionX, WkPositionY: Integer;
WkBoundaryX, WkBoundaryY: Integer;
begin
// ディスプレイモニタに関する情報を取得
// プライマリモニタの左上を原点(0,0)とした値が帰ってくる
WkMonitorInfo := Self.MonitorInfo;
// フォームの位置を保持
WkPositionX := WkMonitorInfo.rcWork.Left;
WkPositionY := WkMonitorInfo.rcWork.Top;
// フォームのサイズをmsg.MinMaxInfo.ptMaxSizeに指定
msg.MinMaxInfo.ptMaxSize.X :=
WkMonitorInfo.rcWork.Right - WkMonitorInfo.rcWork.Left;
msg.MinMaxInfo.ptMaxSize.Y :=
WkMonitorInfo.rcWork.Bottom - WkMonitorInfo.rcWork.Top;
// フォームの位置をmsg.MinMaxInfo.ptMaxPositionに指定
// msg.MinMaxInfo.ptMaxPositionは
// BorderStyleがbsSizeableおよびbsSingleの場合は
// 各モニタの有効面の左上を原点(0,0)とした座標を指定する。
// それ以外のBorderStyleでは
// 各モニタの左上を原点(0,0)として座標値を返す
if (TargetForm.BorderStyle = bsSizeable) or
(TargetForm.BorderStyle = bsSingle) then
begin
msg.MinMaxInfo.ptMaxPosition.X :=
WkPositionX - WkMonitorInfo.rcWork.Left;
msg.MinMaxInfo.ptMaxPosition.Y :=
WkPositionY - WkMonitorInfo.rcWork.Top;
end
else begin
msg.MinMaxInfo.ptMaxPosition.X :=
WkPositionX - WkMonitorInfo.rcMonitor.Left;
msg.MinMaxInfo.ptMaxPosition.Y :=
WkPositionY - WkMonitorInfo.rcMonitor.Top;
end;
// WindowsXP・Server2003でOSがテーマ対応の場合
// BorderStyleがbsDialogが設定されると
// 境界線が表示されないので、その調整のために境界線の幅だけ調整する
if (isWindowsXPUseThemes = True) and
(TargetForm.BorderStyle = bsDialog) then
begin
// 立体効果付きのウィンドウの境界線の幅 +
// 立体効果のないウィンドウの境界の幅 を取得
WkBoundaryX := GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CXBORDER);
WkBoundaryY := GetSystemMetrics(SM_CYEDGE) + GetSystemMetrics(SM_CXBORDER);
msg.MinMaxInfo.ptMaxSize.X :=
msg.MinMaxInfo.ptMaxSize.X + (WkBoundaryX * 2);
msg.MinMaxInfo.ptMaxSize.Y :=
msg.MinMaxInfo.ptMaxSize.Y + (WkBoundaryY * 2);
msg.MinMaxInfo.ptMaxPosition.X :=
msg.MinMaxInfo.ptMaxPosition.X - WkBoundaryX;
msg.MinMaxInfo.ptMaxPosition.Y :=
msg.MinMaxInfo.ptMaxPosition.Y - WkBoundaryY;
end;
{
// デバッグ用
ShowMessage(
'msg.MinMaxInfo.ptMaxPosition.X:' + IntToStr(msg.MinMaxInfo.ptMaxPosition.X) + #13#10 +
'msg.MinMaxInfo.ptMaxPosition.Y:' + IntToStr(msg.MinMaxInfo.ptMaxPosition.Y) + #13#10 +
'msg.MinMaxInfo.ptMaxSize.X:' + IntToStr(msg.MinMaxInfo.ptMaxSize.X) + #13#10 +
'msg.MinMaxInfo.ptMaxSize.Y:' + IntToStr(msg.MinMaxInfo.ptMaxSize.Y)
);
}
end;
procedure TMultiMonitorMaxInfoCalc.WMRightGetMinMaxInfo(
var msg: TWMGetMinMaxInfo);
var
WkMonitorInfo : TMonitorInfo;
WkPositionX, WkPositionY: Integer;
WkBoundaryX, WkBoundaryY: Integer;
begin
// ディスプレイモニタに関する情報を取得
// プライマリモニタの左上を原点(0,0)とした値が帰ってくる
WkMonitorInfo := Self.MonitorInfo;
// フォームのサイズをmsg.MinMaxInfo.ptMaxSizeに指定
msg.MinMaxInfo.ptMaxSize.X :=
Min(FMaxSizeX,
WkMonitorInfo.rcWork.Right - WkMonitorInfo.rcWork.Left);
msg.MinMaxInfo.ptMaxSize.Y :=
WkMonitorInfo.rcWork.Bottom - WkMonitorInfo.rcWork.Top;
// フォームの位置を保持
WkPositionX := WkMonitorInfo.rcWork.Right - msg.MinMaxInfo.ptMaxSize.X;
WkPositionY := WkMonitorInfo.rcWork.Top;
// フォームの位置をmsg.MinMaxInfo.ptMaxPositionに指定
// msg.MinMaxInfo.ptMaxPositionは
// BorderStyleがbsSizeableおよびbsSingleの場合は
// 各モニタの有効面の左上を原点(0,0)とした座標を指定する。
// それ以外のBorderStyleでは
// 各モニタの左上を原点(0,0)として座標値を返す
if (TargetForm.BorderStyle = bsSizeable) or
(TargetForm.BorderStyle = bsSingle) then
begin
msg.MinMaxInfo.ptMaxPosition.X :=
WkPositionX - WkMonitorInfo.rcWork.Left;
msg.MinMaxInfo.ptMaxPosition.Y :=
WkPositionY - WkMonitorInfo.rcWork.Top;
end
else begin
msg.MinMaxInfo.ptMaxPosition.X :=
WkPositionX - WkMonitorInfo.rcMonitor.Left;
msg.MinMaxInfo.ptMaxPosition.Y :=
WkPositionY - WkMonitorInfo.rcMonitor.Top;
end;
// WindowsXP・Server2003でOSがテーマ対応の場合
// BorderStyleがbsDialogが設定されると
// 境界線が表示されないので、その調整のために境界線の幅だけ調整する
if (isWindowsXPUseThemes = True) and
(TargetForm.BorderStyle = bsDialog) then
begin
// 立体効果付きのウィンドウの境界線の幅 +
// 立体効果のないウィンドウの境界の幅 を取得
WkBoundaryX := GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CXBORDER);
WkBoundaryY := GetSystemMetrics(SM_CYEDGE) + GetSystemMetrics(SM_CXBORDER);
msg.MinMaxInfo.ptMaxSize.X :=
msg.MinMaxInfo.ptMaxSize.X + (WkBoundaryX * 2);
msg.MinMaxInfo.ptMaxSize.Y :=
msg.MinMaxInfo.ptMaxSize.Y + (WkBoundaryY * 2);
msg.MinMaxInfo.ptMaxPosition.X :=
msg.MinMaxInfo.ptMaxPosition.X - WkBoundaryX;
msg.MinMaxInfo.ptMaxPosition.Y :=
msg.MinMaxInfo.ptMaxPosition.Y - WkBoundaryY;
end;
{
// デバッグ用
ShowMessage(
'msg.MinMaxInfo.ptMaxPosition.X:' + IntToStr(msg.MinMaxInfo.ptMaxPosition.X) + #13#10 +
'msg.MinMaxInfo.ptMaxPosition.Y:' + IntToStr(msg.MinMaxInfo.ptMaxPosition.Y) + #13#10 +
'msg.MinMaxInfo.ptMaxSize.X:' + IntToStr(msg.MinMaxInfo.ptMaxSize.X) + #13#10 +
'msg.MinMaxInfo.ptMaxSize.Y:' + IntToStr(msg.MinMaxInfo.ptMaxSize.Y)
);
}
end;
procedure TMultiMonitorMaxInfoCalc.WMTopGetMinMaxInfo(
var msg: TWMGetMinMaxInfo);
var
WkMonitorInfo : TMonitorInfo;
WkPositionX, WkPositionY: Integer;
WkBoundaryX, WkBoundaryY: Integer;
begin
// ディスプレイモニタに関する情報を取得
// プライマリモニタの左上を原点(0,0)とした値が帰ってくる
WkMonitorInfo := Self.MonitorInfo;
// フォームの位置を保持
WkPositionX := WkMonitorInfo.rcWork.Left;
WkPositionY := WkMonitorInfo.rcWork.Top;
// フォームのサイズをmsg.MinMaxInfo.ptMaxSizeに指定
msg.MinMaxInfo.ptMaxSize.X :=
WkMonitorInfo.rcWork.Right - WkMonitorInfo.rcWork.Left;
msg.MinMaxInfo.ptMaxSize.Y :=
Min(FMaxSizeY,
WkMonitorInfo.rcWork.Bottom - WkMonitorInfo.rcWork.Top);
// フォームの位置をmsg.MinMaxInfo.ptMaxPositionに指定
// msg.MinMaxInfo.ptMaxPositionは
// BorderStyleがbsSizeableおよびbsSingleの場合は
// 各モニタの有効面の左上を原点(0,0)とした座標を指定する。
// それ以外のBorderStyleでは
// 各モニタの左上を原点(0,0)として座標値を返す
if (TargetForm.BorderStyle = bsSizeable) or
(TargetForm.BorderStyle = bsSingle) then
begin
msg.MinMaxInfo.ptMaxPosition.X :=
WkPositionX - WkMonitorInfo.rcWork.Left;
msg.MinMaxInfo.ptMaxPosition.Y :=
WkPositionY - WkMonitorInfo.rcWork.Top;
end
else begin
msg.MinMaxInfo.ptMaxPosition.X :=
WkPositionX - WkMonitorInfo.rcMonitor.Left;
msg.MinMaxInfo.ptMaxPosition.Y :=
WkPositionY - WkMonitorInfo.rcMonitor.Top;
end;
// WindowsXP・Server2003でOSがテーマ対応の場合
// BorderStyleがbsDialogが設定されると
// 境界線が表示されないので、その調整のために境界線の幅だけ調整する
if (isWindowsXPUseThemes = True) and
(TargetForm.BorderStyle = bsDialog) then
begin
// 立体効果付きのウィンドウの境界線の幅 +
// 立体効果のないウィンドウの境界の幅 を取得
WkBoundaryX := GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CXBORDER);
WkBoundaryY := GetSystemMetrics(SM_CYEDGE) + GetSystemMetrics(SM_CXBORDER);
msg.MinMaxInfo.ptMaxSize.X :=
msg.MinMaxInfo.ptMaxSize.X + (WkBoundaryX * 2);
msg.MinMaxInfo.ptMaxSize.Y :=
msg.MinMaxInfo.ptMaxSize.Y + (WkBoundaryY * 2);
msg.MinMaxInfo.ptMaxPosition.X :=
msg.MinMaxInfo.ptMaxPosition.X - WkBoundaryX;
msg.MinMaxInfo.ptMaxPosition.Y :=
msg.MinMaxInfo.ptMaxPosition.Y - WkBoundaryY;
end;
{
// デバッグ用
ShowMessage(
'msg.MinMaxInfo.ptMaxPosition.X:' + IntToStr(msg.MinMaxInfo.ptMaxPosition.X) + #13#10 +
'msg.MinMaxInfo.ptMaxPosition.Y:' + IntToStr(msg.MinMaxInfo.ptMaxPosition.Y) + #13#10 +
'msg.MinMaxInfo.ptMaxSize.X:' + IntToStr(msg.MinMaxInfo.ptMaxSize.X) + #13#10 +
'msg.MinMaxInfo.ptMaxSize.Y:' + IntToStr(msg.MinMaxInfo.ptMaxSize.Y)
);
}
end;
procedure TMultiMonitorMaxInfoCalc.WMNoneGetMinMaxInfo(
var msg: TWMGetMinMaxInfo);
var
WkMonitorInfo : TMonitorInfo;
WkPositionX, WkPositionY: Integer;
WkBoundaryX, WkBoundaryY: Integer;
begin
// ディスプレイモニタに関する情報を取得
// プライマリモニタの左上を原点(0,0)とした値が帰ってくる
WkMonitorInfo := Self.MonitorInfo;
// フォームの位置を保持
if (TargetForm.BorderStyle = bsSizeable) or
(TargetForm.BorderStyle = bsSingle) then
begin
// bsSizeable, bsSingle は
// 最大化はモニタ有効面の範囲で広がる
WkPositionX := WkMonitorInfo.rcWork.Left;
WkPositionY := WkMonitorInfo.rcWork.Top;
end
else begin
// bsDialog, bsNone, bsSizeToolWin, bsToolWindow は
// 最大化はモニタ全体の範囲で広がる
WkPositionX := WkMonitorInfo.rcMonitor.Left;
WkPositionY := WkMonitorInfo.rcMonitor.Top;
end;
// 境界線の幅を取得
case FTargetForm.BorderStyle of
bsNone:
begin
// ウィンドウの境界線が無い
WkBoundaryX := 0;
WkBoundaryY := 0;
end;
bsDialog, bsSingle, bsToolWindow:
begin
// 立体効果付きのウィンドウの境界線の幅 +
// 立体効果のないウィンドウの境界の幅 を取得
WkBoundaryX := GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CXBORDER);
WkBoundaryY := GetSystemMetrics(SM_CYEDGE) + GetSystemMetrics(SM_CYBORDER);
end;
else
//bsSizeable, bsSizeToolWin
// サイズ変更可能なウィンドウの周囲を囲む枠の幅 を取得
WkBoundaryX := GetSystemMetrics(SM_CXFRAME);
WkBoundaryY := GetSystemMetrics(SM_CYFRAME);
end;
// フォームのサイズをmsg.MinMaxInfo.ptMaxSizeに指定
// 境界線の幅をフォームのサイズに反映させる
if (TargetForm.BorderStyle = bsSizeable) or
(TargetForm.BorderStyle = bsSingle) then
begin
// bsSizeable, bsSingle は
// 最大化はモニタ有効面の範囲で広がる
msg.MinMaxInfo.ptMaxSize.X :=
WkMonitorInfo.rcWork.Right - WkMonitorInfo.rcWork.Left +
(WkBoundaryX * 2);
msg.MinMaxInfo.ptMaxSize.Y :=
WkMonitorInfo.rcWork.Bottom - WkMonitorInfo.rcWork.Top +
(WkBoundaryY * 2);
end
else begin
// bsDialog, bsNone, bsSizeToolWin, bsToolWindow は
// 最大化はモニタ全体の範囲で広がる
msg.MinMaxInfo.ptMaxSize.X :=
WkMonitorInfo.rcMonitor.Right - WkMonitorInfo.rcMonitor.Left +
(WkBoundaryX * 2);
msg.MinMaxInfo.ptMaxSize.Y :=
WkMonitorInfo.rcMonitor.Bottom - WkMonitorInfo.rcMonitor.Top +
(WkBoundaryY * 2);
// Windows Vista(SP1)では、
// bsSizeToolWin, bsToolWindowの時に、縦のサイズがおかしく表示される
// 現象が起こる
// Windows Vista(無印/SP2)は未確認、他のWindowsではこの現象は起きない
end;
// フォームの位置をmsg.MinMaxInfo.ptMaxPositionに指定
// 境界線の幅をフォームの位置に反映させる
// msg.MinMaxInfo.ptMaxPositionは
// BorderStyleがbsSizeableおよびbsSingleの場合は
// 各モニタの有効面の左上を原点(0,0)とした座標を指定する。
// それ以外のBorderStyleでは
// 各モニタの左上を原点(0,0)として座標値を返す
if (TargetForm.BorderStyle = bsSizeable) or
(TargetForm.BorderStyle = bsSingle) then
begin
msg.MinMaxInfo.ptMaxPosition.X :=
WkPositionX - WkMonitorInfo.rcWork.Left - WkBoundaryX;
msg.MinMaxInfo.ptMaxPosition.Y :=
WkPositionY - WkMonitorInfo.rcWork.Top - WkBoundaryY;
end
else begin
msg.MinMaxInfo.ptMaxPosition.X :=
WkPositionX - WkMonitorInfo.rcMonitor.Left - WkBoundaryX;
msg.MinMaxInfo.ptMaxPosition.Y :=
WkPositionY - WkMonitorInfo.rcMonitor.Top - WkBoundaryY;
end;
{
// デバッグ用
ShowMessage(
'msg.MinMaxInfo.ptMaxPosition.X:' + IntToStr(msg.MinMaxInfo.ptMaxPosition.X) + #13#10 +
'msg.MinMaxInfo.ptMaxPosition.Y:' + IntToStr(msg.MinMaxInfo.ptMaxPosition.Y) + #13#10 +
'msg.MinMaxInfo.ptMaxSize.X:' + IntToStr(msg.MinMaxInfo.ptMaxSize.X) + #13#10 +
'msg.MinMaxInfo.ptMaxSize.Y:' + IntToStr(msg.MinMaxInfo.ptMaxSize.Y)
);
}
end;
{ TMonitorInfoParam }
constructor TMonitorInfoParam.Create(AOwner: TComponent);
begin
inherited;
if AOwner is TForm then
begin
FTargetForm := TForm(AOwner)
end
else begin
FTargetForm := nil;
end;
end;
function TMonitorInfoParam.DisplayMonitorInfo: TMonitorInfo;
begin
// ウインドウが存在しない場合は例外を発生させる
if FTargetForm = nil then
begin
raise ETargetFormIsNotFound.Create('TargetFormが指定されていません');
end;
if IsWindow(FTargetForm.Handle) = False then
begin
raise ETargetFormIsNotFound.Create('TargetFormで指定したフォームが存在されていません');
end;
GetMonitorInfoParam;
result := FDisplayMonitorInfo;
end;
procedure TMonitorInfoParam.GetMonitorInfoParam;
begin
// ディスプレイモニタに関する情報を取得
// プライマリモニタの左上を原点として座標値を返す
ZeroMemory(@FMonitorInfo, sizeof(FMonitorInfo));
FMonitorInfo.cbSize := SizeOf(FMonitorInfo);
if GetMonitorInfo(FTargetForm.Monitor.Handle, @FMonitorInfo) = False then
begin
// 念のためリトライ(いるのかな・・・?)
Sleep(100);
if GetMonitorInfo(FTargetForm.Monitor.Handle, @FMonitorInfo) = False then
begin
raise Exception.Create('APIのGetMonitorInfo関数でエラーが発生しました' + #13#10 +
'プログラミングエラーです、開発者にお問い合わせください');
end;
end;
// ディスプレイモニタに関する情報を取得
// 各モニタの左上を原点として座標値を返す
FDisplayMonitorInfo.cbSize := SizeOf(FDisplayMonitorInfo);
FDisplayMonitorInfo.dwFlags := FMonitorInfo.dwFlags;
FDisplayMonitorInfo.rcMonitor.Top := 0;
FDisplayMonitorInfo.rcMonitor.Left := 0;
FDisplayMonitorInfo.rcMonitor.Bottom :=
FMonitorInfo.rcMonitor.Bottom - FMonitorInfo.rcMonitor.Top;
FDisplayMonitorInfo.rcMonitor.Right :=
FMonitorInfo.rcMonitor.Right - FMonitorInfo.rcMonitor.Left;
FDisplayMonitorInfo.rcWork.Top :=
FMonitorInfo.rcWork.Top - FMonitorInfo.rcMonitor.Top;
FDisplayMonitorInfo.rcWork.Left :=
FMonitorInfo.rcWork.Left - FMonitorInfo.rcMonitor.Left;
FDisplayMonitorInfo.rcWork.Bottom :=
FMonitorInfo.rcWork.Bottom - FMonitorInfo.rcMonitor.Top;
FDisplayMonitorInfo.rcWork.Right :=
FMonitorInfo.rcWork.Right - FMonitorInfo.rcMonitor.Left;
end;
function TMonitorInfoParam.MonitorCount: Integer;
begin
result := Screen.MonitorCount;
end;
function TMonitorInfoParam.MonitorInfo: TMonitorInfo;
begin
// ウインドウが存在しない場合は例外を発生させる
if FTargetForm = nil then
begin
raise ETargetFormIsNotFound.Create('TargetFormが指定されていません');
end;
if IsWindow(FTargetForm.Handle) = False then
begin
raise ETargetFormIsNotFound.Create('TargetFormで指定したフォームが存在されていません');
end;
GetMonitorInfoParam;
result := FMonitorInfo;
end;
function TMonitorInfoParam.MonitorNum: Integer;
begin
result := FTargetForm.Monitor.MonitorNum;
end;
procedure TMonitorInfoParam.SetTargetForm(const Value: TForm);
begin
FTargetForm := Value;
end;
end.