A new method of software interface design (pick)

Source: Internet
Author: User
Tags bool extend visual studio
Design keywords: COM myspy IE setuihanlder icustomdoc idochostuihandler getexternal

Objective

In solving various problems, the author prefers to use C + + Builder first to try, this article is the same, but this does not affect the users of other development tools to read, because this is the development of Microsoft technology, the choice of what tools is not important, we understand his principle can use any tool to achieve the same function.

Body

Friends who have used vc.net may know that a new web-based interface design approach is available in vc.net, but there may be very few people who actually use it, at least I have not seen such an interface design method in domestic software. The original use of Vc.net hope that the next version of BCB can add such a flexible interface design method, but not until now, I think can not always wait, so on their own study of the implementation method, finally let me study out. This article is to discuss this method, as well as the feasibility of software design design.

Said so much, may have friends do not know what this interface is different, what are the advantages? If you have the same sense of curiosity, please keep looking.

Under the Windows2000, we often use the Control Panel/Add, Uninstall Software dialog box is based on such an interface (XP is temporarily unclear), I do not say it may be very few people know-the dialog box is a whole page? What, you don't believe me? If this is why the Web page can interact with a local computer program? Why not select the text inside the page? Why can't I pop the right button menu? If it's a Web page, where is its HTML code?

To prove the above, we need some special software, this software is written by the author of Myspy, can go to the author's site (http://siney.yeah.net) for free download, we can see from the Myspy interface to add/ The Delete program's dialog box is an Internet explorer_server, which means it is a Web page,


The address of this page can also be seen on the Myspy Web page: Res://sp3res.dll/default.hta,




The next step is to use Myspy to get the code for this page (you can't directly right-click to get the code), in part as follows:





<meta http-equiv=content-type content= "text/html; charset=gb2312 "><base href=res://appwiz.cpl/><link href=" Arp.css "Type=text/css rel=stylesheet>

<style>>ctls\:P Laces {behavior:url (PLACES.HTC);} Ctls\:listbox {behavior:url (LISTBOX.HTC);} Ctls\:accel {behavior:url (ACCEL.HTC);}. Placesbar {Background-color:threedshadow}. Hide {Display:none}. Nonclientbackground {background-color:buttonface}. Header {padding-bottom:5px;vertical-align:text-top;}. groupimage {margin-right:5px}. Groupdesc {padding-left:1em;padding-right:1em}. Appnamerow {}. appimagetd {width:20px; padding: ' 4px 2px 2px 2px '; InfoPane {padding-top:4px; vertical-align:top;}. Proplabel {width:7em;padding-top:2px;padding-bottom:2px;padding-right:3px;text-align:right}. PropValue {width:6em;text-align:right;padding-right:7px}. Addproplabel {padding-top:2px;padding-bottom:2px;padding-right:3px;text-align:right}. Addpropvalue {width:13em;text-align:right;padding-right:7px}. Buttondescpane {padding-top:5px; padding-bottom:7px;padding-right:5px;}. buttonpane {width:15em; padding:5px; text-align:right;}. Fakeanchor {Cursor:hand;} #idClIentcatname {Font-weight:bold;padding-bottom:1ex}. Disabled {Color:graytext;} #idTblExtendedProps. Focus {Color:highlighttext} </STYLE>





Ho-ho, is not very magical, this is just an example of an application, in fact, there are many software interface using the above method to create an interface, such as Norton Antivirsu,ms Visual studio.net,c# Builder. In fact, in-depth thinking, such an interface is the most difficult is how to interact with the local code, why the click of a button in the Web page to execute their own code? People who have experience in COM programming might think of writing an external object with COM, creating the object in a Web page using a script, and then calling the object's method seem to accomplish this function? But there are a lot of bad places here:

1. Need to register COM local running security, otherwise IE will have security warning, this is certainly the end users do not want to see;

2. Users can easily get the use of COM objects from the HTML code (like the one above with Myspy code) so they can easily use your COM object to complete their own interface, which is not discreet and unsafe.

There may be more bad places, but the authors do not expect that, because Microsoft and other software companies do not do so, they may know more. Here we will discuss a secure and covert implementation approach.

Starting with IE4, Microsoft provides a Icustomdoc interface, Icustomdoc Setuihandler allows users to set up a IDocHostUIHandler based interface to take over the interface processor. There are a number of virtual methods available in IDocHostUIHandler that require programmers to overload them to implement different customization functions, and here's an article detailing the information http://msdn.microsoft.com/library/default.asp ? url=/workshop/browser/hosting/wbcustomization.asp, where we need to overload the GetExternal method to extend the IE DOM, if we successfully extend the DOM, So that's how we can write HTML code to interact with local programs, for example:








<script language= "JScript" >

function MyFunc ()

{

External. HelloWorld (); HelloWorld is the way we expand

}

</SCRIPT>


<body>

<input type= "button" value= "Show Hello World" onclick= "MyFunc ();"/>

</body>




HelloWorld is a way to expand, when the external object calls the HelloWorld method to invoke the local code when the button is clicked, and the external object invokes the GetExternal method mentioned above to query whether the extension is provided. Here's how to implement the GetExternal method to implement an extended external object with the following code:

Class Mydochandler:p ublic IDocHostUIHandler

{

Long RefCount;

Public

Mydochandler (): RefCount (1) {}

Virtual HRESULT stdmethodcalltype QueryInterface (Refiid classid, void** intf) {

if (ClassID = = IID_IUnknown)

{

*intf = (iunknown*) this;

AddRef ();

}

else if (ClassID = = Iid_idochostuihandler)

{

*intf = (idochostuihandler*) this;

AddRef ();

}

else if (ClassID = = IID_IDispatch)

{

*intf = (idispatch*) this;

AddRef ();

}

Else

return e_nointerface;

return S_OK;

}

Virtual ULONG stdmethodcalltype AddRef () {

InterlockedIncrement (&refcount);

return refcount;

}

Virtual ULONG Stdmethodcalltype release () {

InterlockedDecrement (&refcount);

if (refcount = 0)

Delete this;

return refcount;

}

Back to S_OK, screen off the right button menu

Virtual HRESULT stdmethodcalltype showcontextmenu (

/* [in]/DWORD Dwid,

/* [in] * __rpc_far *ppt,

/* [in] * * IUnknown __rpc_far *pcmdtreserved,

/* [in] * * IDispatch __rpc_far *pdispreserved) {

return S_OK;

}

Virtual HRESULT stdmethodcalltype gethostinfo (

/* [Out][in] */dochostuiinfo __rpc_far *pinfo) {

return E_NOTIMPL;

}

Virtual HRESULT stdmethodcalltype ShowUI (

/* [in]/DWORD Dwid,

/* [in] * * IOleInPlaceActiveObject __rpc_far *pactiveobject,

/* [in] * * IOleCommandTarget __rpc_far *pcommandtarget,

/* [in] * * IOleInPlaceFrame __rpc_far *pframe,

/* [in] * * IOleInPlaceUIWindow __rpc_far *pdoc) {

return E_NOTIMPL;

}

Virtual HRESULT stdmethodcalltype hideui (void) {

return E_NOTIMPL;

}

Virtual HRESULT stdmethodcalltype updateui (void) {

return E_NOTIMPL;

}

Virtual HRESULT stdmethodcalltype enablemodeless (

/* [in]/BOOL fenable) {

return E_NOTIMPL;

}

Virtual HRESULT stdmethodcalltype ondocwindowactivate (

/* [in]/BOOL factivate) {

return E_NOTIMPL;

}

Virtual HRESULT stdmethodcalltype onframewindowactivate (

/* [in]/BOOL factivate) {

return E_NOTIMPL;

}

Virtual HRESULT stdmethodcalltype resizeborder (

/* [in] * * Lpcrect Prcborder,

/* [in] * * IOleInPlaceUIWindow __rpc_far *puiwindow,

/* [in]/BOOL FrameWindow) {

return E_NOTIMPL;

}

Virtual HRESULT stdmethodcalltype translateaccelerator (

/* [in] * * lpmsg lpmsg,

/* [in] */const GUID __RPC_FAR *pguidcmdgroup,

/* [in] */DWORD nCmdID) {

return E_NOTIMPL;

}

Virtual HRESULT stdmethodcalltype GetOptionKeyPath (

/* [out] * * LPOLESTR __rpc_far *pchkey,

/* [in] * * DWORD DW) {

return E_NOTIMPL;

}

Virtual HRESULT stdmethodcalltype getdroptarget (

/* [in] * * IDropTarget __rpc_far *pdroptarget,

/* [out] */idroptarget __rpc_far *__rpc_far *ppdroptarget) {

return E_NOTIMPL;

}

Virtual HRESULT stdmethodcalltype getexternal (

/* [out] */IDispatch __rpc_far *__rpc_far *ppdispatch) {

*ppdispatch = new Mycommandhandler ();

return S_OK;

}

Virtual HRESULT stdmethodcalltype translateurl (

/* [in]/DWORD dwtranslate,

/* [in] * * Olechar __rpc_far *pchurlin,

/* [out] */Olechar __rpc_far *__rpc_far *ppchurlout) {

return E_NOTIMPL;

}

Virtual HRESULT stdmethodcalltype filterdataobject (

/* [in] * * IDataObject __rpc_far *pdo,

/* [out] */IDataObject __rpc_far *__rpc_far *ppdoret) {

return E_NOTIMPL;

}

};


The above overloaded the ShowContextMenu method to screen off the right button menu, so that users can not get the page code, about GetExternal is achieved:

Virtual HRESULT stdmethodcalltype getexternal (

/* [out] */IDispatch __rpc_far *__rpc_far *ppdispatch) {

*ppdispatch = new Mycommandhandler ();

return S_OK;

}


You can see that simply returning the Mycommandhandler object, Mycommandhandler must inherit from the IDispatch interface to implement the calling method that supports automation, which is achieved by:

Class Mycommandhandler:public IDispatch

{

Long RefCount;

Public

Mycommandhandler (): RefCount (1) {}

Virtual HRESULT stdmethodcalltype gettypeinfocount (

/* [out] */UINT *pctinfo) {

return S_OK;

}

Virtual HRESULT stdmethodcalltype gettypeinfo (

/* [in] * * UINT itinfo,

/* [in] */LCID LCID,

/* [out] */ITypeInfo **pptinfo) {

return S_OK;

}

Virtual HRESULT stdmethodcalltype getidsofnames (

/* [in] * * REFIID riid,

/* [Size_is][in] * * LPOLESTR *rgsznames,

/* [in] * * UINT cnames,

/* [in] */LCID LCID,

/* [Size_is][out] */DISPID *rgdispid) {

*rgdispid=1;

return S_OK;

}

Virtual/* [local]/HRESULT stdmethodcalltype Invoke (

/* [in] * * DISPID Dispidmember,

/* [in] * * REFIID riid,

/* [in] */LCID LCID,

/* [in] * wflags WORD,

/* [Out][in] * * Dispparams *pdispparams,

/* [out] */VARIANT *pvarresult,

/* [out] * * Excepinfo *pexcepinfo,

/* [out] */UINT *puargerr) {

if (dispidmember==1)

{

MessageBox (0, "Hello World", "Hello", 0); Place your code here

frmweb->edit1->text= "Hello World" (which also can?) )";

}

return S_OK;

}

Virtual HRESULT stdmethodcalltype QueryInterface (Refiid classid, void** intf) {

if (ClassID = = IID_IDispatch)

{

*intf = (idispatch*) this;

AddRef ();

}

Else

return e_nointerface;

return S_OK;

}

Virtual ULONG stdmethodcalltype AddRef () {

InterlockedIncrement (&refcount);

return refcount;

}

Virtual ULONG Stdmethodcalltype release () {

InterlockedDecrement (&refcount);

if (refcount = 0)

Delete this;

return refcount;

}

};


If you understand some of the COM knowledge, we know that the key here is the implementation of the GetIDsOfNames and invoke methods, because automation objects can only be invoked in this way, rather than using function pointers to invoke virtual methods directly, GetIDsOfNames the invocation ID of the specified function name, that is, if there is a method that is "HelloWorld", it will first invoke the GetIDsOfNames method to query whether the method supports the If supported, give the invocation ID of the method (by modifying the rgdispid[out] parameter) and return E_NOTIMPL if not supported, his implementation is simple as follows:

Virtual HRESULT stdmethodcalltype getidsofnames (

/* [in] * * REFIID riid,

/* [Size_is][in] * * LPOLESTR *rgsznames,

/* [in] * * UINT cnames,

/* [in] */LCID LCID,

/* [Size_is][out] */DISPID *rgdispid) {

*rgdispid=1;

return S_OK;

}


Here we assume that there is only one extension function HelloWorld, and if there are multiple, we need to compare the function name of the Rgsznames parameter to return a different call ID, with the invocation ID, the implementation of the Invoke method is simple:

Virtual HRESULT stdmethodcalltype Invoke (

/* [in] * * DISPID Dispidmember,

/* [in] * * REFIID riid,

/* [in] */LCID LCID,

/* [in] * wflags WORD,

/* [Out][in] * * Dispparams *pdispparams,

/* [out] */VARIANT *pvarresult,

/* [out] * * Excepinfo *pexcepinfo,

/* [out] */UINT *puargerr) {

if (dispidmember==1)

{

MessageBox (0, "Hello World", "Hello", 0); Place your code here

frmweb->edit1->text= "Hello World" (which also can?) )";

}

return S_OK;

}


Depending on the dispidmember to implement different code, if the method has parameters can be obtained in the pdispparams, if there is any do not understand can refer to MSDN and some COM books, here is not explained in detail.

The last thing we need to do is to make our browsers know that we have expanded the external code as follows:

Dochandler = new Mydochandler;

Webbrowser->navigate (widestring (L "e:\\projects\\extweb\\ext.htm"));

while (WEBBROWSER-&GT;BUSY)

Application->processmessages ();

Icustomdoc *custdoc;

Webbrowser->document->queryinterface (&custdoc); Get Icustomdoc interface

if (Custdoc)

{

Custdoc->setuihandler (Dochandler); Set up our own interface processor

Custdoc->release ();

}


Note that the above bold "our browser", because such an extension is only for the use of WebBrowser controls in their own programs, does not affect the expansion of IE itself, That is to say that the ext.htm file can only be valid in our program, even if other users get this section of HTM code can not run normally, if you want to test, you get:


Because they don't know how to extend the external object, this solves the problem of using COM as we said earlier.

To tell the truth design such an interface is still a certain degree of difficulty, then it in the actual development of what benefits? I would like to have at least the following points:

1. Interface design and program logic design separation, art can work with programmers, interface design is no longer no aesthetic cell programmer problem;

2. Easy implementation of the skin function, the interface changes do not need to recompile the code, just need to change a different HTM code file can be;

3. Can no longer use the spy tool to get forms handler do various hooks, so that your program to run more secure;

4. Fully use IE existing technology, build more powerful software;

5. Make your software look cooler and more professional.



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.