先来板一板心得:首先win32的进入函数已经不再是控制台程序那时的main函数了,改为WinMain函数。
对于不懂的函数,不要找谁BB了,直接F1,看看它的原型,以及成员,从上到下成员排列的顺序就是下边介绍成员的顺序。
多注意 Parameter、Return Values、Remark下的东西。
每写一个函数或者一个鑫的东西,记得看括号里边的提示参数来写。
妈的,发现上辈子 MSDN 一定是拯救了世界啊 敢脚,太特么有用了,但是瞬敢自个儿的英文水平简直是渣爆小宇宙有木有啊,英文太特么滴重要了,继续努力吧!
欧敏鑫 代码笔记。Ready ,go!
#include
LRESULT CALLBACK WindowProc( HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);//回调函数 即 window procedure(窗口过程)
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
)
{
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = ::CreateSolidBrush(0x0000ff);
wc.hCursor = ::LoadCursor(NULL,IDC_ARROW);//第一个参数如果填了当前实例的话,那么意思就是找当前实例要一个光标,但是当前的实例我们
//我们并没有自定义的光标资源,所以应该填NULL,这样就是默认找操作系统要所选光标。
wc.hIcon = ::LoadIcon(NULL,IDI_QUESTION);// 里边的参数用法、意义跟cursor类似
wc.hInstance = hInstance;
wc.lpfnWndProc = WindowProc; // 看开头的缩写,l 就是 long 型,p 即 pointer,就是指针。fn 是fun的缩写,就是function,函数的意思。
// 所以就是函数指针,所以等号右边 肯定是个函数名。函数原型一定是WndProc 这个名字的,对WNDCLASS按F1找吧。
wc.lpszClassName = "aaaa";// 窗口类名字
wc.lpszMenuName = NULL; // 菜单命,菜单还没学,赋空先;
wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;// CS 就是 Class style的简写 简称CS。
// HREDRAW 是水平重绘,VREDRAW 是垂直重绘。
ATOM aTom = ::RegisterClass(&wc);
if(aTom == 0) return 0;
HWND hWnd = ::CreateWindow(wc.lpszClassName,"first blood",WS_OVERLAPPEDWINDOW,10,10,800,600,NULL,NULL,hInstance,NULL);
if(hWnd == NULL) return 0;
// dwstyle 是窗口的风格,而之前的CS style 是窗口类的风格,是不同的喔。dwstyle 可以设置是不是父窗口啊、子窗口啊,最小化啊,最小化框,
//就是右上角的那个框,有没有边框线啊......
// 按位与 就是 加起来。
// Remarks 备注
//CreateWindow 内部,在返回之前,会发送一个WM_CREATE 消息到窗口过程(回调函数)
::ShowWindow(hWnd,SW_SHOW); //显示 创建的窗口出来。
::UpdateWindow(hWnd);// 若之前showwindow不成功,那就强制显示 创建的窗口
//若此时没有消息循环,那么运行出来的窗口界面只会一闪而过,无停留
MSG msg;// MSG 是个结构体 可以用 . 什么什么
while(::GetMessage(&msg,NULL,0,0)) //WM_QUIT 返回false 另外: 单击窗口右上角的叉叉,会出发一个 WM_CLOSE 消息
{
// 第一个参数,就是获取消息队列里边的消息。第二个是应用程序,这里写空,就是获取所有应用程序(窗口)的消息。
//后两个是消息过滤的范围,但是不知道属于我的消息在哪个范围,所以写0,0,表示获取所有的消息,这样有
//我的消息的话,那就一定不会漏掉!
//只要 从消息队列 取出来的消息 不是WM_QUIT 这个消息,那么返回的 都是 真,就算队列是空的也返回真,检获到WM_QUIT 就返回假(0)。
//WindowProc(msg.hwnd,msg.message,msg.wParam,msg.lParam);// 获取消息后应该 处理消息,用回调函数处理.不过内部已经封装有一个函数,
//来调用回调函数:DispatchMessage(),所以也不用这样写了
::DispatchMessage(&msg); // 分配任务、派遣消息 函数。等价于上面的,但是不让像上面那样用,我们程序猿是要编写回调函数里边的代码,
// 而不是要这样显式的调用 回调函数。
}
//当我们关闭窗口时候,确实把窗口关掉了,但是任务管理器里边还是有程序的进程,因为消息循环还在循环,循环是因为它没有接受到WM_QUIT这
//条消息,所以一直在循环等待接受处理消息,没有停止,程序一直停留在 消息循环这一块转啊转。
return msg.wParam;
}
LRESULT CALLBACK WindowProc( HWND hWnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
switch(uMsg)
{
case WM_CREATE: // 这个WM_CREATE 是函数CreateWindow()函数 在返回之前 发给 回调函数 的一条消息。
break;
case WM_CLOSE: // 这就是单击右上角叉叉出发的消息,被截获,但是截获之后,没有具体的操作,因为代码没写,所以点叉叉,窗口不会有任何反应,
//关闭不了。
::DestroyWindow(hWnd);// 销毁窗口。如果不写 这个case WM_CLOSE,那么默认的回调函数也就会替你处理WM_CLOSE,调用类似销毁窗口的函数,
// 来关闭窗口.
//DestroyWindow(hWnd)函数执行后会发出两条消息给回调函数:WM_DESTROY,WM_NCDESTROY,即 先销毁了客户区,再销毁非客户区,因为之前是先
//创建非客户区,像边框啊什么的。再创建客户区. 类似之前创建 窗口时,也向回调函数 发送了一条WM_CREATE 信息一样。
break;
case WM_DESTROY: // 捕获 WM_DESTROY 消息, 再此来 实习 WM_QUIT 消息的发送,使得 消息循环 得以终止,真的实现结束程序。
::SendMessage(hWnd,WM_QUIT,0,0);//发送 WM_QUIT 消息,但是这个WM_QUIT太特殊,不要用这个send函数 发送,而是用PostQuitMessage()。
::PostQuitMessage(0); // 邮差函数,发送退出,使得 消息循环得以终结,程序得以完全退出.
default:
return ::DefWindowProc(hWnd,uMsg,wParam,lParam);
}
//所有检获到的消息都应该处理,就算不想处理,也得处理,但是就是不想处理怎么办呢?哈哈懒得黑纹啊~~o(∩_∩)o 那就交给系统处理!!!
return ::DefWindowProc(hWnd,uMsg,wParam,lParam);// Default windows procedure 默认的窗口过程。
return 0; // 先写个正确的返回值,保证程序的正确性,架构完整。不懂它什么返回值的,对准它然后 go to definition of 它。
}
// 当我们单击 程序右上角的叉叉时,会发出一个WM_CLOSE消息,然后被消息循环捕获到,再让回调函数去处理,此时就需要我们在回调函数里边写代码,
// 否则就是让操作系统来处理。就用上面的switch语句实现。