2009-01-16 27 views
5

Chạy VBA trong XP Tôi có thể gọi ActivateKeyboardLayout để chuyển ngôn ngữ nhập liệu của tôi từ tiếng Anh sang ngôn ngữ khác. Tuy nhiên, điều này không còn hoạt động trong Vista64 nữa.Làm thế nào tôi có thể gọi ActivateKeyboardLayout từ 64bit Windows Vista bằng VBA

Bất kỳ đề xuất hoặc cách giải quyết nào?

Mã được sử dụng để làm việc dưới XP là tương tự như sau:

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ó một gợi ý để thử

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

Khi tôi cố gắng này, tôi nhận được thông báo lỗi:

Biến sử dụng loại Tự động hóa không được hỗ trợ trong Visual Basic

+0

Thú vị , Tôi sẽ kiểm tra xem trên cấu hình của tôi (Vista 64) ở nhà. Bạn có liên kết mã với cuộc gọi VBA truy cập của mình không? – VonC

+0

Tôi đã cập nhật câu hỏi với mã số – Noah

+0

Bạn đã đúng. Một mục mà tôi không biết là các hằng số bàn phím có thể khác nhau, tùy thuộc vào phiên bản bàn phím được tải. Điều này dẫn tôi đến quan điểm sai lầm rằng mã của bạn không chính xác. Lỗi là của tôi. Tôi đã cố gắng khắc phục điều này bằng cách sửa đổi câu hỏi. – Noah

Trả lời

5

Tuyên bố của bạn cho ActivateKeyboardLayout thực sự không chính xác. Đối với hệ thống 32-bit mã của bạn nên có một cái gì đó như thế này:

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 

Phiên bản 64-bitness của hệ điều hành là một chút của một cá trích đỏ trong trường hợp này. Vì bạn đang chạy một ứng dụng VBA, nó phải chạy như một ứng dụng 32 bit bất kể hệ điều hành. Tôi nghi ngờ vấn đề của bạn có thể là trên hệ thống Vista của bạn bố trí bàn phím Punjabi mà bạn muốn không được tải. ActivateKeyboardLayout sẽ chỉ hoạt động để kích hoạt bố cục bàn phím đã được tải. Đối với một số lý do các nhà thiết kế của API này cảm thấy rằng thất bại do bố trí bàn phím không tồn tại không phải là một lỗi để LastDllError không được thiết lập. Bạn có thể muốn xem xét sử dụng LoadKeyboardLayout cho loại tình huống này.

EDIT: Để kiểm tra xem hai cách bố trí bàn phím bạn đang cố gắng để có được thực sự là nạp bạn có thể sử dụng này:

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 không trả về là "0", cho biết rằng thay đổi không xảy ra. Bàn phím PJ được nạp, vì tôi sử dụng nó mọi lúc, và công việc của tôi là gửi các phím "ALT-SHIFT" kích hoạt bàn phím đó. Như tôi đã đề cập trước đó, các thói quen này hoạt động dưới XP – Noah

+0

Tôi không có trạm làm việc Vista64 nhưng tôi đã thử cài đặt máy Windows 2008 64 bit làm máy trạm và nó hoạt động như mong đợi, bàn phím được đổi thành Punjabi. Bạn có chắc chắn rằng sự kết hợp bàn phím/ngôn ngữ của bạn Punjabi/Punjabi thực sự được cài đặt; không phải thứ gì đó khác biệt một cách tinh tế. –

+0

Tôi vừa có cơ hội để kiểm tra điều này trên Vista và nó hoạt động tốt. Vì vậy, bạn có hoặc tìm thấy một lỗi mơ hồ trong Vista có cái gì để làm với cấu hình máy tính của bạn hoặc bạn không có bố trí bàn phím/đầu vào Punjabi/Punjabi được cài đặt. –

0

Đây chỉ là phỏng đoán mù, nhưng bạn đã thử chạy ứng dụng của mình với tư cách quản trị viên nâng cao để xem liệu nó có tạo sự khác biệt không? Mã lỗi/giá trị của GetLastError là gì?

+0

Không có lỗi, chỉ cần không làm việc (tức là thay đổi cách bố trí bàn phím) – Noah

0

Bạn có thử một .Net line (như trong VB.Net script hoặc those snippets) như:

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

InputLanguage cần được hỗ trợ cho Vista64 với một mã .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

Vấn đề là tôi gọi nó từ VBA (thông qua Access) Tôi không nghĩ rằng các tính năng .NET có sẵn. Đó là lý do tại sao trong XP tôi cần gọi trực tiếp cho API. – Noah

+0

Thú vị, tôi sẽ kiểm tra cấu hình của tôi ở nhà. Bạn có liên kết mã với cuộc gọi VBA truy cập của mình không? – VonC

0

Đối với tính di động 64 bit, bạn có thể cần sử dụng IntPtr. Bạn có thể cho cú đánh này không?

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

Xem thông tin bổ sung trong câu hỏi – Noah

-1

Điều mà tất cả mọi người dường như bỏ qua ở đây là bạn đang làm việc trong VBA, không trong lưới. IntPtr là một kiểu .NET đại diện cho một số nguyên có nguồn gốc từ nền tảng. Trên nền tảng 32 bit, nó là 32 bit, trên nền tảng 64 bit, nó là 64 bit.

Cho rằng HKL là một typedef cho một xử lý, đó là một typedef cho PVOID là một typedef cho VOID *, đó chính xác là những gì bạn cần, nếu bạn đang sử dụng .NET.

VBA không có gì cho số 64 bit, vì vậy bạn phải thực hiện một cách tiếp cận khác.

Trên một máy 64-bit, bạn sẽ phải làm một cái gì đó như thế này:

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 

này nên cho phép bạn vượt qua một giá trị 64 bit trên cây rơm vào chức năng API (qua hai biến). Tuy nhiên, nếu bạn định sử dụng mã này trên các máy 64 bit và 32 bit, bạn sẽ phải thực hiện hai khai báo của API và sau đó xác định cái nào cần gọi.

Ngoài ra, bất kỳ mã nào khác trong VBA gọi API xử lý con trỏ hoặc tay cầm sẽ phải được thay đổi một cách thích hợp để xử lý đầu vào 64 bit (không phải 32).

Trên một lưu ý phụ, bản khai gốc của ActivateKeyboardLayout là sai, vì nó có kiểu trả về là Số nguyên, là giá trị 16 bit, trong khi API trả về loại HKL, 32 hoặc 64 bit, tùy thuộc vào nền tảng.

+0

Vì mã VBA luôn chạy dưới dạng mã 32 bit, nó chỉ truy cập API 32 bit nên không cần đến các con trỏ 64 bit. Cấu trúc HKL64 của bạn nên có các phần Cao và Thấp được đảo ngược để có ít tính cuối cùng. Ngoài ra, phương pháp kinh điển để chuyển các giá trị số nguyên 64 bit trong VBA là sử dụng loại tiền tệ. –

0

Trong phiên bản 64 bit của ứng dụng Office, VBA thực sự là 64 bit. Xem Office 2010 documentation để biết chi tiết về các thay đổi. Đối với ví dụ được đưa ra trong Stephen Martin's answer, bạn sẽ cần phải thay đổi mã như sau để thêm thuộc tính PtrSafe và fixup các thông số đó có một loại HKL trong Win32 API:

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 
Các vấn đề liên quan