Ookii-dialogs-wpf: VistaOpenFileDialog.InitialDirectory๊ฐ€ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2019๋…„ 09์›” 26์ผ  ยท  9์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: ookii-dialogs/ookii-dialogs-wpf

InitialDirectory ์†์„ฑ์ด ๋กœ์ปฌ ๋ฐ ๊ธฐ์กด ํด๋”๋กœ ์„ค์ •๋œ ๋Œ€ํ™” ์ƒ์ž๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๊ฒƒ์€ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค.
๋Œ€ํ™” ์ƒ์ž์—๋Š” ํ•ญ์ƒ ํŒŒ์ผ์ด ์—ด๋ฆฐ ๋งˆ์ง€๋ง‰ ํด๋”๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

 VistaOpenFileDialog dialog = new VistaOpenFileDialog();
 dialog.Filter = "JSON Dateien (*.json)|*.json";
 dialog.InitialDirectory = "C:\\";

์˜ˆ์ƒ๋˜๋Š” ๋™์ž‘ :
VistaOpenFileDialog๋Š” InitialDirectory๊ฐ€ "C : \"๋กœ ์„ค์ •๋˜์–ด์žˆ์„ ๋•Œ ํ•ญ์ƒ C : \์˜ ๋‚ด์šฉ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

Windows 10 Pro 1903 / .Net Framework 4.6

good first issue hacktoberfest help wanted needs-design

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋งŽ์€ Windows ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ๋งˆ์ง€๋ง‰ ๊ฒฝ๋กœ๋ฅผ ๊ธฐ์–ตํ•˜๋Š” "์Šค๋งˆํŠธ ํ•œ"๊ธฐ๋ณธ ๋™์ž‘์„ ๊ฐ€์ง€๊ณ ์žˆ๋Š” ๊ฒƒ์€ ์‚ฌ์‹ค์ด์ง€๋งŒ, ์•ฑ ๊ฐœ๋ฐœ์ž๊ฐ€ ์‚ฌ์šฉ์ž๋ฅผ ๋•๊ธฐ ์œ„ํ•ด ํŠน์ • ์ดˆ๊ธฐ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์ง€์ •ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ํŠน์ • ํ”„๋กœ์ ํŠธ ๊ด€๋ จ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ๋กœ๋“œ / ์ €์žฅํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ™˜๊ฒฝ์˜ ๊ฒฝ์šฐ ์ด๋Š” ๊ธฐ๋ณธ ๋™์ž‘์ž…๋‹ˆ๋‹ค. notepad / paint / word์—์„œ "smart"๋งˆ์ง€๋ง‰ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์„ฑ ๊ฐ€์‹œ๊ณ  ์“ธ๋ชจ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๊ฒŒ๋‹ค๊ฐ€ : Microsoft.Win32.OpenFileDialog ๋Š” ๋˜‘๊ฐ™์€ ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ ์˜ˆ์ƒ๋Œ€๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  9 ๋Œ“๊ธ€

@soulflyman์„ ์‹ ๊ณ  ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ Windows์™€ ํ•จ๊ป˜ ์ œ๊ณต๋˜๋Š” ๋‹ค๋ฅธ ๋ชจ๋“  ์•ฑ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ๊ณผ ์ผ์น˜ํ•˜๋ฏ€๋กœ "์˜ฌ๋ฐ”๋ฅธ"๋™์ž‘์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋งˆ์ง€๋ง‰์œผ๋กœ ์‚ฌ์šฉํ•œ ํด๋”๋ฅผ ๊ธฐ์–ตํ•ฉ๋‹ˆ๋‹ค.

๋ฉ”๋ชจ์žฅ์ด๋‚˜ ๊ทธ๋ฆผํŒ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ผํ•˜๊ฒŒ ์žฌํ˜„ ํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

@buildcomplete ๋Š” PR # 2์™€ ์œ ์‚ฌํ•œ ๋ฌธ์ œ๋ฅผ๋ณด๊ณ 

๋Œ€๋‹จํ•˜๊ฒŒ ๋“ค๋ฆฌ ๋„ค์š”. ๋ง์”€ ๋“œ๋ฆฐ๋Œ€๋กœ ์ƒˆ๋กœ์šด ์„ค์ •์œผ๋กœ ์ „์ ์œผ๋กœ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ๋™์ž‘ (์˜ˆ : ๋ฉ”๋ชจ์žฅ)์„ ์•Œ๊ณ  ์žˆ์—ˆ์ง€๋งŒ InitialDirectory๊ฐ€ ์ˆ˜๋™์œผ๋กœ ์„ค์ •๋˜๋ฉด์ด ๋™์ž‘์ด ๋ณ€๊ฒฝ ๋  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.
๋‚ด ๊ฐ€์ •์€ InitialDirectory๊ฐ€ ๋Œ€ํ™” ์ƒ์ž๊ฐ€ ํ‘œ์‹œ ๋  ๋•Œ๋งˆ๋‹ค ๋˜๋Š” ์ ์–ด๋„์ด ์‹คํ–‰์ค‘์ธ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ์ธ์Šคํ„ด์Šค์— ํ‘œ์‹œ๋˜๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ๋ผ๋Š” ์˜๋ฏธ์˜€์Šต๋‹ˆ๋‹ค. ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ๋‹ซ๊ณ  ๋‹ค์‹œ ์‹œ์ž‘ํ•œ ํ›„์—๋„ ๋ฌด์‹œ๋˜์ง€ ์•Š์„ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
๋‹ค์–‘ํ•œ VistaSaveFileDialog ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ• / ์ˆœ์„œ๋กœ ์‹คํ—˜ํ–ˆ์ง€๋งŒ ์„ฑ๊ณตํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ๋Œ€ํ™” ์ƒ์ž๋Š” ํ•ญ์ƒ InitialDirectoy ์„ค์ •์„ ๋ฌด์‹œํ•˜๊ณ  ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

VistaFileDialog.cs์—์„œ '_initialDirectory'๊ฐ€ ์›ํ•˜๋Š” ๊ฒฝ๋กœ๋กœ ์„ค์ •๋˜์—ˆ์Œ์„ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ฑฐ๊ธฐ์—์„œ ๊ฐ’์€ NativeMethods.cs์˜ CreateItemFromParsingName(string path) ๋กœ ์ด๋™ ํ•œ ๋‹ค์Œ COM ๊ตฌ๋ฉ ์•„๋ž˜๋กœ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
public static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IntPtr pbc, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);

  public static Interop.IShellItem CreateItemFromParsingName(string path)
 {
     object item;
     Guid guid = new Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe"); // IID_IShellItem
     int hr = NativeMethods.SHCreateItemFromParsingName(path, IntPtr.Zero, ref guid, out item);
     if( hr != 0 )
         throw new System.ComponentModel.Win32Exception(hr);
     return (Interop.IShellItem)item;
 }

๋ฐ˜ํ™˜ ๋œ COM ๊ฐœ์ฒด๊ฐ€ null ์ธ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๊ธฐ ๋•Œ๋ฌธ์—์ด SHCreateItemFromParsingName ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํŒจํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

CreateItemFromParsingName

๋ฉ”์„œ๋“œ ์„œ๋ช…์— SetLastError = true๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ํ˜ธ์ถœ ํ›„ Marshal.GetLastWin32Error() ์„ ์‹œ๋„ํ–ˆ์ง€๋งŒ 0์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋งŽ์€ Windows ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ๋งˆ์ง€๋ง‰ ๊ฒฝ๋กœ๋ฅผ ๊ธฐ์–ตํ•˜๋Š” "์Šค๋งˆํŠธ ํ•œ"๊ธฐ๋ณธ ๋™์ž‘์„ ๊ฐ€์ง€๊ณ ์žˆ๋Š” ๊ฒƒ์€ ์‚ฌ์‹ค์ด์ง€๋งŒ, ์•ฑ ๊ฐœ๋ฐœ์ž๊ฐ€ ์‚ฌ์šฉ์ž๋ฅผ ๋•๊ธฐ ์œ„ํ•ด ํŠน์ • ์ดˆ๊ธฐ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์ง€์ •ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ํŠน์ • ํ”„๋กœ์ ํŠธ ๊ด€๋ จ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ๋กœ๋“œ / ์ €์žฅํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ™˜๊ฒฝ์˜ ๊ฒฝ์šฐ ์ด๋Š” ๊ธฐ๋ณธ ๋™์ž‘์ž…๋‹ˆ๋‹ค. notepad / paint / word์—์„œ "smart"๋งˆ์ง€๋ง‰ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์„ฑ ๊ฐ€์‹œ๊ณ  ์“ธ๋ชจ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๊ฒŒ๋‹ค๊ฐ€ : Microsoft.Win32.OpenFileDialog ๋Š” ๋˜‘๊ฐ™์€ ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ ์˜ˆ์ƒ๋Œ€๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋„ ๊ฐ™์€ ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
๋Œ€ํ™” ์ƒ์ž ์ดˆ๊ธฐ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์„ค์ •ํ•  ์ˆ˜์žˆ๋Š” ์„ค์ •์„ ์ถ”๊ฐ€ํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?
๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” Ookii ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฝ”๋“œ์— ๋“ค์–ด๊ฐ”๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ InitialDirectory ์†์„ฑ์„ ๊ณ ๋ คํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค.
์ด ์ฝ”๋“œ ์ค„์„ VistaFileDialog.cs ํŒŒ์ผ๋กœ ๋ณ€๊ฒฝํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
internal virtual void SetDialogProperties(Ookii.Dialogs.Wpf.Interop.IFileDialog dialog) ๋ฉ”์†Œ๋“œ๋กœ
์ด ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝ

// Initial directory
if( !string.IsNullOrEmpty(_initialDirectory) )
{
    Ookii.Dialogs.Wpf.Interop.IShellItem item = NativeMethods.CreateItemFromParsingName(_initialDirectory);
    dialog.SetDefaultFolder(item);
}

...์—

// Initial directory
if( !string.IsNullOrEmpty(_initialDirectory) )
{
    Ookii.Dialogs.Wpf.Interop.IShellItem item = NativeMethods.CreateItemFromParsingName(_initialDirectory);
    dialog.SetFolder(item);
}

๋๋‚ฌ์Šต๋‹ˆ๋‹ค.
์ด์ œ Ookii ๋Œ€ํ™” ์ƒ์ž๊ฐ€ InitialDirectory ์†์„ฑ์œผ๋กœ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.

๋„์›€์ด ๋˜์—ˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

@ gitjsdr26 ๋‹น์‹ ์€ @augustoproiete์— ๋Œ€ํ•œ ํ™๋ณด๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

@nzain , ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. GitHub๋กœ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ข‹์•„, ๋‚˜๋Š”์ด ๋ฌธ์ œ๋ฅผ ๋ฐํžˆ๊ธฐ ์œ„ํ•ด ๋” ๋งŽ์€ ์ •๋ณด๋ฅผ ๋ชจ์•˜๋‹ค.

WPF์˜ OpenFileDialog.InitialDirectory์— ๋Œ€ํ•ด ๋ฌธ์„œํ™” ๋œ ๊ฒƒ๊ณผ ๊ฐ™์€ InitialDirectory ์†์„ฑ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋งํ•ฉ๋‹ˆ๋‹ค.

ํŒŒ์ผ ๋Œ€ํ™” ์ƒ์ž์— ํ‘œ์‹œ๋˜๋Š” ์ดˆ๊ธฐ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๊ฐ€์ ธ ์˜ค๊ฑฐ๋‚˜ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

Ookii Dialogs ์‚ฌ์šฉ์ž๋Š” ์†์„ฑ์˜ ์ด๋ฆ„์ด ๋™์ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋™์ผํ•œ ๋™์ž‘์„ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค. ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๋งŽ์€ ์ƒํ™ฉ์—์„œ์ด ์†์„ฑ์„ ์„ค์ •ํ•ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค (๋ฉ”๋ชจ์žฅ ๋“ฑ). ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๊ฒƒ์€ ๋‹ค๋ฅธ ์ด์•ผ๊ธฐ์ž…๋‹ˆ๋‹ค. _ ์†์„ฑ์ด ์„ค์ •๋˜๋ฉด ์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

InitialDirectory ๋ฅผ ํ˜„์žฌ ํ˜ธ์ถœ ๋œ IFileDialog::SetDefaultFolder ์™€ ํ˜ผ๋™ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ์—ฌ๊ธฐ์— ๋ฌธ์„œ๊ฐ€ ๋งํ•ฉ๋‹ˆ๋‹ค.

์ตœ๊ทผ์— ์‚ฌ์šฉ ๋œ ํด๋” ๊ฐ’์ด์—†๋Š” ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ํด๋”๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด (์ตœ๊ทผ์— ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํด๋”๊ฐ€ ์—†์Œ) ๊ฒฝ์šฐ์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ํด๋”๋ฅผ ์„ค์ •ํ•ด๋„ ์•„๋ฌด๋Ÿฐ ํšจ๊ณผ๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ๊ธฐ๋Šฅ์ด ๋ˆ„๊ตฌ์—๊ฒŒ๋‚˜ ํ•„์š”ํ•œ ๊ฒฝ์šฐ DefaultDirectory ์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์ „์˜ ์“ธ๋ชจ์—†๋Š” ์œ ๋ฌผ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์–ธ์ œ ํšจ๊ณผ๊ฐ€ ์žˆ๋Š”์ง€ ์•„๋Š” ์‚ฌ๋žŒ์ด ์žˆ์œผ๋ฉด ์•Œ๋ ค์ฃผ์„ธ์š”.

PR?

# 2 PR์€ ํ˜„์žฌ 2 ๋…„ ๋™์•ˆ (!) ์—ด๋ ค ์žˆ์œผ๋ฉฐ ๋น„์Šทํ•œ ๊ฒƒ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. ์ €์ž @buildcomplete ๋Š” ์ž์‹ ์˜ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ์ ์–ด๋„ ํ•œ ๋ฒˆ์€ ์ž‘๋™ @ gitjsdr26์ด ์ œ์•ˆํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ์ž‘์—…์„
IFileDialog::SetDefaultFolder(...) ~ IFileDialog::SetFolder(...) .

PR ์ƒ์„ฑ์— ์‹œ๊ฐ„์„ ๋‚ญ๋น„ํ•˜๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค (์ด ๋‹จ์ผ ๋ผ์ธ๋„ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค).

@augustoproiete์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜๋Š”์ง€ ์•Œ๋ ค์ฃผ์„ธ์š” :)

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰