Créez des applications Delphi compatibles Windows Vista - Mise à jour

Windows Vista est maintenant disponible depuis quelques mois. Si vous avez su tirer partie du premier article à ce sujet, cette seconde traduction vous intéressera sans doute.
Nathanial Woolls a complété son article original en réaction aux retours qu'il en a reçus, et pour corriger/améliorer certains codes. C'est la traduction de cette seconde version de Creating Windows Vista Ready Applications que je vous propose ici, afin que vous puissiez profiter du travail qui a été effectué ces derniers mois par les delphistes anglophones les plus actifs.

Un grand merci à Nathanial Woolls pour m'avoir donné l'autorisation à deux reprises de traduire et de vous proposer librement la version française de ses articles.

Article lu   fois.

Les deux auteurs

Site personnel

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Réintroduction

J'ai été pour le moins étonné par l'accueil qui a été réservé à mon article original (version traduite) sur la création d'applications compatibles Windows Vista avec Delphi. J'ai été très flatté d'être inclus dans la Delphi Hour (enregistrement disponible ici).

Le but de cet article est de fournir des informations supplémentaires et mises à jour quant à la création d'applications Delphi compatible Vista. Certains codes de l'article original présentent quelques problèmes que nous examinerons et règlerons, nous explorerons de nouveaux codes pour utiliser les polices, des codes nous permettant de tirer parti du nouveau style de TreeView de Vista, et plus encore.

Cet article suppose que vous avez lu le premier article ; les exemples de code se basent sur ceux développés dans ce dernier.

II. Réparation de polices

Mes remerciements à David Rose qui a aidé à trouver un problème dans SetVistaFont(). J'avais initialement l'impression que modifier Font.Name pour une police qui n'était pas installée laisserait Font.Name inchangée. Ce n'est pas le cas. Notre code original vérifiait Font.Name pour voir si Segoe UI était correctement appliquée à la police de la fiche, ce qui ne fonctionnait pas. Notre nouveau code teste Screen.Fonts pour vérifier que Segoe UI est une police installée.

SetVistaFonts()
Sélectionnez

procedure SetVistaFonts(const AForm: TCustomForm);
begin
  if (IsWindowsVista or not CheckOSVerForFonts)
    and not SameText(AForm.Font.Name, VistaFont)
    and (Screen.Fonts.IndexOf(VistaFont) >= 0) then
  begin
    AForm.Font.Size := AForm.Font.Size + 1;
    AForm.Font.Name := VistaFont;
  end;
end;

Le nouveau code introduit aussi la nouvelle variable globale CheckOSVerForFonts, qui détermine si les modifications de la police doivent prendre effet sous Vista uniquement, ou s'ils doivent aussi s'appliquer sous les autres OS. Le code original n'aurait posé de problèmes que dans le cas où Segoe UI n'aurait pas été installée sous Vista (peu problable), mais ce code est bien plus comple et correct.

III. Ajout pour les polices

Sur le CodeGear Developer Network, Daniel England a soulevé qu'il n'aimait pas que les noms des polices soient codés "en dur". Bien que j'approuve, mon intention était d'essayer de conserver la plupart de ces changements au fil du code, avec l'expérience "prêt à l'emploi" que l'on retrouve avec Delphi. Delphi, par défaut, n'ajuste pas la police de la fiche afin qu'elle corresponde à la police courante de Windows. S'il le faisait, nous n'aurions pas du tout à changer nos polices vers Segoe UI sous Vista.

Ceci étant dit, le premier ajout au code concernant les polices est la procédure SetDesktopIconFonts(). Cette procédure peut être appelée avec un TFont, et l'objet de police verra ses propriétés accordées aux paramètres courants de police des icônes du bureau Windows. Dans l'exemple mis à jour, cette méthode est employée plutôt que SetVistaFont().

SetDesktopIconFonts()
Sélectionnez

procedure SetDefaultFonts(const AFont: TFont);
begin
  AFont.Handle := GetStockObject(DEFAULT_GUI_FONT);
end;

procedure SetDesktopIconFonts(const AFont: TFont);
var
  LogFont: TLogFont;
begin
  if SystemParametersInfo(SPI_GETICONTITLELOGFONT, SizeOf(LogFont),
    @LogFont, 0) then
    AFont.Handle := CreateFontIndirect(LogFont)
  else
    SetDefaultFonts(AFont);
end;

Ce code tente de récupérer les paramètres de polices des icônes du bureau Windows actuel et, si cela échoue, se rabat sur les paramètres de police par défaut de Windows.

Notre second ajout au code concernant les polices est SetVistaContentFonts(). Cette procédure réalise la même opération que SetVistaFonts() mais seulement pour le contenu de composants tel que les TMemo, TRichEdit et autres du genre. Dans ce cas, la nouvelle police est, de facto, Calibri.

SetVistaContentFonts()
Sélectionnez

procedure SetVistaContentFonts(const AFont: TFont);
begin
  if (IsWindowsVista or not CheckOSVerForFonts)
    and not SameText(AFont.Name, VistaContentFont)
    and (Screen.Fonts.IndexOf(VistaContentFont) >= 0) then
  begin
    AFont.Size := AFont.Size + 2;
    AFont.Name := VistaContentFont;
  end;
end;

Un appel à cette nouvelle méthode avec un TFont pour paramètre impliquera le changement du nom de la police vers Calibri et l'augmentation de la taille de la police si l'application est exécutée sous Vista (ou si la variable globale CheckOSVerForFonts est égale à false).

IV. TreeView de style Vista

Le TreeView est un autre composant de l'interface graphique amélioré dans Windows Vista, et qui n'a pas été mentionné dans l'article original. Sous Windows Vista, les sélections dans le TreeView sont sous forme d'un dégradé bleu ciel plutôt que le traditionnel rectangle de sélection, et les boutons du TreeView sont de petits triangles plutôt que des signes "+".

Faire adopter ce nouveau style à nos objets TTreeView est relativement trivial, et le code se trouve dans l'exemple mis à jour dans la méthode SetVistaTreeView().

SetVistaTreeView()
Sélectionnez

procedure SetVistaTreeView(const AHandle: THandle);
begin
  if IsWindowsVista then
    SetWindowTheme(AHandle, 'explorer', nil);
end;

Appeler cette méthode avec le handle du TreeView donnera à ce dernier l'aspect du nouveau TreeView de Vista.

V. L'astuce de PopupParent

Notre article original introduisait un code pour passer outre la fenêtre d'application cachée de Delphi, permettant à plusieurs nouveaux éléments de l'interface utilisateur de Vista de fonctionner correctement, comme Flip 3D et les aperçus en temps réel. Cependant, ces modifications nous obligent à changer la propriété PopupParent avant chaque appel à ShowModal pour assurer un bon agencement en profondeur de nos fiches.

En correspondant avec Eric Fortier, j'ai poussé plus loin mes recherches et tenté de voir s'il était possible de supprimer cette nécessité. Bien que ce soit possible, cela requiert des modifications du code de la VCL (similaires à nos changements de Dialogs.pas dans l'article original).

  • Premièrement, faire une copie de Forms.pas et placer cette copie soit dans le répertoire des sources de votre application ou quelque part dans vos chemins de recherche
  • Deuxièmement, dans cette copie de Forms.pas, allez à la ligne 4032
  • Cherchez l'instruction case sur LPopupMode
  • Commentez la première ligne suivant l'instruction : //pmNone: Application.Handle;
  • Editez la seconde ligne, qui se déclenche pour la valeur pmAuto, afin qu'elle prenne également pmNone en compte : pmNone, pmAuto:
  • Sauvegardez vos modifications sur votre copie de Forms.pas

Cela devrait vous laisser avec une instruction case autour de la ligne 4032 qui inspecte LPopupMode et qui, maintenant, exécute la même action à la fois pour pmNone et pmAuto plutôt que d'utiliser Application.Handle comme parent lorsque PopupMode vaut pmNone. C'est justement ce que l'on veut. Maintenant, la VCL tentera de trouver notre fiche parente en détectant la fenêtre active avec un minimum de logique, plutôt que de simplement utiliser Application.Handle (ce qui ne fonctionne pas à cause de nos modifications du premier article) lorsque PopupMode est égal à pmNone.

VI. Activation étrange

Un des effets de bord du code présenté dans l'article original pour régler les problèmes d'animations et d'aperçus de fenêtres est qu'une fiche en-dessous d'une autre fiche modale peut devenir visuellement active si son bouton de barre des tâches est cliqué. Notez qu'il s'agit seulement d'une altération visuelle, vous ne pouvez pas réellement interagir avec un quelconque élément de la fiche. Max Pyatnitsky a soulevé ce problème sur les newsgroups CodeGear, et j'ai pensé partager une version légèrement modifiée de sa solution (elle est maintenant incluse dans l'exemple mis à jour et l'exécutable compilé):

 
Sélectionnez

procedure TMainForm.WMActivate(var Message: TWMActivate);
begin
  if (Message.Active = WA_ACTIVE) and not IsWindowEnabled(Handle) then
  begin
    SetActiveWindow(Application.Handle);
    Message.Result := 0;
  end else
    inherited;
end;

Merci à Max Pyatnitsky pour sa solution à ce problème. Ce code active la fiche cachée Application quand notre fiche est activée, assurant ainsi que toute fenêtre modale prenne le focus correctement.

VII. Enumérer des fenêtres

Il y a un autre avertissement pour les utilisateurs qui auraient implémenté le code pour contourner la fiche cachée Application de Delphi. Selon Tom Nagy sur les newsgroups CodeGear, les développeurs qui énumèrent les fenêtres en avant-plan avec EnumWindows() sont susceptibles d'utiliser un code tel que celui-ci comme code de la CallBack EnumWindowsProc :

EnumWindowsProc classique
Sélectionnez

if IsWindowVisible(Wnd) and 

  ((GetWindowLong(Wnd, GWL_HWNDPARENT) = 0) or
  (HWND(GetWindowLong(Wnd, GWL_HWNDPARENT)) = GetDesktopWindow)) and
  ((GetWindowLong(Wnd, GWL_EXSTYLE) and WS_EX_TOOLWINDOW) = 0) then
begin
  ...
end;

Selon Tom il s'agirait d'un morceau de code utilisé très couramment lors de l'énumération de fenêtres. Cependant, nos modifications du flag CreateParams de notre fiche causera l'échec de la vérification de WX_EX_TOOLWINDOW. Tom propose la modification de code suivante (retirer la vérification de WX_EX_TOOLWINDOW) pour régler le problème :

Solution de Tom Nagy
Sélectionnez

if IsWindowVisible(Wnd) and 

  ((GetWindowLong(Wnd, GWL_HWNDPARENT) = 0) or
  (HWND(GetWindowLong(Wnd, GWL_HWNDPARENT)) = GetDesktopWindow)) then
begin
  ...
end;

Merci à Tom Nagy pour avoir trouvé ceci et l'avoir indiqué sur les newsgroups. Espérons que cela en aidera d'autres à éviter un bug qui pourrait s'avérer compliqué à détecter !

VIII. Les raccourcis avec ALT cachent des composants

Il existe un autre bug présent dans les applications Delphi lorsqu'elles tournent sous Vista. Ce bug a été rapporté sur Quality Central et possède plusieurs solutions. Le problème est que, lorsque la touche ALT est appuyée, certains TWinControl peuvent disparaître de votre fenêtre jusqu'à ce que leur rafraichissement soit forcé. Il existe ici un composant qui règle ce problème. J'ai essayé les modifications de code dans Controls.pas présentées ici et pour ma part elles n'ont pas réglé le problème. Ceci dit le composant ci-dessus semble fonctionner correctement.

IX. Un Dialogue de Tâche multi-plateforme

L'article original introduisait le concept des Dialogues de Tâche dans Vista, et comment utiliser ces nouveaux styles de dialogues depuis vos applications Delphi. Bien que ces nouveaux Dialogues de Tâche soient un très bon ajout à Windows Vista, il n'est pas aisé de supporter à la fois les fonctionnalités des nouveaux Dialogues de Tâche et de revenir à d'autres dialogues supportés sous XP et plus récent.

Heureusement, les développeurs chez TMS ont fait le travail pour nous ! Se basant sur l'excellent travail qu'ils ont réalisé sur les Dialogues de Tâche de vista, ils ont publié un composant nommé TTaskDialog. Je ne veux pas faire de cet article une publicité cachée, mais étant donné que notre article original s'intéressait particulièrement aux Dialogues de Tâche (parmi les autres éléments de l'interface utilisateur), j'ai pensé que ce composant méritait d'être mentionné.

Le composant TTaskDialog reprend le travail que TMS a déjà réalisé en exposant toutes les fonctionnalités avancées que l'on retrouve dans l'API des Dialogues de Tâche, et apporte un support natif pour les précédent OS comme XP et plus récents. Cela signifie que les développeurs peuvent profiter des avantages de Dialogues de Tâche dès aujourd'hui et continuer à supporter les versions plus récentes de Windows.

X. Conclusion et problèmes en suspens

Tous ces changements rassemblés nous donnent une application dont le support de Windows Vista est amélioré par rapport à l'article original. Nos polices se comporteront maintenant comme elles le doivent lorsque Segoe UI n'est pas disponible, et peuvent éventuellement être modifiées pour s'adapter à la police des icônes du bureau Windows. Nos zones de contenu supportent maintenant un style de police plus récent, et le style de nos contrôles TreeView reprend celui des nouveaux éléments de l'interface utilisateur de Vista.

Application d'exemple mise à jour
Application d'exemple mise à jour

Téléchargez le code d'exemple mis à jour (miroir)
Téléchargez l'application finale (miroir)


Cependant, il reste un problème en suspens, et tout retour ou potentielle solution pour ce problème est le bienvenu (voir les contacts en début de page). Si vous combinez le code du premier article pour supporter les animations de réduction et de maximisation avec le code de cet article pour supporter les nouveaux éléments du TreeView, votre application possèdera un bug, léger mais détectable. Réduire une fenêtre aura pour effet de d'abord disparaître derrière tout fenêtre immédiatement en-dessous d'elle avant de procéder à l'animation vers la barre de tâches. Ce bug peut également être remarqué dans certaines applications Windows, il est donc difficile de dire ce qui pourrait en être la cause. Tout retour est le bienvenu, et l'auteur d'une solution sera cité.

Ci-dessous, vous trouverez une liste complétée de liens vers des articles et des tutoriels impliquant Windows Vista et interfaces utilisateur. Merci encore à tous pour vos retours et votre accueil fait à l'article original. J'espère que cette mise à jour sera d'une plus value intéressante.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2006 Olivier Lance. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.