From: Huw Davies Subject: [PATCH 2/2] comctl32: Implement the legacy notifications during restore. Message-Id: <1435781839-27781-2-git-send-email-huw@codeweavers.com> Date: Wed, 1 Jul 2015 21:17:19 +0100 --- try 2: Use an allocated, rather than a static, string in the test. dlls/comctl32/tests/toolbar.c | 84 ++++++++++++++++++++++++++++++++++++++++--- dlls/comctl32/toolbar.c | 44 ++++++++++++++++++++--- 2 files changed, 119 insertions(+), 9 deletions(-) diff --git a/dlls/comctl32/tests/toolbar.c b/dlls/comctl32/tests/toolbar.c index 96ec3b4..23eb250 100644 --- a/dlls/comctl32/tests/toolbar.c +++ b/dlls/comctl32/tests/toolbar.c @@ -66,6 +66,28 @@ static const struct message save_parent_seq[] = { { 0 } }; +static const struct message restore_parent_seq[] = { + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, -1 }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 0 }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 1 }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 2 }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 3 }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 4 }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 5 }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 6 }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 7 }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 8 }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 9 }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_RESTORE, 0xa }, + { WM_NOTIFY, sent|id, 0, 0, TBN_BEGINADJUST }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_GETBUTTONINFOA, 0 }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_GETBUTTONINFOA, 1 }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_GETBUTTONINFOA, 2 }, + { WM_NOTIFY, sent|id|custdraw, 0, 0, TBN_GETBUTTONINFOA, 3 }, + { WM_NOTIFY, sent|id, 0, 0, TBN_ENDADJUST }, + { 0 } +}; + #define DEFINE_EXPECT(func) \ static BOOL expect_ ## func = FALSE, called_ ## func = FALSE @@ -105,6 +127,8 @@ static void MakeButton(TBBUTTON *p, int idCommand, int fsStyle, int nString) { p->iString = nString; } +static void *alloced_str; + static LRESULT parent_wnd_notify(LPARAM lParam) { NMHDR *hdr = (NMHDR *)lParam; @@ -245,6 +269,35 @@ static LRESULT parent_wnd_notify(LPARAM lParam) if (restore->iItem == -1) return 0; return 1; } + case TBN_GETBUTTONINFOA: + { + NMTOOLBARA *tb = (NMTOOLBARA *)lParam; + tb->tbButton.iBitmap = 0; + tb->tbButton.fsState = 0; + tb->tbButton.fsStyle = 0; + tb->tbButton.dwData = 0; + ok( tb->cchText == 128, "got %d\n", tb->cchText ); + switch (tb->iItem) + { + case 0: + tb->tbButton.idCommand = 7; + alloced_str = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 8 ); + strcpy( alloced_str, "foo" ); + tb->tbButton.iString = (INT_PTR)alloced_str; + return 1; + case 1: + tb->tbButton.idCommand = 9; + tb->tbButton.iString = 0; + /* tb->pszText is ignored */ + strcpy( tb->pszText, "foo" ); + return 1; + case 2: + tb->tbButton.idCommand = 11; + tb->tbButton.iString = 3; + return 1; + } + return 0; + } } return 0; } @@ -271,6 +324,18 @@ static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam, msg.stage = save->iItem; } break; + case TBN_RESTORE: + { + NMTBRESTORE *restore = (NMTBRESTORE *)lParam; + msg.stage = restore->iItem; + } + break; + case TBN_GETBUTTONINFOA: + { + NMTOOLBARA *tb = (NMTOOLBARA *)lParam; + msg.stage = tb->iItem; + } + break; } } @@ -2228,9 +2293,9 @@ static void test_save(void) {0, 1, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, {0, 3, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 1, 2}, {0, 5, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 2, 0}, - {0, 7, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 3, 0}, - {0, 9, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 4, 0}, - {0, 11, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 5, 0}, + {0, 7, 0, BTNS_BUTTON, {0}, 0, (INT_PTR)"foo"}, + {0, 9, 0, BTNS_BUTTON, {0}, 0, 0}, + {0, 11, 0, BTNS_BUTTON, {0}, 0, 3}, {0, 13, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 6, 0}, {0, 0, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 7, 0}, {0, 0, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 8, 0}, @@ -2263,8 +2328,11 @@ static void test_save(void) wnd = NULL; rebuild_toolbar( &wnd ); + + flush_sequences(sequences, NUM_MSG_SEQUENCES); res = SendMessageW( wnd, TB_SAVERESTOREW, FALSE, (LPARAM)¶ms ); ok( res, "restoring failed\n" ); + ok_sequence(sequences, PARENT_SEQ_INDEX, restore_parent_seq, "restore", FALSE); count = SendMessageW( wnd, TB_BUTTONCOUNT, 0, 0 ); ok( count == sizeof(expect_btns) / sizeof(expect_btns[0]), "got %d\n", count ); @@ -2278,7 +2346,15 @@ static void test_save(void) ok( tb.fsState == expect_btns[i].fsState, "%d: got %02x\n", i, tb.fsState ); ok( tb.fsStyle == expect_btns[i].fsStyle, "%d: got %02x\n", i, tb.fsStyle ); ok( tb.dwData == expect_btns[i].dwData, "%d: got %lx\n", i, tb.dwData ); - ok( tb.iString == expect_btns[i].iString, "%d: got %lx\n", i, tb.iString ); + if (IS_INTRESOURCE(expect_btns[i].iString)) + ok( tb.iString == expect_btns[i].iString, "%d: got %lx\n", i, tb.iString ); + else + ok( !strcmp( (char *)tb.iString, (char *)expect_btns[i].iString ), + "%d: got %s\n", i, (char *)tb.iString ); + + /* In fact the ptr value set in TBN_GETBUTTONINFOA is simply copied */ + if (tb.idCommand == 7) + ok( tb.iString == (INT_PTR)alloced_str, "string not set\n"); } DestroyWindow( wnd ); diff --git a/dlls/comctl32/toolbar.c b/dlls/comctl32/toolbar.c index 11e9678..c777f5b 100644 --- a/dlls/comctl32/toolbar.c +++ b/dlls/comctl32/toolbar.c @@ -247,6 +247,8 @@ static LRESULT TOOLBAR_AutoSize(TOOLBAR_INFO *infoPtr); static void TOOLBAR_CheckImageListIconSize(TOOLBAR_INFO *infoPtr); static void TOOLBAR_TooltipAddTool(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *button); static void TOOLBAR_TooltipSetRect(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *button); +static LRESULT TOOLBAR_SetButtonInfo(TOOLBAR_INFO *infoPtr, INT Id, + const TBBUTTONINFOW *lptbbi, BOOL isW); static inline int default_top_margin(const TOOLBAR_INFO *infoPtr) @@ -4151,6 +4153,7 @@ TOOLBAR_Restore(TOOLBAR_INFO *infoPtr, const TBSAVEPARAMSW *lpSave) DWORD dwType; DWORD dwSize = 0; NMTBRESTORE nmtbr; + NMHDR hdr; /* restore toolbar information */ TRACE("restore from %s %s\n", debugstr_w(lpSave->pszSubKey), @@ -4221,13 +4224,44 @@ TOOLBAR_Restore(TOOLBAR_INFO *infoPtr, const TBSAVEPARAMSW *lpSave) TOOLBAR_InsertButtonT(infoPtr, -1, &nmtbr.tbButton, TRUE); } - /* do legacy notifications */ - if (infoPtr->iVersion < 5) + TOOLBAR_SendNotify( &hdr, infoPtr, TBN_BEGINADJUST ); + for (i = 0; ; i++) { - /* FIXME: send TBN_BEGINADJUST */ - FIXME("send TBN_GETBUTTONINFO for each button\n"); - /* FIXME: send TBN_ENDADJUST */ + NMTOOLBARW tb; + TBBUTTONINFOW bi; + WCHAR buf[128]; + UINT code = infoPtr->bUnicode ? TBN_GETBUTTONINFOW : TBN_GETBUTTONINFOA; + INT idx; + + memset( &tb, 0, sizeof(tb) ); + tb.iItem = i; + tb.cchText = sizeof(buf) / sizeof(buf[0]); + tb.pszText = buf; + + /* Use the same struct for both A and W versions since the layout is the same. */ + if (!TOOLBAR_SendNotify( &tb.hdr, infoPtr, code )) + break; + + idx = TOOLBAR_GetButtonIndex( infoPtr, tb.tbButton.idCommand, FALSE ); + if (idx == -1) continue; + + /* tb.pszText is ignored - the string comes from tb.tbButton.iString, which may + be an index or a ptr. Either way it is simply copied. There is no api to change + the string index, so we set it manually. The other properties can be set with SetButtonInfo. */ + free_string( infoPtr->buttons + idx ); + infoPtr->buttons[idx].iString = tb.tbButton.iString; + + memset( &bi, 0, sizeof(bi) ); + bi.cbSize = sizeof(bi); + bi.dwMask = TBIF_IMAGE | TBIF_STATE | TBIF_STYLE | TBIF_LPARAM; + bi.iImage = tb.tbButton.iBitmap; + bi.fsState = tb.tbButton.fsState; + bi.fsStyle = tb.tbButton.fsStyle; + bi.lParam = tb.tbButton.dwData; + + TOOLBAR_SetButtonInfo( infoPtr, tb.tbButton.idCommand, &bi, TRUE ); } + TOOLBAR_SendNotify( &hdr, infoPtr, TBN_ENDADJUST ); /* remove all uninitialised buttons * note: loop backwards to avoid having to fixup i on a -- 1.8.0