Question

I am using vc 6.0. I am trying to prevent user from resize a column in a listview using winapi. I want to prevent the first column(width: 0) from resizing.

I am following codes (1)winapi-listview-cant-prevent-columns-from-resizing (2)Prevent-column-resizing . But It not work.

My function which to handle message is follow:

#define HANDLE_WM_NOTIFY(hwnd, wParam, lParam, fn) \
    (fn)((hwnd), (int)(wParam), (NMHDR FAR*)(lParam))

What did I try:

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; 
                }

Acturally, I am not understand too much about the first code which follow (2)Prevent-column-resizing. But the second should be work. What should I do? Did I miss something? Thanks.

EDIT

My current Code:

I have tried to subclassing the listview control as follow. There is no compile errors. But when the dialog(maybe the listview) is being created, it is crashed. I have no clue about this. I created listview from resource.

Head file

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 

Source file

Message crackers of the dialog

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 to create listview control from resource

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;
}

handle messages from parent after subclassing the listview control

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);

}

handle WM_NOTIFY message by dialog which is the parent of listview control

BOOL Present_OnNotify(HWND hwnd, int id, LPNMHDR lParam)
{
switch(id)
{

    case IDC_LIST_PRESLIST: 
    {
        SubclassWindow(hPresList, (LPARAM)&PresListView_OnNotify);
    }
    break;
}
return TRUE;

EDIT2

I have edit at:

E1 E2 E3

OnInitDialog to create listview control from resource

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;
}

handle messages from parent after subclassing the listview control

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);

}

handle WM_NOTIFY message by dialog which is the parent of listview control

BOOL Present_OnNotify(HWND hwnd, int id, LPNMHDR lParam)
{
    switch(id)
    {    
        case IDC_LIST_PRESLIST: 
        {
E3          // SubclassWindow(hPresList, (LPARAM)&PresListView_OnNotify);
        }
        break;
    }
    return TRUE;
}
Was it helpful?

Solution

You are not subclassing the ListView correctly or processing its messages correctly. Try this instead.

Header file:

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);

Source file:

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);
}

With that said, you really should be using SetWindowSubClass() instead:

Header file:

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);

Source file:

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);
}

If you really need to support Windows 2000 and/or earlier, you should dynamically load SetWindowSubClass() via GetProcAddress() so you can use it when available, and fallback to SetWindowLong() when not available.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top