1/* winTheme.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sf.net> 2 * 3 * $Id$ 4 */ 5 6#ifdef _MSC_VER 7#define WIN32_LEAN_AND_MEAN 8#endif 9 10#include <tkWinInt.h> 11 12#ifndef DFCS_HOT /* Windows 98/Me, Windows 200/XP only */ 13#define DFCS_HOT 0 14#endif 15 16#include "ttk/ttkTheme.h" 17 18/* 19 * BoxToRect -- 20 * Helper routine. Converts a Ttk_Box to a Win32 RECT. 21 */ 22static RECT BoxToRect(Ttk_Box b) 23{ 24 RECT rc; 25 rc.top = b.y; 26 rc.left = b.x; 27 rc.bottom = b.y + b.height; 28 rc.right = b.x + b.width; 29 return rc; 30} 31 32/* 33 * ReliefToEdge -- 34 * Convert a Tk "relief" value into an Windows "edge" value. 35 * NB: Caller must check for RELIEF_FLAT and RELIEF_SOLID, 36 * which must be handled specially. 37 * 38 * Passing the BF_FLAT flag to DrawEdge() yields something similar 39 * to TK_RELIEF_SOLID. TK_RELIEF_FLAT can be implemented by not 40 * drawing anything. 41 */ 42static unsigned int ReliefToEdge(int relief) 43{ 44 switch (relief) { 45 case TK_RELIEF_RAISED: return EDGE_RAISED; 46 case TK_RELIEF_SUNKEN: return EDGE_SUNKEN; 47 case TK_RELIEF_RIDGE: return EDGE_BUMP; 48 case TK_RELIEF_GROOVE: return EDGE_ETCHED; 49 case TK_RELIEF_SOLID: return BDR_RAISEDOUTER; 50 default: 51 case TK_RELIEF_FLAT: return BDR_RAISEDOUTER; 52 } 53} 54 55/*------------------------------------------------------------------------ 56 * +++ State tables for FrameControlElements. 57 */ 58 59static Ttk_StateTable checkbutton_statemap[] = { /* see also SF#1865898 */ 60 { DFCS_BUTTON3STATE|DFCS_CHECKED|DFCS_INACTIVE, 61 TTK_STATE_ALTERNATE|TTK_STATE_DISABLED, 0 }, 62 { DFCS_BUTTON3STATE|DFCS_CHECKED|DFCS_PUSHED, 63 TTK_STATE_ALTERNATE|TTK_STATE_PRESSED, 0 }, 64 { DFCS_BUTTON3STATE|DFCS_CHECKED|DFCS_HOT, 65 TTK_STATE_ALTERNATE|TTK_STATE_ACTIVE, 0 }, 66 { DFCS_BUTTON3STATE|DFCS_CHECKED, 67 TTK_STATE_ALTERNATE, 0 }, 68 69 { DFCS_CHECKED|DFCS_INACTIVE, TTK_STATE_SELECTED|TTK_STATE_DISABLED, 0 }, 70 { DFCS_CHECKED|DFCS_PUSHED, TTK_STATE_SELECTED|TTK_STATE_PRESSED, 0 }, 71 { DFCS_CHECKED|DFCS_HOT, TTK_STATE_SELECTED|TTK_STATE_ACTIVE, 0 }, 72 { DFCS_CHECKED, TTK_STATE_SELECTED, 0 }, 73 74 { DFCS_INACTIVE, TTK_STATE_DISABLED, 0 }, 75 { DFCS_PUSHED, TTK_STATE_PRESSED, 0 }, 76 { DFCS_HOT, TTK_STATE_ACTIVE, 0 }, 77 { 0, 0, 0 }, 78}; 79 80static Ttk_StateTable pushbutton_statemap[] = { 81 { DFCS_INACTIVE, TTK_STATE_DISABLED, 0 }, 82 { DFCS_PUSHED, TTK_STATE_PRESSED, 0 }, 83 { DFCS_HOT, TTK_STATE_ACTIVE, 0 }, 84 { 0, 0, 0 } 85}; 86 87static Ttk_StateTable arrow_statemap[] = { 88 { DFCS_INACTIVE, TTK_STATE_DISABLED, 0 }, 89 { DFCS_PUSHED | DFCS_FLAT, TTK_STATE_PRESSED, 0 }, 90 { 0, 0, 0 } 91}; 92 93/*------------------------------------------------------------------------ 94 * +++ FrameControlElement -- 95 * General-purpose element for things drawn with DrawFrameControl 96 */ 97typedef struct { 98 const char *name; /* element name */ 99 int classId; /* class id for DrawFrameControl */ 100 int partId; /* part id for DrawFrameControl */ 101 int cxId; /* system metric ids for width/height... */ 102 int cyId; /* ... or size if FIXEDSIZE bit set */ 103 Ttk_StateTable *stateMap; /* map Tk states to Win32 flags */ 104 Ttk_Padding margins; /* additional placement padding */ 105} FrameControlElementData; 106 107#define _FIXEDSIZE 0x80000000L 108#define _HALFMETRIC 0x40000000L 109#define FIXEDSIZE(id) (id|_FIXEDSIZE) 110#define HALFMETRIC(id) (id|_HALFMETRIC) 111#define GETMETRIC(m) \ 112 ((m) & _FIXEDSIZE ? (int)((m) & ~_FIXEDSIZE) : GetSystemMetrics((m)&0x0fffffff)) 113 114static FrameControlElementData FrameControlElements[] = { 115 { "Checkbutton.indicator", 116 DFC_BUTTON, DFCS_BUTTONCHECK, FIXEDSIZE(13), FIXEDSIZE(13), 117 checkbutton_statemap, {0,0,4,0} }, 118 { "Radiobutton.indicator", 119 DFC_BUTTON, DFCS_BUTTONRADIO, FIXEDSIZE(13), FIXEDSIZE(13), 120 checkbutton_statemap, {0,0,4,0} }, 121 { "uparrow", 122 DFC_SCROLL, DFCS_SCROLLUP, SM_CXVSCROLL, SM_CYVSCROLL, 123 arrow_statemap, {0,0,0,0} }, 124 { "downarrow", 125 DFC_SCROLL, DFCS_SCROLLDOWN, SM_CXVSCROLL, SM_CYVSCROLL, 126 arrow_statemap, {0,0,0,0} }, 127 { "leftarrow", 128 DFC_SCROLL, DFCS_SCROLLLEFT, SM_CXHSCROLL, SM_CYHSCROLL, 129 arrow_statemap, {0,0,0,0} }, 130 { "rightarrow", 131 DFC_SCROLL, DFCS_SCROLLRIGHT, SM_CXHSCROLL, SM_CYHSCROLL, 132 arrow_statemap, {0,0,0,0} }, 133 { "sizegrip", 134 DFC_SCROLL, DFCS_SCROLLSIZEGRIP, SM_CXVSCROLL, SM_CYHSCROLL, 135 arrow_statemap, {0,0,0,0} }, 136 { "Spinbox.uparrow", 137 DFC_SCROLL, DFCS_SCROLLUP, SM_CXVSCROLL, HALFMETRIC(SM_CYVSCROLL), 138 arrow_statemap, {0,0,0,0} }, 139 { "Spinbox.downarrow", 140 DFC_SCROLL, DFCS_SCROLLDOWN, SM_CXVSCROLL, HALFMETRIC(SM_CYVSCROLL), 141 arrow_statemap, {0,0,0,0} }, 142 143 { 0,0,0,0,0,0, {0,0,0,0} } 144}; 145 146/* ---------------------------------------------------------------------- */ 147 148static void FrameControlElementSize( 149 void *clientData, void *elementRecord, Tk_Window tkwin, 150 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 151{ 152 FrameControlElementData *p = clientData; 153 int cx = GETMETRIC(p->cxId); 154 int cy = GETMETRIC(p->cyId); 155 if (p->cxId & _HALFMETRIC) cx /= 2; 156 if (p->cyId & _HALFMETRIC) cy /= 2; 157 *widthPtr = cx + Ttk_PaddingWidth(p->margins); 158 *heightPtr = cy + Ttk_PaddingHeight(p->margins); 159} 160 161static void FrameControlElementDraw( 162 void *clientData, void *elementRecord, Tk_Window tkwin, 163 Drawable d, Ttk_Box b, unsigned int state) 164{ 165 FrameControlElementData *elementData = clientData; 166 RECT rc = BoxToRect(Ttk_PadBox(b, elementData->margins)); 167 TkWinDCState dcState; 168 HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); 169 170 DrawFrameControl(hdc, &rc, 171 elementData->classId, 172 elementData->partId|Ttk_StateTableLookup(elementData->stateMap, state)); 173 TkWinReleaseDrawableDC(d, hdc, &dcState); 174} 175 176static Ttk_ElementSpec FrameControlElementSpec = { 177 TK_STYLE_VERSION_2, 178 sizeof(NullElement), 179 TtkNullElementOptions, 180 FrameControlElementSize, 181 FrameControlElementDraw 182}; 183 184/*---------------------------------------------------------------------- 185 * +++ Border element implementation. 186 */ 187 188typedef struct { 189 Tcl_Obj *reliefObj; 190} BorderElement; 191 192static Ttk_ElementOptionSpec BorderElementOptions[] = { 193 { "-relief",TK_OPTION_RELIEF,Tk_Offset(BorderElement,reliefObj), "flat" }, 194 {NULL, 0, 0, NULL} 195}; 196 197static void BorderElementSize( 198 void *clientData, void *elementRecord, Tk_Window tkwin, 199 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 200{ 201 paddingPtr->left = paddingPtr->right = GetSystemMetrics(SM_CXEDGE); 202 paddingPtr->top = paddingPtr->bottom = GetSystemMetrics(SM_CYEDGE); 203} 204 205static void BorderElementDraw( 206 void *clientData, void *elementRecord, Tk_Window tkwin, 207 Drawable d, Ttk_Box b, unsigned int state) 208{ 209 BorderElement *border = elementRecord; 210 RECT rc = BoxToRect(b); 211 int relief = TK_RELIEF_FLAT; 212 TkWinDCState dcState; 213 HDC hdc; 214 215 Tk_GetReliefFromObj(NULL, border->reliefObj, &relief); 216 217 if (relief != TK_RELIEF_FLAT) { 218 UINT xFlags = (relief == TK_RELIEF_SOLID) ? BF_FLAT : 0; 219 hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); 220 DrawEdge(hdc, &rc, ReliefToEdge(relief), BF_RECT | xFlags); 221 TkWinReleaseDrawableDC(d, hdc, &dcState); 222 } 223} 224 225static Ttk_ElementSpec BorderElementSpec = { 226 TK_STYLE_VERSION_2, 227 sizeof(BorderElement), 228 BorderElementOptions, 229 BorderElementSize, 230 BorderElementDraw 231}; 232 233/* 234 * Entry field borders: 235 * Sunken border; also fill with window color. 236 */ 237 238typedef struct { 239 Tcl_Obj *backgroundObj; 240} FieldElement; 241 242static Ttk_ElementOptionSpec FieldElementOptions[] = { 243 { "-fieldbackground", TK_OPTION_BORDER, 244 Tk_Offset(FieldElement,backgroundObj), "white" }, 245 { NULL, 0, 0, NULL } 246}; 247 248static void FieldElementSize( 249 void *clientData, void *elementRecord, Tk_Window tkwin, 250 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 251{ 252 paddingPtr->left = paddingPtr->right = GetSystemMetrics(SM_CXEDGE); 253 paddingPtr->top = paddingPtr->bottom = GetSystemMetrics(SM_CYEDGE); 254} 255 256static void FieldElementDraw( 257 void *clientData, void *elementRecord, Tk_Window tkwin, 258 Drawable d, Ttk_Box b, unsigned int state) 259{ 260 FieldElement *field = elementRecord; 261 Tk_3DBorder bg = Tk_Get3DBorderFromObj(tkwin, field->backgroundObj); 262 RECT rc = BoxToRect(b); 263 TkWinDCState dcState; 264 HDC hdc; 265 266 Tk_Fill3DRectangle( 267 tkwin, d, bg, b.x, b.y, b.width, b.height, 0, TK_RELIEF_FLAT); 268 269 hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); 270 DrawEdge(hdc, &rc, EDGE_SUNKEN, BF_RECT); 271 TkWinReleaseDrawableDC(d, hdc, &dcState); 272} 273 274static Ttk_ElementSpec FieldElementSpec = { 275 TK_STYLE_VERSION_2, 276 sizeof(FieldElement), 277 FieldElementOptions, 278 FieldElementSize, 279 FieldElementDraw 280}; 281 282/*------------------------------------------------------------------------ 283 * +++ Button borders. 284 * Drawn with DrawFrameControl instead of DrawEdge; 285 * Also draw default indicator and focus ring. 286 */ 287typedef struct { 288 Tcl_Obj *reliefObj; 289 Tcl_Obj *highlightColorObj; 290 Tcl_Obj *defaultStateObj; 291} ButtonBorderElement; 292 293static Ttk_ElementOptionSpec ButtonBorderElementOptions[] = { 294 { "-relief",TK_OPTION_RELIEF, 295 Tk_Offset(ButtonBorderElement,reliefObj), "flat" }, 296 { "-highlightcolor",TK_OPTION_COLOR, 297 Tk_Offset(ButtonBorderElement,highlightColorObj), "black" }, 298 { "-default", TK_OPTION_ANY, 299 Tk_Offset(ButtonBorderElement,defaultStateObj), "disabled" }, 300 {NULL, 0, 0, NULL} 301}; 302 303static void ButtonBorderElementSize( 304 void *clientData, void *elementRecord, Tk_Window tkwin, 305 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 306{ 307 ButtonBorderElement *bd = elementRecord; 308 int relief = TK_RELIEF_RAISED; 309 int defaultState = TTK_BUTTON_DEFAULT_DISABLED; 310 short int cx, cy; 311 312 Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief); 313 Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState); 314 cx = GetSystemMetrics(SM_CXEDGE); 315 cy = GetSystemMetrics(SM_CYEDGE); 316 317 /* Space for default indicator: 318 */ 319 if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) { 320 ++cx; ++cy; 321 } 322 323 /* Space for focus ring: 324 */ 325 cx += 2; 326 cy += 2; 327 328 *paddingPtr = Ttk_MakePadding(cx,cy,cx,cy); 329} 330 331static void ButtonBorderElementDraw( 332 void *clientData, void *elementRecord, Tk_Window tkwin, 333 Drawable d, Ttk_Box b, unsigned int state) 334{ 335 ButtonBorderElement *bd = elementRecord; 336 int relief = TK_RELIEF_FLAT; 337 int defaultState = TTK_BUTTON_DEFAULT_DISABLED; 338 TkWinDCState dcState; 339 HDC hdc; 340 RECT rc; 341 342 Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief); 343 Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState); 344 345 if (defaultState == TTK_BUTTON_DEFAULT_ACTIVE) { 346 XColor *highlightColor = 347 Tk_GetColorFromObj(tkwin, bd->highlightColorObj); 348 GC gc = Tk_GCForColor(highlightColor, d); 349 XDrawRectangle(Tk_Display(tkwin), d, gc, b.x,b.y,b.width-1,b.height-1); 350 } 351 if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) { 352 ++b.x; ++b.y; b.width -= 2; b.height -= 2; 353 } 354 355 hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); 356 357 rc = BoxToRect(b); 358 DrawFrameControl(hdc, &rc, 359 DFC_BUTTON, /* classId */ 360 DFCS_BUTTONPUSH | Ttk_StateTableLookup(pushbutton_statemap, state)); 361 362 /* Draw focus ring: 363 */ 364 if (state & TTK_STATE_FOCUS) { 365 short int borderWidth = 3; /* @@@ Use GetSystemMetrics?*/ 366 rc = BoxToRect(Ttk_PadBox(b, Ttk_UniformPadding(borderWidth))); 367 DrawFocusRect(hdc, &rc); 368 } 369 TkWinReleaseDrawableDC(d, hdc, &dcState); 370} 371 372static Ttk_ElementSpec ButtonBorderElementSpec = { 373 TK_STYLE_VERSION_2, 374 sizeof(ButtonBorderElement), 375 ButtonBorderElementOptions, 376 ButtonBorderElementSize, 377 ButtonBorderElementDraw 378}; 379 380/*------------------------------------------------------------------------ 381 * +++ Focus element. 382 * Draw dashed focus rectangle. 383 */ 384 385static void FocusElementSize( 386 void *clientData, void *elementRecord, Tk_Window tkwin, 387 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 388{ 389 *paddingPtr = Ttk_UniformPadding(1); 390} 391 392static void FocusElementDraw( 393 void *clientData, void *elementRecord, Tk_Window tkwin, 394 Drawable d, Ttk_Box b, unsigned int state) 395{ 396 if (state & TTK_STATE_FOCUS) { 397 RECT rc = BoxToRect(b); 398 TkWinDCState dcState; 399 HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); 400 DrawFocusRect(hdc, &rc); 401 TkWinReleaseDrawableDC(d, hdc, &dcState); 402 } 403} 404 405static Ttk_ElementSpec FocusElementSpec = { 406 TK_STYLE_VERSION_2, 407 sizeof(NullElement), 408 TtkNullElementOptions, 409 FocusElementSize, 410 FocusElementDraw 411}; 412 413/* FillFocusElement -- 414 * Draws a focus ring filled with the selection color 415 */ 416 417typedef struct { 418 Tcl_Obj *fillColorObj; 419} FillFocusElement; 420 421static Ttk_ElementOptionSpec FillFocusElementOptions[] = { 422 { "-focusfill", TK_OPTION_COLOR, 423 Tk_Offset(FillFocusElement,fillColorObj), "white" }, 424 {NULL, 0, 0, NULL} 425}; 426 427 /* @@@ FIX THIS */ 428static void FillFocusElementDraw( 429 void *clientData, void *elementRecord, Tk_Window tkwin, 430 Drawable d, Ttk_Box b, unsigned int state) 431{ 432 FillFocusElement *focus = elementRecord; 433 if (state & TTK_STATE_FOCUS) { 434 RECT rc = BoxToRect(b); 435 TkWinDCState dcState; 436 XColor *fillColor = Tk_GetColorFromObj(tkwin, focus->fillColorObj); 437 GC gc = Tk_GCForColor(fillColor, d); 438 HDC hdc; 439 440 XFillRectangle(Tk_Display(tkwin),d,gc, b.x,b.y,b.width,b.height); 441 hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); 442 DrawFocusRect(hdc, &rc); 443 TkWinReleaseDrawableDC(d, hdc, &dcState); 444 } 445} 446 447/* 448 * ComboboxFocusElement -- 449 * Read-only comboboxes have a filled focus ring, editable ones do not. 450 */ 451static void ComboboxFocusElementDraw( 452 void *clientData, void *elementRecord, Tk_Window tkwin, 453 Drawable d, Ttk_Box b, unsigned int state) 454{ 455 if (state & TTK_STATE_READONLY) { 456 FillFocusElementDraw(clientData, elementRecord, tkwin, d, b, state); 457 } 458} 459 460static Ttk_ElementSpec ComboboxFocusElementSpec = { 461 TK_STYLE_VERSION_2, 462 sizeof(FillFocusElement), 463 FillFocusElementOptions, 464 FocusElementSize, 465 ComboboxFocusElementDraw 466}; 467 468/*---------------------------------------------------------------------- 469 * +++ Scrollbar trough element. 470 * 471 * The native windows scrollbar is drawn using a pattern brush giving a 472 * stippled appearance when the trough might otherwise be invisible. 473 * We can deal with this here. 474 */ 475 476typedef struct { /* clientData for Trough element */ 477 HBRUSH PatternBrush; 478 HBITMAP PatternBitmap; 479} TroughClientData; 480 481static const WORD Pattern[] = { 482 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa 483}; 484 485static void TroughClientDataDeleteProc(void *clientData) 486{ 487 TroughClientData *cd = clientData; 488 DeleteObject(cd->PatternBrush); 489 DeleteObject(cd->PatternBitmap); 490 ckfree(clientData); 491} 492 493static TroughClientData *TroughClientDataInit(Tcl_Interp *interp) 494{ 495 TroughClientData *cd = (TroughClientData*)ckalloc(sizeof(*cd)); 496 cd->PatternBitmap = CreateBitmap(8, 8, 1, 1, Pattern); 497 cd->PatternBrush = CreatePatternBrush(cd->PatternBitmap); 498 Ttk_RegisterCleanup(interp, cd, TroughClientDataDeleteProc); 499 return cd; 500} 501 502static void TroughElementDraw( 503 void *clientData, void *elementRecord, Tk_Window tkwin, 504 Drawable d, Ttk_Box b, unsigned int state) 505{ 506 TroughClientData *cd = clientData; 507 TkWinDCState dcState; 508 HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); 509 HBRUSH hbr; 510 COLORREF bk, oldbk, oldtxt; 511 512 hbr = SelectObject(hdc, GetSysColorBrush(COLOR_SCROLLBAR)); 513 bk = GetSysColor(COLOR_3DHIGHLIGHT); 514 oldtxt = SetTextColor(hdc, GetSysColor(COLOR_3DFACE)); 515 oldbk = SetBkColor(hdc, bk); 516 517 /* WAS: if (bk (COLOR_3DHIGHLIGHT) == GetSysColor(COLOR_WINDOW)) ... */ 518 if (GetSysColor(COLOR_SCROLLBAR) == GetSysColor(COLOR_BTNFACE)) { 519 /* Draw using the pattern brush */ 520 SelectObject(hdc, cd->PatternBrush); 521 } 522 523 PatBlt(hdc, b.x, b.y, b.width, b.height, PATCOPY); 524 SetBkColor(hdc, oldbk); 525 SetTextColor(hdc, oldtxt); 526 SelectObject(hdc, hbr); 527 TkWinReleaseDrawableDC(d, hdc, &dcState); 528} 529 530static Ttk_ElementSpec TroughElementSpec = { 531 TK_STYLE_VERSION_2, 532 sizeof(NullElement), 533 TtkNullElementOptions, 534 TtkNullElementSize, 535 TroughElementDraw 536}; 537 538/*------------------------------------------------------------------------ 539 * +++ Thumb element. 540 */ 541 542typedef struct { 543 Tcl_Obj *orientObj; 544} ThumbElement; 545 546static Ttk_ElementOptionSpec ThumbElementOptions[] = { 547 { "-orient", TK_OPTION_ANY,Tk_Offset(ThumbElement,orientObj),"horizontal"}, 548 { NULL, 0, 0, NULL } 549}; 550 551static void ThumbElementSize( 552 void *clientData, void *elementRecord, Tk_Window tkwin, 553 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 554{ 555 ThumbElement *thumbPtr = elementRecord; 556 int orient; 557 558 Ttk_GetOrientFromObj(NULL, thumbPtr->orientObj, &orient); 559 if (orient == TTK_ORIENT_HORIZONTAL) { 560 *widthPtr = GetSystemMetrics(SM_CXHTHUMB); 561 *heightPtr = GetSystemMetrics(SM_CYHSCROLL); 562 } else { 563 *widthPtr = GetSystemMetrics(SM_CXVSCROLL); 564 *heightPtr = GetSystemMetrics(SM_CYVTHUMB); 565 } 566} 567 568static void ThumbElementDraw( 569 void *clientData, void *elementRecord, Tk_Window tkwin, 570 Drawable d, Ttk_Box b, unsigned int state) 571{ 572 RECT rc = BoxToRect(b); 573 TkWinDCState dcState; 574 HDC hdc; 575 576 /* Windows doesn't show a thumb when the scrollbar is disabled */ 577 if (state & TTK_STATE_DISABLED) 578 return; 579 580 hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); 581 DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT | BF_MIDDLE); 582 TkWinReleaseDrawableDC(d, hdc, &dcState); 583} 584 585static Ttk_ElementSpec ThumbElementSpec = { 586 TK_STYLE_VERSION_2, 587 sizeof(ThumbElement), 588 ThumbElementOptions, 589 ThumbElementSize, 590 ThumbElementDraw 591}; 592 593/* ---------------------------------------------------------------------- 594 * The slider element is the shaped thumb used in the slider widget. 595 * Windows likes to call this a trackbar. 596 */ 597 598typedef struct { 599 Tcl_Obj *orientObj; /* orientation of the slider widget */ 600} SliderElement; 601 602static Ttk_ElementOptionSpec SliderElementOptions[] = { 603 { "-orient", TK_OPTION_ANY, Tk_Offset(SliderElement,orientObj), 604 "horizontal" }, 605 { NULL, 0, 0, NULL } 606}; 607 608static void SliderElementSize( 609 void *clientData, void *elementRecord, Tk_Window tkwin, 610 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 611{ 612 SliderElement *slider = elementRecord; 613 int orient; 614 615 Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient); 616 if (orient == TTK_ORIENT_HORIZONTAL) { 617 *widthPtr = (GetSystemMetrics(SM_CXHTHUMB) / 2) | 1; 618 *heightPtr = GetSystemMetrics(SM_CYHSCROLL); 619 } else { 620 *widthPtr = GetSystemMetrics(SM_CXVSCROLL); 621 *heightPtr = (GetSystemMetrics(SM_CYVTHUMB) / 2) | 1; 622 } 623} 624 625static void SliderElementDraw( 626 void *clientData, void *elementRecord, Tk_Window tkwin, 627 Drawable d, Ttk_Box b, unsigned int state) 628{ 629 RECT rc = BoxToRect(b); 630 TkWinDCState dcState; 631 HDC hdc; 632 633 hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); 634 DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT | BF_MIDDLE); 635 TkWinReleaseDrawableDC(d, hdc, &dcState); 636} 637 638static Ttk_ElementSpec SliderElementSpec = { 639 TK_STYLE_VERSION_2, 640 sizeof(SliderElement), 641 SliderElementOptions, 642 SliderElementSize, 643 SliderElementDraw 644}; 645 646/*------------------------------------------------------------------------ 647 * +++ Notebook elements. 648 */ 649 650static void ClientElementSize( 651 void *clientData, void *elementRecord, Tk_Window tkwin, 652 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) 653{ 654 paddingPtr->left = paddingPtr->right = GetSystemMetrics(SM_CXEDGE); 655 paddingPtr->top = paddingPtr->bottom = GetSystemMetrics(SM_CYEDGE); 656} 657 658static void ClientElementDraw( 659 void *clientData, void *elementRecord, Tk_Window tkwin, 660 Drawable d, Ttk_Box b, unsigned int state) 661{ 662 RECT rc = BoxToRect(b); 663 TkWinDCState dcState; 664 HDC hdc = TkWinGetDrawableDC(Tk_Display(tkwin), d, &dcState); 665 DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT | BF_SOFT); 666 TkWinReleaseDrawableDC(d, hdc, &dcState); 667} 668 669static Ttk_ElementSpec ClientElementSpec = { 670 TK_STYLE_VERSION_2, 671 sizeof(NullElement), 672 TtkNullElementOptions, 673 ClientElementSize, 674 ClientElementDraw 675}; 676 677/*------------------------------------------------------------------------ 678 * +++ Layouts. 679 */ 680 681TTK_BEGIN_LAYOUT_TABLE(LayoutTable) 682 683TTK_LAYOUT("TButton", 684 TTK_GROUP("Button.border", TTK_FILL_BOTH, 685 TTK_GROUP("Button.padding", TTK_FILL_BOTH, 686 TTK_NODE("Button.label", TTK_FILL_BOTH)))) 687 688TTK_LAYOUT("TCombobox", 689 TTK_GROUP("Combobox.field", TTK_FILL_BOTH, 690 TTK_NODE("Combobox.downarrow", TTK_PACK_RIGHT|TTK_FILL_Y) 691 TTK_GROUP("Combobox.padding", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_BOTH, 692 TTK_GROUP("Combobox.focus", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_BOTH, 693 TTK_NODE("Combobox.textarea", TTK_FILL_BOTH))))) 694 695TTK_END_LAYOUT_TABLE 696 697/* ---------------------------------------------------------------------- */ 698 699MODULE_SCOPE 700int TtkWinTheme_Init(Tcl_Interp *interp, HWND hwnd) 701{ 702 Ttk_Theme themePtr, parentPtr; 703 FrameControlElementData *fce = FrameControlElements; 704 705 parentPtr = Ttk_GetTheme(interp, "alt"); 706 themePtr = Ttk_CreateTheme(interp, "winnative", parentPtr); 707 if (!themePtr) { 708 return TCL_ERROR; 709 } 710 711 Ttk_RegisterElementSpec(themePtr, "border", &BorderElementSpec, NULL); 712 Ttk_RegisterElementSpec(themePtr, "Button.border", 713 &ButtonBorderElementSpec, NULL); 714 Ttk_RegisterElementSpec(themePtr, "field", &FieldElementSpec, NULL); 715 Ttk_RegisterElementSpec(themePtr, "focus", &FocusElementSpec, NULL); 716 Ttk_RegisterElementSpec(themePtr, "Combobox.focus", 717 &ComboboxFocusElementSpec, NULL); 718 Ttk_RegisterElementSpec(themePtr, "thumb", &ThumbElementSpec, NULL); 719 Ttk_RegisterElementSpec(themePtr, "slider", &SliderElementSpec, NULL); 720 Ttk_RegisterElementSpec(themePtr, "Scrollbar.trough", &TroughElementSpec, 721 TroughClientDataInit(interp)); 722 723 Ttk_RegisterElementSpec(themePtr, "client", &ClientElementSpec, NULL); 724 725 for (fce = FrameControlElements; fce->name != 0; ++fce) { 726 Ttk_RegisterElementSpec(themePtr, fce->name, 727 &FrameControlElementSpec, fce); 728 } 729 730 Ttk_RegisterLayouts(themePtr, LayoutTable); 731 732 Tcl_PkgProvide(interp, "ttk::theme::winnative", TTK_VERSION); 733 return TCL_OK; 734} 735 736