VBA 中的 UTF-8 字符 Shell_NotifyIconW [英] UTF-8 Characters Shell_NotifyIconW in VBA

查看:40
本文介绍了VBA 中的 UTF-8 字符 Shell_NotifyIconW的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Shell_NotifyIcon Windows API 向任务栏的状态区域发送消息.

Shell_NotifyIcon Windows API sends a message to the taskbar's status area.

我正在寻找一种方法,让 Windows 通知 API 可以使用 UTF-8 字符.

I'm looking a way to make Windows notification API works with UTF-8 characters.

下面的代码运行良好,但仅限于 ANSI 字符.

The code below works well, but only with ANSI characters.

UTF-8 字符显示为??".

The UTF-8 Characters are displayed as "??".

Option Explicit
Private Declare PtrSafe Function Shell_NotifyIconA Lib "shell32.dll" (ByVal dwMessage As Long, ByRef nfIconData As NOTIFYICONDATA) As LongPtr
Public nfIconData As NOTIFYICONDATA
Private Type NOTIFYICONDATA
    cbSize As Long
    hwnd As LongPtr
    uID As Long
    uFlags As Long
    uCallbackMessage As Long
    hIcon As LongPtr
    szTip As String * 128
    dwState As Long
    dwStateMask As Long
    szInfo As String * 256
    uTimeout As Long
    szInfoTitle As String * 64
    dwInfoFlags As Long
End Type
Public Function toast(Optional ByVal title As String, Optional ByVal info As String, Optional ByVal flag As Long)
With nfIconData
    .dwInfoFlags = flag
    .uFlags = &H10
    .szInfoTitle = title
    .szInfo = info
    .cbSize = &H1F8
End With
Shell_NotifyIconW &H0, nfIconData
Shell_NotifyIconW &H1, nfIconData
End Function
'Flags for the balloon message..
'None = 0
'Information = 1
'Exclamation = 2
'Critical = 3
Sub TestANSI()
toast "Hi"    
End Sub

Sub testUTF8()
toast ChrW(55357) & ChrW(56397)
End Sub

简单地将 Windows API 声明中的 A 更改为 W 并不能解决问题.

Simply changing the A to W in windows API declaration doesn't fix it.

有人有使用 Shell_NotifyIconW 处理 UTF-8 字符的经验吗?

Anyone have experience using Shell_NotifyIconW for UTF-8 charachters?

我已经尝试过下面的代码,但它不起作用.

I've tried with the code below, but it doesn't work.

Option Explicit
Private Declare PtrSafe Function Shell_NotifyIconW Lib "shell32.dll" (ByVal dwMessage As Long, ByRef nfIconData As NOTIFYICONDATA) As LongPtr
Public nfIconData As NOTIFYICONDATA
Private Type NOTIFYICONDATA
    cbSize As Long
    hwnd As LongPtr
    uID As Long
    uFlags As Long
    uCallbackMessage As Long
    hIcon As LongPtr
    szTip As String * 128
    dwState As Long
    dwStateMask As Long
    szInfo As String * 256
    uTimeout As Long
    szInfoTitle As String * 64
    dwInfoFlags As Long
End Type
Public Function toast(Optional ByVal title As String, Optional ByVal info As String, Optional ByVal flag As Long)
With nfIconData
    .dwInfoFlags = flag
    .uFlags = &H10
    .szInfoTitle = title
    .szInfo = info
    .cbSize = &H1F8
End With
Shell_NotifyIconW &H0, nfIconData
Shell_NotifyIconW &H1, nfIconData
End Function
'Flags for the balloon message..
'None = 0
'Information = 1
'Exclamation = 2
'Critical = 3

Sub TestANSI()
toast "Hi"    
End Sub
Sub testUTF8()
toast ChrW(55357) & ChrW(56397)
End Sub

推荐答案

UnicodeUTF-8 是不可互换的术语(请参阅 https://www.joelonsoftware.com/articles/Unicode.html).一种是概念,另一种是坚持该概念的方式.

Unicode and UTF-8 are not interchangeable terms (please see https://www.joelonsoftware.com/articles/Unicode.html). One is a concept, and the other is a way of persisting that concept.

W 函数以 UTF-16 的形式使用 Unicode,因此您希望以这种方式向它们提供 Unicode.

W functions in Windows use Unicode in the form of UTF-16, so you want to provide Unicode to them in that fashion.

您的 AW 版本都没有正确声明,您想先修复它.
然后,对于 W 函数,您必须避免 隐式字符串转换 VB 执行,对于您需要将固定长度的字符串声明为字节数组.因为 VB 字符串已经是 UTF-16 中的 Unicode,这是 W 函数所期望的,您只需要将这些字符串中的字节复制到这些字节数组中.不需要转换,但您需要小心将每个字符串中的最后两个字节留为零.

Both your A and W versions are not declared correctly, you want to fix that first.
Then, for the W function, you have to avoid the implicit string conversion VB performs, for which you need to declare the fixed length strings as byte arrays. Because VB strings are already Unicode in UTF-16, which is what W functions expect, you simply need to copy the bytes from these strings into these byte arrays. No conversion is necessary, but you need to be careful to leave the last two bytes as zeroes in each string.

请注意,与 A 函数不同,W 函数要求您同时提供标题和信息(即 在文档中提到).如果您只提供一个,则不会显示.

Note that unlike the A function, the W function requires you to provide both the title and the info (which is called out in the documentation). If you only provide one, it won't show.

另请注意,不幸的是,VBA 没有为 64 位结构成员提供正确的填充,这严重破坏了 code>LongPtr,所以你需要自己提供.

Also note that unfortunately VBA does not provide correct padding for structure members in 64 bits which heavily undermines the usefulness of LongPtr, so you would need to provide that yourself.

Option Explicit

Private Declare PtrSafe Function Shell_NotifyIconW Lib "shell32.dll" (ByVal dwMessage As Long, ByRef nfIconData As NOTIFYICONDATAW) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)

Private Type NOTIFYICONDATAW
  cbSize As Long
#If Win64 Then
  padding1 As Long
#End If
  hwnd As LongPtr
  uID As Long
  uFlags As Long
  uCallbackMessage As Long
#If Win64 Then
  padding2 As Long
#End If
  hIcon As LongPtr
  szTip(1 To 128 * 2) As Byte
  dwState As Long
  dwStateMask As Long
  szInfo(1 To 256 * 2) As Byte
  uTimeout As Long
  szInfoTitle(1 To 64 * 2) As Byte
  dwInfoFlags As Long
End Type

Private Const NIM_ADD As Long = &H0&
Private Const NIM_MODIFY As Long = &H1&
Private Const NIF_INFO As Long = &H10&

Private Function Min(ByVal a As Long, ByVal b As Long) As Long
  If a < b Then Min = a Else Min = b
End Function

Public Sub Toast(Optional ByVal title As String, Optional ByVal info As String, Optional ByVal flag As Long)
  Dim nfIconData As NOTIFYICONDATAW
  
  With nfIconData
    .cbSize = Len(nfIconData)
    
    .uFlags = NIF_INFO
    .dwInfoFlags = flag
    
    If Len(title) > 0 Then
      CopyMemory ByVal VarPtr(.szInfoTitle(LBound(.szInfoTitle))), ByVal StrPtr(title), Min(Len(title) * 2, UBound(.szInfoTitle) - LBound(.szInfoTitle) + 1 - 2)
    End If
    
    If Len(info) > 0 Then
      CopyMemory ByVal VarPtr(.szInfo(LBound(.szInfo))), ByVal StrPtr(info), Min(Len(info) * 2, UBound(.szInfo) - LBound(.szInfo) + 1 - 2)
    End If
  End With
  
  Shell_NotifyIconW NIM_ADD, nfIconData
  Shell_NotifyIconW NIM_MODIFY, nfIconData
End Sub

Toast ChrW$(55357) & ChrW$(56397), ChrW$(55357) & ChrW$(56397)

这篇关于VBA 中的 UTF-8 字符 Shell_NotifyIconW的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆