Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по Delphi (до версии 2009) - часть 5

Модерирует : ShIvADeSt

ShIvADeSt (19-05-2010 05:14): Продолжаем тут http://forum.ru-board.com/topic.cgi?forum=33&topic=11215  Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

   

ShIvADeSt



Moderator
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Продолжение темы Вопросы по Delphi (до версии 2009) - часть 4

Познаем сами, помогаем другим...
Обсуждаем вопросы, не связанные с юникоидными версиями Delphi - для этого есть соответствующая тема (см. ссылки ниже).

Правила топика:
    Прежде чем спрашивать:
  1. Желательно изучить вопрос, попытаться найти ответ в прилагаемых мануалах, хелпах и анализируя исходники.
  2. Выполнить поиск по топику (открыть "Версия для печати" и поискать ответ там).
  3. Применить фильтр по разделу "Прикладное программирование". Ответы на многие старые вопросы могли быть даны в отдельных темах.
  4. Продумайте вопрос. На поверхностные вопросы вы получите поверхностные ответы, или вообще ответов не получите.
  5. Желательно указывать версии используемого компилятора и операционной системы.
    Прежде чем отвечать:
  1. Если не можете помочь, не мешайте.
  2. Если уж вы отвечаете на вопрос, давайте ответ по сути.
  3. Если вы не уверены, так и говорите! Ошибочный, но авторитетно звучащий ответ хуже, чем отсутствие ответа.
  4. Задавайте дополнительные вопросы, чтобы получить больше информации.
  • Отсутствие ответа не равносильно игнорированию - иногда участники форума просто не знают ответ. Повторная посылка вопроса не приветствуется. Посты типа "неужели никто не знает ответа..." или "может мне все-таки кто-нибудь ответит" недопустимы.  
  • Все большие куски кода (более 5 строк) оформляем в тег [morе] дабы уменьшить размер поста. FAQ по тегу [morе].

  • Всего записей: 3956 | Зарегистр. 29-07-2003 | Отправлено: 02:09 28-06-2009 | Исправлено: psa1974, 12:00 02-02-2010
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    А зачем вам эти GetDIBits/SetDIBits? CreateDIBSection ведь и так возвращает четвертым параметром ссылку на область памяти. Но в любом случае вам надо будет учитывать выравнивание: к каждой строке добавляется несколько байт чтобы ее длина делилась на 4 без остатка. Чтобы избежать проблем с подсчетом выравниваний, можно задать biBitCount =32.

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 21:19 01-05-2010
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Frodo_Torbins
    Ну вот так я создаю битмап:

    Код:
     
      bmi    : TBitmapInfo;
      lpBits : PRGBTriple;
     
    //  with bmi.bmiHeader do
      begin
        biSize          := SizeOf(bmi.bmiHeader);
        biWidth         := MAX_WIDTH;
        biHeight        := -MAX_HEIGTH;
        biPlanes        := 1;
        biBitCount      := 32;
        biCompression   := BI_RGB;
        biSizeImage     := 0;
        biXPelsPerMeter := 1;
        biYPelsPerMeter := 1;
        biClrUsed       := 0;
        biClrImportant  := 0;
      end;
    //
    pcp.hbmMem := CreateDIBSection(hdcIn, bmi, DIB_RGB_COLORS, Pointer(lpBits), 0, 0);
    //
     

     
    Насчет GetDIBits:

    Цитата:
    Однако полученный битмап является DDB - Device Dependent Bitmap (не смотря на то что функция называется CreateDIBSection), что не позволяет нам н напрямую обращатся к битам карты. Поэтому мы должны его сконвертировать в DIB. Для этого заново готовим структуру  bmiInfo

    Вот здесь
     
    Ссылка на область памяти есть, теперь как ее правильно обработать? Там чуть ниже есть код с form1.Canvas.Pixels, да но нафига он мне нужен-то, толку что там извлекли эти пикселы из карты, что дальше с ними делать не показано. Это как конфетку показали и спрятали.
     
    Смотрел также тут пример, да и на некоторых форумах lpBits указан как PRGBTriple, а в других - как массив TRGBTriple. Ну допустим я сохраню этот массив точек после CreateDIBSection, я вот только не понимаю как я могу указать что надо закрасить определенный пиксель с нужными мне координатами.
    Как например:

    Код:
    lpBits[15, 15].rgbtBlue := 0;

    То есть здесь выходит нужно массив, но ранее я уже писал что координаты не совпадают или надо по другому пересчитывать их.

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 13:26 02-05-2010
    TechnoDreamer

    Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Нужен некий контейнер для массива чисел с возможностью вычитания.
    Т.е. имеем массив, к примеру, из таких значений: 1,2,3,4,5
    Второй массив будет 3, 4, 5, 6, 7
    Путем вычитания второго массива из первого, получим 1,2.
     
    Может есть уже какой-нибуть готовый класс-контейнер в Delphi или JCL или самому писать?

    Всего записей: 259 | Зарегистр. 01-06-2008 | Отправлено: 14:35 02-05-2010
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    Я склонен верить документации:
    Цитата:
    The CreateDIBSection function creates a device-independent bitmap (DIB)
    Тем более, что это подтверждается практикой.
     
    Вот вы пишете biBitCount := 32, а сколько будет SizeOf(TRGBTriple)*8? Не зря в Windows.pas рядышком объявлена структура TRGBQuad С ее помощью можно спокойно объявить двумерный массив, как вы и пытались в начале.
     
    P.S. Кстати сейчас наткнулся на функцию StretchDIBits. Использовать ее может быть довольно удобно, но она все же немного проигрывает в скорости StretchBlt.

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 14:51 02-05-2010 | Исправлено: Frodo_Torbins, 14:52 02-05-2010
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Frodo_Torbins
    А, ну это тепрь понятно. Сделал так:
     

    Код:
    var
    lpBits: Array [0..MAX_HEIGTH-1, 0..MAX_WIDTH-1] of TRGBQuad;
     
      procedure SetMemDCPixel(X, Y: Integer);
      begin
        lpBits[Y, X].rgbBlue     := 0;
        lpBits[Y, X].rgbGreen    := 0;
        lpBits[Y, X].rgbRed      := 0;
        lpBits[Y, X].rgbReserved := 0;
      end;
     
    begin
     
      with bmi.bmiHeader do
      begin
        biSize        := SizeOf(bmi.bmiHeader);
        biWidth       := MAX_WIDTH;
        biHeight      := -MAX_HEIGTH;
        biPlanes      := 1;
        biBitCount    := 32;
        biCompression := BI_RGB;
      end;
     
      GetDIBits(pcp.hdcMem, pcp.hbmMem, 0, MAX_HEIGTH, @lpBits, bmi, DIB_RGB_COLORS);
     
      SetMemDCPixel(0, 0);
     
      SetDIBits(pcp.hdcMem, pcp.hbmMem, 0, MAX_HEIGTH, @lpBits, bmi, DIB_RGB_COLORS);
     
    end;

     
    По крайней мере теперь SetMemDCPixel должен работать куда быстрее системного SetPixel в циклах.

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 17:57 02-05-2010 | Исправлено: Maks150988, 17:59 02-05-2010
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    А без GetDIBits/SetDIBits у вас не получается? У меня все прекрасно и без них рисует.

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 20:15 02-05-2010
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Frodo_Torbins
    Так мне надо подготовленный MemoryDC перерисовывать каждый раз. Через GetDIBits получаю текущую область памяти егошнего HBITMAP со своим содержимым, куда я должен заного отрисовать сетку поточечно.
     
    А кстати я бы хотел уточнить одну деталь. Почему если сделать динамический массив и подизменить процедуру так, сетка не рисуется вообще.
     

    Код:
    //
    type
    type
      TBits = Array of Array of TRGBQuad;
    var
      lpBits: TBits;
    //
      procedure SetMemDCPixel(bits: TBits; X, Y: Integer);
      begin
        bits[Y, X].rgbBlue     := 0;
        bits[Y, X].rgbGreen    := 0;
        bits[Y, X].rgbRed      := 0;
        bits[Y, X].rgbReserved := 0;
      end;
    //
      SetLength(lpBits, MAX_HEIGTH, MAX_WIDTH);
      GetDIBits(pcp.hdcMem, pcp.hbmMem, 0, MAX_HEIGTH, @lpBits, bmi, DIB_RGB_COLORS);
      SetMemDCPixel(lpBits, 0, 0);
    //
     

    Все локально в процедуре отрисовки. Пробовал выносить в глобальные переменные - тоже самое. Где ошибка?

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 20:23 02-05-2010 | Исправлено: Maks150988, 20:38 02-05-2010
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    Хм, я сразу после создания битмапа подключаю его к контексту. После этого в любой момент получить изображение с битмапа можно обращаясь к этому DC. Получается так:
    Код:
      bmpDC := CreateCompatibleDC(0);
      bmpHandle := CreateDIBSection(bmpDC, bmi, DIB_RGB_COLORS, Pointer(bmpBits), 0, 0);
      oldBmp:=SelectObject(bmpDC, bmpHandle);
     
      bmpBits^[25, 1].rgbGreen:=255;

    Динамические массивы имеют несколько другую структуру чем статические. lpBits: TBits - это лишь ссылка на массив. Попробуйте передавать в функцию указатель на первый элемент массива.

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 21:45 02-05-2010 | Исправлено: Frodo_Torbins, 21:53 02-05-2010
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Frodo_Torbins
     

    Код:
    GetDIBits(pcp.hdcMem, pcp.hbmMem, 0, MAX_HEIGTH, @lpBits[0, 0], bmi, DIB_RGB_COLORS);

     
    Так?

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 22:19 02-05-2010
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    Вроде так. Работает?

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 22:37 02-05-2010
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Frodo_Torbins
    Нет, не работает, Runtime Error возникает.
     
    Короче я тут выкинул из кода лишнее, оставил только код отрисовки сетки.
    Ссылка
     

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 23:08 02-05-2010
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    Да, точно. Двумерный динамический массив это по сути одномерный динамический массив с указателями на одномерные дин. массивы. Причем эти массивы не обязаны лежать в памяти вместе, а могут быть разбросаны по оперативке как угодно. Т. о. в данном случае мы можем использовать только один большой одномерный дин. массив.
    И кстати память под такие массивы выделяет менеджер памяти делфи, а вы, я вижу, пытаетесь использовать исключительно системный.
     
    И кстати рисовать черным по черному, это оригинально Остальные замечания в коде.

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 00:49 03-05-2010
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Frodo_Torbins
    Спасибо за исправления.
     
    По поводу замечаний:
    1) В WM_PRINTCLIENT я зачищаю буфер кистью, которая идет у контрола по умолчанию, поэтому я могу сразу WM_COLORSTATIC в родителе использовать для закраски фона контрола. По умолчанию контрол должен вести себя как STATIC.
    2) Рисую сетку черным потому что если рисовать на дефолтовом фоне контрола другим цветом оно еле заметно будет или расплываться + вдальнейшем можно конечно же добавить надстройку для смены цветов.
    3) Наверное лучше не использовать при отрисовке координаты от ps.rcPaint, ведь ежели закрыть часть контрола другим окно будет смещение позиции блиттинга.

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 11:53 03-05-2010
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    Ну, вам виднее, как оно у вас там будет взаимодействовать. По поводу ps.rcPaint согласен, просто вчера вечером было лень придумывать лучшее решение. По хорошему там вообще надо не StretchBlt делать, а размер самого битмапа менять и его отрисовку настраивать.

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 13:23 03-05-2010 | Исправлено: Frodo_Torbins, 13:24 03-05-2010
    0D0A

    Junior Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Подскажите, как сделать свое окно полностью прозрачным для курсора мыши? Те чтобы все события мыши шли к нижележащему окну? Нижележащие окна могут принадлежать другим приложениям, так что обработака WM_NCHITTEST с HTTRANSPARENT не помогает...

    Всего записей: 158 | Зарегистр. 21-09-2009 | Отправлено: 16:02 03-05-2010
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    0D0A
    Навскидку, SetWindowLong со стилем WS_EX_TRANSPARENT, если это то что вам нужно.

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 16:47 03-05-2010
    0D0A

    Junior Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Спасибо. Методом тыка получилось с WS_EX_TRANSPARENT or WS_EX_LAYERED и ненулевое SetLayeredWindowAttributes. Одно WS_EX_TRANSPARENT не помогает. В MSDN ни слова про мышь.

    Всего записей: 158 | Зарегистр. 21-09-2009 | Отправлено: 16:59 03-05-2010
    AviDen



    Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    TechnoDreamer, set of byte?

    Всего записей: 316 | Зарегистр. 05-06-2007 | Отправлено: 11:09 04-05-2010
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    У кого соображалка хорошо работает, помогите мне с зеркалированием части изображения с контекста.
     
    Ссылка
     
    Вобщем-то в модуле F_StatBeat.pas в строчке 126 необходимо координаты правильно выставить для StretchBlt. Я что-то не пойму, вроде все правильно делаю, а оно мне половину картинки растягивает, а не блиттит. Правая часть собственно простецки через BitBlt выводится как и нужно.

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 21:10 04-05-2010
    ShIvADeSt



    Moderator
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    Может отдельную тему создать (например, Рисование на Дельфи при помощи API функций) - все таки рисование на Дельфи при помощи АПИ функций достаточно интересная тема и если все будет вместе - то другим будет проще потом использовать.

    ----------
    И создал Бог женщину... Существо получилось злобное, но забавное...

    Всего записей: 3956 | Зарегистр. 29-07-2003 | Отправлено: 01:24 05-05-2010
       

    Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

    Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по Delphi (до версии 2009) - часть 5
    ShIvADeSt (19-05-2010 05:14): Продолжаем тут http://forum.ru-board.com/topic.cgi?forum=33&topic=11215


    Реклама на форуме Ru.Board.

    Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
    Modified by Ru.B0ard
    © Ru.B0ard 2000-2024

    BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

    Рейтинг.ru