📄 gfxlistctrl.cpp
字号:
{
GetSubItemRect(i+1,iCol,rc);
InvalidateRect(rc, true);
}
}
}
//
void CGfxListCtrl::OnInit()
{
//保证列表控件为报表模式
if ((GetStyle()&LVS_TYPEMASK) == LVS_REPORT)
{
//自定义标题控件子类化
HWND hHead = ::GetDlgItem(m_hWnd,0);
VERIFY(wndHeader.SubclassWindow(hHead));
TRACE0("Header subclassed.\n");
wndToolTip.Create(this);
wndToolTip.ShowWindow(SW_HIDE);
ModifyStyle(0,WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
}
}
void CGfxListCtrl::OnPaint()
{
int iItemCount = GetItemCount();
CRect rcAllLabels, rc;
if (iItemCount > 0)
{
GetItemRect(0,rcAllLabels,LVIR_BOUNDS);
if (dwFlag&fHighRowSelect)
{
if (rcAllLabels.right<m_cxClient)
{
CPaintDC dc(this);
CRect rcClip;
dc.GetClipBox(rcClip);
if (!rcClip.IsRectEmpty())
{
rcClip.left = min(rcAllLabels.right-1, rcClip.left);
rcClip.right = m_cxClient;
InvalidateRect(rcClip,FALSE);
}
}
}
}
const MSG *msg = GetCurrentMessage();
DefWindowProc( msg->message, msg->wParam, msg->lParam );
if (iItemCount == 0)
{
GetClientRect(rc);
CRect hrc;
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
ASSERT(pHeader);
pHeader->GetClientRect(hrc);
rc.top += hrc.Height() + 2;
rc.bottom += 20;
CClientDC dc(this);
COLORREF ocrt = dc.SetTextColor(GetSysColor(COLOR_GRAYTEXT));
int obk = dc.SetBkMode(TRANSPARENT);
CFont * oft = dc.SelectObject(&ftNormal);
dc.FillSolidRect(rc, m_clrTextBk);
dc.DrawText(CString("Nessun elemento presente nella lista"),rc, DT_SINGLELINE|DT_CENTER);
dc.SelectObject(oft);
dc.SetBkMode(obk);
dc.SetTextColor(ocrt);
if (dwFlag&fScrollBarAlways) EnableScrollBar(SB_HORZ, ESB_DISABLE_BOTH);
}
else
{
if (dwFlag&fScrollBarAlways)
{
CRect rcAllLabels;
GetItemRect(0,rcAllLabels,LVIR_BOUNDS);
EnableScrollBar(SB_HORZ, rcAllLabels.Width() < m_cxClient ? ESB_DISABLE_BOTH : ESB_ENABLE_BOTH);
}
}
}
//确定点击位置所在的行索引和对应的列索引
int CGfxListCtrl::HitTestEx(CPoint & point, int * col) const
{
int colnum = 0;
int row = HitTest(point, NULL);
if (col) *col = 0;
//确定列表视图控件为LVS_REPORT风格
if ((GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT) return row;
//得到最顶端和最低端的的可见行
row = GetTopIndex();
int bottom = row + GetCountPerPage();
if (bottom > GetItemCount()) bottom = GetItemCount();
int nColumnCount = GetColumnCount();
for( ;row <=bottom;row++)//row < bottom
{
CRect rect;
GetItemRect(row, &rect, LVIR_BOUNDS);
if (rect.PtInRect(point))
{
for (colnum = 0; colnum < nColumnCount; colnum++)
{
int colwidth = GetColumnWidth(colnum);
if (point.x >= rect.left && point.x <= (rect.left + colwidth))
{
if (col) *col = colnum;
return row;
}
rect.left += colwidth;
}
}
}
return -1;
}
void CGfxListCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
CListCtrl::OnLButtonUp(nFlags, point);
}
// 创建组合框控件以编辑指定条目子项
CGfxInCombo * CGfxListCtrl::ComboSubLabel(int nItem, int nCol, bool bEditable, bool bClick)
{
//使用行和列索引,并在创建组合框控件前使指定条目子项可见,然后以合适的尺寸和文本调整创建组合框控件
//保证条目可见
if (!EnsureVisible(nItem, TRUE)) return NULL;
////保证条目子项可见
EnsureSubItemVisible(nCol);
//if(!EnsureSubItemVisible(nCol)) return NULL;
int nColumnCount = GetColumnCount();
int iColWidth = GetColumnWidth(nCol);
if (nCol >= nColumnCount || iColWidth < 5) return NULL;
int offset = 0;
for (int i = 0; i < nCol; i++) offset += GetColumnWidth(i);
CRect rect;
GetItemRect(nItem, &rect, LVIR_BOUNDS);
rect.bottom -= iAutoPreviewHeight;
rect.top ++;
rect.bottom -= 2;
CRect rcClient;
GetClientRect(&rcClient);
LV_COLUMN lvcol;
lvcol.mask = LVCF_FMT;
GetColumn(nCol, &lvcol);
DWORD dwStyle = 0;
//enum { OFFSET_FIRST = 2, OFFSET_OTHER = 6 };
rect.left += offset+OFFSET_OTHER;//+4;
rect.right = rect.left + GetColumnWidth(nCol)- OFFSET_OTHER;// - 3 ;
if (rect.right > rcClient.right) rect.right = rcClient.right;
dwStyle |= WS_CHILD|WS_VISIBLE;
LXHDREX lxhd;
lxhd.iNotifyCode = NTEX_COMBOREQUEST;
lxhd.CtrlId = iCtrlId < 0 ? GetDlgCtrlID() : iCtrlId;
lxhd.iItem = nItem;
lxhd.iSubItem = GetColumnIndex(nCol);
lxhd.dwFlag = 0;
lxhd.dwItemData = GetItemData(nItem);
lxhd.dwMask = LXHDREX::exComboArray;
GetItemTextEx(nItem, nCol, lxhd.csText, &(lxhd.dwItemData));
lxhd.pComboArray = new CStringArray;
ASSERT(lxhd.pComboArray);
if (!SendInfoExMsg(&lxhd))
{
ASSERT(lxhd.pComboArray);
delete lxhd.pComboArray;
return NULL;
}
CGfxInCombo * pCombo = new CGfxInCombo(nItem, nCol, lxhd.csText, lxhd.pComboArray, bEditable, bClick);
pCombo->bLightBorder = pCategoryManager == NULL;
if (dwFlag&fExInfo)
{
lxhd.iNotifyCode = NTEX_ITEMINFO;
CWnd * pWnd = GetReciper();
if (SendInfoExMsg(&lxhd))
{
//设置组合框控件字体
if (lxhd.dwFlag&LXHDREX::exHFont) pCombo->hFontHandle = lxhd.hfText;
else if (lxhd.dwFlag&LXHDREX::exBold) pCombo->hFontHandle = (HFONT) ftBold.GetSafeHandle();
else if (lxhd.dwFlag&LXHDREX::exItalic) pCombo->hFontHandle = (HFONT) ftItalic.GetSafeHandle();
else if (lxhd.dwFlag&LXHDREX::exUnderline) pCombo->hFontHandle = (HFONT) ftUnderline.GetSafeHandle();
else pCombo->hFontHandle = (HFONT) ftNormal.GetSafeHandle();
//设置组合框控件文本颜色
if (lxhd.dwFlag&LXHDREX::exTextColor) pCombo->crColor = lxhd.crText;
}
}
// defie IDC_IPEDIT as you want; is a control id
pCombo->Create(dwStyle, rect, this, IDC_IPEDIT);
return pCombo;
}
// 创建编辑控件以编辑行索引为nItem、列索引为nCol的列表单元
//(bClick=flase表示在编辑控件中全选被编辑文本,bClick=true表示在编辑控件中不选任何内容)
CRichEditCtrl * CGfxListCtrl::EditSubLabel(int nItem, int nCol, bool bClick)
{
//使用行和列索引,并在创建编辑控件前使指定列表单元可见,然后以合适的尺寸和文本调整创建编辑控件
//保证行可见
if (!EnsureVisible(nItem, TRUE)) return NULL;
//保证列可见
EnsureSubItemVisible(nCol);
//if(!EnsureSubItemVisible(nCol)) return NULL;
int nColumnCount = GetColumnCount();
int iColWidth = GetColumnWidth(nCol);
if (nCol >= nColumnCount || iColWidth < 5) return NULL;
int offset = 0;
for (int i = 0; i < nCol; i++) offset += GetColumnWidth(i);
CRect rect;
GetItemRect(nItem, &rect, LVIR_BOUNDS);
rect.bottom -= iAutoPreviewHeight;
rect.top ++;
rect.bottom -= 2;
CRect rcClient;
GetClientRect(&rcClient);
//得到列的对齐方式设置列表单元编辑控件风格
LV_COLUMN lvcol;
lvcol.mask = LVCF_FMT;
GetColumn(nCol, &lvcol);
DWORD dwStyle = WS_CHILD|WS_VISIBLE;
if ((lvcol.fmt&LVCFMT_JUSTIFYMASK) == LVCFMT_LEFT) dwStyle |= ES_LEFT;//why not ES_LEFT|ES_MULTILINE
else if ((lvcol.fmt&LVCFMT_JUSTIFYMASK) == LVCFMT_RIGHT) dwStyle |= ES_RIGHT|ES_MULTILINE;
else dwStyle |= ES_CENTER|ES_MULTILINE;
//enum { OFFSET_FIRST = 2, OFFSET_OTHER = 6 };
rect.left += offset+OFFSET_OTHER;//+4;
rect.right = rect.left + GetColumnWidth(nCol)- OFFSET_OTHER- OFFSET_OTHER;// - 3 ;
if (rect.right > rcClient.right) rect.right = rcClient.right;
DWORD dwData = GetItemData(nItem);
//获取指定列表单元的文本
CString csItem;
GetItemTextEx(nItem, nCol, csItem, &dwData);
//在指定位置上创建编辑控件
CRichEditCtrl *pEdit = new CGfxInEdit(nItem, nCol, csItem, bClick);
pEdit->Create(dwStyle, rect, this, IDC_IPEDIT);
//设置列表单元编辑控件属性
LXHDREX lxhd;
if (dwFlag&fExInfo)
{
lxhd.iNotifyCode = NTEX_ITEMINFO;
lxhd.CtrlId = iCtrlId < 0 ? GetDlgCtrlID() : iCtrlId;
lxhd.iItem = nItem;
lxhd.iSubItem = GetColumnIndex(nCol);
lxhd.dwFlag = 0;
lxhd.dwItemData = dwData;
//获取列表单元附属信息已设置编辑控件
if (SendInfoExMsg(&lxhd))
{
//设置列表单元编辑控件文本字体
if (lxhd.dwFlag&LXHDREX::exHFont) pEdit->SendMessage(WM_SETFONT, (WPARAM) lxhd.hfText, MAKELPARAM(FALSE, 0));
else if (lxhd.dwFlag&LXHDREX::exBold) pEdit->SendMessage(WM_SETFONT, (WPARAM) ftBold.GetSafeHandle(), MAKELPARAM(FALSE, 0));
else if (lxhd.dwFlag&LXHDREX::exItalic) pEdit->SendMessage(WM_SETFONT, (WPARAM) ftItalic.GetSafeHandle(), MAKELPARAM(FALSE, 0));
else if (lxhd.dwFlag&LXHDREX::exUnderline) pEdit->SendMessage(WM_SETFONT, (WPARAM) ftUnderline.GetSafeHandle(), MAKELPARAM(FALSE, 0));
else pEdit->SendMessage(WM_SETFONT, (WPARAM) ftNormal.GetSafeHandle(), MAKELPARAM(FALSE, 0));
//设置列表单元编辑控件文本颜色
if (lxhd.dwFlag&LXHDREX::exTextColor)
{
CHARFORMAT chf;
chf.cbSize = sizeof(CHARFORMAT);
chf.crTextColor = lxhd.crText;
chf.dwMask = CFM_COLOR;
CHARRANGE cr;
pEdit->GetSel(cr);
pEdit->SetSel(0,-1);
pEdit->SetDefaultCharFormat(chf);
pEdit->SetSelectionCharFormat(chf);
pEdit->SetSel(cr);
}
}
}
return pEdit;
}
//处理在列表控件中对列表单元的单击
void CGfxListCtrl::OnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
if (GetFocus() != this) SetFocus();
//获取焦点的屏幕坐标,并将其转换为用户坐标
CPoint point;
GetCursorPos(&point);
ScreenToClient(&point);
int index, colnum;
if ((index = HitTestEx(point, &colnum)) != -1)
{
int cate = -1;
if (pCategoryManager != NULL)
{
//列表为折叠展开态
cate = pCategoryManager->IsListItemACategory(GetItemData(index));
if (cate >= 0)
{
//此条目为目录项条目
if (colnum == 0)
{
//点击了目录项条目的折叠展开按钮
if (pCategoryManager->pCategory[cate].bExpanded)
{
//折叠此目录项
pCategoryManager->RemoveCategoryItems(cate, index, this);
CRect rcAllLabels;
GetItemRect(index,rcAllLabels,LVIR_BOUNDS);
CRect rc;
GetClientRect(&rc);
if (rc.right > rcAllLabels.right)
{
rc.left = rcAllLabels.right;
rc.top = rcAllLabels.bottom;
InvalidateRect(rc, true);
}
}
else
{
//展开此目录项
pCategoryManager->FillCategoryItems(cate, index, this);
}
//设置此目录项的展开标志
pCategoryManager->pCategory[cate].bExpanded = !(pCategoryManager->pCategory[cate].bExpanded);
//重绘此目录项条目
CRect rcLittleBox;
GetSubItemRect(index, 0, rcLittleBox);
rcLittleBox.bottom ++;
rcLittleBox.right ++;
InvalidateRect(rcLittleBox, false);
if (dwFlag&fScrollBarAlways)
{
//列表控件具有滚动风格
//显示水平和垂直滚动条
ShowScrollBar(SB_BOTH);
int iPageItem = GetCountPerPage();
int iItemCount = GetItemCount();
if (iItemCount < iPageItem) EnableScrollBar(SB_VERT, ESB_DISABLE_BOTH);//禁止垂直滚动条上的2个箭头按钮
else EnableScrollBar(SB_VERT, ESB_ENABLE_BOTH);//恢复垂直滚动条上的2个箭头按钮
CRect rcAllLabels;
GetItemRect(0,rcAllLabels,LVIR_BOUNDS);
//禁止或恢复水平滚动条上的2个箭头按钮
EnableScrollBar(SB_HORZ, rcAllLabels.Width() < m_cxClient ? ESB_DISABLE_BOTH : ESB_ENABLE_BOTH);
}
*pResult = 1;
return;
}
}
}
if (iSubItemFocus != colnum)
{
CRect src;
GetSubItemRect(index, iSubItemFocus, src);
InvalidateRect(src);
iSubItemFocus = colnum;
GetSubItemRect(index, iSubItemFocus, src);
InvalidateRect(src);
}
UINT flag = LVIS_FOCUSED;
if ((GetItemState(index, flag) & flag) == flag)
{
if (cate < 0)
{
//此条目非目录项条目
int irealcol = GetColumnIndex(colnum);
//此行可用编辑框编辑则就地生成编辑框对子项进行编辑;
//此行可用组合框编辑则就地生成组合框对子项进行编辑;
//此行可用组合框编辑则就地生成组合框对子项进行编辑;
if (dwhEdit&(1 << irealcol)) EditSubLabel(index, colnum);
else if (dwhCombo&(1 << irealcol)) ComboSubLabel(index, colnum);
else if (dwhComboEx&(1 << irealcol)) ComboSubLabel(index, colnum, true);
}
}
else
{
SetItemState(index, LVIS_SELECTED | LVIS_FOCUSED , LVIS_SELECTED | LVIS_FOCUSED);
}
}
*pResult = 1;
}
//处理LVN_ENDLABELEDIT通告以便使编辑框编辑的结果被接受,并更新列表控件的显示
void CGfxListCtrl::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
LV_ITEM *plvItem = &pDispInfo->item;
*pResult = 0;
if (plvItem->pszText == NULL) return;
//debug
/* CString str11;
str11.Format("%s and %d", ((dwFlag & fAllowMultiChange) ? "multi" : "single"), GetSelectedCount());
AfxMessageBox(str11);*/
//debug
if (dwFlag & fAllowMultiChange && GetSelectedCount() > 1)
{
//若允许多行编辑且有多行被编辑
{
LXHDREX lxhd;
lxhd.iNotifyCode = NTEX_SETTEXT;
lxhd.CtrlId = iCtrlId < 0 ? GetDlgCtrlID() : iCtrlId;
lxhd.dwFlag = 0;
int idx = GetNextItem(-1, LVNI_SELECTED);
while (idx >= 0)
{
lxhd.iItem = idx;
lxhd.iSubItem = GetColumnIndex(plvItem->iSubItem);
lxhd.dwItemData = GetItemData(idx);
lxhd.csText = plvItem->pszText;
if (SendInfoExMsg(&lxhd)) ModifyItemEx(lxhd.iItem, plvItem->iSubItem, lxhd.dwItemData, lxhd.csText);
else ModifyItemEx(lxhd.iItem, plvItem->iSubItem, lxhd.dwItemData);
idx = GetNextItem(idx, LVNI_SELECTED);
}
SetFocus();
return;
}
}
if (plvItem->pszText != NULL)
{
LXHDREX lxhd;
lxhd.iNotifyCode = NTEX_SETTEXT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -