Articles   Members Online:
-Article/Tip Search
-News Group Search over 21 Million news group articles.
Member Area
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Become a Member
-Why sign up!
-Chat Online!
-Indexes NEW!!
-Build your resume
-Find a job
-Post a job
-Resume Search
-Link to us
Visit Embarcadero
Embarcadero Community
Controlling a TCommonDialog window at runtime Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
Delphi 2.x
User Rating
No Votes
# Votes
DSP, Administrator
Reference URL:
			Author: Lou Adler

How can I pop up a dialog like TOpenDialog in the corner of my screen instead of 
the center?


This is kind of a weird one, because normally it's not something you'd consider. 
But take the situation in which you're editing a file and pop up a dialog box. By 
default, Windows dialogs pop up in the center of the screen, essentially blocking 
the view of your work. But to make matters worse, they're modal (which is probably 
a good thing anyway). So, in order to see your work - just in case you need the 
information underneath the dialog - you have to drag them to another location. No 
big deal, just a bit of a hassle.

Knowing this from the user's point of view, what can you do about it as a 
programmer? On the surface, it may seem that you won't be able to do much. The 
dialog boxes in Delphi are descendants of TCommonDialog, which is a standard 
Windows dialog, so direct manipulation with Delphi code isn't possible. Okay, I'm 
writing this article, so you know there's a way. But first, let's look at what 
we're faced with.

TCommonDialog boxes such as TOpenDialog and TSaveDialog are application-modal, 
meaning that when they pop up, your application is inaccessible.
Because of the inaccessibility mentioned above, direct manipulation of the windows 
is impossible.

Given these two factors, what do we do? Well, we go around the back door. And the 
way we'll do this is with a TTimer.

In point one (1), I mentioned that your application is rendered inaccessible when a 
TCommonDialog box pops up to the screen. But that doesn't necessarily mean it's not 
running. Things like a TTimer will still run even if you pop up a modal dialog box. 
With that in mind, all we have to do is start the TTimer before we execute the 
TCommonDialog and have the code in the TTimer's OnTimer event handle finding our 
dialog box and moving it to a new position. Let's look at some code:

1   unit main;
3   interface
5   uses
6     Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
7     ExtCtrls, StdCtrls;
9   type
10    TForm1 = class(TForm)
11      OpenDialog1: TOpenDialog;
12      Button1: TButton;
13      Timer1: TTimer;
14      procedure Button1Click(Sender: TObject);
15      procedure Timer1Timer(Sender: TObject);
16    private
17      { Private declarations }
18      dlgTitle: PChar;
19    public
20      { Public declarations }
21    end;
23  var
24    Form1: TForm1;
26  implementation
27  {$R *.DFM}
29  procedure TForm1.Button1Click(Sender: TObject);
30  begin
31    Timer1.Enabled := True; {Start the timer}
32    GetMem(dlgTitle, SizeOf(OpenDialog1.Title)); {Get memory for dialog title}
33    StrPCopy(dlgTitle, OpenDialog1.Title); {Fill the space}
34    OpenDialog1.Execute; {Pop up the dialog}
35  end;
37  procedure TForm1.Timer1Timer(Sender: TObject);
38  var
39    dlgWnd: HWND;
40    dlgX, dlgY: Integer;
41    dlgRect: TRect;
42  begin
43    dlgWnd := FindWindow('#32770', dlgTitle); {Find the dialog window}
44    if dlgWnd <> 0 then
45    begin
46      {In this next section we're going to get the dimensions of the dialog
47       so that we can use them to put the dialog right in the lower right-
48       hand corner of the screen. 0, 0 in place of the dlgX and dlgY vars
49       will place it where you want it.}
50      GetWindowRect(dlgWnd, dlgRect);
51      dlgX := Screen.Width - (dlgRect.Right - dlgRect.Left);
52      dlgY := Screen.Height - (dlgRect.Bottom - dlgRect.Top);
54      {Set the window's position and kill the timer}
55      SetWindowPos(dlgWnd, 0, dlgX, dlgY, 0, 0, SWP_NOSIZE);
56      Timer1.Enabled := False;
57    end;
59    {Regardless, get rid of this memory allocation. No stinkin' stray pointers}
60    FreeMem(dlgTitle, SizeOf(OpenDialog1.Title));
61  end;
63  end.

The code comments explain everything pretty clearly, so I won't go into details but 
I will tell you that I cheated. I had to ask around to find out what the class 
value for a TOpenDialog box was. However, the nice thing about the 32770 value is 
that it is the class value for all TCommonDialog descendants. Therefore, you can 
use it for all of them. Nice.

As you can see from the code above, I start the timer running before I call the 
execute of the OpenDialog1. Then when the OnTimer event fires off, I look for the 
dialog window using my handy-dandy class value and the title of the dialog that I 
passed into a PChar (because FindWindow will only take a null-terminated string). 
After that, I get the window's dimensions then use them to compute its position 
relative to the screen to put it in the lower right-hand corner of the screen. 
After that, I kill the timer, free unused memory space, and WHAMO! I've got a 
TCommonDialog popping up where I want it and not where Windows will put it.

Are there any down sides to this? The obvious one you'll find when you put this code together is that there is a noticeable flash as the dialog gets moved. This is due in part to the TTimer. I set its interval value to 50ms; a lower value would be negligible for moving the window in time. The only way to prevent the flash is to get a hook into the Windows workspace and keep it from painting. But that would take a heck of a lot of code to put together; in other words, it's more trouble than it's worth.

Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10


Share this page
Download from Google

Copyright © Mendozi Enterprises LLC