https://developer.mozilla.org/en-US/docs/Plugins/Guide/Drawing_and_Event_Handling前端
本章介紹如何肯定插件實例是窗口化仍是無窗口化,如何繪製和重繪插件,以及如何處理插件事件。瀏覽器
在肯定插件實例在網頁中的顯示方式時,您(以及網頁做者)有不少選項。編寫網頁的內容提供商肯定其顯示模式:插件是嵌入式仍是顯示在其本身的單獨頁面中。您能夠經過定義插件自己的方式來肯定插件是窗口化仍是無窗口化。數據結構
- 窗口化插件被繪製到網頁上的其本機窗口(或本機窗口的一部分)中。窗口插件是不透明的,將頁面的一部分隱藏在其顯示窗口下方。這種類型的插件決定了它什麼時候自行繪製。
- 無窗口插件不須要本機窗口。它繪製在一個名爲drawable的目標中,該目標對應於瀏覽器窗口或屏幕外位圖。能夠經過多種方式定義drawable,具體取決於平臺。無窗口插件能夠是不透明或透明的。無窗口插件僅在響應來自瀏覽器的繪製消息時自行繪製。
有關HTML肯定插件顯示模式的方式的信息,請參閱使用HTML顯示插件。less
注意:在Gecko 1.9 Alpha 7以前的X Window System平臺上不支持無窗口插件(錯誤137189)。異步
NPWindow結構部分
加載插件時,會將其繪製到目標區域。此目標是窗口插件的本機窗口,或無窗口插件的drawable。該NPWindow結構表示任一自然窗口或可拉伸。此結構包含有關座標位置,大小,插件狀態(窗口或無窗口)以及某些特定於平臺的信息的信息。ide
注意:當插件被繪製到窗口時,插件負責保留狀態信息並確保恢復原始狀態。函數
對於無窗口插件,瀏覽器使用表示可繪製的NPWindow結構調用NPP_SetWindow方法。對於窗口化插件,瀏覽器使用表示窗口的結構調用方法。NPP_SetWindow
NPWindow
動畫
//The NPWindow Structure typedef enum { NPWindowTypeWindow = 1, NPWindowTypeDrawable } NPWindowType; typedef struct _NPWindow { void* window; /* Platform-specific handle */ uint32 x; /* Position of top-left corner */ uint32 y; /* relative to a Netscape page */ uint32 width; /* Maximum window size */ uint32 height; NPRect clipRect; /* Clipping rectangle in port coordinates */ #ifdef XP_UNIX void * ws_info; /* Platform-dependent additional data */ #endif /* XP_UNIX */ NPWindowType type; /* Whether this is a window or a drawable */ } NPWindow;
window參數是Windows和Unix上瀏覽器窗口層次結構中本機窗口元素的特定於平臺的句柄。在Mac OS上,window是指向NP_Port的指針。ui
該x
和y
字段指定插件相對於頁面的左上角。this
該width
和height
字段指定插件區域的尺寸。插件不該修改這些值。
該clipRect
字段在座標系中定義插件的剪切矩形,其中原點是可繪製或窗口的左上角。只要drawable發生變化,瀏覽器就會調用NPP_SetWindow。對於無窗口插件,插件不可見clipRect
的0,0,0,0
信號。
type字段表示NPWindow
目標區域的類型:
- NPWindowTypeWindow:窗口插件。窗口字段包含窗口的特定於平臺的句柄。
- NPWindowTypeDrawable:無窗口插件。窗口字段包含一個特定於平臺的可繪製句柄,以下所示:
- Windows:HDC
- Mac OS:指向
NP_Port
結構的指針。 - Unix / X11:沒用過。(繪圖信息中提供了drawable。見下文。)
在這兩種狀況下,drawable均可以是一個離屏像素圖。
繪圖插件部分
本節介紹在繪製窗口插件和無窗口插件時使用的方法和過程。如下各節介紹了僅適用於其中一種插件類型的進程。
插件使用這些方法來繪製插件和處理事件:
瀏覽器調用的插件方法:
- NPP_HandleEvent:向實例提供特定於平臺的事件。
- NPP_Print:爲實例請求特定於平臺的打印操做。
- NPP_SetWindow:設置插件繪製的窗口。
瀏覽器端方法,由插件調用:
- NPN_ForceRedraw:強制向無窗口插件發送繪製消息。
- NPN_InvalidateRect:在從新繪製或刷新以前,在無窗口插件中使區域無效。
- NPN_InvalidateRegion:在從新繪製或刷新以前,在無窗口插件中使區域無效。
打印插件
瀏覽器調用該NPP_Print
方法來請求插件實例自行打印。
void NPP_Print(NPP instance, NPPrint *printInfo);
instance參數表示當前插件。
該PrintInfo
參數肯定打印模式。它被設置爲NP_FULL
指示整頁插件打印,或者NP_EMBED
是不是嵌入式插件,做爲嵌入其中的窗口的一部分打印。
- 嵌入式插件與瀏覽器共享打印。插件打印它佔用的頁面部分,瀏覽器處理剩餘的打印過程,包括顯示打印對話框,獲取打印機設備上下文,固然還有打印頁面的其他部分。
嵌入式插件能夠將pluginPrinted
其PrintInfo
參數中的字段設置爲false(默認值)。這是_NPFullPrint
結構的子結構的一個領域NPPrint
。瀏覽器顯示必要的打印對話框並NPP_Print
再次調用。這個時候,PrintInfo->mode
應該設置爲NP_EMBED
。
- 整頁插件可根據須要處理打印對話框和打印過程。在這種狀況下,在瀏覽器顯示任何打印對話框以前,
NPP_Print
調用PrintInfo->mode
等於NP_FULL
。在Mac OS上,整頁打印要求PrintInfo字段包含標準Mac OS THPrint(請參閱參考資料Printing.h
)。
固然,NPP_Print
也PrintInfo->mode
能夠NP_EMBED
在嵌入實例時調用它。在這種狀況下,platformPrint->embedPrint.window
包含應該打印插件的窗口。
在MS Windows上,請注意窗口矩形的座標是TWIPS格式。所以,DPtoLP
在輸出文本時,須要使用Windows API調用轉換x和y座標。
設置窗口
瀏覽器調用該NPP_SetWindow
函數來設置插件繪製或返回錯誤代碼的窗口。此窗口對實例的生命週期有效,或直到NPP_SetWindow
使用不一樣的值再次調用。
NPP_SetWindow
對給定實例的後續調用一般意味着窗口已調整大小。若是任一窗口或window->window
爲null,則插件不得在窗口上執行任何其餘圖形操做,而且應釋聽任何相關資源。
NPError NPP_SetWindow(NPP instance, NPWindow *window);
instance參數表示當前插件。
window參數是指向插件的繪圖目標的指針。對於無窗口插件,指定的特定於平臺的窗口信息window->window
是drawable的特定於平臺的句柄。
MS Windows和Unix
對於MS Windows和Unix上的窗口插件,該window->window
字段是Netscape窗口層次結構的子窗口的句柄。
蘋果系統
該window->window
字段指向一個NP_Port
結構。
獲取資訊
要從瀏覽器接收信息,插件會調用該NPN_GetValue
方法。
NPError NPN_GetValue(NPP instance, NPNVariable variable, void *value);
該instance
參數表示當前插件。
Unix和MS Windows
查詢的信息在變量參數中返回。此參數僅對Unix和MS Windows平臺有效。對於Unix,值是當前display(NPNVxDisplay
)或應用程序的context(NPNVxtAppContext
)。對於MS Windows,該值是發生插件繪圖的本機窗口(NPNVnetscapeWindow
)。
value參數包含插件的名稱。
您還可使用它NPN_GetValue
來幫助建立無窗口插件的菜單或對話框。
窗口插件部分
瀏覽器爲每一個窗口插件提供了本身的本機窗口,一般是瀏覽器窗口自己的子窗口,用於繪製。該插件可徹底控制該窗口內的繪圖和事件處理。
在Mac OS上,瀏覽器不爲窗口插件提供本機窗口,由於Mac OS平臺不支持子窗口。相反,窗口插件在瀏覽器指定的偏移處繪製到與瀏覽器窗口關聯的圖形端口。
在MS Windows和Unix上,瀏覽器爲每一個插件實例建立一個子窗口,並向其傳遞一個窗口NPP_SetWindow
。在Mac OS上,應用程序使用NPP_SetWindow
將其圖形端口的矩形部分專用於每一個實例。在任何平臺上,瀏覽器都應該當心不要插入插件區域,反之亦然。傳入的數據結構NPP_SetWindow
是一個NPWindow
對象,它包含實例區域的座標和各類特定於平臺的數據。
一般,瀏覽器NPP_SetWindow
在建立實例後調用,以便插件能夠當即開始繪製。可是,瀏覽器能夠建立NPP_SetWindow
從不調用的不可見實例,而且永遠不會建立窗口。當使用object
已使用CSS規則隱藏的HTML 元素(請參閱簡介中的插件顯示模式)或使用已設置embed
其hidden
屬性的元素調用插件時,會發生這種狀況。
NPP_SetWindow
只要實例的大小或位置發生變化,瀏覽器就應該再次調用,每次都傳遞相同的NPWindow
對象,但值不一樣。
瀏覽器還能夠NPP_SetWindow
使用窗口的不一樣值屢次調用,包括null。例如,若是用戶從頁面中刪除實例,則瀏覽器應調用NPP_SetWindow
窗口值爲null。此值可防止實例進一步繪製,直到將其粘貼回頁面並NPP_SetWindow
再次使用新值進行調用。
蘋果系統
在Mac OS上,瀏覽器傳遞NP_Port
結構窗口字段中的NPWindow
結構。此結構包含指向CGraphPtr
插件實例應繪製到的圖形端口()的指針以及此端口左上角的x和y座標。插件可使用這些座標調用SetOrigin(portx, porty)
,將其矩形的左上角放在(0,0)處。Mac OS GrafPort
結構的clipRgn
字段應設置爲端口座標中實例的剪切矩形。
因爲插件和瀏覽器共享相同的圖形端口,所以它們共同負責正確管理它。瀏覽器在以兩種方式傳遞插件更新事件以前設置插件的端口:
- 瀏覽器調用
SetOrigin(npport->portx, npport->porty)
。此方法使實例的左上角座標等於(0,0)。 - 瀏覽器將端口的剪輯區域設置爲當前可見的插件區域(不滾動頁面,浮動調色板遮擋或隱藏)。
可是,要使插件在任何其餘時間繪製,例如,要在鼠標按下事件時突出顯示或在空閒時繪製動畫,它必須保存端口的當前設置,並根據須要設置其繪圖環境,繪製,而後將端口還原到之前的設置。在這種狀況下,插件使瀏覽器無需在每次調用插件以前和以後保存和恢復其端口設置。
瀏覽器和插件均可覺得共享端口安裝Drag Manager處理程序。由於不管光標位於何處,Drag Manager都會調用兩個處理程序,當光標位於實例矩形上時,瀏覽器不會顯示拖動突出顯示。此外,當實例矩形內發生丟棄時,瀏覽器不執行任何操做。而後,插件能夠在實例矩形中顯示拖動突出顯示和處理丟棄。
瀏覽器還負責向插件發送針對實例的全部事件,例如當光標位於實例矩形內時單擊鼠標,或者在應用程序打開和關閉時暫停和恢復事件。經過調用將事件發送到插件NPP_HandleEvent
; 有關事件類型的完整列表,請參閱參考條目NPEvent
。
視窗
在Windows上,瀏覽器註冊一個窗口類,併爲插件實例建立該類的實例。而後,插件能夠對窗口進行子類化以接收所需的任何事件。若是插件須要接收週期性時間消息(例如,對於動畫),則應使用計時器或單獨的線程。
Unix的
在Unix上,瀏覽器爲實例建立Motif繪圖區域窗口小部件,並在窗口字段中傳遞窗口小部件的窗口ID NPWindow
。此外,瀏覽器建立一個NPSetWindowCallbackStruct
對象,並將它在ws_info
的領域NPWindow
。與在Windows上同樣,插件能夠接收實例的全部事件,在本例中是經過窗口小部件。若是插件須要接收按期時間消息,則應安裝定時器或分叉線程。
窗口插件的事件處理
窗口化插件實例的全部成像和用戶界面事件都根據其本機平臺的窗口系統進行處理。插件API提供了一個本機窗口句柄,實例經過API調用在其中繪製NPP_SetWindow
。NPP_SetWindow
將實例傳遞給NPWindow
包含本機窗口句柄的對象。
在Windows和Unix上,每一個實例在瀏覽器窗口層次結構中接收本身的子窗口,而且映像和事件處理與此窗口相關。Mac OS不支持子窗口。本機窗口在實例和瀏覽器之間共享。實例必須將其繪圖限制爲共享窗口的指定區域,而且必須始終保存當前設置,設置繪圖環境並將共享繪圖環境恢復爲先前的設置。在Mac OS上,事件經過顯式提供給實例NPP_HandleEvent
。
無窗口插件部分
無窗口插件不須要繪製本機窗口。相反,它會繪製成一個可繪製的(HDC
在Windows或CGrafPtr
Mac OS上),能夠在屏幕上或屏幕外。
無窗口插件爲插件編寫器提供了一些重要的設計可能性:
- 您能夠在一個部分中放置一個無窗口插件; 其餘部分能夠存在於其上方和下方。
- 您能夠建立透明插件。在這種狀況下,瀏覽器繪製插件後面的頁面部分。無窗口插件僅繪製不透明的部分。這樣,插件能夠在現有背景上繪製不規則形狀的區域,例如圖形或文本。
- 瀏覽器支持插件的屏幕外繪製。這使得能夠操縱插件內容。例如,3D應用程序可使用插件的內容做爲紋理貼圖。
因爲無窗口插件能夠分層或繪製到任意drawables,所以瀏覽器(與本機窗口系統相對)負責控制其繪圖和事件處理。
有關控制插件實例的繪製的更多信息,請參閱如下各項:
指定插件是無窗口的
要指定插件是無窗口的,請使用該NPN_SetValue
方法。
instance參數表示當前插件。變量參數包含要設置的插件信息。value參數返回插件的名稱。
要指定插件是無窗口的,請使用NPN_SetValue
with NPPVpluginWindowBool
做爲variable的值,使用false做爲value的值。該插件經過它進行此調用NPP_New method
。若是插件沒有進行此調用,則會將其視爲窗口插件。
Mac OS X上的插件始終沒有窗口。
NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char *argn[], char *argv[], NPSavedData *saved) { ... NPError result = NPN_SetValue(instance, NPPVpluginWindowBool, (void*)false); }
使繪圖區無效
在重繪或刷新部分繪圖區域以前,無窗口插件必須首先使用如下任一瀏覽器方法使區域無效:NPN_InvalidateRect
或NPN_InvalidateRegion
。兩種方法都執行相同的操做:
- 它們在從新繪製或刷新以前使指定的繪圖區域無效。
- 它們將更新事件或繪製消息傳遞給插件。
瀏覽器以定時的間隔重繪文檔的無效區域和無窗口插件。要強制繪製消息,插件能夠NPN_ForceRedraw
在調用其中一個invalidate方法後調用。若是插件調用其中一種方法,它會異步接收繪製消息。
void NPN_InvalidateRect(NPP instance, NPRect *invalidRect); void NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion);
instance參數表示當前插件。在invalidRect
和invalidRegion
參數表示無效區域,在座標系的原點是在插件頂部左指定。
這兩種方法都會致使該NPP_HandleEvent
方法將更新事件或繪製消息傳遞給插件。
#ifdef XP_MAC typedef RgnHandle NPRegion; #elif defined(XP_WIN) typedef HRGN NPRegion; #elif defined(XP_UNIX) typedef Region NPRegion; #else typedef void* NPRegion; #endif /* XP_MAC */ void NPN_InvalidateRect(NPP instance, NPRect *invalidRect); void NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion);
強制繪製消息
窗口和無窗口插件具備不一樣的繪圖模型。窗口插件肯定什麼時候繪製,而無窗口插件繪製以響應來自瀏覽器的繪製消息。NPN_ForceRedraw()
一旦使用NPN_InvalidateRect()
或使區域無效,插件能夠調用同步強制繪製消息NPN_InvalidateRegion()
。
void NPN_ForceRedraw(NPP instance);//再某些瀏覽器上不支持改消息 by_songgp add
此方法致使插件的同步更新事件或繪製消息。
NPN_ForceRedraw()
。
收到油漆信息
除非接收到繪製消息,不然插件不得繪製到其drawable中。它不須要調用特定於平臺的函數來開始在窗口中繪製。也就是說,插件不會BeginPaint
在Windows或BeginUpdate
Mac OS上調用。
- 視窗
插件會收到一條WM_PAINT
消息。該lParam
參數WM_PAINT
保存指向RECT
指定更新區域的邊界框的結構的指針。可是,有些插件會選擇忽略這個paint rect,而是老是更新整個插件窗口。此外,因爲插件和瀏覽器共享相同的HDC,插件必須將當前設置保存在HDC上,設置本身的環境,自行繪製,並將HDC恢復到之前的設置。每當控件返回瀏覽器時,必須在從NPP_HandleEvent
調用與繪圖相關的瀏覽器端方法以前或以後返回以前恢復HDC設置。
- 蘋果系統
插件接收更新事件。drawable CGrafPtr
端口的剪輯區域設置爲更新區域。與Mac OS上的窗口插件同樣,插件必須首先保存端口的當前設置,根據須要設置繪圖環境,繪製並將端口恢復到先前的設置。這應該在插件從NP_HandleEvent
插件調用與繪圖相關的瀏覽器方法以前或以後返回以前發生。
- 的Unix / X11
插件接收GraphicsExpose
事件。該XGraphicsExposeEvent
結構包含Xlib Drawable
(它是一個offscreen pixmap),它Display
和相對於drawable左上角指定的髒矩形(可選剪輯矩形)。
插件應繪製到NPWindow結構和成員中Drawable
指定的偏移量,x
並在y
成員中指定剪輯矩形,並在成員中指定和指定。clipRect
Visual
Colormap
ws_info
製做插件不透明
若是沒有透明區域,無窗口插件是不透明的。當瀏覽器爲插件生成繪製消息時,它假定插件負責繪製要更新的整個區域。因爲瀏覽器不須要在插件後面繪製背景,所以不透明的無窗口插件比透明插件更有效。
默認狀況下,無窗口插件是透明的。要使透明插件不透明,請調用NPN_SetValue
設置NPPVpluginTransparentBool
爲false。插件能夠在指定它是無窗口插件後隨時調用此方法。
使插件透明化
若是窗口具備透明區域,則它是透明的。如下是兩個具備透明區域的插件示例:
- 一個小於封閉
object
或embed
元素指定區域的插件 - 一個非矩形邊界的插件
瀏覽器負責呈現透明無窗口插件的背景。在爲插件生成繪製消息以前,瀏覽器會確保已將背景繪製到要更新的區域中。而後,插件能夠繪製與其不透明區域對應的更新區域的一部分。這可確保插件的透明區域始終有效。
默認狀況下,無窗口插件是透明的。若是要使不透明的無窗口插件透明,請調用該NPN_SetValue
方法並將NPPVpluginTransparentBool
值設置爲true。插件能夠在指定它是無窗口插件後隨時調用此方法。
建立彈出菜單和對話框
僅限MS Windows和Unix / X11
無窗口插件不會在其本身的本機窗口中繪製。相反,它直接繪製給它的drawable。若是您須要在插件中顯示彈出菜單和模式對話框,則此行爲會出現問題; 插件須要父窗口才能建立這樣的窗口。
要解決此問題,請使用NPN_GetValue
以找出插件的繪製位置。使用NPNVnetscapeWindow
做爲變量參數的值。
NPError NPN_GetValue(NPP instance, NPNVariable variable, void *value);
instance參數表示當前插件。變量參數包含調用請求的信息,在這種狀況下NPNVnetscapeWindow
(發生插件繪圖的本機窗口)。
- 視窗
請求的信息(HWND類型的值)從值參數中的NPN_GetValue返回。
在許多狀況下,插件可能仍然必須建立本身的窗口(瀏覽器窗口的透明子窗口),以充當彈出菜單和模式對話框的全部者窗口。您能夠爲此透明子窗口提供本身的WindowProc進程。插件可使用它來處理WM_COMMAND
因爲跟蹤彈出菜單或模式對話框而發送給它的消息。
- 的Unix / X11
NPN_GetValue的value參數必須指向Xlib Window
。成功返回後,它將包含瀏覽器頂層窗口。使用此選項Window
可在對話框上設置WM_TRANSIENT_FOR屬性。
無窗口插件的事件處理
在全部平臺上,特定於平臺的事件都經過該NPP_HandleEvent
方法傳遞給無窗口插件。插件必須NPP_HandleEvent
在處理事件時返回true,不然返回false。Mac OS將這種機制用於窗口插件和無窗口插件; 在此平臺上,NPP_HandleEvent
插件是惟一能夠從其主機應用程序接收事件的方式。
int16 NPP_HandleEvent(NPP instance, NPEvent *event);
instance參數表示當前插件。有關事件類型的列表,應用程序負責傳遞給插件,請參閱NPEvent
結構。
此代碼顯示經過此方法爲每一個平臺傳遞的特定數據:
#ifdef XP_MAC typedef EventRecord NPEvent; #elif defined(XP_WIN) typedef struct _NPEvent { int16 event; int16 wParam; int32 lParam; } NPEvent; #elif defined(XP_UNIX) typedef XEvent NPEvent; #else typedef void NPEvent; #endif /* XP_MAC */ int16 NPP_HandleEvent(NPP instance, NPEvent* event);
在Mac OS上,NPP_HandleEvent
調用時,正確設置當前端口,使其原點與插件的左上角匹配。插件不須要設置當前端口以進行鼠標座標轉換。