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.
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…
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
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.
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 ?
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
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
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.
The next step is using the MSGBOX/ASKBOX syntax to show a dialog title and a multiline message ("sTitle;sText1;…;sTextN") that would be terminated by a blank line. Mind you, seeing the complete source code for ASK3BOX would probably be very educational. Strange how this discussion veered from being a general wishlist of commands to a discussion of how to create ONE them. (I don't mind; this is probably more useful than anything I could come up with.) What I wouldn't mind seeing is some new macro commands that could extract specific values from the system or individual entities and assign them to variables for testing. (There are a few, but not many.)
I'll post the DLL source code tomorrow To do what your're asking, I think the DLL should use 'custom dialog', like TkInter or wxWidget. But I don't know if they are supported in CC3+. Maybe Monsen could answer...
I haven't seen this discussed in the thread, but you should probably not use Unicode in the project description because FastCAD/CC3+ are ASCII-based rather than UTF-16. UTF-8 (Multi-Byte character set in the project description) is ASCII-compatible, which will simplify things a good bit. Getting the right character set is especially important when mixing Windows calls with FastCAD/CC3+ calls.
The errors about wchar_t* not being compatible with char* are likely caused by using Unicode rather than MBCS in the project settings.
You can use any framework that you want with XPs. However, you'll need to include the appropriate runtime with your XP. Most of the existing XPs use the FastCAD dialog facilities or raw Windows SDK calls. The effects are mostly using MFC dialogs, showing that the underlying system doesn't care what you use as long as you adhere to the C interface specification.
Thanks for this. I never thought about that setting at all. For me it seems to use MBCS by default though (the setting is blank, but manually changing it to MBSC produce no difference), but setting it to Unicode instead certainly produces all kinds of errors, none of which are really helpful unless you already knew this.
Thank you. As I said before, "The next step is using the MSGBOX/ASKBOX syntax to show a dialog title and a multiline message ("sTitle;sText1;…;sTextN") that would be terminated by a blank line. " I suspect that trick requires a loop that reads one line at a time until an empty one is encountered and three buffer strings; one used for reading each line of input, one for the dialog title (the first line of input which would be displayed differently on the dialog) and one for the dialog body (the remaining lines concatenated with line breaks). Not sure what the size of the character string buffers should be or how they can be passed to the dialog and formatted differently.
Unfortunately, you'll have to do without setting titles on the dialogs.
While you can technically use any kinds of dialogs in an XP, they are not macro safe, and the two built-in commands that create dialogs with titles (MSGBOX/ASKBOX) have access to deeper functionality in the CC3+ that is not exposed through the XP toolkit, so it is not possible to recreate these yourself in an XP. Collecting multiple lines of text and concatenate that for the final text in the dialog is trivial though. It won't be a loop, because a data request redirects to a new method, but it can redirect to itself, and then just use the Result variable to check if valid input was received (if so, keep the data received, and then make a new identical request, recursion basically), or not (continue on with displaying the dialog).
For any dialog NOT needing to be macro safe, you can accomplish just about whatever you want though, the main issue happens when you need to use your command as part of a macro.
Comments
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.
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 ???
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…
Best way to learn is to experiment.
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 ?
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
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.
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 ?
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.
Can you tell me if it's look ok for you ?
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
Is this one better ?
MSGBOX/ASKBOX
syntax to show a dialog title and a multiline message ("sTitle;sText1;…;sTextN
") that would be terminated by a blank line. Mind you, seeing the complete source code forASK3BOX
would probably be very educational. Strange how this discussion veered from being a general wishlist of commands to a discussion of how to create ONE them. (I don't mind; this is probably more useful than anything I could come up with.) What I wouldn't mind seeing is some new macro commands that could extract specific values from the system or individual entities and assign them to variables for testing. (There are a few, but not many.)To do what your're asking, I think the DLL should use 'custom dialog', like TkInter or wxWidget. But I don't know if they are supported in CC3+. Maybe Monsen could answer...
The errors about wchar_t* not being compatible with char* are likely caused by using Unicode rather than MBCS in the project settings.
You can use any framework that you want with XPs. However, you'll need to include the appropriate runtime with your XP. Most of the existing XPs use the FastCAD dialog facilities or raw Windows SDK calls. The effects are mostly using MFC dialogs, showing that the underlying system doesn't care what you use as long as you adhere to the C interface specification.
So here is the code (just copied/pasted from Visual Studio).
//////////////////////////////////////////////////////////////////////////// // // Written by: Basil Gass // Date: 03/20/20119 // Free to use and modify - just don't say you did it alone ! // XPNAME -> Change to real XP name !$(OutDir)$(TargetName)$(TargetExt) // $(SolutionDir)$(Configuration)\ // //////////////////////////////////////////////////////////////////////////// #include #include extern "C" { #include #include } #define XPID 0xF000 void XPCALL About(void); void XPCALL ASK3BOX(void); char CList[] = "ASK3BOX\0"; PCMDPROC PList[] = { About, ASK3BOX }; XP MyXP = { 0, CList, PList, 0, 0, 0, XPID, 0, 500, 0, 0, 500 }; //////////////////////////////////////////////////////////////////////////// void XPCALL About(void) { InfoBox("AskBox with YES, NO and CANCEL\nMacro command: ASK3BOX\nReturn value: GETA3\n\nCreated by Basil Gass (with the help of Monsen)"); } char * name; void XPCALL ASK3BOX_DLG(const int Result, int Result2, int Result3) { if (Result != X_OK) { CmdEnd(); return; } UNREFERENCED_PARAMETER(Result2); UNREFERENCED_PARAMETER(Result3); FORMSTPKT(MyFPkt, "!01\0", 1) ITEMFMT(name, FT_Stg, FJ_Var, 0, 0) FORMSTEND //FORMST(MyAPkt, "YES, NO, CANCEL QUESTION") int ask = FormSt(&MyFPkt, RSC(FD_CancelBox)); if (ask == 6) { SetVar("GETA3", "1"); } else if (ask == 7) { SetVar("GETA3", "0"); } else { SetVar("GETA3", "-1"); } CmdEnd(); } void XPCALL ASK3BOX() { FORMST(lpszPrompt, "Enter text to be display\nthe ASK3BOX message:\n\0"); RDATA ScaleReq = { sizeof(RDATA), RD_TxWord, NULL, RDF_C+RDF_SPACEOK, (DWORD*)& name, (DWORD*)& lpszPrompt, RDC_ARROW, ASK3BOX_DLG, NULL, NULL, 0, NULL, 0}; ReqData(&ScaleReq); } ////////////////// DllMain - XP initialization & Unload code /////////// BOOL WINAPI DllMain(HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: { MyXP.ModHdl = hDLL; XPRegCmd(&MyXP); break; } case DLL_PROCESS_DETACH: { XPUnregCmd(&MyXP); break; } } return TRUE; } ////////////////////////////////////////////////////////////////////////////
MSGBOX/ASKBOX
syntax to show a dialog title and a multiline message ("sTitle;sText1;…;sTextN
") that would be terminated by a blank line. " I suspect that trick requires a loop that reads one line at a time until an empty one is encountered and three buffer strings; one used for reading each line of input, one for the dialog title (the first line of input which would be displayed differently on the dialog) and one for the dialog body (the remaining lines concatenated with line breaks). Not sure what the size of the character string buffers should be or how they can be passed to the dialog and formatted differently.While you can technically use any kinds of dialogs in an XP, they are not macro safe, and the two built-in commands that create dialogs with titles (MSGBOX/ASKBOX) have access to deeper functionality in the CC3+ that is not exposed through the XP toolkit, so it is not possible to recreate these yourself in an XP.
Collecting multiple lines of text and concatenate that for the final text in the dialog is trivial though. It won't be a loop, because a data request redirects to a new method, but it can redirect to itself, and then just use the Result variable to check if valid input was received (if so, keep the data received, and then make a new identical request, recursion basically), or not (continue on with displaying the dialog).
For any dialog NOT needing to be macro safe, you can accomplish just about whatever you want though, the main issue happens when you need to use your command as part of a macro.