PowerShell调用SendMessage向Notepad2发Unicode文本仅成功1字符的问题
解决Notepad2(Scintilla控件)接收Unicode文本仅显示单个字符的问题
问题背景
已实现通过SendMessage API向标准Notepad发送ANSI和Unicode格式文本,但向Notepad2发送时,ANSI格式正常,Unicode格式仅能显示第一个字符。已尝试将Notepad2默认编码设为UTF-8/UTF-16并重启实例,问题依旧。
问题原因
Notepad使用标准Win32 Edit控件,对WM_SETTEXT消息的Unicode处理符合通用规范;但Notepad2基于Scintilla编辑器,该控件对通用WM_SETTEXT的Unicode支持存在兼容性问题,更推荐使用Scintilla专属的消息接口来设置文本。
修复后的PowerShell脚本
Set-StrictMode -Version Latest $code = @' [DllImport("user32.dll", CharSet = CharSet.Unicode)] public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW")] public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg, IntPtr wParam, string lParam); [DllImport("user32.dll", CharSet = CharSet.Ansi, EntryPoint = "SendMessageA")] public static extern IntPtr SendMessageA(IntPtr hWnd, int Msg, IntPtr wParam, string lParam); '@ $myAPI = Add-Type -MemberDefinition $code -Name Win32ScintillaAPI -Namespace Win32 -PassThru # 切换为Notepad2路径,确保系统能找到可执行文件 $App = "Notepad2.exe" # Notepad2的编辑器控件类名是Scintilla $MyClass = "Scintilla" # 启动两个Notepad2实例分别测试ANSI和Unicode $np2_ansi = Start-Process -PassThru -FilePath $App $np2_unicode = Start-Process -PassThru -FilePath $App # 等待窗口初始化完成,避免句柄获取失败 $null = $np2_ansi.WaitForInputIdle() $null = $np2_unicode.WaitForInputIdle() # 获取主窗口句柄和Scintilla控件句柄 $hwndMain_ansi = $np2_ansi.MainWindowHandle $hwndMain_unicode = $np2_unicode.MainWindowHandle $hwndEdit_ansi = $myAPI::FindWindowEx($hwndMain_ansi, [IntPtr]::Zero, $MyClass, $null) $hwndEdit_unicode = $myAPI::FindWindowEx($hwndMain_unicode, [IntPtr]::Zero, $MyClass, $null) $testText = "ĐĐĐĐảảảảả" $WM_SETTEXT = 0x000C # Scintilla专属设置文本消息,wParam用于指定编码格式 $SCI_SETTEXT = 0x00C2 # UTF-16对应的编码标识 $SC_CP_UTF16 = 1200 # 发送ANSI格式文本(使用SendMessageA) $null = $myAPI::SendMessageA($hwndEdit_ansi, $WM_SETTEXT, [IntPtr]::Zero, "ANSI测试: " + $testText) # 发送Unicode格式文本(使用Scintilla专属消息+UTF-16编码指定) $null = $myAPI::SendMessageW($hwndEdit_unicode, $SCI_SETTEXT, [IntPtr]$SC_CP_UTF16, "Unicode测试: " + $testText)
关键修改说明
- 替换为Scintilla专属消息:用
SCI_SETTEXT(值0x00C2)替代通用的WM_SETTEXT,该消息是Scintilla专门设计的文本设置接口,对Unicode支持更完善。 - 明确编码参数:
SCI_SETTEXT的wParam传入SC_CP_UTF16(值1200),明确告知Scintilla传入字符串的编码格式为UTF-16。 - 简化API声明:移除冗余的SendMessage重载,只保留对应ANSI和Unicode的版本,避免参数传递混淆。
内容的提问来源于stack exchange,提问作者LiquidMetal
相关产品推荐
相关产品推荐

