A new software interface design method

zhaozj2021-02-16  62

Written: aw Ready

You can reprint, copy, but you must join the author's signature Aweay. If you are used for commercial purposes, you must agree.

Keywords: com myspy ie setuihander iCustomDoc IDOCHOSTUIHANDLER GETEXTERNAL

Foreword

In this article, the author likes to try to use C Builder when solving various problems, but this article does not affect other developments of users to read, because this is Microsoft's development technology, what tools are not important We understand that his principle can use any tool to achieve the same function.

text

Friends who have used VC.NET may know that a new web-based interface design method is available in VC.NET, but there may be very few people, at least I have seen this in domestic software. Interface design method. When using VC.NET, I hope that the next version of BCB can join such a flexible interface design method, but it hasn't waited yet, I don't think I can't wait until it is, so I have to study it. The implementation method, finally let I studied it. This article is to discuss such methods and feasibility in software design design.

Said so much, there may be friends, I don't know what the interface is different, what is the advantage? If you have the same curiosity, please continue to look.

Under Windows2000, everyone often uses control panels / adds, uninstalling software dialogs are based on such interfaces (I don't know if XP is temporarily unclear), I don't say fewer people know - the dialog is a web page? What do you not believe? If is the web page interacts with local computer programs? Why can't you choose the text in your web? Why can't you pop up the right-click menu? If it is a web page, then there is there?

In order to prove that the above statement, we need some special software. This software is the author written by MySpy, you can go to the author's site (http://siney.yeah.net) Free download, we can see from MySpy interface The dialog box for adding / deleting programs is an Internet Explorer_server, which means it is a web page.

You can also see the address of this page in MySPY web page is: res: //sp3res.dll/default.hta,

Nearly one step using myspy to get this page code (can not be right-click to get the code), the part is as follows:

Add / Remove Program </ Title></p> <p><</p> <p>Meta</p> <p>http-equiv = content-type content = "text / html; charSet = GB2312"> <base href = res: //appwiz.cpl/> <link href = "arp.css" type = text / css rel = stylesheet></p> <p><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 .Appimagetd {width: 20px; padding: '4px 2px 2px 2px';}. Infopane {Padding-Top: 4px; vertical -Align: Top;}. PropL {Width: 7em; Padding-top: 2px; padding-kettom: 2px; padding-right: 3px; text-align: right;}. PropValue {Width: 6em; Text-Align: Right Padding-right: 7px;}. Addpropl {Padding-top: 2px; padding-kettom: 2px; padding-right: 3px; text-align: Right;}. addpr value {width: 13em; Text-Align: Right; Padding -Right: 7px;}. Buttescpane {Padding-top: 5px; padding-{widt;}. Buttonpane {Width: 15em; padding: 5px; text-align: right;}. Fakenchor {cursor: hand;} # idclientcatname {FONT -Weight: bold; padding-bottom: 1EX;}. Disabled {color: graytext;} # d d cx :dedprops.focus {color: highlighttext;} </ stop></p> <p>嗬嗬, is it very magical, this is just an example of an application. In fact, there are many software interfaces to create interfaces, such as Norton Antivirsu, MS Visual Studio.NET, C # Builder, etc. In fact, in depth, think about how this interface is how to interact with local code, why do you have a button in the web page to perform your code? People who have experience in COM programming may think of writing an external object with COM, using scripts in the web page to create this object, and then call the object method seems to complete such functions? But there are a lot of bad places here: 1. The local run safety of the registration of COM, otherwise IE will have a security warning, which is definitely the end user is not willing to see;</p> <p>2. Users can easily get the use of COM objects in the HTML code (just like the code to get the code above) so they can easily use your COM object to complete their own interface, which is not concealed, not safe.</p> <p>There may be more bad places, but the author does not think that Microsoft and other software companies are not doing this, they may know more. Let's discuss a safe and hidden implementation method.</p> <p>Starting from IE4, Microsoft provides an icustomed interface. ICUSTOMDOC's setuiHandler allows users to set up an IDOCHOSTUIHANDLER-based interface to take over the interface processor, providing a lot of virtual methods in iDochostuiHandler, requiring programmers to overload their different customization features, Here is an article in detail this information http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/hosting/wbcustomization.asp, here we need to overload the getExternal method to extend IE DOM If we successfully expand DOM, then we can write HTML code to interact with local programs, such as:</p> <p><html></p> <p><HEAD></p> <p><Script logage = "jscript"></p> <p>Function myfunc ()</p> <p>{</p> <p>External.helloworld (); // HelloWorld is our extension method</p> <p>}</p> <p></ Script></p> <p></ hEAD></p> <p><body></p> <p><Input Type = "Button" Value = "Show Hello World" OnClick = "myfunc ();" /></p> <p></ body></p> <p></ html></p> <p>HelloWorld is a method we extend. The External object calls the HelloWorld method to call the local code. For the External object, the getExternal method mentioned above will query whether the extension is provided, how to implement the getExternal method Extend the External object, the code is as follows:</p> <p>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, masked context 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;</p> <p>} 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;</p> <p>} Virtual HRESULT STDMETHODCALLTYPE FilterDataObject (/ * [in] * / IDataObject __RPC_FAR * pDO, / * [out] * / IDataObject __RPC_FAR * __ RPC_FAR * ppDORet) {return E_NOTIMPL;}}; above overloaded ShowContextMenu method masked right-click menu, User users cannot get web code, about getExternal is this:</p> <p>Virtual HRESULT stdmethodCallType getExternal (/ * [out] * / idispatch __rpc_far * __ rpc_far * ppdispatch) {* ppdispatch = new mycommandhandler (); return s_ok;}</p> <p>It can be seen that just simply returns MyCommandHandler object, MyCommandHandler must inherit the approach to support automation from the IdisPatch interface, which is implemented in this way:</p> <p>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) {returnifnames (/ * [in] * / refiid riid, / inite * [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] * / disapid dispidmember, / * [in] * / refiid riid, / * [in] * / lcid lcid, / * [in] * / Word wflags, / * [out] [in] * / display * pdispparams, / * [out] * / variant * pvarresult, / * [out] * / excepinfo * pexcepinfo, / * [out] * / uint * puarger) {if (Dispidmember == 1) {MessageBox (0, "Hello World" , "Hello", 0); // Place Your Code Here FRMWEB-> Edit1-> text = "Hello World (this is also possible? ) ";} 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);</p> <p>return refcount;} virtual ULONG STDMETHODCALLTYPE Release () {InterlockedDecrement (& refcount); if (refcount == 0) delete this; return refcount;}}; if you understand some COM knowledge, we know that the key here is GetIDsOfNames and Invoke method Implementation, because the automation object can only be called in this way, and cannot use the function pointer to directly call the virtual method, the GetIDSOFNAMES query the call ID of the specified function name, that is, if one method is "helloworld", then it will call first GetidsOfNames method to query whether this method is supported, if supported, give the call ID (by modifying the RGDisPid [OUT] parameter), return E_NOTIMPL if not support, his implementation is as follows:</p> <p>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;}</p> <p>Here we assume that there is only one extended function helloworld, if there are multiple, we need to compare the function name of the RgszNames parameter to return different call IDs, there is a call ID, and it is very simple to implement the Invoke method:</p> <p>Virtual HRESULT stdmethodCallType Invoke (/ * [in] * / Dispid Dispidmember, / * [in] * / refiid riid, / * [in] * / lcid lcid, / * [in] * / word wflags, / * [out] [in] * / disaparams * 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 = "} Return S_OK;}</p> <p>Different code according to DISPIDMEMBER, if the method is parameter, can be obtained in Pdispparams, if anything you don't understand, you can refer to MSDN and some COM books, this is not explained in detail.</p> <p>Finally, what we have to do is to make our browser know we extended External, the code is as follows: dochandler = new mydochandler; webbrowser-> navigate ; while (webBrowser-> Busy) Application-> ProcessMessages (); ICustomDoc * custdoc; webBrowser-> Document-> QueryInterface (& custdoc); // obtain IcustomDoc interfaces if (custdoc) {custdoc-> SetUIHandler (dochandler); // Set our own interface processor custdoc-> release ();</p> <p>Pay attention to the bold "our browser" above, because such an extension is only for the use of WebBrowser controls in our own programs, which does not affect the extension of IE itself, that is, the ext.htm file can only be valid in our programs. Even if other users get this HTM code, they cannot run normally. If you want to test, you get:</p> <p>Because they don't know how to expand the External object, this solves the problem that we just said using COM.</p> <p>Sentence trick design This is still a difficulty, then what is the benefit of it in actual development? I think at least the following points:</p> <p>1. Interface design and program logic design separation, the art can work with the programmer, and the interface design is no longer no anecdotic.</p> <p>2. Easily implement the SKIN function, the change of the interface does not need to recompile the code, just need to change a different HTM code file;</p> <p>3. You can no longer use the Spy tool to get a variety of hooks to make your program run more secure;</p> <p>4. Fully use IE existing technology to build a more powerful software;</p> <p>5. Make your software more cool, more professional.</p> <p>how about it? Have you ever? Hurry improve your interface. If you have more ideas, you can get in touch with siney@yeah.net. This instance code can log in to the author site download.</p></div><div class="text-center mt-3 text-grey"> 转载请注明原文地址:https://www.9cbs.com/read-12256.html</div><div class="plugin d-flex justify-content-center mt-3"></div><hr><div class="row"><div class="col-lg-12 text-muted mt-2"><i class="icon-tags mr-2"></i><span class="badge border border-secondary mr-2"><h2 class="h6 mb-0 small"><a class="text-secondary" href="tag-2.html">9cbs</a></h2></span></div></div></div></div><div class="card card-postlist border-white shadow"><div class="card-body"><div class="card-title"><div class="d-flex justify-content-between"><div><b>New Post</b>(<span class="posts">0</span>) </div><div></div></div></div><ul class="postlist list-unstyled"> </ul></div></div><div class="d-none threadlist"><input type="checkbox" name="modtid" value="12256" checked /></div></div></div></div></div><footer class="text-muted small bg-dark py-4 mt-3" id="footer"><div class="container"><div class="row"><div class="col">CopyRight © 2020 All Rights Reserved </div><div class="col text-right">Processed: <b>0.044</b>, SQL: <b>9</b></div></div></div></footer><script src="./lang/en-us/lang.js?2.2.0"></script><script src="view/js/jquery.min.js?2.2.0"></script><script src="view/js/popper.min.js?2.2.0"></script><script src="view/js/bootstrap.min.js?2.2.0"></script><script src="view/js/xiuno.js?2.2.0"></script><script src="view/js/bootstrap-plugin.js?2.2.0"></script><script src="view/js/async.min.js?2.2.0"></script><script src="view/js/form.js?2.2.0"></script><script> var debug = DEBUG = 0; var url_rewrite_on = 1; var url_path = './'; var forumarr = {"1":"Tech"}; var fid = 1; var uid = 0; var gid = 0; xn.options.water_image_url = 'view/img/water-small.png'; </script><script src="view/js/wellcms.js?2.2.0"></script><a class="scroll-to-top rounded" href="javascript:void(0);"><i class="icon-angle-up"></i></a><a class="scroll-to-bottom rounded" href="javascript:void(0);" style="display: inline;"><i class="icon-angle-down"></i></a></body></html><script> var forum_url = 'list-1.html'; var safe_token = 'D62gvOxYOncc9Jv_2B8TJxR5tkdCuh81DGCYgKmWyu1zFzrv8dSAw03i0m5NMGQ4Vgn_2F_2B_2BGXWLvlZdIG9z5BPynw_3D_3D'; var body = $('body'); body.on('submit', '#form', function() { var jthis = $(this); var jsubmit = jthis.find('#submit'); jthis.reset(); jsubmit.button('loading'); var postdata = jthis.serializeObject(); $.xpost(jthis.attr('action'), postdata, function(code, message) { if(code == 0) { location.reload(); } else { $.alert(message); jsubmit.button('reset'); } }); return false; }); function resize_image() { var jmessagelist = $('div.message'); var first_width = jmessagelist.width(); jmessagelist.each(function() { var jdiv = $(this); var maxwidth = jdiv.attr('isfirst') ? first_width : jdiv.width(); var jmessage_width = Math.min(jdiv.width(), maxwidth); jdiv.find('img, embed, iframe, video').each(function() { var jimg = $(this); var img_width = this.org_width; var img_height = this.org_height; if(!img_width) { var img_width = jimg.attr('width'); var img_height = jimg.attr('height'); this.org_width = img_width; this.org_height = img_height; } if(img_width > jmessage_width) { if(this.tagName == 'IMG') { jimg.width(jmessage_width); jimg.css('height', 'auto'); jimg.css('cursor', 'pointer'); jimg.on('click', function() { }); } else { jimg.width(jmessage_width); var height = (img_height / img_width) * jimg.width(); jimg.height(height); } } }); }); } function resize_table() { $('div.message').each(function() { var jdiv = $(this); jdiv.find('table').addClass('table').wrap('<div class="table-responsive"></div>'); }); } $(function() { resize_image(); resize_table(); $(window).on('resize', resize_image); }); var jmessage = $('#message'); jmessage.on('focus', function() {if(jmessage.t) { clearTimeout(jmessage.t); jmessage.t = null; } jmessage.css('height', '6rem'); }); jmessage.on('blur', function() {jmessage.t = setTimeout(function() { jmessage.css('height', '2.5rem');}, 1000); }); $('#nav li[data-active="fid-1"]').addClass('active'); </script>