2010-01-27 43 views
8

Khi hiển thị hộp thoại lưu, tôi muốn tự động thay đổi loại bộ lọc của người dùng và tự động thay đổi phần mở rộng tệp. (ví dụ như hoạt động "Lưu dưới dạng" của MSPaint.)(Lưu hộp thoại) Làm thế nào để thay đổi phần mở rộng tập tin tự động vào thay đổi bộ lọc tập tin trong Vista/Win7?

Với TSaveDialog và thiết lập UseLatestCommonDialogs: = False, Tôi có thể xử lý điều này bằng mã sau. (Không có hỗ trợ thoại phổ biến mới nhất, của 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; 

tôi muốn hỗ trợ cả XP và vista/7 với Delphi 2007.

Tôi có nên sử dụng TFileSaveDialog thay vì TSaveDialog với wrapper nội bộ? (Và tôi phải đấu tranh với lập trình COM bằng cách sử dụng IFileDialogControlEvents?)

Hoặc tôi có thể đạt được điều này với TFileSaveDialog và các thuộc tính tiêu chuẩn của nó không? (môi trường phát triển của tôi vẫn còn trên máy XP, vì vậy tôi đã không bao giờ cố gắng. Xin lỗi.)

Tôi nghĩ đó là nhiệm vụ rất phổ biến, nhưng tôi không thể tìm thấy bất kỳ mẫu mã hỗ trợ Vista/7 ...

Trả lời

5

Theo như tôi biết, TFileSaveDialog sẽ tăng ngoại lệ trên XP. Nó cần Vista hoặc lên.

Cập nhật: một số mã D2010 cho TFileSaveDialog chuyển thể từ xử lý sự kiện của bạn ....
(Tôi không có D2007 trên Vista, sử dụng PWideChar thay vì 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; 

Trường hợp FileSaveDialog là:

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

Cảm ơn! Nhưng tôi thường tạo các hộp thoại này trong thời gian chạy, vì vậy tôi có thể chuyển đổi cả TSaveDialog và TFileSaveDialog bằng kiểm tra phiên bản hệ điều hành. – benok

+0

Nó hoạt động với D2007. Tôi chỉ cần thay đổi PChar/string-> PWideChar/WideString. (Có thể nó hoạt động trên D2009 hoặc mới hơn với tự động chuyển đổi kiểu.). Cảm ơn! p.s. Tôi đã cố gắng chuyển đổi bên trong "* SaveDialog1 * TypeChange", sử dụng như "nếu Parent.ClassName = 'TFileSaveDialogWrapper'".(Đó là thủ công hơn chuyển đổi các lớp hộp thoại.) Nhưng tôi không thể hack wrapper, vì nó được định nghĩa trong phần thực hiện ... – benok

4

Bạn đã viết rằng bạn không thể hack vỏ bánh. Tôi sử dụng mã này cho thư viện xuất XLSX/XLS/ODS của mình để thay đổi phần mở rộng của tệp trên cả XP và Vista +.

Một nhược điểm: Người trợ giúp lớp không thể truy cập các trường riêng tư trong Delphi 2007, vì vậy mã này chỉ hoạt động trong Delphi 2009+. Nếu bạn muốn tương thích Delphi 2007, hãy sử dụng cùng một hack cho TOpenDialog như tôi đã sử dụng cho TFileDialogWrapper trong ví dụ này.

{ 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: trên thực tế, nếu bạn đặt DefaultExt tài sản, Delphi/Windows quan tâm đến sự thay đổi phần mở rộng tập tin cho bạn. Trong trường hợp đó bạn không phải làm bất cứ điều gì trong sự kiện OnTypeChange.

+0

Thực ra, tôi đã kiểm tra nó ngay bây giờ - nó chỉ hoạt động trong Delphi XE + vì cấu trúc đơn vị Dialogs. – oxo

+0

Cảm ơn bạn đã trả lời. Tôi vừa để ý. Tôi không sử dụng D2007 nữa, tôi sẽ đọc mã của bạn. Cảm ơn. – benok

0

Tính năng này được triển khai trong Delphi, nhưng bị tắt theo mặc định.

Để kích hoạt, chỉ cần nhập tiện ích mở rộng mặc định trong thuộc tính DefaultExt.

Các vấn đề liên quan