CreateCompatibleDC для линий и т.п.

Тема в разделе "WASM.WIN32", создана пользователем The Svin, 30 мар 2006.

  1. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    The Svin



    Битмап не обязательно создавать при каждом WM_PAINT. Его можно создать на старте программы и "дорисовывать" по мере необходимости. Ещё вариант: делать BitBlt окно -> MemDC, рисовать в MemDC, опять BitBlt MemDC -> окно. Или рисовать с прозрачностью (использовать флаг XOR в BitBlt). Я обычно использую первый вариант.





    ScrollWindowEx, если я правильно понял, поможет сделать это оптимально быстро.



    cresta



    Фон перерисовывается если того требует InvalidateRect и окно имеет фоновую кисть. Винда не навязывает обработку WM_ERASEBKGND.
     
  2. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia


    Это я попробывал с самого начала - не получилось.

    Получается пока только если создать CompatibleBitmap на основе полученного контекста (неважно от BeginPaint или GetDC) и удалить его после EndPaint.







    Наверно неправильно всё-таки я объяснил.

    Под скролом имеется ввиду изменение содержание графика в зависимости от перемещения управляющими кнопками по дампу сигнала. Т.е. там принцип как в Hiew только в графическом смысле. На экран выводится обрабатывается в графическом виде только та часть дампа сигнала которую можно отобразить в диапозоне вывода.

    Т.е. как в Hiew - меняется лишь точка - оффсет начала выводимого куска. Если это делать как делает IDA - т.е. вываливать в окно всё что дали, мы состарится успеем. Там тучу преобразований, выделений разных фильтров и т.п. приходится применять. Если каждый раз всё валить на экран полностью - с ума сойдёшь.
     
  3. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia
    Получилось сделать чтоб битмап создавался один раз.

    Всё одно прибавки в скорости не заметил.

    Ну проценты может какие - 10-15%.

    Не в разы.

    Видимо сами LineTo функции жутко медленные.

    Ладно, простых решений не получилось найти.

    Будем придумывать какую-нить математику с прямым доступом к байтам битмапа что-ли :)
     
  4. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine


    Этот вариант не подошёл из-за специфики поставленной задачи, или не получилось создать на старте битмап? Вместо реального DC окна можно использовать хоть DC десктопа в качестве параметра CreateCompatibleBitmap. Потом храним эту картинку в глобальной переменной и подгружаем в настоящий DC через memory DC + BitBlt. Получается, что рисуем как-бы в оффлайне. Этот вариант работает быстрее, т.к. не приходится выделять память под картинку при каждом WM_PAINT.



    Пожалуй, я тоже уточню... Функция ScrollWindowEx годится, если надо "сдвинуть" текущее содержание окна и дорисовать в тот участок, который раньше не был виден. К примеру, панели со скролл-барами обычно используют эту функцию.
     
  5. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia
    Спасибо участникам. Вы очень помогли мне стартануть в этой области, без черепно мозговых травм :)
     
  6. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia


    Может быть это и пригодилось если бы изначально делалось по этой концепции. Т.е. чтоб для графика отдавалось какое-то окно. Сейчас график - это просто кусок другого окна в который выводится графическая информация. Там на нём несколько участков под графики, под управление и т.п.

    Т.е. определяется интерфейс чисто математическими \ геометрическими рассчётами. В реальности вся куча различных объектов - просто области одного и того же окна.
     
  7. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine


    Да, около того.





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





    Лучше SetDIBits использовать.





    Да, я забыл, что это поверх диалога рисуется. Ясно.
     
  8. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia


    Буду благодарен если в общих чертах опишишь концепцю работы с ней.

    Главное что интересует - как полученые\установленные байты, согласуются с координатами пикселей на экране.

    Что б понимать какие пиксели я изменяю изменяя байты битмапа.
     
  9. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia


    Получилось уже. Сам не пойму почему сначала незаладилось.

    Спасибо.
     
  10. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257




    Пример самодельного шрифта:)

    Пиксели устанавливаются непосредственно в области памяти, занимаемой картой бит в соответствие с маской шрифта. С последующим выводом в hDC окна при помощи SetDIBitsToDevice

    Никаких CreateCompatibleDC, CreateCompatibleBitmap, FillRect, BitBlt, LineTo e.t.c.

    Битмап делается вручную в памяти.



    [​IMG] _1591842000__Draw.zip
     
  11. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Краткий мануал по SetDIBits:



    1й параметр этой функции - реальный экранный DC любого окна (к примеру,
    Код (Text):
    1. hDC = GetDC(0)
    сойдёт)



    2й параметр - объект HBITMAP. Этот битмап не должен находиться ни в каком DC. Пример:
    Код (Text):
    1. hBmp = CreateCompatibleBitmap(hDC,400,400);




    3й параметр - с какой линии начинать копировать данные в битмап. Самая первая линия - 0, но расположение этой линии (верх или низ) зависит от заголовка битмапа в 6м параметре.



    4й парам - сколько линий скопировать.



    5й парам - собственно, байты с пикселями. Формат зависит от заголовка.



    6й парам - заголовок битмапа в формате BITMAPINFO. Он определяет как будут обработаны предыдущие параметры: размер картинки, глубина цвета, картинка вверх ногами или нормальная и т.д.



    7й парам. Тут обычно указывают DIB_RGB_COLORS. Хотя считается, что быстрее всего рисовать через палитру (DIB_PAL_COLORS), но разобраться с палитрой без черепномозговых последствий нереально. Палитры не поддерживаются на многих современных картах, а на некоторых, кажется, лишь эмулируются. В общем, я тут всегда пишу DIB_RGB_COLORS :)



    Вот более полный пример:


    Код (Text):
    1. BITMAPINFOHEADER bih={0};
    2. RGB pBmpBytes[400 * 400];
    3. bih.biSize = sizeof(BITMAPINFOHEADER);
    4. bih.biCompression = BI_RGB;
    5. bih.biWidth = 400;
    6. bih.biHeight = -400; // чтоб не вверх ногами
    7. bih.biPlanes = 1;
    8. bih.biBitCount = 24;
    9. bih.biSizeImage = 0;
    10. hDC = GetDC(0);
    11. hBMP = CreateCompatibleBitmap(hDC,400,400);
    12. if(hBMP){
    13.    // pBmpBytes указывает на массив с пачками RGB
    14.    SetDIBits(hDC,hBmp,0,400,pBmpBytes,(BITMAPINFO*)&bih,DIB_RGB_COLORS);
    15. }




    Чтоб нарисовать чёрную точку по координатам (2,5) пишем 0 по адресу pBmpBytes[5 * 400 + 2] = 0x000000; и вызываем предыдущий код.
     
  12. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia
    Т.е. по байту на пиксель?

    Или могут быть различные размеры байт на пиксель.

    Я думал это зависит от цветового разрешения?

    Т.е. в общем виде типа

    y*pixelsize*Width + x*pixelsize.

    Где y,x координаты пикселя, а pixelsize - сколько байт уходит на описание пикселя.



    Если так - где брать сколько байт уходит на пиксель?

    Вот допустим получил я дамп bmp через GetDIBits.

    Где это значение брать\вычислять?
     
  13. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    The Svin



    Только если в гамме 256 цветов или используется палитра из 256 ячеек. В общем случае, если использовать RGB, то по 32 бит на пиксель.





    Точнее, от bih.biBitCount, а это и есть разрешение.





    Или так:

    pixelsize * (y*width + x)

    Т.к. массив в моём примере состоит из пакетов RGB, то компилятор сам добавляет множитель 4 для pixelsize. RGB - это unsigned int.
     
  14. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia
    В примере

    bih.biBitCount = 24

    так это три байта или четыре? Если по битам - три.

    Но может они пакуются в размеры по степеням двойки?

    1,2,4? Т.е. с округлением вверх до ближайшей степени?

    Например если biBitCount = 4 то всё одно пиксель будет занимать байт (а не поля по 4е бита), а если 24 то

    24/8=3 округляется -> 4 ?
     
  15. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    The Svin



    Хороший вопрос. Судя по последнему приложению, в котором я использовал эту функцию и тому факту, что приложение не падает - 3 байта. Так что множитель в предыдущем примере = 3.





    В 16-цветном разрешении каждый байт хранит 2 пикселя. В Ч/Б картинках 1 бит = 1 пиксель, 1 байт = 8 пикселей. Хотя, если указать флаг RGB, то и 16-цветные и Ч/Б пиксели будут занимать 3 байта. В конечном счёте, всё зависит от заголовка битмапа, а не от разрешения.



    Кстати! Нужно учитывать ещё и тот факт, что если ширина картинки не кратна 8, то в массив нужно добавлять "паддинг" после каждой линии. У Вас ширина = 400. Выравнивание в данном случае не нужно.
     
  16. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Можно попробовать вот что:



    1. Приходит WM_PAINT

    2. Берём GetDC() и "фотографируем" его в битмап

    3. На этой же самой битмап рисуем линии и всё остальное

    4. Обязательно вызываем BeginPaint()

    5. Делаем BitBlt() на полученный HDC

    6. Вызываем EndPaint()



    По теории - должно работать.

    Могу попробовать на практике если будет время.
     
  17. The Svin

    The Svin New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    665
    Адрес:
    Russia


    Не очень понимаю, что фотографируем в битмап?

    Содержание окна?

    А как?
     
  18. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto