2009-05-02 87 views
2

我有一個使用Delphi7編寫的聊天程序。作爲特殊的「效果」,當播放特定的槍聲文件時,我們會顯示一些彈孔。我們通過在彈孔的bmp圖像文件的形狀中繪製一個新的表單,並以幾秒的時間延遲來顯示然後消失。如何在顯示第二個表單時阻止UI鎖定?

但是,所有這些工作,當彈孔圖像在屏幕上時,程序被有效鎖定...當最後一個圖像已經消失時,將焦點返回給用戶。

我的程序員不是真正精通圖形,並認爲這只是你必須付出才能獲得這種效果的代價,但我希望這不是真的......任何關於隨機更好方法的建議在屏幕上顯示彈孔圖像?

+1

您可能希望重新考慮您的主題標題爲「bullet holes」有點神祕,例如「如何在顯示第二個表單時阻止Delphi鎖定」可能更合適,並且會讓您更好的回覆。 – Re0sless 2009-05-02 16:05:31

+8

我敢打賭,「彈孔」獲得更多的意見。 ;-) – 2009-05-02 16:43:53

回答

3

很難說如果沒有看到代碼,並且確切地知道如何打開/加載第二個窗體,但是聽起來好像你打開它們將會鎖定父窗體,直到模態窗體返回結果爲止。

如果是這種情況,那麼你可以簡單地用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; 

上述內容也令人感到意外的是,您在運行時動態創建表單並且第二個表單負責釋放自身。

+0

我還沒有嘗試過這種方法,但是Form1最終不會被這種方法隱藏嗎? – Argalatyr 2009-05-02 16:28:45

+1

如果您將其設置爲始終位於頂部,則不是。 (不知道D7是否可以這樣做,但後來的版本可以。) – 2009-05-02 16:32:09

+0

+1然後,有人(ReOsless或具有高代表性的人)應該使用該屬性設置編輯代碼。 – Argalatyr 2009-05-02 16:56:42

2

在窗體上重疊grahics並不是微不足道的,但我認爲這是TCustomTransparentPanel(內存中的名稱)的用途。

但無論如何,它不應該放慢速度或凍結程序。

0

我相信需要使用SetWinRegion方法在「子彈孔」周圍繪製輪廓。這樣他們可以點擊通過,但洞本身會浮在頂部(只要使用fsStayOnTop的前一個答案)。

即使是閃存圖像也需要某種形式的圖像來充當圖像的容器。這一切都歸結於創建窗口並將圖像噴射到該窗口。它不必「鎖定」屏幕,如果您將其設置爲始終位於頂部並只是「顯示」它(不是ShowModal),它應該出現並浮動。然後我會使用一個計時器來控制它何時被銷燬。 SetWinRegion的優點是,你可以創建一個不規則形狀的窗口,並且用戶不能點擊的窗口將是窗口中包含實際窗體(在區域內)的部分。

+0

感謝大家的回覆......我希望有一種可能的不同方法?像一個單獨的線程或不同的方式來顯示圖像,而不是繪製表單,就像顯示bullethole的閃光圖像或其他東西?建議/意見將是非常讚賞...有我喜歡爾德實現,但不能,如果它要鎖住屏幕..再次感謝大家等功效。這是我第一次使用這一點,這是驚人的你所有人都花費時間和精力來幫助解決這個問題.. Mark Gundy www.magchat.com – MarkGundy 2009-05-04 10:59:25

1

打開第二個窗體真的不是這樣做的方法。也許圖像控制部分透明的圖像大小隻是比你的彈孔大,你可以放在窗體上的任何地方。如果您無法進行透明控制,則可以拍攝表格的該部分的快照並將彈孔置於頂部。

  1. 當子彈應該出現,你讓畫面可見,並帶來正面
  2. 啓動計時器兩秒鐘,並告訴圖象控制刷新
  3. 當計時器熄滅,躲子彈圖片

如果你想動畫淡出,只需更換與在不同的時間不同的人使用定時器在不同的時間

    都會響起圖片
  • 0秒使圖像中顯示出
  • 在1.5秒替換圖片與圖片
  • 褪色的版本在2秒時隱藏畫面

利用這一點,就沒有必要爲另一種形式,和該應用程序保持響應。

0

下面是一個可行的解決方案。你可能想把擊發過程封裝到一個計時器或其他事件驅動的過程中。

表單定義:

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; 
0

如果是彈孔的動畫被寫成循環執行,直到完成那麼這可能是問題。如果是這樣,則嘗試在循環的某處插入Application.ProcessMessages以允許在動畫發生時發生其他事情。

0

請參閱http://msdn.microsoft.com/en-us/library/dd183353(VS.85).aspx,它有一個很好的API調用alpha調用位圖在一起的示例。對於動畫的每個幀,您可能需要獲取代表主屏幕的圖像的副本,然後在適當的透明度級別上將這些字形與其混合。

如前所述,您可以重複執行Application.ProcessMessages,儘管我更喜歡反向操作並使用PostMessage觸發動畫的下一幀。

您將在循環中使用ProcessMessages,但該調用可能導致其他事情在您處於該循環時發生 - 移動窗口,最小化,關閉或再次觸發動畫事件 - 在第一個動畫完成之前。只要你注意到你並不總是在你的循環範圍內運行,這一切都很好。

因此,我更喜歡讓每個動畫幀都做一個PostMessage來觸發下一幀。它只是幫助我保持透視。

相關問題