Как сделать, чтобы флажок заголовка столбца listcontrol был идеально выровнен в соответствии с флажками элемента?
Я хочу создать флажок заголовка для столбца listcontrol в Windows XP. И я могу создать флажок очень успешно, но проблема здесь в том, что выравнивание флажка не соответствует флажкам в listcontrol, и еще одна проблема заключается в том, когда тема изменена, размер флажка становится больше. Вот код, который я использую в 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;
}
}
И когда я запускаю приложение, флажок заголовка listcontrol выглядит следующим образом,
Для следа и ошибки я передал nSize как 16, Какой размер должен быть передан, который должен быть динамическим, а не статическим?
Когда тема изменилась на Windows Classic, это выглядит следующим образом.
Может кто-нибудь, пожалуйста, помогите мне, какой размер будет передаваться в качестве параметра для создания флажка, который должен точно соответствовать флажку элемента и то же самое, когда тема меняется.
1 ответ
Невозможно сделать то, что вы хотите, потому что выравнивание флажков не является стандартным размером. Вы имитируете флажок в элементе управления заголовком, рисуя непосредственно на нем, поэтому лучше всего проверить с различными темами, которые вы хотите поддерживать, а затем отрегулировать смещение в методе CreateCheckboxImageList(), чтобы оно соответствовало смещению, при котором флажки в список управления нарисован.