我要在clistctrl控件中添加按钮,每增加一行,在第m_iBtnColumn列要添加一个按钮,这个按钮是始终可见的。
我该怎么实现这个功能,我现在重载了CListCtrl,在OnPaint()函数中这样做:先删除原来的按钮,再添加新按钮,但是有时点击按钮时,会失去焦点,而且点多了,会出错,代码如下: CArray<CButton*,CButton*> m_ButtonList;void CListCtrlEx::OnPaint()
{
///删除原来的Button
int iBtnCount;
iBtnCount = m_ButtonList.GetSize();
TRACE1("iBtnCount = %d\n",iBtnCount);
for(int i = 0;i < iBtnCount;i++)
{
CButton *pBn;
pBn = m_ButtonList.GetAt(0);
m_ButtonList.RemoveAt(0);
pBn->DestroyWindow();
if(pBn)
delete pBn;
}
// m_ButtonList.RemoveAll();
TRACE1("After iBtnCount = %d\n",m_ButtonList.GetSize()); ////创建新Button
CHeaderCtrl *pHeader = GetHeaderCtrl();
int iListCount;
iListCount = GetItemCount();
TRACE1("*****************Item Count = %d\n",iListCount);
for(i = 0;i < iListCount; i++)
{
DWORD dwStyle;
CRect ColRt;
CRect rt;
pHeader->GetItemRect(m_iBtnColumn,&ColRt);
GetItemRect(i,&rt,LVIR_LABEL);
rt.top += 1;
rt.bottom -=1;
rt.left += ColRt.left;
rt.right = rt.left + ColRt.Width() - 4;
dwStyle = WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON;
CButton *pButn= new CButton();
pButn->Create("发送",dwStyle,rt,this,BUTTON_ID + i);
// pButn->SetButtonStyle()
pButn->ShowWindow(SW_SHOWNORMAL);
m_ButtonList.Add(pButn);
TRACE1("^^^^^^^^^^^^^^^^^^^Button Count = %d\n",m_ButtonList.GetSize());
}
CListCtrl::OnPaint();
}
请高手指点,我哪里出错了??这样做是个好方案吗,该怎么实现?
我该怎么实现这个功能,我现在重载了CListCtrl,在OnPaint()函数中这样做:先删除原来的按钮,再添加新按钮,但是有时点击按钮时,会失去焦点,而且点多了,会出错,代码如下: CArray<CButton*,CButton*> m_ButtonList;void CListCtrlEx::OnPaint()
{
///删除原来的Button
int iBtnCount;
iBtnCount = m_ButtonList.GetSize();
TRACE1("iBtnCount = %d\n",iBtnCount);
for(int i = 0;i < iBtnCount;i++)
{
CButton *pBn;
pBn = m_ButtonList.GetAt(0);
m_ButtonList.RemoveAt(0);
pBn->DestroyWindow();
if(pBn)
delete pBn;
}
// m_ButtonList.RemoveAll();
TRACE1("After iBtnCount = %d\n",m_ButtonList.GetSize()); ////创建新Button
CHeaderCtrl *pHeader = GetHeaderCtrl();
int iListCount;
iListCount = GetItemCount();
TRACE1("*****************Item Count = %d\n",iListCount);
for(i = 0;i < iListCount; i++)
{
DWORD dwStyle;
CRect ColRt;
CRect rt;
pHeader->GetItemRect(m_iBtnColumn,&ColRt);
GetItemRect(i,&rt,LVIR_LABEL);
rt.top += 1;
rt.bottom -=1;
rt.left += ColRt.left;
rt.right = rt.left + ColRt.Width() - 4;
dwStyle = WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON;
CButton *pButn= new CButton();
pButn->Create("发送",dwStyle,rt,this,BUTTON_ID + i);
// pButn->SetButtonStyle()
pButn->ShowWindow(SW_SHOWNORMAL);
m_ButtonList.Add(pButn);
TRACE1("^^^^^^^^^^^^^^^^^^^Button Count = %d\n",m_ButtonList.GetSize());
}
CListCtrl::OnPaint();
}
请高手指点,我哪里出错了??这样做是个好方案吗,该怎么实现?
你在OnPaint中添加删除按钮,严重影响效率!
要知道,不管有没有添加行,只要你的控件的客户区需要重绘,都会调用这个函数.就是不管你有没有添加新行,它都很可能进行删除添加按钮.
如果是这样的话.可以在添加行的函数中在CLsitCtrl的最后添加一行,再添加对应的按钮.
如果是在CLsitCtrl的中间插入一行的话,为了保持其对应关系,只有象你那样全部删除再添加.你要保持主要是行和按钮的一一对应关系.
我主要说的是添加一个函数来处理添加/插入CLsitCtrl的行操作和添加对应的按钮.
说的太乱了,不知道你明白没有.
{
CButton *pBn;
pBn = m_ButtonList.GetAt(0);
m_ButtonList.RemoveAt(0);
pBn->DestroyWindow();
if(pBn)
delete pBn;
}
该成 CButton *pBn=NULL;
for(int i = 0;i < iBtnCount;i++)
{
pBn = m_ButtonList.GetAt(0);
m_ButtonList.RemoveAt(0);
pBn->DestroyWindow();
if(pBn)
{
delete pBn;
pBn=NULL;
}
}
我认为是造成你的"有时点击按钮时,会失去焦点,而且点多了,会出错"的主要原因.
你把添加按钮的操作放在OnPaint中,只要是操作正确的话,虽然效率低,但不会出错.
而变宽,我需要有这个功能。
方法1,先CListCtrl::InsertItem(nItem, lpszItem ),再添加按钮
方法2.因为在CListCtrl中,每行都差不多,调用上一行的"骗骗"它.
哎,这样的话虽然计算机会轻松点,但你会累点!呵呵,
我现在想自己重载headerCtrl被拖动的函数,然后MoveWindow,把按钮移到新位置,
也这样也不用重新删除,再添加,不过我响应LVN_BEGINRDRAG和HDN_BEGINDRAG,还有HDN_ITEMCHANGING,为什么,拖动header头,改变列宽时,消息都走不到这些消息,
我该怎么处理呢
CSortList::CSortList(CImageRetrievalView* pv)
{
m_bAsc= TRUE;
//this->m_nSortedCol = -1;
CreateSortIcons();
//GetHeaderCtrl()->SetImageList(&m_imglstSortIcons);
pView = pv;
}CSortList::~CSortList(void)
{
m_imglstSortIcons.DeleteImageList();
m_bmpUpArrow.DeleteObject();
m_bmpDownArrow.DeleteObject();
}//IMPLEMENT_DYNCREATE(CsercurityView, CFormView)
BEGIN_MESSAGE_MAP(CSortList, CListCtrl)
ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnLvnColumnclick)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSortList message handlersvoid CSortList::OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMListView = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
// TODO: Add your control notification handler code here
//NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if( pNMListView->iSubItem == m_nSortedCol )
m_bAsc = !m_bAsc;
else
{
m_bAsc = FALSE;
m_nSortedCol = pNMListView->iSubItem;
}
SortItems( ListCompare, (DWORD)this );
SetSortIcon();
for (int i=0;i<this->GetItemCount();i++)
this->SetItemData(i, i);
pView->Invalidate();
*pResult = 0;
}
void CSortList::CreateSortIcons()
{
if (!m_imglstSortIcons.m_hImageList)
{
COLORMAP cm = {RGB(0, 0, 0), GetSysColor(COLOR_GRAYTEXT)};
m_imglstSortIcons.Create (9, 5, ILC_COLOR24 | ILC_MASK, 2, 0);
m_bmpUpArrow.LoadMappedBitmap(IDB_HDRUP, 0, &cm, 1);
m_nUpArrow = m_imglstSortIcons.Add(&m_bmpUpArrow, RGB(255, 255, 255));
m_bmpDownArrow.LoadMappedBitmap(IDB_HDRDOWN, 0, &cm, 1);
m_nDownArrow = m_imglstSortIcons.Add(&m_bmpDownArrow, RGB(255, 255, 255));
}
}void CSortList::SetSortIcon()
{
CHeaderCtrl* pHeaderCtrl = this->GetHeaderCtrl();
ASSERT(pHeaderCtrl);pHeaderCtrl->SetImageList(&m_imglstSortIcons);
for( int col = 0; col< GetHeaderCtrl()->GetItemCount(); col++ )
{
HDITEM hdrItem = { 0,};hdrItem.mask = HDI_FORMAT | HDI_IMAGE;BOOL ret = pHeaderCtrl->GetItem(col-1, &hdrItem);
ret = pHeaderCtrl->GetItem(col+1, &hdrItem);
ret = pHeaderCtrl->GetItem(col, &hdrItem);
if ( m_nSortedCol == col)
{
hdrItem.fmt = hdrItem.fmt & HDF_JUSTIFYMASK | HDF_IMAGE | HDF_STRING | HDF_BITMAP_ON_RIGHT;
if( m_bAsc )
hdrItem.iImage = m_nUpArrow;
else
hdrItem.iImage = m_nDownArrow;
}
else
{
hdrItem.fmt = hdrItem.fmt & HDF_JUSTIFYMASK | HDF_STRING;
}
pHeaderCtrl->SetItem(col, &hdrItem);
}
}bool CSortList::GetFullRowSelect()
{
return ( GetExtendedStyle()&LVS_EX_FULLROWSELECT) == LVS_EX_FULLROWSELECT;
}void CSortList::SetFullRowSelect( bool bFullRowSelect )
{
if( bFullRowSelect )
SetExtendedStyle( GetExtendedStyle()|LVS_EX_FULLROWSELECT );
else
SetExtendedStyle( GetExtendedStyle()&(~LVS_EX_FULLROWSELECT) );
}bool CSortList::GetGridLines()
{
return ( GetExtendedStyle() & LVS_EX_GRIDLINES ) == LVS_EX_GRIDLINES;
}void CSortList::SetGridLines( bool bGridLines )
{
if( bGridLines )
SetExtendedStyle( GetExtendedStyle()|LVS_EX_GRIDLINES );
else
SetExtendedStyle( GetExtendedStyle()&(~LVS_EX_GRIDLINES) );
}int CALLBACK CSortList::ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
CSortList* pList=(CSortList*)lParamSort;
int nItem1, nItem2; LVFINDINFO FindInfo;
FindInfo.flags = LVFI_PARAM; // 指定查找方式
FindInfo.lParam = lParam1;
nItem1 = pList->FindItem(&FindInfo, -1); // 得到对应Item索引
FindInfo.lParam = lParam2;
nItem2 = pList->FindItem(&FindInfo, -1); if((nItem1 == -1) || (nItem2 == -1))
{
TRACE("无法找到!\n");
return 0;
} CString Str1,Str2;
Str1 = pList->GetItemText(nItem1, pList->m_nSortedCol); // 得到排序列的Text
Str2 = pList->GetItemText(nItem2, pList->m_nSortedCol);
int iCompRes = 0;
if(Str1 > Str2)
iCompRes = 1;
else if(Str1 == Str2)
iCompRes = 0;
else
iCompRes = -1;if(pList->m_bAsc)
return iCompRes;
else
return iCompRes*-1;
return 0;
}
你可以先试试简单点的Invalidate(),让整个客户区重绘.
不行的话,重绘背景,返回TRUE.
我想也就这两方面的原因吧
通常来说 界面的 画啊,鼠标等动作 都是 有对应的 消息,需要修改界面 都可以通过对消息的处理 或者重载函数 等实现。。明白这些 可以去msdn 里面查找。同时 对你的界面设计帮助会比较大。 不好意思,我没有去帮你实现代码, 空说了一些。希望有所帮助。
其他的还有个小问题,请教一下,就是我加的按钮,其他都还满意,就是滚动条,往下滚动时,按钮会把HeaderCtrl盖上,这不是我想要的结果,我需要的是HeaderCtrl在最上边,能提供些思路吗
添加一个InsertItemEx函数,在其中添加按钮
重载OnPaint(知道效率不高),在其中计算然后Btn->MoveWindow,把按钮移到新位置
最后也遇到了LZ的问题。。就是滚动条,往下滚动时,按钮会把HeaderCtrl盖上,这不是我想要的结果,我需要的是HeaderCtrl在最上边,能提供些思路吗不过,最终我解决了:
办法就是:
if ( rt.top < ColRt.bottom) //按钮的顶端已经超过了HeaderCtrl的底端
pBtn->ShowWindow(SW_HIDE);
else
pBtn->ShowWindow(SW_SHOWNORMAL);