{******************************************************************************* TFormWSEvent 機能: Formに最大化/最小化/通常化を感知するイベントを追加するコンポーネント OnMaximized OnMinimized OnRestored WindowStateが変化した後にイベントが発生する 変化前のWindowStateはイベントの引数で取得することが出来る 変化後のWindowStateはイベント中にFormのプロパティで取得出来る 備考: サブフォームの場合は分かりやすい動作するものの メインフォームの場合はVCLのApplicationWindowが邪魔をするので 本当にFormの最大化/最小化/通常化したときにしかイベントが発生しない。 一見変な動作しているように見える。 コンポーネントを同一Formに2つ配置しても 先に生成された方が優先される(2つ配置しないようにしてくれ) 修正履歴: 2001/09/11 2007/01/18 FuckFormをHookFormに変更 *******************************************************************************} unit FormWSEvent; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TWinStateEventProc = procedure(FormState: TWindowState) of Object; TWinStateChangedEvent = procedure(Sender: TObject; const ChangePreFormWinState: TWindowState) of Object; TWinStateChangingEvent = procedure(Sender: TObject) of Object; TFormWSEvent = class(TComponent) private FOldFormProc: TWndMethod; FOnMinimized: TWinStateChangedEvent; FOnMaximized: TWinStateChangedEvent; FOnRestored: TWinStateChangedEvent; FOnRestoring: TWinStateChangingEvent; FOnMaximizing: TWinStateChangingEvent; FOnMinimizing: TWinStateChangingEvent; procedure FormWndProc(var Message: TMessage); function GetHookForm: TCustomForm; procedure Maximized(FormState: TWindowState); procedure Minimized(FormState: TWindowState); procedure Restored (FormState: TWindowState); procedure Maximizing; procedure Minimizing; procedure Restoring; protected public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property OnMaximized: TWinStateChangedEvent read FOnMaximized write FOnMaximized; property OnMinimized: TWinStateChangedEvent read FOnMinimized write FOnMinimized; property OnRestored: TWinStateChangedEvent read FOnRestored write FOnRestored; property OnMaximizing: TWinStateChangingEvent read FOnMaximizing write FOnMaximizing; property OnMinimizing: TWinStateChangingEvent read FOnMinimizing write FOnMinimizing; property OnRestoring: TWinStateChangingEvent read FOnRestoring write FOnRestoring; property HookForm: TCustomForm read GetHookForm; end; procedure Register; implementation procedure Register; begin RegisterComponents('Samples', [TFormWSEvent]); end; { TFormWSEvent } {------------------------------- // 起動終了 処理: OwnerFormのサブクラス化 履歴: 2001/09/11 //------------------------------} constructor TFormWSEvent.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; 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 TFormWSEvent.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のサブクラス化フックプロシジャー 処理: 備考: 履歴: 2001/09/11 //------------------------------} procedure TFormWSEvent.FormWndProc(var Message: TMessage); function GetSysCommandType(WinState: TWindowState): Longint; begin case WinState of wsNormal: Result := SC_RESTORE; wsMinimized: Result := SC_MINIMIZE; wsMaximized: Result := SC_MAXIMIZE; end; end; var ChangePreWinState, ChangeAfterWinState: TWindowState; AfterEventProc: TWinStateEventProc; begin AfterEventProc := nil; ChangePreWinState := HookForm.WindowState; case Message.Msg of WM_SIZE: begin case TWMSize(Message).SizeType of SIZE_Maximized: begin AfterEventProc := Maximized; end; SIZE_Minimized: begin AfterEventProc := Minimized; end; SIZE_Restored: begin AfterEventProc := Restored; end; else end; //case TWMSize end; //WM_SIZE: WM_SYSCOMMAND: begin case TWMSysCommand(Message).CmdType of SC_MAXIMIZE: begin Maximizing; end; SC_MINIMIZE: begin Minimizing; end; SC_RESTORE: begin Restoring; end; end; end; //WM_SYSCOMMAND else end; //case Message.Msg {↓WinProcedureは先に処理} if Assigned(FOldFormProc) then FOldFormProc(Message); {↓処理後にイベントを発生させる} if Assigned(AfterEventProc) then AfterEventProc(ChangePreWinState); end; //------------------------------ //------------------------------- //フックしたFormを戻す function TFormWSEvent.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; {------------------------------- //WindowStateイベント発生 機能: 適切なWindowStateが設定されている場合 イベントを発生する FormStateには変更前のFormStateが入っている 備考: 履歴: 2001/09/11 //------------------------------} procedure TFormWSEvent.Maximized(FormState: TWindowState); begin if Assigned(FOnMaximized) then // if (FormState in [wsNormal, wsMinimized]) then FOnMaximized(Self, FormState); end; procedure TFormWSEvent.Minimized(FormState: TWindowState); begin if Assigned(FOnMinimized) then // if (FormState in [wsNormal, wsMaximized]) then FOnMinimized(Self, FormState); end; procedure TFormWSEvent.Restored(FormState: TWindowState); begin if Assigned(FOnRestored) then // if (FormState in [wsMinimized, wsMaximized]) then FOnRestored(Self, FormState); end; procedure TFormWSEvent.Maximizing; begin if Assigned(FOnMaximizing) then begin FOnMaximizing(Self); Sleep(1); end; end; procedure TFormWSEvent.Minimizing; begin if Assigned(FOnMinimizing) then begin FOnMinimizing(Self); Sleep(1); end; end; procedure TFormWSEvent.Restoring; begin if Assigned(FOnRestoring) then begin FOnRestoring(Self); Sleep(1); end; end; //------------------------------ end.