В старые времена мы много программировали с нуля. Это не так сложно, как кажется, но для получения результатов требуется несколько недель.
Сначала вам нужна хорошая библиотека для рисования. Минимальная функциональность для этой библиотеки - рисование обрезанных прямоугольников (с использованием шаблонов), линий, растровых изображений и шрифтов. Вы можете обмануть, создав шрифты в виде растровых изображений, а обрезанный прямоугольник - это просто набор горизонтальных линий.
Теперь вам нужны как минимум драйверы для мыши, клавиатуры и таймера (если они еще не предоставлены операционной системой). В общем, вам нужно будет обнаружить клавиши, символьные клавиши (например, Shift и т. Д.), Движения мыши и щелчки мыши. Основные функции таймера позволят вам обнаружить двойной щелчок.
Затем вам нужно создать структуру данных окна . Эта структура данных должна иметь координаты, то есть прямоугольник, ссылку на родительское окно (если не верхнее окно) и оконную функцию, т.е. функцию, которая будет вызываться, когда это окно должно обрабатывать некоторые события.
Как только вы сможете рисовать на экране, вам понадобятся функции алгебры прямоугольников . Вам нужна хотя бы хорошая функция для вычисления пересечения прямоугольников и быстрое разрешение относительно абсолютных координат . Например - если у вашего дочернего окна есть родитель, тогда его 'x и y должны рекурсивно добавляться к родителю x и y, пока вы не достигнете верхнего окна.
На данный момент у вас есть:
- примитивные графические функции,
- оконная конструкция,
- драйвер мыши, драйвер клавиатуры и таймер,
- арифметика прямоугольника.
Теперь вы можете написать свою функцию сбора основного события . Эта функция будет работать постоянно. Его целью будет для обнаружения событий и отправки сообщений в правильные окна . Что такое событие? Хорошо, когда вы запускаете вашу программу, сохраняйте координаты мыши x и y. Затем в цикле проверьте, не изменились ли они. Если они изменились, найдите окно в этой позиции ... и отправьте ему событие WM_MOUSEMOVE. Ваша функция сбора урожая должна обрабатывать:
- мышь двигается
- щелчки мышью
- двойной щелчок мышью (запомните последний щелчок и положение, измерьте время и решите, двойной это щелчок или нет)
- таймер событий
- изменения буфера клавиатуры
...
Теперь вы должны иметь возможность отправлять события в Windows. Но вам действительно нужен механизм для этого. Это комбинация очереди сообщений и оконной процедуры . Обычно это работает так: каждое окно имеет оконную процедуру, которая обычно принимает четыре аргумента: идентификатор сообщения (то есть движение мыши, сообщение рисования), дескриптор окна, параметр 1 и параметр 2. Вы можете вызвать эту оконную процедуру напрямую, используя что-то вроде функции send_message. Или вы можете отправить этому окну сообщение через функцию post_message. Это поместит сообщение в очередь, и окно будет обрабатывать сообщения одно за другим, в конечном итоге получая это сообщение. Так почему вы должны вызывать одни сообщения напрямую и ставить другие в очередь? Из-за приоритета. Видите ли, щелчок клавиатуры может подождать некоторое время, прежде чем обрабатывается. Но перерисовка окна должна быть завершена немедленно, чтобы предотвратить мерцание и неправильные данные на экране.
Таким образом, ваша функция crop_events отправляет сообщения в окна, используя post_message и send_message. И ваш оконный насос сообщений получает их, используя типичный насос сообщений, подобный этому:
while (pmsg = get_message ()! = NULL) send_message (pmsg-> id, pmsg-> hwnd, pmsg-> p1, pmsg-> p2);
get_message просто получает сообщение из очереди и вызывает отправку сообщения. Просто, да? Ну, не совсем так. Таким образом, вы будете получать только сообщения драйвера в окна, но вам также понадобятся некоторые функции для перерисовки окон , их перемещения и т. Д. При создании функции move_window, resize_window, show_window и Функция hide_window, ваши координаты окна будут меняться. Части других окон будут открыты (если верхнее окно было перемещено или закрыто). Вам необходимо рассчитать, на какие окна влияют изменения координат, и отправить сообщение рисования в эти окна (чтобы перекрасить только те части, которые были обнаружены - помните, у вас есть отсечение функции рисования, так что это будет работать).
Эти функции вводят сообщения msg_paint, msg_move, msg_resize, msg_hide ...
Наконец, вам нужно поддерживать иерархию окон . Ваше верхнее окно должно быть рабочим столом. У него должны быть дочерние окна (верхние окна приложения). Эти окна могут иметь дополнительные дочерние окна (кнопки, поля редактирования и т. Д.). Очевидная структура для их хранения - дерево окон . Когда вы обнаруживаете щелчок мышью, вы должны пройти по дереву окон и сделать это умным способом (выяснить, у кого есть фокус, кто модальный и т. Д.), Чтобы отправить сообщение в нужное окно. И когда вы рисуете, вы также должны пройти через всех детей, чтобы увидеть, кто открыт, а кто нет. И последнее, но не менее важное: вам нужно обрабатывать прямоугольник мыши как верхнее окно, чтобы предотвратить мерцание мыши, когда окна перерисовываются или (с использованием таймеров и событий msg_paint) анимируются.
Это примерно так.