2010-01-27 7 views
8

Durante la visualizzazione di una finestra di dialogo di salvataggio, voglio agganciare la modifica del tipo di filtro dell'utente e modificare automaticamente l'estensione del file. (ad esempio l'operazione "Salva con nome" di MSPaint.)(Salva finestra di dialogo) Come cambiare automaticamente l'estensione del file sulla modifica del filtro file in Vista/Win7?

Con TSaveDialog e impostazione UseLatestCommonDialogs: = False, Posso gestirlo tramite il seguente codice. (Senza ultimo supporto di dialogo comune, di cource.)

procedure TForm1.SaveDialog1TypeChange(Sender: TObject); 
var 
    FName, Ext: string; 
begin 
    with TSaveDialog(Sender) do 
    begin 
    if DirectoryExists(FileName) then // FileName is Empty 
     exit; 
    case FilterIndex of 
    1: Ext := '.png'; 
    2: Ext := '.bmp'; 
    3: Ext := '.jpg'; 
    end; 
    FName := ChangeFileExt(ExtractFileName(FileName), Ext); 
    SendMessage(Windows.GetParent(Handle), CDM_SETCONTROLTEXT, 1152, LongInt(PChar(FName))); 
    end; 
end; 

Voglio sostenere sia XP e Vista/7 con Delphi 2007.

Dovrei usare TFileSaveDialog invece di TSaveDialog con involucro interno? (E devo fare i conti con la programmazione COM usando IFileDialogControlEvents?)

Oppure posso ottenere questo con TFileSaveDialog e sono solo le proprietà standard? (Il mio ambiente di sviluppo è ancora in macchina XP, quindi non ho mai provato. Dispiaciuto.)

Credo che sia compito molto comune, ma non ho trovato alcun codice di esempio sostenendo Vista/7 ...

risposta

5

Per quanto ne so, TFileSaveDialog genererà un'eccezione su XP. Ha bisogno di Vista o fino.

Aggiornamento: un codice D2010 per TFileSaveDialog adattato dal vostro gestore di eventi ....
(Non ho D2007 su Vista; utilizzare PWideChar invece di PChar)

procedure TForm1.FileSaveDialog1TypeChange(Sender: TObject); 
var 
    FName, Ext: string; 
    pName: PChar; 
begin 
    with TFileSaveDialog(Sender) do 
    begin 
    if DirectoryExists(FileName) then // FileName is Empty 
     exit; 
    case FileTypeIndex of 
    1: Ext := '.png'; 
    2: Ext := '.bmp'; 
    3: Ext := '.jpg'; 
    end; 
    Dialog.GetFileName(pName); 
    FName := ChangeFileExt(ExtractFileName(pName), Ext); 
    Dialog.SetFileName(PChar(FName)); 
    end; 
end; 

Qualora il FileSaveDialog è:

object FileSaveDialog1: TFileSaveDialog 
    FavoriteLinks = <> 
    FileTypes = < 
    item 
     DisplayName = 'png files' 
     FileMask = '*.png' 
    end 
    item 
     DisplayName = 'bmp files' 
     FileMask = '*.bmp' 
    end 
    item 
     DisplayName = 'jpg files' 
     FileMask = '*.jpg' 
    end> 
    Options = [] 
    OnTypeChange = FileSaveDialog1TypeChange 
end 
+0

Grazie! Ma in genere creo queste finestre di dialogo in runtime, così posso passare sia a TSaveDialog che a TFileSaveDialog con il controllo della versione del sistema operativo. – benok

+0

Funziona con D2007. Ho appena cambiato PChar/string-> PWideChar/WideString. (Potrebbe funzionare su D2009 o successivi con la conversione del tipo automatico). Grazie! p.s. Ho provato a passare all'interno di "* SaveDialog1 * TypeChange", usando come "se Parent.ClassName = 'TFileSaveDialogWrapper'".(E 'più maneggevole rispetto al passaggio classi di dialogo.) Ma non ho potuto incidere involucro, come è definito nella sezione di implementazione ... – benok

4

Lei ha scritto che non si poteva incidere il wrapper. Uso questo codice per la mia libreria di esportazione XLSX/XLS/ODS per modificare l'estensione del file su XP e Vista +.

Uno svantaggio: gli helper di classe non possono accedere ai campi privati ​​in Delphi 2007, quindi questo codice funziona solo in Delphi 2009+. Se si desidera la compatibilità con Delphi 2007, utilizzare lo stesso trucco per TOpenDialog, come in questo esempio utilizzato per TFileDialogWrapper.

{ interface } 

    //some hacking needed to change the file extension at type change, 
    //empty class is just fine... 
    TFileDialogWrapper = class(TObject) 
    private 
    {$HINTS OFF} 
    procedure AssignFileTypes; 
    procedure AssignOptions; 
    function GetFileName: TFileName; 
    function GetHandle: HWND; 
    procedure HandleShareViolation(Sender: TObject; 
     var Response: TFileDialogShareViolationResponse); 
    procedure OnFileOkEvent(Sender: TObject; var CanClose: Boolean); 
    procedure OnFolderChangeEvent(Sender: TObject); 
    procedure OnSelectionChangeEvent(Sender: TObject); 
    procedure OnTypeChangeEvent(Sender: TObject); 
    protected 
    FFileDialog: TCustomFileDialog; 
    {$HINTS ON} 
    end; 
    TOpenDialogHelper = class helper for TOpenDialog 
    public 
    function GetInternalWrapper: TFileDialogWrapper; 
    end; 

{ implementation } 

{ TOpenDialogHelper } 

function TOpenDialogHelper.GetInternalWrapper: TFileDialogWrapper; 
begin 
    Result := TFileDialogWrapper(Self.FInternalWrapper); 
end; 

{ TFileDialogWrapper } 

procedure TFileDialogWrapper.AssignFileTypes; 
begin 
end; 

procedure TFileDialogWrapper.AssignOptions; 
begin 
end; 

function TFileDialogWrapper.GetFileName: TFileName; 
begin 
end; 

function TFileDialogWrapper.GetHandle: HWND; 
begin 
end; 

procedure TFileDialogWrapper.HandleShareViolation(Sender: TObject; 
    var Response: TFileDialogShareViolationResponse); 
begin 
end; 

procedure TFileDialogWrapper.OnFileOkEvent(Sender: TObject; 
    var CanClose: Boolean); 
begin 
end; 

procedure TFileDialogWrapper.OnFolderChangeEvent(Sender: TObject); 
begin 
end; 

procedure TFileDialogWrapper.OnSelectionChangeEvent(Sender: TObject); 
begin 
end; 

procedure TFileDialogWrapper.OnTypeChangeEvent(Sender: TObject); 
begin 
end; 

//use this for OnTypeChane event of a "normal" TOpenDialog/TSaveDialog 

procedure TForm1.DialogTypeChange(Sender: TObject); 
var 
    xFN: WideString; 
    xExporter: TOCustomExporter; 
    xFileName: PWideChar; 
    xFD: TFileDialogWrapper; 
    xFilterIndex: UINT; 
begin 
    if Sender is TOpenDialog then 
    with TOpenDialog(Sender) do begin 
    xFD := GetInternalWrapper; 
    if (xFD <> nil) and (xFD.FFileDialog <> nil) 
    then begin 
     //Vista file dialog 

     xFD.FFileDialog.Dialog.GetFileName(xFileName); 
     if xFileName = '' then 
     exit; 
     xFN := xFileName; 
     xFD.FFileDialog.Dialog.GetFileTypeIndex(xFilterIndex); 

     // DO WHATEVER YOU WANT WITH THE FILENAME HERE // 

     xFD.FFileDialog.Dialog.SetFileName(PWideChar(xFN)); 
    end else begin 
     //Old dialog 
     xFN := ExtractFileName(FileName); 
     if xFN = '' then 
     exit; 

     // DO WHATEVER YOU WANT WITH THE FILENAME HERE // 

     {$HINTS OFF} 
     SendMessage(Windows.GetParent(Handle), CDM_SETCONTROLTEXT, 1152, LongInt(PWideChar(xFN))); 
     {$HINTS ON} 
    end; 
    end; 
end; 

EDIT: in realtà, se si imposta la proprietà DefaultExt, Delphi/Windows a cuore il cambiamento estensione del file per voi. In tal caso non devi fare nulla nell'evento OnTypeChange.

+0

In realtà, ho controllato ora - funziona solo in Delphi XE + a causa di unità di finestre di dialogo dell'architettura. – oxo

+0

Grazie per la risposta. Ho appena notato. Non sto più usando la D2007, leggerò il tuo codice. Grazie. – benok

0

Questa funzione è implementata in Delphi, ma disabilitata per impostazione predefinita.

Per attivarlo, è sufficiente immettere l'estensione predefinita nella proprietà DefaultExt.