library SampleTask; // Simple Task Plugin for UltraExplorer. // - Does not use the TUltraExplorerTaskForm class defined in FormUltaExplorerTask.pas // - Does not use TBX or SpTBX // - Uses FastShareMem.pas to support sharing memory allocations across process boundries // - Sets the Application, Screen, and HintWindowClass to that of the EXE application // - The DLL MUST export the following two function to have UE load it.. // CreatePluginServer, // SetVCLVariables; // - Supports only one Plugin from the DLL. See the UltraExplorerCommon folder // for the common standard UltraExplorer plugins to see how to support // multiple plugins in a single DLL. // - PERFORMANCE: For performance reasons loading DLLs is slow so if possible put as many // plugins into a single DLL as possible. // // // Notes on Creating Forms in a DLL // - Creating the Form in the DLL then using a parent from a control in the // main app fails because if the Form from the DLL is recreated from an event // in the app the DFM resources are linked into the DLL and not the app. This // causes the form to not have any designtime objects when it is recreated (can't // find the resources..) // - The DLL the can take the TApplication and TScreen from the app, save the ones // created in the DLL and cause the DLL to use the applications objects instead. // On releasing the DLL the objects are set back to the original saved versions. // This still does not fix any Tab or Arrow Dialog Key message issues but it does // at least track the Form with the screen and such. It may help some issues. // // - Hints: These will just plain fail. In the VCL this is used to find the control // to show the hint on: // function FindControl(Handle: HWnd): TWinControl; // var // OwningProcess: DWORD; // begin // Result := nil; // if (Handle <> 0) and (GetWindowThreadProcessID(Handle, OwningProcess) <> 0) and // (OwningProcess = GetCurrentProcessId) then // .... // end; // // The control is never found becase the window handle is created in the DLL's // process. // uses FastShareMem in '..\FastShareMem.pas', // MUST BE FIRST IN THE LIST SysUtils, Classes, Forms, Windows, Controls, UltraTaskInf in '..\UltraTaskInf.pas', SamplePlugin in 'SamplePlugin.pas' {SamplePluginForm}; {$R *.res} {$Include Compilers.inc} {$IFNDEF COMPILER_5_UP} var // D5 Fixes this problem; ControlWord: Word; { SavedApplication: TApplication = nil; SavedScreen: TScreen = nil; SavedHintWindowClass: THintWindowClass = nil; } {$ENDIF} function CreatePluginServer: IUltraPlugin; begin Result := TSamplePlugin.Create; end; function RestoreVCLVariables: Boolean; begin { if Assigned(SavedApplication) then Application := SavedApplication; if Assigned(SavedScreen) then Screen := SavedScreen; if Assigned(SavedHintWindowClass) then HintWindowClass := SavedHintWindowClass; } Result := True; end; function SetVCLVariables(ParentApplication, ParentScreen, ParentHintWindowClass: Longword): Boolean; begin // The memory layout of TApplication between D7 and D2006 has changed // so this type of typecasting fails miserably. { if not Assigned(SavedApplication) then begin SavedApplication := Application; Application := TApplication( ParentApplication); end; if not Assigned(SavedScreen) then begin SavedScreen := Screen; Screen := TScreen( ParentScreen); end; if not Assigned(SavedHintWindowClass) then begin SavedHintWindowClass := HintWindowClass; HintWindowClass := THintWindowClass( ParentHintWindowClass) end; } Result := True; end; exports CreatePluginServer, SetVCLVariables; procedure DLLEntryProc(EntryCode: integer); begin case EntryCode of DLL_PROCESS_DETACH: begin RestoreVCLVariables; {$IFNDEF COMPILER_5_UP} Set8087CW(ControlWord); {$ENDIF} end; DLL_PROCESS_ATTACH: begin {$IFNDEF COMPILER_5_UP} Set8087CW($133f); {$ENDIF} end; DLL_THREAD_ATTACH: begin end; DLL_THREAD_DETACH: begin end; end; end; begin IsMultiThread := True; DLLProc := @DLLEntryProc; DLLEntryProc(DLL_PROCESS_ATTACH); end.