WinMain函数
WinMain 是用于应用程序入口点的传统名称。当windows系统启动程序时,调用的就是WinMain程序
int __clrcall WinMain(
[in] HINSTANCE hInstance,//应用程序当前实例句柄
[in] HINSTANCE hPrevInstance,//应用程序上一个实例句柄
[in] LPSTR lpCmdLine,//应用程序的命令行,不包括程序名称。
[in] int nShowCmd//控制窗口的显示方式。
);
创建窗口
1.设计一个窗口类
一个完整的窗体具有图标、背景、光标等特征。对于win32程序,可以通过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, *NPWNDCLASSA, *LPWNDCLASSA;
style
窗体类风格
lpfnWndProc
指向窗口过程的指针。必须使用CallWindowProc函数来调用窗口过程。在应用程序中定义的回调函数,用于处理发送到窗口的消息。
hInstance
包含类的窗口过程的实例的句柄。
hIcon
类图标的句柄。此成员必须是图标资源的句柄。如果此成员为NULL,系统将提供默认图标。
hCursor
类游标的句柄。此成员必须是游标资源的句柄。如果此成员为NULL,则每当鼠标移动到应用程序的窗口中时,应用程序必须显式设置光标形状。
lpszMenuName
类菜单的资源名称,如果此成员为NULL,则属于此类的窗口没有默认菜单。
lpszClassName
窗体类名称
窗口设计完成后,需要使用RegisterClass对其进行注册,注册成功后,才可以进行创建。就像汽车生产,需要有关部门注册审批后才可以进行生产
2.创建窗口
设计好窗口并且注册成功后,就需要用CreateWindow函数创建窗口
HWND CreateWindowExA(
[in] DWORD dwExStyle,
[in, optional] LPCSTR lpClassName,//注册的窗体类名称
[in, optional] LPCSTR lpWindowName,//窗体名称
[in] DWORD dwStyle,//窗体样式
[in] int X,//窗体水平位置
[in] int Y,//窗体垂直位置
[in] int nWidth,//窗体宽度
[in] int nHeight,//窗体高度
[in, optional] HWND hWndParent,//父窗体句柄
[in, optional] HMENU hMenu,//菜单句柄
[in, optional] HINSTANCE hInstance,//实例句柄
[in, optional] LPVOID lpParam//窗体创建数据指针
);
如果lpClassName是字符串,则指定窗口类名。类名可以是用RegisterClass或RegisterClassEx注册的任何名称,前提是注册该类的模块也是创建窗口的模块。类名也可以是任何预定义的系统类名。
hMenu
菜单的句柄,或指定子窗口标识符,具体取决于窗口样式。对于重叠或弹出窗口,hMenu标识要与窗口一起使用的菜单;如果要使用类菜单,则可以为NULL。对于子窗口,hMenu指定子窗口标识符,一个由对话框控件用于通知其父窗口事件的整数值。应用程序确定子窗口标识符;对于具有相同父窗口的所有子窗口,它必须是唯一的。
3.显示窗口
窗口创建后,需要进行显示
消息循环
程序的执行机制可以分为两类,一类是过程驱动,按照实现编辑好的流程按部就班的执行。一类是事件驱动,每个事件的发生都是随机的,针对不同的事件执行不同的处理流程。
win32程序是基于事件驱动的程序。系统事件和用户事件会产生消息,,创建窗口会触发WM_CREATE消息,绘制窗口会触发WM_PAINT消息,我们点击鼠标、键盘、都会触发相应的消息。
BOOL GetMessage(
[out] LPMSG lpMsg,//消息结构体地址
[in, optional] HWND hWnd,//窗体句柄
[in] UINT wMsgFilterMin,//最先的消息
[in] UINT wMsgFilterMax//最后的消息
);
BOOL TranslateMessage(
[in] const MSG *lpMsg
);
LRESULT DispatchMessage(
[in] const MSG *lpMsg
);
编写一个消息循环,不断的从消息队列中取出消息并且进行响应
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GetMessage在收到WM_QUIT消息后返回0,此时退出循环,程序才可以结束,否则程序就通过这个while循环来保证程序始终处于运行状态!
窗口过程函数
DispatchMessage 函数调用消息目标窗口的窗口过程。窗口过程函数的形式:
参数分别是窗体句柄,消息代码和消息代码的两个附加参数
典型的窗口过程只是一个在消息代码上切换的大型 switch 语句。 添加要处理的每个消息的事例。
例子:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
//窗体创建完成消息处理
...
break;
case WM_TIMER:
//定时器消息处理
...
break;
case WM_PAINT:
//窗体重绘消息
...
break;
case WM_DESTROY:
//销毁
PostQuitMessage(0);
break;
default:
//如果不在窗口过程中处理特定消息,请将消息参数直接传递给 DefWindowProc 函数。 此函数对消息执行默认操作,该操作因消息类型而异
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
使用VS建立第一个Win32程序
建立项目
新建Win32项目

选择windows应用程序,空项目,点击完成

右键项目,添加,新建项,选择C++文件,建立一个源程序文件

编写ANSI字符集程序
项目,属性,配置属性,常规,字符集,选择多字节字符集

编辑代码
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const char CLASS_NAME[] = "Sample Window Class";
WNDCLASSA wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClassA(&wc);
// Create the window.
HWND hwnd = CreateWindowExA(
0, // Optional window styles.
CLASS_NAME, // Window class
"My first window", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// All painting occurs here, between BeginPaint and EndPaint.
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
编译运行,效果

Unicode字符集程序
项目,属性,配置属性,常规,字符集,选择Unicode字符集

代码
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASSW wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClassW(&wc);
// Create the window.
HWND hwnd = CreateWindowExW(
0, // Optional window styles.
CLASS_NAME, // Window class
L"My first window", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// All painting occurs here, between BeginPaint and EndPaint.
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
编译运行即可