Balloon WinApi 弹出窗口中的非 ascii 字符
Non ascii characters in Balloon WinApi popup
我尝试显示带有 Unicode 文本的气球弹出窗口,但我总是看到里面有 ???
个字符。当标题 (szInfoTitle
) 不包含 non-ascii 个字符时,一切正常。
下面是完整的 F# 示例:
type NotifyIconData =
struct
val mutable cbSize: System.Int32 // DWORD
val mutable hWnd: System.IntPtr // HWND
val mutable uID: System.Int32 // UINT
val mutable uFlags: System.Int32 // UINT
val mutable uCallbackMessage: System.Int32 // UINT
val mutable hIcon: System.IntPtr // HICON
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)>]
val mutable szTip: System.String // char[128]
val mutable dwState: System.Int32 // DWORD
val mutable dwStateMask: System.Int32 // DWORD
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)>]
val mutable szInfo: System.String // char[256]
val mutable uTimeoutOrVersion: System.Int32 // UINT
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)>]
val mutable szInfoTitle: System.String // char[64]
val mutable dwInfoFlags: System.Int32 // DWORD
val mutable guidItem: Guid
val mutable hBalloonIcon: IntPtr //HIcon
end
[<DllImport("shell32.dll", SetLastError = true)>]
extern bool Shell_NotifyIcon(uint dwMessage, NotifyIconData& pnid)
[<DllImport("kernel32.dll")>]
extern IntPtr GetConsoleWindow();
let createNotify hwnd =
let mutable data = NotifyIconData()
data.cbSize <- Marshal.SizeOf(typedefof<NotifyIconData>)
data.hWnd <- hwnd
data.uID <- 0
data.uFlags <- 0x00000001 ||| 0x00000002 ||| 0x00000004 ||| 0x00000008 ||| 0x00000020 ||| 0x00000080
data.szTip <- "Tooltip"
data.dwState <- 0
data.dwStateMask <- 0x00000001 ||| 0x00000002
data.guidItem <- Guid.NewGuid ()
data.hIcon <- PInvoke.User32.LoadIcon(IntPtr.Zero, IntPtr(32512))
let result = Shell_NotifyIcon(uint NotifyCommand.Add, &(data))
data.uTimeoutOrVersion <- 4
let versionResult = Shell_NotifyIcon(uint NotifyCommand.SetVersion, &(data))
data
let createBalloon message (d: NotifyIconData) =
let mutable data = d
data.uFlags <- 0x00000010 ||| 0x00000020
data.dwInfoFlags <- 4
data.hBalloonIcon <- PInvoke.User32.LoadIcon(IntPtr.Zero, IntPtr(32512))
data.szInfo <- message
data.szInfoTitle <- "Balloon два dva dede ąęśćóŌ"
data.uTimeoutOrVersion <- 30000
let result = Shell_NotifyIcon(uint NotifyCommand.Modify, &(data))
result
let showBallon hwnd message =
GetConsoleWindow ()
|> createNotify
|> createBalloon message
我尝试使用 Shell.NotifyIconW
但它也不起作用。
除了Shell_NotifyIconW
,你还需要检查你的NOTIFYICONDATA
是否是支持Unicode的宽字节版本。检查 cbSize
你得到:
- x86 ANSI :
cbSize
= 508
- x86 统一码:
cbSize
= 956
- x86 编码:
cbSize
= 528
- x86 ANSI :
cbSize
= 976
在我的测试中,使用没有任何字符集设置的示例,默认 cbSize = 528
(ansi 版本),您需要将结构和函数的字符集明确指定为 unicode:
[<StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)>]
type NotifyIconData =
struct
val mutable cbSize: System.Int32 // DWORD
val mutable hWnd: System.IntPtr // HWND
val mutable uID: System.Int32 // UINT
val mutable uFlags: System.Int32 // UINT
val mutable uCallbackMessage: System.Int32 // UINT
val mutable hIcon: System.IntPtr // HICON
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)>]
val mutable szTip: System.String // char[128]
val mutable dwState: System.Int32 // DWORD
val mutable dwStateMask: System.Int32 // DWORD
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)>]
val mutable szInfo: System.String // char[256]
val mutable uTimeoutOrVersion: System.Int32 // UINT
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)>]
val mutable szInfoTitle: System.String // char[64]
val mutable dwInfoFlags: System.Int32 // DWORD
val mutable guidItem: Guid
val mutable hBalloonIcon: IntPtr //HIcon
end
[<DllImport("shell32.dll", CharSet = CharSet.Unicode)>]
extern bool Shell_NotifyIcon(UInt32 dwMessage, NotifyIconData& pnid)
另外Shell_NotifyIcon
文档中也没有说明可以使用错误码
我尝试显示带有 Unicode 文本的气球弹出窗口,但我总是看到里面有 ???
个字符。当标题 (szInfoTitle
) 不包含 non-ascii 个字符时,一切正常。
下面是完整的 F# 示例:
type NotifyIconData =
struct
val mutable cbSize: System.Int32 // DWORD
val mutable hWnd: System.IntPtr // HWND
val mutable uID: System.Int32 // UINT
val mutable uFlags: System.Int32 // UINT
val mutable uCallbackMessage: System.Int32 // UINT
val mutable hIcon: System.IntPtr // HICON
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)>]
val mutable szTip: System.String // char[128]
val mutable dwState: System.Int32 // DWORD
val mutable dwStateMask: System.Int32 // DWORD
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)>]
val mutable szInfo: System.String // char[256]
val mutable uTimeoutOrVersion: System.Int32 // UINT
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)>]
val mutable szInfoTitle: System.String // char[64]
val mutable dwInfoFlags: System.Int32 // DWORD
val mutable guidItem: Guid
val mutable hBalloonIcon: IntPtr //HIcon
end
[<DllImport("shell32.dll", SetLastError = true)>]
extern bool Shell_NotifyIcon(uint dwMessage, NotifyIconData& pnid)
[<DllImport("kernel32.dll")>]
extern IntPtr GetConsoleWindow();
let createNotify hwnd =
let mutable data = NotifyIconData()
data.cbSize <- Marshal.SizeOf(typedefof<NotifyIconData>)
data.hWnd <- hwnd
data.uID <- 0
data.uFlags <- 0x00000001 ||| 0x00000002 ||| 0x00000004 ||| 0x00000008 ||| 0x00000020 ||| 0x00000080
data.szTip <- "Tooltip"
data.dwState <- 0
data.dwStateMask <- 0x00000001 ||| 0x00000002
data.guidItem <- Guid.NewGuid ()
data.hIcon <- PInvoke.User32.LoadIcon(IntPtr.Zero, IntPtr(32512))
let result = Shell_NotifyIcon(uint NotifyCommand.Add, &(data))
data.uTimeoutOrVersion <- 4
let versionResult = Shell_NotifyIcon(uint NotifyCommand.SetVersion, &(data))
data
let createBalloon message (d: NotifyIconData) =
let mutable data = d
data.uFlags <- 0x00000010 ||| 0x00000020
data.dwInfoFlags <- 4
data.hBalloonIcon <- PInvoke.User32.LoadIcon(IntPtr.Zero, IntPtr(32512))
data.szInfo <- message
data.szInfoTitle <- "Balloon два dva dede ąęśćóŌ"
data.uTimeoutOrVersion <- 30000
let result = Shell_NotifyIcon(uint NotifyCommand.Modify, &(data))
result
let showBallon hwnd message =
GetConsoleWindow ()
|> createNotify
|> createBalloon message
我尝试使用 Shell.NotifyIconW
但它也不起作用。
除了Shell_NotifyIconW
,你还需要检查你的NOTIFYICONDATA
是否是支持Unicode的宽字节版本。检查 cbSize
你得到:
- x86 ANSI :
cbSize
= 508 - x86 统一码:
cbSize
= 956 - x86 编码:
cbSize
= 528 - x86 ANSI :
cbSize
= 976
在我的测试中,使用没有任何字符集设置的示例,默认 cbSize = 528
(ansi 版本),您需要将结构和函数的字符集明确指定为 unicode:
[<StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)>]
type NotifyIconData =
struct
val mutable cbSize: System.Int32 // DWORD
val mutable hWnd: System.IntPtr // HWND
val mutable uID: System.Int32 // UINT
val mutable uFlags: System.Int32 // UINT
val mutable uCallbackMessage: System.Int32 // UINT
val mutable hIcon: System.IntPtr // HICON
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)>]
val mutable szTip: System.String // char[128]
val mutable dwState: System.Int32 // DWORD
val mutable dwStateMask: System.Int32 // DWORD
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)>]
val mutable szInfo: System.String // char[256]
val mutable uTimeoutOrVersion: System.Int32 // UINT
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)>]
val mutable szInfoTitle: System.String // char[64]
val mutable dwInfoFlags: System.Int32 // DWORD
val mutable guidItem: Guid
val mutable hBalloonIcon: IntPtr //HIcon
end
[<DllImport("shell32.dll", CharSet = CharSet.Unicode)>]
extern bool Shell_NotifyIcon(UInt32 dwMessage, NotifyIconData& pnid)
另外Shell_NotifyIcon
文档中也没有说明可以使用错误码