Autor Beitrag
jensenwb
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 36



BeitragVerfasst: So 06.10.02 17:56 
Hallo ich möchte in einer DLL die größe meiner Komponenten ändern.

Mein Quelltext der DLL ist

ausblenden volle Höhe Quelltext
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:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
library anpassen;

{ Wichtiger Hinweis zur DLL-Speicherverwaltung: ShareMem muß die
  erste Unit im Uses-Anweisungsteil des Interface-Abschnitts Ihrer
  Unit sein, wenn Ihre DLL Prozeduren oder Funktionen exportiert, die
  String-Parameter oder Funktionsergebnisse übergeben. Dies gilt für
  alle Strings die an und von Ihrer DLL übergeben werden --  selbst
  für diese, die in Records oder Klassen verschachtelt sind. ShareMem
  ist die Schnittstellen-Unit zur DELPHIMM.DLL, welche Sie mit Ihrer
  DLL weitergeben müssen. Um die Verwendung von DELPHIMM.DLL zu
  vermeiden, übergeben Sie String-Parameter unter Verwendung von
  PChar- oder ShortString-Parametern. }

uses
  SysUtils,  Windows,  Messages,  Classes,  Graphics,  Controls,  StdCtrls,  Forms,  DBCtrls,
  DB,  Mask,  Grids,  DBGrids,  ComCtrls,  Tabnotbk,  DBTables,  ExtCtrls,  Buttons,  Dialogs;

{$R *.RES}

procedure anpassendbCombobox(objekt:tdbComboBox); stdcall;
begin
objekt.left:=round(objekt.left*screen.width/800);
objekt.width:=round(objekt.width*screen.width/800);
objekt.height:=round(objekt.height*screen.height/600);
objekt.top:=round(objekt.top*screen.height/600);
objekt.Font.size:=round(objekt.font.size*screen.width/800);
end;

procedure anpassendbgrid(objekt:tdbgrid); stdcall;
begin
objekt.left:=round(objekt.left*screen.width/800);
objekt.width:=round(objekt.width*screen.width/800);
objekt.height:=round(objekt.height*screen.height/600);
objekt.top:=round(objekt.top*screen.height/600);
objekt.Font.size:=round(objekt.font.size*screen.width/800);
end;

procedure anpassenlabel(objekt:tlabel); stdcall;
begin
objekt.left:=round(objekt.left*screen.width/800);
objekt.width:=round(objekt.width*screen.width/800);
objekt.height:=round(objekt.height*screen.height/600);
objekt.top:=round(objekt.top*screen.height/600);
objekt.Font.size:=round(objekt.font.size*screen.width/800);
end;

procedure anpassenbitbtn(objekt:tbitbtn); stdcall;
begin
objekt.left:=round(objekt.left*screen.width/800);
objekt.width:=round(objekt.width*screen.width/800);
objekt.height:=round(objekt.height*screen.height/600);
objekt.top:=round(objekt.top*screen.height/600);
objekt.Font.size:=round(objekt.font.size*screen.width/800);
end;

procedure anpassendbedit(objekt:tdbedit); stdcall;
begin
objekt.left:=round(objekt.left*screen.width/800);
objekt.width:=round(objekt.width*screen.width/800);
objekt.height:=round(objekt.height*screen.height/600);
objekt.top:=round(objekt.top*screen.height/600);
objekt.Font.size:=round(objekt.font.size*screen.width/800);
end;

procedure anpassentabbednotebook(objekt:ttabbednotebook); stdcall;
begin
objekt.left:=round(objekt.left*screen.width/800);
objekt.width:=round(objekt.width*screen.width/800);
objekt.height:=round(objekt.height*screen.height/600);
objekt.top:=round(objekt.top*screen.height/600);
objekt.tabFont.size:=round(objekt.tabfont.size*screen.width/800);
end;

procedure anpassenform(objekt:tform); stdcall;
begin
objekt.left:=round(objekt.left*screen.width/800);
objekt.width:=round(objekt.width*screen.width/800);
objekt.height:=round(objekt.height*screen.height/600);
objekt.top:=round(objekt.top*screen.height/600);
objekt.Font.size:=round(objekt.font.size*screen.width/800);
end;

procedure anpassendbmemo(objekt:tdbmemo); stdcall;
begin
objekt.left:=round(objekt.left*screen.width/800);
objekt.width:=round(objekt.width*screen.width/800);
objekt.height:=round(objekt.height*screen.height/600);
objekt.top:=round(objekt.top*screen.height/600);
objekt.Font.size:=round(objekt.font.size*screen.width/800);
end;

Exports
anpassendbCombobox,
anpassendbgrid,
anpassenlabel,
anpassenbitbtn,
anpassendbedit,
anpassentabbednotebook,
anpassenform,
anpassendbmemo;

begin
end.


Der Quelltext meines Prog ist:

ausblenden volle Höhe Quelltext
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:
unit testanpassen;


interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Grids, DBGrids, StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    DBGrid1: TDBGrid;
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}
procedure anpassenlabel(objekt:tlabel);stdcall;external 'anpassen.dll';
procedure anpassendbgrid(objekt:tdbgrid);stdcall;external 'anpassen.dll';
procedure anpassenform(objekt:tform);stdcall;external 'anpassen.dll';

procedure TForm1.FormCreate(Sender: TObject);
begin
anpassenform(form1);
anpassenlabel(form1.label1);
anpassenlabel(form1.label2);
anpassendbgrid(form1.dbgrid1);
end;

end.


Wenn ich dann das Programm beende erscheint folgende Fehlermeldung:
Exception EAccessViolation im Modul Testanpass.exe bei 00015953.
Zugriffsverletzung bei Adresse 00415953 in Modul 'Testanpass.exe' Lesen von Adresse FFFFFFFF.


Ich hoffe Ihr könnt mir helfen.
bis11
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1247
Erhaltene Danke: 2

Apple Mac OSX 10.11

BeitragVerfasst: So 06.10.02 18:07 
Du mußt die Proceduren auch noch unter der implementation deklarieren. z.B. so :

procedure anpassenlabel(objekt:tlabel);stdcall;
jensenwb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 36



BeitragVerfasst: So 06.10.02 18:16 
Ich habe doch die Proceduren im Implementations-Teil.

Ich weiß jetze nicht so richtig was Du meinst.
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Mo 07.10.02 14:37 
Ja, wo ist denn Sharemem bei dir eingetragen? Um dynamische Datenstrukturen wie Objekte und Strings zwischen DLL und einer Anwendung hin und herzuschieben, musst du doch Sharemem in der Interface-Uses-Klausel sowohl in deinem Programm als auch in deiner DLL angeben (siehe "der Shared-Memory-Manager" in der Delphi-Hilfe), und zwar als erste Unit.

Mal ne andere Sache:
Wieso hast du viele Prozeduren, die alle ein und dasselbe machen, und nur andere Eingabeparametertypen haben? Alle Typen von Objekten, die du übergeben willst, haben haben doch schliesslich die Eigenschaften left,width,height,top und Font von einem einzigen Vorfahren, nämlich TControl, bezogen.

Schreib also einfach eine Routine, der du ein TControl-Objekt übergibst (diese Routine akzeptiert dann sowohl Labels als auch DBGrids, es sind ja Nachfahren von TControl):

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure anpassen(objekt:tcontrol); stdcall; 
begin 
objekt.left:=round(objekt.left*screen.width/800); 
objekt.width:=round(objekt.width*screen.width/800); 
objekt.height:=round(objekt.height*screen.height/600); 
objekt.top:=round(objekt.top*screen.height/600); 
objekt.Font.size:=round(objekt.font.size*screen.width/800); 
end;


Cu, :D
Udontknow
jensenwb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 36



BeitragVerfasst: So 13.10.02 17:14 
Habe den Code so geändert. Der Fehler ist aber trotzdem noch da.

Bitte helft Mir, bin mit meinen latein am ende.
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Mo 14.10.02 07:58 
Nun, dann setze mal einen Haltepunkt direkt auf die erste Zeile im Ereignis OnCreate. Wenn du bis dorthin ohne Fehler kommst, drücke F8, um eine Zeile weiter zu gehen. Wann tritt der Fehler auf?

Du kannst testweise auch mal die Routine Objektanpassen aus deiner DLL herausnehmen und direkt ins Formular packen.
jensenwb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 36



BeitragVerfasst: Sa 19.10.02 20:03 
Der Fehler tritt auf wenn ich das Programm schließe.

Ich habe auch schon die Procedure in meinen Programm direkt eingebunden (rufe keine Procedure aus DLL mehr auf), aber da erscheint immer wenn ich das Prog compilieren will die Fehlermeldung "Undefinierter Bezeichner: 'Font'. "

Meine Procedure sieht wie folgt aus.
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure anpassen(objekt1:tcontrol);
begin
  objekt1.left:=round(objekt1.left*screen.width/800);
  objekt1.width:=round(objekt1.width*screen.width/800);
  objekt1.height:=round(objekt1.height*screen.height/600);
  objekt1.top:=round(objekt1.top*screen.height/600);
  objekt1.Font.size:=round(objekt1.Font.size*screen.width/800);
end;


Woran kann das denn jetzt liegen.

(20.10.02 14:47 Tino) Code-Tags hinzugefügt.
Tino
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: So 20.10.02 14:48 
jensenwb hat folgendes geschrieben:
Woran kann das denn jetzt liegen.

Die Eigenschaft Font ist in dem Objekt tControl in der Protected-Sektion definiert. Diese Eingeschaft ist also nur in abgeleiteten Klassen sichtbar.

Gruß
TINO
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Mo 21.10.02 12:17 
Oh, stimmt. :oops:

Du musst also für jede Objektart, die direkt Nachfahre von TControl ist und bei der du den Font ändern willst, eine weitere Routine schreiben... Ärgerlich... Naja, in dieser Routine kannst du dann wenigstens auf die oben gepostete Routine zurückgreifen, dann sparst ein wenig Code...

Cu,
Udontknow
AndyB
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: Mo 21.10.02 12:30 
Das ist nicht nötig.

Man kann das protected-Attribut so umgehen:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
type THackControl = class(TControl);

procedure anpassen(objekt1:tcontrol); 
begin 
  objekt1.left:=round(objekt1.left*screen.width/800); 
  objekt1.width:=round(objekt1.width*screen.width/800); 
  objekt1.height:=round(objekt1.height*screen.height/600); 
  objekt1.top:=round(objekt1.top*screen.height/600); 
  
  with THackControl(objekt1) do
    Font.size:=round(Font.size*screen.width/800); 
end;

_________________
Ist Zeit wirklich Geld?
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Mo 21.10.02 15:37 
Achja, du hast recht! Das ist ein Kniff, den ich auch schon öfter angewendet habe, wieso ich da nicht draufgekommen bin... :oops:

Die ganze Sache ist natürlich ein wenig heikel, da man eigentlich nie ein Objekt als einen Nachfahren seiner selbst casten sollte. Es klappt aber einwandfrei, wenn man eben nur auf Daten zugreift, die schon in der Vorfahrklasse implementiert sind (wie eben das protected-Element font).

Sogar Prozeduren der Nachfahrklasse lassen sich ausführen, sofern diese nicht Übersteuerungen darstellen. Einzig und allein steht die Bedingung, daß keine in Nachfahrklassen deklarierten Datenfelder in den aufzurufenden Routinen benötigt werden.

Cu,
Udontknow
AndyB
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: Mo 21.10.02 21:18 
Zitat:
Die ganze Sache ist natürlich ein wenig heikel

Nur wenn man nicht weiß, was man macht also mit TWinControl() sollte man nicht auf ein von TControl, aber nicht von TWinControl abgeleitete Klasse zugreifen.


Zitat:
Einzig und allein steht die Bedingung, daß keine in Nachfahrklassen deklarierten Datenfelder in den aufzurufenden Routinen benötigt werden.

Diese Bedingung besteht nicht. Das bei nicht virtuellen Methoden wird die in TControl deklarierte Version der Methode aufgerufen, die natürlich nur auf in TWinControl vorhandene Felder zugreifen kann. Wird jedoch eine virtuelle bzw. dynamische Methode aufgerufen, dann kann diese sehrwohl auf die "neuen" Felder zugreifen.

_________________
Ist Zeit wirklich Geld?
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Di 22.10.02 09:40 
Hallo!

Zitat:
Nur wenn man nicht weiß, was man macht also mit TWinControl() sollte man nicht auf ein von TControl, aber nicht von TWinControl abgeleitete Klasse zugreifen.


Ähh... Wie bitte? Das ist ein bisschen konfus... :wink:

Ich glaube, wir missverstehen uns. Wie willst du auf Felder zugreifen, die im Objekt gar nicht vorhanden sind?

Nehmen wir mal 2 Klassen:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
type TA=class(TObject)
  Element1:Integer;
end;

type TB=Class(TA)
  Element2:integer;
  function GetElement2:integer;
  function Element1Mal2:Integer;
end;

function TB.GetElement2:integer;
begin
  Result:=Element2;
end;


function TB.Element1Mal2:Integer;
begin
  Result:=Element1*2;
end;


Nehmen wir nun an, das du ein Objekt der Klasse A hast.

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
var A:TA;
begin
  A:=TA.Create;
  try
    A.Element1:=20;
    ...
  finally
    A.Free;
  end;
end;


Folgendes ist erlaubt, da die in TB deklarierte Prozedur Element1Mal2 nur auf Datenfelder zugreift, die bereits in A deklariert wurden:

ausblenden Quelltext
1:
ShowMessage(IntToStr(TB(A).Element1Mal2));					


Das hier ist dagegen fatal, weil das Objekt gar kein Element2 besitzt, du greifst irgendwo in den Speicher, häufig kommt es bei solchen Aktionen zur Zugriffsschutzverletzung, manchmal bekommt man einfach Müll zurück.

ausblenden Quelltext
1:
ShowMessage(IntToStr(TB(A).GetElement2));					


Cu, :D
Udontknow