1 module round_rect;
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 import std.traits;
11 
12 pragma(lib, "gdi32.lib");
13 import windows.windef;
14 import windows.winuser;
15 import windows.wingdi;
16 
17 string appName     = "CairoWindow";
18 string description = "Rounded Rectangles";
19 HINSTANCE hinst;
20 
21 import cairo.cairo;
22 import cairo.win32;
23 
24 alias cairo.cairo.RGB RGB;  // conflicts with win32.wingdi.RGB
25 
26 import util.rounded_rectangle;
27 
28 extern (Windows)
29 int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
30 {
31     int result;
32 
33 
34     try
35     {
36         Runtime.initialize();
37         result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
38         Runtime.terminate();
39     }
40     catch (Throwable o)
41     {
42         MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION);
43         result = 0;
44     }
45 
46     return result;
47 }
48 
49 int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
50 {
51     hinst = hInstance;
52     HACCEL hAccel;
53     HWND hwnd;
54     MSG  msg;
55     WNDCLASS wndclass;
56 
57     wndclass.style         = CS_HREDRAW | CS_VREDRAW;
58     wndclass.lpfnWndProc   = &WndProc;
59     wndclass.cbClsExtra    = 0;
60     wndclass.cbWndExtra    = 0;
61     wndclass.hInstance     = hInstance;
62     wndclass.hIcon         = LoadIcon(null, IDI_APPLICATION);
63     wndclass.hCursor       = LoadCursor(null, IDC_ARROW);
64     wndclass.hbrBackground = cast(HBRUSH) GetStockObject(WHITE_BRUSH);
65     wndclass.lpszMenuName  = appName.toUTF16z;
66     wndclass.lpszClassName = appName.toUTF16z;
67 
68     if (!RegisterClass(&wndclass))
69     {
70         MessageBox(null, "This program requires Windows NT!", appName.toUTF16z, MB_ICONERROR);
71         return 0;
72     }
73 
74     hwnd = CreateWindow(appName.toUTF16z,              // window class name
75                         description.toUTF16z,          // window caption
76                         WS_OVERLAPPEDWINDOW,           // window style
77                         CW_USEDEFAULT,                 // initial x position
78                         CW_USEDEFAULT,                 // initial y position
79                         650,                           // initial x size
80                         250,                           // initial y size
81                         null,                          // parent window handle
82                         null,                          // window menu handle
83                         hInstance,                     // program instance handle
84                         null);                         // creation parameters
85 
86     ShowWindow(hwnd, iCmdShow);
87     UpdateWindow(hwnd);
88 
89     while (GetMessage(&msg, null, 0, 0))
90     {
91         TranslateMessage(&msg);
92         DispatchMessage(&msg);
93     }
94 
95     return msg.wParam;
96 }
97 
98 extern (Windows)
99 LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
100 {
101     switch (message)
102     {
103         case WM_CREATE:
104         {
105             window = new Window(hwnd);
106             return 0;
107         }
108 
109         default:
110     }
111 
112     if (window)
113         return window.process(hwnd, message, wParam, lParam);
114     else
115         return DefWindowProc(hwnd, message, wParam, lParam);
116 }
117 
118 Window window;
119 
120 class Window
121 {
122     int  x, y;
123     HWND hwnd;
124     HDC hdc;
125     PAINTSTRUCT ps;
126     RECT rc;
127     HDC _buffer;
128     HBITMAP hBitmap;
129     HBITMAP hOldBitmap;
130 
131     this(HWND hwnd)
132     {
133         this.hwnd = hwnd;
134     }
135 
136     LRESULT process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
137     {
138         switch (message)
139         {
140             case WM_DESTROY:
141                 return OnDestroy(hwnd, message, wParam, lParam);
142 
143             case WM_PAINT:
144                 return OnPaint(hwnd, message, wParam, lParam);
145 
146             case WM_ERASEBKGND:
147                 return 0;
148 
149             default:
150         }
151 
152         return DefWindowProc(hwnd, message, wParam, lParam);
153     }
154 
155     auto OnPaint(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
156     {
157         hdc = BeginPaint(hwnd, &ps);
158         GetClientRect(hwnd, &rc);
159 
160         auto left = rc.left;
161         auto top = rc.top;
162         auto right = rc.right;
163         auto bottom = rc.bottom;
164 
165         auto width  = right - left;
166         auto height = bottom - top;
167         x = left;
168         y = top;
169 
170         _buffer    = CreateCompatibleDC(hdc);
171         hBitmap    = CreateCompatibleBitmap(hdc, width, height);
172         hOldBitmap = SelectObject(_buffer, hBitmap);
173 
174         auto surf = new Win32Surface(_buffer);
175         auto ctx = Context(surf);
176 
177         ctx.setSourceRGB(1, 1, 1);
178         ctx.paint();
179         ctx.translate(50, 40);
180         int xPos = 150;
181         int yPos = 10;
182 
183         foreach (index, method; EnumMembers!RoundMethod)
184         {
185             roundedRectangle!(method)(ctx, index * xPos, yPos, 100, 100, 10, 10);
186 
187             auto clr = RGB(0.9411764705882353, 0.996078431372549, 0.9137254901960784);
188             ctx.setSourceRGB(clr);
189             ctx.fillPreserve();
190 
191             clr = RGB(0.7019607843137254, 1.0, 0.5529411764705883);
192             ctx.setSourceRGB(clr);
193             ctx.stroke();
194         }
195 
196         surf.finish();
197         BitBlt(hdc, 0, 0, width, height, _buffer, x, y, SRCCOPY);
198 
199         SelectObject(_buffer, hOldBitmap);
200         DeleteObject(hBitmap);
201         DeleteDC(_buffer);
202 
203         EndPaint(hwnd, &ps);
204         return 0;
205     }
206 
207     auto OnDestroy(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
208     {
209         PostQuitMessage(0);
210         return 0;
211     }
212 }