触摸屏幕图片浏览控件开发指南

在现代的触摸设备上,用户常常需要查看比屏幕更大的图片。传统的滚动条在这种交互方式下并不总是那么方便,尤其是在“触摸”体验日益流行的今天。因此,决定开发一个新的控件,让用户能够通过手指来浏览图片。之后,添加了缩放功能,让用户能够轻松地查看整张图片,然后进行导航。

使用代码

源代码项目将构建一个DLL文件,包含该控件。然后,可以将其添加到Visual Studio工具箱中,并像使用普通的PictureBox一样使用它。如果打开包含在zip文件中的解决方案,构建它并启动项目,将得到一个示例应用程序,可以将其上传到Pocket PC设备上进行实时测试!使用底部的“实时演示”菜单,使用嵌入的图片(这是标准的Windows Vista壁纸)测试控件,或者可以浏览设备上的其他图片,然后点击“显示”按钮,使用自己的图片测试控件!

以下是一些关键的控件属性:

  • CropLocation: 显示图片部分的左上角点。这个属性让可以获取实际位置,或者在设计时设置默认起始位置,或者在代码中强制滚动。滚动时,该点将被更新。
  • Picture: 正在显示的图片。就像传统的Image属性一样,在设计或运行时使用!
  • StopEdges: 一个布尔值,决定滚动是否在到达图片边缘时停止。
  • Zoom: 一个Int32值,决定实际的缩放值,以百分比表示。"100"意味着100%,或者可以理解为“实际大小”。
  • ZoomMin: 一个Int32值,决定允许的最小缩放值。
  • ZoomMax: 一个Int32值,决定允许的最大缩放值。
  • ZoomStep: 一个Int32值,决定缩放步长。当在运行时调用ZoomIn()或ZoomOut()方法时,Zoom值将按照ZoomStep更新。例如,值为25将得到缩放值25, 50, 75, 100, 125, 150等。

深入了解代码

现在,来看看最重要的代码部分:三个事件,它们是实现功能的核心。这些是OnMouseDown、OnMouseMove和OnPaint。事实上,想要获取用户在屏幕上点击的时刻并保持坐标。然后,当用户在保持手写笔或手指压力的同时移动时,想要滚动图片。

有一个初步的解决方案:记住第一次点击的坐标,然后总是使用这个记忆和实际的MouseMove坐标来计算新的图片坐标。但这有点复杂。所以使用的解决方案将在MouseMove上计算新的图片坐标,然后将新的鼠标(手写笔或手指)坐标作为“第一个”坐标保存。

protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { if (e.Button == MouseButtons.Left) { // 左键点击,保存点击位置 _iFirstTapX = e.X; _iFirstTapY = e.Y; } } protected override void OnMouseMove(MouseEventArgs e) { if (e.Button == MouseButtons.Left) { // 移动CropLocation的大小 _pCropLocation.X -= (e.X - _iFirstTapX); _pCropLocation.Y -= (e.Y - _iFirstTapY); // 替换图片以避免超出边缘 Replace(); // 图片移动了,保存新的点击位置以供下次移动 _iFirstTapX = e.X; _iFirstTapY = e.Y; this.Invalidate(); } } protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) { Graphics gxOff; // 离屏图形 if (_bOffscreen == null) // 双缓冲的Bitmap _bOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height); gxOff = Graphics.FromImage(_bOffscreen); gxOff.Clear(this.BackColor); if (_bPicture != null) { Rectangle rDst = new Rectangle(0, 0, ClientSize.Width, ClientSize.Height); Rectangle rSrc = new Rectangle(_pCropLocation.X, _pCropLocation.Y, ClientSize.Width, ClientSize.Height); gxOff.DrawImage(_bZoomedPicture, rDst, rSrc, GraphicsUnit.Pixel); } // 从内存Bitmap绘制 e.Graphics.DrawImage(_bOffscreen, 0, 0); base.OnPaint(e); }

_iFirstTapX和_iFirstTapY将保持第一次点击的坐标。_pCropLocation是一个Point,定义了应该显示的图片部分的左上角坐标。称之为整个图片的裁剪。然后会看到一个调用Replace()方法。这将检查位移是否超出了图片的边缘,如果StopEdges属性设置为true,它将把它放回。this.Invalidate()总是在控件需要重绘时调用。所以在这里来到了OnPaint事件。正如看到的,它将使用双缓冲来防止闪烁。创建了一个临时的Bitmap,大小与控件相同,然后看看是否设置了图片。如果true,获取原始图片需要显示的矩形部分,并将其绘制到临时Bitmap上。

但等一下!这个_bZoomedPicture是什么?好吧,为了在缩放模式下允许轻松滑动,控件在内存中创建了缩放的图片,这将是绘制的源图片。所以当更改Picture属性、Zoom属性,或者使用ZoomIn()或ZoomOut()方法时,将调用CreateZoomedPicture()来计算这个图片的新版本。以下是代码:

private void CreateZoomedPicture() { // 绘制图片的缩放版本。 // 实际上这个版本将用于控件绘制。 if (_bPicture != null) { if (_iZoom == 100) _bZoomedPicture = _bPicture; else { Graphics gx; _bZoomedPicture = new Bitmap((int)((double)_bPicture.Width * _dZoom), (int)((double)_bPicture.Height * _dZoom)); gx = Graphics.FromImage(_bZoomedPicture); gx.Clear(this.BackColor); Rectangle rDst = new Rectangle(0, 0, _bZoomedPicture.Width, _bZoomedPicture.Height); Rectangle rSrc = new Rectangle(0, 0, _bPicture.Width, _bPicture.Height); gx.DrawImage(_bPicture, rDst, rSrc, GraphicsUnit.Pixel); } } }

在这里,只是利用了.NET Compact Framework的功能:在更大或更小的矩形中绘制源Bitmap。图片将被重新采样,而不必担心如何做到这一点!

类的使用

可以在演示项目中看到,可以制作一个Windows表单,用这个控件填充,并且为设备的两个软按钮定义了Zoom In和Zoom Out两个菜单,然后进行全屏导航。每个按钮的代码将简单地调用touchPictureBox1.ZoomIn()和touchPictureBox1.ZoomOut()!但也可以将它作为一个小控件在表单中使用,进行小范围的导航。

包括将得到一个Visual Studio 2008项目,但它应该很容易在Visual Studio 2005中工作,因为它使用的是.NET CF 2.0。还将得到一个小图标,以便在工具箱中有很好的表示,以及DesignTimeAttributes.xmta文件,以便有良好的属性行为和描述!

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485