孙鑫VC笔记.CHM
孙鑫VC笔记.CHM一.Windows程序内部运行原理1.关于消息和消息队列系统将每个事件都包装成一个称为消息的结构体MSG来传递给应用程序,MSG结构定义如下:typedef struct tagMsg{ HWND hwnd; UINT message; //消息种类,以WM_开头的一些消息 WPARAM wParam;//这两个是消息的补充 LPARAM lParam; DWORD time; //消息被投递post的时间 POINT pt; //这是一个点数据(结构体,有x、y),记录投递消息时光标cursor的屏幕坐标coordinate}MSG;2.windows程序的入口WinMain函数int WINAPI WinMain(HINSTANCE hInstance, // handle to current instance当前运行的实例句柄HINSTANCE hPrevInstance,// handle to previous instance 先前运行的实例句柄LPSTR lpCmdLine, // command line;lp开头(long pointer) 表示指针,str表示字符串;这里是命令行参数int nCmdShow // show state窗口显示状态(最大化、最小化……));(可以在运行里面输入notepad.exe 1.txt传递一个参数)3.窗口的创建 需要经过下面四个操作步骤:·设计一个窗口类·注册窗口类·创建窗口·显示及更新窗口1)typedef struct _WNDCLASS { UINT style; //可以设为CS_HREDRAW,即窗口水平坐标变化时窗口全部重画 WNDPROC lpfnWndProc; //回调函数(由系统调用),直接将函数名赋给此参数(即函数指针) int cbClsExtra; //为窗口类分配附加内存空间(所有属于这个窗口类的窗口共享) int cbWndExtra; //窗口实例附加内存空间 HANDLE hInstance; HICON hIcon; //用LoadIcon赋值 HCURSOR hCursor;//用LoadCursor HBRUSH hbrBackground; //画刷背景,这里用GetStockObject()获取,它参数是系统带的。如:=(HBRUSH)GetStockObject(BLACK_BRUSH),这里有强制类型转换 LPCTSTR lpszMenuName; //CT=constant……菜单名 LPCTSTR lpszClassName; //窗口类名} WNDCLASS; 经常会遇到一类变量,其每一位bit都对应某一种属性(1有0无),系统定义了一些常量(宏定义),只有一位为1,其余为0。若要同时用这几种特性,则用或运算|;要去掉某一特征,用取反~之后再进行与运算&即实现。(or有;and not取消,类似VB)HICONLoadIcon( HINSTANCE hInstance, //若加载标准图标则为NULL(系统自带的,如IDI_APPLICATION) LPCTSTR lpIconName);HGDIOBJ GetStockObject(__inint fnObject);2)然后用RegisterClass(&wndcls)注册窗口类ATOM RegisterClass( CONST WNDCLASS *lpWndClass);3)再用hwnd=CreateWindow()创建窗口HWND CreateWindow( LPCTSTR lpClassName,//窗口类名,必须是先前设计的 LPCTSTR lpWindowName, //窗口名字 DWORD dwStyle,//窗口样式window styles,如WS_OVERLAPPEDWINDOW,若想去掉最大化按钮(加个&~WS_MAXIMIZEBOX) int x,//窗口初始位置,可设置为CW_USEDEFAULT,这样就忽略y的值了 int y, int nWidth,//宽度,也可用CW_USEDEFAULT int nHeight, HWND hWndParent,//父窗口句柄,没有则为NULL HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam //作为WM_CREATE消息的参数lParam);4)显示窗口ShowWindowBOOL ShowWindow( HWND hWnd, int nCmdShow//窗口状态,如SW_SHOWMAXIMIZED);之后用UpdateWindow(hwnd)刷新窗口,这里可有可无4.获取消息GetMessageBOOL GetMessage( //获取到WM_QUIT消息时,返回值为0;其他为非0值 LPMSG lpMsg, HWND hWnd, //为NULL时表示属于当前线程的所有消息 UINT wMsgFilterMin,//最低的消息值 UINT wMsgFilterMax //最高消息值); 消息循环: while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); //将按键消息(KEYDOWN/KEYUP和对应字符的扫描码)转换成WM_CHAR消息 DispatchMessage(&msg); //派送消息,将消息发送给窗口程序 } return 0;5.窗口程序:LRESULT CALLBACK WindowProc( //窗口名可随意取,这里CALLBACK其实就是__stdcall(标准调用格式,宏定义的)HWND hwnd, // handle to windowUINT uMsg, // message identifierWPARAM wParam,// first message parameterLPARAM lParam // second message parameter){ switch(uMsg) { case WM_CHAR: //按下按键 char szChar; sprintf(szChar,"char is %d",wParam);//格式化文本到一个内存区(buffer) MessageBox(hwnd,szChar,"weixin",0); break; case WM_LBUTTONDOWN: MessageBox(hwnd,"mouse clicked","weixin",0); HDC hdc; hdc=GetDC(hwnd); TextOut(hdc,0,50,"计算机编程语言培训",strlen("计算机编程语言培训")); ReleaseDC(hwnd,hdc); break; case WM_PAINT: HDC hDC; PAINTSTRUCT ps; hDC=BeginPaint(hwnd,&ps); TextOut(hDC,0,0,"维新培训",strlen("维新培训")); EndPaint(hwnd,&ps); break; case WM_CLOSE: if(IDYES==MessageBox(hwnd,"是否真的结束?","weixin",MB_YESNO)) { DestroyWindow(hwnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); } return 0;}6.所用其他函数分析:1)int MessageBox( HWND hWnd, LPCTSTR lpText,//显示的文本(存放到一个字符数组,或直接用“”括起输出字符) LPCTSTR lpCaption,//标题 UINT uType// 样式,如MB_OK=0(方便就写0)/MB_OKCANCEL);返回值有:IDOK,IDNO,IDYES……2)画图、输出先用GetDC:HDC GetDC(__inHWND hWnd//窗口句柄,若为NULL则返回整个屏幕的DC(device context设备上下文、环境));再用TextOut输出文本:BOOL TextOut(__inHDC hdc,__inint nXStart, //这两者是文本输出的开始坐标__inint nYStart,__inLPCTSTR lpString,//输出的文本__inint cbString //输出的字符个数);注意最后要释放DC:用ReleaseDCint ReleaseDC(__inHWND hWnd, __inHDC hDC);3)WM_PAINT消息(窗口加载、窗口移动时窗口要重绘)先用 HDC hdc;PAINTSTRUCT ps; hdc=BeginPaint(hwnd,&ps) //在重绘时获取DCHDC BeginPaint(__in HWND hwnd,__outLPPAINTSTRUCT lpPaint //这里是PAINTSTRUCT变量的指针,如&ps);使用(如TextOut(hdc,0,0,"维新培训",strlen("维新培训")))完之后,要用EndPaint释放DCBOOL EndPaint(__inHWND hWnd,__inconst PAINTSTRUCT *lpPaint);这里BeginPaint和EndPaint只能用WM_PAINT消息中4)WM_CLOSE(窗口即将关闭时的消息) if(IDYES==MessageBox(hwnd,"是否真的结束?","weixin",MB_YESNO)) { DestroyWindow(hwnd); }经验:在条件测试的时候,一般把常量(IDYES)写在前面,不容易出错BOOL DestroyWindow( //销毁窗口,程序还没退出,它会发送WM_DESTROY消息和WM_NCDESTROY消息 HWND hWnd);5)WM_DESTROY//窗口销毁void PostQuitMessage( //投递一个WM_QUIT消息给这个线程的消息队列 int nExitCode //它用来当做WM_QUIT消息的wParam);6)其它消息:default: return DefWindowProc(hwnd,uMsg,wParam,lParam); //默认的窗口程序7.用VC编写:1)选择win32 application工程(选择空工程)2)添加C++源文件3)包含头文件:#include "windows.h" #include "stdio.h"4) 写WinMain函数,可查msdn int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);5)在WinMain函数中设计一个窗口类{ WNDCLASS wndcls; wndcls.cbClsExtra=0; wndcls.cbWndExtra=0; wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); wndcls.hIcon=LoadIcon(NULL,IDI_APPLICATION); wndcls.hCursor=LoadCursor(NULL,IDC_ARROW); wndcls.hInstance=hInstance; wndcls.lpfnWndProc=WinSunProc; wndcls.lpszClassName="first"; wndcls.lpszMenuName=NULL wndcls.style=CS_HREDRAW | CS_VREDRAW;}6)在WinMain中注册窗口类 RegisterClass(&wndcls);7)创建窗口HWND hwnd;hwnd=CreateWindow("first","我第一个窗口",WS_OVERLAPPEDWINDOW,USER_DEFAULT,0,0,USER_DEFAULT,NULL,NULL,hInstance,NULL);8)显示窗口 ShowWindow(hwnd,SW_SHOWNORMAL); UpdateWindow(hwnd);9)消息循环 MSG msg; while(GetMessage(&msg,NULL,0,0) //获取到WM_QUIT消息时才退出循环,注意这里是NULL表示接受所有消息 { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; //winmain返回010)窗口过程LRESULT CALLBACK WindowProc( //注意改名WinSunProc,和申明 HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch(uMsg) { case WM_CHAR: break; case WM_LBUTTONDOWN: break; case WM_PAINT: break; case WM_CLOSE: break; case WM_DESTROY: break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); } return 0;}11)编写具体过程:1.WM_CHAR: char szChar; sprintf(szChar,"asc is %d",wParam); MessageBox(hwnd,szChar,"MyFirst",0); 2.WM_PAINT: PAINTSTRUCT ps; HDC hdc; hdc=BeginPaint(hwnd,&ps); TextOut(hdc,0,0,"painting...",strlen("painting...")); EndPaint(hwnd,&ps); break;3.WM_CLOSE: if(IDYES==MessageBox(hwnd,"exit?","MyFirst",MB_YESNO)) { DestroyWindow(hwnd); } break;4.WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); } return 0; 好东东啊,哈哈 不错,感谢无私和分享精神! 这样也行。。。? 支持楼主、楼主英明啊!!! 我看一下,先说谢谢了 不错,感谢无私和分享精神! LZ帖子不给力,勉强给回复下吧 鼎力支持!! 真是被感动的痛哭流涕……
页:
[1]