py-window-styles icon indicating copy to clipboard operation
py-window-styles copied to clipboard

Fix Unicode decoding issue with accented characters and special symbols

Open B16f00t opened this issue 11 months ago • 3 comments

This pull request addresses the issue with accented characters and special symbols in file paths during the drag-and-drop process.

Changes made:

  • Modified the py_drop_func to handle Unicode decoding errors.
  • Initially attempts to decode the file path using UTF-8 encoding.
  • If UTF-8 decoding fails (e.g., due to accented characters), it falls back to Windows-1252 encoding.

This fix ensures that file paths with characters like á, é, í, ó, ú, ñ, and others are handled correctly without causing errors.

This should address and close Issue #42.

B16f00t avatar Jan 25 '25 11:01 B16f00t

For some reason it doesn't work well with some characters like ă, ș and ț. Using the same code from #42 and trying again to drag the folder named ăâîșț to the tkinter window, I'm getting this output:

['C:\\Users\\lenovo\\Desktop\\aâî??']

And normally I should get

['C:\\Users\\lenovo\\Desktop\\ăâîșț']

Valer100 avatar Jan 25 '25 13:01 Valer100

I think this fix is wrong because you can't assume that the encoding for fallback is 'Windows-1252', for example in Chinese Simplified Windows, the correct encoding is 'gbk'.

image

Jesse205 avatar Nov 09 '25 02:11 Jesse205

In fact, just use create_unicode_buffer and DragQueryFileW, so that the string obtained is unicode.

diff --git a/pywinstyles/py_win_style.py b/pywinstyles/py_win_style.py
index fe41ddf..8056ff6 100644
--- a/pywinstyles/py_win_style.py
+++ b/pywinstyles/py_win_style.py
@@ -5,6 +5,7 @@ Version: 1.8
 """
 
 from __future__ import annotations
+from ctypes import create_unicode_buffer
 from typing import Any, Union, Callable
 
 try:
@@ -191,8 +192,8 @@ class apply_dnd():
         prototype = WINFUNCTYPE(typ, typ, typ, typ, typ)
         WM_DROP_FILES = 0x233
         GWL_WND_PROC = -4
-        create_buffer = c_buffer
-        func_DragQueryFile = (windll.shell32.DragQueryFile)
+        create_buffer = create_unicode_buffer
+        func_DragQueryFile = (windll.shell32.DragQueryFileW)
 
         def py_drop_func(hwnd, msg, wp, lp):
             global files
@@ -202,7 +203,7 @@ class apply_dnd():
                 files = []
                 for i in range(count):
                     func_DragQueryFile(typ(wp), i, file_buffer, sizeof(file_buffer))
-                    drop_name = file_buffer.value.decode("utf-8")
+                    drop_name = file_buffer.value
                     files.append(drop_name)
                 func(files)
                 windll.shell32.DragFinish(typ(wp))

Jesse205 avatar Nov 09 '25 02:11 Jesse205