惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tailwind CSS Blog
J
Java Code Geeks
Microsoft Azure Blog
Microsoft Azure Blog
GbyAI
GbyAI
爱范儿
爱范儿
量子位
Martin Fowler
Martin Fowler
V
V2EX
博客园 - 三生石上(FineUI控件)
I
InfoQ
MongoDB | Blog
MongoDB | Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
N
Netflix TechBlog - Medium
D
DataBreaches.Net
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Last Week in AI
Last Week in AI
U
Unit 42
Apple Machine Learning Research
Apple Machine Learning Research
H
Help Net Security
T
The Blog of Author Tim Ferriss
Hugging Face - Blog
Hugging Face - Blog
美团技术团队
Engineering at Meta
Engineering at Meta

博客园 - yesry

程序员专用IM新版本发布,诸多创新非模仿 VC的强大 + ExtJS的漂亮 + (MySQL+SQlite)数据库 + JavaScript的动态语言的灵活 通过桥接器,Java调用任何DLL 学生的福音:做错之题管理 Google 和 baidu 搜索结果二次加工 键鼠模拟的妙用 汉编卷土重来? 用贾樟柯访谈评《疯狂的程序员》 Duceland Widgets Engine 例子一 作为软件从业员面对番茄事件的尴尬立场 招聘Windows API 熟悉人 招IE插件精通人 史上最不安全的浏览器——Dangerous Browser VC调用 JavaScript 难题:如何使当前程序的对象进入脚本 PHP能参与桌面项目吗?适合吗?——C#客户端 嵌入 PHP 一例 互联网公司老板的十大谎言之解——时间成本和竞争成本 我在外资公司的2个月 让大家见识一下新一代分析源代码生成流程图的东东吧 如何进行界面和业务逻辑分开的原型化开发
Widgets 引擎的设计和实现
yesry · 2008-11-05 · via 博客园 - yesry

四、代码实现

1 MFC 的 C++ 部分
  微软的MVC架构不用多说了,主要贴出脚本调用部分:


//这个函数提取页面中的js代码后在msscript.ocx中执行
void BrowserView::FindAndExecuteJavaScript()
{
    
//get javascrip client code
    CString codes[20];
    
int code_item_count=0;
    CComPtr<IHTMLElementCollection> spColl;
    m_spDoc->get_all(&spColl);
    GetScriptCode(spColl,
"JavaScript-BHO",codes,code_item_count);if(JavaScriptHelper==NULL && g_RuntimeVars.env)
    {
        
//get 'JavaScriptHelper' object from dsRE to execute PHP script
        JavaScriptHelper=g_RuntimeVars.env->GetSharedObject(L"JavaScriptHelper");
    }
    
if(JavaScriptHelper)
    {
        
int i;
        
for(i=0;i<code_item_count;i++)
        {
            codes[i].Trim();
            
if(codes[i].GetLength()>0)
            {
                CString code=codes[i];
                
char *buf=(LPSTR)(LPCSTR)code;

                dValue ret;
                JavaScriptHelper->Invoke((dobject)NULL,L

"Execute",buf,code.GetLength(),&ret);//execute JavaScript
            }

        }
    }
}


//这个函数在页面得到正确请求后发生,主要是向msscript.ocx中的js增加全局变量document和用于js调用C++函数的System对象
void BrowserView::OnNavigateComplete2(LPCTSTR strURL)
{
    
if(m_pDisp==NULL || m_spDoc==NULL)
    {
        m_pDisp=CHtmlView::GetHtmlDocument();
        m_pDisp->QueryInterface(IID_IHTMLDocument2,(
void**)&m_spDoc);
    }
if(m_pDisp &&  m_spDoc)
    {
       ...
                
//set Document to msscript.ocx
                dobject dobj_document=g_RuntimeVars.env->WrapExistsInstance(L"dobj_wrap_dispatch",m_pDisp);
                
if(dobj_document)
                {
                    g_RuntimeVars.factory->Share((dobject)g_RuntimeVars.factory,dobj_document,L
"document");
                }
//set global var "System" and "document" to Javascript system
                if(JavaScriptHelper==NULL && g_RuntimeVars.env)
                {
                    
//get 'JavaScriptHelper' object from dsRE to execute PHP script
                    JavaScriptHelper=g_RuntimeVars.env->GetSharedObject(L"JavaScriptHelper");
                    
if(JavaScriptHelper)
                    {
                        dValue ret;
//这一步让msscript.ocx中的js可以访问网页document【特注1】
                        
char *document_code="document=dvm.GetSharedObject(\"document\");";
                        JavaScriptHelper->Invoke((dobject)NULL,L
"Execute",document_code,strlen(document_code),&ret);//execute JavaScript

                      
//这一步让msscript.ocx中的js可以调用MFC C++中的函数【特注2】
                        
char *System_code="sys=dvm.GetSharedObject(\"System\");";
                        JavaScriptHelper->Invoke((dobject)NULL,L
"Execute",System_code,strlen(System_code),&ret);//execute JavaScript

                        
char *alert_code="function alert(msg,title,type){sys.alert(msg,title,type);}";
                        JavaScriptHelper->Invoke((dobject)NULL,L
"Execute",alert_code,strlen(alert_code),&ret);//execute JavaScript

                        
/*char *test="alert('ddddddd');";
                        JavaScriptHelper->Invoke((dobject)NULL,L"Execute",test,strlen(test),&ret);//execute JavaScript*/

                    }
                }
       ...
    }
}

【特注1】通过Composite Bridges的共享对象,使当前MFC的基于CHtmlView的IDispatch对象“进入”js脚本中,方便js操纵。如果在设计中不使用Composite Bridges,则可以编写一个基于IDispatch的COM对象,通过 new ActiveXObject(...)语句创建这个COM对象,然后通过这个对象的某个函数调用的返回值使得CHtmlView对象进入msscript.ocx中的js。

【特注2】System对象用于js操纵C++的函数的。如果不使用哦Composite Bridges技术,就像【特注1】中一样写个COM进入js就是可以了。

Composite Bridges 由于支持脚本调用 Windows API,是理想的脚本扩展类库。同时,Composite Bridges 还支持 VCL 调用,可以作为界面的补充。虽然 Composite Bridges 还能支持.NET调用。不过,无论PHP还是js,都可以通过COM间接调用.NET的,所以不用多此一举。


2 js脚本部分
  这里只列举 CreateWindow 这个API,其他的API可以举一反三:


function CreateWindow(lpClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam)
{
 
/*
  HWND
  WINAPI
  CreateWindowExA(
    DWORD dwExStyle,
    LPCSTR lpClassName,
    LPCSTR lpWindowName,
    DWORD dwStyle,
    int X,
    int Y,
    int nWidth,
    int nHeight,
    HWND hWndParent,
    HMENU hMenu,
    HINSTANCE hInstance,
    LPVOID lpParam);
 
*/
 param
=new dobject("ApiParams");
 param.AppendSignedLong(
0);
 param.AppendAsciiString(lpClassName);
 param.AppendAsciiString(lpWindowName);
 param.AppendSignedLong(dwStyle);
 param.AppendSignedLong(x);
 param.AppendSignedLong(y);
 param.AppendSignedLong(nWidth);
 param.AppendSignedLong(nHeight);
 param.AppendHandlePointer(hWndParent);
 param.AppendHandlePointer(hMenu);
 param.AppendHandlePointer(hInstance);
 param.AppendHandlePointer(lpParam);
return os_api.CallOSAPI(null,"CreateWindowExA",param);
}