NPAPI绘图和事件处理

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_SetWindowNPWindow动画

//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

xy字段指定插件相对于页面的左上角。this

widthheight字段指定插件区域的尺寸。插件不该修改这些值。

clipRect字段在坐标系中定义插件的剪切矩形,其中原点是可绘制或窗口的左上角。只要drawable发生变化,浏览器就会调用NPP_SetWindow对于无窗口插件,插件不可见clipRect0,0,0,0信号。

type字段表示NPWindow目标区域类型:

  • NPWindowTypeWindow:窗口插件。窗口字段包含窗口的特定于平台的句柄。
  • NPWindowTypeDrawable:无窗口插件。窗口字段包含一个特定于平台的可绘制句柄,以下所示:
    • Windows:HDC
    • Mac OS:指向NP_Port结构的指针
    • Unix / X11:没用过。(绘图信息中提供了drawable。见下文。)

在这两种状况下,drawable均可以是一个离屏像素图。

绘图插件部分

本节介绍在绘制窗口插件和无窗口插件时使用的方法和过程。如下各节介绍了仅适用于其中一种插件类型的进程。

插件使用这些方法来绘制插件和处理事件:

浏览器调用的插件方法:

浏览器端方法,由插件调用:

打印插件

浏览器调用该NPP_Print方法来请求插件实例自行打印。

void NPP_Print(NPP instance, NPPrint *printInfo);

instance参数表示当前插件。

PrintInfo参数肯定打印模式。它被设置为NP_FULL指示整页插件打印,或者NP_EMBED是不是嵌入式插件,做为嵌入其中的窗口的一部分打印。

  • 嵌入式插件与浏览器共享打印。插件打印它占用的页面部分,浏览器处理剩余的打印过程,包括显示打印对话框,获取打印机设备上下文,固然还有打印页面的其他部分。

嵌入式插件能够将pluginPrintedPrintInfo参数中字段设置为false(默认值)。这是_NPFullPrint结构的子结构的一个领域NPPrint浏览器显示必要的打印对话框并NPP_Print再次调用这个时候,PrintInfo->mode应该设置为NP_EMBED

  • 整页插件可根据须要处理打印对话框和打印过程。在这种状况下,在浏览器显示任何打印对话框以前,NPP_Print调用PrintInfo->mode等于NP_FULL在Mac OS上,整页打印要求PrintInfo字段包含标准Mac OS THPrint(请参阅参考资料Printing.h)。

固然,NPP_PrintPrintInfo->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 元素(请参阅简介中的插件显示模式)或使用已设置embedhidden属性元素调用插件时,会发生这种状况

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_SetWindowNPP_SetWindow将实例传递给NPWindow包含本机窗口句柄对象。

在Windows和Unix上,每一个实例在浏览器窗口层次结构中接收本身的子窗口,而且映像和事件处理与此窗口相关。Mac OS不支持子窗口。本机窗口在实例和浏览器之间共享。实例必须将其绘图限制为共享窗口的指定区域,而且必须始终保存当前设置,设置绘图环境并将共享绘图环境恢复为先前的设置。在Mac OS上,事件经过显式提供给实例NPP_HandleEvent

无窗口插件部分

无窗口插件不须要绘制本机窗口。相反,它会绘制成一个可绘制的(HDC在Windows或CGrafPtrMac OS上),能够在屏幕上或屏幕外。

无窗口插件为插件编写器提供了一些重要的设计可能性:

  • 您能够在一个部分中放置一个无窗口插件; 其余部分能够存在于其上方和下方。
  • 您能够建立透明插件。在这种状况下,浏览器绘制插件后面的页面部分。无窗口插件仅绘制不透明的部分。这样,插件能够在现有背景上绘制不规则形状的区域,例如图形或文本。
  • 浏览器支持插件的屏幕外绘制。这使得能够操纵插件内容。例如,3D应用程序可使用插件的内容做为纹理贴图。

因为无窗口插件能够分层或绘制到任意drawables,所以浏览器(与本机窗口系统相对)负责控制其绘图和事件处理。

有关控制插件实例的绘制的更多信息,请参阅如下各项:

指定插件是无窗口的

要指定插件是无窗口的,请使用该NPN_SetValue方法。

instance参数表示当前插件。变量参数包含要设置的插件信息。value参数返回插件的名称。

要指定插件是无窗口的,请使用NPN_SetValuewith 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_InvalidateRectNPN_InvalidateRegion两种方法都执行相同的操做:

  • 它们在从新绘制或刷新以前使指定的绘图区域无效。
  • 它们将更新事件或绘制消息传递给插件。

浏览器以定时的间隔重绘文档的无效区域和无窗口插件。要强制绘制消息,插件能够NPN_ForceRedraw在调用其中一个invalidate方法后调用。若是插件调用其中一种方法,它会异步接收绘制消息。

void NPN_InvalidateRect(NPP instance, NPRect *invalidRect); void NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion);

instance参数表示当前插件。invalidRectinvalidRegion参数表示无效区域,在坐标系的原点是在插件顶部左指定。

这两种方法都会致使该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

此方法致使插件的同步更新事件或绘制消息。

注意: 某些浏览器(包括Firefox 4)可能会忽略对其的调用 NPN_ForceRedraw()

收到油漆信息

除非接收到绘制消息,不然插件不得绘制到其drawable中。它不须要调用特定于平台的函数来开始在窗口中绘制。也就是说,插件不会BeginPaint在Windows或BeginUpdateMac 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成员中指定剪辑矩形,并成员中指定指定clipRectVisualColormapws_info

制做插件不透明

若是没有透明区域,无窗口插件是不透明的。当浏览器为插件生成绘制消息时,它假定插件负责绘制要更新的整个区域。因为浏览器不须要在插件后面绘制背景,所以不透明的无窗口插件比透明插件更有效。

默认状况下,无窗口插件是透明的。要使透明插件不透明,请调用NPN_SetValue设置NPPVpluginTransparentBool为false。插件能够在指定它是无窗口插件后随时调用此方法。

使插件透明化

若是窗口具备透明区域,则它是透明的。如下是两个具备透明区域的插件示例:

  • 一个小于封闭objectembed元素指定区域的插件
  • 一个非矩形边界的插件

浏览器负责呈现透明无窗口插件的背景。在为插件生成绘制消息以前,浏览器会确保已将背景绘制到要更新的区域中。而后,插件能够绘制与其不透明区域对应的更新区域的一部分。这可确保插件的透明区域始终有效。

默认状况下,无窗口插件是透明的。若是要使不透明的无窗口插件透明,请调用该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调用时,正确设置当前端口,使其原点与插件的左上角匹配。插件不须要设置当前端口以进行鼠标坐标转换。

相关文章
相关标签/搜索