- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的代码在主 VCL 线程的上下文中运行时运行良好。该代码分配了它自己的 WndProc() 以处理 SendMessage() 调用。我现在尝试将其移至后台线程,因为我担心 SendMessage() 流量会对主 VCL 线程产生不利影响。因此,我创建了一个工作线程,其唯一目的是在其线程 Execute() 方法中分配 WndProc(),以确保 WndProc() 存在于线程的执行上下文中。 WndProc() 处理传入的 SendMessage() 调用。问题是工作线程的 WndProc() 方法永远不会被触发。
注意,doExecute() 是模板方法的一部分,由我的 TThreadExtended 类调用,该类是 Delphi 的 TThread 的后代。 TThreadExtended 实现线程 Execute() 方法并在循环中调用 doExecute()。我进行了三次检查,并且 doExecute() 被重复调用。另请注意,我在创建 WndProc() 之后立即调用 PeekMessage(),以确保 Windows 为线程创建消息队列。然而,我所做的事情是错误的,因为 WndProc() 方法从未被触发。代码如下:
// ========= BEGIN: CLASS - TWorkerThread ========================
constructor TWorkerThread.Create;
begin
FWndProcHandle := 0;
inherited Create(false);
end;
// ---------------------------------------------------------------
// This call is the thread's Execute() method.
procedure TWorkerThread.doExecute;
var
Msg: TMsg;
begin
// Create the WndProc() in our thread's context.
if FWndProcHandle = 0 then
begin
FWndProcHandle := AllocateHWND(WndProc);
// Call PeekMessage() to make sure we have a window queue.
PeekMessage(Msg, FWndProcHandle, 0, 0, PM_NOREMOVE);
end;
if Self.Terminated then
begin
// Get rid of the WndProc().
myDeallocateHWnd(FWndProcHandle);
end;
// Sleep a bit to avoid hogging the CPU.
Sleep(5);
end;
// ---------------------------------------------------------------
procedure TWorkerThread.WndProc(Var Msg: TMessage);
begin
// THIS CODE IS NEVER CALLED.
try
if Msg.Msg = WM_COPYDATA then
begin
// Is LParam assigned?
if (Msg.LParam > 0) then
begin
// Yes. Treat it as a copy data structure.
with PCopyDataStruct(Msg.LParam)^ do
begin
... // Here is where I do my work.
end;
end; // if Assigned(Msg.LParam) then
end; // if Msg.Msg = WM_COPYDATA then
finally
Msg.Result := 1;
end; // try()
end;
// ---------------------------------------------------------------
procedure TWorkerThread.myDeallocateHWnd(Wnd: HWND);
var
Instance: Pointer;
begin
Instance := Pointer(GetWindowLong(Wnd, GWL_WNDPROC));
if Instance <> @DefWindowProc then
begin
// Restore the default windows procedure before freeing memory.
SetWindowLong(Wnd, GWL_WNDPROC, Longint(@DefWindowProc));
FreeObjectInstance(Instance);
end;
DestroyWindow(Wnd);
end;
// ---------------------------------------------------------------
// ========= END : CLASS - TWorkerThread ========================
谢谢,罗伯特
最佳答案
问题是您创建了一个窗口来接收消息,但是您没有标准的消息循环来实际从消息队列中检索消息并让目标窗口处理它们。您需要的是 Application
消息循环的等效项,其 API 形式如下所示:
while integer(GetMessage(Msg, HWND(0), 0, 0)) > 0 do begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
在线程代码中执行此操作(或类似的操作)是必要的。
请注意,您的工作线程中根本不需要辅助窗口,因为线程本身可以有一个消息队列,可以通过调用 PostThreadMessage()
将消息排队到该队列中。 。这相当于标准 PostMessage()
函数调用。两者都不会等待消息被处理,而是立即返回。如果这对您不起作用,那么您确实应该在线程中创建一个窗口并调用 SendMessage()
为了它。然而,消息循环在所有情况下都是必要的。
由于 GetMessage()
是一个阻塞调用,因此您也不必担心“占用 CPU”,因此不需要 Sleep()
调用。
关于Delphi - 线程中的 WndProc() 从未被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2615024/
我有一个让我抓狂的问题。我花了一个星期的时间来追查这个错误,可能只是我对互操作的理解不如我想的那样。在这里: 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。并接收窗口消息。 但是,当表单最小化时,我不再收到任何消息。我知道它必须是那样的,但是有解决方法吗?我不想有一个始终保持打开状态的隐藏表单... 最佳答
我是一名优秀的程序员,十分优秀!