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