문제

While showing a save dialog, I want to hook user's filter type change and change file extension automatically. (e.g. like MSPaint's "Save As" operation.)

With TSaveDialog and setting UseLatestCommonDialogs := False, I can handle this by the following code. (without latest common dialog support, of 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;

I want to support both XP, and vista/7 with Delphi 2007.

Should I use TFileSaveDialog instead of TSaveDialog with internal wrapper ? (And I have to struggle with COM programming using IFileDialogControlEvents ?)

Or can I achieve this with TFileSaveDialog and it's standard properties only ? (My development environment is still on XP machine, so I've never tried. sorry.)

I think it's very common task, but I couldn't find any sample code supporting Vista/7...

도움이 되었습니까?

해결책

기본적으로 값을 대체합니다. 필드가 readonly 인 경우에도 작동하는 경우를 제외하고는 오른쪽에서 왼쪽으로 모든 필드를 효과적으로 복사합니다. 그리고 예, 이 뚜렷하게 이상하게 보이고 있으며, 그것은 다소 무서운 것입니다.

예 :

using System;

class Test
{
    static void Main()
    {
        Point point = new Point(10, 20);
        point.ReplaceWith(new Point(2, 3));
        Console.WriteLine(point); // (2, 3)
    }
}

struct Point
{
    private readonly int x;
    private readonly int y;

    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public void ReplaceWith(Point other)
    {
        this = other;
    }

    public override string ToString()
    {
        return string.Format("({0}, {1})", x, y);
    }
}
.

자세한 정보는 다음을 포함하는 C # 4 사양의 섹션 7.6.7 섹션을 읽습니다.

  • [struct 생성자에서의 사용에 대한 텍스트]

  • 구조체의 인스턴스 메소드 또는 인스턴스 접근 자 내의 1 차 표현식 에서 this가 사용될 때 변수로 분류된다. 변수의 유형은 사용이 발생하는 구조체의 인스턴스 유형입니다.

    • 방법 또는 접근 자가 반복자가 아닌 경우, this 변수는 메소드 또는 접근 자를 호출 한 구조체를 나타내며, struct 유형의 ref 매개 변수와 똑같이 동작합니다. < / li>

    • [이에 대한 텍스트]

다른 팁

You wrote that you couldn't hack the wrapper. I use this code for my XLSX/XLS/ODS exporting library to change the file extension on both XP and Vista+.

One drawback: Class helpers cannot access private fields in Delphi 2007, so this code works only in Delphi 2009+. If you want Delphi 2007 compatibility, use the same hack for TOpenDialog like I used for TFileDialogWrapper in this example.

{ 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: actually, if you set the DefaultExt property, Delphi/Windows care about the file extension change for you. In that case you don't have to do anything in the OnTypeChange event.

엄격한 권한이나 트리밍에 대해 이야기하고 있습니까?지정된 사용자만이 일정 항목을 볼 수있는 경우 워크 플로우가 필요하거나 열을 기반으로 항목에 대해 고유 한 권한을 설정하는 것과 비슷해야합니다.이 작업을 수행 할 수 있습니다.SPD 워크 플로우.

트리밍은 선택한 사용자에게 항목 만 표시하도록보기를 필터링하는 곳입니다.새 사용자 컬럼이 들어있는보기에 필터를 적용하십시오 [ME] - [ME]는 현재 사용자를 사용할 특수 필터입니다.그러나 사용자가 목록에 직접 이동하거나 목록의 다른 필터링 된보기가 여전히 항목을 볼 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top