<对话框控件显示图片>
在VC对话框程序中,图片的显示载体一般需要使用对话框控件。在此总结下在控件上绘图的几点东西:
1、在对话框资源中放置图片控件,并对其类型属性选为Frame。可在对话框的绘图消息响应函数OnPaint或其他函数中,用CWnd类的函数GetDlgItem:CWnd* GetDlgItem( int nID ) const;来获得图片控件的窗口对象,再用函数GetDC:CDC* GetDC( );由窗口对象得到DC,然后就可以用该DC在控件中画图。
2、在对话框资源中放置非Frame类静态控件,先按顺序依次调用CWnd类的Invalidate和UpdateWindow函数后,再开始用DC画图。
注:
I、为了使在运行时能够不断及时更新控件的显示(主要是自己加的显式代码),可以将自己绘制控件的所有代码都全部加入对话框类的消息响应函数OnPaint中。在需要时(例如在绘图参数修改后),自己调用CWnd的Invalidate和UpdateWindow函数,请求系统刷新对话框和控件的显示。因为控件也是窗口,控件类都是CWnd的派生类。所以在对话框和控件中,可以像在视图类中一样,调用各种CWnd的成员函数;
II、为了在鼠标指向控件时,避免控件自己绘制的图形消去,需要设置控件的“Owner Draw”属性为“True”;
III、如果希望非按钮控件(如图片控件和静态文本等),也可以响应鼠标消息(如单击、双击等),需要设置控件的“Notify”属性为“True”;
<使用对话框滚动条浏览控件上的图片>
当图片显示范围超过控件大小时,我们需要使用滚动图片以便浏览超出图片的其他部分。对话框滚动条控件包括水平滚动条和垂直滚动条,使用步骤:
1、像对话框添加两种控件资源,分别添加实例变量;
2、添加控件的响应消息函数CWnd::OnVScroll 和CWnd::OnHScroll,完成控件的滚动消息响应;
3、根据滚动位置更新图片的显示区域;
注:
---------------------------------------------------------------------------------------
CWnd::OnHScroll
afx_msg void OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar );
Parameters
nSBCode
Specifies a scroll-bar code that indicates the user’s scrolling request. This parameter can be one of the following:
- SB_LEFT Scroll to far left.
- SB_ENDSCROLL End scroll.
- SB_LINELEFT Scroll left.
- SB_LINERIGHT Scroll right.
- SB_PAGELEFT Scroll one page left.
- SB_PAGERIGHT Scroll one page right.
- SB_RIGHT Scroll to far right.
- SB_THUMBPOSITION Scroll to absolute position. The current position is specified by the nPos parameter.
- SB_THUMBTRACK Drag scroll box to specified position. The current position is specified by the nPos parameter.
nPos
Specifies the scroll-box position if the scroll-bar code is SB_THUMBPOSITION or SB_THUMBTRACK; otherwise, not used. Depending on the initial scroll range, nPos may be negative and should be cast to an int if necessary.
pScrollBar
If the scroll message came from a scroll-bar control, contains a pointer to the control. If the user clicked a window’s scroll bar, this parameter is NULL. The pointer may be temporary and should not be stored for later use.
Remarks
The framework calls this member function when the user clicks a window’s horizontal scroll bar.
The SB_THUMBTRACK scroll-bar code typically is used by applications that give some feedback while the scroll box is being dragged.
If an application scrolls the contents controlled by the scroll bar, it must also reset the position of the scroll box with the SetScrollPos member function.
Note This member function is called by the framework to allow your application to handle a Windows message. The parameters passed to your function reflect the parameters received by the framework when the message was received. If you call the base-class implementation of this function, that implementation will use the parameters originally passed with the message and not the parameters you supply to the function.
Example
void CMyView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { // Get the minimum and maximum scroll-bar positions. int minpos; int maxpos; pScrollBar->GetScrollRange(&minpos, &maxpos); maxpos = pScrollBar->GetScrollLimit(); // Get the current position of scroll box. int curpos = pScrollBar->GetScrollPos(); // 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) curpos--; break; case SB_LINERIGHT: // Scroll right. if (curpos < maxpos) curpos++; break; case SB_PAGELEFT: // Scroll one page left. { // Get the page size. SCROLLINFO info; pScrollBar->GetScrollInfo(&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; pScrollBar->GetScrollInfo(&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). pScrollBar->SetScrollPos(curpos); CView::OnHScroll(nSBCode, nPos, pScrollBar); }
-----------------------------------------------------------------------------
CWnd::OnVScroll
afx_msg void OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar );
Parameters
nSBCode
Specifies a scroll-bar code that indicates the user’s scrolling request. This parameter can be one of the following:
- SB_BOTTOM Scroll to bottom.
- SB_ENDSCROLL End scroll.
- SB_LINEDOWN Scroll one line down.
- SB_LINEUP Scroll one line up.
- SB_PAGEDOWN Scroll one page down.
- SB_PAGEUP Scroll one page up.
- SB_THUMBPOSITION Scroll to the absolute position. The current position is provided in nPos.
- SB_THUMBTRACK Drag scroll box to specified position. The current position is provided in nPos.
- SB_TOP Scroll to top.
nPos
Contains the current scroll-box position if the scroll-bar code is SB_THUMBPOSITION or SB_THUMBTRACK; otherwise not used. Depending on the initial scroll range, nPos may be negative and should be cast to an int if necessary.
pScrollBar
If the scroll message came from a scroll-bar control, contains a pointer to the control. If the user clicked a window’s scroll bar, this parameter is NULL. The pointer may be temporary and should not be stored for later use.
Remarks
The framework calls this member function when the user clicks the window’s vertical scroll bar.
OnVScroll typically is used by applications that give some feedback while the scroll box is being dragged.
If OnVScroll scrolls the contents of the CWnd object, it must also reset the position of the scroll box with the SetScrollPos member function.
Note This member function is called by the framework to allow your application to handle a Windows message. The parameters passed to your function reflect the parameters received by the framework when the message was received. If you call the base-class implementation of this function, that implementation will use the parameters originally passed with the message and not the parameters you supply to the function.
<程序示例>
滚动消息响应:根据图片的显示大小设置滚动条的滚动步长信息
void CImageboxUI::OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar ) { SCROLLINFO vSI; m_vScrollBar.GetScrollInfo(&vSI); switch (nSBCode) { case SB_TOP: vSI.nPos = 0; break; case SB_BOTTOM: vSI.nPos = INT_MAX; break; case SB_LINEUP: { vSI.nPos -= (int)((m_imageShow.Height()*m_dRatioY)/70); vSI.nPos = vSI.nPos<vSI.nMin? vSI.nMin:vSI.nPos; } break; case SB_LINEDOWN: { vSI.nPos += (int)((m_imageShow.Height()*m_dRatioY)/70); vSI.nPos = vSI.nPos>vSI.nMax? vSI.nMax:vSI.nPos; } break; case SB_PAGEUP: break; case SB_PAGEDOWN: break; case SB_THUMBPOSITION: break; case SB_THUMBTRACK: vSI.nPos = nPos; break; case SB_ENDSCROLL: break; } m_vScrollBar.SetScrollInfo(&vSI); SendMessage(WM_PAINT); CDialog::OnVScroll(nSBCode, nPos, pScrollBar); } void CImageboxUI::OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar ) { SCROLLINFO hSI; m_hScrollBar.GetScrollInfo(&hSI); switch (nSBCode) { case SB_LEFT: hSI.nPos = 0; break; case SB_RIGHT: hSI.nPos = INT_MAX; break; case SB_LINERIGHT: { hSI.nPos += (int)((m_imageShow.Width()*m_dRatioX)/70); hSI.nPos = hSI.nPos<hSI.nMin? hSI.nMin:hSI.nPos; } break; case SB_LINELEFT: { hSI.nPos -= (int)((m_imageShow.Width()*m_dRatioX)/70); hSI.nPos = hSI.nPos<hSI.nMin? hSI.nMin:hSI.nPos; } break; case SB_PAGEUP: break; case SB_PAGEDOWN: break; case SB_THUMBPOSITION: break; case SB_THUMBTRACK: hSI.nPos = nPos; break; case SB_ENDSCROLL: break; } m_hScrollBar.SetScrollInfo(&hSI); SendMessage(WM_PAINT); CDialog::OnHScroll(nSBCode, nPos, pScrollBar); }
根据滚动信息进行图片绘制(双缓冲机制):
void CImageboxUI::OnPaint() { CPaintDC dc(this); // device context for painting // TODO: 在此处添加消息处理程序代码 // 不为绘图消息调用 CDialog::OnPaint() ////////////////////////////////////////////////////////////////////////// // 对话框Static控件双缓冲绘图 CWnd* pImageWnd=GetDlgItem(IDC_STATIC_PIC); if (NULL==pImageWnd) return; pImageWnd->ModifyStyle(0, BS_OWNERDRAW); // 修改CStatic样式,改成自绘制(图形不被消去) // 绘图控件的DC CDC* pDC=pImageWnd->GetDC(); if (NULL==pDC) return; // 绘图背景区域大小 pImageWnd->GetWindowRect(&m_backShow); ScreenToClient(&m_backShow); // 图像绘制的实际大小 CRect imageShow; imageShow.SetRect(0,0, (int)(m_imageShow.Width()*m_dRatioX), (int)(m_imageShow.Height()*m_dRatioY)); // 滚动条信息 SCROLLINFO vSI, hSI; m_vScrollBar.GetScrollInfo(&vSI); m_hScrollBar.GetScrollInfo(&hSI); /// 绘图 CDC memeroyDC; CBitmap memeroyBP; memeroyDC.CreateCompatibleDC(NULL); memeroyBP.CreateCompatibleBitmap(pDC,m_backShow.Width(),m_backShow.Height()); CBitmap *pOldBit=memeroyDC.SelectObject(&memeroyBP); // 在内存上绘制绘图背景 CBrush backBrush; backBrush.CreateSolidBrush(RGB(128,128,128)); CBrush* pOldBrush=memeroyDC.SelectObject(&backBrush); memeroyDC.Rectangle(&m_backShow); memeroyDC.SelectObject(pOldBrush); backBrush.DeleteObject(); // 在内存上绘制实际大小图像 if (m_backShow.Width()<imageShow.Width()) { ; } else { int y=0; int x=(int)((m_backShow.Width()-imageShow.Width())/2.0); if (m_backShow.Height()>imageShow.Height()) { y=(int)((m_backShow.Height()-imageShow.Height())/2.0); } imageShow.OffsetRect(x,y); } imageShow.OffsetRect(-hSI.nPos,-vSI.nPos); m_imageFile.StretchBlt(memeroyDC.m_hDC, imageShow, SRCCOPY); // 将内存图像绘制到控件 pDC->BitBlt(0,0,m_backShow.Width(),m_backShow.Height(),&memeroyDC,0,0,SRCCOPY); // 释放对象和DC memeroyBP.DeleteObject(); memeroyDC.SelectObject(pOldBit); memeroyDC.DeleteDC(); ReleaseDC(pDC); }
<程序效果>