在对话框上放三个控件,分别是CListCtrl、CTreeCtrl、CTabctrl,这三个控件都是自绘的,如何实控件从对话框背景图片截取图片设置为控件的背景?即控件的背景和对话框的背景看上去是共用的同一张图片!

解决方案 »

  1.   

    背景图放在一个全局的内存DC中。
    对话框,控件等,全部从内存DC中拷贝指定区域的图片做背景。
    BitBlt 就可以实现了。
      

  2.   

    我用OnEraseBkgnd返回true,CListCtrl背景透明,可以看到对话框的背景,但是删除某一行的记录时,CListCtrl的背景图片会变花,如何解决呢?当我添加记录后文本的背景色为白色怎么去掉啊文本的背景,如果没白色,文字又看不到??
      

  3.   

    CListCtrl要做背景图的话,要派生一个类自绘,每次添加,删除,选择行,都要重绘背景。
      

  4.   

    看看这个
    http://www.vckbase.com/index.php/wv/206.html
      

  5.   


    用OnEraseBkgnd返回true,可以看到对话框的背景,这个方法不行吗?
      

  6.   

    void CListCtrlCl::OnPaint()
    {
    CListCtrl::OnPaint();
    CDC* cdc=GetDC();
    CRect rect;
    GetClientRect(&rect);
    int Width=rect.Width();
    int Height=rect.Height();
    CDC MemDC;
    MemDC.CreateCompatibleDC(cdc);//创建一个与指定设备兼容的内存设备上下文环境(DC) CBitmap memBmp;
    memBmp.CreateCompatibleBitmap(cdc,Width,Height);//创建与指定的设备环境相关的设备兼容的位图
    //成功返回位图句柄
    CBitmap* pOldMemBmp=MemDC.SelectObject(&memBmp);
    //m_savebmp=MemDC.SelectObject(&memBmp);
    //画背景图片到内存中
    CBitmap* pnewbmp=cdc->SelectObject(&m_Bmp);
    MemDC.BitBlt(0,0,Width,Height,cdc,0,0,SRCCOPY);//保存图片
    cdc->SelectObject(pnewbmp);//选择一对象到指定的设备上下文环境中
    rect.top=0;
    rect.left=0;
    rect.right=Width;
    rect.bottom=rect.top+Height;
    int size=GetHeaderCtrl()->GetItemCount();
    for(int i=0;i<size&&rect.top<Height;i++)
    {
    rect.OffsetRect(0,20);
    }
    cdc->BitBlt(0,0,Width,Height,&MemDC,0,0,SRCCOPY);//绘图

    }
    绘制CListCtrl控件背景图片怎么没用啊
      

  7.   

    "用OnEraseBkgnd返回true,可以看到对话框的背景,这个方法不行吗?"
    问题在于CListCtrl Paint时会改变背景。
      

  8.   

    为什么我在OnPaint里面画背景图片没用啊?
      

  9.   

    是哪里错了吗?我新建一个工程继承CListCtrl类,重写OnPaint函数也没有将CListCtrl背景图片绘制出来
      

  10.   

    谁能帮我一下吗?
    void CListCtrlCl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
    {
    int total=GetItemCount();//设置复选框的状态,界面未刷新
    if(m_Header.bFlag==false)
    {
    for(int i=0;i<total;i++)
    {
    m_bItemCheckState[i] = !m_bItemCheckState[i];
    InvalidateRect(NULL,true);
    }
    }
    m_Header.bFlag=true;
    if (lpDrawItemStruct->CtlType != ODT_LISTVIEW)
    return;

    RECT rectiSubItem = {0};
    RECT rectCheckBox = {0};
    CDC* pDC;
    pDC = CDC::FromHandle(lpDrawItemStruct->hDC); WCHAR szBuffer[256] = {0};
    int nTotalColumn = 0; CHeaderCtrl* pListHeader = NULL;
    LV_ITEM lvi; pListHeader = (CHeaderCtrl*)GetDlgItem(0);
    nTotalColumn = pListHeader->GetItemCount(); //第一列是要显示复选框的一列
    pListHeader->GetItemRect(0,&rectCheckBox);
    //循环地绘制列表控件各个子项
    LV_COLUMN lvc;//, lvcprev ;
    ::ZeroMemory(&lvc, sizeof(lvc));
    lvc.mask = LVCF_WIDTH | LVCF_FMT;
    //for (int iColumn = 0;iColumn<nTotalColumn;++iColumn)
    for(int iColumn=0;GetColumn(iColumn,&lvc);iColumn++)
    {
    CDC* pDC;
    pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    CRect rtClient;
    GetClientRect(&rtClient);
    //for ( int nCol=0; GetColumn(nCol, &lvc); nCol++)
    //{
    if ( iColumn >0 ) 
    {
    // Get Previous Column Width in order to move the next display item
    GetColumn(iColumn-1, &lvc) ;//GetColumn(iColumn-1, &lvcprev) ;
    lpDrawItemStruct->rcItem.left+= lvc.cx;//lvcprev.cx ;
    lpDrawItemStruct->rcItem.right += lpDrawItemStruct->rcItem.left; 
    }
    CRect rcItem;   
    if (!GetSubItemRect(lpDrawItemStruct->itemID,iColumn,LVIR_LABEL,rcItem))   
    continue;   ::ZeroMemory(&lvi, sizeof(lvi));
    lvi.iItem = lpDrawItemStruct->itemID;
    lvi.mask = LVIF_TEXT | LVIF_PARAM;
    lvi.iSubItem = iColumn;//0;
    lvi.pszText = szBuffer;
    lvi.cchTextMax = sizeof(szBuffer);
    VERIFY(GetItem(&lvi)); CRect rcTemp;
    rcTemp = rcItem;
    if ( lpDrawItemStruct->itemState&ODS_SELECTED)
    {
    pDC->FillSolidRect(&rcItem, GetSysColor(COLOR_HIGHLIGHT)) ;//记录选中后设置字体背景色
    }else
    {
    COLORREF color;
    color = GetBkColor();
    CBrush hbrush;
    pDC->FillSolidRect(rcTemp,color);//加了这一句,添加的记录文本都会有背景色,如果删除文本背景透明,但是如果前一列的文本长度大于单元格的长度,文本会继续显示在后一列中,请问这个问题怎么解决啊???
    }
    //pDC->SelectObject(GetStockObject(DEFAULT_GUI_FONT));
    if (iColumn == 0)
    {
    rectCheckBox.top = lpDrawItemStruct->rcItem.top;
    rectCheckBox.bottom = lpDrawItemStruct->rcItem.bottom;
    m_nRowHeight=lpDrawItemStruct->rcItem.bottom-lpDrawItemStruct->rcItem.top;
    DrawFrameControl(lpDrawItemStruct->hDC,&rectCheckBox,DFC_BUTTON,DFCS_CHECKED);
    //绘制复选框
    if (m_bItemCheckState[lpDrawItemStruct->itemID])
    {
    m_bItemCheckState[lpDrawItemStruct->itemID]=true;
    DrawFrameControl(lpDrawItemStruct->hDC,&rectCheckBox,DFC_BUTTON,DFCS_CHECKED);//已选中
    }else
    {
    m_bItemCheckState[lpDrawItemStruct->itemID]=false;
    DrawFrameControl(lpDrawItemStruct->hDC,&rectCheckBox,DFC_BUTTON,DFCS_BUTTONCHECK);//未选中
    }
    }else
    {
    int len=_tcslen(szBuffer);
    CRect tRect;
    GetItemRect(0,&tRect,iColumn);
    pDC->DrawText(szBuffer,len,&lpDrawItemStruct->rcItem,DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS|DT_LEFT);//画文字
    pDC->DrawEdge(&lpDrawItemStruct->rcItem,EDGE_RAISED,BF_BOTTOM);//下划线
    }
    UINT   uFormat=DT_CENTER ;
    if (m_Header.m_Format[iColumn]=='0')
    {
    uFormat = DT_LEFT;
    }else if (m_Header.m_Format[iColumn]=='1')
    {
    uFormat = DT_CENTER;
    }else if (m_Header.m_Format[iColumn]=='2')
    {
    uFormat = DT_RIGHT;
    }
    }
    }
      

  11.   

    "如果前一列的文本长度大于单元格的长度,文本会继续显示在后一列中"
    画文字时
    int len=_tcslen(szBuffer);
    CRect tRect;
    GetItemRect(0,&tRect,iColumn);
    pDC->DrawText(szBuffer,len,&lpDrawItemStruct->rcItem,DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS|DT_LEFT);//画文字
    要查文字可能的pixel程度,超过要截尾:
    CSize GetTextExtent( LPCTSTR lpszString, int nCount ) const;
    即:
    CSize pixLen=pDC->GetTextExtent(szBuffer,len);
    if(pixLen.x < 该列宽度) pDC->DrawText()
      

  12.   


    int len=_tcslen(szBuffer);
    CRect tRect;
    GetSubItemRect(lpDrawItemStruct->itemID,iColumn,LVIR_BOUNDS,tRect);

    CSize pixLen=pDC->GetTextExtent(szBuffer,len);
    if(pixLen.cx<tRect.Width())
    pDC->DrawText(szBuffer,len,&lpDrawItemStruct->rcItem,DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS|DT_LEFT);//画文字
    else
    pDC->DrawText(szBuffer,tRect.Width(),&lpDrawItemStruct->rcItem,DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS|DT_LEFT);//画文字 pDC->DrawEdge(&lpDrawItemStruct->rcItem,EDGE_RAISED,BF_BOTTOM);//下划线
    为什么没用啊?
      

  13.   


    上面这个解决了,是你说的那样,我自己搞错了,呵呵,谢谢!能不能告诉我怎么画CListCtrl、CTreeCtrl、CTabctrl的背景啊
      

  14.   

    "CListCtrl、CTreeCtrl、CTabctrl的背景"
    如果背景是单一颜色,可以在CustomDraw中对每个item设置BkColor。
    如果背景是图就麻烦了。这时要用‘透明窗口’的绘制方法。
    就是把控件的图和背景图混合。
    用EraseBkGrnd是不行的,因为控件绘制时会把背景全覆盖掉。
      

  15.   

    透明窗口可能更简单一点,但是实现方式上与重绘不同。
    我还是看看这个网址吧:http://www.vckbase.com/index.php/wv/206.html
      

  16.   


    void CTreeControl::OnPaint() 
    {
    // create a compatible memory dc 
    //绘制背景图片
    CTreeCtrl::OnPaint();
    }
    我将OnPaint函数改成上面这样,然后注释SetBKImage函数,背景确实是透明,但是节点的背景为白色,并且点击节点展开和收拢都没有刷新界面!该怎么解决啊
      

  17.   

    自己做刷新响应函数?没做过?
    void CTreeControl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult) 
    {
    NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
    // TODO: Add your control notification handler code here
    //Invalidate();
    CRect rc;
    GetClientRect(&rc);
    InvalidateRect(rc);
    SetRedraw(TRUE);//TRUE,则重画标志被设置
    *pResult = 0;
    }void CTreeControl::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult) 
    {
    NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
    // TODO: Add your control notification handler code here
    CRect rc;
    GetClientRect(&rc);
    InvalidateRect(rc);
    //SetRedraw(FALSE);//标志被清除
    SetRedraw(false);
    *pResult = 0;
    }
    我上面调用的系统刷新函数为什么没用呢?将对应控件背景的区域绘制下来,刷新控件的区域,难道不是吗?
      

  18.   

    不是说了吗,CTreeCtrl控件在Paint时不会考虑背景,所有的背景都被Item覆盖了。
      

  19.   


    那我要设置CTreeCtrl背景图和对话框背景图混合怎么做呢?
      

  20.   

    http://www.vckbase.com/index.php/wv/206.html
    可以实现,前提是我要从对话框背景图片上截取一张图片CTreeCtrl控件大小的图片,然后将图片保存为.bmp格式,但是我不知道怎么截取怎么保存?
      

  21.   

    给你一个思路:
    在Paint中:
    1.产生memDC,
    2.把memDC交给DefWindowProc(WM_PAINT,memDC.m_hDC,0);
    让父类把窗口绘在memDC上;
    3.再把背景绘到memDC上 (SRCAND)
    4,绘到dc上。
      

  22.   


    CPaintDC dc(this); // device context for painting

    CRect rcclient;
    GetClientRect(&rcclient);
    CDC memdc;
    memdc.CreateCompatibleDC(&dc);
    CBitmap bitmap;
    bitmap.CreateCompatibleBitmap(&dc, rcclient.Width(), rcclient.Height());
    memdc.SelectObject( &bitmap ); CWnd::DefWindowProc(WM_PAINT, (WPARAM)memdc.m_hDC , 0); CDC maskdc;
    maskdc.CreateCompatibleDC(&dc);
    CBitmap maskbitmap;
    maskbitmap.CreateBitmap(rcclient.Width(), rcclient.Height(), 1, 1, NULL);
    maskdc.SelectObject( &maskbitmap );
    maskdc.BitBlt( 0, 0, rcclient.Width(), rcclient.Height(), &memdc,rcclient.left, rcclient.top, SRCCOPY); CBrush brush;
    brush.CreatePatternBrush(&m_bitmap);
    dc.FillRect(rcclient, &brush);

    memdc.SetBkColor(RGB(0,0,0));         
    memdc.SetTextColor(RGB(255,255,255));  
    memdc.BitBlt(rcclient.left, rcclient.top, rcclient.Width(), rcclient.Height(), &maskdc, rcclient.left, rcclient.top, SRCAND); dc.SetBkColor(RGB(255,255,255));
    dc.SetTextColor(RGB(0,0,0));
    dc.BitBlt(rcclient.left, rcclient.top, rcclient.Width(), rcclient.Height(), &maskdc, rcclient.left, rcclient.top, SRCAND);

    dc.BitBlt(rcclient.left, rcclient.top, rcclient.Width(), rcclient.Height(), &memdc,rcclient.left, rcclient.top,SRCPAINT);
    brush.DeleteObject();你说的是这个吧
      

  23.   

    CBrush brush;
    brush.CreatePatternBrush(&m_bitmap);
    dc.FillRect(rcclient, &brush); 好像有问题
      

  24.   

    这个没有问题,重写SetBkImage给m_bitmap赋值,这就是我在26楼说的,如果不要用SetBkImage给m_bitmap,我怎么取界面上的图片呢?
      

  25.   

    其实:
    1.在EraseBackGround中仍按绘背景处理。
    这时DC中已有背景。
    2在Paint用memDC把控件绘制的取出后,
    dc.bitblt(0,0,wid,hei,&memdc,0,0,SRCAND);
    就可以了。
      

  26.   

    给父对话框发WM_ERASEBKGND或WM_PAINT消息BOOL CListCtrlCl::OnEraseBkgnd( CDC* pDC )
    {
        CWnd* pParent = GetParent();
        ASSERT_VALID(pParent);
        CPoint pt(0, 0);
        MapWindowPoints(pParent, &pt, 1);
        pt = pDC->OffsetWindowOrg(pt.x, pt.y);
        LRESULT lResult = pParent->SendMessage(WM_ERASEBKGND,(WPARAM)pDC->m_hDC, 0L);
        pDC->SetWindowOrg(pt.x, pt.y);
        return lResult;
    }
      

  27.   


    本来我OnEraseBkgnd里面return true,把他改成你这样,就是原来的那个背景了,没有图片
      

  28.   

    你不就是要从对话框背景图片上截取一张图片CTreeCtrl控件大小的图片吗?
    可以参考#36的代码啊,只不过将那个DC换成内存DC,图片用CreateCompatibleBitmap创建,选入内存DC,给父对话框发WM_ERASEBKGND或WM_PAINT消息后,内存DC中的位图就保存了对应的对话框背景了用BitBlt来截屏也可以,但不靠谱的,万一被别的窗口挡住,截到的图片就不对了
    至于发WM_ERASEBKGND消息还是WM_PAINT消息取决于你的对话框背景是在WM_ERASEBKGND还是WM_PAINT画上去的
      

  29.   


    我刚刚在看MapWindowPoints的相关信息,谢谢,我试试看!
      

  30.   

    void CListCtrlCl::OnPaint() 
    {
    //MessageBox(_T("paint"));
    CListCtrl::OnPaint();//否则不能进入drawitem函数
    CPaintDC dc(this);
    CBitmap bitmap;
    CRect rect;
    GetClientRect(&rect);
    bitmap.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());
    CDC memDC;
    memDC.CreateCompatibleDC(&dc);
    memDC.SelectObject(bitmap);
    CWnd* pParent = GetParent();
    //ASSERT_VALID(pParent);
    CPoint pt(0, 0);
    MapWindowPoints(pParent,&pt,2);
    //pt =memDC.OffsetWindowOrg(pt.x,pt.y);//->OffsetWindowOrg(pt.x, pt.y);
    memDC.OffsetWindowOrg(pt.x,pt.y);
    LRESULT lResult = pParent->SendMessage(WM_ERASEBKGND,(WPARAM)memDC.m_hDC, 0L);//pDC->m_hDC
    memDC.SetWindowOrg(pt.x, pt.y);}
    我在OnPaint中这样写的,怎么报错呢???
    Run-Time Check Failure #2 - Stack around the variable 'pt' was Run-Time Check Failure #2 - Stack around the variable 'pt' was corrupted..
      

  31.   

    因为是用CPoint而不是CRect,所以MapWindowPoints最后一个参数是1而不是2
      

  32.   

    给你tree的代码:BOOL cTree::OnEraseBkgnd(CDC* pDC) 
    {
    CRect rc;
    GetClientRect(&rc);
    CDC MemDC;
    MemDC.CreateCompatibleDC(pDC);
    HBITMAP hBmp=(HBITMAP)MemDC.SelectObject(m_bitmap.m_hObject);
    pDC->StretchBlt(0,0,rc.Width(),rc.Height(),&MemDC,0,0,320,240,SRCCOPY);
    // set back
    (HBITMAP)MemDC.SelectObject(hBmp);
    // free
    DeleteObject(MemDC);
    //
    return TRUE;
    }
    //
    void cTree::OnPaint() 
    {
    CPaintDC dc(this);
    // 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);
    // Let the control draws the tree.
    DefWindowProc(WM_PAINT, (WPARAM)memDC.m_hDC, 0 );
    // '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);
    }
      

  33.   

    取对话框中ListCtrl的背景要在对话框的Erasebkgnd中取。
      

  34.   


    BOOL CListCtrlCl::OnEraseBkgnd(CDC* pDC)//背景透明,首先擦除背景
    {
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    //CPaintDC dc(this);
    CBitmap bitmap;
    CRect rect;
    GetClientRect(&rect);
    bitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
    CDC memDC;
    memDC.CreateCompatibleDC(pDC);
    memDC.SelectObject(bitmap);
    CWnd* pParent = GetParent();
    //ASSERT_VALID(pParent);
    CPoint pt(0, 0);
    //MapWindowPoints(pParent,&pt,2);
    MapWindowPoints(pParent,&pt,1);
    //pt =memDC.OffsetWindowOrg(pt.x,pt.y);//->OffsetWindowOrg(pt.x, pt.y);
    memDC.OffsetWindowOrg(pt.x,pt.y);
    LRESULT lResult = pParent->SendMessage(WM_ERASEBKGND,(WPARAM)memDC.m_hDC, 0L);//pDC->m_hDC
    memDC.SetWindowOrg(pt.x, pt.y); return false;
    }
      

  35.   


    我在头文件中声明为CBitmap m_bitmap,在.cpp中没有给其赋值,这样好像不对吧?
    我要手动给m_bitmap赋值吗
      

  36.   

    如果我将m_bitmap.LoadBitmapW(IDB_BITMAPBK);放在OnEraseBkgnd双击节点时会报错,m_hObject==NULL,如果放在构造函数中就没事,现在的问题是,我不知道m_bitmap的作用是干嘛,是画图片吗?如果是,那么我要的从对话框背景图片取,那就没用取到啊,在OnEraseBkgnd中好像没有保存图片的操作?
      

  37.   

    void CListCtrlCl::OnPaint()  
    {
      CListCtrl::OnPaint();//否则不能进入drawitem函数 
      CPaintDC dc(this);
      CBitmap bitmap;
      CRect rect;
      GetClientRect(&rect);
      bitmap.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());
      CDC memDC;
      memDC.CreateCompatibleDC(&dc);
      memDC.SelectObject(bitmap); 
      CWnd* pParent = GetParent();
      //ASSERT_VALID(pParent);
      CPoint pt(0, 0);
      MapWindowPoints(pParent, &pt, 1);
      pt =memDC.OffsetWindowOrg(pt.x,pt.y);
      pParent->SendMessage(WM_ERASEBKGND,(WPARAM)memDC.m_hDC, 0L);
      pParent->SendMessage(WM_PAINT,(WPARAM)memDC.m_hDC, 0L);
      memDC.SetWindowOrg(pt.x, pt.y);
      //至此memDC上已经保存了父窗口的背景内容
      //用户可以调用BitBlt(...)等函数拷贝memDC的内容到子窗口,这样就达到了透明效果;
      CWnd::DefWindowProc(WM_PAINT, (WPARAM)memDC.m_hDC , 0);
      dc.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
      //如果不行就用这里的方法:http://www.vckbase.com/index.php/wv/206.html
    }BOOL CListCtrlCl::OnEraseBkgnd(CDC* pDC)  
    {   
      return TRUE; 
    }
      

  38.   

    m_bitmap的作用是背景图。
    这样对话框必须有自己的背景图。
    对话框的擦背景中就是把这个背景图绘到对话框上,同时你要把ListCtrl所占的那块保留下来。作为他的背景这样list就看上去是透明的了。
      

  39.   

    对话框画背景是
    CPaintDC dc(this);
    CRect rect;
    GetClientRect(&rect);
    CDC memDC;
    memDC.CreateCompatibleDC(&dc);
    CBitmap bmpbkgnd;
    bmpbkgnd.LoadBitmapW(IDB_BITMAPBK);
    BITMAP bkbmp;
    bmpbkgnd.GetBitmap(&bkbmp);
    CBitmap* pbmp=memDC.SelectObject(&bmpbkgnd);
    dc.StretchBlt(0,0,rect.Width(),rect.Height(),&memDC,0,0,bkbmp.bmWidth,bkbmp.bmHeight,SRCCOPY);
    但是这里
    BOOL CTreeControl::OnEraseBkgnd(CDC* pDC) 
    {
    // TODO: Add your message handler code here and/or call default
    CRect treeRect;
    GetClientRect(&treeRect);
    CDC memdc;
    memdc.CreateCompatibleDC(pDC);
    HBITMAP hbmp=(HBITMAP)memdc.SelectObject(m_bitmap.m_hObject);
    pDC->StretchBlt(0,0,treeRect.Width(),treeRect.Height(),&memdc,0,0,treeRect.Width(),treeRect.Height(),SRCCOPY);
    (HBITMAP)memdc.SelectObject(hbmp);
    DeleteObject(memdc);
    return TRUE;
    }
    void CTreeControl::OnPaint() 
    {
    CPaintDC dc(this);
    CRect rc;//获得大小
    GetClientRect(&rc); CDC memdc;//创建一个兼容的内存DC
    memdc.CreateCompatibleDC(&dc); CBitmap bitmap;//将一张兼容的bitmap放入内存DC中
    bitmap.CreateCompatibleBitmap(&dc,rc.Width(),rc.Height());
    HBITMAP oldBmp=(HBITMAP)memdc.SelectObject(&bitmap); DefWindowProc(WM_PAINT,(WPARAM)memdc.m_hDC,0);//响应函数画树 dc.BitBlt(0,0,rc.Width(),rc.Height(),&memdc,0,0,SRCAND);//背景图片,and

    memdc.SelectObject(oldBmp);//设置背景图片
    DeleteObject(bitmap.m_hObject);//释放资源
    DeleteObject(memdc);
    }
    这里好像并没有给m_bitmap赋值,从哪里可以看出,我是从对话框背景相对应的位置画出的CTreeCtrl的背景图片呢?
      

  40.   


    我将dc.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
    改为dc.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 400, 400, SRCCOPY);
    在坐标为(400,400)并没有画出图片,CListCtrl可以看到对话框的背景图片,我想应该是调用这个函数的原因吧
    BOOL CListCtrlCl::OnEraseBkgnd(CDC* pDC)   
    {   
      return TRUE;  
    }
      

  41.   


    从哪里可以看出“ListCtrl所占的那块保留下来”???
      

  42.   

    为什么要改为400,400?具体我没试过,不知道OnEraseBkgnd里直接返回TRUE会不会影响到CWnd::DefWindowProc(WM_PAINT, (WPARAM)memDC.m_hDC , 0);如果会则画出来的背景就是透明的了,否则只能用http://www.vckbase.com/index.php/wv/206.html里的maskdc的方法了,不过我估计也可以用TransparentBlt代替
      

  43.   

    因为坐标不同可以看出到底画出图片了没啊?要不然和OnEraseBkgnd的一样就不知道到底是哪个的效果
      

  44.   


    不是的,BitBlt才开始画,改了坐标,如果图片宽度或高度小于400,就什么都没画出来了
      

  45.   

    "
    dc.StretchBlt(0,0,rect.Width(),rect.Height(),&memDC,0,0,bkbmp.bmWidth,bkbmp.bmHeight,SRCCOPY);
    但是这里
    "
    到这里ClistCtrl的背景并没有保存下来,
    BOOL CTreeControl::OnEraseBkgnd(CDC* pDC)时。
    对话框已经被他覆盖取不到背景的!
      

  46.   


    那怎么办呢?我以为上面添加了控件,对话框的背景不会不覆盖,但是用OnEraseBkgnd不是可以擦除控件的背景而看到对话框的背景吗?既然可以看到为什么不可以保存呢?
      

  47.   

    是这样的,如果工程的资源中有图片可以加载到CListCtrl上,而我要的效果是控件上的背景和对话框的背景图片看上去是一张,能不能将对话框控件的相对于的位置能以图片.bmp保存到工程的目录???请各位大侠帮忙,真的很急!
      

  48.   

    用你42楼的方法好像可以设置CTreeCtrl的图片,但是你画的时候点击节点的时候没遇到刷新的问题吗?我双击节点展开或收拢,还有移动滚动条时,文字就重叠了,不知道怎么解决?你是如何解决的呢?
      

  49.   

    点击节点
    itemexpending 时要Invalidate()
      

  50.   

    “话框控件的相对于的位置能以图片.bmp保存到工程的目录”不必。
    在对话框背景中,(可以先隐藏控件)画完背景后,截取控件大小的位图,(其实应该做成Brush CreatePattenBrush)。这个Brush放对话框中。
    在控件背景时,GetParent-》取这个Brush,就可以画了。
    和文件无关。
      

  51.   


    我用了,没用
    void CTreeControl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult) 
    {
    NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
    // TODO: Add your control notification handler code here
    Invalidate();
    //CRect rc;
    //GetClientRect(&rc);
    //InvalidateRect(rc);
    //SetRedraw(TRUE);//TRUE,则重画标志被设置

    SetRedraw(true);
    *pResult = 0;
    }void CTreeControl::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult) 
    {
    NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
    // TODO: Add your control notification handler code here
    Invalidate();
    //CRect rc;
    //GetClientRect(&rc);
    //InvalidateRect(rc);
    //SetRedraw(FALSE);//标志被清除
    //SetRedraw(false);
    *pResult = 0;
    }
      

  52.   

    不需要:SetRedraw(true);
    我的VC6可以没问题(没ScrollBar)
      

  53.   


    还是一样的,是不是不用重写OnItemexpanded函数啊?
      

  54.   

    带滚动条时的窗口重绘比较讨厌,先把滚动条取消试试(text减短,项数减少)
      

  55.   

    "怎么隐藏控件啊"
    m_MyList.ShowWindow(SW_HIDE)
      

  56.   

    基于http://www.vckbase.com/index.php/wv/206.html修改的:
    http://115.com/file/e7jp2fvb
      

  57.   

    我刚刚调试了一下,自绘CListCtrl控件,在调用在OnPaint函数中CListCtrl::OnPaint();执行后才会执行CHeaderCtrl的继承类,是不是我把你说的代码写在CListCtrl::OnPaint()之前就不用隐藏了呢?      
    OnPaint函数中CListCtrl::OnPaint();写在前面的代码好像都不执行的?我本来想在CListCtrl绘制之前绘制图片放在CListCtrl::OnPaint();的前面好像行不通
      

  58.   

    我给图片添加了一张背景,CTreeCtrl背景还是白色,不是有
    BOOL CMyTreeCtrl::OnEraseBkgnd(CDC* pDC) 
    {
    // TODO: Add your message handler code here and/or call default
    return TRUE;
    }
      

  59.   

    修正一下:http://115.com/file/dpkocgtv这个例子必须在对话框的OnEraseBkgnd中用BitBlt画对话框背景
      

  60.   


    我不知道你的编译器是不是vs2008,我的运行结果就是我想问你们那个问题
    http://my.csdn.net/my/album/detail/1184040
      

  61.   

    我的是VC6你下载我的那个例子后,可以运行一下Release文件夹里的Tree.exe,看一看是不是你想要的效果
      

  62.   

    如果要隐藏控件,那我直接在画控件之前画背景图片不行吗?比如说在Dlg.cpp中
      

  63.   


    void CMyTreeCtrl::OnPaint() 
    {
      CPaintDC dc(this); // device context for painting  CRect rcclient;
      GetClientRect(&rcclient);  // create a compatible memory dc 
      CDC memdc;
      memdc.CreateCompatibleDC(&dc);
      CBitmap bitmap;
      bitmap.CreateCompatibleBitmap(&dc, rcclient.Width(), rcclient.Height());
      CBitmap *oldbitmap = memdc.SelectObject( &bitmap );
      CWnd::DefWindowProc(WM_PAINT, (WPARAM)memdc.m_hDC , 0);  CWnd* pParent = GetParent();
      CPoint pt(0, 0);
      MapWindowPoints(pParent, &pt, 1);
      pt = dc.SetWindowOrg(pt.x, pt.y);
      pParent->SendMessage(WM_ERASEBKGND, (WPARAM)dc.GetSafeHdc(), 0L);
      dc.SetWindowOrg(pt.x, pt.y);  ::TransparentBlt(dc.GetSafeHdc(), 0, 0, rcclient.Width(), rcclient.Height(), memdc.GetSafeHdc(), 0, 0, rcclient.Width(), rcclient.Height(), RGB(255,255,255));  memdc.SelectObject(oldbitmap);
      bitmap.DeleteObject();
    }BOOL CTreeDlg::OnEraseBkgnd(CDC* pDC) 
    {
      CRect rect;
      GetClientRect(&rect);
      CDC memdc;
      memdc.CreateCompatibleDC(pDC);
      memdc.SelectObject( &m_bitmap );
      pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memdc, 0, 0, SRCCOPY);
      return TRUE;
    }
      

  64.   


    我之前设置CTreeCtrl背景透明可以看到对话框的背景,现在是想设置CTreeCtrl和对话框的背景一致,但是按你的方法,文字确实不重叠了,滚动条移动也没问题,就是背景变成 了没有加图片时的样子
      

  65.   

    我的VC6的类向导里,对话框没有OnEraseBkgnd的,要手动加代码的:BEGIN_MESSAGE_MAP(CTreeDlg, CDialog)
      //{{AFX_MSG_MAP(CTreeDlg)
      ON_WM_SYSCOMMAND()
      ON_WM_PAINT()
      ON_WM_ERASEBKGND()
      ON_WM_QUERYDRAGICON()
      //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
      

  66.   

    有这个函数啊
    我猜是不是这个函数MapWindowPoints(pParent, &pt, 1);在执行OnPaint函数的时候对话框的背景图就没了,然后MapWindowPoints取的背景图片就是错的啊
      

  67.   

    下面的代码产生一个CEdit控件的背景(对话框的一部分)BOOL CDrawEditDlg::OnEraseBkgnd(CDC* pDC) 
    {
    // TODO: Add your message handler code here and/or call default
    CDC dcMem;
    dcMem.CreateCompatibleDC(pDC);//DeleteDC needed
    CBitmap* pOldBitmap = dcMem.SelectObject(&m_bitmap);
    // Retrieve the size of our bitmap...
    BITMAP bmp;
    m_bitmap.GetObject(sizeof(bmp),&bmp);
    // and the size of our window's client area
    CRect rect;
    GetClientRect(&rect);
    // Create Edit background brush; only once !
    if(!m_blInitEditBr)
    {// add  edit rect
    CRgn  prgnClip;
    CRect selEditRc;
    m_SelEdit.GetWindowRect(selEditRc);
    prgnClip.CreateRectRgnIndirect(selEditRc);//DeleteObject needed
    CDC* pDCex=GetDCEx(&prgnClip,DCX_PARENTCLIP);//ReleaseDC needed
    // Fill the client area of dlg,include SelEdit with our bitmap
    pDCex->StretchBlt(rect.left, rect.top,rect.Width(), rect.Height(),
    &dcMem,0, 0, bmp.bmWidth, bmp.bmHeight,SRCCOPY);
     //we create the background brush of SelEdit
    CDC dcMemEd;
    dcMemEd.CreateCompatibleDC(pDCex);//DeleteDC needed
    CBitmap EditBmp;//DeleteObject needed
    EditBmp.CreateCompatibleBitmap(pDCex,selEditRc.Width(),selEditRc.Height());
    pOldBitmap = dcMemEd.SelectObject(&EditBmp);
    ScreenToClient(&selEditRc);
    MapWindowPoints(this,selEditRc);
    dcMemEd.BitBlt(0,0,selEditRc.Width(),selEditRc.Height(),
    pDCex,selEditRc.left, selEditRc.top, SRCCOPY);
    CBitmap  *nowBMP=dcMemEd.SelectObject(pOldBitmap); 
    // copy to CB for checking
    #ifdef TEST
    OpenClipboard();
    EmptyClipboard(); 
    SetClipboardData(CF_BITMAP,nowBMP->GetSafeHandle());
    CloseClipboard();
    #endif
    m_pbrEd=new CBrush;
    m_pbrEd->CreatePatternBrush(nowBMP);
    m_blInitEditBr=TRUE;
    //
    DeleteObject(prgnClip);
    DeleteObject(EditBmp);
    ReleaseDC(pDCex);
    dcMemEd.DeleteDC();
    }
    else
    {// MORMAL
    pDC->StretchBlt(rect.left, rect.top,rect.Width(), rect.Height(),
    &dcMem,0, 0, bmp.bmWidth, bmp.bmHeight,SRCCOPY);
    }
    dcMem.SelectObject(pOldBitmap);
    dcMem.DeleteDC(); 
    //
    return TRUE;
    // return CDialog::OnEraseBkgnd(pDC);
    }
    下面是在派生EDit中的调用:
    BOOL CSelEdit::OnEraseBkgnd(CDC* pDC) 
    {
    // TODO: Add your message handler code here and/or call default
    CDrawEditDlg *pdlg=(CDrawEditDlg*)GetParent();
    CRect rc;
    GetWindowRect(&rc);
    ScreenToClient(&rc);
    // afxDump << rc << "\n";
    pDC->FillRect(rc,pdlg->m_pbrEd);//PatternBrush
    return TRUE;
    // return CEdit::OnEraseBkgnd(pDC);
    }
    //
    注意:
    m_pbrEd=new CBrush;
    m_pbrEd->CreatePatternBrush(nowBMP);
    m_blInitEditBr=TRUE;

    3句产生一个位图画刷。
      

  68.   


    我绘制CListCtrl背景图片好像成功了,是这样的我的CHeaderCtrl也实现了一个继承类,我在列头添加了一个复选框,让点击复选框下面的实现反选,为什么只有我点击列名头复选框时,图片才进行绘制呢?好奇怪,我的绘制函数是写在CListCtrl继承类中啊
      

  69.   


    用来绘制CListCtrl的背景图片,我该为
    CMy3dvstarDlg* starDlg=(CMy3dvstarDlg*)GetParent(); 
    CRect rc;
    GetWindowRect(&rc);
    rc.left+=100;
    rc.top+=100;
    pDC->FillRect(rc,starDlg->m_pbrEd);
    图片并没有在我指定的位置进行重绘,是不是根本就没有成功啊!为什么在CListCtrl的(100,100)没有绘制图片呢???
      

  70.   

    如果我在OnPaint函数中调用Invalidate(),对CListCtrl进行增删,图片都没问题就是不停的闪
      

  71.   

    “我的VC6的类向导里,对话框没有OnEraseBkgnd的,要手动加代码的:”
    把对话框改成‘window’(class info)就有了。不要手动的
      

  72.   

    不是有一段测试代码:
    #ifdef TEST
            OpenClipboard();
            EmptyClipboard(); 
            SetClipboardData(CF_BITMAP,nowBMP->GetSafeHandle());
            CloseClipboard();
    #endif
    #ifdef 1 // TEST
    打开画板程序,paste进来看看。
      

  73.   

    可以控制背景,那可以控制删除CListCtrl的记录时,背景不变花不???
      

  74.   

    “附件“中不有个"画图"(PaintBrush)吗。
    CListCtrl本身有个SetBkImage函数,不过没用过。
      

  75.   


    我刚刚试了一下,任何控件,只要在
    BOOL CListCtrlCl::OnEraseBkgnd(CDC* pDC)//背景透明,首先擦除背景
    {
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    CBrush brush;
    CBitmap bit;
    bit.LoadBitmapW(IDB_BITMAPBK);

    CRect rect;
    GetClientRect(&rect);
    brush.CreatePatternBrush(&bit);
    pDC->FillRect(&rect,&brush);
    return TRUE;
    }
    加载的图片都不会有刷新的问题,现在我知道的是
    用你说的
    BOOL CDrawEditDlg::OnEraseBkgnd(CDC* pDC) 
    {
        // TODO: Add your message handler code here and/or call default
        CDC dcMem;
        dcMem.CreateCompatibleDC(pDC);//DeleteDC needed
        CBitmap* pOldBitmap = dcMem.SelectObject(&m_bitmap);
    // Retrieve the size of our bitmap...
        BITMAP bmp;
        m_bitmap.GetObject(sizeof(bmp),&bmp);
    // and the size of our window's client area
        CRect rect;
        GetClientRect(&rect);
    //    Create Edit background brush; only once !
        if(!m_blInitEditBr)
        {// add  edit rect
            CRgn  prgnClip;
            CRect selEditRc;
            m_SelEdit.GetWindowRect(selEditRc);
            prgnClip.CreateRectRgnIndirect(selEditRc);//DeleteObject needed
            CDC* pDCex=GetDCEx(&prgnClip,DCX_PARENTCLIP);//ReleaseDC needed
        // Fill the client area of dlg,include SelEdit with our bitmap
            pDCex->StretchBlt(rect.left, rect.top,rect.Width(), rect.Height(),
                            &dcMem,0, 0, bmp.bmWidth, bmp.bmHeight,SRCCOPY);
     //we create the background brush of SelEdit
            CDC dcMemEd;
            dcMemEd.CreateCompatibleDC(pDCex);//DeleteDC needed
            CBitmap EditBmp;//DeleteObject needed
            EditBmp.CreateCompatibleBitmap(pDCex,selEditRc.Width(),selEditRc.Height());
            pOldBitmap = dcMemEd.SelectObject(&EditBmp);
            ScreenToClient(&selEditRc);
            MapWindowPoints(this,selEditRc);
            dcMemEd.BitBlt(0,0,selEditRc.Width(),selEditRc.Height(),
                            pDCex,selEditRc.left, selEditRc.top, SRCCOPY);
            CBitmap  *nowBMP=dcMemEd.SelectObject(pOldBitmap);
     
    // copy to CB for checking
    #ifdef TEST
            OpenClipboard();
            EmptyClipboard(); 
            SetClipboardData(CF_BITMAP,nowBMP->GetSafeHandle());
            CloseClipboard();
    #endif
            m_pbrEd=new CBrush;
            m_pbrEd->CreatePatternBrush(nowBMP);
            m_blInitEditBr=TRUE;
    //
            DeleteObject(prgnClip);
            DeleteObject(EditBmp);
            ReleaseDC(pDCex);
            dcMemEd.DeleteDC();
        }
        else
        {// MORMAL
            pDC->StretchBlt(rect.left, rect.top,rect.Width(), rect.Height(),
                            &dcMem,0, 0, bmp.bmWidth, bmp.bmHeight,SRCCOPY);
        }
        dcMem.SelectObject(pOldBitmap);
        dcMem.DeleteDC(); 
    //
        return TRUE;
    //    return CDialog::OnEraseBkgnd(pDC);
    }是不是相当于自己创建了一张CBitmap图片,这个与我OnEraseBkgnd中添加的图片,除了一个是工程手动添加的资源,一个是自己创建的资源外,还有什么本质区别没???
    或者说我上面的理解错误?
      

  76.   

     m_pbrEd->CreatePatternBrush(nowBMP);
    这个已经是画刷,不是bitmap 
      

  77.   


     EditBmp.CreateCompatibleBitmap(pDCex,selEditRc.Width(),selEditRc.Height());
      pOldBitmap = dcMemEd.SelectObject(&EditBmp);

    这句话就相当于把图片保存在了EditBmp中吗???
      

  78.   

     EditBmp.CreateCompatibleBitmap(pDCex,selEditRc.Width(),selEditRc.Height());
    这句是空的bmp
    pOldBitmap = dcMemEd.SelectObject(&EditBmp);
    准备绘制
    dcMemEd.BitBlt(0,0,selEditRc.Width(),selEditRc.Height(),
    pDCex,selEditRc.left, selEditRc.top, SRCCOPY);
    这句是绘制
    CBitmap *nowBMP=dcMemEd.SelectObject(pOldBitmap);
    这句是取出绘制完的bmp。
    没有这句bmp还被selected,在 dcMemEd 内。 
      

  79.   

    CDC dcMemEd;
      dcMemEd.CreateCompatibleDC(pDCex);//兼容的内存设备上下文环境
      CBitmap EditBmp;//DeleteObject needed
      EditBmp.CreateCompatibleBitmap(pDCex,selEditRc.Width(),selEditRc.Height());//指定的设备环境相关的设备兼容的位图
      pOldBitmap = dcMemEd.SelectObject(&EditBmp);//对象替换先前的相同类型的对象,是将dcMemEd替换EditBmp,还是将EditBmp替换dcMemEd
      ScreenToClient(&selEditRc);
      MapWindowPoints(this,selEditRc);
      dcMemEd.BitBlt(0,0,selEditRc.Width(),selEditRc.Height(),
    pDCex,selEditRc.left, selEditRc.top, SRCCOPY);//应该是保存图片吧
    CBitmap *nowBMP=dcMemEd.SelectObject(pOldBitmap); // m_pbrEd->CreatePatternBrush(nowBMP);//用 m_pbrEd->CreatePatternBrush(&pOldBitmap)应该与上面是等价的吧ScreenToClient(&selEditRc);
      MapWindowPoints(this,selEditRc);这两句好像似乎没影响
    不懂,求解释???
      

  80.   

    “ pOldBitmap = dcMemEd.SelectObject(&EditBmp);//对象替换先前的相同类型的对象,是将dcMemEd替换EditBmp,还是将EditBmp替换dcMemEd”是把dcMemEd CD中的bmp替换掉。即原来bmp 存pOldBitmap,新bmp是EditBmp“m_pbrEd->CreatePatternBrush(nowBMP);//用 m_pbrEd->CreatePatternBrush(&pOldBitmap)应该与上面是等价的吧”错! pOldBitmap 与你毫无关系!“ScreenToClient(&selEditRc);
      MapWindowPoints(this,selEditRc);这两句好像似乎没影响

    是 确定Edit在对话框中位置,
      

  81.   

    CRect selEditRc;
    m_SelEdit.GetWindowRect(selEditRc);
    要的是整个窗口。
    ScreenToClient(&selEditRc);
    变客户区,
    MapWindowPoints(this,selEditRc);
    变换到对话框中坐标。