VC++SDK中实现直线(矩形,椭圆等)的移动及直线依附矩形椭圆的移动方法(附:运行效果图)
2011-11-03 21:19
483 查看
在SDK中实现画条直线,画个矩形等都有现成的函数供我们去调用,有时候直线,矩形画完之后需要能够随鼠标进行移动进而调整图形的位置。
不知道该怎么去表述,就贴代码吧,代码中已经添加了很详细的注释了。
直接把完整的例子代码都贴出来吧,这样最省事了
。
至于矩形,椭圆的移动就不多说了。
给个简单的运行事例吧。
光棍节要来了。。。。。。。。。
祝各位棍友good luck!!!!
不知道该怎么去表述,就贴代码吧,代码中已经添加了很详细的注释了。
直接把完整的例子代码都贴出来吧,这样最省事了
。
// areatest.cpp : 定义应用程序的入口点。 // #include "stdafx.h" #include "areatest.h" #include <math.h> #define MAX_LOADSTRING 100 // 全局变量: HINSTANCE hInst; // 当前实例 TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本 TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名 // 此代码模块中包含的函数的前向声明: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此放置代码。 MSG msg; HACCEL hAccelTable; // 初始化全局字符串 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_AREATEST, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // 执行应用程序初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_AREATEST)); // 主消息循环: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // // 函数: MyRegisterClass() // // 目的: 注册窗口类。 // // 注释: // // 仅当希望 // 此代码与添加到 Windows 95 中的“RegisterClassEx” // 函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要, // 这样应用程序就可以获得关联的 // “格式正确的”小图标。 // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_AREATEST)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_AREATEST); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } // // 函数: InitInstance(HINSTANCE, int) // // 目的: 保存实例句柄并创建主窗口 // // 注释: // // 在此函数中,我们在全局变量中保存实例句柄并 // 创建和显示主程序窗口。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // 将实例句柄存储在全局变量中 hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 处理主窗口的消息。 // // WM_COMMAND - 处理应用程序菜单 // WM_PAINT - 绘制主窗口 // WM_DESTROY - 发送退出消息并返回 // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { //随便定义2点用来画线 static POINT start={200,200},end={500,500}; //保存鼠标按下的点 static POINT ptButtondown; //保存鼠标移动的点 static POINT ptMousemove; //判断是否绘制 static bool draw; int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc,hdcMem; HBITMAP hBitmap; static HRGN hrgn; RECT clientrect; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_LBUTTONDOWN: { ////////////////////////////////////////////////// ///每次鼠标按下,需要销毁原来的感应区域,重新创建/ ///新的感应区域/////////////////////////////////// DeleteObject(hrgn); hrgn=NULL; POINT pointList[4]; //////////////////////////////////////////////////// ///简单说明一下这里,由于一条直线是由首位2点组成//// ///这里需要给他创建一个感应区域,方便起见,创建一/// ///个矩形感应区域,简单的用了勾股定理3,4,5就是创建// ///一个宽度为2*5,长度为直线长度的矩形裁剪区域,当鼠/ ///标在此区域按下的时候给予感应,变换鼠标形状实施拖/ ///动操作/////////////////////////////////////////// pointList[0].x = (int)(start.x-3); pointList[0].y = (int)(start.y+4); pointList[1].x = (int)(start.x+3); pointList[1].y = (int)(start.y-4); pointList[2].x = (int)(end.x-3); pointList[2].y = (int)(end.y+4); pointList[3].x = (int)(end.x+3); pointList[3].y = (int)(end.y-4); //创建直线新位置的感应区域 hrgn = CreatePolygonRgn(pointList, _countof(pointList), WINDING); ptButtondown.x=LOWORD(lParam); ptButtondown.y=HIWORD(lParam); if(PtInRegion(hrgn,ptButtondown.x,ptButtondown.y)) { OutputDebugString(_T("InRegion")); //设置鼠标捕获,让鼠标逃不出我窗口的手心控制 SetCapture(hWnd); //设置光标为四个方向 SetCursor(LoadCursor(NULL,IDC_SIZEALL)); draw=true; } } break; case WM_MOUSEMOVE: hdc=GetDC(hWnd); if(draw==false) break; OutputDebugString(_T("Move\n")); SetCursor(LoadCursor(NULL,IDC_SIZEALL)); //得到此刻鼠标移动位置的坐标 ptMousemove.x=LOWORD(lParam); ptMousemove.y=HIWORD(lParam); //计算新直线的起点跟终点,加上偏移 start.x=start.x+ptMousemove.x-ptButtondown.x; start.y=start.y+ptMousemove.y-ptButtondown.y; end.x=end.x+ptMousemove.x-ptButtondown.x; end.y=end.y+ptMousemove.y-ptButtondown.y; //在新的位置上画线 MoveToEx(hdc,start.x,start.y,NULL); LineTo(hdc,end.x,end.y); //把当前鼠标移动位置的坐标赋值给ptButtondown,下次计算偏移才准确 ptButtondown.x=ptMousemove.x; ptButtondown.y=ptMousemove.y; //完成在新的位置绘制直线 InvalidateRect(hWnd,NULL,TRUE); ReleaseDC(hWnd,hdc); break; case WM_LBUTTONUP: //释放窗口对鼠标的捕获 ReleaseCapture(); //改变鼠标形状 SetCursor(LoadCursor(NULL,IDC_ARROW)); //设置画线标记 draw=false; break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: 在此添加任意绘图代码... ///////////////////////// //如果嫌弃闪烁,可以使用双缓冲 GetClientRect(hWnd,&clientrect); hdcMem=CreateCompatibleDC(hdc); hBitmap=CreateCompatibleBitmap(hdc,clientrect.right,clientrect.bottom); SelectObject(hdcMem,hBitmap); FillRect(hdcMem,&clientrect,NULL); MoveToEx(hdcMem,start.x,start.y,NULL); LineTo(hdcMem,end.x,end.y); BitBlt(hdc,0,0,clientrect.right,clientrect.bottom,hdcMem,0,0,SRCCOPY); DeleteObject(hBitmap); DeleteDC(hdcMem); /////////////////////////////////// /////////////////////////////////// EndPaint(hWnd, &ps); break; ///////////////////////////////////////////////////////////////////// //由于把整个背景都重绘了,所以不再需要擦除背景了,默认的擦除背景是用/ //DefWindowProc(xxx,WM_ERASEBKGND,X,X)做到的,因此在这里我们主动去告/ //诉系统我已经处理过了。///////////////////////////////////////////// case WM_ERASEBKGND: return true; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // “关于”框的消息处理程序。 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }
至于矩形,椭圆的移动就不多说了。
给个简单的运行事例吧。
光棍节要来了。。。。。。。。。
祝各位棍友good luck!!!!
相关文章推荐
- 在VC++中实现让程序只运行一个实例的方法
- [VC]在VC++中实现让程序只运行一个实例的方法且实现该实例
- 在VC++中实现让程序只运行一个实例的方法
- 在VC++中实现让程序只运行一个实例的方法
- 【C#】对异步请求处理程序IHttpAsyncHandler的理解和分享一个易用性封装 【手记】走近科学之为什么明明实现了IEnumerable<T>的类型却不能调用LINQ扩展方法 【手记】手机网页弹出层后屏蔽底层的滑动响应 【手记】ASP.NET提示“未能创建类型”处理 【Web】一个非常简单的移动web消息框 【手记】解决EXCEL跑SQL遇“查询无法运行或数据库表无法打开...”
- Silverlight实现对图片的涂鸦、绘制矩形、圆形、直线、文本,并且能够移动
- 在VC++中实现让程序只运行一个实例的方法
- VC++实现程序开机启动运行的方法
- [VC/MFC]实现程序运行时隐藏窗口 (多种方法,推荐方法2)
- VC/Wince 实现仿Win8 Metro风格界面3——按钮移动交换、删除、添加快捷方式(附效果图)
- Silverlight实现对图片的涂鸦、绘制矩形、圆形、直线、文本,并且能够移动
- shell脚本实现多进程运行的方法示例
- canvas---canvas常用方法,绘制直线,矩形,文本,画图,曲线,createLinearGradient,translate,stroke,fillText
- IOS Quartz 各种绘制图形用法---实现画图片、写文字、画线、椭圆、矩形、棱形等
- 如何重写PictureBox的OnPaint方法绘制矩形,并实现拖动改变矩形大小,鼠标悬停时提示拖拽方向(二)
- 最小二乘法用于直线,多项式,圆,椭圆的拟合及程序实现
- VC实现HTTP协议的GET和POST方法
- IOS Quartz 各种绘制图形用法---实现画图片、写文字、画线、椭圆、矩形、棱形等
- VC环境和Matlab混合编程的实现方法
- python运行其他程序的实现方法