1 // Written by Christopher E. Miller 2 // See the included license.txt for copyright and license details. 3 4 5 6 module dfl.groupbox; 7 8 private import dfl.control, dfl.base, dfl.button, dfl.drawing; 9 private import dfl.internal.winapi, dfl.application, dfl.event; 10 11 12 private extern(Windows) void _initButton(); 13 14 15 version(NO_DRAG_DROP) 16 version = DFL_NO_DRAG_DROP; 17 18 19 20 class GroupBox: ControlSuperClass { // docmain 21 override @property Rect displayRectangle() { // getter 22 // Should only calculate this upon setting the text ? 23 24 int xw = GetSystemMetrics(SM_CXFRAME); 25 int yw = GetSystemMetrics(SM_CYFRAME); 26 //const int _textHeight = 13; // Hack. 27 return Rect(xw, yw + _textHeight, clientSize.width - xw * 2, clientSize.height - yw - _textHeight - yw); 28 } 29 30 31 override @property Size defaultSize() { // getter 32 return Size(200, 100); 33 } 34 35 36 version(DFL_NO_DRAG_DROP) {} else { 37 override @property void allowDrop(bool dyes) { // setter 38 //if(dyes) 39 // throw new DflException("Cannot drop on a group box"); 40 assert(!dyes, "Cannot drop on a group box"); 41 } 42 43 alias Control.allowDrop allowDrop; // Overload. 44 } 45 46 47 this() { 48 _initButton(); 49 50 if(DEFTEXTHEIGHT_INIT == _defTextHeight) { 51 //_recalcTextHeight(defaultFont); 52 _recalcTextHeight(font); 53 _defTextHeight = _textHeight; 54 } 55 _textHeight = _defTextHeight; 56 57 wstyle |= BS_GROUPBOX /+ | WS_TABSTOP +/; // Should WS_TABSTOP be set? 58 //wstyle |= BS_GROUPBOX | WS_TABSTOP; 59 //wexstyle |= WS_EX_CONTROLPARENT; // ? 60 wclassStyle = buttonClassStyle; 61 ctrlStyle |= ControlStyles.CONTAINER_CONTROL; 62 } 63 64 65 protected override void onFontChanged(EventArgs ea) { 66 _dispChanged(); 67 68 super.onFontChanged(ea); 69 } 70 71 72 protected override void onHandleCreated(EventArgs ea) { 73 super.onHandleCreated(ea); 74 75 _dispChanged(); 76 } 77 78 79 protected override void createParams(ref CreateParams cp) { 80 super.createParams(cp); 81 82 cp.className = BUTTON_CLASSNAME; 83 } 84 85 86 protected override void wndProc(ref Message msg) { 87 switch(msg.msg) { 88 case WM_NCHITTEST: 89 Control._defWndProc(msg); 90 break; 91 92 default: 93 super.wndProc(msg); 94 } 95 } 96 97 98 protected override void onPaintBackground(PaintEventArgs ea) { 99 //Control.onPaintBackground(ea); // DMD 0.106: not accessible. 100 101 RECT rect; 102 ea.clipRectangle.getRect(&rect); 103 FillRect(ea.graphics.handle, &rect, hbrBg); 104 } 105 106 107 protected override void prevWndProc(ref Message msg) { 108 //msg.result = CallWindowProcA(buttonPrevWndProc, msg.hWnd, msg.msg, msg.wParam, msg.lParam); 109 msg.result = dfl.internal.utf.callWindowProc(buttonPrevWndProc, msg.hWnd, msg.msg, msg.wParam, msg.lParam); 110 111 // Work around a Windows issue... 112 if(WM_PAINT == msg.msg) { 113 auto hmuxt = GetModuleHandleA("uxtheme.dll"); 114 if(hmuxt) { 115 auto isAppThemed = cast(typeof(&IsAppThemed))GetProcAddress(hmuxt, "IsAppThemed"); 116 if(isAppThemed && isAppThemed()) { 117 auto txt = text; 118 if(txt.length) { 119 auto openThemeData = cast(typeof(&OpenThemeData))GetProcAddress(hmuxt, "OpenThemeData"); 120 HTHEME htd; 121 if(openThemeData 122 && HTHEME.init != (htd = openThemeData(msg.hWnd, "Button"))) { 123 HDC hdc = cast(HDC)msg.wParam; 124 //PAINTSTRUCT ps; 125 bool gotdc = false; 126 if(!hdc) { 127 //hdc = BeginPaint(msg.hWnd, &ps); 128 gotdc = true; 129 hdc = GetDC(msg.hWnd); 130 } 131 try { 132 scope g = new Graphics(hdc, false); // Not owned. 133 auto f = font; 134 scope tfmt = new TextFormat(TextFormatFlags.SINGLE_LINE); 135 136 Color c; 137 COLORREF cr; 138 auto getThemeColor = cast(typeof(&GetThemeColor))GetProcAddress(hmuxt, "GetThemeColor"); 139 auto gtcState = enabled ? (1 /*PBS_NORMAL*/) : (2 /*GBS_DISABLED*/); 140 if(getThemeColor 141 && 0 == getThemeColor(htd, 4 /*BP_GROUPBOX*/, gtcState, 3803 /*TMT_TEXTCOLOR*/, &cr)) { 142 c = Color.fromRgb(cr); 143 } else { 144 c = enabled ? foreColor : SystemColors.grayText; // ? 145 } 146 147 Size tsz = g.measureText(txt, f, tfmt); 148 149 g.fillRectangle(backColor, 8, 0, 2 + tsz.width + 2, tsz.height + 2); 150 g.drawText(txt, f, c, Rect(8 + 2, 0, tsz.width, tsz.height), tfmt); 151 } 152 finally { 153 //if(ps.hdc) 154 // EndPaint(msg.hWnd, &ps); 155 if(gotdc) { 156 ReleaseDC(msg.hWnd, hdc); 157 } 158 159 auto closeThemeData = cast(typeof(&CloseThemeData))GetProcAddress(hmuxt, "CloseThemeData"); 160 assert(closeThemeData !is null); 161 closeThemeData(htd); 162 } 163 } 164 } 165 } 166 } 167 } 168 } 169 170 171 private: 172 173 enum int DEFTEXTHEIGHT_INIT = -1; 174 static int _defTextHeight = DEFTEXTHEIGHT_INIT; 175 int _textHeight = -1; 176 177 178 void _recalcTextHeight(Font f) { 179 _textHeight = cast(int)f.getSize(GraphicsUnit.PIXEL); 180 } 181 182 183 void _dispChanged() { 184 int old = _textHeight; 185 _recalcTextHeight(font); 186 if(old != _textHeight) { 187 //if(isHandleCreated) 188 { 189 // Display area changed... 190 // ? 191 suspendLayout(); 192 resumeLayout(true); 193 } 194 } 195 } 196 } 197