使用Visio 2003 Drawing Control开发应用(4)

Posted on 2007-10-25 18:40  ant-boss  阅读(549)  评论(0编辑  收藏  举报

还有一个很好的方法,就是直接发送命令
  #region 向Visio工作区发送Visio命令
  [StructLayout(LayoutKind.Sequential)]
   public struct OLECMDTEXT
  {
   public UInt32 cmdtextf;
   public UInt32 cwActual;
   public UInt32 cwBuf;
   public char rgwz;
  }

  [StructLayout(LayoutKind.Sequential)]
   public struct OLECMD
  {
   public UInt32 cmdID;
   public UInt64 cmdf;
  }

  [ComImport(), Guid("B722BCCB-4E68-101B-A2BC-00AA00404770"), InterfaceType

(ComInterfaceType.InterfaceIsIUnknown)]
   public interface IOleCommandTarget
  {
   [PreserveSig()]
   int QueryStatus([In, MarshalAs(UnmanagedType.Struct)] ref Guid pguidCmdGroup, [MarshalAs

(UnmanagedType.U4)] int cCmds, [In, Out] IntPtr prgCmds, [In, Out] IntPtr pCmdText);

   [PreserveSig()]
   int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdExecOpt, object[] pvaIn, [In, Out,

MarshalAs(UnmanagedType.LPArray)] object[] pvaOut);
  }

  /// <summary>
  /// 发送OLE命令
  /// </summary>
  /// <param name="command"></param>
  private void SendCommand(UInt32 command)
  {
   IOleCommandTarget commandTarget =
    (IOleCommandTarget)visDrawing.GetOcx();

   try
   {
    Guid CLSID_Application = new Guid("{0x00021A20, 0x0000, 0x0000, {0xC0, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x46}}");
    commandTarget.Exec(ref CLSID_Application, command, 0, null, null);
   }
   catch(System.Runtime.InteropServices.COMException ex)
   {
    MessageBox.Show(ex.ToString());
   }
  }
  #endregion
这个是从msdn online中的一篇文章学来的。
比如想显示标尺和网格配置的对话框出来
  public void RulesAndGrid(TulipMenuItem item)
  {
   this.SendCommand((UInt32)Visio.VisUICmds.visCmdRulerGridDlg);
  }
那个对话框就出来了。:D
页面设置
  public void PageSetup(TulipMenuItem item)
  {
   this.SendCommand((UInt32)Visio.VisUICmds.visCmdPageMeasureUnitsDlg);
  }
还有好多好多的对话框可以用发命令方式出来
很多快捷键一样可以用,比如Ctrl+F,F3什么的

如果掌握了前面我写的东西,应该开发一个像样的东西就不是很难了。主要是要和自己的业务逻辑挂钩起来。

关于Drawing Control的文章很少,在msdn online上有几篇文章,可以看看,很不错的,有一个例子带了一个VisioUtility.cs的类,有一些用处的。
要解决一些棘手的问题,靠VBA是一个很好的方式。

下面说一些问题:
1、如果你用到这个control的form是mdichild。就要注意,当你第一次打开,没有问题,但是当你关闭了这个子form,再开一个的时候,就会出现异常。如果保留第一个打开的子form不动,打开第二个就没事。这个问题是因为什么一直不知道,最后我的解决方法是主窗体一开就建立一个隐藏的子form
   FormWorkspace formHide = new FormWorkspace(new BusinessProcessResource(), FormMain.userID, "", false, "");
2、带有这个control的form在打开的时候,偶尔会出现异常,那个异常的id根本哪里都查不到。我只能这样做:
    MessageBox.Show(this, "发生未处理的错误,请关闭后重新打开\n" + ex.Message, "异常错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
3、有时候,这个控件里发生异常的时候,异常并不抛出,用try catch根本没有办法得到,会被生生吃了,什么反应没有,这个只能慢慢的去找。
4、有些事件有问题,比如我想抓住Ctrl+Z,也就是Undo的执行,我用Keyup来抓,结果是有时候能抓到,有时抓不到。
5、ShapeSheet的UI在控件中是显示不出来的
6、只能是单窗体运行
7、不能嵌到其他ActivX control中(其他Activex control也一样)
8、不能放到Infopath form中(好像Infopath sp1可以了)
9、不包含VBA


好了,我知道的也就差不多了。当然有很多很多的细节没有说。如果这些没有条理的所谓文章能对大家有帮助,那也是大家的理解能力好,这么乱的东西我自己也看不懂了。:D