1 /** DGui project file.
2 
3 Copyright: Trogu Antonio Davide 2011-2013
4 
5 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
6 
7 Authors: Trogu Antonio Davide
8 */
9 module dgui.core.controls.subclassedcontrol;
10 
11 public import dgui.core.controls.reflectedcontrol;
12 
13 abstract class SubclassedControl: ReflectedControl
14 {
15 	private WNDPROC _oldWndProc; // Original Window Procedure
16 
17 	protected override void createControlParams(ref CreateControlParams ccp)
18 	{
19 		this._oldWndProc = WindowClass.superclass(ccp.superclassName, ccp.className, cast(WNDPROC) /*FIXME may throw*/ &Control.msgRouter);
20 	}
21 
22 	protected override uint originalWndProc(ref Message m)
23 	{
24 		if(IsWindowUnicode(this._handle))
25 		{
26 			m.result = CallWindowProcW(this._oldWndProc, this._handle, m.msg, m.wParam, m.lParam);
27 		}
28 		else
29 		{
30 			m.result = CallWindowProcA(this._oldWndProc, this._handle, m.msg, m.wParam, m.lParam);
31 		}
32 
33 		return m.result;
34 	}
35 
36 	protected override void wndProc(ref Message m)
37 	{
38 		switch(m.msg)
39 		{
40 			case WM_ERASEBKGND:
41 			{
42 				if(SubclassedControl.hasBit(this._cBits, ControlBits.doubleBuffered))
43 				{
44 					Rect r = void;
45 					GetUpdateRect(this._handle, &r.rect, false);
46 
47 					scope Canvas orgCanvas = Canvas.fromHDC(cast(HDC)m.wParam, false); //Don't delete it, it's a DC from WM_ERASEBKGND or WM_PAINT
48 					scope Canvas memCanvas = orgCanvas.createInMemory(); // Off Screen Canvas
49 
50 					Message rm = m;
51 
52 					rm.msg = WM_ERASEBKGND;
53 					rm.wParam = cast(WPARAM)memCanvas.handle;
54 					this.originalWndProc(rm);
55 
56 					rm.msg = WM_PAINT;
57 					//rm.wParam = cast(WPARAM)memCanvas.handle;
58 					this.originalWndProc(rm);
59 
60 					scope PaintEventArgs e = new PaintEventArgs(memCanvas, r);
61 					this.onPaint(e);
62 
63 					memCanvas.copyTo(orgCanvas, r, r.position);
64 					SubclassedControl.setBit(this._cBits, ControlBits.erased, true);
65 					m.result = 0;
66 				}
67 				else
68 				{
69 					this.originalWndProc(m);
70 				}
71 			}
72 			break;
73 
74 			case WM_PAINT:
75 			{
76 				if(SubclassedControl.hasBit(this._cBits, ControlBits.doubleBuffered) && SubclassedControl.hasBit(this._cBits, ControlBits.erased))
77 				{
78 					SubclassedControl.setBit(this._cBits, ControlBits.erased, false);
79 					m.result = 0;
80 				}
81 				else
82 				{
83 					/* *** Not double buffered *** */
84 					Rect r = void;
85 					GetUpdateRect(this._handle, &r.rect, false); //Keep drawing area
86 					this.originalWndProc(m);
87 
88 					scope Canvas c = Canvas.fromHDC(m.wParam ? cast(HDC)m.wParam : GetDC(this._handle), m.wParam ? false : true);
89 					HRGN hRgn = CreateRectRgnIndirect(&r.rect);
90 					SelectClipRgn(c.handle, hRgn);
91 					DeleteObject(hRgn);
92 
93 					SetBkColor(c.handle, this.backColor.colorref);
94 					SetTextColor(c.handle, this.foreColor.colorref);
95 
96 					scope PaintEventArgs e = new PaintEventArgs(c, r);
97 					this.onPaint(e);
98 				}
99 			}
100 			break;
101 
102 			case WM_CREATE:
103 				this.originalWndProc(m);
104 				super.wndProc(m);
105 				break;
106 
107 			default:
108 				super.wndProc(m);
109 				break;
110 		}
111 	}
112 }