Boz
Boz

Reputation: 51

C++ MFC Picturebox Change Bitmap

I create my derived class for display Bitmap in a picturebox and scrolling if necessary.

I have one problem when I change the bitmap the background is not clear and previous bitmap stay. It is problem when the new image are less width/height.

Have you some idea how I could solve this issues?

My code:

I load the bitmap in function ChargerImage and I draw it in the function DessinerImage.

// Picturebox.cpp : fichier d'implémentation
//

#include "stdafx.h"
#include "Picturebox.h"


// CPicturebox

IMPLEMENT_DYNAMIC(CPicturebox, CWnd)

    CPicturebox::CPicturebox()
{
    coeffZoom=8;
}

CPicturebox::~CPicturebox()
{
}


BEGIN_MESSAGE_MAP(CPicturebox, CWnd)
    ON_WM_HSCROLL(5000,OnHScroll)
    ON_WM_VSCROLL(5001,OnVScroll)
END_MESSAGE_MAP()

void CPicturebox::ReserverMemoire()
{
    CPaintDC dc(this);
    m_dcMem.CreateCompatibleDC(&dc );
    ModifyStyle(WS_HSCROLL|WS_VSCROLL,0);
    UINT uiHHeight = GetSystemMetrics(SM_CYHSCROLL);
    UINT uiVWidth = GetSystemMetrics(SM_CXVSCROLL);
    CRect rectClient, rectH, rectV;
    GetClientRect(rectClient);
    rectH = rectClient;
    rectH.top = rectH.bottom - uiHHeight;
    rectH.right -= uiVWidth;

    rectV = rectClient;
    rectV.left = rectV.right - uiVWidth;
    rectV.bottom -= uiHHeight;
    m_HScroll.Create(SBS_HORZ | SBS_BOTTOMALIGN | WS_CHILD , rectH, this, 5000);
    m_HScroll.EnableScrollBar();
    m_VScroll.Create(SBS_VERT | SBS_RIGHTALIGN | WS_CHILD , rectV, this, 5001);
    m_VScroll.EnableScrollBar();
}

void CPicturebox::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
    switch (nSBCode)
    {
    case SB_TOP:
        sourcey = 0;
        break;
    case SB_BOTTOM:
        sourcey = INT_MAX;
        break;
    case SB_THUMBTRACK:
        sourcey = nPos;
        break;
    }

    m_VScroll.SetScrollPos(sourcey);
    InvalidateRect(&rectStaticClient);
    CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
    DessinerImage();
}

void CPicturebox::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
    switch (nSBCode)
    {
    case SB_TOP:
        sourcex = 0;
        break;
    case SB_BOTTOM:
        sourcex = INT_MAX;
        break;
    case SB_THUMBTRACK:
        sourcex= nPos;
        break;
    }    
    m_HScroll.SetScrollPos(sourcex);
    InvalidateRect(&rectStaticClient);
    CWnd::OnHScroll(nSBCode, nPos, pScrollBar);
    DessinerImage();
}
void CPicturebox::ChargerImage(CString lien,int ImageLargeur,int ImageHauteur)
{
    if(m_hBmpNew != NULL )
        DeleteObject(m_hBmpNew);

    sourcex=sourcey=0;        // Set starting Position of Source Bitmap to 
    //be copied to (0,0)
    m_hBmpNew =    (HBITMAP) LoadImage(AfxGetInstanceHandle(), // handle to instance
        lien,  // name or identifier of the image (say "C:\\bitmap.bmp")
        IMAGE_BITMAP,        // image types
        0,     // desired width
        0,     // desired height
        LR_LOADFROMFILE); 
    if( m_hBmpNew == NULL ) {
        AfxMessageBox("Load Image Failed");
    }    
    // put the HBITMAP info into the CBitmap (but not the bitmap itself)
    else {
        GetClientRect( &rectStaticClient );
        rectStaticClient.NormalizeRect();
        m_size.cx = rectStaticClient.Width();    // zero based
        m_size.cy = rectStaticClient.Height();    // zero based

        // Convert to screen coordinates using static as base,
        // then to DIALOG (instead of static) client coords 
        // using dialog as base
        ClientToScreen( &rectStaticClient );
        ScreenToClient( &rectStaticClient);

        m_pt.x = rectStaticClient.left;
        m_pt.y = rectStaticClient.top;
        GetObject( m_hBmpNew , sizeof(BITMAP), &m_bmInfo );
        VERIFY(m_hBmpOld = (HBITMAP)SelectObject(m_dcMem, m_hBmpNew ));
        if(ImageLargeur>600*coeffZoom)
            largeur=600*coeffZoom;
        else
            largeur=ImageLargeur;
        if(ImageHauteur>300*coeffZoom)
            hauteur=300*coeffZoom;
        else
            hauteur=ImageHauteur;

        impressionLargeur=largeur/coeffZoom*m_size.cx/600;
        impressionHauteur=hauteur/coeffZoom*m_size.cy/300;

        int PrintedWidth=m_bmInfo.bmWidth/coeffZoom;
        int PrintedHeight=m_bmInfo.bmHeight/coeffZoom;

        horz.cbSize = sizeof(SCROLLINFO);
        horz.fMask = SIF_ALL;
        horz.nMin = 0;
        horz.nMax = (m_bmInfo.bmWidth-largeur)/coeffZoom;
        horz.nPage =0;
        horz.nPos = 0;
        horz.nTrackPos=0;

        if(PrintedWidth<=600)
            m_HScroll.ShowScrollBar(false);
        else
            m_HScroll.ShowScrollBar(true);

        m_HScroll.SetScrollInfo(&horz);

        vert.cbSize = sizeof(SCROLLINFO);
        vert.fMask = SIF_ALL;
        vert.nMin = 0;
        vert.nMax = (m_bmInfo.bmHeight-hauteur)/coeffZoom;
        vert.nPage = 0;
        vert.nTrackPos=0;

        if(PrintedHeight<=300)
            m_VScroll.ShowScrollBar(false);
        else
            m_VScroll.ShowScrollBar(true);

        m_VScroll.SetScrollInfo(&vert);

        InvalidateRect(&rectStaticClient);
        DessinerImage();
    }
}
void CPicturebox::DessinerImage()
{
    CPaintDC dc(this);
    dc.SetStretchBltMode(HALFTONE);
    CBitmap* pOldBitmap = (CBitmap*)m_dcMem.SelectObject(&m_bmpBitmap);
    dc.StretchBlt(0,0,impressionLargeur,impressionHauteur, &m_dcMem, sourcex+m_HScroll.GetScrollPos()*coeffZoom, sourcey+m_VScroll.GetScrollPos()*coeffZoom,largeur,hauteur,SRCCOPY);
}

Upvotes: 0

Views: 1447

Answers (1)

ScottMcP-MVP
ScottMcP-MVP

Reputation: 10425

You must do the painting in a WM_PAINT message handler, and you must use CPaintDC only in that handler. See the SCRIBBLE tutorial or the DRAWCLI sample program for examples.

Upvotes: 1

Related Questions