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.

How to create checkbox column in listview

Anonymous
Not applicable
Hi

I have a listview in my dialog.
I need a checkbox column in my listview in order user can select a few items.
Is there a way to do that ?

Thanks in advance.
8 REPLIES 8
Ralph Wessel
Mentor
ggiloyan wrote:
I have a listview in my dialog.
I need a checkbox column in my listview in order user can select a few items.
Is there a way to do that ?
There are 2 possible ways to do this:
  • 1) Use DGListSetDialItemOnTabField to place a check box control in the list column;
    2) Use check-box icons placed in the relevant column and watch for a DG_MSG_CLICK message to toggle the icon between checked and unchecked. The documentation for this can be found in the same place as DGListSetDialItemOnTabField. This is the recommended solution.
Ralph Wessel BArch
Software Engineer Speckle Systems
Anonymous
Not applicable
Ralph wrote:
ggiloyan wrote:
I have a listview in my dialog.
I need a checkbox column in my listview in order user can select a few items.
Is there a way to do that ?
There are 2 possible ways to do this:
  • 1) Use DGListSetDialItemOnTabField to place a check box control in the list column;
    2) Use check-box icons placed in the relevant column and watch for a DG_MSG_CLICK message to toggle the icon between checked and unchecked. The documentation for this can be found in the same place as DGListSetDialItemOnTabField. This is the recommended solution.
Thank you for the help.
Anonymous
Not applicable
I have 2 questions:

(1) I am trying to put a column of checkboxes into my listboxes...
Currently doing something like:

DGListSetDialItemOnTabField ( IDD_BACKSYNC, GetListIDFromDialog( pEntry->GetEntryType() ), 2, DG_LIST_UNCHECKEDICON );

IDD_BACKSYNC is the id of the dialog.
GetListIDFromDialog( pEntry->GetEntryType() ) returns an enum of the listbox that is the same value as in .grc file.

2 is the 2nd column.

but not seeing any checkbox.

Seems like I'm doing this incorrectly.

(2)

// THIS LINE WILL CREATE A BLACK, when it should be red.
DGListSetTabItemBackgroundColor ( IDD_BACKSYNC, GetListIDFromDialog( pEntry->GetEntryType() ), DG::ListBox::BottomItem, 1, 255, 0, 0 );


=============================================


'GDLG'  32505  Modal				337  259 800	600  "Sync From Fuzor To ArchiCAD" {
/* [  1] */ Button					 36  543   100   30	LargePlain  "Select All"
/* [  2] */ Button					200  543   100   30	LargePlain  "Select None"
/* [  3] */ Button					350  543   100   30	LargePlain  "Sync Selected"
/* [  4] */ Button					515  543   100   30	LargePlain  "Exit"
/* [  5] */ SingleSelList			 10  20    760   100	LargePlain  PartialItems VScroll 18 HasHeader 18
/* [  6] */ SingleSelList			 10  120   760   100	LargePlain  PartialItems VScroll 18 HasHeader 18
/* [  7] */ SingleSelList			 10  220   760   100	LargePlain  PartialItems VScroll 18 HasHeader 18
/* [  8] */ SingleSelList			 10  320   760   100	LargePlain  PartialItems VScroll 18 HasHeader 18
/* [  9] */ SingleSelList			 10  420   760   100	LargePlain  PartialItems VScroll 18 HasHeader 18
}


class BackSyncDialog : public DG::ModalDialog,
						   public DG::ButtonItemObserver
	{
	public:
		BackSyncDialog ( std::vector<BackSyncBaseTask*> &syncEntries );
		~BackSyncDialog ();

	// Results after running modal dlg
	public:
		void FillData(std::vector<BackSyncBaseTask*> &syncEntries );
	protected:
		DG::Dialog& GetReference ()
		{
			return *this;
		}

		std::wstring GetHeader ( BackSyncTaskType );
		short GetListIDFromDialog ( BackSyncTaskType );

		DG::SingleSelListBox & GetParentListByEntryType ( BackSyncTaskType a_eEntry );
	private:
		enum {
			BtnSelectAllId = 1,
			BtnSelectNoneId = 2,
			BtnSyncSelectedId = 3,
			BtnExitId = 4,
			LstViewFamilyPlacementId = 5,
			LstViewObjectRefitId = 6,
			LstViewDeletionId = 7,
			LstViewMaterialSwitchId = 8,
			LstViewMaterialPropertyId = 9
		};

		DG::SingleSelListBox	FamilyPlacementList;
		DG::SingleSelListBox	ObjectRefitList;
		DG::SingleSelListBox	DeletionList;
		DG::SingleSelListBox	MaterialSwitchList;
		DG::SingleSelListBox	MaterialPropertyList;;

	};
	
	void BackSyncDialog::FillData(std::vector<BackSyncBaseTask*> &syncEntries )
	{
		static const int c_dwNumFields = 4;
		static const int c_COLOR_STATUS = 30;
		static const int c_CHECK_FIELD_WIDTH = 30;
		static const int c_NAME_WIDTH = 200;
		static const int c_DESCRIPTION = 300;
		for ( short i = 0; i < BackSync_Max; i++ )
		{
			DG::SingleSelListBox & group = GetParentListByEntryType ( (BackSyncTaskType)i );
			group.SetTabFieldCount(c_dwNumFields);
			group.SetHeaderSynchronState ( false );

			short pos = 0;
			group.SetTabFieldProperties(1, pos, pos + c_COLOR_STATUS, DG::ListBox::Left, DG::ListBox::EndTruncate, true, true);
			pos += c_COLOR_STATUS;
			group.SetTabFieldProperties(2, pos, pos + c_CHECK_FIELD_WIDTH, DG::ListBox::Left, DG::ListBox::EndTruncate, true, true);
			pos += c_CHECK_FIELD_WIDTH;
			group.SetTabFieldProperties(3, pos, pos + c_NAME_WIDTH, DG::ListBox::Left, DG::ListBox::EndTruncate, true, true);
			pos += c_NAME_WIDTH;
			group.SetTabFieldProperties(4, pos, pos + c_DESCRIPTION, DG::ListBox::Left, DG::ListBox::EndTruncate, true, true);
			pos += c_DESCRIPTION;
			
			GS::UniString header( GetHeader((BackSyncTaskType)i).c_str());
			DBPrintf ( "Setting header for: %ls\n", header.ToUStr().Get());
			group.SetHeaderItemText ( 1, header );
		}
		
		for ( int i = 0; i < syncEntries.size(); i++)
		{
			BackSyncBaseTask *pEntry = syncEntries.at(i);

			DG::SingleSelListBox & group = GetParentListByEntryType( pEntry->GetEntryType() );
			group.AppendItem();
			GS::UniString name( pEntry->GetEntryName().c_str() );
			GS::UniString description ( pEntry->GetEntryDescription().c_str());
			
			group.SetItemValue(DG::ListBox::BottomItem, reinterpret_cast<DGUserData>(pEntry));
			// GetLIstIDFromDialog will return LstViewFamilyPlacementId ... LstViewMaterialPropertyId
			// THIS LINE WILL CREATE A BLACK, when it should be red.
			DGListSetTabItemBackgroundColor ( IDD_BACKSYNC, GetListIDFromDialog( pEntry->GetEntryType() ), DG::ListBox::BottomItem, 1, 255, 0, 0 );
			
			
			// THE BELOW LINE DOESN'T SHOW A CHECKBOX WITH UNCHECKED ICON.
			DGListSetDialItemOnTabField ( IDD_BACKSYNC, GetListIDFromDialog( pEntry->GetEntryType() ), 2, DG_LIST_UNCHECKEDICON );
	
			group.SetTabItemText(DG::ListBox::BottomItem, 3, name );
			group.SetTabItemText(DG::ListBox::BottomItem, 4, description );
			DBPrintf ( "%d: name:%ls desc:%ls\n", i, name.ToUStr().Get(), description.ToUStr().Get());		
		}
		....

	}

}
Ralph Wessel
Mentor
IanTr wrote:
I have 2 questions:

(1) I am trying to put a column of checkboxes into my listboxes...
Currently doing something like:
DGListSetDialItemOnTabField ( IDD_BACKSYNC, GetListIDFromDialog( pEntry->GetEntryType() ), 2, DG_LIST_UNCHECKEDICON );
but not seeing any checkbox.

(2) // THIS LINE WILL CREATE A BLACK, when it should be red.
DGListSetTabItemBackgroundColor ( IDD_BACKSYNC, GetListIDFromDialog( pEntry->GetEntryType() ), DG::ListBox::BottomItem, 1, 255, 0, 0 );
1) DG_LIST_UNCHECKEDICON is the index of an icon resource, so you should apply it to a list with DGListSetTabItemIconId.

2) Try using DGListSetItemBackgroundColor.
Ralph Wessel BArch
Software Engineer Speckle Systems
Oleg
Expert
As you use a class library dialog, there are class member functions.

1. SetOnTabItem, RemoveOnTabItem

2. SetTabItemIcon

Like this:

// Check Icon State
mi_split_list.SetTabItemIcon( item, CHECK_FIELD, DG::Icon(on ? ListBox::CheckedIcon : ListBox::UncheckedIcon) );

// Click handler
void TabAlgoSplit::ListBoxClicked( const DG::ListBoxClickEvent& ev )
{
	if ( ev.GetSource() == &mi_split_list )
	{
		short pos = ev.GetMouseOffset().GetX();
		short beg = mi_split_list.GetTabFieldBeginPosition( CHECK_FIELD );
		short end = mi_split_list.GetTabFieldEndPosition( CHECK_FIELD );
		if (  pos > end || pos < beg )
			return;

		OnSplitCheckClicked( ev.GetListItem() );
	}
}

Anonymous
Not applicable
Hello,

Thanks you for the suggestions.

I end up doing something like this in the Dialog's contructor to put checkboxes in listboxes row. Currently the checkboxes showed up in Archicad18...20. But it DOESN'T show up visually in archicad21. However, functionally
everything, is working i.e. in ListBoxClicked when I query whether the checkbox was checked or not, it will return the correct state. I was just wondering if I needed to do something in Archicad 21 to get the checkbox to show?

I printed out resId & resModule between Archicad 19 & 21 and they matched.
resId of -4 is enum for DG_LIST_UNCHECKEDICON

- icon {...} const DG::Icon &
- DG::Image {resModule=8790715924480 resId=-4 data=0x0000000000000000 } DG::Image
+ __vfptr 0x000007fed2a5ff68 *
resModule 8790715924480 __int64
resId -4 short
data 0x0000000000000000 const void *



DG::Icon icon(ACAPI_GetOwnResModule(), DG_LIST_UNCHECKEDICON );

for ( int i = 0; i < syncEntries.size(); i++)
{
	BackSyncBaseTask *pEntry = syncEntries.at(i);

	DG::SingleSelListBox & group = GetParentListByEntryType( pEntry->GetEntryType() );
	group.AppendItem();
	GS::UniString name( pEntry->GetEntryName().c_str() );
	GS::UniString description ( pEntry->GetEntryDescription().c_str());
	
	group.SetItemValue(DG::ListBox::BottomItem, reinterpret_cast<DGUserData>(pEntry));
	
	group.SetTabItemIcon (DG::ListBox::BottomItem, ROW_CHECK_FIELD, icon );						// Set the icon works in Archicad18 ... 20
	group.SetTabItemText(DG::ListBox::BottomItem, ROW_NAME, name );
	group.SetTabItemText(DG::ListBox::BottomItem, ROW_DESCRIPTION, description );	
}

...

	void BackSyncDialog::ListBoxClicked (const DG::ListBoxClickEvent & ev)
	{
		short dwListItem = ev.GetListItem();
		DG::ListBox *pListBox = ev.GetSource();
		if ( pListBox )
		{
			short pos = ev.GetMouseOffset().GetX();
			short begCheckBox = pListBox->GetTabFieldBeginPosition( ROW_CHECK_FIELD );
			short endCheckBox = pListBox->GetTabFieldEndPosition ( ROW_CHECK_FIELD );
			if ( pos > begCheckBox && pos < endCheckBox )
			{

				DG::Icon myIcon = pListBox->GetTabItemIcon ( dwListItem, ROW_CHECK_FIELD );
				bool bWasChecked = ( myIcon.GetResourceId() == DG_LIST_CHECKEDICON ); // This shows if checked/unchecked even if the checkbox can't be seen in 21.
			
				const DG::Icon & icon = DG::Icon(ACAPI_GetOwnResModule(), bWasChecked ? DG_LIST_UNCHECKEDICON : DG_LIST_CHECKEDICON );
				pListBox->SetTabItemIcon ( dwListItem, ROW_CHECK_FIELD, icon ); 
			}
		}
	}
			
Oleg
Expert
I was just wondering if I needed to do something in Archicad 21 to get the checkbox to show?
Unfortunately, I dont know.
I have no AC21 environment on this workplace for tests.
Oleg
Expert
I was just wondering if I needed to do something in Archicad 21 to get the checkbox to show?
On AC21.
Try the "SysResModule" instead ACAPI_GetOwnResModule(), like this:

#include "RSTypes.hpp"

DG::Icon( SysResModule, ListBox::UncheckedIcon)

Didn't find the answer?

Check other topics in this Forum

Back to Forum

Read the latest accepted solutions!

Accepted Solutions

Start a new conversation!