Delphi - 在 DirectShow 过滤器中创建的表单的消息循环失效
我有一个使用 Delphi Pro 6 和 DSPACK 直接显示库创建的 DirectShow 过滤器。我在windows XP下运行。我尝试在 DirectFilter 的容器类调用其构造函数时动态创建表单,将 NIL 作为 AOwner 参数 (TMyForm.Create(nil)) 传递到构造函数中,然后调用 Form 的 Show() 方法。该表单确实显示但随后似乎停止接收 Windows 消息,因为它从不重新绘制并且不响应输入,然后我尝试创建自己的 WndProc() 并覆盖 Form 的 WndProc() 确实被调用了一次,但再也没有调用过。 我猜
这是因为我是一个 DLL,并且我运行的上下文对窗体的窗口消息处理程序不“友好”;也许与调用它的线程有关。给我一个关于如何解决这个问题的提示,或者从 DirectShow 过滤器的上下文创建持久窗口的正确方法是什么,我会很感激,因为我说过窗口需要持久,所以我无法创建。它作为过滤器属性页,
谢谢, 罗伯特
I have a DirectShow filter created with Delphi Pro 6 and the DSPACK direct show library. I'm running under windows XP. I've tried creating the form dynamically when the container class for the DirectFilter has its constructor called, passing NIL into the constructor as the AOwner parameter (TMyForm.Create(nil) and then calling the Form's Show() method. The form does show but then appears to stop receiving windows messages because it never repaints and does not respond to input. As a test I then tried creating my own WndProc() and overriding the Form's WndProc(). My WndProc() did get called once but never again.
I'm guessing it's because I'm a DLL and the context that I am running in is not "friendly" to the window message handler for the form; perhaps something to do with the thread that calls it or whatever. If someone could give me a tip on how to solve this or what the proper way to create a persistent window is from the context of a DirectShow filter I'd appreciate it. Note, as I said the window needs to be persistent so I can't create it as a Filter property page.
Thanks,
Robert
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我无法帮助您了解 DirectShow 过滤器的具体信息,但我认为有关窗口和消息处理的一些常规信息可能会有所帮助。
Windows 具有线程关联性,这意味着窗口的所有消息都将在创建该窗口的线程的上下文中进行处理。这意味着该线程需要具有标准消息处理循环,即
Application.ProcessMessages()
的低级等效项。来自同一线程和其他线程的消息都将在创建线程的消息队列中排队,消息循环将获取它们,(可选)翻译它们,并将它们分派到目标窗口的窗口处理程序。您所描述的情况可能是由于
创建窗口的线程中没有消息处理队列,或者
创建错误线程中的窗口
(请注意,这些本质上是相同的,但这样表述很明显,可能存在导致此问题的不同问题,需要在不同的环境中修复)方式 - 要么需要在不同的线程中创建窗口,要么需要在线程中创建处理循环。)
您需要找出这两者中的哪一个导致您的窗口不处理消息。您不一定需要重写
WndProc()
,不同消息的消息处理方法将同样工作(或不工作)。您的WndProc()
被调用一次并不能真正告诉您太多信息,因为在某些情况下,从同一线程发送的消息将通过直接调用窗口过程来处理,而无需消息循环。由于您的过滤器驻留在 DLL 中,我认为创建您自己的消息循环不是正确的事情。这适用于模式对话框,将创建该对话框,消息循环将运行直到对话框关闭,然后消息循环将终止并且 DLL 函数将返回。它不适用于 DLL 导出函数,该函数将在消息循环仍在运行时被调用并需要返回所有内容。我假设创建和调用这些过滤器的框架也将处理消息循环。然而,这是一种直觉,不了解 DirectShow 过滤器这很可能是错误的。
可以帮助您调试此问题的是 Visual Studio 中的 Spy++ 等工具,您可以使用它显示有关窗口的信息、记录发送给它们或同一进程或线程中的所有窗口的消息、显示窗口层次结构以及执行许多其他操作有趣的事情。如果你没有,网上有很多克隆软件(一些免费软件),谷歌应该会出现。尝试显示发送到同一线程或进程的所有窗口的消息应该告诉您消息循环是否正在运行。您还应该能够通过运行 SysInternals Process Explorer 或类似工具来获取更多信息。
I can't help you with the DirectShow filter specifics, but I feel that some general information about windows and message handling might help.
Windows have thread affinity, which means that all messages for a window will be handled in the context of the thread that created it. That means that this thread needs to have the standard message processing loop, the low level equivalent of
Application.ProcessMessages()
. Both messages from the same and from other threads will be queued in the message queue of the creating thread, and the message loop will get them, (optionally) translate them, and dispatch them to the window handler of the target window.What you are describing could be caused by either
not having a message processing queue in the thread that creates the window, or
creating the window in the wrong thread
(Note that these are essentially the same, but stated like this it becomes apparent that there may be different problems that cause this, which need to be fixed in different ways - either the window needs to be created in a different thread, or a processing loop needs to be created in the thread.)
You need to find out which of the two causes your window not to process messages. You don't necessarily need to override
WndProc()
, message handling methods for distinct messages will work (or not work) the same. That yourWndProc()
was called once doesn't really tell you much, because under some circumstances messages sent from the same thread will be handled without the message loop, by calling the window proc directly.Since your filter resides in a DLL I don't think that creating your own message loop would be the right thing. This works for a modal dialog, which will be created, the message loop will run until the dialog is closed, and then the message loop will terminate and the DLL function will return. It will not work for a DLL exported function that will be called and needs to return all while the message loop is still running. I assume the framework that creates and calls those filters will handle the message loop as well. However, that is a gut feeling, not knowing about DirectShow filters this may well be wrong.
What might help you to debug this is a tool like Spy++ from Visual Studio, with which you can show information about windows, log messages sent to them or to all windows in the same process or thread, show window hierarchies and do a lot of other interesting things. If you don't have that, there are a lot of clones (some freeware) on the net, which Google should turn up. Trying to show the messages sent to all windows of the same thread or process should tell you whether a message loop is running. You should also be able to get more information by running SysInternals Process Explorer or similar tools.