[PATCH 1/3] comctl32/pager: Support toolbar notification conversion.
Nikolay Sivov
bunglehead at gmail.com
Tue Aug 28 01:41:48 CDT 2018
On 8/28/2018 6:27 AM, Zhiyi Zhang wrote:
> Fix BibleWorks 10 not displaying toolbar.
>
> Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
> ---
> dlls/comctl32/pager.c | 96 ++++++++
> dlls/comctl32/tests/pager.c | 431 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 527 insertions(+)
>
> diff --git a/dlls/comctl32/pager.c b/dlls/comctl32/pager.c
> index de63cad717..0367108db2 100644
> --- a/dlls/comctl32/pager.c
> +++ b/dlls/comctl32/pager.c
> @@ -91,6 +91,17 @@ typedef struct
> #define INITIAL_DELAY 500
> #define REPEAT_DELAY 50
>
> +/* Text field conversion behavior flags for PAGER_SendConvertedNotify() */
> +typedef enum
> +{
> + /* Convert ANSI text from parent back to Unicode for pager */
> + FROM_ANSI = 0x01,
> + /* Convert Unicode text to ANSI for parent before sending. If not set, do nothing */
> + TO_ANSI = 0x02,
Isn't it always from or to ANSI? Maybe name it something like
CONVERT_SEND CONVERT_RECEIVE?
> + /* Send empty text to parent if text is NULL, original text pointer still remain NULL */
> + SET_NULL_EMPTY = 0x04
> +} ConversionFlag;
This should be 'enum consersion_flags', no typedef.
> +
> static void
> PAGER_GetButtonRects(const PAGER_INFO* infoPtr, RECT* prcTopLeft, RECT* prcBottomRight, BOOL bClientCoords)
> {
> @@ -1020,6 +1031,89 @@ static LRESULT PAGER_NotifyFormat(PAGER_INFO *infoPtr, INT command)
> }
> }
>
> +static UINT PAGER_GetAnsiNtfCode(UINT code)
> +{
> + switch (code)
> + {
> + /* Toolbar */
> + case TBN_GETBUTTONINFOW: return TBN_GETBUTTONINFOA;
> + case TBN_GETINFOTIPW: return TBN_GETINFOTIPA;
> + }
> + return code;
> +}
> +
> +static LRESULT PAGER_SendConvertedNotify(PAGER_INFO *infoPtr, NMHDR *hdr, WCHAR **text, INT *textMax, ConversionFlag flags)
It's better to have DWORD for flags.
> +{
> + WCHAR emptyW[] = {0};
Shouldn't it be constant?
> + WCHAR *oldText;
> + INT oldTextMax;
> + void *sendBuffer = NULL;
> + void *receiveBuffer = NULL;
Why are these untyped?
> + INT bufferSize;
> + LRESULT ret = 0;
> +
> + oldText = *text;
> + oldTextMax = textMax ? *textMax : 0;
> +
> + hdr->code = PAGER_GetAnsiNtfCode(hdr->code);
> +
> + if (oldTextMax < 0) goto done;
> +
> + if (!*text && flags & SET_NULL_EMPTY)
> + *text = emptyW;
> +
> + if (*text && flags & TO_ANSI)
> + {
> + bufferSize = WideCharToMultiByte(CP_ACP, 0, *text, -1, 0, 0, NULL, FALSE);
> + bufferSize = max(bufferSize, oldTextMax);
Why is this adjustment necessary?
> + sendBuffer = heap_alloc(bufferSize);
> + if (!sendBuffer) goto done;
> + WideCharToMultiByte(CP_ACP, 0, *text, -1, sendBuffer, bufferSize, NULL, FALSE);
> + *text = sendBuffer;
> + }
> +
> + ret = SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr);
> +
> + if (*text && flags & FROM_ANSI)
> + {
> + bufferSize = lstrlenA((CHAR *)*text);
> + receiveBuffer = heap_alloc(bufferSize + 1);
> + if (!receiveBuffer) goto done;
> + memcpy(receiveBuffer, *text, bufferSize + 1);
> + if (!oldText) goto done;
> + MultiByteToWideChar(CP_ACP, 0, receiveBuffer, -1, oldText, oldTextMax);
Why do you need to make a copy here?
> + }
> +
> +done:
> + heap_free(sendBuffer);
> + heap_free(receiveBuffer);
> + *text = oldText;
> + return ret;
> +}
> +
> +static LRESULT PAGER_Notify(PAGER_INFO *infoPtr, NMHDR *hdr)
> +{
> + if (infoPtr->bUnicode) return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr);
> +
> + switch (hdr->code)
> + {
> + /* Toolbar */
> + case TBN_GETBUTTONINFOW:
> + {
> + NMTOOLBARW *nmtb = (NMTOOLBARW *)hdr;
> + return PAGER_SendConvertedNotify(infoPtr, hdr, &nmtb->pszText, &nmtb->cchText,
> + SET_NULL_EMPTY | TO_ANSI | FROM_ANSI);
> + }
> + case TBN_GETINFOTIPW:
> + {
> + NMTBGETINFOTIPW *nmtbgit = (NMTBGETINFOTIPW *)hdr;
> + return PAGER_SendConvertedNotify(infoPtr, hdr, &nmtbgit->pszText, &nmtbgit->cchTextMax, FROM_ANSI);
> + }
> + }
> + /* Other notifications or notifications above that don't have text, thus no need to convert */
> + return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr);
> +}
> +
> static LRESULT WINAPI
> PAGER_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
> {
> @@ -1115,6 +1209,8 @@ PAGER_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
> return PAGER_NotifyFormat (infoPtr, lParam);
>
> case WM_NOTIFY:
> + return PAGER_Notify (infoPtr, (NMHDR *)lParam);
> +
> case WM_COMMAND:
> return SendMessageW (infoPtr->hwndNotify, uMsg, wParam, lParam);
>
> diff --git a/dlls/comctl32/tests/pager.c b/dlls/comctl32/tests/pager.c
> index a1f6683a57..46f2eb0acb 100644
> --- a/dlls/comctl32/tests/pager.c
> +++ b/dlls/comctl32/tests/pager.c
> @@ -30,10 +30,91 @@
> static HWND parent_wnd, child1_wnd, child2_wnd;
> static INT notify_format;
> static BOOL notify_query_received;
> +static WCHAR test_w[] = {'t', 'e', 's', 't', 0};
> +static CHAR test_a[] = {'t', 'e', 's', 't', 0};
> +static WCHAR t_w[] = {'t', 0};
> +static CHAR large_a[] = "You should have received a copy of the GNU Lesser General Public License along with this ...";
> +static WCHAR buffer[64];
> +static WCHAR buffer2[64];
> +
> +/* Text field conversion behavior flags for PAGER_SendConvertedNotify() */
> +typedef enum
> +{
> + /* Convert ANSI text from parent back to Unicode for pager */
> + FROM_ANSI = 0x01,
> + /* Convert Unicode text to ANSI for parent before sending. If not set, do nothing */
> + TO_ANSI = 0x02,
> + /* Send empty text to parent if text is NULL, original text pointer still remain NULL */
> + SET_NULL_EMPTY = 0x04
> +} ConversionFlag;
> +
> +static struct notify_test_data
> +{
> + UINT unicode;
> + UINT ansi;
> + UINT_PTR id_from;
> + HWND hwnd_from;
> + INT text_size;
> + /* Whether parent receive notification */
> + BOOL received;
> + UINT sub_test_id;
> + /* Text field conversion behavior flags */
> + ConversionFlag flags;
> +} notify_test_data;
>
> #define CHILD1_ID 1
> #define CHILD2_ID 2
>
> +#define expect_eq_int(actual, expected) \
> + do \
> + { \
> + ok((actual) == (expected), "Code:0x%08x Subtest:0x%08x Expect " #actual " 0x%08x, got 0x%08x\n", \
> + notify_test_data.unicode, notify_test_data.sub_test_id, (expected), (actual)); \
> + } while (0)
> +
> +#define expect_eq_long(actual, expected) \
> + do \
> + { \
> + ok((actual) == (expected), "Code:0x%08x Subtest:0x%08x Expect " #actual " 0x%08lx, got 0x%08lx\n", \
> + notify_test_data.unicode, notify_test_data.sub_test_id, (expected), (actual)); \
> + } while (0)
> +
> +#define expect_eq_pointer(actual, expected) \
> + do \
> + { \
> + ok((actual) == (expected), "Code:0x%08x Subtest:0x%08x Expect " #actual " %p, got %p\n", \
> + notify_test_data.unicode, notify_test_data.sub_test_id, (expected), (actual)); \
> + } while (0)
> +
> +#define expect_eq_text_a(actual, expected) \
> + do \
> + { \
> + ok(!lstrcmpA((actual), (expected)), "Code:0x%08x Subtest:0x%08x Expect " #actual " %s, got %s\n", \
> + notify_test_data.unicode, notify_test_data.sub_test_id, (expected), (actual)); \
> + } while (0)
> +
> +#define expect_eq_text_w(actual, expected) \
> + do \
> + { \
> + ok(!lstrcmpW((actual), (expected)), "Code:0x%08x Subtest:0x%08x Expect " #actual " %s, got %s\n", \
> + notify_test_data.unicode, notify_test_data.sub_test_id, wine_dbgstr_w((expected)), \
> + wine_dbgstr_w((actual))); \
> + } while (0)
> +
> +#define expect_text_empty(actual) \
> + do \
> + { \
> + ok((actual) && !(actual)[0], "Code:0x%08x Subtest:0x%08x Expect " #actual " empty\n", \
> + notify_test_data.unicode, notify_test_data.sub_test_id); \
> + } while (0)
> +
> +#define expect_null(actual) \
> + do \
> + { \
> + ok(!(actual), "Code:0x%08x Subtest:0x%08x Expect " #actual " NULL, got %p\n", notify_test_data.unicode, \
> + notify_test_data.sub_test_id, (actual)); \
> + } while (0)
> +
Do we really need this? I'd rather had them inlined.
> static BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
> static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
>
> @@ -419,6 +500,355 @@ static void test_wm_notifyformat(void)
> UnregisterClassW(class_w, GetModuleHandleW(NULL));
> }
>
> +static void wm_notify_text_handler(CHAR **text, INT *textMax)
> +{
> + expect_eq_int(*textMax, notify_test_data.text_size);
> + switch (notify_test_data.sub_test_id)
> + {
> + case 1:
> + if (notify_test_data.flags & SET_NULL_EMPTY)
> + expect_text_empty(*text);
> + else
> + expect_null(*text);
> + break;
> + case 2:
> + {
> + INT length = lstrlenA(*text);
> + ok(length == 0
> + || broken(length == 3) /* 2003 */
> + || broken(length == 1) /* <= Win7 */,
> + "Wrong text length\n");
> + break;
> + }
> + case 3:
> + if (notify_test_data.flags & TO_ANSI)
> + {
> + expect_eq_text_a(*text, test_a);
> + ok(*text != (CHAR *)buffer, "Expect using a new buffer\n");
> + }
> + else
> + {
> + expect_eq_text_w((WCHAR *)*text, test_w);
> + expect_eq_pointer(*text, (CHAR *)buffer);
> + }
> + break;
> + case 4:
> + expect_text_empty(*text);
> + memcpy(*text, test_a, sizeof(test_a));
> + break;
> + case 5:
> + expect_text_empty(*text);
> + *textMax = 1;
> + break;
> + case 6:
> + expect_text_empty(*text);
> + *text = test_a;
> + break;
> + case 7:
> + *text = test_a;
> + break;
> + case 8:
> + expect_text_empty(*text);
> + *text = large_a;
> + break;
> + }
> +}
I don't like those test id's spread like that. Can we have static test
data that we'll iterate through, and symbolic names for test ids?
> +
> +static LRESULT WINAPI test_notify_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
> +{
> + static const WCHAR test[] = {'t', 'e', 's', 't', 0};
> + switch (message)
> + {
> + case WM_NOTIFY:
> + {
> + NMHDR *hdr = (NMHDR *)lParam;
> +
> + /* Not notifications we want to test */
> + if (!notify_test_data.unicode) break;
> + ok(!notify_test_data.received, "Extra notification received\n");
> +
> + expect_eq_long(wParam, notify_test_data.id_from);
> + expect_eq_int(hdr->code, notify_test_data.ansi);
> + expect_eq_long(hdr->idFrom, notify_test_data.id_from);
> + expect_eq_pointer(hdr->hwndFrom, notify_test_data.hwnd_from);
> +
> + if (hdr->code != notify_test_data.ansi)
> + {
> + skip("Notification code mismatch, skipping lParam check\n");
> + return 0;
> + }
> + switch (hdr->code)
> + {
> + /* Toolbar */
> + /* No conversion for TBN_SAVE and TBN_RESTORE */
> + case TBN_SAVE:
> + {
> + NMTBSAVE *nmtbs = (NMTBSAVE *)hdr;
> + switch (notify_test_data.sub_test_id)
> + {
> + case 0:
> + expect_eq_text_w((WCHAR *)nmtbs->tbButton.iString, test_w);
> + break;
> + case 1:
> + nmtbs->tbButton.iString = (INT_PTR)test_a;
> + break;
> + }
> + break;
> + }
> + case TBN_RESTORE:
> + {
> + NMTBRESTORE *nmtbr = (NMTBRESTORE *)hdr;
> + switch (notify_test_data.sub_test_id)
> + {
> + case 0:
> + expect_eq_text_w((WCHAR *)nmtbr->tbButton.iString, test_w);
> + break;
> + case 1:
> + nmtbr->tbButton.iString = (INT_PTR)test_a;
> + break;
> + }
> + break;
> + }
> + case TBN_GETBUTTONINFOA:
> + {
> + NMTOOLBARA *nmtb = (NMTOOLBARA *)hdr;
> + wm_notify_text_handler(&nmtb->pszText, &nmtb->cchText);
> + break;
> + }
> + /* TBN_GETDISPINFOW doesn't get converted to TBN_GETDISPINFOA */
> + case TBN_GETDISPINFOW:
> + {
> + NMTBDISPINFOW *nmtbdi = (NMTBDISPINFOW *)hdr;
> + expect_eq_text_w(nmtbdi->pszText, test_w);
> + expect_eq_int(nmtbdi->cchText, ARRAY_SIZE(buffer));
> + memcpy(nmtbdi->pszText, test_a, sizeof(test_a));
> + break;
> + }
> + case TBN_GETINFOTIPA:
> + {
> + NMTBGETINFOTIPA *nmtbgit = (NMTBGETINFOTIPA *)hdr;
> + wm_notify_text_handler(&nmtbgit->pszText, &nmtbgit->cchTextMax);
> + break;
> + }
> + default:
> + ok(0, "Unexpected message 0x%08x\n", hdr->code);
> + }
> + notify_test_data.received = TRUE;
> + ok(!lstrcmpA(test_a, "test"), "test_a got modified\n");
> + ok(!lstrcmpW(test_w, test), "test_w got modified\n");
> + return 0;
> + }
> + case WM_NOTIFYFORMAT:
> + if (lParam == NF_QUERY) return NFR_ANSI;
> + break;
> + }
> + return DefWindowProcA(hwnd, message, wParam, lParam);
> +}
> +
> +static BOOL register_test_notify_class(void)
> +{
> + WNDCLASSA cls = {0};
> +
> + cls.lpfnWndProc = test_notify_proc;
> + cls.hInstance = GetModuleHandleA(NULL);
> + cls.lpszClassName = "Pager notify class";
> + return RegisterClassA(&cls);
> +}
> +
> +static void send_notify_(HWND pager, UINT unicode, UINT ansi, LPARAM lParam, BOOL code_change, BOOL received)
> +{
> + NMHDR *hdr = (NMHDR *)lParam;
> +
> + notify_test_data.unicode = unicode;
> + notify_test_data.id_from = 1;
> + notify_test_data.hwnd_from = child1_wnd;
> + notify_test_data.ansi = ansi;
> + notify_test_data.received = FALSE;
> +
> + hdr->code = unicode;
> + hdr->idFrom = 1;
> + hdr->hwndFrom = child1_wnd;
> +
> + SendMessageW(pager, WM_NOTIFY, hdr->idFrom, lParam);
> + expect_eq_int(notify_test_data.received, received);
> + expect_eq_int(hdr->code, code_change ? notify_test_data.ansi : notify_test_data.unicode);
> +}
> +
> +#define send_notify(a, b, c, d, e) send_notify_(pager, a, b, c, d, e)
> +
> +/* Send notify to test text field conversion. In parent proc wm_notify_text_handler() handles these messages */
> +static void test_wm_notify_text_helper_(HWND pager, void *ptr, size_t size, WCHAR **text, INT *textMax,
> + UINT code_unicode, UINT code_ansi, ConversionFlag flags)
> +{
> + notify_test_data.flags = flags;
> +
> + /* NULL text */
> + notify_test_data.sub_test_id = 1;
> + memset(ptr, 0, size);
> + *textMax = ARRAY_SIZE(buffer);
> + notify_test_data.text_size = *textMax;
> + send_notify(code_unicode, code_ansi, (LPARAM)ptr, TRUE, TRUE);
> + expect_null(*text);
> + expect_eq_int(*textMax, notify_test_data.text_size);
> +
> + /* Zero text max size */
> + notify_test_data.sub_test_id = 2;
> + memset(ptr, 0, size);
> + memset(buffer, 0, sizeof(buffer));
> + *text = buffer;
> + notify_test_data.text_size = *textMax;
> + send_notify(code_unicode, code_ansi, (LPARAM)ptr, TRUE, TRUE);
> + /* Got *text null on Windows <= Win7 */
> + ok(broken(!*text) || (!lstrlenW(*text) && *text == buffer), "Wrong *text\n");
> + expect_eq_int(*textMax, notify_test_data.text_size);
> +
> + /* Valid notification */
> + notify_test_data.sub_test_id = 3;
> + memset(ptr, 0, size);
> + memcpy(buffer, test_w, sizeof(test_w));
> + *text = buffer;
> + *textMax = ARRAY_SIZE(buffer);
> + notify_test_data.text_size = *textMax;
> + send_notify(code_unicode, code_ansi, (LPARAM)ptr, TRUE, TRUE);
> + if (!(flags & TO_ANSI) && flags & FROM_ANSI)
> + expect_eq_text_w(*text, t_w);
> + else
> + expect_eq_text_w(*text, test_w);
> + expect_eq_pointer(*text, buffer);
> + expect_eq_int(*textMax, notify_test_data.text_size);
> +
> + /* Valid notification. Parent write to buffer */
> + notify_test_data.sub_test_id = 4;
> + memset(ptr, 0, size);
> + memset(buffer, 0, sizeof(buffer));
> + *text = buffer;
> + *textMax = ARRAY_SIZE(buffer);
> + notify_test_data.text_size = *textMax;
> + send_notify(code_unicode, code_ansi, (LPARAM)ptr, TRUE, TRUE);
> + expect_eq_text_w(*text, test_w);
> + expect_eq_pointer(*text, buffer);
> + expect_eq_int(*textMax, notify_test_data.text_size);
> +
> + /* Valid notification. Parent set buffer size to one */
> + notify_test_data.sub_test_id = 5;
> + memset(ptr, 0, size);
> + memset(buffer, 0, sizeof(buffer));
> + *text = buffer;
> + *textMax = ARRAY_SIZE(buffer);
> + notify_test_data.text_size = *textMax;
> + send_notify(code_unicode, code_ansi, (LPARAM)ptr, TRUE, TRUE);
> + expect_eq_pointer(*text, buffer);
> + expect_eq_int(*textMax, 1);
> +
> + /* Valid notification. Parent replace buffer */
> + notify_test_data.sub_test_id = 6;
> + memset(ptr, 0, size);
> + memset(buffer, 0, sizeof(buffer));
> + *text = buffer;
> + *textMax = ARRAY_SIZE(buffer);
> + notify_test_data.text_size = *textMax;
> + send_notify(code_unicode, code_ansi, (LPARAM)ptr, TRUE, TRUE);
> + expect_eq_text_w(*text, test_w);
> + expect_eq_pointer(*text, buffer);
> + expect_eq_int(*textMax, notify_test_data.text_size);
> +
> + /* NULL text. Parent replace buffer */
> + notify_test_data.sub_test_id = 7;
> + memset(ptr, 0, size);
> + *textMax = ARRAY_SIZE(buffer);
> + notify_test_data.text_size = *textMax;
> + send_notify(code_unicode, code_ansi, (LPARAM)ptr, TRUE, TRUE);
> + expect_null(*text);
> + expect_eq_int(*textMax, notify_test_data.text_size);
> +
> + /* Valid notification. Parent replace buffer with a pointer pointing to a string larger than old buffer can store */
> + notify_test_data.sub_test_id = 8;
> + memset(ptr, 0, size);
> + memset(buffer, 0, sizeof(buffer));
> + memset(buffer2, 0, sizeof(buffer2));
> + *text = buffer;
> + *textMax = ARRAY_SIZE(buffer);
> + notify_test_data.text_size = *textMax;
> + send_notify(code_unicode, code_ansi, (LPARAM)ptr, TRUE, TRUE);
> + MultiByteToWideChar(CP_ACP, 0, large_a, -1, buffer2, ARRAY_SIZE(buffer2));
> + ok(!memcmp(*text, buffer2, sizeof(buffer2)), "Expect memory content to be the same\n");
> + expect_eq_pointer(*text, buffer);
> + expect_eq_int(*textMax, notify_test_data.text_size);
> +}
> +
> +#define test_wm_notify_text_helper(a, b, c, d, e, f, g) test_wm_notify_text_helper_(pager, a, b, c, d, e, f, g)
> +
> +static void test_wm_notify_toolbar(HWND pager)
> +{
> + NMTBRESTORE nmtbr;
> + NMTBSAVE nmtbs;
> + NMTOOLBARW nmtb;
> + NMTBDISPINFOW nmtbdi;
> + NMTBGETINFOTIPW nmtbgit;
> +
> + /* No conversion for TBN_SAVE */
> + notify_test_data.sub_test_id = 0;
> + memset(&nmtbs, 0, sizeof(nmtbs));
> + nmtbs.tbButton.iString = (INT_PTR)test_w;
> + send_notify(TBN_SAVE, TBN_SAVE, (LPARAM)&nmtbs, TRUE, TRUE);
> + expect_eq_text_w((WCHAR *)nmtbs.tbButton.iString, test_w);
> +
> + notify_test_data.sub_test_id = 1;
> + memset(&nmtbs, 0, sizeof(nmtbs));
> + nmtbs.tbButton.iString = (INT_PTR)test_w;
> + send_notify(TBN_SAVE, TBN_SAVE, (LPARAM)&nmtbs, TRUE, TRUE);
> + expect_eq_text_a((CHAR *)nmtbs.tbButton.iString, test_a);
> +
> + /* No conversion for TBN_RESTORE */
> + notify_test_data.sub_test_id = 0;
> + memset(&nmtbr, 0, sizeof(nmtbr));
> + nmtbr.tbButton.iString = (INT_PTR)test_w;
> + send_notify(TBN_RESTORE, TBN_RESTORE, (LPARAM)&nmtbr, TRUE, TRUE);
> + expect_eq_text_w((WCHAR *)nmtbr.tbButton.iString, test_w);
> +
> + notify_test_data.sub_test_id = 1;
> + memset(&nmtbr, 0, sizeof(nmtbr));
> + nmtbr.tbButton.iString = (INT_PTR)test_w;
> + send_notify(TBN_RESTORE, TBN_RESTORE, (LPARAM)&nmtbr, TRUE, TRUE);
> + expect_eq_text_a((CHAR *)nmtbr.tbButton.iString, test_a);
> +
> + /* TBN_GETDISPINFOW doesn't get unconverted */
> + memset(&nmtbdi, 0, sizeof(nmtbdi));
> + memcpy(buffer, test_w, sizeof(test_w));
> + nmtbdi.dwMask = TBNF_TEXT;
> + nmtbdi.pszText = buffer;
> + nmtbdi.cchText = ARRAY_SIZE(buffer);
> + notify_test_data.text_size = nmtbdi.cchText;
> + send_notify(TBN_GETDISPINFOW, TBN_GETDISPINFOW, (LPARAM)&nmtbdi, TRUE, TRUE);
> + expect_eq_text_a((CHAR *)nmtbdi.pszText, test_a);
> +
> + test_wm_notify_text_helper(&nmtb, sizeof(nmtb), &nmtb.pszText, &nmtb.cchText, TBN_GETBUTTONINFOW,
> + TBN_GETBUTTONINFOA, SET_NULL_EMPTY | TO_ANSI);
> + test_wm_notify_text_helper(&nmtbgit, sizeof(nmtbgit), &nmtbgit.pszText, &nmtbgit.cchTextMax, TBN_GETINFOTIPW,
> + TBN_GETINFOTIPA, FROM_ANSI);
> +}
> +
> +static void test_wm_notify(void)
> +{
> + static const CHAR *class = "Pager notify class";
> + HWND parent, pager;
> +
> + ok(register_test_notify_class(), "Register test class failed, error 0x%08x\n", GetLastError());
> +
> + parent = CreateWindowA(class, "parent", WS_OVERLAPPED, 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), 0);
> + ok(parent != NULL, "CreateWindow failed\n");
> + pager = CreateWindowA(WC_PAGESCROLLERA, "pager", WS_CHILD, 0, 0, 100, 100, parent, 0, GetModuleHandleA(0), 0);
> + ok(pager != NULL, "CreateWindow failed\n");
> + child1_wnd = CreateWindowA(class, "child", WS_CHILD, 0, 0, 100, 100, pager, (HMENU)1, GetModuleHandleA(0), 0);
> + ok(child1_wnd != NULL, "CreateWindow failed\n");
> + SendMessageW(pager, PGM_SETCHILD, 0, (LPARAM)child1_wnd);
> +
> + test_wm_notify_toolbar(pager);
> +
> + DestroyWindow(parent);
> + UnregisterClassA(class, GetModuleHandleA(NULL));
> +}
> +
> static void init_functions(void)
> {
> HMODULE mod = LoadLibraryA("comctl32.dll");
> @@ -447,6 +877,7 @@ START_TEST(pager)
>
> test_pager();
> test_wm_notifyformat();
> + test_wm_notify();
>
> DestroyWindow(parent_wnd);
> }
>
More information about the wine-devel
mailing list