BIM Coordinator Program (INT) April 22, 2024
Find the next step in your career as a Graphisoft Certified BIM Coordinator!
Archicad C++ API
About Archicad add-on development using the C++ API.

Cancel the open

MudratDetector
Enthusiast

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:

MudratDetector_2-1655824847209.png

 

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:

MudratDetector_0-1655824202280.png

 

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

Chris Gilmer
Intel i9-12950HX CPU @ 2.30GHz, 16 cores
NVIDIA GeForce RTX 3080
48.0 GB RAM
Windows 10 Pro 64-bit
5 REPLIES 5
zinkh
Contributor

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.

 

 

Hi Chris,

 

There are two automation functions which might do what you want:

APIDo_OpenID

APIDo_NewProjectID

 

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

Bernd Schwarzenbacher - Archicad Add-On Developer - Get Add-Ons & Archicad Tips on my Website: Archi-XT.com
MudratDetector
Enthusiast

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

Chris Gilmer
Intel i9-12950HX CPU @ 2.30GHz, 16 cores
NVIDIA GeForce RTX 3080
48.0 GB RAM
Windows 10 Pro 64-bit

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;
}

 

 

 

Chris Gilmer
Intel i9-12950HX CPU @ 2.30GHz, 16 cores
NVIDIA GeForce RTX 3080
48.0 GB RAM
Windows 10 Pro 64-bit

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

Bernd Schwarzenbacher - Archicad Add-On Developer - Get Add-Ons & Archicad Tips on my Website: Archi-XT.com
Learn and get certified!