1

我有一些问题,我用xcode在mac10.8上写了一个npapi插件,我想在插件上画图但是当我通过NPP_SetWindow(NPP instance, NPWindow* pNPWindow)得到pNPWindow->window指针时;我发现 nNPWindow->window 是 NULL ,我必须要找到问题,但我不能,有人可以帮助我。对不起,我的英语太差了。</p>

代码是这样的,

    NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*     argn[], char* argv[], NPSavedData* saved)
    {
        if(instance == NULL)
            return NPERR_INVALID_INSTANCE_ERROR;

        CPlugin *plugin = new CPlugin(instance);
        if(plugin == NULL)
            return NPERR_OUT_OF_MEMORY_ERROR;
        instance->pdata = (void *)plugin;

        NPBool supportsCG = false;
        NPError err;
        err = browser->getvalue(instance, NPNVsupportsCoreGraphicsBool,&supportsCG);

        if (err == NPERR_NO_ERROR && supportsCG)
             browser->setvalue(instance,NPPVpluginDrawingModel,(void*)NPDrawingModelCoreGraphics);

        return NPERR_NO_ERROR;
    }

    NPError NPP_SetWindow(NPP instance, NPWindow* pNPWindow)
   { 
        if(instance == NULL)
            return NPERR_INVALID_INSTANCE_ERROR;
        if(pNPWindow == NULL)
            return NPERR_GENERIC_ERROR;

        if(pNPWindow->window)
            writelog("window != NULL");

        if(pNPWindow->window == NULL)  //this is he problem pNPWindow->window always NULL
            writelog("window == NULL");

        return NPERR_NO_ERROR;
    }
4

2 回答 2

2

您要在 Mac 10.8 上使用的任何东西都不支持碳事件模型,因此 window 将始终为 NULL。假设您尝试使用 CoreGraphics 绘图模型,当触发事件进行绘图时,您将获得 CGContextRef。

有关 Cocoa 事件模型的更多信息,请参阅https://wiki.mozilla.org/NPAPI:CocoaEventModel。您拥有的另一个选项是CoreAnimation模型(在 firefox 和 chrome 上使用InvalidatingCoreAnimation模型)

你可能想看看FireBreath,它适用于 10.8 并为你抽象了这些东西的所有复杂性。

于 2012-11-08T17:14:31.700 回答
0

NPP_SetWindow (NPP npp, NPWindow* pNPWindow)

对于许多人来说,这将是真正有趣的开始——调用这个函数来告诉插件他们在哪个窗口中。来自 Gecko SDK (npapi.h):

typedef struct _NPWindow
{
  void* window;  /* Platform specific window handle */
             /* OS/2: x - Position of bottom left corner  */
             /* OS/2: y - relative to visible netscape window */
  int32 x;       /* Position of top left corner relative */
  int32 y;       /* to a netscape page.                 */
  uint32 width;  /* Maximum window size */
  uint32 height;
  NPRect clipRect; /* Clipping rectangle in port coordinates */
               /* Used by MAC only.           */
  void * ws_info; /* Platform-dependent additonal data, linux specific */
  NPWindowType type; /* Is this a window or a drawable? */
} NPWindow;   

每次调用都会传入一个指向该结构的指针。在 Windows 上,“void* 窗口”将取消对 HWND 的引用。在其他平台上,它同样会被取消引用为适当的类型。

请注意,再次 NPP npp 是第一个参数。除了 NPP_New 之外的所有 NPP 函数都是这种情况,其中也传入了 mimetype。由于我们创建了一个 PluginInstance 对象并将其分配给 NPP_New 中的 npp->pdata,因此我们需要创建一个小的存根函数来将我们的 NPP_New 转发到该对象上的方法,如下所示:

// 每当窗口改变时由浏览器调用,包括设置或销毁

NPErrorNPP_SetWindow (NPP npp, NPWindow* pNPWindow)
{
    if (npp == NULL)
         return NPERR_INVALID_INSTANCE_ERROR;
    else if (npp->pdata == NULL)
        return NPERR_GENERIC_ERROR;

    PluginInstance *inst = (PluginInstance *)npp->pdata;
    return inst->NpapiSetWindow(pNPWindow);
}

在 Windows 上,当调用 SetWindow 时,我们需要保存 HWND 并对窗口进行子类化,以便我们可以获得自己的窗口事件过程。

NPError PluginInstance::NpapiSetWindow (NPWindow* pNPWindow) { NPError rv = NPERR_NO_ERROR;

if(pNPWindow == NULL)
    return NPERR_GENERIC_ERROR;

// window just created; in initWindow, set initialized to true
if(!this->initialized) {
    if(!this->initWindow(pNPWindow)) {
        return NPERR_MODULE_LOAD_FAILED_ERROR;
    }
}

// Window was already created; just pass on the updates
this->updateWindow(pNPWindow);

return rv;
}

使用这些函数,我们会在第一次设置窗口时在一个函数中收到通知,而在每次进行更新时调用另一个函数。

于 2012-11-08T13:44:08.343 回答