Pergunta

Running VBA no XP eu era capaz de chamar ActivateKeyboardLayout para mudar o meu idioma de entrada de Inglês para outro idioma. No entanto, isso não funciona sob Vista64.

Todas as sugestões ou soluções?

O código que é utilizado para trabalhar sob XP foi semelhante ao seguinte:

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

Houve uma sugestão para tentar

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

Quando eu tento isso eu recebo a mensagem de erro:

variável usa um tipo de automatização não suportado no Visual Basic

Foi útil?

Solução

A sua declaração para o ActivateKeyboardLayout é realmente incorreta. Para sistemas de 32 bits seu código deve ser algo como isto:

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

O 64 número de bits do sistema operacional é um pouco de um arenque vermelho neste caso. Desde que você está executando um aplicativo VBA deve ser executado como um aplicativo de 32 bits, independentemente do sistema operacional. Eu suspeito que o problema pode ser que em seu sistema Vista o layout do teclado Punjabi que você quer não está carregado. ActivateKeyboardLayout só vai funcionar para ativar um layout de teclado que já está carregado. Por alguma razão, os designers deste API sentiu que a falha devido ao layout do teclado não existente não foi um erro assim que o LastDLLError não está definido. Você pode querer olhar em usar LoadKeyboardLayout para este tipo de situação.

EDIT: para confirmar que o teclado layout que você está tentando obter é realmente carregado você pode usar isto:

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

Outras dicas

Este é apenas um palpite cego, mas você já tentou executar o seu aplicativo como administrador elevados para ver se ele faz a diferença? Qual é o código de erro / valor GetLastError?

Você tentou um .Net linha (como em VB.Net script ou esses trechos ) como:

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

InputLanguage deve ser suportado para Vista64 com um NET3.5

VB.Net código:

Public Sub ChangeInputLanguage(ByVal InputLang As InputLanguage)
   If InputLanguage.InstalledInputLanguages.IndexOf(InputLang) = -1 Then
        Throw New ArgumentOutOfRangeException()
   End If
    InputLanguage.CurrentInputLanguage = InputLang
End Sub

Para portabilidade de 64 bits pode ser necessário usar IntPtr. você pode dar a este um tiro?

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

Em edições de aplicativos do Office de 64 bits, o VBA é realmente de 64 bits. Consulte Office 2010 documentação para detalhes das mudanças. Para o exemplo dado na resposta de Stephen Martin , você precisará alterar o código da seguinte maneira para adicionar o atributo PtrSafe e Fixup os parâmetros que têm um tipo HKL na API Win32:

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

e

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

A única coisa que toda a gente parece ignorar aqui é que você está trabalhando em VBA, não em .NET. IntPtr é um tipo .NET que representa um número inteiro que é nativo à plataforma. Em uma plataforma de 32 bits é 32 bits, em uma plataforma de 64 bits, é 64 bits.

Tendo em conta que um HKL é um typedef para um identificador, que é um typedef para PVOID que é um typedef para * VOID, é exatamente o que você precisa, se você estivesse usando .NET.

VBA não tem nada para números de 64 bits, então você tem que ter uma abordagem diferente.

Em uma máquina de 64 bits, você terá que fazer algo como isto:

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

Este deve permitem que você passar um valor de 64 bits na pilha para a função de API (através de duas variáveis). No entanto, se você estiver indo para usar este código em 64 bits e 32 bits máquinas, você vai ter que fazer duas declarações da API e, em seguida, determinar qual a chamada.

Além disso, qualquer outro código em VBA que chama APIs que lidam com ponteiros ou alças terá que ser alterado de forma adequada para lidar com 64 bit de entrada (não 32).

Em uma nota lateral, o original da declaração de ActivateKeyboardLayout é errado, uma vez que teve um retorno do tipo Integer, que é um valor de 16 bits, enquanto a API retorna um tipo de HKL, que é 32 ou 64 bits, dependendo na plataforma.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top