Delphi Clinic C++Builder Gate Training & Consultancy Delphi Notes Weblog Dr.Bob's Webshop
Bob Swart (aka Dr.Bob) - Medical Officer Delphi in a Nutshell
 Under The Hood #11 - Lock on Your Status...
See Also: Delphi Papers and Dr.Bob's Examines Columns

Delphi 2 has a nice new TStatusBar component. You can use this to provide a statusbar that consists of many sub-panels, for examples panels that can be used to show the status of the NumLock, CapsLock, ScrollLock and Insert keys (I know a few editors that do that). However, there is no component in Delphi to give me the status of these special keys, nor does the TStatusBar offer me this feature. So, let's see if it's really difficult to customize our TStatusBar and show the status of these keys ourselves...

First, let's start a new project and drop a TStatusBar component (Win95 tab) on the form. If we click on the Panels property, we get a special property editor for TStatusPanels with which we can enter the names and properties of the panels of the Statusbar:

After we've specified four extra panels (for NumLock, CapsLock, ScrollLock and Insert/Overwrite), it's time to write some code to detect the status of these special keys.

The first step is finding a way to detect the status of these keys. Fortunately, I know that the Windows API GetKeyStatus can be used to help us with this (see the Windows API on-line help for more details). GetKeyStatus can be called with a VK_keyvalue as argument, such as VK_NumLock for the NumLock key.
The question remains: what are the VK_keyvalues for the CapsLock, ScrollLock and Insert keys? For that we have to look inside the WINDOWS.PAS file (or WINTYPES.PAS, depending on the version of Delphi you're using). Insert is easy, and is called VK_Insert. ScrollLock is also not difficult, as it's called VK_Scroll. CapsLock, however, is a bit harder, and after a bit of experimenting I found that VK_Capital is the one to use. This results in a method to set the status of these keys as follows:

  procedure TForm1.KeyLocks;
  begin
    if Odd(GetKeyState(vk_NumLock)) then StatusBar1.Panels[0].Text := 'NUM'
                                    else StatusBar1.Panels[0].Text := '';
    if Odd(GetKeyState(vk_Capital)) then StatusBar1.Panels[1].Text := 'CAP'
                                    else StatusBar1.Panels[1].Text := '';
    if Odd(GetKeyState(vk_Scroll)) then StatusBar1.Panels[2].Text := 'SCR'
                                   else StatusBar1.Panels[2].Text := '';
    if Odd(GetKeyState(vk_Insert)) then StatusBar1.Panels[3].Text := 'INS'
                                   else StatusBar1.Panels[3].Text := 'OVR';
  end;

Now, one question remains: when do we call this routine? How do we make sure that the status of these keys is immediately updated in the StatusBar? A fine way to make sure that we always have up-to-date information in the StatusBar is to connect the Application.OnIdle event handler to our KeyLocks routine. For that we need to add two parameters to the KeyLocks routine, and assign it to Application.OnIdle in the FormCreate event, and make sure the Application.OnIdle is cleared again in the FormDestroy event. The complete source code for the form with the StatusBar is as follows:

  unit Unit1;
  interface
  uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    ComCtrls;

  type
    TForm1 = class(TForm)
      StatusBar1: TStatusBar;
      procedure FormCreate(Sender: TObject);
      procedure FormDestroy(Sender: TObject);
    private
      procedure KeyLocks(Sender: TObject; var Done: Boolean);
    end;

  var
    Form1: TForm1;

  implementation
  {$R *.DFM}

  procedure TForm1.FormCreate(Sender: TObject);
  begin
    Application.OnIdle := KeyLocks;
  end;

  procedure TForm1.FormDestroy(Sender: TObject);
  begin
    Application.OnIdle := nil
  end;

  procedure TForm1.KeyLocks(Sender: TObject; var Done: Boolean);
  begin
    if Odd(GetKeyState(vk_NumLock)) then StatusBar1.Panels[0].Text := 'NUM'
                                    else StatusBar1.Panels[0].Text := '';
    if Odd(GetKeyState(vk_Capital)) then StatusBar1.Panels[1].Text := 'CAP'
                                    else StatusBar1.Panels[1].Text := '';
    if Odd(GetKeyState(vk_Scroll)) then StatusBar1.Panels[2].Text := 'SCR'
                                   else StatusBar1.Panels[2].Text := '';
    if Odd(GetKeyState(vk_Insert)) then StatusBar1.Panels[3].Text := 'INS'
                                   else StatusBar1.Panels[3].Text := 'OVR';
  end;

  end.
And in action we get feedback the moment we hit a key:


This webpage © 1996-2017 by Bob Swart (aka Dr.Bob - www.drbob42.com). All Rights Reserved.