WM_PAINT

BlitzPlus Forums/BlitzPlus Programming/WM_PAINT

sswift(Posted 2005) [#1]
I've been trying to figure out how bitmaps are drawn in Windows for a few days now, and I found this code:

case WM_PAINT:
{
    HDC dc = GetDC(hWnd);
    HDC memDC ;
    HBITMAP memBitmap = LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP_ONE));
    HBITMAP oldBitmap ;

    memDC = CreateCompatibleDC(dc) ;
    oldBitmap = (HBITMAP)SelectObject(memDC,memBitmap) ;

    BITMAP bm;
    GetObject(memBitmap, sizeof(BITMAP), (LPVOID)&bm);
    if (memDC != NULL)
    {
        StretchBlt(dc,0, 0, m_nClientWidth, m_nClientHeight, memDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY) ;
    }
    SelectObject(memDC,oldBitmap) ;
}
break;
    
you need to provide this code with the
size of the window, put this code
somewhere under before this code after the.

    RECT rect;
    GetClientRect(hWnd,&rect);
    m_nClientWidth = rect.right-rect.left;
    m_nClientHeight = rect.bottom - rect.top;

Also the code assummes that you have a bitmap with name IDB_BITMAP_ONE to be drawn.



Don't tell me that in order to draw a bitmap in a window, I have to redraw it every single time my app gets a WM_PAINT message!

I obviously can't do that in Blitzplus, because it intercepts all the messages, and automatically runs a program in a special loop that disallows drawing commands whenever someone for example, moves a scrollbar!

Augh... someone please tell me this is not the case and that there is an object I can create in a window like a button that is always there and that I don't have to redraw manually!


sswift(Posted 2005) [#2]
If that IS the case, then I need a way to either:

A) Get a bitmap pointer/device context to a Blitz image so I can use stretchblt to draw to it.

B) Get a pointer to whatever bitmap a canvas is storing in ram that it uses to redraw itself when you flip it in Blitz.

If I could do that, then I could use StretchBlt to blit images into a canvas or other images.


Warren(Posted 2005) [#3]
Don't tell me that in order to draw a bitmap in a window, I have to redraw it every single time my app gets a WM_PAINT message!

That's the standard mechanism. Windows doesn't have a native control that displays a bitmap - that's custom drawing and as such, needs redoing whenever the window becomes dirty (aka receives a WM_PAINT message).


sswift(Posted 2005) [#4]
Hm... It would have been nice if someone had told me that THREE DAYS AGO! :-)


Well, I give up in this crap. I have been unable to find a solution.

I now have a better grasp of how the GDI functions work, but that information is largely useless to me unless I ever decide to start coding in Visual Basic.

Also, I realised after I posted the above when looking at my zooming code to see if I could optimize it further that I HAD FORGOTTEN TO REPLACE THE CALLS TO SCALEIMAGE IN MY MAIN PROGRAM WITH CALLS TO MY NEW ZOOM FUNCTION WHICH I KNEW WAS 8x FASTER THAN SCALEIMAGE.

What can I say? I am an idiot. I wated three days looking for a solution to a problem which wasn't quite as bad as I thought it was.

Still it would be nice to have instant zooming. I have no idea why Mark chose to code his own scale function rather than using the scaleblt command to do scaling. I can only guess it is a holdover from Blitz3D.

Also, I haven't decided if I should code a Blitzplus specific version of my zoom function. It would only get me a 25% increase in speed in 32 bit graphics modes. That means a half a second off a two second scaling time. Doesn't really seem worth all the messy code.


Mr. Write Errors Man(Posted 2005) [#5]
I told you DIB drawing functions would likely not "stick" on B+ canvas. :c)

Why not just limited the zooming options to something like 100%, 200%, 75% and 50%? Shouldn't take ages to produce the four pics?

I agree it's strange that B+ doesn't have some sort of ScaleBlt, as even GDI provides one. Granted the GDI stretchBlt may look ugly, as not all gfx drivers support smoother stretching modes.


sswift(Posted 2005) [#6]
"I told you DIB drawing functions would likely not "stick" on B+ canvas. :c)"


Yes, and I'd already figured that out myself, and that has nothing to do with having to repaint all bitmaps when drawing with windows GDI functions in a C program. :-)

Apparently the reason GDI functions don't "stick" on a canvas is because the GDI functions draw to the canvas's "front buffer", and when the canvas flips, the unmodified backbuffer overwrites it.

But what I realise now (I think), is that this "canvas" gadget is really just a couple device independent bitmaps, and Blitz is calling scaleblt every time Windows sends Blitz a WM_PAINT message. (Or I call FlipCanvas)

That is what I wish I'd known three days ago.

Because that means there is no gadget in windows that will behave like a canvas. And finding that was integral to my plan.

In order for me to simulate a canvas, I would have to be able to intercept the WM_PAINT messages before Blitz gets them, and call the GDI functions to redraw my bitmap into the Window. But I can't do that. So all my efforts have been for naught.


"Why not just limited the zooming options to something like 100%, 200%, 75% and 50%? Shouldn't take ages to produce the four pics?"

Actually, I have done something like that:
http://www.blitzbasic.com/codearcs/codearcs.php?code=1301

That is 8x faster than the standard scaleimage command. But a size like 75% is not possible with this method. It can do 25%, 33%, 50%, 100%, 200%, 300%, but not 75% or 150%.

Ie, it can draw one line for every three, (33%) or it can draw three lines for every one (300%) but it can't do anything in between, because that would be just as slow as ScaleImage with TFormFilter set to False.

But you're mistaken about it not taking ages to produce four pics. 200% is the max I'm going to allow, because it takes a good two seconds to scale an image from 1024x1024 to 2048x2048, and my program will often be dealing with images that are 2048x2048... So it will take eight seconds to soom in to 200%, and two more to scale down to 1024x1024. As such, it is not an option to preclauclate all the scales for each window as that would take too long and the images will be modified too often.

I wonder though... Would the rect command be faster than drawing four pixels in a square manually. Hm...

Also, would the command to copy a block of pixels be faster than reading them individually. If I am scaling an image up, I could use (HEIGHT*WIDTH) copyrect commands to copy the image. More pixels would have to be read and written, but it's possible the command would still be faster if it uses the GDI commands to do the copy.

Unfortunately, doing the same trick to scale down is harder, and may not be worthwhile.


sswift(Posted 2005) [#7]
Holy crap!

My new CopyRect method is 20x faster than the old method!

Now instead of taking two seconds to scale an image from 1024x1024 to 2048x2048, it takes one TENTH of a second!

Woot!

I just wish I'd tried this three days ago when I first considered it instead of spending all this time screwing around with GDI commands! ARGH!!!!!


Oh and I should mention that I'm pretty sure I could make this new method scale to ANY scale, without any speed hit.

In other words, my Zoom function, coded in Blitz, should ultimately end up being able to do what the ScaleImage command does with TFormFilter False enabled, not 10, not 20, not 30, but, EIGHTY TIMES faster!


(And it occurs to me that someone else may have already done this in a code archives entry somewhere.)


Grey Alien(Posted 2005) [#8]
Holy crap!

lmao! (has it ever occured to anyone that these sort of things should be in capitals like acronyms (not shouting)) Also do any non-coders ever write sentences with nested brackets (like this (!))

I was looking at the code archives on blitz coder and couldn't find a really fast scale routine (found a slightly faster one) so if you feel like giving back to the community, then thou shalt be blessed with digital karma.

Windows GDI stinks anyway. Make games and live in peace and harmony forever.


sswift(Posted 2005) [#9]
"I was looking at the code archives on blitz coder and couldn't find a really fast scale routine (found a slightly faster one) so if you feel like giving back to the community, then thou shalt be blessed with digital karma."

Crap! I posted it to the code archives and to the General Forum before you replied to my post!

No karma for me!


Grey Alien(Posted 2005) [#10]
ye har, I'm gonna download that sonofva beeeech now!


Grey Alien(Posted 2005) [#11]
OK, it is good and fast but ... I was already using a fast routine that I found on blitzcoders (I think). I am using it to scale up some text smoothly (1 iteration per frame) and it is ever so slightly faster that your code when the text gets bigger. Don't know why. I am talking your code takes max 14-15ms to do my scaling and the other code takes max 10-11ms to do the same scaling. But thanx anyway. Oh yeah your function is easier to use too.

the other code is this:




Sarge(Posted 2005) [#12]
Well actually a label gadget can be converted into a bitamp image thats what its designed for rather a text label, icon and bitmap.