Les boutons Delphi montrent une bordure blanche sur du verre Aero
j'ai essayé de trouver un beau design en utilisant Aero dans Delphi 2010. Une des utilisations évidentes que l'on voit, est où le cadre de verre est étendu pour inclure les boutons OK/Cancel au bas de l'écran. Je remarque cependant que cela ne semble pas tout à fait juste dans Delphi 2010 - il ya une frontière blanche tout autour de chaque bouton.
cette image affiche le problème: les 3 premiers boutons sont de mon application, les deux derniers ont été pris de Paint.NET propriétés de la couche dialogue.
frontières blanches autour des contrôles Delphes http://i30.tinypic.com/1zzqfm0.png
j'ai essayé diverses combinaisons de DoubleBuffered et quelques combinaisons de placer les commandes sur d'autres commandes d'abord, mais le problème reste. Des idées?
4 réponses
si personne n'a de solution propre, comme solution de contournement, utilisez TBitBtn
avec DoubleBuffered = false
.
Il semble que la seule solution est le propriétaire du tirage, ou d'un tiers d'un bouton de contrôle Vérifier le Bouton de Verre par Roy Klever ou, comme l'indique le QC entrée en lien ci-dessous, TBitBtn avec DoubleBuffered=false, ce qui a été la réponse ci-dessus à cette question.
il s'agit d'un bug dans Windows Aero DWM ou bien d'un bug dans les contrôles communs de windows, ou bien d'un bug dans la façon dont la classe VCL hierachy gère les messages communs de fenêtre de contrôle et la peinture lors de la peinture sur verre. En bref, fenêtres contrôles communs ne se peignent pas correctement sur le verre, ou plutôt la composition DWM (Aero) est cassé. Surprise surprise.
le composant standard du bouton VCL utilise le bouton Window Class de Windows Common Controls.
notez que TSpeedButton n'utilise pas le contrôle commun à windows, et n'a pas ce problème. cependant, il n'accepte pas le focus.
il apparaît Amarcadero est au courant de ce problème, c'est QC # 75246 , qui est fermé parce que c'est vraiment un bug dans la bibliothèque des contrôles communs, comme ne sera pas corriger, avec la suggestion d'utiliser TBitBtn. Les boutons ne sont pas seuls, Cela fait partie d'un groupe de rapports de CQ incluant des panneaux et d'autres contrôles communs.
cependant j'ai un TcxButton commercial (qui fait partie de developer express components) qui accepte la mise au point du clavier, et ne dessine pas ce bug. Tout code qui utilise le bouton Win32 common control semble avoir ce problème. Il est possible qu'un hacker de L'API Win32 de bas niveau puisse trouver une solution. Je suis à la recherche en elle. Cette réponse sera mise à jour si je la trouve.
un détail intéressant: TcxButton a trois styles de dessin, cxButton.LookAndFeel.Kind = {lfOffice11,lfFlat, lfStandard}. En sélectionnant lfOffice11, vous ajoutez ce bug. Il ressemble à une interaction étrange entre la fonction de verre dans aero in Vista / Win7 et le code de dessin du bouton common control/xptheme.
il se peut que la seule solution soit d'utiliser une commande de bouton complètement app-drawn et de ne pas utiliser les boutons Windows common controls, ou n'importe quelle commande de bouton qui s'appuie sur le moteur de thème XP pour tirer des boutons, sur une vitre aero.
Edit: 28 juillet, quelqu'un à L'Embarcadero a fermé l'entrée QC ci-dessus, qui était une erreur. Je leur demande instamment de la rouvrir, ne serait-ce que pour préciser si cette est en effet un bug Windows dans la dll commune des contrôles.
si vous voulez jouer, Faites une copie du code source VCL pour les classes TButton et TCustomButton de StdCtrls, comme je l'ai fait ici, modifiez CNCtlColorBtn, de sorte que vous forcez l'une des trois choses à se produire - PerformEraseBackground, DrawParentBackground ou hered, et voyez les résultats. Des choses intéressantes.
procedure TCustomGlassButton.CNCtlColorBtn(var Message: TWMCtlColorBtn);
begin
PerformEraseBackground(Self, Message.ChildDC);
Message.Result := GetStockObject(NULL_BRUSH);
(*
with ThemeServices do
if ThemesEnabled then
begin
if (Parent <> nil) and Parent.DoubleBuffered then
PerformEraseBackground(Self, Message.ChildDC)
else
DrawParentBackground(Handle, Message.ChildDC, nil, False);
{ Return an empty brush to prevent Windows from overpainting we just have created. }
Message.Result := GetStockObject(NULL_BRUSH);
end
else
inherited;
*)
end;
une lecture intéressante sur L'ère Vista glass / DWM / aero APIs (blog des développeurs c++)
ici je fournis un code qui fait que TButton regarde droit sur le verre. Malheureusement, il fait le formulaire "click-throw", donc je ne pense pas que ce soit une bonne idée. Mais peut-être vous pouvez trouver un moyen de fixer la forme du "sur-jeter".
si vous êtes capable d'utiliser l'api win32, essayez d'exploiter NM_CUSTOMDRAW notification (pas ownerdraw), comme je le fais (Oui, les boutons ne l'envoient, y compris la radio et les cases à cocher. Pour ceux-ci, il est cependant préférable d'utiliser WM_CTLCOLORSTATIC.). C'est comment il est fait en C++, mais l'idée est la même. Alors que mon idée est bonne, il se trouve que mes boutons disparaissent une fois par exécution de programme de la fenêtre, quand ils sont customdrawn et j'ai besoin de passer la souris au-dessus d'eux pour qu'ils soient à nouveau visibles. C'est pourquoi je suis toujours à la recherche de commentaires pour cet. Notez qu'il est très difficile de reproduire les boutons qui disparaissent dans les applications à une seule forme. Je hovewer suis confronté à ce comportement dans chaque projet.
case WM_NOTIFY:
switch(((LPNMHDR)lParam)->code){
case NM_CUSTOMDRAW:
{
NMHDR *nmh=(NMHDR*)lParam;
//these 6000 through 6004 are button identifiers assigned by me
if(nmh->idFrom >= 6000 && nmh->idFrom <= 6004){
switch(((LPNMCUSTOMDRAW)nmh)->dwDrawStage){
case CDDS_PREERASE:
//BackgroundBrush is a HBRUSH used also as window background
FillRect(((LPNMCUSTOMDRAW)nmh)->hdc, &((LPNMCUSTOMDRAW)nmh)->rc, BackgroundBrush);
break;
}
}
break;
}
break;