{******************************************************************************* TFormMinMaxInfo 機能: 配置したFormをフックして WM_GETMINMAXINFOを監視し トラック時の最大/最小サイズ 最大化時のサイズ/位置を設定する それぞれOptionsの lmMinSize/lmMaxSize lmMaximizeSize/lmMaximizePos の値によってどの項目を設定するのかを選択出来る 備考: 通常のWM_GETMINMAXINFOでのやり方では トラック時の最大化サイズが最大化時のサイズにも影響するが MaximizedSizeを指定すると最大化しているのに 移動可能になってしまうので注意。 WindowStateを見る事で解決している。 修正履歴: 2001/09/13 2007/01/17 HookとFuckとを間違えてた..超恥ずかしい...修正した *******************************************************************************} unit FormMinMaxInfo; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TLimitMinMaxInfo = (lmMinSize, lmMaxSize, lmMaximizeSize, lmMaximizePos); TLimitMinMaxInfos = set of TLimitMinMaxInfo; TFormMinMaxInfo = class(TComponent) private FOldFormProc: TWndMethod; FMaxSize: TPoint; FMinSize: TPoint; FMaximizeSize: TPoint; FMaximizePos: TPoint; FOptions: TLimitMinMaxInfos; FPropertyInterlock: Boolean; procedure FormWndProc(var Message: TMessage); function GetHookForm: TCustomForm; procedure SetMaxHeight(const Value: Integer); procedure SetMaximizeHeight(const Value: Integer); procedure SetMaximizeLeft(const Value: Integer); procedure SetMaximizeTop(const Value: Integer); procedure SetMaximizeWidth(const Value: Integer); procedure SetMaxWidth(const Value: Integer); procedure SetMinHeight(const Value: Integer); procedure SetMinWidth(const Value: Integer); procedure SetOptions(const Value: TLimitMinMaxInfos); function GetMinHeight: Integer; function GetMaxHeight: Integer; function GetMaximizeHeight: Integer; function GetMaximizeLeft: Integer; function GetMaximizeTop: Integer; function GetMaximizeWidth: Integer; function GetMaxWidth: Integer; function GetMinWidth: Integer; protected public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property HookForm: TCustomForm read GetHookForm; property Options: TLimitMinMaxInfos read FOptions write SetOptions; property MinHeight: Integer read GetMinHeight write SetMinHeight; property MinWidth: Integer read GetMinWidth write SetMinWidth; property MaxHeight: Integer read GetMaxHeight write SetMaxHeight; property MaxWidth: Integer read GetMaxWidth write SetMaxWidth; property MaximizeHeight: Integer read GetMaximizeHeight write SetMaximizeHeight; property MaximizeWidth: Integer read GetMaximizeWidth write SetMaximizeWidth; property MaximizeTop: Integer read GetMaximizeTop write SetMaximizeTop; property MaximizeLeft: Integer read GetMaximizeLeft write SetMaximizeLeft; property PropertyInterlock: Boolean read FPropertyInterlock write FPropertyInterlock; end; procedure Register; implementation procedure Register; begin RegisterComponents('Samples', [TFormMinMaxInfo]); end; { TFormMinMaxInfo } {------------------------------- // 起動終了 処理: OwnerFormのサブクラス化 履歴: 2001/09/11 //------------------------------} constructor TFormMinMaxInfo.Create(AOwner: TComponent); //自分自身以外に同じクラスのコンポーネントがあった場合Trueを返す関数 //複数のコンポーネントが置かれた場合動作させないための方法 function OtherSameClassCompoExist: Boolean; var i: Integer; begin for i := 0 to TCustomForm(AOwner).ComponentCount-1 do begin if (TCustomForm(AOwner).Components[i] <> Self) and (TCustomForm(AOwner).Components[i].ClassType = Self.ClassType) then begin Result := True; Exit; end; end; Result := False; end; begin inherited; {↓コンポーネントのOwnerがFormならサブクラス化する} if (AOwner is TCustomForm) and (OtherSameClassCompoExist=False) then begin FOldFormProc := TCustomForm(AOwner).WindowProc; TCustomForm(AOwner).WindowProc := FormWndProc; end else begin FOldFormProc := nil; end; FPropertyInterlock := True; end; //------------------------------- //メソッドが一致するかどうか調べる関数 function SameMethod(const A, B: TMethod): Boolean; begin if (A.Code = B.Code) and (A.Data = B.Data) then Result := True else Result := False; end; destructor TFormMinMaxInfo.Destroy; var Method: TWndMethod; begin {↓コンポーネントがサブクラス化しているなら元に戻す} if Assigned(FOldFormProc) and (Self.Owner is TCustomForm) then begin Method := Self.FormWndProc; if SameMethod( TMethod(TCustomForm(Self.Owner).WindowProc), TMethod(Method) ) then begin TCustomForm(Self.Owner).WindowProc := FOldFormProc; FOldFormProc := nil; end else raise EComponentError.Create('サブクラス化解除失敗'); end; inherited; end; //------------------------------ //------------------------------- //フックしたFormを戻す function TFormMinMaxInfo.GetHookForm: TCustomForm; begin {↓フックしていてOwnerがFormなら戻り値に入れる} if Assigned(FOldFormProc) and (Self.Owner is TCustomForm) then begin Result := TCustomForm(Self.Owner); end else begin Result := nil; end; end; {------------------------------- // Formのサブクラス化フックプロシジャー 処理: 備考: 履歴: 2001/09/11 //------------------------------} (*------------------------------- //ハンドルからWindowStateを調べる 引数説明: WndHandle: ハンドル -------------------------------*) function GetWindowState(WndHandle: HWnd): TWindowState; var pw : TWINDOWPLACEMENT; begin pw.length := SizeOf(TWINDOWPLACEMENT); GetWindowPlacement(WndHandle, @pw); case pw.showCmd of SW_SHOWNORMAL:{=1} Result := wsNormal; SW_SHOWMINIMIZED: {=2} Result := wsMinimized; SW_MAXIMIZE: {=3} Result := wsMaximized; else raise Exception.Create('WindowStateのエラー'+IntToStr(pw.showCmd)); end; end; procedure TFormMinMaxInfo.FormWndProc(var Message: TMessage); begin case Message.Msg of WM_GETMINMAXINFO: with TWMGetMinMaxInfo(Message).MinMaxInfo^ do begin if lmMinSize in FOptions then begin ptMinTrackSize := FMinSize; end; if lmMaxSize in FOptions then begin {↓トラックサイズ最大化制限指定の場合 WindowStateがwsMaximizedなら指定してはならない のでGetWindowState関数を使って条件判断} if GetWindowState(HookForm.Handle)<>wsMaximized then begin {↓Maxの場合は0なら制限しない(挙動が変になるから)} if not (FMaxSize.x=0) then ptMaxTrackSize.x := FMaxSize.x; if not (FMaxSize.y=0) then ptMaxTrackSize.y := FMaxSize.y; {↑一方が指定してあって一方が0の場合でも 正しく動作するための処置} end; end; if lmMaximizeSize in FOptions then begin if not (FMaximizeSize.x=0) then ptMaxSize.x := FMaximizeSize.x; if not (FMaximizeSize.y=0) then ptMaxSize.y := FMaximizeSize.y; end; if lmMaximizePos in FOptions then begin ptMaxPosition.x := FMaximizePos.x; ptMaxPosition.y := FMaximizePos.y; end; end; //WM_GetMinMaxInfo: else end; //case Message.Msg FOldFormProc(Message); end; //------------------------------ {------------------------------- // ドラッグ/最大化サイズ制限スイッチプロパティ 機能: Trueになった時に現在のサイズを制限サイズにする 備考: 履歴: 2001/09/13 //------------------------------} procedure TFormMinMaxInfo.SetOptions(const Value: TLimitMinMaxInfos); begin if FOptions <> Value then begin if Assigned(HookForm) and (FPropertyInterlock) then begin if lmMinSize in (Value - Options) then begin FMinSize.y := HookForm.Height; FMinSize.x := HookForm.Width; end; if lmMinSize in (Options - Value) then begin FMinSize.y := 0; FMinSize.x := 0; end; if lmMaxSize in (Value - Options) then begin FMaxSize.y := HookForm.Height; FMaxSize.x := HookForm.Width; end; if lmMaxSize in (Options - Value) then begin FMaxSize.y := 0; FMaxSize.x := 0; end; if lmMaximizeSize in (Value - Options) then begin FMaximizeSize.y := HookForm.Height; FMaximizeSize.x := HookForm.Width; end; if lmMaximizeSize in (Options - Value) then begin FMaximizeSize.y := 0; FMaximizeSize.x := 0; end; if lmMaximizePos in (Value - Options) then begin FMaximizePos.y := HookForm.Top; FMaximizePos.x := HookForm.Left; end; if lmMaximizePos in (Options - Value) then begin FMaximizePos.y := 0; FMaximizePos.x := 0; end; end; //if Assiged(HookForm) FOptions := Value; end; end; //------------------------------ {------------------------------- // ドラッグ最大最小サイズ/最大化サイズ位置制限範囲プロパティ 機能: 備考: 履歴: 2001/09/13 //------------------------------} const ErrorMsg = '0〜2147483647の値にしてください'; procedure TFormMinMaxInfo.SetMinHeight(const Value: Integer); begin if Value < 0 then begin raise EComponentError.Create(ErrorMsg); end; FMinSize.y := Value; end; function TFormMinMaxInfo.GetMinHeight: Integer; begin Result := FMinSize.y; end; procedure TFormMinMaxInfo.SetMinWidth(const Value: Integer); begin if Value < 0 then begin raise EComponentError.Create(ErrorMsg); end; FMinSize.x := Value; end; function TFormMinMaxInfo.GetMinWidth: Integer; begin Result := FMinSize.x; end; procedure TFormMinMaxInfo.SetMaxHeight(const Value: Integer); begin if Value < 0 then begin raise EComponentError.Create(ErrorMsg); end; FMaxSize.y := Value; end; function TFormMinMaxInfo.GetMaxHeight: Integer; begin Result := FMaxSize.y; end; procedure TFormMinMaxInfo.SetMaxWidth(const Value: Integer); begin if Value < 0 then begin raise EComponentError.Create(ErrorMsg); end; FMaxSize.x := Value; end; function TFormMinMaxInfo.GetMaxWidth: Integer; begin Result := FMaxSize.x; end; procedure TFormMinMaxInfo.SetMaximizeHeight(const Value: Integer); begin if Value < 0 then begin raise EComponentError.Create(ErrorMsg); end; FMaximizeSize.y := Value; end; function TFormMinMaxInfo.GetMaximizeHeight: Integer; begin Result := FMaximizeSize.y; end; procedure TFormMinMaxInfo.SetMaximizeWidth(const Value: Integer); begin if Value < 0 then begin raise EComponentError.Create(ErrorMsg); end; FMaximizeSize.x := Value; end; function TFormMinMaxInfo.GetMaximizeWidth: Integer; begin Result := FMaximizeSize.x; end; procedure TFormMinMaxInfo.SetMaximizeLeft(const Value: Integer); begin FMaximizePos.x := Value; end; function TFormMinMaxInfo.GetMaximizeLeft: Integer; begin Result := FMaximizePos.x; end; procedure TFormMinMaxInfo.SetMaximizeTop(const Value: Integer); begin FMaximizePos.y := Value; end; function TFormMinMaxInfo.GetMaximizeTop: Integer; begin Result := FMaximizePos.y; end; //------------------------------ end.