【MFC】前奏 窗体程序初尝试

【MFC】前奏 窗体程序初尝试

下一篇
我最近在学MFC,但是在此之前学了一下直接用WINAPI来写win32窗体程序。
以下就是我直接用C语言调用WINAPI来写win32窗体程序了,详细的就不讲了,代码注释应该很清楚了。
之后我会将后面我学到的内容发布出来,希望能和其他小白新手一起进步。

需要注意的地方:
(1)

CreateWindowExW()//使用这个函数或者使用CreateWindow函数,
				//如果使用了CreateWindowExA()函数窗体程序不会报错但是也不会显示出来

(2)
这个PostQuitMessage(0)是起退出程序的作用,没有这个,即使销毁了窗体(点击右上角的叉叉),程序也不会退出。

case WM_DESTROY:
        PostQuitMessage(0);//发送程序退出消息
        break;

(3)
这些常量的意思可以去MicrosoftDoc查阅

IDI_APPLICATION
IDC_ARROW
CW_USEDEFAULT
WM_CLOSE
#include
//CALLBACK 代表 _stdcall 参数的传递顺序:从右到左以此入栈,并且在函数返回前清空堆栈
LRESULT CALLBACK WindowProc(
    HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam
);
//WINAPI 代表 _stdcall参数的传递顺序:从右到左以此入栈,并且在函数返回前清空堆栈
int WINAPI WinMain(
    HINSTANCE hInstance,//应用程序实例化句柄
    HINSTANCE hPrevInstance,//上一个应用程序句柄,一般为NULL。
    LPSTR lpCmdLine,//命令行参数 类似于 char *argv[]
    int nShowCmd//窗口显示命令,列如 最大化,最小化,正常
)
{
    /*
    步骤
    1、设置窗口
    2、注册窗口
    3、创建窗口
    4、显示和更新
    5、循环取消息
    6、处理消息(窗口过程)
    */
    HWND hwnd;//窗口句柄
    //1、设置窗口
    //WNDCLASS wc;
    //WNDCLASSEXA wcEXA;//窗口类
    WNDCLASS wcEXA;//窗口类
    //wcEX.hInstance
    wcEXA.cbClsExtra = 0;
    wcEXA.cbWndExtra = 0;
    wcEXA.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wcEXA.hCursor = LoadCursorA(NULL, IDC_ARROW);//设置光标//在LoadCursorA中,参数1为NULL表示使用系统默认光标,参数2 IDC_ARROW 表示标准箭头光标(其他可参考 MSDN )
    wcEXA.hIcon = LoadIconA(NULL, IDI_APPLICATION);//窗口图标//参数1为NULL表示使用系统默认图标,参数2 IDI_APPLICATION 表示默认应用图标
    wcEXA.hInstance = hInstance;//应用程序实例化句柄,传入WINMAIN 中的 hInstance 形参即可
    wcEXA.lpfnWndProc = WindowProc;//回调函数//指向应用程序定义的函数的指针,该字段称为窗口过程或“窗口过程 ”
    wcEXA.lpszClassName = TEXT("MyWindows");//指定窗口类名
    //wcEXA.lpszMenuName = TEXT("MyMenu");//指定菜单名称//不使用菜单则为 NULL
    wcEXA.lpszMenuName = NULL;//指定菜单名称//不使用菜单则为 NULL
    wcEXA.style = CS_HREDRAW | CS_VREDRAW;;//指定窗口风格//为0为默认样式

    //2、注册窗口(类)
    if (!RegisterClass(&wcEXA)) {
        MessageBox(NULL, TEXT("程序只能在windowsNT下运行"),
            TEXT("MyWindows"), MB_ICONERROR);
        return 0;
    }

    //3、创建窗口
    /*               CreateWindowExA函数的参数列表
        DWORD dwExStyle,                //窗口扩展风格 //WS_EX_OVERLAPPEDWINDOW
        LPCSTR lpClassName,             //类名
        LPCSTR lpWindowName,            //窗口标题名
        DWORD dwStyle,                  //窗口风格 //WS_CAPTION常量表示该窗口具有标题栏//WS_OVERLAPPEDWINDOW 
        int X,                          //窗口坐标x
        int Y,                          //窗口坐标y
        int nWidth,                     //窗口宽度
        int nHeight,                    //窗口高度
        HWND hWndParent,                //窗口的父窗口句柄
        HMENU hMenu,                    //窗口菜单
        HINSTANCE hInstance,            //窗口实例句柄
        LPVOID lpParam                  //附加值,一般为鼠标的附加值
    */
    
    hwnd=CreateWindowExW(
        WS_EX_OVERLAPPEDWINDOW,
        wcEXA.lpszClassName,
        TEXT("我的窗口"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL
    );
    //4、显示和更新
    ShowWindow(hwnd, nShowCmd);
    UpdateWindow(hwnd);

    //5、循环取消息
    /*    MSG(消息)类型的结构
    HWND        hwnd;       //窗口句柄
    UINT        message;    //消息标识符(消息名称)//应用程序只能使用低位字
    WPARAM      wParam;     //附加消息。确切含义取决于消息成员的值 。(一般为键盘消息)
    LPARAM      lParam;     //附加消息。确切含义取决于消息成员的值 。(一般为鼠标按键消息)
    DWORD       time;       //消息发布(产生)的时间。
    POINT       pt;         //消息发布时的光标位置,以屏幕坐标表示。(点的位置消息,如鼠标所在点)
    */
    MSG msg;//消息
    while (1)
    {
        /*      GetMessageW函数参数列表
            LPMSG lpMsg,            //MSG类型的指针
            HWND hWnd,              //提供指定窗口的窗口句柄,以捕获指定窗口的消息//NULL表示捕获当前线程所有窗口的消息//-1表示当前线程当前消息队列
            UINT wMsgFilterMin,     //最小的过滤消息,一般为0,0表示捕获消息队列中的所有消息
            UINT wMsgFilterMax);    //最大的过滤消息,一般为0,0表示捕获消息队列中的所有消息
        */
        if (GetMessage(&msg, NULL, 0, 0) == FALSE) {
            break;
        }
        //翻译消息
        TranslateMessage(&msg);
        //GetMessageW函数返回值不为FALSE则分发消息
        //分发消息
        DispatchMessage(&msg);
    }

    
    
    return msg.wParam;
}

//6、处理消息(窗口过程)
//CALLBACK 代表 _stdcall 参数的传递顺序:从右到左以此入栈,并且在函数返回前清空堆栈
LRESULT CALLBACK WindowProc(
    HWND hwnd,          //消息所处的窗口句柄
    UINT uMsg,          //具体的消息名称 一般名字格式为 WM_xxxxxx
    WPARAM wParam,      //键盘附加消息
    LPARAM lParam)      //鼠标附加消息
{
    switch (uMsg)
    {
    case WM_CLOSE:
        DestroyWindow(hwnd);//发送另一个消息 WM_DESTROY
        break;
    case WM_DESTROY:
        PostQuitMessage(0);//发送程序退出消息
        break;
    case WM_PAINT: {
        PAINTSTRUCT ps;//绘图结构体
        HDC hdc=BeginPaint(hwnd,&ps);//开始绘图
        TextOut(hdc, 10, 10, TEXT("hello"),strlen("hello"));
        EndPaint(hwnd, &ps);//结束绘图
    }
        break;
    default:
        break;
    }
    return DefWindowProc(hwnd,uMsg,wParam, lParam);//返回值使用默认处理方式
}




以下图片是上面代码编译执行后的结果
【MFC】前奏 窗体程序初尝试_第1张图片
最后有不对的地方欢迎大牛指正。

你可能感兴趣的:(学习MFC,c++,c语言)