青果插件编程注意事项

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认证。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;}}

成功是什么?就是走过了所有通向失败的路,

青果插件编程注意事项

相关文章:

你感兴趣的文章:

标签云: