我有一個使用Delphi7編寫的聊天程序。作爲特殊的「效果」,當播放特定的槍聲文件時,我們會顯示一些彈孔。我們通過在彈孔的bmp圖像文件的形狀中繪製一個新的表單,並以幾秒的時間延遲來顯示然後消失。如何在顯示第二個表單時阻止UI鎖定?
但是,所有這些工作,當彈孔圖像在屏幕上時,程序被有效鎖定...當最後一個圖像已經消失時,將焦點返回給用戶。
我的程序員不是真正精通圖形,並認爲這只是你必須付出才能獲得這種效果的代價,但我希望這不是真的......任何關於隨機更好方法的建議在屏幕上顯示彈孔圖像?
我有一個使用Delphi7編寫的聊天程序。作爲特殊的「效果」,當播放特定的槍聲文件時,我們會顯示一些彈孔。我們通過在彈孔的bmp圖像文件的形狀中繪製一個新的表單,並以幾秒的時間延遲來顯示然後消失。如何在顯示第二個表單時阻止UI鎖定?
但是,所有這些工作,當彈孔圖像在屏幕上時,程序被有效鎖定...當最後一個圖像已經消失時,將焦點返回給用戶。
我的程序員不是真正精通圖形,並認爲這只是你必須付出才能獲得這種效果的代價,但我希望這不是真的......任何關於隨機更好方法的建議在屏幕上顯示彈孔圖像?
很難說如果沒有看到代碼,並且確切地知道如何打開/加載第二個窗體,但是聽起來好像你打開它們將會鎖定父窗體,直到模態窗體返回結果爲止。
如果是這種情況,那麼你可以簡單地用Show方法打開它,然後像這樣設置焦點回到主窗體。
procedure TForm1.Button1Click(Sender: TObject);
var obj:TForm2;
begin
obj := TForm2.Create(nil);
try
obj.FormStyle := fsStayOnTop;
obj.show;
Self.SetFocus; //set focus back to the form1
except
FreeAndNil(obj);
end;
end;
上述內容也令人感到意外的是,您在運行時動態創建表單並且第二個表單負責釋放自身。
在窗體上重疊grahics並不是微不足道的,但我認爲這是TCustomTransparentPanel(內存中的名稱)的用途。
但無論如何,它不應該放慢速度或凍結程序。
我相信需要使用SetWinRegion方法在「子彈孔」周圍繪製輪廓。這樣他們可以點擊通過,但洞本身會浮在頂部(只要使用fsStayOnTop的前一個答案)。
即使是閃存圖像也需要某種形式的圖像來充當圖像的容器。這一切都歸結於創建窗口並將圖像噴射到該窗口。它不必「鎖定」屏幕,如果您將其設置爲始終位於頂部並只是「顯示」它(不是ShowModal),它應該出現並浮動。然後我會使用一個計時器來控制它何時被銷燬。 SetWinRegion的優點是,你可以創建一個不規則形狀的窗口,並且用戶不能點擊的窗口將是窗口中包含實際窗體(在區域內)的部分。
感謝大家的回覆......我希望有一種可能的不同方法?像一個單獨的線程或不同的方式來顯示圖像,而不是繪製表單,就像顯示bullethole的閃光圖像或其他東西?建議/意見將是非常讚賞...有我喜歡爾德實現,但不能,如果它要鎖住屏幕..再次感謝大家等功效。這是我第一次使用這一點,這是驚人的你所有人都花費時間和精力來幫助解決這個問題.. Mark Gundy www.magchat.com – MarkGundy 2009-05-04 10:59:25
打開第二個窗體真的不是這樣做的方法。也許圖像控制部分透明的圖像大小隻是比你的彈孔大,你可以放在窗體上的任何地方。如果您無法進行透明控制,則可以拍攝表格的該部分的快照並將彈孔置於頂部。
如果你想動畫淡出,只需更換與在不同的時間不同的人使用定時器在不同的時間
利用這一點,就沒有必要爲另一種形式,和該應用程序保持響應。
下面是一個可行的解決方案。你可能想把擊發過程封裝到一個計時器或其他事件驅動的過程中。
表單定義:
TForm1 = class(TForm)
btnTurnOn: TButton;
ListBox1: TListBox;
btnTurnOff: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnTurnOnClick(Sender: TObject);
procedure btnTurnOffClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
F:TForm;
Bullet:TBitmap;
x,y:integer;
procedure SubFormPaint(Sender: TObject);
end;
代碼:
procedure TForm1.btnTurnOnClick(Sender: TObject);
begin
if F=nil then
begin
F:=TForm.Create(self);
F.Parent:=self;
F.FormStyle:=fsStayOnTop;
F.BorderStyle:=bsNone;
F.Left:=x;
F.Top:=y;
F.Width:=Bullet.Width;
F.Height:=Bullet.Height;
F.OnPaint:=Self.SubFormPaint;
F.Show;
end
else
begin
inc(x,5);
inc(y,5);
F.Left:=x;
F.Top:=y;
F.Invalidate;
end;
end;
procedure TForm1.btnTurnOffClick(Sender: TObject);
begin
F.Free;
F:=nil;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
F:=nil;
Bullet:=TBitmap.Create;
Bullet.LoadFromFile('C:\source\glyfx\glyfx\Emoticon\BMP\16x16\wink_16.bmp');
x:=1;
y:=1;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Bullet.Free;
end;
procedure TForm1.SubFormPaint(Sender: TObject);
begin
if F<>nil then
F.Canvas.Draw(1,1,Bullet);
end;
如果是彈孔的動畫被寫成循環執行,直到完成那麼這可能是問題。如果是這樣,則嘗試在循環的某處插入Application.ProcessMessages
以允許在動畫發生時發生其他事情。
請參閱http://msdn.microsoft.com/en-us/library/dd183353(VS.85).aspx,它有一個很好的API調用alpha調用位圖在一起的示例。對於動畫的每個幀,您可能需要獲取代表主屏幕的圖像的副本,然後在適當的透明度級別上將這些字形與其混合。
如前所述,您可以重複執行Application.ProcessMessages,儘管我更喜歡反向操作並使用PostMessage觸發動畫的下一幀。
您將在循環中使用ProcessMessages,但該調用可能導致其他事情在您處於該循環時發生 - 移動窗口,最小化,關閉或再次觸發動畫事件 - 在第一個動畫完成之前。只要你注意到你並不總是在你的循環範圍內運行,這一切都很好。
因此,我更喜歡讓每個動畫幀都做一個PostMessage來觸發下一幀。它只是幫助我保持透視。
您可能希望重新考慮您的主題標題爲「bullet holes」有點神祕,例如「如何在顯示第二個表單時阻止Delphi鎖定」可能更合適,並且會讓您更好的回覆。 – Re0sless 2009-05-02 16:05:31
我敢打賭,「彈孔」獲得更多的意見。 ;-) – 2009-05-02 16:43:53