Dès les premières versions des PDA sous Windows CE (appelés Palm Sized PC ou Handheld PC), Microsoft a proposé une interface de programmation (API) ainsi que des outils de développement proches des versions utilisées par les développeurs Windows :
Avec .NET et Visual Studio .NET 2005, la fusion des deux environnements de développement est maintenant achevée :
Cet article va illustrer un certain nombre de concepts de programmation sous Windows Mobile à l'aide du .NET Compact Framework 2.0 à l'aide d'un exemple concret : la gestion d'une base de données de livres.
Pourquoi gérer ses livres sur mobile ? Essentiellement pour avoir un sujet de programmation : mais ça peut par exemple se justifier dans le cas d'un amateur de bandes dessinées qui possède de nombreuses séries incomplètes : avoir la liste des livres dans sa poche peut éviter d'acheter des doublons.
Cette application sera communicante :
Les projets pour Windows Mobile se trouvent regroupés dans une catégorie " Smart Devices " sous le langage choisi. Sous cette catégorie, on trouve ensuite toutes les plates-formes mobiles pour lesquelles un kit de développement a été installé : Visual Studio .NET 2005 vient avec le SDK Pocket PC 2003, les autres kits peuvent être téléchargés et installés indépendamment. Ils complètent l'installation de Visual Studio, apportent des exemples ainsi que des émulateurs permettant de déboguer les applications sans avoir le matériel réel.
Remarque : on voit avec les types de projet notés " (1.0) " qu'il est toujours possible de cibler le .NET Compact 1.0. Dans la mesure où le .NET Compact Framework 2.0 est plus rapide et plus complet, quel est l'intérêt de cibler l'ancienne version ? Eventuellement le déploiement car la plupart des matériels en circulation incorporent le .NET Compact Framework 1.0 en ROM alors que ce n'est pas encore le cas pour le 2.0. Il faut cependant noter qu'une application peut être par la suite " upgradée " vers le .NET CF 2.0 alors que l'opération inverse n'est pas possible. L'upgrade d'un projet est une opération irréversible et il est donc préférable de sauvegarder une copie des sources lors de cette opération. En ce qui le concerne, le choix de la plate-forme n'est pas exclusif : un projet peut contenir cibler plusieurs plates-formes et il est aussi possible d'en ajouter par la suite. Le choix d'une plate-forme détermine quels assemblies pourront être référencés et quel émulateur sera lancé pour le débogage et définit aussi quelques symboles pouvant être utilisés pour une compilation conditionnelle : " PocketPC " ou " Smartphone " . | ![]() |
Bien qu'un certain nombre de classes soient communes entre le .NET Compact Framework et le .NET Framework " standard ", il est généralement préférable de ne pas chercher à partager des assemblies entre les deux plates-formes : les applications développées pour le .NET Compact Framework fonctionnent sur desktop mais l'inverse n'est pas vrai ; il est donc préférable de créer des assemblies différents pour les deux environnements, mais il est alors possible de partager les sources :
L’utilisation de cette dernière option permet d’avoir le même fichier C# partagé entre les projets .NET Framework et .NET Compact Framework.
A l’intérieur des fichiers ainsi partagés, il est possible d’utiliser les directives de compilations définies par Visual Studio lorsque le code est dépendant de la plate-forme, soit avec la directive #if/#endif soit avec l’attribut Conditional :
private void AfficheNotification(string message) {
#if Smartphone
MessageBox.Show(message);
#else
Microsoft.WindowsCE.Forms.Notification notif
= new Microsoft.WindowsCE.Forms.Notification();
notif.InitialDuration = 2;
notif.Visible = true;
#endif
}
Ou par exemple :
[Conditional("PocketPC")]
void AfficheClavier(bool affiche) {
Microsoft.WindowsCE.Forms.InputPanel panel = new
Microsoft.WindowsCE.Forms.InputPanel();
panel.Enabled = affiche;
}
AfficheClavier(true);
}
En ce qui concerne l’interface utilisateur, il faut savoir que depuis Windows Mobile 2003 Second Edition, les Pocket PC ou les Smartphones n’ont plus nécessairement tous la même résolution et peuvent éventuellement voir leur affichage tourné de 90°.
Pour l’essentiel, le .NET Compact Framework gère ces modifications, le principe d’utilisation est le même que pour les applications Windows Standard : on paramètre le redimensionnement et le replacement des objets graphiques à l’aide de leur propriété Anchor. Cette adaptation fonctionne même lorsque le formulaire est déjà affiché.
L’utilisation des différents émulateurs permet de vérifier le comportement des fenêtres en fonction des différentes résolutions ou avec les rotations.
Il faut noter que les dimensions limitées des écrans vont parfois entraîner l’affichage de barres de défilement (a priori dans une seule direction) :
![]() | ![]() ![]() | ![]() |
La base de données de référence sous Windows Mobile est SQL Server. Auparavant, il s'agissait d'une version spécifique mais la version actuelle, appelée SQL Server Compact Edition est aussi disponible sur Desktop où elle se présente sous la forme d'une DLL facilement redistribuable avec une application.
Là encore, SQL Compact partage un certain nombre de concepts et en particulier une bonne partie du langage de programmation (Transact-SQL) avec les autres versions de SQL Server. Comme les classes spécifiques à SQL Compact (SqlCeConnection, SqlCeCommand, etc.) implémentent les mêmes interfaces que les classes SqlConnection ou OleDbConnection, il est possible de partager une bonne partie du code entre l'application mobile et l'application desktop.
L'ouverture de la connexion à la base de données se fait en précisant le chemin de celle-ci :
SqlCeConnection cnx = new SqlCeConnection(
@"Data Source=\Storage Card\SqlData\Livres.sdf");
Une fois, la connexion établie, il est possible d'accéder de manière uniforme à SQL Server, Access (ou toute autre base accessible via OleDb) ou Sql Server Compact. Voici par exemple, le code d'insertion d'une nouvelle série de livre dans la base de données de test :
protected static void AddParameterWithValue(IDbCommand cmd, DbType type,
@TITRE)";
Un des aspects les plus intéressants de SQL Compact est la synchronisation. En effet, beaucoup d'applications mobiles d'entreprises sont basées sur le scénario suivant : l'utilisateur télécharge des données sur son mobile le matin, il effectue ensuite une " tournée " pendant laquelle il enrichit les données récupérées, puis en fin de journée il met à jour la base centrale avec les données saisies.
SQL Mobile offre trois possibilités principales de synchronisation :
Note : Cette dernière possibilité n'est disponible qu'à l'état de CTP actuellement mais est prometteuse pour les utilisateurs particuliers.
La réplication fusion se base sur un des mécanismes de réplication de base de données offert par SQL Server. Le principe de la réplication fusion est le suivant : les bases répliquées sont synchronisées périodiquement, lors de ces synchronisations, les mises à jour effectuées sur chaque base sont transmises et appliquées à l'autre base. En cas de conflit, aucune donnée n'est perdue et les données en conflit sont enregistrées sur la base SQL Server de référence, sur laquelle il est ensuite possible de procéder à une résolution des conflits ; même en cas de conflit, les bases du mobile et du serveur sont identiques après la réplication. Ce type de réplication est bien adapté aux bases connectées épisodiquement.
Le Remote Data Access est plus spécifique aux applications mobiles (alors que la réplication fusion est utilisée dans de nombreux scénarios). Le mobile crée des tables localement à partir de requêtes SQL exécutées sur le serveur ; les modifications effectuées localement sur le mobile peuvent par la suite être rejouées sur le serveur SQL. Il n'y a pas vraiment de notion de synchronisation : on se contente de rejouer sur le serveur les ordres exécutés en mode déconnecté, les modifications effectuées entre temps sur le serveur ne sont pas redescendues sur le mobile lors de la synchronisation.
Dans les deux cas, l'architecture de synchronisation est la suivante : l'agent SQL " client " discute avec un agent SQL " serveur " qui est une DLL ISAPI hébergée dans Internet Information Server. C'est cette DLL et non l'agent " client " qui se connecte au serveur SQL. L'intérêt de cette architecture est évident dans les scénarios de type extranet car ceci évite de devoir exposer le serveur SQL principal sur internet
La configuration de cette réplication se fait selon les étapes suivantes :
La sécurisation de la réplication supporte toutes les options SQL et IIS :
Dans le cadre de l'application exemple, un compte Windows spécifique a été créé (" SqlMobileUser "), IIS effectue cette authentification et prend l'identité correspondante pour effectuer l'accès à SQL Server. Le paramétrage de la réplication dans l'application mobile est le suivant :
SqlCeReplication repl = new SqlCeReplication();
// URL de l'agent de réplication sur IIS
"http://barney2003R2/sqlmobile/sqlcesa30.dll";
repl.AddSubscription(AddOption.CreateDatabase);
// Réplication synchrone
repl.Synchronize();
// Réplication asynchrone (AsyncReplicationData est une structure propre
// à l’application)
AsyncReplicationData data = new AsyncReplicationData(repl, target,
eventHandler);
repl.BeginSynchronize(base_SyncCompletion, base_StartUpload,
base_StartDownload, base_Synchronisation, data);
Ainsi, la petite application exemple stocke les couvertures des livres enregistrés dans la base dans des champs de type IMAGE qui sont répliqués sans difficulté. Dans la mesure où ces images sont de taille raisonnable, il est assez aisé de les manipuler :
public void SauverImage(string id, byte[] image) {
using (IDbCommand cmd = _cnx.CreateCommand()) {
values(@ID, @BITMAPLEN, @BITMAP)";
image.Length);
ID=@ID";
totalLength, len - totalLength);
public List<ResumeLivre> ParTitre(string critere, string page, out int nbTotalResults, out int nbPages) {
Ces web services ne récupèrent pas directement les images mais leurs URLs (en plusieurs tailles). Pour récupérer et stocker localement ces images, il est possible d'utiliser les classes habituelles WebRequest et WebResponse et aussi d'effectuer ces appels de manière asynchrone :
// Récupération asynchrone de l'image
WebRequest request = WebRequest.Create(_details.ImagePath);
request.BeginGetResponse(TelechargerImage, request);
…
private void TelechargerImage(IAsyncResult iar) {
WebRequest request = iar.AsyncState as WebRequest;
using (WebResponse response = request.EndGetResponse(iar)) {
using (Stream responseStream = response.GetResponseStream()) {
_imageData = new byte[response.ContentLength];
int total = 0;
while (total < _imageData.Length) {
int lus = responseStream.Read(_imageData, total,
_imageData.Length - total);
this.Invoke(new VoidDelegate(AfficherImage));
private void AfficherImage() {
if (pictureBox1.Image != null) {
pictureBox1.Image.Dispose();
}
using (MemoryStream ms = new MemoryStream(_imageData)) {
pictureBox1.Image = new Bitmap(ms);
}
}
public interface IDataAccess : IDisposable {
// Méthodes sur les séries
List<Serie> ListeSeries();
void Sauver(Serie serie);
…
// Validation / Annulation transaction
void Commit();
void Rollback();
}
~DataAccessHelper() {
Dispose(false);
}
private void mitParcourir_Click(object sender, EventArgs e) {
using (FrmLivre dlg = new FrmLivre()) {
dlg.Local = true;
dlg.Livres = _livres;
dlg.ShowDialog();
}
}
Dans le même ordre d'idée, certaines applications pour Windows mobile définissent un User Control par écran et affichent tous ces contrôle dans un formulaire unique qui reste affiché en permanence. Un des intérêts de cette approche est de ne faire apparaître qu'une seule entrée correspondant à l'application dans la liste des tâches en cours d'exécution. La copie d'écran ci-jointe montre ce qui se passe quand on empile des fenêtres, même s'il s'agit de boîtes de dialogue modales. Cette approche est cependant un peu plus délicate à mettre en œuvre au niveau de la gestion de la mémoire et en particulier de la suppression des objets stockés dans le User Controls. | ![]() |
public partial class FrmRecherche : Form {
…
private List<ResumeLivre> _resultat;
…
Si on voulait rendre ce formulaire réutilisable en le masquant au lieu de le détruire, il faudrait alors mettre la variable resultat à null pour permettre la collecte de cette collection inutile lorsque le formulaire n'est pas affiché.
Au travers d'un certain nombre de mécanismes, on a vu que la programmation .NET sur Windows Mobile était assez proche de la programmation Winform " classique " et qu'une bonne partie du code pouvait être réutilisée entre ces différents types d'applications. Windows Mobile associée au .NET Compact Framework est la plate-forme idéale pour développer des solutions mobiles qui peuvent fonctionner manière autonome (avec une éventuelle connexion régulière pour échanger des données avec une base de référence) ou connectées. Le futur .NET Framework 3.5 et Visual Studio .NET 2008 continueront dans cette voie en offrant un .NET Compact Framework 3.5 riche en nouveautés.