读书人

关于PostMessage,以及模态非模态窗体解

发布时间: 2012-04-09 13:41:25 作者: rapoo

关于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值发生变化。

读书人网 >.NET

热点推荐