Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/26: Рейтинг темы: голосов - 26, средняя оценка - 4.50
Марийка

Как сделать дерево с чекбоксами?

14.06.2009, 08:42. Показов 5553. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Подскажите, как сделать дерево с чекбоксами? (C++ Builder)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
14.06.2009, 08:42
Ответы с готовыми решениями:

Как сделать TreeView с чекбоксами но не во всех узлах
Нужно красивое TreeView в котором будут чекбоксы только в одной ветви и только для дочерних узлов. Есть ли способ решения такой задачи?

Картинка с чекбоксами в таблице, как работает, как сделать
Здравствуйте! Подскажите как такое называется, как создается - какую-нибудь ссылку на инструкции. Очень хочется разобраться. Спасибо.

Как сделать чтобы при нажатии на кнопку выполнялись действия закрепленные за одним или сразу несколькими чекбоксами?
Есть форма с несколькими чекбоксами. Как сделать чтобы при нажатии на кнопку выполнялись действия закрепленные за одним или сразу...

14
1 / 1 / 2
Регистрация: 13.05.2009
Сообщений: 65
14.06.2009, 14:58
А разве в настройках Дерева нет такого свойства, типа CheckBox = bool или что-то в том роде
0
Марийка
15.06.2009, 02:07
Re: : AlexFilan
В C++ Builder-ре, класс TTreeView, точно нет.
0 / 0 / 0
Регистрация: 22.04.2009
Сообщений: 4
16.06.2009, 12:39
установи дереву стиль TVS_CHECKBOXES
для установки/получения чекбокса шли сообщения TVM_SETITEMSTATE TVM_GETITEMSTATE
в новом commctrl.h для этого есть макросы TreeView_SetCheckState и TreeView_GetCheckState

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/treeview/styles.asp
0
0 / 0 / 1
Регистрация: 02.08.2013
Сообщений: 16
12.02.2015, 22:25
Если использовать
C++
1
SetWindowLong(TreeView1->Handle, GWL_STYLE, GetWindowLong(TreeView1->Handle, GWL_STYLE) | TVS_CHECKBOXES );
то чекбоксы могут находится только в двух состояниях. Для дерева это не очень удобно. Логичнее использовать третье/неопределенное состояние чекбоксов для нодов у которых часть дочерних ноде чекнуты.

Как сделать в TTreeView чекбоксы с тремя состояниями?

Я попытался рисовать чекбоксы в иконках состояния нодов. Сначала нашел функцию
C++
1
LoadBitmap(NULL, MAKEINTRESOURCE(OBM_CHECKBOXES));
но она возвращает картинку состоящую из нескольких и я не знаю как их разделять. Кроме того там нет изображения для третьего состояния чекбокса.
Потом я нашел другую функцию, с помощью которой нарисовал чекбокс в двух состояниях
C++
1
2
3
4
5
6
7
8
9
10
TreeView1->StateImages=ImageList1;
TBitmap *Bitmap = new TBitmap();
Bitmap->SetSize(16,16);
RECT pRect = {0, 0, 16, 16};
ImageList1->Add(Bitmap,NULL);
DrawFrameControl( Bitmap->Canvas->Handle, &pRect, DFC_BUTTON, DFCS_BUTTON3STATE | DFCS_ADJUSTRECT);
ImageList1->Add(Bitmap,NULL);
DrawFrameControl( Bitmap->Canvas->Handle, &pRect, DFC_BUTTON, DFCS_CHECKED | DFCS_ADJUSTRECT );
ImageList1->Add(Bitmap,NULL);
delete Bitmap;
Но параметров для этой функции для рисования неопределенного состояния чекбокса я не нашел.
Потом я нашел еще одну функцию
C++
1
DrawThemeBackground(hTheme, Bitmap->Canvas->Handle, BP_CHECKBOX, CBS_MIXEDNORMAL, &pRect, NULL);
Но по ней в интернете очень мало информации. Даже на английском.
Насколько я понял для первого параметра должна использоваться функция
C++
1
2
3
4
HTHEME OpenThemeData(
  _In_  HWND hwnd,
  _In_  LPCWSTR pszClassList
);
Какие параметры она должна принимать я не понял. И ещё я не понял что надо подключить чтобы работали константы BP_CHECKBOX и CBS_MIXEDNORMAL

Как рисовать чекбоксы в неопределенном состоянии? Как использовать функцию DrawThemeBackground?
Или возможно есть более удобный способ сделать в TTreeView чекбоксы с тремя состояниями?
0
 Аватар для Dinkin
783 / 556 / 136
Регистрация: 31.05.2013
Сообщений: 3,145
Записей в блоге: 3
12.02.2015, 22:55
Доброго, сам недавно столкнулся ..в итоге нашел отличный свободный компонент на делфи (сделан на оснве этого же дерева)написанный умельцем, просто подключите и радуйтесь
Изображения
 
Вложения
Тип файла: rar CheckTreeView.rar (5.8 Кб, 35 просмотров)
0
0 / 0 / 1
Регистрация: 02.08.2013
Сообщений: 16
14.02.2015, 14:34
Всё таки хотелось бы использовать TTreeView. Кто то ведь должен знать как использовать функцию DrawThemeBackground...

Тема актуальна
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33376 / 21500 / 8236
Регистрация: 22.10.2011
Сообщений: 36,896
Записей в блоге: 11
14.02.2015, 16:10
DrawThemeBackground ни разу не обязательна. Вот так спокойно можно добавить третье состояние чекбоксу: How to create a TTreeView with a three state checkbox
0
0 / 0 / 1
Регистрация: 02.08.2013
Сообщений: 16
15.02.2015, 15:40
Цитата Сообщение от volvo
DrawThemeBackground ни разу не обязательна. Вот так спокойно можно добавить третье состояние чекбоксу: How to create a TTreeView with a three state checkbox
TreeView_GetImageList(Handle,TVSIL_STATE ) возвращает NULL...
Возможно вместо "Handle" должно быть что то другое?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33376 / 21500 / 8236
Регистрация: 22.10.2011
Сообщений: 36,896
Записей в блоге: 11
15.02.2015, 16:36
Handle - имеется в виду хендл TreeView. Код абсолютно рабочий, проверено.
0
0 / 0 / 1
Регистрация: 02.08.2013
Сообщений: 16
15.02.2015, 18:23
Цитата Сообщение от volvo Посмотреть сообщение
Handle - имеется в виду хендл TreeView. Код абсолютно рабочий, проверено.
Я долго не понимал как работает этот код потому что он работает совсем не так как нужно. Здесь просто делается бледная копия обычного чекбокса. Подобное можно нарисовать и функцией DrawFrameControl.
Я хочу чтобы чекбокс был стандартный, как в windows
Миниатюры
Как сделать дерево с чекбоксами?   Как сделать дерево с чекбоксами?  
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33376 / 21500 / 8236
Регистрация: 22.10.2011
Сообщений: 36,896
Записей в блоге: 11
15.02.2015, 18:34
Это тебе не так, то не эдак. Ну, делай так, причем сам, раз такой переборчивый... Я так понимаю, тот факт, что вместо "бледной копии" в ImageList можно подсунуть любое изображение - тоже прошел мимо тебя? Ну что ж. Я попытался, ты не понял. Чья это проблема?
0
0 / 0 / 1
Регистрация: 02.08.2013
Сообщений: 16
15.02.2015, 18:44
Цитата Сообщение от volvo Посмотреть сообщение
Я так понимаю, тот факт, что вместо "бледной копии" в ImageList можно подсунуть любое изображение - тоже прошел мимо тебя?
Подсунуть любое изображение не проблема. Я хотел брать эти изображения из системы чтобы они выглядели также как и везде. Я думаю что в этом может помочь функция DrawThemeBackground. И надеюсь что кто-нибудь здесь знает как ей пользоваться.
0
 Аватар для Gremlin
519 / 307 / 58
Регистрация: 30.07.2008
Сообщений: 607
16.02.2015, 03:32
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
// чисто winapi чекбокс
HWND hCheckBox = CreateWindowEx(
    0,
    "Button",
    "My Check Box",
    WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_AUTO3STATE,
    5,
    5,
    100,
    16,
    this->Handle,
    NULL,
    NULL,
    NULL
);
*/
 
// или же для обычного билдеровского TCheckBox
CheckBox1->State = cbGrayed;
 
// или так можно
// SendMessage(CheckBox1->Handle, BM_SETCHECK, BST_INDETERMINATE, 0);
а вот что по стилям говорит msdn
https://msdn.microsoft.com/ru-... hd91s.aspx


Те чек боксы, которые использубтся в TTReeView не совсем оригинальные
это видно по самому класу
TTreeView это TCustomTreeView это Controls::TWinControl
и макрос как бы намекает:
C++
1
2
3
4
#define INDEXTOSTATEIMAGEMASK(i) ((i) << 12)
//...
#define TreeView_SetCheckState(hwndTV, hti, fCheck) \
  TreeView_SetItemState(hwndTV, hti, INDEXTOSTATEIMAGEMASK((fCheck)?2:1), TVIS_STATEIMAGEMASK)
На мой взгляд тут несколько вариантов: либо использовать то что есть, либо сторонний компонент, либо допиливать TTreeView и на его основе создать какой нить TMyTreeView
0
0 / 0 / 1
Регистрация: 02.08.2013
Сообщений: 16
16.02.2015, 20:44
Сделал. Не идеально конечно, но пока и так нормально.

Заполнение ImageList
C++
1
#include <Vsstyle.h>
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
TBitmap *Bitmap = new TBitmap();
Bitmap->SetSize(16,16);
RECT pRect ={0,0,16,16};
HTHEME hTheme=OpenThemeData(NULL,L"BUTTON");
ImageList1->Add(Bitmap,NULL);
DrawThemeBackground(hTheme, Bitmap->Canvas->Handle, BP_CHECKBOX, CBS_UNCHECKEDNORMAL, &pRect, NULL);
ImageList1->Add(Bitmap,NULL);
DrawThemeBackground(hTheme, Bitmap->Canvas->Handle, BP_CHECKBOX, CBS_CHECKEDNORMAL, &pRect, NULL);
ImageList1->Add(Bitmap,NULL);
DrawThemeBackground(hTheme, Bitmap->Canvas->Handle, BP_CHECKBOX, CBS_MIXEDNORMAL, &pRect, NULL);
ImageList1->Add(Bitmap,NULL);
CloseThemeData(hTheme);
delete Bitmap;
Обработка щелчка по чекбоксу
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void __fastcall TForm1::TreeView1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift,
          int X, int Y)
{
    if(Button==mbLeft)
    {
        THitTests HitTests=((TTreeView*)Sender)->GetHitTestInfoAt(X,Y);
        if(HitTests.Contains(htOnStateIcon))
        {
            ((TTreeView*)Sender)->Items->BeginUpdate();
            TTreeNode *Node=((TTreeView*)Sender)->GetNodeAt(X,Y);
            Node->StateIndex=Node->StateIndex==2?1:2;
            CheckChildsNode(Node);
            CheckParentNode(Node);
            ((TTreeView*)Sender)->Items->EndUpdate();
        }
    }
}
Функции для изменения состояния чекбоксов у дочерних и родительских Node
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
void CheckChildsNode(TTreeNode *Node)
{
    for(TTreeNode *ChildNode=Node->getFirstChild();ChildNode
                    ;ChildNode=ChildNode->getNextSibling())
    if(ChildNode->StateIndex!=Node->StateIndex)
    {
        ChildNode->StateIndex=Node->StateIndex;
        CheckChildsNode(ChildNode);
    }
}
void CheckParentNode(TTreeNode *Node)
{
    TTreeNode *ParentNode=Node->Parent;
    if(ParentNode)
    {
        bool Index1=false, Index2=false;
        if(Node->StateIndex==3) ParentNode->StateIndex=3;
        else for(TTreeNode *Node=ParentNode->getFirstChild();Node
                                ;Node=Node->getNextSibling())
        {
            if(Node->StateIndex==2)
            {
                if(Index1)
                {
                    ParentNode->StateIndex=3;
                    break;
                }
                else
                {
                    Index2=true;
                    ParentNode->StateIndex=2;
                }
            }
            else
            {
                if(Index2)
                {
                    ParentNode->StateIndex=3;
                    break;
                }
                else
                {
                    Index1=true;
                    ParentNode->StateIndex=1;
                }
            }
        }
        CheckParentNode(ParentNode);
    }
}


Добавлено через 3 часа 58 минут
Ошибочка закралась...
вот так работает правильно.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
void CheckParentNode(TTreeNode *Node)
{
    TTreeNode *ParentNode=Node->Parent;
    if(ParentNode)
    {
        bool Index1=false, Index2=false;
        if(Node->StateIndex==3) ParentNode->StateIndex=3;
        else for(TTreeNode *Node=ParentNode->getFirstChild();Node
                                ;Node=Node->getNextSibling())
        {
            if(Node->StateIndex==3)         ///////Добавлено
            {                               ///////
                ParentNode->StateIndex=3;   ///////
                break;                      ///////
            }                               ///////
            else if(Node->StateIndex==2)    ///////
            {
                if(Index1)
                {
                    ParentNode->StateIndex=3;
                    break;
                }
                else
                {
                    Index2=true;
                    ParentNode->StateIndex=2;
                }
            }
            else
            {
                if(Index2)
                {
                    ParentNode->StateIndex=3;
                    break;
                }
                else
                {
                    Index1=true;
                    ParentNode->StateIndex=1;
                }
            }
        }
        CheckParentNode(ParentNode);
    }
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
16.02.2015, 20:44
Помогаю со студенческими работами здесь

Радиокнопки сделать чекбоксами
использовать чебоксы не предлагать. нужно поменять стиль радиокнопок, чтобы они выглядели как чебоксы. Нужна кроссбраузерность. ...

Как сделать дерево?
Всем привет помогите сделать дерево , у меня есть 3 кнопки 1 кнопка зелёная, 2 желтая, 3 красная. Эти кнопки это листья что при нажатии на...

Как сделать дерево вариантов на JS?
Нужно сделать визуализацию возможных действий в браузере. Вот как показано на рисунке. Подскажите есть ли готовые решения? Какие есть...

Как сделать дерево регионов?
Я начинающий в PHP и базах данных. Не подскажете ли файл или MySQL код для того, чтобы добавились многие регионы и города, поселки. У меня...

Как сделать дерево в DataGridView?
Здравствуйте, облазил уже уйму сайтов, искал темы, но так и не нашел конкретного ответа, не знаю как сделать дерево в DataGridView , на...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru