Compile C ++ code with better reusability -- band object and comtoys (4)

Source: Internet
Author: User

Compile/Zhao Xiangning

Original: Paul dilascia

MSJ November 1999 & December 1999

Keywords: bands object, desk bands, info/Comm bands, explorer bar, and tool bands.

This document assumes that you are familiar with C ++, COM, and IE.

Download the source code of this article: mybands.zip (KB)
Testeditsrch.zip (75kb)

Part 1: Introduction to band objects
Part 2: bandobj class hierarchy and mybands service program Registration
Part 3: go deep into the band and unveil the band.

Part 4Band object usage Problems

The above describes the basic operations and processing of some band objects. These basic operations are theoretically implemented according to your design ideas. But in the actual programming process, not every thing is done in the way it should. The following describes the problems that may occur when using the band object.
In this document, desktop band must implement the ipersiststream interface to store persistent data. What exactly is the data? According to tracking and diagnosis, only desktop band queries the ipersiststream interface, while Explorer does not query the ipersiststream interface, but queries the ipersiststreaminit interface. So what is the use of ipersiststream? Another comment hidden in the Microsoft example code is as follows: "If you want to drag the desktop band out of the taskbar to the desktop, ipersiststream is a required interface. "As shown in Figure 2 in the first part, if you do not want this feature, you do not need to implement the ipersiststream interface.
The trace also displays the iolecommandtarget and idiscardablebrowserproperty interfaces for Windows queries. The following interface is one of my favorite interfaces. It does not have a function! Someone may ask how can an interface without a function? Idiscardablebrowserproperty is only used to notify ie: "If you access another page, you can discard my page data. They are consumable. "For more information about idiscardablebrowserproperty, see another article on msdn:" discardable properties for your web pages in Internet Explorer 4.0 ".
Finally, trace reveals that Windows has to query another mysterious interface, which is -- {EA5F2D61-E008-11CF-99CB-00C04FD64497}, which is not present in any document, in the source file or registry. If the man-in-law knows the information about this interface, please make it public.
When you create a desktop band for the first time, it may be difficult for Windows to recognize it. However, for the browser bar (band of info and comm type), you only need to restart IE or resource manager once. Windows does not recognize the desktop band. Only one solution is to use ctrl-alt-del to kill the Resource Manager process or restart the machine. However, I recently tested my desktop band in the newly installed version of Windows 98 and found that my desktop band was mysteriously suspended. No matter how many times I registered DLL and killed the Resource Manager process, my desktop band refused to appear. The same problem occurs in Windows 2000.
After countless puzzles and frustrations, I almost fell into despair. At this time, I think that the boss who turned to Ms may solve this problem. The answer is to refer to the Microsoft Knowledge Base Article q214842. This article addresses this secret-"Windows 2000 (the second version of Windows 98 is also the same) refresh the Type Buffer only when it detects a running installer or the registry does not provide a buffer (cache) location. "Windows" can sense "to the installer ?. Is it Superman? This article will reveal two ways to re-establish a kind of buffer for the resource manager: Install it from the setup.exe?install.exe Program (this is called Superman power, but so !) Or delete the following registry key:
Hkey_classes_root/component categories/{00021492-0000-0000-c000-000000000046}/Enum, which is a buffer. ({00021492...} refers to catid_deskband ). I modified the content of the bandobj. RGS file and always deleted this key value. The problem is solved. However, you still need to restart the shell to generate a new type of buffer for Windows.
Next is a series of association problems, which are all caused by the same bug. This problem is: no matter when I compile the source code, there will always be "cannot open mybands. DLL by writing ". Obviously, as long as the resource manager is running, it always keeps the band object active. The same is true for IE: when a user hides or displays a band, ie calls idockingwindow: hidedw and showdw. IE will not release this object until it exits. For desktop band, this means you have to use ctrl-alt-del again to kill it and create it again. It is annoying, but that is no way.
The following is a simple example of debugging. For more information about debugging of shell extension, see the article in the excellent section: "How to debug Windows Shell extension" (the principle is to use ctrlw.altw.shiftto close the shell, and then use cmder.exe as the debugger for debugging, when debugging the desktop band. This method is ineffective because the DLL is always locked. Then I had to restart the machine. It was really bad. I was bored with debugging. Fortunately, tracing can also be used, which is a debugging tool I like. However, the system-level debugger is occasionally used.
When I implemented mybands for the first time, I failed to process the search engine selected by the memory user. That's because I stored the corresponding state in the object's destructor -- but for some reason, the Destructor was not called. As I said earlier, Windows didn't destroy the object, it only closes the window. So I moved the storage code to postncdestroy to solve the problem. However, if the object remains alive even if the user closes it, there is no need to set the storage status because they are still in the memory. Isn't it?
All these minor problems are caused by a major problem. The Trace Output shows that each time you hide or display a desktop band, the resource manager creates a new band object. It will never release the old one! After analysis, we can find out how many times can I hide or display objects before the Windows Memory is exhausted if cmyuncband is 916 bytes and I have 128 MB RAM memory? Microsoft has acknowledged their stupid mistake and promised to solve it soon.
After the problem was fixed, I went back to the category of band. At the beginning, I talked about three types of band objects. In fact, there is another four types: toolbar band. In order to understand the meaning of these terms, my header has been fully occupied, and the toolbar band is located in the rebar of IE. In ie5.0, "radio station" is an example of the toolbar band. (Do you know that IE has a radio receiver? I mean, ie6.0 may have HDTV !)
It is easy to compile the toolbar band. You only need to register the band of the info/Comm type. Add the band class ID (guid) as a string to HKEY_LOCAL_MACHINE/software/Microsoft/Internet Explorer/toolbar. I have modified the bandobj. RGS file to add this value. The file name is explrbar. RGS. Add this file as a resource to the mybands. RC file of the project.

Idr_commband registry discardable "explrbar. RGS"

There is a problem when using band in the toolbar. When you right-click the resource manager to display the band, it has a "radio station" menu item. In fact, it is the name of the first registered toolbar band. This is a known bug-see the Microsoft Knowledge Base Article q231621. Windows 2000 seems to have solved this problem.

Talk about mybands

I think, now you must hate the band object and hope it will be lost from your life. That's a good idea! For me, I have told you everything about the band object. Before I leave, let me talk about mybands-the actual implementation of band. It is simple, but there are some things worth mentioning.
First, both cmycommband and cmyinfoband are derived from a common base class cmyieband. Cmyieband implements a public feature: When you click the band, it sends the VC Knowledge Base homepage and Sina homepage to the browser. To implement this function, the band object requires the iwebbrowser2 interface so that the object can call the iwebbrowser2: navigate function to let the web browser know where to visit. Obviously, this requires some tips, so I first thought of writing:

CComQIPtr
  iwb = m_pSite;     

Of course, it uses QueryInterface to query the iwebbrowser2 interface, but the call to QueryInterface ends with an e_nointerface error and a null pointer. The container does not implement the iwebbrowser2 interface. So where can I obtain this interface? See the following programming code:

CComQIPtr
  sp = m_pSite; m_spWebBrowser2 = NULL; if (sp) {   sp->QueryService(IID_IWebBrowserApp,                    IID_IWebBrowser2,                     (void**)&m_spWebBrowser2);}      

Iserviceprovider is a common method used for COM objects. It provides interfaces that are known to other objects. It seems like QueryInterface, but it is not exactly the same: the container itself does not implement the iwebbrowser2 interface, but the container knows how to obtain an object of it.
Next, let's take a look at cmyuncband (Web search box ). The interesting part here is the edit box control, which is implemented in the ceditsearch class. In order to receive the wm_char message after the user presses the "enter" (Press ENTER) key, I added a wm_getdlgcode message processor whose return value is dlgc_wantallkeys. Let's take a look. All the windows knowledge is still useful here. When the user presses the "enter" Key, ceditsearch intercepts it, And onchar calls the dosearch function to create a URL using the user's input information. Here we need to use "+" to replace space (spaces), So if you use Yahoo to search for "Beanie Baby sex", the generated URL will be: http://ink.yahoo.com/bin/query? P = beeni + baby + sex & Z = 2 & Hc = 0 & HS = 0, ceditsearch will pass this string to iwebbrowser2: navigate. Several search engines are built in ceditsearch, but you can add more search engines by editing the mybands. ini file. The simplest way to obtain the URL in this file is to go to your favorite portal site, use "MySearch" as the search keyword, and add the result URL from the address bar to the mybands. ini file.
Speaking of the INI file used by mybands-in fact, the Registry is very cumbersome when storing simple application configuration information, so I wrote a small class: cinifile to prevent applications from automatically using the registry.

Bool cmybandsdll: initinstance () {// setregistrykey (_ T ("vckbase"); // shield the registry! Cinifile: Use (this, cinifile: localdir); // use the INI file !}

It tells the application to put the INI file in the directory where the program or DLL is located, not the Windows directory. If you do not call setregistrykey, MFC uses the INI file by default, but it stores the file in the Windows directory. I like to put configuration files and programs using them in the same directory, so that you can delete the entire directory without worrying about additional spam. If you want to, cinifile allows you to use the Windows directory or specify a different file name. The method is to set m_pszregistrykey of the application to null and m_pszprofilename to the name of the INI file. Of course, if you use the INI file, you cannot automatically obtain the user-specified settings implemented by the Registry on the machines used by multiple users. So let's take a look at it. Do you want to accuse me of using setregistrykey.
As shown in figure 12 in the third part, it is necessary to make the context menu of the editing box work normally. When you right-click the editing box, the editing box should display your context menu, which should include the cut, copy, and paste menu. No problem. You only need to reload the wm_contextmenu message processing function. However, there is no such thing in the MFC command-I mean the wm_contextmenu message processing function for the edit box, that is, the oninitmenupopup processor of MFC is implemented in cframewnd, instead of in cwnd-although menus can be displayed in any window. This problem is often encountered in programming. The solution is to use a previous code that can be used for any cwnd: cpopupmenuinithandler, which is derived from csubclasswnd.
Csubclasswnd can be used to dynamically subclass any cwnd for message interception. Cpopupmenuinithandler dynamically subclass Edit Control to intercept wm_contextmenu messages. After the message is intercepted, another class/function -- cpopupmenuinit: init is called to complete the work. This function is similar to that in cframewnd, and is almost copied from the original. Cpopupmenuinit: init creates a ccmdui object for each menu item and sends it to the on_update_command_ui processor. You can use cpopupmenuinithandler as you initialize the MFC menu at any time. For detailed code, see the menuinit. cpp file.
Ceditsearch finally simulates the function in the IE address bar, that is, when you click the edit box for the first time, all the text is selected. You can click the cursor once to locate the cursor. To implement these functions, you must process several messages-wm_mouseactivate, WM _ setfocus, wm_lbuttondown, and mouse or keyboard messages-all of which are stored in ceditsearch: windowproc. Sometimes it is easier to use the old c ++ method than message ing. For details, see the source code.
If you have debugged the desktop band application, you will find it painful. I wrote a separate program called testeditsrch, which is used to test ceditsearch, make sure that it works properly and then put it into the desktop band (15th ). I strongly recommend that you do the same. Write the executable code separately, and then move them to the band.

Figure 15

The source code of mybands/bandobj is very long, and it is all monotonous and boring. If you are interested, download the source code!

Summary

The essence of reusable programming is to determine common behavior and encapsulate it into classes or child routines that can be reused in different scenarios. For a band object, bandobj refines the band object into four aspects: Class ID (guid), MFC class, resource ID, and category ID. Add other related resources. For each band object, the COM interface and its data exchange are basically the same. So why do I need to write all the code myself? There is no reason not to use bandobj to create applications related to the band object. All you have to do is derive from the framework class and call addbandclass. Some programmers will argue that bandobj depends on MFC and its large mfc42.dll. Yes, but I don't think there is any burden, at least for Shell expansion. Mfc42.dll is considered part of windows and can be used in all Windows applications.
If you look at cbandobj, you will understand its versatility-not only for band objects, it applies to all com classes. Cbandobj implements icontextmenu and iinputobject using cmenu and the acceleration key table. What else do band objects need to do? Its implementation of iolewindow and idockingwindow only requires one cwnd. Iobjectwithsite saves pointers. There is only one interface ideskband associated with the band object and its only function getbandinfo. Nothing else is substantive. It abstracts the implementation of these interfaces at a deeper level as much as possible, allowing you to easily assemble and reuse these interfaces in various situations in a small class. Shell folder, file reader, ActiveX Control -- everything. You only need to assemble several pieces of code and compile it to create these COM objects. This is really great.
Starting from the next section, I will use bandobj to build my own comtoys to show you how to use bandobj. (To be continued)

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.