ThWilliam
Messages postés418Date d'inscriptionmardi 3 janvier 2006StatutMembreDernière intervention26 novembre 2013
-
20 oct. 2009 à 11:37
Bacterius
Messages postés3792Date d'inscriptionsamedi 22 décembre 2007StatutMembreDernière intervention 3 juin 2016
-
22 oct. 2009 à 06:27
Bonjour à tous.
J'écris un composant transparent dérivé de TCustomControl.
Je ne peux pas le dériver de TGraphicControl, car j'ai besoin d'un contrôle fenêtré.
Cela marche bien, mais j'ai quelques questions :
* si je dessine sur le Canvas en mode Brush.Style = bsClear (par exemple, un texte), j'ai parfois besoin d'effacer le Canvas avant de redessiner. Pour cela, je n'ai trouvé que la méthode RecreateWnd. Est-ce la bonne solution ou qu'ajouter dans WMEraseBkng ?
* Si, à l'exécution, on change la taille du compo, pas de problèmes, il se redessine parfaitement en transparence. Par contre, changer sa position (left, top) exige de faire un RecreateWnd (?).
* le problème de RecreateWnd est qu'il appelle la procedure Paint. Donc impossible à placer dans, p.ex, un événement OnPaint. J'ai essayé en implémentant des procédures BeginUpdate, EndUpdate pour bloquer l'exécution du code dans Paint. Mais impossible de bloquer. Donc évidemment, l'événement OnPaint est rappelé sans arrêt. J'ai trouvé la solution avec un autre événement appelé avant OnPaint. Mais ne trouve pas cela très joli joli.
Ci-dessous la partie du code qui concerne la transparence.
procedure TMyControl.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
if FTransparent then
Params.ExStyle := params.ExStyle or WS_EX_TRANSPARENT;
// apparemment la ligne suivante n'est pas nécessaire
//ControlStyle := ControlStyle - [csOpaque];
end;
procedure TMyControl.CreateWnd;
begin
inherited CreateWnd;
if FTransparent then
begin
SetWindowLong(Parent.Handle, GWL_STYLE,
GetWindowLong(Parent.Handle, GWL_STYLE) and not WS_CLIPCHILDREN);
end;
end;
procedure TMyControl.WMEraseBkng(var msg :TWMEraseBkgnd);
begin
if FTransparent then Msg.Result:= 1 // pas d'effacement
else inherited;
end;
procedure TMyControl.SetTransparent(ATransparent: boolean);
begin
if FTransparent <> ATransparent then
begin
FTransparent:= ATransparent;
Redraw;
end;
end;
procedure TMyControl.SetCaption(ACaption: string);
begin
if FCaption <> ACaption then
begin
FCaption:= ACaption;
ReDraw;
end;
end;
procedure TMyControl.ReDraw;
begin
RecreateWnd;
end;
Guillemouze
Messages postés991Date d'inscriptionsamedi 25 octobre 2003StatutMembreDernière intervention29 août 20136 20 oct. 2009 à 14:01
@cirec: hmmmmmm en es tu sûr ? il me semble que bsClear signifie que la brush est transparente, donc ne dessine rien (laisse ce qu'il y a derriere et ne redessine pas ce qui devrait theoriquement se trouver derriere). Par exemple, si tu dessine un rect bleu en bsSolid, et que tu redessine un rect bsClear par dessus, il ne va pas remplacer ton rect bleu par l'arriere plan!
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 202250 20 oct. 2009 à 14:53
ha ha ha
vielles croyances qui ont la vie dure ...
j'étais persuadé d'effacer l'avant plan avec ça ...
mais après investigations ... vous avez raison ... ça ne fonctionne pas
bon de toute manière c'était pas ce qu'il demandait ... pour effacer/restituer l'arrière plan tu peux essayer ceci:
la PaintBox représente ton composant transparent
et Handle le composant parent (pour moi le Handle de la fiche).
var aRect: TRect;
begin
aRect := PaintBox1.BoundsRect;
InvalidateRect(Handle, @aRect, true);
end;
ThWilliam
Messages postés418Date d'inscriptionmardi 3 janvier 2006StatutMembreDernière intervention26 novembre 20134 20 oct. 2009 à 19:20
Re-bonjour Cirec, et re-merci.
InvalidateRect ne marche pas non plus.
Tu me donnes un exemple avec un PaintBox qui est dérivé de TGraphicControl : dans ce cas, il n'y aucun problème pour la transparence. Mais avec un contrôle fenêtré (<- TWinControl), la transparence gérée par Windows me semble très nébuleuse !!!
Je place sur une Form un TImage avec bitmap.
Je place le composant transparent au-dessus de l'image.
Tout marche bien.
Si, en mode exécution, je déplace le composant (MyCompo.Left:= 500), le composant se déplace en gardant en background la portion du bitmap de l'emplacement d'origine ! Il faut donc recréer les paramètres : RecreateWnd fait appel à CreateParams et à CreateWnd. Sacrée façon de gérer la transparence !
D'où ma question: existe-t-il une autre manière de faire que RecreateWnd ?
Bacterius
Messages postés3792Date d'inscriptionsamedi 22 décembre 2007StatutMembreDernière intervention 3 juin 201610 21 oct. 2009 à 10:30
Il existe un moyen, j'y suis parvenu sur un CustomControl sans appels d'API. Il faut que je retrouve ... 1 seconde ...
Dans le Paint (override) du contrôle :
try
C.Control := self;
if not FUpdating then // Dessin (le controlcanvas contient l'image qui se trouve "derrière" le contrôle avant dessin).
finally
C.Free;
end;
Il me semble que ça marche comme ça (chez moi en tout cas sous Delphi 6 perso)
ThWilliam
Messages postés418Date d'inscriptionmardi 3 janvier 2006StatutMembreDernière intervention26 novembre 20134 21 oct. 2009 à 12:51
Merci Bacterius.
Mais créer un nouveau TControlCanvas (nouveau pcq TCustomControl a le sien), n'arrange rien (ou alors j'ai mal compris ta façon de faire).
Bacterius
Messages postés3792Date d'inscriptionsamedi 22 décembre 2007StatutMembreDernière intervention 3 juin 201610 22 oct. 2009 à 06:27
Aaah désolé moi je dérivais un TButtonControl (pour un bouton), désolé ... mais je suis sûr qu'il existe un moyen, j'y suis déjà parvenu mais à chaque fois en tâtonnant ... faudrait que je retrouve la méthode.