I want to create a header checkbox for the listcontrol column in windows xp.And I am able to create a checkbox very successfully but the problem here is the alignment is of checkbox is not proper to the checkboxes in the listcontrol and one more problem is when the theme is changed the size of checkbox is becoming bigger.Here is the code I am using in the OnInitDialog().
BOOL CCheckLCDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
pcHeaderCtrl->Attach (m_listCtrl.GetHeaderCtrl()->GetSafeHwnd());
pcHeaderCtrl->SetDlgCtrlID(IDC_LISTVIEWCONTROL_HEADER);
m_ListView_HeaderCtrlID = (*pcHeaderCtrl).GetDlgCtrlID();
CRect rect;
m_listCtrl.GetClientRect(rect);
m_listCtrl.InsertColumn(0, _T(""), LVCFMT_LEFT, 80);
m_listCtrl.InsertColumn(1, _T("Name"), LVCFMT_LEFT, 150);
m_listCtrl.InsertColumn(2, _T("Country"), LVCFMT_LEFT, rect.Width() - 230);
CString cs(_T(""));
for(int i = 0; i < 5; i++)
{
cs.Format(_T("%d"), i+1);
m_listCtrl.InsertItem(i, cs);
cs.Format(_T("It's the %d item"), i+1);
m_listCtrl.SetItemText(i, 2, cs);
}
m_listCtrl.SetExtendedStyle( m_listCtrl.GetExtendedStyle() | LVS_EX_CHECKBOXES);
//Header Checkbox is being created in this method.
Init();
return TRUE; // return TRUE unless you set the focus to a control
}
BOOL CCheckLCDemoDlg::Init()
{
if (m_blInited)
return TRUE;
HWND HeaderCtrl = GetDlgItem(IDC_LISTVIEWCONTROL_HEADER)->GetSafeHwnd();
//Everything is being done in this function "CreateCheckboxImageList"
//Function Prototype HIMAGELIST CreateCheckboxImageList(HWND hWnd,HDC hDC,int nSize,COLORREF crBackground,BOOL bUseVisualThemes)
//nSize- refers the size of the checkbox to be created.
HIMAGELIST hil = HDCheckboxImageList::CreateCheckboxImageList(HeaderCtrl,GetDC()->GetSafeHdc(), 16, GetSysColor(COLOR_WINDOW), TRUE);
m_checkImgList.Attach(hil);
pcHeaderCtrl->SetImageList(&m_checkImgList);
HDITEM hdItem;
hdItem.mask = HDI_IMAGE | HDI_FORMAT;
pcHeaderCtrl->GetItem(0, &hdItem);
hdItem.iImage = 1;
hdItem.fmt |= HDF_IMAGE;
pcHeaderCtrl->SetItem(0, &hdItem);
m_blInited = TRUE;
::DeleteObject(hil);
return TRUE;
}
HIMAGELIST CreateCheckboxImageList(HWND hWnd,HDC hDC,
int nSize,
COLORREF crBackground,
BOOL bUseVisualThemes)
{
TRACE(_T("in CreateCheckboxImageList: nSize=%d\n"), nSize);
_ASSERTE(hDC);
_ASSERTE(nSize > 0);
HIMAGELIST hImageList = 0;
//=========================================================================
//
// CHECKBOX IMAGES
//
// From MSDN: "To indicate that the item has no state image, set the
// index to zero. This convention means that image zero in
// the state image list cannot be used as a state image."
//
// Note that comparable
// hot image = cold image index OR 8.
// disabled image = index OR 4.
//
//=========================================================================
static struct CHECKBOXDRAWDATA
{
TCHAR * pszDesc; // description for debugging
int nStateId; // for DrawThemeBackground
UINT nState; // for DrawFrameControl
}
cbdd[] =
{
// cold -----------------------------------------------------------------------------------
/*0000*/_T("unused"), 0, 0,
/*0001*/_T("unchecked normal"), CBS_UNCHECKEDNORMAL, DFCS_BUTTONCHECK | DFCS_FLAT,
/*0010*/_T("checked normal"), CBS_CHECKEDNORMAL, DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_FLAT,
#if 0
/*0011*/_T("tri-state normal"), CBS_MIXEDNORMAL, DFCS_BUTTON3STATE | DFCS_CHECKED | DFCS_FLAT,
/*0100*/_T("unused"), 0, 0,
/*0101*/_T("unchecked disabled"), CBS_UNCHECKEDDISABLED, DFCS_BUTTONCHECK | DFCS_FLAT | DFCS_INACTIVE,
/*0110*/_T("checked disabled"), CBS_CHECKEDDISABLED, DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_FLAT | DFCS_INACTIVE,
/*0111*/_T("tri-state disabled"), CBS_MIXEDDISABLED, DFCS_BUTTON3STATE | DFCS_CHECKED | DFCS_FLAT | DFCS_INACTIVE,
// hot ------------------------------------------------------------------------------------
/*1000*/_T("unused"), 0, 0,
/*1001*/_T("unchecked normal"), CBS_UNCHECKEDHOT, DFCS_BUTTONCHECK | DFCS_FLAT,
/*1010*/_T("checked normal"), CBS_CHECKEDHOT, DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_FLAT,
/*1011*/_T("tri-state normal"), CBS_MIXEDHOT, DFCS_BUTTON3STATE | DFCS_CHECKED | DFCS_FLAT,
/*1100*/_T("unused"), 0, 0,
/*1101*/_T("unchecked disabled"), CBS_UNCHECKEDDISABLED, DFCS_BUTTONCHECK | DFCS_FLAT | DFCS_INACTIVE,
/*1110*/_T("checked disabled"), CBS_CHECKEDDISABLED, DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_FLAT | DFCS_INACTIVE,
/*1111*/_T("tri-state disabled"), CBS_MIXEDDISABLED, DFCS_BUTTON3STATE | DFCS_CHECKED | DFCS_FLAT | DFCS_INACTIVE,
#endif
NULL, 0, 0 // last entry
};
if (nSize > 0)
{
const int nBmpWidth = nSize;
const int nBmpHeight = nSize;
const int nImages = sizeof(cbdd)/sizeof(cbdd[0]) - 1;
_ASSERTE(nImages == 3);
CDC dc;
dc.Attach(hDC);
CBitmap bmpCheckboxes;
// create bitmap with requested size
if (bmpCheckboxes.CreateCompatibleBitmap(&dc, nBmpWidth * nImages, nBmpHeight))
{
// create imagelist for 16 images
hImageList = ImageList_Create(nBmpWidth, nBmpHeight, ILC_COLOR32, nImages, 1);
_ASSERTE(hImageList);
if (hImageList)
{
// create dc for imagelist bitmap
CDC dcMem;
if (dcMem.CreateCompatibleDC(&dc))
{
// create dc for one 16x16 image
CBitmap bmpImage;
bmpImage.CreateCompatibleBitmap(&dc, 16, 16);
//bmpImage.CreateCompatibleBitmap(&dc, 13, 13);
CDC dcImage;
dcImage.CreateCompatibleDC(&dc);
HBITMAP hOldImage = (HBITMAP) dcImage.SelectObject(bmpImage);
RECT rectImage1 = { 0,0,15,15 };
// open theme for checkbox
HTHEME hTheme = NULL;
hTheme = (bUseVisualThemes &&
IsThemeActive() &&
IsAppThemed()) ?
OpenThemeData(NULL, L"BUTTON") : NULL;
// initialize imagelist bitmap
HBITMAP hOldBmp = (HBITMAP) dcMem.SelectObject(bmpCheckboxes);
dcMem.FillSolidRect(0, 0, nBmpWidth*nImages, nBmpHeight,
crBackground);
int nImageWidth = nBmpWidth - 2; // allow 2 for border
int nImageHeight = nBmpHeight - 2;
int nImageLeft = (nBmpWidth - nImageWidth) / 2;
int nImageTop = (nBmpHeight - nImageHeight) / 2;
RECT rectImage = { nImageLeft,
nImageTop,
nImageLeft+nImageWidth,
nImageTop+nImageHeight };
//TRACERECT(rectImage);
// loop thru checkboxes
for (int i = 0; cbdd[i].pszDesc != NULL; i++)
{
//dcImage.FillSolidRect(0, 0, 16, 16, crBackground);
dcImage.FillSolidRect(0, 0, 16, 16, crBackground);
if (_tcscmp(cbdd[i].pszDesc, _T("unused")) == 0)
{
// unused image slot
// note that we skip the first image - they are 1-based
}
else
{
if (hTheme)
{
DrawThemeBackground(hTheme, dcImage,
BP_CHECKBOX, cbdd[i].nStateId, &rectImage1,
NULL);
DrawThemeEdge(hTheme, dcImage,
BP_CHECKBOX, cbdd[i].nStateId, &rectImage1, 0, BF_ADJUST|BF_RECT,
NULL);
}
else
{
dcImage.DrawFrameControl(&rectImage1, DFC_BUTTON,
cbdd[i].nState);
}
// size checkbox as requested
dcMem.StretchBlt((rectImage.left-(2)), 0, nSize, nSize,
&dcImage, 0, 0, 16, 16, SRCCOPY);
}
rectImage.left += nBmpWidth;
rectImage.right += nBmpWidth;
//TRACERECT(rectImage);
}
if (hTheme)
{
CloseThemeData(hTheme);
hTheme = NULL;
}
dcImage.SelectObject(hOldImage);
dcMem.SelectObject(hOldBmp);
BOOL bDelDcRet = dcMem.DeleteDC();
BOOL bDelImageDcRet = dcImage.DeleteDC();
// add imagelist bitmap (16 checkboxes) to imagelist
ImageList_Add(hImageList, bmpCheckboxes, 0);
}
else
{
TRACE(_T("ERROR - failed to create DC\n"));
}
}
else
{
TRACE(_T("ERROR - failed to create image list\n"));
}
}
else
{
TRACE(_T("ERROR - failed to create bitmap\n"));
}
}
else
{
TRACE(_T("ERROR - bad parameters\n"));
}
return hImageList;
}
}
And the when I run the application the listcontrol header checkbox is as follows,
For a trail and error I passed nSize as 16 ,What size needs to be passed which should be dynamical not statical?
When theme changed to windows classic it is as follows.
Can anyone please help me what is the size to be passed as parameter for creating the checkbox which should exactly match with the item checkbox and same thing when theme is changed.
Aucun commentaire:
Enregistrer un commentaire