Not signed in (Sign In)

Vanilla 1.1.4 is a product of Lussumo. More Information: Documentation, Community Support.

Welcome Guest!
Want to take part in these discussions? If you have an account, sign in now.
If you don't have an account, apply for one now.
  1.  

    There have been a lot of new commands added to CC3+ lately so I thought I add my own suggestions to the list.



    • ASK3BOX - Similar to ASKBOX this command creates a dialog box with three buttons; “YES”, “NO” and “CANCEL”. Would be used with another new command GETA3RETCODE to get more options out of query:

      • 0 - “Yes” button was clicked.

      • 1 - “No” button was clicked.

      • 2 - “Cancel” was selected by either clicking the “Cancel” button, the “X” in the upper right hand corner of the dialog or pressing the “Esc” key.

      • 3 - Command failed for another reason.


    • NOTE Commands - Until the recent OPENNOTE command the only way to use map notes was through the “Select Note” dialog (NOTES command). It occurs to me that the text stored in map notes should be usable in other ways. These new commands can manipulate map note in a variety of ways. The IFERR command can be used to check if a new note already exists or an old one does not.

      • ADDNOTE - Creates a new note using the MSGBOX syntax.

      • APNDNOTE - Adds text to an existing note using the MSGBOX syntax. Could be used to log map activity and revisions.

      • ASKNOTE - Creates an ASKBOX dialog using the note name as the title and note content as the text.

      • ASK3NOTE - Creates an ASK3BOX dialog (see above) using the note name as the title and note content as the text.

      • CLRNOTE - Deletes the contents an existing map note without removing it.

      • DELNOTE - Deletes an existing map note by name.

      • EDITNOTE - Edits an existing map note by name using the “Edit Text” dialog.

      • MSGNOTE - Creates an MSGBOX dialog using the note name as the title and note content as the text. For those who prefer message boxes to text windows.

      • NEWNOTE - Creates a new note using the “Edit Text” dialog.

      • RUNNOTE - Runs the macro code contained in the named note as per “OnNewMacro” and “OnOpenMacro” notes. An alternative to using macros or script files.

      • TEXNOTE - Same as the TEX command except it preloads the content of the named note in the “Edit Text” dialog to be placed on the map.


    • TXTWINCOLOR - I don’t like the “white on blue” color scheme of the text window. This command would let me set the foreground and background colors to any on the palette.

    • COPYWIZ - This command would create multilevel copies of the current map as per the last dialog of the “New Map Wizard”. This way one wouldn’t have to manually copy details of a building layout and its environs from one level to another. As a possible enhancement, instead of placing a list of map links on the maps taking up usable area, a context menu could be made that would be called from a clickable hotspot underneath (or possibly including) the level name. All files would be placed in the same directory as the current map by default unless otherwise directed.

    •  
      CommentAuthorMonsen
    • CommentTimeJan 21st 2019
     
    Some interesting suggestions there.


    Have you considered writing them yourself though? Writing XP's can be a bit arcane compared to many modern API's, but it is also a lot of fun. Not sure how easy the TXTWINCOLOR would be to implement by a third party without having support in the core code, but the rest of the commands should be implementable as an XP.
  2.  
    I really didn't think TXTWINCOLOR was doable (the colors just remind me of the BSoD) and most of the documentation on writing XPs seems rather out-of-date (back to CC2 for most of it). I'm not the programmer I used to be (I feel like a dinosaur at times to be honest) and writing macro code is about my speed these days (I've already written the data collection part of a COPYWIZ macro but I'm stuck on the map copying/altering part) but most of the recent new commands seem to be hooking onto existing features of the program. For example OPENNOTE basically emulates clicking the "Ok" button on the “Select Note” dialog (NOTES command). DELNOTE, EDITNOTE and NEWNOTE commands could be written similarly. These ideas inspired a 3 AM bout of insomnia so if they seem a bit out there, that's why.
    • CommentAuthorLoopysue
    • CommentTimeJan 22nd 2019
     
    Oh wow! Someone else who gets a bee in the bonnet that won't stop buzzing!

    Snap :D

    (only mine is usually about drawing something)
    • CommentAuthorbasilgass
    • CommentTimeMar 17th 2019
     
    Posted By: MonsenSome interesting suggestions there.


    Have you considered writing them yourself though? Writing XP's can be a bit arcane compared to many modern API's, but it is also a lot of fun. Not sure how easy the TXTWINCOLOR would be to implement by a third party without having support in the core code, but the rest of the commands should be implementable as an XP.


    I'm coding myself a little bit… and curious to know if I can do this. But I have two questions:

    1. I'm speaking french. "The commands should be implementable as an XP.". What does XP stand for ? I'm guessing your speaking about macros… but what does the term XP mean ?
    2. I checked a lot of tutorials (to learn the syntax and the various command), but can you point me to a tutorial or a reference where the creating of an UI dialog is explained ?
    • CommentAuthorbasilgass
    • CommentTimeMar 17th 2019
     
    Just found answer for:




    1. I'm speaking french. "The commands should be implementable as an XP.". What does XP stand for ? I'm guessing your speaking about macros… but what does the term XP mean ?


    It's a CC3 add-in ( https://cc3-developer.blogspot.com/search/label/Campaign%20Cartographer%203 )
    •  
      CommentAuthorMonsen
    • CommentTimeMar 17th 2019 edited
     
    Correct. XP's are very different from Macros. The latter is just about using the commands the program already give to you in an automated way, while an add-on (XP) is usually written in C++, compiled as a .dll and provide additional functionality and new commands to the program, like my tools here

    A graphical dialog needs to be implemented as an XP too. It can be implemented as a regular Windows SDK dialog if you know how to make those. There are other ways too, but that is the way I know.
    • CommentAuthorbasilgass
    • CommentTimeMar 18th 2019
     
    Thanks again for all your help.

    I'll check all this… and will try to make something!


    Posted By: Monsenwhile an add-on (XP) is usually written in CC3+

    I suppose sou mean in C++ ?

    Can I ask you in which application you're coding XPs ? I downloaded Visual Studio 2017 but wasn't yet able to include the fastCAD32 SDK...
    •  
      CommentAuthorMonsen
    • CommentTimeMar 18th 2019 edited
     
    Yea, I meant C++. And I use Visual Studio 2017. Using in the Enterprise edition myself, but the free Community edition should work just as well.

    To include the fastCad XP toolkit, edit your project properties and under the C/C++ --> general heading, add C:\FCWXP\xpdev; (change to fit your own directoriy paths obviously) to the beginning of the Additional Dependencies line.
    Then, in the Linker --> Input heading, add C:\fcwxp\xpdev\fcw32.lib; to the beginning of that Additional Dependencies line.

    That should be all that is required. Personally, I also like having it copy the output (.dll) file directly to my CC3+ installation directory and call CC3+ when debugging, instead of manually copying in the file each time, but that is not required to build a working setup.
  3.  
    The thing that worries me is that CC3+ is different from CC3 so the toolkits used to develop XPs (which stood for "eXternal Program" originally if anyone is interested) for it should be different as well. Also the last post on the CC3 Developer's Blog was on March 11, 2013 and talked about using Visual Studio Express 2010. Is there a more recent resource I can reference? (I would also like to see the source code for Monsen's tools since I'm sure it would be very educational. ;))
    • CommentAuthorjslayton
    • CommentTimeMar 18th 2019
     
    XPs written against the old SDK should still work with CC3+. They just won't have access to any ProFantasy-specific features.
    • CommentAuthorbasilgass
    • CommentTimeMar 18th 2019 edited
     
    This is where I came so far.

    1. Installed the English version of VS2017 :)

    2. Made the changes in the properties as suggested.

    3. Tried to compile the MYLINE (Complete example) from: https://cc3-developer.blogspot.com/search/label/XP%20development

      --> no luck :(

    4. Removed Precompiled Header (Not Using Precompiled Headers)

      --> no luck :(

    5. Downloaded VS2010 to use the corresponding toolkit and changed Platform Toolset to Visual Studio 2010 (v100)


    With the later, the file compiled correctly (no errors). I copied the DLL file into the CC3+ installation directory… .and... what's next ? The XP doesn't work. If I use MYLINE command, it says that it doesn't recognized it.

    Notice that I also tried your XP. I must do something wrong, because CC3+ doesn't recognize your XP too...
    •  
      CommentAuthorMonsen
    • CommentTimeMar 18th 2019
     
    You did copy the file into the installation directory and not the data directory, right?
    • CommentAuthorbasilgass
    • CommentTimeMar 19th 2019
     
    …well… How can I say this… Hurting my head on the desk a little dozen of times… Yep… copying the file in the correct folder helps a LOT !!! ( I was considering my data folder as my main folder)

    Now it's time to code something - or to try :)


    By the way, can you confirm that it's necessary to use the Visual Studio 2010 toolset ? Or is it possible to use the VS2017/Windows 10 toolset ?
    •  
      CommentAuthorMonsen
    • CommentTimeMar 19th 2019
     
    No need to use VS2010. I am using VS 2017 for my own development.
    • CommentAuthorbasilgass
    • CommentTimeMar 20th 2019
     
    Don't know what I'm doing wrong then. In the attached picture, I tried to compile using VS2017 Toolset. And it doesn't work (maybe a problem with the strings ?)

    But if I change the Platform Toolset to VS2010, it works correctly !



    And another question… In the GETA3RETCODE, I would like the function to return a value, so a MACRO code could get the answer of the ASK3BOX. Is there an example somewhere explaining how to "expose" the value ?
      2019-03-20_21-32-03.jpg
    •  
      CommentAuthorMonsen
    • CommentTimeMar 20th 2019
     
    Hit the C/C++ options, and under Language, set Conformance mode to No, that should probably fix that issue.

    Exposing a variable to a macro is done using
    SetVar(char *pLabel, char *pValue);
    • CommentAuthorbasilgass
    • CommentTimeMar 21st 2019 edited
     
    Thanks

    Posted By: MonsenHit the C/C++ options, and under Language, set Conformance mode to No, that should probably fix that issue.

    Thanks, this solves the problem!



    Posted By: MonsenExposing a variable to a macro is done using
    SetVar(char *pLabel, char *pValue);

    I have some logical problem here… I'm not sure to understand the way it should work.

    I have a XP that is (partial code):

    void XPCALL ASK3BOX(void)
    {
    int RETCODE;
    RETCODE = CancelBox("Questions which can by answer by YES, NO or CANCEL");

    char *RETVALUE("GETA3RETCODE");
    char *VALUE("0");

    SetVar(RETVALUE, VALUE);
    CmdEnd();
    }


    The first question is…. Should I have the SetVar in the same function than the one raising the Yes,No,Cancel dialog ?
    Or should I create a separate function for the return value, like this ?

    void XPCALL GETA3RETCODE(void) {
    char *RETVALUE("GETA3RETCODE");
    char *VALUE("0");

    SetVar(RETVALUE, VALUE);
    CmdEnd();
    }


    Finally… how do you get the returned value in the macro ? I tried Something like below, tried Calling GETA3RETCODE, etc...


    MACRO ASKTEST
    GV result ASK3BOX
    IFZ result resultY
    IFP result resultN
    IFN result resultC
    :resultY
    MSGBOX yes
    :resultN
    MSGBOX no
    :resultC
    MSGBOX cancel
    ENDM


    Also, I'm triying to convert the CancelBox returned value (int) to put it in the VALUE (char*)…


    Sorry to ask so many things… but there aren't a lot of example available (if no example).


    Again, thanks for all your help and patience :)

    Basil
    •  
      CommentAuthorMonsen
    • CommentTimeMar 21st 2019
     
    SetVar should be in the same function that calls the messagebox, doesn't make sense to call yet another command just to get the result.

    To use the value in the macro, just access the variable name you defined using setvar (the first parameter). That string will be a variable name you can access from the CC3+ macro.

    Converting an int to a char array can be done using for example sprintf
    • CommentAuthorbasilgass
    • CommentTimeMar 21st 2019 edited
     
    Posted By: MonsenConverting an int to a char array can be done using for examplesprintf


    I don't know what I did… because I think I tried this one a dozen of times…



    Posted By: MonsenSetVar should be in the same function that calls the messagebox, doesn't make sense to call yet another command just to get the result.

    This was also my guess… but as it wasn't working… I tried other approach.


    Concerning the macro, here is a little test. The value in the XP is GETA3RETCODE


    MACRO ASK3TEST
    ASK3BOX
    MSGBOX GETA3RETCODE
    ENDM


    But I received the attached error… And also, the dialog (Yes, No, Cancel) is launched twice…
      2019-03-21_19-57-41.jpg
    • CommentAuthorbasilgass
    • CommentTimeMar 21st 2019
     
    Also tried this:


    MACRO ASK3TEST
    ASK3BOX
    IFZ GETA3RETCODE yesno
    :yesno
    MSGBOX Success
    ENDM
    •  
      CommentAuthorMonsen
    • CommentTimeMar 21st 2019
     
    Don't use a macro to test commands before you know they are working as desired, it gets so much more complicated to know exactly when the error was thrown. Much better to use the command line manually, lets you handle the commands one by one.

    The error you got will (among other things) happen if you forget the CmdEnd() at the end of the command, so check that one.

    To check that the variable is actually set, you can issue the LISTVARS command.
    • CommentAuthorbasilgass
    • CommentTimeMar 22nd 2019
     
    If I run the script ASK3BOX, the dialog opens correctly.
    If I run LISTVARS, the GETA3RETCODE is displaying correctly.

    So I think the XP is working as intended.

    But the macro doesn't… And I have the error above…


    But if I use this extremely basic version, it is working.

    MACRO ASK3TEST
    ASK3BOX
    ENDM


    And LISTVARS displays the GETA3RETCODE value…

    So, I believe there is something wrong in my macro...
    •  
      CommentAuthorMonsen
    • CommentTimeMar 23rd 2019 edited
     
    No, the problem lies with your XP.

    The issue here is fastcad's way of retrieving command line data. Getting data from a command line is a bit more tricky than getting it from a dialog box (especially the fastcad model where some prompts can also be answered by a mouse click or have modifier keys, as opposed to a more "classic" command line where you just type a full command and have the program parse it only after you hit enter to submit the complete command line), and to get the command line to work properly, data input has a few special particularities.
    The result of this is that the data collection continues unhindered even when your dialog box displays. This causes the next command to error out and you get some weird consequences.
    This is basically the main reason that not all CC3+ commands can be used in a macro, even if they can be typed on the command line.

    To fix this, you need to do things the fastcad way. This is especially important for macro commands, if your dialog was intended to be a standalone command, just having it as it is would have worked.

    Here is some example code to how you could handle this

     1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    	FORMST(MyAPkt, "What do you say?\n\n"
    "Don't be afraid to pick one of the answers"
    )

    int ask = FormSt(&MyAPkt, RSC(FD_CancelBox));

    char buff[2];

    sprintf(buff, "%d", ask);

    SetVar("ASK", buff);

    CmdEnd();
    • CommentAuthorbasilgass
    • CommentTimeMar 23rd 2019
     
    Again, one million thanks !
    In fact, I wasn't using this:


    FORMST(MyAPkt, "What do you say?\n\n"
    "Don't be afraid to pick one of the answers"
    )
    int ask = FormSt(&MyAPkt, RSC(FD_CancelBox));


    But I used directly the function "CancelBox".


    Now, if I can ask you one last thing. Is it possible to pass a value the the XP function ? For example, the text display by the YES/NO/CANCEL dialog or even the dialog title ?
    •  
      CommentAuthorMonsen
    • CommentTimeMar 23rd 2019 edited
     
    Posted By: basilgassBut I used directly the function "CancelBox".
    Yea, that only calls the dialog, but isn't "macro safe". These things can get a bit tricky.



    Posted By: basilgassIs it possible to pass a value the the XP function ?
    You need to have the XP request the data, this is what all the commands that require parameters do.
    Here is an example (Demo() is the function called by the XP command, SayHello() is called from Demo())

     1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    char * name;

    void XPCALL SayHello(const int Result, int Result2, int Result3)
    {
    if (Result != X_OK) { CmdEnd(); return; }
    UNREFERENCED_PARAMETER(Result2);
    UNREFERENCED_PARAMETER(Result3);

    FORMSTPKT(MyFPkt, "Hi !01\nHave a Nice Day\0", 1)
    ITEMFMT(name, FT_Stg, FJ_Var, 0, 0)
    FORMSTEND

    FormSt(&MyFPkt, RSC(FD_MsgBox));
    CmdEnd();
    }

    void XPCALL Demo() {
    FORMST(lpszPrompt, "Your Name:\0")

    RDATA ScaleReq =
    { sizeof(RDATA), RD_TxWord, NULL, RDF_C, (DWORD*)& name,
    (DWORD*)& lpszPrompt,RDC_ARROW, SayHello, NULL, NULL, 0, NULL, 0 };

    ReqData(&ScaleReq);

    }


    ReqData requests data, and if the data is already available (for example specified in a parameter in a macro) it will use that, otherwise the user will see a prompt on the screen. (Or, if in a macro and it expects a parameter and it is missing, it will happily accept the command on the next line instead as the input, causing all kinds of errors)
    • CommentAuthorbasilgass
    • CommentTimeApr 2nd 2019
     
    Hi again! Sorry for taking so long to come back.

    I saw your new blog post. That's very nice !

    May I ask already Something here ?

    In the prompt you have shown (in the post above and I think in the blog post too), the request can only be one word.
    But I'm trying to make the ASK3BOX - which would request two things:

    1. A title (if this is possible).
    2. A sentence (with spaces) to make the question.

    Can you point me on how to do this ? Or will it be in the second post of your tutorial :) ?
    • CommentAuthorbasilgass
    • CommentTimeApr 2nd 2019
     
    Aslo… another question: there are a lot of things in what you described / made.
    Where did you learned them ? I tried to search in the Evolution Computing website (devs of FastCAD), but I can't get / find the documentation to make XPs.
    •  
      CommentAuthorMonsen
    • CommentTimeApr 2nd 2019
     
    I don't think you can set the title of those dialogs, at least I don't know the way.

    If you want full sentences, you need to specify in your data request that spaces are allowed as part of the data (RDF_SPACEOK):
    1
    2
    3
    	RDATA ScaleReq =
    { sizeof(RDATA), RD_TxWord, NULL, RDF_C+RDF_SPACEOK, (DWORD*)& name,
    (DWORD*)& lpszPrompt,RDC_ARROW, SayHello, NULL, NULL, 0, NULL, 0 };


    As for learning the stuff:
    - The documentation is included with the Xp toolkit. It is far from complete, but there are lots of stuff in it.
    - The .h files from the toolkit also contains lot of useful information
    - I have read Lee Saunders' old tutorials, some which are no more available unfortunately
    - And I ask people who knows more than me :)
    • CommentAuthorbasilgass
    • CommentTimeApr 3rd 2019
     
    Thanks for the reply!

    I had already identified RDF_SPACEOK, but didn't thought to 'add' it to RDF_C. Thanks :)
    •  
      CommentAuthorMonsen
    • CommentTimeApr 3rd 2019
     
    Instead of adding it, you could have used bitwise OR if you are more familiar with that syntax:
    RDF_C|RDF_SPACEOK
    • CommentAuthorjslayton
    • CommentTimeApr 3rd 2019
     
    To amplify a wee bit, ALWAYS use RDF_C as the starting point for those callback flags or you won't see the expected parameters in your callback function! The FastCAD default is to pass the parameters in registers, and RDF_C tells it to pass them on the stack as well to allow callbacks using the C calling convention.

    When it comes time to do more complicated routines (e.g. dynamic cursors), there are some support functions (e.g. GetDynCsrData() in __DYNCSR.H) that simplify things a little and ease the burden of trying to save all of the registers properly.
    • CommentAuthorbasilgass
    • CommentTimeApr 3rd 2019
     
    Posted By: MonsenInstead of adding it, you could have used bitwise OR if you are more familiar with that syntax:
    RDF_C|RDF_SPACEOK


    Yes, I'm more used with that syntax :)

    I think I'm done with the ASK3BOX script (dll and macro example). An idea how I can share it easily ? Keep it in this thread (as it started with this), create a new thread or ???



    Posted By: jslaytonTo amplify a wee bit, ALWAYS use RDF_C as the starting point for those callback flags or you won't see the expected parameters in your callback function! The FastCAD default is to pass the parameters in registers, and RDF_C tells it to pass them on the stack as well to allow callbacks using the C calling convention.

    Yes, I tried without it… and it makes CC3 crash! Thanks for the details !
    And I need to learn more before I start making more complicated routines…
    •  
      CommentAuthorMonsen
    • CommentTimeApr 3rd 2019
     
    If you want to share it, you can just zip it up and attach it to this thread. Or just share the source code as text instead if you prefer that.



    Posted By: basilgassAnd I need to learn more before I start making more complicated routines…
    Best way to learn is to experiment.
    • CommentAuthorbasilgass
    • CommentTimeApr 7th 2019 edited
     
    Here is the latest version in a zip file. Can you check it and tell me if it's working ?

    In the zip file, I added a read-me file. Is it clear enough ? As I'm usually speaking french, I'm open to any suggestions :)


    Also, do you know why I need to add TWO new lines for the macro to work correctly ?
    • CommentAuthorbasilgass
    • CommentTimeApr 7th 2019
     
    Macro example:



    MACRO ASK3EXAMPLE
    ASK3BOX Ask your question here which can be canceled or answered by YES or NO!


    IFZ GETA3 gozero
    IFP GETA3 gopos
    IFN GETA3 goneg
    GOTO endif
    :gozero
    MSGBOX
    Result
    You have clicked NO

    GOTO endif
    :goneg
    MSGBOX
    Result
    You have clicked CANCEL

    GOTO endif
    :gopos
    MSGBOX
    Result
    You have clicked YES

    GOTO endif
    :endif
    ENDM
    •  
      CommentAuthorMonsen
    • CommentTimeApr 7th 2019
     
    Posted By: basilgassHere is the latest version in a zip file. Can you check it and tell me if it's working ?
    I thionk this file is a debug build and not a release build. It would only work on my developer install where I have the debug libraries installed. You should make a Release build for general use.


    Posted By: basilgassAlso, do you know why I need to add TWO new lines for the macro to work correctly ?
    You shouldn't use any. That first blank line after the command causes the command to be activated again, while that second blank line then submits a blank line of input to the second instance, which basically cancels the command.
    • CommentAuthorbasilgass
    • CommentTimeApr 8th 2019
     
    I tried to make a release build. But it raised an error.

    I need to find what's going on… I think I need to 'configure' the release build properties. Is there a way to copy the properties from the Debug build to the Release build ?
    •  
      CommentAuthorMonsen
    • CommentTimeApr 8th 2019
     
    You wouldn't want to do that, that would basically turn the release build into a debug build, it is the project properties that controls those things.

    Normally, I would just set both at the same time when initially setting them, but just check the properties listed in the table in my article.
    • CommentAuthorbasilgass
    • CommentTimeApr 8th 2019
     
    That's exactly what I did :) Just took the time to re-read your excellent article and set the properties. In fact, I missed one configuration in the language part… And I think it's now working :)

    Can you tell me if it's look ok for you ?
    • CommentAuthorbasilgass
    • CommentTimeApr 8th 2019
     
    And the macro. As always ( :) ), you're right. There's no need to add two blank spaces !


    MACRO ASK3EXAMPLE
    ASK3BOX Ask your question here which can be canceled or answered by YES or NO!
    IFZ GETA3 gozero
    IFP GETA3 gopos
    IFN GETA3 goneg
    GOTO endif
    :gozero
    MSGBOX
    Result
    You have clicked NO

    GOTO endif
    :goneg
    MSGBOX
    Result
    You have clicked CANCEL

    GOTO endif
    :gopos
    MSGBOX
    Result
    You have clicked YES

    GOTO endif
    :endif
    ENDM
    •  
      CommentAuthorMonsen
    • CommentTimeApr 8th 2019
     
    Still won't run. I think you packed the wrong file though, checking the checksum, I see that it is exactly the same file as was present in your previous .zip.
    • CommentAuthorbasilgass
    • CommentTimeApr 9th 2019
     
    Seems like I should sleep a little bit more :)

    Is this one better ?
    •  
      CommentAuthorMonsen
    • CommentTimeApr 9th 2019
     
    Yep, seems to work now.
    • CommentAuthorbasilgass
    • CommentTimeApr 9th 2019
     
    Thanks Monsen :)