/win32_test.d
D | 237 lines | 186 code | 46 blank | 5 comment | 7 complexity | 7b024527135e0fda6bfa083a1cd402e3 MD5 | raw file
1module win32_test; 2 3/+ 4 + This tutorial is derived from: http://cairographics.org/cookbook/win32quickstart/ 5 + Translated to D2 by Andrej Mitrovic, 2011. 6 +/ 7 8import core.runtime; 9import std.utf; 10 11pragma(lib, "gdi32.lib"); 12import win32.windef; 13import win32.winuser; 14import win32.wingdi; 15 16string appName = "CairoWindow"; 17string description = "A simple win32 window with Cairo drawing"; 18HINSTANCE hinst; 19 20import cairo.cairo; 21import cairo.win32; 22 23alias cairo.cairo.RGB RGB; // conflicts with win32.wingdi.RGB 24 25extern (Windows) 26int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) 27{ 28 int result; 29 void exceptionHandler(Throwable e) { throw e; } 30 31 try 32 { 33 Runtime.initialize(&exceptionHandler); 34 result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow); 35 Runtime.terminate(&exceptionHandler); 36 } 37 catch (Throwable o) 38 { 39 MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION); 40 result = 0; 41 } 42 43 return result; 44} 45 46int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) 47{ 48 hinst = hInstance; 49 HACCEL hAccel; 50 HWND hwnd; 51 MSG msg; 52 WNDCLASS wndclass; 53 54 wndclass.style = CS_HREDRAW | CS_VREDRAW; 55 wndclass.lpfnWndProc = &WndProc; 56 wndclass.cbClsExtra = 0; 57 wndclass.cbWndExtra = 0; 58 wndclass.hInstance = hInstance; 59 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 60 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); 61 wndclass.hbrBackground = cast(HBRUSH) GetStockObject(WHITE_BRUSH); 62 wndclass.lpszMenuName = appName.toUTF16z; 63 wndclass.lpszClassName = appName.toUTF16z; 64 65 if (!RegisterClass(&wndclass)) 66 { 67 MessageBox(NULL, "This program requires Windows NT!", appName.toUTF16z, MB_ICONERROR); 68 return 0; 69 } 70 71 hwnd = CreateWindow(appName.toUTF16z, // window class name 72 description.toUTF16z, // window caption 73 WS_OVERLAPPEDWINDOW, // window style 74 CW_USEDEFAULT, // initial x position 75 CW_USEDEFAULT, // initial y position 76 CW_USEDEFAULT, // initial x size 77 CW_USEDEFAULT, // initial y size 78 NULL, // parent window handle 79 NULL, // window menu handle 80 hInstance, // program instance handle 81 NULL); // creation parameters 82 83 ShowWindow(hwnd, iCmdShow); 84 UpdateWindow(hwnd); 85 86 while (GetMessage(&msg, NULL, 0, 0)) 87 { 88 TranslateMessage(&msg); 89 DispatchMessage(&msg); 90 } 91 92 return msg.wParam; 93} 94 95void roundedRectangle(Context ctx, int x, int y, int w, int h, int radius_x = 5, int radius_y = 5) 96{ 97 enum ARC_TO_BEZIER = 0.55228475; 98 99 if (radius_x > w - radius_x) 100 radius_x = w / 2; 101 102 if (radius_y > h - radius_y) 103 radius_y = h / 2; 104 105 // approximate (quite close) the arc using a bezier curve 106 auto c1 = ARC_TO_BEZIER * radius_x; 107 auto c2 = ARC_TO_BEZIER * radius_y; 108 109 ctx.newPath(); 110 ctx.moveTo(x + radius_x, y); 111 ctx.relLineTo(w - 2 * radius_x, 0.0); 112 ctx.relCurveTo(c1, 0.0, radius_x, c2, radius_x, radius_y); 113 ctx.relLineTo(0, h - 2 * radius_y); 114 ctx.relCurveTo(0.0, c2, c1 - radius_x, radius_y, -radius_x, radius_y); 115 ctx.relLineTo(-w + 2 * radius_x, 0); 116 ctx.relCurveTo(-c1, 0, -radius_x, -c2, -radius_x, -radius_y); 117 ctx.relLineTo(0, -h + 2 * radius_y); 118 ctx.relCurveTo(0.0, -c2, radius_x - c1, -radius_y, radius_x, -radius_y); 119 ctx.closePath(); 120} 121 122extern (Windows) 123LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 124{ 125 switch (message) 126 { 127 case WM_CREATE: 128 { 129 window = new Window(hwnd); 130 return 0; 131 } 132 133 default: 134 } 135 136 if (window) 137 return window.process(hwnd, message, wParam, lParam); 138 else 139 return DefWindowProc(hwnd, message, wParam, lParam); 140} 141 142Window window; 143 144class Window 145{ 146 int x, y; 147 HWND hwnd; 148 HDC hdc; 149 PAINTSTRUCT ps; 150 RECT rc; 151 HDC _buffer; 152 HBITMAP hBitmap; 153 HBITMAP hOldBitmap; 154 155 this(HWND hwnd) 156 { 157 this.hwnd = hwnd; 158 } 159 160 LRESULT process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 161 { 162 switch (message) 163 { 164 case WM_DESTROY: 165 return OnDestroy(hwnd, message, wParam, lParam); 166 167 case WM_PAINT: 168 return OnPaint(hwnd, message, wParam, lParam); 169 170 case WM_ERASEBKGND: 171 return 0; 172 173 default: 174 } 175 176 return DefWindowProc(hwnd, message, wParam, lParam); 177 } 178 179 auto OnPaint(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 180 { 181 hdc = BeginPaint(hwnd, &ps); 182 GetClientRect(hwnd, &rc); 183 184 auto left = rc.left; 185 auto top = rc.top; 186 auto right = rc.right; 187 auto bottom = rc.bottom; 188 189 auto width = right - left; 190 auto height = bottom - top; 191 x = left; 192 y = top; 193 194 _buffer = CreateCompatibleDC(hdc); 195 hBitmap = CreateCompatibleBitmap(hdc, width, height); 196 hOldBitmap = SelectObject(_buffer, hBitmap); 197 198 auto surf = new Win32Surface(_buffer); 199 auto ctx = Context(surf); 200 201 ctx.setSourceRGB(1, 1, 1); 202 ctx.paint(); 203 204 roundedRectangle(ctx, 50, 50, 250, 250, 10, 10); 205 206 auto clr = RGB(0.9411764705882353, 0.996078431372549, 0.9137254901960784); 207 ctx.setSourceRGB(clr); 208 ctx.fillPreserve(); 209 210 clr = RGB(0.7019607843137254, 1.0, 0.5529411764705883); 211 ctx.setSourceRGB(clr); 212 ctx.stroke(); 213 214 ctx.setSourceRGB(0, 0, 0); 215 ctx.selectFontFace("Arial", FontSlant.CAIRO_FONT_SLANT_NORMAL, FontWeight.CAIRO_FONT_WEIGHT_NORMAL); 216 ctx.setFontSize(10.0); 217 auto txt = "Cairo is the greatest thing!"; 218 ctx.moveTo(5.0, 10.0); 219 ctx.showText(txt); 220 221 surf.finish(); 222 BitBlt(hdc, 0, 0, width, height, _buffer, x, y, SRCCOPY); 223 224 SelectObject(_buffer, hOldBitmap); 225 DeleteObject(hBitmap); 226 DeleteDC(_buffer); 227 228 EndPaint(hwnd, &ps); 229 return 0; 230 } 231 232 auto OnDestroy(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 233 { 234 PostQuitMessage(0); 235 return 0; 236 } 237}