vs2015 滚动条实现,浏览Bitmap图片

尽管本章的初衷是用滚动条来显示一张bmp图片,但是他涉及到3大主题

1.       运行时在对话框加载一张bitmap图片

2.       通过滚动条技术显示一张原始大小的bitmap图片

3.       通过双缓存技术实现绘图不闪烁

 代码下载:

http://download.csdn.net/detail/zang141588761/9604527

运行时在对话框加载一张bitmap图片

使用类生成向导,为IDC_STATIC1创建一个名为m_st1 的CStatic控件变量

在对话框的头文件中MyDlg.h,加入如下代码

1.  public:

2.     CRect rectStaticClient;

3.    int sourcex, sourcey,offsetx,offsety;

4.   protected:

5.    CDC m_dcMem;            // Compatible Memory DC for dialog

6.     HBITMAP m_hBmpOld;     //Handle of old bitmap to save

7.    HBITMAP m_hBmpNew;      // Handle of new bitmap from file

8.     BITMAP m_bmInfo;       //Bitmap Information structure

在对话框的实现文件中MyDlg.cpp,加入如下代码

1.     BOOL CMyDlg::OnInitDialog()

2.   {

3.   

4.   // TODO: Add extrainitialization here

5.    CClientDC dc(this);

6.      m_dcMem.CreateCompatibleDC(&dc);

7.      return TRUE; // return TRUEunless you set the focus to a

8.                 // control

9.  }

重写对话框的OnPaint函数

1.      void MyDlg::OnPaint()

2.   {

3.    if (IsIconic())

4.     {

5.      CPaintDC dc(this);   // device context for painting

6.    

7.      SendMessage(WM_ICONERASEBKGND,(WPARAM) dc.GetSafeHdc(),0);

8.    

9.      // Center icon inclient rectangle

10.      int cxIcon=GetSystemMetrics(SM_CXICON);

11.     int cyIcon = GetSystemMetrics(SM_CYICON);

12.      CRect rect;

13.     GetClientRect(&rect);

14.      int x=(rect.Width()- cxIcon+ 1)/2;

15.     int y = (rect.Height()- cyIcon+1)/2;

16.   

17.     // Draw the icon

18.      dc.DrawIcon(x, y, m_hIcon);

19.   }

20.    else

21.   {

22.    //Add the following code

23.   CPaintDC dc(this);

24.      dc.BitBlt(offsetx,offsety,m_size.cx,m_size.cy,

25.               &m_dcMem, sourcex, sourcey,SRCCOPY);

26.    CDialog::OnPaint();

27.  

28.    }

29. }

1.  写入如下代码,在对话框中你想要加载图片的地方
m_hBmpNew= (HBITMAP)LoadImage(

2.     AfxGetInstanceHandle(),  // handle to instance

3.    filename,                // name or identifier of the image,

4.                               // say,"C:\\NewFolder\\1.bmp"

5.    IMAGE_BITMAP,            // image types

6.     0,    // desired width

7.    0,    // desired height

8.     LR_LOADFROMFILE);

9.   

10.    if( m_hBmpNew== NULL)

11. {

12.  AfxMessageBox("Load ImageFailed");

13. }

14.   

15.     // put the HBITMAPinfo into the CBitmap

16.      // (but not the bitmap itself)

17.     else{

18.      m_st1.GetClientRect(&rectStaticClient);

19.   rectStaticClient.NormalizeRect();

20.    m_size.cx=rectStaticClient.Size().cx;

21.   m_size.cy=rectStaticClient.Size().cy;

22.    m_size.cx= rectStaticClient.Width();    //zero based

23.   m_size.cy = rectStaticClient.Height();   // zero based

24.   

25.     // Convert toscreen coordinates using static as base,

26.      // then to DIALOG (instead of static)client coords

27.     // using dialog asbase

28.    m_st1.ClientToScreen(&rectStaticClient);

29.   ScreenToClient(&rectStaticClient);

30.          

31.     m_pt.x = rectStaticClient.left;

32.      m_pt.y= rectStaticClient.top;

33.   GetObject( m_hBmpNew,sizeof(BITMAP),&m_bmInfo);

34.    VERIFY(m_hBmpOld=(HBITMAP)SelectObject(m_dcMem, m_hBmpNew

35.                        )  );

36.  offsetx= m_pt.x;  //

37.   offsety=m_pt.y; //

38.  InvalidateRect(&rectStaticClient);

 

通过滚动条技术显示一张原始大小的bitmap图片

通过类生成向导,创建水平、垂直滚动条成员变量如下:

1.    CScrollBar m_vbar;   //For vertical scroll bar

2.     CScrollBar m_hbar;   //For horizontalscroll bar

你需要创建两个SCROLLINFO 结构体来存储水平与垂直滚动条参数,所以在对话框头文件中声明如下:

1.     public:

2.     CRect rectStaticClient;

3.    int sourcex, sourcey,offsetx,offsety;

4.     SCROLLINFO horz,vert;

在初始化的时候隐藏滚动条

1.      BOOL CMyDlg::OnInitDialog()

2.   {

3.   

4.   // TODO: Add extrainitialization here

5.    CClientDC dc(this);

6.     m_dcMem.CreateCompatibleDC(&dc);

7.    m_vbar.ShowWindow(false);   //Hide vertical scroll bar

8.     m_hbar.ShowWindow(false);   //Hide horizontalscroll bar

9.  return TRUE;                  //return TRUEunless you set the

10.                                 //focus to acontrol

11. }

 

当你加载图片到预先定义的图片空间会有4中情况

1)  加载图片的宽度与长度都大于图片控件。

1.     m_size.cx = rectStaticClient.Width();    // zero based

2.      m_size.cy= rectStaticClient.Height();   // zero based

3.   GetObject( m_hBmpNew,sizeof(BITMAP),&m_bmInfo);

4.   

            Max. verticalScrollingRange=m_bmInfo.bmHeight-m_size.cy

5. Max.HorizontalScrollingRange=m_bmInfo.bmWidth-m_size.cx;

6. m_hbar.ShowWindow(true);

7.  m_vbar.ShowWindow(true);

 

2)  宽度大于图片控件,高度小于等于图片控件

          Max.HorizontalScrollingRange=m_bmInfo.bmWidth-m_size.cx;

          offsety= m_pt.y+((m_size.cy- m_bmInfo.bmHeight)/2);

m_hbar.MoveWindow(offsetx,offsety+ m_bmInfo.bmHeight m_size.cx,18);,                         

m_hbar.ShowWindow(true);

m_vbar.ShowWindow(false);

3)  高度大于图片控件,宽度小于等于图片控件

Max.VerticalScrollingRange=m_bmInfo.bmHeight-m_size.cy;

offsetx= m_pt.x+((m_size.cx- m_bmInfo.bmWidth)/2);

m_vbar.MoveWindow(offsetx+ m_bmInfo.bmWidth,offsety,18,

                            m_size.cy);

m_hbar.ShowWindow(false);

m_vbar.ShowWindow(true);

 

4)  高度与宽度都小于等于图片控件

offsetx= m_pt.x+((m_size.cxn- m_bmInfo.bmWidth)/2);

offsety= m_pt.y+((m_size.cy- m_bmInfo.bmHeight)/2);

m_hbar.ShowWindow(false);

m_vbar.ShowWindow(false);

//Horizontal Scroll Info Structure

horz.cbSize=sizeof(SCROLLINFO);

horz.fMask = SIF_ALL;

horz.nMin=0;

horz.nMax = m_bmInfo.bmWidth-m_size.cx;

horz.nPage=0;

horz.nPos = 0;

horz.nTrackPos=0;

m_hbar.SetScrollInfo(&horz);

 

//Vertical Scroll Info Structure

vert.cbSize=sizeof(SCROLLINFO);

vert.fMask = SIF_ALL;

vert.nMin=0;

vert.nMax = m_bmInfo.bmHeight-m_size.cy;

vert.nPage=0;

vert.nTrackPos=0;

m_vbar.SetScrollInfo(&vert);

InvalidateRect(&rectStaticClient);

 

记住,取决于你加载的图片,滚动条的位置可能不同。所以在加载另一幅图片时,释放保存图片的空间和初始化滚动条的位置。

1.    if(m_hBmpNew!= NULL)

2.       DeleteObject(m_hBmpNew);  //Release memoryholding bitmap

3.  m_vbar.MoveWindow(offsetx+m_size.cx,offsety,18,m_size.cy);

4.       // Reset position of vertical scroll bar

5.  m_hbar.MoveWindow(offsetx,offsety+m_size.cy,m_size.cx,18);

6.       // Reset position of horizontal scroll bar

7.  if(m_hBmpNew!= NULL)

8.       DeleteObject(m_hBmpNew);   //Release memoryholding bitmap

9.    sourcex=sourcey=0;           //Set starting position of Source

10.                                  //bitmap to becopied to (0,0)

11. sm_hBmpNew = (HBITMAP) LoadImage(

12.    AfxGetInstanceHandle(),      // handle to instance

13.   Path of Bitmap,               // name or identifier of the image

14.                                  // (say"C:\\New Folder\\

15.                                 //bitmap.bmp")

16.    IMAGE_BITMAP,                // image types

17.   0,                           // desired width

18.    0,                           // desired height

19.   LR_LOADFROMFILE);

20.    if( m_hBmpNew== NULL){

21.   AfxMessageBox("Load ImageFailed");}

22.   

23.     // put the HBITMAPinfo into the CBitmap (but not the

24.      // bitmap itself)

25.    else{

26.    m_st1.GetClientRect(&rectStaticClient);

27.   rectStaticClient.NormalizeRect();

28.    m_size.cx=rectStaticClient.Size().cx;

29.   m_size.cy=rectStaticClient.Size().cy;

30.    m_size.cx= rectStaticClient.Width();    //zero based

31.   m_size.cy = rectStaticClient.Height();   // zero based

32.   

33.     // Convert toscreen coordinates using static as base,

34.      // then to DIALOG (instead of static)client coords

35.     // using dialog asbase

36.    m_st1.ClientToScreen(&rectStaticClient);

37.   ScreenToClient(&rectStaticClient);

38.          

39.     m_pt.x = rectStaticClient.left;

40.      m_pt.y= rectStaticClient.top;

41.   GetObject( m_hBmpNew,sizeof(BITMAP),&m_bmInfo);

42.    VERIFY(m_hBmpOld=(HBITMAP)SelectObject(m_dcMem, m_hBmpNew

43.                       )  );

44.   

45.   offsetx= m_pt.x;

46.    offsety=m_pt.y;

47. m_vbar.MoveWindow(offsetx+m_size.cx,offsety,18,m_size.cy);

48.      // Reset position of vertical scroll bar

49. m_hbar.MoveWindow(offsetx,offsety+m_size.cy,m_size.cx,18);

50.      // Reset position of horizontal scroll bar

51. horz.cbSize = sizeof(SCROLLINFO);

52.  horz.fMask= SIF_ALL;

53. horz.nMin = 0;

54.  horz.nMax= m_bmInfo.bmWidth-m_size.cx;

55. horz.nPage =0;

56.  horz.nPos=0;

57. horz.nTrackPos=0;

58.  if(m_bmInfo.bmWidth<=m_size.cx)

59. {

60.    if((m_size.cx-m_bmInfo.bmWidth)==0)

61.     offsetx= m_pt.x;

62.    else

63.     offsetx= m_pt.x+((m_size.cx-m_bmInfo.bmWidth)/2);

64.    m_vbar.MoveWindow(offsetx+ m_bmInfo.bmWidth,offsety,18,

65.                               m_size.cy);

66.    m_hbar.ShowWindow(false);

67. }

68.  else

69. m_hbar.ShowWindow(true);

70.  m_hbar.SetScrollInfo(&horz);

71. vert.cbSize = sizeof(SCROLLINFO);

72.  vert.fMask= SIF_ALL;

73. vert.nMin = 0;

74.  vert.nMax= m_bmInfo.bmHeight-(m_size.cy);

75. vert.nPage = 0;

76.  vert.nTrackPos=0;

77. if(m_bmInfo.bmHeight<=m_size.cy)

78.  {

79.   if((m_size.cy-m_bmInfo.bmHeight)==0)

80.      offsety= m_pt.y;

81.   else

82.      offsety= m_pt.y+((m_size.cy-m_bmInfo.bmHeight)/2);

83.   m_hbar.MoveWindow(offsetx,offsety+m_bmInfo.bmHeight,

84.                                      m_size.cx,18);

85.   m_vbar.ShowWindow(false);

86.  }

87. else

88.  m_vbar.ShowWindow(true);

89. m_vbar.SetScrollInfo(&vert);

90.   

91.   InvalidateRect(&rectStaticClient);

处理WM_VSCROLL 和 WM_HSCROLL 消息

1.      void CMyDlg::OnVScroll(UINT nSBCode, UINT nPos,CScrollBar*

2.                                                   pScrollBar)

3.  {

4.     // TODO: Add your message handler code hereand/or call default

5.    switch (nSBCode)

6.   {

7.  case SB_TOP:

8.   sourcey = 0;

9.  break;

10.  case SB_BOTTOM:

11. sourcey = INT_MAX;

12.  break;

13. case SB_THUMBTRACK:

14.  sourcey = nPos;

15. break;

16.  }

17.  

18.  m_vbar.SetScrollPos(sourcey);

19. InvalidateRect(&rectStaticClient);

20.    CDialog::OnVScroll(nSBCode, nPos, pScrollBar);

21. }

22.   

23. void CMyDlg::OnHScroll(UINT nSBCode, UINT nPos,CScrollBar*

24.                                                  pScrollBar)

25. {

26.    // TODO: Add your message handler code hereand/or call default

27. switch (nSBCode)

28.  {

29. case SB_TOP:

30.  sourcex = 0;

31. break;

32.  case SB_BOTTOM:

33. sourcex = INT_MAX;

34.  break;

35. case SB_THUMBTRACK:

36.  sourcex= nPos;

37. break;

38.  }

39. m_hbar.SetScrollPos(sourcex);

40.  InvalidateRect(&rectStaticClient);

41.   CDialog::OnHScroll(nSBCode, nPos, pScrollBar);

 

通过双缓存技术实现绘图不闪烁

 

 

为了消除在绘图的时候闪烁,你需要绘制一个内存DC,并通过BitBlt或StretchBlt函数拷贝到真正的DC。这种技术称为双缓存技术。

重载OnEraseBackground

1.  BOOL MyDlg::OnEraseBkgnd(CDC* pDC)

2.   {

3.    // TODO: Add yourmessage handler code here and/or call default

4.     if(erase)

5.      return false;

6.     else

7.    return CDialog::OnEraseBkgnd(pDC);

8.   }

重置erase 标记位为false在OnPaint函数中

1.  else

2.       {

3.        CPaintDC dc(this);

4.         dc.BitBlt(offsetx,offsety,m_size.cx,m_size.cy,

5.                  &m_dcMem, sourcex, sourcey,SRCCOPY);

6.         erase=false;

7.        CDialog::OnPaint();

8.       

9.      }

实现效果图如下:


        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值