[handy Tool for gamers] Auto-disable Caps Lock

Applications, Games, Tools, User libs and useful stuff coded in PureBasic
PureLust
Enthusiast
Enthusiast
Posts: 477
Joined: Mon Apr 16, 2007 3:57 am
Location: Germany, NRW

[handy Tool for gamers] Auto-disable Caps Lock

Post by PureLust »

I love playing online-games with friends. But during the "battle" it happens that I accidentally activate the caps lock key.
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. :mrgreen:

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
[Edit] AutoStart-Routine changed.
Last edited by PureLust on Sat Jan 22, 2022 3:42 am, edited 6 times in total.
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
User avatar
HeX0R
Addict
Addict
Posts: 979
Joined: Mon Sep 20, 2004 7:12 am
Location: Hell

Re: [handy Tool for gamers] Auto-disable Caps Lock

Post by HeX0R »

Is there a reason you've used the quote tags instead of the code tags?
PureLust
Enthusiast
Enthusiast
Posts: 477
Joined: Mon Apr 16, 2007 3:57 am
Location: Germany, NRW

Re: [handy Tool for gamers] Auto-disable Caps Lock

Post by PureLust »

HeX0R wrote: Fri Jan 21, 2022 4:59 pm Is there a reason you've used the quote tags instead of the code tags?
Yes ... stupidity !!! :wink:

(changed to code tags)
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
User avatar
Bisonte
Addict
Addict
Posts: 1226
Joined: Tue Oct 09, 2007 2:15 am

Re: [handy Tool for gamers] Auto-disable Caps Lock

Post by Bisonte »

Very nice thing, small and effective ;)
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
English is not my native language... (I often use DeepL to translate my texts.)
PureLust
Enthusiast
Enthusiast
Posts: 477
Joined: Mon Apr 16, 2007 3:57 am
Location: Germany, NRW

Re: [handy Tool for gamers] Auto-disable Caps Lock

Post by PureLust »

Bisonte wrote: Sat Jan 22, 2022 10:47 am Very nice thing, small and effective ;)
You are welcome. :wink:

Just came back from another nice gaming-session with friend ... and yesss ... it's soooo nice and effective. :mrgreen:
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
Post Reply