using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Management;
namespace ZrjScrollView
{
internal class NativeMethods
{
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
public RECT(Rectangle r)
{
this.left = r.Left;
this.top = r.Top;
this.right = r.Right;
this.bottom = r.Bottom;
}
public static RECT FromXYWH(int x, int y, int width, int height)
{
return new RECT(new Rectangle(x, y, width, height));
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
static extern int ScrollWindowEx(IntPtr hwnd, int dx, int dy, ref RECT lprcScroll, ref RECT lprcClip, IntPtr hrgnUpdate, ref RECT lprcUpdate, int fuScroll);
public static int ScrollWindow(Control aControl, int dX, int dY, Rectangle rectScroll, Rectangle rectClip, Rectangle rectUpdate)
{
NativeMethods.RECT rcScroll = new RECT(rectScroll);
NativeMethods.RECT rcClip = new RECT(rectClip);
NativeMethods.RECT rcUpdate = new RECT(rectUpdate);
return ScrollWindowEx(aControl.Handle, dX, dY, ref rcScroll, ref rcClip, IntPtr.Zero, ref rcUpdate, 7);
}
//取第一块硬盘编号
public static string GetHardDiskID()
{
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
string strHardDiskID = null;
foreach (ManagementObject mo in searcher.Get())
{
strHardDiskID = mo["SerialNumber"].ToString().Trim();
break;
}
return strHardDiskID;
}
catch
{
return "";
}
}//end
}
public class ViewAreaBase
{
public ViewAreaBase(Control c)
{
this.ownerControl = c;
}
public void Paint(PaintEventArgs e)
{
if (this.visible == false)
return;
Rectangle area = this.Bounds;
if (area.IntersectsWith(e.ClipRectangle) == false)
return;
Region oldRegion = e.Graphics.Clip;
e.Graphics.SetClip(area);
OnPaint(e);
e.Graphics.SetClip(oldRegion, System.Drawing.Drawing2D.CombineMode.Replace);
}
public virtual void OnPaint(PaintEventArgs e)
{
Rectangle area = this.Bounds;
area.Width -= 1;
area.Height -= 1;
e.Graphics.DrawLine(Pens.Black, area.Left, area.Top, area.Right, area.Bottom);
e.Graphics.DrawLine(Pens.Black, area.Left, area.Bottom, area.Right, area.Top);
}
public bool Visible
{
get { return visible; }
set { visible = value; }
}
public Control OwnerControl
{
get { return ownerControl; }
}
#region 属性 Left, Top, Width, Height, Location, Size, Bounds
public int Left
{
get { return x; }
set { x = value; }
}
public int Top
{
get { return y; }
set { y = value; }
}
public int Width
{
get { return width; }
set { width = value; }
}
public int Height
{
get { return height; }
set { height = value; }
}
public Point Location
{
get { return new Point(x, y); }
set { x = value.X; y = value.Y; }
}
public Size Size
{
get { return new Size(width, height); }
set { width = value.Width; height = value.Height; }
}
public Rectangle Bounds
{
get { return new Rectangle(x, y, width, height); }
set { x = value.Left; y = value.Top; width = value.Width; height = value.Height; }
}
#endregion
private Control ownerControl;
private bool visible = true;
private int x;
private int y;
private int width;
private int height;
}
public class ScrollViewArea : ViewAreaBase
{
public ScrollViewArea(Control c)
: base(c)
{
}
public virtual void Scroll(int dx, int dy)
{
viewOrg.Offset(dx, dy);
this.OwnerControl.Invalidate(this.Bounds);
}
public override void OnPaint(PaintEventArgs e)
{
Rectangle vr = new Rectangle(this.Location, this.VirtualSize);
vr.Offset(-this.ViewOrg.X, -this.ViewOrg.Y);
vr.Width -= 1;
vr.Height -= 1;
e.Graphics.DrawLine(Pens.Blue, vr.Left, vr.Top, vr.Right, vr.Bottom);
e.Graphics.DrawLine(Pens.Blue, vr.Left, vr.Bottom, vr.Right, vr.Top);
}
public Size VirtualSize
{
get { return virtualSize; }
set { virtualSize = value; }
}
public Point ViewOrg
{
get { return viewOrg; }
set { viewOrg = value; }
}
private Size virtualSize = Size.Empty;
private Point viewOrg = new Point(0, 0);
}
public class MainArea : ScrollViewArea
{
public MainArea(Control c, string ImageFileName)
: base(c)
{
img = new Bitmap(ImageFileName);
VirtualSize = img.Size;
}
public override void OnPaint(PaintEventArgs e)
{
// draw image
Rectangle dstRect = this.Bounds;
dstRect.Intersect(e.ClipRectangle);
Rectangle srcRect = new Rectangle(this.ViewOrg.X + dstRect.Left - this.Left, this.ViewOrg.Y + dstRect.Top - this.Top, dstRect.Width, dstRect.Height);
e.Graphics.DrawImage(img, dstRect, srcRect, GraphicsUnit.Pixel);
}
private Bitmap img;
}
public class ScrollViewBase : Control
{
public ScrollViewBase()
{
InitializeComponent();
}
private void InitializeComponent()
{
TextBox EditBox = new TextBox();
EditBox.Location = new Point(0, 0);
EditBox.Size = new Size(50, 10);
this.hScrollBar = new HScrollBar();
this.vScrollBar = new VScrollBar();
this.brPanel = new Panel();
this.topLeftArea = new ViewAreaBase(this);
this.topRightArea = new ScrollViewArea(this);
this.leftArea = new ScrollViewArea(this);
this.rightArea = new MainArea(this, @"D:/IMG_0026.JPG");
this.bottomLeftArea = new ViewAreaBase(this);
this.bottomRightArea = new ScrollViewArea(this);
this.SuspendLayout();
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, false);
//this.SetStyle(ControlStyles.Selectable, true);
this.vScrollBar.TabIndex = 0;
this.hScrollBar.TabIndex = 1;
this.brPanel.TabIndex = 2;
this.brPanel.Width = SystemInformation.VerticalScrollBarWidth;
this.brPanel.Height = SystemInformation.HorizontalScrollBarHeight;
this.hScrollBar.Height = this.brPanel.Height;
this.vScrollBar.Width = this.brPanel.Width;
this.brPanel.BackColor = System.Drawing.SystemColors.Control;
this.BackColor = System.Drawing.SystemColors.Window;
AdjustScrollBars();
topRightArea.VirtualSize = new Size(rightArea.VirtualSize.Width, topAreaHeight);
leftArea.VirtualSize = new Size(leftAreaWidth, rightArea.VirtualSize.Height);
bottomRightArea.VirtualSize = new Size(rightArea.VirtualSize.Width, bottomAreaHeight);
this.hScrollBar.Scroll += new ScrollEventHandler(hScrollBar_Scroll);
this.vScrollBar.Scroll += new ScrollEventHandler(vScrollBar_Scroll);
this.Controls.Add(hScrollBar);
this.Controls.Add(vScrollBar);
this.Controls.Add(brPanel);
this.Controls.Add(EditBox);
this.ResumeLayout(false);
}
protected override void OnMouseWheel(MouseEventArgs e)
{
int dx = 0;
int dy = 0;
int newValue;
if (this.vScrollBar.Visible)
{
if (e.Delta > 0) // scroll down
{
dy = -3 * this.vScrollBar.SmallChange;
newValue = Math.Max(this.vScrollBar.Minimum, this.vScrollBar.Value + dy);
dy = Math.Max(dy, newValue - this.vScrollBar.Value);
}
else // scroll up
{
dy = 3 * this.vScrollBar.SmallChange;
newValue = Math.Min(this.vScrollBar.Maximum - this.vScrollBar.LargeChange + 1, this.vScrollBar.Value + dy);
dy = Math.Min(dy, newValue - this.vScrollBar.Value);
}
if (dy != 0)
{
this.vScrollBar.Value = newValue;
rightArea.Scroll(0, dy);
leftArea.Scroll(0, dy);
}
if (e is HandledMouseEventArgs)
{
((HandledMouseEventArgs)e).Handled = true;
}
}
else if (this.hScrollBar.Visible)
{
if (e.Delta > 0) // scroll left
{
dx = -3 * this.hScrollBar.SmallChange;
newValue = Math.Max(this.hScrollBar.Minimum, this.hScrollBar.Value + dx);
dx = Math.Max(dx, newValue - this.hScrollBar.Value);
}
else // scroll right
{
dx = 3 * this.hScrollBar.SmallChange;
newValue = Math.Min(this.hScrollBar.Maximum - this.hScrollBar.LargeChange + 1, this.hScrollBar.Value + dx);
dx = Math.Min(dx, newValue - this.hScrollBar.Value);
}
if (dx != 0)
{
this.hScrollBar.Value = newValue;
topRightArea.Scroll(dx, 0);
rightArea.Scroll(dx, 0);
bottomRightArea.Scroll(dx, 0);
}
if (e is HandledMouseEventArgs)
{
((HandledMouseEventArgs)e).Handled = true;
}
}
base.OnMouseWheel(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
/*
Graphics g = this.CreateGraphics();
string str = e.Location.ToString();
SizeF strSize = g.MeasureString(str, SystemFonts.StatusFont);
g.FillRectangle(Brushes.White, 0,0,strSize.Width,strSize.Height);
g.DrawString(str, SystemFonts.StatusFont, Brushes.Red, 0, 0);
g.Dispose();
*/
base.OnMouseMove(e);
}
protected override void OnPaint(PaintEventArgs e)
{
topLeftArea.Paint(e);
topRightArea.Paint(e);
leftArea.Paint(e);
rightArea.Paint(e);
bottomLeftArea.Paint(e);
bottomRightArea.Paint(e);
base.OnPaint(e);
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
this.SuspendLayout();
AdjustScrollBars();
this.ResumeLayout(false);
}
void vScrollBar_Scroll(object sender, ScrollEventArgs e)
{
// 滚动条无变化时返回
if (e.NewValue == e.OldValue)
return;
int dx = 0;
int dy = e.NewValue - e.OldValue;
rightArea.Scroll(dx, dy);
leftArea.Scroll(dx, dy);
/*
int dx = 0;
int dy = e.NewValue - e.OldValue;
Rectangle rcScroll;
Rectangle rcUpdate;
if (dy > 0)
{
rcScroll = new Rectangle(W1, H1+dy, W2, H2-dy);
rcUpdate = new Rectangle(W1, H1+H2-dy, W2, dy);
}
else
{
rcScroll = new Rectangle(W1, H1, W2, H2 - dy);
rcUpdate = new Rectangle(W1, H1, W2, -dy);
}
Rectangle rcClip = new Rectangle(W1, H1, W2, H2);
NativeMethods.ScrollWindow(this, dx, -dy, rcScroll, rcClip, rcUpdate);
*/
}
void hScrollBar_Scroll(object sender, ScrollEventArgs e)
{
// 滚动条无变化时返回
if (e.NewValue == e.OldValue)
return;
int dx = e.NewValue - e.OldValue;
int dy = 0;
topRightArea.Scroll(dx, dy);
rightArea.Scroll(dx, dy);
bottomRightArea.Scroll(dx, dy);
/*
int dx = e.NewValue - e.OldValue;
int dy = 0;
Rectangle rcScroll;
Rectangle rcUpdate;
if (dx > 0)
{
rcScroll = new Rectangle(W1+dx, H1, W2-dx, H2);
rcUpdate = new Rectangle(W1+W2-dx, H1, dx, H2);
}
else
{
rcScroll = new Rectangle(W1, H1, W2+dx, H2);
rcUpdate = new Rectangle(W1, H1, -dx, H2);
}
Rectangle rcClip = new Rectangle(W1, H1, W2, H2);
NativeMethods.ScrollWindow(this, -dx, 0, rcScroll, rcClip, rcUpdate);
*/
}
private void AdjustScrollBars()
{
if (this.ClientSize.IsEmpty)
return;
ShowMsg();
int scrollBarHeight = this.hScrollBar.Height;
int scrollBarWidth = this.vScrollBar.Width;
this.hScrollBar.Visible = (this.ClientSize.Width < leftAreaWidth + rightArea.VirtualSize.Width);
this.vScrollBar.Visible = (this.ClientSize.Height < topAreaHeight + bottomAreaHeight + rightArea.VirtualSize.Height);
this.brPanel.Visible = (this.hScrollBar.Visible && this.vScrollBar.Visible);
if (this.hScrollBar.Visible == false)
scrollBarHeight = 0;
if (this.vScrollBar.Visible == false)
scrollBarWidth = 0;
#region 调整绘画区大小位置...
topLeftArea.Location = new Point(0, 0);
topLeftArea.Size = new Size(leftAreaWidth, topAreaHeight);
topRightArea.Location = new Point(leftAreaWidth, 0);
topRightArea.Size = new Size(this.ClientSize.Width - leftAreaWidth - scrollBarWidth, topAreaHeight);
leftArea.Location = new Point(0, topAreaHeight);
leftArea.Size = new Size(leftAreaWidth, this.ClientSize.Height - topAreaHeight - scrollBarHeight - bottomAreaHeight);
rightArea.Location = new Point(leftArea.Width, topLeftArea.Height);
rightArea.Size = new Size(topRightArea.Width, leftArea.Height);
bottomLeftArea.Location = new Point(0, topAreaHeight + leftArea.Height);
bottomLeftArea.Size = new Size(leftAreaWidth, bottomAreaHeight);
bottomRightArea.Location = new Point(bottomLeftArea.Width, bottomLeftArea.Top);
bottomRightArea.Size = new Size(rightArea.Width, bottomAreaHeight);
#endregion
#region 重新设置各Area的ViewOrg
int dx = 0;
int dy = 0;
dx = Math.Max(Math.Min(rightArea.VirtualSize.Width - rightArea.ViewOrg.X - rightArea.Width, 0), -rightArea.ViewOrg.X);
dy = Math.Max(Math.Min(rightArea.VirtualSize.Height - rightArea.ViewOrg.Y - rightArea.Height, 0), -rightArea.ViewOrg.Y);
topRightArea.ViewOrg = topRightArea.ViewOrg + new Size(dx, 0);
leftArea.ViewOrg = leftArea.ViewOrg + new Size(0, dy);
rightArea.ViewOrg = rightArea.ViewOrg + new Size(dx, dy);
bottomRightArea.ViewOrg = bottomRightArea.ViewOrg + new Size(dx, 0);
#endregion
#region 调整滚动条大小位置...
if (this.vScrollBar.Visible)
{
this.vScrollBar.Left = this.ClientSize.Width - this.brPanel.Width;
this.vScrollBar.Top = 0;
this.vScrollBar.Height = this.ClientSize.Height - scrollBarHeight;
this.vScrollBar.Maximum = rightArea.VirtualSize.Height;
this.vScrollBar.SmallChange = 20;
this.vScrollBar.LargeChange = rightArea.Height;
this.vScrollBar.Value = rightArea.ViewOrg.Y;
}
if (this.hScrollBar.Visible)
{
this.hScrollBar.Left = 0;
this.hScrollBar.Top = this.ClientSize.Height - this.brPanel.Height;
this.hScrollBar.Width = this.ClientSize.Width - scrollBarWidth;
this.hScrollBar.Maximum = rightArea.VirtualSize.Width;
this.hScrollBar.SmallChange = 20;
this.hScrollBar.LargeChange = rightArea.Width;
this.hScrollBar.Value = rightArea.ViewOrg.X;
}
if (this.brPanel.Visible)
{
this.brPanel.Location = new Point(this.hScrollBar.Width, this.vScrollBar.Height);
}
#endregion
ShowMsg();
this.Invalidate();
}
// 私有数据成员
private ViewAreaBase topLeftArea;
private ScrollViewArea topRightArea;
private ScrollViewArea leftArea;
private MainArea rightArea;
private ViewAreaBase bottomLeftArea;
private ScrollViewArea bottomRightArea;
private HScrollBar hScrollBar;
private VScrollBar vScrollBar;
private Panel brPanel;
TextBox msgBox;
public TextBox MsgBox
{
get { return msgBox; }
set { msgBox = value; }
}
private void ShowMsg()
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("VSize({0,3},{1,3}) ASize({2,3},{3,3}) VOrg({4,3},{5,3}) ScrollValue({6,3},{7,3})/r/n",
rightArea.VirtualSize.Width, rightArea.VirtualSize.Height, rightArea.Width, rightArea.Height,
rightArea.ViewOrg.X, rightArea.ViewOrg.Y, hScrollBar.Value, vScrollBar.Value);
ShowMsg(sb.ToString());
}
private void ShowMsg(string str)
{
if (msgBox != null && msgBox.IsHandleCreated)
{
msgBox.SelectionLength = 0;
msgBox.SelectionStart = msgBox.Text.Length;
msgBox.SelectedText = str;
}
}
private int topAreaHeight = 60;
private int leftAreaWidth = 75;
private int bottomAreaHeight = 55;
}
}