2015-02-01 4 views
0

그림 상자에 비트 맵을 표시하고 필요한 경우 스크롤 할 수있는 파생 클래스를 만듭니다.C++ MFC Picturebox 변경 비트 맵

비트 맵을 변경할 때 배경이 선명하지 않고 이전 비트 맵을 유지할 때 한 가지 문제가 있습니다. 새 이미지의 폭/높이가 작 으면 문제가됩니다.

이 문제를 어떻게 해결할 수 있는지 생각해보십시오.

내 코드 :

나는 기능 ChargerImage에서 비트 맵을로드하고 내가 함수 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); 
} 
+0

죄송합니다. 몇 가지 예가 있습니까? – Boz

+0

새 이미지를로드 한 후'DessinerImage()'에 대한 호출을 제거하십시오. 'InvalidateRect'는 내용의 재 렌더링을 시작하기에 충분합니다 (여러분의'WM_PAINT'-handler가'DessinerImage'를 호출한다고 가정). – IInspectable

답변

1

그림을 WM_PAINT 메시지 처리기에서 수행해야하며 해당 처리기에서만 CPaintDC를 사용해야합니다. 예제는 SCRIBBLE 자습서 또는 DRAWCLI 샘플 프로그램을 참조하십시오.