> 文章列表 > windows编程(1)-第一个窗口程序

windows编程(1)-第一个窗口程序

windows编程(1)-第一个窗口程序

文章首发于:My Blog 欢迎大佬们前来逛逛

1. main函数入口点

win32的main函数入口点为 WinMain或者wWinMain,他们包含四个参数:

int __clrcall WinMain([in] HINSTANCE hInstance,[in] HINSTANCE hPrevInstance,[in] LPSTR     lpCmdLine,[in] int       nShowCmd
);

其中:

  • hInstance:应用程序当前窗口的实例句柄
  • hPrevInstance:应用程序上一个窗口的实例句柄
  • lpCmdLine:应用程序的命令行
  • nShowcmd:控制窗口的显示方式

其中wWinMain与WinMain的区别是 wWinMain适用于多字节字符集,而WinMian适用于unicode字符集。

其中第三个参数WinMain是LPSTR类型:

typedef char CHAR;

但是wWinMain是LPWSTR类型:

typedef wchar_t WCHAR; 

2. 窗口函数六部曲

2.1 注册窗口类

ATOM RegisterClassExA([in] const WNDCLASSEXA *unnamedParam1
);

其中:

  • unnamedParam1:一个WNDCLASSEXA结构体指针变量,这个结构包含了我们所创建对象的窗口的属性信息
struct tagWNDCLASSEXW {UINT        cbSize; 		/* Win 3.x */UINT        style;WNDPROC     lpfnWndProc;int         cbClsExtra;int         cbWndExtra;HINSTANCE   hInstance;HICON       hIcon;HCURSOR     hCursor;HBRUSH      hbrBackground;LPCWSTR     lpszMenuName;LPCWSTR     lpszClassName;/* Win 4.0 */HICON       hIconSm;
}

其中:比较重要的几个参数:

  • hInstance:窗口的示例句柄,就是我们的WinMain包含的hInstance参数
  • lpszClassName:窗口类名
  • cbSize:结构体的大小,必须指定其为sizeof(WNDCLASSEX)
  • style:窗口类的样式,设置水平与垂直重绘:CS_HREDRAW | CS_VREDRAW
  • hbrBackground:窗口回调函数,其接受一个WNDPROC的参数,WNDPROC是一个typedef定义的函数指针,其中包含四个参数:HWND UINT WPARAMS LPARAMS。
//回调函数m_WNDPROC:lpfnWndProc的数据类型
LRESULT CALLBACK m_WNDPROC(HWND hwnd, UINT msg, WPARAM wParams, LPARAM lParams) {return DefWindowProc(hwnd, msg, wParams, lParams);
}//使用return DefWindowProc作为返回值WNDCLASSEX mWinC = {NULL};
mWinC.cbSize = sizeof(WNDCLASSEX);
mWinC.hInstance = hInstance;
mWinC.lpszClassName = "我的第一个窗口";
mWinC.hbrBackground = (HBRUSH)NULL; //画刷
mWinC.lpfnWndProc = m_WNDPROC;
mWinC.style = CS_HREDRAW | CS_VREDRAW;
//注册窗口类
RegisterClassEx(&mWinC);

2.2 创建窗口

HWND CreateWindowExA(DWORD dwExStyle,LPCSTR lpClassName,LPCSTR lpWindowName,DWORD dwStyle,int X,int Y,int nWidth,int nHeight,HWND hWndParent,HMENU hMenu,HINSTANCE hInstance,LPVOID lpParam);

其中:重要的参数有:

  • dwExStyle:设置为mWinC的style即可。
  • lpClassName,lpWindowName:类名与窗口名
  • dwStyle:窗口的样式,设置为WS_OVERLAPPEDWINDOW即可。
  • x y Width Height:窗口的大小和宽高
  • hInstance:窗口的实例句柄。
HWND hwnd =  CreateWindowEx(mWinC.style,mWinC.lpszClassName,"First Window",WS_OVERLAPPEDWINDOW,100, 100, 600, 600,NULL, NULL,mWinC.hInstance,NULL);
if (!hwnd) return false;

其返回值为HWND,表示创建了一个窗口句柄hwnd,如果其为NULL,则创建失败。

2.3 显示窗口

BOOL ShowWindow([in] HWND hWnd,[in] int  nCmdShow
);
  • hwnd:创建的窗口实例句柄
  • nCmdshow:控制窗口的显示方式
ShowWindow(hwnd, SW_SHOW);

2.4 刷新窗口

UpdateWindow(hwnd);

2.5 消息循环

  1. 接受消息
//从调用线程的消息队列中检索消息。 
BOOL GetMessage([out]          LPMSG lpMsg,[in, optional] HWND  hWnd,[in]           UINT  wMsgFilterMin,[in]           UINT  wMsgFilterMax
);

参数:

  • lpMsg:指向MSG的指针,我们需要创建一个MSG类型的变量表示消息变量

  1. 处理消息
//将虚拟密钥消息转换为字符消息。
BOOL TranslateMessage([in] const MSG *lpMsg
);
  • lpMsg:消息指针

  1. 发送消息
//将消息调度到窗口过程。 
LRESULT DispatchMessage([in] const MSG *lpMsg
);
  • 消息指针

// 消息循环
MSG msg{ NULL };
while (true) {//接收消息GetMessage(&msg, NULL, NULL, NULL);//处理消息TranslateMessage(&msg);//发送消息DispatchMessage(&msg);
}

2.6 消息处理函数

消息处理函数即:WNDPROC

我们已经在 2.1 注册窗口类时处理过了。

//消息处理函数
LRESULT CALLBACK m_WNDPROC(HWND hwnd, UINT msg, WPARAM wParams, LPARAM lParams) {return DefWindowProc(hwnd, msg, wParams, lParams);
}
...
...
wMinC.lpfnWndProc=m_WNDPROC
...
...

3. 完整代码

由于我们运行的时Win32程序,我们应该在:

项目 - 属性 - 连接器 - 系统 - 子系统

控制台改为窗口

#include <Windows.h>//回调函数
LRESULT CALLBACK m_WNDPROC(HWND hwnd, UINT msg, WPARAM wParams, LPARAM lParams) {return DefWindowProc(hwnd, msg, wParams, lParams);
}int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR cCmdLine,int nShowCmd
) {// 注册窗口类WNDCLASSEX mWinC = {NULL};mWinC.cbSize = sizeof(WNDCLASSEX);mWinC.hInstance = hInstance;mWinC.lpszClassName = "我的第一个窗口";mWinC.hbrBackground = (HBRUSH)NULL;mWinC.lpfnWndProc = m_WNDPROC;mWinC.style = CS_HREDRAW | CS_VREDRAW;RegisterClassEx(&mWinC);// 创建窗口类HWND hwnd =  CreateWindowEx(mWinC.style,mWinC.lpszClassName,"First Window",WS_OVERLAPPEDWINDOW,100, 100, 600, 600,NULL, NULL,mWinC.hInstance,NULL);if (!hwnd) return false;// 显示窗口类ShowWindow(hwnd, SW_SHOW);// 刷新窗口类UpdateWindow(hwnd);// 消息循环MSG msg{ NULL };while (true) {//接收消息GetMessage(&msg, NULL, NULL, NULL);//处理消息TranslateMessage(&msg);//发送消息DispatchMessage(&msg);}return true;
}