UG模具网

 找回密码
 注册

QQ登录

只需一步,快速开始

瑞洪模具学校UG专业培训招生
查看: 118|回复: 0

[原创] 梦想CAD命令执行原理

[复制链接]
  • TA的每日心情

    2018-8-30 08:48
  • 签到天数: 6 天

    [LV.2]偶尔看看I

    0

    主题

    0

    帖子

    -91

    金币

    乞丐

    积分
    -75
    发表于 2018-8-8 15:56:21 | 显示全部楼层 |阅读模式

    马上注册,结交更多好友,享用更多功能,让你轻松学习交流!

    您需要 登录 才可以下载或查看,没有帐号?注册

    x
    本帖最后由 MxDraw 于 2018-8-8 15:58 编辑
    1 X8 o2 t* E" @2 T
    % r$ q  S' n% c# P6 a0 W. E1.说明:2 `0 b. v/ G& g
    在控件中,所有与用户交到的操作函数,都必须放在命令执行事件中调用。
    6 r- E, o9 z% c9 B( \因为与用户交互操作时,控件会启动一个临时的windows消息循环,这样执行交互函数时,会临时等待用户操作,在事件退出时,控件就有机会控制临时信息消息循环的退出处理。( Z" V* m- ^0 g8 p$ y4 Z
    比如在等待用户交到操作过程中,如果用户点击了窗口上关闭按钮结束程序,或点击了另一个按钮,又重新执行一个命令,这些都需要控件在事件结束时自动处理,防止出错。  G. W  v2 ]$ j: R3 k" \! U
    & {2 G- s8 i! P  H2 ~- E4 H+ ?9 E" z
    2.COM接口的命令执行( i7 s4 M/ Y7 z* Y- z
    DoCommand说明:' q2 ?" V. l5 M' L. @/ S( t: ^. m( x/ u
    该函数开始执行控件的一个用户自定义命令,参数是命令的id,这个id值可以随便取值,它是用来标识该命令,多个命令之间,id值不能重复
    0 V# ^$ s4 J, q  B8 `前面的DoCommand的调用后,程序将会跳转命令执行事件函数中。
    * E/ p2 H8 J2 x命令调用过程流程图:( R& D$ G1 `+ i& X* z# s- {
    图片10.png
    ; O$ `4 N4 j* d比如C#语言:5 i/ q: O8 P0 H1 I0 W$ g; U$ ~1 G
    开始执行一个命令:
    ; A- O9 M# R+ X6 F+ Y. s在界面上放一个按钮“打开DWG”; I/ G% y5 E6 \1 l* ^3 Z5 ]* t
    给按钮增加点击事件如下:
    + C; }& W5 D* ?- Q6 r8 R  private void button6_Click(object sender, EventArgs e)9 y" D- n! i# Q3 V8 @
            {
    . U( @+ J7 B3 C            axMxDrawX1.DoCommand(6);
    ! I: u3 r: u; [3 _' H. t        }
    3 E% L: ?) t% R6 f3 R' n3 B2 V( V8 t- X! u4 H5 p
    axMxDrawX1.DoCommand调用后就会跳到命令事件中,给窗口增加控件命令执行事件,并加代码,如下:8 l8 w3 v" }6 T, G6 B
       private void axMxDrawX1_ImplementCommandEvent(object sender, AxMxDrawXLib._DMxDrawXEvents_ImplementCommandEventEvent e)
    , g2 A% r$ N) N. [" R) g        {
      q* z0 T4 \$ W. h7 j8 W
    , d5 M7 `" G7 U( @3 W! _- F. yif (e.iCommandId == 6)- s3 W6 l+ n! T6 L$ M
                        {4 n% q7 X" K6 c8 v# k- `: X
                    // 打开文件.
    5 P' o7 j1 j7 h# ]) w' A: _. d$ H                OpenFileDialog ofd = new OpenFileDialog();' J% ^2 B/ o( I- g
                    ofd.Filter = "dwg 文件(*.dwg)|*.dwg";
    . H7 G5 B* }9 O4 [' s9 P6 e
    + e4 \/ Y& N; S7 X% U6 N( [4 X                if(ofd.ShowDialog() ==  DialogResult.OK)' j) m4 m0 U/ @2 |1 r
                    {
    3 l! e$ C6 N: N% q: A: F4 S5 F* `                    axMxDrawX1.OpenDwgFile(ofd.FileName);4 c* z1 S/ k" e7 o7 k; G: P
                    }
    - c: m& t$ x: d6 w4 V3 C% c                    }) v1 b( U1 Z3 r; Z: z
                    }
    + o" G- q9 Y" O. I) f0 G+ W( c4 V2 v0 W6 I

    % N. n" {4 g# e$ f  z- b) o7 r! j( L比如JS语言; ]# x! q# V: }3 v8 v
    开始执行一个命令:
    9 m& D: P! R! {在界面上放一个按钮“打开DWG”,如下:
    & l$ t* x4 B  {* Y8 s4 O9 y2 ?% j<input type="button" value="写扩展数据" onclick="DoCmd(11)">
    ' T; T; m/ b8 w2 \( ^8 a3 a, p1 F8 P& Y$ D% E) }4 F& Y0 d' N
    DoCmd代码如下:调用DoCommand执行用户命令,DoCommand调用后就会跳到命令事件中" `- W& M5 y  O
    function DoCmd(iCmd) {* F" b% R9 P  t, O
        mxOcx.DoCommand(iCmd);
    0 y5 @0 \. k1 @+ Q6 w}
    , Q9 E& o) Y8 d8 q  z  J  s* k1 b0 A) [5 i1 a
    : _3 q0 B9 W5 Y9 }- j7 a' f
    添加命令事件:
    ( T! W) X; S9 i% E, ?% Qdocument.getElementById("MxDrawXCtrl").ImplementCommandEventFun = DoCommandEventFunc;
    - }% Y! z, e3 z  k* B: L* ^% b/ k! g1 W6 Z0 ]* Y
    5 R2 s' d9 F* y8 o: J0 ]2 J8 [
    命令事件函数实现: $ e$ M( o( z  F6 \7 O# g# X) \

    3 R8 c" y, @9 o2 w7 e0 ffunction DoCommandEventFunc(iCmd)
    ( w1 |3 A1 O9 Q0 `# O{) h# x7 @7 U" H6 H3 l
         if (iCmd == 11) {4 i) ~  p. N0 ~" E/ E- d
            WriteXData();
    5 N6 g; r" C7 w! |4 g% L9 v    }! R! r6 H1 c# U# J+ j
    }. M& b$ o. Y# ^: o, j
    4 l" q8 C. D1 F7 j, c' F6 g/ G

    / N2 O+ `3 y+ z: l' R- R写扩展数据函数实现:
    0 x% U- l- s! I( q- W0 Y3 p( V8 o! }# Y5 d  j, D3 g* l3 i0 b
    function WriteXData() {+ k5 |; L. W/ v. [, u
        var selEnt = mxOcx.NewComObject("IMxDrawUiPrEntity");
      P" }8 A! W& R6 c: ~
    6 t( I' p" ]3 B+ J0 k    selEnt.message = "选择要写扩展数据的对象";
    7 y3 Z9 j  a" Z* j: F" c/ u5 X  Z    if (selEnt.go() != 1)
    ; C6 n2 \9 Q1 m6 h1 w. J! J; {6 i        return;) e6 K, z& p/ z4 G/ i2 e

    / l  _( j# v, x0 V& v+ y& P    var ent = selEnt.Entity();
    % S) Z' p) I3 V! n  r( b    if (ent == null)
    / d7 |# M+ {( _9 I        return;; H7 Y- m- z7 f* C
    / w3 m: N1 _2 l# h
        if (ent.SetxDataString("ExDataName", 0, "ExDataValue")) {
    6 M8 I1 ?! m2 @( b        alert("写扩展数据成功");; @" b( w( J0 v1 W# c* K3 ?
        }
    ) S& j. _* l8 F+ j    else {
    ( y1 t% T0 b# _+ b        alert("写扩展数据失败");6 K8 v( h& `6 a" n) R0 c
        }
    9 ?3 P% D/ J8 P; q" a6 S' B+ S}
    2 r. G4 f# Q8 j" T' `+ I( u) ^6 s7 y6 v! k! u

    # M0 B9 U8 K9 n- Z- C在工具条定义文件中执行用户命令5 Z9 G: g, {+ c& s  u, Z# \2 [+ h
    工具条定义文件中一行代表一个工具条上的按钮,如果用户想点击工具条上的按钮,按钮执行命令事件,如下定义工具条:% B* k* P& [* t3 b: r0 _& d
    # T9 c+ \) w& @7 R- D
    ("保存dwg文件" "保存dwg文件" "SaveDwg" "IDB_SAVEDWG_BITMAP"  "" "MxDraw.dll" "15")& w  t+ X' Z! K1 q
    " N5 X: v2 ]: X- ?0 j
    上面,定义了一个打开dwg文件按钮,点击这个按钮,相当于执行DoCommand(15)7 r0 T/ \3 d( o; V" `" _+ n/ i3 Y+ G

    6 B& v! T& a; a# m) c5 q在菜单条中执行用户命令. F, L1 p2 W6 X) y. M$ @; J
    菜单条定义文件中一行代表一个菜单命令,如果用户想点击菜单,执行命令事件,如下定义菜单条定义文件:
    : P  f3 H3 a$ {7 d"打开(&O)" "Mx_OpenMxg" "IDB_OPENMXG_BITMAP" "" "" "15". f+ e$ T: a% @5 Y( Z
    上面,定义了一个打开文件菜单,点击这个菜单项,相当于执行DoCommand(15)! ~' h7 V2 s( B4 r, f9 T8 a8 Q
    1 I3 d5 U/ R3 [! O
    为命令注册一个命令名称,方便命令输入和调用
    , v7 j; c, N' Z: p/ x调用RegistUserCustomCommand函数注册命令名称,chm中的帮助如下:
      d6 U( c% @" s3 x. ]: u 图片11.png
    ) K. d# n# [+ j9 s; j例如: VB调用代码
    7 S) R5 I+ C. q* A& B        MxDrawX1.RegistUserCustomCommand " MyTest11", 15/ a1 _8 _0 {4 C4 w# w: ?, Q
    例如: C#调用代码
    ; O( K* T" i9 k9 M* N) _4 f9 F# U& g4 Q
            axMxDrawX1.RegistUserCustomCommand("MyTest11",15);$ z  B7 [3 O; g, g% L
            axMxDrawX1.Focus();
    & M7 D* ]1 c7 Q; B! J9 {, G      // 命令 响应代码# w: p& F2 K6 b
            private void axMxDrawX1_ImplementCommandEvent(object sender, AxMxDrawXLib._DMxDrawXEvents_ImplementCommandEventEvent e)( P. [0 D0 v* ?: D( `4 Q3 k
            {7 n) V. H. _6 ~6 E; Z# w
               if (e.iCommandId == 15)( p$ o) w. K, O) {5 X
                {; l. M- z1 ?# e- f0 I
                    MessageBox.Show("用户定义命令执行....");
    7 J0 W7 Y% d/ n( w3 ~            }. @+ s. O, u7 e9 ]! q
            }5 E: A: M$ |& x' I! j
    1 k& \0 C" [. y  O+ {! F3 T
    1 q4 }: O8 l2 u! C4 U% H4 {! j
    调用控件自带命令4 J* P0 D5 H4 i; C5 S! \0 D9 I
    控件工具条上的按钮,都是控件内部命令实现,点击工具条上的按钮,就会在命令行看到相关命令名称,如:
    ( l7 y& s$ g9 Z. J5 [ 图片12.png
    5 s. y* }6 W" I% G$ F. m9 b如果用户想在自己的按钮中,调用画线命令,如下:% q; w# z- I' H! v4 P0 p
    axMxDrawX1.SendStringToExecute("Mx_Line");- m5 a" @& x9 ?& j+ U9 Q# J7 S
    在命令执行中,再调用另一个命令, @. \# |% \$ o& G+ }7 _
    控件是不允许命令被重入,也就是说不能同时执行两个命令,比如当前用户正交到绘制直线,当用户点击绘制圆按钮时,绘制直线命令就需要立即退出,并进入绘圆命令。
    8 @" B8 E! n% o* ~那么如果用户想要在命令中,调用另一个命令,可以把另一个命令当前一个函数调用,调用如下:
    ; S: n5 B4 T% ?9 j! @- o4 Y/ JaxMxDrawX1.SendStringToExecuteFun("Mx_Line");% L/ `+ V, l8 J9 j: r
    : L, n7 H  g& u; r( L7 }
    命令函数执行完后,可以调用GetEntitysLastCmd函数返回,命令函数新增加的实体,它返一个MxDrawResbuf对象,也就是说,得到一个数组,得到多个新增加的实体。$ |, T( b+ R. o! z% Q0 C. B$ f
    ; F6 Q6 M6 w+ M- f  g) r
    如下JS代码,调用控件的绘制样条线命令,并得到新绘制样的样条线,然后修改它的线重:/ `# f+ `6 g+ [' X% u
    ! ^5 |4 C; P2 n0 `: }! n2 @
    function DrawSpline() {9 l. B1 \5 h  u( F( C
        mxOcx.Cal("Mx_ShowWeight");9 Z4 ^: |7 j# i% b/ F
    1 Z9 k; _! g! x4 p5 @, t- f* F" \. {
        var param = mxOcx.NewResbuf();0 C3 l3 S* }9 H4 u0 |* r3 O( Q
        mxOcx.SendStringToExecuteFun("_DrawSpline", param);# x* }: `, t2 y
        var retparam = mxOcx.GetEntitysLastCmd();( w+ h/ T' Q$ A+ }, R/ H# c
        if (retparam == null)
    ( a! E7 ]) [. J+ ?        return;
    ; c! R; d8 H8 Z, G  m" {, \
    7 F4 p2 Y; T4 f$ a3 J    if (retparam.Count == 0)
    " v% m8 M1 n" v4 Y4 v        return;' Y  f' g. E% A  y

    1 D; h- n4 v* W: A  c: Z    var spline = retparam.AtObject(0);; z4 i! _- U  Z  ~3 }: ~$ T% ?; O
        if (spline == null) {( R8 ]; T" l* d" e  A
            return;
    3 C4 E+ u5 N" S5 y7 |% L: `9 i7 O    }
    3 q" e% C; R6 T3 ]$ d0 w. U. ]/ Y+ X
    0 \" I0 Y/ A8 b    spline.Lineweight = 40;
    ' N) v0 Q+ s& i1 [" L5 J# v2 E) \3 ^# _. z1 W
    }
      @& U$ X$ L" C1 _9 [. S) r2 v$ C7 e2 s: q# D5 l& X4 B
    用些命令在用时,可以转入参数,调用SendStringToExecuteEx函数:0 Q) t" {' Q, a
    如:调用阵列命令,并传递参数1 C/ k! ]! L. I# f0 E# D& g
    MxDrawSelectionSet ss = new MxDrawSelectionSet();
    2 e0 s  \' T7 c* x5 u                        MxDrawUtility utility = new MxDrawUtility();: C; E1 o- L+ s
                            utility.Prompt("选择阵列对象:");
    - _" d4 T3 z, e. T# l5 V9 v                        ss.Select(MCAD_McSelect.mcSelectionSetUserSelect, null, null, null);
    * [8 D' u/ }5 ]+ B' ~                        if (ss.Count == 0)6 w- d. M; r3 }$ j+ S' V
                                return;
    ' K4 I4 J9 N- E1 E3 I                        MxDrawResbuf param = new MxDrawResbuf();% x5 z4 n& ~6 H3 U# L
    - T4 t4 c: Z' V( G. Z- `* X& _/ V
                            // 10行.# h8 n* B$ x; ^  J) Q% R# ~7 ?- B
                            param.AddLongEx(10, 1070);; f# F! R6 r9 f
    ! [! O2 K) X, h, p# p
                            // 20列.
    8 a1 F6 h8 j& g+ y- {' ]                        param.AddLongEx(20, 1070);
    4 `8 P& V! n- ]: U
    " z. A  N: r$ |, ]) S4 q7 }                        // 行偏移.+ a" Z# g0 F/ `2 ~, V/ j7 x* n
                            param.AddDoubleEx(100, 1040);
    2 J& e" p8 n8 r! g$ L  m4 G
    3 N/ t4 ^0 B- _7 h+ A- J                        // 列偏移.* z  o' j# m  ^# _
                            param.AddDoubleEx(150, 1040);
    / h4 L8 r8 J% E2 F6 l/ f, `/ @  K6 o1 N. ?" w
                            // 阵列角度.
      D9 M; h& _5 Z4 \                        param.AddDoubleEx(15.0, 1040);5 f) d( ]/ \1 O
    % r' |3 G! M/ A: b! b
                            // 阵列对象个数.
    $ e  U8 G7 Y! y3 `                        param.AddLongEx(ss.Count, 1070);
    $ Q- b) \2 j" T                        for (int i = 0; i < ss.Count; i++)6 x# m5 ^) m: }
                            {; B3 m3 q8 q5 V, |7 q& m
                                MxDrawEntity ent = ss.Item(i);" W1 J0 z1 Q' r4 n
                                param.AddObjectId(ent.ObjectID);
    3 @) c/ O' v( i- v+ D! r: N) j* K                        }5 i4 p; C" Q7 ?5 v% `( g' Z

    ! a% @3 n8 E( h                        // 调用阵列命令.
    9 c1 K& f& x+ o0 E8 Q# J& a" _                        axMxDrawX1.SendStringToExecuteEx("Mx_Array", param);8 X3 s* |7 }, Z3 h6 a4 \' k/ e1 z

    7 ~1 m; Z3 W. t, G" W8 u3.VC接口的命令执行
    * B) o, q+ F" g6 i( D8 ?, u& \VC2010调用是控件DLL接口,这个调用过程和AutoCAD Arx开发是一样的。8 ]7 ^) ?: O5 K. b  k; N( P7 a

    7 X( u% y; q$ A$ d: M; i命令函数实现:   L+ m. E) ~% C+ }' x' |, ^
    .h文件
    . T$ d2 c0 q3 |3 L, m" Z8 B% n2 S; Iclass CTestCommands
    + M; d2 _% c( m) ~/ ^4 x& `{
    " G) Z) Y) X7 s$ s4 Z; b# a+ Fstatic void TextToCurve();  E3 `& i6 k' D8 f- J8 f0 L- L
    }9 H3 Q- G; j% H, d, X  i, g9 G: _6 p
    * j6 k7 H7 U8 U- S& `9 d
    .cpp 文件/ O: S, y9 a" h9 m+ k8 a, N
    void CTestCommands::TextToCurve()
    * o4 i7 m+ T$ K  h- o8 |{
    - C: L% |9 X( n" l. R" e        ads_name entName;
    0 G/ T/ h; p* w* V! A/ y2 X        ads_point pt;
    , h3 o6 _6 ?5 O" U7 f        if(acedEntSel(_T("选择需要编辑的文字:"),entName,pt) != RTNORM)* f5 [" m* c: e$ x' U/ j! l0 v
            {5 r+ H! u) b: c" s
                    return;' M% S$ W+ y2 K1 `
            }& C- j7 n3 F6 T0 P$ r/ e4 f
            AcDbObjectId objId;% k0 h) Y$ `9 t) P: E
            if(acdbGetObjectId(objId,entName) != Acad::eOk)
    6 {( ]7 ^$ _# C/ c; [! S6 \, A                return;
    ) b3 j1 f0 R/ E5 z6 q. m7 t
    # L" S3 ^0 C, ?        AcDbObjectPointer<McDbEntity> spText(objId,AcDb::kForWrite);
    * U& o5 u+ K" h% U        if(spText.openStatus() != Acad::eOk)
    3 J( v( H, G+ ^0 v" _+ p$ _( m% P                return;* a4 N; v7 S! l* \: s" b$ \. y
    1 I6 s5 N3 Y4 ]$ T4 d

      ~! X1 P- i9 ]6 Z& e        McDbVoidPtrArray aryCurve ;5 z) S/ l3 a4 W( e* x
            if(!MxDraw::TextToCurves(spText.object(),aryCurve) )
    ' i1 g* M. B. M$ k, J                return;3 Z. F# H# N% }9 E/ E' ^% a- D' I& A
    ; ?" S2 i8 n( u1 H) z  b' ]
            for(int i = 0; i < aryCurve.length();i++)' z* F, e7 u7 K2 d3 f. b& l
            {
    ( |6 q0 F9 ^1 I7 o) p9 P                McDbEntity* pEntity = (McDbEntity* )aryCurve;
    + N3 w/ I+ A3 b2 h" N8 T
    1 i: }7 d& ~0 S. v% O) g                MrxDbgUtils::addToCurrentSpaceAndClose(pEntity);
    3 d9 P5 h8 g, h6 t4 C6 M+ e4 x4 n        }
    5 W! \0 G% }) O1 E  A        spText->erase();
    * g% V; x0 l& _5 ?) a}
    4 Q; f' a, T' K7 e  ~) M
    ) [- }! U5 }' S+ J. W' r
    1 F) ]$ j5 o) s# K2 ^6 q注册一个命令:
    : Y: [( f! X1 n- }acedRegCmds->addCommand(_T("SysCmd"), _T("TextToCurve"), _T("TextToCurve"), 1, TextToCurve);
    ' l( G  h+ p3 E) q$ R. p( ^  ?' l" T, P. l
    执行命令:  u2 I. j$ C, g7 u" p9 H$ j& c
    在界面上放一个按钮“文本转曲线”,在按钮响应函数中,调用刚才我们注册信息的命令:
    3 A6 t1 W: Q  X2 x8 LacDocManager->sendStringToExecute(MxDraw::GetDatabase(m_hDrawOcx)->GetDocument(): e/ t. U) {* I9 [' O
                    ,_T("TextToCurve") );
    : `, j6 C: a  ~  e+ H
    瑞洪模具学校,专业的模具设计培训!招生热线:13535692060 咨询:18138921941 唐老师
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    QQ|小黑屋|手机版|Archiver|UG模具网 ( 粤ICP备10229226号 )

    GMT+8, 2020-4-3 18:52 , Processed in 0.645037 second(s), 27 queries , MemCache On.

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表