- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个高度多线程的 Delphi 6 应用程序。我创建了一个源自 TWinControl 的组件。当我第一次构建它时,我使用了一个隐藏窗口,它是 WndProc 来处理消息,并使用 AllocateHwnd() 进行分配。最近,我开始清理代码中的 WndProc,并决定删除辅助 WndProc()。我更改了组件以重写基类 WndProc() 方法,并从那里进行自定义 Windows 消息处理。在该 WndProc() 中,我首先调用继承的处理程序,然后处理我的自定义消息(WM_USER 偏移量),如果找到我的自定义消息之一并处理它,则将消息结果字段设置为 1。
一个重要的说明。我在 WndProc() 重写的顶部放置了一行代码,如果当前线程 id 不是 VCL 主线程,则该代码会抛出异常。我想确保 WndProc() 仅在主 VCL 线程的上下文中执行。
完成此操作并运行我的程序后,我遇到了一些看起来非常奇怪的事情。我正常运行我的程序并执行各种任务,没有出现错误。然后,当我转到与我的 TWinControl 后代位于同一页面上的 TMemo 控件时。如果我在 TMemo 控制内部单击,则会触发主线程检查我的 WndProc() 覆盖。我在上面设置了一个断点,当我进入调用堆栈时,在我的 WndProc() 覆盖之上没有任何内容。
据我所知,并且我已经仔细检查过,我没有对 WndProc() 重写进行显式调用。那不是我会做的事情。但考虑到我的 TWinControl 组件会像所有其他组件一样在主 VCL 线程上创建,我无法理解 WndProc() 重写如何在后台线程的上下文中执行,特别是只有当像这样的 UI 操作时鼠标点击就会发生。我了解我的 WndProc() 是如何与 TMemo 控件绑定(bind)的,因为所有子窗口都卡在顶级窗口 WndProc() 之外,至少这是我的理解。但由于所有组件窗口都是在主 VCL 线程上创建的,那么它们的所有消息队列也应该在该上下文中执行,对吗?
那么我可以创建什么样的情况来让我的 WndProc() 运行,并且只是有时在后台线程的上下文中运行?
最佳答案
在工作线程上下文中可以通过两种方式调用主线程组件的 WndProc()
方法:
工作线程直接调用组件的 WindowProc
属性或其 Perform()
方法。
工作线程通过不安全地使用 TWinControl.Handle
属性窃取了组件窗口的所有权。 Handle
属性 getter 不是线程安全的。如果工作线程在主线程重新创建组件窗口的同一时刻从 Handle
属性中读取数据(TWinControl
窗口不是持久的 - 各种运行时条件可以动态地重新创建它们不会影响大部分 UI 逻辑),然后存在竞争条件,可能允许工作线程在其自己的上下文中分配新窗口(并导致主线程泄漏另一个窗口)。这将导致主线程停止在其上下文中接收和发送消息。如果工作线程有自己的消息循环,那么它将接收和分派(dispatch)消息,从而在错误的线程上下文中调用 WndProc()
方法。
不过,我发现没有生成任何调用堆栈,这很奇怪。应该始终存在某种可用的跟踪。
此外,请确保 MainThreadId
变量(或用于跟踪主线程的任何变量)不会被意外损坏。确保其当前值与启动时的初始值一致。
您应该做的另一件事是在调试器中命名所有线程实例(此功能在 Delphi 6 中引入)。这样,当您的线程验证被触发时,调试器可以向您显示正在调用 WndProc()
方法的线程上下文的确切名称(即使没有调用堆栈跟踪),然后您可以查看查找该线程代码中的错误。
关于delphi - Delphi 6 TWinControl 后代的 WndProc() 有时如何在主 VCL 线程之外执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9060045/
我有一个让我抓狂的问题。我花了一个星期的时间来追查这个错误,可能只是我对互操作的理解不如我想的那样。在这里: public class User { public const int GWL_W
我正在尝试处理 .NET WebBrowser 类型的 Close 事件,这似乎不是开箱即用的。 ( 编辑: 当在浏览器中运行的脚本中发出 window.close() 调用时,会发出此事件。) 我见
一天前,我开始重写我的一个旧组件,并决定提高其可读性。我的组件是一个典型的 TWinControl,它已重写 WndProc 来处理我自己的大量消息。每条消息都有很多代码,阅读代码成了一个问题。 因此
我正在阅读一些教程,遇到以下结构: protected override void WndProc( ref Message m ) { ... base.WndProc( ref m
我想在第二个线程上创建一个表单,该表单将在其 WndProc 方法中接收消息。创建这样的隐形表格的推荐方法是什么?设置“ShowInTaskbar=false”和“Visible=false”是否足够
我的表单中有以下 WndProc 处理程序。它应该防止水平移动表单(只允许垂直移动): protected override void WndProc(ref System.Windows.Forms
我被困住了。我有一个结构 vector ,其成员之一是 HWND。我使用这些 HWND 来处理消息,其他成员是特定于实例的参数。我使用 lpParam 将指向每个新创建的结构实例的指针传递给 WndP
我正在尝试创建一个自定义 GLWindow 类,其中包括我对 OpenGL 窗口的所有设置。但是,我还想在我的 GLWindow 类中包含用于发送到窗口的消息的 WndProc 回调函数。 GLWin
我创建了一个创建DLL 的项目。该项目使用WFS方法,它们访问一些硬件(设备)以获取信息或执行一些命令。 在我的项目中,我首先打开这些设备然后注册它们,然后我使用其他方法获取信息或执行。 HRESUL
我不是 C++ 的新手,但是 Win32 编程的概念对我来说是相当新的。无论如何,当 WM_NCHITTEST 消息通过 WndProc 传递时,我在获取 X 和 Y 坐标时遇到了一些麻烦。为了立即尝
我有一个 Window 类,它包含一个方法来设置窗口句柄 (HWND) 的属性。该方法执行以下功能: _hWnd = CreateWindowEx(dwExStyle, _wcex.lpszClass
我想在它自己的 wndproc 中处理所有 ListBox 消息传递,用于自己的透明项目绘画与 MainWindow 中显示的图像混合。不幸的是,现在只有 WM_PAINT、WM_ERASEBKGND
如果我有一个控制台应用程序,它的句柄是这样设置的; HWND hWnd = GetConsoleWindow(); 那我该如何为窗口设置一个新的wndProc呢? 我尝试使用 SetWindowLon
创建标准窗口控件(例如 "EDIT" 控件)时,其 WNDPROC 被定义为窗口类的一部分(即 "EDIT " 有一个特定的 WNDPROC,旨在使窗口显示并充当编辑控件。 MFC 允许您通过它们的包
当我创建一个新的 Win32 应用程序时,我注意到函数: LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
我想知道是否有一种方法可以缩短这段代码,是否有办法制作一个 #define 来缩短我在消息开关中执行 if 语句的方式。我检查我是否已经设置了一个函数,如果有我就调用它这只是我的 wndproc 的一
我一直在四处寻找,并没有真正看到太多关于为什么有人会覆盖 wndproc 来处理消息的信息。 所以我想知道: 为什么要这样做? 什么时候做? 它在 C# 中的一般用途是什么? 当看到串行 COM 从计
这是我目前所拥有的...即使我实例化了一个 Window(WindowBase 的子类),我还是收到了一个错误,即试图调用一个纯虚函数。基本上,我的程序试图调用 WindowBase::WndProc
我有一个小问题希望有人能帮助我。有什么方法可以连接到其他应用程序 WNDPROC? 情况是我想在另一个应用程序菜单栏中插入一个菜单,并且我想为每个菜单项定义命令。 我能够使用一些 Win32 API
要与特定服务通信,我必须覆盖 WindProc。并接收窗口消息。 但是,当表单最小化时,我不再收到任何消息。我知道它必须是那样的,但是有解决方法吗?我不想有一个始终保持打开状态的隐藏表单... 最佳答
我是一名优秀的程序员,十分优秀!