Элемент управления для рисования в окне gdi

Я использовал Visual Basic 6 в прошлом (LOONG назад), и у него был элемент управления под названием PictureBox, в котором вы могли просто рисовать, получать контекст устройства, если хотите, и т. Д. Теперь я пытаюсь выяснить, как получить аналогичный «контроль» в чистом GDI / WinApi (без MFC, .net, atl, gdi + и т. д.). Я использовал элемент управления кнопки рисования владельцем, но вы не можете (легко) получить координаты мыши при нажатии, поэтому я решил, что мне нужен какой-то другой элемент управления. Я пробовал статический элемент управления, но у него нет поддержки рисования владельцем. Я пробовал обрабатывать WM_PAINT, но, насколько мне известно (после нескольких часов поиска в Google), нет возможности использовать его для обновления только одной области клиента или только одного HWND.

Итак, я спрашиваю, как люди анимируют или копируют выбранные области окна, будь то элемент управления или что-то еще, используя чистый GDI и Windows API? Я знаю, что у MFC есть нечто, называемое подклассом, но поскольку MFC - это просто оболочка для Windows API, ДОЛЖЕН БЫТЬ способ сделать это без него (также, как я сказал ранее, MFC не вариант).


person stelonix    schedule 20.05.2011    source источник
comment
Просто создайте дочернее окно и раскрасьте его в WM_PAINT. Позвоните InvalidateRect(), если вы хотите принудительно перекрасить.   -  person David Heffernan    schedule 20.05.2011
comment
Извините, но я мало что знаю о GDI. Как мне обрабатывать WM_PAINT только для одного дочернего окна?   -  person stelonix    schedule 20.05.2011
comment
Вы обрабатываете сообщение WM_PAINT в своей оконной процедуре.   -  person David Heffernan    schedule 20.05.2011
comment
Если я добавлю дочернее окно с помощью CreateWindow, его WM_PAINT все равно будет обрабатываться родительским окном. Если я обрабатываю WM_PAINT, насколько мне известно, невозможно просто обработать WM_PAINT дочернего окна. Если я ошибаюсь, вы можете опубликовать пример, как это сделать? AFAIK единственный способ установить, какую оконную процедуру использует окно, - это использовать RegisterClass, который я понятия не имею, как это сделать для дочерних окон.   -  person stelonix    schedule 20.05.2011
comment
@knuck Нет, все окна получают сообщения WM_PAINT. Вы можете обрабатывать только WM_PAINT, делая именно это. Все остальные сообщения должны передаваться в DefWindowProc. Оконные процедуры можно изменить, вызвав SetWindowLongPtr. Я думаю, вам нужно освежить свои знания о том, как работает Windows, прежде чем решать эту проблему. Кроме того, почему вам нужно делать проект без помощи графического интерфейса? Это просто усложняет вам жизнь, особенно если у вас ограниченный опыт работы с низкоуровневой Win32.   -  person David Heffernan    schedule 20.05.2011


Ответы (2)


Честно говоря, я думаю, что это может быть большим проектом для вас прямо сейчас. Возможно, вы захотите попробовать несколько более простых проектов с использованием Windows API, прежде чем пытаться это сделать, но я все равно дам вам небольшое объяснение.

Вам нужно будет создать настраиваемый элемент управления. Использование существующего элемента управления для этого - плохая практика, потому что они не предназначены для использования. Чтобы создать собственный элемент управления, вам сначала нужно создать класс окна с WNDCLASSEX или WNDCLASS.

WNDCLASS: http://msdn.microsoft.com/en-us/library/ms633576
WNDCLASSEX: http://msdn.microsoft.com/en-us/library/ms633577

Как только вы это сделаете и установите все необходимые значения членов, вам необходимо зарегистрировать класс с помощью RegisterClass или RegisterClassEx.

Один из членов объектов WNDCLASS (EX) принимает указатель на функцию оконной процедуры. Любое окно, созданное с помощью этого класса окна, будет использовать эту оконную процедуру.

После того, как вы зарегистрировали свой класс окна, вы можете создать окно, используя созданный вами класс окна. Просто сделайте CreateWindow (..., "ВАШ КЛАСС ОКНА ЗДЕСЬ", ...);

Теперь ваша оконная процедура должна выглядеть примерно так:

LRESULT CALLBACK MyDrawProcedure(HWND hwnd, UMSG uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
      case WM_PAINT:
      {
        // Handle painting your control here.
      }
      break;

      default:
         return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }

    return 0;
}

Надеюсь, это немного поможет.

person Gogeta70    schedule 20.05.2011

Создайте дочернее окно и раскрасьте его в WM_PAINT. Позвоните InvalidateRect(), если вы хотите принудительно перекрасить.

person David Heffernan    schedule 20.05.2011