Question

Exécution de VBA sous XP, j’ai pu appeler ActivateKeyboardLayout pour faire passer ma langue de saisie de l’anglais à une autre langue. Toutefois, cela ne fonctionne plus sous Vista64.

Avez-vous des suggestions ou des solutions de contournement?

Le code qui fonctionnait sous XP était semblable au suivant:

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

Il a été suggéré d'essayer

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

Lorsque j'essaie, le message d'erreur suivant s'affiche:

La variable utilise un type Automation non pris en charge dans Visual Basic

Était-ce utile?

La solution

Votre déclaration pour ActivateKeyboardLayout est en réalité incorrecte. Pour les systèmes 32 bits, votre code devrait ressembler à ceci:

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

Les 64 bits du système d’exploitation sont un peu un fil rouge dans ce cas. Étant donné que vous exécutez une application VBA, celle-ci doit être exécutée en tant qu'application 32 bits, quel que soit le système d'exploitation. Je soupçonne que votre problème peut provenir du fait que la configuration de clavier Punjabi que vous souhaitez n'est pas chargée sur votre système Vista. ActivateKeyboardLayout fonctionnera uniquement pour activer une disposition de clavier déjà chargée. Pour une raison quelconque, les concepteurs de cette API ont estimé qu'une défaillance due à une disposition de clavier inexistante n'étant pas une erreur, la LastDllError n'est pas définie. Vous voudrez peut-être envisager d’utiliser LoadKeyboardLayout pour ce type de situation.

EDIT: Pour vérifier que la configuration de clavier que vous essayez d’obtenir est bien chargée, vous pouvez utiliser ceci:

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

Autres conseils

Ceci est juste une hypothèse aveugle, mais avez-vous essayé d'exécuter votre application en tant qu'administrateur élevé pour voir si cela fait une différence? Quel est le code / valeur d'erreur de GetLastError?

Avez-vous essayé un Ligne .Net (comme dans Script VB.Net ou ces extraits ) comme:

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

InputLanguage devrait être prise en charge pour Vista64 avec un .Net3.5

Code 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

Pour une portabilité 64 bits, vous devrez peut-être utiliser IntPtr. Pouvez-vous donner un coup de feu?

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

Dans les éditions 64 bits des applications Office, VBA est bien 64 bits. Consultez la documentation Office 2010 pour plus d'informations. détails des changements. Pour l'exemple cité dans réponse de Stephen Martin , vous devez modifier le code comme suit pour ajouter l'attribut PtrSafe et corriger les paramètres associés à un type HKL dans l'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

et

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

Ce que tout le monde semble oublier, c’est que vous travaillez en VBA, pas en .NET. IntPtr est un type .NET qui représente un entier natif de la plate-forme. Sur une plate-forme 32 bits, c'est 32 bits, sur une plate-forme 64 bits, c'est 64 bits.

Etant donné qu'un HKL est un typedef pour un handle, qui est un typedef pour PVOID qui est un typedef pour VOID *, c'est exactement ce dont vous avez besoin si vous utilisiez .NET.

VBA n’a rien pour les nombres 64 bits, vous devez donc adopter une approche différente.

Sur une machine 64 bits, vous devrez faire quelque chose comme ceci:

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

Ceci devrait vous permettre de transmettre une valeur 64 bits de la pile à la fonction API (à travers deux variables). Cependant, si vous envisagez d’utiliser ce code sur des machines 64 bits et 32 ??bits, vous devrez faire deux déclarations de l’API, puis déterminer laquelle appeler.

De même, tout autre code de VBA appelant des API traitant des pointeurs ou des descripteurs devra être modifié de manière appropriée pour gérer une entrée 64 bits (et non 32).

Sur une note de côté, la déclaration d'origine de ActivateKeyboardLayout est fausse, car elle avait un type de retour Integer, qui est une valeur de 16 bits, tandis que l'API renvoie un type de HKL, 32 ou 64 bits, en fonction sur la plate-forme.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top