I am a beginner with limited level. I write blog mainly to record my learning track. Refer to msdn for code introduction. If there are errors or omissions, please criticize and correct. Thank you for reading!
1. Basic understanding of Windows programming
The simplest windows programming calls some user state API s in windows, mostly user32 dll GDI32. DLL functions in these two library files.
MFC is a class library to C++ Class encapsulates Windows API And includes an application framework to reduce the workload of developers. The classes included include a large number of Windows handle encapsulation classes and many Windows built-in control and assembly Encapsulation class for. MFC is WIN API Combined with C + +, it is not only a page development system, but also contains many classes. The function of many classes is not an interface class. It does not realize the control of a window object. Some classes are processed inside windows.
2. Understanding process of basic framework
After understanding the basic knowledge of c language, the author tries to read the basic framework code.
Each c language program has its own main function, and the based win32 program has WinMain function as the entry point of the program. The basic code is as follows
int CALLBACK WinMain( _In_ HINSTANCE hInstance, //handle to the current instance _In_ HINSTANCE hPrevInstance, //handle to the previous instance _In_ LPSTR lpCmdLine, // command line of the application _In_ int nCmdShow // control how the window to be shown );
In winmain, create the struct of WNDCLASSEX, which contains the basic information of a window. The basic code is as follows
WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
After that, you need to register the window (its meaning is a bit similar to writing function definitions before the main program). The basic code is as follows
if (!RegisterClassEx(&wcex)) { MessageBox(NULL, _T("Call to RegisterClassEx failed!"), _T("Win32 Guided Tour"), NULL); return 1; }
After registering the window, we can create the window. The return value of create window is HWND, handle to the window, which is used to track the window.
static TCHAR szWindowClass[] = _T("win32app"); static TCHAR szTitle[] = _T("Win32 Guided Tour Application"); // The parameters to CreateWindow explained: // szWindowClass: the name of the application // szTitle: the text that appears in the title bar // WS_OVERLAPPEDWINDOW: the type of window to create // CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y) // 500, 100: initial size (width, length) // NULL: the parent of this window // NULL: this application does not have a menu bar // hInstance: the first parameter from WinMain // NULL: not used in this application HWND hWnd = CreateWindow( szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 100, NULL, NULL, hInstance, NULL ); if (!hWnd) { MessageBox(NULL, _T("Call to CreateWindow failed!"), _T("Win32 Guided Tour"), NULL); return 1; }
Then we show this window and let it update
// The parameters to ShowWindow explained: // hWnd: the value returned from CreateWindow // nCmdShow: the fourth parameter from WinMain ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd);
Next, add a message loop to retrieve window related messages from the message queue, and send the received messages to WndProc for processing
window application is a message based programming mode, which uses events to drive programming mode. The so-called message loop is actually a program loop that receives messages from the message queue, retrieves messages, and sends them to WndProc.
MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam;
In addition, we also need a windows procedure function. We are used to calling it WndProc. The basic code is as follows
LRESULT CALLBACK WndProc( _In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam );
In windows programs, when an event occurs, WinProc is used to handle an event. The pattern inside is similar to a switch. There are multiple case s in it. Different responses are made according to the received messages.
Examples are as follows:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: // Initialize form InitGame(hWnd, wParam, lParam); break; case WM_KEYDOWN: // Keyboard press event KeyDown(hWnd, wParam, lParam); break; case WM_KEYUP: // Keyboard release event KeyUp(hWnd, wParam, lParam); break; case WM_MOUSEMOVE: // Mouse movement event MouseMove(hWnd, wParam, lParam); break; case WM_LBUTTONDOWN: // Left mouse button press event LButtonDown(hWnd, wParam, lParam); break; case WM_LBUTTONUP: // Left mouse button release event LButtonUp(hWnd, wParam, lParam); break; case WM_TIMER: // timer event if (currentStage != NULL && currentStage->timerOn) TimerUpdate(hWnd, wParam, lParam); break; case WM_PAINT: // mapping Paint(hWnd); break; case WM_DESTROY: //sign out PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
3.little pieces
(1) Double buffer drawing
WM in WndProc encountered by the author in his study_ Paint function, which involves double buffer drawing.
Because in WM_ In paint, when drawing graphics, the program responds quite frequently. Every time OnEraseBKgnd is executed, the image on the original screen must be erased, then filled with background color, and finally redrawn. This will not only cause the problem that the drawing takes too long, but also cause flickering on the screen during the drawing process. Therefore, we thought of drawing the picture into the memory buffer first, and then using BitBlt to copy it to the screen. BitBlt is fast, so it can display the picture on the screen as a whole. The example code is as follows
void Paint(HWND hWnd) { PAINTSTRUCT ps; HDC hdc_window = BeginPaint(hWnd, &ps); HDC hdc_memBuffer = CreateCompatibleDC(hdc_window); HDC hdc_loadBmp = CreateCompatibleDC(hdc_window); //Initialize cache HBITMAP blankBmp = CreateCompatibleBitmap(hdc_window, WINDOW_WIDTH, WINDOW_HEIGHT); SelectObject(hdc_memBuffer, blankBmp); // Draw background to cache SelectObject(hdc_loadBmp, bmp_Background); BitBlt(hdc_memBuffer, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, hdc_loadBmp, 0, 0, SRCCOPY); //need to do // Finally, draw all the information on the screen BitBlt(hdc_window, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, hdc_memBuffer, 0, 0, SRCCOPY); // Reclaim memory occupied by resources (very important) DeleteObject(blankBmp); DeleteDC(hdc_memBuffer); DeleteDC(hdc_loadBmp); // End drawing EndPaint(hWnd, &ps); }
To be updated