我们有时候需要调整插件窗口的尺寸大小,比如说,当你创建一个视频播放窗口,在用户点击播放之后想要将窗口的大小调整为视频的实际大小。播放完毕之后又将窗口尺寸调整回原来的尺寸大小。
要实现这样一个功能,最简单的方式是写JS来实现,只需要首先用getElementById获取插件,然后设置其width属性和height属性。但是,通常情况下我们只管编写插件,不负责网页的设计,如果我们设计完一个插件,还要为网页设计人员写一大堆的注意事项,是不是可以说我们的插件写得不太高明呢?
为了能够在插件中更改插件窗口的尺寸。我们需要使用的接口其实很少,为了方便,我们为Plugin类添加一个成员函数ChangSize(int width, int height):函数代码如下:
void Plugin::ChangeSize(int width,int height)
{
NPObject *pluginObj;
NPN_GetValue(m_pNPInstance,NPNVPluginElementNPObject,&pluginObj);
NPIdentifier n_width_id = NPN_GetStringIdentifier("width");
NPIdentifier n_height_id = NPN_GetStringIdentifier("height");
NPVariant rval;
// STRINGZ_TO_NPVARIANT("400",rval);
INT32_TO_NPVARIANT(width,rval);
NPN_SetProperty(m_pNPInstance,pluginObj,n_width_id,&rval);
INT32_TO_NPVARIANT(height,rval);
NPN_SetProperty(m_pNPInstance,pluginObj,n_height_id,&rval);
}
代码很简单,不多说了,唯一有难点的是NPNVPluginElementNPObject,因为在MDN上没有对NPN_GetValue(m_pNPInstance,NPNVPluginElementNPObject,&pluginObj);得到的NPObject做任何说明,可能老外都认为NPNVPluginElementNPObject这个词就能够完全说明问题吧!
得到了NPObject,然后就为它设置属性,只需要一个函数NPN_SetProperty和一个宏INT32_TO_NPVARIANT或者STRINGZ_TO_NPVARIANT就可以完成属性的设置,这样一来,就改变了插件窗口的尺寸了。
这种方式与JS方式的实质是一样的,只不过将代码在插件中进行了实现,而且不需要借助插件中调用JS代码。
获取插件路径
该功能不复杂,不过使用了windows提供的API故只适用于windows平台。代码如下:
LPTSTR moduleName = new TCHAR[100];
GetModuleFileName(GetModuleHandle(_T("name")),moduleName,100);
std::string mPath = std::string(moduleName);
GetModuleHandle(_T("name"))的name即你的插件名称,如:npdemo.dll。TCHAR的长度视具体情况而定,用于保存得到的路径。注意需要include tchar.h和string(是string不是string.h)。当然路径其实已经保存在moduleName中了,如果不用string可以不要最后一句(鉴于字符串处理的繁琐,推荐使用string)。
获取页面路径、资源路径
要获取插件页面的路径,可以参考:https://developer.mozilla.org/en-US/docs/Getting_the_page_URL_in_NPAPI_plugin。其中提到了三种方式,但我感觉比较靠谱的方式是第一种,下面是简单的实现代码:
NPObject *pluginObj;
NPN_GetValue(m_pNPInstance,NPNVWindowNPObject,&pluginObj);
NPIdentifier n=NPN_GetStringIdentifier("location");
NPVariant rval;
NPN_GetProperty(m_pNPInstance,pluginObj,n,&rval);
NPObject* locationObj = rval.value.objectValue;
n=NPN_GetStringIdentifier("href");
NPN_GetProperty(m_pNPInstance,locationObj,n,&rval);
std::string pageURL = std::string(rval.value.stringValue.UTF8Characters);
object标签可以使用data属性设置资源的URL,embed标签使用src属性设置资源URL。获取资源路径的代码如下:
NPObject *pluginObj;
NPN_GetValue(m_pNPInstance,NPNVPluginElementNPObject,&pluginObj);
NPIdentifier n=NPN_GetStringIdentifier("src");
NPVariant rval;
NPN_GetProperty(m_pNPInstance, pluginObj, n, &rval);
if(NPVARIANT_IS_STRING(rval))
m_pSrc = std::string(NPVARIANT_TO_STRING(rval).UTF8Characters);
else{
n=NPN_GetStringIdentifier("data");
NPN_GetProperty(m_pNPInstance, pluginObj, n, &rval);
if(NPVARIANT_IS_STRING(rval))
m_pSrc = std::string(NPVARIANT_TO_STRING(rval).UTF8Characters);
}
这样,不管html中使用的是object标签的data还是使用的embed标签中的src设置资源URL,都可以将资源的完整URL保存到m_pSrc中。
除了通用属性如:id、class等,object标签的属性有type、data、width、height,embed标签的属性有type、src、width、height。而flashplayer插件所具有的loop、autoplay等属性都是插件自己添加的,无法用NPN_GetProperty接口进行获取。假设我们要开发一个插件允许使用loop属性,那该怎么实现呢?
这个就要找到NS_NewPluginInstance函数中了,这个函数的参数是一个nsPluginCreateData。这个结构中就保存了标签中所有的属性和属性值。这个函数中创建了一个新的Plugin对象,Plugin对象的构造函数参数为NPP,故此处传递了nsPluginCreateData的instance。如果我们需要获取和识别私有属性如loop,推荐实现一个可以接受nsPluginCreateData的Plugin构造函数。这样就可以在plugin构造函数中获取私有属性的值了。
假设我们要实现私有属性loop。并使得只有如下方式loop才无效:不设置loop属性、loop=false、loop=no、loop=0.其他方式loop如:loop、loop=true、loop=yes、loop=1等都有效。那我们的代码可以这样写:
//读取私有属性。
m_bLoop=false;//初始设为false,保证没有设置该属性时无效
int16_t argNum = cd->argc;//the number of HTML arguments in the element
// cd->argn;//The argn array contains the attribute names
// cd->argv;//the argv array contains the attribute values
int16_t argCur = 0;
for (argCur=0;argCur<argNum;argCur++)
{
if (0==strcmp(cd->argn[argCur],"loop"))
{
m_bLoop = true;
std::string loop = std::string(cd->argv[argCur]);
if(loop=="no"||loop=="false"||loop=="0") m_bLoop = false;
}
}
如上代码所实现的私有属性最简单的组合就是需要loop时用<object name=value loop > </object>不需要loop时用<object name=value > </object>。其中name=value对表示其他属性类似于:id=”plugindemo”。