后台线程可以配置为接收窗口消息.您可以使用发布消息到线程PostThreadMessage.退出该消息循环的正确方法是什么?
在将消息发布到后台线程之前,线程需要通过调用PeekMessage以下内容来确保创建消息队列:
procedure ThreadProcedure;
var
msg: TMsg;
begin
//Call PeekMessage to force the system to create the message queue.
PeekMessage(msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
end;
Run Code Online (Sandbox Code Playgroud)
现在外面的世界能够将消息发布到我们的线程:
PostThreadMessage(nThreadID, WM_ReadyATractorBeam, 0, 0);
Run Code Online (Sandbox Code Playgroud)
我们的线程处于GetMessage循环中:
procedure ThreadProcedure;
var
msg: TMsg;
begin
//Call PeekMessage to force the system to create the message queue.
PeekMessage(msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
//Start our message pumping loop.
//GetMessage will return false when it receives a WM_QUIT
// GetMessage can return -1 if …Run Code Online (Sandbox Code Playgroud) 我有第三方功能
function DataCompare(const S1, S2: string; APartial: Boolean): Boolean;
begin
...
end;
Run Code Online (Sandbox Code Playgroud)
它用于另一个第三方单元.
我希望在运行时用另一个新实现替换函数体.
这可能吗?我想需要一些黑客(ala VirtualMemoryUnprotect).非汇编解决方案非常受欢迎.
这是一个后续问题.
我之前的问题:
我的问题:
TComponent没有像TWinControl这样的窗口句柄.我不想依赖外部的.
这是我的自定义组件的片段
type
TMyClipBoardListener = class(TComponent)
private
FInnerWindowHandle: HWnd;
FNextHWnd: HWnd;
//...
protected
procedure Loaded; override;
procedure WndProc(var Msg: TMessage); // <<< This is my wouldbe Window to handle messages
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
// ...
published
// ...
end;
Run Code Online (Sandbox Code Playgroud)
我的自定义组件的实现摘录
constructor TMyClipBoardListener .Create(AOwner: TComponent);
begin
inherited;
//
FInnerWindowHandle := ...; // <<< What to do here ? Should I pass it to a function/procedure I missed?
end;
destructor TMyClipBoardListener .Destroy; …Run Code Online (Sandbox Code Playgroud) 我正在研究小型监控应用程序,它将通过SNMP,TCP,ICMP与某些设备进行通信,其他线程必须执行一些计算.所有这些结果我必须在GUI(一些Forms或TabSheets)中输出.
我正在考虑下一个可能性:
Synchronize从每一个工作者线程: Synchronize,但仅限于GUI专用线程,或GUI上的Critical Section来显示消息. TTimer主要形式,它将定期检查(100-1000毫秒)共享缓冲区并消耗,而不是Windows消息传递.(它对消息传递有一些好处吗?)亲爱的专家,请解释什么是最佳实践或暴露的替代品的优缺点是什么.
更新:
作为想法:
//共享缓冲区+发送消息变量
LogEvent全局函数将从任何地方调用(也来自工作线程):
procedure LogEvent(S: String);
var
liEvent: IEventMsg;
begin
liEvent := TEventMsg.Create; //Interfaced object
with liEvent do
begin
Severity := llDebug;
EventType := 'General';
Source := 'Application';
Description := S;
end;
MainForm.AddEvent(liEvent); //Invoke main form directly
end;
Run Code Online (Sandbox Code Playgroud)
在主窗体中,事件ListView和共享部分(fEventList: TTInterfaceList已经是线程安全的)我们将:
procedure TMainForm.AddEvent(aEvt: IEventMsg);
begin
fEventList.Add(aEvt);
PostMessage(Self.Handle, WM_EVENT_ADDED, 0, 0);
end;
Run Code Online (Sandbox Code Playgroud)
消息处理程序
procedure WMEventAdded(var Message: TMessage); message WM_EVENT_ADDED;
...
procedure TMainForm.WMEventAdded(var …Run Code Online (Sandbox Code Playgroud) 我的问题是正常的mfc SetTimer,如下所示
void CTimersDlg::OnButtonBegin()
{
// create the timer
SetTimer(m_nTimerID, uElapse, NULL);
}
void CTimersDlg::OnButtonStop()
{
// destroy the timer
KillTimer(m_nTimerID);
}
void CTimersDlg::OnTimer(UINT nIDEvent) // called every uElapse milliseconds
{
// do something, but quickly
CDialog::OnTimer(nIDEvent);
}
Run Code Online (Sandbox Code Playgroud)
但是如果我需要在非dialog.cpp中使用SetTimer,例如在我的sender.cpp中如何创建计时器?在SetTimer字段中,处理程序(回调)函数?
为什么它用于挂钩和重定向功能?
像这样:
procedure RedirectProcedure(OldAddress, NewAddress: Pointer);
var
NewCode: TInstruction;
begin
NewCode.Opcode := $E9; //relative jump
NewCode.Offset := NativeInt(NewAddress)-NativeInt(OldAddress)-SizeOf(NewCode);
PatchCode(OldAddress, NewCode, SizeOf(NewCode));
end;
Run Code Online (Sandbox Code Playgroud)
顺便说一句,$ E9常数意味着什么?