Archive > Archived Posts

GDI+ Works on %WS_Ex_Layered Window?

(1/3) > >>

Gary Beene:
In the code below, I display a rotated image (ruler) with a blue background. The dialog is given the %WS_Ex_Layered style so that the blue background will be transparent color:

--- Code: ---Dialog New Pixels, 0, "Ruler",300,300,400,50, %WS_Popup, %WS_Ex_Layered To hDlg
--- End code ---
and then ...

--- Code: ---SetLayeredWindowAttributes(hDlg, %Blue, 255, %LWA_ALPHA Or %LWA_ColorKey)
--- End code ---

When I use PlgBlt to rotate the image, transparency works fine.  But when I rotate the image with GDI+, the transparency effect is lost - the blue background is visible, rather than being transparent.

Is there an interaction between GDI+ and WS_Ex_Layered windows that would explain this?

Here's the compilable code (uses Jose's includes  :D).  Use the mouse wheel to rotate the image, right mouse click to close the app.

--- Code: ---#Compile Exe
#Dim All
#Debug Error On
#Debug Display On
#Include ""

Global hDlg, hDC As Dword, rulerH, rulerW, rotateW, rotateH As Long, theta As Single

Function PBMain() As Long
   Local StartupInput As GdiplusStartupInput, token As Dword
   StartupInput.GdiplusVersion = 1     ' Initialize GDI+
   GdiplusStartup(token, StartupInput, ByVal %NULL)
   Dialog New Pixels, 0, "Ruler",300,300,400,50, %WS_Popup, %WS_Ex_Layered To hDlg
   Dialog Show Modal hDlg Call DlgProc
   GDIPlusShutDown token
End Function

CallBack Function DlgProc() As Long
   Local PS As PaintStruct
   Select Case Cb.Msg
      Case %WM_InitDialog
         rulerW = 222 : rulerH = 48             'for this example, ruler is fixed at 222x48 pixels
         Dialog Set Color hDlg, %Black, %Blue
         Dialog Set Size hDlg, rulerW, rulerH
         SetLayeredWindowAttributes(hDlg, %Blue, 255, %LWA_ALPHA Or %LWA_ColorKey)
      Case %WM_MouseWheel
         Select Case Hi(Integer,Cb.WParam)    'note the use of Integer
           Case > 0 : theta = theta + 0.05 : RotateRuler
           Case < 0 : theta = theta - 0.05 : RotateRuler
         End Select
      Case %WM_ContextMenu
         Dialog End hDlg        'right mouse click to end app
      Case %WM_LButtonDown
         If Cb.WParam = %MK_LBUTTON Then SendMessage hDlg, %WM_NCLButtonDown, %HTCaption, ByVal %Null  ' force drag
      Case %WM_Paint
         hDC = BeginPaint(hDlg, PS)
         EndPaint hDlg, PS
   End Select
End Function

Sub RotateRuler
   Local iMax,tempx,tempy,w,h,XCenter,YCenter,dx,dy As Long, hTemp, hTempDC, pGraphics, pImage, hBitmap As Dword

       'resize dialog to enclose ruler after rotation
       rotateW = RulerW*Abs(Cos(theta)) + RulerH*Abs(Sin(theta))               'bounding W once ruler is rotated
       rotateH = RulerH*Abs(Cos(theta)) + RulerW*Abs(Sin(theta))               'bounding H once ruler is rotated
       Dialog Get Loc hDlg To tempx, tempy  :  Dialog Get Size hDlg To w,h     'get current dialog size
       Dialog Set Size hDlg, RotateW, RotateH                                  'set dialog size to bounding dimensions
       Dialog Set Loc hDlg, tempx - (RotateW-w)/2, tempy -(RotateH-h)/2        'relocate so rotation is about center of dialog

       If 1 Then                      'GDI+ version of rotation
           'load ruler image, which is in larger-than-needed image, surrounded by transparency color)
           iMax = 300                                             'image containg ruler just happens to be 300x300
           Graphic Bitmap Load "ruler1.bmp", iMax, iMax To hTemp   'centered ruler + blue surrounding
           Graphic Attach hTemp, 0
           Graphic Get DC To hTempDC

           'create GDI+ object
           GdipCreateFromHDC(hTempDC, pGraphics)                      'get pGraphics
           hBitmap = GetCurrentObject(hTempDC, %OBJ_Bitmap)           'get hBitmap
           GDIpCreateBitmapFromHBITMAP(hBitmap, ByVal %Null, pImage)  'get pImage

           'rotate the image
           GdipTranslateWorldTransform(pGraphics, iMax/2, iMax/2, %MatrixOrderPrepend)       ' Move to center
           GdipRotateWorldTransform(pGraphics, theta * 57.3, %MatrixOrderPrepend)                  ' Rotate
           GdipTranslateWorldTransform(pGraphics, -iMax/2, -iMax/2, %MatrixOrderPrepend) ' Return
           GdipDrawImage(pGraphics, pImage, 0, 0)

           Dialog ReDraw hdlg      'clear previous image
           BitBlt hDC, 0,0,rotateW,rotateH, hTempDC, iMax/2-rotateW/2,iMax/2-rotateH/2 , %SRCCopy   'copy ruler image to dialog surface

           If pImage Then GdipDisposeImage(pImage)        'cleanup
           If pGraphics Then GdipDeleteGraphics(pGraphics)'cleanup

      Else                            'PlgBlt version of rotation
           'create memory BMP containing just the ruler (222x48)
           Graphic Bitmap Load "ruler2.bmp", rulerW, rulerH To hTemp     'just the ruler, no surrounding blue color
           Graphic Attach hTemp, 0
           Graphic Get DC To hTempDC

          'get the 3 corners of the rotated image (point are located on hDlg)
           dx = (rotateW - rulerW)/2  : dy = (rotateH - rulerH)/2
           XCenter = rulerW/2         : YCenter = rulerH/2
           Dim PlgPts(2) As PointAPI
           PlgPts(0).X = XCenter + (0        - XCenter) * Cos(theta) - (0        - YCenter) * Sin(theta) + dx 'upper-left in target
           PlgPts(0).Y = YCenter + (0        - XCenter) * Sin(theta) + (0        - YCenter) * Cos(theta) + dy
           PlgPts(1).X = XCenter + (RulerW   - XCenter) * Cos(theta) - (0        - YCenter) * Sin(theta) + dx 'upper-right in target
           PlgPts(1).Y = YCenter + (RulerW   - XCenter) * Sin(theta) + (0        - YCenter) * Cos(theta) + dy
           PlgPts(2).X = XCenter + (0        - XCenter) * Cos(theta) - (RulerH   - YCenter) * Sin(theta) + dx 'lower left in target
           PlgPts(2).Y = YCenter + (0        - XCenter) * Sin(theta) + (RulerH   - YCenter) * Cos(theta) + dy
           Dialog ReDraw hdlg      'clear image, display blue background color
           PlgBlt hDC, PlgPts(0),hTempDC, 0,0,RulerW,RulerH,0&,0,0  'copy ruler image to dialog surface
   End If
End Sub
--- End code ---

Gary Beene:
Sorry, but left off a link to the two images:

Gary Beene:
More information ... conflicting results.

I'm running on Win7. 

When I run under an Aero theme, the transparency works.

But when I run under a basic theme (Windows Classic), the transparency does not work.

Gary Beene:
More data ... transparency doesn't work on my wife's XP machine either.

In looking around the web, I'm seeing a number of posts who's title suggests a similar problem.  But I haven't yet found a clear explanation of why, of how to resolve the problem.

Gary Beene:
Over in the PowerBASIC forums, Donald gave me some code that will work. But he took a slightly different route so I still don't know why the code I posted fails.

Different Question:
In these forums, how do I hide the URL above, and use it to make a highlighted link?


[0] Message Index

[#] Next page

Go to full version