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

    xiaoxiao2026-04-10  4

    尽管本章的初衷是用滚动条来显示一张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.      }

    实现效果图如下:

            

    转载请注明原文地址: https://ju.6miu.com/read-1308707.html
    最新回复(0)