燕山大学-windows-程序设计-实验报告_第1页
燕山大学-windows-程序设计-实验报告_第2页
燕山大学-windows-程序设计-实验报告_第3页
燕山大学-windows-程序设计-实验报告_第4页
燕山大学-windows-程序设计-实验报告_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Windows 程序设计基于Windows API的简单绘图软件 目录1 .概述22.工作区窗口52.1 hWorkWnd窗口的产生52.2结构体定义52.3 文件中函数定义52.4图形的绘制63.工具条的实现93.1 资源编辑93.2 工具条窗口的产生93.3工具栏按钮效果的实现93.4消息传递114. 调色板的创建124.1窗口产生124.2调色功能实现124.2 消息处理135.保存与打开功能的实现145.1保存与打开窗口145.2保存功能145.3打开功能156.总结161 .概述1.1工程简介及窗口框架 项目中一共建立了四个窗口,其中类名为szWindowClass的窗口是父窗口,工作区窗口(szWorkClass)、工具栏(szToolbarClass)以及调色板(szColorbarClass)是子窗口。工作区窗口主要实现基本的绘图功能,工具栏和调色板分别实现绘图工具和颜色的选择功能。另外,为了方便消息的传递,将工作区窗口的句柄hWorkWnd设为全局变量。 项目中MyDrawProj.cpp文件实现主窗口框架的产生及消息处理,function.h和function.cpp实现基本图形的绘制功能,toolbar.h和 toolbar.cpp完成工具栏的产生和消息处理,color.h 和color.cpp实现调色板功能和消息处理。最后file.h和file.cpp完成图像的保存和打开功能主界面截图:1.2 GDI(Graphic Device Interface)绘图概述图形设备接口(GDI)处理来自windows应用程序的图形函数调用,然后把这些调用传递给合适的设备驱动程序,由设备驱动程序来执行与硬件相关的函数,并产生最后的输出结果。设备描述表(DC)是一种windows数据结构,它包含了与一个设备(如显示器)的绘制属性的相关信息。所有的绘制操作通过一个设备上下文对象进行,该对象封装了实现绘制线条,矩形,椭圆等图形windows API函数。设备上下文可以用来向屏幕,打印机和图元件输入结果。1.3 实现绘图的基本原理实验中通过对API函数的调用实现基本图形的绘制,由于窗口大小发生改变或者客户区无效时发生重绘,故采用双缓冲技术绘图,即在内存中创建一个与屏幕绘图区域一致的对象,先将图形绘制到内存中的这个对象上,再一次性将这个对象上的图形拷贝到屏幕上,这样在保持绘图的同时还可以避免闪烁。工具栏和调色板的选择可通过SendMessage函数将用户的选择传到工作区窗口处理,从而画出不同颜色的不同图形。通过对添加bmp文件头将画布保存为bmp图像实现文件的保存功能,通过把打开的bmp图像拷贝到当前工作区实现打开功能,使用OPENFILENAME结构弹出打开和保存对话框。使用一个比当前工作区大以及背景颜色一样的矩形填充当前工作区,实现对图像的清除功能。1.4相关的基本数据类型和函数1.显示窗口的步骤1.注册窗口类typedef struct WNDCLASSEX UINT cbSize; /结构的大小UINT style; /窗口风格WNDPROC lpfnWndProc; /窗口函数指针,指向消息处理函数int cbClsExtra; int cbWndExtra;HINSTANCE hInstance; /实例句柄HICON hIcon; /图标HCURSOR hCursor; /光标HBRUSH hbrBackground; /背景画刷LPCTSTR lpszMenuName; /菜单LPCTSTR lpszClassName; /窗口类名称HICON hIconSm; /窗口图标 WNDCLASSEX, *PWNDCLASSEX;2.创建窗口HWND CreateWindow(LPCTSTR lpClassName, /窗口类名LPCTSTR lpWindowName, /窗口标题DWORD dwStyle, /指定创建窗口的风格int x, /指定窗口的初始水平位置int y, /指定窗口的初始垂直位置int nWidth,/窗口的宽度int nHeight, /窗口的高度HWND hWndParent, /窗口的父窗口HMENU hMenu, /菜单句柄HANDLE hlnstance,/与窗口相关联的模块实例的句柄LPVOID lpParam);3.显示窗口ShowWindow(HWND hWnd, int nCmdShow);hWnd指窗口句柄,nCmdShow指定窗口如何显示,可取SW_HIDE、SW_SHOW等。4.更新客户区UpdateWindow(HWND hWnd);5.进入消息循环WM_CREATE、WM_PAINT、WM_SIZE等消息的处理2.菜单、图标和位图 菜单 LoadMenu(HINSTANCE hlnstance,LPCTSTR lpMenuName)图标 LoadIcon(HINSTANCE hInstance,LPCTSTR lpIconName)位图 LoadImage(HINSTANCE hinst,LPCTSTR lpszName,UINT uType,int cxDesired,int cyDesired,UINT fuLoad)3. 简单GDI绘图函数.直线MoveToEx(HDC hdc,int x,int y, LPPOINTlpPoint);LineTo(HDC hdc,int x,int y);2.矩形Rectangle(HDC hdc,int nLeftRect,int nTopRect, int nRightRect, int nBottomRect)3.椭圆Ellipse(HDC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect)2.工作区窗口2.1. hWorkWnd窗口的产生 (1)在主窗口的WM_CREATE中初始化窗口 hWorkWnd=CreateWindowEx(WS_EX_TRANSPARENT, szWorkClass, NULL,WS_CHILD ,0, 0, 0,0,hWnd,NULL, hInst, NULL);if(!hWorkWnd)MessageBox(hWnd,_T(创建工作区?失败),NULL,NULL);ShowWindow(hWorkWnd,SW_SHOW);(2)在主窗口WM_SIZE中添加代码使工作区窗口占满客户区SetWindowPos(hWorkWnd,NULL,2,2,LOWORD(lParam)-2*2,HIWORD(lParam)-2*2,SWP_NOACTIVATE | SWP_NOZORDER); SetFocus(hWorkWnd);2.2结构体定义typedef struct tagDRAWSTRUbool bDrawing; /工作区是否在绘图的标志POINT PtStart; /起点POINT PtEnd; /终点POINT PtPrev; /前一个点HPEN hpen; /当前选中的画笔HPEN hOldPen; /返回的画笔DWORD Color; /当前选中的颜色DRAWSTRU ,*PDRAWSTRU;2.3 function文件中函数定义/定义函数指针类型 typedef void (*PDRAWFUN) (PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);/绘制直线void LineMouseUp(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);void LineMouseMove(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);void LineMouseDown(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);/绘制矩形void RectMouseDown(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);void RectMouseMove(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);void RectMouseUp(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);/绘制椭圆void CircleMouseDown(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);void CircleMouseMove(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);void CircleMouseUp(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);/绘制线条void CurveMouseDown(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);void CurveMouseMove(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);void CurveMouseUp(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);/画刷void BrushMouseDown(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);void BrushMouseMove(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);void BrushMouseUp(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam);2.4 图形的绘制(1)基本原理鼠标按下时,即产生WM_LBUTTONDOWN消息时记录鼠标按下点的坐标,鼠标移动产生WM_MOUSEMOVE时进行相应绘制,为实现橡皮筋效果需要改变绘图模式,将上一次所画图像用背景色擦掉。鼠标弹起产生WM_LBUTTONUP消息,记录相应坐标绘制图形。 另外,处在屏幕绘图外,还要在Windows内存DC中实现相同操作以保持绘图。(2)主要代码(以绘制矩形)1.鼠标按下操作void RectMouseDown(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam)pDrawStruc-bDrawing=TRUE;pDrawStruc-PtStart.x=LOWORD(lParam);pDrawStruc-PtStart.y=HIWORD(lParam);pDrawStruc-PtEnd=pDrawStruc-PtStart;2.鼠标移动void RectMouseMove(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam)HDC phdc; phdc=GetDC(hWnd); /屏幕DCpDrawStruc-hpen=CreatePen(PS_SOLID ,0,pDrawStruc-Color );/创建画笔pDrawStruc-hOldPen=(HPEN)SelectObject(hdc,pDrawStruc-hpen);/选入设备上下文SelectObject(phdc,pDrawStruc-hpen);if(pDrawStruc-bDrawing)/当前正在绘图SetCapture(hWnd);/捕获鼠标SetROP2(hdc,R2_NOTXORPEN);/改变绘图SelectObject(hdc,GetStockObject(NULL_BRUSH);SetROP2(phdc,R2_NOTXORPEN);SelectObject(phdc,GetStockObject(NULL_BRUSH);/擦掉鼠标上次移动绘制的图形ectangle(hdc,pDrawStruc-PtStart.x,pDrawStruc-PtStart.y,pDrawStruc-PtEnd.x,pDrawStruc-PtEnd.y);Rectangle(phdc,pDrawStruc-PtStart.x,pDrawStruc-PtStart.y,pDrawStruc-PtEnd.x,pDrawStruc-PtEnd.y);/获得新的点pDrawStruc-PtEnd.x=LOWORD(lParam);pDrawStruc-PtEnd.y=HIWORD(lParam); /绘制新的图形 Rectangle(hdc,pDrawStruc-PtStart.x,pDrawStruc-PtStart.y,pDrawStruc-PtEnd.x,pDrawStruc-PtEnd.y);Rectangle(phdc,pDrawStruc-PtStart.x,pDrawStruc-PtStart.y,pDrawStruc-PtEnd.x,pDrawStruc-PtEnd.y);SelectObject (hdc , pDrawStruc-hOldPen);SelectObject (phdc , pDrawStruc-hOldPen);DeleteObject (pDrawStruc-hpen);ReleaseDC(hWnd,phdc); /释放DC3.鼠标弹起void RectMouseUp(PDRAWSTRU pDrawStruc,HWND hWnd,HDC hdc,UINT Message,WPARAM wParam,LPARAM lParam) HDC phdc;phdc=GetDC(hWnd); /获得屏幕DC/创建画笔并选入pDrawStruc-hpen=CreatePen(PS_SOLID ,0,pDrawStruc-Color );pDrawStruc-hOldPen=(HPEN)SelectObject(hdc,pDrawStruc-hpen);SelectObject(phdc,pDrawStruc-hpen);/改变绘图模式SetROP2(hdc,R2_COPYPEN);SelectObject(hdc,GetStockObject(NULL_BRUSH);SetROP2(phdc,R2_COPYPEN);SelectObject(phdc,GetStockObject(NULL_BRUSH);Rectangle(hdc,pDrawStruc-PtStart.x,pDrawStruc-PtStart.y,pDrawStruc-PtEnd.x,pDrawStruc-PtEnd.y);Rectangle(phdc,pDrawStruc-PtStart.x,pDrawStruc-PtStart.y,pDrawStruc-PtEnd.x,pDrawStruc-PtEnd.y);/绘制新的图形pDrawStruc-PtEnd.x=LOWORD(lParam);pDrawStruc-PtEnd.y=HIWORD(lParam);Rectangle(hdc,pDrawStruc-PtStart.x,pDrawStruc-PtStart.y,pDrawStruc-PtEnd.x,pDrawStruc-PtEnd.y);Rectangle(phdc,pDrawStruc-PtStart.x,pDrawStruc-PtStart.y,pDrawStruc-PtEnd.x,pDrawStruc-PtEnd.y);pDrawStruc-bDrawing=false;/鼠标弹起停止绘图SelectObject (hdc , pDrawStruc-hOldPen);SelectObject (phdc , pDrawStruc-hOldPen);DeleteObject (pDrawStruc-hpen);/释放DC和捕获ReleaseCapture();ReleaseDC(hWnd,phdc);注:由于绘制直线和矩形与之相似,不再赘述,绘制连续线条时,只需保存前一个点然后再画便可实现连续效果,另外由于还得再内存画图,故需要在hdc和phdc上执行相同的绘图操作。3.工具条的实现3.1资源编辑 工具栏的每一个图标都对应两个位图,鼠标按下和弹起对应不同的位图从而实现按钮效果,资源列表如下#define IDB_BRUSHDOWN 140#define IDB_CIRCLEDOWN 141#define IDB_LINEDOWN 142#define IDB_PENDOWN 143#define IDB_RECTDOWN 144#define IDB_BRUSHUP 145#define IDB_CIRCLEUP 146#define IDB_LINEUP 147#define IDB_PEN_UP 148#define IDB_RECTUP 1493.2.工具栏窗口的产生 void CreateStandardToolbar(HWND hParent,HINSTANCE hInst)if(!RegistToolbar(hInst) return;HWND hWnd=CreateWindow(szToolbarClass,_T(工具栏),WS_POPUP | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU ,600, 100, 155, 55,hParent,NULL, hInst, NULL);ShowWindow(hWnd,SW_SHOW);在主窗口的WM_CREATE消息中调用以上函数产生工具栏窗口3.3工具栏按钮效果的实现(1)基本原理初始化时将所有弹起时的位图选入设备描述句柄,并拷贝到窗口对应的矩形区域,当鼠标按下时,在指定位置拷贝新的位图将原位图覆盖即可实现按钮效果(2)结构体和数组BUTTON Buttons = IDB_PENDOWN,IDB_PEN_UP,IDB_LINEDOWN,IDB_LINEUP,IDB_BRUSHDOWN,IDB_BRUSHUP,IDB_CIRCLEDOWN,IDB_CIRCLEUP, IDB_RECTDOWN,IDB_RECTUP; /定义一个Button数组保存按钮位图的IDtypedef struct tagBUTTON INT DownID; /鼠标按下的位图 INT UpID; /鼠标弹起的位图BUTTON,*PBUTTON;(3)实现的部分代码case WM_PAINT:hdc = BeginPaint(hWnd, &ps);HDC hdcMem;hdcMem=CreateCompatibleDC(hdc);/创建内存兼容DCHBITMAP hbmp,hbmpOld; for(int i=0;i5;i+)if(Statei)hbmpOld=(HBITMAP)SelectObject(hdcMem,LoadBitmap(hInst,MAKEINTRESOURCE(Buttonsi.DownID);BitBlt(hdc,30*i,0,32,32,hdcMem,0,0,SRCCOPY);hbmp=(HBITMAP)SelectObject(hdcMem,hbmpOld);DeleteObject(hbmp);elsehbmpOld=(HBITMAP)SelectObject(hdcMem,LoadBitmap(hInst,MAKEINTRESOURCE(Buttonsi.UpID);BitBlt(hdc,30*i,0,32,32,hdcMem,0,0,SRCCOPY);hbmp=(HBITMAP)SelectObject(hdcMem,hbmpOld);DeleteObject(hbmp);EndPaint(hWnd, &ps);break;注: 将代码放入WM_PAINT消息中,每当有鼠标在按钮位置按下时,指定窗口无效进行重绘,实现动态显示。 State数组标识按钮的状态,Statei=true表示鼠标按下,Statei=false表示鼠标弹起,从而根据State状态选入响应的位图。3.4消息传递(1)实现原理 由鼠标按下的点的位置计算出对应的按钮索引,自定义TOOL_CHANGE消息采用SendMessage将消息和整型的索引值传递给hWorkWnd窗口,由工作区窗口响应做出响应的绘图处理。(2)部分代码case WM_LBUTTONDOWN: index=LOWORD(lParam)/32; for(int i=0;i5;i+) if(i=index) Statei=true; else Statei=false;SendMessage(hWorkWnd,TOOL_CHANGE,index,lParam);InvalidateRect(hWnd,NULL,TRUE);break;工作区窗口的处理:case TOOL_CHANGE: switch(int(wParam) case 0: /连续线条 Down=CurveMouseDown; Move=CurveMouseMove; Up=CurveMouseUp; break; case 1: /画直线Down=LineMouseDown;Move=LineMouseMove;Up=LineMouseUp;break; case 2: /刷子 Down=BrushMouseDown; Move=BrushMouseMove; Up=BrushMouseUp; break; case 3: /画椭圆 Down=CircleMouseDown; Move=CircleMouseMove; Up=CircleMouseUp; break;4.调色板的实现4.1窗口的产生(1)注册调色板窗口类,然后在主窗口的WM_CREATE消息中调用以下函数产生调色板窗口。void CreateColorbar(HWND hParent,HINSTANCE hInst) if(!RegistColorbar(hInst) MessageBox(hParent,_T(注册颜色条失败),NULL,NULL); HWND hWnd=CreateWindow(szColorbarClass, _T(颜色板), WS_BORDER |WS_CAPTION|WS_SYSMENU ,200, 100, 250, 105,hParent,NULL, hInst, NULL);if(!hWnd)MessageBox(hParent,_T(创建颜色条失败),NULL,NULL);ShowWindow(hWnd,SW_SHOW);(2)截图4.2调色功能实现(1)创建颜色数组DWORD Colors= RGB(0,0,0), RGB(0,255,0), RGB(0,0,255), RGB(0,255,255), RGB(255,0,0),RGB(255,0,255),RGB(255,255,0),RGB(255,192,192);(2)实现原理 初始化时,在指定位置绘制不用颜色的矩形,即为颜色板。鼠标单击响应颜色时,由鼠标位置计算出对应颜色数组里的颜色值,把相应颜色选入设备描述表,并且在右侧指定位置画出相应颜色的矩形。(3)部分代码case WM_LBUTTONDOWN:x=LOWORD(lParam);y=HIWORD(lParam);if(x/404&y/402) /在有颜色的区域内处理 index=x/40+y/40*4;/把用户选择的颜色交给工作区窗口处理SendMessage(hWorkWnd,COLOR_CHANGE,index,lParam); HBRUSH hbr1;HBRUSH hbrOld1;hdc=GetDC(hWnd);hbr1 = CreateSolidBrush(Colorsindex);hbrOld1 =(HBRUSH)SelectObject(hdc, hbr1); /右侧绘制相应颜色的矩形Rectangle(hdc, 175, 10, 235, 70);SelectObject(hdc, hbrOld1);DeleteObject(hbr1);ReleaseDC(hWnd,hdc);else break;break;case WM_PAINT:hdc = BeginPaint(hWnd, &ps);HBRUSH hbr;HBRUSH hbrOld; /绘制不同颜色的矩形for(int i=0;i8;i+)hbr = CreateSolidBrush(Colorsi);hbrOld =(HBRUSH)SelectObject(hdc, hbr);Rectangle(hdc, i%4*40, i/4*40, i%4*40+40, i/4*40+40);if(i=0) Rectangle(hdc, 175, 10, 235, 70);SelectObject(hdc, hbrOld);DeleteObject(hbr);EndPaint(hWnd, &ps);break;4.3消息处理 Color数组设置为全局变量,自定义消息COLOR_CHANGE,工作区窗口收到消息后,在DRAWSTRU数组中改变相应的颜色进行绘图case COLOR_CHANGE:DrawStru.Color=Colors(int)wParam;break;5.保存与打开功能的实现5.1保存与打开窗口(1)实现方式 使用OPENFILENAME结构,GetOpenFileName和GetSaveFileName函数用来初始化打开或保存对话框的信息,获得打开和保存路径,做出相应处理(2)截图(3)部分代码OPENFILENAME sfn;TCHAR szSaveFileMAX_PATH;ZeroMemory(&sfn,sizeof(sfn); /初始化置0sfn.lStructSize = sizeof(sfn);sfn.lpstrFile = szSaveFile;sfn.lpstrFile0 = TEXT(0);sfn.nMaxFile = sizeof(szSaveFil

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论