首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 请教:有关内存贴图问题!好郁闷。。。
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-12 17:01:27 楼主
    请大家告诉我问题出在哪儿?一个pDC、一个pMyDC、一个成员变量m_pFillDC,三个dc中贴图,当执行第二个Bitblt时贴图位置不对,
    需要刷新一次才能正确显示,
    void CDisplayView::OnDraw(CDC* pDC)
    {

        GetClientRect(&rect);

        CDC *pMyDC = new CDC();
        CBitmap bitmap;
        pMyDC->CreateCompatibleDC(pDC);   
        ASSERT(pMyDC->m_hDC != NULL);

        bitmap.CreateCompatibleBitmap(pDC, rect.Width(),rect.Height());
        m_pOldBmp = pMyDC->SelectObject(&bitmap);

        ASSERT(pMyDC->m_hDC!=NULL);
        pMyDC->SetMapMode(pDC->GetMapMode());
        pDC->DPtoLP(&rect);
       
        pMyDC->SetWindowOrg(rect.left, rect.top);
        pMyDC->FillSolidRect(rect, pDC->GetBkColor());
       
        if(m_bFill)
            FillDC(pMyDC);//在这函数里对m_pFillMemDC进行绘图

        pMyDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(),
            m_pFillDC, rect.left, rect.top, SRCCOPY);

        DrawOthers(pMyDC, pDoc);

        pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(),
            pMyDC, rect.left, rect.top, SRCCOPY);
        delete pMyDC;
        pMyDC = NULL;
    }
    void CDisplayView::FillDC(CDC *pTempDC)
    {
        COtdrDoc *pDoc;
        pDoc = (COtdrDoc *)GetDocument();
        ASSERT_VALID(pDoc);
        GetClientRect(&m_LgRect);
        CBitmap bitmap;
        ASSERT(m_pFillDC != NULL);
        if(m_pFillDC->GetSafeHdc())
            m_pFillDC->DeleteDC();
        m_pFillDC->CreateCompatibleDC(pTempDC);
        ASSERT(m_pFillDC->m_hDC != NULL);
        bitmap.CreateCompatibleBitmap(pTempDC, m_LgRect.Width(),m_LgRect.Height());
        m_pOldBmp = m_pFillDC->SelectObject(&bitmap);
        ASSERT(m_pFillDC->m_hDC!=NULL);
        m_pFillDC->SetMapMode(pTempDC->GetMapMode());
        pTempDC->DPtoLP(&m_LgRect);
        m_pFillDC->SetWindowOrg(m_LgRect.left, m_LgRect.top);
        m_pFillDC->FillSolidRect(m_LgRect, pTempDC->GetBkColor());

        DrawBKGrid(pDoc, m_pFillDC);
        DrawLine(pDoc, m_pFillDC);
        DrawFlag(pDoc, m_pFillDC, pTempDC);
    }
    20  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-12 19:59:171楼 得分:0
    总感觉是SetWindowOrg用得不对。
    第一次SetWindowOrg后pMyDC的(0,0) 应该对应pDC的(-rect.left, -rect.top)了吧
    假设m_LgRect和初始rect一样坐标的话, 子函数中DPtoLP后m_LgRect.left = -rect.left, m_LgRect.top = -rect.top
    然后m_pFillDC->SetWindowOrg后m_pFillDC的(0,0)和pDC是一样的
    子函数返回后将m_pFillDC中的内容复制到pMyDC时复制的是偏移了的内容 (??)。
    而且第一次后m_LgRect中坐标全部变掉了, 再次调用后又是DPtoLP, 又是SetWindowOrg, 我也说不清m_pFillDC的(0, 0)究竟指向了哪里了。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-13 11:31:162楼 得分:0
    阿呆所言极是!

    OnDraw中对应rect
    FillDC中对应m_lgrect

    我在调试中发现:当if条件成立就调用FillDC函数,而该函数中的DrawLine函数中会有
    setDocsize(size);
    SetScrollSizes(,size);的操作。而SetScrollSize可能触发再一次调用OnDraw;

    也就差不多是在OnDraw里调用了SetScrollSizes,这样用合适么?

    我if()
      FillDC();
    的目的是希望在view中没有改变的图像的时候就不执行绘图操作,直接贴上次的图就可以;可是现在就可能出现了rect和m_lgrect不一致的问题(不执行FillDC时),导致了贴图错位。

    是不是逻辑关系问题,应该如何修改?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-14 08:43:543楼 得分:0
    所谓SetScrollSize触发OnDraw应该不是直接调用的, 而是通过api InvalidateRect标记区域被修改,然后windows又会post 一个WM_PAINT, 从而引发OnDraw事件的。 所以你可以简单地在SetScrollSize后调用ValidateRect去除修改标记以避免再次触发OnDraw事件。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-15 11:56:574楼 得分:0
    阿呆

    InvalidateRect(FALSE)是不是可以阻止SetScrollSize 所post的WM_PAINT?

    还有就是SetWindowOrg(100,100);是不是就是把(100,100)设为了(0,0)点?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tccqs
    • 等级:
    发表于:2008-01-15 12:27:515楼 得分:0
    学习ing ,帮顶
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 15:23:196楼 得分:0
    不是, InvalidateRect是通知windows某块client区域失效了, windows就会给你的进程post一个WM_PAINT消息。 至于那个bool值只是表明是否要清空背景, 也就是说当你处理WM_PAINT调用BeginPaint时系统是否要发送WM_ERASEBKGND消息, false只是表明不会发这个WM_ERASEBKGND消息。 要阻止windows发送WM_PAINT你只有调用ValidateRect去告诉windows该区域没有被修改过, 不需要发送WM_PAINT.

    SetWindowOrg(100, 100) 是将当前的逻辑坐标(100,100)对应成实际坐标(0,0), 也就是说设置后的逻辑坐标(0, 0) 对应的是实际坐标(-100,-100)
    所以, 为了将实际上的(100, 100)对应成(0, 0), 应该用SetWindowOrg(-100, -100)
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved