我正在使用vc 6.0。我试图阻止用户使用winapi调整列表视图中的列的大小。我想阻止第一列(宽度:0)调整大小。
我正在关注代码(1)winapi-listview-cant-prevent-columns-from-resizing(2)Prevent-column-resizing。但它不起作用。
我处理消息的功能如下:
#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)Prevent-column-resizing并不太了解。但第二个应该是工作。我该怎么办?我错过了什么?感谢。
修改
我目前的代码:
我试图将listview控件子类化如下。没有编译错误。但是当创建对话框(可能是listview)时,它就会崩溃。我对此毫无头绪。我从资源创建了listview。
头文件
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从资源
创建listview控件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;
}
在继承listview控件
之后处理来自父级的消息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从资源
创建listview控件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;
}
在继承listview控件
之后处理来自父级的消息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;
}
答案 0 :(得分:1)
您没有正确地对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和/或更早版本,则应通过SetWindowSubClass()
动态加载GetProcAddress()
,以便在可用时使用它,并在不可用时回退到SetWindowLong()