Wątek przeniesiony 2014-01-13 19:49 z Delphi i Pascal przez olesio.

Procedury wykonywane przy otwieraniu form2

0

Witam serdecznie,

Piszę program - książkę telefoniczną i chciałbym, aby po zaznaczeniu rekordu w listview i kliknięciu edytuj otwierało się okienko z 3 editami w których byłyby wczytane dane z tego listview, tj. imię, nazwisko, telefon, a następnie, po kliknięciu zapisz procedura w dllu zmieniała by dany rekord w liście jednokierunkowej.

W tej chwili mam problem z załadowaniem danych z listview z form1 do editów w form2. Myślałem, ze dam radę za pomocą formcreate, ale nie mogę lub robię coś źle.

Prosiłbym o pomoc. Z góry dzięki :)

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, Vcl.ToolWin,
  Vcl.ActnMan, Vcl.ActnCtrls, Vcl.ActnMenus, Vcl.Menus;

type
  TForm2 = class(TForm)
    StaticText1: TStaticText;
    StaticText2: TStaticText;
    StaticText3: TStaticText;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    zapisz: TButton;
    anuluj: TButton;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure zapiszClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

 procedure Tform2.FormCreate(Sender: TObject);
 begin
 label1.caption:='123';
 end;

procedure TForm2.zapiszClick(Sender: TObject);
begin
 label1.caption:='123';
end;

end. 
procedure TForm1.edytujClick(Sender: TObject);
var
Form2:TForm2;
begin
if assigned(listview1.selected) then
begin
with TForm2.Create(nil) do
    try
      ShowModal;
    finally
      Free;
    end;
end
else
  showmessage('Nie zaznaczono rekordu do edycji!');
end; 
0

Przed ShowModal masz dostęp jednocześnie do Form1.listview1 oraz do Form2.

0

Przy dodaniu

form2.Edit1.Text:='123';

wywala acces violation.
Ok ogarnąłem, wykorzystuje onshow, ale jak wyświetlić subitems z listview1 z form1?

0

Teraz mam następny problem z funkcją edytuj...
A mianowicie wczytauje dane z listview do form 2 i po edycji oraz kliknieciu zapisz tworzy mi nowy rekord, ktory potem chce podmienic w liscie funkcja w dll.
//EDIT
jakims dziwnym sposobem zmienna id zmienia swoja wartosc na 1632660... Jakieś pomysły??

library dll;

uses   windows, System.SysUtils, Vcl.ComCtrls, Vcl.StdCtrls; //<-- wystarczy tylko ten moduł

type
  wskaznik=^TOsoba;
  TOsoba = packed record
    imie,nazwisko,telefon:shortstring;
    nastepny: wskaznik;
    end;

TOsobafile = file of TOsoba;
var
    pierwszy, ostatni:wskaznik;


procedure Dodaj_osobe(rekord:wskaznik);
begin
if Pierwszy=nil then
  begin
    Pierwszy:=rekord;
    Ostatni:=Pierwszy;
  end
else
  begin
    Ostatni^.nastepny:=rekord;
    Ostatni:=rekord;
  end;
end;

procedure wczytaj_liste(nazwa:pchar);
var
  Ofile : TOsobafile;
  NewOsoba : wskaznik;
begin
pierwszy:=nil;
ostatni:=nil;
  AssignFile(Ofile, nazwa);
  Reset(Ofile);
  try
     while not eof(Ofile) do
      begin
        New(NewOsoba);
        Read(Ofile, NewOsoba^);
        NewOsoba^.nastepny:=nil;
        if pierwszy=nil then
          begin
            pierwszy:=NewOsoba;
            ostatni:=pierwszy;
            ostatni^.nastepny:=nil;
          end
        else
          begin
          ostatni^.nastepny:=NewOsoba;
          ostatni:=NewOsoba;
          ostatni^.nastepny:=nil;
          end;
      end;
  finally
    CloseFile(Ofile);
    //MessageBox(0, pwidechar(string(pierwszy.imie)+string(pierwszy.telefon)),'Hello world!',MB_OK);
 end;
end;

procedure Zapisz_zmiany(nazwa:pchar);
var
  Ofile : TOsobafile;
  aktualny : wskaznik;
  nazwa_pliku:string;
begin
try
nazwa_pliku:=string(nazwa);
AssignFile(Ofile, nazwa);
Rewrite(Ofile);
aktualny:=pierwszy;
while aktualny <> nil do
begin
write(Ofile, aktualny^);
aktualny:=aktualny^.nastepny;
end;
finally
Closefile(Ofile);
end;
end;

procedure Wyswietl_liste(listview1:Tlistview);
var
aktualny : wskaznik;
i : integer;
begin;
listview1.Clear;
aktualny:=pierwszy;
i:=0;
while aktualny <> nil do
  begin
     listview1.Items.add;
     listview1.Items.Item[i].caption:=inttostr(i);
     listview1.items.Item[i].SubItems.add(aktualny^.imie);
     listview1.items.Item[i].SubItems.add(aktualny^.nazwisko);
     listview1.items.Item[i].SubItems.add(aktualny^.telefon);
     aktualny:=aktualny^.nastepny;
     inc(i);
  end;
end;

function getfirst:wskaznik;

begin
  result:=pierwszy;
end;


procedure usun_osobe(id:integer);
var
aktualny, poprzedni:wskaznik;
i:integer;
begin
aktualny:=pierwszy;
  if id=0 then
  begin
    pierwszy:=pierwszy.nastepny;
    dispose(aktualny);
  end
  else
  begin
    for i := 0 to id-1 do
    begin
      poprzedni:=aktualny;
      aktualny:=aktualny.nastepny;
    end;
    if aktualny.nastepny <>nil then
      begin
      poprzedni.nastepny:=aktualny.nastepny;
      end
    else
    begin
      poprzedni.nastepny:=nil;
      ostatni:=poprzedni;
    end;
  end;
end;

procedure Skasuj_liste;
var
del:wskaznik;
begin
while pierwszy<> nil do
begin
del:=pierwszy;
pierwszy:=pierwszy^.nastepny;
dispose(del);
end;
end;

procedure edytuj(rekord:wskaznik; id:integer);
var
aktualny, poprzedni:wskaznik;
i:integer;
begin
aktualny:=getfirst;
if id=0 then
begin
rekord^.nastepny:=pierwszy^.nastepny;
pierwszy:=rekord;
end
else
begin
for i := 0 to id-1 do
begin
  poprzedni:=aktualny;
  aktualny:=aktualny^.nastepny;
end;
poprzedni^.nastepny:=rekord;
rekord^.nastepny:=aktualny^.nastepny;
end;
end;


exports  // eksportuj procedurę
  Dodaj_osobe name 'Dodaj_osobe',
  wczytaj_liste name 'Wczytaj_liste',
  zapisz_zmiany name 'Zapisz_zmiany',
  wyswietl_liste name 'Wyswietl_liste',
  usun_osobe name 'usun_osobe',
  getfirst,
  skasuj_liste,
  edytuj;

begin
end.
unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  wskaznik=^TOsoba;
  TOsoba = packed record
    imie,nazwisko,telefon:shortstring;
    nastepny: wskaznik;
    end;
  TForm2 = class(TForm)
    StaticText1: TStaticText;
    StaticText2: TStaticText;
    StaticText3: TStaticText;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    zapisz: TButton;
    anuluj: TButton;
    Label1: TLabel;
    procedure FormShow(Sender: TObject);
    procedure zapiszClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;
implementation
uses
unit1;
procedure edytuj(rekord:wskaznik; id:integer); stdcall; external 'project2.dll' name 'edytuj';


{$R *.dfm}


procedure TForm2.FormShow(Sender: TObject);
begin
edit1.Text:=form1.ListView1.Selected.SubItems[0];
edit2.Text:=form1.ListView1.Selected.SubItems[1];
edit3.Text:=form1.ListView1.Selected.SubItems[2];
label1.caption:=form1.ListView1.Selected.Caption
end;

procedure TForm2.zapiszClick(Sender: TObject);
var
rekord:wskaznik;
id:integer;
begin
new(rekord);
rekord^.imie:=edit1.Text;
rekord^.nazwisko:=edit2.Text;
rekord^.telefon:=edit3.Text;
rekord^.nastepny:=nil;
id:=strtoint(form1.ListView1.Selected.Caption);
edytuj(rekord, id);
form2.close;
end;

end.
0

Dopisek odpowiedniego modułu w sekcji uses przy takim komunikacie circular unit refference to... MUSI BYĆ TYLKO pod sekcją implementation. I kurcze, dlaczego po raz kolejny pytanie o banalne podstawy nie jest w Newbie :/ Tam wątek przenosze, jednak na przyszłość ludziki nauczcie się. Póki dział Newbie istnieje, tam pytamy o tak banalne podstawy jak to.

0
while aktualny <> nil do
begin
  listview1.Items.add;
  listview1.Items.Item[i].caption:=inttostr(i);
  listview1.items.Item[i].SubItems.add(aktualny^.imie);
  listview1.items.Item[i].SubItems.add(aktualny^.nazwisko);
  listview1.items.Item[i].SubItems.add(aktualny^.telefon);

  aktualny:=aktualny^.nastepny;
  inc(i);
end;

Powinno się wykorzystywać referencję do nowego itema, zwróconą przez metodę Items.Add, coś na ten kształt:

while Aktualny <> nil do
begin
  with ListView1.Items.Add() do
  begin
    Caption := IntToStr(I);
    SubItems.Add(Aktualny^.Imie);
    SubItems.Add(Aktualny^.Nazwisko);
    SubItems.Add(Aktualny^.Telefon);

    Aktualny := Aktualny^.Nastepny;
    Inc(I);
  end;
end;

lub można zadeklarować sobie zmienną typu TListItem, do której wpisuje się rezultat Items.Add i na niej już bezpośrednio się operuje.

0

A co z tą zmianą wartości zmiennej przekazywanej z form1 do dll w edytuj()? Dlaczego w form1 jest wszystko ok a po przekazaniu zmienia się na jakąś kosmiczną wartość? (1632636)

0

@daian.freedoom - a typy zmiennej i argumentu są takie same, czy inne? To nie jest przewidziane zachowanie, więc gdzieś albo ta wartość zostaje niezainicjowana, albo zmieniona; Trzba by prześledzić kod od zainicjowania wartości aż do kody funkcji Edytuj i sprawdzić gdzie zmienia się na tę nieoczekiwaną (z kosmosu); Ciężko stwierdzić gołym uchem.

0

zmianna ID jest przesyłana jako integer. W głównym programie tuż przed wysłaniem ma dobrą wartość a w dllu dałem pierwszą komendę messagebox wyświetlającą tą wartość i wyrzuca mi taką dużą, cały skrypt działa dobrze jak ustawiłem wartość ręcznie z określonego zakresu :/

Glowny program: http://4programmers.net/Pastebin/2845
unit2: http://4programmers.net/Pastebin/2843
dll :http://4programmers.net/Pastebin/2844

1 użytkowników online, w tym zalogowanych: 0, gości: 1