Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Картинка в CListCtrl из буфера обмена 
V
    Опции темы
jackevsen
Дата 2.2.2009, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



MFC приложение.Задача следующая: В буфере обмена есть картинка и эту картинку нужно поместить в CListCtrl.Делаю так:

Код

CPaintDC dc(this);
CDC newdc;
 
newdc.CreateCompatibleDC(&dc);
HGDIOBJ pOldBitmap = newdc.SelectObject(icon);
 
//dc.BitBlt(20,20,50,50,&newdc,0,0,SRCCOPY);
 
ListImage.InsertItem(ListImage.GetItemCount(),shText,0);
 
cImageList.Create(32, 32, ILC_COLOR32, 1, 1);
cImageList.Add(newdc.GetCurrentBitmap(),RGB(0,0,0));
ListImage.SetImageList(&cImageList,LVSIL_NORMAL);


CPaintDC dc(this); - здесь this это окно

HGDIOBJ pOldBitmap = newdc.SelectObject(icon); - здесь icon это (HBITMAP)GetClipboardData(uFormat); где uFormat это CF_BITMAP

Ситуация следующая...картинка в буфере обмена есть точно.Если раскомментировать вот эту строчку : //dc.BitBlt(20,20,50,50,&newdc,0,0,SRCCOPY); то картинка нарисуется  на форме.Когда я пытаюсь запихнуть ее в CListCtrl, то у меня появляется только черный квадратик.

Я уже перепробовал разные способы, в том числе создавать CBitmap и запихивать в него icon через FromHandle() и Attach().Ничего не получается...все тот же черный квадратик.

В чем здесь может быть дело?Или я вообще двигаюсь не в том направлении.....? 
PM MAIL   Вверх
Earnest
Дата 3.2.2009, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



1) Если icon - это bitmap (кстати, зачем себе и любям мозги пудритьтакими именами?), то почему ты не помещаешь ее в imageList непосредственно - т.е. просто Add (icon, RGB(...)), зачем это делать через CDC? 
2) Убедись, что картинка по размеру соответствует размеру картинки в image-list и что цвет маски выбран разумный
3) Не вижу, как ты эту картинку присваиваешь итему


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


Новичок



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

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



icon - это HBITMAP, и если сделать так cImageList.Add(icon,RGB(0,0,0)); то на меня наругаются и скажут ,что не могут переконвертить HBITMAP в CBitmap *.
Делал так:
Код

CBitmap bmp;

bmp.FromHandle(icon);

...

cImageList.Add(&bmp,RGB(0,0,0));

...


В этом случае даже черного квадратика не появляется.
Делал так:

Код

CBitmap bmp;

bmp.Attach(icon);

...

cImageList.Add(&bmp,RGB(0,0,0));

...


В этом случае появляется черный квадратик.

CDC я задействовал из-за того, что:
Я пока не очень хорошо разбираюсь в подобных механизмах и в интернете находил код где всегда использовалось CDC.И потом, ради эксперимента я хотел что бы картинка из буфера обмена у меня рисовалась на форме.Эксперимент удался, картинка рисуется, и я подумал раз уж в CDC эта картинка есть, то её можно вытащить и в imageList.Отсюда и строка

cImageList.Add(newdc.GetCurrentBitmap(),RGB(0,0,0));

но в этом случае у меня появляется только черный квадратик.Потом я начал искать пути решения проблемы и пробовал тот код, который написал чуть выше в этом посте.Все равно ничего не получается....
PM MAIL   Вверх
Earnest
Дата 4.2.2009, 08:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Код, где используешь bmp.Attach - правильный, использовать контекст - нафиг не нужно.
Обрати внимание также на остальные пункты моего поста. 

Имена лучше выбирать такие, чтобы они подсказывали, а не путали. Есть тип HICON и есть тип HBITMAP. Если ты битмап обозвал icon, то иконка у тебя будет называться bitmap? Правильные имена очень важны: компилятору-то все равно, а вот коллеги-программисты и побить за такое могут. Я бы точно не удержалась. smile 


--------------------
...
PM   Вверх
jackevsen
Дата 4.2.2009, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Earnest @  4.2.2009,  08:32 Найти цитируемый пост)
Я бы точно не удержалась. smile  


И не сомневаюсь.... В первой же строчке ответа на мою тему: "Ты почему не используешь 9-ю поправку к приложению №276/34 от 7.05.2007, а вместо этого присваиваешь переменным имена по своему разумению.Ты что, не уважаешь комитет по стандартизации?" smile 

В свое оправдание могу сказать, что на работе работаю с языком в котором не важен тип переменой, с каким она объявляется...так как тип этой переменной в функции еще 10 раз поменяться может.А конкретно про имя icon... то это наверное потому, что в свойствах CListCtrl есть свойство View и в нем есть значение Icon....возможно поэтому я эту переменную так назвал  smile И, честно говоря, не думал что придется кусок кода выложить на форуме, так как я это делаю ну в очень запущенных ( для себя ) случаях. 

А так, конечно, про имена переменных полностью согласен.

Теперь по теме....

Что-то у меня не получается.... smile 

А что будет, если размер картинки не соответствует размеру картинки в image-list? Будет видна только часть картинки или она вообще видна не будет?
Такой момент интересный...Когда я все эти манипуляции делаю в OnPaint окна в котором расположен CListCtrl, то у меня в итемах вместо картинки появляются черные квадратики, а если в другой функции , то даже этих квадратиков нету...
Хотя, с другой стороны для эксперимента писал такую строчку: ListImage->SetBkImage(icon,1,bmpInfo.bmHeight,bmpInfo.bmWidth);
и та картинка, которая в буфере обмена,появляется в CListCtrl на заднем плане....Это еще раз доказывает что картинка есть и её можно отобразить....А в итеме никак появляться не хочет.... smile 

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


Эксперт
****


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

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



Цитата(jackevsen @  4.2.2009,  23:23 Найти цитируемый пост)
А что будет, если размер картинки не соответствует размеру картинки в image-list? Будет видна только часть картинки или она вообще видна не будет?

Я точно не помню, но картинка либо вовсе не добавляется, либо вместо нее добавляется что-то типа черного квадрата. Но, во всяком случае, точно не обрезается. Можно проверить - спросить, сколько элементов в imagelist. Кроме того, у imagelist есть всякие функции рисования. Попробуй нарисовать, как ты это делал в первом посте, только через imagelist.
Тебе нужно решать задачу по частям:
1) убедиться, что картинка из clipboard прочитана
2) убезиться, что в imagelist она правильно добавлена
3) и только после этого убедиться, что в итем она правильно попадает
С 1м пунктом ты вроде разобрался, теперь остались 2 других.
Цитата(jackevsen @  4.2.2009,  23:23 Найти цитируемый пост)
....А в итеме никак появляться не хочет.... 

А как ты ее в Item добавляешь?



--------------------
...
PM   Вверх
jackevsen
Дата 5.2.2009, 22:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Я идиот....Нет, я хуже...А еще программистом называюсь....Можно перефразировать один диалог из одной известной передачи:

- Ты что там делал?
- Я программировал.
- Лошара ты, а не программировал!

Когда я добавлял картинку к итему то создавал переменную CImageList прямо в функции отслеживающей изменения в буфере обмена, добавлял его в итем.Кстати, делал это так: ListImage->SetImageList(&cImageList,LVSIL_NORMAL); , а при выходе из функции CImageList  разрушался, следуя правилам видимости переменных....Поэтому картинки видно не было.

Как только я объявил глобальную переменную CImageList cImageList; картинка сразу стала видна в лист контроле.  smile 

Правда теперь другая проблема...Когда я копирую следующую картинку в буфер обмена, то в лист контроле у меня дублируется первая скопированная картинка.... smile Это и понятно, ведь CImageList у меня один и тот же...а это по сути массив картинок и при передачи CImageList лист контролу отображается все та же первая картинка, которая появилась в этом CImageList.

Блин, как же все сложно....теперь нужно решать эту проблему.... smile 

Это сообщение отредактировал(а) jackevsen - 5.2.2009, 23:10
PM MAIL   Вверх
Earnest
Дата 6.2.2009, 08:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Так ты ее не итему добавляешь, а просто устанавливаешь ImageList. Посмотри структуру, которая передается в InsertItem, там есть переменная для номера картинки + еще маску нужно добавить, что ты картинку устанавливаешь. Причем сначала нужно установить контролу ImageList, а потом уже итемы создавать (или картинки им устанавливать).

ImageList конечно, должен жить пока жив список. Поэтому удобнее всего интегрировать его в свой класс-наследник лист-контрола. Создание и присоединение ImageList удобно делать на PreCreateWindow (если контрол динамически создается) или PreSubclassWindow (если ты его в ресурсах на диалог ставишь). Или и там и там, чтобы контрол получился универсальный. Там же можно создавать колонки. 


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


Новичок



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

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



Цитата(Earnest @  5.2.2009,  08:44 Найти цитируемый пост)
А как ты ее в Item добавляешь?


Сам в своем коде запутался...Итему я добавлял картинку так ListImage.InsertItem(ListImage.GetItemCount(),shText,0);

Ну да ладно...с этим я уже разобрался. Переделал добавление на структуру, по твоему совету.  smile 

Как всегда, одна проблема решена, появляется другая.А именно: Я, когда создаю СImageList то делаю размер картинок 100 Х 100.И когда я копирую в буфер картинку большего размера, то эта картинка при добавлении в  СImageList разбивается на несколько картинок одинакового размера, а если я копирую в буфер картинку меньшего размера, то эта картинка вообще не добавляется в СImageList.Поэтом возникла необходимость масштабировать картинку до нужного размера перед добавления её в СImageList.
Делаю так:

Код

CBitmap *bmp,tempBmp;

//Вынимаю данные из буфера обмена
HBITMAP hBitMap = (HBITMAP)GetClipboardData(uFormat);

CPaintDC wndDC(this);
CDC MemDC,imageDC;
BITMAP info;

//Создаю контексты
MemDC.CreateCompatibleDC(&wndDC);
imageDC.CreateCompatibleDC(&wndDC);

//Создаю битмап нужного размера
tempBmp.CreateCompatibleBitmap(&wndDC,100,100);

//Выбираю битмап из буфера обмена в один контекст
HGDIOBJ oldBmp = MemDC.SelectObject(hBitMap);

//Выбираю битмап нужного размера в другой контекст
HGDIOBJ oldImageBmp = imageDC.SelectObject(tempBmp);

//Получаю битпам для того, что бы узнать размер
bmp = MemDC.GetCurrentBitmap();                
bmp->GetBitmap(&info);

//Переписываю битпам из одного контекста в другой
imageDC.StretchBlt(0,0,100,100,&MemDC,0,0,info.bmWidth,info.bmHeight,SRCCOPY);

//Получаю масштабированный битмап
bmp = imageDC.GetCurrentBitmap();

//Запихиваю масштабированный битмап в СImageList                
cImageList->Add(bmp,RGB(0,0,0));


Но у меня появляется черный квадрат....Я вообще правильно делаю масштабирование? 

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


Эксперт
****


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

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




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

Попробуй заменить CPaintDC на CWindowDC или CClientDC или просто GetDC(this) (только не забудь тогда сделать ReleaseDC).


--------------------
...
PM   Вверх
jackevsen
Дата 11.2.2009, 19:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Ура!!! Заработало!!!  smile 

Оказалось, я всего лишь не написал одну строчку, и из-за этой строчки картинки видно не было....Вот эта строчка: imageDC.SelectObject(oldImageBmp);

Тем более, что я видел в других примерах что так нужно делать, но не придал этому такого уж критического значения.
Теперь у меня картинки из буфера обмена красиво попадают в CListCtrl и выглядит это так же как Thumbnails в окне Виндовс.
Вот, окончательный вариант, может кому-то пригодится....

Код

CBitmap *bmp,tempBmp;
                
CPaintDC wndDC(this);
CDC MemDC,imageDC;
BITMAP info;

//Создаю контексты
MemDC.CreateCompatibleDC(&wndDC);
imageDC.CreateCompatibleDC(&wndDC);

//Создаю битмап нужного размера
tempBmp.CreateCompatibleBitmap(&wndDC,100,100);

//Выбираю битмап из буфера обмена в один контекст
HGDIOBJ oldBmp = MemDC.SelectObject(hBitMap);
//Выбираю битмап нужного размера в другой контекст
HGDIOBJ oldImageBmp = imageDC.SelectObject(tempBmp);

//Получаю битпам для того, что бы узнать размер
bmp = MemDC.GetCurrentBitmap();                
bmp->GetBitmap(&info);
                
//Весь этот код для того, что бы картинка красиво отмасштабировалась.
int XDest, YDest, nDestWidth, nDestHeight,TrumbHeight,TrumbWidth;

TrumbHeight = 100;
TrumbWidth = 100;

const float fRatio=(float)TrumbHeight/TrumbWidth;

const float fImgRatio=(float)info.bmHeight/info.bmWidth;
if(fImgRatio > fRatio)
{
    nDestWidth=TrumbHeight/fImgRatio;
    XDest=(TrumbWidth-nDestWidth)/2;
    YDest=0;
    nDestHeight=TrumbHeight;
}
else
{
    XDest=0;
    nDestWidth=TrumbWidth;
    nDestHeight=TrumbWidth*fImgRatio;
    YDest=(TrumbHeight-nDestHeight)/2;
}
                
//Устанавливаю вид копирования
imageDC.SetStretchBltMode(COLORONCOLOR);
//Переписываю битпам из одного контекста в другой
imageDC.StretchBlt(XDest,YDest,nDestWidth,nDestHeight,&MemDC,0,0,info.bmWidth,info.bmHeight,SRCCOPY);
                
//Устанавливаю старые битмапы отбатно в контексты
imageDC.SelectObject(oldImageBmp);
MemDC.SelectObject(oldBmp);

//Запихиваю масштабированный битмап в СImageList 
cImageList->Add(&tempBmp,RGB(0,0,0));

//Удаляю объекты
imageDC.DeleteDC();
MemDC.DeleteDC();
tempBmp.DeleteObject();
bmp->DeleteObject();



Earnest, спасибо за отзывчивость и помощь.  smile , если будут еще проблемы обращусь.  smile 

Ох, как подумаю, сколько еще всего нужно сделать....Следующий шаг это горячие клавиши....Ну,ладно, пойду работать....
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




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


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

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