Jeg er ved at lave et Yatzy spil, for at det skal blive lidt mer overskueligt, ønsker jeg at gemme diverse rutine procedurer' i en DLL fil, jeg har prøvet vha. af http://www.udvikleren.dk/article.php?aid=93&techid=2 ...
Hej,
Du skal betragte din EXE og DLL som 2 seperate projekter som ikke kender noget til hinanden.
Det vil sige at DLL'et kan ikke se nogle variabler i EXE'en med mindre du sender referencen til disse variabler med over (i et kald) til DLL'et.
Måden du kan løser dit problem er:
1. opret en funktion i DLL'et som returnere en Dice struktur.
2. Opret Dice arrayet i dit DLL.
3. Brug arrayet som returneres fra DLL'et i din EXE.
Jeg har prøvet at ændre i dit DLL og EXE så de bruger en strukture (array) i stedet for.
Jeg har ændret i koden direkte her på udvikleren så der kan være små fejl :-)
Men håber du kan få en idé om hvordan det skal gøres.
Her er koden:
library YatzyDLL;
uses
SysUtils, ShareMem, Classes;
{$R *.res}
type
TDiceInfo = record
Dice: TImage; // Terningerne i et TImage array
Arrow: TImage; // Pilene i et TImage array
MarkedDice: Boolean; // hvilke terninger der er markeret
Dices: integer; // Antal øjne terningerne viser
end;
PDiceList = ^TDiceList;
TDiceList = array[1..5] of TDiceInfo;
var
Dices : TDiceList;
{------------------------------------------------------------------------------}
// Her nulstiller vi arrayet samt returnere det til kalderen (app'en).
procedure InitDices(var aDices : PDiceList);
var
I : Integer;
begin
for I := 1 to 5 do
begin
Dices[I].Dice:=nil;
Dices[I].Arrow:=nil;
Dices[I].MarkedDice:=False;
Dices[I].Dices:=0;
end;
ADices := @Dices;
end;
{------------------------------------------------------------------------------}
procedure LockDice(place: byte); stdCall; // Lås terningen ...
begin
Dices[place].MarkedDice := True; // Markér terningen
//eyeColor := $001F1AFF; // Til brug i rapport 2 ...
//diceColor := $001F1AFF; // Til brug i rapport 2 ...
Dices[place].Arrow.Visible := True; // Hvis pil for den valgte terning
// Lav terningens hint om til + [markeret]
Dices[place].Dice.Hint := 'Terning ' + IntToStr(place) + ' - [markeret]';
end;
{------------------------------------------------------------------------------}
procedure UnLockDice(place: byte); stdCall; // Omvendt af LockDice
begin
Dices[place].MarkedDice := False;
//eyeColor := $001F1AFF;
//diceColor := $001F1AFF;
Arrow[place].Visible := False;
Dices[place].Dice.Hint := 'Terning ' + IntToStr(place);
end;
{------------------------------------------------------------------------------}
procedure CheckDice(place: byte); stdCall;
begin
if Dices[place].MarkedDice then // Hvis terning er markeret ...
begin
UnLockDice(place); // ... gør den umarkeret
end
else // Ellers ...
begin
LockDice(place); // ... lås den
end
end;
{------------------------------------------------------------------------------}
function DebugMode: Boolean; stdCall;
begin
Result := DebugHook <> 0;
end;
{------------------------------------------------------------------------------}
procedure LoadDice(place: integer); stdCall;
begin // Denne henter en "frisk" terning baggrund frem
with Dices[place].Dice do // Med den valgte terning, gør følgende :
begin
Picture.LoadFromFile('sort2.bmp'); // Disse behøver vidst ikke forklaring
Width := 70;
Height := 70;
Enabled := True;
//Cursor := crHandPoint;
Visible := True;
ShowHint := True;
Hint := 'Terning ' + IntToStr(place);
end;
end;
exports
InitDices, CheckDice, LockDice, UnLockDice, DebugMode, LoadDice;
begin
end.
unit minUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ExtCtrls, ShareMem;
type
// Vi skal kende record structuren fra DLL'et.
TDiceInfo = record
Dice: TImage; // Terningerne i et TImage array
Arrow: TImage; // Pilene i et TImage array
MarkedDice: Boolean; // hvilke terninger der er markeret
Dices: integer; // Antal øjne terningerne viser
end;
PDiceList = ^TDiceList;
TDiceList = array[1..5] of TDiceInfo;
type
Tfrm1 = class(TForm)
Kast: TButton;
Dice1: TImage; // Terningerne
Dice2: TImage;
Dice3: TImage;
Dice4: TImage;
Dice5: TImage;
Arrow1: TImage; // Pilene
Arrow2: TImage;
Arrow3: TImage;
Arrow4: TImage;
Arrow5: TImage;
DebugButton: TButton;
procedure FormCreate(Sender: TObject);
procedure DrawDice(place, result: integer);
procedure DrawEyes(place, result: integer);
procedure KastClick(Sender: TObject);
procedure DiceClick(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
procedure DebugButtonClick(Sender: TObject);
private
{ Private declarations }
public
Dices : PDiceList;
// Dice: array [1..5] of TImage; // Terningerne i et TImage array
// Arrow: array [1..5] of TImage; // Pilene i et TImage array
// MarkedDice: array [1..5] of Boolean; // hvilke terninger der er markeret
end;
var
frm1: Tfrm1;
// Dices: array [1..5] of integer; // Antal øjne terningerne viser
Total, Strokes: integer; // Antal slag, og den summen af øjnene terningerne viser
eyeColor, diceColor: DWord; // Farverne der bruges til at tegne terningerne med
Allowed: integer; // Til brug i Debugging Mode
procedure InitDices(var ADices : PDiceList); External 'YatzyDLL.dll';
procedure LockDice(place: byte); External 'YatzyDLL.dll';
procedure UnLockDice(place: byte); External 'YatzyDLL.dll';
procedure CheckDice(place: byte); External 'YatzyDLL.dll';
procedure LoadDice(place: integer); External 'YatzyDLL.dll';
function DebugMode: Boolean; External 'YatzyDLL.dll';
implementation
{$R *.dfm}
{------------------------------------------------------------------------------}
procedure Tfrm1.DrawDice(place, result: integer);
begin // Denne tegner selve omridset af terningen, og sender resultat
// og placering videre til DrawEyes-proceduren
with Dices^[place].Dice.Canvas do
begin
Brush.Style := bsClear; // Først indstillingerne til canvasen
with Pen do
begin
Width := 3;
Color := diceColor; // Denne bliver defineret under "initialization"
end;
RoundRect(3, 3, 67, 67, 15, 15); // Koordinaterne til omrids af terning
end;
DrawEyes(place, result); // Tegn øjnene på den givne plads med det
end; // givne resultat
{------------------------------------------------------------------------------}
procedure Tfrm1.DrawEyes(place, result: integer);
begin // Denne tegner øjnene på den tegnede terning
with Dices^[place].Dice.Canvas do
begin
Brush.Style := bsSolid; // Først indstillingerne til canvasen
with Pen do
begin
Width := 2;
Color := eyeColor; // Denne bliver defineret under "initialization"
end;
case result of
1:
Ellipse(30, 30, 42, 42); // Hvis en 1'er tegnes kun en ellipse
2: // en cirkel er en form for ellipse
begin
Ellipse(60, 12, 48, 24);
Ellipse(12, 60, 24, 48);
end;
3:
begin
DrawEyes(place, 1); // En 3'er er jo i virkeligheden bare
DrawEyes(place, 2); // én 1'er og en 2'er
end;
4:
begin
DrawEyes(place, 2); // En 4'er er to 2'ere, hvoraf den ene
Ellipse(12, 12, 24, 24); // 2'er er omvendt
Ellipse(48, 48, 60, 60);
end;
5:
begin
DrawEyes(place, 4); // En 5'er er en 4'er og en 1'er
DrawEyes(place, 1);
end;
6:
begin
DrawEyes(place, 4); // En 6'er er en 4'er med 2 ekstra øjne
Ellipse(12, 29, 24, 41);
Ellipse(60, 29, 48, 41);
end;
end;
end;
end;
{------------------------------------------------------------------------------}
procedure Tfrm1.FormCreate(Sender: TObject);
var
i: integer;
begin
KeyPreview := True; // Aktivér brugen af tastetryk
InitDices(Dices); // Lad DLL'et oprette arrayet og sætte default værdier.
Dices^[1].Dice := Dice1; // Terningbillederne skal defineres da de er placeret
Dices^[2].Dice := Dice2; // i et TImage array.
Dices^[3].Dice := Dice3;
Dices^[4].Dice := Dice4;
Dices^[5].Dice := Dice5;
Dices^[1].Arrow := Arrow1; // ... samme med pilene
Dices^[2].Arrow := Arrow2;
Dices^[3].Arrow := Arrow3;
Dices^[4].Arrow := Arrow4;
Dices^[5].Arrow := Arrow5;
for i:= 1 to 5 do // En løkke der henter baggrundsbillederne,
begin // på hvilke DrawEyes og DrawDice procedurene
LoadDice(i); // opererer.
DrawDice(i, i); // Tegn terningerne 1-5 som startbilleder
Dices^[i].MarkedDice := False; // Ingen terninger er markeret
Dices^[i].Arrow.Visible := False; // Ingen pile er synlige
end;
if DebugMode then
begin
Allowed := 100;
with DebugButton do
begin
Enabled := True;
Visible := True;
end;
ShowMessage('Du kører programmet i Debug Mode, hvilket vil sige,' + #13#10 +
'at du har 100 forsøg, istedet for de normale 3.' + #13#10 +
'Så har du nemmere mulighed for at teste om programmet virker!'
+ #13#10 + 'Du kan til envher tid afslutte Debug Mode, og' +
' dermed spille spillet normalt.' + #13#10 + #13#10 +
'Held og lykke ... !');
frm1.Caption := 'mini-YATZY - [Debug Mode]';
end;
end;
{------------------------------------------------------------------------------}
procedure Tfrm1.KastClick(Sender: TObject);
var
i: integer;
CheckFlag: Boolean;
begin
if (Strokes <> Allowed) then // Hvis IKKE sidste kast
begin
inc(Strokes); // Antal slået gange + 1
Kast.Caption := 'Kast'; // Ændrer navn på kaste-knappen
frm1.Caption := 'mini-YATZY - [kast ' + IntToStr(strokes) + ' af ' +
IntToStr(Allowed) + ']';
// Så man i formens caption kan se hvor mange kast man har tilbage
for i := 1 to 5 do // En løkke der bruges til ...
begin
if not Dices^[i].MarkedDice then // Hvis terningen der er trykket på,
begin // ikke er markeret
LoadDice(i); // Hent baggrundsbillede til terning -
// dermed fjern nuværende
Dices^[i].Dices := (1 + random(6)); // Selve Yatzy slaget, som
// indsættes i Dices-arrayet
DrawDice(i, Dices^[i].Dices); // Tegn terningerne, med passende antal
end; // øjne.
end;
end;
if (Strokes = Allowed) then // Hvis sidste slag:
begin
Kast.Caption := 'Start'; // Kast knappen skal - igen - hedde Start
for i := 1 to 5 do // En løkke der gør følgende:
begin
Dices^[i].MarkedDice := False; // Gør alle terninger umarkeret
Dices^[i].Arrow.Visible := False; // Skjul alle pile
Dices^[i].Dice.Hint := 'Terning ' + IntToStr(i); // Lav terningernes hint
end; // om til standard
Strokes := 0;
end;
CheckFlag := False; // Sæt CheckFlag til False
for i := 2 to 5 do // En løkke der gør følgende:
begin
if (Dices^[1].Dices <> Dices^[i].Dices) then // Hvis terning 1 IKKE er lig
begin // de andre terninger
CheckFlag := True; // Sæt CheckFlag til True
end;
end;
if not CheckFlag then // Hvis CheckFlag er False (altså 5-ens):
begin
// Følgende er beskeden der popper-op hvis man har vundet
ShowMessage('Tillyke du fik 5 ens!' + #13#10 +
'Summen af terningerne var ' + IntToStr(5 * Dices^[1].Dices) + #13#10
+ 'Du var ' + IntToStr(Strokes) + ' kast om at vinde');
for i := 1 to 5 do // En løkke der gør følgende:
begin
Dices^[i].MarkedDice := False; // Gør alle terninger umarkeret
Dices^[i].Arrow.Visible := False; // Skjul alle pile
Dices^[i].Dice.Hint := 'Terning ' + IntToStr(i); // Lav terningernes hint
end; // om til standard
Strokes := 0; // Start spillet forfra
end;
end;
{------------------------------------------------------------------------------}
procedure Tfrm1.DiceClick(Sender: TObject); // Hvis tryk på terning
var
i: integer;
begin
if Strokes = 0 then // Hvis spillet ikke er igang
begin
// Vis da følgende besked
ShowMessage(' Tryk start for at starte et nyt spil ');
end
else
begin
for i := 1 to 5 do // En løkke der gør følgende:
begin
if (Sender = Dices^[i].Dice) then // Hvis Sender er "i"
begin
CheckDice(i); // Hvis terning er markeret bliver den afmarkeret
end; // og vice versa
end;
end;
end;
{------------------------------------------------------------------------------}
procedure Tfrm1.FormKeyPress(Sender: TObject; var Key: Char); // Hvis tastetryk
var
i: integer;
begin
if Strokes = 0 then // Hvis spillet ikke er igang ...
begin
// ... vis da følgende besked
ShowMessage(' Tryk start for at starte et nyt spil ');
end
else
for i := 1 to 5 do // En løkke der gør følgende:
begin
if (Key = IntToStr(i)) then // Hvis trykket tast er "i"
begin
CheckDice(i); // Hvis terning er markeret bliver den afmarkeret
end; // og vice versa
end;
end;
{------------------------------------------------------------------------------}
procedure Tfrm1.DebugButtonClick(Sender: TObject); // Hvis afsluttet Debug-Mode
var
i: integer;
begin
frm1.Caption:= 'mini-YATZY - [intet spil er igang]';
Allowed := 3;
with DebugButton do
begin
Enabled := False;
Visible := False;
end;
Kast.Caption := 'Start'; // Kast knappen skal - igen - hedde Start
for i := 1 to 5 do // En løkke der gør følgende:
begin
Dices^[i].MarkedDice := False; // Gør alle terninger umarkeret
Dices^[i].Arrow.Visible := False; // Skjul alle pile
Dices^[i].Dice.Hint := 'Terning ' + IntToStr(i); // Lav terning hint om
end; // til standard
Strokes := 0;
end;
initialization
randomize; // Initialiserer random generatoren med en tilfældig værdi
eyeColor := $00000000; // Farven til øjnene
diceColor := $00FFFFFF; // Farven til terningen
Strokes := 0; // "Start på en frisk"
Allowed := 3 // Antal gange man må kaste
end.
HUSK at du kan ikke tage koden direkte vha Copy/Paste da noget af koden bliver oversat af udvikleren.dk når du læser forummet direkte. Du skal vælge at svare på dette indlæg og der efter Copy/Paste.
/Michael.
[Redigeret d. 29/10-03 08:57:09 af Michael Skovslund][Redigeret d. 29/10-03 09:03:50 af Michael Skovslund]