I'm trying to create a choose folder-dialog from Python, but I'm having problems setting the initial folder path for the dialog. I think it's a problem converting the string to a LPARAM
when I'm setting the _BROWSEINFO
structure.
bi.lParam = cast(path.encode("ascii", "ignore"), POINTER(LPARAM)).contents
I'm getting this error in the callback:
windll.user32.SendMessageA(handle, _BFFM_SETSELECTIONA, 1, lpdata)
ctypes.ArgumentError: argument 4: <class 'OverflowError'>: int too long to convert
Below is the code I'm using, it seems to work well except the call to SendMessageA.
I'm setting the _BROWSEINFO
structure in browse_folder
,
_WM_USER = 0x400
_BFFM_INITIALIZED = 1
_BFFM_SETSELECTIONA = _WM_USER + 102
_BFFM_SETSELECTIONW = _WM_USER + 103
_BIF_RETURNONLYFSDIRS = 0x00000001
_BIF_NEWDIALOGSTYLE = 0x00000040
_BFFCALLBACK = WINFUNCTYPE(None, HWND, UINT, LPARAM, LPARAM)
def _browse_callback(handle, umsg, lparam, lpdata):
if(umsg == _BFFM_INITIALIZED):
if(lpdata is not None):
windll.user32.SendMessageA(handle, _BFFM_SETSELECTIONA, 1, lpdata)
return 0
class _SHITEMID(Structure):
_fields_ = [
("cb", USHORT),
("abID", BYTE)]
class _ITEMIDLIST(Structure):
_fields_ = [
("mkid", POINTER(_SHITEMID))]
class _BROWSEINFO(Structure):
_fields_ = [
("hwndOwner", HWND),
("pidlRoot", UINT),
("pszDisplayName", LPCSTR),
("lpszTitle", LPCSTR),
("ulFlags", UINT),
("lpfn", _BFFCALLBACK),
("lParam", LPARAM),
("iImage", INT)]
def browse_folder(path, message):
display_name = create_string_buffer(MAX_PATH)
end_path = create_string_buffer(MAX_PATH)
pidl_root = _ITEMIDLIST()
bi = _BROWSEINFO()
bi.hwndOwner = 0
bi.pidlRoot = 0
bi.pszDisplayName = addressof(display_name)
bi.lpszTitle = message.encode("ascii", "ignore")
bi.ulFlags = _BIF_RETURNONLYFSDIRS | _BIF_NEWDIALOGSTYLE
bi.lpfn = _BFFCALLBACK(_browse_callback)
bi.lParam = cast(path.encode("ascii", "ignore"), POINTER(LPARAM)).contents
bi.iImage = 0
pidl = windll.shell32.SHBrowseForFolder(addressof(bi))
print(display_name.value)
windll.shell32.SHGetPathFromIDList(pidl, addressof(end_path))
print(repr(end_path.value))
I switched to unicode and the wide character type as suggested by the comments.
The problem was casting it to an LPARAM
and then dereferencing, but the comments led me to the method from_buffer
on LPARAM
.
I set lParam
as follows:
bi.lParam = LPARAM.from_buffer(c_wchar_p(path))
User contributions licensed under CC BY-SA 3.0