Thread: Problem with blitting dibSections

  1. #1
    Registered User samGwilliam's Avatar
    Join Date
    Feb 2002
    Location
    Newport
    Posts
    382

    Problem with blitting dibSections

    I'm trying to use a dibSection to draw simple shapes, etc. on a window. It's kind of working, but it always draws them from 0, 0 of the whole screen (as opposed to local 0, 0 of the window itself).

    I think it might be something to do with device contexts.

    Does anybody know of any likely errors I could have made?
    Current Setup: Win 10 with Code::Blocks 17.12 (GNU GCC)

  2. #2
    Registered User
    Join Date
    May 2006
    Posts
    903
    Your error ? You didn't post code.

  3. #3
    Registered User samGwilliam's Avatar
    Join Date
    Feb 2002
    Location
    Newport
    Posts
    382
    OK, I've figured that one out for myself. Now I've got another problem with blitting:

    I have a struct:

    Code:
    struct blitArea
    {
    	HWND hostHWnd;
    
    	BITMAPINFO bmp;
    	DWORD*     pBits;
    	HBITMAP    hBmp;
    	HDC        hdcMem;
    	PAINTSTRUCT ps;
    };
    Initialised by:

    Code:
    void blitInit (blitArea *area, int width, int height)
    {
    	area->bmp.bmiHeader.biSize        = sizeof (BITMAPINFOHEADER);
    	area->bmp.bmiHeader.biWidth       = width;
    	area->bmp.bmiHeader.biHeight      = height;
    	area->bmp.bmiHeader.biPlanes      = 1;
    	area->bmp.bmiHeader.biBitCount    = 32;
    	area->bmp.bmiHeader.biCompression = BI_RGB;
    
    	area->hBmp = CreateDIBSection (NULL, &area->bmp, DIB_RGB_COLORS, (void **) &(area->pBits), 
            NULL, 0xff0fffff);
    	area->hdcMem = CreateCompatibleDC (NULL);
    	SelectObject (area->hdcMem, area->hBmp);
    }
    In:

    Code:
    LRESULT CALLBACK MainWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	static HDC hdc = NULL;
    
    	static blitArea area;
    
    	static square *s;
    	
    	switch (msg)
    	{
    		case WM_CREATE:
    			blitInit (&area, WIN_WIDTH, WIN_HEIGHT);
    			area.hostHWnd = hwnd;
    
    			s = new square (&area, 200, 200);
    		break;
    
    		case WM_PAINT:	
    			hdc = GetDC (hwnd);
    	
    			blit (&area, 0, 0, WIN_WIDTH, WIN_HEIGHT, 0, 0);
    
    			ReleaseDC (hwnd, hdc);
    			hdc = NULL;
    		break;
    
    		case WM_LBUTTONDOWN:
    		
    			hdc = GetDC (hwnd);
    
    			if (hdc)
    			{	
    				xp = LOWORD (lParam);
    				yp = HIWORD (lParam);
    
    				s->draw ();
    				
    				ReleaseDC (hwnd, hdc);
    				hdc = NULL;
    			}
    		break;
    I have a class called square that is supposed to draw a white rectangle to the screen with its own method called draw ():

    Code:
    class square
    {
    private:
    	blitArea *a;
    	int x, y;
    
    public:
    
    	square (blitArea *ar, int newX, int newY);
    	void draw (void);
    };
    
    square::square (blitArea *ar, int newX, int newY)
    {
    	a = ar;
    	x = newX;
    	y = newY;
    };
    
    void square::draw (void)
    {
    	HDC hdc = NULL;
    
    	drawRect (a->pBits, x, y, 50, 50, 0xffffffff);
    
    	hdc = GetDC (a->hostHWnd);
    
    	blit (a, 0, 0, 700, 500, 0, 0);
    
    	ReleaseDC (a->hostHWnd, hdc);
    	hdc = NULL;
    	
    };
    Please note, that this is simply a contrived example to illustrate the error I'm experiencing - the actual code is rather large, so I'm sparing you the hassle.

    If I call the square's draw method in the WM_CREATE handler, the subsequent blit () call in the WM_PAINT handler will cause the square to be drawn (naturally).

    But if I wanted to make the square only draw itself when you click the mouse (as seen in the WM_LBUTTONDOWN handler), the square will not appear straight away - you have to cause a WM_PAINT event (like moving the window out of the screen and back).

    The square's draw method calls the blit function itself but it has no effect! Only blit () calls from MainWindowProc seem to have any effect.
    Last edited by samGwilliam; 01-17-2007 at 05:18 PM.

  4. #4
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    1. In WM_PAINT, BeginPaint/EndPaint should be used rather than GetDC.
    2. Typically, all the painting to the target window is done in response to WM_PAINT. When you need to trigger a WM_PAINT you can call the InvalidateRect function.
    3. Your blit function does not seem to take a target DC and the blit function is not posted so it is not clear how you are obtaining the target DC in the blit function. This may hold the reason that your painting from outside WM_PAINT is not working (although even if you get it working, as noted above, it may not be the best approach).

  5. #5
    Registered User samGwilliam's Avatar
    Join Date
    Feb 2002
    Location
    Newport
    Posts
    382
    Hey thanks. I got it sorted the other day (when I stumbled upon that you could only paint from within the WM_PAINT message. I took your advice, though, and took the DC code from the WM_PAINT. The blit code gets the DC now, so that makes things neater, too.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  2. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  3. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  4. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM
  5. beginner problem
    By The_Nymph in forum C Programming
    Replies: 4
    Last Post: 03-05-2002, 05:46 PM