天天看點

捕獲SceneControl的BeforeDraw、AfterDraw事件

由于捕獲BeforeDraw與AfterDraw事件的方法相同,我們以AfterDraw為例進行說明。首先我們來看看什麼時候用到BeforeDraw和AfterDraw。

在AE的幫助文檔中,BeforeDraw事件備注如下:

This event method is often used by an OpenGL routine that renders something before the main features in the scene are drawn.  A good example is the scene background, such as sky/sun/moon etc.  Just like the art of painting, one normally needs to draw the background first and then the main feature.  So this method is generally for the background rendering.  It can also be used for executing some routines other than drawing.

The BeforeDraw method returns a boolean value.  When it's set to true, the SceneGraph's drawing is disabled, and you as a developer take control of the drawing (e.g. via OpenGL).  Otherwise, the SceneGraph takes care of drawing as usual.

譯文:BeforeDraw事件常用于OpenGL程式設計,用于在Scene中繪出主要的要素之前進行相關的渲染操作,渲染Scene的背景就是一個很好的示例,比如天空、太陽、月亮等等。和繪畫一樣,我們需要首先繪制背景,然後才繪制主要的元素。是以這個事件常用于背景的渲染操作。當然它也可以執行除去繪畫之外的一些其它的常用操作。

BeforeDraw方法傳回一個bool類型值。當傳回true的時候,SceneGraph的繪畫功能失效,這時候你作為一個開發人員可以通過OpenGF來控制繪畫。如果傳回false,還是由SceneGraph控制繪畫。

AfterDraw事件備注如下:

This event method is often used by an OpenGL routine that renders something after the main features in the scene are drawn.  Just like the art of painting, one normally needs to draw the background first and then the main feature, followed by foreground features or other miscellaneous features.  So this method is generally used for drawing of graphics after the background and the main features are drawn.  It can also be used for executing some routines other than drawing.

譯文:AfterDraw事件常用于OpenGL程式設計,用于在Scene中繪出主要的要素之後進行相關的渲染操作。和繪畫一樣,我們必須首先繪制背景,然後繪制主要的要素,最後繪制前景要素或者其它的各種各樣的要素。是以這個事件常用于背景和主要要素繪制完成後對Graphics進行繪制。它也可以執行除去繪畫之外的一些其它的常用操作。

我們在MapControl中很容易編寫AfterDraw的代碼,因為MapControl封裝了該事件,但是要想編寫SceneControl的AfterDraw事件代碼卻并未易事。

我們通過SceneControl的SceneGraph屬性獲得了一個ISceneGraph類型的對象,檢視幫助文檔可以得知,ISceneGraph接口隻被SceneGraph類實作,我們然後檢視SceneGraph類所實作的接口,如下圖所示:

捕獲SceneControl的BeforeDraw、AfterDraw事件

我原本希望将該接口QI到ISceneGraphEvents,進而能QI到SceneGraphClass,然後利用SceneGraphClass中的AfterDraw事件。我在調試環境下對擷取的ISceneGraph對象用is關鍵字進行了測試,除去最後的兩個事件接口外,都傳回了true。是以ISceneGraph不能QI到ISceneGraphEvents,更不可能轉換到SceneGraphClass,是以計劃破滅。

後來我在VS編輯器中輸入ISceneGraphEvents時,由于VS的智能感應看到了一個奇怪的接口ISceneGraphEvents_Event,然後我正好在Esri論壇上看到了一篇文章(http://bbs.esrichina-bj.cn/ESRI/thread-13483-1-1.html),也用到了ISceneGraphEvents_Event接口。ISceneGraphEvents_Event接口中也有AfterDraw事件,最終得到的解決方法如下:

public FrmMain()
        {
            InitializeComponent();
            //(this.PipeSceneControl.SceneGraph as SceneGraphEventsClass).AfterDraw += new ISceneGraphEvents_AfterDrawEventHandler(FrmMain_AfterDraw);
            (this.PipeSceneControl.SceneGraph as ISceneGraphEvents_Event).AfterDraw += new ISceneGraphEvents_AfterDrawEventHandler(FrmMain_AfterDraw);
        }

        void FrmMain_AfterDraw(ISceneViewer pViewer)
        {
            
        }
           

下面我們看一下ISceneGraphEvents_Event接口和ISceneGraphEvents接口的差別:

首先,ISceneGraphEvents_Event接口隻能在VS的智能感應中識别,但是在AE的幫助文檔中卻找不到該類型。

其次,ISceneGraphEvents接口在VS的智能感應中可以識别,在AE的幫助文檔中也可以識别。

然後,ISceneGraphEvents_Event接口在VS編輯環境中的AfterDraw是以事件的形式顯示的,如下圖所示:

捕獲SceneControl的BeforeDraw、AfterDraw事件

但是ISceneGraphEvents接口在VS編輯環境中的AfterDraw是以方法的形式顯示的,如下圖所示:

捕獲SceneControl的BeforeDraw、AfterDraw事件

 是以隻能用ISceneGraphEvents_Event接口實作AfterDraw的事件綁定,而不能用ISceneGraphEvents接口。