Mega Code Archive

 
Categories / Delphi / Examples
 

Messages

Delphi and 'messages'. Delphi is object-oriented and Delphi code tends to be event-driven, SO there will always be messages flying around between a program and Windows, and between components within an application, and so on and so forth. Sometimes it may be appropriate to work with messages without recourse to Windows functions, as Delphi itself is set up to help you deal with many of them. Much of the time, however, it's quick and fairly simple to call a Windows API function from within your Delphi code. There's lots of documentation on this in Delphi online Help but here's a few actual examples: EXAMPLES. ************************************************************************* Here we interrogate the Windows API to ascertain the total number of characters in the previous lines of a RichEdit component -note that the i variable is an integer value for the current line... previousChars := SendMessage(REForm.RichEdit.Handle, EM_LINEINDEX, i, 0); Note that SendMessage() is an API function, not a function built in to Delphi, and if we use Delphi Help to tell us about SendMessage, the information we get is actually from the Windows API Help system... ************************************************************************* See also C:\MyDelphi\Scrolling for clever example of trapping Windows messages ************************************************************************* [interprocess, or INTER-APPLICATION messages...] you could do is have a global variable that you fill in the calling procedure and read in the message handler (the message would just be saying, "Check the variable now.). That is not the best idea, though, if for no other reason than it isn't very thread-safe. Instead, you should pass all the information with the message, meanin you should declare a record type that contains all the fields you need to send. Allocate memory for the record (using New or AllocMem) and send the pointer in the lParam value. In the message handler, once it has finished with the data, free the memory. Since you are using PostMessage, the pointer you send cannot be a pointer to a local variable. PostMessage will return immediately to the message poster and when that routine completes, the pointer will point to memory that jus went out of scope, so you must allocate memory from the heap. type PData = ^TData; TData = record Field1: Integer; Field2: PChar; Field3: Double; end; procedure TForm1.SendAMessage(Sender: TObject); var data: PData; begin new(data); // populate data data.Field1 := 28; data.Field2 := nil; data.Field3 := -4.5; PostMessage(Handle, wm_CustomMessage, 0, lParam(data)); // Do not free data here. end; procedure TForm1.HandleAMessage(var Msg: TMessage); var data: PData; begin data := PData(Msg.lParam); // just a type-cast for easier use // process your stuff here dispose(data); end; Finally, check out the wm_CopyData message. It is designed moe for interprocess communication (since pointers aren't valid across process boundaries), but it should still work. It makes a copy of the data you send so that you don't have to worry about persisting pointers. --Rob ************************************************************************* another 'handle messages' example: [in a form's Uses clause:] Messages [procedure declaration] procedure HandleMessages(var Msg: tMsg; var Handled: Boolean); [in FormCreate] Application.OnMessage := HandleMessages; [body of procedure] procedure TMainForm.HandleMessages(var Msg: tMsg; var Handled: Boolean); //handy piece of code that could be used in other contexts. Here we subvert //the default handling of arrow keys by, in effect, trapping Windows //keypress messages. Navigation keys (tab, arrow keys, etc) are processed by //Delphi OnKeyDown and OnKeyUp event handlers, so the code here allows us to //step in and trap the messages for those keys before they reach the Delphi //OnKeyDown and OnKeyUp event handlers... //THIS PROC IS LIKELY TO BE OF ONLY TEMPORARY USEFULNESS- //when the various parts of the application have been turned into COM objects //then trying to subvert keypresses in this way may not be a good idea... begin if (Msg.message = WM_KeyDown) and (Msg.wParam in [VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT]) then begin case Msg.wParam of VK_LEFT: MoveLeftSBClick(Self); VK_RIGHT: MoveRightSBClick(Self); VK_UP: MoveUpSBClick(Self); VK_DOWN: MoveDownSBClick(Self); end; Handled := True; end; end;