Einzelnen Beitrag anzeigen

Hobbycoder

Registriert seit: 22. Feb 2017
955 Beiträge
 
#1

VST IVTEditLink AccessViolation bei WindowProc

  Alt 1. Feb 2021, 19:00
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 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.
Gruß Hobbycoder
Alle sagten: "Das geht nicht.". Dann kam einer, der wusste das nicht, und hat's einfach gemacht.
  Mit Zitat antworten Zitat