1 // Written by Christopher E. Miller 2 // See the included license.txt for copyright and license details. 3 4 5 /// 6 module dfl.tabcontrol; 7 8 private import dfl.internal.dlib; 9 10 private import dfl.control, dfl.panel, dfl.internal.winapi, dfl.drawing; 11 private import dfl.application, dfl.event, dfl.base, dfl.collections; 12 13 14 private extern(Windows) void _initTabcontrol(); 15 16 17 /// 18 class TabPage: Panel 19 { 20 /// 21 this(Dstring tabText) 22 { 23 this(); 24 25 this.text = tabText; 26 } 27 28 /+ 29 /// ditto 30 this(Object v) // package 31 { 32 this(getObjectString(v)); 33 } 34 +/ 35 36 /// ditto 37 this() 38 { 39 Application.ppin(cast(void*)this); 40 41 ctrlStyle |= ControlStyles.CONTAINER_CONTROL; 42 43 wstyle &= ~WS_VISIBLE; 44 cbits &= ~CBits.VISIBLE; 45 } 46 47 48 override Dstring toString() 49 { 50 return text; 51 } 52 53 54 alias Control.opEquals opEquals; 55 56 57 override Dequ opEquals(Object o) 58 { 59 return text == getObjectString(o); 60 } 61 62 63 Dequ opEquals(Dstring val) 64 { 65 return text == val; 66 } 67 68 69 alias Control.opCmp opCmp; 70 71 72 override int opCmp(Object o) 73 { 74 return stringICmp(text, getObjectString(o)); 75 } 76 77 78 int opCmp(Dstring val) 79 { 80 return stringICmp(text, val); 81 } 82 83 84 // imageIndex 85 86 87 override @property void text(Dstring newText) // setter 88 { 89 // Note: this probably causes toStringz() to be called twice, 90 // allocating 2 of the same string. 91 92 super.text = newText; 93 94 if(created) 95 { 96 TabControl tc; 97 tc = cast(TabControl)parent; 98 if(tc) 99 tc.updateTabText(this, newText); 100 } 101 } 102 103 alias Panel.text text; // Overload with Panel.text. 104 105 106 /+ 107 final @property void toolTipText(Dstring ttt) // setter 108 { 109 // TODO: ... 110 } 111 112 113 final @property Dstring toolTipText() // getter 114 { 115 // TODO: ... 116 return null; 117 } 118 +/ 119 120 121 /+ package +/ /+ protected +/ override int _rtype() // package 122 { 123 return 4; 124 } 125 126 127 protected override void setBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) 128 { 129 assert(0); // Cannot set bounds of TabPage; it is done automatically. 130 } 131 132 133 package final @property void realBounds(Rect r) // setter 134 { 135 // DMD 0.124: if I don't put this here, super.setBoundsCore ends up calling setBoundsCore instead of super.setBoundsCore. 136 void delegate(int, int, int, int, BoundsSpecified) _foo = &setBoundsCore; 137 138 super.setBoundsCore(r.x, r.y, r.width, r.height, BoundsSpecified.ALL); 139 } 140 141 142 protected override void setVisibleCore(bool byes) 143 { 144 assert(0); // Cannot set visibility of TabPage; it is done automatically. 145 } 146 147 148 package final @property void realVisible(bool byes) // setter 149 { 150 // DMD 0.124: if I don't put this here, super.setVisibleCore ends up calling setVisibleCore instead of super.setVisibleCore. 151 void delegate(bool byes) _foo = &setVisibleCore; 152 153 super.setVisibleCore(byes); 154 } 155 } 156 157 158 package union TcItem 159 { 160 TC_ITEMW tciw; 161 TC_ITEMA tcia; 162 struct 163 { 164 UINT mask; 165 UINT lpReserved1; 166 UINT lpReserved2; 167 private void* pszText; 168 int cchTextMax; 169 int iImage; 170 LPARAM lParam; 171 } 172 } 173 174 175 /// 176 class TabPageCollection 177 { 178 protected this(TabControl owner) 179 in 180 { 181 assert(owner.tchildren is null); 182 } 183 body 184 { 185 tc = owner; 186 } 187 188 189 private: 190 191 TabControl tc; 192 TabPage[] _pages = null; 193 194 195 void doPages() 196 in 197 { 198 assert(created); 199 } 200 body 201 { 202 Rect area; 203 area = tc.displayRectangle; 204 205 Message m; 206 m.hWnd = tc.handle; 207 208 // Note: duplicate code. 209 //TC_ITEMA tci; 210 TcItem tci; 211 if(dfl.internal.utf.useUnicode) 212 { 213 m.msg = TCM_INSERTITEMW; // <-- 214 foreach(int i, TabPage page; _pages) 215 { 216 // TODO: TCIF_RTLREADING flag based on rightToLeft property. 217 tci.mask = TCIF_TEXT | TCIF_PARAM; 218 tci.tciw.pszText = cast(typeof(tci.tciw.pszText))dfl.internal.utf.toUnicodez(page.text); // <-- 219 static assert(tci.lParam.sizeof >= (void*).sizeof); 220 tci.lParam = cast(LPARAM)cast(void*)page; 221 222 m.wParam = i; 223 m.lParam = cast(LPARAM)&tci.tciw; 224 tc.prevWndProc(m); 225 assert(cast(int)m.result != -1); 226 } 227 } 228 else 229 { 230 m.msg = TCM_INSERTITEMA; // <-- 231 foreach(int i, TabPage page; _pages) 232 { 233 // TODO: TCIF_RTLREADING flag based on rightToLeft property. 234 tci.mask = TCIF_TEXT | TCIF_PARAM; 235 tci.tcia.pszText = cast(typeof(tci.tcia.pszText))dfl.internal.utf.toAnsiz(page.text); // <-- 236 static assert(tci.lParam.sizeof >= (void*).sizeof); 237 tci.lParam = cast(LPARAM)cast(void*)page; 238 239 m.wParam = i; 240 m.lParam = cast(LPARAM)&tci.tcia; 241 tc.prevWndProc(m); 242 assert(cast(int)m.result != -1); 243 } 244 } 245 } 246 247 248 package final @property bool created() // getter 249 { 250 return tc && tc.created(); 251 } 252 253 254 void _added(size_t idx, TabPage val) 255 { 256 if(val.parent) 257 { 258 TabControl tc; 259 tc = cast(TabControl)val.parent; 260 if(tc && tc.tabPages.indexOf(val) != -1) 261 throw new DflException("TabPage already has a parent"); 262 } 263 264 //val.realVisible = false; 265 assert(val.visible == false); 266 assert(!(tc is null)); 267 val.parent = tc; 268 269 if(created) 270 { 271 Message m; 272 //TC_ITEMA tci; 273 TcItem tci; 274 // TODO: TCIF_RTLREADING flag based on rightToLeft property. 275 tci.mask = TCIF_TEXT | TCIF_PARAM; 276 static assert(tci.lParam.sizeof >= (void*).sizeof); 277 tci.lParam = cast(LPARAM)cast(void*)val; 278 if(dfl.internal.utf.useUnicode) 279 { 280 tci.tciw.pszText = cast(typeof(tci.tciw.pszText))dfl.internal.utf.toUnicodez(val.text); 281 m = Message(tc.handle, TCM_INSERTITEMW, idx, cast(LPARAM)&tci.tciw); 282 } 283 else 284 { 285 tci.tcia.pszText = cast(typeof(tci.tcia.pszText))dfl.internal.utf.toAnsiz(val.text); 286 m = Message(tc.handle, TCM_INSERTITEMA, idx, cast(LPARAM)&tci.tcia); 287 } 288 tc.prevWndProc(m); 289 assert(cast(int)m.result != -1); 290 291 if(tc.selectedTab is val) 292 { 293 //val.realVisible = true; 294 tc.tabToFront(val); 295 } 296 } 297 } 298 299 300 void _removed(size_t idx, TabPage val) 301 { 302 if(size_t.max == idx) // Clear all. 303 { 304 if(created) 305 { 306 Message m; 307 m = Message(tc.handle, TCM_DELETEALLITEMS, 0, 0); 308 tc.prevWndProc(m); 309 } 310 } 311 else 312 { 313 //val.parent = null; // Can't do that. 314 315 if(created) 316 { 317 Message m; 318 m = Message(tc.handle, TCM_DELETEITEM, idx, 0); 319 tc.prevWndProc(m); 320 321 // Hide this one. 322 val.realVisible = false; 323 324 // Show next visible. 325 val = tc.selectedTab; 326 if(val) 327 tc.tabToFront(val); 328 } 329 } 330 } 331 332 333 public: 334 335 mixin ListWrapArray!(TabPage, _pages, 336 _blankListCallback!(TabPage), _added, 337 _blankListCallback!(TabPage), _removed, 338 true, false, false, 339 true); // CLEAR_EACH 340 } 341 342 343 /// 344 enum TabAlignment: ubyte 345 { 346 TOP, /// 347 BOTTOM, /// ditto 348 LEFT, /// ditto 349 RIGHT, /// ditto 350 } 351 352 353 /// 354 enum TabAppearance: ubyte 355 { 356 NORMAL, /// 357 BUTTONS, /// ditto 358 FLAT_BUTTONS, /// ditto 359 } 360 361 362 /// 363 enum TabDrawMode: ubyte 364 { 365 NORMAL, /// 366 OWNER_DRAW_FIXED, /// ditto 367 } 368 369 370 /// 371 class TabControlBase: ControlSuperClass 372 { 373 this() 374 { 375 _initTabcontrol(); 376 377 wstyle |= WS_TABSTOP; 378 ctrlStyle |= ControlStyles.SELECTABLE | ControlStyles.CONTAINER_CONTROL; 379 wclassStyle = tabcontrolClassStyle; 380 } 381 382 383 /// 384 final @property void drawMode(TabDrawMode dm) // setter 385 { 386 switch(dm) 387 { 388 case TabDrawMode.OWNER_DRAW_FIXED: 389 _style(wstyle | TCS_OWNERDRAWFIXED); 390 break; 391 392 case TabDrawMode.NORMAL: 393 _style(wstyle & ~TCS_OWNERDRAWFIXED); 394 break; 395 396 default: 397 assert(0); 398 } 399 400 _crecreate(); 401 } 402 403 /// ditto 404 final @property TabDrawMode drawMode() // getter 405 { 406 if(wstyle & TCS_OWNERDRAWFIXED) 407 return TabDrawMode.OWNER_DRAW_FIXED; 408 return TabDrawMode.NORMAL; 409 } 410 411 412 override @property Rect displayRectangle() // getter 413 { 414 if(!created) 415 { 416 return super.displayRectangle(); // Hack? 417 } 418 else 419 { 420 RECT drr; 421 Message m; 422 drr.left = 0; 423 drr.top = 0; 424 drr.right = clientSize.width; 425 drr.bottom = clientSize.height; 426 m = Message(hwnd, TCM_ADJUSTRECT, FALSE, cast(LPARAM)&drr); 427 prevWndProc(m); 428 return Rect(&drr); 429 } 430 } 431 432 433 protected override @property Size defaultSize() // getter 434 { 435 return Size(200, 200); // ? 436 } 437 438 439 /// 440 final Rect getTabRect(int i) 441 { 442 Rect result; 443 444 if(created) 445 { 446 RECT rt; 447 Message m; 448 m = Message(hwnd, TCM_GETITEMRECT, cast(WPARAM)i, cast(LPARAM)&rt); 449 prevWndProc(m); 450 if(!m.result) 451 goto rtfail; 452 result = Rect(&rt); 453 } 454 else 455 { 456 rtfail: 457 with(result) 458 { 459 x = 0; 460 y = 0; 461 width = 0; 462 height = 0; 463 } 464 } 465 466 return result; 467 } 468 469 470 // drawItem event. 471 //EventHandler selectedIndexChanged; 472 Event!(TabControlBase, EventArgs) selectedIndexChanged; /// 473 //CancelEventHandler selectedIndexChanging; 474 Event!(TabControlBase, CancelEventArgs) selectedIndexChanging; /// 475 476 477 protected override void createParams(ref CreateParams cp) 478 { 479 super.createParams(cp); 480 481 cp.className = TABCONTROL_CLASSNAME; 482 } 483 484 485 /// 486 protected void onSelectedIndexChanged(EventArgs ea) 487 { 488 selectedIndexChanged(this, ea); 489 } 490 491 492 /// 493 protected void onSelectedIndexChanging(CancelEventArgs ea) 494 { 495 selectedIndexChanging(this, ea); 496 } 497 498 499 protected override void prevWndProc(ref Message msg) 500 { 501 //msg.result = CallWindowProcA(tabcontrolPrevWndProc, msg.hWnd, msg.msg, msg.wParam, msg.lParam); 502 msg.result = dfl.internal.utf.callWindowProc(tabcontrolPrevWndProc, msg.hWnd, msg.msg, msg.wParam, msg.lParam); 503 } 504 505 506 protected override void wndProc(ref Message m) 507 { 508 // TODO: support the tab control messages. 509 510 switch(m.msg) 511 { 512 /+ 513 case WM_SETFOCUS: 514 _exStyle(_exStyle() | WS_EX_CONTROLPARENT); 515 break; 516 517 case WM_KILLFOCUS: 518 _exStyle(_exStyle() & ~WS_EX_CONTROLPARENT); 519 break; 520 +/ 521 522 case TCM_DELETEALLITEMS: 523 m.result = FALSE; 524 return; 525 526 case TCM_DELETEITEM: 527 m.result = FALSE; 528 return; 529 530 case TCM_INSERTITEMA: 531 case TCM_INSERTITEMW: 532 m.result = -1; 533 return; 534 535 //case TCM_REMOVEIMAGE: 536 // return; 537 538 //case TCM_SETIMAGELIST: 539 // m.result = cast(LRESULT)null; 540 // return; 541 542 case TCM_SETITEMA: 543 case TCM_SETITEMW: 544 m.result = FALSE; 545 return; 546 547 case TCM_SETITEMEXTRA: 548 m.result = FALSE; 549 return; 550 551 case TCM_SETITEMSIZE: 552 m.result = 0; 553 return; 554 555 case TCM_SETPADDING: 556 return; 557 558 case TCM_SETTOOLTIPS: 559 return; 560 561 default: 562 } 563 564 super.wndProc(m); 565 } 566 567 568 protected override void onReflectedMessage(ref Message m) 569 { 570 super.onReflectedMessage(m); 571 572 TabPage page; 573 NMHDR* nmh; 574 nmh = cast(NMHDR*)m.lParam; 575 576 switch(nmh.code) 577 { 578 case TCN_SELCHANGE: 579 onSelectedIndexChanged(EventArgs.empty); 580 break; 581 582 case TCN_SELCHANGING: 583 { 584 scope CancelEventArgs ea = new CancelEventArgs; 585 onSelectedIndexChanging(ea); 586 if(ea.cancel) 587 { 588 m.result = TRUE; // Prevent change. 589 return; 590 } 591 } 592 m.result = FALSE; // Allow change. 593 return; 594 595 default: 596 } 597 } 598 } 599 600 601 /// 602 class TabControl: TabControlBase // docmain 603 { 604 this() 605 { 606 tchildren = new TabPageCollection(this); 607 _pad = Point(6, 3); 608 } 609 610 611 /// 612 final @property void alignment(TabAlignment talign) // setter 613 { 614 switch(talign) 615 { 616 case TabAlignment.TOP: 617 _style(wstyle & ~(TCS_VERTICAL | TCS_RIGHT | TCS_BOTTOM)); 618 break; 619 620 case TabAlignment.BOTTOM: 621 _style((wstyle & ~(TCS_VERTICAL | TCS_RIGHT)) | TCS_BOTTOM); 622 break; 623 624 case TabAlignment.LEFT: 625 _style((wstyle & ~(TCS_BOTTOM | TCS_RIGHT)) | TCS_VERTICAL); 626 break; 627 628 case TabAlignment.RIGHT: 629 _style((wstyle & ~TCS_BOTTOM) | TCS_VERTICAL | TCS_RIGHT); 630 break; 631 632 default: 633 assert(0); 634 } 635 636 // Display rectangle changed. 637 638 if(created && visible) 639 { 640 invalidate(true); // Update children too ? 641 642 TabPage page; 643 page = selectedTab; 644 if(page) 645 page.realBounds = displayRectangle; 646 } 647 } 648 649 /// ditto 650 final @property TabAlignment alignment() // getter 651 { 652 // Note: TCS_RIGHT and TCS_BOTTOM are the same flag. 653 654 if(wstyle & TCS_VERTICAL) 655 { 656 if(wstyle & TCS_RIGHT) 657 return TabAlignment.RIGHT; 658 return TabAlignment.LEFT; 659 } 660 else 661 { 662 if(wstyle & TCS_BOTTOM) 663 return TabAlignment.BOTTOM; 664 return TabAlignment.TOP; 665 } 666 } 667 668 669 /// 670 final @property void appearance(TabAppearance tappear) // setter 671 { 672 switch(tappear) 673 { 674 case TabAppearance.NORMAL: 675 _style(wstyle & ~(TCS_BUTTONS | TCS_FLATBUTTONS)); 676 break; 677 678 case TabAppearance.BUTTONS: 679 _style((wstyle & ~TCS_FLATBUTTONS) | TCS_BUTTONS); 680 break; 681 682 case TabAppearance.FLAT_BUTTONS: 683 _style(wstyle | TCS_BUTTONS | TCS_FLATBUTTONS); 684 break; 685 686 default: 687 assert(0); 688 } 689 690 if(created && visible) 691 { 692 invalidate(false); 693 694 TabPage page; 695 page = selectedTab; 696 if(page) 697 page.realBounds = displayRectangle; 698 } 699 } 700 701 /// ditto 702 final @property TabAppearance appearance() // getter 703 { 704 if(wstyle & TCS_FLATBUTTONS) 705 return TabAppearance.FLAT_BUTTONS; 706 if(wstyle & TCS_BUTTONS) 707 return TabAppearance.BUTTONS; 708 return TabAppearance.NORMAL; 709 } 710 711 712 /// 713 final @property void padding(Point pad) // setter 714 { 715 if(created) 716 { 717 SendMessageA(hwnd, TCM_SETPADDING, 0, MAKELPARAM(pad.x, pad.y)); 718 719 TabPage page; 720 page = selectedTab; 721 if(page) 722 page.realBounds = displayRectangle; 723 } 724 725 _pad = pad; 726 } 727 728 /// ditto 729 final @property Point padding() // getter 730 { 731 return _pad; 732 } 733 734 735 /// 736 final @property TabPageCollection tabPages() // getter 737 { 738 return tchildren; 739 } 740 741 742 /// 743 final @property void multiline(bool byes) // setter 744 { 745 if(byes) 746 _style(_style() | TCS_MULTILINE); 747 else 748 _style(_style() & ~TCS_MULTILINE); 749 750 TabPage page; 751 page = selectedTab; 752 if(page) 753 page.realBounds = displayRectangle; 754 } 755 756 /// ditto 757 final @property bool multiline() // getter 758 { 759 return (_style() & TCS_MULTILINE) != 0; 760 } 761 762 763 /// 764 final @property int rowCount() // getter 765 { 766 if(!created || !multiline) 767 return 0; 768 Message m; 769 m = Message(hwnd, TCM_GETROWCOUNT, 0, 0); 770 prevWndProc(m); 771 return cast(int)m.result; 772 } 773 774 775 /// 776 final @property int tabCount() // getter 777 { 778 return tchildren._pages.length; 779 } 780 781 782 /// 783 final @property void selectedIndex(int i) // setter 784 { 785 if(!created || !tchildren._pages.length) 786 return; 787 788 TabPage curpage; 789 curpage = selectedTab; 790 if(curpage is tchildren._pages[i]) 791 return; // Already selected. 792 curpage.realVisible = false; 793 794 SendMessageA(hwnd, TCM_SETCURSEL, cast(WPARAM)i, 0); 795 tabToFront(tchildren._pages[i]); 796 } 797 798 /// ditto 799 // Returns -1 if there are no tabs selected. 800 final @property int selectedIndex() // getter 801 { 802 if(!created || !tchildren._pages.length) 803 return -1; 804 Message m; 805 m = Message(hwnd, TCM_GETCURSEL, 0, 0); 806 prevWndProc(m); 807 return cast(int)m.result; 808 } 809 810 811 /// 812 final @property void selectedTab(TabPage page) // setter 813 { 814 int i; 815 i = tabPages.indexOf(page); 816 if(-1 != i) 817 selectedIndex = i; 818 } 819 820 /// ditto 821 final @property TabPage selectedTab() // getter 822 { 823 int i; 824 i = selectedIndex; 825 if(-1 == i) 826 return null; 827 return tchildren._pages[i]; 828 } 829 830 831 /+ 832 /// 833 final @property void showToolTips(bool byes) // setter 834 { 835 if(byes) 836 _style(_style() | TCS_TOOLTIPS); 837 else 838 _style(_style() & ~TCS_TOOLTIPS); 839 } 840 841 /// ditto 842 final @property bool showToolTips() // getter 843 { 844 return (_style() & TCS_TOOLTIPS) != 0; 845 } 846 +/ 847 848 849 protected override void onHandleCreated(EventArgs ea) 850 { 851 super.onHandleCreated(ea); 852 853 SendMessageA(hwnd, TCM_SETPADDING, 0, MAKELPARAM(_pad.x, _pad.y)); 854 855 tchildren.doPages(); 856 857 // Bring selected tab to front. 858 if(tchildren._pages.length) 859 { 860 int i; 861 i = selectedIndex; 862 if(-1 != i) 863 tabToFront(tchildren._pages[i]); 864 } 865 } 866 867 868 protected override void onLayout(LayoutEventArgs ea) 869 { 870 if(tchildren._pages.length) 871 { 872 int i; 873 i = selectedIndex; 874 if(-1 != i) 875 { 876 tchildren._pages[i].realBounds = displayRectangle; 877 //assert(tchildren._pages[i].bounds == displayRectangle); 878 } 879 } 880 881 //super.onLayout(ea); // Tab control shouldn't even have other controls on it. 882 super.onLayout(ea); // Should call it for consistency. Ideally it just checks handlers.length == 0 and does nothing. 883 } 884 885 886 /+ 887 protected override void wndProc(ref Message m) 888 { 889 // TODO: support the tab control messages. 890 891 switch(m.msg) 892 { 893 /+ // Now handled in onLayout(). 894 case WM_WINDOWPOSCHANGED: 895 { 896 WINDOWPOS* wp; 897 wp = cast(WINDOWPOS*)m.lParam; 898 899 if(!(wp.flags & SWP_NOSIZE) || (wp.flags & SWP_FRAMECHANGED)) 900 { 901 if(tchildren._pages.length) 902 { 903 int i; 904 i = selectedIndex; 905 if(-1 != i) 906 { 907 tchildren._pages[i].realBounds = displayRectangle; 908 //assert(tchildren._pages[i].bounds == displayRectangle); 909 } 910 } 911 } 912 } 913 break; 914 +/ 915 916 default: 917 } 918 919 super.wndProc(m); 920 } 921 +/ 922 923 924 protected override void onReflectedMessage(ref Message m) 925 { 926 TabPage page; 927 NMHDR* nmh; 928 nmh = cast(NMHDR*)m.lParam; 929 930 switch(nmh.code) 931 { 932 case TCN_SELCHANGE: 933 page = selectedTab; 934 if(page) 935 tabToFront(page); 936 super.onReflectedMessage(m); 937 break; 938 939 case TCN_SELCHANGING: 940 super.onReflectedMessage(m); 941 if(!m.result) // Allowed. 942 { 943 page = selectedTab; 944 if(page) 945 page.realVisible = false; 946 } 947 return; 948 949 default: 950 super.onReflectedMessage(m); 951 } 952 } 953 954 955 /+ 956 /+ package +/ /+ protected +/ override int _rtype() // package 957 { 958 return 0x20; 959 } 960 +/ 961 962 963 private: 964 Point _pad; 965 TabPageCollection tchildren; 966 967 968 void tabToFront(TabPage page) 969 { 970 page.realBounds = displayRectangle; 971 //page.realVisible = true; 972 SetWindowPos(page.handle, HWND_TOP, 0, 0, 0, 0, /+ SWP_NOACTIVATE | +/ SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); 973 assert(page.visible == true); 974 975 /+ 976 // Make sure the previous tab isn't still focused. 977 // Will "steal" focus if done programatically. 978 SetFocus(handle); 979 //SetFocus(page.handle); 980 +/ 981 } 982 983 984 void updateTabText(TabPage page, Dstring newText) 985 in 986 { 987 assert(created); 988 } 989 body 990 { 991 int i; 992 i = tabPages.indexOf(page); 993 assert(-1 != i); 994 995 //TC_ITEMA tci; 996 TcItem tci; 997 tci.mask = TCIF_TEXT; 998 Message m; 999 if(dfl.internal.utf.useUnicode) 1000 { 1001 tci.tciw.pszText = cast(typeof(tci.tciw.pszText))dfl.internal.utf.toUnicodez(newText); 1002 m = Message(hwnd, TCM_SETITEMW, cast(WPARAM)i, cast(LPARAM)&tci.tciw); 1003 } 1004 else 1005 { 1006 tci.tcia.pszText = cast(typeof(tci.tcia.pszText))dfl.internal.utf.toAnsiz(newText); 1007 m = Message(hwnd, TCM_SETITEMA, cast(WPARAM)i, cast(LPARAM)&tci.tcia); 1008 } 1009 prevWndProc(m); 1010 1011 // Updating a tab's text could cause tab rows to be adjusted, 1012 // so update the selected tab's area. 1013 page = selectedTab; 1014 if(page) 1015 page.realBounds = displayRectangle; 1016 } 1017 } 1018