/*--------------------------------------------------- bezier.h --- bezier, (c) jiyun.xia 2011 ---------------------------------------------------*/ #ifndef BEZIER_H_ #define BEZIER_H_ #include <windows.h> enum DRICTION {NO_DIR = 0, X_ADD, X_SUB, Y_ADD, Y_SUB}; struct LINE { POINT start; POINT end; DRICTION dirc; }; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL GetNextPoint(POINT curPt, int curLine, POINT &nextPt, int &indexLine); #endif /*----------------------------------------------- bezier.cpp --- draw bezier. ------------------------------------------------*/ #include "bezier.h" #include <math.h> #include <time.h> #define ID_TIME1 1 #define PEN_WIDTH 0.1 #define LINE_LEN 5 LINE line[4]; int index = 0; POINT bezierPt[4], bezierPt1[4]; bool start = true; long cxClient, cyClient; unsigned char rColor = 0, gColor = 255, bColor = 0; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("sinwave"); HWND hWnd; MSG msg; WNDCLASS wndClass; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hbrBackground = (HBRUSH)::GetStockObject(BLACK_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; wndClass.style = CS_HREDRAW | CS_VREDRAW; if (!::RegisterClass(&wndClass)) { ::MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hWnd = ::CreateWindow(szAppName, TEXT("sinwave No.1"), WS_OVERLAPPEDWINDOW, 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; } BOOL GetNextPoint(POINT curPt, int curLine, POINT &nextPt, int &indexLine) { float k; indexLine = curLine; do { switch (line[indexLine].dirc) { case NO_DIR: break; case X_ADD: k = (float)(line[indexLine].end.y - line[indexLine].start.y) / (line[indexLine].end.x - line[indexLine].start.x); nextPt.x = curPt.x + (long)((LINE_LEN) / ::sqrt(1 + k * k)); if (nextPt.x > line[indexLine].end.x) break; nextPt.y = curPt.y + long(k * (nextPt.x - curPt.x)); return true; case X_SUB: k = (float)(line[indexLine].end.y - line[indexLine].start.y) / (line[indexLine].end.x - line[indexLine].start.x); nextPt.x = curPt.x - (long)((LINE_LEN) / ::sqrt(1 + k * k)); if (nextPt.x < line[indexLine].end.x) break; nextPt.y = curPt.y + long(k * (nextPt.x - curPt.x)); return true; case Y_ADD: if (line[indexLine].end.x == line[indexLine].start.x) { nextPt.x = curPt.x; nextPt.y = curPt.y + LINE_LEN; if (nextPt.y > line[indexLine].end.y) break; return true; } else { k = (float)(line[indexLine].end.y - line[indexLine].start.y) / (line[indexLine].end.x - line[indexLine].start.x); nextPt.y = curPt.y + (long)((LINE_LEN) / ::sqrt((k * k) / (1 + k * k))); if (nextPt.y > line[indexLine].end.y) break; nextPt.x = curPt.x + long((nextPt.y - curPt.y) / k); return true; } case Y_SUB: if (line[indexLine].end.x == line[indexLine].start.x) { nextPt.x = curPt.x; nextPt.y = curPt.y - LINE_LEN; if (nextPt.y < line[indexLine].end.y) break; return true; } else { k = (float)(line[indexLine].end.y - line[indexLine].start.y) / (line[indexLine].end.x - line[indexLine].start.x); nextPt.y = curPt.y - (long)((LINE_LEN) / ::sqrt((k * k) / (1 + k * k))); if (nextPt.y < line[indexLine].end.y) break; nextPt.x = curPt.x + long((nextPt.y - curPt.y) / k); return true; } } indexLine++; if (indexLine > 4) indexLine = 0; curPt = bezierPt[indexLine]; }while (indexLine != curLine); return false; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; POINT nextPt; int i, nextLine; LOGPEN lgPen; HPEN hOldPen, hCurPen; switch (message) { case WM_CREATE: ::SetTimer(hWnd, ID_TIME1, 10, NULL); return 0; case WM_SIZE: cyClient = (long)HIWORD(lParam); cxClient = (long)LOWORD(lParam); line[0].start = line[0].end; line[3].start = line[3].end; hdc = ::GetDC(hWnd); ::SetMapMode(hdc, MM_LOMETRIC); ::SetWindowOrgEx(hdc, cxClient / 2, cyClient / 2, NULL); ::srand((unsigned int)::time(NULL)); for (i = 0; i < 4; ++i) { if (i != 0 && i != 3) { line[i].start.x = ::rand() % cxClient; line[i].start.y = ::rand() % cyClient; ::DPtoLP(hdc, &line[i].start, 1); } line[i].end.x = ::rand() % cxClient; line[i].end.y = ::rand() % cyClient; ::DPtoLP(hdc, &line[i].end, 1); bezierPt[i] = line[i].start; if (i == 0 || i == 3) { if (line[i].end.x > line[i].start.x) { line[i].dirc = X_ADD; } else if (line[i].end.x < line[i].start.x) { line[i].dirc = X_SUB; } else if (line[i].end.y > line[i].start.y) { line[i].dirc = Y_ADD; } else if (line[i].end.y < line[i].start.y) { line[i].dirc = Y_SUB; } else line[i].dirc = NO_DIR; } else { if (line[i].end.y > line[i].start.y) { line[i].dirc = Y_ADD; } else if (line[i].end.y < line[i].start.y) { line[i].dirc = Y_SUB; } else if (line[i].end.x > line[i].start.x) { line[i].dirc = X_ADD; } else if (line[i].end.x < line[i].start.x) { line[i].dirc = X_SUB; } else line[i].dirc = NO_DIR; } } ::ReleaseDC(hWnd, hdc); return 0; case WM_TIMER: if (wParam != ID_TIME1) return 0; index++; if (index > 4) { index = 0; } hdc = ::GetDC(hWnd); ::SetMapMode(hdc, MM_LOMETRIC); ::SetWindowOrgEx(hdc, cxClient / 2, cyClient / 2, NULL); lgPen.lopnColor = RGB(0, 0, 0); lgPen.lopnStyle = PS_SOLID; lgPen.lopnWidth.x = PEN_WIDTH; hCurPen = ::CreatePenIndirect(&lgPen); hOldPen = (HPEN)::SelectObject(hdc, (HPEN)hCurPen); ::PolyBezier(hdc, bezierPt, 4); bezierPt1[0] = bezierPt[1]; bezierPt1[3] = bezierPt[2]; bezierPt1[1] = bezierPt[0]; bezierPt1[2] = bezierPt[3]; ::PolyBezier(hdc, bezierPt1, 4); //::MoveToEx(hdc, bezierPt[0].x, bezierPt[0].y, NULL); //for (i = 1; i < 4; ++i) // ::LineTo(hdc, bezierPt[i].x, bezierPt[i].y); //::LineTo(hdc, bezierPt[0].x, bezierPt[0].y); ::DeleteObject((HPEN)::SelectObject(hdc, (HPEN)hOldPen)); if (!GetNextPoint(bezierPt[index], index, nextPt, nextLine)) { long lparam = cyClient; lparam <<= 16; lparam += cxClient; ::SendMessage(hWnd, WM_SIZE, 0, lparam); return 0; } if (nextLine == index && nextPt.x == bezierPt[index].x && nextPt.y == bezierPt[index].y) { long lparam = cyClient; lparam <<= 16; lparam += cxClient; ::SendMessage(hWnd, WM_SIZE, 0, lparam); return 0; } bezierPt[nextLine] = nextPt; lgPen.lopnColor = RGB(rColor, gColor, bColor); hCurPen = ::CreatePenIndirect(&lgPen); hOldPen = (HPEN)::SelectObject(hdc, (HPEN)hCurPen); ::PolyBezier(hdc, bezierPt, 4); bezierPt1[0] = bezierPt[1]; bezierPt1[3] = bezierPt[2]; bezierPt1[1] = bezierPt[0]; bezierPt1[2] = bezierPt[3]; ::PolyBezier(hdc, bezierPt1, 4); //::MoveToEx(hdc, bezierPt[0].x, bezierPt[0].y, NULL); //for (i = 1; i < 4; ++i) // ::LineTo(hdc, bezierPt[i].x, bezierPt[i].y); //::LineTo(hdc, bezierPt[0].x, bezierPt[0].y); ::DeleteObject((HPEN)::SelectObject(hdc, (HPEN)hOldPen)); ::ReleaseDC(hWnd, hdc); return 0; case WM_PAINT: hdc = ::BeginPaint(hWnd, &ps); ::SetMapMode(hdc, MM_LOMETRIC); ::SetWindowOrgEx(hdc, cxClient / 2, cyClient / 2, NULL); lgPen.lopnColor = RGB(rColor, gColor, bColor); lgPen.lopnStyle = PS_SOLID; lgPen.lopnWidth.x = PEN_WIDTH; hCurPen = ::CreatePenIndirect(&lgPen); hOldPen = (HPEN)::SelectObject(hdc, (HPEN)hCurPen); ::PolyBezier(hdc, bezierPt, 4); bezierPt1[0] = bezierPt[1]; bezierPt1[3] = bezierPt[2]; bezierPt1[1] = bezierPt[0]; bezierPt1[2] = bezierPt[3]; ::PolyBezier(hdc, bezierPt1, 4); //::MoveToEx(hdc, bezierPt[0].x, bezierPt[0].y, NULL); //for (i = 1; i < 4; ++i) // ::LineTo(hdc, bezierPt[i].x, bezierPt[i].y); //::LineTo(hdc, bezierPt[0].x, bezierPt[0].y); ::SelectObject(hdc, (HPEN)hOldPen); ::DeleteObject((HPEN)hCurPen); ::EndPaint(hWnd, &ps); return 0; case WM_DESTROY: ::PostQuitMessage(0); return 0; } return ::DefWindowProc(hWnd, message, wParam, lParam); }