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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> HBITMAP from HDC, Как из HDC вытащить БитМап 
V
    Опции темы
LED
Дата 20.9.2008, 18:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Нужен способ создать при выполнении битмап и нарислвать нечто в нем.
Как я понял, напрямую в  битмапах рисовать нельзя, поэтому приходится создать HDC и рисовать в нем.
Вопрос в том как сделать так, чтобы результаты рисования оказались потом в битмапе
PM MAIL Jabber   Вверх
mekhanikus
Дата 21.9.2008, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вольноопределяющийся
*


Профиль
Группа: Участник
Сообщений: 186
Регистрация: 16.6.2008
Где: Спасск-Дальний

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



Например так:

Код

CreateCompatibleDC
CreateCompatibleBitmap
SelectBitmap



PM MAIL   Вверх
LED
Дата 21.9.2008, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



пробовал селектить битмап в хдц, потом копал в этот хдц из нужного, но когда переселектил битмап в другой хдц, в битмапе ничего того что рисовал не оказалось
PM MAIL Jabber   Вверх
BEOWOLF
Дата 21.9.2008, 20:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Вот пример рабочей функции для снятия скриншота с экрана, функции передаётся rect-прямоугольная область, откуда берётся скриншот.
Код

static HBITMAP CALLBACK ShootDesktop(const CRect& rect)
{
    HDC hdcScreen = CreateDC(TEXT("DISPLAY"), 0, 0, 0); // make virtual screen device context
    HDC hdcCompatible = CreateCompatibleDC(hdcScreen); // make memory device context
    HBITMAP hbmScreen = CreateCompatibleBitmap(hdcScreen, rect.Width(), rect.Height());
    hbmScreen = (HBITMAP)SelectObject(hdcCompatible, hbmScreen); // push bitmap to memory HDC
    BitBlt(hdcCompatible, 0, 0, rect.Width(), rect.Height(), hdcScreen, rect.left, rect.top, SRCCOPY);
    hbmScreen = (HBITMAP)SelectObject(hdcCompatible, hbmScreen); // rotate back bitmap
    DeleteDC(hdcCompatible);
    DeleteDC(hdcScreen);

    return hbmScreen;
}
Дальше эту битовую матрицу можно например сохранить в файл, например в формате PNG:
Код

Gdiplus::Bitmap image(hbmScreen, 0);
CLSID formatClsid;
GetEncoderClsid(L"image/png", formatClsid);
image.Save(L"screen.png", &formatClsid, NULL);
или отобразить на экране через BitBlt в сообщении WM_PAINT. Или скопировать в буфер обмена.
Код

    OpenClipboard(hWnd);
    EmptyClipboard();
    SetClipboardData(CF_BITMAP, hbmScreen);
    CloseClipboard(hWnd);

PM MAIL   Вверх
LED
Дата 21.9.2008, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Писал такую функцию
Код

HANDLE ExpandImage (HANDLE hImgSrc, POINT ptSize)
    {
        POINT Curr;
        POINT Src;
        BITMAP bm;
        HDC hdc = CreateDC (L"Display", 0, 0, 0),
            hPattern = CreateCompatibleDC (hdc),
            hTarget = CreateCompatibleDC (hdc);
        HANDLE hGdiOrig = 0, hImgTarget = CreateCompatibleBitmap (hdc, ptSize.x, ptSize.y);
        GetObject (hImgSrc, sizeof (BITMAP), &bm);
        hGdiOrig = SelectObject (hPattern, hImgSrc);
        hImgTarget = SelectObject (hTarget, hImgTarget);

        Curr.x = 0;
        while (Curr.x < ptSize.x)
        {
            Curr.y = 0;
            while (Curr.y < ptSize.y)
            {
                Src.x = bm.bmWidth/3;
                Src.y = bm.bmHeight/3;
                if (Curr.y == 0) Src.y = 0;
                if (Curr.y >= (ptSize.y) - bm.bmHeight/3)
                {
                    Src.y = 2*(bm.bmHeight/3);
                    Curr.y = (ptSize.y) - bm.bmHeight/3;
                }
                if (Curr.x == 0) Src.x = 0;
                if (Curr.x >= (ptSize.x) - bm.bmWidth/3)
                {
                    Src.x = 2*(bm.bmWidth/3);
                    Curr.x = (ptSize.x) - bm.bmWidth/3;
                }
                BitBlt (
                        hTarget,
                        ptSize.x + Curr.x,
                        ptSize.y + Curr.y,
                        bm.bmWidth/3,
                        bm.bmHeight/3,
                        hPattern,
                        Src.x,
                        Src.y,
                        SRCCOPY);
                Curr.y += bm.bmHeight/3;
            }
            Curr.x += bm.bmWidth/3;
        }
        if (hGdiOrig) SelectObject (hPattern, hGdiOrig);
        hImgTarget = SelectObject (hTarget, hImgTarget);
        DeleteDC (hTarget);
        DeleteDC (hPattern);
        DeleteDC (hdc);
        return hImgTarget;
    }


При дальнейшем использовании полученного битмапа вижу белые прямоуголиник
Код рисования внутри цикла while должен быть правильным (уже давно служит и отлажен)
Где может быть косяк?
PM MAIL Jabber   Вверх
LED
Дата 21.9.2008, 23:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



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

    HANDLE ExpandImage (HANDLE hImgSrc, POINT ptSize)
    {
        POINT Curr;
        POINT Src;
        BITMAP bm;
        HDC hdc = CreateDC (L"Display", 0, 0, 0),
            hPattern = CreateCompatibleDC (hdc),
            hTarget = CreateCompatibleDC (hdc);
        HANDLE hGdiOrig = 0, hImgTarget = CreateCompatibleBitmap (hdc, ptSize.x, ptSize.y);
        GetObject (hImgSrc, sizeof (BITMAP), &bm);
        hGdiOrig = SelectObject (hPattern, hImgSrc);
        hImgTarget = SelectObject (hTarget, hImgTarget);

        Curr.x = 0;
        while (Curr.x < ptSize.x)
        {
            Curr.y = 0;
            while (Curr.y < ptSize.y)
            {
                Src.x = bm.bmWidth/3;
                Src.y = bm.bmHeight/3;
                if (Curr.y == 0) Src.y = 0;
                if (Curr.y >= ptSize.y - bm.bmHeight/3)
                {
                    Src.y = 2*(bm.bmHeight/3);
                    Curr.y = ptSize.y - bm.bmHeight/3;
                }
                if (Curr.x == 0) Src.x = 0;
                if (Curr.x >= ptSize.x - bm.bmWidth/3)
                {
                    Src.x = 2*(bm.bmWidth/3);
                    Curr.x = ptSize.x - bm.bmWidth/3;
                }
                BitBlt (
                        hTarget,
                        Curr.x,
                        Curr.y,
                        bm.bmWidth/3,
                        bm.bmHeight/3,
                        hPattern,
                        Src.x,
                        Src.y,
                        SRCCOPY);
                Curr.y += bm.bmHeight/3;
            }
            Curr.x += bm.bmWidth/3;
        }
        if (hGdiOrig) SelectObject (hPattern, hGdiOrig);
        hImgTarget = SelectObject (hTarget, hImgTarget);
        DeleteDC (hTarget);
        DeleteDC (hPattern);
        DeleteDC (hdc);
        return hImgTarget;
    }



Это сообщение отредактировал(а) LED - 21.9.2008, 23:08
PM MAIL Jabber   Вверх
mekhanikus
Дата 22.9.2008, 11:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вольноопределяющийся
*


Профиль
Группа: Участник
Сообщений: 186
Регистрация: 16.6.2008
Где: Спасск-Дальний

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



Код поковыряю на досуге.
А пока глупый вопрос.
Ты, я так понял, Expand'иш Image?
А нельзя ли для этого использовать StretchBlt?
PM MAIL   Вверх
LED
Дата 22.9.2008, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Тут очень хитрый expand - рамка шириной в треть от всей картинки растягивается без изменения ширины. а внутренности заполняются сердцевиной.
PM MAIL Jabber   Вверх
malor
  Дата 10.6.2011, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(BEOWOLF @  21.9.2008,  20:52 Найти цитируемый пост)
Дальше эту битовую матрицу можно например сохранить в файл, например в формате PNG:
Код

Gdiplus::Bitmap image(hbmScreen, 0);
CLSID formatClsid;
GetEncoderClsid(L"image/png", formatClsid);
image.Save(L"screen.png", &formatClsid, NULL);

У меня на третью строчку ругается:
Цитата
Error    1    error C3861: 'GetEncoderClsid': identifier not found

Прописывание строки 
#include <Gdiplus.h>
недостаточно?

Это сообщение отредактировал(а) malor - 12.6.2011, 11:09
PM MAIL   Вверх
xvr
Дата 12.6.2011, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(malor @  10.6.2011,  17:12 Найти цитируемый пост)
У меня на третью строчку рушается:

Эту функцию надо написать самому, или скопировать отсюда

PM MAIL   Вверх
malor
  Дата 12.6.2011, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Код такой:
Код

VOID CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwtime)
{
    HDC hdesktopDC;
    HDC memDC;
    DWORD dwWidth;
    DWORD dwHeight;
    HBITMAP hBMP;
    int result;

    // Создаем скриншот экрана
    hdesktopDC = ::GetDC(0);
    memDC = CreateCompatibleDC(hdesktopDC);
    dwWidth = GetDeviceCaps(hdesktopDC, HORZRES);
    dwHeight = GetDeviceCaps(hdesktopDC, VERTRES);
    hBMP = CreateCompatibleBitmap(hdesktopDC, dwWidth, dwHeight);
    BitBlt(memDC, 0, 0, dwWidth, dwHeight, hdesktopDC, 0, 0, SRCCOPY);
    hBMP = (HBITMAP)SelectObject(memDC, hBMP);

    CLSID formatClsid;
    Gdiplus::Bitmap image(hBMP, 0);
    result = GetEncoderClsid(L"image/jpeg", &formatClsid);
    image.Save(L"screen.jpeg", &formatClsid, NULL);
    ..................... etc .................................
}

После строки 
    result = GetEncoderClsid(L"image/jpeg", &formatClsid);
компилятор встает на строчку
    Gdiplus::Bitmap image(hBMP, 0);
т.е. предыдущую строку кода, эффект как от нажатия клавиши F5 (идти до следующего breakpont'а).
Зашел по F11 внутрь  функции GetEncoderClsid(...):
она там прекращает свое продвижение на строке
   GetImageEncodersSize(&num, &size);
делая выход.

Почему ?
user posted image
PM MAIL   Вверх
xvr
Дата 12.6.2011, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Либо вы пытаетесь отлаживать оптимизированный код, или забыли пересобрать код после модификаций сорцов.

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "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.1385 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


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

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