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