When I then type in the chat, it often happens that I write with Caps Lock on, which is very annoying.
To solve this problem I wrote this little tool that will automatically disable caps lock if it has been turned on and also it has some nice additional features.
Features:
- quiet startup as Systray-Icon
- small footprint and very low CPU usage
- Option to always turn off Caps Lock as soon as it was turned on
- Disable caps lock only when certain programs are running (when certain window titles were found)
- You can specify up to 10 different programs (window titles) to search for
- Caps lock disabling will be activated when one of the specified window titles is found and will be automatically disabled after the window is closed
- supports autostart at system startup
After using it for a couple of days, I'm really hooked and never want to game without it again.
Maybe it will be useful for some gamers among you as well.
Code: Select all
; ---- Diasable Caps-Lock - automatically disables Capslock once pressed.
; Helpful, for example, to automatically deactivate Caps Lock if you accidentally pressed it while playing.
; - deaktiviert Capslock automatisch, sobald es gedückt wurde.
; Hilfreich um zum Beispiel beim Spielen das versehentlich gedrückte CapsLock automatisch wieder zu deaktivieren.
EnableExplicit
Structure my_WinParam
Title.s
hWnd.i
MatchMode.l
FindHiddenWindows.l
EndStructure
Structure WinRunning
WinTitle.s
running.l
EndStructure
;> ----- read Config-File -----
Define ConfigFile.s = GetUserDirectory(#PB_Directory_ProgramData)+"DisableCapsLock.pref"
OpenPreferences(ConfigFile)
Define AlwaysDisable = ReadPreferenceLong("AlwaysDisable",#False)
Define AutoDisable = ReadPreferenceLong("AutoDisable",#True)
Dim WinTitle.WinRunning(10)
Define n
WinTitle(0)\WinTitle = ReadPreferenceString("WinTitle_0","Battle.net")
WinTitle(1)\WinTitle = ReadPreferenceString("WinTitle_1","Overwatch")
For n = 2 To 9
WinTitle(n)\WinTitle = ReadPreferenceString("WinTitle_"+Str(n),"")
Next
Define AutoStart = ReadPreferenceLong("AutoStart_with_Windows", #False)
ClosePreferences()
;<
#MatchCode_AnythingLeftOK = 1
#MatchCode_AnythingRightOK = 2
#MatchCode_AnySubString = #MatchCode_AnythingLeftOK | #MatchCode_AnythingRightOK
Declare my_EnumWindowsProc(hWnd, lParam)
Declare FindWindow(Title.s, FindHiddenWindows=#False)
Declare PrepPopUpMenu()
Declare SetAutostart(State.b)
SetAutostart(AutoStart) ; Set Autostart-state, read from Pref-File
#Img = 0
#WinMain = 0
#Timer_DisableCapsLock = 0
#Timer_CheckForWindow = 1
#SysTray = 0
#PopUp = 0
#WinWidth = 400
#WinHeight = 400
#Prefix = " - "
Define Quit = #False
Define DummyParam.my_WinParam
Global *param.my_WinParam = @DummyParam
Define DisableActive = #False
Define IconBase64.s, Base64Data.s
;> ---- Read Systray-Icon from Base64 Data
Restore Base64Icon
While Right(Base64Data,2) <> "=="
Read.s Base64Data
IconBase64 + Base64Data
Wend
Define *IconMemory = AllocateMemory(Len(IconBase64))
Base64Decoder(IconBase64, *IconMemory, Len(IconBase64))
If Not CatchImage(#Img,*IconMemory) : End : EndIf
FreeMemory(*IconMemory)
;<
OpenWindow(#WinMain,0,0,#WinWidth,#WinHeight,"Auto-Disable Caps Lock",#PB_Window_ScreenCentered | #PB_Window_NoActivate | #PB_Window_Invisible)
TextGadget(#PB_Any,20,10, #WinWidth-40, 80,"Please enter up to 10 window titles of programs for which you want to automatically disable Caps Lock when those programs are running."+#CR$+#CR$+"You can use '*' before and/or after to define substrings.", #PB_Text_Center)
For n = 0 To 9
StringGadget(10+n,20,100+n*22,#WinWidth-47,17,WinTitle(n)\WinTitle,#PB_String_BorderLess)
SetGadgetColor(10+n,#PB_Gadget_BackColor,$cccccc)
Next
ButtonGadget(98,50,GadgetY(19)+30,120,25,"Cancle")
ButtonGadget(99,#WinWidth-175,GadgetY(19)+30,120,25,"OK")
PrepPopUpMenu()
AddSysTrayIcon(#SysTray,WindowID(#WinMain),ImageID(#Img))
SysTrayIconToolTip(#SysTray,"Auto-Disable Caps Lock")
Repeat
Define Event = WaitWindowEvent(100)
Select Event
Case #PB_Event_SysTray
If EventType() = #PB_EventType_LeftClick Or EventType() = #PB_EventType_RightClick ; if right- or left-click on systray-icon, open PopUp Menu
DisplayPopupMenu(#PopUp, WindowID(#WinMain)) ; show Popup-Menu
EndIf
Case #PB_Event_Menu
Select EventMenu()
Case 1 ; Always auto-disable Caps Lock
SetMenuItemState(#PopUp, 1, Bool(GetMenuItemState(#PopUp,1) = #False)) ; Change MenuItem State on>off | off>on and write new state to Config-File
AlwaysDisable = GetMenuItemState(#PopUp,1)
OpenPreferences(ConfigFile)
WritePreferenceLong("AlwaysDisable",AlwaysDisable)
ClosePreferences()
PrepPopUpMenu()
Case 2 ; Auto-disable Caps Lock if running:
SetMenuItemState(#PopUp, 2, Bool(GetMenuItemState(#PopUp,2) = #False)) ; Change MenuItem State on>off | off>on and write new state to Config-File
AutoDisable = GetMenuItemState(#PopUp,2)
OpenPreferences(ConfigFile)
WritePreferenceLong("AutoDisable",AutoDisable)
ClosePreferences()
PrepPopUpMenu()
Case 90 ; Edit List
For n = 0 To 9
SetGadgetText(10+n,WinTitle(n)\WinTitle)
Next
HideWindow(#WinMain, #False)
Case 95 ; enable/disabe Autostart on Windows Startup
SetMenuItemState(#PopUp, 95, Bool(GetMenuItemState(#PopUp,95) = #False)) ; Change MenuItem State on>off | off>on and write new state to Config-File
AutoStart = GetMenuItemState(#PopUp,95)
OpenPreferences(ConfigFile)
WritePreferenceLong("AutoStart_with_Windows", AutoStart)
ClosePreferences()
SetAutostart(AutoStart)
Case 99 ; Quit
Quit = #True
EndSelect
Case #PB_Event_Timer ; Timer Event for disableing Caps Lock or checking for running Programs
If EventTimer() = #Timer_DisableCapsLock ; disable Caps Lock if active
If GetKeyState_(#VK_CAPITAL) & 1 ; if Caps Lock is active, deactivate it ...
keybd_event_(#VK_CAPITAL,0,#KEYEVENTF_EXTENDEDKEY|0,0)
keybd_event_(#VK_CAPITAL,0,#KEYEVENTF_EXTENDEDKEY|#KEYEVENTF_KEYUP,0)
EndIf
ElseIf EventTimer() = #Timer_CheckForWindow ; check for running Programs (or existing windows)
Define ActDisableState = DisableActive
DisableActive = #False
For n = 0 To 9
If Len(WinTitle(n)\WinTitle) > 0
*param = FindWindow(WinTitle(n)\WinTitle)
If Bool(*param\hWnd) <> Bool(WinTitle(n)\running)
WinTitle(n)\running = Bool(*param\hWnd)
SetMenuItemText(#PopUp, 10+n, #Prefix+WinTitle(n)\WinTitle + Left(" (running)",WinTitle(n)\running * 20))
EndIf
DisableActive | WinTitle(n)\running
EndIf
Next
If ActDisableState <> DisableActive
If AlwaysDisable Or DisableActive
AddWindowTimer(#WinMain, #Timer_DisableCapsLock, 100)
Else
RemoveWindowTimer(#WinMain, #Timer_DisableCapsLock)
EndIf
EndIf
EndIf
Case #PB_Event_Gadget
Select EventGadget()
Case 98 ; Cancle - do nothing
HideWindow(#WinMain, #True)
Case 99 ; OK
OpenPreferences(ConfigFile) ; Filter empty entries and write Title-List to configfile, then recreate Systray-PopUp
For n = 0 To 9
Define ActTitle.s = GetGadgetText(10+n)
If Len(Trim(ActTitle)) = 0 : ActTitle = "" : EndIf
WritePreferenceString("WinTitle_"+Str(n),ActTitle)
WinTitle(n)\WinTitle = ActTitle
WinTitle(n)\running = #False
Next
ClosePreferences()
HideWindow(#WinMain, #True)
PrepPopUpMenu()
EndSelect
EndSelect
Until Event = #PB_Event_CloseWindow Or Quit
End
Procedure my_EnumWindowsProc(hWnd, lParam) ; EnumWindows_() Callback
Protected *param.my_WinParam = lParam
Protected Title.s{260}
If Not *param\FindHiddenWindows ; If invisible Windows are not wanted, check for visibility and quit it invisible
If Not IsWindowVisible_(hwnd)
*param\hWnd = #False
ProcedureReturn #True
EndIf
EndIf
GetWindowText_(hWnd, @Title, 260)
If Title
*param\hWnd = hWnd
Select *param\MatchMode
Case #MatchCode_AnySubString
If FindString(Title, *param\Title, 1, #PB_String_NoCase)
ProcedureReturn #False
EndIf
Case #MatchCode_AnythingRightOK
If UCase(Left(Title, Len(*param\Title))) = UCase(*param\Title)
ProcedureReturn #False
EndIf
Case #MatchCode_AnythingLeftOK
If UCase(Right(Title, Len(*param\Title))) = UCase(*param\Title)
ProcedureReturn #False
EndIf
Default
If UCase(Title) = UCase(*param\Title)
ProcedureReturn #False
EndIf
EndSelect
EndIf
*param\hWnd = #False
ProcedureReturn #True
EndProcedure
Procedure FindWindow(Title.s, FindHiddenWindows=#False) ; Proc to search for Windows by name
Static param.my_WinParam
ClearStructure(@param, my_WinParam)
If Left(Title,1) = "*" : Title = Mid(Title, 2) : param\MatchMode | #MatchCode_AnythingLeftOK : EndIf
If Right(Title,1) = "*" : Title = Left(Title, Len(Title)-1) : param\MatchMode | #MatchCode_AnythingRightOK : EndIf
param\Title = Title
param\FindHiddenWindows = FindHiddenWindows
EnumWindows_(@my_EnumWindowsProc(), @param)
ProcedureReturn @param
EndProcedure
Procedure PrepPopUpMenu() ; create or update SystrayIcon PopUp Window
Protected n
Shared WinTitle(), AlwaysDisable, AutoDisable, DisableActive, AutoStart
If IsMenu(#PopUp) : FreeMenu(#PopUp) : EndIf
If CreatePopupMenu(#PopUp) ; hier beginnt das Erstellen des Popup-Menüs...
MenuItem(1, "Always auto-disable Caps Lock") ; Sie können alle Befehle zum Erstellen eines Menüs
MenuBar()
MenuItem(2, "Auto-disable Caps Lock if running:") ; verwenden, ganz wie bei einem normalen Menü...
For n = 0 To 9
If Len(WinTitle(n)\WinTitle) > 0 : MenuItem(10+n, #Prefix+WinTitle(n)\WinTitle) : DisableMenuItem(#PopUp, 10+n, #True) : EndIf
WinTitle(n)\running = #False
Next
MenuItem(90, "Edit List")
MenuBar()
MenuItem(95, "Autostart at system startup")
MenuBar()
MenuItem(99, "Quit")
SetMenuItemState(#PopUp, 1, AlwaysDisable)
SetMenuItemState(#PopUp, 2, AutoDisable)
SetMenuItemState(#PopUp, 95, AutoStart)
DisableMenuItem(#PopUp,10,#True)
DisableActive = #False
RemoveWindowTimer(#WinMain, #Timer_DisableCapsLock)
RemoveWindowTimer(#WinMain, #Timer_CheckForWindow)
If AlwaysDisable : AddWindowTimer(#WinMain, #Timer_DisableCapsLock, 100) : EndIf
If AutoDisable : AddWindowTimer(#WinMain, #Timer_CheckForWindow , 5000) : EndIf
EndIf
EndProcedure
Procedure SetAutostart(AutoStart.b) ; creates or deletes the registry-entry for autorun when windows starts
Protected Result, hKey, KeyState, lpType, lpData.s = Space(#MAX_PATH), char.c, lpcData = #MAX_PATH * SizeOf(char)
#RegAutostartPath = "Software\Microsoft\Windows\CurrentVersion\Run"
#RegAutoStartProgName = "Auto-Disable_CapsLock"
If AutoStart
RegCreateKeyEx_ (#HKEY_CURRENT_USER, #RegAutostartPath, 0, 0, #REG_OPTION_NON_VOLATILE, #KEY_ALL_ACCESS | #KEY_WOW64_64KEY, 0, @hKey, @KeyState)
RegSetValueEx_ (hKey, #RegAutoStartProgName, 0, #REG_SZ, Chr(34)+ProgramFilename()+Chr(34)+Chr(0), (Len(ProgramFilename())+3) * SizeOf(char))
Else
RegOpenKeyEx_ (#HKEY_CURRENT_USER, #RegAutostartPath, 0, #KEY_ALL_ACCESS | #KEY_WOW64_64KEY, @hKey)
RegDeleteValue_ (hKey, #RegAutoStartProgName)
EndIf
RegCloseKey_(hKey)
EndProcedure
DataSection
Base64Icon:
Data.s "AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAB"
Data.s "AAAAAQAAAAAAAAAAAAAAAAAAAC8AAACYAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAJgAAAAvAAAAAAAAAAAAAACXAAAA5AAAAKkAAACoAAAAqAAAAKkAAACpAAAAqQAA"
Data.s "AKkAAACoAAAAqAAAAKkAAADkAAAAlwAAAAAAAAABAAAAqAAAAKkAAAACAAAAFgAAABQAAAABAAAAAQAAAAEAAAABAAAAFAAAABYAAAACAAAAqQAAAKgAAAABAAAAAQAAAKgAAACpAAAAAAAAAHAAAACo"
Data.s "AAAACgAAAAAAAAAAAAAACgAAAKgAAABwAAAAAAAAAKkAAACoAAAAAQAAAAEAAACoAAAAqQAAAAAAAAA3AAAA2wAAAG4AAABSAAAAUgAAAG4AAADbAAAANwAAAAAAAACpAAAAqAAAAAEAAAABAAAAqAAA"
Data.s "AKkAAAABAAAABwAAALEAAADvAAAAxwAAAMcAAADvAAAAsQAAAAcAAAABAAAAqQAAAKgAAAABAAAAAQAAAKgAAACpAAAAAQAAAAAAAABgAAAAzQAAACEAAAAhAAAAzgAAAGAAAAAAAAAAAQAAAKkAAACo"
Data.s "AAAAAQAAAAEAAACoAAAAqQAAAAEAAAAAAAAAHAAAAM0AAABLAAAATAAAAM0AAAAcAAAAAAAAAAEAAACpAAAAqAAAAAEAAAABAAAAqAAAAKkAAAABAAAAAAAAAAAAAACPAAAAoQAAAKIAAACPAAAAAAAA"
Data.s "AAAAAAABAAAAqQAAAKgAAAABAAAAAQAAAKgAAACpAAAAAQAAAAAAAAAAAAAAPAAAAOEAAADhAAAAPAAAAAAAAAAAAAAAAQAAAKkAAACoAAAAAQAAAAEAAACoAAAAqQAAAAEAAAAAAAAAAAAAAAsAAACr"
Data.s "AAAAqwAAAAsAAAAAAAAAAAAAAAEAAACpAAAAqAAAAAEAAAABAAAAqAAAAKkAAAACAAAAAQAAAAEAAAABAAAAFAAAABQAAAABAAAAAQAAAAEAAAACAAAAqQAAAKgAAAABAAAAAAAAAJcAAADkAAAAqQAA"
Data.s "AKkAAACpAAAAqQAAAKgAAACoAAAAqQAAAKkAAACpAAAAqQAAAOQAAACXAAAAAAAAAAAAAAAvAAAAmAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACYAAAALwAAAAAAAAAA"
Data.s "AAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAwAMAAIABAACAAQAAAAAAABGIAAAQCAAAAAAAAAgQAAAIEAAADDAAAAwwAAAMMAAAAAAAAIAB"
Data.s "AACAAQAAwAMAAA=="
EndDataSection