// 涉及到的函数/结构(部分),不清楚用法的,直接查msdn
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
);
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
HWND CreateWindow(
LPCTSTR lpClassName, // registered class name
LPCTSTR lpWindowName, // window name
DWORD dwStyle, // window style
int x, // horizontal position of window
int y, // vertical position of window
int nWidth, // window width
int nHeight, // window height
HWND hWndParent, // handle to parent or owner window
HMENU hMenu, // menu handle or child identifier
HINSTANCE hInstance, // handle to application instance
LPVOID lpParam // window-creation data
);
typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG, *PMSG;
// 一个简单的Win32应用程序
#include <windows.h>
// 声明窗口过程函数
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
// 定义一个全局变量,作为窗口类名
TCHAR szClassName[] = TEXT("SimpleWin32");
// 应用程序主函数
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR plCmdLine,
int nCmdShow)
{
// 1)设计窗口类
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc; // 关联窗口过程函数
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance; // 实例句柄
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 图标
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); // 光标
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 画刷
wndclass.lpszMenuName = NULL; // 菜单
wndclass.lpszClassName = szClassName; // 类名称
// 2)注册窗口类
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT ("RegisterClass Fail!"),
szClassName, MB_ICONERROR);
return 0;
}
// 3)建立窗口
HWND hwnd = CreateWindow(szClassName, // 窗口类名称
TEXT("The Simple Win32 Application"), // 窗口标题
WS_OVERLAPPEDWINDOW,// 窗口风格,即通常我们使用的windows窗口样式
CW_USEDEFAULT, // 指定窗口的初始水平位置,即屏幕坐标系的窗口的左上角的X坐标
CW_USEDEFAULT, // 指定窗口的初始垂直位置,即屏幕坐标系的窗口的左上角的Y坐标
CW_USEDEFAULT, // 窗口的宽度
CW_USEDEFAULT, // 窗口的高度
NULL, // 父窗口句柄
NULL, // 窗口菜单句柄
hInstance, // 实例句柄
NULL);
// 4)显示更新窗口
ShowWindow(hwnd, nCmdShow);// 显示窗口
UpdateWindow(hwnd); // 更新窗口
// 消息循环
MSG msg;
BOOL bRet;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) //从消息队列中取消息
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg); // 转换消息
DispatchMessage(&msg); // 派发消息
}
}
/* while(true)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // 从消息队列中取消息
{
// handle the error and possibly exit
if (bRet == -1)
return -1;
if (msg.message == WM_QUIT)
break;
TranslateMessage (&msg); // 转换消息
DispatchMessage (&msg); // 派发消息
}
else
{
WaitMessage();
}
}*/
return msg.wParam;
}
// 消息处理函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
// 当用户关闭窗口,窗口销毁,程序需结束,发退出消息,以退出消息循环
PostQuitMessage(0);
break;
default:
// 其他消息交给由系统提供的缺省处理函数
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
总结
1、窗口创建的过程
(1)设计窗口类;
(2)注册窗口类;
(3)建立窗口;
(4)显示更新窗口。
2、函数调用约定(Calling convention)
__stdcall与__cdecl是两种不同的函数调用约定,定义了函数参数入栈的顺序,由调用函数还是被调用函数将参数弹出栈,以及产生函数修饰名的方法。Win32的API函数遵循__stdcall调用约定。在VC++开发环境中,默认的编译选项是cdecl,对于那些遵循__stacall调用约定的函数,在声明时需要显式地加上。
(_cdecl是C Declaration的缩写,表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不需要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。
_stdcall是Standard Call的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回后清除,称为自动清栈。函数在编译的时候就必须确定参数个数,并且调用者必须严格的控制参数的生成,不能多,不能少,否则返回后会出错。
PASCAL约定和C约定正好相反,它规定参数是从左向右传递,由被调用者恢复堆栈。Win16采用了PASCAL约定, 因为PASCAL约定产生的代码量要小。)
参考:《VC++深入详解》孙鑫
虽大部分内容是copy,但也算是一种总结提炼吧!希望坚持!