https://developer.mozilla.org/en-US/docs/Plugins/Guide/Drawing_and_Event_Handling

本章介绍如何确定插件实例是窗口化还是无窗口化,如何绘制和重绘插件,以及如何处理插件事件。

在确定插件实例在网页中的显示方式时,您(以及网页作者)有很多选项。编写网页的内容提供商确定其显示模式:插件是嵌入式还是显示在其自己的单独页面中。您可以通过定义插件本身的方式来确定插件是窗口化还是无窗口化。

  • 窗口化插件被绘制到网页上的其本机窗口(或本机窗口的一部分)中。窗口插件是不透明的,将页面的一部分隐藏在其显示窗口下方。这种类型的插件决定了它何时自行绘制。
  • 无窗口插件不需要本机窗口。它绘制在一个名为drawable的目标中,该目标对应于浏览器窗口或屏幕外位图。可以通过多种方式定义drawable,具体取决于平台。无窗口插件可以是不透明或透明的。无窗口插件仅在响应来自浏览器的绘制消息时自行绘制。

有关HTML确定插件显示模式的方式的信息,请参阅使用HTML显示插件

注意:在Gecko 1.9 Alpha 7之前的X Window System平台上不支持无窗口插件(错误137189)。

NPWindow结构部分

加载插件时,会将其绘制到目标区域。此目标是窗口插件的本机窗口,或无窗口插件的drawable。该NPWindow结构表示任一天然窗口或可拉伸。此结构包含有关坐标位置,大小,插件状态(窗口或无窗口)以及某些特定于平台的信息的信息。

注意:当插件被绘制到窗口时,插件负责保留状态信息并确保恢复原始状态。

对于无窗口插件,浏览器使用表示可绘制的NPWindow结构调用NPP_SetWindow方法。对于窗口化插件,浏览器使用表示窗口的结构调用方法。NPP_SetWindowNPWindow

//The NPWindow Structure

typedef enum {

NPWindowTypeWindow = ,
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的指针。

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

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调用时,正确设置当前端口,使其原点与插件的左上角匹配。插件不需要设置当前端口以进行鼠标坐标转换。

NPAPI绘图和事件处理的更多相关文章

  1. 【风马一族_Android】Android 前端内容1

    Android 前端内容 4.1 View 类概述 4.1.1 关于 View //类型说明 view(视图)指的是用户界面组件的基本构建基块.一个视图占据屏幕上的矩形区域,负责绘图和事件处理.视图是 ...

  2. 【风马一族_Android】Android 前端内容

    Android 前端内容 4.1 View 类概述 4.1.1 关于 View //类型说明 view(视图)指的是用户界面组件的基本构建基块.一个视图占据屏幕上的矩形区域,负责绘图和事件处理.视图是 ...

  3. Android 开发之旅:深入分析布局文件&又是“Hello World!”

    http://www.cnblogs.com/skynet/archive/2010/05/20/1740277.html 引言 上篇可以说是一个分水岭,它标志着我们从Android应用程序理论进入实 ...

  4. Android进阶笔记08:Android 中Activity、Window和View之间的关系

    1. Android 中Activity.Window和View之间的关系(比喻): Activity像一个工匠(控制单元),Window像窗户(承载模型),View像窗花(显示视图) LayoutI ...

  5. iOS中MVC等设计模式详解

    iOS中MVC等设计模式详解 在iOS编程,利用设计模式可以大大提高你的开发效率,虽然在编写代码之初你需要花费较大时间把各种业务逻辑封装起来.(事实证明这是值得的!) 模型-视图-控制器(MVC)设计 ...

  6. activity,view,window,windowmanager代码阅读总结及相互关系

    ActivityThread类:performLaunchActivity函数: activity.attach(appContext, this, getInstrumentation(), r.t ...

  7. android 中View, Window, Activity, WindowManager,ViewRoot几者之间的关系

    (1)View:最基本的UI组件,表示屏幕上的一个矩形区域. (2)Window: 表示一个窗口,不一定有屏幕那么大,可以很大也可以很小:                         它包含一个V ...

  8. Android View, Window,Activity概念区分(2)

    (1)View:最基本的UI组件,表示屏幕上的一个矩形区域. (2)Window: 表示一个窗口,不一定有屏幕那么大,可以很大也可以很小:它包含一个View tree和窗口的layout 参数.Vie ...

  9. IOS 与ANDROID框架及应用开发模式对比一

    IOS 和ANDROID操作系统都是目前流行的移动操作系统,被移动终端和智能设备大量采用,两者都采用了先进的软件技术进行设计,为了方便应用开发两者都采用了先进的设计模式.两者在框架设计上都采用了什么技 ...

随机推荐

  1. SQLSEVER导出 xml文件

    各种都可以参照: 链接:https://wenku.baidu.com/view/778f794bfe4733687e21aa90.html 怎样把SQL Server里的某个表的数据导出成XML文件 ...

  2. Python学习日记(九) 装饰器函数

    1.import time a.time.time() 获取到当前的时间,返回值为浮点型 import time print(time.time()) #1565422783.6497557 b.ti ...

  3. Python学习日记(二) list操作

    l = ['a','b','c','d',1,2,[3,'e',4]] 1.list.append() 在list的结尾新增一个新的元素,没有返回值,但会修改原列表 l.append(5) print ...

  4. python3+django+mysql

    django 连接mysql默认驱动是MySQLdb,MySQLdb没有支持python3的版本,如果使用python3.x版本时,django连接mysql的方法 1.使用pymysql替换MySQ ...

  5. 解决通过vue-router打开tab页,下次进入还是上次history缓存的界面状态的问题

    一.问题描述: 1. 跳转模式:界面A-->界面B(界面A中通过 this.$router.push({name:'组件B名称', params: {参数}}) 通过打开新tab页的方式打开界面 ...

  6. c# 常见文件夹操作

  7. Analysis of Autherntication Protocol with Scyther :Case Study ---补充整理

    1.Needham-Schroeder public Key Protocol (基于非对称的加密协议) the Protocol's authors are Roger NeedHam and Mi ...

  8. 2013.6.24 - OpenNE第四天

    今天晚上跟师兄讨论,这那几篇论文,对于<领域多词表 达翻译对的自动抽取及其应用>那篇,我的感觉是跟实体识别不太吻合.他的大概意思就是先讲所有有可能的多词表达都找出来,然后在用C-value ...

  9. js中绑定事件处理函数,使用event以及传递额外数据

    IE8中使用attachEvent绑定事件处理函数时,不能直接向event 对象添加数据属性.可以用属性复制的方法,包装新的event对象. 1. 属性复制var ObjectExtend = fun ...

  10. littlefs了解一下

    littlefs是一个文件系统,断电数据不会出异常,适合IOT场景.