Can I change the position of standard dialogs in C-Builder?
e. g.:
There is a form with a TOpenDialog OpenInputFile;
if I use the command "OpenInputFile->Show ();", the dialog is placed
right in the middle of my screen.
Can I force C-Builder / Windows to put this dialog at another place, f.
i. top left or at a specified point?
I am using C-Builder 4, NT 4.0
thanks
Robert
> if I use the command "OpenInputFile->Show ();", the
> dialog is placed right in the middle of my screen.
You shold not be calling Show() directly. Use Execute() instead:
OpenInputFile->Execute()
> Can I force C-Builder / Windows to put this dialog at
> another place, f.i. top left or at a specified point?
The dialog is controlled by the OS itself, not the VCL. You can try using
the OnShow event to manualy move the underlying dialog window itself using
MoveWindow(). TOpenDialog inherits a Handle property that is the HWND for
the dialog.
Gambit
Anybody who has already done it?
I would appreciate a few lines of C++ code for this problem?
Robert
Please show your actual code.
You may have to call GetParent() to get the true HWND for the dialog.
Gambit
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
OpenDialog1->FileName = "doc.c";
if (OpenDialog1->Execute())
{
// Place your code here
}
}
void __fastcall TForm1::OpenDialog1SelectionChange(TObject *Sender)
{
MoveWindow(
FindWindow(NULL, "Open"), // handle of window
0, // horizontal position
0, // vertical position
800, // width
300, // height
true // rep
);
}
"God not only plays dice with the universe, and sometimes throws them where
they cannot be seen, but also his dice are sometimes loaded" Rodolfo, 2003
"Robert Schimpfle" <schi...@uni-trier.de> wrote in message
news:3FA01311...@uni-trier.de...
> FindWindow(NULL, "Open"), // handle of window
That will not work if the TOpenDialog has its Title property set.
Gambit
char DialogTitle[] = "DefineSomeTitleHere";
FindWindow(NULL, DialogTitle ), // handle of window
"Human language is an extraordinary invention, despite of being so old it is
highly undefined" Rodolfo, 2003
"Remy Lebeau (TeamB)" <gambit47...@no.spam.yahoo.com> wrote in message
news:3fa1a188$1...@newsgroups.borland.com...
> FindWindow(NULL, DialogTitle ), // handle of window
Better to just use the actual Title:
if( !OpenDialog1->Title.IsEmpty() )
FindWindow(NULL, OpenDialog1->Title.c_str() )
else
FindWindow(NULL, "Open" )
Now, with that said, using the OnShow event is too soon to move the dialog,
and using the OnSelectionChanged event is too late to prevent the dialog
from noticably flickering from one position to another. The following code
works for me in delaying the moving while also hiding the flickering:
#define APPWM_MOVE_OPENDIALOG (WM_APP + 100)
void __fastcall TForm1::Button1Click(TObject *Sender)
{
OpenDialog1->Execute();
}
void __fastcall TForm1::OpenDialog1Show(TObject *Sender)
{
SendMessage(GetDesktopWindow(), WM_SETREDRAW, FALSE, 0);
PostMessage(Handle, APPWM_MOVE_OPENDIALOG, 0, 0);
}
void __fastcall TForm1::WndProc(TMessage &Message)
{
if( Message.Msg == APPWM_MOVE_OPENDIALOG )
{
SetWindowPos(GetParent(OpenDialog1->Handle), NULL,
Message.WParam, Message.LParam, 0, 0, SWP_NOSIZE|SWP_NOZORDER);
SendMessage(GetDesktopWindow(), WM_SETREDRAW, TRUE, 0);
InvalidateRect(NULL, NULL, TRUE);
Message.Result = TRUE;
}
else
TForm::WndProc(Message);
}
Gambit
TOpenDialog* OpenDialog1;
String DlgTitle;
HWND H;
//--------------------------------------------------------------------------
-
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
//CREATE OPENDIALOG --------------------------------------------
OpenDialog1 = new TOpenDialog(this);
OpenDialog1->Title = "This is the Title";
DlgTitle = OpenDialog1->Title;
OpenDialog1->OnShow = OpenDialog1Show;
OpenDialog1->OnSelectionChange = OpenDialog1SelectionChange;
OpenDialog1->Options.Clear();
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
OpenDialog1->FileName = "doc.c";
if (OpenDialog1->Execute())
{
// Place your code here
}
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::OpenDialog1Show(TObject *Sender)
{
H = FindWindow(NULL, DlgTitle.c_str());
MoveWindow(H, 0, 0, 0, 0, false);
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::OpenDialog1SelectionChange(TObject *Sender)
{
MoveWindow(H, 0, 0, 800, 300, true);
}
//--------------------------------------------------------------------------
-
"Programming is the art of picking a needle out of a hayheap." Rodolfo,
2003
What do the Options have to do with anything? The option settings that are
enabled by default are ofHideReadOnly and ofEnableSizing, neither of which
effect the dialog's ability to be moved.
> OpenDialog1->Options.Clear();
You cannot clear the Options like that. You are modifying a temporary
value, not the original property value. Just like with other Set
operations, you need to use the '=' assignment operation instead, ie:
OpenDialog1->Options = TOpenOptions();
> void __fastcall TForm1::OpenDialog1Show(TObject *Sender)
> {
> H = FindWindow(NULL, DlgTitle.c_str());
> MoveWindow(H, 0, 0, 0, 0, false);
> }
I have already determined that you cannot move the dialog from the OnShow
event. That is why my earlier example had to delay the movement. OnShow is
triggered during the handling of the WM_INITDIALOG message, however
TOpenDialog internally repositions the dialog during the handling of the
CDN_INITDONE notification later on, thus cancelling out any movements you do
in the OnShow event.
> void __fastcall TForm1::OpenDialog1SelectionChange(TObject *Sender)
> {
> MoveWindow(H, 0, 0, 800, 300, true);
> }
I guess you missed the point of my earlier example - the OnSelectionChange
event is triggered well after the dialog has become visible, so the user
sees the dialog appear in the middle of the screen and then move to the
coordinates seconds later. Which even you said earlier was an ugly effect
:-p Thus my use of disabling the dekstop's ability to update the screen
while the dialog is being moved, so the user won't see it happen.
Gambit
However, I replaced that line with the one that you posted
OpenDialog1->Options = TOpenOptions(); // Statement 1
The first dialog is not shown because of two things
1- In the OpenDialog1Show event handler the dimensions of the first dialog
are zero
MoveWindow(H, 0, 0, 0, 0, false);
2- If we don't use the Statement 1, we will see the title bar of the first
dialog (with no dialog's client area
because the dimensions are 0). So we clear the options to remove the menu
bar. However, I
did not investigate any further as to see why.
As a result I can only see one dialog box, the one corresponding to the call
in
the OpenDialog1SelectionChange event handler.
MoveWindow(H, 0, 0, 800, 300, true);
The only thing that I noticed is a small flickering of the Parent form (The
one that contaoins the BitBtn)
immediatly before the creation of the Dialog which I think is negligible
(althogh you might think it isn't)
Please, run the program and you will see that there is only one dialog
visible.
TForm1 *Form1;
TOpenDialog* OpenDialog1;
String DlgTitle;
HWND H;
//--------------------------------------------------------------------------
-
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
//CREATE OPENDIALOG --------------------------------------------
OpenDialog1 = new TOpenDialog(this);
OpenDialog1->Title = "This is the Title";
DlgTitle = OpenDialog1->Title;
OpenDialog1->OnShow = OpenDialog1Show;
OpenDialog1->OnSelectionChange = OpenDialog1SelectionChange;
OpenDialog1->Options = TOpenOptions(); //<<================== Replaced
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
OpenDialog1->FileName = "doc.c";
if (OpenDialog1->Execute())
{
// Place your code here
}
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::OpenDialog1Show(TObject *Sender)
{
H = FindWindow(NULL, DlgTitle.c_str());
MoveWindow(H, 0, 0, 0, 0, false); //<<==== Notice NILL dimensions
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::OpenDialog1SelectionChange(TObject *Sender)
{
MoveWindow(H, 0, 0, 800, 300, true); //<<==== Wanted dimensions
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::BitBtn2Click(TObject *Sender)
{
//
OpenDialog2->FileName = "doc.c";
if (OpenDialog2->Execute())
{
// Place your code here
}
}
Rodolfo
And how many times have Borland's examples and documentation been proven
wrong? Too many times.
> 1- In the OpenDialog1Show event handler the dimensions
> of the first dialog are zero
I did not notice earlier that you were shrinking the dialog to 0 dimensions.
However, you should not just pick an arbitrary size for the new dimensions
when re-displaying the dialog later. I ran your example, and upon
re-showing the dialog, it took up half my screen, and half of the dialog was
empty. Very ugly.
Also, there's still no need to use FindWindow(), calling GetParent() on the
OpenDialog's Handle returns the same HWND that FindWindow() would have
found, and is a lot less error-prone to find the wrong window by accident
:-)
> Please, run the program and you will see that there is only one dialog
> visible.
My screen still flickers when I run your code. Whatever window is currently
on top (including the desktop itself in case everything is minimized) when
the dialog is displayed, it is repainted in full upon displaying the dialog.
I'm still sticking with my earlier example, for a few extra lines of code it
produced a cleaner effect for the user.
> OpenDialog1 = new TOpenDialog(this);
I am wondering, why do you keep showing examples that dynamically create
everything at runtime instead of using the form designer at designtime?
Gambit
I know that there is a little bit a flickering I mentioned it in my previous
post.
I didn't say that the example is perfect :-)
> > OpenDialog1 = new TOpenDialog(this);
>
> I am wondering, why do you keep showing examples that dynamically create
> everything at runtime instead of using the form designer at designtime?
There are several reasons. One of them is that, in general, the user can see
exactly all the components
on the form and their properties without posting extra files. Never develop
any form at design time.
Do everything at runtime is less error-prone. Imagine that you develop a
complex mainform at designtime.
Then, one day you open the project and by mistake you change the value of
some properties in your Object
Inspector without realizing. Then you recompile your project and now your
program has got different values
for one or more properties and your program runs but does not behave the way
you intended to.
If you design each and every form at runtime these type of error will never
take effect, since your
program will set the properties at runtime, overriding any values entered in
the Object Inspector by accident.
"Computers are machines that make us think that they could think one
unthinkable day"
Rodolfo, 2003
This is more or less an established technology. In fact, the VCL has
to do the centering itself in the earlier versions of Windows and BCB.
Here's a page that simply answers your question:
http://thunder.prohosting.com/~cbdn/cd002.htm
If you derive your own descendant, you can override DoShow. Here's a
more complicated example of that:
http://home.att.net/~secondcut/opdlgvcl.htm
--
Timothy H. Buchman
========================================
City Center Theater, New York NY
mail address tbuchmanPLEASE(at sign)REMOVEcitycenterD O Torg
Search .borland message archive on http://www.mers.com/searchsite.html
That won't work. Can I suggest the following modification to the code
shown on the above link:
#include <vcl.h>
#pragma hdrstop
#include "MoveWindow.h"
//--------------------------------------------------------------------------
-
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
TOpenDialog* OpenDialog1;
String DlgTitle;
//--------------------------------------------------------------------------
-
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
//CREATE OPENDIALOG --------------------------------------------
OpenDialog1 = new TOpenDialog(this);
OpenDialog1->Title = "Title";
DlgTitle = OpenDialog1->Title;
OpenDialog1->OnShow = OpenDialog1Show;
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
OpenDialog1->FileName = "doc.c";
if (OpenDialog1->Execute())
{
// Place your code here
}
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::OpenDialog1Show(TObject *Sender)
{
TRect rect;
HWND H = GetParent(dynamic_cast<TOpenDialog*>(Sender)->Handle);
GetWindowRect(H, &rect);
MoveWindow(H,
0, // put your coordinate here as required
0, // put your coordinate here as required
rect.right - rect.left,
rect.bottom - rect.top,
true);
Abort();
}
Ah, by the way a short message for Remy: here there is no flickering
and also this is the simplest solution :-)
Rodolfo
Rodolfo