阻止列表视图调整大小列在winapi中不起作用

时间:2014-04-26 16:15:47

标签: windows listview winapi mfc

我正在使用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;
}

1 个答案:

答案 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()