We value your input!
Please participate in Archicad 28 Home Screen and Tooltips/Quick Tutorials survey

Archicad C++ API
About Archicad add-on development using the C++ API.
SOLVED!

APIAny_ChangeAParameterID

poco2013
Mentor
Need some help in changing a STRING parameter in a Library Part. I have looked at several examples and they all only show modifying a float parameter. The problem I'm having is getting the API_​ChangeParamType GS::uchar_t *uStrValue attribute to point to the change string. My code is below. I can not get the correct format for ucscpy below . Please help. I know that I do not fully understand the conversions in Archicad between, ASCII, utf-16 , UTF-8 & UniStings usage, but need some help getting over the hump and started??

// change params here
						GS::UniString newtxt("XXX");
						API_ChangeParamType chgParam;
						API_ParamOwnerType     paramOwner;
						API_GetParamsType    getParams;
						
						BNZeroMemory(&chgParam, sizeof(API_ChangeParamType));
						BNZeroMemory(&paramOwner, sizeof(API_ParamOwnerType));
						BNZeroMemory(&getParams, sizeof(API_GetParamsType));

						paramOwner.libInd = libIndex;
						paramOwner.typeID = API_ObjectID;      /* object element */
						paramOwner.guid = APINULLGuid;
						
						ACAPI_Goodies(APIAny_OpenParametersID, &paramOwner,nullptr);
						err = ACAPI_Goodies(APIAny_GetActParametersID, &getParams, nullptr);
						if(err == NoError){ 
						     chgParam.index = libIndex;
						     CHCopyC("txt", chgParam.name);

						     GS::ucscpy(chgParam.uStrValue.uStr, newtxt.ToUStr()); //exception here
                                                 /*
						 chgParam is incorrect -- getting message error "left of uStr must have       class/struct/union" - I have changed ucsscpy all different ways and can't get it right.
                                                    */
						      err = ACAPI_Goodies(APIAny_ChangeAParameterID, &chgParam,nullptr);
						}
						ACAPI_Goodies(APIAny_CloseParametersID,nullptr,nullptr);
							if (err)
								ACAPI_WriteReport("busted",true);
EDIT:: found the answer here -- viewtopic.php?f=23&t=68038 Thanks Tibor However, using above with correction - still can't get string parameter to change?? Add-On runs with no errors but no change now.
Gerry

Windows 11 - Visual Studio 2022; ArchiCAD 27
1 ACCEPTED SOLUTION

Accepted Solutions
Solution
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
APIAny_ChangeAParameterID changes the parameters value only in the API_GetParamsType object in the memory. It does not changes any element or libpart in the project directly.
You have to do something with the changed params handle to notify any change after the operation.
{
	API_GetParamsType theParams = {};
	API_ParamOwnerType paramOwner = {};
	GS::uchar_t uStrBuffer[BUFFER_SIZE];

	paramOwner.typeID = API_ObjectID;
	paramOwner.libInd = libPartIndex;

	GSErrCode err = ACAPI_Goodies (APIAny_OpenParametersID, &paramOwner);
	err |= ACAPI_Goodies (APIAny_GetActParametersID, &theParams);
	if (err == NoError) {
		API_ChangeParamType changeParam = {};

		CHTruncate (paramName, changeParam.name, API_NameLen);
		GS::ucsncpy (uStrBuffer, newStrValue.ToUStr ().Get (), BUFFER_SIZE);
		changeParam.uStrValue = uStrBuffer;

		err = ACAPI_Goodies (APIAny_ChangeAParameterID, &changeParam);
		if (err == NoError) {
			// Do something with theParams.params
		}
	}

	ACAPI_DisposeAddParHdl (&theParams.params);
	ACAPI_Goodies (APIAny_CloseParametersID);
}
I'm here to help, but at first I have to know what's your purpose...
Do you want to change the parameter value in a placed element instance of the library part? If the answer is yes, then use this code instead of the "// Do something with theParams.params" comment:
API_ElementMemo memo = {};
memo.params = theParams.params;

API_Element	mask;
ACAPI_ELEMENT_MASK_CLEAR (mask);

API_Element	elem = {};
elem.header.guid = elemGuid;
ACAPI_Element_Get (&elem);

err = ACAPI_Element_Change (&elem, &mask, &memo, APIMemoMask_AddPars, true);
Or you would like to change the default value of the parameter in a library part? To achieve that, you have to overwrite the library part in the library.

View solution in original post

2 REPLIES 2
Solution
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
APIAny_ChangeAParameterID changes the parameters value only in the API_GetParamsType object in the memory. It does not changes any element or libpart in the project directly.
You have to do something with the changed params handle to notify any change after the operation.
{
	API_GetParamsType theParams = {};
	API_ParamOwnerType paramOwner = {};
	GS::uchar_t uStrBuffer[BUFFER_SIZE];

	paramOwner.typeID = API_ObjectID;
	paramOwner.libInd = libPartIndex;

	GSErrCode err = ACAPI_Goodies (APIAny_OpenParametersID, &paramOwner);
	err |= ACAPI_Goodies (APIAny_GetActParametersID, &theParams);
	if (err == NoError) {
		API_ChangeParamType changeParam = {};

		CHTruncate (paramName, changeParam.name, API_NameLen);
		GS::ucsncpy (uStrBuffer, newStrValue.ToUStr ().Get (), BUFFER_SIZE);
		changeParam.uStrValue = uStrBuffer;

		err = ACAPI_Goodies (APIAny_ChangeAParameterID, &changeParam);
		if (err == NoError) {
			// Do something with theParams.params
		}
	}

	ACAPI_DisposeAddParHdl (&theParams.params);
	ACAPI_Goodies (APIAny_CloseParametersID);
}
I'm here to help, but at first I have to know what's your purpose...
Do you want to change the parameter value in a placed element instance of the library part? If the answer is yes, then use this code instead of the "// Do something with theParams.params" comment:
API_ElementMemo memo = {};
memo.params = theParams.params;

API_Element	mask;
ACAPI_ELEMENT_MASK_CLEAR (mask);

API_Element	elem = {};
elem.header.guid = elemGuid;
ACAPI_Element_Get (&elem);

err = ACAPI_Element_Change (&elem, &mask, &memo, APIMemoMask_AddPars, true);
Or you would like to change the default value of the parameter in a library part? To achieve that, you have to overwrite the library part in the library.
poco2013
Mentor
Thanks Tibor:

I got it to work now. The confusion was basically that i did not understand how Archicad's API called and created elements.

I just wanted to insert a Library part with mostly the same defaults but to change some key parameters. i did not want change the defaults. Basically reusing a base Lib Part over and over to do different things depending on a few user input param changes from another function.

I did not realize that i did not need to use Change_Parameters at all (since the changes were only used for the current object) but just change the Library part params directly in the element create function after I retrieved the params list with GetParameters for the utility Lib Part.

Sorry for the trouble but your above input helps explain things better for me. I copied it for future reference

Thanks again..
Gerry

Windows 11 - Visual Studio 2022; ArchiCAD 27