I want to be able to open files in Delphi with a Windows GUI where you can scroll through the folders etc. I have already done this with Matlab with a single function that (after selecting the file) returns a string of the path. You could event specify which extension the be shown. Is this kind of function available in delphi and how should I use it.
you can use the TOpenDialog component which is part of the Dialogs unit. you can create in runtime or drop this component from the Dialogs palette.
if you drop the component to your form you can use in this way
OpenDialog1.Filter := 'Only Text files (*.txt)|*.txt';
if OpenDialog1.Execute then
//do you stuff here
or if you create the component in runtime
Var
OpenDialog1 : TOpenDialog;
begin
OpenDialog1:=TOpenDialog.Create(nil);
try
OpenDialog1.Filter := 'Only Text files (*.txt)|*.txt';
if OpenDialog1.Execute then
ShowMessage('Selected File '+OpenDialog1.FileName);
finally
OpenDialog1.Free;
end;
end;
That's available via TOpenDialog which encapsulates the relevant Windows functionality.
Drop a TOpenDialog component on your form. Then you can call OpenDialog1.Execute to show the Windows dialog.
Related
I changed for Delphi 10.3 and its default TOpenDialog contains a preview pane. I made some searches and found the IFileDialogCustomize interface provided by Microsoft to customize standard WinAPI dialogs. I know I have to use the OnSelectionChange event handler to modify the picture of the pane. The big question for me is : how can I access the preview pane image by IFileDialogCustomize? What is the ItemID for this? I couldn't find any answer to this question on the net. Somebody know the answer? Then please share with me and the community! :)
I replaced some code fragments by ... for the sake of brevity, because these are trivial or app dependent sections.
procedure TMainWindow.OnSelectionChange( Sender : TObject );
var
dc : HDC;
aBMP : TBitmap;
function isSelectedFilePreviewAble : boolean;
begin
result := ...;
end;
functon getPreviewPictureDC : HDC;
var
iCustomize : IFileDialogCustomize;
h : THandle;
begin
if OpenDialog1.QueryInterface( IFileDialogCustomize, iCustomize ) = S_OK then
begin
h := iCustomize.??? this is the missing code fragment
result := GetDC( h );
end else
result := 0;
end;
procedure generatePreviewPicture;
begin
...
end;
begin
dc := getPreviewPictureDC;
if ( dc <> 0 ) then
begin
aBMP := TBitmap.Create;
try
if ( isSelectedFilePreviewAble ) then
generatePreviewPicture;
StretchBlt( aBMP.Handle, ...);
finally
aBMP.Free;
ReleaseDC( dc );
end;
end;
end;
I made some searches and found the IFileDialogCustomize interface provided by Microsoft to customize standard WinAPI dialogs.
First, IFileDialogCustomize does not "customize standard WinAPI dialogs". It customizes only IFileOpenDialog and IFileSaveDialog dialogs, no others.
Second, TOpenDialog primarily uses the legacy Win32 API GetOpenFileName() function. On Windows Vista+, GetOpenFileName() uses IFileOpenDialog internally with basic options enabled, so that legacy apps can still have a modern look.
Although, under the following conditions, TOpenDialog will instead use IFileOpenDialog directly rather than using GetOpenFileName():
Win32MajorVersion is >= 6 (Vista+)
UseLatestCommonDialogs is True
StyleServices.Enabled is True
TOpenDialog.Template is nil
TOpenDialog.OnIncludeItem, TOpenDialog.OnClose, and TOpenDialog.OnShow are unassigned.
But even so, TOpenDialog still does not give you access to its internal IFileOpenDialog interface, when it is used.
If you really want to access the dialog's IFileOpenDialog and thus its IFileDialogCustomize, you need to use TFileOpenDialog instead of TOpenDialog (just know that dialog won't work on XP and earlier systems, if you still need to support them).
The big question for me is : how can I access the preview pane image by IFileDialogCustomize?
You don't. The preview pane is not a dialog customization, so it can't be accessed via IFileDialogCustomize. Even if you could get a control ID for the preview pane (which you can't), there is no function of IFileDialogCustomize that would allow you to access the preview pane's HWND or HDC, or otherwise alter the content of the preview pane in any way. The preview pane is an integral and private component of IFileDialog for any file type that supports previews. It is not something that you can access and draw on directly. IFileOpenDialog itself will update the preview pane as needed when the user selects a file that has (or lacks) a preview to display.
My boss want to show previews for our own file formats.
The correct way to handle that on Vista+ is to create a Preview Handler for your custom file types. Then, any Shell component that wants to display previews of your files, including IFileOpenDialog, can use your handler.
I study preparing a dictionary programme with delphi. So far I have solved my problems about Word documents but I've got some problem about PDF documents.
I imported and installed the AcroPdf component with Delphi 7 and I want to get the word (or text) which was selected by dblclicking by user from pdf document which was viewed by the ACROPDF component in Delphi. If I can get it I'll send it the dictionary database directly.
If you help me I'll be glad. Thank you...
Remzi MAKAK
The following shows one way to get the selected text from a Pdf document which is
open in Adobe Acrobat Professional (v.8, English version).
Update The original version of this answer neglected to check the Boolean result of calling MenuItemExecute and specified the wrong argument to it. Both these points are fixed in the updated version of this answer. It turned out that the reason the call to MenuItemExecute was failing was that it is essential to call BringToFront on the Acrobat document before trying to copy the text selected in to to the clipboard.
Create a new Delphi VCL project.
In D7's IDE go to Projects | Import Type Library, and in the Import Type Library pop-up, scroll down until you see something like "Acrobat (Version 1.0) in the list of files, and
"TAcroApp, TAcroAVDoc..." in the Class names box. That is the one you need to import. Click the Create unit button/
In the project's main form file
a. Make sure it USES the Acrobat_Tlb.Pas unit from step 2. You may need to add the path to wherever you saved Acrobat_Tlb.Pas to the SearchPath of your project.
b. Drop a TButton on the form, name it btnGetSel. Drop a TEdit on the form and name it edSelection
Edit the source code of your main form unit as shown below.
Set a debugger breakpoint on Acrobat.MenuItemExecute('File->Copy'); Do not set a breakpoint within the GetSelection procedure as this is likely to defeat the call to BringToFront in it.
Close any running instance of Adobe Acrobat. Check in Task Manager that there are no hidden instances of it running. The reason for these step is to make sure that when you run your app, it "talks" to the instance of Acrobat that it starts, not another one.
Compile and run your app. Once the app and Acrobat are open, switch to Acrobat, select some text, switch back to your app and click the btnGetSel button.
Code:
uses ... Acrobat_Tlb, ClipBrd;
TDefaultForm = class(TForm)
[...]
private
FFileName: String;
procedure GetSelection;
public
Acrobat : CAcroApp;
PDDoc : CAcroPDDoc;
AVDoc : CAcroAVDoc;
end;
[...]
procedure TDefaultForm.FormCreate(Sender: TObject);
begin
// Adjust the following path to suit your system. My application is
// in a folder on drive D:
FFileName := ExtractfilePath(Application.ExeName) + 'Printed.Pdf';
Acrobat := CoAcroApp.Create;
Acrobat.Show;
AVDoc := CoAcroAVDoc.Create;
AVDoc.Open(FileName, FileName); // := Acrobat.GetAVDoc(0) as CAcroAVDoc; //
PDDoc := AVDoc.GetPDDoc as CAcroPDDoc;
end;
procedure TDefaultForm.btnGetSelClick(Sender: TObject);
begin
GetSelection;
end;
procedure TDefaultForm.GetSelection;
begin
// call this once some text is selected in Acrobat
edSelection.Text := '';
if AVDoc.BringToFront then // NB: This call to BringToFront is essential for the call to MenuItemExecute('Copy') to succeed
Caption := 'BringToFront ok'
else
Caption := 'BringToFront failed';
if Acrobat.MenuItemExecute('Copy') then
Caption := 'Copy ok'
else
Caption := 'BringToFront failed';
Sleep(100); // Normally I would avoid ever calling Sleep in a Delphi
// App's main thread. In this case, it is to allow Acrobat time to transfer the selected
// text to the clipboard before we attempt to read it.
try
edSelection.Text := Clipboard.AsText;
except
end;
end;
Left - dialog of Win7 of modern apps
Right - dialog of Win7 of my Delphi7 app
How to make my dlg modern? (How to patch Delphi7)
The offending part for the new dialog to be shown, for Windows 7 and later, is the callback. Here's a quote from "Font Dialog Box":
If you enable a hook procedure without creating a custom template, the
default ChooseFont template for earlier Windows versions will be
loaded.
You can eliminate the hook procedure by modifying a copy of "dialogs.pas" and putting it in your source folder for the current project.
function TFontDialog.Execute: Boolean;
...
// Flags := Devices[FDevice] or (CF_INITTOLOGFONTSTRUCT or CF_ENABLEHOOK);
Flags := Devices[FDevice] or CF_INITTOLOGFONTSTRUCT;
...
// hWndOwner := Application.Handle;
hWndOwner := GetActiveWindow;
...
The latter modification is for displaying the dialog in a reasonable place. Once the hook procedure is disabled, the VCL will not be able to center the dialog. You will also lose "Apply" button functionality and other events (OnShow/Close).
I use FileCtrl.SelectDirectory to show a 'open folder' dialog. However, I am unhappy with it because it doesn't allow the user to enter a path from where to start the browsing.
For example, if the user already has the path in clipboard it should be able to enter it into my dialog instead of wasting 12 seconds to navigate (open) lots of folders until it gets there.
I have found this code which seems to do EXACTLY what FileCtrl.SelectDirectory does. i hopped it will allow me to configure the dialog more. It doesn't.
So, how do I show a editbox in the SelectDirectory where the user can enter the path?
The solution that I have now, is my own dialog box. It is build from zero using TDirectory and TListBox. Very handy. BUT it looks so obsole because it uses Embarcadero's file management controls (TDirectory, TListBox) and we all know how dull they look like.
To make it clear: I would like something like FileCtrl.SelectDirectory but with an extact TEdit or a crumbar where the user can enter its path (if he has any).
Example:
Passing sdShowEdit to FileCtrl.SelectDirectory adds an edit box that you can paste a directory into.
FileCtrl.SelectDirectory('Caption', 'C:\', Dir, [sdNewUI, sdShowEdit]);
If you use the overloaded version of SelectDirectory() that has a Root parameter, it calls SHBrowseForFolder() internally (the other overload displays a custom VCL Win3.1-style dialog instead). If you assign an initial value to the variable that you pass to the Directory parameter, it gets passed to SHBrowseForFolder() as the initial selected folder. You can also specify the sdShowEdit flag in the Options parameter. However, the edit box is not meant for entering full paths. But, if you call SHBrowseForFolder() directly, you can provide your own callback function for it, so when the dialog sends you a BFFM_VALIDATEFAILED event for instance, you can grab the text from the dialog's edit box and send the dialog window a BFFM_SETSELECTION message to navigate to the correct path.
What you are really asking for is the customization provided by the Vista+ IFileDialog dialog instead. You can use the IFileDialogCustomize interface to add custom controls to the dialog, such as edit boxes and buttons, and then implement the IFileDialogControlEvents interface to know when various actions occur on those controls, like button clicks. You can use that to check your custom edit box, or the clipboard, for a valid path and if detected then tell the dialog to navigate to that path via the IFileDialog.SetFolder() method.
TJvDirectoryEdit from Jedi VCS does that. Look it up.
Here are some pictures of it:
If I understand correctly I think this could be your solution.
procedure TForm1.Button1Click(Sender: TObject);
var
opendialog : Topendialog;
begin
openDialog := TOpenDialog.Create(self);
openDialog.InitialDir := GetCurrentDir; {This can also be what is on the clipboard}
openDialog.Options := [ofFileMustExist];
openDialog.Filter := 'Text Document |*.txt'; {This is the type of file the user must open}
openDialog.FilterIndex := 1;
opendialog.execute;
end;
This code creates and shows a simple open dialog.
The path the user then selected is:
opendialog.filename
#davea's answer is ok but it only shows the old (WinXP) dialog style.
So, this is the code I use now. On Win Vista and up it shows the new style dialog and the old style on Win XP:
{$WARN SYMBOL_PLATFORM OFF}
{$IFDEF MSWindows}
function SelectAFolder(VAR Folder: string; CONST Options: TFileDialogOptions= [fdoPickFolders, fdoForceFileSystem, fdoPathMustExist, fdoDefaultNoMiniMode]): Boolean; { Keywords: FolderDialog, BrowseForFolder} { Works with UNC paths }
VAR Dlg: TFileOpenDialog;
begin
{ Win Vista and up }
if OS_IsWindowsVistaUp then
begin
Dlg:= TFileOpenDialog.Create(NIL); { Class for Vista and newer Windows operating systems style file open dialogs }
TRY
Dlg.Options := Options;
Dlg.DefaultFolder := Folder;
Dlg.FileName := Folder;
Result := Dlg.Execute;
if Result
then Folder:= Dlg.FileName;
FINALLY
FreeAndNil(Dlg);
END;
end
else
{ Win XP or down }
Result:= vcl.FileCtrl.SelectDirectory('', ExtractFileDrive(Folder), Folder, [sdNewUI, sdShowEdit, sdNewFolder], nil);
if Result
then Folder:= Trail(Folder);
end;
{$ENDIF}
{$WARN SYMBOL_PLATFORM On}
{ Keywords: FolderDialog, BrowseForFolder}
There doesn't appear to be a simple component available to create a folder selection dialog in Delphi 2009, although a file selection dialog is provided by way of the TOpenDialog.
What is the most common way to create a modern folder selection dialog using Delphi?
There are two overloaded routines in FileCtrl.pas called SelectDirectory
For a modern look, use the second form, with sdNewUI
var
dir : string;
begin
dir := 'C:\temp';
FileCtrl.SelectDirectory('Select', 'C:\', dir, [sdNewFolder, sdNewUI], Self);
end;
NOTE: sdNewFolder, sdNewUI etc are only available from D2006+
you can use SelectDirectory from FileCtrl unit
using FileCtrl;
var
St: string;
begin
St:='c:\';
if SelectDirectory(St,[],0) then
begin
end;
end;
You can download a component PBFolderDialog from "http://bak-o-soft.dk/Delphi/PBFolderDialog.aspx" which is quite easy to use and offers access to all options of the Windows "SHBrowseForFolder" dialog; something which the built-in ones not do.
It's freeware with source and not too difficult to port to Delphi 2009.
See the sample code:
Delphi tip#157: select folder dialog
http://www.scalabium.com/faq/dct0157.htm