2010-01-27 5 views
8

Al mostrar un cuadro de diálogo para guardar, quiero enganchar el cambio del tipo de filtro del usuario y cambiar la extensión de archivo automáticamente. (por ejemplo, como la operación "Guardar como" de MSPaint.)(cuadro de diálogo Guardar) ¿Cómo cambiar la extensión de archivo automáticamente en el cambio de filtro de archivos en Vista/Win7?

Con TSaveDialog y estableciendo UseLatestCommonDialogs: = False, Puedo manejar esto con el siguiente código. (Sin soporte más reciente de diálogo común, de 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; 

quiero apoyar tanto XP y Vista/7 con Delphi 2007.

¿Debo usar TFileSaveDialog en lugar de TSaveDialog con la envoltura interna? (¿Y tengo que luchar con la programación COM usando IFileDialogControlEvents?)

¿O puedo lograr esto con TFileSaveDialog y sus propiedades estándar solamente? (Mi entorno de desarrollo está todavía en la máquina XP, por lo que nunca he intentado. Lo siento.)

Creo que es tarea muy común, pero no pude encontrar ningún código de ejemplo apoyando Vista/7 ...

Respuesta

5

Por lo que sé, TFileSaveDialog generará una excepción en XP. Necesita Vista o arriba.

actualización: un código D2010 para TFileSaveDialog adaptado de su controlador de eventos ....
(no tengo D2007 en Vista, el uso PWideChar en lugar de 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; 

Cuando el FileSaveDialog es:

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

Gracias! Pero normalmente creo estos diálogos en tiempo de ejecución, así que pude cambiar tanto TSaveDialog como TFileSaveDialog con la verificación de la versión del SO. – benok

+0

Funciona con D2007. Solo cambio PChar/string-> PWideChar/WideString. (Puede ser que funcione en D2009 o posterior con conversión de tipo automático). ¡Gracias! p.s. Traté de cambiar dentro de "* SaveDialog1 * TypeChange", usando como "si Parent.ClassName = 'TFileSaveDialogWrapper'".(Es más útil que cambiar clases de diálogo). Pero no pude hackear el contenedor, como se define en la sección de implementación ... – benok

4

usted escribió que no se podía cortar la envoltura Uso este código para mi biblioteca de exportación XLSX/XLS/ODS para cambiar la extensión de archivo tanto en XP como en Vista +.

Un inconveniente: los ayudantes de la clase no pueden acceder a los campos privados en Delphi 2007, por lo que este código solo funciona en Delphi 2009+. Si desea la compatibilidad con Delphi 2007, use el mismo hack para TOpenDialog como lo usé para TFileDialogWrapper en este ejemplo.

{ 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; 

EDITAR: de hecho, si se establece la propiedad DefaultExt, Delphi/Windows se preocupan por el cambio de extensión de archivo para usted. En ese caso, no tiene que hacer nada en el evento OnTypeChange.

+0

En realidad, lo he comprobado ahora: funciona solo en Delphi XE + debido a la arquitectura de la unidad Dialogs. – oxo

+0

Gracias por su respuesta. Me acabo de dar cuenta. Ya no usaré D2007, leeré tu código. Gracias. – benok

0

Esta característica se implementa en Delphi, pero está deshabilitada de forma predeterminada.

Para activarlo, solo ingrese la extensión predeterminada en la propiedad DefaultExt.

Cuestiones relacionadas