ListView 欄標(Header Control)預設允許使用者拖曳調整寬度,若業務需求要求鎖定寬度,需攔截 Header 控件發送的 HDN_BEGINTRACK 通知並阻止預設處理,同時禁用拖曳游標提示。
Header 控件位於 comctl32.dll,已編譯為原生代碼,專案 UNICODE 設定不影響其發送通知版本。實際發送版本取決於父視窗對 WM_NOTIFYFORMAT 的回應(NFR_ANSI/NFR_UNICODE)。最稳健做法:同時處理 HDN_BEGINTRACKA 與 HDN_BEGINTRACKW。
BOOL CLockableHeader::OnChildNotify(UINT msg, WPARAM wp, LPARAM lp, LRESULT* pRes) {
NMHDR& nmh = *(NMHDR*)lp;
if (nmh.code == HDN_BEGINTRACKW || nmh.code == HDN_BEGINTRACKA) {
if (m_bLocked) return *pRes = TRUE; // 吞噬通知,阻止拖曳
}
return CHeaderCtrl::OnChildNotify(msg, wp, lp, pRes);
}
BOOL CLockableHeader::OnSetCursor(CWnd* pWnd, UINT nHit, UINT msg) {
return m_bLocked ? TRUE : CHeaderCtrl::OnSetCursor(pWnd, nHit, msg); // 鎖定時回傳 TRUE 保持箭頭游標
}
OnChildNotify 為虛擬函數,無需訊息映射入口。m_bLocked 由應用程式透過公開 Lock(BOOL) 方法控制。
class CMyView : public CListView {
CLockableHeader m_header;
int OnCreate(LPCREATESTRUCT lpcs) {
if (CListView::OnCreate(lpcs) == -1) return -1;
// Header 控件資源 ID 固定為 0
return m_header.SubclassDlgItem(0, this) ? 0 : -1;
}
};
ID_VIEW_LOCKHEADER 切換 m_bLocked。ON_UPDATE_COMMAND_UI 同步勾選狀態。範例程式展示鎖定前後行為差異,完整原始碼可直接移植專案。此技術同樣適用於 CListCtrl、CTreeCtrl 等內建 Header 控件的 MFC 封裝類別。