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