Understanding the Order-of-Messages in the Win32 API is Very important IMHO.
I too, at one point in time, had about the same problem you're asking now. I did'nt know which messages were sent first and that really obscured me from advancing further into the API.
One very good way to figure this out is to use a File Stream, and print the messages to a '.txt' file everytime your Window Procedure recieves a Message.
A simple basic app like the one below will print the following (omitting the exit messages):
WM_CREATE
WM_SETFOCUS
WM_ERASEBKGND
WM_SIZE
WM_PAINT
As you can see, WM_CREATE is sent first. This is done when you call CreateWindow();. Then, WM_SETFOCUS is sent when you call ShowWindow(); and since the window is now visible on the screen, windows sends a WM_ERASEBKGND (to erase/paint the background with the specified background brush/color) message because the whole client area is INVALID. This is because the window was just created and nothing has yet been drawn/painted on it.
WM_ERASEBKGND message is followed by WM_SIZE. It is important that you know that WM_ERASEBKGND is usually sent before WM_SIZE and WM_PAINT. So saving the client dimensions to a static variable on WM_SIZE and using them in WM_ERASEBKGND will give you unwanted results, because, WM_SIZE has not yet been sent when you process the WM_ERASEBKGND.
Finally, WM_PAINT is sent. WM_PAINT is a low priority message, and because of this, this message is not processed untill all other messages in the message queue have been processed. Therefore, UpdateWindow is called right after ShowWindow. UpdateWindow causes the WM_PAINT message (If there's a WM_PAINT message in the message queue) to be sent IMMEDIATELY instead of untill all other messages have been processed.
Let me also emphasize that an application like this one, on a fairly decent computer, does'nt really need UpdateWindow() to be called right after ShowWindow() because today's computers can process Events lighting fast, and, you really would'nt see any delay in the client area being painted right after eraseing the client background in WM_ERASEBKGND. But, this is really not the case with more advanced, sophisticated appications, or games. An UpdateWindow() would almost certainly be crucial in this case to avoid the user see'ing a delay in painting.
I hope this has helped you. I don't know when WM_NCCREATE is sent as I have yet to deal with this particular message. But you can easily find this out with the technique I mentioned above =)
C and Win32 Code:
#include <windows.h>#include <stdio.h>TCHAR *szWinName = TEXT("3Com");LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);static int InitFile(void);FILE *fp;// pointer to a file streamint WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, TCHAR *szCmdLine, int iCmdShow){ static TCHAR szClassName[] = TEXT("3Com"); HWND hwnd; MSG msg; WNDCLASS wndclass; if ( !InitFile() ) // Initialize and open up the file for output { return 0; } wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hInstance = hInstance; wndclass.lpfnWndProc = WndProc; wndclass.lpszClassName = szClassName; wndclass.lpszMenuName = NULL; wndclass.style = CS_HREDRAW | CS_VREDRAW; if ( !RegisterClass(&wndclass) ) { MessageBox(NULL, TEXT("This Program Requires Windows NT!"), szWinName, MB_ICONEXCLAMATION); return 0; } if ( !(hwnd = CreateWindow(szClassName, szWinName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL)) ) { MessageBox(NULL, TEXT("CreateWindow() Failed!"), szWinName, MB_ICONEXCLAMATION); return 0; } ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while ( GetMessage(&msg, NULL, 0, 0) ) { TranslateMessage(&msg); DispatchMessage(&msg); } fclose(fp); // close the File stream [if you fail to close before exiting, file will not work] return msg.message;}LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam){ HDC hdc; RECT updRect; PAINTSTRUCT ps; TEXTMETRIC tm; static int cxClient, cyClient; static int cxChar, cxCaps, cyChar; switch ( iMsg ) { case WM_CREATE : fprintf(fp, "WM_CREATE\n"); hdc = GetDC(hwnd); GetTextMetrics(hdc, &tm); cxChar = tm.tmAveCharWidth; cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2; cyChar = tm.tmHeight + tm.tmExternalLeading; ReleaseDC(hwnd, hdc); return 0; case WM_SETFOCUS : fprintf(fp, "WM_SETFOCUS\n"); return 0; case WM_ERASEBKGND : fprintf(fp, "WM_ERASEBKGND\n"); hdc = GetDC(hwnd); GetUpdateRect(hwnd, &updRect, FALSE); FillRect(hdc, &updRect, (HBRUSH)GetStockObject(WHITE_BRUSH)); ReleaseDC(hwnd, hdc); return 1; case WM_SIZE : fprintf(fp, "WM_SIZE\n"); cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); return 0; case WM_PAINT : fprintf(fp, "WM_PAINT\n"); hdc = BeginPaint(hwnd, &ps); // do some drawing here... EndPaint(hwnd, &ps); return 0; case WM_KILLFOCUS : fprintf(fp, "WM_KILLFOCUS\n"); return 0; case WM_DESTROY : fprintf(fp, "WM_DESTROY\n"); PostQuitMessage(0); return 0; default : break; } return DefWindowProc(hwnd, iMsg, wParam, lParam);}static int InitFile(void){ if ( !(fp = fopen("C:\\Order of Messages.TXT", "a")) ) { MessageBox(NULL, TEXT("InitFile Failed!"), szWinName, MB_ICONEXCLAMATION); return 0; } return 1;}
relient.
[Edited by - xllx_relient_xllx on June 3, 2005 1:55:32 AM]