AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Eigene Callback Funktion schreiben.
Thema durchsuchen
Ansicht
Themen-Optionen

Eigene Callback Funktion schreiben.

Ein Thema von Luckie · begonnen am 9. Jun 2003 · letzter Beitrag vom 9. Jun 2003
Antwort Antwort
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#1

Eigene Callback Funktion schreiben.

  Alt 9. Jun 2003, 03:12
Gegeben ist eine typisierte Datei mit Datensätzen. Alle Operationen mit dieser Datei sind in eine Klasse gekapselt (hinzufügen, löschen, modifizieren, auslesen, etc.). Nun kann es aber auch vorkommen, dass der Benutzer dieser Klasse alle Datensätze braucht. Er könnte nun in einer Schleife alle Datensätze durchgehen und sie mit der "Lesen"-Methode anzeigen. Dies wollte ich dem Benutzer der Klasse allerdings abnehmen und dachte dabei an eine Callback Funktion. Callback deswegen, damit man beispielsweise eine Fortschrittsanzeige implementieren kann oder so.

Mein erster etwas kläglicher Versuch sieht jetzt so aus:
Delphi-Quellcode:
const
  TCM_MAXRECORDS = WM_USER+74;
  TCM_ENUMRECORDS = WM_USER+75;

function TTypedFile.EnumRecords(hWnd: Cardinal; var Data: TRecord): Boolean;
var
  i : Integer;
begin
  result := TRUE;
  SendMessage(hWnd, TCM_MAXRECORDS, 0, FRecordsCount);
  for i := 1 to FRecordsCount-1 do
  begin
    seek(f, i);
    read(f, Data);
    SendMessageCallback(hWnd, TCM_ENUMRECORDS, 0, 0, @EnumRecords, 0);
  end;
end;
Drei bis vier Probleme:
1. Er kompiliert es mir nicht, weil der 5. Parameter von SendMessageCallback nicht stimmt.
2. Wie rufe ich ich sie im Programm auf?
3. Wie muß die Funktion im Programm aussehen, welche die Nachrichten von meiner Callback empfängt?
4. Wie bekomme ich den Record aus der Callback in die Funktion, die die Nachrichten meiner Callback empfängt, um sie dann irgendwo auszuwerten / anzuzeigen?

Im Anhang mal das Demo zu der TTypedFiles Unit mit der Klasse zum Arbeiten mit typisierten Dateien.

Edit: Auch wenn es sich eventuell anderes lösen läßt, ich hätte es schon gerne mit einer Callback, weil ich es selbst mal verstehen will.

Später soll noch eine Sortier-Routzine rein und da bräuchte ich dann auch wieder eine Callback Funktion.
Angehängte Dateien
Dateityp: exe typedfilessfx.exe (278,7 KB, 7x aufgerufen)
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.105 Beiträge
 
Delphi 11 Alexandria
 
#2
  Alt 9. Jun 2003, 03:31
Moin Luckie,

zu 3.

Deklaration aus dem PSDK für die an SendMessageCallback zu übergebene Funktion:

VOID SendAsyncProc(HWND hwnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult);

In Delphi dann den stdcall nicht vergessen (mach' ich zu gerne )

Diese Funktion wird von Windows aus aufgerufen, sobald das angesprochene Fenster die Message vearbeitet hat, wobei lResult angibt, was das angesprochene als Ergebnis der Message zurückgibt, die anderen Parameter entsprechen denen, die Du mitgeschickt hast.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#3
  Alt 9. Jun 2003, 03:35
Hm, ja danke. Das habe ich auch schon gesehen, bin nur noch nicht so ganz damit klar gekommen.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Motzi
Motzi

Registriert seit: 6. Aug 2002
Ort: Wien
598 Beiträge
 
Delphi XE2 Professional
 
#4
  Alt 9. Jun 2003, 11:55
Aber Achtung! Du implementierst EnumRecords als eine Methode! Eine Methode hat noch einen impliziten Parameter - den Self-Pointer!
Manuel Pöter
  Mit Zitat antworten Zitat
tommie-lie
(Gast)

n/a Beiträge
 
#5
  Alt 9. Jun 2003, 13:33
Dafür hatte ich dir doch die kleine Demo geschrieben!
Hat eigentlich alles richtig gemacht, außer das ich dort auch das stdcall vergessen habe, aber bei mir scheint sich das nicht negativ auf das Verhalten auszuwirken...

Also gut, zu 1:
Warum gibst du denn als Antwortprozedur auch die aufrufprozedur an? Das gibt eine Endlosschleife!
Das Prinzip von Callbacks ist folgendermaßen:
Du läufst durch die Gegend. Plötzlich siehst du ein Reh und schickst jemandem 'n Brief und läufst anschließend weiter. In dem Brief stand eine Adresse, an die auf jeden fall eine Antwort geschickt wird. Der andere kriegt jetzt den Brief und macht darauf hin was (holt sein Gewehr raus ) und du kriegst an diese Adresse wieder einen Brief.
Im Programmierleben sieht das dann so aus:
Message an hWnd, Programm läuft weiter. hWnd kriegt Message, schnappt sie sich und macht was. @SendAsyncProc wird aufgerufen, falls angegeben.
Und bei deinem speziellen Beispiel sieht das so aus:
Lese Record, sende Nachricht. Nachricht wird bearbeitet und EnumRecords wird erneut aufgerufen (während es noch läuft, ob Windows da automatisch 'nen Thread erzeugt, weiß ich nicht). Jeder Aufruf einer Schleife ruft die Schleife erneut auf, und dieser Aufruf erzeugt wieder so viele Schleifen wie es Durchläuft gibt usw. Und irgendwann ist dein Stack voll.
Im Prinzip ist es für dich doch uninteressant, ob der User etwas mit der TCM_ENUMRECORDS-Message gemacht hat, oder nicht, also musst du auch keine Prozedur angeben, mit der du die Antwort erhälst, einfach losschicken und weiter machen. Bearbeitet der User deiner Klasse dann deine Message nicht, stört dich das nicht, bearbeitet er sie (zeigt Dialog oder weiß der Geier was), ist auch nicht schlimm.
Korrekt also:
SendMessageCallback(hWnd, TCM_ENUMRECORDS, 0, 0, nil, 0); // oder 0, bin mir grad' nicht sicher Zu 2: Was aufrufen? Die Nachricht (TCM_ENUMRECORDS) wird wie jede andere Nachricht an das Fenster geschickt und kann bearbeitet werden, entweder in der WndProc, oder bei VCL über eine message-procedure ("message TCM_ENUMPROCS;" hinter Deklaration schreiben).
Und wie du EnumRecords aufrufst, sollte wohl klar sein:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  MyTypedFile.EnumRecords;
end;


3: SDK unter SendCallbackMessage, die Demo von mir für dir oder Christians Antwort

4: Pointer im dwData. Guckst du PSDK:
Zitat von PSDK:
BOOL SendMessageCallback(
HWND hWnd
UINT Msg,
WPARAM wParam,
LPARAM lParam,

SENDASYNCPROC lpCallBack,
ULONG_PTR dwData
);
Daraus folgt:
Delphi-Quellcode:
function TTypedFile.EnumRecords(hWnd: Cardinal; var Data: TRecord): Boolean;
var
  i : Integer;
begin
  result := TRUE;
  SendMessage(hWnd, TCM_MAXRECORDS, 0, FRecordsCount);
  for i := 1 to FRecordsCount-1 do
  begin
    seek(f, i);
    read(f, Data);
    SendMessageCallback(hWnd, TCM_ENUMRECORDS, 0, Integer(@data), 0, 0);
  end;
end;
Dann steht im wParam der Pointer auf das Record, und du kannst das lesen. Allerdings weiß ich nicht, ob der Speicherinhalt gelöscht wird, wenn die Schleife weiterläuft (d.h. mit Sicherheit wird er das...), daher würde ich ein Array of Record nehmen und dieses übergeben. Dann macht auch die Callbackprozedur wieder sinn, denn wenn der Record dann vom Programm bearbeitet wurde, wird die aufgerufen und kann den Record wieder entfernen und somit für den nächsten freimachen.
Wenn der Record allerdings 4 Byte groß ist und in den wParam passt, ist's kein Problem *g*


Alle Klarheiten beseitigt? *g*


Edit: Oh, hab' 3 falsch interpretiert, im Programm sieht die Prozedur, die die Nachricht von deiner Callback gar nicht aus, denn das Callback ist der 5. Parameter. Wie die Prozedur aussieht, die deine Message abfängt, müsstest du am besten wissen: wie jede andere Prozedur, die eine Nachricht abfängt, auch -> WndProc bei nonVCL

Edit2: Copy&Paste-Fehler bereinigt.

Edit3: (hopefully) completed neverending quest for error-free posts
  Mit Zitat antworten Zitat
tommie-lie
(Gast)

n/a Beiträge
 
#6
  Alt 9. Jun 2003, 14:17
So, das hat mir jetzt keine Ruhe gelassen und hab's nu' selbst ausprobiert, anhand deines Quellcodes.
"Sie haben Post". Ach ne, du hast ja gar nicht AOL *g*
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:47 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz