Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Как отобразить иконку 32bit в Picturebox или чем-то другом. / 7 сообщений из 7, страница 1 из 1
31.07.2010, 04:23
    #36769356
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как отобразить иконку 32bit в Picturebox или чем-то другом.
Надо просто отобразить иконку на Picturebox.
Иконка 32bit (с тенями), размер предполагается 48x48 (или больше).
Bitmap 24 bit не годится, фигня-с.

Что умею:
1) Засунуть иконку в ресурсы. Сначала скажем 256 цветов, но после компиляции exe меняю ее на правильную (процесс автоматизирован через bat-файл)
2) Умею ее достать оттуда
Код: plaintext
lngIcon = LoadImage(App.hInstance, MAKEINTRESOURCE( 301 ), IMAGE_ICON,  48 ,  48 , LR_DEFAULTCOLOR)
3) Умею впихнуть ее в API-ImageList например
Код: plaintext
1.
m_hImlBIG = ImageList_Create( 48 ,  48 , ILC_MASK Or ILC_COLOR32,  1 ,  0 )
ImageList_ReplaceIcon m_hImlBIG, - 1 , lngIcon

Знаю напр. как сделать 32-х битный Toolbar, Listview, Treeview и т.п. Собственно задача казалась простой... но чет не соображу как эту 32-битность просто вставить в Picturebox . На Picturebox свет клином не сошелся, можно что нибудь другое. Извращенные идеи уже посещали типа Toolbar какой-нибудь накатать из одной кнопки в режиме enabled=false, но эт...почище Виста-стилей будет, там фон белый у меня должен быть...
Сложные модули с перечислением всего что есть в GDI+/- или попиксельный разбор содержимого иконки со всеми альфа-подканалами тоже конечно нежелательны ради такой ерунды (хотелось бы остаться в этом приятном надеюсь не заблуждении).
...
Рейтинг: 0 / 0
31.07.2010, 12:14
    #36769440
Бенедикт
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как отобразить иконку 32bit в Picturebox или чем-то другом.
Дмитрий77,

попробуйте LoadImage - DrawIconEx (сам не пробовал).
...
Рейтинг: 0 / 0
31.07.2010, 17:09
    #36769544
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как отобразить иконку 32bit в Picturebox или чем-то другом.
Бенедикт,

попробовал, спасибо
вот так вроде оптимально будет

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
Private Declare Function DrawIconEx Lib "user32" (ByVal hdc As Long, ByVal xLeft As Long, ByVal yTop _
As Long, ByVal hIcon As Long, ByVal cxWidth As Long, ByVal cyWidth As Long, ByVal istepIfAniCur _
As Long, ByVal hbrFlickerFreeDraw As Long, ByVal diFlags As Long) As Long
Private Declare Function DestroyIcon Lib "user32" (ByVal hIcon As Long) As Long

Private Const DI_MASK = &H1
Private Const DI_IMAGE = &H2
Private Const DI_NORMAL = DI_MASK Or DI_IMAGE

Dim lngIconPICT As Long

Private Sub Form_Load()
    lngIconPICT = LoadImage(App.hInstance, MAKEINTRESOURCE( 301 ), IMAGE_ICON,  48 ,  48 , LR_DEFAULTCOLOR)
...
Private Sub Form_Paint()
    Picture1.Picture = LoadPicture() 'очистка, иначе черные контуры и т.п.
    'Draw the icon
    DrawIconEx Picture1.hdc,  0 ,  0 , lngIconPICT,  0 ,  0 ,  0 ,  0 , DI_NORMAL 'перерисовываем иначе сотрется как ластиком
End Sub

Private Sub Form_Unload(Cancel As Integer)
    'remove the icon from the memory
    DestroyIcon lngIconPICT
End Sub
Вроде все хорошо и просто.

Здесь один теор. вопрос наверное.
Насколько необходимо
Код: plaintext
   DestroyIcon lngIconPICT
Или оно и так очистится при закрытии приложения?

Я один раз на этом накололся
По таймеру (0,5сек) непрерывно обновлял картинку 16х16 в StatusBar (разные картинки в завис. от условия)
кодом типа
Код: plaintext
1.
2.
    lngIcon = LoadImage(App.hInstance, MAKEINTRESOURCE...
    .picture=lngicon...
    (без Destroy и каждый раз загружая по новой из ресурса)
Забыл закрыть приложение и через наверно 5 часов оно сдохло. Тогда понял ошибку.
...
Рейтинг: 0 / 0
31.07.2010, 19:22
    #36769609
Бенедикт
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как отобразить иконку 32bit в Picturebox или чем-то другом.
Дмитрий77,

"Cтирается как ластиком" если у PictureBox-а AutoRedraw = False. Если True, то можно отрисовать один раз и сделать Refresh. Но в этом случае не будет автоматического обновления при смене цветовой схемы. Поэтому я бы тоже оставил False, разве что отрисовку вынес в Picture1_Paint, очистку через Picture1.Cls.

Вопрос про освобождение ресурсов не теоретический (лучше перебдеть). В данном случае особенности освобождения явно оговариваются в описании функции LoadImage:MSDN, LoadImageWhen you are finished using a bitmap, cursor, or icon you loaded without specifying the LR_SHARED flag, you can release its associated memory by calling one of the functions in the following table.
ResourceRelease function BitmapDeleteObject CursorDestroyCursor IconDestroyIconThe system automatically deletes these resources when the process that created them terminates, however, calling the appropriate function saves memory and decreases the size of the process's working set.
...
Рейтинг: 0 / 0
31.07.2010, 19:57
    #36769640
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как отобразить иконку 32bit в Picturebox или чем-то другом.
Бенедиктразве что отрисовку вынес в Picture1_Paint, очистку через Picture1.Cls.
Picture1.Cls не срабатывает, м.б. потому что PictureBox изначально заряжен простенькой VB-compatible иконкой, вижу ее фон...
Но судя по черным контурам вокруг новой картинки, дело не в исходной.
Код: plaintext
1.
2.
3.
4.
5.
Private Sub Picture1_Paint()
    Picture1.Picture = LoadPicture() 'очистка, иначе черные контуры и т.п.
    'Picture1.Cls
    'Draw the icon
    DrawIconEx Picture1.hdc,  0 ,  0 , lngIconPICT,  0 ,  0 ,  0 ,  0 , DI_NORMAL 'перерисовываем иначе сотрется как ластиком
End Sub
устроило мелькалку, полагаю такое содержимое Picture1_Paint перевызывает циклически ее же саму.
Пришлось вышибать через Alt+Ctrl+Del.
Остановился на своем варианте как на оптимально-безглючном.

БенедиктВопрос про освобождение ресурсов
Исходя из ваших доводов, понял что таки лучше не пренебрегать

Я крайнее время сплошь и рядом использую такой механизм загрузки ImageList (для ListView, Treeview и т.п.)

Код: plaintext
1.
2.
3.
4.
5.
        m_himl = ImageList_Create( 16 ,  16 , ILC_MASK Or ILC_COLOR32,  21 ,  0 )
        lngIcon = LoadImage(App.hInstance, MAKEINTRESOURCE( 101 ), IMAGE_ICON,  16 ,  16 , LR_DEFAULTCOLOR)
        ImageList_ReplaceIcon m_himl, - 1 , lngIcon
        lngIcon = LoadImage(App.hInstance, MAKEINTRESOURCE( 102 ), IMAGE_ICON,  16 ,  16 , LR_DEFAULTCOLOR)
        ImageList_ReplaceIcon m_himl, - 1 , lngIcon
... 

Т.е единственная переменная lngIcon на эдак 20 картинок, и я ее не освобождаю.
Надо (DestroyIcon lngIcon)? Один раз? Сразу после того как сформировал ImageList?
Или забить? За несколько месяцев эксплуатации проблем и претензий не возникало...
...
Рейтинг: 0 / 0
02.08.2010, 22:52
    #36771983
Бенедикт
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как отобразить иконку 32bit в Picturebox или чем-то другом.
Дмитрий77,

я имею ввиду, с учётом проявившихся подробностей,
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Dim lngIconPICT As Long

Private Sub Form_Load()
 lngIconPICT = LoadImage(...)
 Set Picture1.Picture = Nothing 'очистка от имеющейся иконки
 Picture1.AutoRedraw = False
End Sub

Private Sub Form_Unload(Cancel As Integer)
 'remove the icon from the memory
 If lngIconPICT Then DestroyIcon lngIconPICT
End Sub

Private Sub Picture1_Paint()
 'Draw the icon
 DrawIconEx Picture1.hDC,  0 ,  0 , lngIconPICT,  0 ,  0 ,  0 ,  0 , DI_NORMAL 'перерисовываем иначе сотрется как ластиком
End Sub
Впрочем, это мелочная оптимизация.Дмитрий77Исходя из ваших доводов, понял что таки лучше не пренебрегатьКонечно.
авторЯ крайнее время сплошь и рядом использую такой механизм загрузки ImageList...
Или забить? За несколько месяцев эксплуатации проблем и претензий не возникало...По описаниюImageList_ReplaceIconBecause the system does not save hicon , you can destroy it after the function returns if the icon or cursor was created by the CreateIcon function. You do not need to destroy hicon if it was loaded by the LoadIcon function; the system automatically frees an icon resource when it is no longer needed.на 20 штук можно забить, если ресурсы ну совсем уж не поджимают (но чуть-чуть о будущем читателе кода (чаще всего о себе, любимом) позаботиться, оставив об этом комментарий). Либо всё же удалить, если больше в программе не нужны, на ImageList это не повлияет.

P. S. Между "конечно" и "можно забить" противоречия нет. Просто, кроме того, что явное освобождение ресурса вляется "хорошим поведением" прикладной программы, оно самоописательно. "Можно забить" - такой же легальный выбор, но он а) чреват, в чём вы сами убедились, б) вызывает вопросы у того, кто код читает (так что неплохо сказать читателю хотя бы об осознанности этого выбора).

P.P.S Компромисом с точки зрения технологичности является использование объектной обёртки системной сущности (в данном случае, например, экземпляр COM-объекта, поддерживающий интерфейс IPictureDisp, созданный через OleCreatePictureIndirect()), так как при выходе из области или переинициализации объектной переменной системные ресурсы освобождаются автоматически.
...
Рейтинг: 0 / 0
03.08.2010, 02:50
    #36772106
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как отобразить иконку 32bit в Picturebox или чем-то другом.
Бенедиктя имею ввиду, с учётом проявившихся подробностей... Впрочем, это мелочная оптимизация.
Бенедикт, а сами пробовали?
Код: plaintext
1.
 Set Picture1.Picture = Nothing 'очистка от имеющейся иконки
Изначальную иконку я могу и так стереть...исторически забита туда в конструкторе, ну и ладно...
Дело не в этом. Обратите внимание, что я стираю "остатки", что есть в Picturebox перед каждой рисовкой, и это выполнять надо не один раз, а перед каждой новой рисовкой картинки, иначе картинка (уж как не знаю, я хотел простого кода, я его получил, простой код не предполагает разбора скелета по косточкам) интерферирует сама с собой и дает черные контуры как на 24-bit bmp. Думаю если не брать 32-bit, то этого эффекта не будет вовсе, надо именно 32bit...
Хотя согласен, чтобы воспроизвести то о чем говорим надо кучу кода добавить и еще подмену в самом exe сделать, Вам конечно не проблема, а с другой стороны все равно время надо...Вам смысл проверять? Ну если только из любви к искусству, я сам такой во многих вопросах...
Я таки воспользуюсь здесь мыслию "мелочная оптимизация" и оставлю свой вариант.

Бенедикта) чреват, в чём вы сами убедились
я там если вы про это
Дмитрий77Я один раз на этом накололся
По таймеру (0,5сек) непрерывно обновлял картинку 16х16 в StatusBar (разные картинки в завис. от условия)
кодом типа

Код: plaintext
1.
2.
    lngIcon = LoadImage(App.hInstance, MAKEINTRESOURCE...
    .picture=lngicon...
    (без Destroy и каждый раз загружая по новой из ресурса)

то я там допустил гораздо более грубую ошибку.
Я не просто не освобождал ресурс на протяжении программы, а каждые 0,5сек в теч. нескольких часов захватывал новый.
То что сдохла не скоро, с одной стороны говорит о достаточно большом запасе "прочности", с одной стороны, т.е. 20 иконок для ImageList это всего лишь 10секунд (из 5-ти критических часов).
С другой стороны
Дмитрий77Надо (DestroyIcon lngIcon)? Один раз? Сразу после того как сформировал ImageList?
надо наверно освобождать не один раз, а после добавления каждой очередной иконки, ибо забить переменную новым значением отнюдь не означает освободить ресурс. Это означает забыть навсегда адрес ресурса. Не так ли?

Аккуратности конечно учиться надо, приходит со временем полагаю, и на будущее я это учту(про освобождение), но на самом деле...столько "неаккуратностей".
В свое время вы меня чуть научили премудростям GDI+-. И я именно его и стараюсь использовать. Но то что я сам нарыл нерез Wia-как-там ее так и осталось местами (на пару с GDI в одном exe к примеру). Причем понимаю ведь, что лишние 2MB dll за собой таскаю. Но руки не доходят. Начнешь менять, всплывет куча всего и чего-нибудь забудешь...а компилятор не всегда подскажет.
Другой пример...у меня ушло больше месяца чтобы аккуратно поменять в 2-х (не маленьких) exe Common Control 6 => Control5+API, но я таки на это решился и оно себя оправдало.
...а потом пришлось еще возиться, чтобы Toolbar(Control-5) поменять на Toolbar-чисто API. Но оно себя опять оправдало (Виста заливки). А если бы я скажем стал писать прогу сразу с Toolbar-API, то я бы сразу расстроился и забил бы навсегда и на все. Поэтому все относительно и всему свое время...
В данном случае меня "мой вариант" с одной картинкой более чем устраивает...
Ну, увидел в другой проге (прога очевидно C++ и писана на высоком профессиональном уровне) знакомую иконку-стандартную виндовскую и с черными контурами, и подумал, как так можно такой ляп, ведь люди же профи, да еще за новую версию своей проги вот с этой вот паршивой иконкой новых денег хотят (а у меня лицензия кстати, мне как законному юзеру стало неприятно). Ну думаю, надо у себя сделать лучше...
Когда-нибудь надо будет нарисовать несколько картинок м.б. не 48x48 а 1048x1048, тогда я задумаюсь по новой, вспомню этот топик, и буду искать ответ...
...
Рейтинг: 0 / 0
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Как отобразить иконку 32bit в Picturebox или чем-то другом. / 7 сообщений из 7, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]