如何获取 MessageDlgPos 维度?

How do I get the MessageDlgPos dimensions?

我想将 MessageBox 放置在相对于字符串网格中的活动单元格的特定位置,使用 MessageDlgPos() 没问题,只是我想防止框 运行 关闭当活动单元格靠近右侧或底部时,屏幕的右侧或底部。我需要的是一种获取盒子尺寸的方法,但我看不到获取这些尺寸的简单方法。有人知道如何不创建我自己的盒子吗?

MessageDlg...() 函数不支持您的请求。在显示对话框之前,对话框的尺寸是未知的,并且您无法直接访问对话框 window 到 query/re-position,除非使用 WH_CBT hook from SetWindowsHookEx().

话虽这么说...

在 Windows 带有 Vcl.Dialogs.UseLatestCommonDialogs=true and Visual Styles enabled, the MessageDlg...() functions call the Win32 TaskDialogIndirect() API to display a message box. You have no control over that dialog's dimensions, so you would have to wait for that dialog to issue a TDN_DIALOG_CONSTRUCTED notification to then query its actual dimensions before it is displayed, so you can then adjust its position as needed. However, the MessageDlg...() functions do not provide access to any of TaskDialogIndirect()'s notifications (TCustomTaskDialog, which is used internally, does have an OnDialogConstructed event, amongst other events). So, if you wanted to reposition this dialog, you would have to call TaskDialogIndirect() yourself with a custom callback function (or, use the VCL's TTaskDialog 包装器的 Vista+ 上。

在 pre-Vista 上,或禁用 [​​=23=] 或视觉样式时,MessageDlg...() 函数通过 Vcl.Dialogs.CreateMessageDialog() 显示自定义 VCL TForm,您可以调用直接,然后根据需要查询、操作和显示返回的 TForm。请务必在使用完后 Free() 它。

自己创建 MessageDlg。添加 OnActivate 或 OnShow 事件。在这个方法中,询问/更改对话框的属性。

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.StdCtrls;

type
  Tfrm = class(TForm)
    btn: TButton;
    procedure btnClick(Sender: TObject);
  private
   procedure OnDlgActivate(Sender: TObject);
  public
    { Public-Deklarationen }
  end;

var
  frm: Tfrm;


implementation

uses
  Vcl.Dialogs, System.TypInfo;

{$R *.dfm}


procedure Tfrm.btnClick(Sender: TObject);
var
  Ldlg  : TForm;
  LiRet : integer;
begin
  Ldlg := CreateMessageDialog('Hallo World!', mtInformation,mbYesNo, mbYes);
  try
    Ldlg.OnActivate := OnDlgActivate;
    LiRet := Ldlg.ShowModal;
  finally
    Ldlg.free;
  end;

end;

procedure Tfrm.OnDlgActivate(Sender: TObject);
var
  Lfrm: TForm;
  LcTxt: string;
begin
  Lfrm  := Sender as TForm;
  LcTxt := Format('%s %sLeft: %d / Top: %d', [Lfrm.ClassName, sLineBreak, Lfrm.Left, Lfrm.Top]);

  ShowMessage(LcTxt);
end;

end.

您可以使用实际的 TTaskDialog。您可以创建自己的版本,添加 TaskDialogConstructed 过程并在 TaskDialogConstructed 过程中获取维度。大致如下。

type
  TTaskDialog = class(Vcl.Dialogs.TTaskDialog)
  protected
    procedure TaskDialogConstructed(Sender: TObject);
  end;

procedure TTaskDialog.TaskDialogConstructed(Sender: TObject);
var
  TaskDialog: TTaskDialog;
  R: TRect;
begin
  TaskDialog := Sender as TTaskDialog;
  Win32Check(GetWindowRect(TaskDialog.Handle, R));
  
  {... Do whatever with R ...}
  
end;
    
function ExecuteTaskDialog(AOwner: TComponent; ATitle, AText: string; ACommonButtons: TTaskDialogCommonButtons = [tcbOK]): integer;
var
  TaskDialog: TTaskDialog;
begin
  TaskDialog := TTaskDialog.Create(AOwner);
  with TaskDialog do
  begin
    Caption := Application.Title;
    Title := ATitle;
    Text := AText;
    MainIcon := tdiNone;
    Flags := Flags + [tfUseHiconMain];
    CommonButtons := ACommonButtons;
    CustomMainIcon.LoadFromResourceName(HInstance, 'MAINICON');
    OnDialogConstructed := TaskDialogConstructed;
    Execute;
    Result := ModalResult;
    Free;
  end;
end;