SharpE Service Development Kit
Version: 0.7.3.0 (TD3)
Last updated: 20.08.2007
Introduction
This document will explain how to create new services for the SharpE Core application. All example source code is related to the template service which is accessible on the svn. The template service is designed to be compiled with the free Turbo Explorer version of Delphi.
No third party components are required to compile the template service.
The Service Project File
How does it work?
A SharpCore? service is a dynamic link library (dll) which is loaded by the SharpCore? host application. Services are invisible "applications" which provide functionality to the shell by running in the background.
The service dll is controlled by exporting a frew pre-defined functions which are then executed by SharpCore?.
File content and exported functions
The .dpr library file contains the exported functions of the service. Whenever SharpCore? wants to do something with a service, those functions are called. It is very important that all functions described below exist in a module dll file. If one of those functions is not exported then the module will not be loaded by SharpBar?!
Services should be compiled with enable dvcl and rtl runtime packages. It is possible to compile a service without runtime packages but this will increase the memory usage of the service. To enable compiling with runtime packages, go to Project -> Options -> Packages in Delphi and make sure that "Compile with runtime packages" is checked and that the editbox below contains:
vcl;rtl
The following list shows all the functions which have to be exported by a module.
function Start(owner: hwnd): hwnd;
- The Start function is called when a service is started by SharpCore?.
In this function, a service should initialize everything it needs to run in the background (hooks, actions, hotkeys, windows...).
The owner: hwnd parameter is the handle to the main window of the SharpCore? host application.
The return value is not used at the moment, so it's not necessary to return any special handle.
procedure Stop;
- The Stop procedure is called when a service is stopped by SharpCore?.
When this procedure is called, a service must make sure that everything which was created in the Start procedure is properly freed from memory. After calling the stop procedure, a service is no longer allowed to have any existing windows, actions, hookes, classes, etc that could make SharpCore? unable to unload the dll file.
function SCMsg(msg: string): integer;
- Using the SCMsg function is optional. If a service exports this function, then it will be called when a message is sent to this service.
The msg : string parameter specifies the message which was sent to the service.
Only services which are supposed to receive and handle messages that are sent to the service by other parts of the shell should export this function.
Global Windows Messages
A service normally can't receive global window message broadcasts because a service isn't using a window. However, for some services it might be important to react on global window messages like WM_DISPLAYCHANGE or even to SharpE-wide shell broadcasts like the WM_SETTINGSCHANGE message.
You can easily make a service receive global window messages by creating an invisible "dummy" window.
First you have to define a new class which will hold the message handler. It's also necessary to declare a new var to store the window handle of the new message window.
01 type 02 TActionEvent = Class(TObject) 03 Procedure MessageHandler(var Message: TMessage); 04 end; 05 06 var 07 AE:TActionEvent; 08 h:THandle;
Then in the Start function of the service, the class and the message window have to be created.
01 ae := TActionEvent.Create; 02 h := allocatehwnd(Ae.MessageHandler);
Of course both the class and the message window have to be freed manually in the Stop procedure of the service.
01 DeallocateHWnd(h); 02 AE.Free;
The last step is to declare the actual message handler of our !TActionEvent class which will handle the global window messages.
01 procedure TActionEvent.MessaegHandler(var Message: TMessage); 02 begin 03 04 end;
The Message parameter in this function can be used to handle the received message.
