Discussion:
Editing a bitmap in memory
(too old to reply)
bmearns
2011-03-20 23:03:58 UTC
Permalink
I'm very new to GDI programming, and I'm having trouble with what I
assume are some conceptual issues regarding bitmaps and/or device
contexts. I've been reading through as much of the reference materials
(on msdn) as I can, but there's a lot of it. I'm hoping someone here
can help me out.

I'm trying to programatically draw a bitmap, and then modify it in
response to, say, a mouse click. More generally, I'm just trying to
edit a bitmap that's in memory. I've created the bitmap in WM_CREATE
like this:

//////////////////////////////////////////////////////////////////

HBITMAP bgBitmapHbm;
// ...
case WM_CREATE:
{
unsigned int i,j;
HDC memHDC;
HBITMAP oldBitmap;

hdc = GetDC(hwnd);
memHDC = CreateCompatibleDC(hdc);
bgBitmapHbm = CreateCompatibleBitmap(hdc, WINDOW_WIDTH,
WINDOW_HEIGHT);
oldBitmap = SelectObject(memHDC, bgBitmapHbm);

for(i=0; i<WINDOW_WIDTH; i++) {
for(j=0; j<WINDOW_HEIGHT; j++) {
SetPixel(memHDC, i, j, RGB(i*255/WINDOW_WIDTH,
j*255/WINDOW_HEIGHT, 100));
}
}

SelectObject(memHDC, oldBitmap);
DeleteDC(memHDC);
ReleaseDC(hwnd, hdc);
}
break;
//////////////////////////////////////////////////////////////////

I've successfully gotten the program to display the bitmap in WM_PAINT
like this:

//////////////////////////////////////////////////////////////////
case WM_PAINT:
{
HDC memHDC;
HBITMAP oldBitmap;
BITMAP bm;
PAINTSTRUCT ps;

hdc = BeginPaint(hwnd, &ps);
memHDC = CreateCompatibleDC(hdc);
oldBitmap = SelectObject(memHDC, bgBitmapHbm);

GetObject(bgBitmapHbm, sizeof(bm), &bm);
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, memHDC, 0, 0,
SRCCOPY);

SelectObject(memHDC, oldBitmap);
DeleteDC(memHDC);

EndPaint(hwnd, &ps);
}
break;
//////////////////////////////////////////////////////////////////

But then in my mouse click handler, I try to use SetPixel again to
change the bitmap, but it doesn't seem to do anything (meaning, the
bitmap as displayed does not look any different). I've verified that
the handler is working by launching a MessageBox, and even confirmed
that I can write text to the window from the mouse click handler (with
TextOut). Here's the code:
//////////////////////////////////////////////////////////////////
case WM_LBUTTONDOWN:
{
HDC hdc, memHDC;
HBITMAP oldBitmap;
unsigned int i, j;

hdc = GetDC(hwnd);
memHDC = CreateCompatibleDC(hdc);
oldBitmap = SelectObject(memHDC, bgBitmapHbm);

for(i=0; i<100; i++)
{
for(j=0; j<80; j++)
{
SetPixel(memHDC, i, j, RGB(100, 255, 30));
}
}
UpdateWindow(hwnd);

SelectObject(memHDC, oldBitmap);
DeleteDC(memHDC);
ReleaseDC(hwnd, hdc);
}
break;
//////////////////////////////////////////////////////////////////

If anyone can help me fix this (and preferably explain why this isn't
working), I'd really appreciate it.

Thanks,
-Brian
jon
2011-03-20 23:43:07 UTC
Permalink
UpdateWindow() only dispatches WM_PAINT if any areas are marked as
invalid; if not, nothing will happen.
Try using InvalidateRect() or RedrawWindow() (with appropriate flags)
to invalidate the window.
Post by bmearns
But then in my mouse click handler, I try to use SetPixel again to
change the bitmap, but it doesn't seem to do anything (meaning, the
bitmap as displayed does not look any different). I've verified that
the handler is working by launching a MessageBox, and even confirmed
that I can write text to the window from the mouse click handler (with
//////////////////////////////////////////////////////////////////
        {
            HDC hdc, memHDC;
            HBITMAP oldBitmap;
            unsigned int i, j;
            hdc = GetDC(hwnd);
            memHDC = CreateCompatibleDC(hdc);
            oldBitmap = SelectObject(memHDC, bgBitmapHbm);
            for(i=0; i<100; i++)
            {
                for(j=0; j<80; j++)
                {
                    SetPixel(memHDC, i, j, RGB(100, 255, 30));
                }
            }
            UpdateWindow(hwnd);
            SelectObject(memHDC, oldBitmap);
            DeleteDC(memHDC);
            ReleaseDC(hwnd, hdc);
        }
        break;
//////////////////////////////////////////////////////////////////
If anyone can help me fix this (and preferably explain why this isn't
working), I'd really appreciate it.
Thanks,
-Brian
bmearns
2011-03-21 00:20:47 UTC
Permalink
Post by jon
UpdateWindow() only dispatches WM_PAINT if any areas are marked as
invalid; if not, nothing will happen.
Try using InvalidateRect() or RedrawWindow() (with appropriate flags)
to invalidate the window.
[snip]

Thanks, that was part of my problem. I had tried using InvalidateRect
before, but it just made my entire bitmap disappear. Turns out I
needed to call it after releasing the windows DC.

Thanks for the help!
-Brian

Continue reading on narkive:
Loading...