comctl32/listview: Always send LVN_ITEMCHANGING notification even if nothing changed.
This commit is contained in:
parent
c1d1d74614
commit
7773d6b095
|
@ -4233,20 +4233,19 @@ static BOOL set_main_item(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL
|
||||||
if ((lpLVItem->mask & LVIF_TEXT) && textcmpWT(lpItem->hdr.pszText, lpLVItem->pszText, isW))
|
if ((lpLVItem->mask & LVIF_TEXT) && textcmpWT(lpItem->hdr.pszText, lpLVItem->pszText, isW))
|
||||||
uChanged |= LVIF_TEXT;
|
uChanged |= LVIF_TEXT;
|
||||||
|
|
||||||
TRACE("uChanged=0x%x\n", uChanged);
|
TRACE("change mask=0x%x\n", uChanged);
|
||||||
if (!uChanged) return TRUE;
|
|
||||||
*bChanged = TRUE;
|
|
||||||
|
|
||||||
ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
|
memset(&nmlv, 0, sizeof(NMLISTVIEW));
|
||||||
nmlv.iItem = lpLVItem->iItem;
|
nmlv.iItem = lpLVItem->iItem;
|
||||||
nmlv.uNewState = (item.state & ~stateMask) | (lpLVItem->state & stateMask);
|
nmlv.uNewState = (item.state & ~stateMask) | (lpLVItem->state & stateMask);
|
||||||
nmlv.uOldState = item.state;
|
nmlv.uOldState = item.state;
|
||||||
nmlv.uChanged = uChanged;
|
nmlv.uChanged = uChanged ? uChanged : lpLVItem->mask;
|
||||||
nmlv.lParam = item.lParam;
|
nmlv.lParam = item.lParam;
|
||||||
|
|
||||||
/* send LVN_ITEMCHANGING notification, if the item is not being inserted */
|
/* Send LVN_ITEMCHANGING notification, if the item is not being inserted
|
||||||
/* and we are _NOT_ virtual (LVS_OWNERDATA), and change notifications */
|
and we are _NOT_ virtual (LVS_OWNERDATA), and change notifications
|
||||||
/* are enabled */
|
are enabled. Even nothing really changed we still need to send this,
|
||||||
|
in this case uChanged mask is just set to passed item mask. */
|
||||||
if(lpItem && !isNew && infoPtr->bDoChangeNotify)
|
if(lpItem && !isNew && infoPtr->bDoChangeNotify)
|
||||||
{
|
{
|
||||||
HWND hwndSelf = infoPtr->hwndSelf;
|
HWND hwndSelf = infoPtr->hwndSelf;
|
||||||
|
@ -4257,6 +4256,9 @@ static BOOL set_main_item(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!uChanged) return TRUE;
|
||||||
|
*bChanged = TRUE;
|
||||||
|
|
||||||
/* copy information */
|
/* copy information */
|
||||||
if (lpLVItem->mask & LVIF_TEXT)
|
if (lpLVItem->mask & LVIF_TEXT)
|
||||||
textsetptrT(&lpItem->hdr.pszText, lpLVItem->pszText, isW);
|
textsetptrT(&lpItem->hdr.pszText, lpLVItem->pszText, isW);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright 2006 Mike McCormack for CodeWeavers
|
* Copyright 2006 Mike McCormack for CodeWeavers
|
||||||
* Copyright 2007 George Gov
|
* Copyright 2007 George Gov
|
||||||
* Copyright 2009-2012 Nikolay Sivov
|
* Copyright 2009-2013 Nikolay Sivov
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -52,6 +52,8 @@ static BOOL blockEdit;
|
||||||
static BOOL g_block_hover;
|
static BOOL g_block_hover;
|
||||||
/* notification data for LVN_ITEMCHANGED */
|
/* notification data for LVN_ITEMCHANGED */
|
||||||
static NMLISTVIEW g_nmlistview;
|
static NMLISTVIEW g_nmlistview;
|
||||||
|
/* notification data for LVN_ITEMCHANGING */
|
||||||
|
static NMLISTVIEW g_nmlistview_changing;
|
||||||
/* format reported to control:
|
/* format reported to control:
|
||||||
-1 falls to defproc, anything else returned */
|
-1 falls to defproc, anything else returned */
|
||||||
static INT notifyFormat;
|
static INT notifyFormat;
|
||||||
|
@ -209,7 +211,7 @@ static const struct message ownerdata_deselect_all_parent_seq[] = {
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct message select_all_parent_seq[] = {
|
static const struct message change_all_parent_seq[] = {
|
||||||
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
|
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
|
||||||
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
|
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
|
||||||
|
|
||||||
|
@ -227,6 +229,15 @@ static const struct message select_all_parent_seq[] = {
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct message changing_all_parent_seq[] = {
|
||||||
|
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
|
||||||
|
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
|
||||||
|
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
|
||||||
|
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
|
||||||
|
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
static const struct message textcallback_set_again_parent_seq[] = {
|
static const struct message textcallback_set_again_parent_seq[] = {
|
||||||
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
|
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
|
||||||
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
|
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
|
||||||
|
@ -430,6 +441,12 @@ static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LP
|
||||||
"BEGIN" : "END", pScroll->dx, pScroll->dy);
|
"BEGIN" : "END", pScroll->dx, pScroll->dy);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case LVN_ITEMCHANGING:
|
||||||
|
{
|
||||||
|
NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
|
||||||
|
g_nmlistview_changing = *nmlv;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case LVN_ITEMCHANGED:
|
case LVN_ITEMCHANGED:
|
||||||
{
|
{
|
||||||
NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
|
NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
|
||||||
|
@ -2169,9 +2186,8 @@ static void test_multiselect(void)
|
||||||
item.stateMask = LVIS_SELECTED;
|
item.stateMask = LVIS_SELECTED;
|
||||||
SendMessageA(hwnd, LVM_SETITEMSTATE, task.initPos == -1 ? item_count-1 : task.initPos, (LPARAM)&item);
|
SendMessageA(hwnd, LVM_SETITEMSTATE, task.initPos == -1 ? item_count-1 : task.initPos, (LPARAM)&item);
|
||||||
|
|
||||||
selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
|
selected_count = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
|
||||||
|
ok(selected_count == 1, "expected 1, got %d\n", selected_count);
|
||||||
ok(selected_count == 1, "There should be only one selected item at the beginning (is %d)\n",selected_count);
|
|
||||||
|
|
||||||
/* Set SHIFT key pressed */
|
/* Set SHIFT key pressed */
|
||||||
GetKeyboardState(kstate);
|
GetKeyboardState(kstate);
|
||||||
|
@ -2220,16 +2236,62 @@ static void test_multiselect(void)
|
||||||
r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
|
r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
|
||||||
expect(TRUE, r);
|
expect(TRUE, r);
|
||||||
|
|
||||||
ok_sequence(sequences, PARENT_SEQ_INDEX, select_all_parent_seq,
|
ok_sequence(sequences, PARENT_SEQ_INDEX, change_all_parent_seq,
|
||||||
"select all notification", FALSE);
|
"select all notification", FALSE);
|
||||||
|
|
||||||
|
/* select all again (all selected already) */
|
||||||
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||||
|
|
||||||
|
memset(&g_nmlistview_changing, 0xcc, sizeof(g_nmlistview_changing));
|
||||||
|
|
||||||
|
item.stateMask = LVIS_SELECTED;
|
||||||
|
item.state = LVIS_SELECTED;
|
||||||
|
r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
|
||||||
|
expect(TRUE, r);
|
||||||
|
|
||||||
|
ok(g_nmlistview_changing.uNewState == LVIS_SELECTED, "got 0x%x\n", g_nmlistview_changing.uNewState);
|
||||||
|
ok(g_nmlistview_changing.uOldState == LVIS_SELECTED, "got 0x%x\n", g_nmlistview_changing.uOldState);
|
||||||
|
ok(g_nmlistview_changing.uChanged == LVIF_STATE, "got 0x%x\n", g_nmlistview_changing.uChanged);
|
||||||
|
|
||||||
|
ok_sequence(sequences, PARENT_SEQ_INDEX, changing_all_parent_seq,
|
||||||
|
"select all notification 2", FALSE);
|
||||||
|
|
||||||
/* deselect all items */
|
/* deselect all items */
|
||||||
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||||
|
|
||||||
item.state = 0;
|
item.state = 0;
|
||||||
item.stateMask = LVIS_SELECTED;
|
item.stateMask = LVIS_SELECTED;
|
||||||
SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
|
SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
|
||||||
|
|
||||||
|
ok_sequence(sequences, PARENT_SEQ_INDEX, change_all_parent_seq,
|
||||||
|
"deselect all notification", FALSE);
|
||||||
|
|
||||||
|
/* deselect all items again */
|
||||||
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||||
|
item.state = 0;
|
||||||
|
item.stateMask = LVIS_SELECTED;
|
||||||
|
SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
|
||||||
|
ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "deselect all notification 2", TRUE);
|
||||||
|
|
||||||
|
/* any non-zero state value does the same */
|
||||||
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||||
|
|
||||||
|
memset(&g_nmlistview_changing, 0xcc, sizeof(g_nmlistview_changing));
|
||||||
|
|
||||||
|
item.stateMask = LVIS_SELECTED;
|
||||||
|
item.state = LVIS_CUT;
|
||||||
|
r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
|
||||||
|
expect(TRUE, r);
|
||||||
|
|
||||||
|
ok(g_nmlistview_changing.uNewState == 0, "got 0x%x\n", g_nmlistview_changing.uNewState);
|
||||||
|
ok(g_nmlistview_changing.uOldState == 0, "got 0x%x\n", g_nmlistview_changing.uOldState);
|
||||||
|
ok(g_nmlistview_changing.uChanged == LVIF_STATE, "got 0x%x\n", g_nmlistview_changing.uChanged);
|
||||||
|
|
||||||
|
ok_sequence(sequences, PARENT_SEQ_INDEX, changing_all_parent_seq,
|
||||||
|
"set state all notification 3", FALSE);
|
||||||
|
|
||||||
SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
|
SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
|
||||||
for (i=0;i<3;i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
item.state = LVIS_SELECTED;
|
item.state = LVIS_SELECTED;
|
||||||
item.stateMask = LVIS_SELECTED;
|
item.stateMask = LVIS_SELECTED;
|
||||||
SendMessageA(hwnd, LVM_SETITEMSTATE, i, (LPARAM)&item);
|
SendMessageA(hwnd, LVM_SETITEMSTATE, i, (LPARAM)&item);
|
||||||
|
@ -5470,6 +5532,7 @@ START_TEST(listview)
|
||||||
test_LVS_EX_TRANSPARENTBKGND();
|
test_LVS_EX_TRANSPARENTBKGND();
|
||||||
test_LVS_EX_HEADERINALLVIEWS();
|
test_LVS_EX_HEADERINALLVIEWS();
|
||||||
test_deleteitem();
|
test_deleteitem();
|
||||||
|
test_multiselect();
|
||||||
|
|
||||||
unload_v6_module(ctx_cookie, hCtx);
|
unload_v6_module(ctx_cookie, hCtx);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue