Delphi Tips 
-----------------------------

0141  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.3
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/24 西坂良幸 編集
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;

参照: [Delphi-ML:12600] [Delphi-ML:24640] <ダイアログ> <Dialogs> <コンポーネント >

[新規作成] [最新の情報に更新]

How To
Lounge
KeyWords


Tips
Delphi
Home
Osamu Takeuchi osamu@big.or.jp