码迷,mamicode.com
首页 > 其他好文 > 详细

青果插件编程注意事项

时间:2015-04-22 20:41:34      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:

1. 插件被激活后,会根据设置去加载游戏的loader,每个游戏都有一个对应的loader,
形式为loader.dll,需要游戏方自己开发,功能相当于原先的Launcher.exe。


2. 插件会创建好一个标准win32窗口传递给loader.dll,我们就是针对这个窗口编程,与平时开发一样,基本上就是标准的win32编程方式。


3. loader.dll 需要导出几个标准接口,供插件调用,代码实现在文件末尾。
编写loader.dll的时候,就根据这几个标准接口去实现相应功能(比如更新client、调用client,前面说了,相当于Launcher)。


4. 客户端也作为一个dll被loader加载,即client.dll,最好使用LoadLibraryEx。


5. 这个标准的win32窗口是unicode的!!!
可以使用 WINUSERAPI BOOL WINAPI IsWindowUnicode( __in HWND hWnd) 判断。
loader.dll和client.dll最好也是unicode的,不要是mbcs,这样从插件、到loader、到client,都是unicode的,不用做任何额外处理,不需要任何hack代码。


6. 一般来说,client中,自己不处理的windows消息,会调用 DefWindowProc 进行处理。
根据前一条规则,这些“自己不处理的windows消息”,一定要调用 DefWindowProcW 进行处理,因为窗口是unicode的。
如果loader.dll和client.dll是unicode的,调用 DefWindowProc 相当于调用 DefWindowProcW。
如果loader.dll和client.dll是mbcs的,在浏览器中运行时需要显示调用 DefWindowProcW,否则可能出现窗口标题栏乱码等情况;client.exe单独运行时需要调用 DefWindowProcA。
要根据窗口是否是Unicode的,来调用相应的 DefWindowProc,mbcs的窗口必须调用 DefWindowProcA,unicode的窗口必须调用 DefWindowProcW,否则出现不可预料的问题。
窗口是否是Unicode,是根据创建窗口前,调用的 RegisterClass、RegisterClassEx 版本决定的(百度百科)。


7. 插件会调用 DefWindowProc ,处理 loader.dll 和 client.dll 不处理的消息,根据接口之一 _FancyMessage 的返回值进行判断。
_FancyMessage 返回非0,则插件不调用 DefWindowProc ; _FancyMessage 返回0,则插件调用 DefWindowProc 。
一般来说,client代码中,编写WndProc时,原有的一些编程习惯是这样:自己处理的消息处理后、返回0,不处理的break,转去调用 DefWindowProc;
这种编程习惯会导致返回0的那些消息,会被插件层的 DefWindowProc 再次处理,可能导致不可预料的问题,最典型的的就是 WM_SETCURSOR 消息,你设置完返回0,
插件层的 DefWindowProc 再次处理 WM_SETCURSOR ,导致鼠标指针被系统重置为默认形状,你会看到鼠标指针不停闪烁,一会儿是游戏中的形状、一会儿是标准箭头。


疑问:client中如果调用了 DefWindowProcW ,处理了游戏逻辑不处理的消息, DefWindowProcW 的返回值是否是0,这个没有研究过,不清楚,
可以肯定的是,如果client中的 DefWindowProcW 返回了0,插件层的 DefWindowProcW 会再重复处理一遍,会产生什么问题,不得而知。


8. 游戏保存目录为C:\Users\[用户名]\fancy\[游戏名],比如黑暗之光的游戏目录为 C:\Users\admin\fancy\lost。
要获得这个目录,可以调用系统函数SHGetSpecialFolderPath,并对其结果做一定加工。

9. loader.dll 需要打上青果签名,否则插件是不认的~~


10. 启动插件的页面代码,可以靠研究黑暗之光的页面获得。
跟青果对接的时候,他们会给你一个简单的示例,但光这个是远远不够的,你们还是需要去研究黑暗之光的页面机制。


11. loader.dll中加载client.dll的时候,最好使用LoadLibraryEx(szDllAbsolutePath, 0, LOAD_WITH_ALTERED_SEARCH_PATH);这样基本上所有的浏览器下都没问题。
否则,在不同浏览器下运行时,可能有些会找不到client.dll,导致无法加载。
ie、Chrome、360se还都是比较稳健的,使用LoadLibrary也没问题。
火狐、Safari、QQ浏览器都有点折腾,用LoadLibrary很容易报找不到client.dll。


12. 无插件情况下用360安全浏览器启动jzwl不能的问题,启动黑光可以。
360安全浏览器自带的插件对loader的url里的域名有检查,没在他白名单的不加载。
把loader.dll放在360cdn就可以解决问题;或者去360官网做url认证http://trust.360.cn/join.html。


13. 如果游戏中鼠标右键有操作,比如换装,在带右键手势的浏览器中运行的时候,会出现‘游戏右键操作’和‘浏览器右键手势’冲突的情况。
可以通过鼠标钩子的方式屏蔽右键消息,回调函数中返回1,浏览器就不会接收到了。然后可以通过其它的方式传递给客户端。
目前360安全浏览器手势被屏蔽了,遨游也可以,2345、搜狗等仍然不能屏蔽手势。

/************************************************************************/
/*                                                                      */
/************************************************************************/




loader.dll导出的标准接口(直接复制、粘贴可以用):


#include "stdafx.h"
#include "fancy.h"


unsigned long gTLS = 0;
extern "C"
{


//----------------------------------------------------------------------------
// _FancyCreate Implementation
//----------------------------------------------------------------------------


unsigned int __declspec( dllexport ) _FancyCreate( void* window, const wchar_t* game, const wchar_t* vers, const wchar_t* host, unsigned long mode )
{
::TlsSetValue( gTLS, Fancy3DLoader::CreateLoader( window, mode ) );


::SetTimer( (HWND) window, 0, 10, 0 );


return 1;
}


//----------------------------------------------------------------------------
// _FancyDelete Implementation
//----------------------------------------------------------------------------


void __declspec( dllexport ) _FancyDelete( void* window )
{
::KillTimer( (HWND) window, 0 );


Fancy3DLoader* loader = (Fancy3DLoader*) ::TlsGetValue( gTLS );
if ( loader )
delete loader;


::TlsSetValue( gTLS, 0 );
}


//----------------------------------------------------------------------------
// _FancySetup Implementation
//----------------------------------------------------------------------------


void __declspec( dllexport ) _FancySetup( const wchar_t* name, const wchar_t* value )
{
Fancy3DLoader* loader = (Fancy3DLoader*) ::TlsGetValue( gTLS );
if ( loader )
loader->Setup( name, value );
}


//----------------------------------------------------------------------------
// _FancyUpdate Implementation
//----------------------------------------------------------------------------


unsigned int __declspec( dllexport ) _FancyUpdate( void* window, unsigned long elapse )
{
Fancy3DLoader* loader = (Fancy3DLoader*) ::TlsGetValue( gTLS );
if ( loader )
loader->Update( elapse );


return 1;
}


//----------------------------------------------------------------------------
// _FancyRender Implementation
//----------------------------------------------------------------------------


void __declspec( dllexport ) _FancyRender( void* window )
{
Fancy3DLoader* loader = (Fancy3DLoader*) ::TlsGetValue( gTLS );
if ( loader )
loader->Render( );
}


//----------------------------------------------------------------------------
// _FancyMessage Implementation
//----------------------------------------------------------------------------


unsigned int __declspec( dllexport ) _FancyMessage( void* window, unsigned long msgid, unsigned long wparam, unsigned long lparam )
{
Fancy3DLoader* loader = (Fancy3DLoader*) ::TlsGetValue( gTLS );
if ( loader )
return loader->Message( msgid, wparam, lparam );


return 1;
}


//----------------------------------------------------------------------------
// _FancyProgress Implementation
//----------------------------------------------------------------------------


float __declspec( dllexport ) _FancyProgress( )
{
// For backwards compatibility.


Fancy3DLoader* loader = (Fancy3DLoader*) ::TlsGetValue( gTLS );
if ( loader )
return loader->GetProgress( );


return 0.0f; 
}


}

青果插件编程注意事项

标签:

原文地址:http://blog.csdn.net/unknowm/article/details/45199963

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!