Introduction▲
Après une première et une seconde partie sur les développements qu'il est possible de faire dans Vista, nous allons continuer à découvrir ce qu'il est possible de faire sous ce nouveau système d'exploitation.
I. Créer une application dans le panneau de configuration▲
Dans un article précédent, j'expliquai comment il était possible de personnaliser le Welcome Center et dans un autre, j'expliquai le développement de widget pour la SideBar. Aujourd'hui, nous allons nous attaquer à quelque chose de pas forcément plus compliqué, moins évident à mettre en pratique, mais qui, j'en suis sûr, pourra trouver une utilité pour certains d'entre vous. Nous allons voir comment personnaliser le panneau de configuration pour y faire apparaitre nos propres éléments.
Depuis de nombreuses années, la personnalisation d'une application ou d'un système d'exploitation fait partie de mes passe-temps favoris. Et alors que je cherchais à comprendre comment marchait Windows 2000 à l'époque, je me rappelle avoir été intrigué par un élément nvidia ajouté à mon panneau de configuration et j'ai cherché à l'enlever, car…l'icône était laide (oui oui). J'ai alors découvert qu'il s'agissait simplement de fichier *.cpl développé et enregistré sur le système.
Pour ceux qui voulaient développer leur propre composant, il leur fallait suivre scrupuleusement les étapes décrites sur la MSDN.
Une chance pour nous, tout ceci a été revu sous Windows Vista et il est devenu très simple de personnaliser le panneau de configuration, peut-être même aussi simple que la personnalisation du Welcome Center.
Voici un exemple simple de ce que vous saurez faire avec cet article.
I-A. Création d'un GUID▲
Ce petit mini chapitre est presque hors contexte puisqu'il va simplement vous expliquer comment générer un GUID. Un GUID est un Global Unique IDentifier, c'est-à-dire, une chaine de caractères servant d'identifiant unique permettant de désigner un élément, programme ou autre, de façon unique, un peu comme le numéro sur votre carte d'identité. Pratiquement tous les éléments de votre système, que ce soit un dossier système particulier, ou un gestionnaire d'extension et bien d'autres choses, ont leur GUID et notre preview handler, n'échappera pas à la règle. Un GUID est de la forme {CEC124F7-656C-458b-9E7C-43462DE09D01} et en créer un à la main en s'assurant qu'il est unique n'est pas évident. Il faudrait regarder dans votre registre qu'il n'est pas utilisé et si un jour vous deviez utiliser ce GUID sur des postes clients, vous n'auriez pas la certitude de son unicité. Il n'y a donc pas de solution magique et il vous faut utiliser un petit utilitaire fourni par Microsoft qui se nomme GUIDGEN.exe. Pour générer un GUID, rien de tel que Visual Studio et son menu Tools > Generate GUID. Choisissez alors un format registre.
Si vous avez Visual Studio 2008, alors là, manque de chance, le menu n'existe pas, l'outil n'est plus installé avec Visual Studio par défaut. Vous avez alors deux choix, soit le GUIDGEN.exe a été installé et se trouve alors dans C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\, soit tout simplement, il n'est pas sur votre organisateur, et il faut le télécharger sur le site de Microsoft. Une fois celui-ci téléchargé et placé où bon vous semble, vous devez cliquer sur le menu Tools > External Tools… pour configurer un nouveau menu qui fera appel à l'utilitaire. Et c'est tout. Voilà, c'était une petite parenthèse que je jugeais nécessaire, car je suis tombé sur ce problème au moment de la rédaction de cet article.
I-B. Création de notre applet▲
Comme je l'ai dit, vous pourriez avoir besoin de lancer une application développée pour votre entreprise et vous aimeriez la lancer depuis le panneau de configuration. Si par le passé, vous deviez créer une DLL (renommée en .cpl) et implémentant CplApplet, il est maintenant possible, simplement à l'aide de quelques clés registres et d'un fichier XML de rajouter plusieurs actions aux panneaux de configurations.
La première étape consiste à générer un GUID comme vu dans le chapitre précédent. Créez ce GUID et notez-le dans un fichier texte. Profitez-en pour créer trois autres GUID que vous copierez aussi dans le fichier texte afin de ne pas les oublier. Durant cet article, et pour que ce soit clair pour tout le monde, j'utiliserai des GUID factices, mais facilement reconnaissables. J'aurais ainsi :
{00000000-0000-0000-0000-000000000000}
{00000000-0000-0000-0000-000000000001}
{00000000-0000-0000-0000-000000000002}
{00000000-0000-0000-0000-000000000003}
Commençons par enregistrer ce GUID dans le registre. Ouvrez Regedit.exe et rendez-vous à HKEY_CLASSES_ROOT\CLSID\ et créez une nouvelle clé nommée avec votre premier GUID. Dans sa clé présente par défaut, mettez la valeur « MonPremierApplet ». Cette chaine peut-être n'importe laquelle, elle ne nous sera pas utile dans le cas de cet article.
Créez ensuite quatre autres clés de type chaine comme le tableau suivant
Nom de la clé |
Valeur que moi j'ai mise |
Description |
---|---|---|
InfoTip |
mon tooltip à moi ! |
Le texte affiché par l'infobulle quand la souris survolera l'applet |
System.ApplicationName |
Developpez.MonApplet |
Le nom de votre applet. Essayez d'utiliser la forme des espaces de noms, à savoir Entreprise.NomApplet |
System.ControlPanel.Category |
1,8 |
Catégories où apparaitra votre applet |
System.Software.TasksFileUrl |
c:\infos.xml |
Chemin vers un fichier XML de configuration de l'applet. Créez un fichier xml vide sur votre disque et pointez dessus |
Pour les catégories, les valeurs possibles sont les suivantes :
Valeur |
Catégorie |
---|---|
1 |
Apparence et personnalisation |
2 |
Matériel et audio |
3 |
Réseau et Internet |
4 |
non utilisé… |
5 |
Système et maintenance |
6 |
Horloge, langue et région |
7 |
Options d'ergonomie |
8 |
Programmes |
9 |
Comptes utilisateurs et protection des utilisateurs |
10 |
Sécurité |
11 |
Ordinateur Mobile (uniquement visible sur les ordinateurs portables) |
Vous devriez avoir quelque chose ressemblant à ceci :
I-C. Enregistrer l'applet▲
Il reste une étape importante pour utiliser l'applet créé. Pour rappel, nous avons déclaré un GUID et rajouté quelques informations, mais rien ne permet à Windows de savoir que ce GUID est un applet. Nous allons donc nous rendre dans le registre à la clé : HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\NameSpace\ et vous allez rajouter une clé avec comme nom, celui de votre premier GUID. Puis dans sa clé par défaut, vous allez taper le nom de votre applet : « MonPremierApplet ». Avec cette simple ligne, vous indiquez au système d'aller charger les informations de ce GUID qui est censé représenter un applet du panneau de configuration. Si vous vous amusez à indiquer un mauvais ID, votre applet n'apparaitra pas, mais n'empêchera pas le chargement des autres applets.
I-D. L'ajout des tâches▲
Maintenant que votre applet est visible dans le panneau de configuration (s'il ne l'est pas, recommencez les étapes depuis le début), nous allons le personnaliser. Vous vous rappelez que nous avons créé un fichier XML vide nommé infos.xml. Ouvrez-le et collez le code suivant :
<?xml version="1.0" ?>
<applications
xmlns
=
"http://schemas.microsoft.com/windows/cpltasks/v1"
xmlns
:
sh
=
"http://schemas.microsoft.com/windows/tasks/v1"
>
<application
id
=
"{00000000-0000-0000-0000-000000000000}"
>
<!-- id de votre applet -->
</application>
</applications>
À l'intérieur de celui-ci, vous allez décrire trois tâches (le nombre importe peu, mais évitez d'en mettre plus de quatre ou cinq pour des raisons d'esthétisme. Chaque tâche ressemblera à ceci :
<
sh
:
task
id
=
"{00000000-0000-0000-0000-000000000001}"
>
<
sh
:
name>
Lancer Visual Studio</
sh
:
name>
<
sh
:
keywords>
visual;studio;developpement;dev</
sh
:
keywords>
<
sh
:
command>
C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe</
sh
:
command>
</
sh
:
task>
Faites donc de même pour créer deux tâches de plus, l'une lançant une page web et l'autre un fichier de votre disque dur.
<
sh
:
task
id
=
"{00000000-0000-0000-0000-000000000002}"
>
<
sh
:
name>
Visiter Developpez.com</
sh
:
name>
<
sh
:
keywords>
developpez;lgmorand;</
sh
:
keywords>
<
sh
:
command>
http://www.developpez.com</
sh
:
command>
</
sh
:
task>
<
sh
:
task
id
=
"{00000000-0000-0000-0000-000000000003}"
>
<
sh
:
name>
Ouvrir un fichier</
sh
:
name>
<
sh
:
keywords>
fichier;aide;</
sh
:
keywords>
<
sh
:
command>
C:\test.txt</
sh
:
command>
</
sh
:
task>
Dans le registre, nous avons précisé que l'applet, apparaitrait dans deux catégories (la 1 et la 8), nous allons alors créer une catégorie dans le XML tel que suit :
<
category id=
"1"
>
<
sh:
task idref=
"{00000000-0000-0000-0000-000000000001}"
/>
<
sh:
task idref=
"{00000000-0000-0000-0000-000000000002}"
/>
<
sh:
task idref=
"{00000000-0000-0000-0000-000000000003}"
/>
</
category>
<
category id=
"8"
>
<
sh:
task idref=
"{00000000-0000-0000-0000-000000000003}"
/>
<
sh:
task idref=
"{00000000-0000-0000-0000-000000000002}"
/>
</
category>
Vous noterez que l'une n'a que deux tâches, et surtout elle ne les a pas dans le même ordre. Ceci a pour but de permettre de créer UN SEUL applet, mais qui sera affiché sous différentes formes et affichant différentes tâches selon la catégorie dans laquelle il est chargé.
Voici le résultat final :
I-E. Pour aller un peu plus loin▲
I-E-1. Changer l'icône de l'applet▲
Il est possible de configurer l'icône de l'applet qui apparaitra. Dans le registre, dans CLSID, sous la clé de votre applet, rajoutez la clé DefaultIcon et dans sa sous-clé par défaut, tapez le chemin d'une image PNG.
C'est tout !
I-E-2. Faire apparaitre le bouclier de l'UAC à côté des tâches critiques▲
Les recommandations de Microsoft pour le développement sur Windows Vista requièrent qu'une icône particulière apparaisse à côté des applications lançant une tâche nécessitant une élévation de privilèges.
Pour cela, rien de bien compliqué, il suffit de rajouter l'attribut needsElevation sur la tâche de votre choix
<
sh
:
task
id
=
"{00000000-0000-0000-0000-000000000001}"
needsElevation
=
"true"
>
I-E-3. Lancer une application à partir du titre de l'applet▲
Nous avons vu comment ajouter des tâches et lancer des applications à partir de celle-ci. Nous allons voir qu'il est possible de lancer une application depuis le titre de l'applet ou si vous préférez, avoir un applet fonctionnel, sans avoir à déclarer des tâches.
Pour cela, rendez-vous dans le registre dans CLSID/votre_guid, puis ajoutez une sous-clé Shell contenant une sous-clé Open et enfin une sous-clé Command, dont la valeur par défaut contiendra le chemin vers l'application que vous souhaitez lancer. Exemple :
I-F. Conclusion et liens complémentaires▲
Vous avez donc vu, comment très facilement, il était possible au sein d'une entreprise ou même simplement chez vous, de personnaliser.
Si vous voulez creuser un peu plus sur la création d'éléments du panneau de configuration, je vous conseille les deux liens suivants :
The Windows Vista and Windows Server 2008 Developer Story: Developing for Control Panel
Guidelines about Control Panels
II. Amélioration des interfaces graphiques▲
Pour continuer sur la lancée, je finis les articles sur le développement sur Windows Vista par un chapitre sur la création de contrôles « à la Vista ». Nous allons donc voir comment créer ces contrôles. Il n'y a bien sûr aucune magie là-dessous et il n'est pas question de recoder un contrôle de zéro, mais simplement de vous présenter des API non ou peu documentées que vous pourriez trouver en fouillant allègrement la MSDN comme ici.
II-A. La textBox améliorée▲
Améliorer une textBox ? Que peut-on rajouter à un simple champ de saisie ? Un filtre ? Le framework 2.0 contient déjà les MaskedEditBox. Pourquoi pas un message d'aide à la saisie.
Il s'agirait d'un texte qui serait affiché dans la textbox tant que l'utilisateur n'a pas saisi de texte. Cela peut se faire en envoyant un message particulier à une textbox ainsi que le texte à afficher.
Voici ce à quoi ça ressemblerait :
Et bien les API systèmes le permettent, notamment grâce à l'envoi d'un message particulier au contrôle : le message EM_SETCUEBANNER. L'implémentation n'est pas complexe, il suffit d'envoyer ce message ainsi que le texte à afficher, au contrôle que l'on souhaite voir afficher le texte.
Voici un custom control pour lequel vous pouvez en mode design, définir le texte à afficher :
public
class
MaTextbox :
TextBox
{
[DllImport(
"user32.dll"
, CharSet = CharSet.Auto)]
private
static
extern
Int32 SendMessage
(
IntPtr hWnd,
int
msg,
int
wParam,
[
MarshalAs
(
UnmanagedType.
LPWStr)]
string
lParam);
private
const
int
EM_SETCUEBANNER =
0x1501
;
private
string
_cueText =
String.
Empty;
[Category(
"Custom"
),
Description
(
"Texte affiché comme conseil"
),
]
public
string
CueText
{
get
{
return
_cueText;
}
set
{
_cueText =
value
;
SendMessage
(
this
.
Handle,
EM_SETCUEBANNER,
0
,
_cueText);
}
}
}
II-B. Le SplitButton▲
Le SplitButton est un nouveau contrôle apparu sous Windows Vista qui permet de mixer un bouton avec un contextMenu. Le bouton ne permet pas simplement d'afficher un contextMenu lorsqu'on clique dessus puisque cela, nous pouvions déjà le faire avec un bouton normal. Non, il s'agit d'un bouton « normal » proposant également une petite flèche permettant d'afficher un menu contextuel.
Là encore, tout n'est question que d'envoyer un message (BS_SPLITBUTTON) et d'utiliser un second (BCM_SETDROPDOWNSTATE). Néanmoins, si faire apparaitre un SplitButton est facile, pour le rendre parfaitement fonctionnel, et utiliser un contextmenu (pas un contextmenustrip), cela devient une autre paire de manches. Plutôt que réinventer la roue, je vous donne ici une classe que j'ai repris d'un certain Nicholas Kwan et que j'ai corrigée (même s'il reste des bugs) :
using
System;
using
System.
Drawing;
using
System.
Runtime.
InteropServices;
using
System.
Windows.
Forms;
/*************************
* modifié depuis un contrôle fait par Nicholas Kwan
* http://www.tevine.com
* *********************/
namespace
developpez.
com.
vista.
controls
{
//This control now supports dropdowns.
public
delegate
void
DropDownClicked
(
);
public
class
SplitButton :
Button
{
[DllImport(
"user32.dll"
, CharSet = CharSet.Unicode)]
private
static
extern
IntPtr SendMessage
(
HandleRef hWnd,
UInt32 Msg,
IntPtr wParam,
string
lParam);
[DllImport(
"user32.dll"
, CharSet = CharSet.Auto)]
public
static
extern
IntPtr SendMessage
(
IntPtr hWnd,
int
msg,
int
wParam,
int
lParam);
public
const
int
BCM_FIRST =
0x00001600
;
public
const
int
BCM_SETDROPDOWNSTATE =
BCM_FIRST +
0x0006
;
public
const
int
BS_SPLITBUTTON =
0x0000000C
;
public
const
int
WM_KILLFOCUS =
0x08
;
public
const
int
WM_LBUTTONDOWN =
0x201
;
public
const
int
WM_LBUTTONUP =
0x202
;
public
const
int
WM_MOUSELEAVE =
0x2A3
;
public
const
int
WM_PAINT =
0x0F
;
public
const
int
WM_USER =
0x400
;
private
ContextMenu ddm_ =
new
ContextMenu
(
);
public
int
dropdownpushed;
public
int
isatdropdown;
public
int
isbumped;
public
int
ismousedown;
public
SplitButton
(
)
{
FlatStyle =
FlatStyle.
System;
DropDown_Clicked +=
launchmenu;
ddm_.
Collapse +=
CloseMenuDropdown;
}
//Set the theme
protected
override
CreateParams CreateParams
{
get
{
CreateParams cParams =
base
.
CreateParams;
cParams.
Style |=
BS_SPLITBUTTON;
return
cParams;
}
}
public
ContextMenu Dropdownmenu
{
get
{
return
ddm_;
}
set
{
ddm_ =
value
;
this
.
ddm_.
Collapse +=
new
EventHandler
(
this
.
CloseMenuDropdown);
}
}
protected
override
void
WndProc
(
ref
Message m)
{
// Listen for operating system messages; Filter out a lot of messages here
//The dropdown glyph changes:
//Mousedown (at dropdown area) => Dropdown Event fired => Glyph changes => MouseUp => Glyph Changes
switch
(
m.
Msg)
{
case
(
BCM_SETDROPDOWNSTATE):
//PROBLEM: other buttons also have would encounter this message
if
(
m.
HWnd ==
Handle)
{
////This message seems to occur when the drop down is clicked;
////Occures several times, but one of them have the value of 1 in WParams
if
(
m.
WParam.
ToString
(
) ==
"1"
)
{
if
(
dropdownpushed ==
0
)
{
//One time-initiation per mouse press
dropdownpushed =
1
;
DropDown_Clicked
(
);
}
}
if
(
ismousedown ==
1
)
{
isatdropdown =
1
;
}
}
break
;
case
(
WM_PAINT):
//Paints the control to have the dropdown when needed
if
(
dropdownpushed ==
1
)
{
SetDropDownState
(
1
);
}
break
;
case
(
WM_LBUTTONDOWN):
ismousedown =
1
;
break
;
case
(
WM_MOUSELEAVE):
if
(
isatdropdown ==
1
)
{
SetDropDownState
(
0
);
isatdropdown =
0
;
ismousedown =
0
;
}
break
;
case
(
WM_LBUTTONUP):
if
(
isatdropdown ==
1
)
{
SetDropDownState
(
0
);
isatdropdown =
0
;
ismousedown =
0
;
}
break
;
case
(
WM_KILLFOCUS):
if
(
isatdropdown ==
1
)
{
SetDropDownState
(
0
);
isatdropdown =
0
;
ismousedown =
0
;
}
break
;
}
base
.
WndProc
(
ref
m);
}
public
void
SetDropDownState
(
int
Pushed)
{
if
(
Pushed ==
0
)
{
dropdownpushed =
0
;
//Removes dropdown pushed state
}
SendMessage
(
this
.
Handle,
BCM_SETDROPDOWNSTATE,
Pushed,
0
);
}
public
event
DropDownClicked DropDown_Clicked;
//The event which would be fired whenever the drop-down is clicked on.
private
void
InitializeComponent
(
)
{
SuspendLayout
(
);
ResumeLayout
(
false
);
}
public
void
launchmenu
(
)
{
if
(
ddm_.
MenuItems.
Count !=
0
)
{
ddm_.
Show
(
this
,
new
Point
(
Width,
Height),
LeftRightAlignment.
Left);
}
}
public
void
CloseMenuDropdown
(
object
sender,
EventArgs e)
{
//Hmm... contextmenu "collapse" state doesn't seem to fire up when a menuitem is clicked. Does not work here yet.
SetDropDownState
(
0
);
}
}
}
Voici le résultat obtenu :
II-C. Sélection semi-transparente sur les listViews▲
Certains ne le savent peut-être pas, mais l'explorateur Windows n'est principalement composé que d'une listView améliorée dans laquelle apparaissent les fichiers et les dossiers de votre disque dur. Lorsque vous sélectionnez des fichiers, un carré semi-transparent bleu apparait. Nous allons voir qu'il est très simple d'inclure cette sélection au sein de nos listViews.
Il suffit pour cela d'envoyer simplement le code du double-buffering LVS_EX_DOUBLEBUFFER, qui sert normalement à éviter le scintillement des contrôles.
const
int
LVS_EX_DOUBLEBUFFER =
0x00010000
;
SendMessage
(
listView1.
Handle,
0x1000
+
54
,
LVS_EX_DOUBLEBUFFER,
LVS_EX_DOUBLEBUFFER);
Conclusion▲
Et voilà que se termine déjà la troisième partie du développement d'applications sous Windows Vista. Il se peut fort que ce soit le dernier de la série. En effet, depuis octobre, je tourne exclusivement sous Windows Seven et celui-ci permet de nouvelles choses encore plus intéressantes. Il est donc fort possible que je m'oriente vers la réécriture plus complète et plus structurée du développement d'applications, mais cette fois-ci, appliqué au futur système d'exploitation de Microsoft.
III. Remerciements▲
Je tiens à remercier ram-0000 pour ses corrections et conseils apportés à l'article.