WM_NOTIFY и проблема цепочки суперклассов в Win32

Для справки я использую метод суперкласса окна, описанный в этой статье. Конкретная проблема возникает, если я хочу обрабатывать сообщения WM_NOTIFY (т.е. для пользовательского рисования) из базового элемента управления в суперклассе. Мне нужно либо отразить их обратно из родительского окна, либо установить мое собственное окно в качестве родителя (передается внутри CREATESTRUCT для WM_(NC)CREATE для базовый класс). Этот метод отлично работает, если у меня есть один суперкласс. Если я переклассифицирую свой суперкласс, у меня возникнут проблемы. Теперь 3 WindowProc работают в одном и том же HWND, и когда я отражаю WM_NOTIFY сообщений (или отправляю их себе из родительского трюка выше), они всегда переходят к самому внешнему (наиболее производному) WindowProc. У меня нет возможности определить, являются ли они сообщениями, предназначенными для внутреннего суперкласса (предполагается, что базовые сообщения отправляются первому суперклассу) или сообщениями, предназначенными для внешнего суперкласса (сообщения из внутреннего суперкласса предназначены для внешнего суперкласса). Эти сообщения неразличимы, поскольку все они исходят от одного и того же HWND с одним и тем же идентификатором элемента управления. Есть ли способ решить эту проблему без создания нового окна для инкапсуляции каждого уровня наследования?

Извините за стену текста. Это сложная концепция для объяснения. Вот диаграмма.

один суперкласс:

SuperA::WindowProc() -> Base::WindowProc()---\
             ^--------WM_NOTIFY(Base)--------/

суперкласс суперкласса:

SuperB::WindowProc() -> SuperA::WindowProc() -> Base::WindowProc()---\
             ^--------WM_NOTIFY(Base)--------+-----------------------/
             ^--------WM_NOTIFY(A)-----------/

Все сообщения WM_NOTIFY во втором случае исходят от одного и того же HWND и идентификатора элемента управления, поэтому я не могу различить сообщения, предназначенные для SuperA (от Base), и сообщения, предназначенные для SuperB (от SuperA). Есть идеи?


person Community    schedule 17.04.2009    source источник


Ответы (2)


Естественно, элемент управления (оригинал?) отправляет сообщения РОДИТЕЛЮ. Предположительно, вы перехватываете их и отправляете обратно в исходный элемент управления. Внешний слой, конечно, увидит их первым (а затем может просто передать их, если не захочет их обрабатывать).

Вы не сказали, какие сообщения NOTIFY вы хотите перехватить и почему. Но, поскольку теперь у вас есть контроль над ними в родительском процессе, чтобы отправить их обратно, почему бы просто не изменить сообщение. Сверните свою собственную структуру NMHDR, внедрите сообщение и данные и добавьте некоторую идентификацию для уровня суперкласса. В своем суперклассе удалите те, которые вам нужны, переформатируйте те, которые вам не нужны, и отправьте их дальше.

Звучит немного сумбурно. На этом уровне я был бы склонен вернуться к основам и создать свой собственный общий элемент управления (конечно, в зависимости от того, что вы на самом деле пытаетесь сделать).

person David L Morris    schedule 05.12.2009

Borland обошла это в VCL, изменив идентификатор сообщения на родительском уровне. Когда родительское окно получает сообщение WM_NOTIFY, идентификатор сообщения увеличивается на определенное смещение (CN_BASE), а затем сообщение передается непосредственно дочернему окну, указанному в сообщении. Затем дочерняя оконная процедура (и любые подклассы дочернего элемента) может искать сообщения (CN_BASE + WM_NOTIFY) и получать доступ к исходным данным WM_NOTIFY. Тот же метод применим и к сообщениям WM_COMMAND. Попробуйте сделать что-то подобное в своем коде.

person Remy Lebeau    schedule 30.04.2010