2022-06-21 05:26 PM - edited 2022-06-21 10:02 PM
Archicad 23 | Win 10
I am trying to solve a problem of our users opening .bpn files from the recent files list instead of the corresponding .pln file. I have a couple of things in place - one of which reads, at opening, the value of the "FILENAME" parameter from Project Info... and determines if the file is a .bpn file. I do that with ACAPI_Notify_CatchProjectEvent and APINotify_Open in the Initialize() function of the menu load and catch the file extension prior to anything being loaded in the drawing editor. A user defined function is called to determine the file extension and displays a warning dialog. I do that with this code in the function:
If a .bpn file is detected, a dialog appears with a warning and the opening of the model stops. The warning dialog will eventually become a much more severe version of this:
I would like to cancel the opening of the .bpn model completely, once the user presses 'OK' and not have to depend on the user reading or following directions.
I have searched high and low without success. Can someone point me in the right direction to programmatically cancel [File > Open] ? Or maybe execute [File > Open] to a new, blank file? Is it possible at this particular stage in the open?
thx - chris
2022-06-21 11:13 PM
This is so important it should be integrated to Archicad. How many times I worked on files for hours, just to see that colleagues made changes on the bpn instead of the plan.
2022-06-22 09:33 AM
Hi Chris,
There are two automation functions which might do what you want:
There's also APIDo_CloseID, but it has a note that it's not for public usage. So I assume it might not work for us as an external developer.
Unfortunately I don't have time right now to test them properly and check if they work in your situation as well. But please report back if they work or if there are any issues, so maybe we can help further with that additional information.
Best,
Bernd
2022-06-22 06:29 PM - edited 2022-06-22 06:33 PM
Hello again Bernd!
I was starting to look in to the APIDo_OpenID() function yesterday evening. I was looking at the APIDo_CloseID() function also. I had not stumbled on to the APIDo_NewProjectID() function yet.
I did find this:
https://community.Graphisoft.com/t5/Developer-forum/How-to-close-Archicad-file/m-p/132746
I will report back here on how any of this works out.
Thanks - chris
2022-06-23 06:28 PM - edited 2022-06-23 06:34 PM
It is not doable with APIDo_OpenID in the specific needs of my situation.
https://community.Graphisoft.com/t5/Developer-forum/ACAPI-Automate-OpenID/m-p/218492
The same rules apply for APIDo_NewProjectID. The search continues...
You can follow my chain reaction from the initial call of ACAPI_Notify_CatchProjectEvent to APIDo_OpenID here:
// -----------------------------------------------------------------------------
// Initialize
// Called after the Add-On has been loaded into memory
// ACAPI_Notify_CatchProjectEvent monitors for APINotify_Open
// and runs JHP_EventHandler on detection
// -----------------------------------------------------------------------------
GSErrCode __ACENV_CALL Initialize (void)
{
GSErrCode err = ACAPI_Install_MenuHandler (JHP_AUTOLOAD_MENU_STRINGSID, MenuCommandHandler);
err = ACAPI_Notify_CatchProjectEvent(APINotify_Open, JHP_EventHandler);
return err;
}
// Initialize
// -----------------------------------------------------------------------------
// JHP_EventHandler
// Called with ACAPI_Notify_CatchProjectEvent by APINotify_Open event.
// When APINotify_Open is detected, GetProjectInfo() is run
// -----------------------------------------------------------------------------
static GSErrCode __ACENV_CALL JHP_EventHandler(API_NotifyEventID notifID, Int32 /*param*/)
{
GSErrCode err = NoError;
switch (notifID) {
case APINotify_Open:
{
GetProjectInfo();
break;
}
// case APINotify_Close:
// {
// break;
// }
// case APINotify_Quit:
// {
// break;
// }
//
default: break;
}
return err;
}
//------------------------------------------------------
// Project events handler function
// GetProjectInfo
// Called by JHP_EventHandler
// Attempts to open corresponding .pln file with APIDo_OpenID
//------------------------------------------------------
int GetProjectInfo()
{
char** autoTextIdKeys;
char** autoTextIdValues;
GSErrCode err = ACAPI_Goodies(APIAny_GetAutoTextKeysID, &autoTextIdKeys, &autoTextIdValues);
if (err == NoError)
{
Int32 count = BMGetPtrSize(reinterpret_cast<GSPtr>(autoTextIdKeys)) / sizeof(char*);
for (Int32 i = 0; i < count; i++)
{
if (autoTextIdKeys[i] == nullptr)
{
BMKillPtr(&autoTextIdValues[i]);
continue;
}
GS::UniString strKey = GS::UniString(autoTextIdKeys[i]);
GS::UniString strValue = GS::UniString(autoTextIdValues[i]);
////
//// Check "FILENAME" for .bpn extension.
////
if (strKey == "FILEPATH")
{
if (strValue.EndsWith(".bpn"))
{
ACAPI_WriteReport(GS::UniString("The file you have opened ends with .bpn\n\nThis is a backup version of your project and is NOT your working file."), true);
API_FileOpenPars openPars;
BNZeroMemory(&openPars, sizeof(API_FileOpenPars));
GS::UniString strPlnPath = strValue.GetSubstring(0,(strValue.FindLast("\\") + 1));
GS::UniString strPlnFile = strValue.GetSubstring((strValue.FindLast("\\") + 1),((strValue.GetLength() - strValue.FindLast("\\")) - 5)) + ".pln";
ACAPI_WriteReport(strPlnPath + strPlnFile, true);
IO::Location strLocation(strPlnPath);;
//API_SpecFolderID specID = API_ApplicationFolderID;
//ACAPI_Environment(APIEnv_GetSpecFolderID, &specID, &strLocation);
//strLocation.AppendToLocal("Archicad Examples");
//strLocation.AppendToLocal("Residential House");
openPars.file = new IO::Location(strLocation, IO::Name(strPlnFile.ToCStr()));
GSErrCode err = ACAPI_Automate(APIDo_OpenID, &openPars, nullptr);
if (err != NoError)
ACAPI_WriteReport("Cannot open\n\n" + strPlnPath + strPlnFile, true);
delete openPars.file;
}
}
BMKillPtr(&autoTextIdKeys[i]);
BMKillPtr(&autoTextIdValues[i]);
}
}
BMKillPtr(reinterpret_cast<GSPtr*>(&autoTextIdKeys));
BMKillPtr(reinterpret_cast<GSPtr*>(&autoTextIdValues));
return err;
}
2022-06-27 01:26 PM
Hi Chris,
that's unfortunate. I wasn't aware about the restriction regarding the Notification scope. Unfortunately I can't think of another solution via the Archicad API.
Maybe a workaround via a AHK, AutoIt or some other Windows GUI automatisation could work. With those you could maybe detect the dialog and a .bpn string and auto stop the loading of a bpn file.
Best,
Bernd