Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Создать таблицу цветов, Программно заполнить ImageList 
:(
    Опции темы
Sphinx
Дата 23.6.2010, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 20.7.2006

Репутация: нет
Всего: нет



Цитата(Earnest @  23.6.2010,  15:51 Найти цитируемый пост)
Да и у автора уже реализация была на его основе, совсем чуть-чуть изменить.

Этот вариант был использован только потому, что я не знал другого. А вариант через ImageList был неоднократно опробован. Но одно дело, когда в ImageList добавить пяток, десяток образцов иконок, а когда несколько десятков, то тут становится сложнее создавать образцы и корректировать цвета. Возникла идея создавать в памяти множество (по количеству цветов) 24-битных битмапов, заполняя их нужным цветом и потом включать их в ImageList. Но как это делать я не знаю и, собственно об этом изначально был вопрос.

Цитата(Earnest @  23.6.2010,  15:29 Найти цитируемый пост)
Создаем совместимый битмап нужного размера, заполняем его нужным цветом (да хотя бы с помощью PatBlt), вставляем в ImageList

Можно немного подробнее, достаточно просто перечислить функции и очередность их вызова.

Но вариант через NM_CUSTOMDRAW мне больше нравится. Он более гибок и менее ресурсоемок. Вот только не удается получить работающий код. Если удастся заставить его работать, то я предпочту этот вариант.

Цитата(GremlinProg @  23.6.2010,  15:40 Найти цитируемый пост)
скажу больше: для такой задачи я бы использовал listbox 

Если сказал А, то говори и Б
Какова последовательность действий для этого?



Это сообщение отредактировал(а) Sphinx - 23.6.2010, 19:24
PM MAIL   Вверх
Earnest
Дата 23.6.2010, 19:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Sphinx, если несколько десятков, да еще и редактировать, тогда действительно, лучше через CustomDraw. Но можно и через ImageList. Вообще, полезно иметь выбор, в голове, на будущее, и вообще.
Значит, насчет добавления в ImageList
1) создать битмап  - CreateCompatibleBitmap - но может и не совместимый, а какой-то конкретной цветности - суть в том, что все картинки в ImageList должны быть одинаковых размеров и цветности..
2) совместимый контекст - CreateCompatibleDC, 
3) дальше выбираем битмап в контекст (SelectObject) и рисуем в этом контексте что хотим. В твоем случае - нужно просто закрасить - куча вариантов на любой вкус: от Rectangle до PatBlt
4) Осталось добавить битмап в ImageList: одна из функций Add, т.е. ImageList_AddXXX проще всего, по-моему, использовать Masked, в качестве цвета маски передать что угодно - хоть белый, хоть черный, лишь бы не свой.
5) Если захочется редактировать, то насколько помню, есть функции Set\Get


--------------------
...
PM   Вверх
Sphinx
Дата 23.6.2010, 20:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 20.7.2006

Репутация: нет
Всего: нет



Цитата(Earnest @  23.6.2010,  19:57 Найти цитируемый пост)
создать битмап  - CreateCompatibleBitmap - но может и не совместимый, а какой-то конкретной цветности - суть в том, что все картинки в ImageList должны быть одинаковых размеров и цветности..

А битмап может быть один или надо создавать их столько сколько нужно цветов? Если один, то как указать, где заканчивается один цвет и начинается другой? т.е как один битмап подключить к ImageList несколько раз.
PM MAIL   Вверх
Sphinx
Дата 24.6.2010, 09:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 20.7.2006

Репутация: нет
Всего: нет



Цитата(Earnest @  23.6.2010,  19:57 Найти цитируемый пост)
Значит, насчет добавления в ImageList

Сделал тестовый вариант, работает:
Код

  himl = ImageList_Create(16, 16, ILC_COLORDDB, NUMCOLORS, 0);
  for(i=0; i<NUMCOLORS; i++){
    hDC = GetDC(hwndLV);
    hdcCompatible = CreateCompatibleDC(hDC);
    hbmScreen = CreateCompatibleBitmap(hDC, 16, 16);
    SelectObject(hdcCompatible, hbmScreen);
    ReleaseDC(hwndLV, hDC);

    FillingColor(hdcCompatible, i );

    DeleteDC(hdcCompatible);
    ImageList_Add(himl, hbmScreen, NULL);
    DeleteObject(hbmScreen);
  }
  ListView_SetImageList(hwndLV, himl, LVSIL_SMALL);

Посмотрите, все ли корректно. Не уверен в манипуляциях с контекстами - все ли что нужно удаляется.

PM MAIL   Вверх
Earnest
Дата 24.6.2010, 09:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Sphinx, можно по-разному. Если нужно сразу загрузить несколько цветов, то можно все их в один битмап засунуть и раскрасить по секциям. Ну примерно так, как ты тулбар рисуешь - посмотри на битмап, соответствующий тулбару, и все поймешь. Граница цветов определяется размерами картинки в ImageList (т.е. ее шириной). ImageList из этого битмапа нарежет себе столько картинок, сколько в нем секций заданной ширины. А потом можно добавлять по одному. Естественно, для добавления битмап создается временный - после запихивания в ImageList хранить его не надо.

Добавлено через 7 минут и 44 секунды
Цитата(Sphinx @  24.6.2010,  10:05 Найти цитируемый пост)
Не уверен в манипуляциях с контекстами - все ли что нужно удаляется.

Цитата(Sphinx @  24.6.2010,  10:05 Найти цитируемый пост)
DeleteDC(hdcCompatible);

Перед этим нужно "освободить" битмап из контекста - пока он выбран, он на самом деле не удалится. Проще всего сохранят то, что возвращает SelectObject, и потом восстанавливать.

Кроме того, нет никакой необходимости создавать и разрушать контекст и битмап в цикле, можно просто перекрашивать.
Т.е. в цикле остается только Filling и ImageList_Add.

И я бы поставила проверку, что ImageList_Add возвращает i: что-то типа VERIFY (ImageList_Add(himl, hbmScreen, NULL) == i);
Даже не столько ради самой проверки, а чтобы показать читателю, что соответствующая цвету картинка имеет индекс i.


--------------------
...
PM   Вверх
Sphinx
Дата 24.6.2010, 09:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 20.7.2006

Репутация: нет
Всего: нет



Цитата(Earnest @  24.6.2010,  09:07 Найти цитируемый пост)
примерно так, как ты тулбар рисуешь

Спасибо, с битмапом понятно, а вот как в таком случае с ImageList? Какой размер указывать и количество. Если реальные, то получится в нем всего один image. 
PM MAIL   Вверх
GremlinProg
Дата 24.6.2010, 09:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Sphinx @  23.6.2010,  21:23 Найти цитируемый пост)
Если сказал А, то говори и Б. Какова последовательность действий для этого?

:))

1. создаешь массив, допустим так:
Код

typedef struct _MyColor{
  COLORREF Rgb;
  LPCTSTR lpszName;
}MyColor;

MyColor Colors[] = {
  { RGB( 255, 0, 0 ), TEXT("красный") },
  { RGB( 0, 255, 0 ), TEXT("зеленый") },
  ...
};

2. создаешь список со стилями LBS_OWNERDRAWFIXED | LBS_NODATA
3. задаешь число его элементов:
Код

::SendMessage( hwndListBox, LB_SETCOUNT, sizeof( Colors ) / sizeof( Colors[0] ), 0 );

4. перехватываешь у родителя WM_DRAWITEM:
Код

case WM_DRAWITEM:
    lpDraw = (LPDRAWITEMSTRUCT)lParam;
    //    если это listbox
    if( lpDraw->CtlType != ODT_LISTBOX ){
        break;
    }
    //    красим фон
    ::FillRect( lpDraw->hDC, &lpDraw->rcItem, ::GetSysColorBrush( COLOR_WINDOPW )  );
    if( itemID < 0 ){
        break;
    }
    //    вычисляем область иконки
    ::SetRect(
        &rcIcon,
        lpDraw->rcItem.left,
        lpDraw->rcItem.top,
        lpDraw->rcItem.left + ( lpDraw->rcItem.bottom - lpDraw->rcItem.top ),
        lpDraw->rcItem.bottom,
    );
    //    вычисляем область текста
    ::SubtractRect( &rcText, &lpDraw->rcItem, &rcIcon  );
    //    рисуем текст
    ::DrawText( lpDraw->hDC, Colors[itemID].Name, -1, &rcText, DT_SINGLELINE | DT_VCENTER );
    //    рисуем иконку
    ::InflateRect( &rcIcon, -1, -1 );
    hBrush    = ::GetStockObject( DC_BRUSH );
    hBrush    = ::SelectObject( lpDraw->hDC, hBrush );
    ::SetDCBrushColor( lpDraw->hDC, Colors[itemID].Rgb );
    ::Rectangle( lpDraw->hDC, rcIcon.left, rcIcon.top, rcIcon.right, rcIcon.bottom );
    hBrush    = ::SelectObject( lpDraw->hDC, hBrush );
    ::DeleteObject( hBrush );
    break;


вроде бы все,
фокус и выделение не рисовал, сам нарисуешь,
код не проверял, принцип должен быть ясен


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Earnest
Дата 24.6.2010, 09:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Размер - это размер картинки, тут сам определись. Он сам определит, сколько отдельных изображений получится. Только тогда нужно использовать не Add, а Load. А потом никто не мешает добавлять картинки по одной, как ты сделал в цикле.

Добавлено через 2 минуты и 26 секунд
А нет, вру. В добавляемом через Add битмапе тоже может содержаться несколько картинок. A Load - это из ресурсов.


--------------------
...
PM   Вверх
Sphinx
Дата 24.6.2010, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 20.7.2006

Репутация: нет
Всего: нет



Цитата(Earnest @  24.6.2010,  09:07 Найти цитируемый пост)
Кроме того, нет никакой необходимости создавать и разрушать контекст и битмап в цикле, можно просто перекрашивать.
Т.е. в цикле остается только Filling и ImageList_Add.

Почему то не получается так. Пока не удален контекст, содержимое битмапа не копируется, хотя ImageList_Add отрабатывает корректно.
Цитата

И я бы поставила проверку, что ImageList_Add возвращает i: что-то типа VERIFY (ImageList_Add(himl, hbmScreen, NULL) == i);

А что, бывают случаи когда индекс начинается не с нуля или перепрыгивает?

Добавлено через 5 минут
GremlinProg, спасибо. Буду разбираться и пробовать.

Добавлено через 14 минут и 51 секунду
Earnest, удалось пользоваться одним битмапом, вот подправленный вариант:
Код

 himl = ImageList_Create(16, 16, ILC_COLORDDB, NUMCOLORS, 0);
 hDC = GetDC(hwndLV);
 hdcCompatible = CreateCompatibleDC(hDC);
 hbmScreen = CreateCompatibleBitmap(hDC, 16, 16);
  for(i=0; i<NUMCOLORS; i++){
    hbakdc=SelectObject(hdcCompatible, hbmScreen);

    FillingColor(hdcCompatible, i );

    SelectObject(hdcCompatible, hbakdc);
    ImageList_Add(himl, hbmScreen, NULL);
  }
  DeleteDC(hdcCompatible);
  DeleteObject(hbmScreen);
  ListView_SetImageList(hwndLV, himl, LVSIL_SMALL);


Это сообщение отредактировал(а) Sphinx - 24.6.2010, 10:07
PM MAIL   Вверх
Earnest
Дата 24.6.2010, 12:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Цитата(Sphinx @  24.6.2010,  11:03 Найти цитируемый пост)
А что, бывают случаи когда индекс начинается не с нуля или перепрыгивает?

Нет, но, во-первых это проверка для того, чтобы лишний раз убедиться, что в ImageLis нет лишних картинок. Ты ведь говорил о том, что нужно добавление динамическое, т.е. в произвольные моменты времени. Т.е. этот код - стартовый.
А кроме того, чтобы читатель понял как извлечь картинку для цвета из ImageList он должен опираться на неявные знания: что ImageList возвращает индекс добавленной картинки, что в нем ровно столько картинок, сколько ты сделал цветов и т.д. Поверь, такие вещи забываются очень быстро, так что код должен помогать читателю.

Странно, что неосвобожденный битмап не копируется, я никогда не сталкивалась, но все возможно.
Я бы тогда создала 1 битмап шириной NUMCOLORS картинок, нарисовала в нем все цвета и добавила все скопом. Т.е. в цикле будет только раскраска прямоугольников (со сдвигом по х, конечно). 


--------------------
...
PM   Вверх
Sphinx
Дата 24.6.2010, 13:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 20.7.2006

Репутация: нет
Всего: нет



Цитата(Earnest @  24.6.2010,  12:25 Найти цитируемый пост)
Нет, но, во-первых это проверка для того, чтобы лишний раз убедиться, что в ImageLis нет лишних картинок

Не соглашусь. Откуда там взяться лишним картинкам, если ImageList только что создан. Вся информация о цвете (его hex-код, текстовое название...) хранится в массиве структур из которого она последовательно выбирается для добавления к ImageList. Поэтому индекс цвета и индекс в массиве структур должны и будут совпадать. При добавлении нового цвета он будет добавляться в конец массива структур и в конец ImageList. Другое дело, если массив структур со свойствами цветов будет сортироваться. Тогда надо будет в него добавлять поле со значением индекса в ListImage. После ImageList_Add надо делать проверку, что функция отработала корректно и если да, то можно сохранить возвращенный индекс в свойствах цвета (если в этом есть необходимость). А делать проверку соответствия возвращеного индекса индексу в массиве структур... не знаю, мне кажется безсмысленно.
PM MAIL   Вверх
Earnest
Дата 24.6.2010, 16:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Цитата(Earnest @  24.6.2010,  13:25 Найти цитируемый пост)
Ты ведь говорил о том, что нужно добавление динамическое, т.е. в произвольные моменты времени. Т.е. этот код - стартовый.

Т.е. ImageList когда-то создан, а потом туда по мере необходимости картинки добавляются.

Но если не хочешь, чтобы
Цитата(Earnest @  24.6.2010,  13:25 Найти цитируемый пост)
код должен помогать читателю.

не надо, убеждать не буду. 




--------------------
...
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0927 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.