From eb317039e081805dac62281f29cacdbaa9b6deb3 Mon Sep 17 00:00:00 2001 From: Zhiyi Zhang Date: Mon, 17 Sep 2018 23:27:00 +0800 Subject: [PATCH] comctl32/pager: Support comboboxex notification conversion. Signed-off-by: Zhiyi Zhang Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/comctl32/pager.c | 61 +++++++++++++++++++++++++++---- dlls/comctl32/tests/pager.c | 72 +++++++++++++++++++++++++++++++++++-- 2 files changed, 125 insertions(+), 8 deletions(-) diff --git a/dlls/comctl32/pager.c b/dlls/comctl32/pager.c index 6403b98e0d2..96a66806eeb 100644 --- a/dlls/comctl32/pager.c +++ b/dlls/comctl32/pager.c @@ -101,7 +101,11 @@ enum conversion_flags /* Convert ANSI text from parent back to Unicode for children */ CONVERT_RECEIVE = 0x02, /* Send empty text to parent if text is NULL. Original text pointer still remains NULL */ - SEND_EMPTY_IF_NULL = 0x04 + SEND_EMPTY_IF_NULL = 0x04, + /* Set text to null after parent received the notification if the required mask is not set before sending notification */ + SET_NULL_IF_NO_MASK = 0x08, + /* Zero out the text buffer before sending it to parent */ + ZERO_SEND = 0x10 }; static void @@ -1038,6 +1042,10 @@ static UINT PAGER_GetAnsiNtfCode(UINT code) { switch (code) { + /* ComboxBoxEx */ + case CBEN_DRAGBEGINW: return CBEN_DRAGBEGINA; + case CBEN_ENDEDITW: return CBEN_ENDEDITA; + case CBEN_GETDISPINFOW: return CBEN_GETDISPINFOA; /* Toolbar */ case TBN_GETBUTTONINFOW: return TBN_GETBUTTONINFOA; case TBN_GETINFOTIPW: return TBN_GETINFOTIPA; @@ -1060,7 +1068,8 @@ static BOOL PAGER_AdjustBuffer(PAGER_INFO *infoPtr, INT size) return TRUE; } -static LRESULT PAGER_SendConvertedNotify(PAGER_INFO *infoPtr, NMHDR *hdr, WCHAR **text, INT *textMax, DWORD flags) +static LRESULT PAGER_SendConvertedNotify(PAGER_INFO *infoPtr, NMHDR *hdr, UINT *mask, UINT requiredMask, WCHAR **text, + INT *textMax, DWORD flags) { CHAR *sendBuffer = NULL; CHAR *receiveBuffer; @@ -1074,14 +1083,21 @@ static LRESULT PAGER_SendConvertedNotify(PAGER_INFO *infoPtr, NMHDR *hdr, WCHAR hdr->code = PAGER_GetAnsiNtfCode(hdr->code); + if (mask && !(*mask & requiredMask)) + { + ret = SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); + if (flags & SET_NULL_IF_NO_MASK) oldText = NULL; + goto done; + } + if (oldTextMax < 0) goto done; - if ((*text && (flags & CONVERT_SEND)) || (!*text && (flags & SEND_EMPTY_IF_NULL))) + if ((*text && flags & (CONVERT_SEND | ZERO_SEND)) || (!*text && flags & SEND_EMPTY_IF_NULL)) { bufferSize = textMax ? *textMax : lstrlenW(*text) + 1; sendBuffer = heap_alloc_zero(bufferSize); if (!sendBuffer) goto done; - WideCharToMultiByte(CP_ACP, 0, *text, -1, sendBuffer, bufferSize, NULL, FALSE); + if (!(flags & ZERO_SEND)) WideCharToMultiByte(CP_ACP, 0, *text, -1, sendBuffer, bufferSize, NULL, FALSE); *text = (WCHAR *)sendBuffer; } @@ -1117,17 +1133,50 @@ static LRESULT PAGER_Notify(PAGER_INFO *infoPtr, NMHDR *hdr) switch (hdr->code) { + /* ComboBoxEx */ + case CBEN_GETDISPINFOW: + { + NMCOMBOBOXEXW *nmcbe = (NMCOMBOBOXEXW *)hdr; + return PAGER_SendConvertedNotify(infoPtr, hdr, &nmcbe->ceItem.mask, CBEIF_TEXT, &nmcbe->ceItem.pszText, + &nmcbe->ceItem.cchTextMax, ZERO_SEND | SET_NULL_IF_NO_MASK | CONVERT_RECEIVE); + } + case CBEN_DRAGBEGINW: + { + NMCBEDRAGBEGINW *nmdbW = (NMCBEDRAGBEGINW *)hdr; + NMCBEDRAGBEGINA nmdbA = {{0}}; + nmdbA.hdr.code = PAGER_GetAnsiNtfCode(nmdbW->hdr.code); + nmdbA.hdr.hwndFrom = nmdbW->hdr.hwndFrom; + nmdbA.hdr.idFrom = nmdbW->hdr.idFrom; + nmdbA.iItemid = nmdbW->iItemid; + WideCharToMultiByte(CP_ACP, 0, nmdbW->szText, ARRAY_SIZE(nmdbW->szText), nmdbA.szText, ARRAY_SIZE(nmdbA.szText), + NULL, FALSE); + return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)&nmdbA); + } + case CBEN_ENDEDITW: + { + NMCBEENDEDITW *nmedW = (NMCBEENDEDITW *)hdr; + NMCBEENDEDITA nmedA = {{0}}; + nmedA.hdr.code = PAGER_GetAnsiNtfCode(nmedW->hdr.code); + nmedA.hdr.hwndFrom = nmedW->hdr.hwndFrom; + nmedA.hdr.idFrom = nmedW->hdr.idFrom; + nmedA.fChanged = nmedW->fChanged; + nmedA.iNewSelection = nmedW->iNewSelection; + nmedA.iWhy = nmedW->iWhy; + WideCharToMultiByte(CP_ACP, 0, nmedW->szText, ARRAY_SIZE(nmedW->szText), nmedA.szText, ARRAY_SIZE(nmedA.szText), + NULL, FALSE); + return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)&nmedA); + } /* Toolbar */ case TBN_GETBUTTONINFOW: { NMTOOLBARW *nmtb = (NMTOOLBARW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, &nmtb->pszText, &nmtb->cchText, + return PAGER_SendConvertedNotify(infoPtr, hdr, NULL, 0, &nmtb->pszText, &nmtb->cchText, SEND_EMPTY_IF_NULL | CONVERT_SEND | CONVERT_RECEIVE); } case TBN_GETINFOTIPW: { NMTBGETINFOTIPW *nmtbgit = (NMTBGETINFOTIPW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, &nmtbgit->pszText, &nmtbgit->cchTextMax, CONVERT_RECEIVE); + return PAGER_SendConvertedNotify(infoPtr, hdr, NULL, 0, &nmtbgit->pszText, &nmtbgit->cchTextMax, CONVERT_RECEIVE); } /* Tooltip */ case TTN_GETDISPINFOW: diff --git a/dlls/comctl32/tests/pager.c b/dlls/comctl32/tests/pager.c index cd7b637b910..b689549aa57 100644 --- a/dlls/comctl32/tests/pager.c +++ b/dlls/comctl32/tests/pager.c @@ -65,7 +65,9 @@ enum test_conversion_flags CONVERT_RECEIVE = 0x04, DONT_CONVERT_RECEIVE = 0x08, SEND_EMPTY_IF_NULL = 0x10, - DONT_SEND_EMPTY_IF_NULL = 0x20 + DONT_SEND_EMPTY_IF_NULL = 0x20, + SET_NULL_IF_NO_MASK = 0x40, + ZERO_SEND = 0x80 }; static struct notify_test_info @@ -578,7 +580,10 @@ static void notify_generic_text_handler(CHAR **text, INT *text_max) { send_data = (notify_test_info.test_id == CONVERT_SEND ? test_convert_send_data : test_dont_convert_send_data) + notify_test_info.sub_test_id; - if (notify_test_info.flags & CONVERT_SEND) + if (notify_test_info.flags & ZERO_SEND) + ok(!lstrcmpA(*text, empty_a), "Code 0x%08x test 0x%08x sub test %d expect empty text, got %s\n", + notify_test_info.unicode, notify_test_info.test_id, notify_test_info.sub_test_id, *text); + else if (notify_test_info.flags & CONVERT_SEND) ok(!lstrcmpA(send_data->expect_text, *text), "Code 0x%08x test 0x%08x sub test %d expect %s, got %s\n", notify_test_info.unicode, notify_test_info.test_id, notify_test_info.sub_test_id, (CHAR *)send_data->expect_text, *text); @@ -659,6 +664,32 @@ static LRESULT WINAPI test_notify_proc(HWND hwnd, UINT message, WPARAM wParam, L } switch (hdr->code) { + /* ComboBoxEx */ + case CBEN_INSERTITEM: + case CBEN_DELETEITEM: + { + NMCOMBOBOXEXW *nmcbe = (NMCOMBOBOXEXW *)hdr; + notify_generic_text_handler((CHAR **)&nmcbe->ceItem.pszText, NULL); + break; + } + case CBEN_DRAGBEGINA: + { + NMCBEDRAGBEGINA *nmcbedb = (NMCBEDRAGBEGINA *)hdr; + ok(!lstrcmpA(nmcbedb->szText, test_a), "Expect %s, got %s\n", nmcbedb->szText, test_a); + break; + } + case CBEN_ENDEDITA: + { + NMCBEENDEDITA *nmcbeed = (NMCBEENDEDITA *)hdr; + ok(!lstrcmpA(nmcbeed->szText, test_a), "Expect %s, got %s\n", nmcbeed->szText, test_a); + break; + } + case CBEN_GETDISPINFOA: + { + NMCOMBOBOXEXA *nmcbe = (NMCOMBOBOXEXA *)hdr; + notify_generic_text_handler(&nmcbe->ceItem.pszText, &nmcbe->ceItem.cchTextMax); + break; + } /* Toolbar */ case TBN_SAVE: { @@ -836,6 +867,33 @@ static void test_notify_generic_text_helper(HWND pager, const struct generic_tex else notify_test_info.test_id = DONT_SEND_EMPTY_IF_NULL; send_notify(pager, para->code_unicode, para->code_ansi, (LPARAM)para->ptr, TRUE); + + notify_test_info.test_id = SET_NULL_IF_NO_MASK; + memset(para->ptr, 0, para->size); + memset(buffer, 0, sizeof(buffer)); + *para->text = buffer; + if (para->text_max) *para->text_max = ARRAY_SIZE(buffer); + send_notify(pager, para->code_unicode, para->code_ansi, (LPARAM)para->ptr, TRUE); + if(para->flags & SET_NULL_IF_NO_MASK) + ok(!*para->text, "Expect null text\n"); +} + +static void test_wm_notify_comboboxex(HWND pager) +{ + static NMCBEDRAGBEGINW nmcbedb; + static NMCBEENDEDITW nmcbeed; + + /* CBEN_DRAGBEGIN */ + memset(&nmcbedb, 0, sizeof(nmcbedb)); + memcpy(nmcbedb.szText, test_w, sizeof(test_w)); + send_notify(pager, CBEN_DRAGBEGINW, CBEN_DRAGBEGINA, (LPARAM)&nmcbedb, FALSE); + ok(!lstrcmpW(nmcbedb.szText, test_w), "Expect %s, got %s\n", wine_dbgstr_w(test_w), wine_dbgstr_w(nmcbedb.szText)); + + /* CBEN_ENDEDIT */ + memset(&nmcbeed, 0, sizeof(nmcbeed)); + memcpy(nmcbeed.szText, test_w, sizeof(test_w)); + send_notify(pager, CBEN_ENDEDITW, CBEN_ENDEDITA, (LPARAM)&nmcbeed, FALSE); + ok(!lstrcmpW(nmcbeed.szText, test_w), "Expect %s, got %s\n", wine_dbgstr_w(test_w), wine_dbgstr_w(nmcbeed.szText)); } static void test_wm_notify_tooltip(HWND pager) @@ -880,6 +938,8 @@ static void test_wm_notify(void) { static const CHAR *class = "Pager notify class"; HWND parent, pager; + /* Combo Box Ex */ + static NMCOMBOBOXEXW nmcbe; /* Tool Bar */ static NMTBRESTORE nmtbr; static NMTBSAVE nmtbs; @@ -888,6 +948,13 @@ static void test_wm_notify(void) static NMTBGETINFOTIPW nmtbgit; static const struct generic_text_helper_para paras[] = { + /* Combo Box Ex */ + {&nmcbe, sizeof(nmcbe), &nmcbe.ceItem.mask, CBEIF_TEXT, &nmcbe.ceItem.pszText, &nmcbe.ceItem.cchTextMax, + CBEN_INSERTITEM, CBEN_INSERTITEM, DONT_CONVERT_SEND | DONT_CONVERT_RECEIVE}, + {&nmcbe, sizeof(nmcbe), &nmcbe.ceItem.mask, CBEIF_TEXT, &nmcbe.ceItem.pszText, &nmcbe.ceItem.cchTextMax, + CBEN_DELETEITEM, CBEN_DELETEITEM, DONT_CONVERT_SEND | DONT_CONVERT_RECEIVE}, + {&nmcbe, sizeof(nmcbe), &nmcbe.ceItem.mask, CBEIF_TEXT, &nmcbe.ceItem.pszText, &nmcbe.ceItem.cchTextMax, + CBEN_GETDISPINFOW, CBEN_GETDISPINFOA, ZERO_SEND | SET_NULL_IF_NO_MASK | DONT_CONVERT_SEND | CONVERT_RECEIVE}, /* Tool Bar */ {&nmtbs, sizeof(nmtbs), NULL, 0, (WCHAR **)&nmtbs.tbButton.iString, NULL, TBN_SAVE, TBN_SAVE, DONT_CONVERT_SEND | DONT_CONVERT_RECEIVE}, @@ -916,6 +983,7 @@ static void test_wm_notify(void) test_notify_generic_text_helper(pager, paras + i); /* Tests for those that can't be covered by generic text test helper */ + test_wm_notify_comboboxex(pager); test_wm_notify_tooltip(pager); DestroyWindow(parent);