From: Mike Williams on 11 May 2010 05:26 "Robert" <noname(a)noserver.com> wrote in message news:7j3hu5141guoo4s9lfo6r2rs0c3lvkr71l(a)4ax.com... > 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). The actual routine I'm using to draw the > shadows is something I picked up (I think) from the groups . . The code you posted isn't complete but I can see roughly what you are doing with it. As I said in my previous response, there are all sorts of ways of accomplishing your task, and any method that eliminates the individual calls to SetPixel which you are currently using will speed it up a lot. There are all sorts of options. Here's one: http://groups.google.co.uk/group/microsoft.public.vb.general.discussion/browse_thread/thread/d8aa1d12ca8c4f97/124d0f6ae6c23388?#124d0f6ae6c23388 Mike
From: Robert on 12 May 2010 03:20 On Tue, 11 May 2010 10:26:24 +0100, "Mike Williams" <Mike(a)WhiskeyAndCoke.com> wrote: >"Robert" <noname(a)noserver.com> wrote in message >news:7j3hu5141guoo4s9lfo6r2rs0c3lvkr71l(a)4ax.com... > >> 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). The actual routine I'm using to draw the >> shadows is something I picked up (I think) from the groups . . > >The code you posted isn't complete but I can see roughly what you are doing >with it. As I said in my previous response, there are all sorts of ways of >accomplishing your task, and any method that eliminates the individual calls >to SetPixel which you are currently using will speed it up a lot. There are >all sorts of options. Here's one: > >http://groups.google.co.uk/group/microsoft.public.vb.general.discussion/browse_thread/thread/d8aa1d12ca8c4f97/124d0f6ae6c23388?#124d0f6ae6c23388 > >Mike > Thanks for the link. I tried out the routine as it is and it's a *lot* faster. I'm not looking forward to trying to understand it enough to draw the same kind of shadow as the old routine, though. I'm Familiar with the SAFEARRAY hack but manipulating colour values to create a feathered effect is something I know nothing about. One last question: In your opinion would the technique in your link be more efficient than something like this one (after it's been converted to use GDI rather than GDI+) ... http://www.codeproject.com/KB/miscctrl/Transparent_drop_shadow_i.aspx ....which builds drop shadows from five small transparent bitmaps stored as a resource? Rob
From: Mike Williams on 12 May 2010 14:51 "Robert" <noname(a)noserver.com> wrote in message news:u0giu598t8t60qgh2mdr6i4otakfse22ut(a)4ax.com... > In your opinion would the technique in your link be more > efficient than something like this one (after it's been converted > to use GDI rather than GDI+) ... > http://www.codeproject.com/KB/miscctrl/Transparent_drop_shadow_i.aspx > ...which builds drop shadows from five small transparent > bitmaps stored as a resource? I don't use either C++ or GDI+ so I don't know exactly what the code at the link you have just posted is doing with the .png images, but presumably if it is drawing the shadow correctly (so that it is not just grey but will work on any background) then any GDI+ function it calls will be using the ..png image's alpha channel data when it performs the drawing, in which case the drawing itself is unlikely to be much faster than the equivalent GDI32 AlphaBlend function would be on a similar sized fixed image. However, it is likely to gain some speed because it is using fixed ready prepared translucency images, whereas the GDI32 code at the link I posted is calculating each pixel's required translucency in the code itself, before it calls the AlphaBlend function. Of course you could probably use the same technique of five fixed bitmaps in VB6 with the GDI32 AlphaBlend function if you want (at least I think you can, I've never tried it myself). AlphaBlend is capable of stretching images, and of course it is capable of using per-pixel alpha values, so I don't see why you should not be able to use both of those functions together. I've never tried it myself, but I don't see why not. You would then be able to have one ready prepared small per-pixel alpha DIBSection for the bottom edge, which you could "stretch" when required to whatever size you want for any particular sized main rectangle (a "wide" stretch of the small DIB for the bottom). You would need a similar but differently orientated small per-pixel alpha DIBSection for the right side which you could stretch "tall" at runtime in the same manner, and the three small rectangular per-pixel alpha DIBSections for the three corners. All of those five small DIBSections (32 bit DIBSections of course, because they will have alpha channels) could be created when your code first runs and you could hang onto them for the duration of your program, using them as required. You would need to calculate the required alpha values for all bitmaps of course when your code first runs, particularly for the "rounded" corners, but if you have problems calculating suitable values in code (my math is not good in that area!) then you could always hard code them (or load them or the data for them from a resource) using per-pixel alpha values that you have obtained by examining the grey levels of some ready prepared "corner images" (perhaps those which are presumably in the download at the link you posted, or even from a screen grab of those corners). All five DIBSections would be a fixed size, so it should be very easy. Such DIBs would each effectively be "a black rectangle with suitable alpha values" and would therefore be able to be drawn over any background colour, or any background photo or whatever, using AlphaBlend and they should produce the appropriate shadow. This of course is all "thinking on the hoof" at the moment and I haven't got time to try any of that stuff to see if it actually works (at least not at the moment), but I think it can be done. > I'm Familiar with the SAFEARRAY hack but manipulating > colour values to create a feathered effect is something I know > nothing about. Well since you're happy with the SAFEARRAY stuff then you could always use code similar to the code you posted in your original message (when you said it produces exactly the effect you are after but is just too slow), but get rid of the calls to GetPixel and SetPixel, which is what is slowing it down the most. You could create two suitably sized DIBSections (for the right and bottom edges), or even one large full rectangle sized DIB and blit just the two sections into it, and then point a SAFEARRAY structure at the DIB and use pretty much the same code you are using, but accessing the DIB data instead of Getting and Setting screen pixels, and then Blit the DIB to the display. Somehting like that, anyway. There are probably various other options open to you as well, but those I have mentioned are the ones that come to mind at the moment. Mike
From: Robert on 14 May 2010 04:38 On Wed, 12 May 2010 19:51:38 +0100, "Mike Williams" <Mike(a)WhiskeyAndCoke.com> wrote: > >"Robert" <noname(a)noserver.com> wrote in message >news:u0giu598t8t60qgh2mdr6i4otakfse22ut(a)4ax.com... > >> In your opinion would the technique in your link be more >> efficient than something like this one (after it's been converted >> to use GDI rather than GDI+) ... >> http://www.codeproject.com/KB/miscctrl/Transparent_drop_shadow_i.aspx >> ...which builds drop shadows from five small transparent >> bitmaps stored as a resource? > >I don't use either C++ or GDI+ so I don't know exactly what the code at the >link you have just posted is doing with the .png images, but presumably if >it is drawing the shadow correctly (so that it is not just grey but will >work on any background) then any GDI+ function it calls will be using the >.png image's alpha channel data when it performs the drawing, in which case >the drawing itself is unlikely to be much faster than the equivalent GDI32 >AlphaBlend function would be on a similar sized fixed image. However, it is >likely to gain some speed because it is using fixed ready prepared >translucency images, whereas the GDI32 code at the link I posted is >calculating each pixel's required translucency in the code itself, before it >calls the AlphaBlend function. > >Of course you could probably use the same technique of five fixed bitmaps in >VB6 with the GDI32 AlphaBlend function if you want (at least I think you >can, I've never tried it myself). AlphaBlend is capable of stretching >images, and of course it is capable of using per-pixel alpha values, so I >don't see why you should not be able to use both of those functions >together. I've never tried it myself, but I don't see why not. You would >then be able to have one ready prepared small per-pixel alpha DIBSection for >the bottom edge, which you could "stretch" when required to whatever size >you want for any particular sized main rectangle (a "wide" stretch of the >small DIB for the bottom). You would need a similar but differently >orientated small per-pixel alpha DIBSection for the right side which you >could stretch "tall" at runtime in the same manner, and the three small >rectangular per-pixel alpha DIBSections for the three corners. All of those >five small DIBSections (32 bit DIBSections of course, because they will have >alpha channels) could be created when your code first runs and you could >hang onto them for the duration of your program, using them as required. You >would need to calculate the required alpha values for all bitmaps of course >when your code first runs, particularly for the "rounded" corners, but if >you have problems calculating suitable values in code (my math is not good >in that area!) then you could always hard code them (or load them or the >data for them from a resource) using per-pixel alpha values that you have >obtained by examining the grey levels of some ready prepared "corner images" >(perhaps those which are presumably in the download at the link you posted, >or even from a screen grab of those corners). All five DIBSections would be >a fixed size, so it should be very easy. Such DIBs would each effectively be >"a black rectangle with suitable alpha values" and would therefore be able >to be drawn over any background colour, or any background photo or whatever, >using AlphaBlend and they should produce the appropriate shadow. This of >course is all "thinking on the hoof" at the moment and I haven't got time to >try any of that stuff to see if it actually works (at least not at the >moment), but I think it can be done. > >> I'm Familiar with the SAFEARRAY hack but manipulating >> colour values to create a feathered effect is something I know >> nothing about. > >Well since you're happy with the SAFEARRAY stuff then you could always use >code similar to the code you posted in your original message (when you said >it produces exactly the effect you are after but is just too slow), but get >rid of the calls to GetPixel and SetPixel, which is what is slowing it down >the most. You could create two suitably sized DIBSections (for the right and >bottom edges), or even one large full rectangle sized DIB and blit just the >two sections into it, and then point a SAFEARRAY structure at the DIB and >use pretty much the same code you are using, but accessing the DIB data >instead of Getting and Setting screen pixels, and then Blit the DIB to the >display. Somehting like that, anyway. There are probably various other >options open to you as well, but those I have mentioned are the ones that >come to mind at the moment. > >Mike > > > Thanks again. The code in the link is blitting the three corner images and then tiling the right and bottom edge images using the GDI+ texturebrush. Obviously to convert it to GDI one would have to tile the edge images using multiple blits rather than rectangle (unless patternbrush supports transparency, which I doubt) Anyway, for the moment I'm going to go with your suggestion. It seems to be fast enough and I think I can alter my control painting code to keep flicker to an acceptable level when resizing "columns" without resorting to double buffering.
From: Mike Williams on 14 May 2010 10:11
"Robert" <noname(a)noserver.com> wrote in message news:132qu5lb6ts7gt2vf5i36tlkfsj9gmbqtd(a)4ax.com... > Thanks again . . I'm going to go with your suggestion. It seems > to be fast enough and I think I can alter my control painting code > to keep flicker to an acceptable level when resizing "columns" > without resorting to double buffering. I'm not sure which of them you mean because I have suggested a number of different methods. Do you mean my suggestion to stick with your original code but to replace the GetPixel and SetPixel stuff with a SAFEARRAY pointed at the bitmap data? If so then I think you will find it easily fast enough for your needs, especially when run as a standard native code compiled exe as would be the case in the field. There is of course also some room for optimization in some of your existing functions which calculate the required data, which were not important factors when you were using GetPixel and SetPixel but which can make a significant difference to the speed of the faster SAFEARRAY method, so you can always speed it up some more if the need arises. > The [C++ / GDI+] code in the link is blitting the three corner > images and then tiling the right and bottom edge images using > the GDI+ texturebrush. Obviously to convert it to GDI one > would have to tile the edge images using multiple blits rather than > rectangle (unless patternbrush supports transparency, which I doubt) Actually this morning I started to write some code to perform the same job in VB6 as the C++ / GDI+ code at that link is doing. So far I have concentrated only on the bottom dropshadow, and that part is almost finished, so as soon as I've had the chance to finish it off and check whether it works okay then I'll respond again. If the bottom dropshadow code works okay then it should be easy to add similar code for the right dropshadow, and of course the three corners are not a problem at all. Mike |