麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > Delphi > 正文

Delphi關(guān)于線程的消息處理

2019-11-18 18:03:06
字體:
供稿:網(wǎng)友
 

在平時寫程序時,總是碰到窗體(TForm)與線程(TThread)消息通信問題。令人煩惱的是窗體不能向線程(TThread)發(fā)送消息(線程沒有窗口句柄)。經(jīng)過幾天的折騰,想出二種解決方案,拿出來跟大家探討探討。

第一。我們知道VC++ 中的MFC類庫是自已封裝了消息處理(BEGINMESSAGE, ENDMESSAGE),在MFC中對消息的處理是通過建立一張消息映射表,而把方法(function)或過程(PRocedure)的地址保存到映射表里(消息處理實(shí)質(zhì)上是方法或過程的調(diào)用),再加上一個消息分發(fā)機(jī)制,來實(shí)現(xiàn)消息的接收發(fā)送 <詳見VC++技術(shù)內(nèi)幕>。所以我們只要為線程里建立一張消息映射表,并建立相應(yīng)的消息分發(fā)機(jī)制。這樣就可以處理窗體發(fā)送到線程的消息。以下代碼是實(shí)現(xiàn)消息映射表和消息分發(fā)的類(詳見 <../消息處理設(shè)計(jì)(線程)1/MessageHandle.pas>

unit MessageHandle;

 

interface

uses messages,Classes,SysUtils,Dialogs;

 

const PMSG_BASE = $BE00;   //自定義消息基址;

      PMSG_NUM = 200;      //消息表大小;

 

{**自定義消息處理類

  *;功能 = 建立自定義消息表,處理線程之間

  *   以及與主窗體之間的自定義消息(宏觀)

*}

 

  //消息處理句柄

  TMessageHandle = procedure(var Message: TMessage) of Object;

 

  TPDispatcher = class(TObject)

  private

    //消息對應(yīng)表(消息ID為數(shù)組下標(biāo));

    MessageHandles: array of TMessageHandle;

    //從消息ID得到數(shù)組ID

    function GetIndexFromMsgID(const aMessageID: cardinal): Integer;

  public

    constructor Create;

    destructor Destroy;

    //發(fā)送消息

    procedure SendMessage(var Message: TMessage); overload;

    //添加自定義消息到消息對應(yīng)表;

    procedure AddHandle(const aMessageID: cardinal; aMessageHandle: TMessageHandle);

  end;

  //

 

implementation

 

{ TPDispatcher }

constructor TPDispatcher.Create;

var i: Integer;

begin

  SetLength(MessageHandles,PMSG_NUM);  //200個消息的消息對應(yīng)表

  //初始化消息隊(duì)列;

  for i := 0 to Pred(PMSG_NUM) do

    MessageHandles[i] := nil;

end;

 

destructor TPDispatcher.Destroy;

begin

   {釋放消息對應(yīng)表}

  FreeAndNil(MessageHandles);

end;

 

procedure TPDispatcher.AddHandle(const aMessageID: cardinal;

  aMessageHandle: TMessageHandle);

var tID: Integer;

begin

  tID := GetIndexFromMsgID(aMessageID);

  Assert((tID > 0) or (tID < Pred(PMSG_NUM)) );

  Assert(Assigned(aMessageHandle));

  MessageHandles[tID] := aMessageHandle;

end;

 

function TPDispatcher.GetIndexFromMsgID(const aMessageID: cardinal): Integer;

begin

  Result := aMessageID - PMSG_BASE;

end;

 

procedure TPDispatcher.SendMessage(var Message: TMessage);

var tID: Integer;

    tMsgHandle: TMessageHandle;

begin

  tID := GetIndexFromMsgID(Message.Msg);

  Assert((tID > 0) or (tID < Pred(PMSG_NUM)));

  tMsgHandle := MessageHandles[tID];

 

  if Assigned(tMsgHandle) then

    tMsgHandle(Message);

end;

現(xiàn)在我們只需要注冊一下自定義的消息,然后通過消息分發(fā)類(TPDispatcher),實(shí)現(xiàn)對線程消息的處理。代碼如下<詳見../消息處理設(shè)計(jì)(線程)1/test/unit1.pas>

Unit unit1

const

      {自定久線程消息}

      MY_MESSAGE2 = PMSG_BASE + 02; 

type

  TForm1 = class(TForm)

    AddMsgList: TButton;

    SendThead: TButton;

    sendForm: TButton;

    sendOther: TButton;

    procedure SendTheadClick(Sender: TObject);  //發(fā)送消息

    procedure FormCreate(Sender: TObject);

    procedure FormDestroy(Sender: TObject);

  private

    Fdispatcher: TPDispatcher;  消息映射表類

    Fhandle: TPHandler;

    FThread:  TPTHread;  自定義線程類

  public

    { Public declarations }

  end;

 

var

  Form1: TForm1;

 

implementation

 

{$R *.dfm}

procedure TForm1.SendTheadClick(Sender: TObject);

var aMessage: TMessage;begin

    aMessage.Msg := MY_MESSAGE2;

    aMessage.WParam := 1;

    Fdispatcher.SendMessage(aMessage);

  end;

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

  {創(chuàng)建消息映射表類}

  Fdispatcher := TPDispatcher.Create;

  Fhandle := TPHandler.Create;

  {創(chuàng)建線程}

    FThread := TPThread.Create(false);

  {向映射表中增加消息}

   Fdispatcher.AddHandle(MY_MESSAGE2,FThread.DoMessage);

end;

 

procedure TForm1.FormDestroy(Sender: TObject);

var i: Integer;

begin

  FreeAndNil(Fdispatcher);

  FreeAndNil(Fhandle);

  for i:= 0 to 3 do

    FreeAndNil(FThread[i]);

end;

 

第二。窗口可以處理消息是因?yàn)樗写翱诰浔榱耸咕€程也能處理消息,我們可以通過為線程加上一個相應(yīng)窗口類的窗口名柄。(源碼 <../消息處理設(shè)計(jì)(線程)2 / pThread.pas >中)

unit pThread;

 

interface

uses classes,sysutils,Windows,Messages,Dialogs;

const MY_MESSAGE1 = $BD00 + 01;

Type

{** 消息處理線程類

  *;功能 = 添加線程處理消息能力,

*}

  TPMsgThread = class(TThread)

  private

    //窗口句柄

    FWndHandle: HWND;

    //窗口數(shù)據(jù)信息

    FWndClass: WNDCLASS;

    //指向窗口回調(diào)函數(shù)的指針

    FObjectInstance: Pointer;

    //初始化窗口數(shù)據(jù)

    procedure InitWnd;

    //創(chuàng)建隱藏窗口

    procedure CreateWnd;

    //注冊隱藏窗口

    procedure RegistWnd;

    procedure DestroyWnd;

    //窗口回調(diào)函數(shù)

    procedure pWndProc(var Message: TMessage); virtual;

  protected

    procedure Execute; override;

    procedure DoTerminate; override;

  public

    constructor Create(CreateSuspended: Boolean); virtual;

    property WndHandle: HWND read FWndHandle write FWndHandle;

  end;

 

implementation

const WND_NAME = 'PY20';

{ TPMsgThread }

 

constructor TPMsgThread.Create(CreateSuspended: Boolean);

begin

  inherited Create(CreateSuspended);

  FWndHandle := Integer(nil);

  InitWnd;

  RegistWnd;

  CreateWnd;

end;

 

procedure TPMsgThread.CreateWnd;

begin

  if(WndHandle = Integer(nil)) then

    WndHandle := CreateWindow(FWndClass.lpszClassName, FWndClass.lpszClassName,

      WS_POPUP or WS_CAPTION or WS_CLipSIBLINGS or WS_SYSMENU

      or WS_MINIMIZEBOX,

      GetSystemMetrics(SM_CXSCREEN) div 2,

      GetSystemMetrics(SM_CYSCREEN) div 2,

      0, 0, 0, 0, FWndClass.hInstance, nil);

  //置換窗口回調(diào)函數(shù)

  SetWindowLong(WndHandle, GWL_WNDPROC, Longint(FObjectInstance));

end;

 

procedure TPMsgThread.DestroyWnd;

begin

  UnregisterClass(FWndClass.lpszClassName,FWndClass.hInstance);

  DestroyWindow(WndHandle);

end;

 

procedure TPMsgThread.DoTerminate;

begin

  inherited;

  DestroyWnd;

end;

 

procedure TPMsgThread.Execute;

begin

end;

 

procedure TPMsgThread.InitWnd;

begin

  FwndClass.lpszClassName := PChar(WND_NAME);

  FWndClass.hInstance := Handle;

  FWndClass.lpfnWndProc := @DefWindowProc;

end;

 

procedure TPMsgThread.pWndProc(var Message: TMessage);

begin

end;

 

procedure TPMsgThread.RegistWnd;

begin

  FObjectInstance := Classes.MakeObjectInstance(pWndProc);

  if(FWndClass.hInstance <> Integer(nil)) then

    RegisterClass(FWndClass);

end;


上一篇:Delphi控件制作技巧[二]

下一篇:Delphi控件制作技巧[一]

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
學(xué)習(xí)交流
熱門圖片

新聞熱點(diǎn)

疑難解答

圖片精選

網(wǎng)友關(guān)注

主站蜘蛛池模板: 色七七网站 | 亚洲免费永久 | 一本一本久久a久久精品综合小说 | 欧美淫视频| 欧美日韩精品中文字幕 | 最新一区二区三区 | 久久精品亚洲一区 | 性视频久久 | 成人免费网视频 | 成熟女人特级毛片www免费 | av在线视| 免费在线观看毛片视频 | 国产成人精品区 | 毛片视频网址 | 欧美人xx| 国产免费成人在线 | 嫩草www | 毛片大全在线观看 | 一级美女大片 | 欧美日本91精品久久久久 | 成人艳情一二三区 | 国产精品久久久久久久av三级 | 国产91久久久久 | 国产精品一区自拍 | 国产精品自拍啪啪 | 亚洲精品aⅴ中文字幕乱码 欧美囗交 | 中文欧美日韩 | 四季久久免费一区二区三区四区 | 一区二区久久 | 欧美色性 | 久久伊人国产精品 | 黄色毛片视频在线观看 | 久久亚洲成人网 | 成人h精品动漫一区二区三区 | 小情侣嗯啊哦视频www | 免费观看一区二区三区视频 | 99精品视频在线看 | 制服丝袜成人动漫 | 婷婷中文字幕一区二区三区 | 国产精品.com| 性爱免费视频 |