У меня есть приложение 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, 0,
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), 0,
ParentControl.Left + ((ParentControl.Width - Width) div 2),
ParentControl.Top + ((ParentControl.Height - Height) div 3),
Width, Height,
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. Диалог открывается в той же позиции, что и в первый раз.
Это с Delphi 2007, работающим на Windows XP, целевая коробка также работает под управлением Windows XP.