我正在使用vc 6.0。 我试图阻止用户调整列表视图中的列使用winapi。 我想阻止第一列(宽度:0)的大小。
我是以下代码(1) winapi-listview-cant-prevent-columns-from-resizing (2) 防止列resize 。 但它不工作。
我处理邮件的function如下:
#define HANDLE_WM_NOTIFY(hwnd, wParam, lParam, fn) \ (fn)((hwnd), (int)(wParam), (NMHDR FAR*)(lParam))
我尝试了什么:
1
BOOL Present_OnNotify(HWND hwnd, int id, LPNMHDR lParam) { switch(id) { case IDC_LIST_PRESLIST: { HD_NOTIFY *pHDN = (HD_NOTIFY*)lParam; if(lParam->code == HDN_BEGINTRACKW || lParam->code == HDN_BEGINTRACKA || lParam->code == HDN_DIVIDERDBLCLICKA || lParam->code == HDN_DIVIDERDBLCLICKW ) { if(0==ListView_GetColumnWidth(hwnd,pHDN->iItem)) { DWORD dwMaskedItem = 0L; DWORD m_dwNoSizeCols = 1L; if (pHDN->iItem < 32) { dwMaskedItem = (0x01 << pHDN->iItem); } dwMaskedItem &= m_dwNoSizeCols; if (dwMaskedItem != 0L) { return TRUE; } } } } break; } return TRUE; }
2
BOOL Present_OnNotify(HWND hwnd, int id, LPNMHDR lParam) { switch(id) { case IDC_LIST_PRESLIST: { HD_NOTIFY *pHDN = (HD_NOTIFY*)lParam; if(lParam->code == HDN_BEGINTRACKW || lParam->code == HDN_BEGINTRACKA || lParam->code == HDN_DIVIDERDBLCLICKA || lParam->code == HDN_DIVIDERDBLCLICKW ) { if(0==ListView_GetColumnWidth(hwnd,pHDN->iItem)) { SetWindowLong(hwnd, DWL_MSGRESULT, TRUE); return TRUE; }
实际上,我不太了解后面的第一个代码(2) 防止列resize 。 但第二个应该是工作。 我该怎么办? 我错过了什么? 谢谢。
编辑
我目前的代码:
我试图按照如下inheritancelistview控件。 没有编译错误。 但是当对话框(也许是listview)被创build时,它会崩溃。 我对此毫无头绪。 我从资源创build列表视图。
头文件
BOOL WINAPI Present_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL Present_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam); void Present_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify); void Present_OnClose(HWND hwnd); void InitPresLVColumn(HWND hwnd); BOOL Present_OnNotify(HWND hWnd, int id, LPNMHDR lParam); //to handle WM_NOTIFY message LRESULT CALLBACK PresListView_OnNotify(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // function to handle message override from parent
源文件
消息对话框的破解者
BOOL WINAPI Present_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { HANDLE_MSG(hwnd, WM_INITDIALOG, Present_OnInitDialog); HANDLE_MSG(hwnd, WM_COMMAND, Present_OnCommand); HANDLE_MSG(hwnd, WM_CLOSE, Present_OnClose); HANDLE_MSG(hwnd, WM_NOTIFY, Present_OnNotify); //handle WM_NOTIFY } return FALSE; }
OnInitDialog从资源创build列表视图控件
BOOL Present_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) { //#define SubclassWindow(hwnd, lpfn) \ // ((WNDPROC)SetWindowLong((hwnd), GWL_WNDPROC, (LPARAM)(WNDPROC)(lpfn))) //#define SubclassDialog(hwndDlg, lpfn) \ // ((DLGPROC)SetWindowLong(hwndDlg, DWL_DLGPROC, (LPARAM)(DLGPROC)(lpfn))) InitPresLVColumn(hwnd); hPresList=GetDlgItem(hwnd,IDC_LIST_PRESLIST); // Create ListView from resource SendMessage(hPresList,LVM_SETEXTENDEDLISTVIEWSTYLE,0,LVS_EX_FULLROWSELECT); InitPCBox(hwnd); return FALSE; }
在inheritancelistview控件之后处理来自父级的消息
LRESULT CALLBACK PresListView_OnNotify(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { HD_NOTIFY *pHDN = (HD_NOTIFY*)lParam; if(pHDN->hdr.code == HDN_BEGINTRACKW || pHDN->hdr.code == HDN_BEGINTRACKA \ || pHDN->hdr.code == HDN_DIVIDERDBLCLICKA || pHDN->hdr.code == HDN_DIVIDERDBLCLICKW ) { int i = ListView_GetColumnWidth(hwnd,pHDN->iItem); if(0==i) { SetWindowLong(hwnd, DWL_MSGRESULT, TRUE); return TRUE; } } return CallWindowProc((WNDPROC)&Present_OnNotify, hPresList, uMsg, wParam, lParam); }
通过对话框来处理WM_NOTIFY消息,它是listview控件的父对象
BOOL Present_OnNotify(HWND hwnd, int id, LPNMHDR lParam) { switch(id) { case IDC_LIST_PRESLIST: { SubclassWindow(hPresList, (LPARAM)&PresListView_OnNotify); } break; } return TRUE;
EDIT2
我已经编辑在:
E1 E2 E3
OnInitDialog从资源创build列表视图控件
BOOL Present_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) { InitPresLVColumn(hwnd); hPresList=GetDlgItem(hwnd,IDC_LIST_PRESLIST); // Create ListView from resource SendMessage(hPresList,LVM_SETEXTENDEDLISTVIEWSTYLE,0,LVS_EX_FULLROWSELECT); E1 SubclassWindow(hPresList, (LPARAM)&PresListView_OnNotify); InitPCBox(hwnd); return FALSE; }
在inheritancelistview控件之后处理来自父级的消息
LRESULT CALLBACK PresListView_OnNotify(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { HD_NOTIFY *pHDN = (HD_NOTIFY*)lParam; if(pHDN->hdr.code == HDN_BEGINTRACKW || pHDN->hdr.code == HDN_BEGINTRACKA \ || pHDN->hdr.code == HDN_DIVIDERDBLCLICKA || pHDN->hdr.code == HDN_DIVIDERDBLCLICKW ) { int i = ListView_GetColumnWidth(hwnd,pHDN->iItem); if(0==i) { SetWindowLong(hwnd, DWL_MSGRESULT, TRUE); return TRUE; } } E2 return CallWindowProc(PresListView_OnNotify, hPresList, uMsg, wParam, lParam); }
通过对话框来处理WM_NOTIFY消息,它是listview控件的父对象
BOOL Present_OnNotify(HWND hwnd, int id, LPNMHDR lParam) { switch(id) { case IDC_LIST_PRESLIST: { E3 // SubclassWindow(hPresList, (LPARAM)&PresListView_OnNotify); } break; } return TRUE; }
您没有正确地继承ListView或正确处理其消息。 试试这个。
头文件:
WNDPROC PrevPresLVWndProc; BOOL WINAPI Present_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL Present_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam); ... LRESULT CALLBACK PresListView_OnNotify(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
源文件:
BOOL WINAPI Present_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch( uMsg ) { HANDLE_MSG(hwnd, WM_INITDIALOG, Present_OnInitDialog); ... } return DefWindowProc(hwnd, uMsg, wParam, lParam); } BOOL Present_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) { ... hPresList = GetDlgItem(hwnd, IDC_LIST_PRESLIST); // Create ListView from resource ... PrevPresLVWndProc = (WNDPROC) GetWindowLongPtr(hPresList, GWL_WNDPROC); SetWindowLongPtr(hPresList, GWL_WNDPROC, (LONG_PTR)&PresListView_OnNotify); ... return FALSE; } LRESULT CALLBACK PresListView_OnNotify(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if( uMsg == WM_NOTIFY ) { switch( ((NMHDR*)lParam)->code ) { case HDN_BEGINTRACKA: case HDN_BEGINTRACKW: case HDN_DIVIDERDBLCLICKA: case HDN_DIVIDERDBLCLICKW: { LPNMHEADER pNMHdr = (LPNMHEADER)lParam; if( ListView_GetColumnWidth(hwnd, pNMHdr->iItem) == 0 ) return TRUE; break; } } } return CallWindowProc(PrevPresLVWndProc, hwnd, uMsg, wParam, lParam); }
这就是说,你真的应该使用SetWindowSubClass()
来代替:
头文件:
BOOL WINAPI Present_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL Present_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam); ... LRESULT CALLBACK PresListView_OnNotify(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
源文件:
BOOL WINAPI Present_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch( uMsg ) { HANDLE_MSG(hwnd, WM_INITDIALOG, Present_OnInitDialog); ... } return DefWindowProc(hwnd, uMsg, wParam, lParam); } BOOL Present_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) { ... hPresList = GetDlgItem(hwnd, IDC_LIST_PRESLIST); // Create ListView from resource ... SetWindowSubclass(hPresList, &PresListView_OnNotify, 1, 0); ... return FALSE; } LRESULT CALLBACK PresListView_OnNotify(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { if( uMsg == WM_NOTIFY ) { switch( ((NMHDR*)lParam)->code ) { case HDN_BEGINTRACKA: case HDN_BEGINTRACKW: case HDN_DIVIDERDBLCLICKA: case HDN_DIVIDERDBLCLICKW: { LPNMHEADER pNMHdr = (LPNMHEADER)lParam; if( ListView_GetColumnWidth(hwnd, pNMHdr->iItem) == 0 ) return TRUE; break; } } } return DefSubclassProc(hWnd, uMsg, wParam, lParam); }
如果您确实需要支持Windows 2000和/或更早版本,则应该通过GetProcAddress()
动态加载SetWindowSubClass()
,以便在可用时使用它,并在不可用时回SetWindowLong()
。