From: Mike Williams on
"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
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

"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
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
"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