반응형
[UI/UX 개선] 네트워크 경로 접근성 해결을 위한 '탐색기 스타일' 다이얼로그 도입
도입 이유 3가지 요약
1. 네트워크(UNC) 경로 접근성 한계 극복
- 기존 (FolderBrowserDialog): 트리(Tree) 구조로 되어 있어, \\192.168.10.5 같은 네트워크 경로를 찾아가려면 '네트워크' 아이콘부터 수동으로 클릭해 들어가야 하며 속도가 매우 느립니다.
- 변경 (CommonOpenFileDialog): 윈도우 탐색기와 동일한 주소창이 있어, 네트워크 경로를 복사/붙여넣기 하여 즉시 이동할 수 있습니다.
2. 사용자 경험(UX) 표준화
- 기존: 윈도우 XP 시절의 구형 UI로 인해 오퍼레이터가 이질감을 느낍니다.
- 변경: 사용자가 평소 쓰던 '파일 열기' 창과 동일한 UI를 제공하므로, '즐겨찾기', '최근 항목' 등을 그대로 활용할 수 있어 직관적입니다.
3. 주소창 입력 지원
- 기존: 오직 마우스 클릭으로만 폴더를 선택해야 합니다.
- 변경: 상단 주소 표시줄에 직접 경로를 타이핑하거나 수정할 수 있어, 깊은 경로(Deep Path)로의 접근 효율이 압도적으로 높습니다.
Step 0: 사전 준비 (NuGet 설치)
먼저 패키지 관리자 콘솔에서 안정적인 1.1.1 버전을 설치했는지 확인하십시오. (8.x 버전은 4.8 환경에서 에러가 납니다.)
PowerShell
Install-Package WindowsAPICodePack-Shell -Version 1.1.1
Step 1: 공용 헬퍼 클래스 (The Solution)
다이얼로그 로직을 폼마다 복사/붙여넣기 하지 말고, DialogHelper라는 정적 클래스로 만들어 두면 유지보수가 쉽습니다.
파일명: Utils\DialogHelper.cs
C#
using System;
using System.Windows.Forms;
using Microsoft.WindowsAPICodePack.Dialogs; // NuGet 패키지 네임스페이스
namespace A2_SOP_Linescan.Utils
{
public static class DialogHelper
{
/// <summary>
/// 탐색기 스타일의 폴더 선택 다이얼로그를 엽니다.
/// </summary>
/// <param name="ownerHandle">부모 폼의 핸들 (this.Handle)</param>
/// <param name="initialPath">초기 진입 경로 (없으면 바탕화면)</param>
/// <param name="title">창 제목</param>
/// <returns>선택된 폴더 경로 (취소 시 string.Empty 반환)</returns>
public static string ShowFolderDialog(IntPtr ownerHandle, string initialPath = "", string title = "폴더 선택")
{
// 리소스 누수 방지를 위한 using 필수
using (CommonOpenFileDialog dialog = new CommonOpenFileDialog())
{
// [핵심 1] 폴더 선택 모드 활성화 (이게 없으면 파일 선택창이 됨)
dialog.IsFolderPicker = true;
dialog.Title = title;
dialog.Multiselect = false; // 다중 선택 방지
dialog.EnsurePathExists = true; // 존재하지 않는 경로 입력 방지
dialog.AddToMostRecentlyUsedList = false; // MRU 목록 오염 방지
dialog.AllowNonFileSystemItems = false; // 가상 폴더 선택 방지
// [핵심 2] 초기 경로 설정 (네트워크 경로 등)
if (!string.IsNullOrEmpty(initialPath) && System.IO.Directory.Exists(initialPath))
{
dialog.InitialDirectory = initialPath;
}
else
{
// 기본값: 바탕화면
dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
}
// [핵심 3] 부모 핸들을 넘겨주어 완벽한 모달(Modal)로 동작하게 함
if (dialog.ShowDialog(ownerHandle) == CommonFileDialogResult.Ok)
{
return dialog.FileName; // 사용자가 선택한 폴더 경로
}
}
return string.Empty; // 취소 버튼 누름
}
}
}
Step 2: 사용 방법 (Usage in Form)
메인 폼(FormMain)이나 설정 폼(FormConfig)에서 버튼을 눌렀을 때 사용하는 방법입니다.
파일명: FormConfig.cs
C#
using System;
using System.Windows.Forms;
using A2_SOP_Linescan.Utils; // 위에서 만든 Helper 네임스페이스
namespace A2_SOP_Linescan.UI
{
public partial class FormConfig : Form
{
public FormConfig()
{
InitializeComponent();
}
private void btnSelectPath_Click(object sender, EventArgs e)
{
// 1. 현재 텍스트박스에 있는 경로를 초기값으로 줌
string currentPath = txtSavePath.Text;
// 2. 헬퍼 함수 호출 (this.Handle을 넘기는 것이 중요!)
string selectedPath = DialogHelper.ShowFolderDialog(
this.Handle,
currentPath,
"검사 이미지 저장 경로를 선택하세요"
);
// 3. 결과 처리 (빈 문자열이면 취소한 것임)
if (!string.IsNullOrEmpty(selectedPath))
{
txtSavePath.Text = selectedPath;
// (옵션) 로그 남기기
// LogManager.Instance.Info($"저장 경로 변경됨: {selectedPath}");
}
}
}
}
Step 3: 핵심 코드 분석
- dialog.IsFolderPicker = true;
- 이 속성이 CommonOpenFileDialog의 정체성입니다.
- true: 폴더 선택 창 (우리가 원하는 것)
- false: 파일 열기 창 (일반적인 OpenFileDialog)
- dialog.ShowDialog(ownerHandle)
- 인자 없이 ShowDialog()를 쓰면 다이얼로그가 폼 뒤로 숨거나, 사용자가 다이얼로그를 무시하고 폼을 조작할 수 있습니다.
- this.Handle (IntPtr)을 넘겨주어야 윈도우 OS가 "이 다이얼로그는 저 폼의 자식이다"라고 인식하여, 부모 폼을 잠그고(Disable) 중앙에 띄워줍니다.
- CommonFileDialogResult.Ok
- WinForms 기본 다이얼로그는 DialogResult.OK를 쓰지만, 이 라이브러리는 CommonFileDialogResult 열거형을 씁니다. 혼동하지 않도록 주의하십시오.
이 코드를 복사해서 Utils 폴더에 넣어두시면, 프로젝트 내 어디서든 한 줄로 멋진 탐색기 창을 띄울 수 있습니다.
반응형