List View Item Control.
Here is a sample listing of code that will add bitmap IDs(win32 application) or ICON Ids to the list view control. few month back I made this to add a feature to my existing application module.
You cannot blindly add this to ur workspace since it need some modifications. Treat this as a code snippet or an example to make the target.!! Happy coding
/**
class/structure: SListControl
author: renjith
creation: 25-march-2008
Modification History
---------------------------------------------------------------------------------
Date comments Reason
---------------------------------------------------------------------------------
27-Mar-08 Added ne method AddBmpImage() which To add this class in
takes a vector of Ids and Names as Input. main dialog of CADPartDB
16-Jun-08 Added new methods SetProductName() and Support for new fron-end
GetProductName() to support the new front interface (insert/update
end Interface the contents of DB)
---------------------------------------------------------------------------------
**/
#pragma once
#include <commctrl.h>
#include "../resource.h"
#include "../stdafx.h"
struct SListControl
{
private:
LV_ITEM lvi;
LV_COLUMN lvc;
std::vector<_str> m_strProdName;
public:
//int AddString ( LPCTSTR str ) { return ::SendMessage( handle, LB_ADDSTRING, 0, (LPARAM)str ); };
int GetCurSel();
void SetProductName(const std::vector<_str> & strVecName);
std::vector<_str> GetProductName();
void AddBmpImage(std::vector<int> nVecIDs,std::vector<_str> strVecName);
bool AddBmpImage(int nIDStart,int nIDEnd, _str strName);
bool AddIconImage(int nIDStart,int nIDEnd, _str strName);
};
/**
class/structure: SListControl
author: renjith
creation: 25-march-2008
Modification History
---------------------------------------------------------------------------------
Date comments Reason
---------------------------------------------------------------------------------
27-Mar-08 Added ne method AddBmpImage() which To add this class in
takes a vector of Ids and Names as Input. main dialog of CADPartDB
16-Jun-08 Added new methods SetProductName() and Support for new fron-end
GetProductName() to support the new front interface (insert/update
end Interface the contents of DB)
---------------------------------------------------------------------------------
**/
#include "guicontrolenhanced.h"
#include "StdAfx.h"
#include <commctrl.h>
#include "../resource.h"
/*
#include <string>
#include <vector>
using namespace std;*/
void SListControl::SetProductName(const std::vector<_str> & strVecName)
{
m_strProdName = strVecName;
}
std::vector<_str> SListControl::GetProductName()
{
return m_strProdName;
}
void SListControl::AddBmpImage(std::vector<int> nVecIDs,std::vector<_str> strVecName)
{
int nMAX = nVecIDs.size();
HWND hList = handle;
RECT Rect;
HIMAGELIST himlLarge;
SetProductName(strVecName);
//LV_ITEM lvi;
//LV_COLUMN lvc;
int iStatus;
int i;
char szStr[ 32 ];
//Registers and initializes certain common control window classes.
InitCommonControls();
if( ! hList )
MessageBox(NULL,"hList is Null","",MB_OK);
// Create an Image list, of 80x80 pixels
himlLarge = ImageList_Create(80,80,ILC_COLOR32,100,100);
//4th argument is the number of images that the image list initially contains.
//5th argument is the the number of images by which the image list can grow when
//the system needs to make room for new images.
for( i = 0; i < nMAX; i++ ) // Add Images to each image list
{
HBITMAP hBitMap; // bitmap handler
int imlindex=-1;
hBitMap=LoadBitmap(g_hModule,MAKEINTRESOURCE(nVecIDs[i]));
if(!hBitMap)
MessageBox(NULL,"hBitMap is null","Msg",MB_OK);
imlindex = ImageList_Add(himlLarge,hBitMap,NULL);
}
// Make the listview use the images lists and exit
//ListView_SetImageList( hList, himlLarge, LVSIL_NORMAL);
// this is # defined in the header as...
SendMessage(hList, LVM_SETIMAGELIST, (WPARAM)(LVSIL_NORMAL), (LPARAM)(HIMAGELIST)(himlLarge));
GetClientRect( hList, &Rect ); // Get the listview RECT size
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = Rect.right - Rect.left; // Make bar width of window
lvc.pszText = "Item Status";
lvc.iSubItem = 0; // Add display column (for Report View)
//iStatus = ListView_InsertColumn( hList, 0, &lvc );
iStatus = SendMessage((hList), LVM_INSERTCOLUMN, (WPARAM)(int)(0), (LPARAM)(const LV_COLUMN *)(&lvc));
lvi.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT | LVIF_STATE;
lvi.state = 0;
lvi.stateMask = LVIS_FOCUSED; // Set generic structure values
lvi.pszText = szStr;
for( i = 0; i < nMAX; i++ ) // Add 20 items to the control
{
wsprintf( szStr, "%s",strVecName[i].c_str() ); // Name depends on number
lvi.iImage = i ; // 5 images
lvi.iItem = i;
lvi.iSubItem = 0;
lvi.lParam = 1;
//iStatus = ListView_InsertItem( hList, &lvi ); // Add item to control
iStatus = ::SendMessage((hList), LVM_INSERTITEM, 0, (LPARAM)(const LV_ITEM *)( &lvi));
}
}
bool SListControl::AddBmpImage(int nIDStart,int nIDEnd, _str strName)
{
int nMAX = nIDEnd - nIDStart;
HWND hList = handle;
RECT Rect;
HIMAGELIST himlLarge;
// HIMAGELIST himlSmall;
//LV_ITEM lvi;
//LV_COLUMN lvc;
int iStatus;
int i;
char szStr[ 32 ];
InitCommonControls();
if( ! hList )
MessageBox(NULL,"hList is Null","",MB_OK);
// Create two lists, one for 32x32 and another for 16x16 icons
himlLarge = ImageList_Create(80,80,ILC_COLOR32,100,100);//100, 100, ILC_COLOR32, 0, 10
for( i = 0; i <= nMAX; i++ ) // Add icons to each image list
{
HBITMAP hBitMap; // bitmap handler
int imlindex=-1;
hBitMap=LoadBitmap(g_hModule,MAKEINTRESOURCE(nIDStart+i));
if(!hBitMap)
MessageBox(NULL,"hBitMap is null","Msg",MB_OK);
imlindex = ImageList_Add(himlLarge,hBitMap,NULL);
}
// Make the listview use the images lists and exit
//ListView_SetImageList( hList, himlLarge, LVSIL_NORMAL);
SendMessage(hList, LVM_SETIMAGELIST, (WPARAM)(LVSIL_NORMAL), (LPARAM)(HIMAGELIST)(himlLarge));
GetClientRect( hList, &Rect ); // Get the listview RECT size
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = Rect.right - Rect.left; // Make bar width of window
lvc.pszText = "Item Status";
lvc.iSubItem = 0; // Add display column (for Report View)
//iStatus = ListView_InsertColumn( hList, 0, &lvc );
iStatus = SendMessage((hList), LVM_INSERTCOLUMN, (WPARAM)(int)(0), (LPARAM)(const LV_COLUMN *)(&lvc));
lvi.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT | LVIF_STATE;
lvi.state = 0;
lvi.stateMask = LVIS_FOCUSED; // Set generic structure values
lvi.pszText = szStr;
for( i = 0; i <= nMAX; i++ ) // Add 20 items to the control
{
wsprintf( szStr, "%s #%d",strName.c_str(), i + 1 ); // Name depends on number
lvi.iImage = i ; // 5 images
lvi.iItem = i;
lvi.iSubItem = 0;
lvi.lParam = 1;
//iStatus = ListView_InsertItem( hList, &lvi ); // Add item to control
iStatus = ::SendMessage((hList), LVM_INSERTITEM, 0, (LPARAM)(const LV_ITEM *)( &lvi));
}
// SendMessage(hList,LVM_DELETEITEM,3,0);
return true;
}
bool SListControl::AddIconImage(int nIDStart,int nIDEnd, _str strName)
{
int nMAX = nIDEnd - nIDStart;
HWND hList = handle;
RECT Rect;
HICON hiconItem;
HIMAGELIST himlLarge;
//LV_ITEM lvi;
//LV_COLUMN lvc;
int iStatus;
char szStr[ 32 ];
int i;
InitCommonControls();
if( ! hList )
MessageBox(NULL,"hList is Null","",MB_OK);
// Create lists, for 32x32 icons
himlLarge = ImageList_Create( GetSystemMetrics( SM_CXICON ),
GetSystemMetrics( SM_CYICON ),
TRUE, 1, 1 );
for( i = 0; i < nMAX; i++ ) // Add icons to each image list
{
hiconItem = (HICON)LoadImage( g_hModule, MAKEINTRESOURCE( 1000+i ),IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR );
if(!hiconItem)
MessageBox(NULL,"hiconItem is Null","",MB_OK);
ImageList_AddIcon( himlLarge, hiconItem );
DeleteObject( hiconItem );
}
// Make the listview use the images lists and exit
//ListView_SetImageList( hList, himlLarge, LVSIL_NORMAL);
SendMessage(hList, LVM_SETIMAGELIST, (WPARAM)(LVSIL_NORMAL), (LPARAM)(HIMAGELIST)(himlLarge));
GetClientRect( hList, &Rect ); // Get the listview RECT size
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = Rect.right - Rect.left; // Make bar width of window
lvc.pszText = "Item Status";
lvc.iSubItem = 0; // Add display column (for Report View)
//iStatus = ListView_InsertColumn( hList, 0, &lvc );
iStatus = SendMessage((hList), LVM_INSERTCOLUMN, (WPARAM)(int)(0), (LPARAM)(const LV_COLUMN *)(&lvc));
lvi.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT | LVIF_STATE;
lvi.state = 0;
lvi.stateMask = LVIS_FOCUSED; // Set generic structure values
lvi.pszText = szStr;
for( i = 0; i < nMAX; i++ ) // Add 20 items to the control
{
wsprintf( szStr, "%s #%d",strName.c_str(), i + 1 ); // Name depends on number
lvi.iImage = i ;//% 5; // 5 images
lvi.iItem = i;
lvi.iSubItem = 0;
lvi.lParam = 1;
//iStatus = ListView_InsertItem( hList, &lvi ); // Add item to control
iStatus = ::SendMessage((hList), LVM_INSERTITEM, 0, (LPARAM)(const LV_ITEM *)( &lvi));
}
return true;
}
int SListControl::GetCurSel()
{
//return ListView_GetNextItem(handle,-1,LVNI_FOCUSED);;
return SendMessage(handle,LVM_GETNEXTITEM,-1,LVNI_FOCUSED); // return item selected
}
C/C++ Coder
/********************************** **************************
*** Dipl.- Inf. Detlef Hafer
*** D-91058 Erlangen (Germany)
********************************** ***************************/
#include "stdio.h>"
#include "stdlib.h"
#include "string.h"
#define BACK -1
#define FORWARD 1
#define NSIZE 9
#define BOOL bool
#define FALSE false
#define TRUE true
int F[NSIZE][NSIZE];
#if _DEBUG
static int M[NSIZE][NSIZE] = { {1, 6, 4, 0, 0, 0, 0, 0, 2},
{2, 0, 0, 4, 0, 3, 9, 1, 0},
{0, 0, 5, 0, 8, 0, 4, 0, 7},
{0, 9, 0, 0, 0, 6, 5, 0, 0},
{5, 0, 0, 1, 0, 2, 0, 0, 8},
{0, 0, 8, 9, 0, 0, 0, 3, 0},
{8, 0, 9, 0, 4, 0, 2, 0, 0},
{0, 7, 3, 5, 0, 9, 0, 0, 1},
{4, 0, 0, 0, 0, 0, 6, 7, 9} };
#endif
static BOOL findnumber (int z, int s)
{
int u = (z/3)*3;
int v = (s/3)*3;
int m = F[z][s];
F[z][s] = 0;
for (int t = m+1; t <= NSIZE; t++)
{
for (int i = 0; i < NSIZE; i++)
{
div_t q = div(i,3);
if ((F[i][s] == t) || (F[z][i] == t) || F[u+q.quot][v+q.rem] == t)
break;
}
if (i == NSIZE )
{
F[z][s] = t;
return TRUE;
}
}
return FALSE;
}
BOOL soduko (void)
{
BOOL bFix[NSIZE][NSIZE];
int r = FORWARD;
#if _DEBUG
memcpy(F, M, sizeof(M));
#endif
for (int i = 0; i < NSIZE; i++)
for (int j = 0; j < NSIZE; j++)
bFix[i][j] = (F[i][j] != 0);
i = 0;
while ( (i >= 0) && (i < NSIZE*NSIZE) )
{
div_t q = div(i,NSIZE);
int z = q.quot;
int s = q.rem;
if ( ! bFix[z][s])
{
if ( ! findnumber(z,s))
r = BACK;
else
r = FORWARD;
}
i += r;
}
if ( i < 0)
{
// no solution
return FALSE;
}
return TRUE;
}
int main()
{
soduko();
for (int i = 0; i < NSIZE; i++)
{
for (int j = 0; j < NSIZE; j++)
{
printf("%d ",M[i][j]);
}
printf("\n");
}
printf("\n");
printf("\n");
for (int i = 0; i < NSIZE; i++)
{
for (int j = 0; j < NSIZE; j++)
{
printf("%d ",F[i][j]);
}
printf("\n");
}
}
Here is a short description of the virtual tables layout. This is mostly taken out of the existing Taligent runtime.
Virtual tables
Virtual tables
Virtual tables (vtables) are used to dispatch virtual functions, to access virtual base class sub objects, and to access information for runtime type identi?cation (RTTI). Each class that has virtual member functions or virtual bases has an associated set of vtables. The vtable pointers within all the objects (instances) of a class point to the same set of vtables.
Vtable layout
Each vtable consists of the following parts, in the order listed.All offsets in a vtable are of type ptrdiff_t.
"Virtual base offsets" are used to access the virtual bases of anobject and to non virtual bases when pointer adjustment is required for some overriden virtual function. Each entry is a displacement to a virtual base subobject from the location within the object of the vtable pointer that addresses this vtable. These entries are only necessary if the class directly or indirectly inherits from virtual base classes, or if it overrides a virtual function defined in a base class and if adjustment from the based to the derived class is needed. The values can be positive or negative.
"Offset to top" holds the displacement to the top of the object from the location within the object of the vtable pointer that addresses this vtable. A negative value indicates the vtable pointer is part of an embedded base class subobject; otherwise it is zero. The offset provides a way to ?nd the top of the object from any base subobject with a vtable pointer. This is necessary for dynamic_cast
"Typeinfo pointer" points to the typeinfo object used for RTTI. All entries in each of the vtables for a given class point to the same typeinfo object.
"Duplicate base information pointer" points to a table used to perform runtime disambiguation of duplicate base classes for dynamic casts. The entries in each of the vtables for a given class do not all point to the same table of duplicate base information.
Function pointers are used for virtual function dispatch. Each Pointer holds either the address of a virtual function of the class, or the address of a secondary entry point that performs certain
adjustments before transferring control to a virtual function. [To be discussed] In the case of shared library builds, [Solution 1] a function pointer entry contains the address of a function descriptor, which contains the target GP value and the actual function address [Solution 2] a function pointer entry contains two words: the value of the target GP value and the actual function address [Solution 3] a function pointer points to an import table generated by the dynamic loader, which will transfer control to the target function.
The function pointers are grouped so that the entries for all virtual functions introduced by a base class are kept together, in declaration order. Function pointers from a derived class immediately follow those for the base class. The order of function pointers therefore depends on the static type of subobject whose vtable pointer points to that virtual table.
A vtable pointer in an object addresses the "offset to top" ?eld of a vtable. This location is known as the address point of thevtable. Note that the virtual base offsets are at negative displacements from the address point.
The typeinfo and duplicate base information are covered in separate discussions.
Types of vtables
The following categories describe the rules for how vtables of a class are constructed from the vtables of its bases.
Category 1
This category is for a class that inherits no base classes. If the class declares no virtual functions, then it has no vtable, and its objects have no vtable pointers.
If the class declares virtual functions, then it has a single vtable containing RTTI ?elds followed by function pointer entries. There is one function pointer entry for each virtual function declared in the class. The vtable pointer in an object of the class addresses this vtable.
Category 2
This category is for a class that inherits only non-virtual base classes, and the non- virtual base classes have no base classes, and there is no adjustment in any of the overriden virtual functions.
If none of the base classes have vtables, a vtable is constructed for the class according to the same rules as in Category 1. Otherwise the class has a vtable for each base class that has a vtable. The class's vtables are constructed from copies of the base class vtables. The entries are the same, except: - The RTTI ?elds contain information for the class, rather than for the base class. - The function pointer entries for virtual functions inherited from the base class and overridden by this class are replaced with the addresses of the overridden functions (or the corresponding adjustor secondary entry points), - At negative offsets, offsets to the base classes are generated if used by adjustor secondary entry points.
Informally, each of these vtables has a name in the form Base-in-Derived vtable, where Base is a base class and Derived is the derived class. Each vtable pointer in an object addresses one of
these vtables for the class. The vtable pointer of an A subobject within a B object would address the A-in-B vtable.
The vtable copied from the primary base class is also called the primary vtable; it is addressed by the vtable pointer at the top of the object. The other vtables of the class are called secondary
vtables; they are addressed by vtable pointers inside the object.
Aside from the function pointer entries that correspond to those of the primary base class, the primary vtable holds the following additional entries at its tail:- Entries for virtual functions introduced by this class - Entries for overridden virtual functions not already in the vtable. (These are also called replicated entries because they are already in the secondary vtables of the class.) [I wonder if this is actually needed, this seems to be a consequence of RRBC]
The primary vtable, therefore, has the base class functions appearing before the derived class functions. The primary vtable can be viewed as two vtables accessed from a shared vtable pointer.
Note Another bene?t of replicating virtual function entries is that it reduces the number of this pointer adjustments during virtual calls. Without replication, there would be more cases where the this pointer would have to be adjusted to access a secondary vtable prior to the call. These additional cases would be exactly those where the function is overridden in the derived class, implying an additional thunk adjustment back to the original pointer. Thus replication saves
two adjustments for each virtual call to an overridden function introduced by a non-primary base class.
Category 3
This category is for a class that inherits only virtual base classes, and the virtual base classes have no base classes.
The class has a vtable for each virtual base class that has a vtable. These are all secondary vtables and are constructed from copies of the base class vtables according to the same rules as in Category 2. The vtable pointers of the virtual base subobjects within the object address these vtables.
The class also has a vtable that is not copied from the virtual base class vtables. This vtable is the primary vtable of the class and addressed by the vtable pointer at the top of the object, which is not shared. It holds the following function pointer entries:- Entries for virtual functions introduced by this class - Entries for overridden virtual functions. (These are also called replicated entries, because they are already in the secondary vtables of the class)
The primary vtable also has virtual base offset entries to allow ?nding the virtual base subobjects. There is one virtual base offset entry for each virtual base class. For a class that inherits only virtual bases, the entries are in the reverse order in which the virtual bases appear in the class declaration, that is, the entry for the leftmost virtual base is closest to the address point of the vtable.
Category 4
This category is for a class that directly or indirectly inherits base classes that are either virtual or non-virtual.
The rules for constructing vtables of the class are a combination of the rules from Categories 2 and 3, and for the most part can be determined inductively. However the rules for placing virtual base offset entries in the vtables requires elaboration.
The primary vtable has virtual base offset entries for all virtual bases directly or indirectly inherited by the class. Each secondary vtable has entries only for virtual bases visible to the
corresponding base class. The entries in the primary vtable are ordered so that entries for virtual bases visible to the primary base class appear below entries for virtual bases only visible to this class.
For virtual bases only visible to this class, the entries are in the reverse order in which the virtual bases are encountered in a depth-?rst, left-to-right traversal of the inheritance graph formed by the class de?nitions. Note that this does not follow the order that virtual bases are placed in the object.
[To be discussed] Vtables for partially constructed objects
In some situations, a special vtable, called a construction vtable is used during the execution of base class constructors and destructors. These vtables are for speci?c cases of virtual inheritance.
During the construction of a class object, the object assumes the type of each of its base classes, as each base class subobject is constructed. RTTI queries in the base class constructor will return the type of the base class, and virtual calls will resolve to member functions of the base class rather than the complete class. Normally, this behavior is accomplished by setting, in the base class constructor, the object's vtable pointers to the addresses of the vtables for the base class.
However, if the base class has direct or indirect virtual bases, the vtable pointers have to be set to the addresses of construction vtables. This is because the normal base class vtables may not hold the correct virtual base index values to access the virtual bases of the object under construction, and adjustment addressed by these vtables may hold the wrong this parameter adjustment if the adjustment is to cast from a virtual base to another part of the object. The problem is that a complete object of a base class and a complete object of a derived class do not have virtual bases at the same offsets.
A construction vtable holds the virtual function addresses and the RTTI information associated with the base class and the virtual base indexes and the addresses of adjustor entry points with this parameter adjustments associated with objects of the complete class.
To ensure that the vtable pointers are set to the appropriate vtables during base class construction, a table of vtable pointers, called the VTT, which holds the addresses of construction and non-construction vtables is generated for the complete class. The constructor for the complete class passes to each base class constructor a pointer to the appropriate place in the VTT where the base class constructor can ?nd its set of vtables. Construction vtables are used in a similar way during the execution of base class destructors.
Subscribe to:
Posts (Atom)