ループ中のプログラム実行中に終了するとエラー

解決


武田  2009-04-07 20:36:07  No: 33951

皆様よろしくお願いします。winXP  Delphi6  Personalです。
いま、音楽ファイルをListboxにフルパスでセットし順番に再生する
プログラムを作成していますが、曲が終わって次の曲にチェンジするのに
WindowsMediaPlayer1PlayStateChangeの終了イベントを使用しているため
ループで待たせています。
途中で画面右上の終了×ボタンで終了すると「Access violation at addressエラー」
がでます。いろいろやってみましたが解決できません。
関係すると思われる部分のコードを少し長くなりますが書いてみます。
Pagecontrolに動的にWindowsMediaPlayer1を貼り付けて終わったら破棄します。
FormにListboxとPagecontrolを貼り付けています。
とんでもないことをやっているから怒られるのですがよろしくお願いします。
type
  TTabSheetEx = class(TTabSheet)
  public
    WindowsMediaPlayer1: TWindowsMediaPlayer;
    destructor Destroy; override;
  end;
TForm1 = class(TForm)
・・・
var
  PlayListNo:integer;  //現在再生中のプレイリスト番号
  PlayMode:Boolean;//再生中のファイルが終了したイベント受け取り
  MovieStopFlag:Boolean;  //プレイの終了命令
・・・・
destructor TTabSheetEx.Destroy;  // TabsheetExの破棄同時にブラウザの破棄
begin
    WindowsMediaPlayer1.Free;
    inherited;
end;
・・・・
//動的にタブを作成しWindowsMediaPlayer1を貼り付ける
function TForm1.TabSheetCreate(Category,Title:string):Boolean;
var
    TabSheetEx: TTabSheetEx;
begin
    Tmode:=Category;
    TabSheetEx :=  TTabSheetEx.Create(Form1.PageControl1);
    TabSheetEx.Parent       := Form1.PageControl1;
    TabSheetEx.PageControl  := Form1.PageControl1;
    TabSheetEx.Caption:=Title;
    Form1.PageControl1.ActivePage := TTabSheet(TabSheetEx);
    with (PageControl1.ActivePage as TTabSheetEx) do
    begin
        WindowsMediaPlayer1:= TWindowsMediaPlayer.Create(self);
        WindowsMediaPlayer1.Align:=alClient;
        WindowsMediaPlayer1.Parent:=self;
        WindowsMediaPlayer1.OnPlayStateChange
        := Form1.WindowsMediaPlayer1PlayStateChange;
    end;
    result:=true;
end;
//Listboxのアイテムをダブルクリックして開始する
procedure TForm1.ListBox1DblClick(Sender: TObject);
begin
    PlayListNo:=ListBox1.ItemIndex;
    if TabSheetCreate(tMOVI,'マルチプレイヤー')=false then exit;
    MoviePlay
end;
//再生終了のイベント発生したらカウントアップし、falseにしてループを抜ける
procedure TForm1.WindowsMediaPlayer1PlayStateChange(Sender: TObject; NewState: Integer);
begin
    if (NewState = wmppsMediaEnded)  then
    begin Inc(PlayListNo);PlayMode:=false;end;
end;
//プレイヤー。途中でループして曲が終わるのを待つ、曲が無くなるまで繰り返す
procedure TForm1.MoviePlay;
begin
    MovieStopFlag:=false;
  while (PlayListNo <  ListBox1.Items.Count) do//曲が最後になるまで
  begin
        with (PageControl1.ActivePage as TTabSheetEx) do
        begin
        WindowsMediaPlayer1.controls.stop;
        WindowsMediaPlayer1.currentPlaylist.clear;
        WindowsMediaPlayer1.URL:=ListBox1.Items.Strings[PlayListNo];
        WindowsMediaPlayer1.controls.play;
        end;
        PlayMode:=true;
        //--------------------曲が終わってMediaEndedイベントでループを抜ける
        while PlayMode do
        begin
            if MovieStopFlag=true then exit;
            Application.ProcessMessages;
            Sleep(20);
        end;
        if MovieStopFlag=true then break;
    end;
    PlayMode:=false;
    MovieStopFlag:=true;
end;
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var i:integer;
begin
    MaltiMediaPlay:=true;//一応強制終了したつもり
    PlayMode:=false;
    for i:=PageControl1.PageCount-1 downto 0 do//タブの削除
        TTabSheetEx(Form1.PageControl1.Pages[i]).Free;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
    PageControl1.Free;//破棄する
end;


つもりだけで  2009-04-07 21:40:20  No: 33952

>    MaltiMediaPlay:=true;//一応強制終了したつもり
終了してないんでないの?


Manbon  2009-04-07 21:54:58  No: 33953

タブを削除する前に
WindowsMediaPlayer1.Free;
がいるのでは?

あと、ループで待つのではなくて、
WindowsMediaPlayer1PlayStateChange
で次の曲に進むようにしたほうがいいような・・・。


D  2009-04-07 22:50:02  No: 33954

トレース実行やステップ実行を利用すればどこでエラーになるかが分かるかと思います。

WindowsMediaPlayerをFreeするときにPlayModeをFalseにしていますよね。
このときMoviePlayのループは回っている状態です。
で、PlayModeはFalseなので二重ループのうちの内側からは抜けます。
でも外側のループは抜けません。
その結果FreeしたWindowsMediaPlayerをstopさせようとするでエラーが起きます。


武田  2009-04-08 08:08:26  No: 33955

皆さん有り難うございます。
ループを抜ける方法を考えてみます。
有り難うございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加