From: Rob on 9 May 2010 19:41 Hi, I'm working on a usercontrol that is basically a bunch of different sized boxes (sometimes more than 30 on screen at once). I'd like those boxes to have an alphablended dropshadow effect but the code I've been using to draw (using SetPixel) the shadows is to slow when the whole control has to be drawn at once. What approach to drawing dropshadows that blend with the background would be quickest? Thanks Rob
From: Mike Williams on 10 May 2010 16:08 "Rob" <noname(a)noserver.com> wrote in message news:p3fus59m0sinmmeuvac6bf4t99a9279fpc(a)4ax.com... > I'm working on a usercontrol that is basically a bunch of different > sized boxes (sometimes more than 30 on screen at once). I'd like > those boxes to have an alphablended dropshadow effect but the > code I've been using to draw (using SetPixel) the shadows is to > slow when the whole control has to be drawn at once. What > approach to drawing dropshadows that blend with the background > would be quickest? You say that you want an alphablend drop shadow effect, so I assume you are actually using the AlphaBlend function? Is that what you are using? If so then you will find it pretty quick. The problem is that you also say you are using SetPixel to set individual pixels, which is dreadfully slow for such tasks, so I'm not sure exactly what you are doing. The only reason I can see which might cause you to be using /both/ the AlphaBlend function and the SetPixel function is if you are using AlphaBlend in its "per pixel translucency" mode (where you have set the BlendFunction AlphaFormat to AC_SRC_ALPHA) and which requires you to fiddle about with the individual "pre-multiplication" of each bitmap colour byte with its alpha channel. Is that what you are doing? If so then you really need to get your bitmap pixel data into a DIB (if it is not already in one) and then point a VB SafeArray structure at the DIB data which will enable you to perform the pre-multiplication stuff very quickly by accessing the DIB data as though it was a standard VB Byte array. However, having said that, per pixel translucency is not actually required for the job you are doing (at least judging by your explanation of that job). There are all sorts of ways of drawing things with drop shadows, with different methods being suitable for different circumstances depending on exactly what it is you are drawing and whether they are regularly or irregularly shaped. For example, you say you are drawing "boxes", which I assume are rectangular and solid. If that is the case then you can draw them, and their drop shadows, with considerably less code that you could if they were rectangles with rounded corners or if they were irregularly shaped. Perhaps it might be best if you were to describe in more detail exactly what bitmaps your are drawing, and how you are initially creating those bitmaps, and exactly what you mean by "drop shadow" (I know that sounds odd, but to me a drop shadow is where the background in the shadow area is blended with black, but I've come across some people who see it differently and see it as being blended with the pixels of the object that is causing the shadow, which of course is not quite the same as a shadow). It would also be very helpful if you were to post your existing code, so we can see exactly what it is you are currently doing. Mike
From: Mike Williams on 10 May 2010 17:16 "Rob" <noname(a)noserver.com> wrote in message news:p3fus59m0sinmmeuvac6bf4t99a9279fpc(a)4ax.com... > I'm working on a usercontrol that is basically a bunch of different > sized boxes (sometimes more than 30 on screen at once). I'd like > those boxes to have an alphablended dropshadow effect but the > code I've been using to draw (using SetPixel) the shadows is to > slow when the whole control has to be drawn at once. What > approach to drawing dropshadows that blend with the background > would be quickest? One thing I forgot to mention in my previous response is the fact that Micro$oft, having failed for many years in their attempts to destroy VB6 itself, and having also failed in their long standing attempts to destroy this newsgroup by sending in their team of specially brainwashed MVP saboteurs (Bill McCarthy, Paul Clement, Cor ligthert and others), has finally decided to attempt to destroy the group in a different way, by closing down its servers, which incidentally is in any case part of their plan to extract the maximum profits for themselves by shamelessly riding on the backs of the unpaid volunteers who freely give their time here to help the programming community. Therefore, it might be best if you forgot for the time being about responding to my own answer to your question in this group and if you instead re-posted your original question to the following group, which is not connected in any way with the Micro$oft servers: comp.lang.visual.basic.misc Mike
From: Mike Williams on 10 May 2010 17:22 "Mike Williams" <Mike(a)WhiskeyAndCoke.com> wrote in message news:O%23sKBYI8KHA.4508(a)TK2MSFTNGP06.phx.gbl... > . . . if you instead re-posted your original question to the following > group, which is not connected in any way with the Micro$oft servers: > comp.lang.visual.basic.misc Sorry, that's: comp.lang.basic.visual.misc Mike
From: Robert on 10 May 2010 19:46
Thanks for the reply At the moment the drop shadow is being drawn directly on the usercontrol's DC using setpixel using a value calculated based on the background colour (which, at the moment, is COLOR_WINDOW but I'd like the option to use a gradient or even a tiled bitmap in future) The boxes in question are simple rectangles which contain text. The height of a box is determined by the amount of text it contains. Widths are all the same but can be changed by the user (which can also effect the heights). If you picture the Outlook CardView you won't be too far off. The actual routine I'm using to draw the shadows is something I picked up (I think) from the groups by (I think) MikeD, as follows: Public Sub DrawShadow(ByVal hdc As Long, rec As RECT, Optional nOpacity As Long = 6) Dim X As Long, Y As Long, c As Long ' Simulate a shadow on right edge... For X = 1 To 4 ' For Y = 0 To 3 ' c = GetPixel(hDC, Rec.Right - X, Rec.Bottom + Y) ' SetPixel hDC, Rec.Right - X, Rec.Top + Y, c ' Next Y ' For Y = 4 To 7 ' c = GetPixel(m_hDC, Rec.Right - X, Rec.Top + Y) ' SetPixel m_hDC, Rec.Right - X, Rec.Top + Y, _ ' pMask(3 * X * (Y - 3), c) ' Next Y For Y = 1 To 4 c = GetPixel(hdc, rec.Right - X, rec.Top + Y) SetPixel hdc, rec.Right - X, rec.Top + Y, _ pMask(nOpacity * X * (Y - 0), c) Next Y For Y = 5 To RectHeight(rec) - 5 c = GetPixel(hdc, rec.Right + X, rec.Top + Y) SetPixel hdc, rec.Right - X, rec.Top + Y, _ pMask((nOpacity * 5) * X, c) Next Y For Y = RectHeight(rec) - 4 To RectHeight(rec) - 1 c = GetPixel(hdc, rec.Right - X, rec.Top + Y) SetPixel hdc, rec.Right - X, rec.Top + Y, _ pMask(nOpacity * X * -(Y - RectHeight(rec)), c) Next Y Next X ' Simulate a shadow on the bottom edge... For Y = 1 To 4 ' For X = 0 To 3 ' c = GetPixel(hDC, Rec.Left + X, Rec.Bottom - Y) ' SetPixel hDC, Rec.Left + X, Rec.Bottom - Y, c ' Next X ' For X = 4 To 7 ' c = GetPixel(m_hDC, Rec.Left + X, Rec.Bottom - Y) ' SetPixel m_hDC, Rec.Left + X, Rec.Bottom - Y, _ ' pMask(3 * (X - 3) * Y, c) ' Next X For X = 1 To 4 c = GetPixel(hdc, rec.Left + X, rec.bottom - Y) SetPixel hdc, rec.Left + X, rec.bottom - Y, _ pMask(nOpacity * (X - 0) * Y, c) Next X For X = 5 To RectWidth(rec) - 5 c = GetPixel(hdc, rec.Left + X, rec.bottom - Y) SetPixel hdc, rec.Left + X, rec.bottom - Y, _ pMask((nOpacity * 5) * Y, c) Next X Next Y End Sub ' - Function pMask splits a color ' into its RGB components and ' transforms the color using ' a scale 0..255 Private Function pMask(ByVal lScale As Long, ByVal lColor As Long) As Long Dim r As Long Dim g As Long Dim b As Long r = pTransform(lScale, GetRValue(lColor)) g = pTransform(lScale, GetGValue(lColor)) b = pTransform(lScale, GetBValue(lColor)) pMask = rgb(r, g, b) End Function ' - Function pTransform converts ' a RGB subcolor using a scale ' where 0 = 0 and 255 = lScale Private Function pTransform(ByVal lScale As Long, ByVal lColor As Long) As Long pTransform = lColor - Int(lColor * lScale / 255) End Function |