L’objectif d’un clavier virtuel est d’offrir à l’utilisateur, un confort d’utilisation qui ne lui fera pas regretter son clavier physique favori.
La principale différence est que le clavier physique est détaché de l’écran tandis qu’un clavier virtuel est quant à lui, prisonnier de cette jungle de pixels.
L’enjeu est donc de réduire ce désavantage au minimum.
Et la première difficulté que nous avons rencontré fut de rendre le CVK totalement “transparent” aux yeux du système d’exploitation. Concrètement, lorsque l’on clique sur une fenetre, celle-ci reprends le focus, devenant active. Cependant, pour un clavier virtuel, le but étant de saisir des informations dans une autre fenetre, ce mécanisme rendrait la chose impossible.
Il existe un moyen de résoudre ce problème : controler soi-meme les évenements de la souris lorsqu’ils sont sur le clavier, et les traiter nous meme, comme si le système ne savait pas que l’on avait cliqué.
Or ceci à ses limites : lorsqu’une fenetre ou un autre composant du système se trouve au dessus du clavier, (typiquement un menu, comme menu démarrer pour windows, ou des menus de barres des taches) le clic est lui aussi ignoré…
Solution !
Rendre le CVK non activable : pour ceci : on surcharge notre méthode CreateParams de la classe Windows.Form
///Message système qui définit, à la création, si la form devient active sur un click
private const int WS_EX_NOACTIVATE = 0×8000000;
///Message système qui définit, à la création, si la form peut avoir une barre de titre
private const int WS_CAPTION = 0xc00000;
/// <summary>
/// Override virtual method to have a form with Resizable borders but no
/// TitleBar and to made the form inactive when clicks are performed over its
/// </summary>
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
long Style = cp.Style;
cp.Style ^= WS_CAPTION;
cp.ExStyle |= WS_EX_NOACTIVATE;
return cp;
}
}
Les paramètres de créations sont, soit soustraits ( ^= ) soit ajoutés ( |= ) sur les styles étendus ( ExStyle ) ou de bases ( Style ).
Il faut aussi penser à redéfinir la méthode WndProc de la classe Form et capter le message WM_MOVING.
En effet, lors d’un déplacement ou d’un redimensionnement, si la fenêtre n’est pas activable (comme démontré ci-dessus), nous ne verrons pas en temps réel son déplacement, mais uniquement lors du relâché du bouton.
private const int WM_MOVING = 534;
/// <summary>
/// Helper structure used to retrieve and follow the location of the form on a moving or resizing operation
/// </summary>
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
/// <summary>
/// Windows.Form Methode witch processes Windows messages.
/// </summary>
protected override void WndProc( ref Message m )
{
// Listen for operating system messages.
switch (m.Msg)
{
case WM_MOVING:
RECT r;
r = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
this.Location = new Point(r.Left, r.Top);
break;
}
base.WndProc(ref m);
}
Il en va de même pour le redimensionnement de la Form : capter le message WM_SIZING, afin d’avoir un redimensionnement en temps réel.
Toujours dans notre méthode WndProc :
private const int WM_SIZING = 0×0214;
//Resizing the form thanks to the border althought it is inactivated. Shows live the resizing.
case WM_SIZING:
r = ( RECT ) Marshal.PtrToStructure( m.LParam, typeof( RECT ) );
this.Size = new Size( r.Right - r.Left, r.Bottom - r.Top );
//If the left or top anchors or the top right are selected
if (
m.WParam == ( IntPtr ) WMSZ_LEFT ||
m.WParam == ( IntPtr ) WMSZ_TOP ||
m.WParam == ( IntPtr ) WMSZ_TOPLEFT ||
m.WParam == ( IntPtr ) WMSZ_BOTTOMLEFT ||
m.WParam == ( IntPtr ) WMSZ_TOPRIGHT)
{ //We also change the top left location of the form
this.Location = new Point( r.Left, r.Top );
}
Marshal.StructureToPtr( r, m.LParam, true );
break;
