首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

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

2012-04-09 
关于PostMessage,以及模态非模态窗体这个是重发的,原来那个沉到底了代码中,在一个串口监控线程用PostMessa

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

热点排行