Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.64/22: Рейтинг темы: голосов - 22, средняя оценка - 4.64
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906

Разноцветнопульсирующий ListBox

04.09.2012, 15:15. Показов 4682. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Господа, вот бьюсь тут над развеселым подсвечиванием строк в ListBoxe. В интернете куча однотипной информации по этому поводу и при чем в основном на делфях. По образу и подобию получилось соорудить следующее:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void __fastcall TForm1::ListBox1DrawItem(TWinControl *Control, int Index,
      TRect &Rect, TOwnerDrawState State)
{
    if(ListBox1->Items->Strings[Index][1]=='2') // Если первый символ любой строки есть 2
    //if( (Index) % 2 != 0 )
      {
      //Если прорисовываемая строка чётная.
      ListBox1->Brush->Color = RGB(100, 150, 150);
      ListBox1->Font->Color = RGB(255, 255, 255);
      ListBox1->Canvas->FillRect(Rect);
      ListBox1->Canvas->TextOut(Rect.Left, Rect.Top, ((TListBox *)Control)->Items->Strings[Index] );
      }
   else
      {
      //Если прорисовываемая строка нечётная.
      ListBox1->Brush->Color = RGB(150, 150, 100);
      ListBox1->Font->Color = RGB(255, 255, 255);
      ListBox1->Canvas->FillRect(Rect);
      ListBox1->Canvas->TextOut(Rect.Left, Rect.Top, ((TListBox *)Control)->Items->Strings[Index]);
      }
}
То есть в событии OnDrowItem у ListBox-а прописан вот такой вот откуда-то спертый код.

Свойство Style у все того же ListBox-а установлено в lbOwnerDrawFixed

Результатом всего этого действительно является вывод разноцветных строк.
Но вот только при первом отображении можно наблюдать, что строка с начальной цифрой 3 выделилась цветом, хотя в обработчике вроде написано искать 2 (самая левая миниатюра).

Дальше больше! Передвигая позицию курсора вверх-вниз, видим, что строки начинают выделяться вообще непонятным образом. И продолжая уже беспощадно хаотично тыкать мышкой в строки сходящего с ума ListBoxa добиваемся полной инверсии цветового выделения.

Отсюда закономерный вопрос: может я где-то ошибся? Подскажите пожалуйста.

И еще вопрос вдогонку: по каким конкретно событиям обновляется ListBox? Сдается мне, что тут не все так просто.
Миниатюры
Разноцветнопульсирующий ListBox   Разноцветнопульсирующий ListBox   Разноцветнопульсирующий ListBox  

0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
04.09.2012, 15:15
Ответы с готовыми решениями:

При выделении строки в ListBox отображать ее в Edit, где можно отредактировать и заменить в ListBox-е
Подскажите пожалуйста как зделать задачку:При выделении строки в поле ListBox даная строка отображалась в Edit, где можна его...

Перенести данные из ListBox на форме в Listbox на PageСontrol
Доброго времени суток! Как заставить данные которые вносятся на Form в ListBox перенести на Listbox, который находится на Pagekontrol?

Возможно ли при выборе через opendialog заносить в ListBox имена файлов, а при чтении из ListBox получать путь к файлам?
Возможно ли при выборе через opendialog заносить в ListBox имена файлов, а при чтении из ListBox получать путь к файлам?

5
 Аватар для Google_Bot
0 / 0 / 0
Регистрация: 30.08.2012
Сообщений: 11
04.09.2012, 16:04
Ну во первых:
C++
1
void __fastcall TForm1::ListBox1DrawItem(TWinControl *Control, int Index, TRect &Rect, TOwnerDrawState State)
Это событие выбора конкретной строчки.

Во вторых, ты выбрал строчку (мышкой) и тут же ищешь по всему листбоксу первый символ.

Вдумайся в логику:
Я программа, я выделила строчку, начинаю поиск, нашла выделенную строчку, проверила = "нет!", на первом месте "1" не "2", значит начинаю выполнять "else", меняю цвет у всего листбокса (именно у всего, так как ты обращаешься к свойству не строки а бокса целиком).

1)Я бы писал это не в событие выбора строчки, а где ни будь в создании листбокса или в его заполнении.
2)Если я правильно помню "Rect" это прямоугольник выделения (кароче строка которая щас выделена), вот ему и надо цвет менять.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33399 / 21509 / 8236
Регистрация: 22.10.2011
Сообщений: 36,907
Записей в блоге: 12
04.09.2012, 16:40
Цитата Сообщение от Google_Bot Посмотреть сообщение
Это событие выбора конкретной строчки.
Дальше можно не читать. OnDrawItem - событие выбора строки? Это даже не смешно. Это именно отрисовка конкретной строки: OnDrawItem
Occurs when an item in an owner-draw list box needs to be redisplayed.
Добавлено через 16 минут
Решение - тривиально:
C++
1
2
3
// ListBox1->Brush->Color = RGB(100, 150, 150);
// заменить на 
ListBox1->Canvas->Brush->Color = RGB(100, 150, 150);
, и никаких фокусов с цветом не будет.
1
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
04.09.2012, 16:54  [ТС]
Так.
Вроде бы событие ListBox1DrawItem происходит при каждом изменении самого ListBox-а. Но что-то мне подсказывает, что пресловутое изменение это не только добавление, удаление или отображение в нем чего-либо.
И да, я меняю цвет у всего ListBox-а. Всмысле он меняется у всего. Когда же FillRect, согласно справке, должен отрисовывать прямоугольник. Хотя по той же справке как-то туманно написано про верхний и левый угол. Это получается что он рисует прямоугольник от заданных границ слева и сверху до бесконечности вправо и вниз?

Я предполагаю, что
C++
1
ListBox1->Canvas->FillRect(Rect);
рисует прямоугольник фона, а
C++
1
ListBox1->Canvas->TextOut(Rect.Left, Rect.Top, ((TListBox *)Control)->Items->Strings[Index]);
соответственно в тот же прямоугольник пишет текст. И тут вроде бы как бы логика сходится. Но что-то он промахивается и слишком много потом думает где не надо.

В сам метод
C++
1
ListBox1DrawItem(TWinControl *Control, int Index, TRect &Rect, TOwnerDrawState State)
среда передает кого изменять (Control), какую строку (Index), координаты прямоугольника, описанного вокруг текущей строки (Rect), и варианты отображения объекта (State). Так что вроде метод уже написан так, что бы облегчить жизнь и не заморачиваться над поиском каждой строки.
Но по скольку у меня что-то не правильно работает, значит где-то я рассуждаю неправильно.

Добавлено через 2 минуты
UI, чтоб я без тебя делал.

Добавлено через 1 минуту
UI, а что ж он без канвы пытался такого замутить? Просто уже интересно даже.

Добавлено через 10 минут
Просто наблюдение: при выставлении в Style свойств lbOwnerDrawFixed и lbOwnerDrawVariable выделение работает одинаково и корректно.
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
11.01.2013, 15:56  [ТС]
В продолжении темы. Пытаюсь сделать, чтобы по разноцветно выделенному листбоксу можно было бы передвигаться выделением. Не просто курсором, а чтобы строка, в которую ткнули, подсвечивалась.
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
void __fastcall TForm1::ListBox1DrawItem(TWinControl *Control, int Index,
      TRect &Rect, TOwnerDrawState State)
{
if(ListBox1->Items->Strings[Index]==3)
  {
  if(Index==ListBox1->ItemIndex) // курсор на нем
    {
    ListBox1->Canvas->Brush->Color = clSkyBlue;
    ListBox1->Canvas->Font->Color = clWindow;
    }
  else                                   // курсор не на этой строке
    {
    ListBox1->Canvas->Brush->Color = clSilver;  // Подсветить строчечку сереньким
    ListBox1->Canvas->Font->Color = clWindow; //RGB(255, 255, 255);
    }
  }
else
  {
  if(Index==ListBox1->ItemIndex) // Курсор
    {
    ListBox1->Canvas->Brush->Color = clMenuHighlight;
    ListBox1->Canvas->Font->Color = clWindow;
    }
  else                                   // Нет
    {
    ListBox1->Canvas->Brush->Color = clWindow;
    ListBox1->Canvas->Font->Color = clWindowText;
    }
  }
 
  ListBox1->Canvas->FillRect(Rect);
  ListBox1->Canvas->TextOut(Rect.Left, Rect.Top, ((TListBox *)Control)->Items->Strings[Index] );
 
}
Листбокс отображается нормально, но стоит выделить какую-либо строку, а затем убрать с нее выделение, как назад она уже не красится. То есть в итоге, при тыкании на весь листбокс, все его строки инвертируются.

На миниатюрах ниже слева просто отображенный список, справа натыканый мышом на первые три строки.
Название: 1111.JPG
Просмотров: 423

Размер: 2.9 КбНазвание: 2222.JPG
Просмотров: 428

Размер: 3.7 Кб

Как было обнаружено, событие DrawItem обрабатывается раньше чем присваивается ItemIndex. То есть DrawItem в своем теле еще не знает значение выбранной строки листбокса. Ровно как ItemIndex заполняется только после завершения DrawItem-а. (даже больше: DrawItem обрабатывается раньше чем MouseDown)

Вот собственно вопрос в том, как можно опередить DrawItem?
Ну или как-то по другому сделать.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33399 / 21509 / 8236
Регистрация: 22.10.2011
Сообщений: 36,907
Записей в блоге: 12
12.01.2013, 15:17
SatanaXIII, проверяй, выделена ли строка, которая сейчас рисуется, или нет, через State.Contains(odSelected). Вот так:

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
void __fastcall TForm1::ListBox1DrawItem(TWinControl *Control, int Index, TRect &Rect,
          TOwnerDrawState State)
{
    if(Index == 3) // рисуется строка № 3
    {
        if(State.Contains(odSelected)) // третья строка выделена?
            ListBox1->Canvas->Brush->Color = clSkyBlue;
        else
            ListBox1->Canvas->Brush->Color = clSilver;  // Подсветить строчечку сереньким
        ListBox1->Canvas->Font->Color = clWindow;
    }
    else
    {
        // рисуется другая строка
        if(State.Contains(odSelected)) // Выделена?
        {
            ListBox1->Canvas->Brush->Color = clMenuHighlight;
            ListBox1->Canvas->Font->Color = clWindow;
        }
        else // Нет
        {
            ListBox1->Canvas->Brush->Color = clWindow;
            ListBox1->Canvas->Font->Color = clWindowText;
        }
    }
    ListBox1->Canvas->FillRect(Rect);
    ListBox1->Canvas->TextOut(Rect.Left, Rect.Top, ((TListBox *)Control)->Items->Strings[Index] );
}
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
12.01.2013, 15:17
Помогаю со студенческими работами здесь

Выбранный элемент ListBox одной формы перенести в ListBox на другую форму
проблема такая: в программе(в форме Form1) должна по нажатию кнопки открываться 2-я форма, в которой есть listbox и 2 кнопки: закрыть и...

Копировать выделенные строки из listbox в listbox с большим кол-вом колонок
Добрый день всем. Такая проблема. Пытаюсь из listbox одной формы скопировать выделенные строки в listbox другой формы. Один listbox...

MVVM. Как прибиндить TextBox к вложенному ListBox в ListBoxItem основного ListBox
<UserControl x:Class="Wpf_CareerPattern.Views.MainView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ...

В ListBox вводится последовательность строк. Вывести их в ListBox в обратном порядке
Помогите пожалуйста решить задачу :) очень надеюсь на ответ... В ListBox вводится последовательность строк. Вывести их в ListBox в...

ListBox как сделать что бы элемент ListBox выполнял действия
на пример элемент ListBox очистил бы texbox


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru