CListCtrl學習筆記(2)—中級篇

來源:互聯網
上載者:User

專題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);

       //注意水平捲軸的影響,如果已經移動了水平捲軸,可能left為0,或者超出總大小

       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失去焦點和得到焦點的事件.這個就不是我的工作了,因為每個人的要求不一樣啊!

看看我的效果!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.