Win32 中的 WM_NOTIFY 和超类链接问题
作为参考,我使用这篇文章中概述的窗口超类方法。 如果我想处理来自超类中的基本控件的 WM_NOTIFY
消息(即用于自定义绘图),则会出现特定问题,我需要从父窗口反射它们,或者将我自己的窗口设置为父窗口(在 WM_(NC)CREATE
的 CREATESTRUCT 内部传递给基类)。 如果我有一个超类,这个方法就可以正常工作。 如果我对我的超类进行超类化,那么我就会遇到问题。 现在,3 个 WindowProc 在同一个 HWND 中运行,当我反映 WM_NOTIFY 消息(或将它们从上面的父技巧发送给我自己)时,它们总是转到最外层(最派生的)WindowProc。 我无法判断它们是用于内部超类的消息(基本消息应该发送到第一个超类)还是用于外部超类的消息(来自内部超类的消息用于外部超类)。 这些消息是无法区分的,因为它们都来自具有相同控制 ID 的相同 HWND。 有没有办法解决这个问题,而无需创建新窗口来封装每个继承级别?
抱歉,文字墙。 这是一个很难解释的概念。 这是一个图表。
单个超类:
SuperA::WindowProc() -> Base::WindowProc()---\ ^--------WM_NOTIFY(Base)--------/
超类的超类:
SuperB::WindowProc() -> SuperA::WindowProc() -> Base::WindowProc()---\ ^--------WM_NOTIFY(Base)--------+-----------------------/ ^--------WM_NOTIFY(A)-----------/
第二种情况下的 WM_NOTIFY
消息都来自相同的 HWND 和控件 ID,因此我无法区分用于 SuperA 的消息(来自 Base)和用于SuperB(来自SuperA)。 有任何想法吗?
For reference I'm using the window superclass method outlined in this article. The specific issue occurs if I want to handle WM_NOTIFY
messages (i.e. for custom drawing) from the base control in the superclass I either need to reflect them back from the parent window or set my own window as the parent (passed inside CREATESTRUCT for WM_(NC)CREATE
to the base class). This method works fine if I have a single superclass. If I superclass my superclass then I run into a problem. Now 3 WindowProcs are operating in the same HWND, and when I reflect WM_NOTIFY
messages (or have them sent to myself from the parent trick above) they always go to the outermost (most derived) WindowProc. I have no way to tell if they're messages intended for the inner superclass (base messages are supposed to go to the first superclass) or messages intended for the outer superclass (messages from the inner superclass are intended for the outer superclass). These messages are indistinguishable because they all come from the same HWND with the same control ID. Is there any way to resolve this without creating a new window to encapsulate each level of inheritance?
Sorry about the wall of text. It's a difficult concept to explain. Here's a diagram.
single superclass:
SuperA::WindowProc() -> Base::WindowProc()---\ ^--------WM_NOTIFY(Base)--------/
superclass of a superclass:
SuperB::WindowProc() -> SuperA::WindowProc() -> Base::WindowProc()---\ ^--------WM_NOTIFY(Base)--------+-----------------------/ ^--------WM_NOTIFY(A)-----------/
The WM_NOTIFY
messages in the second case all come from the same HWND and control ID, so I cannot distinguish between the messages intended for SuperA (from Base) and messages intended for SuperB (from SuperA). Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当然,控件(原来的?)正在向父级发送消息。 据推测,您正在拦截这些并将它们发布回原始控件。 当然,外层会首先看到这些(如果不想处理它们,则可以将它们传递出去)。
您还没有说明您想要拦截哪种 NOTIFY 消息或原因。 但是,既然您现在可以在父过程中控制它们以将它们发送回,为什么不直接更改消息呢。 滚动您自己的 NMHDR 结构,嵌入消息和数据,并为超类的级别添加一些标识。 在您的超类中,剥离您想要的内容,重新格式化您不需要的内容,然后将其发送。
听起来确实有点乱。 在那个级别,我倾向于回到基础知识并构建我自己的通用控件(当然,这取决于您实际上想要做什么)。
Naturally, the control (the original?) is sending messages to the PARENT. Presumably, you are intercepting these and posting them back to the original control. The outer layer of course would see these first (and then could just pass them on if it didn't want to handle them).
You haven't said what sort of NOTIFY messages you want to intercept or why. But, since you now have control over them in the parent proc to send them back in, why not just change the message. Roll your own NMHDR struct, embedded the message and data, and add some identification for the level of the super class. In your superclass, peel off the ones you want, reformat the ones you don't, and send them on.
It does sounds a tad messy. At that level I would be inclined to go right back to basics and build my own own common control (depending on, of course, what you are actually trying to do).
Borland 在 VCL 中通过更改父级别的消息 ID 解决了这个问题。 当父窗口收到WM_NOTIFY消息时,消息ID会增加一个定义的偏移量(CN_BASE),然后该消息被直接传递到该消息指定的子窗口。 然后,子窗口过程(以及子窗口的任何子类)可以查找(CN_BASE + WM_NOTIFY)消息并访问原始的 WM_NOTIFY 数据。 相同的技术也适用于 WM_COMMAND 消息。 尝试在您的代码中执行类似的操作。
Borland got around this in the VCL by changing the message ID at the parent level. When a parent window receives a WM_NOTIFY message, the message ID is incremented by a defined offset (CN_BASE), and then the message is passed directly to the child window that the message specifies. The child window procedure (and any subclasses of the child) can then look for (CN_BASE + WM_NOTIFY) messages and have access the original WM_NOTIFY data. The same technique applies for WM_COMMAND messages as well. Try doing something similar in your code.