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.

User Control

poco2013
Mentor
As a newbie to the API, I am still wading through the documentation. Was wondering if anyone has any info on User Control Number 262. I think something to do with color.

I can't find anything in the documentation although it may be buried deep. The header file does not give much info either, other than a couple options - not described. I can't get this control to execute so I can't verify. Although I really have no idea as to what options to use or the tool size requirements.

Archicad 18
Gerry

Windows 11 - Visual Studio 2022; ArchiCAD 27
4 REPLIES 4
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
Hi,

You can see one UC262 item in the Document -> Pen Sets -> Pens&Colors dialog at the bottom. It has cells, ideal to show pens.

I wrote you an example code to try it:

The dialog resource:
'GDLG'  32590  Modal                0    0  327  278  "Pen User Control" {
/* [  1] */ Button				  250    9   61   20	LargePlain  "Close"
/* [  2] */ UserControl			    0   65  327  214	262  0  0  0  0  0 /* Pen */
/* [  3] */ LeftText			   16    9   30   20	LargePlain  vCenter  StaticEdge  ""
/* [  4] */ RightText			   50   11   74   16	LargePlain  vCenter  "Pen Weight:"
/* [  5] */ RealEdit			  129    7   66   24	LargePlain  "0.0"  "100.0"
/* [  6] */ LeftText			  201    2   20   14	SmallPlain  vBottom  "mm"
/* [  7] */ UserControl			  201   17   12   12	257  0x0005  0x0600  0 /*Change mm/Pt*/
/* [  8] */ RightText			   13   41  110   16	LargePlain  vCenter  "Description:"
/* [  9] */ TextEdit			  129   37  182   24	LargePlain  255
}


'DLGH'  32590  DLG_32590_Pen_User_Control {
1	""							Button_0
2	""							UC262_0
3	""							LeftText_0
4	""							RightText_0
5	""							RealEdit_0
6	""							LeftText_1
7	""							UC257_0
8	""							RightText_1
9	""							TextEdit_0
}
The header file:
// *********************************************************************************************************************
// API Development Kit 18; Mac/Win
//
// Namespaces:        Contact person:
//     -None-						LT
//
// [SG compatible] - Yes
// *********************************************************************************************************************

#ifndef USERCONTROLSDIALOG_HPP
#define USERCONTROLSDIALOG_HPP

#pragma once


// --- Includes --------------------------------------------------------------------------------------------------------

#include	"DG.h"
#include	"UC.h"
#include	"DGModule.hpp"
#include	"UCModule.hpp"
#include	"Array.hpp"


#define USER_CONTROLS_DIALOG_RESID			32590


// --- PenSettingsEditPensPage -----------------------------------------------------------------------------------------

class PenSettingsEditPensPage: public DG::ModalDialog
{
friend class PenSettingsEditPensObserver;

public:
	enum PenWeightUnit {
		NotDefined			= 0,
		PenWeight_MM		= 1,
		PenWeight_Pt		= 2
	};

private:
	enum {
		OkButtonId				= 1,
		PenControlId			= 2,
		PenNumberStaticId		= 3,
		PenWidthStaticId		= 4,
		PenWidthEditId			= 5,
		UnitStaticId			= 6,
		UnitControlId			= 7,
		DescriptionStaticId		= 8,
		PenNameEditId			= 9
	};

	DG::Button			okButton;
	UC::UC262			penControl;
	DG::LeftText		penNumberStatic;
	DG::RightText		penWidthStatic;
	DG::RealEdit		penWidthEdit;
	DG::LeftText		unitStatic;
	UC::UC257			unitControl;
	DG::RightText		descriptionStatic;
	DG::TextEdit		penNameEdit;

	API_Attribute		penAttr;
	PenWeightUnit		penWeightUnit;

	PenWeightUnit		GetPenWeightUnit ();

	void		InitializeUnitMenu (void);
	void		HandleUnitControlChange (Int32 selectedUnit);
	void		UpdatePenControl (void);

public:
	PenSettingsEditPensPage (GSResModule dialResModule, short resId);
   ~PenSettingsEditPensPage ();
};


// --- PenSettingsEditPensObserver -------------------------------------------------------------------------------------

class PenSettingsEditPensObserver:	public DG::PanelObserver,
									public DG::UserControlObserver,
									public DG::ButtonItemObserver,
									public DG::CompoundItemObserver
{
private:
	PenSettingsEditPensPage* dialog;

protected:

	virtual void	PanelOpened (const DG::PanelOpenEvent& ev);

	virtual void	ButtonClicked (const DG::ButtonClickEvent& ev);
	virtual void	UserControlChanged (const DG::UserControlChangeEvent& ev);

public:
	explicit	PenSettingsEditPensObserver (PenSettingsEditPensPage* penSettingsEditPensPage);
			   ~PenSettingsEditPensObserver ();
};

#endif
The source:
// *********************************************************************************************************************
// API Development Kit 18; Mac/Win
//
// Namespaces:			Contact person:
//		-None-						LT
//
// [SG compatible] - Yes
// *********************************************************************************************************************

#include	"APIEnvir.h"
#include	"ACAPinc.h"					// also includes APIdefs.h
#include	"GSUtilsDefs.h"

#include	"UserControlsDialog.hpp"


//--------------------------- Attribute_Get helper function -----------------------

GSErrCode Attribute_Get (API_Attribute* attr, const API_AttrTypeID& typeID, const short index)
{
	GSErrCode err = NoError;
	BNZeroMemory (attr, sizeof (API_Attribute));
	attr->header.typeID = typeID;
	attr->header.index = index;
	// search by type and index
	err = ACAPI_Attribute_Get (attr);
	if (err != NoError)
		ACAPI_WriteReport ("ACAPI_Attribute_Get failed", true);
	return err;
}


// --- PenSettingsEditPensPage -----------------------------------------------------------------------------------------

PenSettingsEditPensPage::PenSettingsEditPensPage (GSResModule dialResModule, short resId):
	DG::ModalDialog		(dialResModule, resId, dialResModule),

	okButton			(GetReference (), OkButtonId),
	penControl			(GetReference (), PenControlId),
	penNumberStatic		(GetReference (), PenNumberStaticId),
	penWidthStatic		(GetReference (), PenWidthStaticId),
	penWidthEdit		(GetReference (), PenWidthEditId),
	unitStatic			(GetReference (), UnitStaticId),
	unitControl			(GetReference (), UnitControlId),
	descriptionStatic	(GetReference (), DescriptionStaticId),
	penNameEdit			(GetReference (), PenNameEditId),

	penWeightUnit (PenSettingsEditPensPage::NotDefined)
{
	// unit control
	InitializeUnitMenu ();

	penWidthEdit.Disable ();
	penNameEdit.Disable ();
	okButton.SetAsDefault ();

	// Length type units
	penWeightUnit = GetPenWeightUnit ();
}


PenSettingsEditPensPage::~PenSettingsEditPensPage ()
{
}


// ... Private functions of the page ...................................................................................

PenSettingsEditPensPage::PenWeightUnit PenSettingsEditPensPage::GetPenWeightUnit ()
{
	if (penWeightUnit == PenSettingsEditPensPage::NotDefined) {
		DGUnitData	dgUnit;
		DG::GetUnit (&dgUnit);
		if (dgUnit.lengthType == DG_UNIT_FOOT_DECINCH || dgUnit.lengthType == DG_UNIT_FOOT_INCH ||
			dgUnit.lengthType == DG_UNIT_DECINCH      || dgUnit.lengthType == DG_UNIT_DECFOOT   ||
			dgUnit.lengthType == DG_UNIT_INCH)
		{
			penWeightUnit = PenSettingsEditPensPage::PenWeight_Pt;
		} else {
			penWeightUnit = PenSettingsEditPensPage::PenWeight_MM;
		}
	}

	return penWeightUnit;
}


void	PenSettingsEditPensPage::InitializeUnitMenu (void)
{
	short nCells = 2;
	GSSize dataSize = UC257DataSize (nCells);
	GSHandle cntlData = BMAllocateHandle (dataSize, ALLOCATE_CLEAR, 0);
	if (DBERROR (cntlData == NULL))
		return;

	BMhLock (cntlData);
	UC257HeadData*	header = reinterpret_cast<UC257HeadData*> (*cntlData);

	header->minWidth = 50;
	header->nColumns = 1;
	header->nCells = nCells;

	UC257CellData* cell = &header->cell[0];

	GS::UniString text = "mm";
	GS::snuprintf (cell[0].text, sizeof (cell[0].text), text.ToUStr ());
	cell[0].value = 1;
	cell[0].flags = CF257_VALID | CF257_SHOWTEXT;

	text = "Pt";
	GS::snuprintf (cell[1].text, sizeof (cell[1].text), text.ToUStr ());
	cell[1].value = 2;
	cell[1].flags = CF257_VALID | CF257_SHOWTEXT;

	unitControl.SetCallBack (NULL);

	unitControl.SetControlType (UC::UC257::Text);
	unitControl.SetButtonType (UC::UC257::SmallButton);
	unitControl.SetPaletteType (UC::UC257::PlainPalette);
	unitControl.SetFontType (UC::UC257::SmallFont);
	unitControl.SetData (*cntlData, 0, dataSize);
	BMhUnlock (cntlData);
	BMKillHandle (&cntlData);
}


void	PenSettingsEditPensPage::HandleUnitControlChange (Int32 selectedUnit)
{
	double penWidth = penAttr.pen.width;;
	if (selectedUnit == PenSettingsEditPensPage::PenWeight_Pt)
		penWidth *= MM_TO_POINT;
	penWidthEdit.SetValue (penWidth);

	GS::UniString str = (selectedUnit == PenSettingsEditPensPage::PenWeight_MM) ? "mm" : "Pt";
	unitStatic.SetText (str);
}


void	PenSettingsEditPensPage::UpdatePenControl (void)
{
	short penCount = 0;
	ACAPI_Attribute_GetNum (API_PenID, &penCount);

	penControl.Setup (penCount, 13, 20);
	for (short cellIndex = 1; cellIndex <= penCount; cellIndex++) {
		API_Attribute attr;
		Attribute_Get (&attr, API_PenID, cellIndex);
		Gfx::Color color;
		color.Set ((unsigned char) (attr.pen.rgb.f_red * 255.0),
				 (unsigned char) (attr.pen.rgb.f_green * 255.0),
				 (unsigned char) (attr.pen.rgb.f_blue * 255.0));
		penControl.SetCellData (cellIndex, cellIndex, false, CCF262_USEDPEN, color.GetRed (), color.GetGreen (),
								color.GetBlue (), GS::UniString (), GS::UniString ());
	}
	penControl.Redraw ();
}


// --- PenSettingsEditPensObserver -------------------------------------------------------------------------------------

PenSettingsEditPensObserver::PenSettingsEditPensObserver (PenSettingsEditPensPage* penSettingsEditPensPage):
	dialog (penSettingsEditPensPage)
{
	dialog->Attach (*this);
	AttachToAllItems (*dialog);
}


PenSettingsEditPensObserver::~PenSettingsEditPensObserver ()
{
	dialog->Detach (*this);
	DetachFromAllItems (*dialog);
	dialog = NULL;
}

void	PenSettingsEditPensObserver::PanelOpened (const DG::PanelOpenEvent& /*ev*/)
{
	short penId = 1;
	dialog->penControl.SetValue (penId);
	Attribute_Get (&dialog->penAttr, API_PenID, penId);

	GS::UniString str = GS::UniString::Printf ("%u", penId);
	dialog->penNumberStatic.SetText (str);

	dialog->unitControl.SetValue (dialog->penWeightUnit);
	dialog->HandleUnitControlChange (dialog->penWeightUnit);

	str = dialog->penAttr.pen.description;
	dialog->penNameEdit.SetText (str);

	dialog->UpdatePenControl ();
}


void	PenSettingsEditPensObserver::UserControlChanged (const DG::UserControlChangeEvent& ev)
{
	if (ev.GetSource () == &dialog->penControl) {
		short penId = dialog->penControl.GetValue ();
		Attribute_Get (&dialog->penAttr, API_PenID, penId);

		GS::UniString str = GS::UniString::Printf ("%u", penId);
		dialog->penNumberStatic.SetText (str);

		dialog->HandleUnitControlChange (dialog->unitControl.GetValue ());

		str = dialog->penAttr.pen.description;
		dialog->penNameEdit.SetText (str);
	} else if (ev.GetSource () == &dialog->unitControl) {
		dialog->HandleUnitControlChange (dialog->unitControl.GetValue ());
	}
}


void	PenSettingsEditPensObserver::ButtonClicked (const DG::ButtonClickEvent& ev)
{
	if (ev.GetSource () == &dialog->okButton) {
		dialog->PostCloseRequest (DG::ModalDialog::Accept);
	}
}
To try:
	PenSettingsEditPensPage		dialog (ACAPI_GetOwnResModule (), USER_CONTROLS_DIALOG_RESID);
	if (DBERROR (dialog.GetId () == 0)) {
		return;
	}

	PenSettingsEditPensObserver	observer (&dialog);
	dialog.Invoke ();
poco2013
Mentor
Thanks for the response and the code. I now understand the usage of control 262 based on its use in archicad. I was confused because the User Control documentation stops at 261. However, I wasn't able to compile your code. Pardon the rookie question but I get an "can't find the header DrawDialogItems.hpp error. I assume you want to name the program header, UserControlsDialog.hpp, but where would DrawDialogItems.hpp be.

I'm not at all familiar with the protocol here. -- Sorry, but thanks again for the code!!.
Gerry

Windows 11 - Visual Studio 2022; ArchiCAD 27
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
poco2013 wrote:
I get an "can't find the header DrawDialogItems.hpp error
Sorry, that was one of my private header files.
I updated my code, deleted that include and added Attribute_Get helper function.
poco2013
Mentor
Thanks for the revised code and the Attribute_get Function which was also one of the missing identifier errors.

Got your code to compile -- Thanks -- Still experimenting
Gerry

Windows 11 - Visual Studio 2022; ArchiCAD 27