TOpenDialogで、Executeメソッド実行時に表示位置を変えたい。
|
TOpenDialogは、OnShowイベントの段階では、位置がすでに決まっているようです。調べてみると、何回かWM_NOTIFYが送られますが、NMHDR構造体のCodeメンバーがCDN_INITDONEになるダイアログの初期化時を捕まえるとうまくいくようです。(ただし、これでも最初のExecute時しか効果ありません。D4のみ?)
以下のような拡張ダイアログコンポが紹介されています。
// 定義部
type
TQueryDlgPosEvent = procedure(Sender: TObject; var pt: TPoint) of object;
ThtOpenDialogEx = class(TOpenDialog)
private
FQueryDlgPos: TQueryDlgPosEvent;
protected
procedure DefaultHandler(var Message); override;
procedure DoQueryDlgPos; virtual;
published
property OnQueryDlgPos: TQueryDlgPosEvent read FQueryDlgPos write FQueryDlgPos;
end;
// 実装部n
procedure ThtOpenDialogEx.DefaultHandler(var Message);
begin
inherited;
with TWMNotify(Message) do
if (Msg = WM_NOTIFY) then
if (NMHdr^.Code = CDN_INITDONE) then
DoQueryDlgPos;
end;
procedure ThtOpenDialogEx.DoQueryDlgPos;
var
DlgHandle: THandle;
Rect: TRect;
pt: TPoint;
begin
if Assigned(FQueryDlgPos) then
begin
DlgHandle := GetParent(Handle);
GetWindowRect(DlgHandle, Rect);
pt.x := (GetSystemMetrics(SM_CXSCREEN) - Rect.Right + Rect.Left) div 2;
pt.y := (GetSystemMetrics(SM_CYSCREEN) - Rect.Bottom + Rect.Top) div 3;
FQueryDlgPos(Self, pt);
SetWindowPos(DlgHandle, HWND_TOP, pt.X, pt.Y, 0, 0,
SWP_NOSIZE or SWP_NOZORDER);
end;
end;
// テスト
procedure TForm1.Button1Click(Sender: TObject);
var
OpenDialogEx:ThtOpenDialogEx;
begin
OpenDialogEx:=ThtOpenDialogEx.Create(self);
try
with OpenDialogEx do
begin
OnQueryDlgPos := QueryDlgPos;
Execute;
end;
finally
OpenDialogEx.Free;
end;
end;
procedure TForm1.QueryDlgPos(Sender: TObject; var pt: TPoint);
begin
Pt.x := 800;
pt.y := 600;
end;
追記:
DefaultHandlerメソッドのかわりに、WndProcメソッドをオーバーライドしてもほぼ同じ結果が得られます。
以下は、イベントの代わりに、InitialLeft, InitialTop、というプロパティを設定しています。
procedure ThtOpenDialogEx.WndProc(var Message: TMessage);
var
DlgHandle: THandle;
begin
inherited WndProc(Message);
if (Message.Msg = WM_NOTIFY) then
if (TWMNOTIFY(Message).NMHdr^.Code = CDN_INITDONE)
and not ((FInitialLeft < 0) or (FInitialTop < 0)) then
begin // 負数のときは処理しない
DlgHandle := GetParent(Handle);
SetWindowPos(DlgHandle, 0, FInitialLeft, FInitialTop, 0, 0, SWP_NOSIZE or SWP_NOZORDER);
end;
end;
|
|