Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   array per message in eigener anwendung versenden (https://www.delphipraxis.net/153618-array-per-message-eigener-anwendung-versenden.html)

silver-moon-2000 10. Aug 2010 11:09

array per message in eigener anwendung versenden
 
Hallo zusammen,

tut mir (schon fast) leid, Euch wieder mal nerven zu müssen, aber weder Suchfunktion noch Tante Google konnten mir weiterhelfen:

Das folgende Konstrukt wurde mir von meinem Vorgänger (Praktikant, wie ich auch) so überlassen und ich soll es nun wieder aufnehmen (wobei ich auch nicht mehr Ahnung habe :oops:).

Ich soll / muss / darf ein Array von einem Object aus per Message an ein anderes Object "verschicken", jedoch innerhalb meiner eigenen Anweisung.

Delphi-Quellcode:
const wm_my_notify = wm_user + 1;

type RQueueItem = record
  Level : Integer;
  comm : Boolean;
  BP : Boolean;
[...]
end;

type TAQueue = array of RQueueItem;
Delphi-Quellcode:
type TClassOne = class(TObject)
  private
    FQueue : TAQueue;
    procedure CreateQueue;
  public
    procedure Notify;
end;

procedure TClassOne.CreateQueue;
begin
  SetLength(FQueue, 100);
  //Befüllen des FQueue;
end;

procedure TClassOne.Notify;
begin
  //soll Fqueue per Message versenden
  SendMessage(classTwo.handle, wm_my_notify, Cardinal(@FQueue), 0);
end;
Delphi-Quellcode:
type TClassTwo = class(TObject)
  private
    FHandle : THandle;
    FQueue : TAQueue;
    procedure WndProc(msg : TMessage);
  public
end;

procedure TClassTwo.WndProc(msg : Tmessage);
var test : Integer;
begin
  if msg.msg = wm_my_notify then
    test := ((msg.wparam)^ as TAQueue)[0].Level; //funktioniert nicht
//??? Zugriff auf Queue-Array
end;
ClassTwo hat per AllocateHwnd ein Handle erhalten.
ClassOne füllt sein FQueue und soll es dann per Message an ClassTwo übertragen.

Die Message kommt auf prima an, ich kann auch Integers o.Ä. übertragen (z.B.
Delphi-Quellcode:
 SendMessage(classTwo.handle, wm_my_notify, High(FQueue), 0);
funktioniert tadellos und ich kann in ClassTwo auswerten mit
Delphi-Quellcode:
test := msg.wparam
Nur habe ich keine Ahnung, wie ich in ClassTwo wieder auf das Array bzw. dessen Struktur zugreifen soll, also konkret, was in TClassTwo.WndProc zu stehen hat, damit ich das Array verarbeiten kann.

Ich hoffe, ich konnte halbwegs verständlich machen, was mein Problem ist. Wäre dankbar, wenn sich jemand meines Problems annehmen könnte.

himitsu 10. Aug 2010 11:16

AW: array per message in eigener anwendung versenden
 
Du sendest nur den Zeiger ... SendMessage kann nunmal nur maximal 2 Integer/Pointer in WPARAM und LPARAM versenden
und den restlichen Speicher (mit dem Arrayinhalt) schickst du nicht rüber.

Du könntest via WM_COPYDATA nutzen ... allerdings mußt du da auch den Array-Inhalt und nicht ebenfalls nur den Array-Zeiger verschicken

oder du gehst über das Clipboard (aber Achtung, nicht daß du dort einfach so blind die Zwischenablage löschts/überschreibst)


Nee, Luckie hat recht

Luckie 10. Aug 2010 11:21

AW: array per message in eigener anwendung versenden
 
So lange er innerhalb des eigenen Prozesses bleibt, sollte es kein Problem sein nur den Zeiger zu verschicken. Er behäkt ja seine Gültigkeit. Nur der Empfänger muss eben beachten, dass er nur ein Zeiger auf das erste Element bekommt. Deswegen sollte man noch die Länge des Arrays mitverschicken.

himitsu 10. Aug 2010 11:27

AW: array per message in eigener anwendung versenden
 
stümmt

OK, wenn du nur lesend drauf zugreifen willst, dann müßte es so gehn.
Delphi-Quellcode:
SendMessage(classTwo.handle, wm_my_notify, WPARAM(FQueue), 0);

test := TAQueue(msg.wparam)[0].Level;
Das nutzt den internen Zeiger des Arrays. Dieses ist aber nur solange gültig/möglich, wie das Array nicht beim Empfänger verändert wird.

über @ und ^ müßte es eigentlich auch gehn, nur daß man hier einen Zeiger auf die Variable übergibt, wo dann auch Änderungen mäglich wären.

Das as ist nur für Objekte (und neuerdings auch für Interfaces) und nicht für "normale" Typen, wie ein Array.

Luckie 10. Aug 2010 11:28

AW: array per message in eigener anwendung versenden
 
Und um LPARAM würde ich die Länge mit schicken.

silver-moon-2000 10. Aug 2010 11:40

AW: array per message in eigener anwendung versenden
 
Zitat:

Zitat von himitsu (Beitrag 1040770)
Das nutzt den internen Zeiger des Arrays. Dieses ist aber nur solange gültig/möglich, wie das Array nicht beim Empfänger verändert wird.

Wird es nicht. Im Empfänger wird es nur gelesen.

Zitat:

Zitat von himitsu (Beitrag 1040770)
Das as ist nur für Objekte (und neuerdings auch für Interfaces) und nicht für "normale" Typen, wie ein Array.

Und wieder was neues gelernt...

Zitat:

Zitat von himitsu (Beitrag 1040770)
OK, wenn du nur lesend drauf zugreifen willst, dann müßte es so gehn.

Zitat:

Zitat von Luckie (Beitrag 1040771)
Und um LPARAM würde ich die Länge mit schicken.

Oh man, diese Mittagspause hat sich wirklich gelohnt. Ich könnte Euch beinahe knutschen. Beinahe!

himitsu 10. Aug 2010 11:41

AW: array per message in eigener anwendung versenden
 
Zitat:

Zitat von Luckie (Beitrag 1040771)
Und um LPARAM würde ich die Länge mit schicken.

bei einem/diesem dynamischen Array ist die Länge doch eingebaut :zwinker:

du kannst auch nur eine bestimmtes Item übergeben:
Delphi-Quellcode:
type PQueueItem = ^RQueueItem;

SendMessage(classTwo.handle, wm_my_notify, WPARAM(@FQueue[0]), 0);

test := PQueueItem(msg.wparam)^.Level;
// geht auch ohne "^", da Delphi in Fall des nachfolgenden "." sich dieses "^" einfach implizit dahindenkt

PS: Laut M$ sollte man besser die Typen WPARAM, LPARAM und RPARAM LRESULT (für's Result) verwenden, statt deinem Cardinal.

silver-moon-2000 10. Aug 2010 12:15

AW: array per message in eigener anwendung versenden
 
Zitat:

Zitat von himitsu (Beitrag 1040777)
du kannst auch nur eine bestimmtes Item übergeben:
Delphi-Quellcode:
type PQueueItem = ^RQueueItem;

SendMessage(classTwo.handle, wm_my_notify, WPARAM(@FQueue[0]), 0);

test := PQueueItem(msg.wparam)^.Level;
// geht auch ohne "^", da Delphi in Fall des nachfolgenden "." sich dieses "^" einfach implizit dahindenkt

Da stelle ich mich auf den Standpunkt: Wenn mans richtig macht (machen kann :wink:), dann braucht Delphi nicht mehr zu raten. Ist vor allem dann wichtig, wenn man in einer Sprache programmiert, die so etwas nicht automatisch macht.

Zitat:

Zitat von himitsu (Beitrag 1040777)
PS: Laut M$ sollte man besser die Typen WPARAM, LPARAM und RPARAM LRESULT (für's Result) verwenden, statt deinem Cardinal.

wurde notiert und geändert.

Nochmals danke für Deine / Eure Zeit & Mühe

himitsu 10. Aug 2010 13:34

AW: array per message in eigener anwendung versenden
 
Das ist aber kein Problem der Sprache.
Du nutzt hier ja einen Befehl der WinAPI und diese wird in allen Sprachen gleich angesprochen. (heißt also, unter C# würde es genauso aussehn)

Bitte.

Luckie 10. Aug 2010 16:54

AW: array per message in eigener anwendung versenden
 
Gerade C# ist ein schlechtes Beispiel, wegen dem unmanaged code. Ich hätte eher C oder so als Beispiel genannt. Aber warum eigentlich per SendMessage? Ich hätte ein Ereignos ausgelöst und der Empfänger hätte sich dann das Array selber abgeholt. Und wenn man es noch weiter treiben würde, könnte man aus dem Array eine Liste machen. Und aus den Records Objekte und dann eine ObjectList nehmen.

silver-moon-2000 10. Aug 2010 18:32

AW: array per message in eigener anwendung versenden
 
Zitat:

Zitat von silver-moon-2000 (Beitrag 1040788)
Zitat:

Zitat von himitsu (Beitrag 1040777)
Delphi-Quellcode:
// geht auch ohne "^", da Delphi in Fall des nachfolgenden "." sich dieses "^" einfach implizit dahindenkt

Da stelle ich mich auf den Standpunkt: Wenn mans richtig macht (machen kann :wink:), dann braucht Delphi nicht mehr zu raten. Ist vor allem dann wichtig, wenn man in einer Sprache programmiert, die so etwas nicht automatisch macht.

Zitat:

Zitat von himitsu
Das ist aber kein Problem der Sprache.
Du nutzt hier ja einen Befehl der WinAPI und diese wird in allen Sprachen gleich angesprochen. (heißt also, unter C# würde es genauso aussehn)

"...einfach implizit dahindenkt..." bedeutet für mich: Da gehört was hin, was vielleicht nicht dort steht, aber automatisch ergänzt wird, um dem User das Leben einfacher zu machen.
Soll also (für mich) heißen: Sinnvoll zu lernen, dass da eigentlich etwas hingehört (hier ein Dereferenzierer), dann macht man es in Zukunft (hoffentlich) auch in einer anderen Sprache nicht falsch.
Oder habe ich Dich falsch verstanden?

Zitat:

Zitat von Luckie
Aber warum eigentlich per SendMessage? Ich hätte ein Ereignos ausgelöst und der Empfänger hätte sich dann das Array selber abgeholt. Und wenn man es noch weiter treiben würde, könnte man aus dem Array eine Liste machen. Und aus den Records Objekte und dann eine ObjectList nehmen.

Erstmal, weil ich den Code so übernommen habe und ihn nicht umschreiben wollte. Man kann sich nun sicherlich trefflich darüber streiten, ob das Umschreiben den "Mehrwert" (also Objekte statt Records, Objectlist etc.) lohnt, zumal es ja jetzt (mit Eurer Hilfe) soweit funktioniert, dass man drauf "aufbauen" kann.

Zur Sache Ereignis <> Message bin ich ehrlich gesagt noch nicht so bewandert, wie ich die Ereignisse definieren soll.

[edit]

Aber lass mich mal überlegen, ob ich Dich richtig verstehe:

:arrow: ClassOne besitzt ein Ereignis
Delphi-Quellcode:
type TQueueTransfer = procedure(parameter : TAQueue) of object;

type TClassOne = class(TObject)
  private
    FQueue : TAQueue;
    procedure CreateQueue;
    FOnQueueCreated : TQueueTransfer;
  public
    property OnQueueCreated : TQueueTransfer read FOnQueueCreated write FOnQueueCreated;
end;

procedure TClassOne.CreateQueue;
begin
//Queue erzeugen und füllen
  if Assigned(FOnQueueCreated) then
    FOnQueueCreated(FQueue);
end;
:arrow: ClassTwo besitzt eine Methode "GetQueue", welche die Queue bei einem Ereignis entgegennehmen soll.
Delphi-Quellcode:
type TClassTwo = class(TObject)
  private
    FClassOne : TClassOne;
    procedure GetQueue(queue : TAQueue);
  public
end;
:arrow: Irgendwo anders (meinetwegen in einer "Superklasse") werden die beiden "verheiratet"
Delphi-Quellcode:
[...]
FClassOne := TClassOne.Create;
FClassTwo := TClassTwo.Create;
FClassOne.OnQueueCreated := FClassTwo.GetQueue;
[...]
:arrow: Das würde bedeuten, dass sich ClassOne und ClassTwo nicht mehr kennen müssen.
Bisher musste ja ClasssOne eine Referenz auf das ClasssTwo.Handle speichern, was jetzt wegfallen würde. Dafür muss es eine Superklasse geben, die beide Klassen kennt und für deren Verwaltung (Create / Free) zuständig ist.

Das gefällt mir in der Hinsicht besser, da ich persönlich eine Abneigung dagegen habe, dass jeder jeden kennen muss, damit die Sache funktioniert.

Also wenn ich Dich richtig verstanden habe und das auch so funktioniert, gefällt es mir recht gut und es wäre meines Erachtens den Aufwand wert, die Chose umzuschreiben. Mal sehen, ob ich dazu Zeit finde.


p.s. was bedeutet eigentlich dieses "of object"? Dass es sich um eine Prozedur eines Objects, also um eine Methode handelt?

xZise 10. Aug 2010 19:04

AW: array per message in eigener anwendung versenden
 
Zitat:

Zitat von silver-moon-2000 (Beitrag 1040877)
p.s. was bedeutet eigentlich dieses "of object"? Dass es sich um eine Prozedur eines Objects, also um eine Methode handelt?

Du hast es erfasst.

Und so hast du es auch für spätere Projekte gelernt und musst nicht mehr den Umweg über SendMessage machen. Gerade in Delphi ist die Implementierung ziemlich einfach was das angeht. Wenn ich da an Java denke graust es mir schon :P

MfG
Fabian

Luckie 10. Aug 2010 20:52

AW: array per message in eigener anwendung versenden
 
Eventuell solltest du dir das mal angucken: http://www.michael-puff.de/Artikel/C...rKlassen.shtml und dir mal mein Memory angucken: http://www.michael-puff.de/Programmi...ckieMemory.zip

silver-moon-2000 10. Aug 2010 21:58

AW: array per message in eigener anwendung versenden
 
Zitat:

Zitat von Luckie (Beitrag 1040900)
Eventuell solltest du dir das mal angucken: http://www.michael-puff.de/Artikel/C...rKlassen.shtml und dir mal mein Memory angucken: http://www.michael-puff.de/Programmi...ckieMemory.zip

Man dankt. Ich bin momentan zu müde, werde mir morgen aber sicher Dein Memory mal ansehen. Sieht interessant aus.

Ich denke (ohne Euch abwürgen zu wollen), dass damit meine Fragen erschöpfend beantwortet sind und bedanke mich nochmal beim "Geheimniskrämer", beim "Glücklichen", beim "Sich Übenden" und summarisch bei allen "stillen" Lesern.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:36 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz