Very Basic Window Update

Hey, I'm having a problem with a program I'm writing. This is my first time using Windows API and I'm unable to get the Window to "repaint" itself. Here is my WindowProc() function. Thanks in advance for any help with my problem or general advice you may have!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
        static bool bRedraw = false;

        // Message Interpretation
	switch (uMsg)
	{

	// In the case that the window is closed
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;

	// In the case that a key is pressed
        // This is where the problem is, I want to write out some text
        // (in this case WIN) when I hit enter while the window is in focus,
        // but when I do, nothing happens.
	case WM_KEYDOWN:
		switch (wParam)
		{
		// In the case which that key is enter
		case (VK_RETURN):
			bRedraw = true;
			SendMessage(hwnd, WM_PAINT, wParam, lParam);
			bRedraw = false;
			break;
		}
		return 0;

	// In the case that the window is drawn
	case WM_PAINT:
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hwnd, &ps);
		FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
		TextOut(hdc, 10, 10, L"Prospect Number:", 16);
		TextOut(hdc, 10, 34, L"Delete Code:", 12);
		TextOut(hdc, 10, 58, L"Current Delete Code:", 20);
		if (bRedraw)
		{
			TextOut(hdc, 10, 82, L"WIN", 3);
		}
		EndPaint(hwnd, &ps);
		return 0;
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Never send WM_PAINT messages.

To force a redraw, you mark part (or all) of your client area as "dirty" with InvalidateRect. This will trigger Windows to send appropriate WM_PAINT messages automatically.

1
2
3
4
5
6
7
8
9
10
11
12
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//        static bool bRedraw = false;  <-  get rid of this

//...
		case (VK_RETURN):
//			bRedraw = true;
//			SendMessage(hwnd, WM_PAINT, wParam, lParam);
//			bRedraw = false;
			InvalidateRect( hwnd, NULL, TRUE );  // invalidate the entire client, which
				// will cause a full redraw
			break;



EDIT:

Details on InvalidateRect can be found here:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd145002%28v=vs.85%29.aspx
Last edited on
Thanks a lot for the response. I had tried InvalidateRect() after scouring Google, but it didn't cause any change. I did however take your advice of removing the static bool bRedraw and it caused the text to appear. I was assuming that sending the message caused the window to be redrawn straight away while I was just enabling and then immediately disabling my flag making the window not change as it was being updated.

I now have functional code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
	// In the case that a key is pressed
	case WM_KEYDOWN:
		switch (wParam)
		{
		// In the case which that key is enter
		case (VK_RETURN):
			bRedraw = true;
			InvalidateRect(hwnd, NULL, TRUE);
			break;
		}
		return 0;

	// In the case that the window is drawn
	case WM_PAINT:
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hwnd, &ps);
		FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
		TextOut(hdc, 10, 10, L"Prospect Number:", 16);
		TextOut(hdc, 10, 34, L"Delete Code:", 12);
		TextOut(hdc, 10, 58, L"Current Delete Code:", 20);
		if (bRedraw)
		{
			SetTextColor(hdc, RGB(255, 0, 0));
			TextOut(hdc, 10, 82, L"INVALID PROSPECT FORMAT", 23);
			bRedraw = false;
		}
		EndPaint(hwnd, &ps);
		return 0;


If you still suggest me removing the bool, what other way would be good to update if only when certain criteria are met (for now just enter)?
If you still suggest me removing the bool,


I do.

what other way would be good to update if only when certain criteria are met (for now just enter)?


WM_PAINT messages aren't sent for no reason. They're sent when the screen needs to be redrawn. If you don't redraw it when it needs to be redrawn it'll look weird.

If, for example, another window 'B' is placed in front of yours... then your window is brought back to the front. The part of your window that was behind window 'B' will need to be redrawn, so Windows will send your program a WM_PAINT message.

In that situation, your 'bRedraw' variable will be false, and therefore you will not be drawing properly to the screen. As such, you'll be able to change what is visible on-screen simply by moving the window around / minimizing+restoring / etc.


To see what I mean... in your case... run your program and press "Enter" to make the "Invalid prospect format" message come up. Then minimize your window and restore it. Notice how the message disappears.

For an even UGLIER example of what I mean... press "Enter" to get the message, then drag another window over yours so only half of the message is blocked. Then bring your program back to the front. Notice how you're left with only a half printed message. It makes the program look broken.


WM_PAINT should draw the scene in full. The logic that changes what is drawn should be done elsewhere. Rather than having a "redraw" flag... have a "print message" flag:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
	// In the case that a key is pressed
	case WM_KEYDOWN:
		switch (wParam)
		{
		// In the case which that key is enter
		case (VK_RETURN):
			bPrintMessage = true;  // logic update, indicating you now want the message printed
			InvalidateRect(hwnd, NULL, TRUE);
			break;
		}
		return 0;

	// In the case that the window is drawn
	case WM_PAINT:
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hwnd, &ps);
		FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
		TextOut(hdc, 10, 10, L"Prospect Number:", 16);
		TextOut(hdc, 10, 34, L"Delete Code:", 12);
		TextOut(hdc, 10, 58, L"Current Delete Code:", 20);
		if (bPrintMessage)   // if we want to print the message...
		{
			// print it...
			SetTextColor(hdc, RGB(255, 0, 0));
			TextOut(hdc, 10, 82, L"INVALID PROSPECT FORMAT", 23);
			// .. but do NOT update bPrintMessage here, as that is a logic change
			//   and is unrelated to drawing
		}
		EndPaint(hwnd, &ps);
		return 0;



You could then clear bPrintMessage through a logic change when the user does something else... like presses escape or something. But between the time of those logic updates... the message will still be printed no matter how many times the window is repainted. So you can minimize, drag other windows over it, resize, etc, etc and the scene will remain consistent as the user would expect.






Lastly... on a side note... you are using the wrong character type for your functions. You are passing wide strings (with the preceeding L) to functions which take TCHAR strings.

TCHAR strings are not wide strings. this is only working because your compiler settings are just so. If you want to use wide strings, you must call the 'W' form of WinAPI functions.... ie... TextOutW, and not TextOut.

For more info, I've made several posts about this... here are a few of them from a recent thread that you might find interesting:
http://v2.cplusplus.com/forum/windows/105027/#msg566862
http://v2.cplusplus.com/forum/windows/105027/#msg566904
I saw almost exactly what you said would happen and I fixed it. Thank you very much. I also changed TextOut to TextOutW.

With a bit of deviation, I would like to know one more thing. This message processing is being done for my main window. I however want the WM_KEYDOWN to be processed by one of two child textboxes. How would I either go about processing the child windows' messages through the main window (or if that is uncouth through their own message processing)? Would this require registering the textboxes and creating a second windowproc?
I however want the WM_KEYDOWN to be processed by one of two child textboxes.


You should just use a normal Edit Box control for text entry, rather than try to simulate one manually.

Unfortunately I can't help you here since I haven't created windows controls manually in forever.
I'll direct the few other questions I have elsewhere. This thread has been more helpful than I originally expected. Thanks so much!
Topic archived. No new replies allowed.