/* 名 称:中点画椭圆算法 * 作 者:fj * 时 间:2010年9月16日20:52:24 * 功 能:根据鼠标输入的椭圆外截矩形坐标画出椭圆 */ #include <windows.h> LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); inline int Round(const float a); void EllipseMidpoint(HDC hDC, int xCenter, int yCenter, int Rx, int Ry); void EllipsePlotPoints(HDC hDC, int xCenter, int yCenter, int x, int y); COLORREF rgb[3] = {RGB(255, 0, 0), RGB(0, 255, 0), RGB(0, 0, 255)}; // 显示像素的颜色 int color = 0; // 默认为红色 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) { HWND hwnd; // 窗口句柄 MSG msg; // 消息队列 WNDCLASSEX wincl; // 声明一个窗口类 // 初始化窗口类 // wincl.hInstance = hInstance; wincl.lpszClassName = "openGL"; wincl.lpfnWndProc = WindowProcedure; wincl.style = CS_DBLCLKS; wincl.cbSize = sizeof(WNDCLASSEX); wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wincl.hCursor = LoadCursor (NULL, IDC_CROSS); wincl.lpszMenuName = NULL; wincl.cbClsExtra = 0; wincl.cbWndExtra = 0; wincl.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 注册窗口类 // if (!RegisterClassEx (&wincl)) return 0; // 创建窗口 // hwnd = CreateWindowEx (0, /* Extended possibilites for variation */ "openGL", /* Classname */ "openGL__FJ", /* Title Text */ WS_OVERLAPPEDWINDOW, /* default window */ GetSystemMetrics(SM_CXSCREEN) / 4, /* Windows decides the position */ GetSystemMetrics(SM_CYSCREEN) / 4, /* where the window ends up on the screen */ GetSystemMetrics(SM_CXSCREEN) / 2, /* The programs width */ GetSystemMetrics(SM_CYSCREEN) / 2, /* and height in pixels */ HWND_DESKTOP, /* The window is a child-window to desktop */ NULL, /* No menu */ hInstance, /* Program Instance handler */ NULL /* No Window Creation data */ ); // 显示窗口 // ShowWindow (hwnd, nCmdShow); // 进入消息循环 // while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage(&msg); // 翻译消息 DispatchMessage(&msg); // 处理消息 } return msg.wParam; } // 窗口过程函数 // LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static RECT rect; HDC hdc; // 记录椭圆的外截矩形 switch (message) { case WM_RBUTTONDOWN: InvalidateRect(hwnd, NULL, 1); // 刷新显示区 color = 0; // 椭圆颜色置为默认 break; case WM_LBUTTONDOWN: // 捕捉椭圆外截矩形的左上角坐标 rect.left = LOWORD(lParam); rect.top = HIWORD(lParam); break; case WM_LBUTTONUP: // 捕捉椭圆外截矩形的右下角坐标,并显示椭圆 rect.right = LOWORD(lParam); rect.bottom = HIWORD(lParam); hdc = GetDC(hwnd); // 通过矩形的坐标计算中点及长短轴的坐标,并显示椭圆 EllipseMidpoint(hdc, (rect.right + rect.left) / 2, (rect.bottom + rect.top) / 2, // 中点坐标 (rect.right - rect.left) / 2, (rect.bottom - rect.top) / 2); // 长轴和短轴 // 改变颜色 ++color; if (color >= 3) color = 0; ReleaseDC(hwnd,hdc); break; case WM_DESTROY: PostQuitMessage (0); break; default: return DefWindowProc (hwnd, message, wParam, lParam); } return 0; } // 小数四舍五入 // inline int Round(const float a) { return static_cast<int>(a + 0.5); } // 给定中点及长短轴画椭圆 // void EllipseMidpoint(HDC hDC, int xCenter, int yCenter, int Rx, int Ry) { int Rx2(Rx * Rx), Ry2(Ry * Ry); int twoRx2(2 * Rx2), twoRy2(2 * Ry2); int p; int x(0), y(Ry); int px(0), py(twoRx2 * y); // 画出椭圆长短轴上的四个点 EllipsePlotPoints(hDC, xCenter, yCenter, x, y); // 计算区域1中决策参数的初始值 p = Round(static_cast<float>(Ry2 - (Rx2 * Ry) + (0.25 * Rx2))); // 画区域1计算出来的点 while (px < py) { ++x; px += twoRy2; if (p < 0) p += Ry2 + px; else { --y; py -= twoRx2; p += Ry2 + px - py; } EllipsePlotPoints(hDC, xCenter, yCenter, x, y); } // 用区域1中计算的最后点来计算区域2中参数的初始值 p = Round(static_cast<float>(Ry2 * (x + 0.5) * (x + 0.5) + Rx2 * (y - 1) * (y - 1) - Rx2 * Ry2)); // 画区域2计算出来的点 while (y > 0) { --y; py -= twoRx2; if (p > 0) p += Rx2 - py; else { ++x; px += twoRy2; p += Rx2 - py + px; } EllipsePlotPoints(hDC, xCenter, yCenter, x, y); } } // 把某一点的像素按颜色显示出来,并利用对称性显示其它三个点 // void EllipsePlotPoints(HDC hDC, int xCenter, int yCenter, int x, int y) { SetPixel(hDC, xCenter + x, yCenter + y, rgb[color]); SetPixel(hDC, xCenter - x, yCenter + y, rgb[color]); SetPixel(hDC, xCenter + x, yCenter - y, rgb[color]); SetPixel(hDC, xCenter - x, yCenter - y, rgb[color]); }