Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1311 connectés 

  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  GDI - Texte transparent sur Form transparent

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

GDI - Texte transparent sur Form transparent

n°2018709
aspx
Posté le 24-08-2010 à 15:35:39  profilanswer
 

Bonjour,
 
Je suis sur un projet test qui m'affiche un Windows Form qui suit la souris. Le Form est constitué d'un PNG (type splashscreen) dont j'obtiens la transparence en retapant les fonctions natives Win32 GDI. Le truc c'est que j'aimerais afficher un texte transparent qui suit ce Form à l'aide de TextOut. J'ai essayé de spécifier en paramètre le HDC du Form courant mais cela n'affiche rien... J'arrive à afficher du texte sur le DC du screen cependant, mais il ne suit pas mon form du coup...
 
Pour ce qui est du code, tout se passe dans la méthode Form_Paint(object sender, PaintEventArgs e). Le HDC ici est nul, ce qui permet d'écrire sur le screen directement.
 

Code :
  1. IntPtr Hdc = API.GetDC(IntPtr.Zero);
  2. IntPtr memDc = API.CreateCompatibleDC(Hdc);
  3. IntPtr hBitmap = IntPtr.Zero;
  4. IntPtr oldBitmap = IntPtr.Zero;
  5. try
  6. {
  7.     //Display-image
  8.     Bitmap bmp = new Bitmap(backgroundImage);
  9.     hBitmap = bmp.GetHbitmap(Color.FromArgb(0));  //Set the fact that background is transparent
  10.     oldBitmap = API.SelectObject(memDc, hBitmap);
  11.    
  12.     //Display-rectangle
  13.     Size size = bmp.Size;
  14.     Point pointSource = new Point(0, 0);
  15.     Point topPos = new Point(this.Left, this.Top);
  16.     //Set up blending options
  17.     API.BLENDFUNCTION blend = new API.BLENDFUNCTION();
  18.     blend.BlendOp = API.AC_SRC_OVER;
  19.     blend.BlendFlags = 0;
  20.     blend.SourceConstantAlpha = alpha;
  21.     blend.AlphaFormat = API.AC_SRC_ALPHA;
  22.     API.SetBkMode(Hdc, API.MODE_TRANSPARENT);
  23.     API.TextOut(Hdc, this.Left, this.Top, text, text.Length);
  24.     API.UpdateLayeredWindow(this.Handle, Hdc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, API.ULW_ALPHA);
  25.     //Clean-up
  26.     bmp.Dispose();
  27.     API.ReleaseDC(IntPtr.Zero, Hdc);
  28.    
  29.     if (hBitmap != IntPtr.Zero)
  30.     {
  31.         API.SelectObject(memDc, oldBitmap);
  32.         API.DeleteObject(hBitmap);
  33.     }
  34.     API.DeleteDC(memDc);
  35. }
  36. catch (Exception)
  37. {
  38. }


 
Pour la classe API qui permet d'utiliser les fonctions natives :
 

Code :
  1. internal class API
  2.     {
  3.         public const byte AC_SRC_OVER = 0x00;
  4.         public const byte AC_SRC_ALPHA = 0x01;
  5.         public const Int32 ULW_ALPHA = 0x00000002;
  6.         [StructLayout(LayoutKind.Sequential, Pack = 1)]
  7.         public struct BLENDFUNCTION
  8.         {
  9.             public byte BlendOp;
  10.             public byte BlendFlags;
  11.             public byte SourceConstantAlpha;
  12.             public byte AlphaFormat;
  13.         }
  14.        
  15.         [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
  16.         public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);
  17.         [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
  18.         public static extern IntPtr GetDC(IntPtr hWnd);
  19.         [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
  20.         public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
  21.         [DllImport("user32.dll", ExactSpelling = true)]
  22.         public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
  23.         [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
  24.         public static extern bool DeleteDC(IntPtr hdc);
  25.         [DllImport("gdi32.dll", ExactSpelling = true)]
  26.         public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
  27.         [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
  28.         public static extern bool DeleteObject(IntPtr hObject);
  29.         [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
  30.         public static extern int TextOut(IntPtr hDC, int x, int y, string lpString, int nCount);
  31.         [DllImport("gdi32.dll" )]
  32.         public static extern int SetBkMode(IntPtr hdc, int mode);
  33.         // Background Modes
  34.         public const int MODE_TRANSPARENT = 1;
  35.         public const int MODE_OPAQUE = 2;
  36.     }


 
J'utilise cette méthode là car la transparence marche plutôt bien, j'aimerais juste pouvoir rajouter du texte à côté en plus. Si quelqu'un voit où est le pépin...
 
Merci d'avance!

mood
Publicité
Posté le 24-08-2010 à 15:35:39  profilanswer
 

n°2018784
tpierron
Posté le 24-08-2010 à 20:38:13  profilanswer
 

Mouais, c'est plus compliqué que ça. Le problème c'est que l'API TextOut ne sait pas gérer les bitmaps avec canal alpha. J'imagine que tu dessines ton texte dans une partie de l'image ou le canal alpha vaut 0 ou presque (ie: complètement transparent).
 
Ton texte est bien là, mais avec un canal alpha valant 0... donc invisible. Si tu utilisais le mode opaque pour dessiner le texte, tu verrais l'arrière plan entourant le texte transparent. Si tu tiens vraiment à utiliser GDI, va falloir sortir l'artillerie lourde : dessiner ton texte dans un bitmap offscreen, puis utiliser la fonction AlphaBlend pour combiner le tout (en calculant le canal alpha à la main et en faisant gaffe d'utiliser des bitmap pré-multipliés). Yäy, c'est le fun GDI!¡!
 
Sinon, en .net, il me semble que tu ais directement accès à GDI+, tu devrais regarder de ce coté, car cette lib supporte l'écriture de texte avec canal alpha, avec une API un peu moins pourrie que GDI.

n°2018909
aspx
Posté le 25-08-2010 à 12:34:43  profilanswer
 

Merci beaucoup pour ta réponse je vais voir ce que je peux faire!
 
Pour ce qui est de mon utilisation de GDI c'est juste que j'ai trouvé un projet sur le net qui utilise par interop les fonctions de gdi32.dll (splashscreen png transparent sans screenshot ou quoi). Je l'ai adapté à ma sauce du coup j'essaie d'afficher du texte en appelant pareil les fonctions de gdi.
 
Après si on peut faire ça simplement en gdi+ je suis preneur...

n°2019185
aspx
Posté le 26-08-2010 à 16:04:08  profilanswer
 

Je regarde depuis hier ce qu'il se dit sur le sujet sur le net et c'est pas très positif concernant GDI+ et la transparence... La plupart des projets qui permettent une transparence d'une winform avec un png dessus utilisent les fonctions natives GDI et c'est une sacré prise de tête...
 
J'ai du mal à croire que rien n'a été fait en C# pour permettre une bonne gestion de la transparence des PNG sur des form sans bordures (sans passer par des appels aux fonctions de gdi32.dll par ex)... Quelqu'un a des infos là dessus ?
 
Merci !

n°2019210
tpierron
Posté le 26-08-2010 à 17:47:50  profilanswer
 

Chuis pas sûr de ce que tu veux faire exactement. De ce que j'avais compris tu as un splash screen semi-transparent, tu voudrais coller du texte, genre version, build, etc ... sur une partie transparente. Normallement ça devrait fonctionner avec GDI+, par exemple un test vite fait à l'arrache :
 
http://www.izipik.com/images/201008/26/lgsmo4-layered-window-text-gdi_-alpha-channel.png
 
La fenêtre en question est celle contenant la tasse de café. Il y a une fenêtre explorer juste en dessous. Le texte "Hello world" à été rajouté avec GDI+, avec un code du style à appeler juste avant UpdateLayeredWindow() :
 

Code :
  1. HDC        hdc = (HDC)GFX_GetDevice((GC)gc);
  2. Graphics   graphics(hdc);
  3. FontFamily fontFamily(L"Arial" );
  4. Font       font(&fontFamily, 12, FontStyleRegular, UnitPixel);
  5. PointF     point(10, 10);
  6. SolidBrush brush(Color(0,0,0));
  7. WCHAR      str[] = L"Hello world !";
  8.  
  9. graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
  10. for (int i = 10; i < 100; i += 10)
  11. {
  12.     point.X = point.Y = i;
  13.     brush.SetColor(Color(255, i * 255 / 100, 0));
  14.     graphics.DrawString(str, -1, &font, point, &brush);
  15. }


 
Avec GDI, ton texte serait invisible sauf dans les parties ou le canal alpha > 0. C'est ce que tu voulais faire ?
 
Edit: c'est en C++, pas en .NET, mais l'API est très similaire.


Message édité par tpierron le 26-08-2010 à 17:48:38
n°2019342
aspx
Posté le 27-08-2010 à 12:24:21  profilanswer
 

Merci beaucoup pour ta réponse! En effet ça a l'air de bien marcher comme ça. J'ai récemment décidé de passer au WPF finalement et ça marche niquel. Je voulais utiliser le GDI/GDI+ pour rester en .NET 2.0 car je développe par dessus une appli 2.0 mais l'interop fonctionne à merveille donc aucun soucis !
 
Merci beaucoup!


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  GDI - Texte transparent sur Form transparent

 

Sujets relatifs
[Résolu] Div avec photo et texte pour index gallerieFormulaire et texte qui disparait
texte qui s'affiche au survol de la sourisremplir une base de donnée à l'aide d'un fichier texte
Ajouter du texte à un copié collé en JS ?[PERL?] interface texte avec gestion des touches directionnelles
[VB.net] Reload, refresh form après changement de la languerecherche texte dans .bat
Scinder un texte html sans casser les balises 
Plus de sujets relatifs à : GDI - Texte transparent sur Form transparent


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR