C# Windows应用中OpenText DocumentView切换文档保留缩放状态的事件咨询
解决OpenText DocumentView控件捕获缩放矩形坐标的问题
我之前也碰到过类似的OpenText DocumentView控件的问题——常规鼠标、键盘事件抓不到矩形缩放的坐标,确实头疼,因为这个控件的内部交互逻辑是封装起来的,常规事件被它内部处理掉了。给你两个可行的解决方案,亲测有效:
方案1:用控件内置的专属缩放事件
OpenText的DocumentView其实有专门对应矩形缩放的事件,只是官方文档有时候藏得比较深。你可以试试监听这两个事件:
ZoomRectangleStarted:用户开始拖动绘制缩放矩形时触发,刚好用来记录起点坐标ZoomRectangleCompleted:用户松开鼠标完成矩形绘制时触发,这里能拿到终点坐标,直接构造出完整的缩放矩形
给你写个示例代码参考:
// 窗体初始化的时候绑定事件 private Point _zoomStartPoint; private Rectangle _lastSavedZoomRect; public YourForm() { InitializeComponent(); docView.ZoomRectangleStarted += DocView_ZoomRectangleStarted; docView.ZoomRectangleCompleted += DocView_ZoomRectangleCompleted; docView.PageChanged += DocView_PageChanged; } private void DocView_ZoomRectangleStarted(object sender, EventArgs e) { // 把系统鼠标坐标转换成控件内部的客户端坐标 _zoomStartPoint = docView.PointToClient(Cursor.Position); } private void DocView_ZoomRectangleCompleted(object sender, EventArgs e) { Point endPoint = docView.PointToClient(Cursor.Position); // 构造正确的矩形(避免起点在右下角的情况,确保宽高为正) _lastSavedZoomRect = new Rectangle( Math.Min(_zoomStartPoint.X, endPoint.X), Math.Min(_zoomStartPoint.Y, endPoint.Y), Math.Abs(_zoomStartPoint.X - endPoint.X), Math.Abs(_zoomStartPoint.Y - endPoint.Y) ); } // 切换文档时恢复缩放状态 private void DocView_PageChanged(object sender, EventArgs e) { if (_lastSavedZoomRect.Width > 0 && _lastSavedZoomRect.Height > 0) { docView.ZoomToRectangle(_lastSavedZoomRect); } }
方案2:拦截Windows消息(适配旧版本控件)
如果你的控件版本比较老,没有上面说的内置事件,那可以通过重写控件的WndProc方法拦截Windows消息来捕获坐标。因为控件在绘制缩放矩形时,本质还是会发送WM_LBUTTONDOWN、WM_LBUTTONUP这些基础消息,只是被内部消化了,常规事件触发不了。
你可以先创建一个自定义的DocumentView子类:
public class CustomDocView : DocumentView { // 自定义事件,用来传递捕获到的缩放矩形 public event EventHandler<RectangleEventArgs> ZoomRectangleCreated; private Point _dragStartPos; private bool _isDraggingZoomRect; protected override void WndProc(ref Message m) { const int WM_LBUTTONDOWN = 0x0201; const int WM_LBUTTONUP = 0x0202; switch (m.Msg) { case WM_LBUTTONDOWN: // 先判断控件当前是不是处于矩形缩放模式 if (this.ZoomMode == ZoomMode.Rectangle) { // 解析消息里的鼠标坐标 _dragStartPos = new Point(m.LParam.ToInt32() & 0xFFFF, m.LParam.ToInt32() >> 16); _isDraggingZoomRect = true; } break; case WM_LBUTTONUP: if (_isDraggingZoomRect) { Point dragEndPos = new Point(m.LParam.ToInt32() & 0xFFFF, m.LParam.ToInt32() >> 16); Rectangle zoomRect = new Rectangle( Math.Min(_dragStartPos.X, dragEndPos.X), Math.Min(_dragStartPos.Y, dragEndPos.Y), Math.Abs(_dragStartPos.X - dragEndPos.X), Math.Abs(_dragStartPos.Y - dragEndPos.Y) ); // 触发自定义事件,把矩形传递出去 ZoomRectangleCreated?.Invoke(this, new RectangleEventArgs(zoomRect)); _isDraggingZoomRect = false; } break; } // 别忘了把消息传给基类处理 base.WndProc(ref m); } } // 自定义事件参数类,用来携带缩放矩形 public class RectangleEventArgs : EventArgs { public Rectangle ZoomRect { get; } public RectangleEventArgs(Rectangle rect) { ZoomRect = rect; } }
然后在你的窗体里用这个自定义控件,绑定事件就可以了:
private Rectangle _lastSavedZoomRect; public YourForm() { InitializeComponent(); customDocView.ZoomRectangleCreated += CustomDocView_ZoomRectangleCreated; customDocView.PageChanged += CustomDocView_PageChanged; } private void CustomDocView_ZoomRectangleCreated(object sender, RectangleEventArgs e) { _lastSavedZoomRect = e.ZoomRect; } private void CustomDocView_PageChanged(object sender, EventArgs e) { if (_lastSavedZoomRect.Width > 0 && _lastSavedZoomRect.Height > 0) { customDocView.ZoomToRectangle(_lastSavedZoomRect); } }
额外提醒
- 如果是控件版本太旧导致没有内置事件,建议升级到最新的OpenText Content Suite SDK,新版本的控件事件更完善
- 保存的矩形是控件内部的客户端坐标,因为你说文档结构相似,直接用
ZoomToRectangle就能对应到相同区域;如果文档尺寸有差异,可能需要按比例换算坐标 - 测试的时候注意,只有当控件处于矩形缩放模式时,这些逻辑才会生效,别忘确认
ZoomMode设置正确
内容的提问来源于stack exchange,提问作者Ch.
相关产品推荐
相关产品推荐

