Introduction
This article is for those who did not find, any useful code examples and information regarding ListControl (ListView
). For me, it was really hard to get a working code for Win32 API, since I don't code in MFC. The only help I was able to get was win32.hlp which contains every API by Microsoft. Note that it did not have any examples in it. Also searching through forums can be helpful, but it is slow and sometimes you really wanna get some stuff going fast and clear. I decided to write this article for the coders who don't know any MFC (class) or just starting with ListControl via APIs. First, I must say that all examples I've seen so far lacked information for mon-MFC coders!. If you can't code or can't understand MFC, and are using the API, then this little article is for you.
So let's start.
#include <commctrl.h>
Add it into your C/CPP file so we can use its functions. We add a ListControl to our dialog (you can also create it via the CreateWindowEx
API!). Once we named it, (IDC_LIST
), we add 2 buttons which will do something to our ListView
. Once we've done it, we need to save its HANDLE (which is HWND
). We use a static HWND hList=NULL;
as a global variable (so we can access it in any function). Now we need to initialize our ListView
(I will do it in the WM_INITDIALOG
message). First we get the handle: hList=GetDlgItem(hWnd,IDC_LIST)
;, then we add a LVITEM LvItem; struct
(also a global variable). The LVITEM struct
consists of a few parameters:
typedef struct _LV_ITEM {
UINT mask; int iItem; int iSubItem; UINT state; UINT stateMask; LPTSTR pszText; int cchTextMax; int iImage; LPARAM lParam; } LV_ITEM;
We also add a LVCOLUMN LvCol;
(global variable). The LVCOLUMN struct
consists of a few parameters:
typedef struct _LV_COLUMN {
UINT mask; int fmt; int cx; LPTSTR pszText; int cchTextMax; int iSubItem; } LV_COLUMN;
Now that we know about the struct
's members, let's initialize and use what we need: at the WM_INITDIALOG
message.
Memset(&LvCol,0,sizeof(LvCol)); LvCol.mask=LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; LvCol.cx=0x28; LvCol.pszText="Item"; LvCol.cx=0x42;
For more information that our list control can supply us, we can use the extended styles (full raw select):
SendMessage(hList,LVM_SETEXTENDEDLISTVIEWSTYLE,
0,LVS_EX_FULLROWSELECT);
Now, let us put some columns (as much as you like):
SendMessage(hList,LVM_INSERTCOLUMN,0,(LPARAM)&LvCol); LvCol.pszText="Sub Item1"; SendMessage(hList,LVM_INSERTCOLUMN,1,(LPARAM)&LvCol); LvCol.pszText="Sub Item2"; SendMessage(hList,LVM_INSERTCOLUMN,2,(LPARAM)&LvCol); LvCol.pszText="Sub Item3"; SendMessage(hList,LVM_INSERTCOLUMN,3,(LPARAM)&LvCol); LvCol.pszText="Sub Item4"; SendMessage(hList,LVM_INSERTCOLUMN,4,(LPARAM)&LvCol); LvCol.pszText="Sub Item5"; SendMessage(hList,LVM_INSERTCOLUMN,5,(LPARAM)&LvCol);
Once we've added headers (columns) to our listview
, we need to add some items to it. This is done via the above mentioned LVITEM struct
.
memset(&LvItem,0,sizeof(LvItem));
LvItem.mask=LVIF_TEXT; LvItem.cchTextMax = 256; LvItem.iItem=0; LvItem.iSubItem=0; LvItem.pszText="Item 0";
SendMessage(hList,LVM_INSERTITEM,0,(LPARAM)&LvItem);
for(i=1;i<=5;i++) {
LvItem.iSubItem=i;
sprintf(Temp,"SubItem %d",i);
LvItem.pszText=Temp;
SendMessage(hList,LVM_SETITEM,0,(LPARAM)&LvItem); }
How about inserting a new item?
LvItem.iItem=1; LvItem.iSubItem=0; LvItem.pszText="Item 1";
SendMessage(hList,LVM_INSERTITEM,0,(LPARAM)&LvItem);
for(i=1;i<=5;i++) {
LvItem.iSubItem=i;
sprintf(Temp,"SubItem %d",i);
LvItem.pszText=Temp;
SendMessage(hList,LVM_SETITEM,0,(LPARAM)&LvItem); }
Note: Temp is a char
variable: char Temp[255]=""
.
Adding an item via the button:
case IDC_ADDITEM:
{
int iItem;
char ItemText[100];
iItem=SendMessage(hList,LVM_GETITEMCOUNT,0,0);
GetDlgItemText(hWnd,IDC_ADD,ItemText,100);
if((lstrlen(ItemText))==0) {
MessageBox(hWnd,"Please Write Some Text",
"Error",MB_OK|MB_ICONINFORMATION);
break;
}
LvItem.iItem=iItem; LvItem.iSubItem=0;
LvItem.pszText=ItemText;
SendMessage(hList,LVM_INSERTITEM,0,(LPARAM)&LvItem);
}
break;
Adding a Subitem via the button:
case IDC_ADDSUBITEM:
{
int Item,i;
char SubItemText[100];
Item=SendMessage(hList,LVM_GETITEMCOUNT,0,0);
GetDlgItemText(hWnd,IDC_ADDSUB,SubItemText,100);
if((lstrlen(SubItemText))==0) {
MessageBox(hWnd,"Please Write Some Text",
"Error",MB_OK|MB_ICONINFORMATION);
break;
}
LvItem.iItem=Item-1;
for(i=1;i<=5;i++) {
LvItem.pszText=SubItemText;
LvItem.iSubItem=i;
SendMessage(hList,LVM_SETITEM,0,
(LPARAM)&LvItem); }
}
break;
Put both item and SubItems.
case IDC_BOTH:
{
int itemIndex,j;
char iSubItemText[100]="";
char iItemText[100]="";
itemIndex=SendMessage(hList,LVM_GETITEMCOUNT,0,0);
GetDlgItemText(hWnd,IDC_ADD,iItemText,100); GetDlgItemText(hWnd,IDC_ADDSUB,iSubItemText,100);
if((lstrlen(iSubItemText) && lstrlen(iItemText))==0)
{
MessageBox(hWnd,"Please Write Some Text",
"Error",MB_OK|MB_ICONINFORMATION);
break;
}
LvItem.iItem=itemIndex; LvItem.iSubItem=0; LvItem.pszText=iItemText; SendMessage(hList,LVM_INSERTITEM,0,(LPARAM)&LvItem);
for(j=1;j<=5;j++) {
LvItem.pszText=iSubItemText; LvItem.iSubItem=j;
SendMessage(hList,LVM_SETITEM,0,(LPARAM)&LvItem); }
}
break;
Deleting all items at the list control is done via one message to the list control:
SendMessage(hList,LVM_DELETEALLITEMS,0,0);
Deleting Specific Selected Item in the ListView
.
We use the flag (global variable) to help us notice when an item is focused or selected (has a blue color wrapping the item).
case IDC_DELSELITEM:
if(flag) SendMessage(hList,LVM_DELETEITEM,iSelect,0);
flag=0; break;
The next part is to show how a user selects an item and responds to the button or how do we use the mouse and affect the list view while clicking on it with double click, left click.. etc.
Affecting the ListView
must be done via the WM_NOTIFY
message, this is because the ListView
doesn't have it over its properties like ListBox has! We put the WM_NOTIFY
message under the switch(Message){...}
.
case WM_NOTIFY: {
switch(LOWORD(wParam)) {
case IDC_LIST:
To make us select the items (we are using full raw select), we need to use NMHDR
and its members:
if(((LPNMHDR)lParam)->code == NM_CLICK)
{
}
A list of code we can use for our listview
are:
...
...
NM_CLICK - pnmh = (NMHDR FAR *) lParam;
NM_DBLCLK - pnmh = (NMHDR FAR *) lParam;
NM_KILLFOCUS - pnmh = (NMHDR FAR *) lParam;
NM_RCLICK - pnmh = (NMHDR FAR *) lParam;
NM_RDBLCLK - pnmh = (NMHDR FAR *) lParam;
NM_RETURN - pnmh = (NMHDR FAR *) lParam;
NM_SETFOCUS - pnmh = (NMHDR FAR *) lParam;
LVN_ENDLABELEDIT - pdi = (LV_DISPINFO FAR *) lParam;
LVN_BEGINLABELEDIT -pdi = (LV_DISPINFO FAR *) lParam;
...
...
See win32.hlp for more useful messages.
So, let's continue from what we left, we need to select an item in order to delete it. We are using the code we learned/used from above:
if(((LPNMHDR)lParam)->code == NM_CLICK)
{
iSelect=SendMessage(hList,LVM_GETNEXTITEM,
-1,LVNI_FOCUSED);
if(iSelect==-1) {
MessageBox(hWnd,"No Items in ListView",
"Error",MB_OK|MB_ICONINFORMATION);
break;
}
flag=1; }
Note: iSelect
is a global variable.
Say we want to get the text from an item & subitems once we double click an item. We need to add a NM_DBLCLK
message and process it with our code:
if(((LPNMHDR)lParam)->code == NM_DBLCLK)
{
}
We use all the messages that the listview
has to offer us and from the code we used above, it wont be hard to get the item/sub items:
case WM_NOTIFY:
{
switch(LOWORD(wParam))
{
case IDC_LIST:
if(((LPNMHDR)lParam)->code == NM_DBLCLK)
{
char Text[255]={0};
char Temp[255]={0};
char Temp1[255]={0};
int iSlected=0;
int j=0;
iSlected=SendMessage(hList,LVM_GETNEXTITEM,-1,LVNI_FOCUSED);
if(iSlected==-1)
{
MessageBox(hWnd,"No Items in ListView",
"Error",MB_OK|MB_ICONINFORMATION);
break;
}
memset(&LvItem,0,sizeof(LvItem));
LvItem.mask=LVIF_TEXT;
LvItem.iSubItem=0;
LvItem.pszText=Text;
LvItem.cchTextMax=256;
LvItem.iItem=iSlected;
SendMessage(hList,LVM_GETITEMTEXT,
iSlected, (LPARAM)&LvItem);
sprintf(Temp1,Text);
for(j=1;j<=5;j++)
{
LvItem.iSubItem=j;
SendMessage(hList,LVM_GETITEMTEXT,
iSlected, (LPARAM)&LvItem);
sprintf(Temp," %s",Text);
lstrcat(Temp1,Temp);
}
MessageBox(hWnd,Temp1,"test",MB_OK);
}
}
}
Label Editing
Say we want to edit our item's text at runtime, how can we do it? We will use the LVN_BEGINLABELEDIT
and LVN_ENDLABELEDIT
messages.
if(((LPNMHDR)lParam)->code == LVN_BEGINLABELEDIT)
{
hEdit=ListView_GetEditControl(hList);
}
When we give the listbox an "edit labels" dialog property, we are able to edit the item's text when we press on it with the mouse [select item -> click small left button]. Once we did it, we need to trap the editbox created at run-time by the listbox. We use the LVN_BEGINLABELEDIT
message to begin the label edit. Once it's trapped, we are saving the created edit's handle.
I used the ListView_GetEditControl
macro because it is shorter to write :), but you can use the SendMessage
as well. (Return a HWND
if using HWND hEdit=(HWND)SendMessage()
.) We save the handle into hEdit
.
Note: hEdit
is a global variable!
Once we saved the handle, we need to use LVN_ENDLABELEDIT
message to actually get the text from the created edit and save it over a text buffer.
if(((LPNMHDR)lParam)->code == LVN_ENDLABELEDIT)
{
int iIndex;
char text[255]="";
iIndex=SendMessage(hList,LVM_GETNEXTITEM,
-1,LVNI_FOCUSED);
LvItem.iSubItem=0; LvItem.pszText=text; GetWindowText(hEdit, text, sizeof(text));
SendMessage(hList,LVM_SETITEMTEXT,
(WPARAM)iIndex,(LPARAM)&LvItem); }
ListView Colors
You won't believe how much time I took to dig this up to actually work! I mean, 99.99% examples were MFC only!
So here we go, finally, pure WinAPI code for listview colors.
Note: This code is found deeply inside MSDN!
First we handle the WM_NOTIFY
message to use a NM_CUSTOMDRAW
notification. We don't need to use any owner drawn listview, and since this is custom drawn, we can paint the items/subitems at our will.
if(((LPNMHDR)lParam)->code == NM_CUSTOMDRAW)
{
SetWindowLong(hWnd, DWL_MSGRESULT,
(LONG)ProcessCustomDraw(lParam));
return TRUE;
}
We will set a new style which will be a result of our painting function.
LRESULT ProcessCustomDraw (LPARAM lParam)
{
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
switch(lplvcd->nmcd.dwDrawStage)
{
case CDDS_PREPAINT : return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT: if (((int)lplvcd->nmcd.dwItemSpec%2)==0)
{
lplvcd->clrText = RGB(255,0,0);
lplvcd->clrTextBk = RGB(200,200,200);
return CDRF_NEWFONT;
}
else{
lplvcd->clrText = RGB(0,0,255);
lplvcd->clrTextBk = RGB(255,255,255);
return CDRF_NEWFONT;
}
break;
case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
if (iSelect == (int)lplvcd->nmcd.dwItemSpec)
{
if (0 == lplvcd->iSubItem)
{
lplvcd->clrText = RGB(255,0,0);
lplvcd->clrTextBk = RGB(255,255,255);
return CDRF_NEWFONT;
}
else if (1 == lplvcd->iSubItem)
{
lplvcd->clrTextBk = RGB(255,0,0);
lplvcd->clrTextBk = RGB(255,255,255);
return CDRF_NEWFONT;
}
}
}
return CDRF_DODEFAULT;
}
There you code, change/implement code at your will. This is a very good working skeleton of a custom draw, painting items! :-)
---Sub item Colors---
Sub item colors are really cool when you don't wanna have same color for a row. The basic idea is to send a CDRF_NOTIFYSUBITEMDRAW
notification to our result. We will send this message first thing when our item is going to be repainted!
switch(lplvcd->nmcd.dwDrawStage)
{
case CDDS_PREPAINT : {
return CDRF_NOTIFYITEMDRAW;
}
break;
case CDDS_ITEMPREPAINT: {
return CDRF_NOTIFYSUBITEMDRAW;
}
break;
}
The only thing left is to trap this notification and to start drawing the sub items with any color/back-color we want, in a single item.
switch(lplvcd->nmcd.dwDrawStage)
{
case CDDS_PREPAINT : return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT: {
return CDRF_NOTIFYSUBITEMDRAW;
}
break;
case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
{
switch(lplvcd->iSubItem)
{
case 0:
{
lplvcd->clrText = RGB(255,255,255);
lplvcd->clrTextBk = RGB(240,55,23);
return CDRF_NEWFONT;
}
break;
case 1:
{
lplvcd->clrText = RGB(255,255,0);
lplvcd->clrTextBk = RGB(0,0,0);
return CDRF_NEWFONT;
}
break;
case 2:
{
lplvcd->clrText = RGB(20,26,158);
lplvcd->clrTextBk = RGB(200,200,10);
return CDRF_NEWFONT;
}
break;
case 3:
{
lplvcd->clrText = RGB(12,15,46);
lplvcd->clrTextBk = RGB(200,200,200);
return CDRF_NEWFONT;
}
break;
case 4:
{
lplvcd->clrText = RGB(120,0,128);
lplvcd->clrTextBk = RGB(20,200,200);
return CDRF_NEWFONT;
}
break;
case 5:
{
lplvcd->clrText = RGB(255,255,255);
lplvcd->clrTextBk = RGB(0,0,150);
return CDRF_NEWFONT;
}
break;
}
}
}
return CDRF_DODEFAULT;
ListView BackGround Image
Isn't it cool to have a picture (JPG, BMP, GIF...) on your ListView
color? It makes it a bit more pro look. I guess it is more about personal taste. Anyhow, the ListView
will use the OLE object to connect to the image and will draw it over the control.
First, the ListView
will use a struct
to store information regarding the image and its properties. The LVBKIMAGE struct
:
typedef struct tagLVBKIMAGE {
ULONG ulFlags; HBITMAP hbm; LPTSTR pszImage; UINT cchImageMax; int xOffsetPercent; int yOffsetPercent; } LVBKIMAGE, *LPLVBKIMAGE;
First thing to do is to initialize the OLE object! Microsoft suggests 2 ways for that: CoInitialize(NULL);
or OleInitialize(NULL)
. The code itself is pretty much self explained!
case WM_INITDIALOG:
{
LVBKIMAGE plvbki={0}; char url[]="C:\\a.jpg"; plvbki.ulFlags=LVBKIF_SOURCE_URL; plvbki.pszImage=url; plvbki.xOffsetPercent=40; plvbki.yOffsetPercent=15; OleInitialize(NULL); SendMessage(hList,LVM_SETTEXTBKCOLOR,
0,(LPARAM)CLR_NONE); SendMessage(hList,LVM_SETBKIMAGE,0,
(LPARAM)(LPLVBKIMAGE)&plvbki); }
break;
You can see that I have used CLR_NONE
. Now, if your list view is not using custom control (Listview colors, see section above), then this line will set the background color of each row to transparent!
The only thing left to do is to close the OLE COM object. This is what Microsoft suggested anyway, doing it by: CoUninitialize();
or OleUninitialize();
. When your application is closed, funny, it causes a crash here. I'll check it later :-)
---Adding Item's Renaming Cancel Event---
Heya, ever wanted that effect when you edit a folder's name and you typed the wrong name, and wanna start over and go back to the original folder's name by ESC key? (you probably know it..)
We want to add the same effect to our listview
's items too! For this, we need to learn about Windows messages and process them. Usually think about an EverLasting look that monitors the window you are using, and listens for every message that you process:
Mouse, KeyBoard...etc., you should already be familiar with them. This is what we need to to:
- Save the original text of item
- Monitor for a key press
- If ESC key pressed, re-save old text else
we get the new text and show it on the new item's caption.
Let's start by creating our *Global* vars (so we can access then from any function/message).
bool escKey=0; char tempstr[100]=""; TCHAR tchar; MSG msg;
And now for the re-coding & adding some stuff:
We first begin with adding the below code to the WM_INITDIALOG
:
ShowWindow(hWnd,SW_NORMAL);
UpdateWindow(hWnd);
while(TRUE)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message==WM_QUIT)
{
break; }
TranslateMessage(&msg); DispatchMessage(&msg); }
}
Notice the WM_QUIT
. To break the while
loop, we must process this when a user hits the [X]. The while
will be broken and we will go to the WM_CLOSE
message where we must add 1 line:
case WM_CLOSE:
{
PostQuitMessage(0);
EndDialog(hWnd,0); }
break;
Now for the main part, you already know the messages that Windows sends to the ListView
in order to edit an item's caption right?
LVN_BEGINLABELEDIT
LVN_ENDLABELEDIT
We already have a code for them, but we need to add a slight addition:
if(((LPNMHDR)lParam)->code == LVN_BEGINLABELEDIT)
{
hEdit=ListView_GetEditControl(hList);
GetWindowText(hEdit, tempstr, sizeof(tempstr)); }
Here we save the text before we actually edit it! That's great and the last part:
if(((LPNMHDR)lParam)->code == LVN_ENDLABELEDIT)
{
int iIndex;
char text[255]="";
tchar = (TCHAR)msg.wParam; if(tchar == 0x1b) escKey=1;
iIndex=SendMessage(hList,LVM_GETNEXTITEM,-1,LVNI_FOCUSED);
if(iIndex==-1)
break;
LvItem.iSubItem=0;
if(escKey==0) {
LvItem.pszText=text;
GetWindowText(hEdit, text, sizeof(text));
SendMessage(hList,LVM_SETITEMTEXT,
(WPARAM)iIndex,(LPARAM)&LvItem);
}
else{ LvItem.pszText=tempstr; SendMessage(hList,LVM_SETITEMTEXT,
(WPARAM)iIndex,(LPARAM)&LvItem);
escKey=0;
}
}
break;
We first begin by checking tchar
's content...why?
Ok, well, you probably know that ENTER /ESC and some more are keys that will finish up the editing of the text! So we can't check for those keys in the while()
loop, because it will be skipped by the LVN_ENDLABELEDIT
message. So first thing we check is, if ESC was hit.
Using a boolean variable, we can determine whenever a cancel event has occurred, or we can actually process the new text.
Selecting (Highlighting) items/All Items
It is not really hard, we use this piece of code:
Select Item:
ListView_SetItemState(hList, -1, 0, LVIS_SELECTED); SendMessage(hList,LVM_ENSUREVISIBLE ,
(WPARAM)item,FALSE); ListView_SetItemState(hList,item,
LVIS_SELECTED ,LVIS_SELECTED); ListView_SetItemState(hList,item,
LVIS_FOCUSED ,LVIS_FOCUSED);
Select All Item:
ListView_SetItemState(hList, -1, 0,
LVIS_SELECTED); ListView_SetItemState(hList,-1,
LVIS_SELECTED ,LVIS_SELECTED);
The -1 means ALL items. If you want an individual item, just write its index number.
Bugs and Help
It could be that you are using Win2000 for compiling this source code and you may happen to get into a few problems of linking or compiling..
Problem
The thread exits with code 0x0 (exit 0) // something like this :).
When you compile your exe and try to run it, it wont run. Nothing is loading..??? This is because we didn't link with the comctl32.lib. Add it to your link settings: Project -> Settings -> Link Tab -> general -> add comctl32.lib into "object/libary modules" -> click OK. Rebuild project.. and try to run. It's suppose to work. Another way of solving this is to add this code to your WinMain
:
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwICC = ICC_LISTVIEW_CLASSES;
InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX);
BOOL bRet = InitCommonControlsEx(&InitCtrls);
It could work, I haven't tried it..
Yet another approach is directly via the: InitCommonControls();
function!! Write it in the case WM_INITDIALOG:
---F.A.Q---
Q. Why sometimes I get wrong result from the LVM_GETNEXTITEM
when I select items out of the range?
A. This is because we have to set a flag called LVNI_SELECTED
:
SendMessage(hList,LVM_GETNEXTITEM,-1,LVNI_FOCUSED|LVNI_SELECTED);
Q. How do I attach a popup menu when clicking on an item (right button...etc.)?
A. Really easy. First make the menu in the resource editor, and use this code:
HMENU hMenu = LoadMenu (NULL, MAKEINTRESOURCE (IDR_MENU));
HMENU hPopupMenu = GetSubMenu (hMenu, 0);
POINT pt;
SetMenuDefaultItem (hPopupMenu, -1, TRUE);
GetCursorPos (&pt);
SetForegroundWindow (hWnd);
TrackPopupMenu (hPopupMenu,
TPM_LEFTALIGN, pt.x, pt.y, 0, hWnd, NULL);
SetForegroundWindow (hWnd);
DestroyMenu (hPopupMenu);
DestroyMenu (hMenu);
Note: Make sure you pressed on an item, use a if(selected!=-1)
or alike code. That way we prevent from showing the popup menu anytime/anywhere.
Q. How do I color the: entire text color, list view back color, text back color?
A. It is not really hard. We can do it like this:
int count=SendMessage(GetDlgItem(hWnd,
IDC_LIST),LVM_GETITEMCOUNT ,0,0);
SendMessage(GetDlgItem(hWnd,IDC_LIST),
LVM_SETTEXTCOLOR,0,(LPARAM)SetColor());
SendMessage(GetDlgItem(hWnd,IDC_LIST),
LVM_SETTEXTBKCOLOR,0,(LPARAM)SetColor());
SendMessage(GetDlgItem(hWnd,IDC_LIST),
LVM_SETBKCOLOR,0,(LPARAM)SetColor());
SendMessage(GetDlgItem(hWnd,IDC_LIST),
LVM_REDRAWITEMS ,0,count);
UpdateWindow(hWnd);
..
..
..
LONG SetColor()
{
static CHOOSECOLOR cc ;
static COLORREF crCustColors[16] ;
cc.lStructSize = sizeof (CHOOSECOLOR) ;
cc.hwndOwner = NULL ;
cc.hInstance = NULL ;
cc.rgbResult = RGB (0x80, 0x80, 0x80) ;
cc.lpCustColors = crCustColors ;
cc.Flags = CC_RGBINIT | CC_FULLOPEN ;
cc.lCustData = 0 ;
cc.lpfnHook = NULL ;
cc.lpTemplateName = NULL ;
ChooseColor (&cc);
return cc.rgbResult;
}
Note: However, this code has a really tiny bug. If the user presses the cancel/[X] from the color dialog, the default color of it will be returned, and colors your default list box color. However, it's not really hard to fix.
Q. How can I edit an item's caption using a button/menu...etc., just like renaming a folder with right click on mouse option?
A. Send the message: LVM_EDITLABEL
to the list view. Example: SendMessage(hList,LVM_EDITLABEL ,(WPARAM)index,(LPARAM)0);
.
We come to the end of this article. I hope everyone enjoyed this as much as it took me time to find and add a proper code ;-).