匪
匪匪
Unregistered / Unconfirmed
GUEST, unregistred user!
程序主要表现形式:播放一首MP3音乐,同时将标签进行变色处理
因为播放规则会不一样,比如A句播放一遍,再停100ms,B句播放两遍,再停10ms,所以我将这些规则全部放入一个Tlist中预先存起来。然后在一个线程中,从这个TList中取出操作,解析后,再运行。可能有人会说你干嘛一定要用线程来画界面呢,我是没办法的办法,目前是这样子做的,如果有更好的方法,也无法改了,只能用线程实现了。
现在程序的问题是:当播放一首音乐的时候(同时标签正在变色过程中),我点击另一句C,同时开始播放C句对应的音乐,当点击过快时,以前一句的色彩来不及清除。具体代码如下:
procedure TChThread.Execute;
begin
try
Coinitialize(nil);
while not Terminateddo
begin
WaitForSingleObject(EventHandle, INFINITE);
ResetEvent(EventHandle);
if not Box.FStopAction then
begin
Sleep(0);
Action; //真正执行的代码在此
Sleep(0);
end;
if Terminated then
begin
Box.PressStop := True;
Box.FStopAction := True;
Break;
end;
end;
//等待主线程激活该事件
WaitForSingleObject(CloseEvent, THREADWAITTIME);
//线程执行完毕后,激活终止事件
SetEvent(WaitEvent);
finally
CoUninitialize;
end;
end;
--------------------------------------
procedure TChThread.Action;
begin
Box.ThreadAction;//这里是运行控件中的一个函数。
end;
---------------------------------------
procedure TCBox.ThreadAction;
var
i: Integer;
begin
//依据操作记录队列,从中取出相关的操作记录,并依据操作类型,生成不同的操作
for i:= 0 to ActionList.Count - 1do
begin
if not FStopAction then
begin
case pRecordAction(ActionList.Items)^.aStyle of
aPlay: Play(pPlayAction(ActionList.Items));
aPause: Pause(pPauseAction(ActionList.Items));
end;
end;
end;
end;
---------------------------------------
procedure TCBox.Play(action: pPlayAction);
var
i,j: Integer;
ObjectList: TList;
AudioName: string;
begin
if action^.aStyle = aPlay then
begin
ObjectList:= nil;
//找到相关控件组(句子与图片可能有几个对应的)
FoundContrl(action^.oStyle, action^.Id, ObjectList);
if (Assigned(ObjectList)) and (ObjectList.Count >0) then
begin
AudioName:= '';
AudioName:= XML.GetAudio(action^.oStyle, Action^.Id);
if AudioName <> '' then
begin
for i:= 0 to action^.Num - 1do
if FStopAction then
begin
//MediaPlay.Stop;
Break;
end
else
ChangeColor(ObjectList, AudioName);//标签变色的代码就在此中
end;
end;
end;
end;
--------------------------------------
//-------------------------变色----------------------------//
//函数功能: //
// 以句为单位变色,同时播放该句对应的音乐 //
//---------------------------------------------------------//
procedure TCBox.ChangeColor(lObjectList: TList;
AudioName: string);
var
i: Integer;
strAudioName: string;
SI: TScrollInfo;
begin
strAudioName:= FAudioPath + AudioName;
ChangeColorLength := 0;
//判断是否需要滚动条下移
SI.cbSize := SizeOf(TScrollInfo);
SI.fMask := SIF_ALL;
GetScrollInfo(Self.Handle, SB_VERT, SI);
if TLabel(pPraseObject(lObjectList.Items[0])^.oRecord).Top + SI.nPos +
TLabel(pPraseObject(lObjectList.Items[0])^.oRecord).Height >= SI.nPage + SI.nPos then
begin
SetScrollPositon(True);
end;
Mp3(strAudioName);
if IsChangeColor then
begin
//字体组变成红色
for i:= 0 to lObjectList.Count - 1do
if TLabel(pPraseObject(lObjectList.Items)^.oRecord).Visible then
begin
TLabel(pPraseObject(lObjectList.Items)^.oRecord).Font.Color:= clRed;
end;
Step := GetLabelStep;
mp3MinLeft := mp3Time;
mp3Start := GetTickCount;
//字体变色,从lObjectList中第一个元素开始,循环变色
mp3Pause := False;
try
for i:= 0 to lObjectList.Count - 1do
if TLabel(pPraseObject(lObjectList.Items)^.oRecord).Visible then
begin
if (not FStopAction) then
begin
ChangeLabelColor(TLabel(pPraseObject(lObjectList.Items)^.oRecord));
TLabel(pPraseObject(lObjectList.Items)^.oRecord).Font.Color := clBlack;
end;
end;
except
StopMultimedia('Hjj');
CloseMultimedia('Hjj');
end;
//还原色彩为黑色
if (not FStopAction) then
if Assigned(lObjectList) then
begin
for i:= 0 to lObjectList.Count - 1do
if TLabel(pPraseObject(lObjectList.Items)^.oRecord).Visible then
begin
TLabel(pPraseObject(lObjectList.Items)^.oRecord).Font.Color:= clBlack;
end;
end;
end;
if not FStopAction then
Sleep(mp3SleepTime + 20);
StopMultimedia('Hjj');
CloseMultimedia('Hjj');
end;
上面的函数不说大家也知道了,变色效果跟卡拉OK一样,先是对应的句子变成红色,然后随着音乐的播放,前面的变成蓝色,至到所有的都变成蓝色,最后全部句子变成黑色,可是我的代码在随机快速的点击后,有时候蓝色没有清除。
-----------------------------------
该函数是对具体的某一个标签进行变色处理。包括了计算变色步进的进度值。
procedure TCBox.ChangeLabelColor(Labe: TLabel);
var
i, Height, Width, j: Integer;
rRect: TRect;
a1, a2: Integer;
strText: string;
FontName: TFontName;
FontStyle: TFontStyles;
FontSize: Integer;
Num: Integer;
//单词个数
ATime: Integer;
//每字符平均时间(ms)
TmpLabel: TLabel;
begin
try
try
strText := Labe.Caption;
Num := Length(strText);
FontName := Labe.Font.Name;
FontStyle := Labe.Font.Style;
FontSize := Labe.Font.Size;
Height:= Labe.Canvas.TextHeight(Caption);
Width:= Labe.Canvas.TextWidth(Trim(Caption));
//构造临时标签,求出每字符的长度
TmpLabel := TLabel.Create(Self);
TmpLabel.Font.Size := FontSize;
TmpLabel.Font.Style := FontStyle;
TmpLabel.Font.Name := FontName;
ATime := mp3Time div Num;
mp3SleepTime := mp3Time mod Num;
with Labedo
begin
i:= 0;
j:= 0;
//每次重画的长度
while (i <= Num)do
begin
TmpLabel.Caption := strText;
j := j + TmpLabel.Width;
if not FStopAction then
begin
//如果最后剩下的时间少于10ms,则一次性步进完毕
a1:= GetTickCount;
if (mp3Time - (a1 - mp3Start) <=2) and (mp3Time - (a1 - mp3Start) >0)then
begin
Canvas.Brush.Style:= bsClear;
Canvas.Font.Color:= clBlue;
rRect:= Rect(0, 0, Width, Height);
Canvas.Lock;
Canvas.TextRect(rRect, 0, 0, Caption);
Canvas.Unlock;
Break;
end
else
if (mp3Time - (a1 - mp3Start) > 2) then
begin
Canvas.Brush.Style:= bsClear;
Canvas.Font.Color:= clBlue;
rRect:= Rect(0, 0, j, Height);
Sleep(ATime);
Canvas.Lock;
Canvas.TextRect(rRect, 0, 0, Caption);
Canvas.Unlock;
end
else
Break;
i := i + 1;
end
else
begin
mp3Pause := True;
//代表人为结束
Break;
end;
end;
end;
except
TmpLabel.Free;
end;
finally
TmpLabel.Free;
end;
end;
希望高手来帮我解决此问题,只要问题能解决,可以再开300分的帖。
因为播放规则会不一样,比如A句播放一遍,再停100ms,B句播放两遍,再停10ms,所以我将这些规则全部放入一个Tlist中预先存起来。然后在一个线程中,从这个TList中取出操作,解析后,再运行。可能有人会说你干嘛一定要用线程来画界面呢,我是没办法的办法,目前是这样子做的,如果有更好的方法,也无法改了,只能用线程实现了。
现在程序的问题是:当播放一首音乐的时候(同时标签正在变色过程中),我点击另一句C,同时开始播放C句对应的音乐,当点击过快时,以前一句的色彩来不及清除。具体代码如下:
procedure TChThread.Execute;
begin
try
Coinitialize(nil);
while not Terminateddo
begin
WaitForSingleObject(EventHandle, INFINITE);
ResetEvent(EventHandle);
if not Box.FStopAction then
begin
Sleep(0);
Action; //真正执行的代码在此
Sleep(0);
end;
if Terminated then
begin
Box.PressStop := True;
Box.FStopAction := True;
Break;
end;
end;
//等待主线程激活该事件
WaitForSingleObject(CloseEvent, THREADWAITTIME);
//线程执行完毕后,激活终止事件
SetEvent(WaitEvent);
finally
CoUninitialize;
end;
end;
--------------------------------------
procedure TChThread.Action;
begin
Box.ThreadAction;//这里是运行控件中的一个函数。
end;
---------------------------------------
procedure TCBox.ThreadAction;
var
i: Integer;
begin
//依据操作记录队列,从中取出相关的操作记录,并依据操作类型,生成不同的操作
for i:= 0 to ActionList.Count - 1do
begin
if not FStopAction then
begin
case pRecordAction(ActionList.Items)^.aStyle of
aPlay: Play(pPlayAction(ActionList.Items));
aPause: Pause(pPauseAction(ActionList.Items));
end;
end;
end;
end;
---------------------------------------
procedure TCBox.Play(action: pPlayAction);
var
i,j: Integer;
ObjectList: TList;
AudioName: string;
begin
if action^.aStyle = aPlay then
begin
ObjectList:= nil;
//找到相关控件组(句子与图片可能有几个对应的)
FoundContrl(action^.oStyle, action^.Id, ObjectList);
if (Assigned(ObjectList)) and (ObjectList.Count >0) then
begin
AudioName:= '';
AudioName:= XML.GetAudio(action^.oStyle, Action^.Id);
if AudioName <> '' then
begin
for i:= 0 to action^.Num - 1do
if FStopAction then
begin
//MediaPlay.Stop;
Break;
end
else
ChangeColor(ObjectList, AudioName);//标签变色的代码就在此中
end;
end;
end;
end;
--------------------------------------
//-------------------------变色----------------------------//
//函数功能: //
// 以句为单位变色,同时播放该句对应的音乐 //
//---------------------------------------------------------//
procedure TCBox.ChangeColor(lObjectList: TList;
AudioName: string);
var
i: Integer;
strAudioName: string;
SI: TScrollInfo;
begin
strAudioName:= FAudioPath + AudioName;
ChangeColorLength := 0;
//判断是否需要滚动条下移
SI.cbSize := SizeOf(TScrollInfo);
SI.fMask := SIF_ALL;
GetScrollInfo(Self.Handle, SB_VERT, SI);
if TLabel(pPraseObject(lObjectList.Items[0])^.oRecord).Top + SI.nPos +
TLabel(pPraseObject(lObjectList.Items[0])^.oRecord).Height >= SI.nPage + SI.nPos then
begin
SetScrollPositon(True);
end;
Mp3(strAudioName);
if IsChangeColor then
begin
//字体组变成红色
for i:= 0 to lObjectList.Count - 1do
if TLabel(pPraseObject(lObjectList.Items)^.oRecord).Visible then
begin
TLabel(pPraseObject(lObjectList.Items)^.oRecord).Font.Color:= clRed;
end;
Step := GetLabelStep;
mp3MinLeft := mp3Time;
mp3Start := GetTickCount;
//字体变色,从lObjectList中第一个元素开始,循环变色
mp3Pause := False;
try
for i:= 0 to lObjectList.Count - 1do
if TLabel(pPraseObject(lObjectList.Items)^.oRecord).Visible then
begin
if (not FStopAction) then
begin
ChangeLabelColor(TLabel(pPraseObject(lObjectList.Items)^.oRecord));
TLabel(pPraseObject(lObjectList.Items)^.oRecord).Font.Color := clBlack;
end;
end;
except
StopMultimedia('Hjj');
CloseMultimedia('Hjj');
end;
//还原色彩为黑色
if (not FStopAction) then
if Assigned(lObjectList) then
begin
for i:= 0 to lObjectList.Count - 1do
if TLabel(pPraseObject(lObjectList.Items)^.oRecord).Visible then
begin
TLabel(pPraseObject(lObjectList.Items)^.oRecord).Font.Color:= clBlack;
end;
end;
end;
if not FStopAction then
Sleep(mp3SleepTime + 20);
StopMultimedia('Hjj');
CloseMultimedia('Hjj');
end;
上面的函数不说大家也知道了,变色效果跟卡拉OK一样,先是对应的句子变成红色,然后随着音乐的播放,前面的变成蓝色,至到所有的都变成蓝色,最后全部句子变成黑色,可是我的代码在随机快速的点击后,有时候蓝色没有清除。
-----------------------------------
该函数是对具体的某一个标签进行变色处理。包括了计算变色步进的进度值。
procedure TCBox.ChangeLabelColor(Labe: TLabel);
var
i, Height, Width, j: Integer;
rRect: TRect;
a1, a2: Integer;
strText: string;
FontName: TFontName;
FontStyle: TFontStyles;
FontSize: Integer;
Num: Integer;
//单词个数
ATime: Integer;
//每字符平均时间(ms)
TmpLabel: TLabel;
begin
try
try
strText := Labe.Caption;
Num := Length(strText);
FontName := Labe.Font.Name;
FontStyle := Labe.Font.Style;
FontSize := Labe.Font.Size;
Height:= Labe.Canvas.TextHeight(Caption);
Width:= Labe.Canvas.TextWidth(Trim(Caption));
//构造临时标签,求出每字符的长度
TmpLabel := TLabel.Create(Self);
TmpLabel.Font.Size := FontSize;
TmpLabel.Font.Style := FontStyle;
TmpLabel.Font.Name := FontName;
ATime := mp3Time div Num;
mp3SleepTime := mp3Time mod Num;
with Labedo
begin
i:= 0;
j:= 0;
//每次重画的长度
while (i <= Num)do
begin
TmpLabel.Caption := strText;
j := j + TmpLabel.Width;
if not FStopAction then
begin
//如果最后剩下的时间少于10ms,则一次性步进完毕
a1:= GetTickCount;
if (mp3Time - (a1 - mp3Start) <=2) and (mp3Time - (a1 - mp3Start) >0)then
begin
Canvas.Brush.Style:= bsClear;
Canvas.Font.Color:= clBlue;
rRect:= Rect(0, 0, Width, Height);
Canvas.Lock;
Canvas.TextRect(rRect, 0, 0, Caption);
Canvas.Unlock;
Break;
end
else
if (mp3Time - (a1 - mp3Start) > 2) then
begin
Canvas.Brush.Style:= bsClear;
Canvas.Font.Color:= clBlue;
rRect:= Rect(0, 0, j, Height);
Sleep(ATime);
Canvas.Lock;
Canvas.TextRect(rRect, 0, 0, Caption);
Canvas.Unlock;
end
else
Break;
i := i + 1;
end
else
begin
mp3Pause := True;
//代表人为结束
Break;
end;
end;
end;
except
TmpLabel.Free;
end;
finally
TmpLabel.Free;
end;
end;
希望高手来帮我解决此问题,只要问题能解决,可以再开300分的帖。