PlaySound zacina mi cały program.

0

Witam.
Staram się zrobić dość prosty program, dzięki któremu będzie się coś działo gdy pojawi się jakiś tekst w listboxie.

Jak na razie wygląda to tak:

procedure testsound();
begin
PlaySound('alarm.wav', 0, SND_FILENAME);
sleep(2000);
end;

procedure TForm1.AlarmTimer(Sender: TObject);
var
w:integer;
begin
for w:=0 to ListBox1.Items.Count-1 do
if ListBox1.Items[w]= edit1.text then
begin
testsound();
end;
end;

W listboxie mi czyta teksty rzecz jasna.

Niestety, kiedy już wyje alarm dzieje się to monotonnie, a ja nawet nie mogę wyłączyć programu, gdyż się cały zacina. Jest może jakaś głębsza luka w tym skrypcie, przez którą własnie się to dzieje? Dodam, że jak alarm zawyje to przestaje mi nawet odświeżać listboxa.

Ps. Czytałem trochę o tych playsound i nikt nie ma takiego problemu ;< Nie znalazłem pomocy. Nie znalazłem również odpowiedzi na nurtujące mnie pytanie ''jak zrobić, by dźwięk był odtwarzany tylko jeden raz. Nie koniecznie chcę to zrobić, jednak może kiedyś mi się przyda.

Z góry dzięki.

@@
Dodam, że jak zrobiłem playsound na timerze i ustawiłem interval na 5000 to podczas odtwarzania dzwięku wszystko się ścinało, a później było ok.

0
procedure TForm1.AlarmTimer(Sender: TObject);
var
  w:integer;
begin
  for w:=0 to ListBox1.Items.Count-1 do
    if ListBox1.Items[w]= edit1.text then
    begin
      TestSound();
      AlarmTimer.Enabled := false;
      Break;
    end;
  end;

Odtwarza raz, zatrzymuje timer i przerywa pętlę.

0

Hm. Może i raz, ale wtedy wyłącza mi ten timer, a ja go potrzebuję :) Chcę tylko by zawsze odtwarzało dźwięk tylko jeden raz, nie wyłączając tego na stałe..

co do SND_Async to czytałem o tym i też to teraz zastosowałem. Nadal muli, choć nie aż tak. Mogę przynajmniej po kilku próbach zamknąć program xD

Proszę o dalsze rady..

@@@

z procedury testsound usunałem sleep. Jest nieco lepiej, jednak teraz ten dźwięk trochę wkurza, bo jest za szybko odtwarzany : p

0

Spróbuj odtwarzania w wątku, ewentualnie wykorzystaj bass.dll jeżeli nie musisz ograniczać rozmiaru programu i dodatków do niego.

1

Nie ma prawa mulić chyba że przez ten śmieszny timer. Po co jest ten timer?

0

Pierwsze słyszę o tym Bass.DLL, jednak na chwilę obecną jestem dość ograniczony jeżeli chodzi o programowanie (czas to zmienić). Chętnie o tym poczytam, dzięki.
Choć nie wiem czy to coś da. Jesteś pewny że mi to nie będzie zamulać jeżeli tego użyję ?

0

@DroniC, po raz setny - weź się naucz przynajmniej podstaw z podstaw:

procedure TForm1.AlarmTimer(Sender: TObject);
begin
  if ListBox1.Items.IndexOf(edit1.text)>=0 then testsound();
end;

Pokazuj kod po każdej poprawce, ponieważ przy twojej przerażająco małej wiedzy z zakresu nawet podstaw programowania, stwierdzenie: - "... co do SND_Async to czytałem o tym i też to teraz zastosowałem ..." - oznacza tyle co nic. Nie zdziwię się jeżeli twoje zastosowanie wygląda następująco: x:=SND_Async;

Dopóki nie zapoznasz się z podstawami podstaw, zwyczajnie rozmawiasz w innym języku niż reszta forum.

1

Na pewno bass.dll nic nie zamula, a ma większe możliwości. Poza tym tak jak pisał poprzednik. Może timer wadzi, bo interval jest krótszy niż koniecznośc wykrycia konieczności odtworzenia dźwięku albo dłuższe niż sam dźwięk do odtworzenia. Co do bass jeszcze, to użycie tej dllki jest banalne. Tymbardziej, że istnieje do niej bogata dokumentacja oraz mnóstwo przykładów, w tym dla Delphi.

0

Tekst w ListBox nie zmienia się "z kosmosu" więc wywal ten timer który jest do niczego niepotrzebny i sensownie reaguj na zmianę/ dodanie tekstu masz praktycznie gotowca:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TListBoxSetString = procedure (Sender: TObject; Index: Integer; Value: string) of Object;
  TListBox = class(StdCtrls.TListBox)
  private
    fOnListBoxSetString: TListBoxSetString;
  protected
    procedure ListBoxAddString(var Msg: TMessage); message LB_ADDSTRING;
    procedure ListBoxInsertString(var Msg: TMessage); message LB_INSERTSTRING;
  public
    property OnListBoxSetString: TListBoxSetString read fOnListBoxSetString
      write fOnListBoxSetString;
  end;


  TForm1 = class(TForm)
    ListBox1: TListBox;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
     procedure OnListBoxSetString(Sender: TObject; Index: Integer; Value: string);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure TListBox.ListBoxAddString(var Msg: TMessage);
var
  s: string;
begin
  inherited;
  s:= PChar(Msg.LParam);
  if Assigned(fOnListBoxSetString) then
    fOnListBoxSetString(Self, Self.Items.Count - 1, s);
end;

procedure TListBox.ListBoxInsertString(var Msg: TMessage);
var
  s: string;
begin
  inherited;
  s:= PChar(Msg.LParam);
  if Assigned(fOnListBoxSetString) then
    fOnListBoxSetString(Self, Msg.WParam, s);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ListBox1.OnListBoxSetString:=  OnListBoxSetString;
end;

procedure TForm1.OnListBoxSetString(Sender: TObject; Index: Integer; Value: string);
begin
  //tutaj sprawdzasz co dodano lub zmieniono Index to pozycja (który Item a Value to nowa wartość (nowy string)
  ShowMessage(Format('Wstawiono lub zmieniono Item: %d - %s', [Index, Value]));
end;

end.
0

Timer mi był do tego potrzebny żeby odświeżać info jakby.. Np. był napis 1003040 to mi go dodało do listboxu i odświeżało co chwila.. co chwila go dodając. Jak się jednak napis zmienił to wtedy dodawało mi i kolejny. Timer własnie do odświeżania był. Prawdę mówiąc nie wiedziałem nawet że można bez niego..

0

Jak zobaczyłeś owszem można. ListBox to standardowa kontrolka. Dlatego w ramach własnego procesu nikt Ci nie broni bezinwazyjnie "podczepić" się pod funkcję obsługi komunikatów.

0

Nie bardzo wiem jak użyć tego kodu od kAzka, ale postaram się to wykminić może jutro :) No nic, dzięki za pomoc.

0

Masz całość wraz z odtwarzaniem dźwięku (jeżeli tekst jest dodawany a dźwięk już jest odtwarzany to nie ponawia odtwarzania):

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, MMSystem;

type
  TListBoxSetString = procedure (Sender: TObject; Index: Integer; Value: string) of Object;
  TListBox = class(StdCtrls.TListBox)
  private
    fOnListBoxSetString: TListBoxSetString;
  protected
    procedure ListBoxAddString(var Msg: TMessage); message LB_ADDSTRING;
    procedure ListBoxInsertString(var Msg: TMessage); message LB_INSERTSTRING;
  public
    property OnListBoxSetString: TListBoxSetString read fOnListBoxSetString
      write fOnListBoxSetString;
  end;

  TPlaySoundThread = class(TThread)
  protected
    procedure Execute; override;
  public
    destructor Destroy; override;
  end;

  TForm1 = class(TForm)
    ListBox1: TListBox;
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
     fPlaySoundThread: TPlaySoundThread;
     fPlayThreadHandle: Cardinal;
     procedure OnListBoxSetString(Sender: TObject; Index: Integer; Value: string);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

// ----- TListBox

procedure TListBox.ListBoxAddString(var Msg: TMessage);
var
  s: string;
begin
  inherited;
  s:= PChar(Msg.LParam);
  if Assigned(fOnListBoxSetString) then
    fOnListBoxSetString(Self, Self.Items.Count - 1, s);
end;

procedure TListBox.ListBoxInsertString(var Msg: TMessage);
var
  s: string;
begin
  inherited;
  s:= PChar(Msg.LParam);
  if Assigned(fOnListBoxSetString) then
    fOnListBoxSetString(Self, Msg.WParam, s);
end;

// ----- TPlaySoundThread

procedure TPlaySoundThread.Execute;
begin
  FreeOnTerminate:= True;
  PlaySound('alarm.wav', 0, SND_FILENAME);
end;

destructor TPlaySoundThread.Destroy;
begin
  PlaySound(nil, 0, 0); //na wszelki wypadek zakonczyc odtwarzanie
  inherited;
end;

// ----- TForm1

procedure TForm1.FormCreate(Sender: TObject);
begin
  ListBox1.OnListBoxSetString:=  OnListBoxSetString;
end;

//tutaj sprawdzasz co dodano lub zmieniono Index to pozycja (który Item) a Value to nowa wartość (nowy string)
procedure TForm1.OnListBoxSetString(Sender: TObject; Index: Integer; Value: string);
var
  ExitCode: Cardinal;
begin
  //tutaj procedura sprawdzajaca
  //ShowMessage(Format('Wstawiono lub zmieniono Item: %d - %s', [Index, Value]));
  if Edit1.text = Value then  //porownujesz tekst
  begin
    GetExitCodeThread(fPlayThreadHandle, ExitCode);
    //sprawdzamy czy watek aktywny a wiec muzyka jest juz odtwarzana
    if ExitCode <> STILL_ACTIVE then //jezeli nie to tworzymy watek w ktorym jest otwarzana muzyka
    begin
      fPlaySoundThread:= TPlaySoundThread.Create(True);
      fPlayThreadHandle:= fPlaySoundThread.Handle;
      fPlaySoundThread.Resume;
    end;
  end;
end;

end.
0

Skrypt wygląda dość fajnie, ale tamten był nieco na innej zasadzie.
W const miał ustawiony adres programu + pod implementation były funkcje czytające, dlatego też było to robione tak:

Listbox2.Items.Add(MemReadString(msg1));

Tutaj nie rozumiem pewien rzeczy, a mianowicie: fOnListBoxSetString o co z tym chodzi ?

dodanie znacznika <code class="delphi"> - furious programming

1

To wywołuje zdarzenie OnListBoxSetString dodane do ListBox czyli w konsekwencji procedurę procedure TForm1.OnListBoxSetString(Sender: TObject; Index: Integer; Value: string); a skoro masz ListBox2 to wszystkie ListBox1 musisz zmienić na ListBox2 a pozycje do listy dodajesz tak jak dodawałeś czyli może być Listbox2.Items.Add(MemReadString(msg1));.

0

Niestety choćbym nie wiem gdzie umieścił Listbox1.Items.Add(MemReadString(msg1)); to mi to nie trybi xd

0

Widocznie coś zrobiłeś nie tak ale na to musiałbym widzieć kod co tam porobiłeś.

0

Kod ogólnie zmianie nie uległ, gdyż zrobiłem nowy projekt tak jakby na brudno..Dodałem tylko do const jeden address wysniffowany przez cheat engine, oraz funkcje czytania. po prostu :) jedno nad implementation, drugie pod.. reszta kodu to samo. Gdzie powinienem w takim razie wrzucić to o czym mówiłem ?

0

http://wklej.org/id/1312730/

tak jak mówiłem, nic się nie zmieniło praktycznie xd ciągle mi działa tylko i wyłącznie timer..

0

Ech wywal Listbox1.Items.Add(MemReadString(msg1));z OnListBoxSetString a w tym timerze co dodajesz to dodajesz do ListBox2 a na zdarzenie OnListBoxSetString ma reagować ListBox1 bo masz ListBox1.OnListBoxSetString:= OnListBoxSetString; więc jak ma działać?

0

Do listbox specjalnie to dodawałem tak, żeby to było jakby osobno ; P Przecież była mowa, że bez timera da radę to zrobić...

Moglbys mi to jakos bardziej wyjasnic ? ; / Sorry ze brak polskich znakow, ale w szkole siedze, a mieszkam za granica.

0

Mógłby mi ktoś z tym pomóc? Nie wiem gdzie tam dodać Listbox1.Items.Add(MemReadString(msg1)); by to działało..

Robiłem już dosłownie wszystko np:

procedure TListBox.ListBoxAddString(var Msg: TMessage);
var
  s: string;
  m:string;
begin
  inherited;
  m := (MemReadString(msg1));
  s:= PChar(Msg.LParam);
  if Assigned(fOnListBoxSetString) then
    fOnListBoxSetString(Self, Self.Items.Count - 1, s);
end;

procedure TListBox.ListBoxInsertString(var Msg: TMessage);
var
  s: string;
  m:string;
begin
  inherited;
  s:= PChar(Msg.LParam);
  m:= (MemReadString(msg1));
  if Assigned(fOnListBoxSetString) then
    fOnListBoxSetString(Self, Msg.WParam, s);
end;

Dosłownie nie chce działać. Może coś nie tak z kodem..

zamiana znacznika <quote> na <code class="delphi"> - furious programming

1

Przede wszystkim powinieneś wziąć się za ogarnięcie podstaw. A dopiero później pisać coś, co współpracuje z Cheat Engine tak jak chcesz. Poza tym kod funkcji odczytującej string z pamięci podchodzi mi pod gimbusiarską tibie. Nie lepiej dodać obsługę błedów i zrobić to na przykład tak dla konkretnego PID'u, a nie klasy czy tytułu okna?

function MemReadString(ProcessId, Address : DWORD) : string;
var
  I : Integer;
  NB : longword;
  HProcess : Cardinal;
  Temp : array[1..MAX_PATH] of Byte;
begin
  Result := '';
  HProcess := OpenProcess(PROCESS_ALL_ACCESS, False, ProcessId);
  if HProcess > 0 then
  begin
    ReadProcessMemory(HProcess, Ptr(Address), @Temp[1], Length(Temp), NB);
    CloseHandle(HProcess);
    for I := Low(Temp) to High(Temp) do
    begin
      if (Temp[I] < 32) then
      begin
        Break;
      end;
      Result := Result + Chr(Temp[i]);
    end;
  end;
end;

Poza tym Cheat Engine ma otwarty kod, więc lepiej jego sobie pomodyfikować, a nie męczyć się w odczytywanie procesu. Poza tym pytałeś jak wykryć dodawanie do ListBox'a i to kod, który podał @kAzek robi to doskonale. Sprawdziłem. Poniżej masz działający kod z dodanym tylko jednym buttonem dla testów. Natomiast samo czytanie z procesu Cheat Engine robić powinieneś spróbować zrobić według mnie w wątku. Może być z użyciem klasy TThread. Przykład użycia już podał Ci @kAzek ewentualnie sobie pogooglouj za przykładami i informacjami o wątkach. Ewentualnie można to zrobić w WinAPI z użyciem funkcji CreateThread. A błąd w kodzie, który wkleiłeś polegal na tym, że zapętlił się on, bo bez sensu wywoływałeś go w kółko z samego z siebie i stąd błąd Stack overflow.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, MMSystem;

type
  TListBoxSetString = procedure(Sender : TObject; Index : Integer; Value : string) of object;
  TListBox = class(StdCtrls.TListBox)
  private
    fOnListBoxSetString : TListBoxSetString;
  protected
    procedure ListBoxAddString(var Msg : TMessage); message LB_ADDSTRING;
    procedure ListBoxInsertString(var Msg : TMessage); message LB_INSERTSTRING;
  public
    property OnListBoxSetString : TListBoxSetString read fOnListBoxSetString
      write fOnListBoxSetString;
  end;

  TPlaySoundThread = class(TThread)
  protected
    procedure Execute; override;
  public
    destructor Destroy; override;
  end;

type
  TForm1 = class(TForm)
    Edit1 : TEdit;
    ListBox1 : TListBox;
    ListBox2 : TListBox;
    Button1 : TButton;
    procedure FormCreate(Sender : TObject);
    procedure Button1Click(Sender : TObject);
  private
    fPlaySoundThread : TPlaySoundThread;
    fPlayThreadHandle : Cardinal;
    procedure OnListBoxSetString(Sender : TObject; Index : Integer; Value : string);
  public
  end;

var
  Form1 : TForm1;

implementation

{$R *.dfm}

procedure TListBox.ListBoxAddString(var Msg : TMessage);
var
  s : string;
begin
  inherited;
  s := PChar(Msg.LParam);
  if Assigned(fOnListBoxSetString) then
    fOnListBoxSetString(Self, Self.Items.Count - 1, s);
end;

procedure TListBox.ListBoxInsertString(var Msg : TMessage);
var
  s : string;
begin
  inherited;
  s := PChar(Msg.LParam);
  if Assigned(fOnListBoxSetString) then
    fOnListBoxSetString(Self, Msg.WParam, s);
end;

procedure TPlaySoundThread.Execute;
begin
  FreeOnTerminate := True;
  PlaySound('alarm.wav', 0, SND_FILENAME);
end;

destructor TPlaySoundThread.Destroy;
begin
  PlaySound(nil, 0, 0);
  inherited;
end;

procedure TForm1.FormCreate(Sender : TObject);
begin
  ListBox1.OnListBoxSetString := OnListBoxSetString;
end;

procedure TForm1.OnListBoxSetString(Sender : TObject; Index : Integer; Value : string);
var
  ExitCode : Cardinal;
begin
  if Edit1.text = Value then
  begin
    GetExitCodeThread(fPlayThreadHandle, ExitCode);
    if ExitCode <> STILL_ACTIVE then
    begin
      fPlaySoundThread := TPlaySoundThread.Create(True);
      fPlayThreadHandle := fPlaySoundThread.Handle;
      fPlaySoundThread.Resume;
    end;
  end;
end;

procedure TForm1.Button1Click(Sender : TObject);
begin
  ListBox1.Items.Add('Test');
end;

Czyli podsumowując. Pomoc i kod, które zaoferował @kAzek pomagają ładnie wykryć zmiany w ListBoxie i wystąpienie jako dodanego lub wstawionego elementu tego z treścią podaną w Edit1. Do tego nie potrzeba wcale jak widzisz Timer'a. Natomiast wykrywanie zmian w procesie Cheat Engine zrób po swojemu. Chociaż jak wspomniałem, zrobił bym to raczej w wątku w pętli while not Terminated do, a nie Timerze.

Chociaż to trochę zabawa "na około". Ponieważ jak pisałem skoro Cheat Engine ma własny kod źródlowy (starsze wersje jaką częściej używam jak 5.6 ma go w Delphi, a nowsze o ile wiem są pisane i kompilowane pod datmowym Lazarusem). To nic nie stoi na przeszkodzie dodać to, co potrzeba do kodu źródlowego operaując na jego kopii. I sobie to przekompilować.

0

Dzięki że zadałeś Sobie tyle trudu by to sprawdzić i tak się rozpisać :)
Za podstawy się zacząłem właśnie brać.

Wracając do tematu. Teoretycznie to z tego tekstu wnioskuję to, że naciskając na button1 w listboxie1 pojawi się tekst o nazwie Test. Skoro alarm reaguje (podobno) na rzecz, która znajduje się w tym listboxie to po wpisaniu w Edit1 Test powinien zawyć alarm. Niestety tak się nie dzieje ; ] Jesteś pewien, że Tobie alarm się odtworzył?

Z tego co widzę (właśnie przez ten nie działający alarm) to po prostu wklikałeś do buttona Listbox1.Items.Add('Testt'). W jakim celu ?/

@Nadal nie widzę, że da się to zrobić bez timera. Co to za atrakcja naciskać na button by dodać tekst ; p
Równie dobrze mogłem na button dodać Listbox1.Items.Add(memreadstring(msg1); ale i tak co z tego, skoro ten alarm się nie załącza ; <

0

@DroniC, problem polega na tym że nie znając podstaw podstaw nie jesteś w stanie nawet wytłumaczyć to czego chcesz, ponieważ jak już pisałem rozmawiamy na innych językach.

Jak chcesz aby reagowało na zmianę w Edit1 to już dostałeś wcześniej rozwiązanie, w Edit1Change dajesz:

  if ListBox1.Items.IndexOf(edit1.text)>=0 then testsound();

gdzie testsound() to zawartość if ExitCode <> STILL_ACTIVE then z kodu wyżej.

0

@DroniC: jestem pewien, że u mnie zadziałalo. Button został dodany dla testów. Jeżeli dodamy do ListBox'a jakiś tekst. To, jeżeli mamy go wpisanego w Edit1 (ważna jest również wielkośc znaków oczywiście). To usłyszymy dźwięk, pod warunkiem, że plik alarm.wav istnieje w podaktalogu z exekiem naszej aplikacji. Tak to zdaje się miało działać. Jeżeli nie to może najlepiej weź wytłumacz jak to ma działać. Bo tego co pisałeś, to właśnie tak działa jak można było zrozumieć z Twojego opisu.

I nie ma co podchodzić do tego tak, że "zabieram się za podstawy". Tylko najpierw je ogarniasz. Kombinujesz zawsze SAM - aż "do bólu". W razie problemów googlując za rozwiązaniem, ile się da. A pisanie na jakiekolwiek forum z pytaniem, traktujesz jako na prawdę ostateczność. I tutaj na ogół pomagamy naprowadzić na rozwiązanie, ale @kAzek był tak dobry, że zapodał gotowca. Jednak Ty nie chcesz umieć z niego skorzystać, ani zrozumieć tego kodu, bo nie chcesz poswięcić czas na ogarnięcie podstaw. Oczywiscie już dawno to powinieneś zrobić. Wtedy bierz się za próby stworzenia jakiegoś zaawansowanego programu.

0

Nie możliwe że to działa :) Jutro nawet Ci nagram filmik koło 18/19 wrzucę jak wrócę do domu ; ) Mam alarm w katalogu z programem i wszystko powinno być git z tego co mówisz.
Nawet dodałem, żeby dodało do listboxa zawartość edit1, czyli automatycznie to dodając powinien być alarm, a tu co? Cichosza...

Sprawdź kod. Wgl. nie jest zmieniony.
http://wklej.org/id/1313661/

Nie możliwe że to u Ciebie działa,a u mnie nie. Bądź łaskaw się temu przyjżeć jeszcze raz. Dodaje mi item do listboxu, ale alarmu nie ma ; /

1

Podejrzewam że poprzez brak podstaw podstaw nawet nie zajarzyłeś że należy podłączyć metodę procedure TForm1.FormCreate(Sender : TObject); pod zdarzenie formatki OnCreate.

Podejrzewam że bardziej chodziło ci o takie coś:

unit Unit1;

interface uses
  Windows,
  Messages,
  SysUtils,
  Classes,
  Graphics,
  Controls,
  Forms,
  Dialogs,
  StdCtrls,
  MMSystem;

type
  TPlaySoundThread = class(TThread)
  protected
    procedure Execute; override;
  end;

  TForm1 = class(TForm)
    Edit1 : TEdit;
    ListBox1 : TListBox;
    Button1: TButton;
    procedure Button1Click(Sender : TObject);
    procedure Edit1Change(Sender: TObject);
  private
    fPlaySoundThread:TPlaySoundThread;
    fPlayThreadHandle:Cardinal;
  public
  end;

var
  Form1 : TForm1;

implementation

{$R *.dfm}

procedure TPlaySoundThread.Execute;
begin
  FreeOnTerminate:=True;
  PlaySound('alarm.wav',0,SND_FILENAME);
end;

procedure TForm1.Button1Click(Sender : TObject);
begin
  if ListBox1.Items.IndexOf(Edit1.Text)<0 then Listbox1.Items.Add(Edit1.Text);
end;

procedure TForm1.Edit1Change(Sender: TObject);
var ExitCode:Cardinal;
begin
  if ListBox1.Items.IndexOf(Edit1.Text)>=0 then
  begin
    GetExitCodeThread(fPlayThreadHandle,ExitCode);
    if ExitCode<>STILL_ACTIVE then
    begin
      fPlaySoundThread:=TPlaySoundThread.Create(True);
      fPlayThreadHandle:=fPlaySoundThread.Handle;
      fPlaySoundThread.Resume;
    end;
  end;
end;

end.

z tym że podejrzewam że nie dasz rady podłączyć zdarzenia OnChange dla Edit1

1

Zamiast nagrywać mi filmik to byś ogarnąl podstawy. Kod na 100% działa, jeżeli rozumiemy co chcesz zrobić. Jeżeli Tobie nie działa to jedna z trzech przyczyn:

  1. Nie masz prawidłowo działającej karty dźwiękowej lub wyciszone głośniki/słuchawki.
  2. Brakuje pliku o nazwie alarm.wav w tym samym katalogu co exek programu.
  3. Plik alarm.wav jest pustym dźwiękiem lub tak ściszonym, że go nie słychać.
  4. Najbardziej prawopodobne: nie dodałeś u siebie metody OnCreate Formatki.

Ogarnij się. Zobacz przykład w załączniku. Wpisz w pole edycyjne Test i kliknij button. Dźwiek sie odtworzy. Wpisz coś innego i się nie odtworzy. A i jeżeli chcesz być traktowany tutaj poważnie. Bez względu na swój wiek. To nie stosuj w tematach, które ja lub większośc tutaj może przeczytać, "składni gimbus++". Czyli wszelkie kaleczące nasz język debilne skróty w stylu wgl/cb/sb/ocb. Osobiście widząc takie coś mam ochotę odciąć Cię od Internetu :/ To nie forum gimbaza.web. Na koniec jeszcze raz powtórze. Ogarnij najpierw podstawy. Dopiero wtedy bierz się za programownie czegokolwiek. Uwierz mi to dobra rada.

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