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