Avatar billede konrad_ix Nybegynder
21. juni 2004 - 16:07 Der er 7 kommentarer

Har 'unit' skal bruge 'library'

Jeg har de sidste par dage huseret her i Delphi miljøet.
Nu smider jeg så en lidt større opgave. Eller rettere: Jeg smider den opgave der ligger til grund for mine tidligere spørgsmål. Jeg har fået følgende med mig:

Interfaces til ACSDLL.DLL:

Alle funktioner skal deklareres, men behøver ikke nødvendigvis bruges.

function Init(Var S: PChar): integer; export;

Kaldes når ACSAgent startes op, her kan man lave initialisering af diverse ting og sager.
Parametren S sendes tilbage til ACSAgent, og angiver hvad menupunktet som kalder DLLUserCmd skal have som caption.

function Done: integer; export;

Kaldes når ACSAgent lukkes ned, her kan man rydde op o.s.v.

function FindCustomer(Navn: Pchar): integer; export;

Selve søgerutinen, når agenten tager et kald, kaldes denne rutine. Parametren NAVN kan være hvad som helst, bare det er i strengformat. (Navn, kundenummer o.s.v.)

function DLLUserCmd(S:PChar): Integer; export;

Rutine som kan kaldes fra ACSAgent, f.eks. "Vis alle i Access"


//CUT---


unit DLLMain;

interface

function Init(Var S: PChar): integer; export;
function Done: integer; export;
function FindCustomer(Navn: Pchar): integer; export;
function DLLUserCmd(S:PChar): Integer; export;

implementation

uses
  Windows,SysUtils,IniFiles,ComObj,ActiveX;

Const
  acViewNormal  = $00000000;
  acViewDesign  = $00000001;
  acViewPreview  = $00000002;
  acAdd          = $00000000;
  acEdit        = $00000001;
  acReadOnly    = $00000002;
  acWindowNormal = $00000000;
  acHidden      = $00000001;
  acIcon        = $00000002;
  acDialog      = $00000003;

var
  Nix,
  Acc:Variant;
  FormName,
  DB,
  FFilePath: string;

function Init(Var S: PChar): integer;
Var IniFile : TIniFile;
    buffer  : array [0..255] of char;
    S1      : String;
begin
  CoInitialize(nil);
  GetWindowsDirectory(buffer,SizeOf(buffer));
  S := 'Vis alle i Access';
  S1 := String(Buffer)+'\ACS4000.ini';
  IniFile := TIniFile.Create(S1);
  With IniFile Do
  Begin
    FormName := ReadString('DLL','FormName','Hovedvindue');
    DB      := ReadString('DLL', 'Database', 'C:\Access\TP Teknik.Mdb');
    Free;
  End;
  Try
    Acc := GetActiveOleObject('Access.Application');
  Except
    Acc := CreateOleObject('Access.Application');
  End;
  Acc.Visible := True;
  Try
    Acc.OpenCurrentDatabase(DB, False);
    Acc.DoCmd.OpenForm(FormName, acViewNormal, Nix, Nix, acEdit, acWindowNormal, Nix);
    Result := 0;
  Except
    Result := -1;
  End;
end;

function Done: integer;
begin
  OleUninitialize;
  Result := 0;
end;

function FindCustomer(Navn: Pchar): integer;
Var S :String;
    V :Integer;
    C :Int64;
begin
  S := String(Navn);
  Val(S,C,V);
  If V = 0 Then
  Begin
    S := Format('([Telefon] = ''%d'') OR ',[C]);  //OR
    S := S+Format('([Primær nummerserie fra] <= ''%d'' AND [Primær nummerserie til] >= ''%d'')',[C,C]);
    S := S+Format(' OR ([Sekundær nummerserie fra] <= ''%d'' AND [Sekundær nummerserie til] >= ''%d'')',[C,C]);
    Acc.DoCmd.OpenForm(FormName,acViewNormal,Nix,S,acEdit,acWindowNormal,Nix);
    Result := 0;
  End
  Else Result :=-1;
end;

function DLLUserCmd(S:PChar): Integer;
Begin
  Acc.DoCmd.ShowAllRecords;
  Result := 0;
End;

initialization

end.

Mit spørgsmål er, hvordan jeg får lavet denne 'unit' om til et library (DLL). Ydermere er jeg meget usikker hvorvidt der er nogle logiske fejl. Er jo ikke så rutineret en programmør :-D

På forhånd tak for al hjælp

Birger Wilhelmsen
Avatar billede borrisholt Novice
23. juni 2004 - 08:02 #1
Dit spørgsmål giver ikke mening. Derfor har du ingen svar fået på det !

Hvis du vil have en DLL fil skal du vælge det under New projekt.

Forskellen (mend projektet er i Delphi) er at DPR filen startet med "library" og ikke med "program". Hvis du har en unit du ønsker at bruge i Din DLL fil skal du bare use den på samme måde som i en Exe fil !

Jens B
Avatar billede konrad_ix Nybegynder
23. juni 2004 - 13:00 #2
Tak for svaret, Jens. Det som jeg ikke lige fik nævnt er, at det er reverse engineering. Derfor har jeg selv siddet og rodet med det. Og jeg tror faktisk at det endte med at være nogenlunde.

{ Code start }

library ACSDLL;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses
  SysUtils,
  Classes,
  Windows,
  Inifiles,
  ComObj,
  ActiveX,
  Dialogs; // Not nessesary at this point, but required for userdialogs

{$R *.res}

const // Global Constants - All used for MS Access interaction
  acViewNormal  = $00000000;
  acViewDesign  = $00000001;
  acViewPreview  = $00000002;
  acAdd          = $00000000;
  acEdit        = $00000001;
  acReadOnly    = $00000002;
  acWindowNormal = $00000000;
  acHidden      = $00000001;
  acIcon        = $00000002;
  acDialog      = $00000003;
 
var // Global Variables
  Nix, Access: Variant; // Access variable is the MS Access Database
  FormName, DB, FFilePath: string;

function Init(var S: PChar): Integer; export;
var IniFile : TIniFile;
    buffer  : array [0..255] of char;
    S1      : string;

begin
  CoInitialize(nil);
  GetWindowsDirectory(buffer,SizeOf(buffer));
  S      := 'Vis alle i Access';
  S1      := string(buffer)+'\ACS4000.ini';
  IniFile := TIniFile.Create(S1);
  with IniFile do
  begin
    FormName := ReadString('DLL','FormName','Hovedvindue');
    DB      := ReadString('DLL','Database','C:\ACSTEST\TEST_DAB.mdb');
    Free;
  end; // With
  try
    { open the Access application }
    Access := GetActiveOleObject('Access.Application');
  except
    Access := CreateOleObject('Access.Application');
  end; // Try
  Access.Visible := True;
  try
    { open the database
      The second parameter specifies whether you want to open the
      database in Exclusive mode }
    Access.OpenCurrentDatabase(DB, False);
    { open the form
      The value for the second parameter should be one of acViewDesign,
      acViewNormal, or acViewPreview. acViewNormal, which is the default }
    Access.DoCmd.OpenForm(FormName, acViewNormal, Nix, Nix, acEdit, acWindowNormal, Nix);
    Result := 0;
  except
    Result := -1;
  end; // Try
end; // function Init

function Done: Integer; export;
begin
  OleUninitialize;
  Result := 0;
end; // function Done

function FindCustomer(Navn: PChar): Integer; export;
var S : string;
    V : Integer;
    C : Int64;

begin
  S := string(Navn);
  Val(S,C,V);
  if V = 0 then
  begin
    S := Format('([Telefon] = ''%d'') OR ',[C]);  //OR
    S := S + Format('([Primær nummerserie fra] <= ''%d'' AND [Primær nummerserie til] >= ''%d'')',[C,C]);
    S := S + Format(' OR ([Sekundær nummerserie fra] <= ''%d'' AND [Sekundær nummerserie til] >= ''%d'')',[C,C]);
    Access.DoCmd.OpenForm(FormName,acViewNormal,Nix,S,acEdit,acWindowNormal,Nix);
    Result := 0;
  end // If
  else
    Result :=-1;
  end; // function FindCustomer

function DLLUserCmd(S: PChar): Integer; export;
begin
  Access.DoCmd.ShowAllRecords;
  Result := 0;
end; // function DLLUserCmd

exports Init;
exports Done;
exports FindCustomer;
exports DLLUserCmd;

begin

end. // library TestDLL

{ Code end }
Avatar billede borrisholt Novice
23. juni 2004 - 13:16 #3
Yep nemlig, og hvis du ville bruge nogle funktioner fra en unit, skal du blot use den
Avatar billede konrad_ix Nybegynder
23. juni 2004 - 13:41 #4
Jeg har dog stadig lige et spørgsmål vedrørende 'string' i forhold til 'PChar'. Det er vist ikke så godt med 'string'. Kan jeg i dette tilfælde bare udskifte uden problemer? Det samme gør sig sådan set gældende for 'val' og 'en-anden-jeg-ikke-lige-kan-huske'
Avatar billede borrisholt Novice
23. juni 2004 - 13:48 #5
Du kan bare bruge Stenge blot du følger de anvisninger der er i toppen af din fil. Ellers brug ShortString, eller Pchar. Og ja det skulle ikke betyde noget
Avatar billede konrad_ix Nybegynder
23. juni 2004 - 13:56 #6
Et andet spørgsmål der har givet mig rigtig mange kvaler. Denne DLL skal erstatte en eksisterende DLL i et program. Der er også et ønske om et brugerinterface. En af mine 'S' variabler skal trigge et spørgsmål til brugeren. Eksempelvis: 'Vil du se denne bruger i Access? (Y/N). Problemet er at al arbejde skal foregå i Dll'en. Mener du det vil være meget svært? Jeg tror det må være noget med at Init kalder en function, der prompter brugeren (funtion UserPropt), og returnerer en 'boolean' (eller lignende) til Init. function UserPrompt skal så kalde en 'Messagebox' rutine. Er dette helt skævt?
Avatar billede konrad_ix Nybegynder
23. juni 2004 - 14:18 #7
Fik udskiftet alle 'string' med 'ShortString' og den compiler uden problemer. Tak for det.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester