tags:

views:

291

answers:

3

The default position of TSaveDialog is the center of the screen. How to set the position of the TSaveDialog window? I want something like that:

SaveDialog1.top := topValue;
SaveDialog1.left := leftValue;
if (SaveDialog1.execute(self.handle)) then begin
  ...
end;
A: 

Have a look here.

Ulrich Gerhardt
In this solution is the same problem as in the next solution. The position is set correctly once at the first dialog show. But following dialog show doesn't change position. The dialog is still on the same first set position.
+2  A: 

I found sample for this at this page, but I have modified it to work with exiting TSaveDialog instead of creating new class.

type
 TSaveDialog = class(Dialogs.TSaveDialog)
   protected
      fTop: integer;
      fLeft: integer;
      procedure WndProc(var Message: TMessage); override;
   public
      property top: integer read fTop write fTop;
      property left: integer read fLeft write fLeft;
   end;

type
  TForm1 = class(TForm)
    dlgSave1: TSaveDialog;
    btn1: TButton;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;


var
  Form1: TForm1;

implementation

{$R *.dfm}
uses
  CommDlg;

procedure TForm1.btn1Click(Sender: TObject);
begin
  dlgSave1.left := 20;
  dlgSave1.top := 100;
   if dlgSave1.Execute then
   // do your work here
end;

{ TMySaveDialog }

procedure TSaveDialog.WndProc(var Message: TMessage);
begin
  inherited WndProc(Message);
  if (Message.Msg = WM_NOTIFY) then
      case (POFNotify(Message.LParam)^.hdr.code) of
           CDN_INITDONE: SetWindowPos(POFNotify(Message.LParam)^.hdr.hwndFrom, 0, fLeft, fTop, 0, 0, SWP_NOSIZE);
      end;
end;
Mohammed Nasman
it was my question on that page. But this solution is not complete. Because the position is set only once at the begining. Second or third setting of position failed.
Isn't setting it *once* enough???
Ulrich Gerhardt
I want show the dialog every time in the center of the main form. Example of the problem: the user closes the save dialog, then move the main form and then open again the save dialog => in this point I'm not able to move the save dialog to the center of the main form.
+1  A: 

The GetSaveFileName API function, which is what TSaveDialog is a wrapper form, doesn't provide any way to control the position of the dialog box, so you need to intercept an early message to the dialog and adjust the position there, as other solutions you've seen have done.

You want the dialog box to be centered over your form, so solutions that provide Top and Left properties for the dialog won't work very well since they don't take the window's size into account, and they also require you to calculate new coordinates before you call Execute every time.

Here's a different idea. It will still require overriding WndProc.

type
  TCenterSaveDialog = class(TSaveDialog)
  private
    FCenterForm: TCustomForm;
  protected
    procedure WndProc(var Message: TMessage); override;
  public
    // When this property is assigned, the dialog will center
    // itself over the given form each time the dialog appears.
    property CenterForm: TCustomForm read FCenterForm write FCenterForm;
  end;

procedure TCenterSaveDialog.WndProc(var Message: TMessage);
var
  lpOfNotify: POFNotify;
  FormRect, DialogRect: TRect;
  NewLeft, NewTop: Integer;
begin
  inherited;
  if (Message.Msg = wm_Notify) and Assigned(CenterForm) then begin
    lpOfNotify := POFNotify(Message.LParam);
    if lpOfNotify.hdr.code = cdn_InitDone then begin
      GetWindowRect(CenterForm.Handle, FormRect);
      GetWindowRect(lpOfNotify.hdr.hwndFrom, DialogRect);
      NewLeft := FormRect.Left
        + (FormRect.Right - FormRect.Left) div 2
        - (DialogRect.Right - DialogRect.Left) div 2;
      NewTop := FormRect.Top
        + (FormRect.Bottom - FormRect.Top) div 2
        - (DialogRect.Bottom - DialogRect.Top) div 2;
      SetWindowPos(lpOfNotify.hdr.hwndFrom, 0,
        NewLeft, NewTop, 0, 0,
        swp_NoActivate or swp_NoOwnerZOrder or swp_NoSize or swp_NoZOrder);
    end;
  end;
end;

See also: cdn_InitDone

Rob Kennedy