#c# #c #winapi #graphics #gdi
#c# #c #winapi #графика #gdi
Вопрос:
Мне нужно что-то нарисовать в окне (это не мое — оно определяется пользователем, если это имеет значение).
Мне уже удалось рисовать в окне, получив контекст устройства с помощью GetDC и рисуя нормально, проблема в том, что я не знаю, когда рисовать в окне — окно постоянно перерисовывает само себя (например, игра). У меня есть несколько идей, но пока они ни хороши, ни плохи / нет реализации.
- Использование таймера.Это была худшая идея, но я попробую что-нибудь прямо сейчас. очевидно, что, поскольку окно постоянно перерисовывается, оно будет мерцать. Я думал заставить окно перерисовываться перед моими рисунками, но все равно это бесполезно. не могу придумать хорошую реализацию с таймером…
- Перехватить сообщение WM_PAINT. используя перехват SetWindowsHookEx WM_GETMESSAGE, я могу использовать событие, которое получает сообщение WM_PAINT всякий раз, когда его получает другое окно, но WM_PAINT отправляется до завершения рисования. Я обнаружил в MSDN, что вместо перехвата WH_GETMESSAGE Windows вы можете использовать WndProcRetHook, который вызывается после обработки сообщений Windows и получает структуру, содержащую информацию о сообщении, но пока безуспешно — я не могу заставить его работать…
- Подключение функций рисования.Я попытался подключить функцию рисования (или функции), такие как ReleaseDC и / или EndPaint, которые делают окно недействительным, чтобы я мог делать свои рисунки в последнюю минуту. на этот раз я заставил это работать довольно хорошо — но оно все еще немного мерцает, а в некоторых окнах подключение ReleaseDC каким-то образом препятствует рендерингу окна — оно даже не стирает его фон. иногда даже весь процесс завершается сбоем.
Итак, я ищу хороший метод, позволяющий рисовать в окне последним, прежде чем оно отобразится на экране. Я предпочитаю избегать перехватов, которые не выполняются с помощью SetWindowsHookEx (например: external DLL), но это тоже было бы неплохо.
Спасибо.
Ответ №1:
Альтернативный подход может заключаться в том, чтобы не рисовать непосредственно в окне, а вместо этого создать прозрачное многоуровневое окно, которое вы сохраняете расположенным поверх основного. Таким образом, рисование в вашем окне не мешает рисованию в главном окне, и наоборот.
Возможно, вам потребуется предпринять определенные шаги, чтобы щелчки мыши проходили через ваше окно в главное окно; например. обработайте WM_NCHITTEST с помощью HTTRANSPARENT и используйте стиль WS_EX_TRANSPARENT.
Комментарии:
1. Это одна вещь, которую я имел в виду. проблема в том, что рисунки тоже прозрачны… Цвета сливаются в зависимости от прозрачности, поэтому я добавил определяемые пользователем параметры для управления обратным цветом окна и прозрачностью для достижения наилучших результатов. Я надеюсь, что это сработает хорошо. Спасибо.
2. Я не знаю, почему я не подумал об этом до сих пор, но до сих пор я использовал свойство Opacity, когда я мог просто установить TransparencyKey в свойство backgroundColor, и тогда мои рисунки будут отображаться без определенной прозрачности, а мое окно будет полностью прозрачным. 😉
3. Да, подход с использованием цветовой клавиши, вероятно, подойдет здесь.
4. Я согласен с @BrendanMcK в том, что предложенное им решение менее навязчиво. Вот ссылка на VB.net проект, который инкапсулирует прозрачность и поведение при нажатии. Надеюсь, это поможет.
Ответ №2:
Поскольку в Windows Windows требуется рисовать по требованию, единственный способ сделать это — использовать SetWindowsHookEx()
для подключения окна WM_PAINT к этому окну.
Это нетривиальный процесс, который требует, чтобы ваш код paint находился в DLL (чтобы DLL можно было загрузить в адресное пространство целевого приложения).
В общем, это не очень хорошая идея, если у вас нет очень веской причины для этого.
Комментарии:
1. Спасибо за ваш ответ. У меня есть другие способы делать то, что я хочу, но этот был лучшим… что ж, если бы я мог реализовать это хорошим способом. 😉