Why do I get abnormally high processor use on this simple program?

Dear all,

I simply can't figure out what I am doing wrong. Why is processor use on this program at maximum? What did I mess up?

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <windows.h>
 
HINSTANCE hInst;	
char szIndicatorWindowClass[]= "IndicatorWindow1";	
char szTitleIndicatorWindow[]= "I will eat your RAM";	

LRESULT CALLBACK	WndProcIndicatorWindow(HWND, UINT, WPARAM, LPARAM);
int APIENTRY IndicatorWindow(HINSTANCE hInstance,HINSTANCE hPrevInstance,
     LPTSTR lpCmdLine,int nCmdShow);
int WINAPI WinMain( HINSTANCE hModule, HINSTANCE unused, 
          PSTR cmd, int show )
{	hInst=hModule;
	IndicatorWindow(hModule,0,0,show);
	return TRUE;
}

HWND hWindowMain;

int APIENTRY IndicatorWindow( HINSTANCE hInstance,
HINSTANCE hPrevInstance,LPTSTR lpCmdLine,	int nCmdShow)
{ MSG msg;
  WNDCLASSEX wcex={sizeof(wcex)};// set first member, zero the rest
  wcex.style         = CS_HREDRAW|CS_VREDRAW;
  wcex.lpfnWndProc   = WndProcIndicatorWindow;
  wcex.hInstance     = hInstance;
  wcex.hCursor       = LoadCursor( NULL, IDC_ARROW );
  wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  wcex.lpszMenuName  = szIndicatorWindowClass;
  wcex.lpszClassName = szIndicatorWindowClass;
  RegisterClassEx( &wcex );
  hWindowMain = CreateWindow(szIndicatorWindowClass, szTitleIndicatorWindow, 
    WS_OVERLAPPEDWINDOW, 50, 50, 100,
    100, NULL, NULL, hInstance, NULL);
  if (!hWindowMain)
  { return FALSE;
  }
  ShowWindow(hWindowMain, nCmdShow);
  UpdateWindow(hWindowMain);   
  ::SendMessage(hWindowMain,WM_PAINT,0,0);
  while (GetMessage(&msg, NULL, 0, 0))
  { TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return (int) msg.wParam;
}


LRESULT CALLBACK WndProcIndicatorWindow(HWND hWnd, 
  UINT message, WPARAM wParam, LPARAM lParam)
{ switch (message)
  {
    case WM_CREATE:
      break;
    case WM_CTLCOLORSTATIC:
      break;
    case WM_SIZING:
      break;
    case WM_PAINT: 
      break;
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    default:
    return DefWindowProc(hWnd, message, wParam, lParam);
  }
  return 0;
}


P.S. this is a chopped-down version of my actual program.
Thanks a lot for helping me resolve this!
Last edited on
It might be down to your handling of the WM_PAINT message.
closed account (z05DSL3A)
In the case of the code posted, as guestgulkan said, it is the handling of WM_PAINT, try the following for comparison:
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
LRESULT CALLBACK WndProcIndicatorWindow(HWND hWnd, 
  UINT message, WPARAM wParam, LPARAM lParam)
{ 
  PAINTSTRUCT ps;
  HDC hdc;
  switch (message)
  {
    case WM_CREATE:
      break;
    case WM_CTLCOLORSTATIC:
      break;
    case WM_SIZING:
      break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code here...
        EndPaint(hWnd, &ps);
      break;
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    default:
    return DefWindowProc(hWnd, message, wParam, lParam);
  }
  return 0;
}


How are you handling WM_PAINT in the actual program?

Edit:
If you are using Visual Studio, Have a look under it's start menu location for Visual Studio Tools and see if you have Spy++ installed. You can use this tool to look at what messages are being posted to your software. if you use it on your code in your original post you will see your program being bombarded with WM_PAINT messages.
Last edited on
your program being bombarded with WM_PAINT messages.

Technically, it's not being "bombarded." There is only one (at most) WM_PAINT message in the queue at a time. However, it is never being removed so it keeps being retrieved by GetMessage. Another way to deal with it is to pass it to DefWindowProc whose default processing will remove it.
I thought you were always supposed to call DefWindowProc for all messages after you do your own processing. Otherwise really weird stuff starts happening.
Thanks to all of you! I chose Hammurabi's solution:
pass it to DefWindowProc
.

@Disch I didn't know that for DefWindowProc. Maybe that explains some weird redrawing behavior I got with my program...

So I get it: when you get a WM_PAINT message in your message queue, you must process (i.e. remove it) it to stop Windows from calling your WndProc over and over again. That is done for you by the BeginPaint - EndPaint sequence. Which of those two (if any) removes the WM_PAINT message from the message queue?
Windows makes rects "dirty" indicating they need redrawing. As long as there is at least 1 dirty rect, Windows will keep sending WM_PAINT messages.

EndPaint validates the window (removes all dirty rects). But you shouldn't call EndPaint without a matching call to BeginPaint.

Another way to validate the window is with ValidateRect(hWnd,NULL);

EDIT:

I realize I may be contradicting Hammurabi. He's probably correct in that there's only one WM_PAINT in the queue -- I simply said that "Windows keeps sending it" because that's easiest to visuaize, even though it isn't technically correct.
Last edited on
closed account (z05DSL3A)
WM_PAINT is a bit of an odd message, GetMessage doesn't really take it out of the queue. It remains 'valid' while the client area is marked as invalid. Calling BeginPaint followed by EndPaint will mark the client area as valid.

DefWindowProc simply calls BeginPaint and EndPaint in succession so that the client area is validated.

Disch, I don't think you have always call DefWindowProc.
I thought you were always supposed to call DefWindowProc for all messages after you do your own processing.

Nope. From MSDN:

The DefWindowProc function calls the default window procedure to provide default processing for any window messages that an application does not process.

http://msdn.microsoft.com/en-us/library/ms633572.aspx
I stand corrected! Good to know.
The two idioms I've seen for a WindowProc are as follows. They both only call DefWindowProc if they don't otherwise process the message.

1
2
3
4
5
6
7
switch( msg ){
case WM_WHATEVER:
    // ...
    break;
default: return DefWindowProc(...);
}
return 0;


1
2
3
4
5
6
switch( msg ){
case WM_WHATEVER:
    // ...
    return 0;
}
return DefWindowProc(...);

Topic archived. No new replies allowed.