Je haalt een paar dingen door elkaar en daardoor zal je code niet werken. Geen nood, GoT helpt je wel op het rechte pad.
Zoek eerst in de Delphi help naar 'TMessage'. TMessage.Msg is slechts een identifier, een Longint, die aangeeft welke message het betreft. In jouw geval is dat WM_STARTSEARCH. De betekenis van TMessage.WParam en TMessage.LParam is message-afhankelijk en kun je bij zelf-gedefinieerde messages gebruiken om extra informatie te versturen. Zij zijn allebei van het type Longint.
Een Longint is natuurlijk niet genoeg om een complete record in op te slaan en de combinatie van WParam en LParam is eveneens te klein. Maar je kunt een truc gebruiken. Verstuur in WParam niet plaats van de complete record, maar een pointer naar de record (dus het geheugenadres van de record). Een pointer is 32 bits groot, precies evenveel als een Longint. Je verstuurt dan niet de record zelf, maar slechts een verwijzing ernaartoe.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| unit MijnMessages;
interface
uses
Windows, Messages, SysUtils; // en misschien nog een paar
type
TSearchDirection = (sdDown, sdUp);
{ De info die we willen versturen }
PSearchInfo = ^TSearchInfo;
TSearchInfo = record
SearchItem: string;
SearchArea: Integer;
CompleteWord: Boolean;
CaseSensitive: Boolean;
SearchDirection: TSearchDirection;
end;
const
WM_STARTSEARCH = WM_USER + 4; // zelf gedefinieerde message constante
type
{ Ter info, een message ziet er (ongeveer) als volgt uit: }
{ TMessage = packed record
Msg: Cardinal;
WParam: Longint;
LParam: Longint;
Result: Longint;
end; }
{ Nu gaan we onze eigen message maken, waarbij we de betekenis
van WParam en LParam gaan veranderen, maar wel zodanig dat zij
precies evenveel bits beslaan als is TMessage. }
TWMStartSearch = packed record
Msg: Cardinal;
SearchInfo: PSearchInfo; // even groot als een Longint
Ongebruikt: Longint; // even groot als een Longint
Result: Longint;
end;
implementation
end. |
Nu willen we in ons form verstuurde WMStartSearch messages afvangen. Daarvoor moeten we met de hand een paar regels aan de code van ons form toevoegen.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| uses
MijnMessages; { <-- toevoegen aan uses clausule }
TForm1 = class(TForm)
private
procedure WMStartSearch(var Msg: TWMStartSearch); message WM_STARTSEARCH;
...
implementation
procedure TForm1.WMStartSearch(var Msg: TWMStartSearch);
var
InfoPtr: PSearchInfo;
Info: TSearchInfo;
begin
{ Een beetje omslachtig, maar het laat goed zien wat er gebeurt }
InfoPtr := Msg.SearchInfo;
Info := InfoPtr^;
{ Nu iets met de info doen }
ShowMessage(Info.SearchItem);
end; |
Een message versturen gaat zo:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| var
Info: TSearchInfo;
InfoPtr: PSearchInfo;
WParam: Longint;
begin
{ Eerst de Info record vullen }
with Info do
begin
SearchItem := 'klooien met messages';
SearchArea := 1000;
CompleteWord := False;
CaseSensitive := True;
SearchDirection := sdDown;
end;
{ Nu versturen, voor de duidelijkheid met wat onnodig lange code }
InfoPtr := @Info;
WParam := Longint(InfoPtr); // WParam is even groot als InfoPtr
Perform(WM_STARTSEARCH, WParam, 0);
end; |
Dit werkt trouwens alleen binnen één applicatie! Je verwijst immers naar een stuk geheugen binnen een applicatie (namelijk een TSearchInfo record) en daar heeft een andere applicatie geen toegang toe.
Wil je meer over dit onderwerp weten, zoek dan een naar 'message crackers' of 'message cracking'.
Een goede grap mag vrienden kosten.