CAD开发者社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

ObjectARX 开发指南

aced命令迁移

2022-12-31 04:55| 发布者: admin| 查看: 256| 评论: 0|来自: AutoCAD

摘要: aceedCommand 本身在无光纤运行时不起作用,因为需要开发人员干预来确定所需的使用类型。有两种迁移路径 aced命令用法。

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

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

acedCmdNF.h Content
//////////////////////////////////////////////////////////////////////////////
//
//  Copyright 2020 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

In the ‘Subroutine’ the first input token is fed to the Command: prompt, so should initiate a command, the last input token completes a command. A ‘token’ is a segment of a command. In a call like this: acedCommandS

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

RTSTR, _T("_Line") is the first command token, and is the last, which finishes the LINE command. RTSTR, _T(””)

If your call follows this contract, then use . Migrating the above code to is as simple as typing the extra ‘S’, like this: acedCommandacedCommandSacedCommandS

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

However, if acedCommandS is not suitable if you want to pass in enough tokens to begin a command but not finish it. When the tokens run out, any command in progress is cancelled. Partially completed command side effects are not rolled back. For example, the following statement would fail to prompt the user for another endpoint, there would be no new line added to the database:

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

Given that, usage is a lot simpler than as you will see, you save time by migrating your code to use wherever possible. acedCommandSacedCommandCacedCommandS

acedCommandC

The "Coroutine" can be summarized as: anywhere you stop for user interaction in an call will require you to use . acedCommandacedCommandacedCommandC

With fibers enabled, returning control to AutoCAD to process them is taken care up within the logic, which switches fibers as needed. With fibers disabled, ARX commands and LISP must actually return to their caller. AutoCAD will invoke supplied “callback” functions to allow the ARX command and LISP logic to continue. acedCommand

A simple example of usage that requires the Coroutine approach is in the function for the TYPE2 command implementation in NAMEXXX: 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"));
}
Note: is a simple helper function to check whether the command is still active. isLineActive

Converted to the usage, this code would look something like this. (Comments have been removed here for brevity, but the included NAMEYYY project is fully commented): 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);
}

There is a difference in behavior for the migrated TYPE2 command. In the version of the sample, control returns to your function even if the user ends the LINE command by pressing ESCAPE. In the sample, pressing ESCAPE also cancels your own command – so the expression is only executed if the LINE command is ended by hitting ENTER or (for example) the CLOSE keyword. acedCommandacedCommandCacutPrintf

The TYPE3 command implementation shows another (less common) Coroutine usage:

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-5-19 12:43

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

返回顶部