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