FLASH控件在程式中的自适應大小問題[解決]
轉載 | 2009-07-02
具體的問題是這樣的,在自己做的ocx裡面用到了media player,程式設計語言是delphi7(或6),但是有兩個問題始終解決不了,
一是media player無法随parent做resize,即使把media player的align設成client;
二是對運作時生成的media player變換uimode時,得到的media player的視窗大小總是不正确。 其實這兩個問題在delphi中還是具有一定的普遍性的,不隻是media player,凡是ocx都會遇到的,比如flash的ocx.
對于問題一,在大富翁論壇上有一個解決方案,就是在media player的parent的resize事件對media player中調用setfocus,或者DoObjectVerb(-1). 3年之前我也一直是這麼做的,不過這種做法卻是有問題的。因為setfocus,或者DoObjectVerb(-1)這2個調用會使media player的parent失去焦點,也就是說,在winxp下當你在放大或縮小一個視窗的時候,會發現拖了一下就拖不動了。是以這種解決方法隻适合拖動時不顯示視窗内容的情況,比如win2000以前的系統,而winxp系統預設是拖動不顯示視窗内容的。 至于問題二也是最近才發現的,因為以前不需要在運作時改變media player的uimode。現象是當運作時改變media player的uimode時,得到的media player的視窗大小不是符合原來的大小,似乎總是回到一個預設大小,而且在切換過程中視窗會閃2次,當你再次以同樣的值調用uimode時(比如按一個按鈕),media player的視窗才回到正确的位置。但是這個問題又不能通過在代碼中連續2次調用
uiMode = xx來解決,即使兩次調用之間加了applicaion.processmessage也不行. 關于這個問題在大富翁論壇沒有提及. 那這兩個問題歸根結底是什麼問題,造成該問題的原因又是什麼呢?通過2天大量的試驗發現,這兩個問題都是delphi對ole容器的實作不當造成的,原因很簡單,在vb6中就不會出現這樣的問題。是以,問題歸根結底不是微軟的錯,而是borland的錯! 說到borland,有讓我想起了vcl的另外一個bug,那就是控件的parent屬性。在vcl中,當你改變一個控件的parent時,vcl會先把該控件的資料先儲存到一個memory stream中,然後将這個控件的視窗銷毀,從parent的list中删除對這個控件的引用,然後在新的parent的list中加入對該控件的引用,最後,如果需要再重新creat這個控件的視窗。我實在不能了解borland為什麼要這樣做,他憑什麼要對控件的視窗下毒手?并且是否控件的所有狀态都得以儲存,進而可以正确的被恢複?我試過,比如listview,被選中的item在換了parent之後就沒有正确的顯示。至于第一條就更嚴重了,比如我用media player播放一段視訊,在換了parent之後發現視訊竟然停止播放了,實在令人匪夷所思。而同樣的操作在vb6裡面就完全沒問題。更加令人發指的是,對于這兩個臭名昭著的bug,borland竟然視而不見,随着delphi6, delphi7的釋出,問題依舊。使得程式員隻能繞開parent,使用widnows.setparent來解決問題,進而丢失了align帶來的便利。
在回到本文主要讨論的2個問題中來,說說這2個問題的解決,也确實有趣。問題最終是通過google,而不是百度,由外國程式員而不是中國程式員解決的。通過不斷的更換關鍵詞,終于在google中找到了一個挪威語寫的文章,雖然挪威語看不懂,但是代碼看的懂,加上論壇表情符号,基本可以了解大概,一試,果然不假,第一個問題就此解決。為了了解當事人到底說了什麼,又到google上找了一個可以将挪威語翻譯成英語的網站,還行,雖然語句基本不連貫,對于我們這種讀英文以詞度意,而不看布局謀篇的,也基本受用。感覺,那是"相當"好!!! 最後,第二個問題也在第一個問題的提示下順利解決。
問題一解決:
type TLocOleCtrl=Class(TOleControl);
procedure TForm1.FormResize(Sender: TObject);
begin
TLocOleCtrl(WindowsMediaPlayer1).OnPosRectChange(Rect(0,0,ClientWidth, ClientHeight));
end;
原文: http://arsserwoo.spaces.live.com/blog/cns!FDD447423EF45BC6!126.entry#comment