The Global ARCHICAD Community

Stay informed. Get help. Share your knowledge.

Discussions about using GRAPHISOFT's tools (API DevKit) for independent software developers

Moderators: ejrolon, Barry Kelly, Karl Ottenstein, LaszloNagy, gkmethy, Ed Brown, Mihály Palenik, Tibor Lorántfy, MOREH Tamas, Akos Somorjai

#243104
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.
#243291
Ralph Wessel 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.
By IanTr
#274626
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 );


=============================================
Code: Select all
'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());      
      }
      ....

   }

}
#274630
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.
User avatar
By Oleg
#274651
As you use a class library dialog, there are class member functions.

1. SetOnTabItem, RemoveOnTabItem

2. SetTabItemIcon

Like this:

Code: Select all// 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() );
   }
}

By IanTr
#274768
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 *



Code: Select allDG::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 );
         }
      }
   }
         
User avatar
By Oleg
#275011
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:

Code: Select all#include "RSTypes.hpp"

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