Domanda

Con VBA sotto XP sono stato in grado di chiamare ActivateKeyboardLayout per cambiare la mia lingua di input dall'inglese in un'altra lingua. Tuttavia, questo non funziona più con Vista64.

Qualche suggerimento o soluzione alternativa?

Il codice che funzionava con XP era simile al seguente:

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

C'è stato un suggerimento da provare

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

Quando provo questo ottengo il messaggio di errore:

La variabile utilizza un tipo di automazione non supportato in Visual Basic

È stato utile?

Soluzione

La tua dichiarazione per ActivateKeyboardLayout non è corretta. Per i sistemi a 32 bit il codice dovrebbe essere simile al seguente:

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

Il 64-testimone del sistema operativo è un po 'un'aringa rossa in questo caso. Poiché stai eseguendo un'app VBA, deve essere in esecuzione come app a 32 bit indipendentemente dal sistema operativo. Ho il sospetto che il tuo problema potrebbe essere che sul tuo sistema Vista il layout della tastiera Punjabi che desideri non è caricato. ActivateKeyboardLayout funzionerà solo per attivare un layout di tastiera già caricato. Per qualche motivo i progettisti di questa API hanno ritenuto che l'errore dovuto al layout di tastiera inesistente non fosse un errore, quindi LastDllError non è stato impostato. Potresti voler esaminare l'utilizzo di LoadKeyboardLayout per questo tipo di situazione.

EDIT: per verificare che il layout della tastiera che si sta tentando di ottenere sia effettivamente caricato, è possibile utilizzare questo:

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

Altri suggerimenti

Questa è solo un'ipotesi cieca, ma hai provato a eseguire la tua app come amministratore elevato per vedere se fa la differenza? Qual è il codice / valore di errore di GetLastError?

Hai provato a .Net line (come in VB.Net script o quei frammenti ) come:

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

InputLanguage dovrebbe essere supportato per Vista64 con un .Net3.5

Codice 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

Per la portabilità a 64 bit potrebbe essere necessario utilizzare IntPtr. Puoi provarci?

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

Nelle edizioni a 64 bit delle app di Office, VBA è effettivamente a 64 bit. Vedere Documentazione di Office 2010 per dettagli delle modifiche. Per l'esempio fornito in la risposta di Stephen Martin , dovrai modificare il codice come segue per aggiungere l'attributo PtrSafe e correggere i parametri che hanno un tipo HKL nell'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

La cosa che tutti sembrano trascurare qui è che stai lavorando in VBA, non in .NET. IntPtr è un tipo .NET che rappresenta un numero intero nativo della piattaforma. Su una piattaforma a 32 bit è a 32 bit, su una piattaforma a 64 bit, è a 64 bit.

Dato che un HKL è un typedef per un handle, che è un typedef per PVOID che è un typedef per VOID *, è esattamente ciò di cui hai bisogno, se stavi usando .NET.

VBA non ha nulla per i numeri a 64 bit, quindi devi adottare un approccio diverso.

Su una macchina a 64 bit, dovrai fare qualcosa del genere:

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

Questo dovrebbe consentire di passare un valore di 64 bit nello stack alla funzione API (attraverso due variabili). Tuttavia, se utilizzerai questo codice su macchine a 64 e 32 bit, dovrai fare due dichiarazioni dell'API e quindi determinare quale chiamare.

Inoltre, qualsiasi altro codice in VBA che chiama API che gestiscono puntatori o handle dovrà essere modificato in modo appropriato per gestire l'input a 64 bit (non 32).

In una nota a margine, la dichiarazione originale di ActivateKeyboardLayout è errata, poiché aveva un tipo restituito Integer, che è un valore a 16 bit, mentre l'API restituisce un tipo di HKL, che è 32 o 64 bit, a seconda sulla piattaforma.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top