Windows学习心得【按钮控件】

来源:互联网 发布:如何创建网络软件公司 编辑:程序博客网 时间:2024/05/20 03:42
#include<windows.h>#define ID_SMALLER 1#define ID_LARGER 2#define BTN_WIDTH (8* cxChar)#define BTN_HEIGHT (4* cyChar)LRESULT CALLBACK WndProc(HWND ,UINT,WPARAM,LPARAM);//首先是一个回调函数的声明HINSTANCE hInst;int WINAPI WinMain(HINSTANCE hInstance,//应用程序当前实例的句柄   HINSTANCE hPrevInstance,//应用程序先前实例的句炳   PSTR szCmdLine,//指向命令行的指针   int iCmdShow)//指明窗口的显示方式{static TCHAR szAppName[]=TEXT("OwnDraw");MSG msg;//消息HWND hwnd;//句柄WNDCLASS wndclass;//类名hInst=hInstance;wndclass.style=CS_HREDRAW | CS_VREDRAW;//窗口的创建方式,在此为水平重画和竖直重画wndclass.cbClsExtra=0;//窗口类的扩展,此处为0wndclass.cbWndExtra=0;//窗口实例的扩展,此处为0wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);//设置窗口背景的颜色,在此处设置为白色wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);//设置光标的显示方式,此处设置为标准型wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);//设置窗口的显示类型,此处为应用程序类wndclass.hInstance=hInstance;//窗口的实例句柄wndclass.lpfnWndProc=WndProc;//回调函数wndclass.lpszClassName=szAppName;//类名wndclass.lpszMenuName=NULL;//菜单名,此处没有菜单故设置为NULLif(!RegisterClass(&wndclass))//创建窗口,若失败显示以下信息{MessageBox(NULL,TEXT("This program requires Windows NT!"),szAppName,MB_ICONERROR);return 0;}////创建窗口,如果函数成功,返回值为新窗口的句柄:如果函数失败,返回值为NULLhwnd=CreateWindow(szAppName,TEXT("Owner-Draw Button Demo"),//窗口的名字WS_OVERLAPPEDWINDOW,//指定创建窗口的风格CW_USEDEFAULT,//指定窗口的初始水平位置CW_USEDEFAULT,//指定窗口的初始垂直位置CW_USEDEFAULT,//以设备单元指明窗口的宽度。若是CW_USEDEFAULT,则系统为窗口选择一个缺省的宽度CW_USEDEFAULT,//以设备单元指明窗口的高度NULL,//指向被创建窗口的父窗口或所有者窗口的句柄,此处为NULLNULL,//菜单句柄,或依据窗口风格指明一个子窗口标识,此处为NULLhInstance,//与窗口相关联的模块实例的句柄NULL);//指向一个值的指针,该值传递给窗口WM_CREATE消息ShowWindow(hwnd,iCmdShow);//显示窗口,hWnd:指窗口句柄。iCmdShow:指定窗口如何显示UpdateWindow(hwnd);//更新窗口,hWnd:指窗口句柄while(GetMessage(&msg,NULL,0,0))//消息循环{TranslateMessage(&msg);//该函数将虚拟键消息转换为字符消息 DispatchMessage(&msg);//该函数分发一个消息给窗口程序}return msg.wParam;//wParam是消息携带的参数,可以是个值,也可以是个地址}void Triangle(HDC hdc,POINT pt[]){SelectObject(hdc,GetStockObject(BLACK_BRUSH));//设置画刷Polygon(hdc,pt,3);//该函数画一个由直线相连的两个以上顶点组成的多边形,用当前画笔画多边形轮廓,用当前画刷和多边形填充模式填充多边形//第一个参数为设备环境句柄//第二个参数为指向用于指定多边形顶点的POINT结构数组的指针//第三个参数为点的个数SelectObject(hdc,GetStockObject(WHITE_BRUSH));//设置画刷}LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){static HWND hwndSmaller,hwndLarger;static int cxClient,cyClient,cxChar,cyChar;int cx,cy;LPDRAWITEMSTRUCT pdis;//DRAWITEMSTRUCT结构为需要自绘的控件或者菜单项提供了必要的信息POINT pt[3];//定义点的结构体RECT rc;//rect结构定义了一个矩形框左上角以及右下角的坐标switch(message){case WM_CREATE://当一个应用程序创建窗口时,会通过消息处理函数cxChar=LOWORD(GetDialogBaseUnits());//GetDialogBaseUnits函数返回系统的对话基本单位,该基本单位为系统字体字符的平均宽度和高度cyChar=HIWORD(GetDialogBaseUnits());//同上//创建缩小控件的句柄hwndSmaller=CreateWindow(TEXT("button"),//类名TEXT(" "),//按钮名字,此处为空格,(这个值没太大意义)WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,//指定创建的风格 //WS_CHILD创建子窗口。不能用于WS_POPUP(创建一个弹出窗口)风格//WS_VISIBLE,创建一个窗口,最初是可见的//BS_OWNERDRAW创建一个自绘按钮0,//由于此处为按钮控件,此处为0(起始x坐标)0,//由于此处为按钮控件,此处为0(起始y坐标)BTN_WIDTH,//宽度BTN_HEIGHT,//高度hwnd,//父窗口的句柄(HMENU)ID_SMALLER,//此按钮句柄的标识hInst,//与窗口相关联的模块实例的句柄NULL);//指向一个值的指针,该值传递给窗口WM_CREATE消息//创建增大控件的句柄hwndLarger=CreateWindow(TEXT("button"),//类名TEXT(" "),//按钮名字,此处为空格,(这个值没太大意义)WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,//指定创建的风格//WS_CHILD创建子窗口。不能用于WS_POPUP(创建一个弹出窗口)风格//WS_VISIBLE,创建一个窗口,最初是可见的//BS_OWNERDRAW创建一个自绘按钮0,//由于此处为按钮控件,此处为0(起始x坐标)0,//由于此处为按钮控件,此处为0(起始y坐标)BTN_WIDTH,//宽度BTN_HEIGHT,//高度hwnd,//父窗口的句柄(HMENU) ID_LARGER,//此按钮句柄的标识hInst,//与窗口相关联的模块实例的句柄NULL);//指向一个值的指针,该值传递给窗口WM_CREATE消息return 0;case WM_SIZE://当主窗口的客户区部分大小改变时,我们的应用程序将接收到 WM_SIZE 消息。当然该窗口第一次显示时,我们也将接收到该消息cxClient=LOWORD(lParam);//获取窗口的宽度cyClient=HIWORD(lParam);//获取窗口的高度MoveWindow(hwndSmaller,cxClient/2-3*BTN_WIDTH/2,cyClient/2-BTN_HEIGHT/2,BTN_WIDTH,BTN_HEIGHT,TRUE);//MoveWindow函数改变指定窗口的位置和大小.//第一个参数为当前实例的句柄//第二个参数为左顶点的新x坐标//第二个参数为左顶点的新y坐标//第三个参数为新宽度//第四个参数为新高度//第五个参数为是否要重画MoveWindow(hwndLarger,cxClient/2+BTN_WIDTH/2,cyClient/2-BTN_HEIGHT/2,BTN_WIDTH,BTN_HEIGHT,TRUE);//参考上面的注释return 0;case WM_COMMAND://当用户点击菜单,按钮或下拉列表框等控件时,会触发该消息GetWindowRect(hwnd,&rc);//该函数返回指定窗口的边框矩形的尺寸。该尺寸以相对于屏幕坐标左上角的屏幕坐标给出switch(wParam){case ID_SMALLER:rc.left+=cxClient/20;rc.right-=cxClient/20;rc.top+=cyClient/20;rc.bottom-=cyClient/20;break;//若单击缩小按钮,则将窗口尺寸减小百分之10//以上算法为重算新的窗口位置和大小case ID_LARGER:rc.left-=cxClient/20;rc.right+=cxClient/20;rc.top-=cyClient/20;rc.bottom+=cyClient/20;break;//若单击增大按钮,则将窗口尺寸增大百分之10//以上算法为重算新的窗口位置和大小}MoveWindow(hwnd,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,TRUE);//移动主窗口return 0;case WM_DRAWITEM://一般此消息在控件需要重画时发出,在收到此消息之后控件才会执行重画pdis=(LPDRAWITEMSTRUCT)lParam;//lParam参数是一个指针,指向一个LPDRAWITEMSTRUCT类型的结构//然后保存在变量pdis中,这个结构存有必要的信息来帮助程序绘制按钮//这里有必要说明一下这个结构里面比较重要的几个几个参数//hDc按钮设备环境//rcItem为RECT结构,提供按钮的尺寸//CtlID为控件窗口的ID//itemState,它显示按钮是否按下或有输入焦点FillRect(pdis->hDC,&pdis->rcItem,(HBRUSH)GetStockObject(WHITE_BRUSH));//FillRect函数用指定的画刷填充矩形,此函数包括矩形的左上边界,但不包括矩形的右下边界//pdis->hDC设备环境句柄。//&pdis->rcItem指向含有将填充矩形的逻辑坐标的RECT结构的指针//(HBRUSH)GetStockObject(WHITE_BRUSH)用来填充矩形的画刷的句柄FrameRect(pdis->hDC,&pdis->rcItem,(HBRUSH)GetStockObject(BLACK_BRUSH));//FrameRect函数用指定的画刷为指定的矩形画边框。边框的宽和高总是一个逻辑单元//&pdis->rcItem指向含有将填充矩形的逻辑坐标的RECT结构的指针////(HBRUSH)GetStockObject(BLACK_BRUSH)用来填充矩形的画刷的句柄cx=pdis->rcItem.right-pdis->rcItem.left;//获取按钮的宽度cy=pdis->rcItem.bottom-pdis->rcItem.top;//获取按钮的高度switch(pdis->CtlID){case ID_SMALLER://画出按钮里面的四个三角形//下面的算法用处就是分别获取每个三角形在按钮内的位置然后调用函数来绘画pt[0].x=3*cx/8;pt[0].y=1*cy/8;pt[1].x=5*cx/8;pt[1].y=1*cy/8;pt[2].x=4*cx/8;pt[2].y=3*cy/8;Triangle(pdis->hDC,pt);//调用Triangle函数来画三角形pt[0].x = 7 * cx / 8 ;  pt[0].y = 3 * cy / 8 ;            pt[1].x = 7 * cx / 8 ;  pt[1].y = 5 * cy / 8 ;            pt[2].x = 5 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;Triangle(pdis->hDC,pt);pt[0].x = 5 * cx / 8 ;  pt[0].y = 7 * cy / 8 ;            pt[1].x = 3 * cx / 8 ;  pt[1].y = 7 * cy / 8 ;            pt[2].x = 4 * cx / 8 ;  pt[2].y = 5 * cy / 8 ;Triangle (pdis->hDC, pt) ;                           pt[0].x = 1 * cx / 8 ;  pt[0].y = 5 * cy / 8 ;            pt[1].x = 1 * cx / 8 ;  pt[1].y = 3 * cy / 8 ;            pt[2].x = 3 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;                           Triangle (pdis->hDC, pt) ;            break ;case ID_LARGER ://同上            pt[0].x = 5 * cx / 8 ;  pt[0].y = 3 * cy / 8 ;            pt[1].x = 3 * cx / 8 ;  pt[1].y = 3 * cy / 8 ;            pt[2].x = 4 * cx / 8 ;  pt[2].y = 1 * cy / 8 ;                           Triangle (pdis->hDC, pt) ;                           pt[0].x = 5 * cx / 8 ;  pt[0].y = 5 * cy / 8 ;            pt[1].x = 5 * cx / 8 ;  pt[1].y = 3 * cy / 8 ;            pt[2].x = 7 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;                           Triangle (pdis->hDC, pt) ;                           pt[0].x = 3 * cx / 8 ;  pt[0].y = 5 * cy / 8 ;            pt[1].x = 5 * cx / 8 ;  pt[1].y = 5 * cy / 8 ;            pt[2].x = 4 * cx / 8 ;  pt[2].y = 7 * cy / 8 ;                           Triangle (pdis->hDC, pt) ;                           pt[0].x = 3 * cx / 8 ;  pt[0].y = 3 * cy / 8 ;            pt[1].x = 3 * cx / 8 ;  pt[1].y = 5 * cy / 8 ;            pt[2].x = 1 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;                           Triangle (pdis->hDC, pt) ;            break ;}if (pdis->itemState & ODS_SELECTED)//ODS_SELECTED选中的菜单项(代表选中了)               InvertRect (pdis->hDC, &pdis->rcItem) ;//InvertRect函数通过对矩形内部的像素点进行逻辑NOT操作而将窗口中的矩形反转(当点中是,黑色三角形变为白色)//第一个参数为设备环境句柄//第二个参数为指向包含将被反转的矩形的逻辑坐标的RECT结构的指针                            if (pdis->itemState & ODS_FOCUS)//ODS_FOCUS如果控件需要输入焦点,则设置该值(就是说重绘按钮)          {               pdis->rcItem.left   += cx / 16 ;//获取新按钮的信息               pdis->rcItem.top    += cy / 16 ;               pdis->rcItem.right  -= cx / 16 ;               pdis->rcItem.bottom -= cy / 16 ;                              DrawFocusRect (pdis->hDC, &pdis->rcItem) ;//画一个焦点矩形   //hdc:设备环境句柄   //第二个参数指向含有将填充矩形的逻辑坐标的RECT结构的指针          }          return 0 ;case WM_DESTROY ://WM_DESTROY 是关闭程序的//在这里有必要区分一下下面的几个消息//WM_CLOSE 是关闭窗口的//WM_QUIT 是关闭消息循环的          PostQuitMessage (0) ;//该函数向系统表明有个线程有终止请求。通常用来响应WM_DESTROY消息           return 0 ;}return DefWindowProc (hwnd, message, wParam, lParam) ;//该函数调用缺省的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理}

0 0