Soutien Delphi pour Aero Glass et la propriété DoubleBuffered-que se passe-t-il et comment les utiliser?

je suis confus par Delphi 2009/2010 soutien pour les caractéristiques de verre thème Aero dans les fenêtres, et par quoi, exactement DoubleBuffered signifie, Et ce qu'il a à voir avec le verre Aero. J'ai trouvé que DoubleBuffered n'est pas seulement une propriété dans la VCL, il se trouve aussi dans .net WinForms . Au départ, je me suis demandé s'il définissait une sorte de bit de style de fenêtre utilisé par la bibliothèque des contrôles communs, ou quoi. Pourquoi est-il utilisé, et quand doit-il être utilisé?

[Mise à jour: je devrais dire que je sais ce que "double-buffering" est, comme une technique générale pour la réduction de clignotant, ce que je me suis demandé est, pourquoi il a quoi que ce soit à voir avec les contrôles de rendu sur une vitre en verre Aero dans Windows Vista/Windows 7, et en particulier pourquoi un bouton de toutes les choses ont besoin d'avoir double-buffering mis vrai, pour travailler sur verre?. Le blog en lien ci-dessous semble plus instructif.]

en particulier, je suis confus par la propriété DoubleBuffered, et je veux savoir, pourquoi elle existe, et que sa relation entre le verre et le double tampon bien dans une forme et un contrôle sont définies. Quand vous lisez c++ articles comme celui-ci vous voyez qu'il n'y a aucune mention de double tampon.

[Update2: ce qui suit contenait certaines erreurs factuelles, et a été modifié:]

j'ai trouvé des développeurs C++ parlant de la façon dont ils peuvent appeler SetLayeredWindowAttributes pour éviter le bug" black becomes glass " que DWM/Aero compositing provoque lorsque vous l'activez dans votre application Win32 classique [cependant le lien de blog ci-dessous me dit que cela ne fonctionne plus dans Windows 7, et en fait seulement brièvement travaillé dans Vista, jusqu'à ce que Microsoft l'a bloqué]. Ne devrions-nous pas utiliser une autre couleur, comme le magenta brillant et le transformer en couleur de transparence du verre? [End WRONG Idea]

quelles sont les règles pour quand DoubleBuffered doit être mis et pas fixé, et pourquoi a été DoubleBuffered ajouté à la VCL en premier lieu? Quand il causer des problèmes lors de l'ensemble? (Il semble remote desktop est un cas, mais est-ce le seul cas?) et quand il n'est pas défini, nous obtenons glitched out rendu de texte de bouton, très probablement parce qu'il apparaît que Delphi ne change pas la valeur par défaut "render black as glass" dans L'Aero DWM.

il me semble que l'Aero Glass rendering se fait fondamentalement d'une manière étrange ou difficile à comprendre [par Windows lui-même, pas par Delphi, qui se contente d'envelopper cette fonctionnalité], et que beaucoup de code source VCL interne en 2009/2010 dans les classes de StdCtrls doit faire beaucoup de logique complexe pour rendre les choses correctement sur Aero Glass, et pourtant il a encore beaucoup de problèmes et me semble que c'est fait mal, et que cela pourrait être derrière cette question liée, et qc. [Update3: beaucoup de problèmes de rendu sur le verre, dans la VCL rendent fait mal à l'intérieur commun contrôle, ce qui semble, Microsoft ne se soucie pas de réparer. En bref, les correctifs de code Delphi VCL ne peuvent pas corriger le fait que L'ancienne bibliothèque de commandes communes de Windows et la fonction moderne [mais excentrique] de composition de verre Aero ne s'aiment pas beaucoup et ne fonctionnent pas particulièrement bien ensemble. Merci Microsoft pour avoir construit une telle technologie de haute qualité et de le libérer sur le monde.]

et si ce n'était pas encore assez amusant; pourquoi avons-nous Parentdoublé?

[mise à Jour le 30 juillet: Cette question est intéressant pour moi parce que je pense que cela montre que le travail sur l'API Windows pour résoudre ce problème, lorsque vous avez un grand existants VCL cadre, est un dur de dur de problème.]

25
demandé sur Community 2010-07-29 00:29:45

4 réponses

À Propos De DoubleBuffer

.NET peut en avoir un, et il peut avoir le même nom et le même but que celui de Delphi, mais Delphi implémente DoubleBuffer à partir de ground-up et je suppose .NET fait la même chose. Aucun bits de style de fenêtre n'est utilisé pour implémenter ceci.

DoubleBuffer et Verre Aero

assez simple: ne pas placer DoubleBuffer pour les contrôles qui sont assis sur le verre. Pour que le DoubleBuffering fonctionne il faut être capable d'initialiser le "tampon" - mais avec quoi l'initialiser pour le verre? Le DoubleBuffering n'est pas requis pour les commandes standard de Windows (y compris TButton). Pour les nouveaux contrôles qui nécessitent à la fois des surfaces transparentes et un comportement de type doublebuffer, on peut utiliser l'api fenêtres en couches.

l'Obtention de commandes pour travailler sur Verre

Étape 1:

TForm1 = class(TForm)
...
protected
  procedure CreateWindowHandle(const Params: TCreateParams); override;
...
end;

procedure TForm15.CreateWindowHandle(const Params: TCreateParams);
begin
  inherited;
  SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED);
  SetLayeredWindowAttributes(Handle, RGB(60, 60, 60), 0, LWA_COLORKEY);
end;

Étape 2 , ceci doit être votre formulaire OnPaint handler:

procedure TForm15.FormPaint(Sender: TObject);
var rClientRect:TRect;
begin
  if GlassFrame.Enabled then
  begin
    rClientRect := ClientRect;

    Canvas.Brush.Color := RGB(60, 60, 60);
    Canvas.Brush.Style := bsSolid;
    Canvas.FillRect(rClientRect);

    if not GlassFrame.SheetOfGlass then
    begin
      rClientRect.Top := rClientRect.Top + GlassFrame.Top;
      rClientRect.Left := rClientRect.Left + GlassFrame.Left;
      rClientRect.Right := rClientRect.Right - GlassFrame.Right;
      rClientRect.Bottom := rClientRect.Bottom - GlassFrame.Bottom;
      Canvas.Brush.Color := clBtnFace;
      Canvas.FillRect(rClientRect);
    end;
  end;
end;

Step 3 : Set GlassFrame.Enabled = True; définissez toutes les autres propriétés du verre, ajoutez des commandes à la forme, où que vous les aimiez. Peut-être sur du verre ou n'importe où ailleurs. Assurez-vous que les contrôles n'ont pas "DoubleBuffered = True". C'est, en profiter. J'ai testé avec TButton, TCkBox et TEdit.

... MODIFIER. ..

malheureusement en utilisant cette méthode "verre" est traité comme un 100% surface transparente, et ce n'est pas - on dirait du verre, mais ça ne se comporte pas comme du verre. Le problème avec 100% de transparence est, si vous cliquez sur cette zone transparente, votre cliquez va à la fenêtre derrière votre fenêtre. Horrible.

au moment de cet écrit, je suis assez sûr qu'il n'y a pas D'API pour changer la couleur de la clé noire par défaut pour le verre d'origine (google trouve d'innombrables billets de blog et forum sur la façon dont vous avez besoin d'utiliser le dessin personnalisé pour les contrôles qui sont assis sur le verre et il n'y a aucune fonction pour changer cela dans la liste des fonctions DWM sur MSDN ). Sans changer la couleur Noire par défaut la plupart des contrôles ne peuvent pas rendre correctement parce qu'ils écrivent le texte en utilisant clWindowText et c'est noir. Un truc suggéré trouvé sur plusieurs forums est de changer la couleur de transparence en utilisant L'API SetLayeredWindowAttributes. Et ça marche!!! Une fois que c'est fait le texte noir sur les contrôles montre jeter, mais malheureusement le verre n'est plus le verre, le verre ressemble au verre mais se comporte comme une transparence à 100%. Cela invalide assez fortement cette solution et montre un double standard du côté de Microsoft: le noir original ne se comporte pas comme une transparence de 100% mais si nous le changeons en quelque chose de mieux il se comporte comme une transparence de 100%.

à mon avis, l'idée courante d'utiliser des commandes sur mesure sur verre est erronée. C'est la seule chose qui pourrait marcher, mais c'est mal, parce que nous sommes censés utiliser des contrôles qui sont cohérents à travers le plate-forme: proposer des contrôles personnalisés ouvre la porte à des applications incohérentes, de type winamp, où chaque utilisateur crée à nouveau la roue en fonction de ses idées artistiques. Même si un développeur réussit à recréer fidèlement n'importe quel contrôle de fenêtres donné et le faire fonctionner sur le verre, le "correctif" est seulement temporaire et doit être recréé pour la prochaine version de fenêtres. Pour ne pas mentionner un devrait probablement avoir plusieurs variantes pour les versions existantes de windows.

l'autre solution est pour utiliser des fenêtres en couches avec UpdateLayeredWindow. Mais C'est une douleur pour tellement de raisons.

C'est une impasse pour moi. Mais je vais donner à la question un drapeau "préféré", si quelque chose de mieux se présente, j'aimerais le savoir.

15
répondu Cosmin Prund 2010-07-30 06:43:02

votre question a suscité un billet de blog de CR sur Delphi Haven ...

en regardant le débordement de la pile, j'ai juste j'ai remarqué une question assez détaillée (vraiment, un ensemble de questions) sur Aero verre.

7
répondu Roddy 2010-07-29 10:49:00

DoubleBuffered est un technique graphique standard utilisé pour réduire le scintillement. Fondamentalement, vous dessinez une nouvelle version de votre forme sur une deuxième toile puis de le remplacer par l'actuel. Ce swap est rapide, même si le processus de dessin est lent. Il n'y a pas de relation directe entre cela et L'Aéro - vous pouvez utiliser l'un ou l'autre ou les deux indépendamment. Le double buffering existe depuis très longtemps à Delphi, mais nous avons maintenant beaucoup plus de cycles de processeur par rafraîchissement de l'écran. de moins en moins nécessaire. Qui peut être pourquoi vous n'avez pas entendu parler de lui.

double buffering est quelque chose que vous ne devez utiliser que de manière réactive - si vous voyez flicker lorsque votre application repeint l'écran l'allumer et voir ce qui se passe. Dans ce cas, votre premier recours serait de désactiver les mises à jour/EnableUpdates (voir L'aide Delphi pour celles-ci) et la LockWindowUpdate (idem) de L'API Windows.

Parent DoubleBuffered, like most Parent... propriétés, Vous dit si cela form utilisera la propriété DoubleBuffered de son parent. Cela vous permet de définir la propriété une fois sur votre formulaire principal d'application et l'avoir affecter chaque formulaire que vous créez. Ou pas, si vous mettez cette propriété à false.

c'est une situation typique quand vous avez du code rétrocompatible - il y a des choses là-dedans qui sont rarement utilisées aujourd'hui mais qui fonctionnent encore (et sont parfois encore nécessaires), même si la plupart des gens n'ont jamais besoin de s'inquiéter à leur sujet. Pour la plupart des gens, ils sont juste là et vous pouvez les ignorer, mais pour certains d'entre nous ils sont désespérément nécessaires (nous avons un couple de formes vraiment, vraiment complexes que nous redessinons dans des modèles parfois complexes pour arrêter le scintillement)

3
répondu 2010-07-29 06:08:32

OK, je vais essayer de redresser un peu.

tout d'abord, le double buffering est une technique très standard en matière de rendu à l'écran. Je l'utilise tout le temps, par exemple, dans mon éditeur de texte composant. Imaginez le texte doit être redessiné. Très simplement dit, j'efface d'abord tout le rect client, plus ou moins par FillRect(ClientRect) , puis je dessine les lignes, du premier au dernier visible, chacune du premier caractère au dernier visible. Mais ce aura l'air très laid à l'utilisateur final, ayant quelques millisecondes ou plus avec un affichage clair, entre deux états de presque le même contenu textuel.

la solution, est de faire tout le dessin à un hors-écran bitmap, et tout simplement tirer le hors-écran bitmap sur l'écran quand il est complet. Puis, si le préveous et le nouveau cadre sont identiques, il ne se passera rien avec l'affichage, en contraste avec le cas non-double-tamponné, où l'écran affichera un rectangle blanc vide pendant quelques millisecondes, c'est-à-dire que l'écran clignotera. J'utilise toujours le double-buffering pour tous mes contrôles visuels, et cela améliore vraiment la qualité et la sensation d'eux, énormément. Sur un système moderne avec des gigaoctets de mémoire (RAM), l'utilisation accrue de la mémoire n'est en aucun cas un problème. Et dans presque tous les cas, l'échange des tampons est assez rapide (bien qu'il y ait assez de pixels à copier).

souvent, vous pouvez observer l'absence de double-buffering lors du redimensionnement des fenêtres. Parfois, ils clignotent comme h**L. Il pourrait également être intéressant de noter que les technologies telles que L'OpenGL sont essentiellement à double tampon (dans la plupart des cas, au moins).

donc le double Tamponnage n'a rien à voir avec les feuilles de verre. En fait, la plupart des décendants du Delphi TWinControl a les DoubleBuffered et ParentDoubleBuffered propriétés ( référence ).

le bien ParentDoubleBuffered est affecté à DoubleBuffered de la même manière que ParentColor est lié à Color , ParentShowHint à ShowHint , ParentFont à Font , etc. Il décide simplement si le contrôle hérite ou non de la valeur du paramètre de sa fenêtre mère.

maintenant à la question sur le verre. Eh bien, il est de notoriété publique qu'il est en général maladroit d'ajouter des contrôles à un feuille de verre (ou cadre de verre), au moins dans une application VCL. Quelqu'un devrait écrire un long article de blog discuter de la façon de faire correctement...

1
répondu Andreas Rejbrand 2010-07-29 12:22:04