⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 droppolino_codegurusubmission.htm

📁 一个完整的IE插件的程序的源代码(有些参考价值)
💻 HTM
字号:
<!--#include virtual="header.shtml" -->
<!--#include virtual="/global/getCss.inc" -->
<center>
	<h3>
		<font color="#AOAO99"> Drop Bar. A Windows Explorer / Internet Explorer Toolbar</font>
	</h3>
</center>
<hr>
This article was contributed by <a href="mailto:christian@o3tt3rli.com">Christian 
	Oetterli</a>.
<p><img src="shot.jpg">
<p><u>Environment:</u> VC6, NT4, 98, Me, 2000, XP
</p>
<p>

	<h3>Introduction</h3>

	Drop Bar is a Windows Explorer / Internet Explorer toolbar that allows drag and 
	drop of files onto its buttons. user defined actions can then be performed with 
	the files being dropped. A buttons actions can be programmed in your preferred 
	scripting language such as javascript or vbscript.
</p>
<p>
	<h3>Design</h3>
	Drop Bar is COM class that resides in the library Droppolino.dll. It is based 
	upon an ATL "Simple Object" skeleton. The main toolbar functionality is 
	provided by implementing the IDeskBand and the IObjectWithSite interfaces.
</p>
<p>
	I decided not to use MFC to keep minimal dependencies. I decided also keep 
	using familiar classes like CString, CRect, CDC ... Therefore a MFC CString 
	replacement (ATL_CString.h ATL_CString.cpp) is included in the project. These 
	files are auto-generated as explained in K. Shane Triem's CodeGuru article <a href="http://codeguru.earthweb.com/atl/MFCCStringForATL.shtml">
		Add MFC's CString class to ATL with No MFC Dependencies</a>. For comfy 
	handling of structs like RECT, SIZE there exists minimal class wrappers CRect, 
	CSize ... (see utility.h, utility.cpp).
</p>
<p>
	Drop Bar uses <a href="http://www.microsoft.com/xml">MSXML</a> for storing its 
	configuration and <a href="http://www.microsoft.com/scripting">Microsoft Script 
		Control</a> for scripting functionality. These libraries must be installed 
	in order to successfully build the project. References are included through the 
	files reference_msxml3.h and reference_msscript.h. these files #import the libraries msxml3.dll, msscript.ocx with usage of COM 
	Support Classes. Using COM Support Classes is, in my opinion, the preferred
	way of programming COM with MS C++. Using them has some pitfalls however. It's almost impossible to have no naming conflicts when using the #import no_namespace attribute and the namespace that is declared in the type 
	library is often long and hard to bear in mind. What I do is rename_namespace to a short and meaningful name that is most often the 
	name of the library file itself. For instance XML or MSScript. See the 
	following snippet from reference_msxml3.h.
	<pre>
#import "msxml3.dll" rename_namespace("XML")
</pre>
	Now typedef most commonly used interfaces into the global namespace.
	<pre>
// typedef default interfaces of coclasses to make it more readable
typedef XML::IXMLDOMDocumentPtr IXMLDOMDocumentPtr;
typedef XML::IXMLDOMElementPtr IXMLDOMElementPtr;
</pre>
	For dealing with COM Support Classes there exists several helper functions and 
	macros (comstuff.h). It removes those scaring underscores from classes like 
	_variant_t and _bstr_t and makes it, let's say, human readable! It uses the 
	_com_util namespace. Versions of VB functions like isNull(), isEmpty(), isMissing() 
	are also provided.
</p>
<p>One major advantage of COM Support Classes is QueryInterface'ing through copy 
	constructors and (of course) no reference counting. The following snippet 
	demonstrates QueryInterface'ing through copy constructor.
</p>
<p>
	<pre>
variant value = IXMLDOMElementPtr(xmlDocument->SelectSingleNode("body"))->getAttribute("bgcolor");
</pre>
	You will never get that on one line using CComPtr, CComQIPtr.
</p>
String conversion is efficient and easier because Drop Bar uses UNICODE only. 
Therefore conversions between BSTR and CString can be achieved by simple type
casting. Snippet from comstuff.h.
<pre>
// casts bstr to CString.
// @param s bstr to convert.
// @return casted string.
#define asCString(s) (BSTR)(bstr)s

// casts CString to bstr.
// @param cs CString to convert.
// @return casted string.
#define asBSTR(cs) (LPCWSTR)cs
</pre>
<p>
	The main entry point for Drop Bar is the call to IObjectWithSite::SetSite(). If 
	Drop Bar gets attached to the site it creates its main window, registers itself 
	as a drop target and creates a window of class TOOLTIPS_CLASS for displaying 
	the buttons descriptions (tool tips). Drop Bar then draws its buttons in the 
	CDropBar::OnDraw() function.
</p>
<p>
	When Drop Bar needs to draw its buttons (OnDraw()) it first checks if the 
	configuration file has changed. If it has so it reloads it and displays the 
	changes accordingly. This is done by listening on a FindFirstChangeNotification 
	handle. A FindFirstChangeNotification handle is set up on the users "My 
	Documents" folder (where the configuration file resides).
	<pre>
CDropBar::CDropBar()
	...
{
	...
	// listen on config path for changes
	setConfigFileChange(FindFirstChangeNotification(
		  getConfigPath()
		, FALSE
		, FILE_NOTIFY_CHANGE_LAST_WRITE));
	...
}
</pre>
	Check configuration on OnDraw().
	<pre>
HRESULT CDropBar::OnDraw(ATL_DRAWINFO& di)
{
	...
	// check if a change was made and reset Drop Bar	
	checkConfig();
	...
}
</pre>
	If a change was made in this folder compare the configuration files timestamp 
	with the one previously remembered. If the timestamps are not equal then the 
	configuration file has changed.
	<pre>
void CDropBar::checkConfig()
{
	HANDLE change = getConfigFileChange();

	if (WAIT_OBJECT_0 == WaitForSingleObject(change, 1))
	{
		// something has changed in config path.
		// check if signaled by config file.

		FILETIME time = configTime();

		if (! isLastConfigTime(time))
		{
			reset();

			setLastConfigTime(time);
		}
	}

	FindNextChangeNotification(change);
}
</pre>
</p>
<p>
	As mentioned above Drop Bar uses a xml file for storing its configuration. This 
	file is named dropBar.xml and resides in the users "My Documents" folder. This 
	folder is obtained with a call to SHGetSpecialFolderPath().
	<pre>
CString CDropBar::getConfigPath() const
{
	CString path;

	SHGetSpecialFolderPath(m_hWnd, path.GetBuffer(_MAX_PATH), CSIDL_PERSONAL, FALSE);
	path.ReleaseBuffer();

	return path;
}
</pre>
	The structure of the xml is described in the contained DTD. 
	
<pre>
&lt;!DOCTYPE dropBar
[
	&lt;!ELEMENT dropBar (script?, button*)&gt;
	&lt;!ATTLIST dropBar version CDATA #FIXED "1.0"&gt;

	&lt;!ELEMENT script (#PCDATA)&gt;
	&lt;!ATTLIST script language CDATA "javascript"&gt;

	&lt;!ELEMENT button (icon?, script?)&gt;
	&lt;!ATTLIST button description CDATA #IMPLIED&gt;
	&lt;!ATTLIST button separator CDATA "0"&gt;

	&lt;!ELEMENT icon EMPTY&gt;
	&lt;!ATTLIST icon file CDATA #REQUIRED&gt;
	&lt;!ATTLIST icon index CDATA "0"&gt;
]&gt;
</pre>
	
	Here is the explanation.
</p>
<p>
	The document elements name is "dropBar". It must have an attribute "version" with the value set to "1.0". It may contain a "script" element and 
	any number (0..~) of "button" elements. "script" elements may have an attribute 
	"language" that specifies the scripting language to be chosen (vbscript, 
	javascript...). If no language attribute exists "javascript" will be used. The 
	"script" element of "dropBar" should contain a onCustomize(file) function that 
	gets called whenever the user right-clicks Drop Bar and choses "Customize..." 
	from the context menu. The file parameter is the full path of the configuration file. Snippet from sampleConfig.xml:
	<pre>
&lt;script&gt;
	function onCustomize(file)
	{
		// run notepad to edit configuration file
		new ActiveXObject("WScript.Shell").Run("notepad \"" + file + "\"");
	}
&lt;/script&gt;
</pre>
	
</p>
<p>
	A "button" element should have a "description" attribute. It is used as the 
	text for the buttons tool tip. If a buttons "separator" attribute is not equals 
	"0" (true) then a separator is displayed in the Drop Bar. If the "separator" 
	attribute is "0" (which is the default value) then the button must contain an 
	"icon" and a "script" element. The "icon" element must have a "file" attribute 
	that specifies the full path of the file containing the icon. The "icon" element can 
	specify an "index" attribute that specifies the index of the icon within the 
	file. If "index" is not specified the default value "0" will be used. The buttons 
	"script" element should contain an onClick() and an onDrop(file) function. 
	onClick() gets called whenever the user clicks on that button. onDrop(file) 
	gets called whenever a file is dropped onto the button. The file parameter 
	specifies the file being dropped.
</p>
<p>
	For an example configuration with buttons for Notepad, Command Prompt, Visual Studio... please refere to the file 
	sampleConfig.xml that is part of this distribution.
</p>
<p>
	If loading of the configuration fails for any reason, may because of malformed xml or wrong 
	structure, Drop Bar loads a default configuration from its resources. 
	CXMLDOMDocument::loadXMLRes() provides this functionality.
	
<pre>
// loads xml from custom resource of type "XML"
// @param resId id of resource.
// @param module module where the resource is located.
// @return true if successfull.
bool CXMLDOMDocument::loadXMLRes(LPCTSTR resId, HINSTANCE module)
{
	HRSRC res = FindResource(module, resId, L"XML");

	bool ok = res != 0;

	if (ok)
	{
		HGLOBAL hRes = LoadResource(module, res);

		ok = hRes != 0;

		if (ok)
		{
			DWORD size = SizeofResource(module, res);
			char *data = (char*)hRes;
			bool deleteData = false;

			if (data[size])
			{
				// size bigger than page

				data = new char[size + 1];

				memcpy(data, (char*)hRes, size + 1);
			
				// terminate
				data[size] = 0;

				deleteData = true;
			}

			bstr xml = data;

			if (deleteData)
			{
				delete data;
			}

			ok = 0 != (*this)->loadXML(xml);
		}
	}

	return ok;
}
</pre>	
</p>
<p>
	When registering/unregistering Drop Bar the Drop Bar class must 
	additionally register/unregister itself for the component category CATID_DeskBand.  
	Additionally Drop Bar must create/delete its key from the registry where Internet Explorer stores all 
	currently installed toolbars (HKLM\Software\Microsoft\Internet Explorer\Toolbar). 
	registerToolbarBand() provides this functionality. Snippet from utility.cpp.

<pre>
// registers class for necessary component categories and Internet Explorer registry entries.
// @param clsid class id that is a Internet Explorer Band.
// @param doRegister true if wants to register, false if wants to unregister.
void registerToolbarBand(const CLSID &clsid, bool doRegister)
{
	ICatRegisterPtr cat(CLSID_StdComponentCategoriesMgr);

	CLSID catIds[1];
	catIds[0] = CATID_DeskBand;

	if (doRegister)
	{
		cat->RegisterClassImplCategories(clsid, 1, catIds);
	}
	else
	{
		cat->UnRegisterClassImplCategories(clsid, 1, catIds);
	}
	
	// create or delete internet explorer toolbar entry
	CRegKey key;
	
	if (ERROR_SUCCESS == key.Open(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Internet Explorer\\Toolbar"))
	{
		LPOLESTR clazz;
		
		if (SUCCEEDED(StringFromCLSID(clsid, &clazz)))
		{
			if (doRegister)
			{
				key.SetValue(L"", clazz);
			}
			else
			{
				key.DeleteValue(clazz);
			}

			CoTaskMemFree(clazz);
		}
	}
}
</pre>
</p>
<p>
	<h3>Additional Links/ Information</h3>
	<table cellpadding="2" cellspacing="2">
		<tr>
			<td>Use CString without MFC</td>
			<td><a href="http://codeguru.earthweb.com/atl/MFCCStringForATL.shtml">Add MFC's CString 
					class to ATL with No MFC Dependencies</a></td>
		</tr>
		<tr>
			<td>IDropTarget implementation</td>
			<td>class CDropBar</td>
		</tr>
		<tr>
			<td>obtaining HDROP handle from IDataObject</td>
			<td>CDropBar::dropEffect()</td>
		</tr>
		<tr>
			<td><a href="http://www.microsoft.com/xml">MSXML</a></td>
			<td>CDropBar::loadConfig()</td>
		</tr>
		<tr>
			<td><a href="http://www.microsoft.com/scripting">Microsoft Script Control</a></td>
			<td>CDropBar::execConfig()</td>
		</tr>
		<tr>
			<td>Listening on folder for changes</td>
			<td>CDropBar::CDropBar(), CDropBar::checkConfig(), CDropBar::OnDestroy()</td>
		</tr>
		<tr>
			<td>obtaining last write time of a file</td>
			<td>CDropBar::configTime()</td>
		</tr>
		<tr>
			<td>Using TOOLTIPS_CLASS</td>
			<td>CDropBar::SetSite(), CDropBar::addTools(), CDropBar::delTools(), 
				CDropBar::onToolsRelayEvent()</td>
		</tr>
		<tr>
			<td>flicker free drawing using BitBlt()</td>
			<td>CDropBar::OnDraw()</td>
		</tr>
		<tr>
			<td>registering for COM component categories</td>
			<td>registerToolbarBand()</td>
		</tr>
		<tr>
			<td>get system folders (My Documents, Program Files...)</td>
			<td>CDropBar::getConfigPath()</td>
		</tr>
		<tr>
			<td>get notified when mouse leaves window (TrackMouseEvent())</td>
			<td>CDropBar::initMouseLeave()</td>
		</tr>
		<tr>
			<td>using SAFEARRAY</td>
			<td>CDropBar::execScript()</td>
		</tr>
		<tr>
			<td>using std::vector</td>
			<td>class CIcons, class CParams, class CRects</td>
		</tr>
		<tr>
			<td>load XML from resource</td>
			<td>CXMLDOMDocument::loadXMLRes()</td>
		</tr>
		<tr>
			<td>another button implementation</td>
			<td>CDropBar::OnLButtonDown(), CDropBar::OnMouseMove(), CDropBar::OnLButtonUp(), 
				CDropBar::OnMouseLeave(), CDropBar::OnDraw()</td>
		</tr>
		<tr>
			<td>load icons from file</td>
			<td>CDropBar::getIcons()</td>
		</tr>
		<tr>
			<td>XML, DTD</td>
			<td>dropBar.xml, sampleConfig.xml</td>
		</tr>
	</table>
</p>
<h3>Credits</h3>
<p>
	<ul>
	<li>This software has been developed using Microsoft Visual C++ 6.0</li>
	<li><a href="mailto:shane@steptech.com">K. Shane Triem</a>'s CodeGuru article <a href="http://codeguru.earthweb.com/atl/MFCCStringForATL.shtml">Add MFC's CString class to ATL with No MFC Dependencies</a></li>
	</ul>
</p>
<h3>Downloads</h3>
<a href="Droppolino.exe">Download Self-Extracting Installer - 274 Kb</a>
<br>
<a href="Droppolino.src.zip">Download source - 39 Kb</a>
<h3>History</h3>
Date Posted: April 17, 2002
<br>
<!-- Only use the following if the article is updated -->
<!-- Date Last Updated:  [today's date in the format month day, year] -->
<!--#include virtual="footer.shtml" -->

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -