Title: Messages between a ClientEXE and a FormDLL
Question: This overview describes messages send back from a DLL to a client and explains how to receive and use them in your application.
Answer:
The code snippet provides a set of mechanisms for facilitating communications between a client and a form DLL.
It's possible to check for example in a multiple choice test the answers from a form DLL with the help of win messages.
Let's start with the client (EXE), which declares functions of DLL:
procedure WMNotifyMsg(var Msg: TMessage);
Message wm_User+2001;
function createDialog(Parent: THandle): DlgHandle; FAR;
EXTERNAL 'mcdialog.dll'; index 1;
procedure setQuestion(Handle: DlgHandle; quest,
answ1, answ2, answ3: PChar); FAR;
EXTERNAL 'mcdialog.dll'; index 2;
the index number increases speed slightly, cause the function that is to be dynamically linked doesn't need to be searched by name.
So next we have to create the form (questDialog) from the DLL:
type
dlgHandle = Pointer;
private
questDialog : dlgHandle;
//property Handle: HWnd read GetHandle; from Controls
procedure TForm1.FormCreate(Sender: TObject);
begin
questDialog:= createDialog(handle);
S_Stop:= false;
timer1.Enabled:= true;
timesec:= 1;
newQuestion;
end;
With the handle passed to the DLL we provide a kind of callback.
When the client establishes a link by using the createDialog(handle), with the handle property of itself in the Controls structure, the client has requested the DLL send the answer item back each time the item's value in the dllform changes.
The questDailog is then a pointer to the dllform.
questDialog:= createDialog(handle);
In such cases, the DLL sends the new value of the data item in the specified format by PostMessage(ParentHandle, WMNotifyMsg, answer, 0) and sends the client back a WMNotifyMsg message, as shown in the next example:
from the DLL
---------------------------------------------------
We use the same msg identifier like the client:
const
WMNotifyMsg = wm_User+2001;
In the dll we create the form and save the client handle (parentHandle) which is the handle to the the window that received WM_NOTIFY.
function createDialog(Parent: THandle): TfrmQuest; export;
begin
result:= TfrmQuest.Create(Application);
result.ParentHandle:= Parent;
result.Show;
end;
Now we're able to proceed a simple message to the client:
procedure Tfrmquest.BitBtnIgnoreClick(Sender: TObject);
begin
//50 is coded as ignore an answer from DLLForm to EXE
notify(50);
end;
The notify procedure in the DLL is the name of the remote procedure which sends messages to the client:
procedure Tfrmquest.Notify(answer: WORD);
begin
if ParentHandle 0 then
PostMessage(ParentHandle, WMNotifyMsg, answer, 0);
end;
The WM_NOTIFY message informs the parent window of a control that an event has occurred in the control or that the control requires some kind of information.
procedure Tfrmquest.btnnextClick(Sender: TObject);
begin
Notify(ansGroup.ItemIndex+1);
end;
At least the client proceeds with the calculation of answers:
procedure TForm1.WMNotifyMsg(var Msg: TMessage);
begin
if not S_Stop then begin;
Inc(qnumber);
if CORRECT_[questNr] = Msg.WParam then
Inc(correct)
else begin
if Msg.WParam = 50 then
inc(ignored) else
if msg.WParam 0 then
Inc(wrong);
end;
calcAnswers;
end;
end;
clientEXE formDLL
I I
I------createDialog(handle)--------------- I parenthandle
I I
I I I---show--I
I I I------newQuestion------------------------ I
I ---notify-I
I I I I
Tip: When you want to open n-Forms in a form-dll with ShowModal() but you and others don't want to see each form in the task-manager, you can switch it off with:
procedure CreateParams(var params: TCreateParams); override;
begin
inherited createParams(Params);
params.ExStyle:= WS_EX_PALETTEWINDOW;
end;
//cu at EKON 11