我在内存中用CClientDC中绘制位图,定义的尺寸很大,怎么总是不能完全显示?子窗体位置变化后,对应的位图大小也跟着变,总是残缺不全。是不是用的DC类型不对?在后台绘制的位图,受当前活动视(子窗体)的大小影响吗?有没有解决办法?

解决方案 »

  1.   

    1、选择视的基类为CScrollView.
    2、响应ID_FILE_NEW,什么也不做。
    3、响应DeleteContents函数,清除位图对象
    if(m_Bitmap.m_hObject!=NULL)
       m_Bitmap.DeleteObject();
    4、在文档类的OnOpenDocument函数打开位图文件,初始化位图对象
    if (IsModified())
    TRACE0("Warning: OnOpenDocument replaces an unsaved document\n");
    DeleteContents();
    //设置等待鼠标
    BeginWaitCursor();
    //打开位图文件
    HBITMAP hImage = (HBITMAP)LoadImage(NULL, lpszPathName, IMAGE_BITMAP,
    0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION|LR_DEFAULTSIZE);
    EndWaitCursor();
    if (!hImage) {
    DWORD LastError = GetLastError();
    // Error message should be fomatted with LastError included
    AfxMessageBox("LoadImage failed");
    return FALSE;
    }
    //构造位图对象
    if (!m_Bitmap.Attach(hImage)) {
    AfxMessageBox("Bitmap could not be attached");
    return FALSE;
    }
    SetModifiedFlag(FALSE);
    //更新所有视图
    UpdateAllViews(NULL);
    return TRUE;
    5、在文档类头文件中添加代码
    public:
    HBITMAP GetHandle() const {return (HBITMAP)m_Bitmap.m_hObject;};
    void SelectOldBitmap(CDC *pDCMem) {pDCMem->SelectObject(m_pOldBitmap);};
    void SelectBitmap(CDC *pDCMem)
    {m_pOldBitmap=pDCMem->SelectObject(&m_Bitmap);};
    int GetBitmap(BITMAP* pBitMap) {return m_Bitmap.GetBitmap(pBitMap);};
    protected:
    CBitmap m_Bitmap;
    CBitmap* m_pOldBitmap;
    6、用类向导删除视类的OnInitialUpdate.
    7、用类向导响应视类的OnUpdate函数.
    void CXXXXView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
    {
    CXXXXDoc* pDoc = GetDocument();
    //获得主窗口指针
    CFrameWnd* pParentFrame = GetParentFrame();
    BITMAP BitMap;
    if (!pDoc->GetHandle())
    return;
    //获得位图结构
    pDoc->GetBitmap(&BitMap);
    //设置滚动条范围
    SetScrollSizes(MM_TEXT, CSize(BitMap.bmWidth, BitMap.bmHeight));
    //重新规划主窗口大小
    pParentFrame->RecalcLayout();
    ResizeParentToFit();
    }
    7、在视类的OnDraw显示
    CXXXXDoc* pDoc = GetDocument();
    BITMAP BitMap;
    CDC DCMem;
    // Do not call CWnd::OnPaint() for painting messages
    ASSERT_VALID(pDoc);
    if (!pDoc->GetHandle())
    return;
    //创建内存设备场景
    if (!DCMem.CreateCompatibleDC(pDC))
    TRACE0("DCMem.CreateCompatibleDC failed\n");
    pDoc->SelectBitmap(&DCMem);
    pDoc->GetBitmap(&BitMap);
    //将位图拷贝到显示设备场景中,进行显示,这是没有缩放的显示
    if (!pDC->BitBlt(0, 0, BitMap.bmWidth, BitMap.bmHeight, &DCMem, 0, 0, SRCCOPY))
    TRACE0("BitBlt failed\n");
    pDoc->SelectOldBitmap(&DCMem);
    DCMem.DeleteDC();
    8、用StrechBlt来实现图片的缩放,你可以先设定好自己的缩放模式和缩放参数。比如在头文件中
    添加缩放参数变量int m_nStretchType;并在构造函数中初始化m_nStretch=STRECH_1_1;
    #define STRECH_1_1 0
    #define STRECH_FULL_X 1
    #define STRECH_FULL_Y   2
    #define STRECH_FULL 3
    #define STRECH_CENTER   4
    9、增加函数SetStrechType(int nStrechType)
    {
        m_nStrechType = nStrechType;
        Invalidate();
    }
    10、实现缩放显示
    在OnDraw()函数中先获得位图参数:
    BITMAP bmp;
    m_bmpImage.GetBitmap(&bmp);
    //开始缩放
    switch(m_nStrechType)
    {
    case STRECH_1_1://1:1
    dc.BitBlt(r.left,r.top,r.Width(),r.Height(),&memdc,0,0,SRCCOPY);
    break;
    case STRECH_FULL_X://按宽度
    dc.StretchBlt(r.left,r.top,r.Width(),bmp.bmHeight,&memdc,0,0,
    bmp.bmWidth,bmp.bmHeight,SRCCOPY);
    break;
    case STRECH_FULL_Y://按高度
    dc.StretchBlt(r.left,r.top,bmp.bmWidth,r.Height(),&memdc,0,0,
    bmp.bmWidth,bmp.bmHeight,SRCCOPY);
    break;
    case STRECH_FULL://充满窗口
    dc.StretchBlt(r.left,r.top,r.Width(),r.Height(),&memdc,0,0,
    bmp.bmWidth,bmp.bmHeight,SRCCOPY);
    break;
    case STRECH_CENTER://居中显示,大小为窗口的一半
    dc.StretchBlt(r.Width()/4,r.Height()/4,r.Width()/2,r.Height()/2,&memdc,0,0,
    bmp.bmWidth,bmp.bmHeight,SRCCOPY);
    break;
    }
    再创建内存设备场景,参考上面的OnDraw函数,然后if(!pDC->StretchBlt(.......))后面差不多一致,应该差不多了吧。
      

  2.   

    后面缩放是在OnPaint中实现的,m_bmpImage是另一个CBitmap对象.pDC要改成dc.或者把对应的dc.xxxx  改成pDC->xxxx(如果在OnDraw函数中实现缩放的话)