June 26, 2024, 08:44:49 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Advanced listview demo

Started by Ionic Wind Support Team, January 06, 2006, 10:28:26 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Ionic Wind Support Team

January 06, 2006, 10:28:26 PM Last Edit: February 23, 2006, 09:55:11 AM by Ionic Wizard
Conversion of the advanced listview demo from IBasic Pro.  Doesn't subclass the header control to change the cursor, I'll leave that as an experiment for the reader. 

Once I add the CHeaderControl class it will be even simpler.  It is a heck of lot more readable than the original version.


//This is an advanced list view demo. The list view is created in report mode
//and two columns are added. The colors of the individual items are changed
//requires Aurora 1.0 Alpha2 or greater

//Compile as a WINDOWS target
#typedef UINT unsigned int
#define NM_CUSTOMDRAW (-12)
#define HDN_FIRST (-300)
#define HDN_BEGINTRACKA (HDN_FIRST-6)
#define HDN_BEGINTRACKW (HDN_FIRST-26)
#define CDDS_PREPAINT 1
#define CDDS_ITEM 0x10000
#define CDDS_SUBITEM 0x20000
#define CDDS_ITEMPREPAINT (CDDS_ITEM | CDDS_PREPAINT)
#define CDDS_SUBITEMPREPAINT (CDDS_SUBITEM | CDDS_ITEMPREPAINT)
#define CDRF_NOTIFYITEMDRAW 0x20
#define CDRF_NOTIFYSUBITEMDRAW 0x20
#define CDRF_DODEFAULT 0
#define CDRF_NEWFONT 2
#define DWL_MSGRESULT 0

import int SetWindowLongA(uint hwnd,int nIndex,uint dwNewLong);
import int SetPropA(hwnd as unsigned int,lpString as STRING,hData as unsigned int);
import unsigned int GetPropA(hwnd as unsigned int,lpString as STRING);
import unsigned int GetParent(uint hwnd);
import int SetBkColor(hdc as UINT,cBack as UINT);
import int SetTextColor(hdc as UINT,crColor as UINT);

struct NMLISTVIEW
{
def hwndFrom as unsigned int;
def idFrom as INT;
def code as INT;
    def iItem as INT;
    def iSubItem as INT ;
    def uNewState as unsigned int;
    def uOldState as unsigned int;
    def uChanged as unsigned int;
    def ptActionx as INT;
def ptActiony as INT;
    def lParam as INT;
}

//type for handling custom drawing of the header control
struct NMCUSTOMDRAWINFO
{
NMHDR hdr;
UINT dwDrawStage;
UINT hdc;
RECT rc;
UINT dwItemSpec;
UINT uItemState;
UINT lItemlParam;
}

//struct for handling custom drawing of the list view control
struct NMLVCUSTOMDRAW
{
    NMCUSTOMDRAWINFO nmcd;
    UINT clrText;
    UINT clrTextBk;
//if internet explore version >= 4.0
    int iSubItem;
}

#define LISTVIEW_1 1

//our derived listview class
class ColorListView:CListView
{
declare OnNotify(int code,int nID,NMHDR *pnmhdr),int;
int m_bLocked; //variable indicating whether columns are resizeable or not

}

//our dialog class
class dlg:CDialog
{
declare OnInitDialog(),int;
declare OnClose(),int;
declare OnNotify(int code,int nID,NMHDR *pnmhdr),int;
declare OnControl(int nID, int nNotifyCode, unsigned int hControl),int;
ColorListView *m_pListView;
}


global sub main()
{
dlg d1;
d1.Create(0,0,300,202,0x80C80080,0,"ListView demo",0);
d1.AddControl(CTLISTVIEW,"",23,15,254,147,AWS_VISIBLE|ALVS_REPORT|AWS_BORDER,AWS_EX_CLIENTEDGE,LISTVIEW_1);
d1.AddControl(CTCHECKBOX,"Lock Column Resize",23,164,240,20,AWS_VISIBLE,0,200);
d1.AddControl(CTSTATIC,"Click on column headers",23,184,240,20,AWS_VISIBLE,0,300);
d1.DoModal();
return 0;
}

dlg::OnClose(),int
{
CloseDialog(1);
return true;
}

dlg::OnInitDialog(),int
{
/* Initialize any controls here */
//get the dialog created listview
CListView *pList = GetControl(LISTVIEW_1);
//Create our derived listview
m_pListView = new(ColorListView,1);
//lock the columns initially
m_pListView->m_bLocked = true;

//set up some columns and items
pList->InsertColumn(0,"Column1");
pList->InsertColumn(1,"Column2");
pList->InsertColumn(2,"Column3");
pList->InsertItem(0,"Item 1");
pList->SetItemText(0,1,"Sub Item 1");
pList->SetItemText(0,2,"Sub Item 2");
pList->InsertItem(1,"Item 2");
pList->SetItemText(1,1,"Sub Item 1");
pList->InsertItem(2,"Item 3");
pList->SetExtendedStyle(ALVS_EX_FLATSB|ALVS_EX_FULLROWSELECT|ALVS_EX_GRIDLINES|ALVS_EX_LABELTIP);
//replace the internal "this" pointer of the dialog created listview control with our derived one
//this allows our derived handlers to be called.  Kind of like subclassing.
//Eventually I'll stick this in a method of the window class.
//It wouldn't be needed for a control created in a window, only a dialog.
SetPropA(pList->m_hWnd,"THIS",m_pListView);
//copy the 'windows' handle to the control.
m_pListView->m_hWnd = pList->m_hWnd;

//set out checkbox
CButton *pCheck = GetControl(200);pCheck->SetCheck(true);

CenterWindow();
return true;
}

dlg::OnControl(int nID, int nNotifyCode, unsigned int hControl),int
{
select nID
{
case 200:
CButton *pCheck = GetControl(200);
IF nNotifyCode = 0
m_pListView->m_bLocked = pCheck->GetCheck();
}
return true;
}

dlg::OnNotify(int code,int nID,NMHDR *pnmhdr),int
{
CStatic *pStatic = GetControl(300);
select code
{
case LVNCOLUMNCLICK:
pStatic->SetText(USING("Column ## clicked",*(NMLISTVIEW)pnmhdr.iSubItem+1));
case NM_CUSTOMDRAW:
SetWindowLongA(m_hWnd,DWL_MSGRESULT,ColorListView(m_hWnd,pnmhdr));

}
return true;
}

SUB ColorListView(UINT hwnd,NMLVCUSTOMDRAW *pnmcd),UINT
{
DEF rv as UINT;
SELECT pnmcd->nmcd.dwDrawStage
{
CASE CDDS_PREPAINT:
rv = CDRF_NOTIFYITEMDRAW;
CASE CDDS_ITEMPREPAINT:
//pnmcd->nmcd.dwItemSpec is the zero based item the control is drawing
//but we want to color each column item (subitem) individually
rv =CDRF_NOTIFYSUBITEMDRAW;
CASE CDDS_SUBITEMPREPAINT:
//pnmcd->iSubItem contains the zero based sub item number
//on system with IE 4.0 or greater installed.
SELECT pnmcd->iSubItem
{
CASE 0://  the ITEM color
pnmcd->clrText = RGB(0,0,0);
pnmcd->clrTextBk = RGB(255,0,0);
CASE 1: //the first sub item
pnmcd->clrText = RGB(0,0,0);
pnmcd->clrTextBk = RGB(0,255,0);
DEFAULT: //the color of the rest of the line
pnmcd->clrText = RGB(0,0,0);
pnmcd->clrTextBk = RGB(255,0,255);
}
rv = CDRF_NEWFONT;
DEFAULT:
rv = CDRF_DODEFAULT;
}
RETURN rv;
}

ColorListView::OnNotify(int code,int nID,NMHDR *pnmhdr),int
{
select code
{
//color the header control buttons
case NM_CUSTOMDRAW:
return ColorHeader(pnmhdr);
case HDN_BEGINTRACKA:
case& HDN_BEGINTRACKW:
if m_bLocked return true; //eat it
}
return false;
}

SUB ColorHeader(NMCUSTOMDRAWINFO *pnmcd),UINT
{
SELECT(pnmcd->dwDrawStage)
{
CASE CDDS_PREPAINT:
return CDRF_NOTIFYITEMDRAW;
CASE CDDS_ITEMPREPAINT:
//color the backound of the header columns first col blue, second  yellow, third black
//change the text color of the first and second columns while we are at it
SELECT pnmcd->dwItemSpec
{
CASE 0:
SetTextColor(pnmcd->hDC,RGB(255,255,255));
SetBkColor(pnmcd->hDC,RGB(50,50,255));
CASE 1:
SetBkColor(pnmcd->hDC,RGB(255,255,50));
CASE 2:
SetTextColor(pnmcd->hDC,RGB(255,255,255));
SetBkColor(pnmcd->hDC,RGB(0,0,0));
}
return CDRF_NEWFONT;
}
return CDRF_DODEFAULT;
}


EDIT: Changed to reflect the latest compiler version.
Ionic Wind Support Team

Haim

Hi,
In the advanced listview example a standard listview is first created and than the derived class is "inserted" in its place. Is it possible to create and use a derived control class directly and still have the parent window receive all the notifications as if it were a standard control?
I am trying to create my own derived listview control, so it can be reused without having to code around it.
Haim

Ionic Wind Support Team

You can just call the Create member of your derived class, usually in OnInitDialog for dialogs.    Create dynamically with NEW.

In a window you can call a controls Create member anytime after the window is created.
Ionic Wind Support Team

Haim

Thanks.
I still miss something...
why then was the "THIS" swap in the example necessary?

Ionic Wind Support Team

Just showing how it could be done with AddControl which the dialog editor generates.   If you allocate your own control and call the Create member then none of that is necessary.

Plus it's an old example ;)
Ionic Wind Support Team

Haim

Thanks.
I guess I too am  an old example...  ;)