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