none
为什么LISTCTRL不听使唤? RRS feed

  • 问题

  • 新建一个MFC工程->Single Document
    没有Document/View 支持
    于是系统自动生成一个APP类,一个CChildView:public CWnd类和一个CMainFrame类。

     

    int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    {
        if (CWnd ::OnCreate(lpCreateStruct) == -1)
            return -1;
        
        m_list.SetNotifyTarget(this);
        m_list.Create(WS_CHILD|WS_VISIBLE|WS_BORDER,CRect(0,0,0,0),this,1000);
        
        m_img.Create(16,16,ILC_MASK,2,0);
        m_img.Add(LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ONLINE)));
        m_img.Add(LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_OFFLINE)));
        
        m_list.SetImageList(&m_img,LVSIL_SMALL);
        m_list.InsertColumn(0,TEXT("Sign Number"),LVCFMT_LEFT,100);
        m_list.InsertColumnWithEditBox(1,TEXT("Location"),LVCFMT_LEFT,120,-1,NULL,TRUE,TRUE,16);
        m_list.InsertColumnWithEditBox(2,TEXT("Description"),LVCFMT_LEFT,135,-1,NULL,FALSE,FALSE,14);
        m_list.InsertColumnWithDecimalEdit(3,TEXT("Price"),LVCFMT_LEFT,60,-1,NULL,FALSE,0.01f,999.99f,2);
        m_list.InsertColumnWithDecimalEdit(4,TEXT("Save"),LVCFMT_LEFT,60,-1,NULL,FALSE,0.01f,999.99f,2);
        m_list.InsertColumnWithDropdownList(5,TEXT("Product Type"),LVCFMT_LEFT,100,-1,NULL,TEXT("EA\nKG"));
        m_list.InsertColumnWithDecimalEdit(6,TEXT("Unit Price"),LVCFMT_LEFT,80,-1,NULL,FALSE,0.01f,999.99f,2);
        m_list.InsertColumnWithEditBox(7,TEXT("Unit of Measure"),LVCFMT_LEFT,120,-1,NULL,FALSE,FALSE,5);
        m_list.InsertColumnWithDropdownList(8,TEXT("Border Scroll"),LVCFMT_LEFT,100,-1,NULL,TEXT("ON\nOFF\nRUN"));
        
        m_list.InsertItem(0,TEXT("001"),1);
        m_list.SetItemText(0,1,TEXT("HALL"));
        m_list.SetItemText(0,2,TEXT("DESCRIPTION"));
        m_list.SetItemText(0,3,TEXT("18.60"));
        m_list.SetItemText(0,4,TEXT("0.40"));
        m_list.SetItemText(0,5,TEXT("KG"));
        m_list.SetItemText(0,6,TEXT("1.86"));
        m_list.SetItemText(0,7,TEXT("LITRE"));
        m_list.SetItemText(0,8,TEXT("RUN"));
        m_list.InsertItem(1,TEXT("001"),0);
        m_list.SetItemText(1,1,TEXT("HALL"));
        m_list.SetItemText(1,2,TEXT("DESCRIPTION"));
        m_list.SetItemText(1,3,TEXT("18.60"));
        m_list.SetItemText(1,4,TEXT("0.40"));
        m_list.SetItemText(1,5,TEXT("KG"));
        m_list.SetItemText(1,6,TEXT("1.86"));
        m_list.SetItemText(1,7,TEXT("LITRE"));
        m_list.SetItemText(1,8,TEXT("RUN"));
        return 0;
    }
    
    void CEditableList::PreSubclassWindow() 
    {
        CListCtrl::PreSubclassWindow();
        CWnd *pParent = GetParent();
        if(m_nMaxColumnsCount == 0)
        {
            m_nMaxColumnsCount = (UINT32)(GetNotifyTarget()->SendMessage(WM_REQUEST_COLUMN_COUNT,(WPARAM)GetSafeHwnd(),0));
            if(m_nMaxColumnsCount > 0xFFFF0000)
                m_nMaxColumnsCount &= 0xFFFF;
            else
                m_nMaxColumnsCount = 0;
        }
        
        m_hBrushBackground = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
        if(m_nMaxColumnsCount > 0)
        {
            m_pConfigurations = new COLUMN_CONFIGURATION[m_nMaxColumnsCount];
            ModifyStyle(LVS_ICON|LVS_SMALLICON|LVS_LIST,LVS_REPORT,SWP_FRAMECHANGED);
            SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT);
        }
        else
        {
            throw(TEXT("Parent must process WM_REQUEST_COLUMNS_COUNT,and return 0xFFFF0000|(max_columns_count)."));
        }
    }
    


    1问、为什么在PreSubclassWindow调用GetParent()得到的不是CChildView的指针,而是一个CTempWnd?
    2问、为什么LVS_REPORT风格没有切换过来 (见下图)?

     3问、为什么在PreSubclassWindow中GetParent()返回的是一个CTempWnd的指针而不是我指定的CChildView的指针?
    4问、我把LVS_REPORT写在m_list.Create(WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_REPORT,...)这里就OK,这是为什么?

     


    MaRs``
    2011年12月30日 2:23

答案

  • 是的,确实是有这样的问题,PreSubclassWindow里调用,可能原因是HWND虽然不为NULL,但是窗口还没有准备好,ModifStyle()函数调用成功了,但是没能影响到最后实际生成的窗口上.所以你最好还是在Create(...)动态创建的时候设置这个LVS_REPORT风格,或者在OnCreate函数中设置。PreSubclassWindow在OnCreate函数调用之前会被调用。
    Visual C++ enthusiast, like network programming and driver development. At present is being engaged in the WinCE/Windows Mobile platform embedded development.
    • 已建议为答案 shawken 2011年12月30日 9:43
    • 已标记为答案 MaRs`` 2012年1月2日 8:44
    2011年12月30日 6:07
    版主

全部回复

  • 是的,确实是有这样的问题,PreSubclassWindow里调用,可能原因是HWND虽然不为NULL,但是窗口还没有准备好,ModifStyle()函数调用成功了,但是没能影响到最后实际生成的窗口上.所以你最好还是在Create(...)动态创建的时候设置这个LVS_REPORT风格,或者在OnCreate函数中设置。PreSubclassWindow在OnCreate函数调用之前会被调用。
    Visual C++ enthusiast, like network programming and driver development. At present is being engaged in the WinCE/Windows Mobile platform embedded development.
    • 已建议为答案 shawken 2011年12月30日 9:43
    • 已标记为答案 MaRs`` 2012年1月2日 8:44
    2011年12月30日 6:07
    版主
  • 您好,谢谢您的回复。

    我在CChildView::OnCreate中PostMessage一个WM_POST_CREATE,在该消息的响应函数中

    m_list.ModifyStyle(LVS_TYPEMASK,LVS_REPORT);也没有效果,这是为什么呢?甚至把这一行放在CChildView::OnPaint,不断让View重绘ListCtrl仍然没有切换到report样式。


    MaRs``
    • 已编辑 MaRs`` 2011年12月30日 6:22
    2011年12月30日 6:13
  • 您好,谢谢您的回复。

    我在CChildView::OnCreate中PostMessage一个WM_POST_CREATE,在该消息的响应函数中

    m_list.ModifyStyle(LVS_TYPEMASK,LVS_REPORT);也没有效果,这是为什么呢?甚至把这一行放在CChildView::OnPaint,不断让View重绘ListCtrl仍然没有切换到report样式。


    MaRs``
    我说的OnCreate函数不是指的CChildView类的OnCreate函数,而是您的CListCtrl派生类CEditableList类的WM_CREATE消息的响应函数OnCreate
    Visual C++ enthusiast, like network programming and driver development. At present is being engaged in the WinCE/Windows Mobile platform embedded development.
    2011年12月30日 7:20
    版主
  • 我理解您的意思。

    但是我想把EditableList封装起来,如何可以确保LVS_REPORT在窗口创建后被设置呢?

    在通过对话框资源创建EditableList时不会执行到EditableList::OnCreate


    MaRs``
    2011年12月30日 7:29
  • 解决了,但是不明白为什么?

    在PreSubclassWindow中Post一个Message,在该Message的相应函数中进行ModifyStyle即可。

    奇怪的是PreSubclassWindow中ModifyStyle返回TRUE但是样式并没有被修改。

    不明白,求高手解释!


    MaRs``
    2011年12月31日 0:35