CCM*_*CCM 5 delphi media-player
我是一名新手程序员,如果这对你们所有人来说听起来非常基本,那么道歉.我有一个程序看起来(基本上)像这样:
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
panel1.caption:='This is a sentence';
with MediaPlayer1 do
begin
filename:='f:\untitled.wma';
open;
wait:=true;
play;
close;
end;
end;
Run Code Online (Sandbox Code Playgroud)
问题是,panel1直到媒体播放器播放声音文件时,标题才会改变; 我需要改变标题,让玩家同时开始玩.我怎样才能确保这一点?
我认为该过程将按顺序执行每行代码,这意味着panel1更改的标题,然后媒体播放器开始行动.我哪里出错了?
qua*_*oft 10
VCL组件(例如TPanel)通常有一个调用的内部方法Invalidate(),当属性(如Caption)更改时调用该方法,并且该更改需要重新绘制控件的一部分(例如,绘制新的标题文本).
此方法仅在窗口控件内设置一个标志,但不调用重绘方法本身.这样做的原因是Repaint(),如果一次更改许多属性(顺序,在短时间内),则避免多次调用该方法.
Repaint()当组件通过主消息循环(从应用程序的主线程 - GUI线程处理)接收要重新绘制的消息时,实际调用该方法.
您开始播放媒体播放器的方式是阻止,因为您将Wait属性设置为True,这会使播放器阻止调用线程(再次是主线程),直到文件播放完毕.
这不会给主线程处理它的消息队列并启动重绘的机会.
快速解决问题的方法是becsystems建议的那个,或者这个:
panel1.Caption := 'This is a sentence';
Application.ProcessMessages();
Run Code Online (Sandbox Code Playgroud)
ProcessMessages()在开始播放文件之前,调用将使主线程有机会处理消息队列并执行更新.
这是一个快速修复,因为主线程在开始播放后仍然会被阻止,这将阻止窗口的其他部分重新绘制(例如,尝试移动窗口或在播放时最小化并最大化它).
becsystems建议的代码类似,但不是处理消息队列,只是强制控件重绘.
要正确解决问题,您不应使用该Wait属性,而是处理OnNotify媒体播放器的事件.
这是一个例子,改编自Swiss Delphi Center(未测试,因为我目前没有安装Delphi):
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
panel1.Caption := 'This is a sentence';
with MediaPlayer1 do
begin
Notify := True;
OnNotify := NotifyProc;
Filename := 'f:\untitled.wma';
Open;
Play;
end;
end;
procedure TForm1.NotifyProc(Sender: TObject);
begin
with Sender as TMediaPlayer do
begin
case Mode of
mpStopped: {do something here};
end;
// Set to true to enable next-time notification
Notify := True;
end;
end;
Run Code Online (Sandbox Code Playgroud)
这里发布的VCL消息循环(Delphi Developer's Guide的一部分)有一个简短的解释:
另外,与问题无关,但请看一下Delphi编码风格指南.当代码发布格式化时,这很好.
Refresh设置标题后添加调用,即:
panel1.caption:='This is a sentence';
Refresh;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
136 次 |
| 最近记录: |