There seem to be two ways to do it. A very complicated way, and a simple way.
Code: Select all
Global old
Global En_layout, hKL
Enumeration #PB_Event_FirstCustomValue
#APP_Event_KBDLayoutChanged
EndEnumeration
Macro force_change_to_En
If GetKeyboardLayout_(0) <> En_layout ; En
ActivateKeyboardLayout_(hKL, #KLF_REORDER)
EndIf
EndMacro
Procedure MakeLong(low, high)
ProcedureReturn low | (high<<16)
EndProcedure
Procedure WndProc(hWnd, uMsg, wParam, lParam)
If uMsg = #WM_INPUTLANGCHANGE
If lParam <> En_layout
Debug "diff"
PostEvent(#APP_Event_KBDLayoutChanged)
EndIf
EndIf
ProcedureReturn CallWindowProc_(old, hWnd, uMsg, wParam, lParam)
EndProcedure
En_layout = MakeLong(1033, 1033) ; En
If OpenWindow(0, 0, 0, 322, 250, "EditorGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
hWnd = WindowID(0)
EditorGadget(0, 8, 8, 306, 133)
ButtonGadget(1, 10, 145, 80, 30, "ok")
StringGadget(2, 100, 145, 200, 30, "try to change kbd layout here")
StringGadget(3, 0, 0, 0, 0, "") ; phantom gadget. Don't use -1 !
; otherwise the system icon for changing keyboard layout will disappear from the tray when you click on it
For a = 0 To 5
AddGadgetItem(0, a, "Line "+Str(a))
Next
;hKL = LoadKeyboardLayout_("00000401",#KLF_REORDER) ;For Arabic
hKL = LoadKeyboardLayout_("00000409",#KLF_REORDER) ;For English
If hKL
ActivateKeyboardLayout_(hKL,#KLF_REORDER)
Else
MessageRequester("INFO","The required Language not found",#MB_OK|#MB_ICONINFORMATION)
EndIf
SetActiveGadget(0)
old = SetWindowLongPtr_(GadgetID(0), #GWLP_WNDPROC, @WndProc())
Repeat
Select WaitWindowEvent(1)
Case #APP_Event_KBDLayoutChanged
force_change_to_En
Case #PB_Event_CloseWindow
Quit = 1
Case #PB_Event_Gadget
If EventGadget() = 0
If EventType() = #PB_EventType_LostFocus
Debug "Lost Focus"
ElseIf EventType() = #PB_EventType_Focus
Debug "Got Focus"
force_change_to_En
EndIf
EndIf
EndSelect
Until Quit = 1
EndIf
Code: Select all
Interface ITfInputProcessorProfiles Extends IUnknown
Register.l(*rclsid.CLSID)
Unregister.l(*rclsid.CLSID)
AddLanguageProfile.l(*rclsid.CLSID, langid,w, *guidProfile.GUID, *pchDesc, cchDesc.l, *pchIconFile, cchFile.l, uIconIndex.l)
RemoveLanguageProfile.l(*rclsid.CLSID, langid.w, *guidProfile.GUID)
EnumInputProcessorInfo.l(*ppEnum)
GetDefaultLanguageProfile.l(langid.w, *catid.GUID, *pclsid.CLSID, *pguidProfile.GUID)
SetDefaultLanguageProfile.l(langid.w, *rclsid.CLSID, *guidProfiles.GUID)
ActivateLanguageProfile.l(*rclsid.CLSID, langid.w, *guidProfiles.GUID)
GetActiveLanguageProfile.l(*rclsid.CLSID, *plangid.LANGID, *pguidProfile.GUID)
GetLanguageProfileDescription.l(*rclsid.CLSID, langid.w, *guidProfile.GUID, *pbstrProfile)
GetCurrentLanguage.l(*plangid.LANGID)
ChangeCurrentLanguage.l(langid.w)
GetLanguageList.l(*ppLangId, *pulCount)
EnumLanguageProfiles.l(langid.w, *ppEnum)
EnableLanguageProfile.l(*rclsid.CLSID, langid.w, *guidProfile.GUID, fEnable.l)
IsEnabledLanguageProfile.l(*rclsid.CLSID, langid.w, *guidProfile.GUID, *pfEnable)
EnableLanguageProfileByDefault.l(*rclsid.CLSID, langid.w, *guidProfile.GUID, fEnable.l)
SubstituteKeyboardLayout.l(*rclsid.CLSID, langid.w, *guidProfile.GUID, hKL)
EndInterface
Interface ITfSource Extends IUnknown
AdviseSink.l(*riid.IID, *punk, *pdwCookie)
UnadviseSink.l(dwCookie.l)
EndInterface
Interface ITfLanguageProfileNotifySink Extends IUnknown
OnLanguageChange.l(langid.w, *pfAccept)
OnLanguageChanged.l()
EndInterface
DataSection
IID_IUnknown:
Data.l $00000000
Data.w $0000, $0000
Data.b $C0, $00, $00, $00, $00, $00, $00, $46
CLSID_TF_InputProcessorProfiles: ; 33c53a50-f456-4884-b049-85fd643ecfed
Data.l $33c53a50
Data.w $f456, $4884
Data.b $b0, $49, $85, $fd, $64, $3e, $cf, $ed
; DEFINE_GUID(IID_ITfInputProcessorProfiles, 0x1f02b6c5, 0x7842, 0x4ee6, 0x8a,0x0b, 0x9a,0x24,0x18,0x3a,0x95,0xca)
IID_ITfInputProcessorProfiles:
Data.l $1f02b6c5
Data.w $7842, $4ee6
Data.b $8a, $0b, $9a, $24, $18, $3a, $95, $ca
; DEFINE_GUID(IID_ITfSource, 0x4ea48a35, 0x60ae, 0x446f, 0x8f,0xd6, 0xe6,0xa8,0xd8,0x24,0x59,0xf7)
IID_ITfSource:
Data.l $4ea48a35
Data.w $60ae, $446f
Data.b $8f, $d6, $e6, $a8, $d8, $24, $59, $f7
; DEFINE_GUID(IID_ITfLanguageProfileNotifySink, 0x43c9fe15, 0xf494, 0x4c17, 0x9d,0xe2, 0xb8,0xa4,0xac,0x35,0x0a,0xa8)
IID_ITfLanguageProfileNotifySink:
Data.l $43c9fe15
Data.w $f494, $4c17
Data.b $9d, $e2, $b8, $a4, $ac, $35, $0a, $a8
EndDataSection
Enumeration #PB_Event_FirstCustomValue
#APP_Event_KBDLayoutChanged
EndEnumeration
Structure tagITfLanguageProfileNotifySink
*pVtbl
*pQueryInterface
*pAddRef
*pRelease
*pOnLanguageChange
*pOnLanguageChanged
lRefCount.l
Cookie.l
layout.i
EndStructure
Procedure.l ITfLanguageProfileNotifySink_QueryInterface(*this.tagITfLanguageProfileNotifySink, *riid.IID, *ppvObject.Integer)
If *ppvObject And *riid
If CompareMemory(*riid, ?IID_IUnknown, SizeOf(IID)) Or CompareMemory(*riid, ?IID_ITfLanguageProfileNotifySink, SizeOf(IID))
*this\lRefCount + 1
*ppvObject\i = *this
Else
*ppvObject\i = 0
ProcedureReturn #E_NOINTERFACE
EndIf
Else
ProcedureReturn #E_POINTER
EndIf
ProcedureReturn #S_OK
EndProcedure
Procedure.l ITfLanguageProfileNotifySink_AddRef(*this.tagITfLanguageProfileNotifySink)
*this\lRefCount + 1
;Debug #PB_Compiler_Procedure + " " + *this\lRefCount
ProcedureReturn *this\lRefCount
EndProcedure
Procedure.l ITfLanguageProfileNotifySink_Release(*this.tagITfLanguageProfileNotifySink)
*this\lRefCount - 1
;Debug #PB_Compiler_Procedure + " " + *this\lRefCount
If *this\lRefCount <= 0
Debug "FreeMemory"
FreeMemory(*this)
ProcedureReturn 0
EndIf
ProcedureReturn *this\lRefCount
EndProcedure
Procedure.l ITfLanguageProfileNotifySink_OnLanguageChange(*this.tagITfLanguageProfileNotifySink, langid.w, *pfAccept.Long)
;Debug #PB_Compiler_Procedure + " " + Hex(langid)
ProcedureReturn #S_OK
EndProcedure
Procedure.l ITfLanguageProfileNotifySink_OnLanguageChanged(*this.tagITfLanguageProfileNotifySink)
;Debug #PB_Compiler_Procedure
If GetKeyboardLayout_(0) <> *this\layout And GetActiveGadget() = 0
Debug #PB_Compiler_Procedure + " - PostEvent"
PostEvent(#APP_Event_KBDLayoutChanged)
EndIf
ProcedureReturn #S_OK
EndProcedure
Procedure SetKBDLayoutChangeEvent(*TfLanguageProfileNotifySink.tagITfLanguageProfileNotifySink)
Protected Result
Protected Profiles.ITfInputProcessorProfiles, TfSource.ITfSource
; https://learn.microsoft.com/en-us/windows/win32/api/msctf/nn-msctf-itfinputprocessorprofiles
; https://learn.microsoft.com/en-us/windows/win32/api/msctf/nn-msctf-itflanguageprofilenotifysink
; https://learn.microsoft.com/en-us/windows/win32/api/msctf/nn-msctf-itfsource
If CoCreateInstance_(?CLSID_TF_InputProcessorProfiles, 0, #CLSCTX_INPROC_SERVER, ?IID_ITfInputProcessorProfiles, @Profiles) = #S_OK
If Profiles
If Profiles\QueryInterface(?IID_ITfSource, @TfSource) = #S_OK
If TfSource
If TfSource\AdviseSink(?IID_ITfLanguageProfileNotifySink, *TfLanguageProfileNotifySink, @*TfLanguageProfileNotifySink\Cookie) = #S_OK
Debug "Sink OK"
Result = TfSource
EndIf
EndIf
EndIf
Profiles\Release()
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Procedure MakeLong(low, high)
ProcedureReturn low | (high<<16)
EndProcedure
Macro force_change_to_En
If GetKeyboardLayout_(0) <> En_layout ; En
ActivateKeyboardLayout_(hKL, #KLF_REORDER)
EndIf
EndMacro
Define TfSource.ITfSource
Define *TfLanguageProfileNotifySink.tagITfLanguageProfileNotifySink
Define hKL, En_layout, PrevLayout
hKL = LoadKeyboardLayout_("00000409",#KLF_REORDER) ;For English
;hKL = LoadKeyboardLayout_("00000401",#KLF_REORDER) ;For Arabic
If hKL
*TfLanguageProfileNotifySink = AllocateMemory(SizeOf(tagITfLanguageProfileNotifySink))
If *TfLanguageProfileNotifySink
With *TfLanguageProfileNotifySink
\pVtbl = *TfLanguageProfileNotifySink + OffsetOf(tagITfLanguageProfileNotifySink\pQueryInterface)
\pQueryInterface = @ITfLanguageProfileNotifySink_QueryInterface()
\pAddRef = @ITfLanguageProfileNotifySink_AddRef()
\pRelease = @ITfLanguageProfileNotifySink_Release()
\pOnLanguageChange = @ITfLanguageProfileNotifySink_OnLanguageChange()
\pOnLanguageChanged= @ITfLanguageProfileNotifySink_OnLanguageChanged()
\layout = MakeLong(1033, 1033) ; En
En_layout = \layout
EndWith
TfSource = SetKBDLayoutChangeEvent(*TfLanguageProfileNotifySink)
If TfSource
Debug "SetKBDLayoutChangeEvent OK : " + *TfLanguageProfileNotifySink\Cookie
Else
Debug "SetKBDLayoutChangeEvent Failed."
FreeMemory(*TfLanguageProfileNotifySink)
EndIf
EndIf
Else
MessageRequester("INFO","The required Language not found",#MB_OK|#MB_ICONINFORMATION)
EndIf
If OpenWindow(0, 0, 0, 322, 250, "EditorGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
EditorGadget(0, 8, 8, 306, 133)
ButtonGadget(1, 10, 145, 80, 30, "ok")
StringGadget(2, 100, 145, 200, 30, "try to change kbd layout here")
StringGadget(3, 0, 0, 0, 0, "") ; phantom gadget. Don't use -1 !
; otherwise the system icon for changing keyboard layout will disappear from the tray when you click on it
For a = 0 To 5
AddGadgetItem(0, a, "Line "+Str(a))
Next
SetActiveGadget(0)
PrevLayout = GetKeyboardLayout_(0)
force_change_to_En
Repeat
Select WaitWindowEvent(1)
Case #APP_Event_KBDLayoutChanged
ActivateKeyboardLayout_(hKL, #KLF_REORDER)
Debug "Changed to English"
Case #PB_Event_CloseWindow
Quit = 1
Case #PB_Event_Gadget
If EventGadget() = 0
If EventType() = #PB_EventType_LostFocus
Debug "Lost Focus"
ActivateKeyboardLayout_(PrevLayout, #KLF_REORDER)
ElseIf EventType() = #PB_EventType_Focus
Debug "Got Focus"
PrevLayout = GetKeyboardLayout_(0)
force_change_to_En
EndIf
EndIf
EndSelect
Until Quit = 1
EndIf
If TfSource
If TfSource\UnadviseSink(*TfLanguageProfileNotifySink\Cookie) = #S_OK
Debug "UnadviseSink OK"
EndIf
TfSource\Release()
EndIf