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

How to operate a Modal Dialog with Enter key?

szfri
Participant

Hi Everyone!

 

While trying the possibilities of the API I stumbled into a problem I don't know how to solve.

 

When I open a modal dialog that I coded and press the Enter key the dialog just closes as if I clicked on the Cancel button. If I operate with mouse and click on the OK or any other button it works just fine and the addon runs fine.

 

Can anyone please point me into the right direction how to detect which button is in focus and after pressing the Enter key the process would run as if I clicked that button?

 

My dialog window class is derived from DG::ModalDialog. What am I missing or not noticing?

Any help is appreciated! 

Ferenc Szőke
architect
3 REPLIES 3
Viktor Kovacs
Graphisoft
Graphisoft

The default Enter and Escape behavior automatically applies to your dialog if the OK and the Cancel buttons are the first two items in your dialog resource.

 

For example, take a look at the dialog in the maze generator example add-on.

Hi Viktor,

 

Thank you so much for the quick answer! I checked my AddOn.grc and the first two buttons are OK and Cancel. Still it's not responding as it should when hitting Enter while OK button is in focus. Here's the grc content:

 

 

'GDLG' ID_ADDON_DLG Modal | grow   40   40  410  128  "Dialog Window" {
/* [  1] */ Button				  310   95   90   23	LargePlain  "OK"
/* [  2] */ Button				  210	95	 90   23	LargePlain	"Cancel"
/* [  3] */ Button				   10	95	 90	  23	LargePlain	"About..."
/* [  4] */ Separator			   10   83  390    2
/* [  5] */ Icon				   13	50	 22	  22	10002 /* pen icon */
/* [  6] */ Icon				   10	50   22   22	10004 /* font icon */
/* [  7] */ IntEdit				   43	49	 30	  24	SmallPlain "0" "255" /* font color number */ 
/* [  8] */ UserControl			   77	50	 33   22	257	0x0001	0x1100	0	/* color user control */
/* [  9] */ PushCheck			  327	50	 25   22	LargeBold	noFrame		"B"
/* [ 10] */ PushCheck			  353	50	 25   22	LargeItalic	noFrame		"I"
/* [ 11] */ PushCheck			  379	50	 25	  22	LargeUnderline	noFrame		"U"
/* [ 12] */ Icon				  242	50	 22	  22	10006 /* font size icon */
/* [ 13] */ RealEdit			  273	49	 30   24	SmallPlain "0.1" "1000.0"	/* font size */
/* [ 14] */ LeftText			  306	55	 30	  24	SmallPlain "mm" /* unit label */
/* [ 15] */ PopupControl		  120	50	 110  22	80	3 /* font type popup menu */
/* [ 16] */ Icon				   10   20   29	  14	10007 /* layer icon */
/* [ 17] */ UserControl			   43   10   187  30	263 /* layer popup menu */
/* [ 18] */ LeftText			  242	12   110  30	SmallPlain "Szoveg tavolsag\na honszint szintjetol:"	/* MAGYAR */
/* [ 19] */ RealEdit			  355	13	 30   24	SmallPlain "0.00" "1000.0"	/* label dist in m */
/* [ 20] */ LeftText			  388	17	 30	  24	SmallPlain "m" /* label dist unit */
}

 

 

Interestingly when the About button is in focus and I hit Enter the About dialog appears as it should.

Here's my header file for the dialog:

 

 

#ifndef SETTINGSDIALOG_HPP
#define SETTINGSFIALOG_HPP

#include "APIEnvir.h"
#include "ACAPinc.h"

#include "ResourceIds.hpp"
#include "DGModule.hpp"
#include "UCModule.hpp"
#include "StringConversion.hpp"


class SettingsDialog : public DG::ModalDialog,
	public DG::PanelObserver,
	public UC::FontPopUpObserver,
	public DG::ButtonItemObserver,
	public DG::CompoundItemObserver,	
	public DG::CheckItemObserver,
	public DG::IntEditObserver,
	public DG::UserControlObserver,
	public DG::RealEditObserver,
	public DG::PopUpObserver

{
private:
	enum DialogResourceIds
	{
		ExampleDialogResourceId = ID_ADDON_DLG,
		OKButtonId = 1,
		CancelButtonId = 2,
		AboutButtonId = 3,
		SeparatorId = 4,
		// Pen Icon -> 5
		// Font Icon -> 6
		FontColorEditId = 7,
		FontColorUserControlId = 8,
		BoldCheckId = 9,
		ItalicCheckId = 10,
		UnderlineCheckId = 11,
		// FontSizeIcon -> 12
		FontSizeEditId = 13,
		// LeftText -> 14
		FontPopUpId = 15,
		// Layer Icon -> 16
		LayerPopUpId = 17,
		// LeftText -> 18
		LabelHeightEditId = 19
		// LeftText -> 20
	};

	
	
	DG::Button	okButton;
	DG::Button	cancelButton;
	UC::FontPopUp	fontPopUp;
	DG::Button	aboutButton;
	DG::Separator	separator;
	DG::IntEdit	fontColor;
	DG::UserControl	fontColorUserControl;
	DG::PushCheck	boldCheck;
	DG::PushCheck	italicCheck;
	DG::PushCheck	underlineCheck;
	DG::RealEdit	fontSize;
	DG::PopUp	layerPopUp;
	DG::RealEdit	labelHeight;
		
	short* font_type_data;
	GS::Int32* pen_col_data;
	unsigned short* face_bits_data;
	double* font_size_data;
	double* label_height_data;
	bool* cont_w_exec = nullptr;
	API_AttributeIndex* layer = nullptr;

	virtual void PanelResized(const DG::PanelResizeEvent& ev) override;

	virtual void ButtonClicked(const DG::ButtonClickEvent& ev) override;
	virtual void IntEditChanged(const DG::IntEditChangeEvent&) override;
	virtual void UserControlChanged(const DG::UserControlChangeEvent&) override;
	virtual void RealEditChanged(const DG::RealEditChangeEvent&) override;
	virtual void PopUpChanged(const DG::PopUpChangeEvent&);
	
	void UpdateValues(short* ft_type, GS::Int32* pn_col, unsigned short* face_bts, double* ft_s, double* lbl_h);

public:
	SettingsDialog(short* ft_type, GS::Int32* pn_col, unsigned short* face_bts, double* ft_s, double* lbl_h, bool* c_w_ex, API_AttributeIndex* _layer);
	virtual ~SettingsDialog();
};

#endif //!SETTINGSDIALOG_HPP

 

 

My design so far is a bit primitive compared to the maze example, I have more data members which I also shall collect into a settings class. And my ButtonClicked function (in case OK is pressed) initiates the UpdateValues function which updates the data members and then continues with the rest of the addon. (I'm still not familiar with the ACAPI_GetPreferences and ACAPI_SetPreferences functions, but I think they are what I was looking for for a while to improve the addon.)

 

Here's the implementation of my ButtonClicked function:

 

void SettingsDialog::ButtonClicked(const DG::ButtonClickEvent& ev)
	{
		if (ev.GetSource() == &okButton) {
			UpdateValues(font_type_data, pen_col_data, face_bits_data, font_size_data, label_height_data);
			*cont_w_exec = true;
			PostCloseRequest(DG::ModalDialog::Accept);
		}

		else if (ev.GetSource() == &cancelButton) {
			*cont_w_exec = false;
			PostCloseRequest(DG::ModalDialog::Cancel);
		}

		else if (ev.GetSource() == &aboutButton) {
			AboutDialog abtdial;
			abtdial.Invoke();
		}
		else
		{
			ACAPI_WriteReport("Unknown event source", true);
		}

	}

 

I know I'm doing something wrong as I'm not a developer by profession just an architect with some C++ experience. I think the Archicad API is the coolest thing that exists for an Archicad user. I have sometimes problems understanding the documentation or the example code. Any further advice or help is appreciated!

Ferenc Szőke
architect
szfri
Participant

The thing I noticed is, if I organize the code as it is in the maze generator, namely I move the addon functions from ButtonClicked to PanelCloseRequested and only the PostCloseRequest function stays in the ButtonClicked function, hitting Enter works as it should! So thank you for your help! Since I don't know why it is this way but it works, I'll follow this way of organizing the code.

Ferenc Szőke
architect