It is currently Tue Jun 18, 2013 7:26 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: [SOLVED] DrawText() & TextOut() WinAPI on Layered Window
PostPosted: Tue May 08, 2012 2:22 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat Feb 19, 2011 3:47 am
Posts: 410
[This issue has been solved by PureBasic expert Danilo] (linked)

Image

In the following code, which creates a layered window, I'm able to draw text on it using PureBasic's DrawText() function, but get this cut-out effect (illustrated above) if the WinAPI DrawText() or TextOut() functions are used.

Does anyone know what causes this behaviour?

NOTE: You'll need a PNG image to test this code (or just download this one):
Code:
; modified from original code by Le Soldat Inconnu - Thank You!
; http://forum.purebasic.com/english/viewtopic.php?f=12&t=39079&hilit=transparency

UsePNGImageDecoder()

Enumeration
  #MainWindow
  #imageFile
EndEnumeration

Global.l appQuit

Procedure WndProc(hWnd, uMsg, wParam, lParam)
  Shared sysProc
  result = CallWindowProc_(sysProc, hWnd, uMsg, wParam, lParam) 
  Select uMsg
    Case #WM_NCHITTEST
      SendMessage_(hWnd, #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
    Case #WM_LBUTTONDOWN
      If WindowMouseX(#MainWindow)>0 And WindowMouseX(#MainWindow)<60
        If WindowMouseY(#MainWindow)>0 And WindowMouseY(#MainWindow)<60
          appQuit = 1
          ProcedureReturn 0
        EndIf
      EndIf     
  EndSelect
  ProcedureReturn result
EndProcedure

Procedure AlphaImageWindow(WindowID, ImageID, Alpha)
  Protected Image_HDC, Image_Bitmap.BITMAP, Image_BitmapInfo.BITMAPINFO, ContextOffset.POINT, Blend.BLENDFUNCTION
  Protected xx, yy, x, y, Rouge, Vert, Bleu, AlphaChannel
  Protected Dim Echelle.f($FF)
  For x = 0 To $FF
    Echelle(x) = x / $FF
  Next
   
  Image_HDC = CreateCompatibleDC_(#Null)
  Image_Ancienne = SelectObject_(Image_HDC, ImageID)
   
  GetObject_(ImageID, SizeOf(BITMAP), @Image_Bitmap)
  Image_BitmapInfo\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  Image_BitmapInfo\bmiHeader\biWidth = Image_Bitmap\bmWidth
  Image_BitmapInfo\bmiHeader\biHeight = Image_Bitmap\bmHeight
  Image_BitmapInfo\bmiHeader\biPlanes = 1
  Image_BitmapInfo\bmiHeader\biBitCount = 32
   
  xx = Image_Bitmap\bmWidth - 1
  yy = Image_Bitmap\bmHeight - 1
  Protected Dim Image.l(xx, yy)
   
  GetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
   
  For x = 0 To xx
    For y = 0 To yy
      Couleur = Image(x, y)
      AlphaChannel = Couleur >> 24 & $FF
      If AlphaChannel < $FF
        Rouge = (Couleur & $FF) * Echelle(AlphaChannel)
        Vert = (Couleur >> 8 & $FF) * Echelle(AlphaChannel)
        Bleu = (Couleur >> 16 & $FF) * Echelle(AlphaChannel)
        Image(x, y) = Rouge | Vert << 8 | Bleu << 16 | AlphaChannel << 24
      EndIf
    Next
  Next
   
  SetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
   
  Blend\AlphaFormat = 1
  Blend\BlendOp = 0
  Blend\BlendFlags = 0
  Blend\SourceConstantAlpha = Alpha
  UpdateLayeredWindow_(WindowID, 0, 0, @Image_BitmapInfo + 4, Image_HDC, @ContextOffset, 0, @Blend, 2)
     
  SelectObject_(Image_HDC, Image_Ancienne)
  DeleteDC_(Image_HDC)
EndProcedure

Define imageFile.s = OpenFileRequester("Select Image:", "", "PNG|*.png", 0)
If imageFile And LoadImage(#imageFile, imageFile)
  wFlags = #PB_Window_BorderLess | #PB_Window_ScreenCentered | #PB_Window_Invisible
  OpenWindow(#MainWindow, #PB_Any, #PB_Any, ImageWidth(#imageFile), ImageHeight(#imageFile), "Layered Window", wFlags)
  sysProc = SetWindowLong_(WindowID(#MainWindow), #GWL_WNDPROC, @WndProc())
  SetWindowLong_(WindowID(#MainWindow), #GWL_EXSTYLE, GetWindowLong_(WindowID(#MainWindow), #GWL_EXSTYLE) | #WS_EX_LAYERED)
  HideWindow(#MainWindow, 0)
 
  ;PureBasic drawing
  ;==============
  LoadFont(1, "Arial", 20, #PB_Font_Bold)
  StartDrawing(ImageOutput(#imageFile))
  DrawingFont(FontID(1))
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawText(50, 130, "SOLID TEXT...", #Red)
  StopDrawing()
 
  ;Windows drawing
  ;=============
  ddc = StartDrawing(ImageOutput(#imageFile))
    SelectObject_(ddc, FontID(1))
    SetBkMode_(ddc, #TRANSPARENT)
    SetTextColor_(ddc, $FFFF)
    TextOut_(ddc, 50, 180, "CUT-OUT TEXT!", 13)
  StopDrawing()
   
  AlphaImageWindow(WindowID(#MainWindow), ImageID(#imageFile), 255)   

  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        appQuit = 1
    EndSelect
  Until appQuit = 1
EndIf
End

_________________
Texas Instruments 99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too!


Last edited by TI-994A on Thu May 10, 2012 5:29 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: DrawText() & TextOut() WinAPI on Layered Window
PostPosted: Wed May 09, 2012 8:45 am 
Offline
Addict
Addict
User avatar

Joined: Thu Feb 09, 2006 11:27 pm
Posts: 1720
Maybe you need something like this...

NOTE: You'll don't need a PNG image to test this code :lol:

Code:

#size=640

OpenWindow(0,0,0,#size,#size,"Text out",#PB_Window_ScreenCentered)

LoadFont(0,"Calibri",-160,#PB_Font_Bold)

CreateImage(1,#size,#size,32|#PB_Image_Transparent)
StartDrawing(ImageOutput(1))
DrawingMode(#PB_2DDrawing_AllChannels)
Box(100,100,480,320,#Blue|$FF000000)
DrawingMode(#PB_2DDrawing_AlphaChannel)
DrawingFont(FontID(0))
DrawText(130,180,"PURE",0)
StopDrawing()


CreateImage(0,#size,#size,32)
StartDrawing(ImageOutput(0))
For i=0 To 999
   Circle(Random(#size),Random(#size),Random(20)+20,Random(#White))
Next i
DrawAlphaImage(ImageID(1),0,0)
StopDrawing()


ImageGadget(0,0,0,#size,#size,ImageID(0))

Repeat
   Select WaitWindowEvent()
   Case #PB_Event_CloseWindow,#WM_CHAR
      Break
   EndSelect
ForEver



Top
 Profile  
 
 Post subject: Re: DrawText() & TextOut() WinAPI on Layered Window
PostPosted: Wed May 09, 2012 11:25 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat Feb 19, 2011 3:47 am
Posts: 410
Hi Michael Vogel. Thanks for your reply, and for the great example; really good illustration for DrawAlphaImage().

But actually, I wasn't trying to reproduce the effect, but rather figure out why it was happening. When we draw on a PNG image with PureBasic's DrawText(), it comes out fine; but if we use Windows DrawText() API, it doesn't draw the text, but instead cuts out transparent regions of the text.

Originally, I thought that it had something to do with layered windows; but in fact, we get the same effect on any PNG image. Here's a small snippet to demonstrate this:
Code:
UsePNGImageDecoder()
InitNetwork()

Enumeration
  #MainWindow
  #ImageGadget
  #imageFile
  #drawFont
EndEnumeration

If ReceiveHTTPFile("http://images1.wikia.nocookie.net/__cb20120202174654/central/images/7/71/Tv_series.png", GetTemporaryDirectory() + "image.png")
  LoadImage(#imageFile, GetTemporaryDirectory() + "image.png")
  wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
  OpenWindow(#MainWindow, #PB_Any, #PB_Any, ImageWidth(#imageFile), ImageHeight(#imageFile), "Why does this happen?", wFlags)
  SetWindowColor(#MainWindow, #Magenta)
 
  LoadFont(#drawFont, "Arial", 20, #PB_Font_Bold)
  StartDrawing(ImageOutput(#imageFile))
    DrawingFont(FontID(#drawFont))
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawText(30, 180, "TEXT IS SOLID", #Red)
  StopDrawing()
 
  ddc = StartDrawing(ImageOutput(#imageFile))
    SelectObject_(ddc, FontID(#drawFont))
    SetBkMode_(ddc, #TRANSPARENT)
    SetTextColor_(ddc, $0)   ;<<<====== text should be black
    TextOut_(ddc, 30, 120, "TEXT IS CUT OUT!", 16)
  StopDrawing()
   
  ImageGadget(#ImageGadget, 0, 0, ImageWidth(#imageFile), ImageHeight(#imageFile), ImageID(#imageFile))

  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        appQuit = 1
    EndSelect
  Until appQuit = 1
 
EndIf

End

Any idea why this happens?

_________________
Texas Instruments 99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too!


Top
 Profile  
 
 Post subject: Re: DrawText() & TextOut() WinAPI on Layered Window
PostPosted: Wed May 09, 2012 11:45 am 
Offline
Addict
Addict
User avatar

Joined: Sat Apr 26, 2003 8:26 am
Posts: 1291
The API functions draw the text, but they set the alpha channel of 32bit images to 0, so it looks transparent.

Just set the alpha channel again after using the API functions.
Code:
UsePNGImageDecoder()
InitNetwork()

Enumeration
  #MainWindow
  #ImageGadget
  #imageFile
  #drawFont
EndEnumeration

If ReceiveHTTPFile("http://images1.wikia.nocookie.net/__cb20120202174654/central/images/7/71/Tv_series.png", GetTemporaryDirectory() + "image.png")
  LoadImage(#imageFile, GetTemporaryDirectory() + "image.png")
  wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
  OpenWindow(#MainWindow, #PB_Any, #PB_Any, ImageWidth(#imageFile), ImageHeight(#imageFile), "Why does this happen?", wFlags)
  SetWindowColor(#MainWindow, #Magenta)
  LoadFont(#drawFont, "Arial", 20, #PB_Font_Bold)
  StartDrawing(ImageOutput(#imageFile))
    DrawingFont(FontID(#drawFont))
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawText(30, 180, "TEXT IS SOLID", #Red)
  StopDrawing()
 
  ddc = StartDrawing(ImageOutput(#imageFile))
    SelectObject_(ddc, FontID(#drawFont))
    SetBkMode_(ddc, #TRANSPARENT)
    SetTextColor_(ddc, 0)   ;<<<====== text should be black
    TextOut_(ddc, 30, 120, "TEXT IS CUT OUT!", 16)

    DrawingMode(#PB_2DDrawing_AlphaChannel) ; set Alpha Channel
    DrawingFont(FontID(#drawFont))
    t.s = "TEXT IS CUT OUT!"
    Box(30,120,TextWidth(t),TextHeight(t),$FFFFFFFF)
  StopDrawing()
   
  ImageGadget(#ImageGadget, 0, 0, ImageWidth(#imageFile), ImageHeight(#imageFile), ImageID(#imageFile))

  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        appQuit = 1
    EndSelect
  Until appQuit = 1
 
EndIf

No need to open more topics for the same issue. ;)


Top
 Profile  
 
 Post subject: Re: DrawText() & TextOut() WinAPI on Layered Window
PostPosted: Wed May 09, 2012 12:49 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat Feb 19, 2011 3:47 am
Posts: 410
Danilo wrote:
The API functions draw the text, but they set the alpha channel of 32bit images to 0, so it looks transparent.

Just set the alpha channel again after using the API functions.
Hi Danilo! And thanks a lot for the solution; I wouldn't have figured that out.
Danilo wrote:
No need to open more topics for the same issue.
You're right, although my intention was to refine the subject matter to clearly describe the issue. With your solution, I've expunged the last thread.

Thanks again! Truly appreciate your help.

_________________
Texas Instruments 99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: zxretrosoft and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye