Thread: drawing a bitmap in new position

  1. #1
    Registered User
    Join Date
    Nov 2001
    Posts
    162

    Question drawing a bitmap in new position

    I have some code that draws a bitmap at 0,0 and an edit box that you can input a number to determine the bitmap's position. It's like this:

    void DrawPieces(HDC hdcWindow)
    {
    ErasePieces(hdcWindow);
    HDC hdcMemory;

    hdcMemory = CreateCompatibleDC(hdcWindow);

    SelectObject(hdcMemory, XMask);
    BitBlt(hdcWindow, xpos, 20, bmXPiece.bmWidth, bmXPiece.bmHeight, hdcMemory, 0, 0, SRCAND);

    SelectObject(hdcMemory, XPiece);
    BitBlt(hdcWindow, xpos, 20, bmXPiece.bmWidth, bmXPiece.bmHeight, hdcMemory, 0, 0, SRCPAINT);

    DeleteDC(hdcMemory);
    }
    which is called from the WM_PAINT command. It draws it fine, but when I update the variable it doesn't redraw it in a new location. I used the the EN_UPDATE thing on the edit control so it does update the var, and sends it, but the image stays in the same place. How do I make it draw at a different location? Thanks a lot.

  2. #2
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    It could be it is drawing but you are not calling the paint.

    After the variable, in the edit, is updated call an InvalidateRect() or UpdateWindow()

    You are clearing the hdc by painting it white (neutral) again?

    I would also use SCRCOPY as this uses only the bmp's colours not a combination of the current screen and the bmp's. (SCRAND uses the AND operator on the pixcel value from the screen and the pixcel value on the bmp)

    When you select the bmp into the hdcMemory the return is the previous bmp. You need to catch this and return it before the DeleteDC() or you will lose all its GDI memory.

    hSysBMP=SelectObject(hdcMemory,XMask);
    //ect

    XMask=SelectObject(hdcMemory,XPiece);
    //ect

    XPiece=SelectObject(hdcMemory,hSysBMP);
    DeleteDC(hdcMemory);

    You are using the same BITMAP sizes for both BitBlt(). Is this a typo or are XMask and XPiece the same size?
    If so you are drawing one over the top of the other.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  3. #3
    Registered User
    Join Date
    Nov 2001
    Posts
    162
    The XMask is the bmp that covers up the blank spots on the XPiece bmp. I am clearing the hdc by making a rect around the bmp and using the FillRect() function to paint it the color of the window background. Also, it updates the image poswhen I minimize the screen and restore it, but that is the only way it moves, so I have no idea what to do to make it move without doing that. Thanks.

  4. #4
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    OK....
    If when you minimise it draws correctly then you have it almost correct. Try opening a small window, ie resource meter, and covering up your bmp. See it move.

    It is a paint msg problem. Make sure you are correctly calling the paint. It is not enough to draw it to a hdc you must then tell windows to redraw the correct area with the right HDC.
    Have you got the InvalidateRect() after getting the new xpos?

    What hdc is used in your BeginPaint() / EndPaint() call?
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  5. #5
    Registered User
    Join Date
    Nov 2001
    Posts
    162
    Here are my functions, that I use. I have tried a few different things but I is stumping me:

    void DrawPieces(HDC hdcWindow)
    {
    HDC hdcMemory;

    hdcMemory = CreateCompatibleDC(hdcWindow);

    SelectObject(hdcMemory, XMask);
    BitBlt(hdcWindow, xpos, 20, bmXPiece.bmWidth, bmXPiece.bmHeight, hdcMemory, 0, 0, SRCAND);

    SelectObject(hdcMemory, XPiece);
    BitBlt(hdcWindow, xpos, 20, bmXPiece.bmWidth, bmXPiece.bmHeight, hdcMemory, 0, 0, SRCPAINT);

    DeleteDC(hdcMemory);
    }

    void ErasePieces(HDC hdcWindow)
    {
    RECT rc;
    rc.left = xpos;
    rc.top = 10;
    rc.right = xpos + bmXPiece.bmWidth;
    rc.bottom = 10 + bmXPiece.bmHeight;
    FillRect(hdcWindow, &rc, (HBRUSH)(COLOR_BTNFACE+1));
    }

    case WM_PAINT:
    {
    PAINTSTRUCT ps;
    HDC hdcWindow;

    hdcWindow = BeginPaint(hwnd, &ps);

    ErasePieces(hdcWindow, hwnd);
    DrawPieces(hdcWindow);

    EndPaint(hwnd, &ps);
    }
    Thanks alot, I really appreciate it.

  6. #6
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    First,

    you are loosing GDI mem in DrawPieces()
    Try this
    Code:
    void DrawPieces(HDC hdcWindow) 
    { 
    HDC hdcMemory; 
    HBITMAP hSysBMP;
    
    hdcMemory = CreateCompatibleDC(hdcWindow); 
    hSysBMP=SelectObject(hdcMemory, XMask); 
    BitBlt(hdcWindow, xpos, 20, bmXPiece.bmWidth, bmXPiece.bmHeight, hdcMemory, 0, 0, SRCAND); 
    //this one will release XMask, I assume it is global
    SelectObject(hdcMemory, XPiece); 
    BitBlt(hdcWindow, xpos, 20, bmXPiece.bmWidth, bmXPiece.bmHeight, hdcMemory, 0, 0, SRCPAINT);
    //put the HDC back EXACTLY as you created it
    SelectObject(hdcMemory,hSysBMP); 
    DeleteDC(hdcMemory); 
    }
    When you / the user enters a new location for the BMP what do you do?

    Do you call for a paint msg?

    This is done with
    InvalidateRect() or UpdateWindow()

    Without this how will the app know that you want it to redraw the screen?

    Use InvalidateRect() if you know the area to repaint (ie the dialogs client rect would be my choice, use GetClientRect() to find it)

    Call the paint as soon as you have a NEW valid location.


    //edit
    On another point.
    It is best to do as little as possible in the Paint function. It would be better to draw to a temp HDC and then after all the drawing is done, in this case the BMP is moved, copy this temp HDC to your hdcWindow. Then call for the paint.

    The idea is all screen updates are quick (the OS may call a paint). None happen half way thru your drawing.

    After you fix this problem,
    Try a search here on FRAMEBUFFER's or look for 'help loading BMP's' ect
    //end edit
    Last edited by novacain; 12-05-2001 at 10:39 PM.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  7. #7
    Registered User
    Join Date
    Nov 2001
    Posts
    162
    When I try to use that code you did for drawpieces() it says:
    ANSI C++ forbids implicit conversion from `void *' in assignment
    about the hSysBMP class. I am using Dev-c++, if that matters. Also, when you user clicks the set button I added this :

    case IDC_SET:
    xpos = GetDlgItemInt(hwnd, IDC_POS, NULL, TRUE);
    ErasePieces(hdcWindow, hwnd);
    GetClientRect(hwnd, &window);
    InvalidateRect(hwnd, &window, 0);
    break;

    it now updates the x right, but doesn't erase the old one. Almost there! All my other code is the same for now.

  8. #8
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    DO NOT call erasepieces() as this is called in the paint and should not be needed.
    In ErasePieces() you want to draw over the LAST xpos not the NEW xpos. Why not erase the whole by sending in the client rect?
    You could try

    InvalidateRect(hWnd,&Rect,TRUE);
    //the last is a flag to erase the background, you have set it to false.

    As to the void pointer, I don't know. How have you declared XMask? Declare hSysBMP as the same type.
    Is it complaining about the HBITMAP hSysBMP line, do you use the HBITMAP type?

    Or with the hSysBMP=SelectObject(...); line?

    I use HBITMAP for bitmaps but HGLOBAL or HGDIOBJ could work.

    In your Win9x System Tools you have a resource meter.(can add if not installed) The bottom bar on the display is GDI resources. (Move the resource meter dialog over your BMP making it redraw) Make sure that you are not using up GDI's. The exe should not reduce the amount left as it runs.

    PS you may find EN_CHANGE helpful under the edit box case. I would change SRCPAINT, SRCAND to SCRCOPY in your BitBlt's.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  9. #9
    Registered User
    Join Date
    Nov 2001
    Posts
    162

    Thanks

    Hey man, I really appreciate your help in all those questions. It has helped me a lot. I got it working right, now. -Ben
    Last edited by Crossbow; 12-06-2001 at 03:43 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Drawing circle into a bitmap file
    By brokensail in forum C++ Programming
    Replies: 2
    Last Post: 10-30-2006, 01:26 AM
  2. Button handler
    By Nephiroth in forum Windows Programming
    Replies: 8
    Last Post: 03-12-2006, 06:23 AM
  3. (Dos) Drawing a bitmap?
    By Blackroot in forum C++ Programming
    Replies: 8
    Last Post: 12-30-2005, 03:21 AM
  4. OpenGL -- Bitmaps
    By HQSneaker in forum Game Programming
    Replies: 14
    Last Post: 09-06-2004, 04:04 PM
  5. Drawing more than 1 bitmap
    By bluehead in forum Windows Programming
    Replies: 2
    Last Post: 12-07-2002, 09:51 AM