// 涉及到的函数/结构(部分),不清楚用法的,直接查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,但也算是一种总结提炼吧!希望坚持!