开发:
图形结构:
先把“七小孩”给画出来吧。我把坐标都定死了,我的设想应该是按客户区的大小是可以伸缩的,这也是一个验证的过程,不管怎么样先把图呈现出来先。画图是比较容易的,建立颜色画刷(CreateSolidBrush),选进设备描述表(SelectObject),画多边形(Polygon),一切都那么容易...
/ ////////////////////////////////////////////////////////////////////////// //Author: shenzi //Date: 2009.12.15 //Version: 0.1 /////////////////////////////////////////////////////////////////////////// #include #include #include #include "resource.h" //右键点击“七巧板”,旋转的角度,5度 const float acc = static_cast(5.0/180.0*3.1415926); //“七巧板”图形的多边形结构 struct TangPolygon { POINT polyPoint[4]; //多边形点,因为最多四边形,为简单就设为“四个点” COLORREF rgb; //图形颜色 size_t polyType; //图形类型,即 3:三角形;4:四边形 float angle; //保存“世界坐标”角度,绘图时用 }; //预设的“七巧板” TangPolygon g_Tangram[7] = { {{0, 0, 0, 320, 160, 160, 0, 0},RGB(255, 0, 0)/*赤色*/ ,3, 0}, {{0, 0, 160, 160, 320, 0, 0, 0},RGB(255, 165, 0)/*橙色*/ ,3, 0}, {{0, 320, 160, 320, 80, 240, 0, 0},RGB(255, 255, 0)/*黄色*/ ,3, 0}, {{160, 160, 240, 240, 240, 80, 0, 0},RGB(0, 255, 0)/*绿色*/ ,3, 0}, {{160, 320, 320, 320, 320, 160, 0, 0},RGB(0, 127, 255)/*青色*/ ,3, 0}, {{80, 240, 160, 320, 240, 240, 160, 160},RGB(0, 0, 255)/*蓝色*/ ,4, 0}, {{240, 80, 240, 240, 320, 160, 320, 0},RGB(139, 0, 255)/*紫色*/ ,4, 0} }; |
/ ////////////////////////////////////////////////////////////////////////// //Author: shenzi //Date: 2009.12.15 //Version: 0.1 /////////////////////////////////////////////////////////////////////////// #include "Tangram.h" //窗口过程函数 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //辅助函数,得到图形的中心坐标 POINT GetCenter(POINT *pPoint, size_t size); //主函数 int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PTSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("Tangram"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); //画了个“七巧板”ICON wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TANGRAM)); wndclass.hInstance = hInstance; wndclass.lpfnWndProc = WndProc; wndclass.lpszClassName = szAppName; wndclass.lpszMenuName = NULL; wndclass.style = CS_HREDRAW | CS_VREDRAW ; if (!::RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("Erroe:..."), TEXT("Error"), MB_ICONERROR); return 0; } hwnd = ::CreateWindow(szAppName, //取了个名字“七小孩”,版本就是0.1了,以后可能慢慢完善。 TEXT("Chi7ren! Version 0.1"), WS_OVERLAPPEDWINDOW | WS_VSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ::ShowWindow(hwnd, iCmdShow); ::UpdateWindow(hwnd); while(::GetMessage(&msg, NULL, 0, 0)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { //客户区大小 static int cxClient, cyClient; HDC hdc, hdcMem ; HBITMAP hBmp; HBRUSH hbrush; static int priX, priY; int moveLenthX, moveLenthY; //指定当前可移动的“小孩”。 static int movePolygon; PAINTSTRUCT ps; COLORREF color; POINT center; unsigned int i; //“世界坐标”旋转用到的两个XFORM结构 static XFORM Tansform = {1, 0, 0, 1, 0, 0}; static XFORM Tanslate = {1, 0, 0, 1, 0, 0}; switch (message) { //窗口大小改变时,得到新的客户区大小; case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); return 0; //鼠标左键,确定当前可移动的图形 case WM_LBUTTONDOWN: priX = LOWORD(lParam); priY = HIWORD(lParam); hdc = ::GetDC(hwnd); color = ::GetPixel(hdc, priX, priY); for (i = 0; i < 7; i++) { if (color == g_Tangram[i].rgb) { movePolygon = i; break; } } ::ReleaseDC(hwnd, hdc); return 0; //鼠标右键,实现图形的旋转功能,"SHIFT"改变旋转方向; case WM_RBUTTONDOWN: priX = LOWORD(lParam); priY = HIWORD(lParam); hdc = ::GetDC(hwnd); color = ::GetPixel(hdc, priX, priY); for (i = 0; i < 7; i++) { if (color == g_Tangram[i].rgb) { movePolygon = i; if (wParam & MK_SHIFT) { g_Tangram[i].angle += acc; } else { g_Tangram[i].angle -= acc; } break; } } ::ReleaseDC(hwnd, hdc); ::InvalidateRect(hwnd, NULL, FALSE); return 0; //鼠标移动并且左键按下,得到移动距离,并重绘 case WM_MOUSEMOVE: if (wParam & MK_LBUTTON) { moveLenthX = LOWORD(lParam) - priX; moveLenthY = HIWORD(lParam) - priY; priX = LOWORD(lParam); priY = HIWORD(lParam); for (i = 0; i < g_Tangram[movePolygon].polyType; i++) { g_Tangram[movePolygon].polyPoint[i].x += moveLenthX; g_Tangram[movePolygon].polyPoint[i].y += moveLenthY; } } ::InvalidateRect(hwnd, NULL, FALSE); return 0; //状态改变时,绘图 case WM_PAINT: hdc = ::BeginPaint(hwnd, &ps); //兼容DC,并选进相应的位图,解决“屏幕闪烁”问题;在兼容DC上画图, //画完后再BitBlt到客户区,实现双缓存。 hdcMem = ::CreateCompatibleDC(hdc); hBmp = ::CreateCompatibleBitmap(hdc, cxClient, cyClient); ::SelectObject(hdcMem, hBmp); //为选进位图设定背景:白色 ::PatBlt(hdcMem, 0, 0, cxClient, cyClient, WHITENESS); //设定设备描述表高级图形模式,允许全局转换,即实现图形世界坐标转换; ::SetGraphicsMode(hdcMem, GM_ADVANCED); //绘制“七巧板” for (i = 0; i < 7; i++) { //得到当前处理图形的中心点 center = GetCenter(g_Tangram[i].polyPoint, g_Tangram[i].polyType); //全局转换: //1.重置当前全局转换 ::ModifyWorldTransform(hdcMem, NULL, MWT_IDENTITY); //2.先把世界坐标移到“中心”点 Tansform.eDx = static_cast(-center.x); Tansform.eDy = static_cast(-center.y); ::ModifyWorldTransform(hdcMem, &Tansform, MWT_RIGHTMULTIPLY); //3.再做旋转 Tanslate.eM11 = cos(g_Tangram[i].angle); Tanslate.eM12 = -sin(g_Tangram[i].angle); Tanslate.eM21 = sin(g_Tangram[i].angle); Tanslate.eM22 = cos(g_Tangram[i].angle); ::ModifyWorldTransform(hdcMem, &Tanslate, MWT_RIGHTMULTIPLY); //4.最后移回原处 Tansform.eDx = static_cast(center.x); Tansform.eDy = static_cast(center.y); ::ModifyWorldTransform(hdcMem, &Tansform, MWT_RIGHTMULTIPLY); //选定图形颜色,绘制该图形 hbrush = ::CreateSolidBrush(g_Tangram[i].rgb); ::SelectObject(hdcMem, hbrush); ::Polygon(hdcMem, g_Tangram[i].polyPoint, g_Tangram[i].polyType); ::DeleteObject(hbrush); } //****重置全局转换,不知道为什么需要加这条语句,不加这条语句最后个图形的 //旋转就会处问题。 ::ModifyWorldTransform(hdcMem, NULL, MWT_IDENTITY); //把结果“贴到”客户区 ::BitBlt(hdc, 0, 0, cxClient, cyClient, hdcMem, 0, 0, SRCCOPY); //删除创建的对象 ::DeleteObject(hBmp); ::DeleteDC(hdcMem); ::EndPaint(hwnd, &ps); return 0; case WM_DESTROY: ::PostQuitMessage(0); return 0; } return ::DefWindowProc(hwnd, message, wParam, lParam); } POINT GetCenter(POINT *pPoint, size_t size) { unsigned int i = 0; POINT center = {0, 0}; for (i = 0; i < size; i++) { center.x += pPoint[i].x; center.y += pPoint[i].y; } center.x /= size; center.y /= size; return center; } |