TouchPictureBox,用手指滑动图片!





4.00/5 (10投票s)
在小屏幕上查看图片时,放弃传统的滚动条。


引言
这个想法是在开发一个智能设备应用程序时产生的,该应用程序需要显示比屏幕更大的图片。我发现滚动条并不容易使用,即使在如今“触摸”体验如此流行的时代!所以我决定构建一个新的控件,让用户可以用手指浏览图片。之后,我添加了缩放功能,以便用户可以轻松地看到整个图片,然后对其进行浏览。
Using the Code
源代码项目将构建一个包含该控件的 DLL 文件。然后,您就可以将其添加到 Visual Studio 工具箱中,然后像普通的 PictureBox
一样使用它。如果您打开 zip 文件中的解决方案,进行构建并启动项目,您将获得一个示例应用程序,可以将其上传到您的 Pocket PC 设备上进行实时测试!使用底部的“实时演示”菜单,通过嵌入的图片(这是 Windows Vista 的标准壁纸)来测试该控件,或者您可以浏览设备上的其他图片,然后点击“显示”按钮来使用您自己的图片测试该控件!
控件属性
CropLocation
:显示图片部分的左上角坐标Point
。此属性允许您获取实际位置,或者在设计时设置一个默认起始位置,或者在代码中设置以强制滚动。该点将在滚动时更新。为了更好地理解,请看下图。Picture
:显示的图片Bitmap
。就像传统的Image
属性一样使用它,可以在设计时或运行时使用!StopEdges
:一个boolean
值,用于确定滚动是否会在到达图片边缘时停止。这些图片说明了该行为。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)
{
// Left button clicked, save click position
_iFirstTapX = e.X;
_iFirstTapY = e.Y;
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
// Displace the CropLocation by the move size
_pCropLocation.X -= (e.X - _iFirstTapX);
_pCropLocation.Y -= (e.Y - _iFirstTapY);
// Replace picture to avoid going further than the edges
Replace();
// Picture has moved, save the new click position for next move
_iFirstTapX = e.X;
_iFirstTapY = e.Y;
this.Invalidate();
}
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
Graphics gxOff; // Offscreen graphics
if (_bOffscreen == null) // Bitmap for doublebuffering
_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);
}
// Draw from the memory 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()
{
// Draw zoomed version of the picture.
// In fact this version will be used for control drawing.
if (_bPicture != null)
{
// If zoom value is 100, just take original picture !
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 CompactFramework 的功能:将源 bitmap
绘制到更大或更小的矩形中。图片将被重采样,而无需担心如何做到这一点!
使用此类
您可以在演示项目中看到,您可以创建一个填充有该控件的 Windows 窗体,以及两个用于设备的两个软按钮的“放大”和“缩小”菜单,然后进行全屏导航。每个按钮的代码只会简单地调用 touchPictureBox1.ZoomIn()
和 touchPictureBox1.ZoomOut()
!但您也可以将其用作窗体中的小型控件,用于小范围导航。
随附的项目是一个 Visual Studio 2008 项目,但将其在 Visual Studio 2005 中运行应该也很容易,因为它使用了 .NET CF 2.0。您还将获得一个小图标,以便在工具箱中良好地表示,以及 DesignTimeAttributes.xmta 文件,以获得良好的属性行为和描述!
此类将在 Windows Mobile 5 和 Windows Mobile 6 上运行,但您应该很容易地将其用于桌面应用程序进行编译,这样用户就可以使用鼠标滑动,或者在 Tablet PC 上使用他们的触笔进行滑动!
历史
- 2008 年 10 月 15 日:第一个版本