How to handle multiple WM_NOTIFY cases ?

Pages: 12
I have 2 List view controls and I need to send the VM_NOTIFY for both of them..
The program compile and run but I see some issues if I toggle between them.
One of them shows correctly and the other shows only the first column and the second shows few words most of the rows are empty.



LRESULT NotifyHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

This is the second one:

LRESULT NotifyHandlerXP(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

How to handle in the MainWndProc?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
   static HWND hWndListView;

   switch(msg)
     {
    case WM_NOTIFY:
        {
          return (NotifyHandler(hWnd, msg, wp, lp));
          return (NotifyHandlerXP(hWnd, msg, wp, lp));
          break;
        }
     default:
        return DefWindowProcW(hWnd, msg, wp, lp);
     }
   return 0;
}


HWND CreateListView(HWND hWndParent)
hWndListView = CreateListView(hWnd);

HWND CreateListViewXP(HWND hWndParentXP)
hWndListView = CreateListViewXP(hWnd);

These are the 2 handlers for the both List View controls.

I only thought of an IF statement.. I'm working on it right now.
Last edited on
Line 10 will never be executed
Yes Thomas .. I wrote it like that just to make you understand. What I meant

The WM_NOTIFY message is sent from a control, one of the ListViews, to its parent Window. The parent then needs to decide what action to take. In the case where the ListView needs to be updated I need to call the relevant handler for that ListView, not for both of them. The information in the WM_NOTIFY message tells which control raised the notify event.

But how do I do that.. that is my question.. if any part of the code needed.. I can put it on.. ?
If I call in WM_NOTIFY the second one like this

1
2
3
4
5
case WM_NOTIFY:
        {
          return (NotifyHandlerXP(hWnd, msg, wp, lp));
          break;
        }


this will show me only the second control and the first list view control will show me only part of the list, well most of the rows empty..
Last edited on
You could try something like
1
2
3
4
5
6
7
8
9
10
11
12
13
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
   static HWND hWndListView;

   switch(msg)
     {
    case WM_NOTIFY:
        {
          LRESULT r1 = NotifyHandler(hWnd, msg, wp, lp);
          if ( r1 == ? ) {
             return NotifyHandlerXP(hWnd, msg, wp, lp);
          }
          return r1; // the error from the first notify 

I'll leave you to figure out what to replace the ? with, as the measure of success for the first notify call.
I don't think that the result of NotifyHandler(...)/NotifyHandlerXP(...) is actually relevant for the MainWndProc(...). So I would suggest to not return them at all.
I just put them like this:

1
2
3
4
5
6
case WM_NOTIFY:
        {
         (NotifyHandlerXP(hWnd, msg, wp, lp));
         (NotifyHandler(hWnd, msg, wp, lp));
          break;
        }


When I ran the code .. I get no errors.. and no warnings .
the problem is with the second column of the NotifyHandlerXP

I just add one more column and update them from the case below.. and I jump the second case where the second column is read.. and seems all is fine ,, the 3rd and 4th columns shows exactly what would 2nd and 3rd has to show... and the NotifyHandler just show fine..
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
HWND CreateListViewXP(HWND hWndParentXP)
{
    HWND hWndListXP;
    int index;
    LV_COLUMN lvC;
    char szText[MAX_PATH];
    LV_ITEM lvI;
    int iSubItem;

    InitCommonControls();

    hWndListXP = CreateWindowEx(0L, WC_LISTVIEW, NULL, WS_VISIBLE | WS_CHILD | WS_BORDER |
                           LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER, 0, 32, 500, 448,
                           hWndParentXP, (HMENU)ID_LISTVIEW, hInst, NULL);

    ListView_SetExtendedListViewStyle(hWndListXP, LVS_EX_FULLROWSELECT | LVM_ENSUREVISIBLE);

    if(hWndListXP == NULL)
        return NULL;

    lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
    lvC.fmt = LVCFMT_RIGHT;
    lvC.cx = 140;
    lvC.pszText = szText;

    for(index = 0; index <= NUM_COLUMNSXP; index++)
    {
        lvC.iSubItem = index;
        LoadString(hInst, IDS_CHARLEVEL + index, szText, sizeof(szText));
        if(ListView_InsertColumn(hWndListXP, index, &lvC) == -1)
            return NULL;
    }

    lvI.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
    lvI.state = 0;
    lvI.stateMask = 0;

    for(index = 0; index < NUM_ITEMSXP; index++)
    {
        lvI.iItem = index;
        lvI.iSubItem = 0;
        lvI.pszText = LPSTR_TEXTCALLBACK;
        lvI.cchTextMax = MAX_ITEMLEN;
        lvI.lParam = (LPARAM)&argsXpInfo[index];

        if(ListView_InsertItem(hWndListXP, &lvI) == -1)
            return NULL;

        for(iSubItem = 1; iSubItem < NUM_COLUMNSXP; iSubItem++)
        {
            ListView_SetItemText(hWndListXP, index, iSubItem, LPSTR_TEXTCALLBACK);
        }
    }
    return(hWndListXP);
}
LRESULT NotifyHandlerXP(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    LV_DISPINFOW *pLvdi = (LV_DISPINFOW *)lParam;
    XPINFO *pXP = (XPINFO *)(pLvdi->item.lParam);

    if(wParam != ID_LISTVIEW)
        return 0L;

    switch(pLvdi->hdr.code)
    {
    case LVN_GETDISPINFOW:
        switch(pLvdi->item.iSubItem)
        {
        case 0:
            pLvdi->item.pszText = pXP->szCharLevel;
            break;
        case 2:
            pLvdi->item.pszText = pXP->szXpNedded;
            break;
        case 3:
            pLvdi->item.pszText = pXP->szXpNeddedNextLvl;
            break;
        default:
            break;
        }
        default:
            break;
    }
    return 0L;
}
In case LVN_GETDISPINFOW: when I switch the pLvdi->item.isubitem the case 2 and 3 has to be 1 and 2... and now shows me correctly but the second column is now empty. that would be case 1
In meantime this other view list working just fine

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
HWND CreateListView(HWND hWndParent)
{
	HWND hWndList;
	int index;
	LV_COLUMN lvC;
	char szText[MAX_PATH];
	LV_ITEM lvI;
	int iSubItem;

	InitCommonControls();

	hWndList = CreateWindowEx(0L, WC_LISTVIEW, NULL, WS_VISIBLE | WS_CHILD | WS_BORDER |
                           LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER, 0, 32, 795, 448,
                            hWndParent, (HMENU)ID_LISTVIEW, hInst, NULL);

    ListView_SetExtendedListViewStyle(hWndList, LVS_EX_FULLROWSELECT | LVM_ENSUREVISIBLE);

	if (hWndList == NULL)
		return NULL;

	lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
	lvC.fmt = LVCFMT_LEFT;
	lvC.cx = 250;
	lvC.pszText = szText;

	for (index = 0; index <= NUM_COLUMNS; index++)
	{
		lvC.iSubItem = index;
		LoadString(hInst, IDS_SYMBOLS + index, szText, sizeof(szText));
		if (ListView_InsertColumn(hWndList, index, &lvC) == -1)
			return NULL;
	}

	lvI.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
	lvI.state = 0;
	lvI.stateMask = 0;

	for (index = 0; index < NUM_ITEMS; index++)
	{
		lvI.iItem = index;
		lvI.iSubItem = 0;
		lvI.pszText = LPSTR_TEXTCALLBACK;
		lvI.cchTextMax = MAX_ITEMLEN;
		lvI.lParam = (LPARAM)&argsAbrInfo[index];

		if (ListView_InsertItem(hWndList, &lvI) == -1)
			return NULL;

		for (iSubItem = 1; iSubItem < NUM_COLUMNS; iSubItem++)
		{
			ListView_SetItemText(hWndList, index, iSubItem, LPSTR_TEXTCALLBACK);
		}
	}
	return (hWndList);
}
LRESULT NotifyHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	LV_DISPINFOW *pLvdi = (LV_DISPINFOW *)lParam;
	ABRINFO *pAbr = (ABRINFO *)(pLvdi->item.lParam);

	if (wParam != ID_LISTVIEW)
		return 0L;

	switch(pLvdi->hdr.code)
	{
		case LVN_GETDISPINFOW:
			switch (pLvdi->item.iSubItem)
			{
				case 0:
					pLvdi->item.pszText = pAbr->szSymbol;
					break;
				case 1:
					pLvdi->item.pszText = pAbr->szDescription;
					break;
				default:
					break;
			}
			break;
		default:
			break;
	}
	return 0L;
}
and here I only have 2 columns.. and the cases are 0 and 1..
I can tell ya that they use the same ID_LISTWIEW 1000 that I have define it in the resource.h
This is the resource.h only for the list view control

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// constants
#define ID_LISTVIEW         1000
#define NUM_ITEMS           150
#define NUM_COLUMNS         1
#define MAX_ITEMLEN         64
#define MAX_SYMBOLS         19
#define MAX_DESCRIPTION     117
#define MAX_CHARLEVEL       3
#define MAX_XPNEEDED        11
#define MAX_XPNEEDEDNEXTLEVEL   10
#define NUM_ITEMSXP         99
#define NUM_COLUMNSXP       2


// stringtable defines
#define IDS_SYMBOLS         1
#define IDS_DESCRIPTION     2
#define IDS_CHARLEVEL       3
#define IDS_XPNEEDED        4
#define IDS_NEXTLVL         5

//Functions from resources.cpp
void LoadFileInResource(HWND hWnd);
HWND CreateListView(HWND hWndParent);
LRESULT NotifyHandler(HWND, UINT, WPARAM, LPARAM);
HWND CreateListViewXP(HWND hWndParentXP);
LRESULT NotifyHandlerXP(HWND, UINT, WPARAM, LPARAM);

// structures
typedef struct tagABRINFO
{
    WCHAR szSymbol[MAX_SYMBOLS];
    WCHAR szDescription[MAX_DESCRIPTION];
} ABRINFO;

typedef struct tagXPINFO
{
    WCHAR szCharLevel[MAX_CHARLEVEL];
    WCHAR szXpNedded[MAX_XPNEEDED];
    WCHAR szXpNeddedNextLvl[MAX_XPNEEDEDNEXTLEVEL];
} XPINFO;
Last edited on
0 is counted ..where I have NUM_COLUMNS 1 means are 2 columns (case 0 and 1)
same NUM_COLUMNSXP 2 (3 columns)
The resource.rc file for the 2 list view controls looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/////////////////////////////////////////////////////////////////////////////
//
// String Table 1
//

STRINGTABLE DISCARDABLE
BEGIN
    IDS_SYMBOLS             "Symbols"
    IDS_DESCRIPTION         "Description"
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table 2
//

STRINGTABLE DISCARDABLE
BEGIN
    IDS_CHARLEVEL           "Character Level"
    IDS_XPNEEDED            "XP Needed"
    IDS_NEXTLVL             "XP Needed for next level"
END
///////////////////////////////////////////////////////////////////////////// 
I was thinking for a solution .. What if I use the same NotifyHandler for the both list view controls.. ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// global array of Abbreviations
ABRINFO argsAbrInfo[] =
{
	{L"", L""},
	{L"", L""},
	{L"", L""},
	{L"", L""},
	{L"", L""},
	{L"", L""},
	{L"", L""},
	{L"", L""},
	{L"", L""},
	{L"", L""},
	{L"", L""},
	{L"", L""},
	{L"", L""},
	.
	.
	.
	.down
	. to 150
};
// global array of XP
XPINFO argsXpInfo[] =
{
	{L"", L"", L""},
	{L"", L"", L""},
	{L"", L"", L""},
	{L"", L"", L""},
	{L"", L"", L""},
	{L"", L"", L""},
	{L"", L"", L""},
	{L"", L"", L""},
	{L"", L"", L""},
	{L"", L"", L""},
	{L"", L"", L""},
	{L"", L"", L""},
	{L"", L"", L""},
	.
	.
	.
	.down
	. to 99
};


You can copy, paste and put whatever or make them smaller and try the code..
If you make them smaller be sure to modify the
#define NUM_ITEMS 150
and hte
#define NUM_ITEMSXP 99
in the resource.h
where I have NUM_COLUMNS 1 means are 2 columns (case 0 and 1)
Do yourself a favor and use the correct num which is 2. case 0 and 1 are the indexes of the colums not the size.

See this:
1
2
3
4
		for (iSubItem = 1; iSubItem < NUM_COLUMNS; iSubItem++) // Note: <
		{
			ListView_SetItemText(hWndList, index, iSubItem, LPSTR_TEXTCALLBACK);
		}
Due to the < you will not set the last item. So either use <= or set NUM_COLUMNS -> 2
Right I got this one.. and is true. . But I did mention
"case 0 and 1 are the indexes of the colums ... and I didn't mention they are SIZE of the columns :)
Last edited on
Pages: 12