HtmlEditor常用模式
1、撤销重做模式
基础封装:
#region 重做单元 /// <summary> /// 表示开始进行重做单元 /// </summary> /// <param name="title"></param> private void StartUndoUnit(string title = "coolform") { var ims = htmlDesignEditor.Document as IMarkupServices2; ims.BeginUndoUnit(title); } /// <summary> /// 表示结束进行重做单元 /// </summary> private void EndUndoUnit() { var ims = htmlDesignEditor.Document as IMarkupServices2; ims.EndUndoUnit(); } #endregion
封装好后,在通过代码来改变HtmlEditor内的内容时,需要把更改的操作包含在起来,如:
StartUndoUnit(); foreach (var tempSelectCell in cells) { var element = tempSelectCell.Value; IHTMLStyle style = element.style; style.SetTextAlign("center"); } EndUndoUnit();
只有把操作代码给StartUndoUnit()跟EndUndoUnit()包含起来后,HtmlEditor才会把里面的多个操作当作是一个工作单元,当你使用Undo()撤销时,才会一次性进行撤销操作。
2、鼠标区域限制
当进行拖拉跳转单元格等操作时,我们需要鼠标拖拉的范围进行调整,即限制鼠标的可活动范围:
#region "鼠标区域限制" /// <summary> /// 移除鼠标区域限制 /// </summary> /// <remarks></remarks> private void RemoveMouseRect() { Cursor.Clip = Rectangle.Empty; } /// <summary> /// 设置鼠标区域限制,此区域大小由传入的控件参数决定 /// </summary> /// <param name="el"></param> /// <remarks></remarks> private void SetMouseRect(IHTMLElement el) { Size s = new Size(el.offsetWidth, el.offsetHeight); Point p = _coolPf.GetAbsoluteLocation(el); SetMouseRect(p, s); } /// <summary> /// 设置鼠标区域限制 /// </summary> /// <param name="p">The p.</param> /// <param name="s">The s.</param> private void SetMouseRect(Point p, Size s) { Rectangle r = this.htmlDesignEditor.RectangleToScreen(this.htmlDesignEditor.ClientRectangle); p.X += r.Left; p.Y += r.Top; IHTMLElement2 body = this.htmlDesignEditor.HtmlDocument2.GetBody() as IHTMLElement2; p.X -= body.GetScrollLeft(); p.Y -= body.GetScrollTop(); //检测最左边缘 if (p.X < 0) { s.Width += p.X; p.X = 0; } //检测最上边缘 if (p.Y < r.Top) { s.Height = s.Height + p.Y - r.Top; p.Y = r.Top; } //检测可见区域 int height = r.Height; int width = r.Width; if (r.Left < 0) { width = r.Width + r.Left; } if (r.Top < 0) { height = r.Height + r.Top; } //设置可见区域 if (width < s.Width) { s.Width = width; } if (height < s.Height) { s.Height = height - 20; } if (p.X + s.Width > r.Left + r.Width) { s.Width -= 6; } var newRect = new Rectangle(p, s); Cursor.Clip = newRect; } #endregion
eg:如选择单元格时,需要限制鼠标在当前表格范围内:
//开始选择单元格 //保存相关的信息 //设置鼠标限制区域 //改变鼠标形状 if (_selectTableCellHelper.StartSelectCell(el)) { Cursor.Current = new Cursor("CellSelect.cur"); SetMouseRect(_selectTableCellHelper.MouseDownTable); return; }
选择完成后,需要清空对鼠标的区域限制:
if (_selectTableCellHelper.State == SelectCellState.Doing) { _selectTableCellHelper.State = SelectCellState.Finish; RemoveMouseRect(); Cursor.Current = Cursors.Default; }
3、对控件加入自定义的行为展示
在进行控件设计时,我们分别定义了很多控件,如文本框,时间日期框等等,但文本框,时间日期框本质上都是input控件,为了在设计时能区别不同的控件,我们对某些控件加入特殊的行为展示,如对时间日期控件加入日期小标志,如下图。
如何加入自定义行为,请参见:IElementBehaviorFactory, IElementBehavior, IHTMLPainter三个接口。
eg:
public class DateTimeBehavior : IElementBehaviorFactory, IElementBehavior, IHTMLPainter { protected IHTMLDocument2 Document { get { return (IHTMLDocument2)this.Element.document; } } protected IHTMLElement Element { get { return _behaviorSite.GetElement(); } } protected IHTMLWindow2 Window { get { return this.Document.GetParentWindow(); } } private IElementBehaviorSite _behaviorSite; public IElementBehaviorSite ElementSite { get { return _behaviorSite; } } public IHTMLPaintSite PaintSite { get { return (IHTMLPaintSite)_behaviorSite; } } public void Update() { PaintSite.InvalidateRect(IntPtr.Zero); } #region IElementBehaviorFactory 成员 public IElementBehavior FindBehavior(string bstrBehavior, string bstrBehaviorUrl, IElementBehaviorSite pSite) { return this; } #endregion #region IElementBehavior 成员 public void Init(IElementBehaviorSite pBehaviorSite) { _behaviorSite = pBehaviorSite; } public void Notify(int dwEvent, IntPtr pVar) { if (dwEvent == 1) { //IHTMLEventObj eventobj = this.Element as IHTMLEventObj; //mshtml.IHTMLElement el = ElementSite.GetElement() as mshtml.IHTMLElement; //mshtml.IHTMLImgElement imgel =( mshtml.IHTMLImgElement)el ; //mshtml.HTMLImgEvents2_Event imageEvent = imgel as mshtml.HTMLImgEvents2_Event; //imageEvent.onmousemove += new mshtml.HTMLImgEvents2_onmousemoveEventHandler(imageEvent_onmousemove); //imageEvent.onmousedown += new mshtml.HTMLImgEvents2_onmousedownEventHandler(imageEvent_onmousedown); //imageEvent.onmouseup += new mshtml.HTMLImgEvents2_onmouseupEventHandler(imageEvent_onmouseup); } } void imageEvent_onmousemove(mshtml.IHTMLEventObj pEvtObj) { mshtml.IHTMLElement el = pEvtObj.srcElement; int ex = el.offsetWidth - 20; if (pEvtObj.offsetX >= ex && pEvtObj.offsetX <= el.offsetWidth && pEvtObj.offsetY <= 20) { _buttonPushed = true; Update(); } else { _buttonPushed = false; Update(); } // System .Diagnostics .Debug .WriteLine ("move:"+_buttonPushed .ToString ()); } public void Detach() { //OnBehaviorDetach(); _behaviorSite = null; } #endregion #region IHTMLPainter 成员 public void Draw(int leftBounds, int topBounds, int rightBounds, int bottomBounds, int leftUpdate, int topUpdate, int rightUpdate, int bottomUpdate, int lDrawFlags, IntPtr hdc, IntPtr pvDrawObject) { //mshtml.IHTMLElement el = ElementSite.GetElement() as mshtml.IHTMLElement; //mshtml.IHTMLTable3 table = el as mshtml.IHTMLTable; try { Graphics g = Graphics.FromHdc(hdc); //Rectangle bounds = new Rectangle(leftBounds, topBounds, rightBounds - leftBounds, bottomBounds - topBounds); //Rectangle updateRect = new Rectangle(leftUpdate, topUpdate, rightUpdate - leftUpdate, bottomUpdate - topUpdate); //g.DrawRectangle(new Pen(SystemColors.Control), rightBounds - 20, topBounds, 20, 20); //g.FillRectangle(new SolidBrush(SystemColors.Control), rightBounds - 20, topBounds, 20, 20); //g.FillEllipse(new SolidBrush(Color.Black), rightBounds - 15, topBounds + 5, 10, 10); g.PageUnit = GraphicsUnit.Pixel; g.DrawImage(Image.FromFile("datePicker.gif"), leftBounds +20, topBounds); g.Dispose(); } catch { } } public void OnResize(int cx, int cy) { Size size = new Size(cx, cy); } private bool _buttonPushed = false; public void GetPainterInfo(HTML_PAINTER_INFO htmlPainterInfo) { //htmlPainterInfo = new HTML_PAINTER_INFO(); //OnGetPainterInfo(ref htmlPainterInfo); htmlPainterInfo.lFlags = 0x000002; htmlPainterInfo.lZOrder = 8; htmlPainterInfo.iidDrawObject = Guid.Empty; htmlPainterInfo.rcBounds = new RECT(20, 0, 0, 20); //htmlPainterInfo = new HTML_PAINTER_INFO(); } private const int ButtonPart = 1009; #endregion private void imageEvent_onmousedown(mshtml.IHTMLEventObj pEvtObj) { mshtml.IHTMLElement el = pEvtObj.srcElement; int ex = el.offsetWidth - 20; if (pEvtObj.offsetX >= ex && pEvtObj.offsetX <= el.offsetWidth && pEvtObj.offsetY <= 20) //if (((mshtml.IHTMLEventObj3)pEvtObj).behaviorPart == ButtonPart) { _buttonPushed = true; Update(); } } private void imageEvent_onmouseup(mshtml.IHTMLEventObj pEvtObj) { if (_buttonPushed) { _buttonPushed = false; Update(); if (((mshtml.IHTMLEventObj3)pEvtObj).behaviorPart == ButtonPart) { //System.Windows.Forms.MessageBox.Show("ASDdsdsddssdsdsddsFASFA"); OnClick(); } } } private void OnClick() { //throw new Exception("The method or operation is not implemented."); } #region IHTMLPainter 成员 public void HitTestPoint(int ptx, int pty, out int pbHit, out int plPartID) { Point pt = new Point(ptx, pty); plPartID = 0; pbHit = 0; if (pt.X <= 20 && pt.Y <= 20) plPartID = ButtonPart; if (plPartID > 0) { pbHit = 1; } } #endregion }
使用:
添加:
var grid = new DateTimeBehavior(); object obj = grid; IHTMLElement2 ele2 = input as IHTMLElement2; dynamic cookieid = ele2.AddBehavior(null,ref obj);
删除:
IHTMLElement2 ele = element as IHTMLElement2; int behaviorid = _toolTipBehaviorCookiedIDList[uniqueId]; ele.RemoveBehavior(behaviorid);
*请注意,删除Behavior需要根据添加Behavior到控件时返回的id才能删除,故添加时需要记录保存ID