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