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