2009-01-16 36 views
5

在XP下運行VBA我能夠調用ActivateKeyboardLayout將我的輸入語言從英語切換到另一種語言。但是,這不再適用於Vista64。如何使用VBA從64位Windows Vista調用ActivateKeyboardLayout

任何建議或解決方法?

所使用XP下工作的代碼是類似以下內容:

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

有人建議嘗試

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

當我嘗試這個,我得到的錯誤信息:

變量使用Visual Basic不支持的自動化類型

+0

有趣,我會在家裏檢查我的配置(Vista 64)。你有代碼與你的Access VBA調用關聯嗎? – VonC 2009-02-13 13:47:17

+0

我已更新問題代碼 – Noah 2009-02-13 14:12:46

+0

您是對的。我不知道的一個項目是鍵盤常量可能會有所不同,具體取決於加載的鍵盤版本。這讓我誤以爲你的代碼是不正確的。錯誤是我的。我試圖通過修改這個問題來解決這個問題。 – Noah 2009-02-21 14:14:03

回答

5

您對ActivateKeyboardLayout的聲明實際上是不正確的。對於32位系統,你的代碼應該是這樣的:

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系統上你想要的旁遮普鍵盤佈局沒有加載。 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 
0

這只是一個盲目的猜測,但是您是否曾嘗試將您的應用程序作爲高級管理員運行,以查看它是否有所作爲?什麼是GetLastError的錯誤代碼/值?

+0

沒有錯誤,只是不起作用(即改變鍵盤佈局) – Noah 2009-02-13 14:31:24

0

你有沒有嘗試.Net line(如VB.Net scriptthose snippets),如:

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

問題是,我從VBA調用它(通過訪問)我不認爲.NET功能可用。這就是爲什麼在XP下我需要直接調用API。 – Noah 2009-02-13 13:32:41

0

對於64位可移植性,您可能需要使用IntPtr。你能給這個鏡頭嗎?

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

,每個人都似乎在這裏忽略的事情是,你是在VBA工作,不在.NET中。 IntPtr是一個.NET類型,它表示一個本地平臺的整數。在32位平臺上,它是32位,在64位平臺上是64位。

鑑於HKL是一個句柄的typedef,它是一個用於VOID *的typedef的PVOID類型定義,如果您使用的是.NET,它正是您所需要的。

對於64位數字,VBA沒有任何東西,所以你必須採取不同的方法。

在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 

應該允許您通過堆棧的API函數(跨兩個變量在64位值)。但是,如果您打算在64位和32位計算機上使用此代碼,則必須對API進行兩次聲明,然後確定要調用哪一個。

此外,VBA中調用處理指針或句柄的API的任何其他代碼都必須進行相應更改以處理64位輸入(而非32位)。

在附註中,ActivateKeyboardLayout的原始聲明是錯誤的,因爲它有一個返回類型Integer,它是一個16位值,而API返回一個HKL類型,它是32位或64位,取決於平臺。

0

在Office應用程序的64位版本中,VBA確實是64位版本。有關更改的詳細信息,請參見Office 2010 documentation。對於Stephen Martin's answer給出的例子中,你將需要更改代碼,如下所示添加PtrSafe屬性和修正內容有Win32 API中一個HKL類型的參數:

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 
相關問題