?
Solved

OpenDialog on top

Posted on 2005-03-24
6
Medium Priority
?
2,025 Views
Last Modified: 2012-08-13

I have an application with multiple forms that need to stay on top
Using help from otehrs here I got it to work...
See this thread ... http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_21274097.html

But now I discovered a problem and can't find a solution

If I have a form that use
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
  inherited;
  with Params do begin
     ExStyle := ExStyle or WS_EX_TOPMOST;
    WndParent := GetDesktopwindow;
  end;
end;

and I open a Dialog such as TOpenDialog , the first time it works well and show on top, but if I close the dialog and re-open it, then it show under the other form...

I've try to do this but it won't help

procedure TForm1r.OpenDialog1Show(Sender: TObject);
begin
      SetWindowPos(OpenDialog1.handle,HWND_TOPMOST, 0,0,0,0, SWP_NOSIZE or SWP_NOMOVE);
End;

Thanks for your help!
0
Comment
Question by:PaulP
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
6 Comments
 
LVL 17

Expert Comment

by:geobul
ID: 13621874
Hi,

Try this way:

    with Application do begin
         NormalizeTopMosts; // or NormalizeAllTopMosts;
         // your code for opening the dialog here
         if OpenDialog1.Execute then begin
           ...
         end;
         RestoreTopMosts;
      end;

Regards, Geo
0
 

Author Comment

by:PaulP
ID: 13622185
Humm that doesn't work... in factm now the dialog alwasy show at the back even on the first time....

It  seems that this
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
  inherited;
  with Params do begin
     ExStyle := ExStyle or WS_EX_TOPMOST;
    WndParent := GetDesktopwindow;
  end;
end;

Solve one main issue I had, but cause some other issue...

0
 
LVL 34

Accepted Solution

by:
Slick812 earned 1000 total points
ID: 13627302
You have removed your form from the Delphi normal order of Forms, so you will have problems, when it reorders the Forms when dialogs show and other stuff. . . .
You can use an Open Dialog box created by API, and it will be infront of whatever window you assign as it's parent,
Here is a unit called DlgOpenSave.pas, that I often use, it has a function called    OpenSavDlg( )   which will return a string of the file name the user chooses. .
it is used like this -



var
fName: String;

begin
{this uses the DlgOpenSave unit. The OpenSavDlg function
 creates a system open-save dialog and returns the file path the user
       picked from the dialog}
fName := OpenSavDlg(Form2.Handle,'','',True);
      // this has empty strings in it's parameters to get the default settings

if fName = '' then
    fName := 'User Canceled'
ShowMessage(fName);

// - - - - - - -
{ the next does more to set the Open Dialog}

fName := ExtractFileName(ParamStr(Zero));
fName := ChangeExt(fName,'.DPR');
fName := fName+'  File'#0+fName+#0'Meta Files .?MF'#0'*.?mf'#0+
            'Other files, WAV,DOC,BMP'#0+'*.wav;*.doc;*.bmp'#0'All files'#0'*.*'#0#0;
{WARNING !
you can NOT use any normal delphi string modifiers, like + , after you add the
Null #0, if you do use the + operator, the string will be CUT OFF at the first #0.
so you should do all of your string modificatons before you add the #0}

fName := OpenSavDlg(Form2.Handle,ExtractFilePath(ParamStr(Zero)), fName, True);

if fName = '' then
    fName := 'User Canceled'
ShowMessage(fName);

end;


 = = = = = = = =  = = = = = = = = =  = = =

code for unit - -



unit DlgOpenSave;
{this Unit has three functions to create system Open-Save Dialogs}

interface

uses Windows;

type
  { TDlgOptions are the 11 members which control the dialog creation Flags
     in the TDlgSetUp-record Options set}
  TDlgOptions = (doSave, doReadOnlyCB, doCheckRead, doFileExist,
                 doPathExist, doOverWrite, doCreatePompt, doLinks,
                 doNoChangeDir, doTrackFolder, doCusFilter);

  TDlgSetUp = record // used for dialog Settings in the OpenDlgOpt function
    hOwner: Cardinal; // replaced with the Filter Index when OpenDlgOpt returns
    iniDirPath, iniFileName, Filter, Title, DefExt: String;
    // the four strings above are optional
    Options: Set of TDlgOptions;
    end;

{setting the Options Set to include a TDlgOptions -
doSave - Makes a Save dialog, otherwize an Open dialog is shown
doReadOnlyCB - will show the Read-Only check box at bottom of dialog
doCheckRead - will check the read-Only check box, included in Option if user checks
doFileExist - system checks to see if file name exists, then asks user
doPathExist - system checks to see if file path exists, then asks user
doOverWrite - if file name exists, asks user if OK to over-write
doCreatePompt - if file name does not exist, asks if OK to create file
doLinks - will return the link .lnk file name, instead of the file it is linked to
doNoChangeDir - the current folder will not change with the dialog folder
doTrackFolder - places the folder path in the OpenFolder string when dialog closes
doCusFilter - Sets the CustomFilter array to save the user's custom filter}


  TMultiResult = record // result record of the OpenMultiSel function
    fOffSet: Integer; // File Name character off-set in fNames
    fNames: String; // #0 delimited string with multi-FileNames
    end;


// the OpenSavDlg is a simple Open-Save dialog creation function
function OpenSavDlg(hOwner: Cardinal; const iniDirPath, Filter: String;
                    Open: BOOL): String;

// the OpenDlgOpt can set many more dialog options with the DlgSetUp record
function OpenDlgOpt(var DlgSetUp: TDlgSetUp; FilterIndex: Cardinal = 1): String;

// the OpenMultiSel is a Multi-Selection Open dialog that returns a TMultiResult
function OpenMultiSel(hOwner: Cardinal; const iniDirPath, Filter,
                      Title: String): TMultiResult;

var
OpenFolder: String = 'C:'; // contains the Last Open Folder if doTrackFolder
CustomFilter: Array[0..511] of Char; // records the user custom filter if doCusFilter


implementation

uses Messages, CommDlg, SmallUtils;

const
Zero = 0;
One = 1;

All_Files: PChar = 'All files'#0'*.*'#0;



function OpenSavDlg(hOwner: Cardinal; const iniDirPath, Filter: String;
                    Open: BOOL): String;
var
OFName : TOpenFileName;
FileName: Array[Zero..2047] of Char;
begin
// basic open-save dialog creation
ZeroMemory(@FileName, SizeOf(FileName));
ZeroMemory(@OFName, SizeOf(OFName));

with OFName do
  begin
  lStructSize := sizeof(ofName);
  hwndowner := hOwner;
  nMaxFile := SizeOf(FileName);
  lpstrFile := @FileName;
  nFilterIndex := One;
  if Length(iniDirPath) > One then
    lpstrInitialDir := PChar(iniDirPath)
    else
    lpstrInitialDir := PChar(GetFilePath(ParamStr(Zero)));

  if Length(Filter) < 4 then
    lpstrFilter := All_Files
    else
    lpstrFilter := PChar(Filter);

  if Open then
    Flags := OFN_EXPLORER or OFN_FILEMUSTEXIST or OFN_HIDEREADONLY
    else
    Flags := OFN_EXPLORER or OFN_PATHMUSTEXIST or OFN_OVERWRITEPROMPT or
               OFN_HIDEREADONLY;
  end;

Result := '';
if Open then
  begin
  if GetOpenFileName(OFName) then
    Result := FileName;
  end else
  if GetSaveFileName(OFName) then
    Result := FileName;
end;



function OpenDlgOpt(var DlgSetUp: TDlgSetUp; FilterIndex: Cardinal = One): String;
const
// this FlagValues holds some of the constants for the OFName.Flags
FlagValues: array[TDlgOptions] of Cardinal = (Zero, Zero, OFN_READONLY,
                  OFN_FILEMUSTEXIST, OFN_PATHMUSTEXIST, OFN_OVERWRITEPROMPT,
                  OFN_CREATEPROMPT, OFN_NODEREFERENCELINKS,
                  OFN_NOCHANGEDIR, {OFN_EXTENSIONDIFFERENT, }Zero, Zero);
var
OFName : TOpenFileName;
FilePath: Array[Zero..2047] of Char;
i: TDlgOptions;

  procedure SetResult;
  begin
  //this procedure is used to set Result for both the Open and Save dialogs
  Result := FilePath;
  DlgSetUp.hOwner := OFName.nFilterIndex; { place the current Filter Index
                 into the hOwner incase you need to reset it to user's Index}

  // the doTrackFolder will record the folder path, so you can open the next
  // open-save Dlg in the same folder as the last open save
  if doTrackFolder in DlgSetUp.Options then
    OpenFolder := GetFilePath(Result);
  {the OFName.Flags will have the OFN_READONLY bit if the check box was checked}
  if OFName.Flags and OFN_READONLY <> Zero then
    DlgSetUp.Options := [doCheckRead];
  end;


begin
{this is a more flexable open dlg function, it has a TDlgSetUp record to
change the dialog with Owner, Title, Filter and other Options}
ZeroMemory(@FilePath, SizeOf(FilePath));
ZeroMemory(@OFname, SizeOf(OFName));

with OFName, DlgSetUp do
  begin
  lStructSize := sizeof(OFName);
  hwndOwner := hOwner; // the owner is set to DlgSetUp.hOwner
  nMaxFile := SizeOf(FilePath);
  lpstrFile := @FilePath;
  if Length(iniFileName) > One then
    StrCopy(lpstrFile, PChar(iniFileName)); // set first file name here

  if Length(iniDirPath) > One then
    lpstrInitialDir := PChar(iniDirPath)
    else // set default initial Folder to this programs folder
    lpstrInitialDir := PChar(GetFilePath(ParamStr(0)));

  if length(Filter) < 4 then
    lpstrFilter := All_Files
    else
    lpstrFilter := PChar(Filter);
  nFilterIndex := FilterIndex;

  if length(Title) > Zero then
    lpstrTitle := PChar(Title); // set dlg Title to OpenSet.Title

  if length(DefExt) > One then
    lpstrDefExt := PChar(DefExt);{lpstrDefExt will automatically add that file
                                    ext to a file name with no ext}

  Flags := OFN_EXPLORER or OFN_ENABLESIZING or OFN_HIDEREADONLY;
  // start with default Flags for Explorer, Sizing and no CheckBox
  if Options * [doCheckRead..doNoChangeDir] <> [] then
    for i := doCheckRead to doNoChangeDir do
      if i in Options then
        Flags := Flags or FlagValues[i];
  // the for loop above will place flag values in FlagValues array
  // into the OFName.Flags if that option is in the set

  if doReadOnlyCB in Options then // take out the read only checkbox
      Flags := Flags and (not OFN_HIDEREADONLY);

  if doCusFilter in Options then
    begin // make a Custom Filter recorder availible
    lpstrCustomFilter := @CustomFilter;
    nMaxCustFilter := SizeOf(CustomFilter);
    end;

  Exclude(Options, doCheckRead); // Take out the Check Read option
  end;

Result := '';
if doSave in DlgSetUp.Options then
  begin
  if GetSaveFileName(OFName) then
    SetResult; // places the file path into Result
  end else
  if GetOpenFileName(OFName) then
    SetResult;

end;


function OpenMultiSel(hOwner: Cardinal; const iniDirPath, Filter,
                      Title: String): TMultiResult;
var
OFName : TOpenFileName;
begin
{this will create a Multi-Selection Open Dialg box, and the Result of this
 function is a TMultiResult record, which has the file-name OffSet as the
 fOffSet element, used to extract the file names from the #0 delimited result
 string in Result.fNames}
SetLength(Result.fNames, 3070); // larger file name buffer for multi files
ZeroMemory(@Result.fNames[One], Length(Result.fNames));
Result.fOffSet := -1; // set Result.fOffSet to an error result of -1
ZeroMemory(@OFName, SizeOf(OFName));

with OFName do
  begin
  lStructSize := sizeof(OFName);
  hwndowner := hOwner;
  hInstance := SysInit.hInstance;
  nMaxFile := Length(Result.fNames);
  lpstrFile := PChar(Result.fNames);
// adding the OFN_ALLOWMULTISELECT flag bit will change the file-path string return
  Flags := OFN_ALLOWMULTISELECT or OFN_EXPLORER or OFN_FILEMUSTEXIST or
           OFN_ENABLESIZING or OFN_HIDEREADONLY;
  if Length(Filter) < 4 then
    lpstrFilter := All_Files
    else
    lpstrFilter := PChar(Filter);
  lpstrTitle := PChar(Title);
  nFilterIndex := One;
  lpstrInitialDir:= PChar(iniDirPath);
  end;

if GetOpenFileName(OFName) then
  Result.fOffSet := OFName.nFileOffset // set fOffSet to the file name offset
  else
  Result.fNames := '';

end;

initialization
CustomFilter := 'Your Filter'#0'*.*'#0#0;

end.

 = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

ask questions if you need more
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:PaulP
ID: 13646456
Hello Slick!

Thanks for this Open/Save dialog code... workls well!

But I need an example on how to use the MultiSelect...

I'm not sure on the best method to extract the filename... from the MultiResult.fname

Thanks!
0
 
LVL 34

Expert Comment

by:Slick812
ID: 13649588
OK, the OpenMultiSel( ) function returns a TMultiResult, with a #0 delimited text string in  fNames, and the fOffSet will have the offset to the first file name,. You will need to transverse through all the file names and extract them, using PChar methods is the best way I think, as in this code -

procedure DoMultiFile;
var
MultiRe: TMultiResult;
filePath: String;
pFileName: PChar;
begin
{the OpenMultiSel function uses a Multi-Selection dialog, the Result
 string is different than a normal open dialog, it has null #0 delimited
 file path and names}
MultiRe := OpenMultiSel(hForm1, 'C:\Stuff', 'Text files  .TXT'#0'*.txt'+
              #0'All files'#0'*.*'#0#0,'Open more than One File, Multi-Select');
{a TMultiResult is the result form a OpenMultiSel, the fOffSet will be
 -1 if it fails, or the File-Name charater offset if it succeeds}
if MultiRe.fOffSet <> -1 then
  begin
  // I list the file name in the hListBox1 List Box
  SendMessage(hListBox1, LB_RESETCONTENT, Zero, Zero);
  SetString(filePath, PChar(MultiRe.fNames), MultiRe.fOffSet-1);
  { the Folder path is in the first section of the MultiRe.fNames
   MultiRe.fNames is several #0 delimited only if more than one file
   I use SetString( ) with the MultiRe.fOffSet-1 number to know it's length

   if there is only ONE file name, the result string will not have #0
   delimters, I test for the #0 delimter at MultiRe.fOffSet}
  if MultiRe.fNames[MultiRe.fOffSet] <> #0 then // true if single file name
    begin
    SendMessage(hListBox1, LB_ADDSTRING, Zero,
                Integer(@MultiRe.fNames[MultiRe.fOffSet+1]));
    // the list box will add single string above using the file name offset
    end else
    begin
    pFileName := StrEnd(PChar(MultiRe.fNames));
    // StrEnd will get the #0 delimiter
    Inc(pFileName); // move to character after #0
    while pFileName^ <> #0 do // loop until there are two #0
      begin
      // add #0 terminated file name to list box
      SendMessage(hListBox1, LB_ADDSTRING, Zero, Integer(pFileName));
      pFileName := StrEnd(pFileName);
      Inc(pFileName);
      end;
    end;
  end else filePath := 'User Canceled or Error'; // MultiRe.fOffSet = -1
end;


 - - - - - - - - - - - - - - - - - - - - - - - - - - - -

if you need to use delphi methods, you can change

 SendMessage(hListBox1, LB_ADDSTRING, Zero, Integer(pFileName));

to ( using a TStringList as StringList1)

StringList1.Add(pFileName);
0
 
LVL 34

Expert Comment

by:Slick812
ID: 13649601
for the  OpenDlgOpt( ) function -


var
DlgSetUp1: TDlgSetUp;

with DlgSetUp1 do
  begin
  hOwner := Form23.Handle;
  iniDirPath := 'C:\Stuff';
  iniFileName := 'NewFile1.txt';
  Filter := 'Text files  .TXT'#0'*.txt'#0'New Text files,+
            ' NewFile.TXT'#0'NewFile?.txt;NewFile??.txt'#0+
            'All files'#0'*.*'#0#0;
  Title := 'Save Something Else';
  DefExt := '.txt';
  Options := [doSave,doPathExist,doOverWrite,doCusFilter];
  end;
fName := OpenDlgOpt(DlgSetUp1, 2);
if fName <> '' then
  Showmessage(fName);
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…
Suggested Courses
Course of the Month11 days, 3 hours left to enroll

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question