次は、GDI+版です。Direct2Dを触ってみたのですが、ウィンドウメッセージをまたいで扱うデータが存在することから、結局C++クラスを導入することにしました。
最初に作ったC++クラスを使わない版も併せて公開しておきます。
とりあえずC++クラス化しただけというわけで、雑な作りですが勘弁願います。
#include <windows.h> #include <windowsx.h> #include <gdiplus.h> #include <math.h> #ifdef _MSC_VER #define hypot _hypot #pragma comment(lib, "gdiplus.lib") #endif namespace gp = Gdiplus; void DrawKochCurveGdiplus(gp::Graphics& g, gp::Pen* pen, double startX, double startY, double endX, double endY, int level) { double dx = endX - startX; double dy = endY - startY; double trisectionLengthX = dx / 3.; double trisectionLengthY = dy / 3.; double triangleHeight = hypot( trisectionLengthX, trisectionLengthY) * 0.5 * sqrt(3.); //下向きがyの正の向きであることに注意 double angle = atan2(-dy, dx); double vertexX = startX + dx * 0.5 - triangleHeight * sin(angle); double vertexY = startY + dy * 0.5 - triangleHeight * cos(angle); double mid1x = startX + trisectionLengthX; double mid1y = startY + trisectionLengthY; double mid2x = mid1x + trisectionLengthX; double mid2y = mid1y + trisectionLengthY; if (level == 0) { g.DrawLine( pen, static_cast<float>(startX), static_cast<float>(startY), static_cast<float>(mid1x), static_cast<float>(mid1y)); g.DrawLine( pen, static_cast<float>(mid1x), static_cast<float>(mid1y), static_cast<float>(vertexX), static_cast<float>(vertexY)); g.DrawLine( pen, static_cast<float>(vertexX), static_cast<float>(vertexY), static_cast<float>(mid2x), static_cast<float>(mid2y)); g.DrawLine( pen, static_cast<float>(mid2x), static_cast<float>(mid2y), static_cast<float>(endX), static_cast<float>(endY)); } else { level--; DrawKochCurveGdiplus( g, pen, startX, startY, mid1x, mid1y, level); DrawKochCurveGdiplus( g, pen, mid1x, mid1y, vertexX, vertexY, level); DrawKochCurveGdiplus( g, pen, vertexX, vertexY, mid2x, mid2y, level); DrawKochCurveGdiplus( g, pen, mid2x, mid2y, endX, endY, level); } } class MyWindow { public: static ATOM Register(HINSTANCE hinst) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hinst; wc.hIcon = static_cast<HICON>(LoadImage( 0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED)); wc.hCursor = static_cast<HCURSOR>(LoadImage( 0, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED)); wc.hbrBackground = static_cast<HBRUSH>( GetStockObject(WHITE_BRUSH)); wc.lpszMenuName = 0; wc.lpszClassName = TEXT("Test"); wncClassAtom = RegisterClass(&wc); return wncClassAtom; } HWND Create(HINSTANCE hinst) { return CreateWindow( reinterpret_cast<LPCTSTR>( static_cast<UINT_PTR>(wncClassAtom)), TEXT("GDI+ Test"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hinst, this); } HWND GetHWnd() const { return hwnd; } private: void OnPaint(HWND hwnd) { PAINTSTRUCT ps; gp::Graphics g(BeginPaint(hwnd, &ps)); g.SetSmoothingMode(gp::SmoothingModeHighQuality); gp::Pen pen(gp::Color(), 2.f); DrawKochCurveGdiplus(g, &pen, 10, 100, 300, 100, 3); EndPaint(hwnd, &ps); } void OnDestroy(HWND) { PostQuitMessage(0); } static bool OnNCCreate(HWND hwnd, CREATESTRUCT const* pcs) { SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pcs->lpCreateParams)); static_cast<MyWindow*>(pcs->lpCreateParams)->hwnd = hwnd; return true; } static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { MyWindow* p = reinterpret_cast<MyWindow*>( GetWindowLongPtr(hwnd, GWLP_USERDATA)); switch (msg) { HANDLE_MSG(hwnd, WM_NCCREATE, OnNCCreate); HANDLE_MSG(hwnd, WM_PAINT, p->OnPaint); HANDLE_MSG(hwnd, WM_DESTROY, p->OnDestroy); } return DefWindowProc(hwnd, msg, wParam, lParam); } HWND hwnd; static ATOM wncClassAtom; }; ATOM MyWindow::wncClassAtom; int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, PTSTR, int cmdShow) { if (!MyWindow::Register(hinst)) return 1; MyWindow wnd; if (!wnd.Create(hinst)) return 1; gp::GdiplusStartupInput gsi; ULONG_PTR gdiplusToken; if (gp::GdiplusStartup(&gdiplusToken, &gsi, 0) != gp::Ok) return -1; ShowWindow(wnd.GetHWnd(), cmdShow); UpdateWindow(wnd.GetHWnd()); MSG msg; for (;;) { int ret = GetMessage(&msg, 0, 0, 0); if (ret == -1) return -1; else if (ret == 0) break; TranslateMessage(&msg); DispatchMessage(&msg); } gp::GdiplusShutdown(gdiplusToken); return static_cast<int>(msg.wParam); } |
スポンサード リンク |