2009-01-16 8 views
5

VBA unter XP laufen konnte ich ActivateKeyBoardLayout nennen meine Eingabesprache von Englisch in eine andere Sprache zu wechseln. Dies funktioniert jedoch nicht mehr unter Vista64.Wie kann ich anrufen ActivateKeyBoardLayout von 64-Bit-Windows Vista VBA

Irgendwelche Vorschläge oder Abhilfen?

Der Code, der unter XP verwendet zu arbeiten, war ähnlich der folgenden:

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

es einen Vorschlag

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

Wenn ich dies versuchen zu versuchen, war erhalte ich die Fehlermeldung:

Variable verwendet einen Automatisierungstyp, der in Visual Basic nicht unterstützt wird

+0

Interessante Ich werde das auf meiner Konfiguration (Vista 64) zu Hause überprüfen. Ist der Code mit Ihrem Access VBA-Anruf verknüpft? – VonC

+0

Ich habe die Frage mit dem Code – Noah

+0

aktualisiert Sie haben Recht. Das eine Element, das mir nicht bewusst war, ist, dass die Tastaturkonstanten variieren können, abhängig von der Version der geladenen Tastatur. Dies führte mich zu der falschen Meinung, dass Ihr Code falsch war. Der Fehler gehört mir. Ich habe versucht, dies zu korrigieren, indem ich die Frage modifiziere. – Noah

Antwort

5

Ihre Deklaration für ActivateKeyboardLayout ist eigentlich falsch. Für 32-Bit-Systeme sollten Sie Ihren Code so etwas wie dieses:

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 

Die 64-Bitness des Betriebssystems ist ein bisschen wie ein roter Hering in diesem Fall. Da Sie eine VBA-App ausführen, muss sie unabhängig vom Betriebssystem als 32-Bit-App ausgeführt werden. Ich vermute, Ihr Problem könnte sein, dass auf Ihrem Vista-System das von Ihnen gewünschte Punjabi-Tastaturlayout nicht geladen ist. ActivateKeyboardLayout funktioniert nur, um ein Tastaturlayout zu aktivieren, das bereits geladen ist. Aus irgendeinem Grund empfanden die Entwickler dieser API, dass ein Fehler aufgrund des nicht vorhandenen Tastaturlayouts kein Fehler war, so dass der LastDllError nicht gesetzt ist. Vielleicht möchten Sie LoadKeyboardLayout für diese Art von Situation verwenden.

EDIT: Um zu überprüfen, dass das Tastaturlayout Sie tatsächlich zu bekommen versuchen geladen können Sie verwenden:

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

oldLayout kommt als "0" zurück, was darauf hinweist, dass die Änderung nicht stattgefunden hat. Die PJ-Tastatur ist geladen, da ich sie ständig benutze, und mein Workaround ist, die "ALT-SHIFT" -Tasten zu senden, die diese Tastatur aktivieren. Wie ich bereits erwähnt habe, funktionieren diese Routinen unter XP – Noah

+0

Ich habe keine Vista64-Workstation, aber ich habe es gerade auf einer Windows 2008 64-Bit-Maschine Setup als Workstation versucht und es hat wie erwartet funktioniert, die Tastatur wurde Punjabi geändert. Sind Sie sicher, dass Ihre Tastatur/Sprachkombination Punjabi/Punjabi tatsächlich installiert ist? nicht etwas ganz anderes. –

+0

Ich hatte gerade eine Chance, dies auf Vista zu überprüfen, und es hat gut funktioniert. Sie haben also entweder einen obskuren Fehler in Vista entdeckt, der etwas mit der Konfiguration Ihres Computers zu tun hat, oder Sie haben das Punjabi/Punjabi Tastaturlayout/die Eingabesprache nicht installiert. –

0

Dies ist nur eine blinde Vermutung, aber haben Sie versucht, Ihre App als erhöhte Administrator ausführen, um zu sehen, ob es einen Unterschied macht? Was ist der Fehlercode/Wert von GetLastError?

+0

Kein Fehler, funktioniert einfach nicht (zB das Tastaturlayout ändern) – Noah

0

Haben Sie versucht, eine .Net line (wie in VB.Net script oder those snippets) wie:

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

InputLanguage sollte für Vista64 mit einem .Net3.5

VB.Net Code unterstützt:

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

Das Problem ist, dass ich es von VBA (über Access) anrufe. Ich glaube nicht, dass .NET-Funktionen verfügbar sind. Deshalb musste ich unter XP die API direkt aufrufen. – Noah

+0

Interessant, ich werde das auf meiner Konfiguration zu Hause überprüfen. Ist der Code mit Ihrem Access VBA-Anruf verknüpft? – VonC

0

Für die 64-Bit-Portabilität müssen Sie möglicherweise IntPtr verwenden. Kannst du das versuchen?

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

Siehe zusätzliche Informationen in Frage – Noah

-1

Die Sache, dass jeder hier ist zu übersehen scheint, dass Sie in VBA arbeiten, nicht in .NET. IntPtr ist ein .NET-Typ, der eine auf der Plattform native Ganzzahl darstellt. Auf einer 32-Bit-Plattform sind es 32 Bit, auf einer 64-Bit-Plattform sind es 64 Bit.

Vorausgesetzt, dass ein HKL ist ein typedef für ein Handle, das ist ein typedef für PVOID, die ein typedef für VOID * ist, ist es genau das, was Sie brauchen, wenn Sie .NET verwenden.

VBA hat nichts für 64-Bit-Zahlen, so müssen Sie einen anderen Ansatz.

Auf einem 64-Bit-Maschine, werden Sie, so etwas zu tun haben:

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 

Diese sollte können Sie einen 64-Bit-Wert auf dem Stapel auf die API-Funktion übergeben (über zwei Variablen). Wenn Sie diesen Code jedoch auf 64-Bit- und 32-Bit-Rechnern verwenden möchten, müssen Sie zwei Deklarationen der API vornehmen und dann bestimmen, welche API aufgerufen werden soll.

Außerdem muss jeder andere Code in VBA, der APIs aufruft, die sich mit Zeigern oder Handles befassen, entsprechend geändert werden, um 64-Bit-Eingaben zu verarbeiten (nicht 32).

Nebenbei bemerkt ist die ursprüngliche Deklaration von ActivateKeyboardLayout falsch, da es einen Rückgabetyp von Integer hatte, der ein 16-Bit-Wert ist, während die API einen Typ von HKL zurückgibt, der 32 oder 64 Bit ist abhängig von der Plattform.

+0

Da VBA-Code immer als 32-Bit-Code ausgeführt wird, greift er nur auf die 32-Bit-API zu, so dass keine 64-Bit-Zeiger benötigt werden. In Ihrer HKL64-Struktur sollten die High- und Low-Teile für Little-Endiantys umgekehrt sein. Die kanonische Methode zum Übergeben von 64-Bit-Ganzzahlwerten in VBA besteht auch in der Verwendung des Währungstyps. –

0

In 64-Bit-Editionen von Office-Anwendungen ist VBA tatsächlich 64-Bit. Details zu den Änderungen finden Sie unter Office 2010 documentation. Für das Beispiel in Stephen Martin's answer gegeben, müssen Sie den Code ändern als das PtrSafe Attribut hinzufügen folgt und die Parameter fixup, die einen HKL Typ in der Win32-API haben:

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 

und

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