본문 바로가기

프로그래밍/Delphi

[Delphi] XP에서 TSaveDialog의 확장자 필터타입 바꿨을때 파일명 확장자가 자동으로 변경되지 않는 문제


1. TSaveDialog
  TSaveDialo를 이용하여 저장하고자 하는 파일 타입들을 등록하고 선택적으로 파일 타입을 선택하여 저장할 수 있다.
  이때 파일타입 변경시 Windows7에서는 기본 지정된 파일명의 확장자가 자동으로 변경된 파일 타입의 확장자로 변경되는데
  WindowsVISTA에서는 자동 변경되지 않음 또한 XP에서도 자동으로 변경되지 않는 문제가 발생함

2. 해결방법
  VISTA에서는 TSaveDialog.OnTypeChange 이벤트에서 필터 인덱스에 따라서 확장자를 강제 지정하여
 Dioalog.FileName에 강제 지정해 주면 변경 되는데

  XP에서는 이마저도 되지 않는다.
  구글링을 통해 여러 문서를 찾아 보았으나 원천적인 버그로 기록 되어 있고 별다른 해법이 존재하지 않아서 다음과 같이 해결 하고자 함

  해법 :
    OnTypeChange Event 핸들러에서 파일 타입에 따른 확장자를 획득한 후
   TSaveDalog창내의 파일명 컨트롤(COMBOBOXEX32 > COMBOBOX > EDIT)을 찾아내어 해당 컨트롤에 직접 변경할 파일명을 지정해 주도록 함 이때 전체 경로를 포함한 파일명을 지정하면 지저분해 지기 때문에 순수 파일명만을 추출하여 해당 컨트롤에 강제 입력해 주는 방법을 이용하도록 함

참고로 TSaveDialog내에서 COMBOBOXEX32 컨트롤은 메인에서 9번째 인덱스를 가지며 자식 컨트롤인 COMBOBOX는 첫번째, 또 그 자식 컨트롤인 EDIT도 첫번째 인덱스를 가짐 따라서 해당 컨트롤을 순서적으로 찾도록 함 한 번에 찾을 수도 있음... 고민해 볼것....

// 자식 컨트롤에서 몇번째 컨트롤 핸들 찾기
function FindChildWindow(winHandle: HWND; nIdx: Integer): HWND; overload;
var
  szClassName, szWindowName, szText: array[0..256] of Char;
    {title bar를 저장 할 buffer}
  count: integer;
  pasClassName, pasWindowName: string;
begin
  result := 0;
  winHandle := FindWindowEx(winHandle, 0, nil, nil);
  count := 0;
  while winHandle <> 0 do
  begin
    inc(count);
    if nIdx = count then
    begin
      result := winHandle;
      break;
    end;
    winHandle := GetNextWindow(winHandle, GW_HWNDNEXT);
  end;
end;

//EDIT 컨트롤의 TEXT 세팅
procedure SendCharToEditControl(hd : THandle; AMsg : string);
var
  i : integer;
begin
    SendMessage(hd, WM_SETTEXT,0, Integer(PChar(AMsg)) );

//한자씩 보내기(키보드 효과)
//  for i := 1 to length(AMsg) do
//    SendMessage(hd, WM_CHAR, ord(AMsg[i]),0);
end;

//TSaveDialog.OnTypeChange 이벤트 핸들러
procedure TfrmOrderEdit.dlgSaveTocFileTypeChange(Sender: TObject);
var
  ext : string;
  fname : string;
  hd : HWND;
begin
  case dlgSaveTocFile.FilterIndex of
    1 : ext := '.xls';
    2 : ext := '.txt';
  end;

  //확장자만 얻기 (sm은 스트링라이브러리이므로 아래 부분은 맘대로 구현해도 됨)
  fname := sm.AfterRev('\', sm.BeforeRev('.', dlgSaveTocFile.FileName) + ext);

  hd := FindChildWindow(GetParent(dlgSaveTocFile.Handle),9); //FIND COMBOBOXEX32
  hd := FindChildWindow(hd, 1); //FIND COMBOOX
  hd := FindChildWindow(hd, 1); //FIND EDIT

  //TEXT 변경하기(파일명 부분)
  SendCharToEditControl(hd, fname);
end;