A New Software Interface Design Method

Source: Internet
Author: User

A New Software Interface Design Method

Author: aweay

You can reprint and copy the data, but you must add the author's signature aweay. If it is used for commercial purposes, it must be approved by the author.

Download instance code

Keyword: COM myspy ie setuihanlder icustomdoc idochostuihandler getexternal

Preface

When solving various problems, the author prefers to try using C ++ builder first. This is also true for this article, but it does not affect the reading of other development tools, because it is Microsoft's development technology, it is not important to choose a tool. We understand its principle and can use any tool to implement the same function.

Body

Used VC. net friends may know that in VC. NET provides a new web-based interface design method, but few people may actually use it. At least I have never seen such an Interface Design Method in domestic software. When I first used vc.net, I hoped that the next version of BCB could add such a flexible interface design method. However, I still haven't waited until now, and I cannot wait until now, so I studied the implementation methods and finally asked me to study them. This article discusses this method and its feasibility in software design.

After talking about this, some friends may not know what the differences and advantages of this interface are? If you have the same sense of attention, please continue.

In Windows, you often use the control panel/Add or uninstall Software Dialog Box Based on this interface (it is not clear in XP ), few people may know that the dialog box is a webpage? What do you not believe? Why can a webpage interact with a local computer program? Why can't I select text on the webpage? Why can't the right-click menu be displayed? Where is the HTML code of a webpage?

In order to prove the above, we need some special software, this software is written by the author myspy, can go to the author's site (http://siney.yeah.net) free download to use, we can see from the myspy interface that the "Add/delete program" dialog box is an Internet assumer_server, which indicates that it is a webpage,

On the myspy web page, you can also see the address of this page: Res: // sp3res. dll/Default. HTA,

 

You can use myspy to obtain the code of this webpage (you cannot right-click it to obtain the Code), as shown in the following section:

 

<HTML xmlns: CTLs>

<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/: Places {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>
 

 

Zookeeper, isn't it amazing, this is just an example of an application, in fact there are many software interface using the above method to create the interface, such as Norton antivirsu, MS visual studio.net, C # builder. In fact, if you think deeply, the most difficult interface is how to interact with local code. Why can you click a button on a webpage to execute your own code? People who have experience in COM programming may think of writing an external object with COM, creating this object using scripts on the webpage, and then calling the object method seems to be able to complete this function? However, there are many disadvantages:

1. You need to register the local running security of COM. Otherwise, ie will receive a security warning, which is definitely not expected by the end user;

2. users can easily obtain the use of COM objects from HTML code (just like using myspy to Obtain Code), so that they can easily use your COM object to complete their own interface, this is not concealed and insecure.

There may be more bad things, but for now the author did not think, because Microsoft and other software companies do not do this, they may know more. Next we will discuss a safe and concealed implementation method.

Since ie4, Microsoft has provided an icustomdoc interface. The setuihandler of icustomdoc allows you to set an interface based on idochostuihandler to take over the interface processor. Many virtual methods are provided in idochostuihandler, need the programmer to reload them to implement different customization functions, here is an article detailed on these information http://msdn.microsoft.com/library/default.asp? Url =/Workshop/Browser/hosting/wbcustomization. ASP. here we need to reload the getexternal method to expand the IE Dom. If we have successfully extended the Dom, we can write HTML code to interact with local programs. For example:

 

 

<HTML>

<Head>

<Script language = "jscript">

Function myfunc ()

{

External. helloworld (); // helloworld is our extension method.

}

</SCRIPT>

</Head>

<Body>

<Input type = "button" value = "show Hello World" onclick = "myfunc ();"/>

</Body>

</Html>
 

Helloworld is an extension method. When you click the button, the external object will call the helloworld method to call the local code, for the external object, the getexternal method mentioned above is called to query whether extended object is provided. The following is how to implement the getexternal method to implement extended external object. The Code is as follows:

Class mydochandler: Public 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;

}

// Return s_ OK, blocking the right-click menu

Virtual hresult stdmethodcalltype showcontextmenu (

/* [In] */DWORD dwid,

/* [In] */point _ 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,

/* [In] */const guid _ rpc_far * pguid1_group,

/* [In] */DWORD n1_id ){

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 * ppdroptarget ){

Return e_notimpl;

}

Virtual hresult stdmethodcalltype getexternal (

/* [Out] */idispatch _ rpc_far * ppdispatch ){

* Ppdispatch = new mycommandhandler ();

Return s_ OK;

}

Virtual hresult stdmethodcalltype translateurl (

/* [In] */DWORD dwtranslate,

/* [In] */olechar _ rpc_far * pchillin,

/* [Out] */olechar _ rpc_far * ppchurchill ){

Return e_notimpl;

}

Virtual hresult stdmethodcalltype filterdataobject (

/* [In] */idataobject _ rpc_far * PDO,

/* [Out] */idataobject _ rpc_far * ppdoret ){

Return e_notimpl;

}

};
 

The showcontextmenu method is overloaded to block the right-click menu so that users cannot get webpage code. getexternal is implemented as follows:

Virtual hresult stdmethodcalltype getexternal (

/* [Out] */idispatch _ rpc_far * ppdispatch ){

* Ppdispatch = new mycommandhandler ();

Return s_ OK;

}
 

As you can see, the mycommandhandler object is simply returned. mycommandhandler must inherit from the idispatch interface to support automatic calling. It is implemented as follows:

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,

/* [Out] */itypeinfo ** pptinfo ){

Return s_ OK;

}

Virtual hresult stdmethodcalltype getidsofnames (

/* [In] */refiid riid,

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

/* [In] */uint cnames,

/* [In] */lcid,

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

* Rgdispid = 1;

Return s_ OK;

}

Virtual/* [local] */hresult stdmethodcalltype invoke (

/* [In] */dispid dispidmember,

/* [In] */refiid riid,

/* [In] */lcid,

/* [In] */word wflags,

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

/* [Out] */variant * pvarresult,

/* [Out] */partition info * ppartition info,

/* [Out] */uint * puargerr ){

If (dispidmember = 1)

{

MessageBox (0, "Hello World", "hello", 0); // place your code here

Frmweb-> edit1-> text = "Hello World (Can this be true ?) ";

}

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 know some com knowledge, we know that the key here is the implementation of the getidsofnames and invoke methods, because automatic objects can only be called in this way, instead, you cannot use a function pointer to directly call a virtual method. getidsofnames queries the call ID of the specified function name, that is, if there is a method "helloworld ", then it will first call the getidsofnames method to check whether this method is supported. If yes, it will give the call ID of this method (by modifying the rgdispid [out] parameter). If not, it will return e_notimpl, its implementation is as follows:

Virtual hresult stdmethodcalltype getidsofnames (

/* [In] */refiid riid,

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

/* [In] */uint cnames,

/* [In] */lcid,

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

* Rgdispid = 1;

Return s_ OK;

}
 

Here we assume that there is only one extension function helloworld. If there are multiple extension functions, we need to compare the function names of the rgsznames parameter to return different call IDs with the call IDs, implementing the invoke method is simple:

Virtual hresult stdmethodcalltype invoke (

/* [In] */dispid dispidmember,

/* [In] */refiid riid,

/* [In] */lcid,

/* [In] */word wflags,

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

/* [Out] */variant * pvarresult,

/* [Out] */partition info * ppartition info,

/* [Out] */uint * puargerr ){

If (dispidmember = 1)

{

MessageBox (0, "Hello World", "hello", 0); // place your code here

Frmweb-> edit1-> text = "Hello World (Can this be true ?) ";

}

Return s_ OK;

}
 

Different codes are implemented based on different dispidmember implementations. If the method has parameters, you can obtain them in pdispparams. If you have any questions, refer to msdn and some com books, I will not explain it in detail here.

The last thing we need to do is to make our browser know that we have extended external. The Code is as follows:

Dochandler = new mydochandler;

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

While (webbrowser-> busy)

Application-> processmessages ();

Icustomdoc * custdoc;

Webbrowser-> document-> QueryInterface (& custdoc); // obtain the icustomdoc Interface

If (custdoc)

{

Custdoc-> setuihandler (dochandler); // set our own interface Processor

Custdoc-> release ();

}
 

The hosts file is only valid in our program. Even if other users get this HTM code, it cannot run normally. If you want to test it, what you get is:

Because they don't know how to expand the external object, this solves the problem of using COM just now.

To tell the truth, it is still difficult to design such an interface. What are the advantages of this interface in actual development? I would like to have at least the following points:

1. The interface design is separated from the program logic design. The artist can work with the programmer, and the interface design is no longer a problem for aesthetic cell programmers;

2. It is easy to implement the skin function. You do not need to re-compile the code to change the interface. You only need to change to a different HTM code file;

3. You can no longer use the spy tool to obtain the form handler for various hooks, making your program run safer;

4. Make full use of existing ie technologies to build more powerful software;

5. Make your software look cooler and more professional.

How is it? Is it exciting? Improve your interface. If you have more ideas, you can get in touch with siney@yeah.net.

 

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.