最初了解Windows api编程呢,就是先创建出一个最简洁的窗口,就如我们学习C/C++时的"Helloword"一样,这是进入windows编程大门的重要一个步,下面就开始吧...
大家都知道C/C++中,程序的执行是从main()函数开始的,main()是整个程序的入口函数,是不可或缺的。同样,windows编程中,也是有入口函数的,不过这里不是main,而是WinMain(),Win表示windows窗口,并且所创建的工程类型也是不同的,大家之前写C/C++,创建的工程可能是win32控制台应用程序,这里呢,需要创建的是win32项目,如下:
创建工程时,点击下一步,选择空项目,如下图选择:
创建好工程之后呢,我们创建一个.c或者.cpp文件就可以了
工程的创建过程,明确了之后呢,下面就先将所需要用到的步骤和Function给稍微列举解释下:
第一步:
创建一个窗口类WNDCLASS 的对象wndclass,并且为wndclass进行初始化赋值操作,这一步非常重要,后面会详细说下。
第二步:
注册窗口类:RegisterClass(WNDCLASS lpWndClass),通过判断该函数的返回值是否为0,非0成功。
第三步:
创建窗口:HWND CreateWindow( DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam ),这个函数会创建出来一个窗口,但是呢,这里创建出来的窗口,还处于不可见的状态,只是在内存中已经创建出来了,接下来还需要显示出来。
第四步:
显示窗口:ShowWindow(HWND hwnd, int iCmdShow);
第五步:
更新窗口:UpdateWindow(HWND hwnd),发送一些初始消息,更新GDI等
第六步:
每个窗口都有一个自己的窗口消息队列,里面存放了需要处理的窗口消息,接下来就是建立一个窗口的消息循环,在窗口退出之前一直处于工作状态,不断的从消息队列中获取消息,获取消息的函数是:
BOOL GetMessage( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax );
该函数需要在while()中执行,如while(GetMessage(&msg, NULL, 0, 0)),这是最简单的写法,我们这里就使用这个就可以了。
第七步:
在GetMessage()获取到消息是虚拟键消息,需要进行处理,调用TranslateMessage(MSG *lpMsg),这个函数的功能是将虚拟键消息转换成字符消息通俗说就是翻译消息。
第八步:
TranslateMessage()之后呢,需要对消息进行派发,将每个消息发送到相应的需要到达的目标窗口或控件,派发函数:
LRESULT DispatchMessage(MSG *lpMsg);
至此呢,创建窗口的主要步骤已经完成了,但是我们还需要创建一个窗口的回调函数,在初始化窗口类的时候,是需要有这个回调函数的,这个回调函数将被windows系统进行回调。回调函数的格式必须按照如下格式:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
通常来说在创建窗口类的时候,就应该先把这个函数写出来,好了,接下来,就上代码喽
#include
//窗口回调函数声明
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
/*
函数名:WinMain:入口函数
参数:
hInstance是windows传递的窗口句柄
hPrevInstance是这个窗口的前一个窗口的句柄,目前没有用,只是为了兼容以前的版本
szCmdLine是传递进来的命令行命令,这里没有使用
iCmdShow指定的窗口的显示方式如:显示,隐藏等。
*/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("HelloWin"); //创建窗口的时候需要一个窗口类名
HWND hwnd; //创建窗口函数CreateWindow()会返回一个HWND句柄,这里定义下,用来接收这个句柄
MSG msg; //消息结构体,在消息循环的时候需要
WNDCLASS wndclass; //创建窗口类对象
//对窗口类的各属性进行初始化
wndclass.style = CS_HREDRAW | CS_VREDRAW; /*窗口类的风格,CS前缀,C表示Class,S表示
Style,这里使用了水平和垂直风格*/
wndclass.lpfnWndProc = WndProc; /*这里将回到函数的名字赋值用以windows后面回调*/
wndclass.cbClsExtra = 0; //附加参数,通常情况下为0
wndclass.cbWndExtra = 0; //附加参数,通常情况下为0
wndclass.hInstance = hInstance; //窗口句柄,这里将WinMain中的hInstance句柄赋值就可
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); /*窗口图标,LoadIcon()是加载图标,这里是加载一个系统资源图标,LoadIcon()的原型是HICON LoadIcon(HINSTANCE, LPCSTR);*/
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); /*加载鼠标,同上相似*/
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); /*窗口画刷,这里是使用的白色画刷,所以创建出来的窗口的背景颜色则是白色的*/
wndclass.lpszMenuName = NULL; //窗口菜单名称,这里没有菜单,设为NULL
wndclass.lpszClassName = szAppName; //窗口类名称,这个窗口类名称可作为这个窗口的唯一标识
/*注册窗口类*/
if (!RegisterClass(&wndclass))
{
//注册窗口类失败时,弹出提示
MessageBox(NULL, TEXT("This program requires Window NT!"), szAppName, MB_ICONERROR);
return 0;
}
/*创建窗口
HWND CreateWindow(
LPCTSTR lpClassName, //窗口类名
LPCTSTR lpWindowName, //窗口标题
DWORD dwStyle, //窗口风格,WS开头
int x, //窗口左上角x坐标
int y, //窗口左上角y坐标
int nWidth, //窗口宽度
int nHeight, //窗口高度
HWND hWndParent, //父窗口句柄
HMENU hMenu, //菜单句柄
HANDLE hlnstance, //窗口句柄
LPVOID lpParam); //改值会传递给窗口WM_CREATE消息的一个参数
*/
hwnd = CreateWindow(szAppName, //窗口类名
TEXT("The Hello Program"), //窗口标题,会在窗口的左上角标题栏显示
WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL, //窗口风格
CW_USEDEFAULT, //窗口左上角x位置,这里使用的系统默认值,可自定义
CW_USEDEFAULT, //窗口左上角y位置
CW_USEDEFAULT, //窗口的宽度
CW_USEDEFAULT, //窗口的高度
NULL, //该窗口的父窗口或所有者窗口的句柄,这里用不到,设为NULL
NULL, //窗口菜单句柄,这里没有菜单,设置为NULL
hInstance, //窗口句柄
NULL //传递给窗口WM_CREATE消息的一个参数,这里不用,设置为NULL
);
/*显示窗口,显示方式使用WinMain的参数*/
ShowWindow(hwnd, iCmdShow);
/*更新窗口*/
UpdateWindow(hwnd);
/*消息循环,获取消息*/
while (GetMessage(&msg, hwnd, NULL, 0))
{
//翻译消息
TranslateMessage(&msg);
//派发消息
DispatchMessage(&msg);
}
//返回消息的wParam参数给系统
return msg.wParam;
}
/*窗口回调函数*/
LRESULT CALLBACK WndProc(HWND hwnd, UINT message/*窗口消息*/, WPARAM wParam, LPARAM lParam)
{
//处理消息
switch (message)
{
case WM_CREATE:
/*窗口在创建时,会接收到该消息,通常在这里进行初始化操作*/
return 0;
case WM_SIZE:
/*窗口被改变大小时,会接收到该消息,在窗口被创建时也会收到一次*/
return 0;
case WM_PAINT:
/*窗口有绘图操作更新时,会收到这个消息*/
return 0;
case WM_DESTROY:
/*关不窗口时,会收到该消息,PostQuitMessage()像系统表明终止当前线程,没有这个函数的话,窗口不会关闭*/
PostQuitMessage(0);
return 0;
}
//将不需要处理的消息传递给系统作默认处理
return DefWindowProc(hwnd, message, wParam, lParam);
}
通过以上代码就创建了一个简单的窗口
窗口类结构设置了窗口的各项属性,然后将初始化好的窗口类结构注册到系统中,让系统知道,我这里将要创建一个窗口,并且窗口属性是什么。
回调函数是硬性要求的,是必须的,系统会调用这个函数,而我们在则这个函数中作需要的操作
关于什么是回调函数,如果不太清楚的话,请看下面的连接了解下:
https://baike.baidu.com/item/%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0/7545973?fr=aladdin
好了,创建一个窗口就这样完成了,如果有错误或不对的地方,希望大家指正,谢谢。