ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

MFC 基础入门

2022-02-06 21:34:28  阅读:177  来源: 互联网

标签:MFC 窗口 入门 WINAPI 基础 int hInstance wc NULL


windows底层 API 是由C语言写的,而MFC则是在此基础上通过C++进行了封装。

要想利用MFC进行编程,那么就得从main方法开始
MFC的main函数C的写法是

温馨小提示:函数变量名如果带有p的一般都是指针,入参的时候的传地址

#include <Windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nShowCmd) {
	// 主程序内容。。。
}

下面是c++的写法

#include <Windows.h>

extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nShowCmd) {
	// 主程序内容。。。
}

需要注意的是MFC的函数得加上 宏定义WINAPI 表示参数的传递顺序,参数从右到左依次入栈,函数return前清空函数栈

  1. hInstance 当前音乐实例句柄
  2. hPrevInstance 上一个音乐程序句柄,在win32环境下一般为NULL
  3. lpCmdLine 类型LPTSTR 等同于 char* args[]
  4. nShowCmd 显示的命令 最大化、最小化、正常

写一个窗口程序主要分为

  1. 设计窗口
  2. 注册窗口
  3. 创建窗口
  4. 显示和更新
  5. 循环获取消息
  6. 处理消息

一、设计一个窗口

实际上windows已经把窗口封装成了一个结构体WNDCLASS,我们只需要对这个结构体内容进行补充,一个窗口类的信息就设置好了。
通过宏定义调整过去会发现结构体有下面这些内容

重复的内容不做额外解释

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;		// 显示的风格(最大化、最小化、0 是默认值)
    WNDPROC     lpfnWndProc;// ==>窗口过程的回调函数(消息回调)
    int         cbClsExtra; // 类的额外的内存
    int         cbWndExtra; // 窗口额外的内存
    HINSTANCE   hInstance;	// 应用程序实例句柄
    HICON       hIcon;		// 窗口上方的图标
    HCURSOR     hCursor;	// 光标,wc.hCursor = LoadCursor(NULL,IDC_HAND);第一个参数为NULL表示使用系统光标,第二个参数表示鼠标的形状(指针,小手等)
    HBRUSH      hbrBackground;	// 背景,一般使用白色刷(HBRUSH) GetStockObject(WHITE_BRUSH);
    LPCWSTR     lpszMenuName;	// 指定窗口类名称
    LPCWSTR     lpszClassName;	// 指定才当名称
} 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

二、注册窗口

温馨提示:在调用API的时候会发现有些方法带W 或 A,是由于编码导致API 不同所致,W是Unicode编码的、A是Ascii码编码的,实际上在使用的过程中没有太大区别

WNDCLASS wc;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);// 设置背景
// 注册窗口类
RegisterClass(&wc);

三、创建窗口

创建窗口的函数定义如下,这几个方法名称很相似,实际上使用起来基本上一直
W 与 A 的区别就子啊与编码的不同而已

#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

通过点击CreateWindow跳转过去会找到完整的定义

HWND CreateWindowW(
  [in, optional]  lpClassName, // 窗口类名字(带p表示指针),字符串char *
  [in, optional]  lpWindowName,// 窗口的名称(带p表示指针),字符串char *
  [in]            dwStyle,		// WS_OVERLAPPEDWINDOW 风格
  [in]            x,			// 显示窗口的坐标 CW_USEDEFAULT
  [in]            y,			// (x,y)是窗口左上角那个点
  [in]            nWidth,		// 窗口宽
  [in]            nHeight,		// 窗口高
  [in, optional]  hWndParent,	// 父窗口句柄,NULL
  [in, optional]  hMenu,		// 窗口菜单句柄,NULL
  [in, optional]  hInstance,	// 实例句柄hInstance(winMain传进来的那个)
  [in, optional]  lpParam		// 鼠标附加值,左右键
);

四、显示和更新窗口

五、循环获取消息

首先需要明白消息的结构内容,消息定义如下
消息结构体

#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) */

获取消息的函数

WINUSERAPI
BOOL
WINAPI
GetMessageA(
    _Out_ LPMSG lpMsg,
    _In_opt_ HWND hWnd,
    _In_ UINT wMsgFilterMin,
    _In_ UINT wMsgFilterMax);
WINUSERAPI
BOOL
WINAPI
GetMessageW(
    _Out_ LPMSG lpMsg,		// 返回的消息
    _In_opt_ HWND hWnd,		// 捕获哪一个窗口的消息,如果为NULL则是捕获所有窗口消息,并且 min 和 max 为0
    _In_ UINT wMsgFilterMin,// 想要捕获所有消息则 min 和 max 都设置为0
    _In_ UINT wMsgFilterMax);
#ifdef UNICODE
#define GetMessage  GetMessageW
#else
#define GetMessage  GetMessageA
#endif // !UNICODE

完整的通过MFC创建一个窗口并且弹出一条消息

#include <afx.h>
#include <Windows.h>
// 消息处理函数
LRESULT CALLBACK Wndproc(
        HWND hwnd, // 消息所属的窗口句柄
        UINT uMsg, // 具体消息名称 WM_XXXX 消息名
        WPARAM wparam,// 键盘附加消息
        LPARAM lparam // 鼠标附加消息
) {

    switch (uMsg) {
    	//点击关闭窗口的按钮,会发送一条WM_DESTROY消息
        case WM_CLOSE:
            DestroyWindow(hwnd);
            break;
        //处理销毁消息
        case WM_DESTROY:
            PostQuitMessage(0);//放弃后面所有消息(有结束窗口的含义)
            break;
        //鼠标左键弹起
        case WM_LBUTTONUP:
            //int x = LOWORD(lparam);
            //int y = HIWORD(lparam);
            //弹出一条消息对话框
            MessageBox(hwnd, TEXT("弹出的消息"), TEXT("弹出框的标题"),MB_OK);
            break;
       

    }
    // 默认的消息处理
    return DefWindowProc(hwnd,uMsg,wparam,lparam);
}

extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/,
                                LPTSTR /*lpCmdLine*/, int nShowCmd) {
    //1、定义窗口
    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、注册窗口
    RegisterClass(&wc);
    // 创建窗口,宽高都为300,窗口标题为demo
    HWND hwnd = CreateWindowW(wc.lpszClassName, TEXT("demo"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
                              300, 300, NULL, NULL, hInstance, NULL);
    //3、显示与更新窗口
    ShowWindow(hwnd, SW_SHOWNORMAL);
    UpdateWindow(hwnd);
    //4、循环获取消息
    MSG msg;
    while (true) {
        if (GetMessage(&msg, NULL, 0, 0) == FALSE) {
            break;
        }
        // 翻译消息
        TranslateMessage(&msg);
        // 分发消息
        DispatchMessage(&msg);
    }

    return 0;
}

标签:MFC,窗口,入门,WINAPI,基础,int,hInstance,wc,NULL
来源: https://blog.csdn.net/qq_41813208/article/details/122780582

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有