Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi VST IVTEditLink AccessViolation bei WindowProc (https://www.delphipraxis.net/206817-vst-ivteditlink-accessviolation-bei-windowproc.html)

Hobbycoder 1. Feb 2021 18:00

VST IVTEditLink AccessViolation bei WindowProc
 
Hi,

ich benötige in einer VST einen Editor in zwei Spalten. Ich habe mir die Klasse mit dem implementiern Interface IVEditLink gemäß den zahlreichen Beispielen erstellt. Jedoch als Edit-Komponente habe ich TJvValidateEdit genommen, weil mir da das Editieren von z.B: Currency besser gefällt.
Soweit scheint das auch zu funktioniere, jedoch bekomme ich in der Methode "TEditValueEditLink.ProcessMessage" immer eine AV in der Zeile
Delphi-Quellcode:
FEdit.WindowProc(Message);
, wobei ich leider den Wert von Message im Debugger nicht auslesen kann.

Ich habe schon JvValidateEdit gegen ein normales TEdit getauscht, aber der Fehler bleibt der gleiche. Mit dem integrierten Editor des VST gibt es keine Probleme.

Das FEdit existiert. Wenn ich das WindowProc auskommentiere, läuft es, jedoch werden ja die Fensterbotschaften nicht mehr an das Control weitergeleitet (Es wird auch an der falschen STelle gezeichnet).

Hier mal meine Unit:
Delphi-Quellcode:
unit TNSLagerWareneingang;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VirtualTrees, Vcl.ExtCtrls, uArtikel, JvValidateEdit, JvEdit;

type
  IVTEditLink = interface
    ['{2BE3EAFA-5ACB-45B4-9D9A-B58BCC496E17}']
    function BeginEdit: Boolean; stdcall; // Called when editing actually starts.
    function CancelEdit: Boolean; stdcall; // Called when editing has been cancelled by the tree.
    function EndEdit: Boolean; stdcall; // Called when editing has been finished by the tree. Returns True if successful, False if edit mode is still active.
    function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; stdcall;
                                                           // Called after creation to allow a setup.
    function GetBounds: TRect; stdcall; // Called to get the current size of the edit window
                                                           // (only important if the edit resizes itself).
    procedure ProcessMessage(var Message: TMessage); stdcall;
                                                           // Used to forward messages to the edit window(s)-
    procedure SetBounds(R: TRect); stdcall; // Called to place the editor.
  end;

  TEditValueEditLink = class (TInterfacedObject, IVTEditLink)
  private
    FEdit: TJvValidateEdit;
    FTree : TVirtualStringTree;
    FNode : PVirtualNode;
    FColumn : Integer;
    procedure GetNodeText;
  public
    destructor Destroy; override;
    function BeginEdit: Boolean; virtual; stdcall;
    function CancelEdit: Boolean; virtual; stdcall;
    function EndEdit: Boolean; virtual; stdcall;
    function GetBounds: TRect; virtual; stdcall;
    function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; stdcall;
    procedure ProcessMessage(var Message: TMessage); virtual; stdcall;
    procedure SetBounds(R: TRect); stdcall;
  end;

  TfrmTNSLagerWareneingang = class(TForm)
    pnlBottom: TPanel;
    vstArtikel: TVirtualStringTree;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure vstArtikelInitNode(Sender: TBaseVirtualTree; ParentNode,
      Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
    procedure vstArtikelGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
    procedure FormShow(Sender: TObject);
    procedure vstArtikelCreateEditor(Sender: TBaseVirtualTree;
      Node: PVirtualNode; Column: TColumnIndex; out EditLink: IVTEditLink);
    procedure vstArtikelEditing(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; var Allowed: Boolean);
    procedure vstArtikelFocusChanged(Sender: TBaseVirtualTree;
      Node: PVirtualNode; Column: TColumnIndex);
  private
    procedure BuildArtikelList;
    { Private-Deklarationen }
  public
    ArtikelList: TArtikelList;
    { Public-Deklarationen }
  end;

var
  frmTNSLagerWareneingang: TfrmTNSLagerWareneingang;

implementation

{$R *.dfm}

procedure TfrmTNSLagerWareneingang.BuildArtikelList;
begin
  vstArtikel.BeginUpdate;
  try
    vstArtikel.Clear;
    vstArtikel.RootNodeCount:=ArtikelList.Count;
  finally
    vstArtikel.EndUpdate;
  end;
end;

procedure TfrmTNSLagerWareneingang.FormCreate(Sender: TObject);
begin
  ArtikelList:=TArtikelList.Create(true);
end;

procedure TfrmTNSLagerWareneingang.FormDestroy(Sender: TObject);
begin
  ArtikelList.Free;
end;

procedure TfrmTNSLagerWareneingang.FormShow(Sender: TObject);
begin
  BuildArtikelList;
end;

procedure TfrmTNSLagerWareneingang.vstArtikelCreateEditor(
  Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
  out EditLink: IVTEditLink);
begin
  case Column of
    3, 5: EditLink:=TEditValueEditLink.Create;
  end;
end;

procedure TfrmTNSLagerWareneingang.vstArtikelEditing(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean);
begin
  Allowed:=(Column=3) or (Column=5);
end;

procedure TfrmTNSLagerWareneingang.vstArtikelFocusChanged(
  Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
begin
//  Sender.EditNode(Node, 3);
end;

procedure TfrmTNSLagerWareneingang.vstArtikelGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: string);
var
  a: TArtikel;
begin
  a:=TArtikel(vstArtikel.GetNodeData(Node)^);
  if Assigned(a) then
    case Column of
      0: CellText:=a.ArtikelNummer;
      1: CellText:=a.Beschreibung;
      2: CellText:=a.Count.ToString;
      3: CellText:=a.CountGelief.ToString;
      4: CellText:=FormatFloat('#,##0.00 €', a.EK);
      5: CellText:=FormatFloat('#,##0.00 €', a.EKGelief);
      6: CellText:=a.Distributor;
    end;
end;

procedure TfrmTNSLagerWareneingang.vstArtikelInitNode(Sender: TBaseVirtualTree;
  ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
begin
  vstArtikel.SetNodeData(Node, ArtikelList[Node.Index]);
end;

{ TEditValueEditList }

function TEditValueEditLink.BeginEdit: Boolean;
begin
  Self.FEdit.Show;
  Self.FEdit.SetFocus;
  Self.GetNodeText;
  Self.FEdit.SelectAll;
end;

function TEditValueEditLink.CancelEdit: Boolean;
begin
  Result := True;
  FEdit.Hide;
end;

destructor TEditValueEditLink.Destroy;
begin
  FEdit.Free;
  inherited Destroy;
end;

function TEditValueEditLink.EndEdit: Boolean;
begin
  try
    case FColumn of
     3: TArtikel(FTree.GetNodeData(FNode)^).CountGelief:=FEdit.Value;
     5: TArtikel(FTree.GetNodeData(FNode)^).EKGelief:=FEdit.Value;
    end;
    FTree.InvalidateNode(FNode);
  except
    on e: Exception do
      MessageBox(FTree.Parent.Handle, PChar(e.Message), 'Fehler', MB_OK or MB_ICONERROR or MB_TASKMODAL);
  end;
  Result := True;
end;

function TEditValueEditLink.GetBounds: TRect;
begin
  Result := FEdit.BoundsRect;
end;

procedure TEditValueEditLink.GetNodeText;
begin
  case FColumn of
    3: Self.FEdit.Value := TArtikel(FTree.GetNodeData(FNode)^).CountGelief;
    5: Self.FEdit.Value := TArtikel(FTree.GetNodeData(FNode)^).EKGelief;
  end;
end;

function TEditValueEditLink.PrepareEdit(Tree: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex): Boolean;
begin
  Result := True;
  FTree := Tree as TVirtualStringTree;
  FNode := Node;
  FColumn := Column;
  FEdit := TJvValidateEdit.Create(FTree);
  FEdit.Visible := False;
  FEdit.Parent := FTree;
  case FColumn of
    3: self.FEdit.DisplayFormat:=dfInteger;
    5: self.FEdit.DisplayFormat:=dfCurrency;
  end;
end;

procedure TEditValueEditLink.ProcessMessage(var Message: TMessage);
begin
  if Assigned(FEdit) then
    FEdit.WindowProc(Message);
end;

procedure TEditValueEditLink.SetBounds(R: TRect);
var
  Dummy : Integer;
begin
  FTree.Header.Columns.GetColumnBounds(FColumn, Dummy, R.Right);
  R.Left := Dummy;// + FTree.Margin * 2;
  FEdit.Width := R.Width;
  R.Bottom := Abs(R.Top) + Abs(FTree.NodeHeight[FTree.FocusedNode]);
  InflateRect(R, 0, 1);
  FEdit.BoundsRect := R;
end;

end.

Aviator 2. Feb 2021 09:20

AW: VST IVTEditLink AccessViolation bei WindowProc
 
Ich kann so auf die Schnelle jetzt nichts erkennen. Ein Vergleich mit meinen EditLinks die ich seit Jahren im Einsatz habe zeigt jetzt auch nichts ungewöhnliches. Habe allerdings den Code jetzt auch nicht in ein Projekt reingenommen und dort getestet. Hilft der StackTrace eventuell weiter? Woher kommt die Message?


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:35 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