Introduction to MFC Basics

Posted by wgordonw1 on Sun, 06 Feb 2022 20:09:20 +0100

The underlying API of windows is written by C language, and MFC is encapsulated by C + +.

If you want to program with MFC, you have to start with the main method
The main function C of MFC is written as

Warm tip: if the function variable name has p, it is generally the pointer and the address when entering the parameter

#include <Windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nShowCmd) {
	// Main program content...
}

The following is the writing method of c + +

#include <Windows.h>

extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nShowCmd) {
	// Main program content...
}

It should be noted that MFC functions have to add macro definitions. WINAPI indicates the transfer order of parameters. Parameters are stacked from right to left, and the function stack is cleared before function return

  1. hInstance current music instance handle
  2. The handle of a music program on hPrevInstance is generally NULL in win32 environment
  3. lpCmdLine type LPTSTR is equivalent to char* args []
  4. nShowCmd displays the commands maximize, minimize, and normal

The main program is divided into one window

  1. Design window
  2. Registration window
  3. create a window
  4. Display and update
  5. Loop get message
  6. Processing messages

1, Design a window

In fact, windows has encapsulated the window into a structure WNDCLASS. We only need to supplement the content of this structure and set the information of a window class.
After adjusting the macro definition, you will find that the structure has the following contents

There is no additional explanation for repeated contents

typedef struct tagWNDCLASSA {
    UINT        style;
    WNDPROC     lpfnWndProc;
    int         cbClsExtra;
    int         cbWndExtra;
    HINSTANCE   hInstance;
    HICON       hIcon;
    HCURSOR     hCursor;
    HBRUSH      hbrBackground;
    LPCSTR      lpszMenuName;
    LPCSTR      lpszClassName;
} WNDCLASSA, *PWNDCLASSA, NEAR *NPWNDCLASSA, FAR *LPWNDCLASSA;
typedef struct tagWNDCLASSW {
    UINT        style;		// Display style (maximize, minimize, 0 is the default)
    WNDPROC     lpfnWndProc;// ==>Callback function of window procedure (message callback)
    int         cbClsExtra; // Class
    int         cbWndExtra; // Window extra memory
    HINSTANCE   hInstance;	// Application Instance Handle 
    HICON       hIcon;		// Icon above window
    HCURSOR     hCursor;	// Cursor, WC hCursor = LoadCursor(NULL,IDC_HAND); The first parameter is null, indicating the use of the system cursor, and the second parameter indicates the shape of the mouse (pointer, small hand, etc.)
    HBRUSH      hbrBackground;	// Background, generally use white brush (HBRUSH) GetStockObject(WHITE_BRUSH);
    LPCWSTR     lpszMenuName;	// Specifies the name of the window class
    LPCWSTR     lpszClassName;	// Specify the proper name
} WNDCLASSW, *PWNDCLASSW, NEAR *NPWNDCLASSW, FAR *LPWNDCLASSW;
#ifdef UNICODE
typedef WNDCLASSW WNDCLASS;
typedef PWNDCLASSW PWNDCLASS;
typedef NPWNDCLASSW NPWNDCLASS;
typedef LPWNDCLASSW LPWNDCLASS;
#else
typedef WNDCLASSA WNDCLASS;
typedef PWNDCLASSA PWNDCLASS;
typedef NPWNDCLASSA NPWNDCLASS;
typedef LPWNDCLASSA LPWNDCLASS;
#endif // UNICODE

2, Registration window

Warm tip: when calling API, you will find that some methods have w or A, which is caused by different APIs due to coding. W is encoded in Unicode and A is encoded in Ascii. In fact, there is no big difference in the process of using

WNDCLASS wc;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);// Set background
// Register window class
RegisterClass(&wc);

3, Create window

The function of creating a window is defined as follows. The names of these methods are very similar. In fact, they are basically used all the time
The difference between W and A is just the difference between sub ah and code

#define CreateWindowA(lpClassName, lpWindowName, dwStyle, x, y,\
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)\
CreateWindowExA(0L, lpClassName, lpWindowName, dwStyle, x, y,\
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)
#define CreateWindowW(lpClassName, lpWindowName, dwStyle, x, y,\
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)\
CreateWindowExW(0L, lpClassName, lpWindowName, dwStyle, x, y,\
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)
#ifdef UNICODE
#define CreateWindow  CreateWindowW
#else
#define CreateWindow  CreateWindowA
#endif // !UNICODE

Click create window to jump to the past and find the complete definition

HWND CreateWindowW(
  [in, optional]  lpClassName, // Window class name (with p for pointer), string char*
  [in, optional]  lpWindowName,// Name of the window (with p for pointer), string char*
  [in]            dwStyle,		// WS_OVERLAPPEDWINDOW style
  [in]            x,			// Display the coordinates of the window CW_USEDEFAULT
  [in]            y,			// (x,y) is the point in the upper left corner of the window
  [in]            nWidth,		// Window width
  [in]            nHeight,		// Window height
  [in, optional]  hWndParent,	// Parent window handle, NULL
  [in, optional]  hMenu,		// Window menu handle, NULL
  [in, optional]  hInstance,	// Instance handle hinstance (the one passed in from WinMain)
  [in, optional]  lpParam		// Mouse added value, left and right keys
);

4, Display and update windows

5, Loop get message

First, you need to understand the structure and content of the message. The message definition is as follows
Message structure

#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)

/*
 * Message structure
 */
typedef struct tagMSG {
    HWND        hwnd;
    UINT        message;
    WPARAM      wParam;
    LPARAM      lParam;
    DWORD       time;
    POINT       pt;
#ifdef _MAC
    DWORD       lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */

Function to get message

WINUSERAPI
BOOL
WINAPI
GetMessageA(
    _Out_ LPMSG lpMsg,
    _In_opt_ HWND hWnd,
    _In_ UINT wMsgFilterMin,
    _In_ UINT wMsgFilterMax);
WINUSERAPI
BOOL
WINAPI
GetMessageW(
    _Out_ LPMSG lpMsg,		// Returned message
    _In_opt_ HWND hWnd,		// Which window message is captured? If it is NULL, all window messages are captured, and min and max are 0
    _In_ UINT wMsgFilterMin,// To capture all messages, set min and max to 0
    _In_ UINT wMsgFilterMax);
#ifdef UNICODE
#define GetMessage  GetMessageW
#else
#define GetMessage  GetMessageA
#endif // !UNICODE

Complete through MFC to create a window and pop up a message

#include <afx.h>
#include <Windows.h>
// Message processing function
LRESULT CALLBACK Wndproc(
        HWND hwnd, // The window handle to which the message belongs
        UINT uMsg, // Specific message name WM_XXXX message name
        WPARAM wparam,// Keyboard additional message
        LPARAM lparam // Mouse attached message
) {

    switch (uMsg) {
    	//Clicking the button to close the window will send a WM message_ Destroy message
        case WM_CLOSE:
            DestroyWindow(hwnd);
            break;
        //Process destroy message
        case WM_DESTROY:
            PostQuitMessage(0);//Discard all subsequent messages (meaning end window)
            break;
        //Left mouse button pops up
        case WM_LBUTTONUP:
            //int x = LOWORD(lparam);
            //int y = HIWORD(lparam);
            //A message dialog box pops up
            MessageBox(hwnd, TEXT("Pop up message"), TEXT("Title of pop-up box"),MB_OK);
            break;
       

    }
    // Default message handling
    return DefWindowProc(hwnd,uMsg,wparam,lparam);
}

extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/,
                                LPTSTR /*lpCmdLine*/, int nShowCmd) {
    //1. Define window
    WNDCLASS wc;
    wc.lpszClassName = TEXT("WINDEMO");
    wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
    wc.hCursor = LoadCursor(NULL, IDC_HAND);
    wc.hIcon = LoadIcon(NULL, IDI_ERROR);
    wc.hInstance = hInstance;
    wc.style = 0;
    wc.lpszMenuName = NULL;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.lpfnWndProc = Wndproc;
    //2. Registration window
    RegisterClass(&wc);
    // Create a window with width and height of 300, and the window title is demo
    HWND hwnd = CreateWindowW(wc.lpszClassName, TEXT("demo"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
                              300, 300, NULL, NULL, hInstance, NULL);
    //3. Display and update window
    ShowWindow(hwnd, SW_SHOWNORMAL);
    UpdateWindow(hwnd);
    //4. Loop get message
    MSG msg;
    while (true) {
        if (GetMessage(&msg, NULL, 0, 0) == FALSE) {
            break;
        }
        // Translate messages
        TranslateMessage(&msg);
        // Distribute messages
        DispatchMessage(&msg);
    }

    return 0;
}

Topics: C++ Windows MFC win10