CButton重绘图片实现自由缩放和拖动


如图所示,上方图片显示利用了重绘的CButton控件,下方List利用了CListCtrl,比较麻烦的地方在于图片缩放和移动的控制,实现的功能有:

1.鼠标左键点击上方图片有效区(非黑色区域)的任一点,保存该点在图片中的逻辑坐标,在图片中以绿色点标注该点,同时在下方List中显示坐标

2.鼠标右键点击图片任一点,则将最近保存的点删除,消除显示的标注点和坐标

3.鼠标左键点击下方List的任一行,该行被高亮激活,图上同时对应的标注点变为红色

4.鼠标右键点击下方List中被高亮激活的行时,会出现右键菜单,鼠标左键点击菜单中Delete时,对应保存的点被删除,同时消除显示的标注点和坐标。

5.图片和列表的大小和布局会随着对话框大小改变而改变。

6.当鼠标位置位于图片范围内是,鼠标滚轮滚动可以缩放图片。缩放中心根据鼠标位置自动调整,图片缩放的过程中能够在保持宽高比的情况下尽量填充满整个窗口,而且能够避免缩放过程中图片越界出现黑边。按下鼠标滚轮,拖动一段距离后松开,可以达到拖动图片的目的。

在图片上框取一部分区域来显示,StretchDIBits(dcMem, m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),m_nLeft,m_nBottom, m_rect.Width()*m_dZoomScale, m_rect.Height()*m_dZoomScale, m_pData, (BITMAPINFO*)m_pHeader, DIB_RGB_COLORS, SRCCOPY);

其中m_rect为Button的大小,m_rect*m_dZoomScale为框取的大小,m_nLeft,m_nBottom分别为选取框的最左边和最下边,以图像坐标系为参考,图片左下角为初始点(0,0)。

详细代码查看 http://download.csdn.net/detail/qq_26973095/9881516

响应滚轮缩放:

BOOL CButtonPic::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	// TODO: Add your message handler code here and/or call default
	if (m_pHeader == NULL || m_pData == NULL)
		return FALSE;
	CPoint   point;
	GetCursorPos(&point);
	ScreenToClient(&point);
	if (zDelta == 120)
	{
		if (m_dZoomScale > m_dZoomStep)								//m_dZoomStep滚轮改变的缩放比例
		{
			m_dZoomScale -= m_dZoomStep;
			int tmpLeft = m_nLeft + point.x*m_dZoomStep;                                     
			int tmpBottom = m_nBottom + (m_rect.Height() - point.y)*m_dZoomStep;		//以鼠标所在位置为中心放大图片
			if (tmpLeft < 0 || (m_pHeader->biWidth - tmpLeft) < m_dZoomScale*m_rect.Width())//如果放大后的图片在宽度上不能完全覆盖rect的宽度
			{							            										//则将放大中心的纵坐标设置在rect的半高处;下面同理
				m_nLeft = m_nLeft + m_rect.Width() *m_dZoomStep / 2;
			}
			else
			{
				m_nLeft = tmpLeft;
			}
			if (tmpBottom < 0 || (m_pHeader->biHeight - tmpBottom) < m_dZoomScale*m_rect.Height()) //m_pHeader为位图的信息头


			{
				m_nBottom = m_nBottom + m_rect.Height()*m_dZoomStep / 2  //m_rect为Button的大小,m_rect*m_dZoomScale为框取的大小

			}
			else
			{
				m_nBottom = tmpBottom;
			}
		}
	}
	else if (zDelta == -120)
	{
		if (m_dZoomScale < m_dInitialZScale)		//m_dInitialZScale为初始时的缩放比例,此时图像最小,恰好塞满整个rect

		{
			m_dZoomScale += m_dZoomStep;
			int tmpLeft = m_nLeft - point.x*m_dZoomStep;
			int tmpBottom = m_nBottom - (m_rect.Height() - point.y)*m_dZoomStep;

			if (tmpLeft < 0)					//如果放大后选取的框在图像最左边的左边,即左边出现黑
			{							//则将选取框往右移
				m_nLeft = 0;
			}
			else if ((m_pHeader->biWidth - tmpLeft) < m_dZoomScale*m_rect.Width())	//不能让图片缩小后出现黑边
			{										//则将选取框往左移
				m_nLeft = m_pHeader->biWidth - m_dZoomScale*m_rect.Width();
			}
			else
			{
				m_nLeft = tmpLeft;
			}

			if (tmpBottom < 0)
			{
				m_nBottom = 0;
			}
			else if ((m_pHeader->biHeight - tmpBottom) < m_dZoomScale*m_rect.Height()) //不能让图片缩小后出现黑边

			{
				m_nBottom = m_pHeader->biHeight - m_dZoomScale*m_rect.Height();
			}
			else
			{
				m_nBottom = tmpBottom;
			}
			if (m_dZoomScale*m_rect.Height() > m_pHeader->biHeight)       //不能让图片缩小后出现黑边

			{
				m_nBottom = (m_pHeader->biHeight - m_rect.Height()*m_dZoomScale) / 2;
			}
			if (m_dZoomScale*m_rect.Width() > m_pHeader->biWidth) 		//不能让图片缩小后出现黑边

			{

				m_nLeft = (m_pHeader->biWidth - m_rect.Width()*m_dZoomScale) / 2;
			}
		}
	}
	Invalidate();
	return CButton::OnMouseWheel(nFlags, zDelta, pt);
}








  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值