Problem with select row in list control
-
I have a list control which is declared like this
CListCtrl m_list1;
I set the background color to black, and the text color to white. Whenever I select a row, I just want to draw a rectangular wrap to the row. So I implement the item change method, like this:
void AlarmCompreMsgDig::OnLvnItemchangedList1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast(pNMHDR);
m_lstAlarmCompreMsg.SetItemState(-1, 0, LVIS_SELECTED); // first, diselect the rowint rowIndex = pNMLV->iItem; CRect rec; // boundary rectangular that wrap the row m\_lstAlarmCompreMsg.GetItemRect(rowIndex, rec, LVIR\_BOUNDS); // a little adjust the rectangular rec.top -= 2; rec.bottom += 2; CDC\* cdc = m\_lstAlarmCompreMsg.GetDC(); CPen aPen; aPen.CreatePen(PS\_SOLID, 1, RGB(255, 255, 255)); // select color White CPen\* pOldPen = cdc->SelectObject(&aPen); // Select the pen // Now draw the rectangular cdc->Rectangle(rec); // select back the old pen cdc->SelectObject(pOldPen); \*pResult = 0;
}
That's all. When I select a row, it works. Then I select another row, it works but do not erase the previous rectangular. So my list control is full of rectangular. :(( Does anyone know how to erase the previous rectangular? Thanks in advance, :)
-
I have a list control which is declared like this
CListCtrl m_list1;
I set the background color to black, and the text color to white. Whenever I select a row, I just want to draw a rectangular wrap to the row. So I implement the item change method, like this:
void AlarmCompreMsgDig::OnLvnItemchangedList1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast(pNMHDR);
m_lstAlarmCompreMsg.SetItemState(-1, 0, LVIS_SELECTED); // first, diselect the rowint rowIndex = pNMLV->iItem; CRect rec; // boundary rectangular that wrap the row m\_lstAlarmCompreMsg.GetItemRect(rowIndex, rec, LVIR\_BOUNDS); // a little adjust the rectangular rec.top -= 2; rec.bottom += 2; CDC\* cdc = m\_lstAlarmCompreMsg.GetDC(); CPen aPen; aPen.CreatePen(PS\_SOLID, 1, RGB(255, 255, 255)); // select color White CPen\* pOldPen = cdc->SelectObject(&aPen); // Select the pen // Now draw the rectangular cdc->Rectangle(rec); // select back the old pen cdc->SelectObject(pOldPen); \*pResult = 0;
}
That's all. When I select a row, it works. Then I select another row, it works but do not erase the previous rectangular. So my list control is full of rectangular. :(( Does anyone know how to erase the previous rectangular? Thanks in advance, :)
When you select an item in a list control,
OnLvnItemchangedList1()
gets called multiple times. Once for the previous item, and again for the current item. Change the pen color accordingly."Love people and use things, not love things and use people." - Unknown
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
-
When you select an item in a list control,
OnLvnItemchangedList1()
gets called multiple times. Once for the previous item, and again for the current item. Change the pen color accordingly."Love people and use things, not love things and use people." - Unknown
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
Thank you for your answer, DavidCrow. Actually, I have a int member of dialog to keep the old row. So this function look like this:
void AlarmCompreMsgDig::OnLvnItemchangedList1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast(pNMHDR);
m_lstAlarmCompreMsg.SetItemState(-1, 0, LVIS_SELECTED); // first, diselect the rowint rowIndex = pNMLV->iItem; CRect rec; // boundary rectangular that wrap the row m\_lstAlarmCompreMsg.GetItemRect(rowIndex, rec, LVIR\_BOUNDS); // a little adjust the rectangular rec.top -= 2; rec.bottom += 2; CDC\* cdc = m\_lstAlarmCompreMsg.GetDC(); CPen aPen; // oldRowIndex is the member of dialog if (oldRowIndex == rowIndex){ // this occurs 1st, and 3rd also aPen.CreatePen(PS\_SOLID, 1, RGB(0, 0, 0)); // select color Black (background color) } else // this occurs 2nd { aPen.CreatePen(PS\_SOLID, 1, RGB(255, 255, 255)); // select color White oldRowIndex = rowIndex; // update oldRowIndex } CPen\* pOldPen = cdc->SelectObject(&aPen); // Select the pen // Now draw the rectangular cdc->Rectangle(rec); // select back the old pen cdc->SelectObject(pOldPen); \*pResult = 0;
}
But there is something wrong here: this function is called 3 time totally. The 1st time it will erase the old rectangular, the second time it draw new rectangular, and then the last time it erase the new created rectangular. I don't know why???
-
Thank you for your answer, DavidCrow. Actually, I have a int member of dialog to keep the old row. So this function look like this:
void AlarmCompreMsgDig::OnLvnItemchangedList1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast(pNMHDR);
m_lstAlarmCompreMsg.SetItemState(-1, 0, LVIS_SELECTED); // first, diselect the rowint rowIndex = pNMLV->iItem; CRect rec; // boundary rectangular that wrap the row m\_lstAlarmCompreMsg.GetItemRect(rowIndex, rec, LVIR\_BOUNDS); // a little adjust the rectangular rec.top -= 2; rec.bottom += 2; CDC\* cdc = m\_lstAlarmCompreMsg.GetDC(); CPen aPen; // oldRowIndex is the member of dialog if (oldRowIndex == rowIndex){ // this occurs 1st, and 3rd also aPen.CreatePen(PS\_SOLID, 1, RGB(0, 0, 0)); // select color Black (background color) } else // this occurs 2nd { aPen.CreatePen(PS\_SOLID, 1, RGB(255, 255, 255)); // select color White oldRowIndex = rowIndex; // update oldRowIndex } CPen\* pOldPen = cdc->SelectObject(&aPen); // Select the pen // Now draw the rectangular cdc->Rectangle(rec); // select back the old pen cdc->SelectObject(pOldPen); \*pResult = 0;
}
But there is something wrong here: this function is called 3 time totally. The 1st time it will erase the old rectangular, the second time it draw new rectangular, and then the last time it erase the new created rectangular. I don't know why???
tataxin wrote:
But there is something wrong here: this function is called 3 time totally.
Which is correct. The first time you select an item, it should get called once with a new state of
LVSI_FOCUSED|LVSI_SELECTED
. The next time you select an item, it should get called three times: the first time for the old item to remove theLVSI_FOCUSED
style; the second time for the old item to remove theLVSI_SELECTED
style; and a third time for the new item with a new state ofLVSI_FOCUSED|LVSI_SELECTED
. Make sense?"Love people and use things, not love things and use people." - Unknown
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
-
tataxin wrote:
But there is something wrong here: this function is called 3 time totally.
Which is correct. The first time you select an item, it should get called once with a new state of
LVSI_FOCUSED|LVSI_SELECTED
. The next time you select an item, it should get called three times: the first time for the old item to remove theLVSI_FOCUSED
style; the second time for the old item to remove theLVSI_SELECTED
style; and a third time for the new item with a new state ofLVSI_FOCUSED|LVSI_SELECTED
. Make sense?"Love people and use things, not love things and use people." - Unknown
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
oh, that's great. I try to find out this, but not success up to now. And, can you explain some more, what should I change in my source code now? I tried some thing but not correct. the structure of pNMLV is
typedef struct tagNMLISTVIEW {
NMHDR hdr;
int iItem;
int iSubItem;
UINT uNewState;
UINT uOldState;
UINT uChanged;
POINT ptAction;
LPARAM lParam;
} NMLISTVIEW, *LPNMLISTVIEW;which member should I take and how to compare with LVIS_FOCUSED, LVIS_SELECTED? In fact, I tried this
int x = pNMLV->uChanged;
if (x == ){
// draw rectangular here
} else if (x == LVIS_FOCUSED){
// remove old rectangular here
} else if (x == LVIS_SELECTED){
// do nothing
}but it's always be LVIS_FOCUSED|LVIS_SELECTED, so it always draws and draws
-
oh, that's great. I try to find out this, but not success up to now. And, can you explain some more, what should I change in my source code now? I tried some thing but not correct. the structure of pNMLV is
typedef struct tagNMLISTVIEW {
NMHDR hdr;
int iItem;
int iSubItem;
UINT uNewState;
UINT uOldState;
UINT uChanged;
POINT ptAction;
LPARAM lParam;
} NMLISTVIEW, *LPNMLISTVIEW;which member should I take and how to compare with LVIS_FOCUSED, LVIS_SELECTED? In fact, I tried this
int x = pNMLV->uChanged;
if (x == ){
// draw rectangular here
} else if (x == LVIS_FOCUSED){
// remove old rectangular here
} else if (x == LVIS_SELECTED){
// do nothing
}but it's always be LVIS_FOCUSED|LVIS_SELECTED, so it always draws and draws
tataxin wrote:
int x = pNMLV->uChanged;
Look at the two "state" members.
tataxin wrote:
if (x == ){
You have to compare bits here.
"Love people and use things, not love things and use people." - Unknown
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
-
oh, that's great. I try to find out this, but not success up to now. And, can you explain some more, what should I change in my source code now? I tried some thing but not correct. the structure of pNMLV is
typedef struct tagNMLISTVIEW {
NMHDR hdr;
int iItem;
int iSubItem;
UINT uNewState;
UINT uOldState;
UINT uChanged;
POINT ptAction;
LPARAM lParam;
} NMLISTVIEW, *LPNMLISTVIEW;which member should I take and how to compare with LVIS_FOCUSED, LVIS_SELECTED? In fact, I tried this
int x = pNMLV->uChanged;
if (x == ){
// draw rectangular here
} else if (x == LVIS_FOCUSED){
// remove old rectangular here
} else if (x == LVIS_SELECTED){
// do nothing
}but it's always be LVIS_FOCUSED|LVIS_SELECTED, so it always draws and draws
I solved it, The final source code is;
if ((pNMLV->uChanged & LVIF_STATE) != LVIF_STATE)
return; // state has not changedif (pNMLV->uOldState & LVIS\_SELECTED) { // remove old rectangular here } else if (pNMLV->uNewState & LVIS\_SELECTED) { // draw new rectangular here }
It works, great!!!!! Thank you for your suggestion, DavidCrow, :)