1 // Written by Christopher E. Miller
2 // See the included license.txt for copyright and license details.
3 
4 
5 
6 module dfl.colordialog;
7 
8 private import dfl.commondialog, dfl.base, dfl.internal.winapi, dfl.internal.wincom;
9 private import dfl.internal.utf, dfl.application, dfl.drawing, dfl.internal.dlib;
10 
11 
12 
13 class ColorDialog: CommonDialog { // docmain
14    this() {
15       Application.ppin(cast(void*)this);
16 
17       cc.lStructSize = cc.sizeof;
18       cc.Flags = INIT_FLAGS;
19       cc.rgbResult = Color.empty.toArgb();
20       cc.lCustData = cast(typeof(cc.lCustData))cast(void*)this;
21       cc.lpfnHook = cast(typeof(cc.lpfnHook))&ccHookProc;
22       _initcust();
23    }
24 
25 
26 
27    @property void allowFullOpen(bool byes) { // setter
28       if(byes) {
29          cc.Flags &= ~CC_PREVENTFULLOPEN;
30       } else {
31          cc.Flags |= CC_PREVENTFULLOPEN;
32       }
33    }
34 
35    /// ditto
36    @property bool allowFullOpen() { // getter
37       return (cc.Flags & CC_PREVENTFULLOPEN) != CC_PREVENTFULLOPEN;
38    }
39 
40 
41 
42    @property void anyColor(bool byes) { // setter
43       if(byes) {
44          cc.Flags |= CC_ANYCOLOR;
45       } else {
46          cc.Flags &= ~CC_ANYCOLOR;
47       }
48    }
49 
50    /// ditto
51    @property bool anyColor() { // getter
52       return (cc.Flags & CC_ANYCOLOR) == CC_ANYCOLOR;
53    }
54 
55 
56 
57    @property void solidColorOnly(bool byes) { // setter
58       if(byes) {
59          cc.Flags |= CC_SOLIDCOLOR;
60       } else {
61          cc.Flags &= ~CC_SOLIDCOLOR;
62       }
63    }
64 
65    /// ditto
66    @property bool solidColorOnly() { // getter
67       return (cc.Flags & CC_SOLIDCOLOR) == CC_SOLIDCOLOR;
68    }
69 
70 
71 
72    final @property void color(Color c) { // setter
73       cc.rgbResult = c.toRgb();
74    }
75 
76    /// ditto
77    final @property Color color() { // getter
78       return Color.fromRgb(cc.rgbResult);
79    }
80 
81 
82 
83    final @property void customColors(COLORREF[] colors) { // setter
84       if(colors.length >= _cust.length) {
85          _cust[] = colors[0 .. _cust.length];
86       } else {
87          _cust[0 .. colors.length] = colors[];
88       }
89    }
90 
91    /// ditto
92    final @property COLORREF[] customColors() { // getter
93       return _cust;
94    }
95 
96 
97 
98    @property void fullOpen(bool byes) { // setter
99       if(byes) {
100          cc.Flags |= CC_FULLOPEN;
101       } else {
102          cc.Flags &= ~CC_FULLOPEN;
103       }
104    }
105 
106    /// ditto
107    @property bool fullOpen() { // getter
108       return (cc.Flags & CC_FULLOPEN) == CC_FULLOPEN;
109    }
110 
111 
112 
113    @property void showHelp(bool byes) { // setter
114       if(byes) {
115          cc.Flags |= CC_SHOWHELP;
116       } else {
117          cc.Flags &= ~CC_SHOWHELP;
118       }
119    }
120 
121    /// ditto
122    @property bool showHelp() { // getter
123       return (cc.Flags & CC_SHOWHELP) == CC_SHOWHELP;
124    }
125 
126 
127 
128    override DialogResult showDialog() {
129       return runDialog(GetActiveWindow()) ?
130              DialogResult.OK : DialogResult.CANCEL;
131    }
132 
133    /// ditto
134    override DialogResult showDialog(IWindow owner) {
135       return runDialog(owner ? owner.handle : GetActiveWindow()) ?
136              DialogResult.OK : DialogResult.CANCEL;
137    }
138 
139 
140 
141    override void reset() {
142       cc.Flags = INIT_FLAGS;
143       cc.rgbResult = Color.empty.toArgb();
144       _initcust();
145    }
146 
147 
148 
149    protected override bool runDialog(HWND owner) {
150       if(!_runDialog(owner)) {
151          if(!CommDlgExtendedError()) {
152             return false;
153          }
154          _cantrun();
155       }
156       return true;
157    }
158 
159 
160    private BOOL _runDialog(HWND owner) {
161       if(cc.rgbResult == Color.empty.toArgb()) {
162          cc.Flags &= ~CC_RGBINIT;
163       } else {
164          cc.Flags |= CC_RGBINIT;
165       }
166       cc.hwndOwner = owner;
167       cc.lpCustColors = _cust.ptr;
168       return ChooseColorA(&cc);
169    }
170 
171 
172  private:
173    enum DWORD INIT_FLAGS = CC_ENABLEHOOK;
174 
175    CHOOSECOLORA cc;
176    COLORREF[16] _cust;
177 
178 
179    void _initcust() {
180       COLORREF cdef;
181       cdef = Color(0xFF, 0xFF, 0xFF).toRgb();
182       foreach(ref COLORREF cref; _cust) {
183          cref = cdef;
184       }
185    }
186 }
187 
188 
189 private extern(Windows) UINT ccHookProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
190    enum PROP_STR = "DFL_ColorDialog";
191    ColorDialog cd;
192    UINT result = 0;
193 
194    try {
195       if(msg == WM_INITDIALOG) {
196          CHOOSECOLORA* cc;
197          cc = cast(CHOOSECOLORA*)lparam;
198          SetPropA(hwnd, PROP_STR.ptr, cast(HANDLE)cc.lCustData);
199          cd = cast(ColorDialog)cast(void*)cc.lCustData;
200       } else {
201          cd = cast(ColorDialog)cast(void*)GetPropA(hwnd, PROP_STR.ptr);
202       }
203 
204       if(cd) {
205          result = cast(UINT)cd.hookProc(hwnd, msg, wparam, lparam);
206       }
207    } catch(DThrowable e) {
208       Application.onThreadException(e);
209    }
210 
211    return result;
212 }
213