帶滾動條的大圖無刷新顯示框

 以前看到有人開發的帶滾動條的大圖無刷新顯示框,不知道採用什麼技術開發的,基本功能可以,但是滾動條長度有時會超出圖形框,用戶體驗大打折扣。閒來無事時,決定自己動手寫一個。技術很簡單,就是從CWnd繼承一個窗口類,根據圖像大小自動顯示滾動條,由於知道圖形大小和窗口大小,滾動條的最大值就確定了,根據滾動條的位置就可以算出當前窗口影射到圖像上的位置,然後創建內存dc,從圖像上copy相應大小的圖形到內存dc上,然後複製到窗口dc上,這樣就大功告成,簡單吧。代碼如下:

 

#if !defined(AFX_BAR_H__90C0CEA8_EB58_4CC7_A33A_CEC11E8527AE__INCLUDED_)
#define AFX_BAR_H__90C0CEA8_EB58_4CC7_A33A_CEC11E8527AE__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Bar.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CShowBitmap window

class CShowBitmap : public CWnd
{
// Construction
public:
 CShowBitmap();

// Attributes
public:

// Operations
public:

// Overrides
 // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(CShowBitmap)
 //}}AFX_VIRTUAL

// Implementation
public:
 virtual ~CShowBitmap();

 // Generated message map functions
protected:
 //{{AFX_MSG(CShowBitmap)
 afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
 afx_msg void OnPaint();
 afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
 afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
 afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
 afx_msg void OnMButtonDown(UINT nFlags, CPoint point);
 afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
 //}}AFX_MSG
 DECLARE_MESSAGE_MAP()
public:
 void SetBitmap(HBITMAP hbit);
 BOOL Create( LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
protected:
 void DrawBmp(CDC *pDC);
 HBITMAP m_hBit;
 BOOL m_bHScroll;
 BOOL m_bVScroll;
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_BAR_H__90C0CEA8_EB58_4CC7_A33A_CEC11E8527AE__INCLUDED_)

 

///cpp file

 

// Bar.cpp : implementation file
//

#include "stdafx.h"
#include "ShowBitmap.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define INTSCROL 10
/////////////////////////////////////////////////////////////////////////////
// CShowBitmap

CShowBitmap::CShowBitmap()
{
 m_hBit = NULL;
 m_bHScroll = FALSE;
 m_bVScroll = FALSE;
}

CShowBitmap::~CShowBitmap()
{
}


BEGIN_MESSAGE_MAP(CShowBitmap, CWnd)
 //{{AFX_MSG_MAP(CShowBitmap)
 ON_WM_VSCROLL()
 ON_WM_PAINT()
 ON_WM_HSCROLL()
 ON_WM_MOUSEWHEEL()
 ON_WM_LBUTTONDOWN()
 ON_WM_MBUTTONDOWN()
 ON_WM_RBUTTONDOWN()
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CShowBitmap message handlers

void CShowBitmap::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
 // TODO: Add your message handler code here and/or call default
 int minpos;
 int maxpos;
 GetScrollRange(SB_VERT,&minpos, &maxpos);
 maxpos = GetScrollLimit(SB_VERT);

 // Get the current position of scroll box.
 int curpos = GetScrollPos(SB_VERT);

 // Determine the new position of scroll box.
 switch (nSBCode)
 {
  case SB_TOP:      // Scroll to far up.
   curpos = minpos;
   break;

  case SB_BOTTOM:      // Scroll to far right.
   curpos = maxpos;
   break;

  case SB_ENDSCROLL:   // End scroll.
   break;

  case SB_LINEUP:      // Scroll left.
   if (curpos > minpos)
   {
    if(curpos - minpos >= INTSCROL)
     curpos -= INTSCROL;
    else
     curpos = minpos;
   }
   break;

  case SB_LINEDOWN:   // Scroll right.
   if (curpos < maxpos)
   {
    if(maxpos - curpos >= INTSCROL)
     curpos += INTSCROL;
    else
     curpos = maxpos;
   }
  break;

  case SB_PAGEUP:    // Scroll one page left.
  {
   // Get the page size.
   SCROLLINFO   info;
   GetScrollInfo(SB_VERT,&info, SIF_ALL);

   if (curpos > minpos)
   curpos = max(minpos, curpos - (int) info.nPage);
  }
  break;

  case SB_PAGEDOWN:      // Scroll one page right.
  {
   // Get the page size.
   SCROLLINFO   info;
   GetScrollInfo(SB_VERT,&info, SIF_ALL);
   if (curpos < maxpos)
    curpos = min(maxpos, curpos + (int) info.nPage);
  }
  break;

  case SB_THUMBPOSITION: // Scroll to absolute position. nPos is the position
   curpos = nPos;      // of the scroll box at the end of the drag operation.

  break;

  case SB_THUMBTRACK:   // Drag scroll box to specified position. nPos is the
   curpos = nPos;     // position that the scroll box has been dragged to.
  break;
 }

 // Set the new position of the thumb (scroll box).
 SetScrollPos(SB_VERT,curpos);

 //CRect rc;
 // GetClientRect(rc);
 DrawBmp(GetDC());
 CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
 //  InvalidateRect(rc);
}

BOOL CShowBitmap::Create( LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
 CString strCls;
 // ´´½¨±à¼­¿ò
 strCls = AfxRegisterWndClass(CS_CLASSDC|CS_SAVEBITS, LoadCursor(NULL, IDC_ARROW));
 BOOL bRet = CWnd::Create(strCls,lpszWindowName,dwStyle|WS_BORDER|WS_VSCROLL|WS_HSCROLL|WS_CHILD|WS_VISIBLE,rect,pParentWnd,nID,pContext); 
 if(bRet)
 {
  ModifyStyleEx(0,WS_EX_TRANSPARENT |WS_EX_CLIENTEDGE );
  ShowScrollBar(SB_BOTH,FALSE);
 }
 return bRet;
}

void CShowBitmap::SetBitmap(HBITMAP hbit)
{
 m_hBit = hbit;
 ShowScrollBar(SB_BOTH,FALSE);
 m_bHScroll = FALSE;
 m_bVScroll = FALSE;
 CRect rc;
 GetClientRect(rc);

 // Çå¿Õ½çÃæ
 if(m_hBit == NULL)
 {
  DrawBmp(GetDC());
  return;
 }
 // ÉèÖÃscroll
 // µÃµ½Í¼ÐÎÐÅÏ¢
 BITMAP bi;
 ::GetObject(m_hBit,sizeof(BITMAP),&bi);
 m_bHScroll = (bi.bmWidth - rc.Width()) > 0;
 m_bVScroll = (bi.bmHeight - rc.Height()) > 0;
 SCROLLINFO scinfo;
 scinfo.cbSize = sizeof(SCROLLINFO);
 scinfo.fMask = SIF_ALL;
 scinfo.nMin = 0;
 scinfo.nTrackPos = 0;
 scinfo.nPos = 0;
 ShowScrollBar(SB_HORZ,m_bHScroll);
 ShowScrollBar(SB_VERT,m_bVScroll);
 GetClientRect(rc);
 if(m_bHScroll)
 {
  scinfo.nMax = bi.bmWidth;  
  scinfo.nPage = rc.Width();
  SetScrollInfo(SB_HORZ,&scinfo); 
 }
 if(m_bVScroll)
 {
  scinfo.nMax = bi.bmHeight;
  scinfo.nPage = rc.Height();
  SetScrollInfo(SB_VERT,&scinfo); 
 }
 DrawBmp(GetDC());
}

void CShowBitmap::DrawBmp(CDC *pDC)
{
 CRect rc;
 GetClientRect(rc);
 if(m_hBit == NULL)
 {
  CBitmap bitTmp;
  CDC memDc;
  memDc.CreateCompatibleDC(NULL);  
  bitTmp.CreateCompatibleBitmap(pDC,rc.Width(),rc.Height());
  CBitmap * pOld = (CBitmap*)memDc.SelectObject(&bitTmp);  
  CBrush brush;
  brush.CreateSolidBrush(RGB(255,255,255));
  memDc.FillRect(rc,&brush); 
  pDC->BitBlt(0,0,rc.Width(),rc.Height(),&memDc,0,0,SRCCOPY);
  memDc.SelectObject(pOld);
  return;
 }
 int x =0,y = 0;

 BITMAP bi;
 ::GetObject(m_hBit,sizeof(BITMAP),&bi);

 int nH,nW;
 int nDx,nDy;
 nDx = 0;
 nDy = 0;
 if(m_bVScroll) // ÊúÖ±¹ö¶¯Ìõ
 {
  y = GetScrollPos(SB_VERT);
  nH = rc.Height();
 }
 else
 {
  nH = bi.bmHeight;
  nDy = (rc.Height() - nH)/2;
 }
 if(m_bHScroll) // ˮƽ¹ö¶¯Ìõ
 {
  x = GetScrollPos(SB_HORZ);
  nW = rc.Width();
 }
 else
 {
  nW = bi.bmWidth;
  nDx = (rc.Width() - nW)/2;
 }

 CBitmap bitTmp,bit;
 CDC memDc,dc;
 bit.Attach(m_hBit);
 memDc.CreateCompatibleDC(NULL);
 CBitmap * pOldbmp = memDc.SelectObject(&bit);
 dc.CreateCompatibleDC(NULL);
 bitTmp.CreateCompatibleBitmap(pDC,rc.Width(),rc.Height());
 CBitmap * pOld = (CBitmap*)dc.SelectObject(&bitTmp); 
 CBrush brush;
 brush.CreateSolidBrush(RGB(255,255,255));
 dc.FillRect(rc,&brush);
 dc.SetStretchBltMode(COLORONCOLOR);
 dc.StretchBlt(nDx,nDy,nW,nH,&memDc,x,y,nW,nH,SRCCOPY);
 pDC->BitBlt(0,0,rc.Width(),rc.Height(),&dc,0,0,SRCCOPY);
 dc.SelectObject(pOld);
 memDc.SelectObject(pOldbmp);
 bit.Detach();

/* CBitmap bitTmp;
 CDC dc;


 dc.CreateCompatibleDC(pDC);
 bitTmp.CreateCompatibleBitmap(pDC,100,100);
 CBitmap * pOld = (CBitmap*)dc.SelectObject(&bitTmp);
 CBrush brush;
 brush.CreateSolidBrush(RGB(255,255,255));
 dc.FillRect(CRect(0,0,100,100),&brush);
 dc.MoveTo(10,10);
 dc.LineTo(100,10);
 dc.SelectObject(pOld);

 pDC->SelectObject(bitTmp); 
// bitTmp.Detach();*/

}

void CShowBitmap::OnPaint()
{
 CPaintDC dc(this); // device context for painting
 DrawBmp(&dc);

/* CDC * pDC;
 pDC = CDC::FromHandle(::GetDC(NULL));
 CBitmap bitTmp;
 CDC dc;
 dc.CreateCompatibleDC(pDC);
 bitTmp.CreateCompatibleBitmap(pDC,100,100);
 CBitmap * pOld = (CBitmap*)dc.SelectObject(&bitTmp);
 CBrush brush;
 brush.CreateSolidBrush(RGB(255,255,255));
 dc.FillRect(CRect(0,0,100,100),&brush);
 dc.MoveTo(10,10);
 dc.LineTo(100,10);
 dc.SelectObject(pOld);
 pDC->SelectObject(bitTmp);*/ 
}

void CShowBitmap::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{

 int minpos;
 int maxpos;
 GetScrollRange(SB_VERT,&minpos, &maxpos);
 maxpos = GetScrollLimit(SB_HORZ);

 // Get the current position of scroll box.
 int curpos = GetScrollPos(SB_HORZ);

// Determine the new position of scroll box.
 switch (nSBCode)
 {
  case SB_LEFT:      // Scroll to far left.
  curpos = minpos;
  break;

  case SB_RIGHT:      // Scroll to far right.
  curpos = maxpos;
  break;

  case SB_ENDSCROLL:   // End scroll.
  break;

  case SB_LINELEFT:      // Scroll left.
  if (curpos > minpos)
  {
   if(curpos - minpos >= INTSCROL)
    curpos -= INTSCROL;
   else
    curpos = minpos;
  }
  break;

  case SB_LINERIGHT:   // Scroll right.
  if (curpos < maxpos)
  {
   if(maxpos - curpos >= INTSCROL)
    curpos += INTSCROL;
   else
    curpos = maxpos;
  }
  break;

  case SB_PAGELEFT:    // Scroll one page left.
  {
   // Get the page size.
   SCROLLINFO   info;
   GetScrollInfo(SB_HORZ,&info, SIF_ALL);

   if (curpos > minpos)
   curpos = max(minpos, curpos - (int) info.nPage);
  }
  break;

  case SB_PAGERIGHT:      // Scroll one page right.
  {
   // Get the page size.
   SCROLLINFO   info;
   GetScrollInfo(SB_HORZ,&info, SIF_ALL);
   if (curpos < maxpos)
    curpos = min(maxpos, curpos + (int) info.nPage);
  }
  break;

  case SB_THUMBPOSITION: // Scroll to absolute position. nPos is the position
  curpos = nPos;      // of the scroll box at the end of the drag operation.

  break;

  case SB_THUMBTRACK:   // Drag scroll box to specified position. nPos is the
  curpos = nPos;     // position that the scroll box has been dragged to.
  break;
 }

 // Set the new position of the thumb (scroll box).
 SetScrollPos(SB_HORZ,curpos);

 DrawBmp(GetDC());

 CWnd::OnHScroll(nSBCode, nPos, pScrollBar);
}

BOOL CShowBitmap::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
 // TODO: Add your message handler code here and/or call default
 if(m_bVScroll)
 {
  if(zDelta > 0) // ÏòÉÏ
   OnVScroll(SB_LINEUP,0,NULL);
  else // ÏòÏÂ
   OnVScroll(SB_LINEDOWN,0,NULL);
 }
 return CWnd::OnMouseWheel(nFlags, zDelta, pt);
}


void CShowBitmap::OnLButtonDown(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 this->SetFocus();
 CWnd::OnLButtonDown(nFlags, point);
}

void CShowBitmap::OnMButtonDown(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 this->SetFocus();
 CWnd::OnMButtonDown(nFlags, point);
}

void CShowBitmap::OnRButtonDown(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 this->SetFocus();
 CWnd::OnRButtonDown(nFlags, point);
}

 

發佈了27 篇原創文章 · 獲贊 1 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章