Windows应用程序简介

我准备从头开始好好学学MFC原理及应用,先从Win API开始学起,不仅要会用,知其然更要知其所以然,这样才能走的更远。

先讲一下Windows应用程序的消息机制,Windows 程序的进行是依靠外部发生的事件来驱动。程序循环等待输入,然后做出适当的处理。输入分为两类:一类是由硬件(鼠标键盘)产生的消息,加入系统消息队列(system queue)中;一类是由windows系统或其他windows程序传来的消息,加入程序消息队列(application queue)中。

比如我们点击鼠标,会产生一个硬件输入,USER模块捕捉到一个硬件事件,生成一个对应的消息加入系统消息队列中,Windows程序获取到该消息,翻译并接住USER模块分发给窗口过程并加以处理,这就是Windows程序消息机制的整个流程。

下面我来给大家展示一个简单的例子。

1、创建空的Windows项目,添加一个cpp文件,并包含windows.h头文件
#include <windows.h>
// 添加两个全局变量,方便使用
HINSTANCE _hInst; // instance 句柄
HWND _hWnd; // 窗口句柄

2、实现Windows程序的入口函数

//在控制台程序中,入口函数是main函数
//但在windows程序中,入口函数是WinMain函数
int CALLBACK WinMain(
HINSTANCE hInstance,
HINSTANCE hPreInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
// 注册窗口类
if(!InitApplication(hInstance)) return FALSE;
// 创建并显示窗口类
if(!InitInstance(hInstance, nShowCmd)) return FALSE;

// 循环获取消息
MSG msg;
while(GetMessage(&msg, NULL/*NULL表示捕捉所有窗口的消息*/, 0, 0)) {
    TranslateMessage(&msg); //翻译消息,对于组合键消息,需要先翻译,而不是分开分发
    DispatchMessage(&msg);  //分发消息
}

return 0;

}

3、注册窗口

BOOL InitApplication( HINSTANCE hInstance )
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW; //窗口显示风格
wc.lpfnWndProc = (WNDPROC)WndProc; // 窗口消息处理函数
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance; //应用程序实例句柄
wc.hIcon = LoadIcon(NULL/使用系统默认的图标/, IDI_ERROR); // 图标
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // 光标样式
wc.hbrBackground= (HBRUSH)GetStockObject(WHITE_BRUSH); // 窗口背景颜色
wc.lpszClassName= TEXT(“Test”); //窗口类名称
wc.lpszMenuName = TEXT(“TestMenu”); // 菜单资源名称
return RegisterClass(&wc); // 注册窗口
}

4、创建+显示窗口

BOOL InitInstance( HINSTANCE hInstance, int nShowCmd )
{
_hInst = hInstance;

_hWnd = CreateWindow(
    TEXT("Test"), //类名,注意此处类名必须和加载时的类名一致
    TEXT("TestWnd"),   //窗口名称
    WS_OVERLAPPEDWINDOW,    //窗口类型,边框,最大最小化等
    CW_USEDEFAULT,  //窗口位置和大小
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    NULL,   //父窗口柄
    NULL,   //菜单句柄
    hInstance,  //与窗口关联的模块实例的句柄
    NULL
    );

if(!_hWnd) return FALSE;

ShowWindow(_hWnd, nShowCmd);    //显示窗口
UpdateWindow(_hWnd);    //发送WM_PAINT消息
return TRUE;

}

5、循环获取消息并分发

int CALLBACK WinMain(
HINSTANCE hInstance,
HINSTANCE hPreInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
/*
Queued message structure
typedef struct tagMSG
{
HWND hwnd;
UINT message; // WM_xxx,例如WM_MOUSEMOVE,WM_SIZE…
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;
*/
//循环获取消息
MSG msg;
while(GetMessage(&msg, NULL/NULL表示捕捉所有窗口的消息/, 0, 0)) {
TranslateMessage(&msg); //翻译消息,对于组合键消息,需要先翻译,而不是分开分发
DispatchMessage(&msg); //分发消息

}

}
这部分代码在入口函数中已经有,但是这里在提出来强调一下。GetMessage函数循环从消息队列中获取消息并翻译分发,接下来便是处理消息。

6、窗口过程,处理消息
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
int wmId, wmEvent;

switch(message) {
    case WM_COMMAND:    //命令消息,对应控件产生的消息
        wmId = LOWORD(wParam);    //分离出低位的控件ID
        wmEvent = HIWORD(wParam);    //高位的事件类型
        break;

    case WM_CLOSE:    //右上角的x,关闭窗口
        DestroyWindow(hWnd);    //仅关闭窗口,没有关闭进程,并发送另一个消息WM_DESTROY
        break;

    case WM_DESTROY:    //摧毁窗口消息    
        PostQuitMessage(0);        //真正的关闭进程
        break;

    case WM_LBUTTONDOWN:    
    {
        //鼠标左键按下时,显示当前坐标
        int xPos = LOWORD(lParam);
        int yPos = HIWORD(lParam);
        char buff[1024];
        wsprintf(buff, TEXT("X = %d, Y = %d"), xPos, yPos);
        MessageBox(hWnd, buff, TEXT("鼠标左键按下"), MB_OK);
        break;
    }

    case WM_PAINT:    //在窗口绘制文字
    {
        PAINTSTRUCT ps;    //绘图结构体
        HDC hdc = BeginPaint(hWnd, &ps);    //画家
        TextOut(hdc, 100, 100, TEXT("HELLO"), strlen("HELLO"));
        EndPaint(hWnd, &ps);
        break;
    }

    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;

}

到这里,一个简单的Windows应用程序便编写完成了,由于没有添加控件,控件消息处理没有详细说明,后续补足。

大家可以尝试运行代码看看,结合注释一起理解一下。

参考文献:

《深入浅出MFC》侯捷版

原文链接,觉得有用请关注一下,谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值