关于PostMessage,以及模态非模态窗体
这个是重发的,原来那个沉到底了
代码中,在一个串口监控线程用PostMessage给一个非模态窗口,老是不行,GetLastError=1440,说是句柄无效。
然后把这个窗口改成模态窗口,就成功了,搞不懂,难道真是非模态和模态的原因?
串口控件是CPort,监控线程中用到了CPort的WaitForEvent这个函数,源代码如下:
- Delphi(Pascal) code
// waits for event to occur on serial portprocedure TCustomComPort.WaitForEvent(var Events: TComEvents; StopEvent: THandle; Timeout: Integer);var Overlapped: TOverlapped; Mask: DWORD; Success: Boolean; Signaled, EventHandleCount: Integer; EventHandles: array[0..1] of THandle;begin // cannot call method if event thread is running if FThreadCreated then raise EComPort.CreateNoWinCode(CError_ThreadCreated); FillChar(Overlapped, SizeOf(TOverlapped), 0); Overlapped.hEvent := CreateEvent(nil, True, False, nil); EventHandles[0] := Overlapped.hEvent; if StopEvent <> 0 then begin EventHandles[1] := StopEvent; EventHandleCount := 2; end else EventHandleCount := 1; try SetCommMask(FHandle, EventsToInt(Events)); // let's wait for event or timeout Success := WaitCommEvent(FHandle, Mask, @Overlapped); if (Success) or (GetLastError = ERROR_IO_PENDING) then begin Signaled := WaitForMultipleObjects(EventHandleCount, @EventHandles, False, Timeout); Success := (Signaled = WAIT_OBJECT_0) or (Signaled = WAIT_OBJECT_0 + 1) or (Signaled = WAIT_TIMEOUT); SetCommMask(FHandle, 0); end; if not Success then raise EComPort.Create(CError_WaitFailed, GetLastError); Events := IntToEvents(Mask); finally CloseHandle(Overlapped.hEvent); end;end;
我的监控线程大体如下:
[Delphi(Pascal) code]
procedure TControlThread.Execute;
var
Msg:TMsg;
begin
FreeOnTerminate:=True;
while True do
begin
if PeekMessage(Msg,0,0,0,PM_REMOVE) then
begin
if Msg.message = WM_COLLECT_STOP then
begin
FQuitEvent.SetEvent;
Break;
end;
end;
if FSerialPort.ReceiveTerminalParam(FStopEven) then
begin
PostMessage(FFormHandle,WM_RECEIVE_PROBEPARAM,0,0); //这个FFormHandle如果是非模态窗体的句柄就失败;如果是模态窗体句柄就成功!
SaveProbeParam(FSerialPort.ProbeParam);
Sleep(500);
end;
end;
end;
[/Code]
ReceiveTerminalParam函数
[Delphi(Pascal) code]
function TControlSerialPort.ReceiveTerminalParam(StopEvent:TEvent):Boolean;
begin
Result:=False;
if WaitForUpload(StopEvent) then
begin
//检测串口缓冲中的数据标志及长度
//处理数据
end;
end;
[/Code]
WaitForUpload函数:
[Delphi(Pascal) code]
function TControlSerialPort.WaitForUpload(StopEvent:TEvent): Boolean;
var
Events:TComEvents;
begin
Result:=False;
Events:=[evRxChar];
FComPort.WaitForEvent(Events,StopEvent.Handle,WaitInfinite);
if evRxChar in Events then
Result:=True;
end;
[/Code]
StopEvent用于终止监控串口
[解决办法]
你先看看FFormHandle你是否得到了
[解决办法]
记住窗体的Handle并不是一个好的方式。因为窗体的handle可能会发生变化。比如在设置form.Postion时,会触发WinControl.ReCreateWnd方法。这会导致窗体handle值发生变化。