CAD开发者社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

AutoCAD 2022 开发者帮助

acedCommand 迁移

2024-5-18 18:50| 发布者: admin| 查看: 11| 评论: 0|原作者: admin|来自: AutoCAD

acedCommand 迁移

acedCommand在运行无光纤时,它本身不起作用,因为需要开发人员干预来确定所需的使用类型。有两种迁移路径可供使用。acedCommand

迁移路径基于两个新函数:和 。“S”和“C”前缀分别代表“子例程”和“协程”。选择替换哪个功能取决于 的预期用途。acedCommandSacedCommandCacedCommandacedCommand

acedCmdNF.h Content
//////////////////////////////////////////////////////////////////////////////
//
//  Copyright 2021 Autodesk, Inc.  All rights reserved.
//
//  Use of this software is subject to the terms of the Autodesk license 
//  agreement provided at the time of installation or download, or which 
//  otherwise accompanies this software in either electronic or hard copy form.   
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

#include "acedinpt.h"
#include "acdocman.h"

// acedCmdNF.h:
// Fiberless variants of acedCommand and acedCmd
// plus supporting functions

#ifdef __cplusplus
    extern "C" {
#endif
#pragma pack (push, 8)

// acedFiberWorld:
// Returns
// true if $FIBERWORLD is 1, and
// false if $FIBERWORLD is 0
// On both Windows-based and Mac-based AutoCAD, by default returns "false"
//
ACAD_PORT bool acedFiberWorld();

//
// acedCommandS:  syntax-compatible replacement of acedCommand,
//                use for "full commands", not partial ones.
//                This command essentially begins with its own
//                private command line processor, initialized at
//                the "Command:" prompt.   The commands are executed
//                in the same manner as with acedCommand, except that
//                when the supplied input has all been executed,
//                the private command line processor is deleted
//                and the previous command line processor is unchanged
//                from when the call is made.   modality and
//                transparent "builtin" commands may not be nested.
//                
//
int             acedCommandS(int rtype, ...);

// acedCmdS
//
// Does the same thing with the same restructions as acedCommandS,
// with a resbuf chain rather than a veriable arguments list.
// Two more supplied parameters are intended for future use.
//
class AcApDocument;

int             acedCmdS(const resbuf*       rb,
               bool          forFutureUse  = false,
               AcApDocument* pForFutureUse = NULL);

// acedCommandC, acedCmdC:
// "coroutine" relationship with calling command processor.
// Queues up the resbuf chain for feeding to the
// calling command processor and stores the "returning"
// callback function pointer and data pointer.
// In the text here, they will be collectively
// referred to as "acedCmdC", which in fact is
// the common implementation.  "acedCmd" will represent
// the corresponding legacy command functions.
//
// After making call, caller must return from its 
// command (or defun/regfunc) entry
// point to allow the command processor to process the
// pending command input.  Once done with that input,
// AutoCAD will call pReturnFcn, with pReturnFcnParams
// passed in.
//
// There are some common rules for the use of both acedCmdC
// and acedCmd within a recognized application callback
// (specifically, these functions are only operative within
// specific AutoCAD contexts:
// - a command, registered in ARX via AcEdCommandStack::addCommand
// - a LISP invocation of a function registered via acedDefun
//   (and/or acedRegfunc).
// - a coroutine callback passed in from acedCmdC
// - Evaluation of LISP (command) statement evaluation.
// - builtin commands (plus AcEdCommand commands with the
//   ACRX_CMD_NONEWSTACK flag set).
// - Session Fiber Commands (or Application Execution Context)
// - Transparent commands, executed at an input prompt of another
//   command in progress (Regardless of builtin or ARX-registered)
// 
// 1. acedCmdC may be invoked from non-LISP calling contexts
//    regardless of the $FIBERWORLD
//    setting, (the exclusion from transparent commands remains).
//
//    From LISP contexts where acedInvoke() is active (i.e. acedDefun'ed
//    functions being called from LISP),
//    acedCmdC may only be invoked when $FIBERWORLD is 0.
//
//    acedCmd, in comparison, cannot be invoked unless $FIBERWORLD
//    is 1, if done, it will return an error status. It also
//    cannot be invoked from builtin commands, nor transparent commands.
//
//    Therefore, function logic running in an acedDefun/acedInvoke
//    context should test acedFiberWorld to determine whether
//    to run acedCmd or acedCmdC is permissible. Notice that
//    acedCmdS is safe to run in this context regardless of the
//    $FIBERWORLD setting.
//
// 2. While it is not a destination in one's migration,
//    Command and defun'ed function logic (but not coroutine callbacks,
//    described next) may invoke acedCmd any number of times,
//    but after making a call to acedCmdC, the function must
//    return without making a call to either acedCmdC nor acedCmd.
//    If such a call is made, the resbuf chain previously supplied
//    by acedCmdC will be replaced with the subsequent chain.
//    acedCmd will return an error status and take no action.
// 3. Coroutine continuation functions may call acedCmdC,
//    but use of acedCmd will return an error status
//    and no action.
// 2. acedCmdS may be used in any of these contexts (and many more)
//    and at any time within these contexts.
//    It is unobvious to invoke acedCmdS
//    after calling acedCmdC and before returning to have its
//    input procssed, since the acedCmdS will be executed
//    synchronously, but it would work.
// 3. Repeated calls to acedCmdC without returning for processing
//    in between will simply erase the earlier acedCmdC contents.
//    In other words, only one call will count before returning,
//    so don't bother making multiple calls.
// 4. Commands and LISP expressions which use different mixes of
//    acedCmd, acedCmdC and acedCmdS may invoke each other
//    without regard to the makeup of the other command/expression.
//    Command processor modality restrictions will still apply
//    such as no nesting of nontransparent commands nor transparent
//    commands.
//
// WARNING: support of these functions in logic operated through
//          invocation of functions registered via acedDefun
//          is incomplete in ACAD 2011.
//

typedef int (*AcEdCoroutineCallback)(void* pData);

ACAD_PORT int acedCommandC(AcEdCoroutineCallback pCallback,
                           void* pReturnFcnParms,
                           int rtype, ...);
ACAD_PORT int acedCmdC(AcEdCoroutineCallback pCallback,
                       void* pReturnFcnParms,
                       const struct resbuf *rb);

// acedPendingCmdCTokens
//
// This predicate should be checked immediately after calling
// acedInvoke from a function registered via acedDefun that
// has itself been invoked from LISP.  If it returns true, then
// the calling
// function should itself also immediately return RSRSLT, without
// necessarily establishing a return value.   The tokens will be
// processed, and either the calling function will be called back
// (see acedResumeInvocation below for determining if this is the
// case), or cancel will terminate the rest of the operation.
// Note that acedFiberWorld() must return true for acedCmdC
// to succeed in an acedInvoke context, and for this function to
// return true.
//
// Returns
// true  after a function has invoked acedCmdC
//       from a LISP context, and LISP has yet to return.
//       See preceding for how to proceed when true is returned.
// false when there are no pending comand tokens, in which
//       case the caller should proceed normally.
//      
ACAD_PORT bool acedPendingCmdCTokens();


// acedResumingInvocation
//
// Returns
// true  when in a function registered via acedDefun and/or acedRegFunc
//       and invoked from LISP that is being called back after a
//       previous invocation called acedCommandC or acedCmdC, (see
//       acedPendingCmdCTokens()), either directly or via a nested
//       invocation.
//       In this case, the function is responsible for
//       determining how to resume.   If, during its resumption,
//       acedCommandC or acedCmdC is invoked again, then after
//       returning to process those tokens, the function will be
//       "resumed" again, until no call to acedCommandC or acedCmdC
//       is made.  Because acedCommandC/acedCmdC can be invoked
//       regardless of the $FIBERWORLD state, this function can
//       also return true, in any case.
// false in all other conditions, including whenever acedFiberWorld()
//       is true.
//
ACAD_PORT bool acedResumingInvocation();

// acedCallBackOnCancel
//
// If you have made a call to acedCommandC or acedCmdC and wish to
// have your registered callback called when a CANCEL or other error occurs,
// call this function before returning.   If you don't call this function
// and a CANCEL or other error occurs, your callback will not be
// called, instead AutoCAD will directly cancel the command state.
//
ACAD_PORT void acedCallBackOnCancel();

// acedCmdCWasCancelled
//
// When your registered callback is called in response to a CANCEL or error,
// this function will return true, else it will return false.
//
ACAD_PORT bool acedCmdCWasCancelled();

#pragma pack (pop)
#ifdef __cplusplus
    }
#endif  /* __cplusplus */

// acedPendingFiberlessDocSwitch:
//
// pNextActiveDocument: Optional parameter to receive the next active document
// if the function returns true. Pass in NULL if the value is not needed.
// 
// Returns
// True if:
// - $FIBERWORLD is 0 and
// - a cancel is in progress and
// - a document switch has been requested but
//   hasn't occurred yet,
// 
// else false is returned.
//
// If a cancel happens at an input prompt and you
// want your command to continue in the new document,
// use something like AcApDocumentManager::sendStringToExecute
// to the new document to perpetuate control.
//
ACAD_PORT bool acedPendingFiberlessDocSwitch(AcApDocument** pNextActiveDocument = NULL);

acedCommandS

在“子例程”中,第一个输入标记被馈送到 Command: 提示符,因此应该启动命令,最后一个输入标记完成命令。“令牌”是命令的一段。在这样的通话中:acedCommandS

acedCommand(RTSTR, _T("_Line"), RTSTR, _T("0,0"), RTSTR, _T("111,111"), , RTSTR, _T("") , RTNONE); 

RTSTR, _T("_Line")是第一个命令令牌,也是最后一个,用于完成 LINE 命令。RTSTR, _T(””)

如果您的调用遵循此协定,则使用 .将上述代码迁移到就像键入额外的“S”一样简单,如下所示:acedCommandacedCommandSacedCommandS

acedCommandS(RTSTR, _T("Line"), RTSTR, _T("0,0"), RTSTR, _T("111,111"), RTSTR, _T(""), RTNONE); 

但是,如果 acedCommandS 不适合传入足够的令牌来开始命令但不能完成命令。当令牌用完时,任何正在进行的命令都将被取消。部分完成的命令副作用不会回滚。例如,以下语句无法提示用户输入另一个终结点,并且不会向数据库添加新行:

acedCommandS(RTSTR, _T("Line"), RTSTR, _T("0,0"), RTNONE); 

鉴于此,使用起来比您将看到的要简单得多,您可以通过迁移代码以尽可能使用来节省时间。acedCommandSacedCommandCacedCommandS

acedCommandC

“协程”可以概括为:在呼叫中,您停下来进行用户交互的任何地方都需要您使用 。acedCommandacedCommandacedCommandC

启用光纤后,在逻辑中负责将控制权返回给AutoCAD进行处理,该逻辑会根据需要切换光纤。禁用光纤后,ARX 命令和 LISP 必须实际返回给调用方。AutoCAD 将调用提供的“回调”函数,以允许 ARX 命令和 LISP 逻辑继续执行。acedCommand

需要协程方法的简单用法示例是 NAMEXXX 中 TYPE2 命令实现的函数:acedCommand

static void adskacedCommandTeststype2(void) 
{
    acedCommand(RTSTR, _T("Line"), RTSTR, _T("0,0"), RTSTR, _T("111,111"),RTNONE);
    while(isLineActive())
        acedCommand(RTSTR,PAUSE,RTNONE);
    acutPrintf(_T("\nFinished LINE command - control returned to addin\n"));
}
注意:是一个简单的帮助程序功能,用于检查命令是否仍处于活动状态。isLineActive

转换为用法,此代码将如下所示。(为简洁起见,此处删除了注释,但包含的 NAMEYYY 项目已完全注释):acedCommandC

static void myCallbackFn1(void * pData)
{
    if (isLineActive())
        acedCommandC(&myCallbackFn1, NULL, RTSTR,PAUSE,RTNONE);
    else
        acutPrintf(_T("\nFinished LINE command - control returned to addin\n"));
}

static void adskacedCommandTeststype2(void)
{
    acedCommandC(&myCallbackFn1, NULL, RTSTR, _T("Line"),
       RTSTR, _T("0,0"), RTSTR, _T("111,111"), RTNONE);
}

迁移的 TYPE2 命令的行为存在差异。在示例版本中,即使用户按 ESCAPE 结束 LINE 命令,控制也会返回到函数。在此示例中,按 ESCAPE 键也会取消您自己的命令 – 因此,仅当 LINE 命令通过按 ENTER 或(例如)CLOSE 关键字结束时,才会执行表达式。acedCommandacedCommandCacutPrintf

TYPE3 命令实现显示了另一种(不太常见的)协程用法:

static void adskacedCommandTeststype3(void)
{
    acedCommand(RTSTR, _T("Line"), RTSTR, _T("0,0"), RTSTR, _T("111,111"),RTNONE);
    for (int i=0; i<3; ++i)
        acedCommand(RTSTR, PAUSE, RTNONE);
    acedCommand(RTSTR, _T(""), RTNONE);
    acutPrintf(_T("\nFinished LINE command - control returned to addin\n"));
}

在这里,我们只是画一条线,并允许用户最多画三条额外的线。

迁移到使用情况后,这将如下所示:acedCommandC

static void myCallbackFn2(void * pData)
{
    struct MyData *pCountData = reinterpret_cast<struct MyData *>(pData);
    if (pCountData->mCount < 3)
    {
        acedCommandC(&myCallbackFn2, reinterpret_cast<void *>(pCountData),
           RTSTR, PAUSE, RTNONE);
    }
    else if (pCountData->mCount == 3)
    {
        acedCommandC(&myCallbackFn2, reinterpret_cast<void *>(pCountData),
            RTSTR, _T(""), RTNONE);
    }
    pCountData->mCount++;
}

static void adskacedCommandTeststype3(void)
{
    static struct MyData countData;
    countData.mCount = 0;
    acedCommandC(&myCallbackFn2, reinterpret_cast<void *>(&countData),
        RTSTR, _T("Line"), RTSTR, _T("0,0"), RTSTR, _T("111,111"), RTNONE);
}

路过

雷人

握手

鲜花

鸡蛋

最新评论

QQ|Archiver|CAD开发者社区 ( 苏ICP备2022047690号-1 )

GMT+8, 2024-6-27 16:16

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

返回顶部