Thread: Redraw contents after minimize

  1. #1
    Registered User
    Join Date
    Dec 2010
    Posts
    71

    Redraw contents after minimize

    this is the code:
    Code:
    #include <windows.h>
    
    const char g_szClassName[] = "myWindowClass";
    
    HDC desen=NULL;
    PAINTSTRUCT ps;
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	switch(msg)
    	{
    		case WM_CLOSE:
    			DestroyWindow(hwnd);
    		break;
    		case WM_PAINT:
    		{
    			desen=BeginPaint(hwnd,&ps);
    			
    		}
    		break;
    		case WM_LBUTTONDOWN:
    			switch(wParam)
    			{
    				case MK_LBUTTON:
    				{
    					POINTS p;
    					p=MAKEPOINTS(lParam);
    					LineTo(desen,p.x,p.y);
    
    				}
    				break;
    			}
    		break;
    		case WM_DESTROY:
    			EndPaint(hwnd,&ps);
    			PostQuitMessage(0);
    		break;
    		default:
    			return DefWindowProc(hwnd, msg, wParam, lParam);
    	}
    	return 0;
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    	LPSTR lpCmdLine, int nCmdShow)
    {
    	WNDCLASSEX wc;
    	HWND hwnd;
    	MSG Msg;
    
    	wc.cbSize		 = sizeof(WNDCLASSEX);
    	wc.style		 = 0;
    	wc.lpfnWndProc	 = WndProc;
    	wc.cbClsExtra	 = 0;
    	wc.cbWndExtra	 = 0;
    	wc.hInstance	 = hInstance;
    	wc.hIcon		 = LoadIcon(NULL, IDI_APPLICATION);
    	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);
    	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    	wc.lpszMenuName  = NULL;
    	wc.lpszClassName = g_szClassName;
    	wc.hIconSm		 = LoadIcon(NULL, IDI_APPLICATION);
    
    	if(!RegisterClassEx(&wc))
    	{
    		MessageBox(NULL, "Window Registration Failed!", "Error!",
    			MB_ICONEXCLAMATION | MB_OK);
    		return 0;
    	}
    
    	hwnd = CreateWindowEx(
    		WS_EX_CLIENTEDGE,
    		g_szClassName,
    		"A Bitmap Program",
    		WS_OVERLAPPEDWINDOW,
    		CW_USEDEFAULT, CW_USEDEFAULT, 540, 320,
    		NULL, NULL, hInstance, NULL);
    
    	if(hwnd == NULL)
    	{
    		MessageBox(NULL, "Window Creation Failed!", "Error!",
    			MB_ICONEXCLAMATION | MB_OK);
    		return 0;
    	}
    
    	ShowWindow(hwnd, nCmdShow);
    	UpdateWindow(hwnd);
    
    	while(GetMessage(&Msg, NULL, 0, 0) > 0)
    	{
    		TranslateMessage(&Msg);
    		DispatchMessage(&Msg);
    	}
    	return Msg.wParam;
    }
    I saw this example but is whith image bitmap.Must declare two hdc to save my drawing before minimize?And instead of the second parameter in SelectObject(desen,) must be function to create a region like CreateRectRgn()?
    Last edited by nutzu2010; 07-05-2011 at 03:05 PM.

  2. #2
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    First question... why would you want to redraw after minimize?

    Seems you'd want to do that after WM_SHOWWINDOW puts the window back on screen
    or after WM_EXITSIZEMOVE to ensure the new window is correctly refreshed.

  3. #3
    Registered User
    Join Date
    Dec 2010
    Posts
    71
    oh,sorry...i wanna show my drawing when the window is about to be shown.Should not put code in WM_PAINT?

  4. #4
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Yep, WM_PAINT is what you want. The others can be used for calls to UpdateWindow() in some cases.

    The thing is WM_PAINT is low priority and may not be called right away if other WM_PAINT messages are in the queue...

  5. #5
    Registered User
    Join Date
    Dec 2010
    Posts
    71
    Ok,I understood,and what functions should be used to redisplay the drawing?

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by nutzu2010 View Post
    Ok,I understood,and what functions should be used to redisplay the drawing?
    Ummm ... the same ones that were used to draw it in the first place???

  7. #7
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    BeginPaint() must ALWAYS be followed by an EndPaint()

    A WM_PAINT is generated when an area of the window is 'invalidated' (InvalidateRect() etc).

    In the WM_PAINT you must call BeginPaint() to obtain the paint requirements (HDC, area etc)

    You then draw.

    You then set the 'invalidated' area to 'valid' by calling EndPaint()

    This must be done in the WM_PAINT handler (not for any other msg) and for the same paint msg.

    BTW....
    WM_PAINT msgs are the lowest priority in the OS msg queue (just below WM_TIMER) and are one of the few msgs that are modified while in the OS msg queue (the invalid areas are concatinated into one).

    However using both
    InvalidaetRect()
    UpdateWindow()
    will bypass the OS msg queue and send the WM_PAINT directly to the windows callback.
    Last edited by novacain; 07-05-2011 at 10:17 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

  8. #8
    Registered User
    Join Date
    Dec 2010
    Posts
    71
    I don't think I explained well.I know to draw a line:
    Code:
    #include <windows.h>
    
    const char g_szClassName[] = "myWindowClass";
    
    HDC desen=NULL;
    PAINTSTRUCT ps;
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	switch(msg)
    	{
    		case WM_CLOSE:
    			DestroyWindow(hwnd);
    		break;
    		case WM_PAINT:
    		{
    			desen=BeginPaint(hwnd,&ps);
    			LineTo(desen,200,200);
    			EndPaint(hwnd,&ps);
    		}
    		break;
    		case WM_LBUTTONDOWN:
    			switch(wParam)
    			{
    				case MK_LBUTTON:
    				{
    
    				}
    				break;
    			}
    		break;
    		case WM_DESTROY:
    			PostQuitMessage(0);
    		break;
    		default:
    			return DefWindowProc(hwnd, msg, wParam, lParam);
    	}
    	return 0;
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    	LPSTR lpCmdLine, int nCmdShow)
    {
    	WNDCLASSEX wc;
    	HWND hwnd;
    	MSG Msg;
    
    	wc.cbSize		 = sizeof(WNDCLASSEX);
    	wc.style		 = 0;
    	wc.lpfnWndProc	 = WndProc;
    	wc.cbClsExtra	 = 0;
    	wc.cbWndExtra	 = 0;
    	wc.hInstance	 = hInstance;
    	wc.hIcon		 = LoadIcon(NULL, IDI_APPLICATION);
    	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);
    	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    	wc.lpszMenuName  = NULL;
    	wc.lpszClassName = g_szClassName;
    	wc.hIconSm		 = LoadIcon(NULL, IDI_APPLICATION);
    
    	if(!RegisterClassEx(&wc))
    	{
    		MessageBox(NULL, "Window Registration Failed!", "Error!",
    			MB_ICONEXCLAMATION | MB_OK);
    		return 0;
    	}
    
    	hwnd = CreateWindowEx(
    		WS_EX_CLIENTEDGE,
    		g_szClassName,
    		"A Bitmap Program",
    		WS_OVERLAPPEDWINDOW,
    		CW_USEDEFAULT, CW_USEDEFAULT, 540, 320,
    		NULL, NULL, hInstance, NULL);
    
    	if(hwnd == NULL)
    	{
    		MessageBox(NULL, "Window Creation Failed!", "Error!",
    			MB_ICONEXCLAMATION | MB_OK);
    		return 0;
    	}
    
    	ShowWindow(hwnd, nCmdShow);
    	UpdateWindow(hwnd);
    
    	while(GetMessage(&Msg, NULL, 0, 0) > 0)
    	{
    		TranslateMessage(&Msg);
    		DispatchMessage(&Msg);
    	}
    	return Msg.wParam;
    }
    ,but I want to do that with mouse(not just a line, more),without my drawing to be erased when my window is restored from being minimised.
    I hope you understand(sorry for my English).

  9. #9
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    To make the line remain after a minimise you need a 'memory DC' or 'back buffer'.

    When the app starts (WM_CREATE/WM_INITDIALOG) you create a HDC and bitmap (compatible with the screen and select the bitmap into the memory DC).

    When the left mouse button is pressed you erase the memory HDC.

    When the mouse moves you draw a line to the memory DC (usually only while the mouse button is down). You call for a direct paint msg (as described in my last post)

    In the WM_PAINT you BitBlt() the memory DC to the HDC, using the rect, both from the PAINTSTRUCT.

    When the app closes you clean up the memory DC and bitmap.

    [Search for my posts on 'double buffering', CreateCompatibleDC() etc. I have posted this type of code many times before. ]
    "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

  10. #10
    Registered User
    Join Date
    Dec 2010
    Posts
    71
    I don't quite understand
    "When the left mouse button is pressed you erase the memory HDC."
    Why do I need to put more DeleteDc() than CreateCompatibleDC() ?
    Code:
    #include <windows.h>
    
    const char g_szClassName[] = "myWindowClass";
    
    
    PAINTSTRUCT ps;
    HDC hdc,hdcMem;
    HBITMAP paintOld,paint;
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	switch(msg)
    	{
    		case WM_CLOSE:
    			DeleteObject(paintOld);
    			EndPaint(hwnd,&ps);
    			DestroyWindow(hwnd);
    		break;
    		case WM_CREATE:
    		{
    			hdc=BeginPaint(hwnd,&ps);//return a hdc
    			hdcMem=CreateCompatibleDC(hdc);//creeaza o memorie Dc
    			paint=CreateCompatibleBitmap(hdc,530,310);
    			paintOld=SelectObject(hdcMem,paint);//selecteaza obiectul desen in memoria Dc
    		}
    		break;
    		case WM_PAINT:
    		{
    			BitBlt(hdc,ps.rcPaint.top,ps.rcPaint.left,530,310,hdcMem,ps.rcPaint.top,ps.rcPaint.left,SRCCOPY);
    		}
    		break;
    		case WM_LBUTTONDOWN:
    
    			switch(wParam)
    			{
    				case MK_LBUTTON:
    				{
    					DeleteDC(hdcMem);
    					POINTS p;
    					p=MAKEPOINTS(lParam);
    					
    					LineTo(hdcMem,p.x,p.y);
    				}
    				break;
    			}
    		break;
    		case WM_DESTROY:
    			PostQuitMessage(0);
    		break;
    		default:
    			return DefWindowProc(hwnd, msg, wParam, lParam);
    	}
    	return 0;
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    	LPSTR lpCmdLine, int nCmdShow)
    {
    	WNDCLASSEX wc;
    	HWND hwnd;
    	MSG Msg;
    
    	wc.cbSize		 = sizeof(WNDCLASSEX);
    	wc.style		 = 0;
    	wc.lpfnWndProc	 = WndProc;
    	wc.cbClsExtra	 = 0;
    	wc.cbWndExtra	 = 0;
    	wc.hInstance	 = hInstance;
    	wc.hIcon		 = LoadIcon(NULL, IDI_APPLICATION);
    	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);
    	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    	wc.lpszMenuName  = NULL;
    	wc.lpszClassName = g_szClassName;
    	wc.hIconSm		 = LoadIcon(NULL, IDI_APPLICATION);
    
    	if(!RegisterClassEx(&wc))
    	{
    		MessageBox(NULL, "Window Registration Failed!", "Error!",
    			MB_ICONEXCLAMATION | MB_OK);
    		return 0;
    	}
    
    	hwnd = CreateWindowEx(
    		WS_EX_CLIENTEDGE,
    		g_szClassName,
    		"A Bitmap Program",
    		WS_OVERLAPPEDWINDOW,
    		CW_USEDEFAULT, CW_USEDEFAULT, 540, 320,
    		NULL, NULL, hInstance, NULL);
    
    	if(hwnd == NULL)
    	{
    		MessageBox(NULL, "Window Creation Failed!", "Error!",
    			MB_ICONEXCLAMATION | MB_OK);
    		return 0;
    	}
    
    	ShowWindow(hwnd, nCmdShow);
    	UpdateWindow(hwnd);
    	while(GetMessage(&Msg, NULL, 0, 0) > 0)
    	{
    		TranslateMessage(&Msg);
    		DispatchMessage(&Msg);
    	}
    	return Msg.wParam;
    }
    Last edited by nutzu2010; 07-08-2011 at 02:33 AM.

  11. #11
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    By 'erase' I meant clear or return to a solid colour (ie paint the whole screen white again). I did not mean DeleteDC().

    Only do this if you want the line to be cleared each time the user presses the left mouse button (don't do this if you want multiple line showing at once).

    You are close....but need some changes.

    In CREATE
    remove the call to BeginPaint()

    In Close
    Before you DeleteDC(memDC) add a call to SelectObject(memDC,paintOld) to put the memDC back to the default state (ie return the original GDI objects)
    Remove the call to EndPaint()

    In PAINT
    Start with BeginPaint()
    Then BitBlt()
    Finally clean up with EndPaint()

    The only place you can call BeginPaint() is within the WM_PAINT msg handler (it will not work anywhere else).

    You MUST follow any BeginPaint() with an EndPaint() in teh SAME message.

    In the BitBlt() use ps.rcPaint.right-ps.rcPaint.left as width and ps.rcPaint.bottom - ps.rcPaint.top as height (not the total width). This reduces the area you draw and so speeds up the painting.

    On LButton down
    Erase the DC with FillRect() (optional)
    Capture the START point that the mouse was at (mouse coordinates when pressed). This may require a conversion from sceen to client coodinates (ScreenToClient() ) [recent thread discusses these different coords]

    On LButton UP
    Capture the END point (may require conversion as above)
    Draw a line from START to END with LineTo()
    Generate a PAINT msg with InvalidateRect() followed by UpdateWindow()




    Once you have those bits working look at drawing while the mouse moves.
    Last edited by novacain; 07-10-2011 at 07:55 PM. Reason: Clarity
    "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

  12. #12
    Registered User
    Join Date
    Dec 2010
    Posts
    71
    I'm sorry that I not posted earlier.Meanwhile I found your explanation and a code.In combination with Drawing Lines with the Mouse i can draw lines with mouse and the line remain after a minimise.

    Remains to do more examples to understand better.I managed to make a rectangle with mouse,now I want to make a triangle with the mouse.


    Thanks for the advice!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. redraw after minimize
    By Prads in forum Windows Programming
    Replies: 6
    Last Post: 03-21-2010, 11:16 AM
  2. Forcing Cursor Redraw
    By PJYelton in forum Windows Programming
    Replies: 4
    Last Post: 07-07-2003, 07:07 PM
  3. Control redraw issue.
    By Sebastiani in forum Windows Programming
    Replies: 1
    Last Post: 01-10-2003, 06:46 PM
  4. Graphic screen redraw
    By bob5845 in forum C++ Programming
    Replies: 0
    Last Post: 04-09-2002, 08:45 PM
  5. Dialog box redraw
    By SushiFugu in forum Windows Programming
    Replies: 6
    Last Post: 02-05-2002, 11:21 AM