解决方案 »

  1.   

    自己可以填充子控件的DRAWITEMSTRUCT信息
      

  2.   

    我知道可以填充,但是比如说里面的  
      UINT        CtlType;
        UINT        itemID;
        UINT        itemAction;
     ULONG_PTR   itemData;这几个如何得到
      

  3.   

    我是想在onpaint之内调用之,这样就容易操作
      

  4.   

    建议使用 WM_DRAWITEM 消息,
      

  5.   

    使用WM_DRAWITEM这个消息也要填参数啊
      

  6.   

    "在onpaint之内调用之" 可以, 但 onpaint 中可以全部自己绘,没必要调用它.
      

  7.   

    给个例子:
    主窗口 有个 m_pListBox
    主窗口 OnPaintfor (int jj=0;jj< 20;jj)
    {
    DRAWITEMSTRUCT  ds;
    ds.CtlType=ODT_LISTBOX;
    ds.CtlID=m_pListBox->GetDlgCtrlID();
    ds.ItemID=jj;// current idx 
    ds.itemAction=ODA_DRAWENTIRE;
    ds.hwndItem=m_pListBox->GetSafeHwnd();
    ds.hDC= dc.GetSafeHdc();
    ds.rcItem=CRect(0,0,60,20);// GetItemRect(jj);
    ds.itemData=m_pListBox->GetItemData(jj);
    ds.itemState=m_pListBox->GetSel(jj)>0?ODS_SELECTED:0);
    //ds.itemState |= ODS_FOCUS;
    m_pListBox->DrawItem(&ds)
    }手打的 !
      

  8.   


    谢谢,我今天就是这么搞的,但是遇到个问题如下:
    HWND childwnd = ::GetWindow(m_hWnd, GW_CHILD);
    UINT ctlid;
    int width,height;
    ClientToScreen(&rcClient);
    while(childwnd != NULL)
    {
                    DRAWITEMSTRUCT  ds;
                    ds.CtlType=ODT_LISTBOX;
                    ds.CtlID=m_pListBox->GetDlgCtrlID();//填充结构体
                     ..................
                    CButton::DrawItem(&ds)//调用绘制
            childwnd = ::GetWindow(childwnd, GW_HWNDNEXT);
            }
    while会出现已经出现过得childwnd ;
      

  9.   

    我是想在onpaint之内调用之,这样就容易操作如果用OnPaint就不用OnDrawItem
    这两个消息或者说绘制途径是相互独立的
    在OnPaint中完全可以获取到所有控件的信息完成相应绘制
      

  10.   

    例如有个用于 listbox 的 CTitleTip ,当listbox 是ownerdraw 时, 这个tip 把自己的dc 通过DRAWITEMSTRUCT 给listbox.
    然后 调用 m_pListBox->DrawItem(&ds) ; 让listbox把 当前 项 text 绘制到 tip 上. 上面9 楼是代码 片断.
      

  11.   

    // CTitleTip message handlersvoid CTitleTip::OnPaint() 
    {
        ASSERT(m_nItemIndex != m_nNoIndex);    CPaintDC DC(this);    int nSavedDC = DC.SaveDC();    CRect ClientRect;
        GetClientRect(ClientRect);    if (IsListBoxOwnerDraw())
        {
            // Let the listbox do the real drawing.
            DRAWITEMSTRUCT DrawItemStruct;        DrawItemStruct.CtlType = ODT_LISTBOX;
            DrawItemStruct.CtlID = m_pListBox->GetDlgCtrlID();
            DrawItemStruct.itemID = m_nItemIndex;
            DrawItemStruct.itemAction = ODA_DRAWENTIRE;
            DrawItemStruct.hwndItem = m_pListBox->GetSafeHwnd();
            DrawItemStruct.hDC = DC.GetSafeHdc();
            DrawItemStruct.rcItem = ClientRect;
            DrawItemStruct.itemData = m_pListBox->GetItemData(m_nItemIndex);
            DrawItemStruct.itemState = (m_pListBox->GetSel(m_nItemIndex) > 0 ? 
                                        ODS_SELECTED : 0);
            if (m_pListBox->GetStyle() & LBS_MULTIPLESEL)
            {
                if (m_pListBox->GetCaretIndex() == m_nItemIndex)
                {
                    DrawItemStruct.itemState |= ODS_FOCUS;
                }
            }
            else
            {
                DrawItemStruct.itemState |= ODS_FOCUS;
            }        m_pListBox->DrawItem(&DrawItemStruct);
        }
        else
        {
            // Do all of the drawing ourselves
    ........
      

  12.   

    谢谢你的回复,我想这么做的原因是一次性的把背景和控件都绘制在同一个内存dc上,实现双缓冲,所以这么纠结,代码架构不是我架构的,改架构很麻烦所有想得到DrawItemStruc信息然后就可以不用改以前的架构从而实现双缓冲,
      

  13.   

    可以先call 控件的 DefWindowProc(WM_PAINT, YourMemDC,0);
    让控件 把 它的 图 画在  YourMemDC, 上. (Onpaint 不能指定DC)
    对 TreeCtrl, ListCtrl 这个方法行得通, 对你的控件只能试试.
      

  14.   

    我可以这么理解么,在Onpai立先建立一个MemDc画背景然后callDefWindowProc,然后在Onpaint结束前再copy到screenDc上?
      

  15.   

    这是ListCtrl的例子:void CMyListCtrl::OnPaint() 
    {
    CPaintDC dc(this); // device context for painting

    // TODO: Add your message handler code here
    // get size
    CRect rc;
    GetClientRect(&rc);
    // Create a compatible memory DC 
    CDC memDC;
    memDC.CreateCompatibleDC(&dc);
    // Select a compatible bitmap into the memory DC
    CBitmap bitmap;
    bitmap.CreateCompatibleBitmap( &dc, rc.Width(), rc.Height());
    HBITMAP oldBmp=(HBITMAP)memDC.SelectObject(&bitmap);
    // fill the region not occupied
    memDC.FillRect(&rc,CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
    // Let the control draws the list.
    // CHeaderCtrl *pHead=GetHeaderCtrl();
    // pHead->SendMessage(WM_PAINT, (WPARAM)memDC.m_hDC, 0 );// on screen ?
    // ::DefWindowProc(pHead->m_hWnd, WM_PAINT, (WPARAM)memDC.m_hDC, 0 );// not ?
    DefWindowProc(WM_PAINT, (WPARAM)memDC.m_hDC, 0 );
    // copy to CB for checking
    #ifndef TEST
    memDC.SelectObject(oldBmp);
    OpenClipboard();
    EmptyClipboard(); 
    SetClipboardData(CF_BITMAP,bitmap);
    CloseClipboard();
    oldBmp=(HBITMAP)memDC.SelectObject(&bitmap);
    #endif
    // 'and' to the background
    dc.BitBlt(0, 0, rc.Width(), rc.Height(),&memDC,0 ,0 ,SRCAND);
    // set back
    memDC.SelectObject(oldBmp);
    // free
    DeleteObject(bitmap.m_hObject);
    DeleteObject(memDC);

    // Do not call CListCtrl::OnPaint() for painting messages
    }