在對listctrl的控制項進行重載的過程中,GetHeaderCtrl()返回NULL的問題

來源:互聯網
上載者:User

標籤:des   style   blog   http   color   io   os   使用   ar   

先談談我的問題吧!

在使用listctrl的過程中,我需要在列表頭部添加checkbox,實現全選的功能。

經過網上資料的羅列,我找到了一個demo,使用的重繪的方法,在使用的過程中,我發現我的列表頭無法繪出checkbox,於是開始找問題,最後發現是因為cheadctlcl這個重載的類裡面的函數無法響應,

於是問題一步步逼近,為什麼重載函數無法調用?cheadctlcl類的所有函數都無法響應。於是找了下問題,最後發現問題出在:

void CListCtrlEx::PreSubclassWindow()
{
// TODO: 在此添加專用代碼和/或調用基類
//__super::PreSubclassWindow();
ModifyStyle(0,LVS_OWNERDRAWFIXED);
CListCtrl::PreSubclassWindow();
ModifyStyle(0,LVS_REPORT|LVS_SHOWSELALWAYS|LVS_SORTDESCENDING );
CHeaderCtrl *pHeader = this->GetHeaderCtrl();
m_Header.SubclassWindow(pHeader->GetSafeHwnd());
}

調試發現,GetHeaderCtrl()調用返回老是為空白。

於是就到網上找資料,找到下面這篇文章!!!

//////////////////////////////////////// 引用:http://wangqingyun84.blog.163.com/blog/static/7908361720119744913240////////////////////////////////////////////////

如果要自訂CListCtrl控制項的表頭, 比如最常用的雙行顯示文字, 或者要顯示一些圖片什麼的, 最常用的方法就是自訂一個CHeaderCtrl類, 然後子類化. 步驟如下:

1. 先自訂一個CHeaderCtrl類的子類, 比如CHeaderCtrlEx. 接下來有兩種方法
其一, 最暴力的方法是重寫OnPaint()函數, 也就是給CHeaderCtrlEx添加ON_WM_PAINT()訊息處理函數, 但這時所有的東西都要自已來繪製, 也就是整個的表頭都要自已來繪製, 甚至包括中間的分隔線. 顯然過於激進...
其二, 稍微溫和點的方法. 使用HDI_FORMAT這個style. 實際上每當調用InsertColumn()插入一列時, 都可以指定該style, 那麼繪製該列時就會調用OnDrawItem()函數, 當然了這是需要使用ON_WM_DRAWITEM()宏的, 在該訊息響應函數中就可以自訂的繪製各種東西. 當然了每次繪製都是一個某列的表頭. 這可不像CListCtrl的那個LVS_OWNERDRAWFIXED, 那個是一下繪製整個的一個item也就是一行.
2. 其次呢就是要子類化CListCtrl類的header control, 當然了我都是定義一個CListCtrl的子類, 假設名字叫做CListCtrlEx. 那麼我們需要做的就是在該類中定義一個CHeaderCtrEx _headerCtrl, 之後呢選個合適的機會_headerCtrl.SubClassWindow(GetHeaderCtrl()->GetSafeHwnd())就可以了

我們的問題就是: 何時子類化, 也就是調用這條代碼...

1. 網上好多地方都說是要在PreSubclassWindow()函數中...
2. 但一baidu這個GetHeaderCtrl(), 大家就有一個永恒的問題了: GetHeaderCtrl()傳回值為NULL...
3. 有人說在PreSubclassWindow()中返回NULL, 但是在OnCreate()函數中就OK了...

但實際上好多的都用不同的方法解決了這個問題:
1. 最會逃避的方法就是用資源編輯器添加一個CListCtrl, 然後子類化成CListCtrlEx, 然後無論是在PreSubclassWindow()還是OnCreate()都沒有任何的問題...
2. 有人說在PreSubclassWindow()中不行, 要在OnCreate()中才可以...
3. 但動態建立時還會有問題了, 也就是_listCtrl.Create(...), 用這種方法建立的控制項, 在PreSubclassWindow()和OnCreate()時都還會有問題
4. 還有人極具創造力, 如,引用如下:
I noticed this too. If the list control is created as part of a dialog
template (for example) then the HWND of the header control exists inside of
the PreSubclassWindow function, whereas if the list control is created
dynamically (with a call to CListCtrl::Create()) then it does not.
I solved the problem by PostMessage‘ing a user?defined message to myself
from inside of the PreSubclassWindow function. In the handler for the
user?defined message, the HWND for the header always exists, regardless of
how the list control was created, and I subclass the header from inside this
handler (and not from inside the PreSubclassWindow function).
I think it works because the user?defined message is posted at the end of
the message queue and is therefore handled at a later time, when everything
has "settled down" and both the list control and its header both have been
created.
也就是說, 這是在PreSubclassWindow()函數中沒有直接調用GetHeaderCtrl(), 而是朝自己發了一個自訂訊息, 然後添加該訊息處理函數, 在收到該訊息時再調用GetHeaderCtrl(), 這時"一般"都沒有問題.

 

那麼問題的關鍵是怎麼呢???

很簡單: 就是GetHeaderCtrl()只有在LVS_REPORT時才會返回表頭對象, 其它style時肯定會返回空.

之所以在資源編輯器中靜態拖進去控制項不會有問題, 可能是因為拖進去控制項時就已經設定其style為LVS_REPORT, 通過實驗可以發現, 如果不是LVS_REPORT時, 那麼在PreSubclassWindow()函數中GetHeaderCtrl()依然會返回NULL.
唯一讓人迷惑不解的是, 靜態添加時, 如果不指定其style為LVS_REPORT, 那麼雖然PreSubclassWindow()中是不可能的, 但OnCreate()中卻一直GetHeaderCtrl()可能正常工作, 故, 不解...

 

所以, 解決方案為:
1. 通過靜態資源編輯器來添加控制項, 那麼如果是指定了LVS_REPORT時, 那麼無論是在PreSubclassWindow()還是OnCreate()均沒有問題, GetHeaderCtrl()都好使.
2. 通過靜態資源編輯器來添加控制項, 那麼如果沒有指定LVS_REPORT, 則只能在OnCreate()中使用GetHeaderCtrl(), 在PreSubclassWindow()中是不可以的.
3. 最好的方法是, 在_listCtrl.Create()中務必要指定LVS_REPORT, 那麼在調用了基類的CListCtrl::OnCreate()後, GetHeaderCtrl()必然可以工作...
或者更好一點, 就是在GetHeaderCtrl()之前, 先修改一下: ModifyStyle(0, LVS_REPORT), 這樣最有把握..., 但是啊, 這種方法在PreSubclassWindow()中不是特別好用, 因為PreSubclassWindow()是在OnCreate()調用之前使用, 此時控制項還不存在, 所以不好用

////////////////////////////////////////////////////////////////////////////////////////////////

最後的解決方案,是對clistctrlex類中重載OnCreate函數,在OnCreate函數中實現子類化就實現了功能。

 

 

在對listctrl的控制項進行重載的過程中,GetHeaderCtrl()返回NULL的問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.