Windows and message handling. Part 2


© Lyapin Ilya

Previous article is a theoretical introduction into windows and message handling. Now let's look at the example.
Let's take an example from Client Message Handling article and rework it using windows and messages.

Terms.

May be you remember that previous example shows how to create message (task) queue processed in context of the separate thread and communications between the main and working threads.

Like in previous example. let's assume that the thread receives abstract blocks of data (TILClientData objects) and "process" them sequentially calling its "ProcessData()" method.

Previous implementation of TMyThread create critical section protected list and manage the queue on it's own. Now Windows will manage queue for us (or we'll use standard thread message queue). You will see that the source code is somewhat smaller.

AllocateHWnd and DeallocateHWnd functions.

The window should be created in order to receive messages and process them in the context of the thread. The easiest way to create window is AllocateHWnd function (Forms unit).

It create popup window of 'TPUtilWindow' class. The only needed parameter is address of the window function, so you do not need to specify numerous parameters of CreateWindows API function. Please note that window function should be a class method and is called with object instance in the Self parameter.

Handle returned by AllocateHWnd should be further closed by DeallocateHWnd.

Source code.

TMYTHREAD implementation looks like following

const

CM_TERMINATE=WM_USER+$100;
cm_DATA=WM_USER+$101;

type

TMyThread=class(TThread)
private

hWindow:HWND;
procedure DoProcessData(Item:TObject);
procedure WinProc(var Message:TMessage);

protected

procedure Execute;override;

public

procedure terminate;
procedure AddToProcess(Item:TObject);
constructor Create;
destructor Destroy;override;

end;

// TMyThread

constructor TMyThread.Create;
begin

inherited Create(true);

end;

destructor TMyThread.Destroy;
begin

inherited Destroy;

end;

procedure TMyThread.Execute;
var MSG:tmsg;
begin
try

hWindow:=AllocateHWnd(WinProc);
try

PeekMessage(MSG,0,0,0,PM_NOREMOVE);
Form1.Memo1.Lines.Add('Begin execution');

repeat

if GetMessage(msg,0,0,0) then
DispatchMessage(MSG);

until terminated;

Form1.Memo1.Lines.Add('Finishing execution...');
while PeekMessage(msg,0,0,0,PM_REMOVE) do
DispatchMessage(MSG);
Form1.Memo1.Lines.Add('Finish execution');

finally

DeallocateHWnd(hWindow);
hWindow:=0;

end;

except on e:Exception do
begin

ShowMessage('Unhandled exception in TMyThread.Execute:'+e.ClassName+' '+
e.Message+#13'Appliction wil be terminated');ExitProcess(1);

end;
end;
end;

procedure TMyThread.terminate;
begin

PostMessage(hWindow,CM_TERMINATE,0,0);

end;

procedure TMyThread.AddToProcess(Item:TObject);
begin

Form1.Memo1.Lines.Add('Adding item #'+Inttostr(TILClientData1(Item).FRNumber));
Win32Check(PostMessage(hWindow,cm_DATA,Integer(Item),0));

end;

procedure TMyThread.DoProcessData(Item:TObject);
begin

TILClientData(Item).ProcessData;
Item.Free;

end;

procedure TMyThread.WinProc(var Message: TMessage);
begin

case Message.Msg of
CM_TERMINATE: inherited terminate;
cm_DATA: DoProcessData(TObject(Pointer(Message.WParam)));
else Message.Result:=DefWindowProc(hWindow,Message.Msg,Message.WParam,Message.LParam);
end;

end;

Code explanation.

The most part of the module is the same (only TMyThread implementation is affected) - so here is only changes.
TILClientData, TILClientData1, TForm1 classes are explaned in previous articles.

Const section of the unit declares two constants - CM_DATA and CM_TERMINATE - message identifiers. Please note that their values are from the range that is intended for private application message. It's good way to avoid message id conflicts.

TMyThread class inherited from TThread represents new thread.

TmyThread.Execute creates window by calling AllocateHWnd function and enter the message loop. Terminated property should be set to TRUE to break the loop. All unprocessed messages will be processed by second PeekMessage loop. Then the window handle will be freed and thread finishes execution.

Go To Page: 1 2


The copyright of the article Windows and message handling. Part 2 in Delphi Programming is owned by . Permission to republish Windows and message handling. Part 2 in print or online must be granted by the author in writing.

Post this Article to facebook Add this Article to del.icio.us! Digg this Article furl this Article Add this Article to Reddit Add this Article to Technorati Add this Article to Newsvine Add this Article to Windows Live Add this Article to Yahoo Add this Article to StumbleUpon Add this Article to BlinkLists Add this Article to Spurl Add this Article to Google Add this Article to Ask Add this Article to Squidoo