得到0

// HitTestEx   
- Determine the row index and column index for a point
// Returns     
- the row index or -1 if point is not over a row
// point       
- point to be tested.
// col         
- to hold the column index
 
//
考虑到滚动条的情况
int
 CMyListCtrl::HitTestEx(CPoint &point, int
 *col) const

{
        
int
 colnum = 0;
        
int
 row = HitTest( point, NULL );
        

        
if
( col ) *col = 0;
 
        
// Make sure that the ListView is in LVS_REPORT

        
if
( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
               
return
 row;
 
        
// Get the top and bottom row visible

        
row = GetTopIndex();
        
int
 bottom = row + GetCountPerPage();
        
if
( bottom > GetItemCount() )   
//
么有滚动条
               
bottom = GetItemCount();
        

        
// Get the number of columns

        
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
        
int
 nColumnCount = pHeader->GetItemCount();
 
        
// Loop through the visible rows

        
for
( ;row <= bottom;row++)
        
{
               
// Get bounding rect of item and check whether point falls in it.

               
CRect rect;
               
GetItemRect( row, &rect, LVIR_BOUNDS );
               
if
( rect.PtInRect(point) )
               
{
                       
// Now find the column

                       
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;
}

 

 

CListCtrl 类成员

CListCtrl::HitTest

int HitTest(LVHITTESTINFO* pHitTestInfo) const
int HitTest(CPoint pt,UINT* pFlags=NULL) const

返回值:
返回参数pHitTestInfo 指定位置的项的索引,否则为-1

参数: pHitTestInfo 含有要进行击中测试的位置以及接受击中测试有关结果信息的LVHITTESTINFO 结构的地址。
pt
被测试的指针。
pFlags
指向接受测试结果信息的整数的指针。请参阅联机文档 平台SDK” 中有关LVHITTESTINFO 结构的flags 成员的注解。

说明:
如果有,则决定哪一个列表视图项在指定的位置上。
可以通过使用结构中flags 成员的LVHT_ABOVE, LVHT_BELOW,LVHT_TOLEFT 以及LVHT_TORIGHT 的值来决定是否滚动列表视图控件的内容。上述两种标志可以自由组合,例如,假设其位于客户区域的左上角。
可以通过测试结构中flags 成员的LVHT_ONITEM 值来决定是否给定的位置位于列表视图项的上方。该数值通过结构flags 成员中的 LVHT_ONITEMICONLVHT_ONITEMLABEL,LVHT_ONITEMSTATEICON 的值的位或运算而获取。

 

 

 

如何使CListCtrl 完全可编辑

专题1: 如何使CListCtrl 完全可编辑?

1.         背景 : 我们知道如果CListCtrl 是报表样式, 那么CListCtrl 所提供的编辑功能只局限于第一列. 也就是说只有第一列可编辑. 这样显然无法满足一般数据库的要求. 我们想要每个子项都能编辑.

2.         思路 : CEdit 是一个很好的可控制编辑控件. 如何把CEdit 和我们的CListCtrl 联系起来? 一种很好的想法是------ 一般我们如果想编辑某一项, 那么就应该去双击. 双击以后就让CEdit 在那里显示, 当然要把大小调整和子项表格一样. 如果CEdit 失去了焦点, 表示修改完毕, 那么立即更改子项的数据, 同时让CEdit 隐藏. 因为每次只能编辑一项, 所以只需要一个CEdit 就够了.

3.         方法:

(1)      首先从CListCtrl 派生一个类, 其他已经有的变量或者函数设置我已经介绍, 如果不清楚的读者, 可以去参考 基础篇”.

(2)      有一点可以肯定, 我们必须响应双击事件:

void Cmylist::OnLButtonDblClk(UINT nFlags, CPoint point)

{

int index; // 行号

int colnum; // 列号

GetWindowRect(r); // 稍后说明

GetParent()->ScreenToClient(r); // 稍后说明

if((index=HitTestEx(point,&colnum))!=-1)

    EditSubItem(index,colnum);

CListCtrl::OnLButtonDblClk(nFlags, point);

}

其中HitTestEx 是用来求出双击点所在的行列号, 如果行号不为-1, 那么就调用函数EditSubItem. 这个函数会根据行列号求出该子项具体坐标, 方便CEdit 调整位置.

(3)      如何求出行列号? 行号是很好求出来的 , 但是列号就不是很简单了, 必须详细判断.

int Cmylist::HitTestEx(CPoint &point, int *pcolumn)

{

       int columnNum=0;

// 获取页面内首行索引号, 不一定是0, 要考虑滚动条的情况

int row=GetTopIndex();

// GetCountPerPage() 获取在页面内行的总数

       int bottom=row+this->GetCountPerPage();

        // 防止超出范围

       if(bottom>this->GetItemCount())

              bottom=GetItemCount();

        // 获取列的总数

       int ncolumncount=this->GetHeaderCtrl()->GetItemCount();

        // 可以肯定双击点肯定在页面内, 因此从页面首行索引号开始判断

       for(;row<=bottom;++row)

       {

              CRect rect;

               // 求出行的rect

              GetItemRect(row,&rect,LVIR_BOUNDS);

               // 点是否在行的矩形内

              if(rect.PtInRect(point))

               // 如果点在行的矩形内, 求出点在哪一列

                     for(columnNum=0;columnNum<ncolumncount;columnNum++)

                     {

                             // 求出列的宽度

                            int colwidth=this->GetColumnWidth(columnNum);

                            if(point.x>=rect.left&&point.x<=(rect.left+colwidth))

                            {

                                   *pcolumn=columnNum;

                                   return row;

                            }

                            rect.left+=colwidth;

                     }

       }

       return -1;

}

当然上面那种方法有点复杂, 是完全从头开始判断. 其实我们可以先利用CListCtrl 提供的函数求出行号, 再求列号, 这样稍微简单点

int Cmylist::HitTestEx(CPoint &point, int *pcolumn)

{

       int columnNum=0;

        int row=HitTest(point);// 求出行号

    int ncolumncount=this->GetHeaderCtrl()->GetItemCount();

         LVHITTESTINFO Info;
        Info.pt=point;
        this->SubItemHitTest(&Info);
       *pcolumn=Info.iSubItem;

       if(*pcolumn>=0&&*pcolumn<ncolumncount)
       return row;

       else

        return -1;

       /* int ncolumncount=this->GetHeaderCtrl()->GetItemCount();

       

              CRect rect;

              GetItemRect(row,&rect,LVIR_BOUNDS);

              if(rect.PtInRect(point))

                     for(columnNum=0;columnNum<ncolumncount;columnNum++)

                     {

                            int colwidth=this->GetColumnWidth(columnNum);

                            if(point.x>=rect.left&&point.x<=(rect.left+colwidth))

                            {

                                   *pcolumn=columnNum;

                                   return row;

                            }

                            rect.left+=colwidth;

                     }*/

       

       }

(4)      求出具体CEdit 移动坐标

int Cmylist::Item_X(int row, int column,CRect& rect_X)

{

       int offset=0;

       for(int i=0;i<column;i++)

              offset+=GetColumnWidth(i);

       CRect rect;

       GetItemRect(row,rect,LVIR_BOUNDS);

       // 注意水平滚动条的影响, 如果已经移动了水平滚动条, 可能left0, 或者超出总大小

       if(offset+rect.left<0||offset+rect.left>client_rect.right)

       {

              CSize size;

               //offset 肯定为正, 如果出现了rect.left 为负

              if(offset+rect.left>0)

                     size.cx=- (offset+rect.left);

              else

                     size.cx=offset+rect.left;

              size.cy=0; // 垂直不用管

               // 如果某一列的一半在滚动条左边, 一半在右边, 就再次调整滚动条的位置.

              Scroll(size);

              rect.left - =size.cx;

       }

       rect.left+=offset+2;

       rect.right=rect.left+GetColumnWidth(column)-2;

        //bottom top 不用管

       rect_X=rect;

       return rect.right;

}

(5)      移动CEdit

void Cmylist::EditSubItem(int Item, int Column)

{

       CRect rect;

       // 求出行列所在rect

       this->Item_X(Item,Column,rect);

       EditCellShow(rect,Item,Column,r);

}

void Cmylist::EditCellShow(CRect rect, int Item, int Column,CRect r)

{

        // 还记得r? 在开始的双击函数OnLButtonDblClk, 它是CListCtrl 在父窗口中的位置

    rect.left+=r.left;

       rect.top+=r.top+2;

       rect.right+=r.left;

       rect.bottom+=r.top+2;

//pedit CEdit 对象的指针, 提供接口, 只要在程序中让pedit 指向一个对象即可

       pedit->MoveWindow(rect,TRUE);

       pedit->ShowWindow(TRUE);  

       pedit->SetFocus();

}

^_^! 这样就完成了. 效果还可以. 当然你还要去响应CEdit 失去焦点和得到焦点的事件. 这个就不是我的任务了, 因为每个人的要求不一样啊!

看看我的效果!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值