加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 如何定位TOpenDialog

发布时间:2020-12-15 09:06:03 所属栏目:大数据 来源:网络整理
导读:我有一个Delphi应用程序,它使用TOpenDialog让用户选择一个文件.默认情况下,打开的对话框以当前监视器为中心显示,现在可以离应用程序窗口“英里”.我希望对话框以TOpenDialog的所有者控件为中心显示,如果失败了,我会选择应用程序的主窗口. 以下代码类型的工作
我有一个Delphi应用程序,它使用TOpenDialog让用户选择一个文件.默认情况下,打开的对话框以当前监视器为中心显示,现在可以离应用程序窗口“英里”.我希望对话框以TOpenDialog的所有者控件为中心显示,如果失败了,我会选择应用程序的主窗口.

以下代码类型的工作,它是从TJvOpenDialog派生的,它给了我一些如何做到的提示:

type
  TMyOpenDialog = class(TJvOpenDialog)
  private
    procedure SetPosition;
  protected
    procedure DoFolderChange; override;
    procedure WndProc(var Msg: TMessage); override;
  end;

procedure TMyOpenDialog.SetPosition;
begin
var
  Monitor: TMonitor;
  ParentControl: TWinControl;
  Res: LongBool;
begin
  if (Assigned(Owner)) and (Owner is TWinControl) then
    ParentControl := (Owner as TWinControl)
  else if Application.MainForm <> nil then
    ParentControl := Application.MainForm
  else begin
    // this code was already in TJvOpenDialog
    Monitor := Screen.Monitors[0];
    Res := SetWindowPos(ParentWnd,Monitor.Left + ((Monitor.Width - Width) div 2),Monitor.Top + ((Monitor.Height - Height) div 3),Width,Height,SWP_NOACTIVATE or SWP_NOZORDER);
    exit; // =>
  end;
  // this is new
  Res := SetWindowPos(GetParent(Handle),ParentControl.Left + ((ParentControl.Width - Width) div 2),ParentControl.Top + ((ParentControl.Height - Height) div 3),SWP_NOACTIVATE or SWP_NOZORDER);
end;

procedure TMyOpenDialog.DoFolderChange
begin
  inherited DoFolderChange;  // call inherited first,it sets the dialog style etc.
  SetPosition;
end;

procedure TMyOpenDialog.WndProc(var Msg: TMessage);
begin
  case Msg.Msg of
    WM_ENTERIDLE: begin
      // This has never been called in my tests,but since TJVOpenDialog
      // does it I figured there may be some fringe case which requires
      // SetPosition being called from here.
      inherited; // call inherited first,it sets the dialog style etc.
      SetPosition;
      exit;
    end;
  end;
  inherited;
end;

“有点工作”意味着第一次打开对话框时,它会以所有者表单为中心显示.但是,如果我然后关闭对话框,移动窗口并再次打开对话框,SetWindowPos似乎没有任何效果,即使它确实返回true.对话框在第一次打开的位置打开.

这是在Windows XP上运行的Delphi 2007,目标框也运行Windows XP.

解决方法

TJvOpenDialog是TOpenDialog的后代,因此您应该在VCL居中对话后运行您的展示位置调用. VCL在响应CDN_INITDONE通知时执行此操作.响应WM_SHOWWINDOW消息太早了,在我的测试中,窗口过程从不接收WM_ENTERIDLE消息.

uses
  commdlg;

[...]

procedure TJvOpenDialog.DoFolderChange;
begin
  inherited DoFolderChange;  
//  SetPosition; // shouldn't be needing this,only place the dialog once
end;

procedure TJvOpenDialog.WndProc(var Msg: TMessage);
begin
  case Msg.Msg of
    WM_NOTIFY: begin
      if POFNotify(Msg.LParam)^.hdr.code = CDN_INITDONE then begin
        inherited;    // VCL centers the dialog here
        SetPosition;  // we don't like it ;)
        Exit;
      end;
  end;
  inherited;
end;

要么,

procedure TJvOpenDialog.WndProc(var Msg: TMessage);
begin
  case Msg.Msg of
    WM_NOTIFY: if POFNotify(Msg.LParam)^.hdr.code = CDN_INITDONE then
                 Exit;
  end;
  inherited;
end;

有了操作系统所说的对话框,它实际上是有意义的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读