在 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 不支持的自动化类型

有帮助吗?

解决方案

您的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

其他提示

这仅仅是一个盲目的猜测,但你尝试过运行你的应用作为提升的管理员,看它是否有差别?什么是GetLastError函数的错误代码/值?

你有没有尝试过 .Net线路 (如 VB.Net 脚本 或者 那些片段) 喜欢:

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

输入语言 应该支持 Vista64 .Net3.5

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

有关的64位的可移植性您可能需要使用的IntPtr。你可以给这个一杆?

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

这是每个人似乎都在这里忽略的事情是,你是在VBA工作,而不是在.NET。 IntPtr的是代表一个整数,其是天然的平台.NET类型。在32位的平台它是32位,64位的平台上,它是64位。

假设一个HKL是一个把手,这是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

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

此外,在VBA任何其他代码调用与指针或句柄处理的API将必须被适当地改变,可处理64位输入端(未32)。

在一个方面说明,ActivateKeyboardLayout的原始声明是错误的,因为它有整数,它是一个16位值返回类型,而API返回一个类型HKL,它是32或64位,这取决于的在平台。

scroll top