1 编写一个Hex Edit控件,使用VS2010建立一个类控件库,分别增加两个类文件,一个命名为HexEdit.cs, 一个命名为TextEditControl.cs,具体内容如下所示:
1)HexEdit.cs
using System.Drawing; using System.Windows.Forms; namespace Sense.Test.UIControl { // 摘要: // 在Sense.Test.UIControl中显示一个十六进制控件 public class HexEdit { // 摘要: // 初始化Sense.Test.UIControl.HexEdit类的一个新实例 public HexEdit() { _IsShowAddressColumn = false; _AddressWidth = 100; _AddressShowBit = AddressBit.Bit8; _AddressFontColor = Color.Black; //_AddressBGColor = Color.FromArgb(190, 190, 190); _AddressBGColor = Color.White; _IsShowHeadColumn = false; _HeadHeight = 22; _HeadFontColor = Color.Black; _HeadShowBit = HeadBit.Bit32; _HeadBGColor = Color.FromArgb(240, 240, 240); _HeadStaffColor = Color.Black; _IsShowStringColumn = false; _StringFontColor = Color.Black; //_StringBGColor = Color.FromArgb(120, 120, 120); _StringBGColor = Color.White; //_DataBGColor = Color.FromArgb(150, 150, 150); _DataBGColor = Color.White; _DataType = EncodingType.ANSI; _IsSupportMultiSelect = false; _IsSupportClickSelect = false; _BorderLineColor = Color.FromArgb(130, 249, 252); _BorderBGColor = Color.FromArgb(222, 252, 249); _IsSupportMenu = false; } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的地址属性 private bool _IsShowAddressColumn; public bool IsShowAddressColumn { get { return _IsShowAddressColumn; } set { _IsShowAddressColumn = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的地址宽度 private int _AddressWidth; public int AddressWidth { get { return _AddressWidth; } set { _AddressWidth = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的地址背景色 private Color _AddressBGColor; public Color AddressBGColor { get { return _AddressBGColor; } set { _AddressBGColor = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的地址显示位数 private AddressBit _AddressShowBit; public AddressBit AddressShowBit { get { return _AddressShowBit; } set { _AddressShowBit = value; } } public enum AddressBit { Bit4 = 1, Bit8 } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的地址字体画刷颜色 private Color _AddressFontColor; public Color AddressFontColor { get { return _AddressFontColor; } set { _AddressFontColor = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的Head属性 private bool _IsShowHeadColumn; public bool IsShowHeadColumn { get { return _IsShowHeadColumn; } set { _IsShowHeadColumn = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的Head的高度 private int _HeadHeight; public int HeadHeight { get { return _HeadHeight; } set { _HeadHeight = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的Head背景色 private Color _HeadBGColor; public Color HeadBGColor { get { return _HeadBGColor; } set { _HeadBGColor = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的Head的字体颜色 private Color _HeadFontColor; public Color HeadFontColor { get { return _HeadFontColor; } set { _HeadFontColor = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的Head的标尺颜色 private Color _HeadStaffColor; public Color HeadStaffColor { get { return _HeadStaffColor; } set { _HeadStaffColor = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的Head的显示位数 private HeadBit _HeadShowBit; public HeadBit HeadShowBit { get { return _HeadShowBit; } } public enum HeadBit { Bit16 = 16, Bit32 = 32 } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的字符串属性 private bool _IsShowStringColumn; public bool IsShowStringColumn { get { return _IsShowStringColumn; } set { _IsShowStringColumn = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的字符串字体颜色 private Color _StringFontColor; public Color StringFontColor { get { return _StringFontColor; } set { _StringFontColor = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的String背景色 private Color _StringBGColor; public Color StringBGColor { get { return _StringBGColor; } set { _StringBGColor = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的Data背景色 private Color _DataBGColor; public Color DataBGColor { get { return _DataBGColor; } set { _DataBGColor = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的数据编码格式 private EncodingType _DataType; public EncodingType DataType { get { return _DataType; } set { _DataType = value; } } public enum EncodingType { ANSI = 1, Unicond } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的是否支持多行属性 private bool _IsSupportMultiSelect; public bool IsSupportMultiSeletc { get { return _IsSupportMultiSelect; } set { _IsSupportMultiSelect = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的是否支持单击Adress行选择整行属性 private bool _IsSupportClickSelect; public bool IsSupportClickSelect { get { return _IsSupportClickSelect; } set { _IsSupportClickSelect = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的选择数据时的颜色 private Color _BorderBGColor; public Color BorderBGColor { get { return _BorderBGColor; } set { _BorderBGColor = value; } } private Color _BorderLineColor; public Color BorderLineColor { get { return _BorderLineColor; } set { _BorderLineColor = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.HexEdit类的是否支持右键显示菜单 private bool _IsSupportMenu; public bool IsSupportMenu { get { return _IsSupportMenu; } set { _IsSupportMenu = value; } } } }
using System; using System.Collections.Generic; using System.Windows.Forms; using System.Drawing; using System.Drawing.Drawing2D; using System.Collections; using System.Text.RegularExpressions; using System.Text; using System.Runtime.InteropServices; using System.IO; namespace Sense.Test.UIControl { public class TextEditControl : Control { #region 构造函数 // 摘要: // 初始化Sense.Test.UIControl.TextEditControl类的一个新实例 public TextEditControl() { //设置窗体Style this.SetStyle(ControlStyles.UserPaint, true); //支持用户重绘窗体 this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); //在内存中先绘制界面 this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); //双缓冲,防止绘制时抖动 this.SetStyle(ControlStyles.DoubleBuffer, true); this.UpdateStyles(); //外部线条宽度及画笔 _fOutLineWidth = 2; _OutLinePen = new Pen(Color.FromArgb(0x78, 0x82, 0x8F), _fOutLineWidth); //背景色 _BackgroundColor = Color.White; //默认字体 _Font = new Font("Courier New", 12); //初始化垂直滚动条 m_VScrollBarWidth = 15; m_VScrollBarPos = 0; m_VScrollBar = new System.Windows.Forms.VScrollBar(); m_VScrollBar.Visible = false; m_VScrollBar.Enabled = false; m_VScrollBar.Minimum = 0; m_VScrollBar.Maximum = 0; m_VScrollBar.Scroll += new System.Windows.Forms.ScrollEventHandler(m_VScrollBar_Scroll); m_VScrollBar.MouseWheel += new System.Windows.Forms.MouseEventHandler(m_VScrollBar_Mouse_Wheel); this.Controls.Add(m_VScrollBar); //默认不支持HexEdit m_HexEdit = new HexEdit(); HexEdit hexedit = new HexEdit(); hexedit.IsShowHeadColumn = true; hexedit.IsShowAddressColumn = true; hexedit.IsShowStringColumn = false; hexedit.DataType = Sense.Test.UIControl.HexEdit.EncodingType.ANSI; hexedit.IsSupportClickSelect = true; hexedit.AddressShowBit = Sense.Test.UIControl.HexEdit.AddressBit.Bit4; SizeF sizef = CalcFontSize("0000h", _Font); hexedit.AddressWidth = (int)sizef.Width; HexEdit(hexedit); m_HexEditData = null; m_HexMousePos = new POS(); m_HexMousePos.iPos = -1; m_HexMousePos.iArea = -1; m_HexMousePos.bLeftPos = false; m_HexMousePos.bRightPos = false; m_AddressPos = -1; m_IsCreateCaret = false; m_IsHideCaret = true; //初始化菜单 m_HexMenu = new ContextMenu(); m_HexMenuItem0 = new MenuItem(); m_HexMenuItem0.Text = "Insert a string..."; m_HexMenuItem0.Name = "string"; m_HexMenuItem0.Click += new System.EventHandler(MenuItem0_Click); m_HexMenuItem1 = new MenuItem(); m_HexMenuItem1.Text = "Paste a string from clipboard"; m_HexMenuItem1.Name = "paste"; m_HexMenuItem1.Click += new System.EventHandler(MenuItem1_Click); m_HexMenuItem2 = new MenuItem(); m_HexMenuItem2.Text = "Load from file..."; m_HexMenuItem2.Name = "Load"; m_HexMenuItem2.Click += new System.EventHandler(MenuItem2_Click); m_HexMenuItem3 = new MenuItem(); m_HexMenuItem3.Text = "Save to file..."; m_HexMenuItem3.Name = "save"; m_HexMenuItem3.Click += new System.EventHandler(MenuItem3_Click); m_HexMenuItem4 = new MenuItem(); m_HexMenuItem4.Text = "Clear this memory block"; m_HexMenuItem4.Name = "clear"; m_HexMenuItem4.Click += new System.EventHandler(MenuItem4_Click); m_HexMenu.MenuItems.Add(m_HexMenuItem0); m_HexMenu.MenuItems.Add(m_HexMenuItem1); m_HexMenu.MenuItems.Add("-"); m_HexMenu.MenuItems.Add(m_HexMenuItem2); m_HexMenu.MenuItems.Add(m_HexMenuItem3); m_HexMenu.MenuItems.Add("-"); m_HexMenu.MenuItems.Add(m_HexMenuItem4); //AddHexEditData("12345678123456781234234567812345678123423456781234567812342345678123456781234234567812345678123423456781234567812342345678123456781234234567812345678123423456781234567812342345678123456781234234567812345678123423456781234567812342345678123456781234"); } #endregion #region 公开属性 // 摘要: // 获取/设置Sense.Test.UIControl.TextEditControl类的外部线条宽度 private float _fOutLineWidth; public float fOutLineWidth { get { return _fOutLineWidth; } set { _fOutLineWidth = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.TextEditControl类的外部线条画笔 private Pen _OutLinePen; public Pen OutLinePen { get { return _OutLinePen; } set { _OutLinePen = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.TextEditControl类的背景色 private Color _BackgroundColor; public Color BackgroundColor { get { return _BackgroundColor; } set { _BackgroundColor = value; } } // 摘要: // 获取/设置Sense.Test.UIControl.TextEditControl类的字体 private Font _Font; public Font Font { get { return _Font; } set { _Font = value; } } // 摘要: // HexEdit控件显示的数据 private string m_HexEditData; public string HexEditData { get { return m_HexEditData; } set { AddHexEditData(value); } } #endregion #region 公开函数 // 摘要: // 添加HexEdit控件 public void HexEdit(HexEdit hexedit) { m_HexEdit = hexedit; } // 摘要: // 添加HexEdit要显示的数据 public void AddHexEditData(string strData) { m_HexEditData = strData; if (!m_VScrollBar.Visible) { HideVScrollBar(); } Rectangle rt = CalcEditRectangle(); byte[] bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); int iMaxDataRow = bt.Length / (int)m_HexEdit.HeadShowBit; if (bt.Length + 1 % (int)m_HexEdit.HeadShowBit != 0) { iMaxDataRow += 1; } int iHeight = rt.Y; if (m_HexEdit.IsShowHeadColumn) { iHeight += m_HexEdit.HeadHeight; } if (iMaxDataRow * (int)_Font.Height > rt.Height - iHeight) { ShowVScrollBar(); } } #endregion #region 窗体绘制函数 // 摘要: // 绘制Sense.Test.UIControl.TextEditControl控件 protected override void OnPaint(PaintEventArgs e) { this.BackColor = _BackgroundColor; this.Focus(); OnDrawHexEditHead(e); OnDrawHexEditAddress(e); OnDrawHexEditData(e); OnDrawHexEditString(e); OnDrawHexEditAddressSelectEdit(e); OnDrawHexEditDataSelectEdit(e); OnDrawEditOutLine(e); } // 摘要: // 绘制Sense.Test.UIControl.TextEditControl控件的外部线条 private void OnDrawEditOutLine(PaintEventArgs e) { Point[] pt = { new Point(0, 0), new Point(this.Width, 0), new Point(this.Width, this.Height), new Point(0, this.Height), new Point(0, 0) }; e.Graphics.DrawLines(OutLinePen, pt); } // 摘要: // 绘制Sense.Test.UIControl.TextEditControl控件HexEdit的表头 private void OnDrawHexEditHead(PaintEventArgs e) { Rectangle rt = CalcEditRectangle(); int iOffset = 0; int iStaffCount = 0; string strMsg = null; Point pt1 = new Point(); Point pt2 = new Point(); if (m_HexEdit.IsShowHeadColumn) { //填充Head背景色 Brush brush = new SolidBrush(m_HexEdit.HeadBGColor); Rectangle headrt = new Rectangle(rt.X, rt.Y, rt.Width, m_HexEdit.HeadHeight); e.Graphics.FillRectangle(brush, headrt); if (m_HexEdit.IsShowAddressColumn) { iOffset = m_HexEdit.AddressWidth; } //绘制标尺 brush = new SolidBrush(m_HexEdit.HeadFontColor); pt1.X = rt.X + iOffset; SizeF sizef = CalcFontSize("00", _Font); iOffset = pt1.X; Pen pen = new Pen(m_HexEdit.HeadStaffColor); iStaffCount = (int)m_HexEdit.HeadShowBit; for (int ix = 0; ix < iStaffCount; ix++) { strMsg = ix.ToString("X2"); pt1.X = iOffset; pt1.Y = rt.Y + m_HexEdit.HeadHeight - _Font.Height - 2; if (pt1.X - rt.X >= rt.Width) { break; } e.Graphics.DrawString(strMsg, _Font, brush, pt1); pt1.X += (int)sizef.Width / 2; pt1.Y += _Font.Height - 4; pt2.X = pt1.X; pt2.Y = pt1.Y + 5; e.Graphics.DrawLine(pen, pt1, pt2); iOffset += (int)sizef.Width; } } } // 摘要: // 绘制Sense.Test.UIControl.TextEditControl控件HexEdit的地址栏 private void OnDrawHexEditAddress(PaintEventArgs e) { Rectangle rt = CalcEditRectangle(); int iHeight = 0; int iOffset = 0; string strMsg = null; Point pt1 = new Point(); int iMaxDataRow = 0; if (m_HexEdit.IsShowAddressColumn) { iHeight = rt.Y; if (m_HexEdit.IsShowHeadColumn) { iHeight += m_HexEdit.HeadHeight; } if (m_HexEditData == null) { return; } byte[] bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); iMaxDataRow = bt.Length / (int)m_HexEdit.HeadShowBit; if (bt.Length % (int)m_HexEdit.HeadShowBit != 0) { iMaxDataRow += 1; } if (m_HexEdit.AddressShowBit == UIControl.HexEdit.AddressBit.Bit4) { SizeF sizef = CalcFontSize("0000h", _Font); if (m_HexEdit.AddressWidth < (int)sizef.Width) { m_HexEdit.AddressWidth = (int)sizef.Width; } iOffset = m_HexEdit.AddressWidth - (int)sizef.Width; } else { SizeF sizef = CalcFontSize("00000000h", _Font); if (m_HexEdit.AddressWidth < (int)sizef.Width) { m_HexEdit.AddressWidth = (int)sizef.Width; } iOffset = m_HexEdit.AddressWidth - (int)sizef.Width; } Brush bgbrush = new SolidBrush(m_HexEdit.AddressBGColor); Brush fontbrush = new SolidBrush(m_HexEdit.AddressFontColor); Rectangle art = new Rectangle(); for (int ix = m_VScrollBarPos; ix < iMaxDataRow; ix++) { art.X = rt.X; art.Y = iHeight + (ix - m_VScrollBarPos) * _Font.Height; art.Width = m_HexEdit.AddressWidth; art.Height = _Font.Height; if (art.Y + _Font.Height >= rt.Height) { return; } e.Graphics.FillRectangle(bgbrush, art); pt1.X = rt.X + iOffset; pt1.Y = iHeight + (ix - m_VScrollBarPos) * _Font.Height; if (m_HexEdit.HeadShowBit == UIControl.HexEdit.HeadBit.Bit16) { if (m_HexEdit.AddressShowBit == UIControl.HexEdit.AddressBit.Bit4) { strMsg = (ix * 16).ToString("X4") + "h"; } else { strMsg = (ix * 16).ToString("X8") + "h"; } } else { if (m_HexEdit.AddressShowBit == UIControl.HexEdit.AddressBit.Bit4) { strMsg = (ix * 32).ToString("X4") + "h"; } else { strMsg = (ix * 32).ToString("X8") + "h"; } } e.Graphics.DrawString(strMsg, _Font, fontbrush, pt1); } } } // 摘要: // 绘制Sense.Test.UIControl.TextEditControl控件HexEdit的数据栏 private void OnDrawHexEditData(PaintEventArgs e) { Rectangle rt = CalcEditRectangle(); int iHeight = 0; int iOffset = 0; string strMsg = null; Point pt1 = new Point(); int iMaxDataRow = 0; int iStaffCount = (int)m_HexEdit.HeadShowBit; int iDataOffset = 0; if (m_HexEditData == null) { return; } byte[] bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); iMaxDataRow = bt.Length / (int)m_HexEdit.HeadShowBit; if (bt.Length + 1 % (int)m_HexEdit.HeadShowBit != 0) { iMaxDataRow += 1; } iHeight = rt.Y; if (m_HexEdit.IsShowHeadColumn) { iHeight += m_HexEdit.HeadHeight; } iOffset = rt.X; if (m_HexEdit.IsShowAddressColumn) { iOffset += m_HexEdit.AddressWidth; } SizeF sizef = CalcFontSize("00", _Font); Brush fontbrush = new SolidBrush(m_HexEdit.StringFontColor); Brush bgbrush = new SolidBrush(m_HexEdit.DataBGColor); Rectangle drt = new Rectangle(); //绘制数据 iDataOffset = m_VScrollBarPos * iStaffCount; for (int ix = m_VScrollBarPos; ix < iMaxDataRow; ix++) { pt1.X = rt.X + iOffset; pt1.Y = iHeight; //绘制行背景 drt.X = iOffset; drt.Y = iHeight; drt.Width = (int)m_HexEdit.HeadShowBit * (int)sizef.Width; drt.Height = _Font.Height; e.Graphics.FillRectangle(bgbrush, drt); for (int iy = iDataOffset; iy < iDataOffset + iStaffCount; iy++) { if (iy >= bt.Length) { break; } strMsg = bt[iy].ToString("X2"); e.Graphics.DrawString(strMsg, _Font, fontbrush, pt1); pt1.X += (int)sizef.Width; } iDataOffset += iStaffCount; iHeight += _Font.Height; if (iHeight + _Font.Height >= rt.Height) { break; } } } // 摘要: // 绘制Sense.Test.UIControl.TextEditControl控件HexEdit的string栏 private void OnDrawHexEditString(PaintEventArgs e) { Rectangle rt = CalcEditRectangle(); int iOffset = 0; SizeF sizef = CalcFontSize("00", _Font); Point pt1 = new Point(); Brush fontbrush = new SolidBrush(m_HexEdit.StringFontColor); Brush bgbrush = new SolidBrush(m_HexEdit.StringBGColor); int iHeight = 0; int iMaxDataRow = 0; int iStaffCount = (int)m_HexEdit.HeadShowBit; int iDataOffset = 0; string strMsg = null; int iLoop = 0; if (m_HexEdit.IsShowStringColumn) { if (m_HexEditData == null) { return; } byte[] bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); iMaxDataRow = bt.Length / (int)m_HexEdit.HeadShowBit; if (bt.Length % (int)m_HexEdit.HeadShowBit != 0) { iMaxDataRow += 1; } iOffset = rt.X; if (m_HexEdit.IsShowAddressColumn) { iOffset += m_HexEdit.AddressWidth; } iOffset += (int)m_HexEdit.HeadShowBit * (int)sizef.Width; iHeight = rt.Y; if (m_HexEdit.IsShowHeadColumn) { iHeight += m_HexEdit.HeadHeight; } Rectangle drt = new Rectangle(); sizef = CalcFontSize("0000000000000000", _Font); byte[] bTemp = new byte[16]; iDataOffset = m_VScrollBarPos * iStaffCount; //绘制数据 for (int ix = m_VScrollBarPos; ix < iMaxDataRow; ix++) { drt.X = iOffset; drt.Y = iHeight; drt.Width = (int)sizef.Width + 1; drt.Height = _Font.Height; e.Graphics.FillRectangle(bgbrush, drt); pt1.X = iOffset; pt1.Y = iHeight; for (int iy = 0; iy < bTemp.Length; iy++) { bTemp[iy] = 0; } if (bt.Length - iDataOffset >= iStaffCount) { Array.Copy(bt, iDataOffset, bTemp, 0, iStaffCount); iLoop = iStaffCount; } else { Array.Copy(bt, iDataOffset, bTemp, 0, bt.Length - iDataOffset); iLoop = bt.Length - iDataOffset; } strMsg = null; if (m_HexEdit.DataType == UIControl.HexEdit.EncodingType.Unicond) { strMsg = ConvertByteToStirng(bTemp, m_HexEdit.DataType); } else { for (int j = 0; j < iLoop; j++) { if (bTemp[j] > 0x1F && !(bTemp[j] > 0x7E && bTemp[j] < 0xFF)) { strMsg += ((char)bTemp[j]).ToString(); } else { strMsg += '.'; } } } e.Graphics.DrawString(strMsg, _Font, fontbrush, pt1); iDataOffset += iStaffCount; iHeight += _Font.Height; if (iHeight + _Font.Height >= rt.Height) { break; } } } } // 摘要: // 绘制Sense.Test.UIControl.TextEditControl控件HexEdit选择地址栏后的选择框 private void OnDrawHexEditAddressSelectEdit(PaintEventArgs e) { if (m_HexEdit.IsSupportClickSelect) { if (m_HexEdit.IsShowAddressColumn && m_AddressPos != -1) { Rectangle rt = CalcEditRectangle(); Rectangle rect = new Rectangle(); rect.X = rt.X; rect.Y = rt.Y + (m_AddressPos - m_VScrollBarPos) * (int)_Font.Height; if (m_HexEdit.IsShowHeadColumn) { rect.Y += m_HexEdit.HeadHeight; } rect.Width = rt.Width - m_VScrollBarWidth; rect.Height = _Font.Height; /* LinearGradientBrush lgbrush = new LinearGradientBrush(rect, m_HexEdit.BorderFirstColor, m_HexEdit.BorderSecondColor, LinearGradientMode.Vertical); */ Brush lgbrush = new SolidBrush(Color.FromArgb(60, m_HexEdit.BorderBGColor)); e.Graphics.FillRectangle(lgbrush, rect); e.Graphics.DrawRectangle(new Pen(m_HexEdit.BorderLineColor, 1), rect); } } } // 摘要: // 绘制数据选择区域外框 private void OnDrawHexEditDataSelectEdit(PaintEventArgs e) { } #endregion #region 重写函数 // 摘要: // 重载消息处理函数,该函数不处理WM_ERASEBKGRND消息 protected override void WndProc(ref Message m) { //0x00000014 WM_ERASEBKGRND if (m.Msg == 0x00000014) { return; } base.WndProc(ref m); } // 摘要: // 处理键盘输入键消息 protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { if (m_HexMousePos.iPos != -1 && m_HexMousePos.iArea != -1) { if (keyData >= Keys.D0 && keyData <= Keys.F) { //表明是在Hex区域 if (m_HexMousePos.iArea == 1) { byte[] bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); byte b = 0; byte c = 0; this.Focus(); if (m_HexMousePos.iPos < bt.Length) { if (m_HexMousePos.bLeftPos) { c = (byte)(bt[m_HexMousePos.iPos] & 0x0F); b = HexCharValue((byte)keyData); } if (m_HexMousePos.bRightPos) { b = (byte)((bt[m_HexMousePos.iPos] & 0xF0) >> 4); c = HexCharValue((byte)keyData); } bt[m_HexMousePos.iPos] = (byte)((b << 4) | c); m_HexEditData = ConvertByteToStirng(bt, m_HexEdit.DataType); } else { byte[] bt1; if (m_HexEdit.DataType == UIControl.HexEdit.EncodingType.ANSI) { bt1 = new byte[bt.Length + 1]; bt1[bt.Length] = 0; } else { bt1 = new byte[bt.Length + 2]; bt1[bt.Length] = 0; bt1[bt.Length + 1] = 0; } Array.Copy(bt, bt1, bt.Length); if (m_HexMousePos.bLeftPos) { c = (byte)(bt1[m_HexMousePos.iPos] & 0x0F); b = HexCharValue((byte)keyData); } if (m_HexMousePos.bRightPos) { b = (byte)((bt1[m_HexMousePos.iPos] & 0xF0) >> 4); c = HexCharValue((byte)keyData); } bt1[m_HexMousePos.iPos] = (byte)((b << 4) | c); m_HexEditData = ConvertByteToStirng(bt1, m_HexEdit.DataType); } bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); Rectangle rt = CalcEditRectangle(); int iMaxDataRow = bt.Length / (int)m_HexEdit.HeadShowBit; if (m_HexMousePos.bRightPos && m_HexMousePos.iPos == (bt.Length - 1)) { if ((bt.Length + 1) % (int)m_HexEdit.HeadShowBit == 1) { iMaxDataRow += 1; int iHeight = rt.Y; if (m_HexEdit.IsShowHeadColumn) { iHeight += m_HexEdit.HeadHeight; } if (iMaxDataRow * (int)_Font.Height > rt.Height - iHeight) { m_VScrollBarPos++; ShowVScrollBar(); m_VScrollBar.Value = m_VScrollBarPos; } } } else { m_VScrollBar.Maximum = iMaxDataRow + 8; } this.Invalidate(); OnVK_Right(); return true; } } else { switch (keyData) { case Keys.Up: OnVK_Up(); break; case Keys.Down: OnVK_Down(); break; case Keys.Left: OnVK_Left(); break; case Keys.Right: OnVK_Right(); break; } } } else if (m_AddressPos != -1) { switch (keyData) { case Keys.Up: OnVK_Up(); break; case Keys.Down: OnVK_Down(); break; } } return true; } #endregion #region 消息响应函数 // 摘要: // 处理垂直拉条的移动 private void m_VScrollBar_Scroll(object obj, ScrollEventArgs e) { if (m_VScrollBarPos != e.NewValue) { m_VScrollBarPos = e.NewValue; m_AddressPos = -1; if (!m_IsHideCaret) { OnHideCaret(); m_IsHideCaret = true; } m_HexMousePos.iPos = -1; m_HexMousePos.iArea = -1; m_HexMousePos.bLeftPos = false; m_HexMousePos.bRightPos = false; this.Invalidate(); } } // 摘要: // 处理垂直拉条的移动 private void m_VScrollBar_Mouse_Wheel(object obj, MouseEventArgs e) { return; } // 摘要: // 处理鼠标移动消息 protected override void OnMouseMove(MouseEventArgs e) { Rectangle rtHeader = new Rectangle(0, 0, 0, 0); Point pt = new Point(e.X, e.Y); this.Focus(); } // 摘要: // 处理鼠标中间键滚动消息 protected override void OnMouseWheel(MouseEventArgs e) { if (m_VScrollBar.Enabled == true) { m_VScrollBar.Focus(); } } // 摘要: // 处理鼠标按下消息 protected override void OnMouseDown(MouseEventArgs e) { this.Focus(); if (e.Button == MouseButtons.Left || e.Button == MouseButtons.Right) { Point pt = new Point(e.X, e.Y); Rectangle rt = CalcEditRectangle(); Rectangle rect = new Rectangle(); Region rg; int iHeight = 0; int iOffset = 0; int iWidth = 0; SizeF sizef = CalcFontSize("00", _Font); byte[] bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); int iMaxDataRow = bt.Length / (int)m_HexEdit.HeadShowBit; if (bt.Length + 1 % (int)m_HexEdit.HeadShowBit != 0) { iMaxDataRow += 1; } #region 判断是否在Address区 if (m_HexEdit.IsShowAddressColumn) { iHeight = rt.Y; if (m_HexEdit.IsShowHeadColumn) { iHeight += m_HexEdit.HeadHeight; } for (int ix = m_VScrollBarPos; ix < iMaxDataRow; ix++) { rect.X = rt.X; rect.Y = iHeight; rect.Width = m_HexEdit.AddressWidth; rect.Height = _Font.Height; rg = new Region(rect); if (rg.IsVisible(pt)) { m_AddressPos = ix; if (m_AddressPos >= iMaxDataRow) { m_AddressPos = -1; } if (m_AddressPos != -1) { int iSTotalHeight = (ix + 1 - m_VScrollBarPos) * _Font.Height; if (m_HexEdit.IsShowHeadColumn) { iSTotalHeight += m_HexEdit.HeadHeight; } if (iSTotalHeight > rt.Height) { m_VScrollBarPos++; m_AddressPos--; m_VScrollBar.Value = m_VScrollBarPos; } } this.Invalidate(); return; } else { m_AddressPos = -1; this.Invalidate(); } iHeight += _Font.Height; if (iHeight + _Font.Height > rt.Height) { break; } } } #endregion #region 判断是否在Data区 iHeight = rt.Y; if (m_HexEdit.IsShowHeadColumn) { iHeight += m_HexEdit.HeadHeight; } iOffset = rt.X; if (m_HexEdit.IsShowAddressColumn) { iOffset += m_HexEdit.AddressWidth; } rect.X = iOffset; rect.Y = rt.Y; if (m_HexEdit.IsShowHeadColumn) { rect.Y += m_HexEdit.HeadHeight; } rect.Width = (int)m_HexEdit.HeadShowBit * (int)sizef.Width; if ((iMaxDataRow - m_VScrollBarPos) * _Font.Height > rt.Height - rect.Y) { rect.Height = rt.Height - rect.Y; } else { rect.Height = (iMaxDataRow - m_VScrollBarPos) * _Font.Height; } rg = new Region(rect); if (rg.IsVisible(pt)) { //如果没有创建Caret,则创建 OnCreateCaret(); for (int ix = m_VScrollBarPos; ix < iMaxDataRow; ix++) { iWidth = iOffset; for (int iy = 0; iy < (int)m_HexEdit.HeadShowBit; iy++) { rect.X = iWidth; rect.Y = iHeight; rect.Width = (int)sizef.Width / 2; rect.Height = _Font.Height; rg = new Region(rect); if (rg.IsVisible(pt)) { SetCaretPos(rect.X, rect.Y); ShowCaret(this.Handle); m_IsHideCaret = false; ShowRightMouseMeun(e, pt); m_HexMousePos.iPos = iy + ix * (int)m_HexEdit.HeadShowBit; m_HexMousePos.iArea = 1; m_HexMousePos.bLeftPos = true; m_HexMousePos.bRightPos = false; return; } rect.X += (int)sizef.Width / 2; rect.Width = (int)sizef.Width - (int)sizef.Width / 2; rg = new Region(rect); if (rg.IsVisible(pt)) { SetCaretPos(rect.X, rect.Y); ShowCaret(this.Handle); m_IsHideCaret = false; ShowRightMouseMeun(e, pt); m_HexMousePos.iPos = iy + ix * (int)m_HexEdit.HeadShowBit; m_HexMousePos.iArea = 1; m_HexMousePos.bLeftPos = false; m_HexMousePos.bRightPos = true; return; } iWidth += (int)sizef.Width; if (iy + ix * (int)m_HexEdit.HeadShowBit >= bt.Length) { break; } } iHeight += _Font.Height; if (iHeight + _Font.Height >= rt.Height) { OnHideCaret(); break; } } } else { OnHideCaret(); } #endregion } } // 摘要: // 处理鼠标按键弹起消息 protected override void OnMouseUp(MouseEventArgs e) { this.Focus(); } // 摘要: // 响应弹出FORM的OK/CANCLE按钮 private void OK_Click(object obj, EventArgs e) { Button bt = (Button)obj; Form f1 = bt.Parent as Form; f1.DialogResult = DialogResult.OK; } private void CANCLE_Click(object obj, EventArgs e) { Button bt = (Button)obj; Form f1 = bt.Parent as Form; f1.DialogResult = DialogResult.Cancel; } #endregion #region 菜单函数 // 摘要: // 插入一个string private void MenuItem0_Click(object obj, EventArgs e) { if (m_HexMousePos.iPos != -1) { int iRow = 0; int iColumn = 0; Form f1 = new Form(); SizeF sizef = CalcFontSize("00", _Font); f1.Text = "Insert a string..."; f1.ShowIcon = false; f1.MaximizeBox = false; f1.MinimizeBox = false; f1.StartPosition = FormStartPosition.Manual; f1.FormBorderStyle = FormBorderStyle.FixedDialog; f1.Size = new System.Drawing.Size(470, 300); GetRowAndColumn(ref iRow, ref iColumn); f1.Location = new System.Drawing.Point(iColumn * (int)sizef.Width, iRow * _Font.Height); Label lb = new Label(); lb.Text = "插入string的长度: "; lb.Location = new Point(20, 23); lb.Size = new System.Drawing.Size(110, 20); lb.Visible = true; f1.Controls.Add(lb); TextBox tb = new TextBox(); tb.Location = new System.Drawing.Point(130, 20); tb.Size = new System.Drawing.Size(200, 20); tb.Visible = true; f1.Controls.Add(tb); Label lb1 = new Label(); lb1.Text = "插入string的内容: "; lb1.Location = new Point(20, 50); lb1.Size = new System.Drawing.Size(110, 20); lb1.Visible = true; f1.Controls.Add(lb1); TextBox tb1 = new TextBox(); tb1.Location = new System.Drawing.Point(20, 75); tb1.Size = new System.Drawing.Size(310, 180); tb1.Visible = true; tb1.Multiline = true; f1.Controls.Add(tb1); Button button = new Button(); button.Text = "OK"; button.Location = new Point(350, 18); button.Size = new System.Drawing.Size(100, 30); button.Visible = true; button.Click += new System.EventHandler(OK_Click); f1.Controls.Add(button); Button button1 = new Button(); button1.Text = "Cancle"; button1.Location = new Point(350, 50); button1.Size = new System.Drawing.Size(100, 30); button1.Visible = true; button1.Click += new System.EventHandler(CANCLE_Click); f1.Controls.Add(button1); if (DialogResult.OK == f1.ShowDialog()) { string strLength = tb.Text; string strContext = tb1.Text; if (Int32.Parse(strLength) == strContext.Length) { byte[] bt = ConvertStringToByte(strContext, m_HexEdit.DataType); byte[] bSource = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); byte[] bDestination = new byte[bSource.Length + bt.Length]; if (m_HexMousePos.iPos > bSource.Length) { Array.Copy(bSource, 0, bDestination, 0, bSource.Length); Array.Copy(bt, 0, bDestination, bSource.Length, bt.Length); } else { Array.Copy(bSource, 0, bDestination, 0, m_HexMousePos.iPos); Array.Copy(bt, 0, bDestination, m_HexMousePos.iPos, bt.Length); Array.Copy(bSource, m_HexMousePos.iPos, bDestination, m_HexMousePos.iPos + bt.Length, bSource.Length - m_HexMousePos.iPos); } m_HexEditData = ConvertByteToStirng(bDestination, m_HexEdit.DataType); this.Invalidate(); } else { MessageBox.Show("要插入的数据长度与实际数据的数据内容的长度不相等!"); } } CreateNewCaret(); } } // 摘要: // 从剪贴板上复制 private void MenuItem1_Click(object obj, EventArgs e) { IDataObject ido = Clipboard.GetDataObject(); if (ido.GetDataPresent(DataFormats.Text)) { string strData = (string)ido.GetData(DataFormats.Text); byte[] bt = ConvertStringToByte(strData, m_HexEdit.DataType); byte[] bSource = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); byte[] bDestination = new byte[bSource.Length + bt.Length]; if (m_HexMousePos.iPos > bSource.Length) { Array.Copy(bSource, 0, bDestination, 0, bSource.Length); Array.Copy(bt, 0, bDestination, bSource.Length, bt.Length); } else { Array.Copy(bSource, 0, bDestination, 0, m_HexMousePos.iPos); Array.Copy(bt, 0, bDestination, m_HexMousePos.iPos, bt.Length); Array.Copy(bSource, m_HexMousePos.iPos, bDestination, m_HexMousePos.iPos + bt.Length, bSource.Length - m_HexMousePos.iPos); } m_HexEditData = ConvertByteToStirng(bDestination, m_HexEdit.DataType); this.Invalidate(); } } // 摘要: // 从文件中载入数据 private void MenuItem2_Click(object obj, EventArgs e) { if (m_HexMousePos.iPos == -1) { return; } if (m_HexMousePos.iArea == 1) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "all file (*.*)|*.*"; ofd.FilterIndex = 1; ofd.RestoreDirectory = true; ofd.FileName = null; if (DialogResult.OK == ofd.ShowDialog()) { string strFilePath = ofd.FileName; byte[] bt1 = ReadHexDataFromFile(strFilePath); string strData = ConvertByteToStirng(bt1, UIControl.HexEdit.EncodingType.ANSI); byte[] bt = ConvertStringToByte(strData, m_HexEdit.DataType); byte[] bSource = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); byte[] bDestination = new byte[bSource.Length + bt.Length]; if (m_HexMousePos.iPos > bSource.Length) { Array.Copy(bSource, 0, bDestination, 0, bSource.Length); Array.Copy(bt, 0, bDestination, bSource.Length, bt.Length); } else { Array.Copy(bSource, 0, bDestination, 0, m_HexMousePos.iPos); Array.Copy(bt, 0, bDestination, m_HexMousePos.iPos, bt.Length); Array.Copy(bSource, m_HexMousePos.iPos, bDestination, m_HexMousePos.iPos + bt.Length, bSource.Length - m_HexMousePos.iPos); } m_HexEditData = ConvertByteToStirng(bDestination, m_HexEdit.DataType); this.Invalidate(); } CreateNewCaret(); } } // 摘要: // 将数据保存至文件 private void MenuItem3_Click(object obj, EventArgs e) { SaveFileDialog sfd = new SaveFileDialog(); sfd.Filter = "all file (*.*)|*.*"; sfd.FilterIndex = 1; sfd.RestoreDirectory = true; sfd.FileName = null; if (DialogResult.OK == sfd.ShowDialog()) { byte[] bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); WriteHexDataToFile(sfd.FileName, bt); } CreateNewCaret(); } // 摘要: // 清空数据 private void MenuItem4_Click(object obj, EventArgs e) { byte[] bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); for (int ix = 0; ix < bt.Length; ix++) { bt[ix] = 0; } m_HexEditData = ConvertByteToStirng(bt, m_HexEdit.DataType); this.Invalidate(); } #endregion #region 私有函数 // 摘要: // 获取窗体可操作区域位置 private Rectangle CalcEditRectangle() { Rectangle rt = new Rectangle(); rt.X = (int)fOutLineWidth / 2; rt.Y = (int)fOutLineWidth / 2; rt.Width = this.Width - (int)fOutLineWidth; rt.Height = this.Height - (int)fOutLineWidth; ; return rt; } // 摘要: // 在指定Font下获取字符串的Size private SizeF CalcFontSize(string strText, Font font) { Graphics g = this.CreateGraphics(); SizeF sizeF = g.MeasureString(strText, font); g.Dispose(); return sizeF; } // 摘要: // 显示垂直滚动条 private void ShowVScrollBar() { if (!m_VScrollBar.Enabled) { m_VScrollBar.Enabled = true; m_VScrollBar.Minimum = 0; } byte[] bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); int iMaxDataRow = bt.Length / (int)m_HexEdit.HeadShowBit; if ((bt.Length + 1) % (int)m_HexEdit.HeadShowBit == 1) { iMaxDataRow += 1; } m_VScrollBar.Maximum = iMaxDataRow + 8; //m_VScrollBar.Show(); } // 摘要: // 隐藏垂直滚动条 private void HideVScrollBar() { Rectangle rt = CalcEditRectangle(); m_VScrollBar.Location = new Point(rt.X + rt.Width - m_VScrollBarWidth, rt.Top); m_VScrollBar.Size = new Size(m_VScrollBarWidth, rt.Height); m_VScrollBar.Enabled = false; m_VScrollBar.Visible = true; m_VScrollBarPos = 0; } // 摘要: // 判断传入的char是否为汉字 private bool IsChineseChar(char character) { //汉字的范围在4E00 - 9FA5之间,所以只需要判断是否在此空间内即可 Regex reg = new Regex(@"[\u4e00-\u9fa5]"); string strData = character.ToString(); if (reg.IsMatch(strData)) { return true; } else { return false; } } // 摘要: // 将是汉字的字符转换成byte数组 private byte[] ConvertChineseToByte(char character, UIControl.HexEdit.EncodingType dt) { if (dt == UIControl.HexEdit.EncodingType.ANSI) { return Encoding.GetEncoding("GB2312").GetBytes(character.ToString()); } else if (dt == UIControl.HexEdit.EncodingType.Unicond) { return Encoding.GetEncoding("Unicode").GetBytes(character.ToString()); } else { return null; } } // 摘要: // 将是string字符串转换成byte数组 private byte[] ConvertStringToByte(string strData, UIControl.HexEdit.EncodingType dt) { if (dt == UIControl.HexEdit.EncodingType.ANSI) { char[] cData = strData.ToCharArray(); int iLength = 0; for (int ix = 0; ix < cData.Length; ix++) { if (IsChineseChar(cData[ix])) { iLength += 2; } else { iLength += 1; } } byte[] bData = new byte[iLength]; for (int ix = 0, iy = 0; ix < cData.Length; ix++) { if (IsChineseChar(cData[ix])) { bData[iy] = (byte)((cData[ix] >> 8) & 0xFF); iy++; bData[iy] = (byte)cData[ix]; } else { bData[iy] = Convert.ToByte(cData[ix]); } iy++; } return bData; } else if (dt == UIControl.HexEdit.EncodingType.Unicond) { return Encoding.GetEncoding("Unicode").GetBytes(strData); } else { return null; } } // 摘要: // 将是byte数组转换成string字符串 private string ConvertByteToStirng(byte[] bData, UIControl.HexEdit.EncodingType dt) { if (dt == UIControl.HexEdit.EncodingType.ANSI) { char[] cData = new char[bData.Length]; Array.Copy(bData, cData, bData.Length); return new string(cData); } else if (dt == UIControl.HexEdit.EncodingType.Unicond) { return Encoding.GetEncoding("Unicode").GetString(bData); } else { return null; } } // 摘要: // 将一个Hex字符转换为8字节的byte private byte HexCharValue(byte b) { if ('0' <= b && b <= '9') { return (byte)(b - '0'); } else if ('A' <= b && b <= 'F') { return (byte)(b - 'A' + 10); } else if ('a' <= b && b < 'f') { return (byte)(b - 'a' + 10); } else { return 0; } } // 摘要: // Caret向左移动 private void OnVK_Left() { if (m_HexMousePos.iPos != -1 && m_HexMousePos.iArea != -1) { //表明在Data区 if (m_HexMousePos.iArea == 1) { int iRow = m_HexMousePos.iPos / (int)m_HexEdit.HeadShowBit; int iColumn = 0; int iOffset = 0; Rectangle rt = CalcEditRectangle(); Point pt = new Point(); SizeF sizef = CalcFontSize("00", _Font); int iHeight = 0; this.Focus(); if (m_HexMousePos.iPos % (int)m_HexEdit.HeadShowBit != 0) { iColumn = m_HexMousePos.iPos % (int)m_HexEdit.HeadShowBit; } else { iColumn = 0; } iOffset = rt.X; if (m_HexEdit.IsShowAddressColumn) { iOffset += m_HexEdit.AddressWidth; } iHeight = rt.Y; if (m_HexEdit.IsShowHeadColumn) { iHeight += m_HexEdit.HeadHeight; } //表示在每行的起始位置 if (iColumn == 0) { //表明在第一个字节的右部 if (m_HexMousePos.bRightPos) { pt.X = iOffset; pt.Y = iHeight + (iRow - m_VScrollBarPos) * _Font.Height; m_HexMousePos.bRightPos = false; m_HexMousePos.bLeftPos = true; SetCaretPos(pt.X, pt.Y); return; } //表明在第一个字节的左部 if (m_HexMousePos.bLeftPos) { if (iRow > 0) { iRow -= 1; if (iRow < m_VScrollBarPos) { m_VScrollBarPos--; m_VScrollBar.Value = m_VScrollBarPos; this.Invalidate(); } pt.X = iOffset + (int)m_HexEdit.HeadShowBit * (int)sizef.Width - (int)sizef.Width / 2; pt.Y = iHeight + (iRow - m_VScrollBarPos) * _Font.Height; m_HexMousePos.iPos = (iRow + 1) * (int)m_HexEdit.HeadShowBit - 1; m_HexMousePos.bRightPos = true; m_HexMousePos.bLeftPos = false; SetCaretPos(pt.X, pt.Y); } } } //表示不在每行的起始位置 else { //表明在字节的右部 if (m_HexMousePos.bRightPos) { pt.X = iOffset + iColumn * (int)sizef.Width; pt.Y = iHeight + (iRow - m_VScrollBarPos) * _Font.Height; m_HexMousePos.bRightPos = false; m_HexMousePos.bLeftPos = true; SetCaretPos(pt.X, pt.Y); return; } //表明在字节的左部 if (m_HexMousePos.bLeftPos) { pt.X = iOffset + (iColumn - 1) * (int)sizef.Width + (int)sizef.Width - (int)sizef.Width / 2; pt.Y = iHeight + (iRow - m_VScrollBarPos) * _Font.Height; m_HexMousePos.iPos -= 1; m_HexMousePos.bRightPos = true; m_HexMousePos.bLeftPos = false; SetCaretPos(pt.X, pt.Y); return; } } } } } // 摘要: // Caret向上移动 private void OnVK_Up() { if (m_AddressPos != -1) { if (m_AddressPos - m_VScrollBarPos == 0) { if (m_VScrollBarPos > 0) { m_VScrollBarPos--; m_VScrollBar.Value = m_VScrollBarPos; } } if (m_AddressPos - m_VScrollBarPos > 0) { m_AddressPos--; } OnHideCaret(); this.Invalidate(); } else if (m_HexMousePos.iPos != -1 && m_HexMousePos.iArea != -1) { //表明在Data区 if (m_HexMousePos.iArea == 1) { int iRow = m_HexMousePos.iPos / (int)m_HexEdit.HeadShowBit; int iColumn = 0; int iOffset = 0; Rectangle rt = CalcEditRectangle(); Point pt = new Point(); SizeF sizef = CalcFontSize("00", _Font); int iHeight = 0; int iMaxDataRow = 0; byte[] bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); this.Focus(); iMaxDataRow = bt.Length / (int)m_HexEdit.HeadShowBit; if ((bt.Length + 1) % (int)m_HexEdit.HeadShowBit == 1) { iMaxDataRow += 1; } if (m_HexMousePos.iPos % (int)m_HexEdit.HeadShowBit != 0) { iColumn = m_HexMousePos.iPos % (int)m_HexEdit.HeadShowBit; } else { iColumn = 0; } iOffset = rt.X; if (m_HexEdit.IsShowAddressColumn) { iOffset += m_HexEdit.AddressWidth; } iHeight = rt.Y; if (m_HexEdit.IsShowHeadColumn) { iHeight += m_HexEdit.HeadHeight; } if (iRow >= m_VScrollBarPos) { if (iRow > 0 && iRow == m_VScrollBarPos) { m_VScrollBarPos--; m_VScrollBar.Value = m_VScrollBarPos; this.Invalidate(); } if (iRow == 0) { return; } iRow--; //表明在第一个字节的右部 if (m_HexMousePos.bRightPos) { pt.X = iOffset + iColumn * (int)sizef.Width + (int)sizef.Width / 2; pt.Y = iHeight + (iRow - m_VScrollBarPos) * _Font.Height; m_HexMousePos.iPos -= (int)m_HexEdit.HeadShowBit; m_HexMousePos.bRightPos = true; m_HexMousePos.bLeftPos = false; SetCaretPos(pt.X, pt.Y); return; } //表明在第一个字节的左部 if (m_HexMousePos.bLeftPos) { pt.X = iOffset + iColumn * (int)sizef.Width; pt.Y = iHeight + (iRow - m_VScrollBarPos) * _Font.Height; m_HexMousePos.iPos -= (int)m_HexEdit.HeadShowBit; m_HexMousePos.bRightPos = false; m_HexMousePos.bLeftPos = true; SetCaretPos(pt.X, pt.Y); return; } } } } } // 摘要: // Caret向右移动 private void OnVK_Right() { if (m_HexMousePos.iPos != -1 && m_HexMousePos.iArea != -1) { //表明在Data区 if (m_HexMousePos.iArea == 1) { int iRow = m_HexMousePos.iPos / (int)m_HexEdit.HeadShowBit; int iColumn = 0; int iOffset = 0; Rectangle rt = CalcEditRectangle(); Point pt = new Point(); SizeF sizef = CalcFontSize("00", _Font); int iHeight = 0; byte[] bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); this.Focus(); int iMaxDataRow = bt.Length / (int)m_HexEdit.HeadShowBit; if (bt.Length % (int)m_HexEdit.HeadShowBit == 1) { iMaxDataRow += 1; } int iMaxShowRow = 0; for (int ix = 0; ix < 0xFFFF; ix++) { iHeight = (ix + 1) * _Font.Height; if (iHeight + _Font.Height > rt.Height) { iMaxShowRow = ix; break; } } if (m_HexMousePos.iPos % (int)m_HexEdit.HeadShowBit != 0) { iColumn = m_HexMousePos.iPos % (int)m_HexEdit.HeadShowBit; } else { iColumn = 0; } iOffset = rt.X; if (m_HexEdit.IsShowAddressColumn) { iOffset += m_HexEdit.AddressWidth; } iHeight = rt.Y; if (m_HexEdit.IsShowHeadColumn) { iHeight += m_HexEdit.HeadHeight; } //表明在最后一个字节 if (iColumn == 0x0F) { //表明在字节的右部 if (m_HexMousePos.bRightPos) { if (iRow < iMaxDataRow) { iRow++; if (iRow - m_VScrollBarPos > iMaxShowRow - 1) { m_VScrollBarPos++; m_VScrollBar.Value = m_VScrollBarPos; this.Invalidate(); } pt.X = iOffset; pt.Y = iHeight + (iRow - m_VScrollBarPos) * _Font.Height; m_HexMousePos.iPos += 1; m_HexMousePos.bRightPos = false; m_HexMousePos.bLeftPos = true; SetCaretPos(pt.X, pt.Y); return; } } //表明在字节的左部 if (m_HexMousePos.bLeftPos) { pt.X = iOffset + iColumn * (int)sizef.Width + (int)sizef.Width / 2; pt.Y = iHeight + (iRow - m_VScrollBarPos) * _Font.Height; m_HexMousePos.bRightPos = true; m_HexMousePos.bLeftPos = false; SetCaretPos(pt.X, pt.Y); return; } } else { //表明在字节的右部 if (m_HexMousePos.bRightPos) { if (iRow * (int)m_HexEdit.HeadShowBit + iColumn + 1 > bt.Length) { return; } pt.X = iOffset + (iColumn + 1) * (int)sizef.Width; pt.Y = iHeight + (iRow - m_VScrollBarPos) * _Font.Height; m_HexMousePos.iPos += 1; m_HexMousePos.bRightPos = false; m_HexMousePos.bLeftPos = true; SetCaretPos(pt.X, pt.Y); return; } //表明在字节的左部 if (m_HexMousePos.bLeftPos) { pt.X = iOffset + iColumn * (int)sizef.Width + (int)sizef.Width / 2; pt.Y = iHeight + (iRow - m_VScrollBarPos) * _Font.Height; m_HexMousePos.bRightPos = true; m_HexMousePos.bLeftPos = false; SetCaretPos(pt.X, pt.Y); return; } } } } } // 摘要: // Caret向下移动 private void OnVK_Down() { if (m_AddressPos != -1) { byte[] bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); int iMaxDataRow = bt.Length / (int)m_HexEdit.HeadShowBit; if (bt.Length % (int)m_HexEdit.HeadShowBit != 0) { iMaxDataRow += 1; } int iShowMaxRow = 0; int iHeight = 0; Rectangle rt = CalcEditRectangle(); iHeight = rt.Y; if (m_HexEdit.IsShowHeadColumn) { iHeight += m_HexEdit.HeadHeight; } for (int ix = 0; ix < 0xFFFF; ix++) { iHeight = (ix + 1) * _Font.Height; if (iHeight + _Font.Height > rt.Height) { iShowMaxRow = ix; break; } } if ((m_AddressPos - m_VScrollBarPos) == iShowMaxRow - 1) { if (m_VScrollBarPos < iMaxDataRow - 8) { m_VScrollBarPos++; m_VScrollBar.Value = m_VScrollBarPos; } } if ((m_AddressPos - m_VScrollBarPos) < iShowMaxRow - 1 && m_AddressPos < iMaxDataRow - 1) { m_AddressPos++; } OnHideCaret(); this.Invalidate(); } else if (m_HexMousePos.iPos != -1 && m_HexMousePos.iArea != -1) { //表明在Data区 if (m_HexMousePos.iArea == 1) { int iRow = m_HexMousePos.iPos / (int)m_HexEdit.HeadShowBit; int iColumn = 0; int iOffset = 0; Rectangle rt = CalcEditRectangle(); Point pt = new Point(); SizeF sizef = CalcFontSize("00", _Font); int iHeight = 0; int iMaxShowRow = 0; int iMaxDataRow = 0; byte[] bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); this.Focus(); iMaxDataRow = bt.Length / (int)m_HexEdit.HeadShowBit; if ((bt.Length + 1) % (int)m_HexEdit.HeadShowBit == 1) { iMaxDataRow += 1; } if (m_HexMousePos.iPos % (int)m_HexEdit.HeadShowBit != 0) { iColumn = m_HexMousePos.iPos % (int)m_HexEdit.HeadShowBit; } else { iColumn = 0; } iOffset = rt.X; if (m_HexEdit.IsShowAddressColumn) { iOffset += m_HexEdit.AddressWidth; } for (int ix = 0; ix < 0xFFFF; ix++) { iHeight = (ix + 1) * _Font.Height; if (iHeight + _Font.Height > rt.Height) { iMaxShowRow = ix; break; } } iHeight = rt.Y; if (m_HexEdit.IsShowHeadColumn) { iHeight += m_HexEdit.HeadHeight; } if (iRow <= iMaxDataRow) { if ((iRow + 1) * (int)m_HexEdit.HeadShowBit + iColumn + 1 > bt.Length + 1) { return; } if (iRow - m_VScrollBarPos == iMaxShowRow - 1 ) { m_VScrollBarPos++; m_VScrollBar.Value = m_VScrollBarPos; this.Invalidate(); } if (iRow == iMaxDataRow) { return; } iRow++; //表明在第一个字节的右部 if (m_HexMousePos.bRightPos) { pt.X = iOffset + iColumn * (int)sizef.Width + (int)sizef.Width / 2; pt.Y = iHeight + (iRow - m_VScrollBarPos) * _Font.Height; m_HexMousePos.iPos += (int)m_HexEdit.HeadShowBit; m_HexMousePos.bRightPos = true; m_HexMousePos.bLeftPos = false; SetCaretPos(pt.X, pt.Y); return; } //表明在第一个字节的左部 if (m_HexMousePos.bLeftPos) { pt.X = iOffset + iColumn * (int)sizef.Width; pt.Y = iHeight + (iRow - m_VScrollBarPos) * _Font.Height; m_HexMousePos.iPos += (int)m_HexEdit.HeadShowBit; m_HexMousePos.bRightPos = false; m_HexMousePos.bLeftPos = true; SetCaretPos(pt.X, pt.Y); return; } } } } } // 摘要: // 创建Caret private void OnCreateCaret() { //如果没有创建Caret,则创建 if (!m_IsCreateCaret) { m_IsCreateCaret = true; CreateCaret(this.Handle, IntPtr.Zero, (int)_Font.Size, _Font.Height); } } // 摘要: // 隐藏Caret,并设置相关位置 private void OnHideCaret() { if (!m_IsHideCaret) { HideCaret(this.Handle); m_IsHideCaret = true; } m_HexMousePos.iPos = -1; m_HexMousePos.iArea = -1; m_HexMousePos.bLeftPos = false; m_HexMousePos.bRightPos = false; } // 摘要: // 显示右键菜单 private void ShowRightMouseMeun(MouseEventArgs e, Point pt) { if (e.Button == MouseButtons.Right) { m_HexMenu.Show(this, pt); } } // 摘要: // 判断文件是否存在 private bool IsFileExist(string path) { if (File.Exists(path)) { return true; } else { return false; } } // 摘要: // 从文件中读取十六进制数据流 private byte[] ReadHexDataFromFile(string path) { if (!IsFileExist(path)) { return null; } FileStream fs = new FileStream(path, FileMode.Open); BinaryReader br = new BinaryReader(fs); byte[] bt = br.ReadBytes((int)fs.Length); br.Close(); return bt; } // 摘要: // 将数据写入到文件中 private bool WriteHexDataToFile(string path, byte[] bt) { if (IsFileExist(path)) { if (DialogResult.OK != MessageBox.Show(path + " 文件已经存在,是否替换?")) { return false; } } FileStream fs = new FileStream(path, FileMode.Create); BinaryWriter bw = new BinaryWriter(fs); bw.Write(bt, 0, bt.Length); bw.Close(); return true; } // 摘要: // 获取行号/列号 private void GetRowAndColumn(ref int iRow, ref int iColumn) { if (m_HexMousePos.iPos != -1) { if (m_HexMousePos.iArea == 1) { iRow = m_HexMousePos.iPos / (int)m_HexEdit.HeadShowBit; iColumn = m_HexMousePos.iPos % (int)m_HexEdit.HeadShowBit; return; } } iRow = -1; iColumn = -1; } // 摘要: // 重新生成Caret private void CreateNewCaret() { int irow = 0; int iColumn = 0; Rectangle rt = CalcEditRectangle(); SizeF sizef = CalcFontSize("00", _Font); int iHeight = 0; int iWidth = 0; if (m_IsCreateCaret) { DestroyCaret(); m_IsCreateCaret = false; } if (!m_IsCreateCaret) { GetRowAndColumn(ref irow, ref iColumn); if (irow != -1 && iColumn != -1) { OnCreateCaret(); m_IsCreateCaret = true; iHeight = rt.Y + (irow - m_VScrollBarPos) * _Font.Height; if (m_HexEdit.IsShowHeadColumn) { iHeight += m_HexEdit.HeadHeight; } iWidth = rt.X + iColumn * (int)sizef.Width; if (m_HexEdit.IsShowAddressColumn) { iWidth += m_HexEdit.AddressWidth; } if (m_HexMousePos.bRightPos) { iWidth += (int)sizef.Width / 2; } SetCaretPos(iWidth, iHeight); ShowCaret(this.Handle); byte[] bt = ConvertStringToByte(m_HexEditData, m_HexEdit.DataType); m_VScrollBar.Maximum = bt.Length / (int)m_HexEdit.HeadShowBit + 8; } } } #endregion #region 私有变量 // 摘要: // 垂直滚动条 private VScrollBar m_VScrollBar; // 摘要: // 垂直滚动条的位置 private int m_VScrollBarPos; // 摘要: // 垂直滚动条宽度 private int m_VScrollBarWidth; // 摘要: // HexEdit控件 private HexEdit m_HexEdit; // 摘要: // HexEdit控件中鼠标选择的数据位置 private POS m_HexMousePos; private struct POS { public int iPos; public int iArea; public bool bLeftPos; public bool bRightPos; } // 摘要: // HexEdit控件中鼠标单击Address栏的位置 private int m_AddressPos; // 摘要: // 是否创建了Caret private bool m_IsCreateCaret; // 摘要: // 是否隐藏了Caret private bool m_IsHideCaret; // 摘要: // 菜单 private ContextMenu m_HexMenu; private MenuItem m_HexMenuItem0; private MenuItem m_HexMenuItem1; private MenuItem m_HexMenuItem2; private MenuItem m_HexMenuItem3; private MenuItem m_HexMenuItem4; #endregion #region 动态加载函数 [DllImport("user32.dll")] static extern bool CreateCaret(IntPtr hWnd, IntPtr hBitmap, int nWidth, int nHeight); [DllImport("user32.dll")] static extern bool ShowCaret(IntPtr hWnd); [DllImport("User32.dll")] static extern bool HideCaret(IntPtr hWnd); [DllImport("User32.dll")] static extern bool SetCaretPos(int x, int y); [DllImport("user32.dll")] static extern bool DestroyCaret(); #endregion } }
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:WF="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration" xmlns:Hx="clr-namespace:Sense.Test.UIControl;assembly=TextEditControl" x:Name="Window" Title="开发测试工具" Width="900" Height="600" Background="White" WindowState="Maximized"> <Grid> <WF:WindowsFormsHost Margin="5, 10, 5, 5"> <Hx:TextEditControl HexEditData="12345678123456781234234567812345678123423456781234567812342345678123456781234234567812345678123423456781234567812342345678123456781234234567812345678123423456781234567812342345678123456781234234567812345678123423456781234567812342345678123456781234"/> </WF:WindowsFormsHost> </Grid> </Window>