浏览器的定制与扩展

下载源代码

本文分如下章节:

  • 前言
  • 在MFC中使用浏览器
  • 怎样扩展或定制浏览器
  • 定制鼠标右键弹出出菜单
  • 实现脚本扩展(很重要的external接口)
  • C++代码中如何调用网页脚本中的函数
  • 定制消息框的标题
  • 怎样定制、修改浏览器向Web服务器发送的HTTP请求头
  • 怎样修改浏览器标识
  • 去掉讨厌的异常警告
  • 怎样处理浏览器内的拖放
  • 怎样禁止网页元素的选取
  • 其它

前言

  由于本人在开发中经常要在程序中嵌入浏览器,为了符合自己的需求经常要对浏览器进行扩展和定制, 解决这些问题需在网上找资料和学习的过程,我想可能很多开发者或许会遇到同样的问题,特写此文,以供大家参考。


在MFC中使用浏览器

  在MFC中微软为我们提供了CHtmlView、CDHtmlDialog类让我们的程序很方便的嵌入浏览器和进行浏览器的二次开发,这比直 接使用WebBrowser控件要方便很多,所以本文中讨论的浏览器的问题都是针对CHtmlView来讨论的。文中将提到一个类CLhpHtmlView, 它是CHtmlView的派生类,文中提及的扩展或定制都将在CLhpHtmlView类(或派生类)上实现。


怎样扩展或定制浏览器

  浏览器定义了一些扩展接口(如IDocHostUIHandler可以定制浏览器界面有关的行为),以便开发者进行定制和扩展。浏览 器会在需要的时候向他的控制站点查询这些接口,在控制站点里实现相应的接口就可以进行相应的扩展。在MFC7.01类 库中,CHtmlView使用的控制站点是CHtmlControlSite的,在CHtmlControlSite类中 只实现了接口IDocHostUIHandler, 而要实现更多的扩展接口,必须用自定义的控制站类来取代CHtmlControlSite,在下文中提及的类CDocHostSite即为自定义 的控制站类。

关于接口的介绍请参考:
http://dev.csdn.net/develop/article/48/48483.shtm 

如何使自定义的控制站点来替换默认的控制站点呢?在MFC7.0中只需重载CHtmlView的虚函数CreateControlSite即可:

BOOL CLhpHtmlView::CreateControlSite(COleControlContainer * pContainer, 
COleControlSite ** ppSite, UINT /*nID*/, REFCLSID /*clsid*/)
{*ppSite = new CDocHostSite(pContainer, this);// 创建自己的控制站点实例return (*ppSite) ? TRUE : FALSE;
}
VC6.0要替换控制站要复杂的多,这里就不讨论了,如需要6.0版本的请给我发邮件到yourshine@21cn.com。


定制鼠标右键弹出出菜单

  要定制浏览器的鼠标右键弹出菜单,必须在自定义的控制站点类中实现IDocHostUIHandler2接口,并且IE的 版本是5.5或以上。在接口IDocHostUIHandler2的ShowContextMenu方法中调用浏览器类的OnShowContextMenu虚函数,我们 在浏览器类的派生类重载此虚函数即可实现右键菜单的定制,参见代码
HRESULT CDocHostSite::XDocHostUIHandler::ShowContextMenu(DWORD dwID,POINT * ppt,IUnknown * pcmdtReserved,IDispatch * pdispReserved)
{METHOD_PROLOGUE(CDocHostSite, DocHostUIHandler);return pThis->m_pView->OnShowContextMenu( dwID, ppt, pcmdtReserved,pdispReserved );
}HRESULT CLhpHtmlView::OnShowContextMenu(DWORD dwID, LPPOINT ppt,LPUNKNOWN pcmdtReserved, LPDISPATCH pdispReserved)
{HRESULT result = S_FALSE;switch(m_ContextMenuMode){case NoContextMenu:			// 无菜单result=S_OK;break;case DefaultMenu:				// 默认菜单break;case TextSelectionOnly:			// 仅文本选择菜单if(!(dwID == CONTEXT_MENU_TEXTSELECT || dwID == CONTEXT_MENU_CONTROL))result=S_OK;break;case CustomMenu:				// 自定义菜单if(dwID!=CONTEXT_MENU_TEXTSELECT)result=OnShowCustomContextMenu(ppt,pcmdtReserved,pdispReserved);break;}return result;
}		
在CLhpHtmlView中定义的枚举类型CONTEXT_MENU_MODE举出了定制右键弹出菜单的四种类型
enum CONTEXT_MENU_MODE		// 上下文菜单
{NoContextMenu,		// 无菜单DefaultMenu,		// 默认菜单TextSelectionOnly,		// 仅文本选择菜单CustomMenu		// 自定义菜单
};
  通过CLhpHtmlView的函数SetContextMenuMode来设置右键菜单的类型。如果设定的右键弹出菜单是“自定义菜单”类型, 我们只要在CLhpHtmlView的派生类中重载OnShowCustomContextMenu虚函数即可,如下代码 CDemoView是CLhpHtmlView的派生类
HRESULT CDemoView::OnShowCustomContextMenu(LPPOINT ppt, LPUNKNOWN pcmdtReserved,LPDISPATCH pdispReserved)
{if ((ppt==NULL)||(pcmdtReserved==NULL)||(pcmdtReserved==NULL))return S_OK;HRESULT hr=0;IOleWindow *oleWnd=NULL;hr=pcmdtReserved->QueryInterface(IID_IOleWindow, (void**)&oleWnd);if((hr != S_OK)||(oleWnd == NULL))return S_OK;HWND hwnd=NULL;hr=oleWnd->GetWindow(&hwnd);if((hr!=S_OK)||(hwnd==NULL)){oleWnd->Release();return S_OK;}IHTMLElementPtr	pElem=NULL;hr = pdispReserved->QueryInterface(IID_IHTMLElement, (void**)&pElem);if(hr != S_OK){oleWnd->Release();return S_OK;}IHTMLElementPtr	pParentElem=NULL;_bstr_t	tagID;BOOL go=TRUE;pElem->get_id(&tagID.GetBSTR());while(go && tagID.length()==0){hr=pElem->get_parentElement(&pParentElem);if(hr==S_OK && pParentElem!=NULL){pElem->Release();pElem=pParentElem;pElem->get_id(&tagID.GetBSTR());}elsego=FALSE;};if(tagID.length()==0)tagID="no id";CMenu Menu,SubMenu;Menu.CreatePopupMenu();CString strTagID = ToStr(tagID);if(strTagID == "red")Menu.AppendMenu(MF_BYPOSITION, ID_RED, "您点击的是红色");else if(strTagID == "green")Menu.AppendMenu(MF_BYPOSITION, ID_GREEN, "您点击的是绿色");else if(strTagID == "blue")Menu.AppendMenu(MF_BYPOSITION, ID_BLUE, "您点击的是蓝色");elseMenu.AppendMenu(MF_BYPOSITION, ID_NONE, "你点了也白点,请在指定的地方点击");int MenuID=Menu.TrackPopupMenu(TPM_RETURNCMD|TPM_LEFTALIGN|TPM_RIGHTBUTTON,ppt->x, ppt->y, this);switch(MenuID){case ID_RED:MessageBox("红色");break;case ID_GREEN:MessageBox("红色");break;case ID_BLUE:MessageBox("红色");break;case ID_NONE:MessageBox("haha");break;}oleWnd->Release();pElem->Release();return S_OK;
}		

实现脚本扩展(很重要的external接口)


  在你嵌入了浏览器的工程中,如果网页的脚本中能调用C++代码,那将是一件很惬意的事情,要实现这种交互,就必须实现脚本扩展。实现脚本扩展就是在程序中实现一个IDispatch接口,通过CHtmlView类的OnGetExternal虚函数返回此接口指针,这样就可以在脚本中通过window.external.XXX(关键字window可以省略)来 引用接口暴露的方法或属性(XXX为方法或属性名)。在MFC中从CCmdTarget派生的类都可以实现自动化,而不必在MFC工程中引入繁杂的ATL。从CCmdTarget派生的类实现自动化接口的时候不要忘了在构造函数中调用EnableAutomation函数。
  要使虚函数OnGetExternal发挥作用必须在 自定义的控制站点类中实现IDocHostUIHandler,在接口IDocHostUIHandler的GetExternal方法中调用浏览器类的OnGetExternal虚函数,我们在浏览器类的派生类重载OnGetExternal虚函数, 通过参数lppDispatch返回一个IDispatch指针,这样脚本中引用window.external时就是引用的返回的接口,参见代码
HRESULT CDocHostSite::XDocHostUIHandler::GetExternal(IDispatch ** ppDispatch)
{METHOD_PROLOGUE(CDocHostSite, DocHostUIHandler);return pThis->m_pView->OnGetExternal( ppDispatch );
}CLhpHtmlView::CLhpHtmlView(BOOL isview)
{......EnableAutomation();// 允许自动化
}HRESULT CLhpHtmlView::OnGetExternal(LPDISPATCH *lppDispatch)
{*lppDispatch = GetIDispatch(TRUE);// 返回自身的IDispatch接口return S_OK;
}      
请注意上面代码中,在OnGetExternal返回的是自身IDispatch接口, 这样就不比为脚本扩展而另外写一个从CCmdTarget派生的新类, CLhpHtmlView本身就是从CCmdTarget派生,直接在上面实现接口就是。

下用具体示例来说明怎样实现脚本扩展

示例会在网页上点击一个按钮而使整个窗口发生抖动

从CLhpHtmlView派生一个类CDemoView,在类中实现IDispatch, 并通过IDispatch暴露方法WobbleWnd
---------------------------------------------------------------------------
文件 DemoView.h
---------------------------------------------------------------------------
.......
class CDemoView : public CLhpHtmlView
{......DECLARE_DISPATCH_MAP() // 构建dispatch映射表以暴露方法或属性......void WobbleWnd();// 抖动窗口
};---------------------------------------------------------------------------
文件 DemoView.cpp
---------------------------------------------------------------------------......// 把成员函数映射到Dispatch映射表中,暴露方法给脚本
BEGIN_DISPATCH_MAP(CDemoView, CLhpHtmlView)DISP_FUNCTION(CDemoView, "WobbleWnd", WobbleWnd, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()......void CDemoView::WobbleWnd()
{// 在这里实现抖动窗口......
}---------------------------------------------------------------------------
文件 Demo.htm
---------------------------------------------------------------------------...... οnclick="external.WobbleWnd()" ......		
这里我要介绍一下DISP_FUNCTION宏,它的作用是将一个函数映射到Dispatch映射表中,我们看
DISP_FUNCTION(CDemoView, "WobbleWnd", WobbleWnd, VT_EMPTY, VTS_NONE)

CDemoView是宿主类名, "WobbleWnd"是暴露给外面的名字(脚本调用时使用的名字), VT_EMPTY是返回值得类型为空,VTS_NONE说明此方法没有参数,如果要映射的函数有返回值和参数该 如何映射,通过下面举例来说明

DISP_FUNCTION(CCalendarView,"TestFunc",TestFunc,VT_BOOL,VTS_BSTR VTS_I4 VTS_I4)BOOL TestFunc(LPCSTR param1, int param2, int param3)
{.....
}		
  参数表VTS_BSTR VTS_I4 VTS_I4是用空格分隔,他们的类型映射请参考MSDN,这要提醒的是不要把VTS_BSTR与CString对应,而应与LPCSTR对应。


C++代码中如何调用网页脚本中的函数

  IHTMLDocument2::scripts属性表示HTML文档中所有脚本对象。使用脚本对象的IDispatch接口的GetIDsOfNames方法可以得到脚本函数的 DispID,得到DispID后,使用IDispatch的Invoke函数可以调用对应的脚本函数。CLhpHtmlView提供了方便的调用JavaScript的函数,请参考CLhpHtmlView中有关键字“JScript”的代码。


定制消息框的标题

  我们在脚本中调用alert弹出消息框时,消息框的标题是微软预定义的“Microsoft Internet Explorer”,如下图:

ReBrwmsgbox.gif

  在自定义的控制站点类中实现IDocHostShowUI接口,在接口的ShowMessage方法中调用浏览器的OnShowMessage,我们重载 OnShowMessage虚函数即可定制消息框的标题,实现代码如下:
// 窗口标题"Microsoft Internet Explorer"的资源标识
#define IDS_MESSAGE_BOX_TITLE 2213
HRESULT CLhpHtmlView::OnShowMessage(HWND hwnd,LPOLESTR lpstrText,LPOLESTR lpstrCaption,DWORD dwType,LPOLESTR lpstrHelpFile,DWORD dwHelpContext,LRESULT * plResult)
{//载入Shdoclc.dll 和IE消息框标题字符串HINSTANCE hinstSHDOCLC = LoadLibrary(TEXT("SHDOCLC.DLL"));if (hinstSHDOCLC == NULL)return S_FALSE;CString strBuf,strCaption(lpstrCaption);strBuf.LoadString(hinstSHDOCLC, IDS_MESSAGE_BOX_TITLE);// 比较IE消息框标题字符串和lpstrCaption// 如果相同,用自定义标题替换if(strBuf==lpstrCaption)strCaption = m_DefaultMsgBoxTitle;// 创建自己的消息框并且显示*plResult = MessageBox(CString(lpstrText), strCaption, dwType);//卸载Shdoclc.dll并且返回FreeLibrary(hinstSHDOCLC);return S_OK;
}		
从代码中可以看到通过设定m_DefaultMsgBoxTitle的值来改变消息宽的标题,修改此值是同过SetDefaultMsgBoxTitle来实现
void CLhpHtmlView::SetDefaultMsgBoxTitle(CString strTitle)
{m_DefaultMsgBoxTitle=strTitle;
}

怎样定制、修改浏览器向Web服务器发送的HTTP请求头


  在集成了WebBrowser控件的应用中,Web服务器有时可能希望客户端(浏览器)发送的HTTP请求中附带一些额外的信息或自定义的 HTTP头字段,这样就必须在浏览器中控制向Web服务器发送的HTTP请求。 下面是捕获的一个普通的用浏览器发送的HTTP请求头:
GET /text7.htm HTTP/1.0
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, \
application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Referer: http://localhost
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Poco 0.31; LHP Browser 1.01; \
.NET CLR 1.1.4322)
Host: localhost
Connection: Keep-AliveCHtmlView的 
void Navigate2(LPCTSTR lpszURL,DWORD dwFlags = 0,LPCTSTR lpszTargetFrameName = NULL,LPCTSTR lpszHeaders = NULL,LPVOID lpvPostData = NULL,DWORD dwPostDataLen = 0 
);
函数参数lpszHeaders可以指定HTTP请求头,示例如下:
Navigate2(_T("http://localhost"),NULL,NULL, "MyDefineField: TestValue");
我们捕获的HTTP头如下:

ReBrwHHd.gif



怎样修改浏览器标识


  在HTTP请求头中User-Agent字段表明了浏览器的版本以及操作系统的版本等信息。WEB服务器经常需要知道用户请求页面时是来自IE还是来自自己的客户端中的WebBrowser控件, 以便分开处理,而WebBrowser控件向WEB服务器发送的浏览器标识(User-Agent字段)跟用IE发送的是一样的,怎样区分自己的浏览器和IE呢? 微软没有提供现成的方法,要自己想法解决。 前面讨论的定制HTTP请求头就是为这一节准备的。 思路是这样的: 在自己的浏览器里处理每一个U页面请求,把请求头User-Agent改成自己想要的。 在CHtmlView的OnBeforeNavigate2虚函数里来修改HTTP请求是再好不过了,
#define WM_NVTO		(WM_USER+1000)class NvToParam
{
public:CString URL;DWORD Flags;CString TargetFrameName;CByteArray PostedData;CString Headers;
};void CDemoView::OnBeforeNavigate2(LPCTSTR lpszURL, DWORD nFlags, LPCTSTR lpszTargetFrameName, CByteArray& baPostedData, LPCTSTR lpszHeaders, BOOL* pbCancel)
{CString strHeaders(lpszHeaders);if(strHeaders.Find("User-Agent:LHPBrowser 1.0") < 0)// 检查头里有没有自定义的User-Agent串{*pbCancel = TRUE;// 没有,取消这次导航if(!strHeaders.IsEmpty())strHeaders += "\r\n";strHeaders += "User-Agent:LHPBrowser 1.0";// 加上自定义的User-Agent串NvToParam* pNvTo = new NvToParam;pNvTo->URL = lpszURL;pNvTo->Flags = nFlags;pNvTo->TargetFrameName = lpszTargetFrameName;baPostedData.Copy(pNvTo->PostedData);pNvTo->Headers = strHeaders;// 发送一个自定义的导航消息,并把参数发过去PostMessage(WM_NVTO,(WPARAM)pNvTo);return;}CHtmlView::OnBeforeNavigate2(lpszURL, nFlags, lpszTargetFrameName, baPostedData, lpszHeaders, pbCancel);
}LRESULT CDemoView::OnNvTo(WPARAM wParam, LPARAM lParam)
{NvToParam* pNvTo = (NvToParam*)wParam;Navigate2((LPCTSTR)pNvTo->URL, pNvTo->Flags, pNvTo->PostedData, (LPCTSTR)pNvTo->TargetFrameName, (LPCTSTR)pNvTo->Headers);delete pNvTo;return 1;
}
  在OnBeforeNavigate2中如果发现没有自定义的User-Agent串,就加上这个串,并取消本次导航,再Post一个消息(一定要POST,让OnBeforeNavigate2跳出以后再进行导航 ),在消息中再次导航,再次导航时请求头已经有了自己的标识,所以能正常的导航。


去掉讨厌的异常警告

  在程序中使用了CHtmlView以后,我们在调整窗口大小的时候经常会看到输出窗口输出的异常警告: ReusingBrowser.exe 中的 0x77e53887 处最可能的异常: Microsoft C++ exception: COleException @ 0x0012e348 。
Warning: constructing COleException, scode = DISP_E_MEMBERNOTFOUND($80020003).
这是由于CHtmlView在处理WM_SIZE消息时的一点小问题引起的,采用如下代码处理WM_SIZE消息就不会有此警告了
void CLhpHtmlView::OnSize(UINT nType, int cx, int cy)
{CFormView::OnSize(nType, cx, cy);if (::IsWindow(m_wndBrowser.m_hWnd)) { CRect rect; GetClientRect(rect); // 就这一句与CHtmlView的不同::AdjustWindowRectEx(rect, GetStyle(), FALSE, WS_EX_CLIENTEDGE);m_wndBrowser.SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOACTIVATE | SWP_NOZORDER); } 
}

怎样处理浏览器内的拖放


  有时可能有这样的需求,我们希望在资源管理器里托一个文件到浏览器而做出相应的处理,甚至是将文件拖到某一个网页元素上来做出相应的处理,而浏览器默认的处理拖放文件操作是将文件打开,但WebBrowser控件给了我们一个自己处理拖放的机会。 那就是在自定义的控制站点类中实现IDocHostUIHandler,在接口IDocHostUIHandler的GetDropTarget方法中调用 浏览器类的OnGetDropTarget虚函数。要处理网页内的拖放,必需在OnGetDropTarget函数中返回一个自己定义的IDropTarget接口指针, 所以我们自己写一个类CMyOleDropTarget从COleDropTarget类派生,并且在实现IDropTarget接口,此类的代码在这就不列出了,请下载演示 程序,参考文件MyOleDropTarget.h和MyOleDropTarget.cpp。我们看CLhpHtmlView中OnGetDropTarget的代码
HRESULT CLhpHtmlView::OnGetDropTarget(LPDROPTARGET pDropTarget, LPDROPTARGET* ppDropTarget )
{m_DropTarget.SetIEDropTarget(pDropTarget);LPDROPTARGET pMyDropTarget;pMyDropTarget = (LPDROPTARGET)m_DropTarget.GetInterface(&IID_IDropTarget);if(pMyDropTarget){*ppDropTarget = pMyDropTarget;pMyDropTarget->AddRef();return S_OK;}return S_FALSE;
}
  m_DropTarget即为自定义的处理拖放的对象。这样就能通过在从CLhpHtmlView派生的类中重载OnDragEnter、OnDragOver、 OnDrop、OnDragLeave虚函数来处理拖放了。在这里顺带讲一下视图是怎样处理拖放的。 要使视图处理拖放,首先在视图里添加一个COleDropTarget(或派生类)成员变量,如CLhpHtmlView中的“CMyOleDropTarget m_DropTarget;”,再在 视图创建时调用COleDropTarget对象的Register,即把视图与COleDropTarget对象关联起来,如CLhpHtmlView中的“m_DropTarget.Register(this);”,再对拖放 触发的事件进行相应的处理, OnDragEnter 把某对象拖入到视图时触发,在此检测拖入的对象是不是视图想接受的对象,如是返回“DROPEFFECT_MOVE”表示接受此对象,如
if(pDataObject->IsDataAvailable(CF_HDROP))// 被拖对象是文件吗?return DROPEFFECT_MOVE;
  OnDragOver 被拖对象在视图上移动,同OnDragEnter一样检测拖入对象,如果要接受此对象返回“DROPEFFECT_MOVE”。 OnDrop 拖着被拖对象在视图上放开鼠标,在这里对拖入对象做出处理; OnDragLeave 拖着被拖对象离开视图。 C++的代码写好了,但事情还没完,还必须在网页里用脚本对拖放事件进行处理, 即页面里哪个元素要接受拖放对象哪个元素就要处理ondragenter、ondragover、ondrop,代码其实很简单,让事件的返回值为false即可,这样 C++的代码才有机会处理拖放事件,代码如下:
......
<td οndragenter="event.returnValue = false" οndragοver="event.returnValue = false" \
οndrοp="event.returnValue = false">
......
  如果要使整个视图都接受拖放,则在Body元素中处理此三个事件。 注意:别忘了让工程对OLE的支持即在初始化应用程序时调用AfxOleInit()。


怎样禁止网页元素的选取

  用网页做界面时多数情况下是不希望网页上的元素是能够被鼠标选中的, 要使网页元素不能被选中做法是:给浏览器的“宿主信息标记”加上DOCHOSTUIFLAG_DIALOG标记。

“宿主信息标记”用N个标记位来控制浏览器的许多性质,如:
  • 禁用浏览器的3D的边缘;
  • 禁止滚动条;
  • 禁用脚本;
  • 定义双击处理的方式;
  • 禁用浏览器的自动完成功能;

...... 更多详情请参考MSDN的DOCHOSTUIFLAG帮助。

怎样修改“宿主信息标记”?

在CDocHostSite中实现IDocHostUIHandler, 在GetHostInfo方法中调用浏览器的OnGetHostInfo虚函数,在虚函数OnGetHostInfo中便可指定“宿主信息标记”,如:

HRESULT CLhpHtmlView::OnGetHostInfo(DOCHOSTUIINFO * pInfo)
{pInfo->cbSize = sizeof(DOCHOSTUIINFO);pInfo->dwFlags = DOCHOSTUIFLAG_DIALOG | DOCHOSTUIFLAG_THEME  | DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_SCROLL_NO;pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;return S_OK;
}
用脚本也可实现: 在Head中加入脚本:
document.onselectstart=new Function(''return false'');
或者
<body onselectstart="return false">。

其它


在CLhpHtmlView中还提供了几个函数, 修改网页元素的内容:
BOOL PutElementHtml(CString ElemID,CString Html);
取表单元素的值:
BOOL GetElementValue(CString ElemID,CString& Value);
设置表单元素的值:
BOOL PutElementValue(CString ElemID,CString Value);
给表单元素设置焦点:
void ElementSetFocus(CString EleName);


转载于:https://www.cnblogs.com/cdo/archive/2005/06/24/180026.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/301092.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通过反射实现IOC功能

闲来没事&#xff0c;自己就想着根据反射可以自己写一个简易的IOC组件。IOC组件说白了就是根据反射实例化对应的接口。废话不多说&#xff0c;开始说说我的解决方案。1、项目结构图&#xff1a;IOCTest为web MVC项目。Common 通过配置文件实例化对应的接口IBLL定义的接口BLL实现…

php 分享微博,php微信分享到朋友圈、QQ、朋友、微博

本文实例为大家分享了php微信分享到朋友圈、QQ、朋友、微博的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下前台代码wx.config({debug: false,appId: "{$signPackage[appId]}",timestamp: "{$signPackage[timestamp]}",nonceStr: "{$signP…

如果这个世界都不按套路出牌将会变成怎么样。。。 | 今日最佳

全世界只有3.14 % 的人关注了青少年数学之旅&#xff08;图源网络&#xff0c;侵权删&#xff09;请你有话“直”说↓ ↓ ↓

关于面试,避开这几点,成功几率更大~~~

概述 又是一个大学毕业季&#xff0c;刚好最近几年参与过很多面试&#xff0c;把其中遇到的一些具有“代表性”的面试场景总结出来和小伙伴聊聊&#xff0c;助力小伙伴跳过一些面试大坑(强烈希望)。对于面试&#xff0c;有很多小伙伴认为只是聊技术、聊能力&#xff0c;其实不仅…

脚本语言php是什么意思,php是什么脚本语言

PHP是一种简单的&#xff0c;面向对象的&#xff0c;解释型的&#xff0c;健壮的&#xff0c;安全的&#xff0c;性能非常之高的&#xff0c;独立于架构的&#xff0c;可移植的&#xff0c;动态的脚本语言。PHP具有和JAVA类似的Class关键字。因为不需要虚拟机&#xff0c;以致速…

[IOS地图开发系类]2、位置解码CLGeocoder

2019独角兽企业重金招聘Python工程师标准>>> 接第一步的操作&#xff0c;获取到地址信息经纬度后&#xff0c;我们可以对其进行解码&#xff0c;解码采用的CLGeocoder这个类&#xff0c;使用方式如下&#xff1a; 1、在ViewControlelr.m文件中声明一个CLGeocoder的…

微软相关的开发资源列表(update)

MSDN总站 http://www.msdn.com/MSDN中文站 http://www.microsoft.com/china/msdn/MSDN台湾站http://www.microsoft.com/taiwan/ASP.NET总站 http://www.asp.net/http://www.gotdotnet.com/SQLServerCentral.com is the largest free SQL Server community on the Internet. W…

备战数学建模国赛,快速搞定算法模型!

全世界只有3.14 % 的人关注了青少年数学之旅说到数学建模&#xff0c;大家的第一反应就是国赛、美赛等数学建模比赛&#xff0c;但这只是冰山一角&#xff0c;不过这个反应却也很正常&#xff0c;因为很多小伙伴接触数学建模的契机&#xff0c;大部分还是因为数学建模相关的竞赛…

考虑用Task.WhenAll

异步能在一定场景中带性能的飞跃&#xff0c;同步调用性能&#xff0c;也以带来时间的节省。先看一下被调用的api:using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Th…

wordpress home.php,WordPress主题通过function.php来加载js和css文件

WordPress主题开发的时候可以直接将需要的js或css写在head标签中&#xff0c;但是现在已经不主张这种加载方式了&#xff0c;现在WordPress主题通过function.php来加载js和css文件。基本架构//加载css及jsfunction wpdie_add_scripts() {wp_enqueue_style(style, get_template_…

国际数学大师评丘成桐:在哈佛,一人就是一个数学系

全世界只有3.14 %的人关注了青少年数学之旅丘成桐教授与蕉岭县乡亲们亲切交谈国际数学大师、阿贝尔奖获得者辛格评价丘成桐&#xff1a;“即使在哈佛&#xff0c;一个人就是一个数学系”《数学界的国王》是美国《纽约时报》刊登丘成桐人物报道的标题&#xff0c;此报道更是《纽…

你的密码已泄露!使用C#阻止弱密码

虽然&#xff0c;我们为了安全考虑&#xff0c;在注册用户时会检查密码规则&#xff0c;避免弱密码&#xff0c;比如百度的注册页面&#xff1a; 但是&#xff0c;现在的黑客也不会傻到用穷举的办法生成密码去攻击网站&#xff0c;更常用的方式是使用已泄露密码生成的字典。那这…

SVN的VS.NET插件——AnkhSVN

用了几个月SubVersionTortoiseSVN&#xff0c;感觉很不错。唯一美中不足的就是TortoiseSVN是在WINDOWS资源管理中进行操作的&#xff0c;在实际开发中&#xff0c;项目中新建了个文件&#xff0c;经常会忘记了将文件加入SVN管理。这样在下次提交时这个文件就不会被提交&#xf…

中国人数学好,数学思维差?

小天经常可以看到在微博热搜吐槽歪果仁数学不好的段子&#xff0c;比如6.8&#xff0c;我们习惯给11.8&#xff0c;让收银员找5块钱&#xff0c;但歪果仁就不行啦&#xff0c;这样他们会更乱&#xff01;所以我们容易觉得中国人数学好&#xff0c;算数特别快还准&#xff01;但…

生产力提升! 自己动手自定义Visual Studio 2019的 类创建模板,制作简易版Vsix安装包...

序言最近一直在开发 webApi 接口&#xff0c;为了方便我采用了反Restful风格开发&#xff0c;90%的接口均采用post方式&#xff0c;小部分查询采用Get方式&#xff0c;接口的入参和出参定义每次都需要手动创建2个类&#xff0c;心不累手累&#xff0c;怎么能减轻点工作&#xf…

【个人笔记】关于IO类中流的整理

学习IO部分的知识后&#xff0c;被处理流的各种类搞得有点乱&#xff0c;所以得写篇文章总结下。IO包里面有很多输入输出类&#xff0c;一般我们是通过控制流来控制输入输出的。IO包里面对于控制流分为两大类&#xff0c;一类是字节流&#xff0c;一类是字符流。字符流的两个大…

全国胸最小的省是哪个,你知道吗?| 今日最佳

全世界只有3.14 % 的人关注了青少年数学之旅&#xff08;图源网络&#xff0c;侵权删&#xff09;所以最大的是哪个省的↓ ↓ ↓

.NET Core with 微服务 - Elastic APM

上一次我们介绍了Seq日志聚合组件。这次要给大家介绍的是Elastic APM &#xff0c;一款应用程序性能监控组件。APM 监控围绕对应用、服务、容器的健康监控&#xff0c;对接口的调用链、性能进行监控。在我们实施微服务后&#xff0c;由于复杂的业务逻辑&#xff0c;服务之间的调…

java 推送数据给js,Node.js实现数据推送

场景&#xff1a;后端更新数据推送到客户端(Java部分使用Tomcat服务器)。后端推送数据的解决方案有很多&#xff0c;比如轮询、Comet、WebSocket。1. 轮询对于后端来说开发成本最低&#xff0c;就是按照传统的方式处理Ajax请求并返回数据&#xff0c;在学校的时候实验室的项目一…

【开学季限时免费】下载19880元大数据开发全链路教程(视频+源码)

随着大数据、云计算、物联网、人工智能这些行业的发展崛起&#xff0c;对于大数据人才的需求越来越大&#xff0c;而大数据人才的培养发展周期相对较长&#xff0c;导致了大数据人才短缺&#xff0c;市场供不应求。所以也就出现了大数据开发工程师、数仓工程师、ETL工程师.....…