Windows Datentypen und TMessage

Antworten
siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Windows Datentypen und TMessage

Beitrag von siro »

Hallo und ein frohes neues Jahr wünsche ich euch.

Ich portiere grad meine Komponenten von Delphi 6 auf Lazarus und das gestaltet sich teilweise sehr problematisch.

Nach langem Suchen und debuggen, bin ich der Meinung das Problem liegt in den Datentypen selbst, bzw. durch 32 Bit 64 Bit.

Meine Komponenten schicken sich gegenseitig eigene Messages mittels "Perform" dazu habe ich mir eine eigene Message Struktur geschaffen,
ich vermute diese kollidiert mit der Windows TMessage, welche in der Datei "messages.inc" definiert ist.
Dort steht:

Code: Alles auswählen

 
 
     PMessage = ^TMessage;
     TMessage = record
        msg      : UINT;
        // Delphi docs say no filler here. Because next field is
        // already 8 byte aligned in 64-bit?
        case longint of
          0: (
              wParam : WPARAM;
              lParam : LPARAM;
              Result : LRESULT;
             );
          1: (
              wParamlo,
              wParamhi : HALFPARAM;  // Is there Windows type for half an w/lparam?
              wParamFiller : TDwordFiller;
              lParamlo,
              lParamhi : HALFPARAM;
              lParamFiller : TDwordFiller;
              Resultlo,
              Resulthi : HALFLRESULT;
              ResultFiller : TDwordFiller;
             );
       end




Das beisst sich vermutlich mit meinem Record von Delphi, der wie fogt aussieht:

Code: Alles auswählen

 
Type TSiroMessage = Record
  MSG    : Cardinal;           { hat immer die Konstante WM_SIRO  }
  SMID   : WORD;               { die Identifizierungsnr. der Message (SMID_xxx) }
  Sender : TObject;            { der Absender, wer die Message geschickt hat, normalerweise "self" }
  result : Longint;            { Ergebnis = 1 bedeutet: Message wurde verarbeitet }
end;


Ein buntes Mischmasch von 16 32 64 Bit vermute ich für das Chaos :-)
In Delphi 3 und 6 laufen die Komponenten damit einwandfrei

Könnt Ihr mir eine Tipp geben, wie ich das "sinnvoll" gestalten kann ? und wo sind die Datentypen
WPARM LPARAM LRESULT HALFPARAM HALFRESULT UINT definiert ?



Noch etwas Info wie ich Perform aufrufe:

Code: Alles auswählen

 
 
{ es gibt nur eine einzige "neue" Windows Botschaft mit dem Namen bzw. Wert "WM_SIRO" }
 
CONST WM_SIRO = WM_USER + 1000;
 
{ die verschiedenen Messages werden durch  Identifizierungs-Codes auseinandergehalten }
{ SMID_xxx  bedeutet Siro Message Identifier }
{ Dies ist also der zweite Parameter der Message }
 
 SMID_SCALE_DESTROY    = 1{ wird unmittelbar VOR dem Auflösen eines Scale gesendet }
 SMID_WINXY_DESTROY    = 2{ wird unmittelbar VOR dem Auflösen eines WinXY gesendet }
 SMID_SCALE_CHANGED    = 3{ die Scalierung hat sich geändert }
 SMID_WINXY_MOUSE_MOVE = 4{ Maus wurde innerhalb eines WinXY bewegt }
 SMID_SNAP_CHANGED     = 5{ der SnapX oder SnapY vom Scale hat sich geaendert }
{ eine globale Funktion nicht Objekt gebunden: }
{ sendet an alle Komponenten die von TControl abgeleitet sind und sich auf dem }
{ Besitzerfenster befinden, die uebergebene SiroMessage, ausser an sich selbst, }
{ da sie ja von sich selbst geschickt wird. }
 
procedure SendSiroMessage(SMID:Word; Sender:TComponent);
var own:TComponent; i:Integer; c:TControl;
begin
  own:=(Sender).Owner;                 { Das Besitzerfenster ermitteln }
  if NOT Assigned(own) then exit;      { haste keins, dann exit }
  if Own.ComponentCount = 0 then exit; { hat das Besitzer Fenster keine Komponenten dann ende }
 
  { an alle Control-Komponenten schicken, ausser an sich selbst }
  { TControl ist die erste Komponente in der Hierarchie, welche Messages empfängt }
  { bzw.  die Function Perform unterstützt }
 
  With own do begin
    for i:=0 to ComponentCount-1 do begin       { alle Komponenten des Besitzerfenster abklappern }
      if Components[i] is TControl then begin     { wenn Komponente von TControl abgeleitet ist }
        c:=TControl(Components[i]);                 { c ist nun die gewaehlte Komponente }
        if c <> Sender then c.Perform(WM_SIRO,SMID,lParam(Sender)) { ! nicht an sich selbst schicken }
      end;
    end; { for i }
  end; { with own }
 
end;
 


Ich danke euch schonmal im voraus
Siro
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Windows Datentypen und TMessage

Beitrag von wp_xyz »

Ich bin bei meinen eigenen Konvertierungen immer recht gut vorangekommen, indem ich folgendes beachtet habe:

  • Die Units Windows und Messages sind tabu. Verwende stattdessen LCLIntf, LCLType und LMessages - die sind cross-platform. (In LCLType findest du auch WPARAM etc.)
  • TMessage heißt bei Lazarus TLMessage (in LCLType deklariert).
  • Die WM_XXXX Konstanten heißen LM_XXXX.
  • Die TWMXXXX-Typen heißen TLMXXXX (also TLMButtonDown statt TWMButtonDown).
  • TCMXXX und CM_XXX bleiben unverändert.

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Windows Datentypen und TMessage

Beitrag von siro »

Hallo, vielen Dank erst einmal für die Information.
Ich schaue mir das grade an, habe bisher nur in Delphi Anwendungen für Windows gemacht.
so werde ich das mal mit einer kleinen, einfachen Komponente probieren.
Dann werde ich meine TMessage in eine TLMessage umsetzten, dann müste es eigentlich wieder funktionieren.

Siro
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Windows Datentypen und TMessage

Beitrag von siro »

ich muss ja wirklich nochmal einen Dank an wp_xyz ausrichten.
Das Umstellen meiner Komponenten klappt jetzt recht gut und und die par Zeilen Infos von Dir mit den Kürzeln sind ein echtes Nachschlagewerk. TOP

Nun konnte ich auch noch ein Problem lösen:

Ich hatte ja eine eigene MessageStruktur wie folgt:

Code: Alles auswählen

Type TSiroMessage2 = Record
  MSG    : Cardinal;           { hat immer die Konstante WM_SIRO  }
  SMID   : WORD;               { die Identifizierungsnr. der Message (SMID_xxx) }
  Sender : TObject;            { der Absender, wer die Message geschickt hat, normalerweise "self" }
  result : Longint;            { Ergebnis = 1 bedeutet: Message wurde verarbeitet }
end


Jetzt hab ich mir mal die Größe der Datentypen ausgeben lassen und war erstaunt:
WORD = 2 Bytes
WPARAM = 8 Bytes
TObject = 8 Bytes
LPARAM = 8 Bytes

Ein Word hat ja nur 2 Bytes, aber ein WPARAM hat 8 Bytes :shock: und da beisst es sich natürlich in meinen Komponenten.
Ich habe jetzt die Struktur umgestellt und siehe da, nun läuft es auch.

Code: Alles auswählen

Type TSiroMessage1 = Record
  MSG    : Cardinal;           { hat immer die Konstante LM_SIRO  }
  SMID   : WPARAM;             { die Identifizierungsnr. der Message (SMID_xxx) }
  Sender : LPARAM;             { der Absender, wer die Message geschickt hat, normalerweise "self" }
  result : LRESULT;            { Ergebnis = 1 bedeutet: Message wurde verarbeitet }
end;               
 


So langesam bekomme ich richtig Spass an Lazarus :D
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

marcov
Beiträge: 1100
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: Windows Datentypen und TMessage

Beitrag von marcov »

siro hat geschrieben:Könnt Ihr mir eine Tipp geben, wie ich das "sinnvoll" gestalten kann ? und wo sind die Datentypen
WPARM LPARAM LRESULT HALFPARAM HALFRESULT UINT definiert ?


Kontrolliere die große unter 64-bit von (1) FPC's TMessage und deine eigene records. Sie sollen gleich sein.

Die Typen sind in unit windows und/oder messages.

Aber es gibt auch System unabhängige Versionen. Ich glaube in "lclmessages".

Antworten