본문 바로가기

프로그래밍/Delphi

[Delphi/Tip] 디렉토리 선택 다이얼로그 호출하기

델파이(Delphi) 코드로 폴더를 선택할 수 있는 다이얼로그를 호출 하는 방법


유용하고 바로쓸 수 있는 코드 만들기...


폴더를 선택하기 위해서는 3가지 방법이 있으며 호출 예를 보고 선호하는 방식 사용


1) TFileOpenDialog 를 이용한 방법으로 

Windows VISTA 이상의 운영체제의 폴더 선택창


2) SelectDirectory 함수를 이용한 방법

Windows XP 이하의 운영체제의 폴더 선택창(물론 상위 버전에서도 동일하게 보임)


3) TOpenDialog를 커스터마이징 한 방법

    파일 선택 다이얼로그에서 파일관련 정보를 숨기는 방법으로 커스터마이징 처리




폴더 선택 데모 프로그램(SelectDirectory.dproj)



소스코드


unit ufrmSelectDir;
{** 델파이를 이용한 폴더 선택 예제
 * 작성일자 : 2018-10-17
 * 작성자 : niceondal@gmail.com
 *}
interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, FileCtrl;

//***************************************
//** Window Messages를 이용한 폴더선택 **
//***************************************
//참고: http://www.delphipages.com/forum/showthread.php?p=185734
//Dialog.OnShow에 의해 불려질 프로시저를 저장할 클래스 정의
type
  TOpenDir = class(TObject)
public
  Dialog: TOpenDialog;
  procedure HideControls(Sender: TObject);
end;

type
  TfrmSelectDir = class(TForm)
    mmLogs: TMemo;
    btnUseTFileOpenDialog: TButton;
    btnUseSelectDirectory: TButton;
    btnSelectDirectoryAuto: TButton;
    btnUseTOpenDialog: TButton;
    procedure btnUseTFileOpenDialogClick(Sender: TObject);
    procedure btnUseSelectDirectoryClick(Sender: TObject);
    procedure btnSelectDirectoryAutoClick(Sender: TObject);
    procedure btnUseTOpenDialogClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    function SelectDir(var ADir : String) : boolean;
  end;

var
  frmSelectDir: TfrmSelectDir;

implementation

{$R *.dfm}

//TOpenDialog를 이용한 폴더 선택 함수
function CommonSelectDir(var Dir: string): boolean;
var
  OpenDialog: TOpenDialog;
  OpenDir: TOpenDir;
begin
  OpenDialog:= TOpenDialog.Create(nil);
  OpenDir:= TOpenDir.create;
  try
    //생성된 TOpenDialog 객체 참조
    OpenDir.Dialog:= OpenDialog;
    OpenDialog.OnShow:= OpenDir.HideControls;
    //확장자 없이 폴더만 보여주기위한 설정
    OpenDialog.FileName:= '*.';
    OpenDialog.Filter:=   '*.';
    OpenDialog.Title:=    '폴더 선택';
    //파일의 존재유무 체크
    OpenDialog.Options:= OpenDialog.Options + [ofNoValidate];
    //초기 기본 폴더 지정
    OpenDialog.InitialDir:= Dir;
    //폴더 선택 다이얼로그 호출
    if OpenDialog.Execute then begin
      Dir:= ExtractFilePath(OpenDialog.FileName);
      result:= true;
    end else begin
      result:= false;
    end;
  finally
    //객체 해제
    OpenDir.Free;
    OpenDialog.Free;
  end;
end;

procedure TfrmSelectDir.btnUseTFileOpenDialogClick(Sender: TObject);
begin
  with TFileOpenDialog.Create(nil) do
    try
      Title := '폴더 선택';
      Options := [fdoPickFolders, fdoPathMustExist, fdoForceFileSystem]; // YMMV
      OkButtonLabel := '선택';
      DefaultFolder := 'C:\Temp';
      FileName := 'C:\Temp';
      if Execute then
        mmLogs.Lines.Add('선택된 폴더(use TFileOpenDialog) : ' + FileName);
    finally
      Free;
    end
end;

procedure TfrmSelectDir.btnUseTOpenDialogClick(Sender: TObject);
var
  dir : String;
begin
  dir := 'C:\Temp';
  if CommonSelectDir(dir) then
    mmLogs.Lines.Add('선택된 폴더(use OpenDialog) : ' + dir);
end;

function TfrmSelectDir.SelectDir(var ADir: String): boolean;
begin
  result := false;
  if Win32MajorVersion>=6 then //Windwos VISTA 이상 버전 체크
  begin
    with TFileOpenDialog.Create(self) do
    try
      Title := '폴더 선택';
      Options := [fdoPickFolders, fdoPathMustExist, fdoForceFileSystem];
      OkButtonLabel := '선택';
      DefaultFolder := ADir;
      FileName := ADir;
      if Execute then
      begin
        result := true;
        ADir := FileName;
      end;
    finally

    end;
  end
  else
  begin
    result := SelectDirectory('폴더 선택', ExtractFileDrive(ADir), ADir,
               [sdNewUI, sdNewFolder]);
  end;
end;

procedure TfrmSelectDir.btnSelectDirectoryAutoClick(Sender: TObject);
var
  dir : String;
begin
  dir := 'C:\Temp';
  if SelectDir(dir) then
    mmLogs.Lines.Add('선택된 폴더(Auto) : ' + dir);
end;

procedure TfrmSelectDir.btnUseSelectDirectoryClick(Sender: TObject);
var
  dir : string;
begin
  dir := 'C:\Temp';
  if SelectDirectory('폴더 선택', ExtractFileDrive(dir), dir,
             [sdNewUI, sdNewFolder]) then
    mmLogs.Lines.Add('선택된 폴더(use SelectDirectory) : ' + dir);
end;

//이 파일은 기본 TOpenDialog에서 FileType등의 콤보 박스를 감춘다
procedure TOpenDir.HideControls(Sender: TObject);
const
  //CDM_HIDECONTROL and CDM_SETCONTROLTEXT values from:
  //  doc.ddart.net/msdn/header/include/commdlg.h.html
  //  CMD_HIDECONTROL = CMD_FIRST + 5 = (WM_USER + 100) + 5;
  //Usage of CDM_HIDECONTROL and CDM_SETCONTROLTEXT here:
  //  msdn.microsoft.com/en-us/library/ms646853%28VS.85%29.aspx
  //  msdn.microsoft.com/en-us/library/ms646855%28VS.85%29.aspx
  CDM_HIDECONTROL =    WM_USER + 100 + 5;
  CDM_SETCONTROLTEXT = WM_USER + 100 + 4;
  //Component IDs from:
  //  msdn.microsoft.com/en-us/library/ms646960%28VS.85%29.aspx#_win32_Open_and_Save_As_Dialog_Box_Customization
  //Translation into exadecimal in dlgs.h:
  //  www.koders.com/c/fidCD2C946367FEE401460B8A91A3DB62F7D9CE3244.aspx
  //
  //파일유형 필터 컨트롤
  cmb1: integer  = $470; //파일유형 필터 콤보박스
  stc2: integer  = $441; //파일유형 라벨
  //파일명 관련 컨트롤
  cmb13: integer = $47c; //현재 선택된 파일이름을 가진 콤보박스
  edt1: integer  = $480; //현재 선택된 파일이름을 가진 에디트 박스
  stc3: integer  = $442; //파일명 라벨
var H: THandle;
begin
  H:= GetParent(Dialog.Handle);
  //파일유형 필터 콤보박스를 숨김
  SendMessage(H, CDM_HIDECONTROL, cmb1,  0);
  SendMessage(H, CDM_HIDECONTROL, stc2,  0);
  //파일명 라벨, 에디터, 콤보박스를 숨김
  SendMessage(H, CDM_HIDECONTROL, cmb13, 0);
  SendMessage(H, CDM_HIDECONTROL, edt1,  0);
  SendMessage(H, CDM_HIDECONTROL, stc3,  0);
  //참고: 길이가 AUTO로 설정되지 않은 라벨 TEXT를 바꾸기 위해서는 다음과 같이 처리
  //SendMessage(H, CDM_SETCONTROLTEXT, stc3, DWORD(pChar('Hello!')));
end;

end.


데모파일 다운로드 : SelectDirectory.zip