Lock Key Status

Example scripts and tips (replaces Old Scripts & Tips archive)

Moderators: Dorian (MJT support), JRL, Phil Pendlebury

Post Reply
User avatar
JRL
Automation Wizard
Posts: 3525
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Lock Key Status

Post by JRL » Fri Feb 26, 2021 10:20 pm

Yes. Sort of a pun.

In any case my keyboard's LEDs have stopped working and I'm tired of not knowing whether my caps lock in on or off. This opens a little dialog that tells you. Left to right is Caps lock, Num Lock and Scroll Lock status.

This little script demos a few advanced dialog capabilities. For example:

It shows how to make your Dialog stay on top of other windows. You need two things for this to happen. Your dialog needs to have its FormStyle parameter set to "fsStayOnTop". Additionally the dialog position needs to be set on a frequent basis so there is a loop that captures the dialog's position then "moves" the dialog to its current location 100 times per second. This causes the dialog to stay at the top level of the desktop windows.

It shows a method to move a dialog around the screen with the mouse even though there is no titlebar to grab to move the dialog. Select anywhere on the dialog and move it around the desktop.

It shows a use for SetControlText> as mentioned in THIS forum post. In this case if a second instance of the script is run, it passes the initial coordinates of the dialog back to the first instance of the script. The first instance of the script then moves its dialog to those coordinates and the second instance quits. This is useful for not having multiple instances running. Also, if a second instance was started it usually means the first instance's dialog is off screen somewhere and therefore not visible. Passing the initial coordinates and having the dialog move there makes it visible and available again.

ALT + Q will close the program.

Code: Select all

//Initial position for the Lock Key display dialog.
//Values could be stored in a config file.
Let>DiaXPos=0
Let>DiaYPos=0
//////////////////////////////////////////////////


//Allows only one instance of the app.
//Also puts the dialog in its initial position
IfWindowOpen>Display Lock Key States
  SetControlText>Display Lock Key States,TEdit,2,DiaXPos
  SetControlText>Display Lock Key States,TEdit,1,DiaYPos
  Exit>0
EndIF
//////////////////////////////////////////////


//Key down events to detect lock key pressed 
OnEvent>Key_Down,VK20,0,DetectCapState
OnEvent>Key_Down,VK144,0,DetectNumState
OnEvent>Key_Down,VK145,0,DetectScrState
////////////////////////////////////////////

//Alt + Q event to quit the app
OnEvent>Key_Down,VK81,3,Quit
///////////////////////////////


SRT>Quit
  Exit>0
END>Quit

Let>lOCKTimeFlag=0
Let>MoveDialogFlag=0
Let>VK_CAPITAL=20
Let>VK_NUMLOCK=144
Let>VK_SCROLL=145

Dialog>Dialog1
object Dialog1: TForm
  BorderStyle = bsNone
  Caption = 'Display Lock Key States'
  ClientHeight = 20
  ClientWidth = 80
  Color = 16777200
  Formstyle = fsStayOnTop
  object Panel1: TPanel
    Left = 5
    Top = 5
    Width = 10
    Height = 10
    Caption = ''
    ParentBackground = False
  end
  object Panel2: TPanel
    Left = 35
    Top = 5
    Width = 10
    Height = 10
    Caption = ''
    ParentBackground = False
  end
  object Panel3: TPanel
    Left = 65
    Top = 5
    Width = 10
    Height = 10
    Caption = ''
    ParentBackground = False
  end
  object Edit1: TEdit
    Visible = False
  end
  object Edit2: TEdit
    Visible = False
  end
end
EndDialog>Dialog1


//Dialog handlers that allow the mouse to move the dialog
AddDialogHandler>Dialog1,,OnMouseDown,srtMoveDialog
AddDialogHandler>Dialog1,,OnMouseUp,srtNoMoveDialog
AddDialogHandler>Dialog1,Panel1,OnMouseDown,srtMoveDialog
AddDialogHandler>Dialog1,Panel1,OnMouseUp,srtNoMoveDialog
AddDialogHandler>Dialog1,Panel2,OnMouseDown,srtMoveDialog
AddDialogHandler>Dialog1,Panel2,OnMouseUp,srtNoMoveDialog
AddDialogHandler>Dialog1,Panel3,OnMouseDown,srtMoveDialog
AddDialogHandler>Dialog1,Panel3,OnMouseUp,srtNoMoveDialog
/////////////////////////////////////////////////////////


//Initial Dialog position saved to Dialog Labels for SetControlText> use.
SetDialogProperty>Dialog1,Edit1,Text,DiaXPos
SetDialogProperty>Dialog1,Edit2,Text,DiaYPos
/////////////////////////////////////////////////////////////


Show>Dialog1


Wait>0.1
GoSub>DetectCapState
Wait>0.1
GoSub>DetectNumState
Wait>0.1
GoSub>DetectScrState

//Loop and subs to allow mouse to move the dialog
//and to keep the dialog on top of other windows.
Label>StayOnTopLoop
  Wait>0.01
  //Constantly moving the dialog to its current position
  //in conjuction with setting the dialog's form style to 
  //"fsStayOnTop" Keeps it on top of other windows.
  GetDialogProperty>Dialog1,Edit1,Text,DiaXPos
  GetDialogProperty>Dialog1,Edit2,Text,DiaYPos
  Let>WIN_USEHANDLE=1
    MoveWindow>Dialog1.handle,DiaXPos,DiaYPos
  Let>WIN_USEHANDLE=0
  ///////////////////////////////////////////////////////
  
  
  //When flag var is set to one the dialog will
  //follow the mouse.
  If>MoveDialogFlag=1
    GetCursorPos>CurX,CurY
    Let>DiaXPos=%CurX%-%XDiff%
    Let>DiaYPos=%CurY%-%YDiff%
    SetDialogProperty>Dialog1,Edit1,Text,DiaXPos
    SetDialogProperty>Dialog1,Edit2,Text,DiaYPos
  EndIf
  /////////////////////////////////////////////
Goto>StayOnTopLoop

SRT>srtMoveDialog
  If>MoveDialogFlag=0
    Let>WIN_USEHANDLE=1
      GetWindowPos>Dialog1.handle,DiaXPos,DiaYPos
    Let>WIN_USEHANDLE=0
    GetCursorPos>CurX,CurY
    Let>XDiff=%CurX%-%DiaXPos%
    Let>YDiff=%CurY%-%DiaYPos%
  EndIF
  Let>MoveDialogFlag=1
END>srtMoveDialog

SRT>srtNoMoveDialog
  Let>MoveDialogFlag=0
END>srtNoMoveDialog
/////////////////////////////////////////////////


SRT>DetectCapState
  Timer>LockTimeNow
  Let>LockTimeDiff=%LockTimeNow%-%LockTimeFlag%
  If>{%LockTimeDiff%>50}
    LibFunc>User32,GetKeyState,CAP_STATE,VK_CAPITAL
    If>{(%Cap_state%=65409)or(%Cap_state%=1)}
      SetDialogObjectColor>Dialog1,Panel1,111111
    Else
      SetDialogObjectColor>Dialog1,Panel1,16777200
    EndIf
  EndIf
  Let>LockTimeFlag=LockTimeNow
END>DetectCapState

SRT>DetectNumState
  Timer>LockTimeNow
  Let>LockTimeDiff=%LockTimeNow%-%LockTimeFlag%
  If>{%LockTimeDiff%>50}
    LibFunc>User32,GetKeyState,NUM_STATE,VK_NUMLOCK
    If>{(%Num_state%=65409)or(%Num_state%=1)}
      SetDialogObjectColor>Dialog1,Panel2,111111
    Else
      SetDialogObjectColor>Dialog1,Panel2,16777200
    EndIf
  EndIf
  Let>LockTimeFlag=LockTimeNow
END>DetectNumState

SRT>DetectScrState
  Timer>LockTimeNow
  Let>LockTimeDiff=%LockTimeNow%-%LockTimeFlag%
  If>{%LockTimeDiff%>50}
    LibFunc>User32,GetKeyState,SCR_STATE,VK_SCROLL
    If>{(%Scr_state%=65409)or(%Scr_state%=1)}
      SetDialogObjectColor>Dialog1,Panel3,111111
    Else
      SetDialogObjectColor>Dialog1,Panel3,16777200
    EndIf
  EndIf
  Let>LockTimeFlag=LockTimeNow
END>DetectScrState
Edit1 - 01/06/2022

It seemed reasonable to expect that clicking on the boxes would actually set the key state so the following will do that. Also changed the boxes to representative characters because over time I forgot which was which.
So now C = Caps Lock, N = Num Lock and S = Scroll Lock.

Code: Select all

//Initial position for the Lock Key display dialog.
//Values could be stored in a config file.
Let>DiaXPos=920
Let>DiaYPos=1015
//////////////////////////////////////////////////

//Allows only one instance of the app.
//Also puts the dialog in its initial position
IfWindowOpen>Display Lock Key States
  SetControlText>Display Lock Key States,TEdit,2,DiaXPos
  SetControlText>Display Lock Key States,TEdit,1,DiaYPos
  Exit>0
EndIF
//////////////////////////////////////////////


//Key down events to detect lock key pressed 
OnEvent>Key_Down,VK20,0,DetectCapState
OnEvent>Key_Down,VK144,0,DetectNumState
OnEvent>Key_Down,VK145,0,DetectScrState
////////////////////////////////////////////

//Alt + Q event to quit the app
OnEvent>Key_Down,VK81,3,Quit
///////////////////////////////


SRT>Quit
  Exit>0
END>Quit

Let>lOCKTimeFlag=0
Let>MoveDialogFlag=0
Let>VK_CAPITAL=20
Let>VK_NUMLOCK=144
Let>VK_SCROLL=145


Dialog>Dialog1
object Dialog1: TForm
  BorderStyle = bsNone
  Caption = 'Display Lock Key States'
  ClientHeight = 20
  ClientWidth = 80
  Color = 16777215
  Formstyle = fsStayOnTop
  object Panel1: TLabel
    Left = 2
    Top = -2
    Width = 10
    Height = 10
    Caption = 'C'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clGray
    Font.Height = -16
    Font.Name = 'Arial'
    Font.Style = [fsBold]
    ParentFont = False
  end
  object Panel2: TLabel
    Left = 33
    Top = -2
    Width = 10
    Height = 10
    Caption = 'N'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clGray
    Font.Height = -16
    Font.Name = 'Arial'
    Font.Style = [fsBold]
    ParentFont = False
  end
  object Panel3: TLabel
    Left = 65
    Top = -2
    Width = 10
    Height = 10
    Caption = 'S'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clGray
    Font.Height = -16
    Font.Name = 'Arial'
    Font.Style = [fsBold]
    ParentFont = False
  end
  object Edit1: TEdit
    Visible = False
  end
  object Edit2: TEdit
    Visible = False
  end
end
EndDialog>Dialog1


//Dialog handlers that allow the mouse to move the dialog
AddDialogHandler>Dialog1,,OnMouseDown,srtMoveDialog
AddDialogHandler>Dialog1,,OnMouseUp,srtNoMoveDialog
AddDialogHandler>Dialog1,Panel1,OnMouseDown,srtMoveDialog
AddDialogHandler>Dialog1,Panel1,OnMouseUp,srtNoMoveDialog(1)
AddDialogHandler>Dialog1,Panel2,OnMouseDown,srtMoveDialog
AddDialogHandler>Dialog1,Panel2,OnMouseUp,srtNoMoveDialog(2)
AddDialogHandler>Dialog1,Panel3,OnMouseDown,srtMoveDialog
AddDialogHandler>Dialog1,Panel3,OnMouseUp,srtNoMoveDialog(3)
/////////////////////////////////////////////////////////


//Initial Dialog position saved to Dialog Labels for SetControlText> use.
SetDialogProperty>Dialog1,Edit1,Text,DiaXPos
SetDialogProperty>Dialog1,Edit2,Text,DiaYPos
///////////////////////////////////////////////////////////////


Show>Dialog1


Wait>0.1
GoSub>DetectCapState
Wait>0.1
GoSub>DetectNumState
Wait>0.1
GoSub>DetectScrState

//Loop and subs to allow mouse to move the dialog
//and to keep the dialog on top of other windows.
Label>StayOnTopLoop
  Wait>0.01
  //Constantly moving the dialog to its current position
  //in conjuction with setting the dialog's form style to 
  //"fsStayOnTop" Keeps it on top of other windows.
  GetDialogProperty>Dialog1,Edit1,Text,DiaXPos
  GetDialogProperty>Dialog1,Edit2,Text,DiaYPos
  Let>WIN_USEHANDLE=1
    MoveWindow>Dialog1.handle,DiaXPos,DiaYPos
  Let>WIN_USEHANDLE=0
  ///////////////////////////////////////////////////////
  
  
  //When flag var is set to one the dialog will
  //follow the mouse.
  If>MoveDialogFlag=1
    GetCursorPos>CurX,CurY
    Let>DiaXPos=%CurX%-%XDiff%
    Let>DiaYPos=%CurY%-%YDiff%
    SetDialogProperty>Dialog1,Edit1,Text,DiaXPos
    SetDialogProperty>Dialog1,Edit2,Text,DiaYPos
  EndIf
  /////////////////////////////////////////////
Goto>StayOnTopLoop

SRT>srtMoveDialog
  VbEval>timer,vStartTime
  If>MoveDialogFlag=0
    Let>WIN_USEHANDLE=1
      GetWindowPos>Dialog1.handle,DiaXPos,DiaYPos
    Let>WIN_USEHANDLE=0
    GetCursorPos>CurX,CurY
    Let>XDiff=%CurX%-%DiaXPos%
    Let>YDiff=%CurY%-%DiaYPos%
  EndIF
  Let>MoveDialogFlag=1
END>srtMoveDialog

SRT>srtNoMoveDialog
  VbEval>timer-%vStartTime%,vEndTime
  If>vEndTime<0.3
    If>srtNoMoveDialog_var_1=1
      Press CAPS
    EndIf
    If>srtNoMoveDialog_var_1=2
      Press num lock
    EndIf
    If>srtNoMoveDialog_var_1=3
      Press scroll lock
    EndIf

    GoSub>DetectCapState
    Wait>0.1
    GoSub>DetectNumState
    Wait>0.1
    GoSub>DetectScrState
  EndIf
  Let>MoveDialogFlag=0
END>srtNoMoveDialog
/////////////////////////////////////////////////


SRT>DetectCapState
  Timer>LockTimeNow
  Let>LockTimeDiff=%LockTimeNow%-%LockTimeFlag%
  If>{%LockTimeDiff%>50}
    LibFunc>User32,GetKeyState,CAP_STATE,20
    If>{(%Cap_state%=65409)or(%Cap_state%=1)}
      SetDialogObjectFont>Dialog1,Panel1,Arial,16,1,111111
    Else
      SetDialogObjectFont>Dialog1,Panel1,Arial,16,0,15790230
    EndIf
  EndIf
  Let>LockTimeFlag=LockTimeNow
END>DetectCapState

SRT>DetectNumState
  Timer>LockTimeNow
  Let>LockTimeDiff=%LockTimeNow%-%LockTimeFlag%
  If>{%LockTimeDiff%>50}
    LibFunc>User32,GetKeyState,NUM_STATE,VK_NUMLOCK
    If>{(%Num_state%=65409)or(%Num_state%=1)}
      SetDialogObjectFont>Dialog1,Panel2,Arial,16,1,111111
    Else
      SetDialogObjectFont>Dialog1,Panel2,Arial,16,0,15790230
    EndIf
  EndIf
  Let>LockTimeFlag=LockTimeNow
END>DetectNumState

SRT>DetectScrState
  Timer>LockTimeNow
  Let>LockTimeDiff=%LockTimeNow%-%LockTimeFlag%
  If>{%LockTimeDiff%>50}
    LibFunc>User32,GetKeyState,SCR_STATE,VK_SCROLL
    If>{(%Scr_state%=65409)or(%Scr_state%=1)}
      SetDialogObjectFont>Dialog1,Panel3,Arial,16,1,111111
    Else
      SetDialogObjectFont>Dialog1,Panel3,Arial,16,0,15790230
    EndIf
  EndIf
  Let>LockTimeFlag=LockTimeNow
END>DetectScrState

Post Reply
Sign up to our newsletter for free automation tips, tricks & discounts