5

在 XP 下运行 VBA 我能够调用 ActivateKeyboardLayout 将我的输入语言从英语切换到另一种语言。但是,这不再适用于 Vista64。

有什么建议或解决方法吗?

以前在 XP 下工作的代码类似于以下内容:

Private Declare Function ActivateKeyboardLayout Lib "user32" ( _
    ByVal HKL As Long, ByVal flags As Integer) As Integer
Const aklPUNJABI As Long = &H4460446
ActivateKeyboardLayout aklPUNJABI, 0

有人建议尝试

Public Declare Function ActivateKeyboardLayout Lib "user32" ( _
    ByVal nkl As IntPtr, ByVal Flags As uint) As Integer

当我尝试这个时,我收到错误消息:

变量使用 Visual Basic 不支持的自动化类型

4

6 回答 6

5

您对 ActivateKeyboardLayout 的声明实际上是不正确的。对于 32 位系统,您的代码应该是这样的:

Private Declare Function ActivateKeyboardLayout Lib "user32" (ByVal HKL As Long, _
    ByVal flags As Long) As Long

Const aklPUNJABI As Long = &H4460446
Dim oldLayout as Long
oldLayout = ActivateKeyboardLayout(aklPUNJABI, 0)
If oldLayout = 0 Then
   'Oops an error'
Else
   'Save old layout for later restore?'
End If

在这种情况下,操作系统的 64 位有点像红鲱鱼。由于您正在运行 VBA 应用程序,因此无论操作系统如何,它都必须作为 32 位应用程序运行。我怀疑您的问题可能是在您的 Vista 系统上未加载您想要的旁遮普语键盘布局。ActivateKeyboardLayout 仅用于激活已加载的键盘布局。出于某种原因,此 API 的设计者认为由于键盘布局不存在而导致的失败不是错误,因此未设置 LastDllError。对于这种情况,您可能需要考虑使用 LoadKeyboardLayout。

编辑:要仔细检查您尝试获取的键盘布局是否已实际加载,您可以使用以下命令:

Private Declare Function GetKeyboardLayoutList Lib "user32" (ByVal size As Long, _
    ByRef layouts As Long) As Long

Dim numLayouts As Long
Dim i As Long
Dim layouts() As Long

numLayouts = GetKeyboardLayoutList(0, ByVal 0&)
ReDim layouts(numLayouts - 1)
GetKeyboardLayoutList numLayouts, layouts(0)

Dim msg As String
msg = "Loaded keyboard layouts: " & vbCrLf & vbCrLf

For i = 0 To numLayouts - 1
   msg = msg & Hex(layouts(i)) & vbCrLf
Next

MsgBox msg
于 2009-02-16T18:21:11.813 回答
0

这只是一个盲目的猜测,但是您是否尝试过以提升的管理员身份运行您的应用程序以查看它是否有所作为?GetLastError 的错误代码/值是什么?

于 2009-01-16T03:07:35.650 回答
0

您是否尝试过.Net 行(如VB.Net 脚本那些片段),例如:

InputLanguage.CurrentInputLanguage = 
    InputLanguage.FromCulture(New System.Globalization.CultureInfo("ar-EG"))

带有.Net3.5的 Vista64 应该支持InputLanguage

VB.Net 代码:

Public Sub ChangeInputLanguage(ByVal InputLang As InputLanguage)
   If InputLanguage.InstalledInputLanguages.IndexOf(InputLang) = -1 Then
        Throw New ArgumentOutOfRangeException()
   End If
    InputLanguage.CurrentInputLanguage = InputLang
End Sub
于 2009-02-13T08:01:53.960 回答
0

对于 64 位可移植性,您可能需要使用 IntPtr。你能试一试吗?

Public Declare Function ActivateKeyboardLayout Lib "user32" (ByVal nkl As IntPtr, ByVal Flags As uint) As Integer
于 2009-02-14T17:49:15.287 回答
0

在 64 位版本的 Office 应用程序中,VBA 确实是 64 位的。有关更改的详细信息,请参阅Office 2010 文档。对于Stephen Martin 的回答中给出的示例,您需要按如下方式更改代码以添加属性并修复在 Win32 APIPtrSafe中具有类型的参数:HKL

Private Declare PtrSafe Function ActivateKeyboardLayout Lib "user32" (ByVal HKL As LongPtr, _
    ByVal flags As Long) As LongPtr

Const aklPUNJABI As LongPtr = &H4460446
Dim oldLayout as LongPtr
oldLayout = ActivateKeyboardLayout(aklPUNJABI, 0)
If oldLayout = 0 Then
   'Oops an error'
Else
   'Save old layout for later restore?'
End If

Private Declare PtrSafe Function GetKeyboardLayoutList Lib "user32" (ByVal size As Long, _
    ByRef layouts As LongPtr) As Long

Dim numLayouts As Long
Dim i As Long
Dim layouts() As LongPtr

numLayouts = GetKeyboardLayoutList(0, ByVal 0&)
ReDim layouts(numLayouts - 1)
GetKeyboardLayoutList numLayouts, layouts(0)

Dim msg As String
msg = "Loaded keyboard layouts: " & vbCrLf & vbCrLf

For i = 0 To numLayouts - 1
   msg = msg & Hex(layouts(i)) & vbCrLf
Next

MsgBox msg
于 2016-12-03T00:33:09.257 回答
-1

在这里每个人似乎都忽略了一件事情,那就是您是在 VBA 中工作,而不是在 .NET 中工作。IntPtr 是一种 .NET 类型,它表示平台原生的整数。在 32 位平台上是 32 位,在 64 位平台上是 64 位。

鉴于 HKL 是句柄的 typedef,它是 PVOID 的 typedef,它是 VOID * 的 typedef,如果您使用的是 .NET,这正是您所需要的。

VBA 没有针对 64 位数字的任何内容,因此您必须采用不同的方法。

在 64 位机器上,您必须执行以下操作:

Public Type HKL64
    High As Long
    Low As Long
End Type

Private Declare Function ActivateKeyboardLayout Lib "user32" ( _
    Byval HklHigh As Long, Byval HklLow As Long, _
    ByVal flags As Integer) As HKL64

应该允许您将堆栈上的 64 位值传递给 API 函数(跨两个变量)。但是,如果您要在 64 位和 32 位机器上使用此代码,您将不得不对 API 进行两次声明,然后确定调用哪一个。

此外,VBA 中调用处理指针或句柄的 API 的任何其他代码都必须适当更改以处理 64 位输入(不是 32 位)。

附带说明一下,ActivateKeyboardLayout 的原始声明是错误的,因为它的返回类型为 Integer,这是一个 16 位值,而 API 返回的类型是 HKL,它是 32 位或 64 位,具体取决于平台.

于 2009-02-19T01:12:48.327 回答