| # ★ BrowseForFolder | |
| # ★★★★★★★★★★★★★ | |
| # | |
| # Author/s : cremno | |
| # RGSS ver : 1 to 3 | |
| module BrowseForFolder | |
| class BrowseForFolderError < StandardError | |
| end | |
| HWND = Win32API.new('user32', 'GetActiveWindow', 'V', 'L').call | |
| SHBrowseForFolder = Win32API.new('shell32', 'SHBrowseForFolderW', 'P', 'L') | |
| SHGetPathFromIDList = | |
| Win32API.new('shell32', 'SHGetPathFromIDListW', 'LP', 'L') | |
| CoTaskMemFree = Win32API.new('ole32', 'CoTaskMemFree', 'L', 'V') | |
| MultiByteToWideChar = | |
| Win32API.new('kernel32', 'MultiByteToWideChar', 'LLPLPL', 'L') | |
| WideCharToMultiByte = | |
| Win32API.new('kernel32', 'WideCharToMultiByte', 'LLPLPLPP', 'L') | |
| BIF_RETURNONLYFSDIRS = 0x0000_0001 | |
| BIF_EDITBOX = 0x0000_0010 | |
| BIF_NEWDIALOGSTYLE = 0x0000_0040 | |
| BIF_USENEWUI = BIF_EDITBOX | BIF_NEWDIALOGSTYLE | |
| CP_UTF8 = 65_001 | |
| MAX_PATH = 260 | |
| SIZEOF_WCHAR_T = 2 | |
| def self.alloc_buffer(size) | |
| "\0" * size | |
| end | |
| def self.str_to_wcs(str) | |
| len = MultiByteToWideChar.call(CP_UTF8, 0, str, -1, 0, 0) | |
| if len <= 0 | |
| fail(BrowseForFolderError, "MultiByteToWideChar returned #{len}") | |
| end | |
| wcs = alloc_buffer(len * SIZEOF_WCHAR_T) | |
| MultiByteToWideChar.call(CP_UTF8, 0, str, -1, wcs, len) | |
| wcs | |
| end | |
| def self.wcs_to_str(wcs) | |
| len = WideCharToMultiByte.call(CP_UTF8, 0, wcs, -1, 0, 0, 0, 0) | |
| if len <= 0 | |
| fail(BrowseForFolderError, "WideCharToMultiByte returned #{len}") | |
| end | |
| str = alloc_buffer(len - 1) | |
| WideCharToMultiByte.call(CP_UTF8, 0, wcs, -1, str, len, 0, 0) | |
| str | |
| end | |
| def self.select(title = 'Select a folder:', default_if_cancelled = '') | |
| flags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI | |
| bi = [HWND, 0, 0, str_to_wcs(title), flags, 0, 0, 0].pack('LLLpLLl') | |
| pidlist = SHBrowseForFolder.call(bi) | |
| if pidlist == 0 | |
| default_if_cancelled | |
| else | |
| path = alloc_buffer(MAX_PATH * SIZEOF_WCHAR_T) | |
| r = SHGetPathFromIDList.call(pidlist, path) | |
| r == 0 && fail(BrowseForFolderError, "SHGetPathFromIDList returned #{r}") | |
| wcs_to_str(path) | |
| end | |
| ensure | |
| CoTaskMemFree.call(pidlist) | |
| end | |
| end |