На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
  
> Отрисовка на Static-контроле , WM_DRAWITEM
    Диалоговое окно создано с помощью DialogBoxParam, в нём имеется Static-контрол, на котором происходит рисование.
    Вернее, рисование происходит на совместимом DC (назовём его Draw), но потом нужно туда (в Static) этот рисунок копировать.

    В данный момент у меня сделано так:
    Static имеет опцию стиля SS_OWNERDRAW
    • В оконной функции DialogProc я ловлю WM_DRAWITEM (wParam = ID контрола из ресурсов). Тут я тупо делаю BitBlt (переношу из совместимого DC Draw в DC Static-контрола). Без BeginPaint/EndPaint, потому как если я использую их (с hwnd = хендлу контрола), то почему-то ничего не рисуется. А если я использую hwnd = хендлу диалога, то рисуется, но само собой, на всём окне, а не на контроле.

    Меня гложет мысль, что это неправильно: перерисовывать весь контрол при каждом WM_DRAWITEM.
    Как сделать грамотно?

    p.s. BeginPaint/EndPaint (с hwnd = хендлу контрола) рисуется нормально при ловле WM_PAINT, а не WM_DRAWITEM, но там возникают другие глюки...
      Цитата Jin X @
      Как сделать грамотно?

      Знать бы что такое "Грамотно"..
      1. Можно делать так, как сейчас.
      2. Можно не объявлять стиль SS_OWNERDRAW.
      Делать сабклассинг, перехватить оконную процедуру
      и самому обрабатывать сообщение WM_PAINT с использованием BeginPaint/EndPaint.
      3. Можно после перехвата оконной процедуры разрешить стандартную
      прорисовку контрола. После её завершения ещё самому пытаться что-нибудь дорисовать
      на его поверхности. Из того же WM_PAINT.
      ---
      Выбирай что удобнее и лучше подходит именно для твоей задачи.
      Сообщение отредактировано: ЫукпШ -
        Цитата Jin X @
        • В оконной функции DialogProc я ловлю WM_DRAWITEM (wParam = ID контрола из ресурсов). Тут я тупо делаю BitBlt (переношу из совместимого DC Draw в DC Static-контрола). Без BeginPaint/EndPaint, потому как если я использую их (с hwnd = хендлу контрола), то почему-то ничего не рисуется. А если я использую hwnd = хендлу диалога, то рисуется, но само собой, на всём окне, а не на контроле.


        Покажи, как ты обрабатываешь WM_DRAWITEM
          Цитата ЫукпШ @
          Делать сабклассинг, перехватить оконную процедуру
          и самому обрабатывать сообщение WM_PAINT с использованием BeginPaint/EndPaint.
          Надо изучить этот вопрос. Как это должно выглядеть...
          В общем-то, нашёл статьи даже нужные ;)

          Цитата Олег М @
          Покажи, как ты обрабатываешь WM_DRAWITEM
          У меня на асме :)
          ExpandedWrap disabled
                    .elseif edx == WM_DRAWITEM && r8d == IDC_GRAPHIC    ; отрисовка содержимого окна
                        mov r10d,rect.right
                        sub r10d,rect.left          ; R10 = ширина клиентской части графика
                        mov r11d,rect.bottom
                        sub r11d,rect.top           ; R11 = высота клиентской части графика
                        invoke  BitBlt, hGraphicDC, 0, 0, r10, r11, hDrawDC, 0, 0, SRCCOPY  ; выводим изображение на график
                        mov eax,TRUE
          p.s. В rect у меня размеры, полученные через GetClientRect:
          ExpandedWrap disabled
                    .if edx == WM_INITDIALOG            ; инициализация диалога
                        invoke  GetDlgItem, rcx, IDC_GRAPHIC    ; получаем хендл графика (контрола)
                        invoke  GetClientRect, rax, &rect   ; получаем размер клиентской части графика
                        . . .

          Попутно вопрос: rect.left и rect.top всегда будут = 0 ?
          Т.е. можно ли безболезненно убрать sub r10d,rect.left и sub r11d,rect.top?
            Цитата Jin X @
            invoke  BitBlt, hGraphicDC, 0, 0, r10, r11, hDrawDC, 0, 0, SRCCOPY      ; выводим изображение на график

            Ты бы вместо BitBlt попробовал сначала что-нибудь типа FillRect, чтоб убедится, чтo всё правильно.
            И откуда ты берёшь hGraphicDC, точно из DRAWITEMSTRUCT?


            Цитата Jin X @
            Меня гложет мысль, что это неправильно: перерисовывать весь контрол при каждом WM_DRAWITEM.
            Как сделать грамотно?


            Перерисовывать только прямоугольник, который изменился - GetClipBox, вроде.
              Цитата Jin X @
              Цитата ЫукпШ @
              Делать сабклассинг, перехватить оконную процедуру
              и самому обрабатывать сообщение WM_PAINT с использованием BeginPaint/EndPaint.
              Надо изучить этот вопрос. Как это должно выглядеть...
              В общем-то, нашёл статьи даже нужные ;)

              Можно сделать класс-сабклассинг. Унаследоваться от него..
              В результате получим контрол с возможностью сабклассинга
              и со всем необходимым хозяйством "внутри".
                Цитата Олег М @
                Ты бы вместо BitBlt попробовал сначала что-нибудь типа FillRect, чтоб убедится, чтo всё правильно.
                И откуда ты берёшь hGraphicDC, точно из DRAWITEMSTRUCT?
                А зачем мне в этом убеждаться, если всё работает? Вопрос в оптимизации, а не работоспособности :)
                  Цитата Jin X @
                  Цитата Олег М @
                  Ты бы вместо BitBlt попробовал сначала что-нибудь типа FillRect, чтоб убедится, чтo всё правильно.
                  И откуда ты берёшь hGraphicDC, точно из DRAWITEMSTRUCT?
                  А зачем мне в этом убеждаться, если всё работает? Вопрос в оптимизации, а не работоспособности

                  Вопрос заключается не в первом предложении, а во втором. По хорошему/правильному, для рисования нужно использовать hDC и rcItem из DRAWITEMSTRUCT. Хоть в мсдн практически ничего не говорится об особенностях WM_DRAWITEM для статик-контрола, но наверняка в случае, если нужно перерисовывать не всё окно, а его часть, то rcItem должно соответствовать GetClipBox.

                  PS: Еще к вопросу об "оптимизации". Не знаю как насчет твоего статика, но, например, в случае кнопки, WM_DRAWITEM может вызываться при установке или потере фокуса кнопки. В этом случае можно\нужно анализировать поля itemAction и itemState и при необходимости рисовать не всю кнопку, а только рамку фокуса. Кто знает, если твой статик не заблокирован от получения фокуса, может для него WM_DRAWITEM также вызывается при установке\потере фокуса, когда не обязательно перерисовывать всё изображение?
                    Цитата leo @
                    Вопрос заключается не в первом предложении, а во втором. По хорошему/правильному, для рисования нужно использовать hDC и rcItem из DRAWITEMSTRUCT.


                    Я что-то типа того делал. Обрабатываешь WM_DRAWIETM для HWND своего статика

                    Дальше

                    ExpandedWrap disabled
                      LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
                      RECT rect = dis->rcItem;
                      HGDIOBJ hbrush = ::CreateSolidBrush(RGB(0,0,255));
                      ::SelectObject(dis->hDC,hbrush);
                      ::SetBkColor(dis->hDC,RGB(0,0,255));


                    Добавлено
                    Жень, на асме это "назло врагам"?
                      Цитата ter_nk_ @
                      Дальше

                      ExpandedWrap disabled
                        LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
                        RECT rect = dis->rcItem;
                        HGDIOBJ hbrush = ::CreateSolidBrush(RGB(0,0,255));
                        ::SelectObject(dis->hDC,hbrush);
                        ::SetBkColor(dis->hDC,RGB(0,0,255));

                      А "DeleteObject" ?
                      Не оптимально при каждом вызове обработчика создавать кисть.
                      Она же с постоянным цветом - лучше создать заранее.
                        Цитата ЫукпШ @
                        А "DeleteObject" ?
                        Не оптимально при каждом вызове обработчика создавать кисть.
                        Она же с постоянным цветом - лучше создать заранее.


                        До таких-то вещей уж как-то сам, это же подразумевается, что такие ресурсы типа GDI создать при загрузке где-то, а когда не надо выгрузить.
                          В целом ясно. Всем спасибо. Надо использовать rcItem. Static фокус не получает (WS_TABSTOP отсутствует).
                          Вопрос только в том, что если itemAction имеет флаг ODA_DRAWENTIRE, то rcItem всё равно будет корректно заполнен? По логике должен и об обратно ничего не сказано, но мало ли...

                          Цитата ter_nk_ @
                          Жень, на асме это "назло врагам"?
                          Нет, просто так нужно в данном случае :)
                            Цитата
                            Before returning from processing this message, an application should ensure that the device context identified by the hDC member of the DRAWITEMSTRUCT structure is in the default state.
                            В каком таком default state? А в каком ещё он может быть? И как его привести в это состояние?

                            Ещё такой момент...
                            Структура имеет вид:
                            ExpandedWrap disabled
                              typedef struct tagDRAWITEMSTRUCT {
                                UINT      CtlType;
                                UINT      CtlID;
                                UINT      itemID;
                                UINT      itemAction;
                                UINT      itemState;
                                HWND      hwndItem;
                                HDC       hDC;
                                RECT      rcItem;
                                ULONG_PTR itemData;
                              } DRAWITEMSTRUCT;
                            На всякий случай спрошу: правильно ли я понимаю, что тут идёт выравнивание каждого элемента по размеру типа? Т.е. поскольку HWND имеет размер QWORD (8 байт) для x64, то перед ним будет резерв в 4 байта, т.к. в этой структуре он располагается по смещению, не кратному размеру типа HWND (т.е. по смещению 5*4 = 20, а кратно 8 только число 24).
                            Поэтому смещение rcItem будет = 10*4 (а не 9*4). По факту так и получается, rcItem.left имеет смещение 10*4 = 40 = 28h.
                              Цитата Jin X @
                              В каком таком default state? А в каком ещё он может быть? И как его привести в это состояние?

                              Это значит, что если ты делаешь какие-то SelectObject для изменения pen, brush, font, то по окончании своих художеств должен вернуть их все в дефолтное состояние. См. ремарки к SelectObject
                              Цитата
                              An application should always replace a new object with the original, default object after it has finished drawing with the new object.

                              PS: Но к твоей задаче это не имеет отношения, т.к. ты рисуешь не непосредственно на оконном hDC, а в отдельном битмапе, и затем просто копируешь картинку в hDC, не изменяя его дефолтных свойств.

                              Добавлено
                              Цитата Jin X @
                              правильно ли я понимаю, что тут идёт выравнивание каждого элемента по размеру типа?

                              Да
                              Сообщение отредактировано: leo -
                                Цитата leo @
                                PS: Но к твоей задаче это не имеет отношения, т.к. ты рисуешь не непосредственно на оконном hDC, а в отдельном битмапе, и затем просто копируешь картинку в hDC, не изменяя его дефолтных свойств.
                                Почему не имеет? Это относится только к оконным hdc? Если да, то где об этом сказано?

                                По идее как-то так должно быть:
                                ExpandedWrap disabled
                                  originalPen = SelectObject(hdc, GreatePen(PS_DASH, 3, 0x80));
                                  ...
                                  DeleteObject(SelectObject(hdc, originalPen));
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0444 ]   [ 16 queries used ]   [ Generated: 28.03.24, 20:29 GMT ]