How can I call ActivateKeyboardLayout from 64-bit Windows Vista using VBA

Running VBA under XP I managed to call ActivateKeyboardLayout to switch the input language from English to another. However, this no longer works under Vista64.

Any suggestions or workarounds?

The code used to work in XP was similar to the following:

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

It was suggested to try

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

When I try this, I get an error message:

The variable uses an automation type that is not supported in Visual Basic.

+5
source share
6 answers

Your ad for ActivateKeyboardLayout is actually incorrect. For 32-bit systems, your code should look something like this:

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 Punjabi, , . 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
+5

, , , ? /​​ GetLastError?

0

. ( VB.Net script ), :

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

InputLanguage 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
0

64- IntPtr. ?

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

64- Office VBA 64-. . Office 2010. , Stephen Martin answer, , PtrSafe , HKL Win32 API:

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
0

, , , , , VBA, .NET. IntPtr - .NET, , . 32- 32 , 64- 64 .

, HKL typedef , typedef PVOID, typedef VOID *, , , .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).

On the other hand, the original ActivateKeyboardLayout declaration is incorrect because it had an Integer return type, which is a 16-bit value, while the API returns an HKL type, which is 32 or 64 bits, depending on the platform.

-1
source

All Articles