Delphi Clinic | C++Builder Gate | Training & Consultancy | Delphi Notes Weblog | Dr.Bob's Webshop |
|
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: