كيف يمكنني الاتصال ActivateKeyboardLayout من 64bit Windows Vista باستخدام VBA

StackOverflow https://stackoverflow.com/questions/449207

سؤال

تشغيل VBA تحت XP كنت قادرا على استدعاء ActivateKeyboardLayout للتبديل رأيي اللغة من الإنجليزية إلى لغة أخرى.غير أن هذا لم يعد يعمل تحت Vista64.

أي اقتراحات أو الحلول?

التعليمات البرمجية التي تستخدم للعمل تحت 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

هل كانت مفيدة؟

المحلول

الخاص بك الإعلان عن 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-بت التطبيق بغض النظر عن نظام التشغيل.وأظن أن المشكلة قد يكون على ويندوز فيستا نظام البنجابية تخطيط لوحة المفاتيح الذي تريد تحميل.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

نصائح أخرى

هذا هو مجرد أعمى تخمين ، ولكن هل حاولت تشغيل التطبيق الخاص بك كما مرتفعة المسؤول لمعرفة ما إذا كان يحدث فرقا ؟ ما هو رمز الخطأ / قيمة GetLastError?

هل جرب .صافي خط (كما في VB.Net السيناريو أو تلك القصاصات) مثل:

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

64 بت قابلية قد تحتاج إلى استخدام IntPtr.يمكنك أن تجرب هذا ؟

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

في 64 بت من تطبيقات Office ، VBA هو في الواقع 64 بت.انظر Office 2010 الوثائق لمزيد من التفاصيل حول التغييرات.على المثال المذكور في ستيفن مارتن الإجابة, سوف تحتاج إلى تغيير التعليمات البرمجية كما يلي لإضافة PtrSafe السمة إصلاح المعلمات التي HKL اكتب في 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

الشيء الذي يبدو أن الجميع نغفل هنا هو أن كنت تعمل في VBA ، ليس في .صافي.IntPtr هو .صافي النوع الذي يمثل عدد صحيح الذي هو الأصلي إلى المنصة.على إصدار 32-بت هو 32 بت على 64 بت هو 64 بت.

بالنظر إلى أن HKL هو typedef عن التعامل معها ، وهو ل typedef PVOID وهو typedef عن الفراغ * ، هو بالضبط ما تحتاجه إذا كنت تستخدم .صافي.

VBA لا يملك أي شيء 64 بت الأرقام, لذلك عليك أن تأخذ نهجا مختلفا.

على 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

هذا يجب أن تسمح لك لتمرير 64 بت القيمة على المكدس على دالة API (عبر اثنين من المتغيرات).ومع ذلك ، إذا كنت تنوي استخدام هذا الرمز على 64 بت و 32 بت آلات كنت ستطبعها لجعل اثنين من الإعلانات API ومن ثم تحديد أي واحد للاتصال.

أيضا, أي رمز آخر في VBA التي تدعو واجهات برمجة التطبيقات التي تتعامل مع مؤشرات أو مقابض يجب ان يتم تغييرها بشكل مناسب للتعامل مع 64 بت الإدخال (لا 32).

على الجانب علما ، الأصلي إعلان ActivateKeyboardLayout هو الخطأ ، كما كان عائد من نوع عدد صحيح ، وهو 16-بت القيمة ، في حين API نوع من HKL ، والتي هي 32 أو 64 بت ، اعتمادا على المنصة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top