Le premier site francophone dédié au développement Pocket PC

Fenêtre flottante sur un Pocket PC avec le .NET Compact Framework
Auteur
Romuald Tisserand
Date 14 mai 2004
 
   


Introduction


Depuis qu'il est possible de développer des applications avec la plate-forme " .Net " sur un Pocket PC grâce au " Compact Framework ", il est un élément d'interface utilisateur que Microsoft n'a pas souhaité proposer : les fenêtres flottantes. Hors, souvent, une fenêtre flottante est un moyen esthétique et ergonomique d'afficher des informations, citons par exemple :

Les informations relatives à un traitement en cours (copie de fichiers…),
Questions à l'utilisateur,

Cet article a pour but de vous montrer comment implémenter une telle fenêtre. Mais avant de commencer, définissons tout d'abord le cahier des charges de notre fenêtre flottante :

La fenêtre ne doit pas être affichée en plein écran,
La fenêtre doit proposer une barre de titre (couleurs et police seront celles en vigueur sur le système),
La fenêtre doit être déplaçable avec le stylet (en pressant sur la barre de titre),
Pendant le déplacement de la fenêtre, un rectangle doit être dessiné au fur et à mesure du déplacement du stylet,
La fenêtre doit être ré-utilisable, c'est à dire que la fenêtre présentée ici sera un canevas (ou " template ") de fenêtre flottante pour les applications.

Vous remarquerez que les boutons " Ok " et " Annuler " ne font pas partie du cahier des charges. En effet, proposer ces boutons dans la barre de titre d'une fenêtre (comme une application Pocket PC normale n'est pas vraiment ergonomique si celle-ci est flottante. Aussi nous laisserons le soin à chacun de développer ces boutons.

IMPORTANT : Pour mettre en œuvre la fenêtre flottante décrite dans cet article, vous devez utiliser le " .Net Compact Framework SP2 ". En effet, certaines propriétés (nous les mentionnerons au fur et à mesure de l'article) ne sont disponible que dans le SP2. Vous pouvez télécharger le " SP2 " à cette adresse. Veillez bien à installer ce " SP2 " sur l'émulateur et/ou le Pocket PC selon la cible sur laquelle vous effectuez vos tests.

Installation du " OpenNETCF Smart Device Framework "

Vous pouvez télécharger le " Smart Device Framework " (j'utiliserai l'acronyme SDF dans la suite du document) à cette adresse.

Le SDF est très utile car il a la bonne idée de proposer l'accès à des éléments qui ne sont pas directement accessibles depuis le .Net CF. Par contre, en utilisant certains éléments du SDF, qui accèdent eux-mêmes directement au système d'exploitation Windows CE, vous perdez l'indépendance de la plate-forme chère à .Net, on ne peut pas tout avoir.

Premiers pas

Nous commencerons classiquement par créer un projet de type " Smart Device Application " (j'utilise une version anglaise de VS, mais il vous sera facile de retrouver l'équivalent en Français) que nous appellerons " MonExe ". Ce projet sera une " application Windows " pour la plate-forme " Pocket PC ".

Afin de bien séparer le code des IHM du reste, nous créons une classe appelée " Lanceur " qui contiendra le code de la méthode " Main " et nous supprimons celle-ci du code de " Form1 ". Et laissons, provisoirement la méthode " Main " vide.


Pour nous ajoutons à la solution en cours, un nouveau projet " OpenNETCF Application " de type " class library " que nous appelons " Fenetre ". Une fois le projet créé, supprimons la classe " Class1 ", puis ajoutons une fenêtre que nous appelons " Flottante ". Ajoutons maintenant une dépendance du projet " Fenetre " dans " MonExe " et modifions la méthode " Main " de façon à afficher la fenêtre " Flottante " comme une boîte de dialogue.

Pourquoi afficher la fenêtre comme une boîte de dialogue ? Tout simplement car elle se ferme lors d'un appui sur " Ok " ce qui n'est pas le cas d'une fenêtre normale, on gagne donc du temps lors du développement (sinon il faut activer l'action " stop debugging " dans Visual Studio ce qui est assez rébarbatif. Exécutons maintenant notre programme.


D'accord ce n'est pas très visuel, mais nous allons maintenant faire mieux.


Un bouton de fermeture

Comme nous ne proposerons pas de bouton de fermeture, et toujours afin de nous simplifier la vie, nous allons poser un bouton sur la fenêtre qui nous permettra de fermer celle-ci au fil du développement. Ce bouton pourra être supprimé une fois le projet terminé.

Posons donc un bouton sur la fenêtre, nous l'appellerons, au hasard, " Ok " et nous écrirons le code correspondant pour fermer la fenêtre :

 

Maintenant que nous pouvons facilement afficher la fenêtre et la fermer, passons aux choses sérieuses.


Une fenêtre qui n'est pas " plein écran "

Rappelons nous, la première de nos exigences est d'afficher une fenêtre qui soit " fenêtrée " c'est à dire affichée, mais pas en plein écran.

Pour cela, nous allons " jouer " avec les propriétés de la fenêtre. Et pour avoir une fenêtre qui ne soit pas " plein écran ", encore faut-il que sa taille soit inférieure à celle du dit écran. Nous allons donc modifier la propriété " Size " pour, disons, fixer la taille à 100 * 100.
Mais si vous exécutez le programme, la fenêtre est toujours plein écran…hé hé, ce serait trop facile.

La première propriété à modifier est " FormBorderStyle " qu'il convient de fixer à " None ". Ainsi la fenêtre n'a plus de bordure. Puis nous allons aussi fixer la position de la fenêtre à 50*50 ainsi nous pourrons vérifier qu'elle n'est pas plein écran. Exécutons.


Nous avons donc une fenêtre qui n'est pas " plein écran ". Mais sa barre de titre et ses boutons sont toujours affichés dans la barre de titre du Pocket PC. Nous allons changer cela.


La barre de titre

Création de la barre de titre

Nous allons commencer par supprimer les boutons de la barre de titre. Rien de plus facile, il suffit de passer la propriété " ControlBox " à " false ". Mais comme nous pouvons le constater cela ne suffit pas. Le titre " Flottante " est toujours affiché en haut. Là, nous allons compliquer un peu les choses.

Et c'est là que le " OpenNETCF SDF " va grandement nous aider, car nous allons appeler directement l'API Win32 pour ajouter la barre de titre.

Tout d'abord, il nous faut ajouter l'espace de noms nécessaire :

using OpenNETCF.Win32;

Puis nous modifions le code du constructeur de la fenêtre comme suit :

public Flottante()
{

InitializeComponent();

// Récupèrer le handle de la fenêtre
IntPtr hWnd = Win32Window.FromControl(this);

// Liste des styles à enlever (voir article)
int enleves = (int)(Win32Window.WindowStyle.WS_SYSMENU|
Win32Window.WindowStyle.WS_MINIMIZEBOX|
Win32Window.WindowStyle.WS_MAXIMIZEBOX);

// Liste des styles à ajouter
int ajoutes = (int)(Win32Window.WindowStyle.WS_CAPTION|
Win32Window.WindowStyle.WS_POPUP);

// Mise à jour du style de la fenêtre
Win32Window.UpdateWindowStyle(hWnd, enleves, ajoutes);

}

Là quelques explications s'imposent.

Nous avons, pour commencer, récupérer le " handle " de la fenêtre, c'est-à-dire l'identifiant unique de celle-ci dans le système.

Nous avons ensuite créé une liste des styles à enlever. Vous allez me dire que ce sont les styles que nous avons " proprement " supprimés plus haut dans le document et vous avez raison. Mais d'après certains dialogues que j'ai pu avoir aux US, il semble que certains styles plus ou moins cachés subsistent. Donc 2 précautions valent mieux qu'une.

Puis nous avons créé la liste des styles à ajouter, on commence par " WS_POPUP " qui est le style à utiliser pour toute fenêtre de type dialogue, puis nous ajoutons le style " WS_CAPTION " qui ajoute non seulement la barre de titre, mais aussi une fine bordure autour de la fenêtre.

La dernière ligne va, en une seule ligne de code, enlever les styles voulus et ajouter ceux désirés.

Si nous exécutons ce code, nous obtenons :


Nous avons donc une fenêtre flottante, avec une barre de titre, que l'on peut déplacer. Vous remarquerez que le positionnement des contrôles est respectée, il faudra juste prévoir une place vide tout en bas de la fenêtre dans le " form designer " de Visual Studio pour la barre de titre (nous allons voir ça dans le chapitre suivant).

Reste un problème, c'est que la barre de titre apparaît aussi dans le menu du Pocket PC et ça c'est pas génial. Eh bien malheureusement, il va falloir vous y faire car pour l'instant, je n'ai pas trouvé de solution à ce problème. Il s'agit d'un fonctionnement interne à Windows CE. Un test très simple à faire est d'analyser le style d'une fenêtre normale, c'est-à-dire plein écran comme vous les connaissez. En analysant ce style vous pourrez voir que " officiellement " une fenêtre plein écran n'a pas de titre. La barre de titre de votre Pocket PC est une sorte d'application qui affiche le titre et le menu système, s'il y a lieu, de la fenêtre actuelle visible. Si quelqu'un a une solution pour contourner ce problème, je suis preneur à l'adresse donnée en fin de document. Une autre manière de vérifier que ce fonctionnement est standard sous Windows CE est d'observer la fenêtre de connexion ActiveSync quand vous branchez votre Pocket PC au PC, cette fenêtre est écrite en code natif (pas en .Net donc) et bien vous avez quand même le titre " Connexion " qui s'affiche tout en haut comme dans notre exemple.

Il convient néanmoins de relativiser ce problème. En effet, dès que vous n'aurez plus besoin de votre " popup ", il vous suffit de la fermer et la barre Windows CE reprend son affichage adéquat, ce problème est donc assez mineur.

Note : vous avez sans doute remarqué que la couleur de la barre de titre est bleue et ne correspond pas à la couleur de votre thème favori. C'est malheureusement normal, Microsoft n'a visiblement pas jugé nécessaire cette fonctionnalité. Ce bleu est la couleur système de Windows CE.

Ajustement de la zone cliente

Notre barre de titre nous pose un petit problème : elle occupe une bonne part de la place allouée aux contrôles (la zone cliente), comme nous pouvons le voir en comparant les 2 captures suivantes :

Nous allons donc mettre en œuvre un mécanisme de compensation automatique de la zone cliente, de façon à pouvoir librement utilisée le canevas que nous sommes en train de concevoir.

Il convient de tout d'abord, de mesurer la zone cliente avant le changement de style :


InitializeComponent();

// Mémorise la zone cliente avant le changement de style
Size aireAvant = this.ClientSize;

// Récupèrer le handle de la fenêtre
IntPtr hWnd = Win32Window.FromControl(this);


…et nous faisons pareil après le changement de style :


// Mise à jour du style de la fenêtre
Win32Window.UpdateWindowStyle(hWnd, enleves, ajoutes);

// Mesure l'aide cliente après le changement de style
Size aireApres = this.ClientSize;


}

Maintenant nous pouvons calculer le changement de taille de la zone restituer la taille voulue :


// Mesure l'aide cliente après le changement de style
Size aireApres = this.ClientSize;

// Restitue la taille de l'aire cliente
aireApres.Width += aireAvant.Width - aireApres.Width;
aireApres.Height += aireAvant.Height - aireApres.Height;
this.ClientSize = aireApres;


}

La preuve en images :

Ce qui a été dessiné
Avant traitement
Après traitement

Ne reste plus qu'à supprimer le bouton " Ok " ainsi que le code de traitement associé et nous sommes prêts à exploiter ce merveilleux canevas de fenêtre flottante.

A l'usage

Nous allons maintenant mettre en œuvre un concept que VS ne supporte que partiellement quand il s'agit d'un programme " smart devices " : l'héritage visuel. C'est à dire la possibilité qu'une fenêtre hérite d'une autre.

Et quand je dis que VS ne le supporte que partiellement, je parle bien sur du " form designer " qui ne supporte l'édition graphique des fenêtres que si celles-ci dérivent directement de System.Windows.Forms.Form. Donc une fois l'héritage déclaré, il devient impossible de concevoir la fenêtre avec le " form designer " ; alors que cela est parfaitement possible pour une application " .Net " standard.

Nous allons donc modifier la méthode " Main " de la classe " Lanceur " pour afficher la fenêtre de " MonExe ", il s'agit de " Form1 " dans notre exemple.

static void Main()
{
new Form1().ShowDialog();
}

Puis nous ajoutons des contrôles à cette fenêtre, modifions sa taille…


Si on exécute le programme tel quel :

Jusque ici c'est normal, maintenant, afin de mettre en œuvre notre canevas, nous devons modifier l'héritage de " Form1 "

public class Form1 : Fenetre.Flottante

…et on exécute :

Et oh miracle !! Ca marche. C'est quand même bien l'informatique !!


Conclusion

J'aurais aimé terminer cet article par un chapitre consacré à l'intégration de notre fenêtre flottante dans un assistant pour VS. Mais j'ai abandonné cette idée pour 2 raisons.

La première est qu'après avoir analysé la documentation sur les assistants (trop succincte au demeurant), la valeur ajoutée de cette intégration est trop faible comparé au travail nécessaire pour réaliser un assistant valable.

La 2é raison est que le concept " d'héritage visuel ", à savoir la possibilité de créer des fenêtres " mères " puis d'en dériver des " filles " que l'on manipule dans le " form designer " de VS, n'est pas supporté par VS quand il s'agit de projets de type " smart devices ".

Pourquoi ? C'est une bonne question. VS.Net 2005 (Whidbey) règlera peut être ce problème.

Gardez bien à l'esprit que chaque modification d'une fenêtre " flottante " dans le " form designer " ne pourra se faire que si, au préalable, vous avez remis l'héritage de la fenêtre à sa valeur par défaut (System.Windows.Forms.Form).

Si vous désirez plus d'informations ou simplement pour correspondre avec moi, n'hésitez pas à me contacter à softromu@hotmail.com.

Romuald Tisserand

 

 
   

Copyright 2001-2004 - Tous droits réservés
Toutes les autres marques et produits présents dans ces pages sont la propriété exclusive de leurs sociétés respectives.