10

保存ダイアログを表示しながら、ユーザーのフィルタータイプの変更をフックし、ファイル拡張子を自動的に変更したい。(たとえば、MSPaintの「名前を付けて保存」操作のように。)

TSaveDialogとUseLatestCommonDialogs:= Falseを設定すると、次のコードでこれを処理できます。(最新の一般的なダイアログサポートなしで、当然のことです。)

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;

XPと、Delphi2007でのvista/7の両方をサポートしたいと思います。

内部ラッパーでTSaveDialogの代わりにTFileSaveDialogを使用する必要がありますか?(そして、 IFileDialogControlEventsを使用したCOMプログラミングに苦労する必要がありますか?)

または、TFileSaveDialogを使用してこれを実現できますか?それは標準のプロパティのみですか?(私の開発環境はまだXPマシン上にあるので、試したことはありません。申し訳ありません。)

非常に一般的な作業だと思いますが、Vista/7をサポートするサンプルコードが見つかりませんでした...

4

3 に答える 3

5

私の知る限り、TFileSaveDialog は XP で例外を発生させます。Vista以上が必要です。

更新:イベント ハンドラーから適用されたTFileSaveDialogのD2010 コードの一部.... (Vista には D2007 がありません。PChar の代わりに PWideChar を使用します)

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;

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
于 2010-01-27T08:35:50.267 に答える
4

あなたはラッパーをハックできないと書きました。このコードを XLSX/XLS/ODS エクスポート ライブラリに使用して、XP と Vista+ の両方でファイル拡張子を変更します。

1 つの欠点: クラス ヘルパーは Delphi 2007 のプライベート フィールドにアクセスできないため、このコードは Delphi 2009+ でのみ機能します。Delphi 2007 との互換性が必要な場合は、この例で TFileDialogWrapper に使用したのと同じハックを TOpenDialog に使用してください。

{ 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 : 実際には、DefaultExtプロパティを設定すると、Delphi/Windows がファイル拡張子の変更を考慮します。OnTypeChangeその場合、イベントで何もする必要はありません。

于 2012-10-08T20:04:02.430 に答える
2

この機能は Delphi に実装されていますが、デフォルトでは無効になっています。

有効にするには、DefaultExtプロパティにデフォルトの拡張子を入力するだけです。

于 2016-08-17T09:36:30.693 に答える