Reactos

[COMCTL32_WINETEST] Sync with Wine Staging 4.18. CORE-16441

+1306 -176
+675 -117
modules/rostests/winetests/comctl32/button.c
··· 47 47 /****************** button message test *************************/ 48 48 #define ID_BUTTON 0x000e 49 49 50 - #define COMBINED_SEQ_INDEX 0 51 - #define NUM_MSG_SEQUENCES 1 50 + #define COMBINED_SEQ_INDEX 0 51 + #define PARENT_CD_SEQ_INDEX 1 52 + #define NUM_MSG_SEQUENCES 2 52 53 53 54 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES]; 54 55 ··· 160 161 return ret; 161 162 } 162 163 164 + static struct 165 + { 166 + DWORD button; 167 + UINT line; 168 + UINT state; 169 + DWORD ret; 170 + BOOL empty; 171 + } test_cd; 172 + 173 + #define set_test_cd_state(s) do { \ 174 + test_cd.state = (s); \ 175 + test_cd.empty = TRUE; \ 176 + test_cd.line = __LINE__; \ 177 + } while (0) 178 + 179 + #define set_test_cd_ret(r) do { \ 180 + test_cd.ret = (r); \ 181 + test_cd.empty = TRUE; \ 182 + test_cd.line = __LINE__; \ 183 + } while (0) 184 + 185 + static void disable_test_cd(void) 186 + { 187 + test_cd.line = 0; 188 + } 189 + 163 190 static LRESULT WINAPI test_parent_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 164 191 { 165 192 static LONG defwndproc_counter = 0; 166 193 static LONG beginpaint_counter = 0; 194 + static HDC cd_first_hdc; 167 195 struct message msg = { 0 }; 196 + NMCUSTOMDRAW *cd = (NMCUSTOMDRAW*)lParam; 197 + NMBCDROPDOWN *bcd = (NMBCDROPDOWN*)lParam; 168 198 LRESULT ret; 169 199 170 200 if (ignore_message( message )) return 0; ··· 184 214 add_message(sequences, COMBINED_SEQ_INDEX, &msg); 185 215 } 186 216 217 + if (message == WM_NOTIFY && cd->hdr.code == NM_CUSTOMDRAW && test_cd.line) 218 + { 219 + /* Ignore an inconsistency across Windows versions */ 220 + UINT state = cd->uItemState & ~CDIS_SHOWKEYBOARDCUES; 221 + 222 + /* Some Windows configurations paint twice with different DC */ 223 + if (test_cd.empty) 224 + { 225 + cd_first_hdc = cd->hdc; 226 + test_cd.empty = FALSE; 227 + } 228 + 229 + ok_(__FILE__,test_cd.line)(!(cd->dwDrawStage & CDDS_ITEM), 230 + "[%u] CDDS_ITEM is set\n", test_cd.button); 231 + 232 + ok_(__FILE__,test_cd.line)(state == test_cd.state, 233 + "[%u] expected uItemState %u, got %u\n", test_cd.button, 234 + test_cd.state, state); 235 + 236 + msg.message = message; 237 + msg.flags = sent|parent|wparam|lparam|id|custdraw; 238 + msg.wParam = wParam; 239 + msg.lParam = lParam; 240 + msg.id = NM_CUSTOMDRAW; 241 + msg.stage = cd->dwDrawStage; 242 + if (cd->hdc == cd_first_hdc) 243 + add_message(sequences, PARENT_CD_SEQ_INDEX, &msg); 244 + 245 + ret = test_cd.ret; 246 + switch (msg.stage) 247 + { 248 + case CDDS_PREERASE: 249 + ret &= ~CDRF_NOTIFYPOSTPAINT; 250 + cd->dwItemSpec = 0xdeadbeef; 251 + break; 252 + case CDDS_PREPAINT: 253 + ret &= ~CDRF_NOTIFYPOSTERASE; 254 + break; 255 + case CDDS_POSTERASE: 256 + case CDDS_POSTPAINT: 257 + ok_(__FILE__,test_cd.line)(cd->dwItemSpec == 0xdeadbeef, 258 + "[%u] NMCUSTOMDRAW was not shared, stage %u\n", test_cd.button, msg.stage); 259 + break; 260 + } 261 + return ret; 262 + } 263 + 264 + if (message == WM_NOTIFY && bcd->hdr.code == BCN_DROPDOWN) 265 + { 266 + UINT button = GetWindowLongW(bcd->hdr.hwndFrom, GWL_STYLE) & BS_TYPEMASK; 267 + RECT rc; 268 + 269 + GetClientRect(bcd->hdr.hwndFrom, &rc); 270 + 271 + ok(bcd->hdr.hwndFrom != NULL, "Received BCN_DROPDOWN with no hwnd attached, wParam %lu id %lu\n", 272 + wParam, bcd->hdr.idFrom); 273 + ok(bcd->hdr.idFrom == wParam, "[%u] Mismatch between wParam (%lu) and idFrom (%lu)\n", 274 + button, wParam, bcd->hdr.idFrom); 275 + ok(EqualRect(&rc, &bcd->rcButton), "[%u] Wrong rcButton, expected %s got %s\n", 276 + button, wine_dbgstr_rect(&rc), wine_dbgstr_rect(&bcd->rcButton)); 277 + 278 + msg.message = message; 279 + msg.flags = sent|parent|wparam|lparam|id; 280 + msg.wParam = wParam; 281 + msg.lParam = lParam; 282 + msg.id = BCN_DROPDOWN; 283 + add_message(sequences, COMBINED_SEQ_INDEX, &msg); 284 + return 0; 285 + } 286 + 187 287 if (message == WM_PAINT) 188 288 { 189 289 PAINTSTRUCT ps; ··· 461 561 { 0 } 462 562 }; 463 563 564 + static const struct message empty_cd_seq[] = { { 0 } }; 565 + 566 + static const struct message pre_cd_seq[] = 567 + { 568 + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE }, 569 + { 0 } 570 + }; 571 + 572 + static const struct message pre_pre_cd_seq[] = 573 + { 574 + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE }, 575 + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT }, 576 + { 0 } 577 + }; 578 + 579 + static const struct message pre_post_pre_cd_seq[] = 580 + { 581 + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE }, 582 + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTERASE }, 583 + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT }, 584 + { 0 } 585 + }; 586 + 587 + static const struct message pre_pre_post_cd_seq[] = 588 + { 589 + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE }, 590 + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT }, 591 + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTPAINT }, 592 + { 0 } 593 + }; 594 + 595 + static const struct message pre_post_pre_post_cd_seq[] = 596 + { 597 + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE }, 598 + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTERASE }, 599 + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT }, 600 + { WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTPAINT }, 601 + { 0 } 602 + }; 603 + 604 + static const struct message bcn_dropdown_seq[] = 605 + { 606 + { WM_KEYDOWN, sent|wparam|lparam, VK_DOWN, 0 }, 607 + { BCM_SETDROPDOWNSTATE, sent|wparam|lparam|defwinproc, 1, 0 }, 608 + { WM_NOTIFY, sent|parent|id, 0, 0, BCN_DROPDOWN }, 609 + { BCM_SETDROPDOWNSTATE, sent|wparam|lparam|defwinproc, 0, 0 }, 610 + { WM_KEYUP, sent|wparam|lparam, VK_DOWN, 0xc0000000 }, 611 + { WM_PAINT, sent }, 612 + { WM_DRAWITEM, sent|parent|optional }, /* for owner draw button */ 613 + { WM_PAINT, sent|optional }, /* sometimes sent rarely */ 614 + { WM_DRAWITEM, sent|parent|optional }, 615 + { 0 } 616 + }; 617 + 464 618 static HWND create_button(DWORD style, HWND parent) 465 619 { 466 620 HMENU menuid = 0; ··· 479 633 480 634 static void test_button_messages(void) 481 635 { 636 + enum cd_seq_type 637 + { 638 + cd_seq_empty, 639 + cd_seq_normal, 640 + cd_seq_optional 641 + }; 642 + 482 643 static const struct 483 644 { 484 645 DWORD style; ··· 489 650 const struct message *setstate; 490 651 const struct message *clearstate; 491 652 const struct message *setcheck; 653 + enum cd_seq_type cd_setfocus_type; 654 + enum cd_seq_type cd_setstyle_type; 655 + enum cd_seq_type cd_setstate_type; 656 + enum cd_seq_type cd_setcheck_type; 492 657 } button[] = { 493 658 { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, 494 659 setfocus_seq, killfocus_seq, setstyle_seq, 495 - setstate_seq, setstate_seq, setcheck_ignored_seq }, 660 + setstate_seq, setstate_seq, setcheck_ignored_seq, 661 + cd_seq_normal, cd_seq_normal, cd_seq_normal, cd_seq_optional }, 496 662 { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON, 497 663 setfocus_seq, killfocus_seq, setstyle_seq, 498 - setstate_seq, setstate_seq, setcheck_ignored_seq }, 664 + setstate_seq, setstate_seq, setcheck_ignored_seq, 665 + cd_seq_normal, cd_seq_normal, cd_seq_normal, cd_seq_optional }, 499 666 { BS_CHECKBOX, DLGC_BUTTON, 500 667 setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, 501 - setstate_static_seq, setstate_static_seq, setcheck_static_seq }, 668 + setstate_static_seq, setstate_static_seq, setcheck_static_seq, 669 + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional }, 502 670 { BS_AUTOCHECKBOX, DLGC_BUTTON, 503 671 setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, 504 - setstate_static_seq, setstate_static_seq, setcheck_static_seq }, 672 + setstate_static_seq, setstate_static_seq, setcheck_static_seq, 673 + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional }, 505 674 { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, 506 675 setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, 507 - setstate_static_seq, setstate_static_seq, setcheck_radio_redraw_seq }, 676 + setstate_static_seq, setstate_static_seq, setcheck_radio_redraw_seq, 677 + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional }, 508 678 { BS_3STATE, DLGC_BUTTON, 509 679 setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, 510 - setstate_static_seq, setstate_static_seq, setcheck_static_seq }, 680 + setstate_static_seq, setstate_static_seq, setcheck_static_seq, 681 + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional }, 511 682 { BS_AUTO3STATE, DLGC_BUTTON, 512 683 setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, 513 - setstate_static_seq, setstate_static_seq, setcheck_static_seq }, 684 + setstate_static_seq, setstate_static_seq, setcheck_static_seq, 685 + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional }, 514 686 { BS_GROUPBOX, DLGC_STATIC, 515 687 setfocus_groupbox_seq, killfocus_static_seq, setstyle_static_seq, 516 - setstate_static_seq, setstate_static_seq, setcheck_ignored_seq }, 688 + setstate_static_seq, setstate_static_seq, setcheck_ignored_seq, 689 + cd_seq_empty, cd_seq_empty, cd_seq_empty, cd_seq_empty }, 517 690 { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, 518 691 setfocus_seq, killfocus_seq, setstyle_user_seq, 519 - setstate_user_seq, clearstate_seq, setcheck_ignored_seq }, 692 + setstate_user_seq, clearstate_seq, setcheck_ignored_seq, 693 + cd_seq_normal, cd_seq_empty, cd_seq_empty, cd_seq_empty }, 520 694 { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, 521 695 setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, 522 - setstate_static_seq, setstate_static_seq, setcheck_radio_redraw_seq }, 696 + setstate_static_seq, setstate_static_seq, setcheck_radio_redraw_seq, 697 + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional }, 523 698 { BS_OWNERDRAW, DLGC_BUTTON, 524 699 setfocus_ownerdraw_seq, killfocus_ownerdraw_seq, setstyle_ownerdraw_seq, 525 - setstate_ownerdraw_seq, clearstate_ownerdraw_seq, setcheck_ignored_seq }, 700 + setstate_ownerdraw_seq, clearstate_ownerdraw_seq, setcheck_ignored_seq, 701 + cd_seq_empty, cd_seq_empty, cd_seq_empty, cd_seq_empty }, 526 702 { BS_SPLITBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON | DLGC_WANTARROWS, 527 703 setfocus_seq, killfocus_seq, setstyle_seq, 528 - setstate_seq, setstate_seq, setcheck_ignored_seq }, 704 + setstate_seq, setstate_seq, setcheck_ignored_seq, 705 + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_empty }, 529 706 { BS_DEFSPLITBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON | DLGC_WANTARROWS, 530 707 setfocus_seq, killfocus_seq, setstyle_seq, 531 - setstate_seq, setstate_seq, setcheck_ignored_seq }, 708 + setstate_seq, setstate_seq, setcheck_ignored_seq, 709 + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_empty }, 532 710 { BS_COMMANDLINK, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, 533 711 setfocus_seq, killfocus_seq, setstyle_seq, 534 - setstate_seq, setstate_seq, setcheck_ignored_seq }, 712 + setstate_seq, setstate_seq, setcheck_ignored_seq, 713 + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_empty }, 535 714 { BS_DEFCOMMANDLINK, DLGC_BUTTON | DLGC_DEFPUSHBUTTON, 536 715 setfocus_seq, killfocus_seq, setstyle_seq, 537 - setstate_seq, setstate_seq, setcheck_ignored_seq }, 716 + setstate_seq, setstate_seq, setcheck_ignored_seq, 717 + cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_empty } 538 718 }; 539 719 LOGFONTA logfont = { 0 }; 540 - const struct message *seq; 720 + const struct message *seq, *cd_seq; 541 721 HFONT zfont, hfont2; 542 722 unsigned int i; 543 723 HWND hwnd, parent; ··· 565 745 hfont2 = CreateFontIndirectA(&logfont); 566 746 ok(hfont2 != NULL, "Failed to create Tahoma font\n"); 567 747 748 + #define check_cd_seq(type, context) do { \ 749 + if (button[i].type != cd_seq_optional || !test_cd.empty) \ 750 + ok_sequence(sequences, PARENT_CD_SEQ_INDEX, cd_seq, "[CustomDraw] " context, FALSE); \ 751 + } while(0) 752 + 568 753 for (i = 0; i < ARRAY_SIZE(button); i++) 569 754 { 570 755 HFONT prevfont, hfont; ··· 572 757 DWORD style, state; 573 758 HDC hdc; 574 759 760 + test_cd.button = button[i].style; 575 761 hwnd = create_button(button[i].style, parent); 576 762 ok(hwnd != NULL, "Failed to create a button.\n"); 577 763 ··· 599 785 SetFocus(0); 600 786 flush_events(); 601 787 SetFocus(0); 788 + cd_seq = (button[i].cd_setfocus_type == cd_seq_empty) ? empty_cd_seq : pre_pre_cd_seq; 602 789 flush_sequences(sequences, NUM_MSG_SEQUENCES); 790 + set_test_cd_ret(CDRF_DODEFAULT); 791 + set_test_cd_state(CDIS_FOCUS); 603 792 604 - todo = button[i].style != BS_OWNERDRAW; 605 793 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 606 794 SetFocus(hwnd); 607 795 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 608 796 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 609 - ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setfocus, "SetFocus(hwnd) on a button", todo); 797 + ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setfocus, "SetFocus(hwnd) on a button", FALSE); 798 + check_cd_seq(cd_setfocus_type, "SetFocus(hwnd)"); 610 799 611 - todo = button[i].style == BS_OWNERDRAW; 800 + set_test_cd_state(0); 612 801 SetFocus(0); 613 802 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 614 803 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 615 - ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].killfocus, "SetFocus(0) on a button", todo); 804 + ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].killfocus, "SetFocus(0) on a button", FALSE); 805 + check_cd_seq(cd_setfocus_type, "SetFocus(0)"); 616 806 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); 807 + 808 + cd_seq = (button[i].cd_setstyle_type == cd_seq_empty) ? empty_cd_seq : pre_pre_cd_seq; 809 + set_test_cd_state(0); 617 810 618 811 SendMessageA(hwnd, BM_SETSTYLE, button[i].style | BS_BOTTOM, TRUE); 619 812 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 620 813 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 621 814 todo = button[i].style == BS_OWNERDRAW; 622 815 ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setstyle, "BM_SETSTYLE on a button", todo); 816 + check_cd_seq(cd_setstyle_type, "BM_SETSTYLE"); 623 817 624 818 style = GetWindowLongA(hwnd, GWL_STYLE); 625 819 style &= ~(WS_VISIBLE | WS_CHILD | BS_NOTIFY); ··· 629 823 state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); 630 824 ok(state == 0, "expected state 0, got %04x\n", state); 631 825 826 + cd_seq = (button[i].cd_setstate_type == cd_seq_empty) ? empty_cd_seq : pre_pre_cd_seq; 632 827 flush_sequences(sequences, NUM_MSG_SEQUENCES); 828 + set_test_cd_state(CDIS_SELECTED); 633 829 634 830 SendMessageA(hwnd, BM_SETSTATE, TRUE, 0); 635 831 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 636 832 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 637 833 ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setstate, "BM_SETSTATE/TRUE on a button", FALSE); 834 + check_cd_seq(cd_setstate_type, "BM_SETSTATE/TRUE"); 638 835 639 836 state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); 640 837 ok(state == BST_PUSHED, "expected state 0x0004, got %04x\n", state); ··· 644 841 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 645 842 646 843 flush_sequences(sequences, NUM_MSG_SEQUENCES); 844 + set_test_cd_state(0); 647 845 648 846 SendMessageA(hwnd, BM_SETSTATE, FALSE, 0); 649 847 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 650 848 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 651 849 ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].clearstate, "BM_SETSTATE/FALSE on a button", FALSE); 850 + check_cd_seq(cd_setstate_type, "BM_SETSTATE/FALSE"); 652 851 653 852 state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); 654 853 ok(state == 0, "expected state 0, got %04x\n", state); ··· 660 859 state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); 661 860 ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state); 662 861 862 + cd_seq = (button[i].cd_setcheck_type == cd_seq_empty) ? empty_cd_seq : pre_pre_cd_seq; 663 863 flush_sequences(sequences, NUM_MSG_SEQUENCES); 864 + set_test_cd_state(0); 664 865 665 866 if (button[i].style == BS_RADIOBUTTON || 666 867 button[i].style == BS_AUTORADIOBUTTON) ··· 674 875 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 675 876 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 676 877 ok_sequence(sequences, COMBINED_SEQ_INDEX, seq, "BM_SETCHECK on a button", FALSE); 878 + check_cd_seq(cd_setcheck_type, "BM_SETCHECK"); 677 879 678 880 state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); 679 881 ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state); ··· 683 885 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); 684 886 685 887 flush_sequences(sequences, NUM_MSG_SEQUENCES); 888 + set_test_cd_state(0); 686 889 687 890 SendMessageA(hwnd, BM_SETCHECK, BST_CHECKED, 0); 688 891 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ 689 892 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 690 893 ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setcheck, "BM_SETCHECK on a button", FALSE); 894 + check_cd_seq(cd_setcheck_type, "BM_SETCHECK"); 691 895 692 896 state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); 693 897 if (button[i].style == BS_PUSHBUTTON || ··· 735 939 736 940 DeleteDC(hdc); 737 941 942 + /* Test Custom Draw return values */ 943 + if (button[i].cd_setfocus_type != cd_seq_empty && 944 + broken(button[i].style != BS_USERBUTTON) /* WinXP */) 945 + { 946 + static const struct 947 + { 948 + const char *context; 949 + LRESULT val; 950 + const struct message *seq; 951 + } ret[] = { 952 + { "CDRF_DODEFAULT", CDRF_DODEFAULT, pre_pre_cd_seq }, 953 + { "CDRF_DOERASE", CDRF_DOERASE, pre_pre_cd_seq }, 954 + { "CDRF_SKIPDEFAULT", CDRF_SKIPDEFAULT, pre_cd_seq }, 955 + { "CDRF_SKIPDEFAULT | CDRF_NOTIFYPOSTERASE | CDRF_NOTIFYPOSTPAINT", 956 + CDRF_SKIPDEFAULT | CDRF_NOTIFYPOSTERASE | CDRF_NOTIFYPOSTPAINT, pre_cd_seq }, 957 + { "CDRF_NOTIFYPOSTERASE", CDRF_NOTIFYPOSTERASE, pre_post_pre_cd_seq }, 958 + { "CDRF_NOTIFYPOSTPAINT", CDRF_NOTIFYPOSTPAINT, pre_pre_post_cd_seq }, 959 + { "CDRF_NOTIFYPOSTERASE | CDRF_NOTIFYPOSTPAINT", 960 + CDRF_NOTIFYPOSTERASE | CDRF_NOTIFYPOSTPAINT, pre_post_pre_post_cd_seq }, 961 + }; 962 + UINT k; 963 + 964 + for (k = 0; k < ARRAY_SIZE(ret); k++) 965 + { 966 + disable_test_cd(); 967 + SetFocus(0); 968 + set_test_cd_ret(ret[k].val); 969 + set_test_cd_state(CDIS_FOCUS); 970 + SetFocus(hwnd); 971 + flush_sequences(sequences, NUM_MSG_SEQUENCES); 972 + 973 + while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 974 + if (button[i].cd_setfocus_type != cd_seq_optional || !test_cd.empty) 975 + ok_sequence(sequences, PARENT_CD_SEQ_INDEX, ret[k].seq, ret[k].context, FALSE); 976 + } 977 + } 978 + 979 + disable_test_cd(); 980 + 981 + if (!broken(LOBYTE(LOWORD(GetVersion())) < 6)) /* not available pre-Vista */ 982 + { 983 + /* Send down arrow key to make the buttons send the drop down notification */ 984 + flush_sequences(sequences, NUM_MSG_SEQUENCES); 985 + SendMessageW(hwnd, WM_KEYDOWN, VK_DOWN, 0); 986 + SendMessageW(hwnd, WM_KEYUP, VK_DOWN, 0xc0000000); 987 + while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 988 + ok_sequence(sequences, COMBINED_SEQ_INDEX, bcn_dropdown_seq, "BCN_DROPDOWN from the button", FALSE); 989 + } 990 + 738 991 DestroyWindow(hwnd); 739 992 } 993 + 994 + #undef check_cd_seq 740 995 741 996 DeleteObject(hfont2); 742 997 DestroyWindow(parent); ··· 1228 1483 RegisterClassA(&cls); 1229 1484 } 1230 1485 1486 + static void test_bcm_splitinfo(HWND hwnd) 1487 + { 1488 + UINT button = GetWindowLongA(hwnd, GWL_STYLE) & BS_TYPEMASK; 1489 + int glyph_size = GetSystemMetrics(SM_CYMENUCHECK); 1490 + int border_w = GetSystemMetrics(SM_CXEDGE) * 2; 1491 + BUTTON_SPLITINFO info, dummy; 1492 + HIMAGELIST img; 1493 + BOOL ret; 1494 + 1495 + memset(&info, 0xCC, sizeof(info)); 1496 + info.mask = 0; 1497 + memcpy(&dummy, &info, sizeof(info)); 1498 + 1499 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info); 1500 + if (ret != TRUE) 1501 + { 1502 + static BOOL once; 1503 + if (!once) 1504 + win_skip("BCM_GETSPLITINFO message is unavailable. Skipping related tests\n"); /* Pre-Vista */ 1505 + once = TRUE; 1506 + return; 1507 + } 1508 + ok(!memcmp(&info, &dummy, sizeof(info)), "[%u] split info struct was changed with mask = 0\n", button); 1509 + 1510 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, 0); 1511 + ok(ret == FALSE, "[%u] expected FALSE, got %d\n", button, ret); 1512 + ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, 0); 1513 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1514 + 1515 + info.mask = BCSIF_GLYPH | BCSIF_SIZE | BCSIF_STYLE; 1516 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info); 1517 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1518 + ok(info.mask == (BCSIF_GLYPH | BCSIF_SIZE | BCSIF_STYLE), "[%u] wrong mask, got %u\n", button, info.mask); 1519 + ok(info.himlGlyph == (HIMAGELIST)0x36, "[%u] expected 0x36 default glyph, got 0x%p\n", button, info.himlGlyph); 1520 + ok(info.uSplitStyle == BCSS_STRETCH, "[%u] expected 0x%08x default style, got 0x%08x\n", button, BCSS_STRETCH, info.uSplitStyle); 1521 + ok(info.size.cx == glyph_size, "[%u] expected %d default size.cx, got %d\n", button, glyph_size, info.size.cx); 1522 + ok(info.size.cy == 0, "[%u] expected 0 default size.cy, got %d\n", button, info.size.cy); 1523 + 1524 + info.mask = BCSIF_SIZE; 1525 + info.size.cx = glyph_size + 7; 1526 + info.size.cy = 0; 1527 + ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info); 1528 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1529 + info.size.cx = info.size.cy = 0xdeadbeef; 1530 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info); 1531 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1532 + ok(info.mask == BCSIF_SIZE, "[%u] wrong mask, got %u\n", button, info.mask); 1533 + ok(info.size.cx == glyph_size + 7, "[%u] expected %d, got %d\n", button, glyph_size + 7, info.size.cx); 1534 + ok(info.size.cy == 0, "[%u] expected 0, got %d\n", button, info.size.cy); 1535 + 1536 + /* Invalid size.cx resets it to default glyph size, while size.cy is stored */ 1537 + info.size.cx = 0; 1538 + info.size.cy = -20; 1539 + ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info); 1540 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1541 + info.size.cx = info.size.cy = 0xdeadbeef; 1542 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info); 1543 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1544 + ok(info.mask == BCSIF_SIZE, "[%u] wrong mask, got %u\n", button, info.mask); 1545 + ok(info.size.cx == glyph_size, "[%u] expected %d, got %d\n", button, glyph_size, info.size.cx); 1546 + ok(info.size.cy == -20, "[%u] expected -20, got %d\n", button, info.size.cy); 1547 + 1548 + info.size.cx = -glyph_size - 7; 1549 + info.size.cy = -10; 1550 + ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info); 1551 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1552 + info.size.cx = info.size.cy = 0xdeadbeef; 1553 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info); 1554 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1555 + ok(info.mask == BCSIF_SIZE, "[%u] wrong mask, got %u\n", button, info.mask); 1556 + ok(info.size.cx == glyph_size, "[%u] expected %d, got %d\n", button, glyph_size, info.size.cx); 1557 + ok(info.size.cy == -10, "[%u] expected -10, got %d\n", button, info.size.cy); 1558 + 1559 + /* Set to a valid size other than glyph_size */ 1560 + info.mask = BCSIF_SIZE; 1561 + info.size.cx = glyph_size + 7; 1562 + info.size.cy = 11; 1563 + ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info); 1564 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1565 + info.size.cx = info.size.cy = 0xdeadbeef; 1566 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info); 1567 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1568 + ok(info.mask == BCSIF_SIZE, "[%u] wrong mask, got %u\n", button, info.mask); 1569 + ok(info.size.cx == glyph_size + 7, "[%u] expected %d, got %d\n", button, glyph_size + 7, info.size.cx); 1570 + ok(info.size.cy == 11, "[%u] expected 11, got %d\n", button, info.size.cy); 1571 + 1572 + /* Change the glyph, size.cx should be automatically adjusted and size.cy set to 0 */ 1573 + dummy.mask = BCSIF_GLYPH; 1574 + dummy.himlGlyph = (HIMAGELIST)0x35; 1575 + ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&dummy); 1576 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1577 + info.mask = BCSIF_GLYPH | BCSIF_SIZE; 1578 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info); 1579 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1580 + ok(info.mask == (BCSIF_GLYPH | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask); 1581 + ok(info.himlGlyph == (HIMAGELIST)0x35, "[%u] expected 0x35, got %p\n", button, info.himlGlyph); 1582 + ok(info.size.cx == glyph_size, "[%u] expected %d, got %d\n", button, glyph_size, info.size.cx); 1583 + ok(info.size.cy == 0, "[%u] expected 0, got %d\n", button, info.size.cy); 1584 + 1585 + /* Unless the size is specified manually */ 1586 + dummy.mask = BCSIF_GLYPH | BCSIF_SIZE; 1587 + dummy.himlGlyph = (HIMAGELIST)0x34; 1588 + dummy.size.cx = glyph_size + 11; 1589 + dummy.size.cy = 7; 1590 + ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&dummy); 1591 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1592 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info); 1593 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1594 + ok(info.mask == (BCSIF_GLYPH | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask); 1595 + ok(info.himlGlyph == (HIMAGELIST)0x34, "[%u] expected 0x34, got %p\n", button, info.himlGlyph); 1596 + ok(info.size.cx == glyph_size + 11, "[%u] expected %d, got %d\n", button, glyph_size, info.size.cx); 1597 + ok(info.size.cy == 7, "[%u] expected 7, got %d\n", button, info.size.cy); 1598 + 1599 + /* Add the BCSS_IMAGE style manually with the wrong BCSIF_GLYPH mask, should treat it as invalid image */ 1600 + info.mask = BCSIF_GLYPH | BCSIF_STYLE; 1601 + info.himlGlyph = (HIMAGELIST)0x37; 1602 + info.uSplitStyle = BCSS_IMAGE; 1603 + ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info); 1604 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1605 + info.mask |= BCSIF_SIZE; 1606 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info); 1607 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1608 + ok(info.mask == (BCSIF_GLYPH | BCSIF_STYLE | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask); 1609 + ok(info.himlGlyph == (HIMAGELIST)0x37, "[%u] expected 0x37, got %p\n", button, info.himlGlyph); 1610 + ok(info.uSplitStyle == BCSS_IMAGE, "[%u] expected 0x%08x style, got 0x%08x\n", button, BCSS_IMAGE, info.uSplitStyle); 1611 + ok(info.size.cx == border_w, "[%u] expected %d, got %d\n", button, border_w, info.size.cx); 1612 + ok(info.size.cy == 0, "[%u] expected 0, got %d\n", button, info.size.cy); 1613 + 1614 + /* Change the size to prevent ambiguity */ 1615 + dummy.mask = BCSIF_SIZE; 1616 + dummy.size.cx = glyph_size + 5; 1617 + dummy.size.cy = 4; 1618 + ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&dummy); 1619 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1620 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info); 1621 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1622 + ok(info.mask == (BCSIF_GLYPH | BCSIF_STYLE | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask); 1623 + ok(info.himlGlyph == (HIMAGELIST)0x37, "[%u] expected 0x37, got %p\n", button, info.himlGlyph); 1624 + ok(info.uSplitStyle == BCSS_IMAGE, "[%u] expected 0x%08x style, got 0x%08x\n", button, BCSS_IMAGE, info.uSplitStyle); 1625 + ok(info.size.cx == glyph_size + 5, "[%u] expected %d, got %d\n", button, glyph_size + 5, info.size.cx); 1626 + ok(info.size.cy == 4, "[%u] expected 4, got %d\n", button, info.size.cy); 1627 + 1628 + /* Now remove the BCSS_IMAGE style manually with the wrong BCSIF_IMAGE mask */ 1629 + info.mask = BCSIF_IMAGE | BCSIF_STYLE; 1630 + info.himlGlyph = (HIMAGELIST)0x35; 1631 + info.uSplitStyle = BCSS_STRETCH; 1632 + ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info); 1633 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1634 + info.mask |= BCSIF_SIZE; 1635 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info); 1636 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1637 + ok(info.mask == (BCSIF_IMAGE | BCSIF_STYLE | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask); 1638 + ok(info.himlGlyph == (HIMAGELIST)0x35, "[%u] expected 0x35, got %p\n", button, info.himlGlyph); 1639 + ok(info.uSplitStyle == BCSS_STRETCH, "[%u] expected 0x%08x style, got 0x%08x\n", button, BCSS_STRETCH, info.uSplitStyle); 1640 + ok(info.size.cx == glyph_size, "[%u] expected %d, got %d\n", button, glyph_size, info.size.cx); 1641 + ok(info.size.cy == 0, "[%u] expected 0, got %d\n", button, info.size.cy); 1642 + 1643 + /* Add a proper valid image, the BCSS_IMAGE style should be set automatically */ 1644 + img = pImageList_Create(42, 33, ILC_COLOR, 1, 1); 1645 + ok(img != NULL, "[%u] failed to create ImageList\n", button); 1646 + info.mask = BCSIF_IMAGE; 1647 + info.himlGlyph = img; 1648 + ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info); 1649 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1650 + info.mask |= BCSIF_STYLE | BCSIF_SIZE; 1651 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info); 1652 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1653 + ok(info.mask == (BCSIF_IMAGE | BCSIF_STYLE | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask); 1654 + ok(info.himlGlyph == img, "[%u] expected %p, got %p\n", button, img, info.himlGlyph); 1655 + ok(info.uSplitStyle == (BCSS_IMAGE | BCSS_STRETCH), "[%u] expected 0x%08x style, got 0x%08x\n", button, BCSS_IMAGE | BCSS_STRETCH, info.uSplitStyle); 1656 + ok(info.size.cx == 42 + border_w, "[%u] expected %d, got %d\n", button, 42 + border_w, info.size.cx); 1657 + ok(info.size.cy == 0, "[%u] expected 0, got %d\n", button, info.size.cy); 1658 + pImageList_Destroy(img); 1659 + dummy.mask = BCSIF_SIZE; 1660 + dummy.size.cx = glyph_size + 5; 1661 + dummy.size.cy = 4; 1662 + ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&dummy); 1663 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1664 + 1665 + /* Change it to a glyph; when both specified, BCSIF_GLYPH takes priority */ 1666 + info.mask = BCSIF_GLYPH | BCSIF_IMAGE; 1667 + info.himlGlyph = (HIMAGELIST)0x37; 1668 + ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info); 1669 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1670 + info.mask |= BCSIF_STYLE | BCSIF_SIZE; 1671 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info); 1672 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1673 + ok(info.mask == (BCSIF_GLYPH | BCSIF_IMAGE | BCSIF_STYLE | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask); 1674 + ok(info.himlGlyph == (HIMAGELIST)0x37, "[%u] expected 0x37, got %p\n", button, info.himlGlyph); 1675 + ok(info.uSplitStyle == BCSS_STRETCH, "[%u] expected 0x%08x style, got 0x%08x\n", button, BCSS_STRETCH, info.uSplitStyle); 1676 + ok(info.size.cx == glyph_size, "[%u] expected %d, got %d\n", button, glyph_size, info.size.cx); 1677 + ok(info.size.cy == 0, "[%u] expected 0, got %d\n", button, info.size.cy); 1678 + 1679 + /* Try a NULL image */ 1680 + info.mask = BCSIF_IMAGE; 1681 + info.himlGlyph = NULL; 1682 + ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info); 1683 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1684 + info.mask |= BCSIF_STYLE | BCSIF_SIZE; 1685 + ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info); 1686 + ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret); 1687 + ok(info.mask == (BCSIF_IMAGE | BCSIF_STYLE | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask); 1688 + ok(info.himlGlyph == NULL, "[%u] expected NULL, got %p\n", button, info.himlGlyph); 1689 + ok(info.uSplitStyle == (BCSS_IMAGE | BCSS_STRETCH), "[%u] expected 0x%08x style, got 0x%08x\n", button, BCSS_IMAGE | BCSS_STRETCH, info.uSplitStyle); 1690 + ok(info.size.cx == border_w, "[%u] expected %d, got %d\n", button, border_w, info.size.cx); 1691 + ok(info.size.cy == 0, "[%u] expected 0, got %d\n", button, info.size.cy); 1692 + } 1693 + 1231 1694 static void test_button_data(void) 1232 1695 { 1233 1696 static const DWORD styles[] = ··· 1279 1742 ok(desc->parent == parent, "Unexpected 'parent' field.\n"); 1280 1743 ok(desc->style == (WS_CHILD | BS_NOTIFY | styles[i]), "Unexpected 'style' field.\n"); 1281 1744 } 1745 + 1746 + /* Data set and retrieved by these messages is valid for all buttons */ 1747 + test_bcm_splitinfo(hwnd); 1282 1748 1283 1749 DestroyWindow(hwnd); 1284 1750 } ··· 1431 1897 { 1432 1898 static const char *button_text2 = "WWWW\nWWWW"; 1433 1899 static const char *button_text = "WWWW"; 1900 + static const WCHAR button_note_short[] = { 'W',0 }; 1901 + static const WCHAR button_note_long[] = { 'W','W','W','W','W','W','W','W','W','W','W','W','W','W','W','W',0 }; 1902 + static const WCHAR button_note_wordy[] = { 'T','h','i','s',' ','i','s',' ','a',' ','l','o','n','g',' ','n','o','t','e',' ','f','o','r',' ','t','h','e',' ','b','u','t','t','o','n',',',' ', 1903 + 'w','i','t','h',' ','m','a','n','y',' ','w','o','r','d','s',',',' ','w','h','i','c','h',' ','s','h','o','u','l','d',' ','b','e',' ', 1904 + 'o','v','e','r','a','l','l',' ','l','o','n','g','e','r',' ','t','h','a','n',' ','t','h','e',' ','t','e','x','t',' ','(','g','i','v','e','n',' ', 1905 + 't','h','e',' ','s','m','a','l','l','e','r',' ','f','o','n','t',')',' ','a','n','d',' ','t','h','u','s',' ','w','r','a','p','.',0 }; 1434 1906 static const DWORD imagelist_aligns[] = {BUTTON_IMAGELIST_ALIGN_LEFT, BUTTON_IMAGELIST_ALIGN_RIGHT, 1435 1907 BUTTON_IMAGELIST_ALIGN_TOP, BUTTON_IMAGELIST_ALIGN_BOTTOM, 1436 1908 BUTTON_IMAGELIST_ALIGN_CENTER}; 1437 1909 static const DWORD aligns[] = {0, BS_TOP, BS_LEFT, BS_RIGHT, BS_BOTTOM, 1438 1910 BS_CENTER, BS_VCENTER, BS_RIGHTBUTTON, WS_EX_RIGHT}; 1439 1911 DWORD default_style = WS_TABSTOP | WS_POPUP | WS_VISIBLE; 1440 - const LONG client_width = 400, client_height = 200; 1441 - LONG image_width, height, line_count, text_width; 1912 + const LONG client_width = 400, client_height = 200, extra_width = 123, large_height = 500; 1913 + struct 1914 + { 1915 + DWORD style; 1916 + LONG extra_width; 1917 + } pushtype[] = 1918 + { 1919 + { BS_PUSHBUTTON, 0 }, 1920 + { BS_DEFPUSHBUTTON, 0 }, 1921 + { BS_SPLITBUTTON, extra_width * 2 + GetSystemMetrics(SM_CXEDGE) }, 1922 + { BS_DEFSPLITBUTTON, extra_width * 2 + GetSystemMetrics(SM_CXEDGE) } 1923 + }; 1924 + LONG image_width = 48, height = 48, line_count, text_width; 1442 1925 HFONT hfont, prev_font; 1443 1926 DWORD style, type; 1444 1927 BOOL ret; ··· 1453 1936 HIMAGELIST himl; 1454 1937 BUTTON_IMAGELIST biml = {0}; 1455 1938 RECT rect; 1456 - INT i, j; 1939 + INT i, j, k; 1457 1940 1458 1941 /* Check for NULL pointer handling */ 1459 1942 hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_PUSHBUTTON | default_style, 0, 0, client_width, client_height, ··· 1496 1979 1497 1980 /* Tests for image placements */ 1498 1981 /* Prepare bitmap */ 1499 - image_width = 48; 1500 - height = 48; 1501 1982 hdc = GetDC(0); 1502 1983 hmask = CreateCompatibleBitmap(hdc, image_width, height); 1503 1984 hbmp = CreateCompatibleBitmap(hdc, image_width, height); 1985 + himl = pImageList_Create(image_width, height, ILC_COLOR, 1, 1); 1986 + pImageList_Add(himl, hbmp, 0); 1504 1987 1505 - /* Only bitmap for push button, ideal size should be enough for image and text */ 1506 - hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_DEFPUSHBUTTON | BS_BITMAP | default_style, 0, 0, client_width, 1507 - client_height, NULL, NULL, 0, NULL); 1508 - ok(hwnd != NULL, "Expect hwnd not NULL\n"); 1509 - SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp); 1510 - SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE); 1511 - ZeroMemory(&size, sizeof(size)); 1512 - ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size); 1513 - ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n"); 1514 - /* Ideal size contains text rect even show bitmap only */ 1515 - ok((size.cx >= image_width + text_width && size.cy >= max(height, tm.tmHeight)), 1516 - "Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx, image_width + text_width, 1517 - size.cy, max(height, tm.tmHeight)); 1518 - DestroyWindow(hwnd); 1988 + #define set_split_info(hwnd) do { \ 1989 + BUTTON_SPLITINFO _info; \ 1990 + int _ret; \ 1991 + _info.mask = BCSIF_SIZE; \ 1992 + _info.size.cx = extra_width; \ 1993 + _info.size.cy = large_height; \ 1994 + _ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&_info); \ 1995 + ok(_ret == TRUE, "Expected BCM_SETSPLITINFO message to return true\n"); \ 1996 + } while (0) 1997 + 1998 + for (k = 0; k < ARRAY_SIZE(pushtype); k++) 1999 + { 2000 + /* Only bitmap for push button, ideal size should be enough for image and text */ 2001 + hwnd = CreateWindowA(WC_BUTTONA, button_text, pushtype[k].style | BS_BITMAP | default_style, 0, 0, client_width, 2002 + client_height, NULL, NULL, 0, NULL); 2003 + ok(hwnd != NULL, "Expect hwnd not NULL\n"); 2004 + set_split_info(hwnd); 2005 + SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp); 2006 + SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE); 2007 + ZeroMemory(&size, sizeof(size)); 2008 + ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size); 2009 + ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n"); 2010 + /* Ideal size contains text rect even show bitmap only */ 2011 + ok(size.cx >= image_width + text_width + pushtype[k].extra_width && size.cy >= max(height, tm.tmHeight), 2012 + "Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx, 2013 + image_width + text_width + pushtype[k].extra_width, size.cy, max(height, tm.tmHeight)); 2014 + ok(size.cy < large_height, "Expect ideal cy %d < %d\n", size.cy, large_height); 2015 + DestroyWindow(hwnd); 1519 2016 1520 - /* Image alignments when button has bitmap and text*/ 1521 - for (i = 0; i < ARRAY_SIZE(aligns); i++) 1522 - for (j = 0; j < ARRAY_SIZE(aligns); j++) 2017 + /* Image alignments when button has bitmap and text*/ 2018 + for (i = 0; i < ARRAY_SIZE(aligns); i++) 2019 + for (j = 0; j < ARRAY_SIZE(aligns); j++) 2020 + { 2021 + style = pushtype[k].style | default_style | aligns[i] | aligns[j]; 2022 + hwnd = CreateWindowA(WC_BUTTONA, button_text, style, 0, 0, client_width, client_height, NULL, NULL, 0, NULL); 2023 + ok(hwnd != NULL, "Expect hwnd not NULL\n"); 2024 + set_split_info(hwnd); 2025 + SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp); 2026 + SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE); 2027 + ZeroMemory(&size, sizeof(size)); 2028 + ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size); 2029 + ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n"); 2030 + if (!(style & (BS_CENTER | BS_VCENTER)) || ((style & BS_CENTER) && (style & BS_CENTER) != BS_CENTER) 2031 + || !(style & BS_VCENTER) || (style & BS_VCENTER) == BS_VCENTER) 2032 + ok(size.cx >= image_width + text_width + pushtype[k].extra_width && size.cy >= max(height, tm.tmHeight), 2033 + "Style: 0x%08x expect ideal cx %d >= %d and ideal cy %d >= %d\n", style, size.cx, 2034 + image_width + text_width + pushtype[k].extra_width, size.cy, max(height, tm.tmHeight)); 2035 + else 2036 + ok(size.cx >= max(text_width, height) + pushtype[k].extra_width && size.cy >= height + tm.tmHeight, 2037 + "Style: 0x%08x expect ideal cx %d >= %d and ideal cy %d >= %d\n", style, size.cx, 2038 + max(text_width, height) + pushtype[k].extra_width, size.cy, height + tm.tmHeight); 2039 + ok(size.cy < large_height, "Expect ideal cy %d < %d\n", size.cy, large_height); 2040 + DestroyWindow(hwnd); 2041 + } 2042 + 2043 + /* Image list alignments */ 2044 + biml.himl = himl; 2045 + for (i = 0; i < ARRAY_SIZE(imagelist_aligns); i++) 1523 2046 { 1524 - style = BS_DEFPUSHBUTTON | default_style | aligns[i] | aligns[j]; 1525 - hwnd = CreateWindowA(WC_BUTTONA, button_text, style, 0, 0, client_width, client_height, NULL, NULL, 0, NULL); 2047 + biml.uAlign = imagelist_aligns[i]; 2048 + hwnd = CreateWindowA(WC_BUTTONA, button_text, pushtype[k].style | default_style, 0, 0, client_width, 2049 + client_height, NULL, NULL, 0, NULL); 1526 2050 ok(hwnd != NULL, "Expect hwnd not NULL\n"); 1527 - SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp); 2051 + set_split_info(hwnd); 1528 2052 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE); 2053 + SendMessageA(hwnd, BCM_SETIMAGELIST, 0, (LPARAM)&biml); 1529 2054 ZeroMemory(&size, sizeof(size)); 1530 2055 ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size); 1531 2056 ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n"); 1532 - if (!(style & (BS_CENTER | BS_VCENTER)) || ((style & BS_CENTER) && (style & BS_CENTER) != BS_CENTER) 1533 - || !(style & BS_VCENTER) || (style & BS_VCENTER) == BS_VCENTER) 1534 - ok((size.cx >= image_width + text_width && size.cy >= max(height, tm.tmHeight)), 1535 - "Style: 0x%08x expect ideal cx %d >= %d and ideal cy %d >= %d\n", style, size.cx, 1536 - image_width + text_width, size.cy, max(height, tm.tmHeight)); 2057 + if (biml.uAlign == BUTTON_IMAGELIST_ALIGN_TOP || biml.uAlign == BUTTON_IMAGELIST_ALIGN_BOTTOM) 2058 + ok(size.cx >= max(text_width, height) + pushtype[k].extra_width && size.cy >= height + tm.tmHeight, 2059 + "Align:%d expect ideal cx %d >= %d and ideal cy %d >= %d\n", biml.uAlign, size.cx, 2060 + max(text_width, height) + pushtype[k].extra_width, size.cy, height + tm.tmHeight); 2061 + else if (biml.uAlign == BUTTON_IMAGELIST_ALIGN_LEFT || biml.uAlign == BUTTON_IMAGELIST_ALIGN_RIGHT) 2062 + ok(size.cx >= image_width + text_width + pushtype[k].extra_width && size.cy >= max(height, tm.tmHeight), 2063 + "Align:%d expect ideal cx %d >= %d and ideal cy %d >= %d\n", biml.uAlign, size.cx, 2064 + image_width + text_width + pushtype[k].extra_width, size.cy, max(height, tm.tmHeight)); 1537 2065 else 1538 - ok((size.cx >= max(text_width, height) && size.cy >= height + tm.tmHeight), 1539 - "Style: 0x%08x expect ideal cx %d >= %d and ideal cy %d >= %d\n", style, size.cx, 1540 - max(text_width, height), size.cy, height + tm.tmHeight); 2066 + ok(size.cx >= image_width + pushtype[k].extra_width && size.cy >= height, 2067 + "Align:%d expect ideal cx %d >= %d and ideal cy %d >= %d\n", 2068 + biml.uAlign, size.cx, image_width + pushtype[k].extra_width, size.cy, height); 2069 + ok(size.cy < large_height, "Expect ideal cy %d < %d\n", size.cy, large_height); 1541 2070 DestroyWindow(hwnd); 1542 2071 } 1543 2072 1544 - /* Image list alignments */ 1545 - himl = pImageList_Create(image_width, height, ILC_COLOR, 1, 1); 1546 - pImageList_Add(himl, hbmp, 0); 1547 - biml.himl = himl; 1548 - for (i = 0; i < ARRAY_SIZE(imagelist_aligns); i++) 1549 - { 1550 - biml.uAlign = imagelist_aligns[i]; 1551 - hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_DEFPUSHBUTTON | default_style, 0, 0, client_width, 2073 + /* Icon as image */ 2074 + /* Create icon from bitmap */ 2075 + ZeroMemory(&icon_info, sizeof(icon_info)); 2076 + icon_info.fIcon = TRUE; 2077 + icon_info.hbmMask = hmask; 2078 + icon_info.hbmColor = hbmp; 2079 + hicon = CreateIconIndirect(&icon_info); 2080 + 2081 + /* Only icon, ideal size should be enough for image and text */ 2082 + hwnd = CreateWindowA(WC_BUTTONA, button_text, pushtype[k].style | BS_ICON | default_style, 0, 0, client_width, 2083 + client_height, NULL, NULL, 0, NULL); 2084 + ok(hwnd != NULL, "Expect hwnd not NULL\n"); 2085 + set_split_info(hwnd); 2086 + SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon); 2087 + SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE); 2088 + ZeroMemory(&size, sizeof(size)); 2089 + ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size); 2090 + ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n"); 2091 + /* Ideal size contains text rect even show icons only */ 2092 + ok(size.cx >= image_width + text_width + pushtype[k].extra_width && size.cy >= max(height, tm.tmHeight), 2093 + "Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx, 2094 + image_width + text_width + pushtype[k].extra_width, size.cy, max(height, tm.tmHeight)); 2095 + ok(size.cy < large_height, "Expect ideal cy %d < %d\n", size.cy, large_height); 2096 + DestroyWindow(hwnd); 2097 + 2098 + /* Show icon and text */ 2099 + hwnd = CreateWindowA(WC_BUTTONA, button_text, pushtype[k].style | default_style, 0, 0, client_width, 1552 2100 client_height, NULL, NULL, 0, NULL); 1553 2101 ok(hwnd != NULL, "Expect hwnd not NULL\n"); 2102 + set_split_info(hwnd); 2103 + SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon); 1554 2104 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE); 1555 - SendMessageA(hwnd, BCM_SETIMAGELIST, 0, (LPARAM)&biml); 1556 2105 ZeroMemory(&size, sizeof(size)); 1557 2106 ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size); 1558 2107 ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n"); 1559 - if (biml.uAlign == BUTTON_IMAGELIST_ALIGN_TOP || biml.uAlign == BUTTON_IMAGELIST_ALIGN_BOTTOM) 1560 - ok((size.cx >= max(text_width, height) && size.cy >= height + tm.tmHeight), 1561 - "Align:%d expect ideal cx %d >= %d and ideal cy %d >= %d\n", biml.uAlign, size.cx, 1562 - max(text_width, height), size.cy, height + tm.tmHeight); 1563 - else if (biml.uAlign == BUTTON_IMAGELIST_ALIGN_LEFT || biml.uAlign == BUTTON_IMAGELIST_ALIGN_RIGHT) 1564 - ok((size.cx >= image_width + text_width && size.cy >= max(height, tm.tmHeight)), 1565 - "Align:%d expect ideal cx %d >= %d and ideal cy %d >= %d\n", biml.uAlign, size.cx, 1566 - image_width + text_width, size.cy, max(height, tm.tmHeight)); 1567 - else 1568 - ok(size.cx >= image_width && size.cy >= height, "Align:%d expect ideal cx %d >= %d and ideal cy %d >= %d\n", 1569 - biml.uAlign, size.cx, image_width, size.cy, height); 2108 + ok(size.cx >= image_width + text_width + pushtype[k].extra_width && size.cy >= max(height, tm.tmHeight), 2109 + "Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx, 2110 + image_width + text_width + pushtype[k].extra_width, size.cy, max(height, tm.tmHeight)); 2111 + ok(size.cy < large_height, "Expect ideal cy %d < %d\n", size.cy, large_height); 1570 2112 DestroyWindow(hwnd); 2113 + DestroyIcon(hicon); 1571 2114 } 1572 2115 1573 - /* Icon as image */ 1574 - /* Create icon from bitmap */ 1575 - ZeroMemory(&icon_info, sizeof(icon_info)); 1576 - icon_info.fIcon = TRUE; 1577 - icon_info.hbmMask = hmask; 1578 - icon_info.hbmColor = hbmp; 1579 - hicon = CreateIconIndirect(&icon_info); 1580 - 1581 - /* Only icon, ideal size should be enough for image and text */ 1582 - hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_DEFPUSHBUTTON | BS_ICON | default_style, 0, 0, client_width, 1583 - client_height, NULL, NULL, 0, NULL); 1584 - ok(hwnd != NULL, "Expect hwnd not NULL\n"); 1585 - SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon); 1586 - SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE); 1587 - ZeroMemory(&size, sizeof(size)); 1588 - ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size); 1589 - ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n"); 1590 - /* Ideal size contains text rect even show icons only */ 1591 - ok((size.cx >= image_width + text_width && size.cy >= max(height, tm.tmHeight)), 1592 - "Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx, image_width + text_width, size.cy, 1593 - max(height, tm.tmHeight)); 1594 - DestroyWindow(hwnd); 1595 - 1596 - /* Show icon and text */ 1597 - hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_DEFPUSHBUTTON | default_style, 0, 0, client_width, 1598 - client_height, NULL, NULL, 0, NULL); 1599 - ok(hwnd != NULL, "Expect hwnd not NULL\n"); 1600 - SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon); 1601 - SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE); 1602 - ZeroMemory(&size, sizeof(size)); 1603 - ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size); 1604 - ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n"); 1605 - ok((size.cx >= image_width + text_width && size.cy >= max(height, tm.tmHeight)), 1606 - "Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx, image_width + text_width, size.cy, 1607 - max(height, tm.tmHeight)); 1608 - DestroyWindow(hwnd); 2116 + #undef set_split_info 1609 2117 1610 2118 /* Checkbox */ 1611 2119 /* Both bitmap and text for checkbox, ideal size is only enough for text because it doesn't support image(but not image list)*/ ··· 1667 2175 1668 2176 if (type == BS_COMMANDLINK || type == BS_DEFCOMMANDLINK) 1669 2177 { 1670 - todo_wine ok((size.cx == 0 && size.cy > 0), "Style 0x%08x expect ideal cx %d >= %d and ideal cy %d >= %d\n", 1671 - style, size.cx, 0, size.cy, 0); 2178 + ok((size.cx == 0 && size.cy > 0), "Style 0x%08x expect ideal cx %d == %d and ideal cy %d > %d\n", 2179 + style, size.cx, 0, size.cy, 0); 1672 2180 } 1673 2181 else 1674 2182 { ··· 1704 2212 } 1705 2213 else if (type == BS_COMMANDLINK || type == BS_DEFCOMMANDLINK) 1706 2214 { 1707 - todo_wine ok((size.cx == 0 && size.cy > 0), 1708 - "Style 0x%08x expect ideal cx %d >= %d and ideal cy %d >= %d\n", style, size.cx, 0, 1709 - size.cy, 0); 2215 + ok((size.cx == 0 && size.cy > 0), 2216 + "Style 0x%08x expect ideal cx %d == %d and ideal cy %d > %d\n", style, size.cx, 0, 2217 + size.cy, 0); 1710 2218 } 1711 2219 else 1712 2220 { ··· 1718 2226 } 1719 2227 } 1720 2228 2229 + /* Command Link with note */ 2230 + hwnd = CreateWindowA(WC_BUTTONA, "a", style, 0, 0, client_width, client_height, NULL, NULL, 0, NULL); 2231 + ok(hwnd != NULL, "Expected hwnd not NULL\n"); 2232 + SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp); 2233 + ret = SendMessageA(hwnd, BCM_SETNOTE, 0, (LPARAM)button_note_short); 2234 + ok(ret == TRUE, "Expected BCM_SETNOTE to return true\n"); 2235 + size.cx = 13; 2236 + size.cy = 0; 2237 + ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size); 2238 + ok(ret == TRUE, "Expected BCM_GETIDEALSIZE message to return true\n"); 2239 + ok(size.cx == 13 && size.cy > 0, "Expected ideal cx %d == %d and ideal cy %d > %d\n", size.cx, 13, size.cy, 0); 2240 + height = size.cy; 2241 + size.cx = 32767; 2242 + size.cy = 7; 2243 + ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size); 2244 + ok(ret == TRUE, "Expected BCM_GETIDEALSIZE message to return true\n"); 2245 + ok(size.cx < 32767, "Expected ideal cx to have been adjusted\n"); 2246 + ok(size.cx > image_width && size.cy == height, "Expected ideal cx %d > %d and ideal cy %d == %d\n", size.cx, image_width, size.cy, height); 2247 + 2248 + /* Try longer note without word breaks, shouldn't extend height because no word splitting */ 2249 + ret = SendMessageA(hwnd, BCM_SETNOTE, 0, (LPARAM)button_note_long); 2250 + ok(ret == TRUE, "Expected BCM_SETNOTE to return true\n"); 2251 + k = size.cx; 2252 + size.cy = 0; 2253 + ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size); 2254 + ok(ret == TRUE, "Expected BCM_GETIDEALSIZE message to return true\n"); 2255 + ok(size.cx == k && size.cy == height, "Expected ideal cx %d == %d and ideal cy %d == %d\n", size.cx, k, size.cy, height); 2256 + 2257 + /* Now let it extend the width */ 2258 + size.cx = 32767; 2259 + size.cy = 0; 2260 + ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size); 2261 + ok(ret == TRUE, "Expected BCM_GETIDEALSIZE message to return true\n"); 2262 + ok(size.cx > k && size.cy == height, "Expected ideal cx %d > %d and ideal cy %d == %d\n", size.cx, k, size.cy, height); 2263 + 2264 + /* Use a very long note with words and the same width, should extend the height due to word wrap */ 2265 + ret = SendMessageA(hwnd, BCM_SETNOTE, 0, (LPARAM)button_note_wordy); 2266 + ok(ret == TRUE, "Expected BCM_SETNOTE to return true\n"); 2267 + k = size.cx; 2268 + ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size); 2269 + ok(ret == TRUE, "Expected BCM_GETIDEALSIZE message to return true\n"); 2270 + ok(size.cx <= k && size.cy > height, "Expected ideal cx %d <= %d and ideal cy %d > %d\n", size.cx, k, size.cy, height); 2271 + 2272 + /* Now try the wordy note with a width smaller than the image itself, which prevents wrapping */ 2273 + size.cx = 13; 2274 + ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size); 2275 + ok(ret == TRUE, "Expected BCM_GETIDEALSIZE message to return true\n"); 2276 + ok(size.cx == 13 && size.cy == height, "Expected ideal cx %d == %d and ideal cy %d == %d\n", size.cx, 13, size.cy, height); 2277 + DestroyWindow(hwnd); 2278 + 2279 + 1721 2280 pImageList_Destroy(himl); 1722 - DestroyIcon(hicon); 1723 2281 DeleteObject(hbmp); 1724 2282 DeleteObject(hmask); 1725 2283 ReleaseDC(0, hdc);
+222 -43
modules/rostests/winetests/comctl32/edit.c
··· 1485 1485 DestroyWindow (hwEdit); 1486 1486 } 1487 1487 1488 + static BOOL is_cjk(HDC dc) 1489 + { 1490 + const DWORD FS_DBCS_MASK = FS_JISJAPAN|FS_CHINESESIMP|FS_WANSUNG|FS_CHINESETRAD|FS_JOHAB; 1491 + FONTSIGNATURE fs; 1492 + 1493 + switch (GdiGetCodePage(dc)) { 1494 + case 932: case 936: case 949: case 950: case 1361: 1495 + return TRUE; 1496 + default: 1497 + return (GetTextCharsetInfo(dc, &fs, 0) != DEFAULT_CHARSET && 1498 + (fs.fsCsb[0] & FS_DBCS_MASK)); 1499 + } 1500 + } 1501 + 1488 1502 static void test_margins_usefontinfo(UINT charset) 1489 1503 { 1490 - INT margins, threshold, expect, empty_expect, small_expect; 1491 1504 HWND hwnd; 1492 1505 HDC hdc; 1506 + TEXTMETRICW tm; 1493 1507 SIZE size; 1494 - BOOL cjk; 1495 1508 LOGFONTA lf; 1496 1509 HFONT hfont; 1497 1510 RECT rect; 1511 + INT margins, threshold, expect, empty_expect; 1512 + const UINT small_margins = MAKELONG(1, 5); 1498 1513 1499 1514 memset(&lf, 0, sizeof(lf)); 1500 1515 lf.lfHeight = -11; ··· 1513 1528 1514 1529 hdc = GetDC(hwnd); 1515 1530 hfont = SelectObject(hdc, hfont); 1516 - size.cx = GdiGetCharDimensions( hdc, NULL, &size.cy ); 1531 + size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy ); 1532 + if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) || 1533 + !(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) { 1534 + skip("%s for charset %d isn't available\n", lf.lfFaceName, charset); 1535 + hfont = SelectObject(hdc, hfont); 1536 + ReleaseDC(hwnd, hdc); 1537 + DestroyWindow(hwnd); 1538 + DeleteObject(hfont); 1539 + return; 1540 + } 1517 1541 expect = MAKELONG(size.cx / 2, size.cx / 2); 1518 - small_expect = 0; 1519 - empty_expect = size.cx >= 28 ? small_expect : expect; 1520 - 1521 - charset = GetTextCharset(hdc); 1522 - switch (charset) 1523 - { 1524 - case SHIFTJIS_CHARSET: 1525 - case HANGUL_CHARSET: 1526 - case GB2312_CHARSET: 1527 - case CHINESEBIG5_CHARSET: 1528 - cjk = TRUE; 1529 - break; 1530 - default: 1531 - cjk = FALSE; 1532 - } 1533 - 1534 1542 hfont = SelectObject(hdc, hfont); 1535 1543 ReleaseDC(hwnd, hdc); 1536 1544 1537 1545 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0); 1538 1546 ok(margins == 0, "got %x\n", margins); 1539 1547 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0)); 1540 - margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0); 1541 - if (!cjk) 1542 - ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins)); 1543 - else 1544 - { 1545 - ok(HIWORD(margins) > 0 && LOWORD(margins) > 0, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins)); 1546 - expect = empty_expect = small_expect = margins; 1547 - } 1548 + SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO)); 1549 + expect = SendMessageA(hwnd, EM_GETMARGINS, 0, 0); 1548 1550 DestroyWindow(hwnd); 1549 1551 1550 - threshold = (size.cx / 2 + size.cx) * 2; 1552 + threshold = HIWORD(expect) + LOWORD(expect) + size.cx * 2; 1553 + empty_expect = threshold > 80 ? small_margins : expect; 1551 1554 1552 - /* Size below which non-cjk margins are zero */ 1555 + /* Size below the threshold, margins remain unchanged */ 1553 1556 hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold - 1, 100, NULL, NULL, NULL, NULL); 1554 1557 ok(hwnd != NULL, "got %p\n", hwnd); 1555 1558 GetClientRect(hwnd, &rect); ··· 1559 1562 ok(margins == 0, "got %x\n", margins); 1560 1563 1561 1564 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0)); 1565 + SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins); 1566 + SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO)); 1562 1567 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0); 1563 - ok(margins == small_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins)); 1568 + ok(margins == small_margins, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins)); 1564 1569 DestroyWindow(hwnd); 1565 1570 1566 - /* Size at which non-cjk margins become non-zero */ 1571 + /* Size at the threshold, margins become non-zero */ 1567 1572 hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold, 100, NULL, NULL, NULL, NULL); 1568 1573 ok(hwnd != NULL, "got %p\n", hwnd); 1569 1574 GetClientRect(hwnd, &rect); ··· 1573 1578 ok(margins == 0, "got %x\n", margins); 1574 1579 1575 1580 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0)); 1581 + SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins); 1582 + SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO)); 1576 1583 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0); 1577 1584 ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins)); 1578 1585 DestroyWindow(hwnd); ··· 1587 1594 ok(margins == 0, "got %x\n", margins); 1588 1595 1589 1596 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0)); 1597 + SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins); 1598 + SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO)); 1590 1599 margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0); 1591 1600 ok(margins == empty_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins)); 1592 1601 DestroyWindow(hwnd); ··· 1594 1603 DeleteObject(hfont); 1595 1604 } 1596 1605 1606 + static INT get_cjk_fontinfo_margin(INT width, INT side_bearing) 1607 + { 1608 + INT margin; 1609 + if (side_bearing < 0) 1610 + margin = min(-side_bearing, width/2); 1611 + else 1612 + margin = 0; 1613 + return margin; 1614 + } 1615 + 1616 + static DWORD get_cjk_font_margins(HDC hdc) 1617 + { 1618 + ABC abc[256]; 1619 + SHORT left, right; 1620 + UINT i; 1621 + 1622 + if (!GetCharABCWidthsW(hdc, 0, 255, abc)) 1623 + return 0; 1624 + 1625 + left = right = 0; 1626 + for (i = 0; i < ARRAY_SIZE(abc); i++) { 1627 + if (-abc[i].abcA > right) right = -abc[i].abcA; 1628 + if (-abc[i].abcC > left) left = -abc[i].abcC; 1629 + } 1630 + return MAKELONG(left, right); 1631 + } 1632 + 1633 + static void test_margins_default(const char* facename, UINT charset) 1634 + { 1635 + HWND hwnd; 1636 + HDC hdc; 1637 + TEXTMETRICW tm; 1638 + SIZE size; 1639 + BOOL cjk; 1640 + LOGFONTA lf; 1641 + HFONT hfont; 1642 + RECT rect; 1643 + INT margins, expect, font_expect; 1644 + const UINT small_margins = MAKELONG(1, 5); 1645 + const WCHAR EditW[] = {'E','d','i','t',0}, strW[] = {'W',0}; 1646 + struct char_width_info { 1647 + INT lsb, rsb, unknown; 1648 + } info; 1649 + HMODULE hgdi32; 1650 + BOOL (WINAPI *pGetCharWidthInfo)(HDC, struct char_width_info *); 1651 + 1652 + hgdi32 = GetModuleHandleA("gdi32.dll"); 1653 + pGetCharWidthInfo = (void *)GetProcAddress(hgdi32, "GetCharWidthInfo"); 1654 + 1655 + memset(&lf, 0, sizeof(lf)); 1656 + lf.lfHeight = -11; 1657 + lf.lfWeight = FW_NORMAL; 1658 + lf.lfCharSet = charset; 1659 + strcpy(lf.lfFaceName, facename); 1660 + 1661 + hfont = CreateFontIndirectA(&lf); 1662 + ok(hfont != NULL, "got %p\n", hfont); 1663 + 1664 + /* Unicode version */ 1665 + hwnd = CreateWindowExW(0, EditW, strW, WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL); 1666 + ok(hwnd != NULL, "got %p\n", hwnd); 1667 + GetClientRect(hwnd, &rect); 1668 + ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect)); 1669 + 1670 + hdc = GetDC(hwnd); 1671 + hfont = SelectObject(hdc, hfont); 1672 + size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy ); 1673 + if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) || 1674 + !(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) { 1675 + skip("%s for charset %d isn't available\n", lf.lfFaceName, charset); 1676 + hfont = SelectObject(hdc, hfont); 1677 + ReleaseDC(hwnd, hdc); 1678 + DestroyWindow(hwnd); 1679 + DeleteObject(hfont); 1680 + return; 1681 + } 1682 + cjk = is_cjk(hdc); 1683 + if (cjk && pGetCharWidthInfo && pGetCharWidthInfo(hdc, &info)) { 1684 + short left, right; 1685 + 1686 + left = get_cjk_fontinfo_margin(size.cx, info.lsb); 1687 + right = get_cjk_fontinfo_margin(size.cx, info.rsb); 1688 + expect = MAKELONG(left, right); 1689 + 1690 + font_expect = get_cjk_font_margins(hdc); 1691 + if (!font_expect) 1692 + /* In this case, margins aren't updated */ 1693 + font_expect = small_margins; 1694 + } 1695 + else 1696 + font_expect = expect = MAKELONG(size.cx / 2, size.cx / 2); 1697 + 1698 + hfont = SelectObject(hdc, hfont); 1699 + ReleaseDC(hwnd, hdc); 1700 + 1701 + margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0); 1702 + ok(margins == 0, "got %x\n", margins); 1703 + SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins); 1704 + SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0)); 1705 + margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0); 1706 + ok(margins == font_expect, "%s:%d: got %d, %d\n", facename, charset, HIWORD(margins), LOWORD(margins)); 1707 + SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins); 1708 + SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO)); 1709 + margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0); 1710 + ok(margins == expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(expect), LOWORD(expect), HIWORD(margins), LOWORD(margins)); 1711 + DestroyWindow(hwnd); 1712 + 1713 + /* ANSI version */ 1714 + hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL); 1715 + ok(hwnd != NULL, "got %p\n", hwnd); 1716 + GetClientRect(hwnd, &rect); 1717 + ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect)); 1718 + 1719 + margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0); 1720 + ok(margins == 0, "got %x\n", margins); 1721 + SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins); 1722 + SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0)); 1723 + margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0); 1724 + ok(margins == font_expect, "%s:%d: got %d, %d\n", facename, charset, HIWORD(margins), LOWORD(margins)); 1725 + SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins); 1726 + SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO)); 1727 + margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0); 1728 + ok(margins == expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(expect), LOWORD(expect), HIWORD(margins), LOWORD(margins)); 1729 + DestroyWindow(hwnd); 1730 + 1731 + DeleteObject(hfont); 1732 + } 1733 + 1734 + static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam) 1735 + { 1736 + return 0; 1737 + } 1738 + 1739 + static BOOL is_font_installed(const char*name) 1740 + { 1741 + HDC hdc = GetDC(NULL); 1742 + BOOL ret = FALSE; 1743 + 1744 + if (!EnumFontFamiliesA(hdc, name, find_font_proc, 0)) 1745 + ret = TRUE; 1746 + 1747 + ReleaseDC(NULL, hdc); 1748 + return ret; 1749 + } 1750 + 1597 1751 static void test_margins(void) 1598 1752 { 1599 1753 DWORD old_margins, new_margins; ··· 1668 1822 but not by < Win 8 and Win 10. */ 1669 1823 1670 1824 test_margins_usefontinfo(DEFAULT_CHARSET); 1671 - } 1825 + 1826 + test_margins_default("Tahoma", ANSI_CHARSET); 1827 + test_margins_default("Tahoma", EASTEUROPE_CHARSET); 1828 + 1829 + test_margins_default("Tahoma", HANGUL_CHARSET); 1830 + test_margins_default("Tahoma", CHINESEBIG5_CHARSET); 1831 + 1832 + if (is_font_installed("MS PGothic")) { 1833 + test_margins_default("MS PGothic", SHIFTJIS_CHARSET); 1834 + test_margins_default("MS PGothic", GREEK_CHARSET); 1835 + } 1836 + else 1837 + skip("MS PGothic is not available, skipping some margin tests\n"); 1672 1838 1673 - static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam) 1674 - { 1675 - return 0; 1839 + if (is_font_installed("Ume P Gothic")) { 1840 + test_margins_default("Ume P Gothic", SHIFTJIS_CHARSET); 1841 + test_margins_default("Ume P Gothic", GREEK_CHARSET); 1842 + } 1843 + else 1844 + skip("Ume P Gothic is not available, skipping some margin tests\n"); 1845 + 1846 + if (is_font_installed("SimSun")) { 1847 + test_margins_default("SimSun", GB2312_CHARSET); 1848 + test_margins_default("SimSun", ANSI_CHARSET); 1849 + } 1850 + else 1851 + skip("SimSun is not available, skipping some margin tests\n"); 1676 1852 } 1677 1853 1678 1854 static void test_margins_font_change(void) 1679 1855 { 1680 - DWORD margins, font_margins, ret; 1856 + DWORD margins, font_margins; 1681 1857 HFONT hfont, hfont2; 1682 1858 HWND hwEdit; 1683 1859 LOGFONTA lf; 1684 - HDC hdc; 1685 1860 1686 - hdc = GetDC(0); 1687 - ret = EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0); 1688 - ReleaseDC(0, hdc); 1689 - if (ret) 1861 + if (!is_font_installed("Arial")) 1690 1862 { 1691 - trace("Arial not found - skipping font change margin tests\n"); 1863 + skip("Arial not found - skipping font change margin tests\n"); 1692 1864 return; 1693 1865 } 1694 1866 ··· 1699 1871 memset(&lf, 0, sizeof(lf)); 1700 1872 strcpy(lf.lfFaceName, "Arial"); 1701 1873 lf.lfHeight = 16; 1702 - lf.lfCharSet = DEFAULT_CHARSET; 1874 + lf.lfCharSet = GREEK_CHARSET; /* to avoid associated charset feature */ 1703 1875 hfont = CreateFontIndirectA(&lf); 1704 1876 lf.lfHeight = 30; 1705 1877 hfont2 = CreateFontIndirectA(&lf); ··· 3143 3315 HWND hwnd, parent_wnd; 3144 3316 WNDPROC oldproc; 3145 3317 MSG msg; 3318 + POINT orig_pos; 3319 + 3320 + GetCursorPos(&orig_pos); 3146 3321 3147 3322 parent_wnd = CreateWindowA("ParentWnd", "", WS_OVERLAPPEDWINDOW, 3148 3323 0, 0, 200, 200, NULL, NULL, GetModuleHandleA(NULL), NULL); ··· 3157 3332 oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)edit_subclass_proc); 3158 3333 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc); 3159 3334 3335 + SetCursorPos(400, 400); 3336 + 3160 3337 SetFocus(parent_wnd); 3161 3338 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3162 3339 SetFocus(hwnd); ··· 3167 3344 SetFocus(parent_wnd); 3168 3345 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 3169 3346 ok_sequence(sequences, COMBINED_SEQ_INDEX, killfocus_combined_seq, "Kill focus", TRUE); 3347 + 3348 + SetCursorPos(orig_pos.x, orig_pos.y); 3170 3349 3171 3350 DestroyWindow(hwnd); 3172 3351 }
+2 -3
modules/rostests/winetests/comctl32/imagelist.c
··· 1563 1563 if(hbmDst) 1564 1564 DeleteObject(hbmDst); 1565 1565 1566 - if(hdcDst) 1567 - DeleteDC(hdcDst); 1566 + DeleteDC(hdcDst); 1568 1567 1569 1568 if(hbmMask) 1570 1569 DeleteObject(hbmMask); ··· 2181 2180 rgb[2].rgbBlue = 0xff; 2182 2181 check_color_table("remove all, add 8", hdc, himl, ilc, rgb, default_table); 2183 2182 2184 - /* remove all, add 4. Color table remains the same since it's inplicitly 2183 + /* remove all, add 4. Color table remains the same since it's implicitly 2185 2184 been set by the previous _Add */ 2186 2185 ret = pImageList_Remove(himl, -1); 2187 2186 ok(ret, "got %d\n", ret);
+202 -3
modules/rostests/winetests/comctl32/listbox.c
··· 784 784 DestroyWindow( hList ); 785 785 } 786 786 787 + static void test_changing_selection_styles(void) 788 + { 789 + static const DWORD styles[] = 790 + { 791 + 0, 792 + LBS_NODATA | LBS_OWNERDRAWFIXED 793 + }; 794 + static const DWORD selstyles[] = 795 + { 796 + 0, 797 + LBS_MULTIPLESEL, 798 + LBS_EXTENDEDSEL, 799 + LBS_MULTIPLESEL | LBS_EXTENDEDSEL 800 + }; 801 + static const LONG selexpect_single[] = { 0, 0, 1 }; 802 + static const LONG selexpect_single2[] = { 1, 0, 0 }; 803 + static const LONG selexpect_multi[] = { 1, 0, 1 }; 804 + static const LONG selexpect_multi2[] = { 1, 1, 0 }; 805 + 806 + HWND parent, listbox; 807 + DWORD style; 808 + LONG ret; 809 + UINT i, j, k; 810 + 811 + parent = create_parent(); 812 + ok(parent != NULL, "Failed to create parent window.\n"); 813 + for (i = 0; i < ARRAY_SIZE(styles); i++) 814 + { 815 + /* Test if changing selection styles affects selection storage */ 816 + for (j = 0; j < ARRAY_SIZE(selstyles); j++) 817 + { 818 + LONG setcursel_expect, selitemrange_expect, getselcount_expect; 819 + const LONG *selexpect; 820 + 821 + listbox = CreateWindowA(WC_LISTBOXA, "TestList", styles[i] | selstyles[j] | WS_CHILD | WS_VISIBLE, 822 + 0, 0, 100, 100, parent, (HMENU)ID_LISTBOX, NULL, 0); 823 + ok(listbox != NULL, "%u: Failed to create ListBox window.\n", j); 824 + 825 + if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) 826 + { 827 + setcursel_expect = LB_ERR; 828 + selitemrange_expect = LB_OKAY; 829 + getselcount_expect = 2; 830 + selexpect = selexpect_multi; 831 + } 832 + else 833 + { 834 + setcursel_expect = 2; 835 + selitemrange_expect = LB_ERR; 836 + getselcount_expect = LB_ERR; 837 + selexpect = selexpect_single; 838 + } 839 + 840 + for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++) 841 + { 842 + ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"x"); 843 + ok(ret == k, "%u: Unexpected return value %d, expected %d.\n", j, ret, k); 844 + } 845 + ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0); 846 + ok(ret == ARRAY_SIZE(selexpect_multi), "%u: Unexpected count %d.\n", j, ret); 847 + 848 + /* Select items with different methods */ 849 + ret = SendMessageA(listbox, LB_SETCURSEL, 2, 0); 850 + ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret); 851 + ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 0)); 852 + ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret); 853 + ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 2)); 854 + ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret); 855 + 856 + /* Verify that the proper items are selected */ 857 + for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++) 858 + { 859 + ret = SendMessageA(listbox, LB_GETSEL, k, 0); 860 + ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n", 861 + j, ret, selexpect[k]); 862 + } 863 + 864 + /* Now change the selection style */ 865 + style = GetWindowLongA(listbox, GWL_STYLE); 866 + ok((style & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == selstyles[j], 867 + "%u: unexpected window styles %#x.\n", j, style); 868 + if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) 869 + style &= ~selstyles[j]; 870 + else 871 + style |= LBS_MULTIPLESEL | LBS_EXTENDEDSEL; 872 + SetWindowLongA(listbox, GWL_STYLE, style); 873 + style = GetWindowLongA(listbox, GWL_STYLE); 874 + ok(!(style & selstyles[j]), "%u: unexpected window styles %#x.\n", j, style); 875 + 876 + /* Verify that the same items are selected */ 877 + ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0); 878 + ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n", 879 + j, getselcount_expect, ret); 880 + 881 + for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++) 882 + { 883 + ret = SendMessageA(listbox, LB_GETSEL, k, 0); 884 + ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n", 885 + j, ret, selexpect[k]); 886 + } 887 + 888 + /* Lastly see if we can still change the selection as before with old style */ 889 + if (setcursel_expect != LB_ERR) setcursel_expect = 0; 890 + ret = SendMessageA(listbox, LB_SETCURSEL, 0, 0); 891 + ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret); 892 + ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 1)); 893 + ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret); 894 + ret = SendMessageA(listbox, LB_SELITEMRANGE, FALSE, MAKELPARAM(2, 2)); 895 + ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret); 896 + 897 + /* And verify the selections */ 898 + selexpect = (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) ? selexpect_multi2 : selexpect_single2; 899 + ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0); 900 + ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n", 901 + j, getselcount_expect, ret); 902 + 903 + for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++) 904 + { 905 + ret = SendMessageA(listbox, LB_GETSEL, k, 0); 906 + ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n", 907 + j, ret, selexpect[k]); 908 + } 909 + 910 + DestroyWindow(listbox); 911 + } 912 + } 913 + DestroyWindow(parent); 914 + } 915 + 787 916 static void test_itemfrompoint(void) 788 917 { 789 918 /* WS_POPUP is required in order to have a more accurate size calculation ( ··· 1812 1941 strcpy(pathBuffer, "C:\\"); 1813 1942 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE); 1814 1943 ok(res, "DlgDirList failed to list C:\\ folders\n"); 1815 - todo_wine ok(!strcmp(pathBuffer, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer); 1944 + ok(!strcmp(pathBuffer, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer); 1816 1945 1817 1946 strcpy(pathBuffer, "C:\\*"); 1818 1947 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE); ··· 1823 1952 SetLastError(0xdeadbeef); 1824 1953 strcpy(pathBuffer, "C:\\INVALID$$DIR"); 1825 1954 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE); 1826 - todo_wine ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res); 1827 - todo_wine ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS, 1955 + ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res); 1956 + ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS, 1828 1957 "GetLastError should return 0x589, got 0x%X\n",GetLastError()); 1829 1958 1830 1959 DestroyWindow(hWnd); ··· 1867 1996 GetUpdateRect( listbox, &r, TRUE ); 1868 1997 ok( !IsRectEmpty( &r ), "got empty rect\n"); 1869 1998 1999 + ret = SendMessageA( listbox, LB_SETCOUNT, -5, 0 ); 2000 + ok( ret == 0, "got %d\n", ret ); 2001 + ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 ); 2002 + ok( ret == -5, "got %d\n", ret ); 2003 + 1870 2004 DestroyWindow( listbox ); 1871 2005 1872 2006 for (i = 0; i < ARRAY_SIZE(styles); ++i) ··· 1903 2037 ok_sequence(sequences, LB_SEQ_INDEX, getlistboxinfo_seq, "GetListBoxInfo()", FALSE); 1904 2038 1905 2039 DestroyWindow(listbox); 2040 + DestroyWindow(parent); 2041 + } 2042 + 2043 + static void test_init_storage( void ) 2044 + { 2045 + static const DWORD styles[] = 2046 + { 2047 + LBS_HASSTRINGS, 2048 + LBS_NODATA | LBS_OWNERDRAWFIXED, 2049 + }; 2050 + HWND parent, listbox; 2051 + LONG ret, items_size; 2052 + int i, j; 2053 + 2054 + parent = create_parent(); 2055 + for (i = 0; i < ARRAY_SIZE(styles); i++) 2056 + { 2057 + listbox = CreateWindowA(WC_LISTBOXA, "TestList", styles[i] | WS_CHILD, 2058 + 0, 0, 100, 100, parent, (HMENU)ID_LISTBOX, NULL, 0); 2059 + 2060 + items_size = SendMessageA(listbox, LB_INITSTORAGE, 100, 0); 2061 + ok(items_size >= 100, "expected at least 100, got %d\n", items_size); 2062 + 2063 + ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0); 2064 + ok(ret == items_size, "expected %d, got %d\n", items_size, ret); 2065 + 2066 + /* it doesn't grow since the space was already reserved */ 2067 + ret = SendMessageA(listbox, LB_INITSTORAGE, items_size, 0); 2068 + ok(ret == items_size, "expected %d, got %d\n", items_size, ret); 2069 + 2070 + /* it doesn't shrink the reserved space */ 2071 + ret = SendMessageA(listbox, LB_INITSTORAGE, 42, 0); 2072 + ok(ret == items_size, "expected %d, got %d\n", items_size, ret); 2073 + 2074 + /* now populate almost all of it so it's not reserved anymore */ 2075 + if (styles[i] & LBS_NODATA) 2076 + { 2077 + ret = SendMessageA(listbox, LB_SETCOUNT, items_size - 1, 0); 2078 + ok(ret == 0, "unexpected return value %d\n", ret); 2079 + } 2080 + else 2081 + { 2082 + for (j = 0; j < items_size - 1; j++) 2083 + { 2084 + ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)""); 2085 + ok(ret == j, "expected %d, got %d\n", j, ret); 2086 + } 2087 + } 2088 + 2089 + /* we still have one more reserved slot, so it doesn't grow yet */ 2090 + ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0); 2091 + ok(ret == items_size, "expected %d, got %d\n", items_size, ret); 2092 + 2093 + /* fill the slot and check again, it should grow this time */ 2094 + ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)""); 2095 + ok(ret == items_size - 1, "expected %d, got %d\n", items_size - 1, ret); 2096 + ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0); 2097 + ok(ret == items_size, "expected %d, got %d\n", items_size, ret); 2098 + ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0); 2099 + ok(ret > items_size, "expected it to grow past %d, got %d\n", items_size, ret); 2100 + 2101 + DestroyWindow(listbox); 2102 + } 1906 2103 DestroyWindow(parent); 1907 2104 } 1908 2105 ··· 2420 2617 test_LB_SELITEMRANGE(); 2421 2618 test_LB_SETCURSEL(); 2422 2619 test_listbox_height(); 2620 + test_changing_selection_styles(); 2423 2621 test_itemfrompoint(); 2424 2622 test_listbox_item_data(); 2425 2623 test_listbox_LB_DIR(); 2426 2624 test_listbox_dlgdir(); 2427 2625 test_set_count(); 2626 + test_init_storage(); 2428 2627 test_GetListBoxInfo(); 2429 2628 test_missing_lbuttonup(); 2430 2629 test_extents();
+82
modules/rostests/winetests/comctl32/listview.c
··· 6475 6475 ok(ret, "Failed to unregister test class.\n"); 6476 6476 } 6477 6477 6478 + static void test_item_state_change(void) 6479 + { 6480 + static const DWORD styles[] = { LVS_ICON, LVS_LIST, LVS_REPORT, LVS_SMALLICON }; 6481 + LVITEMA item; 6482 + HWND hwnd; 6483 + DWORD res; 6484 + int i; 6485 + 6486 + for (i = 0; i < ARRAY_SIZE(styles); i++) 6487 + { 6488 + hwnd = create_listview_control(styles[i]); 6489 + 6490 + insert_item(hwnd, 0); 6491 + 6492 + /* LVM_SETITEMSTATE with mask */ 6493 + memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); 6494 + memset(&item, 0, sizeof(item)); 6495 + item.mask = LVIF_STATE; 6496 + item.stateMask = LVIS_SELECTED; 6497 + item.state = LVIS_SELECTED; 6498 + res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 6499 + ok(res, "Failed to set item state.\n"); 6500 + 6501 + ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem); 6502 + ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem); 6503 + ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n"); 6504 + ok(g_nmlistview.uNewState == LVIS_SELECTED, "got new state 0x%08x\n", g_nmlistview.uNewState); 6505 + ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState); 6506 + ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); 6507 + 6508 + /* LVM_SETITEMSTATE 0 mask */ 6509 + memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); 6510 + memset(&item, 0, sizeof(item)); 6511 + item.stateMask = LVIS_SELECTED; 6512 + item.state = 0; 6513 + res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 6514 + ok(res, "Failed to set item state.\n"); 6515 + 6516 + ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem); 6517 + ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem); 6518 + ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n"); 6519 + ok(g_nmlistview.uNewState == 0, "Unexpected new state %#x.\n", g_nmlistview.uNewState); 6520 + ok(g_nmlistview.uOldState == LVIS_SELECTED, "Unexpected old state %#x.\n", g_nmlistview.uOldState); 6521 + ok(g_nmlistview.uChanged == LVIF_STATE, "Unexpected change mask %#x.\n", g_nmlistview.uChanged); 6522 + 6523 + /* LVM_SETITEM changes state */ 6524 + memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); 6525 + memset(&item, 0, sizeof(item)); 6526 + item.stateMask = LVIS_SELECTED; 6527 + item.state = LVIS_SELECTED; 6528 + item.mask = LVIF_STATE; 6529 + res = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); 6530 + ok(res, "Failed to set item.\n"); 6531 + 6532 + ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem); 6533 + ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem); 6534 + ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n"); 6535 + ok(g_nmlistview.uNewState == LVIS_SELECTED, "Unexpected new state %#x.\n", g_nmlistview.uNewState); 6536 + ok(g_nmlistview.uOldState == 0, "Unexpected old state %#x.\n", g_nmlistview.uOldState); 6537 + ok(g_nmlistview.uChanged == LVIF_STATE, "Unexpected change mask %#x.\n", g_nmlistview.uChanged); 6538 + 6539 + /* LVM_SETITEM no state changes */ 6540 + memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); 6541 + memset(&item, 0, sizeof(item)); 6542 + item.lParam = 11; 6543 + item.mask = LVIF_PARAM; 6544 + res = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); 6545 + ok(res, "Failed to set item.\n"); 6546 + 6547 + ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem); 6548 + ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem); 6549 + ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n"); 6550 + ok(g_nmlistview.uNewState == 0, "Unexpected new state %#x.\n", g_nmlistview.uNewState); 6551 + ok(g_nmlistview.uOldState == 0, "Unexpected old state %#x.\n", g_nmlistview.uOldState); 6552 + ok(g_nmlistview.uChanged == LVIF_PARAM, "Unexpected change mask %#x.\n", g_nmlistview.uChanged); 6553 + 6554 + DestroyWindow(hwnd); 6555 + } 6556 + } 6557 + 6478 6558 START_TEST(listview) 6479 6559 { 6480 6560 ULONG_PTR ctx_cookie; ··· 6538 6618 test_LVSCW_AUTOSIZE(); 6539 6619 test_LVN_ENDLABELEDIT(); 6540 6620 test_LVM_GETCOUNTPERPAGE(); 6621 + test_item_state_change(); 6541 6622 6542 6623 if (!load_v6_module(&ctx_cookie, &hCtx)) 6543 6624 { ··· 6582 6663 test_LVSCW_AUTOSIZE(); 6583 6664 test_LVN_ENDLABELEDIT(); 6584 6665 test_LVM_GETCOUNTPERPAGE(); 6666 + test_item_state_change(); 6585 6667 6586 6668 unload_v6_module(ctx_cookie, hCtx); 6587 6669
+6 -2
modules/rostests/winetests/comctl32/pager.c
··· 564 564 static const INT formats[] = {NFR_UNICODE, NFR_ANSI}; 565 565 HWND parent, pager, child; 566 566 LRESULT ret; 567 + BOOL bret; 567 568 INT i; 568 569 569 - ok(register_notifyformat_class(), "Register test class failed, error 0x%08x\n", GetLastError()); 570 + bret = register_notifyformat_class(); 571 + ok(bret, "Register test class failed, error 0x%08x\n", GetLastError()); 570 572 571 573 for (i = 0; i < ARRAY_SIZE(formats); i++) 572 574 { ··· 1280 1282 {&nmtv, sizeof(nmtv), &nmtv.itemOld.mask, TVIF_TEXT, &nmtv.itemOld.pszText, &nmtv.itemOld.cchTextMax, 1281 1283 TVN_SELCHANGEDW, TVN_SELCHANGEDA, CONVERT_SEND, TVITEM_OLD_HANDLER} 1282 1284 }; 1285 + BOOL bret; 1283 1286 INT i; 1284 1287 1285 - ok(register_test_notify_class(), "Register test class failed, error 0x%08x\n", GetLastError()); 1288 + bret = register_test_notify_class(); 1289 + ok(bret, "Register test class failed, error 0x%08x\n", GetLastError()); 1286 1290 1287 1291 parent = CreateWindowA(class, "parent", WS_OVERLAPPED, 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), 0); 1288 1292 ok(parent != NULL, "CreateWindow failed\n");
+21 -5
modules/rostests/winetests/comctl32/progress.c
··· 254 254 { 3, 15, 5 }, 255 255 { 3, 15, -5 }, 256 256 { 3, 15, 50 }, 257 + { -15, 15, 5 }, 258 + { -3, -2, -5 }, 259 + { 0, 0, 1 }, 260 + { 5, 5, 1 }, 261 + { 0, 0, -1 }, 262 + { 5, 5, -1 }, 263 + { 10, 5, 2 }, 257 264 }; 258 265 HWND progress; 259 266 int i, j; ··· 261 268 for (i = 0; i < ARRAY_SIZE(stepit_tests); i++) 262 269 { 263 270 struct stepit_test *test = &stepit_tests[i]; 271 + PBRANGE range; 264 272 LRESULT ret; 265 273 266 274 progress = create_progress(0); 267 275 268 276 ret = SendMessageA(progress, PBM_SETRANGE32, test->min, test->max); 269 277 ok(ret != 0, "Unexpected return value.\n"); 278 + 279 + SendMessageA(progress, PBM_GETRANGE, 0, (LPARAM)&range); 280 + ok(range.iLow == test->min && range.iHigh == test->max, "Unexpected range.\n"); 270 281 271 282 SendMessageA(progress, PBM_SETPOS, test->min, 0); 272 283 SendMessageA(progress, PBM_SETSTEP, test->step, 0); ··· 277 288 int current; 278 289 279 290 pos += test->step; 280 - if (pos > test->max) 281 - pos = (pos - test->min) % (test->max - test->min) + test->min; 282 - if (pos < test->min) 283 - pos = (pos - test->min) % (test->max - test->min) + test->max; 291 + if (test->min != test->max) 292 + { 293 + if (pos > test->max) 294 + pos = (pos - test->min) % (test->max - test->min) + test->min; 295 + if (pos < test->min) 296 + pos = (pos - test->min) % (test->max - test->min) + test->max; 297 + } 298 + else 299 + pos = test->min; 284 300 285 301 SendMessageA(progress, PBM_STEPIT, 0, 0); 286 302 287 303 current = SendMessageA(progress, PBM_GETPOS, 0, 0); 288 - ok(current == pos, "Unexpected position %d, expected %d.\n", current, pos); 304 + ok(current == pos, "%u: unexpected position %d, expected %d.\n", i, current, pos); 289 305 } 290 306 291 307 DestroyWindow(progress);
+3
modules/rostests/winetests/comctl32/subclass.c
··· 273 273 ret = pSetWindowSubclass(hwnd, NULL, 1, 0); 274 274 ok(ret == FALSE, "Expected FALSE\n"); 275 275 276 + pRemoveWindowSubclass(hwnd, wnd_proc_sub, 2); 277 + pRemoveWindowSubclass(hwnd, wnd_proc_sub, 5); 278 + 276 279 DestroyWindow(hwnd); 277 280 } 278 281
+17 -1
modules/rostests/winetests/comctl32/trackbar.c
··· 931 931 static void test_thumb_length(void) 932 932 { 933 933 HWND hWndTrackbar; 934 - int r; 934 + int r, r2; 935 935 936 936 hWndTrackbar = create_trackbar(defaultstyle, hWndParent); 937 937 ok(hWndTrackbar != NULL, "Expected non NULL value\n"); ··· 961 961 962 962 ok_sequence(sequences, TRACKBAR_SEQ_INDEX, thumb_length_test_seq, "thumb length test sequence", TRUE); 963 963 ok_sequence(sequences, PARENT_SEQ_INDEX, parent_thumb_length_test_seq, "parent thumb length test sequence", TRUE); 964 + 965 + DestroyWindow(hWndTrackbar); 966 + 967 + /* Fixed thumb length does not depend on window size. */ 968 + hWndTrackbar = CreateWindowA(TRACKBAR_CLASSA, "Trackbar Control", WS_VISIBLE | TBS_ENABLESELRANGE 969 + | TBS_FIXEDLENGTH, 0, 0, 0, 0, hWndParent, NULL, GetModuleHandleA(NULL), NULL); 970 + 971 + r = SendMessageA(hWndTrackbar, TBM_GETTHUMBLENGTH, 0, 0); 972 + 973 + DestroyWindow(hWndTrackbar); 974 + 975 + hWndTrackbar = CreateWindowA(TRACKBAR_CLASSA, "Trackbar Control", WS_VISIBLE | TBS_ENABLESELRANGE 976 + | TBS_FIXEDLENGTH, 0, 0, 200, 200, hWndParent, NULL, GetModuleHandleA(NULL), NULL); 977 + 978 + r2 = SendMessageA(hWndTrackbar, TBM_GETTHUMBLENGTH, 0, 0); 979 + ok(r2 == r, "Unexpected thumb length %d.\n", r); 964 980 965 981 DestroyWindow(hWndTrackbar); 966 982 }
+1 -1
modules/rostests/winetests/comctl32/treeview.c
··· 1364 1364 visibleItem = (HTREEITEM)SendMessageA(pHdr->hwndFrom, TVM_GETNEXTITEM, 1365 1365 TVGN_NEXTVISIBLE, (LPARAM)visibleItem); 1366 1366 *(HTREEITEM*)&rect = visibleItem; 1367 - ok(visibleItem != NULL, "There must be a visible item after the first visisble item.\n"); 1367 + ok(visibleItem != NULL, "There must be a visible item after the first one.\n"); 1368 1368 ok(SendMessageA(pHdr->hwndFrom, TVM_GETITEMRECT, TRUE, (LPARAM)&rect), 1369 1369 "Failed to get rect for second visible item.\n"); 1370 1370 }
+75 -1
modules/rostests/winetests/comctl32/updown.c
··· 28 28 * - check UDM_SETBUDDY message 29 29 * - check UDM_GETBUDDY message 30 30 * - up-down control and buddy control must have the same parent 31 - * - up-down control notifies its parent window when its position changes with UDN_DELTAPOS + WM_VSCROLL or WM_HSCROLL 32 31 * - check UDS_ALIGN[LEFT,RIGHT]...check that width of buddy window is decreased 33 32 * - check that UDS_SETBUDDYINT sets the caption of the buddy window when it is changed 34 33 * - check that the thousands operator is set for large numbers ··· 165 164 { 0 } 166 165 }; 167 166 167 + static const struct message test_updown_pos_notifications_seq[] = { 168 + { WM_CTLCOLOREDIT, sent|optional }, 169 + { WM_COMMAND, sent|wparam, MAKELONG(0, EN_SETFOCUS) }, 170 + { WM_NOTIFY, sent|id, 0, 0, UDN_DELTAPOS }, 171 + { WM_COMMAND, sent|wparam, MAKELONG(0, EN_UPDATE) }, 172 + { WM_COMMAND, sent|wparam, MAKELONG(0, EN_CHANGE) }, 173 + { WM_VSCROLL, sent|wparam, MAKELONG(SB_THUMBPOSITION, 51) }, 174 + { WM_CTLCOLOREDIT, sent|optional }, 175 + { WM_VSCROLL, sent|wparam, MAKELONG(SB_ENDSCROLL, 51) }, 176 + /* no WM_NOTIFY(NM_RELEASEDCAPTURE) message */ 177 + { 0 } 178 + }; 179 + 180 + static const struct message test_updown_pos_notifications_horz_seq[] = { 181 + { WM_CTLCOLOREDIT, sent|optional }, 182 + { WM_COMMAND, sent|wparam, MAKELONG(0, EN_SETFOCUS) }, 183 + { WM_NOTIFY, sent|id, 0, 0, UDN_DELTAPOS }, 184 + { WM_COMMAND, sent|wparam, MAKELONG(0, EN_UPDATE) }, 185 + { WM_COMMAND, sent|wparam, MAKELONG(0, EN_CHANGE) }, 186 + { WM_HSCROLL, sent|wparam, MAKELONG(SB_THUMBPOSITION, 51) }, 187 + { WM_CTLCOLOREDIT, sent|optional }, 188 + { WM_HSCROLL, sent|wparam, MAKELONG(SB_ENDSCROLL, 51) }, 189 + /* no WM_NOTIFY(NM_RELEASEDCAPTURE) message */ 190 + { 0 } 191 + }; 192 + 168 193 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 169 194 { 170 195 static LONG defwndproc_counter = 0; ··· 186 211 if (defwndproc_counter) msg.flags |= defwinproc; 187 212 msg.wParam = wParam; 188 213 msg.lParam = lParam; 214 + if (message == WM_NOTIFY && lParam) 215 + msg.id = ((NMHDR*)lParam)->code; 189 216 add_message(sequences, PARENT_SEQ_INDEX, &msg); 190 217 } 191 218 ··· 900 927 DestroyWindow(updown); 901 928 } 902 929 930 + static void test_updown_pos_notifications(void) 931 + { 932 + HWND updown; 933 + RECT rect; 934 + UINT x, y; 935 + int result; 936 + 937 + /* test updown control notifications without UDS_HORZ style */ 938 + updown = create_updown_control(UDS_ALIGNRIGHT | UDS_SETBUDDYINT, g_edit); 939 + SetFocus(updown); 940 + flush_sequences(sequences, NUM_MSG_SEQUENCES); 941 + 942 + /* click on the up-arrow button */ 943 + GetClientRect(updown, &rect); 944 + x = rect.left + (rect.right - rect.left) / 2; 945 + y = rect.top + (rect.bottom - rect.top) / 4; 946 + result = SendMessageA(updown, WM_LBUTTONDOWN, 0, MAKELPARAM(x, y)); 947 + expect(result, 0); 948 + result = SendMessageA(updown, WM_LBUTTONUP, 0, MAKELPARAM(x, y)); 949 + expect(result, 0); 950 + 951 + ok_sequence(sequences, PARENT_SEQ_INDEX, test_updown_pos_notifications_seq, 952 + "test updown to parent notify (vertical)", FALSE); 953 + 954 + DestroyWindow(updown); 955 + 956 + /* test updown control notifications with UDS_HORZ style */ 957 + updown = create_updown_control(UDS_ALIGNRIGHT | UDS_SETBUDDYINT | UDS_HORZ, g_edit); 958 + SetFocus(updown); 959 + flush_sequences(sequences, NUM_MSG_SEQUENCES); 960 + 961 + /* click on the right-arrow button */ 962 + GetClientRect(updown, &rect); 963 + x = rect.left + (rect.right - rect.left) * 3 / 4; 964 + y = rect.top + (rect.bottom - rect.top) / 2; 965 + result = SendMessageA(updown, WM_LBUTTONDOWN, 0, MAKELPARAM(x, y)); 966 + expect(result, 0); 967 + result = SendMessageA(updown, WM_LBUTTONUP, 0, MAKELPARAM(x, y)); 968 + expect(result, 0); 969 + 970 + ok_sequence(sequences, PARENT_SEQ_INDEX, test_updown_pos_notifications_horz_seq, 971 + "test updown to parent notify (horizontal)", FALSE); 972 + 973 + DestroyWindow(updown); 974 + } 975 + 903 976 static void init_functions(void) 904 977 { 905 978 HMODULE hComCtl32 = LoadLibraryA("comctl32.dll"); ··· 931 1004 test_updown_unicode(); 932 1005 test_UDS_SETBUDDYINT(); 933 1006 test_CreateUpDownControl(); 1007 + test_updown_pos_notifications(); 934 1008 935 1009 DestroyWindow(g_edit); 936 1010 DestroyWindow(parent_wnd);