Microsoft KB Archive/815716

= How to invoke the View Source dialog box, the Find dialog box, and the Internet Options dialog box for the WebBrowser control in Visual C++ .NET or in Visual C++ 2005 =

Article ID: 815716

Article Last Modified on 11/29/2007

-

APPLIES TO


 * Microsoft Visual C++ 2005 Express Edition
 * Microsoft Visual C++ .NET 2003 Standard Edition
 * Microsoft .NET Framework 1.1
 * Microsoft Internet Explorer 6.0

-





For a Microsoft Visual Basic .NET version of this article, see 311288.



For a Microsoft Visual C# .NET version of this article, see 329014.

This article refers to the following Microsoft .NET Framework Class Library namespaces:
 * System::ComponentModel
 * System::Collections
 * System::Windows::Forms
 * System::Runtime::InteropServices



SUMMARY
This article describes how to invoke the Microsoft Internet Explorer View Source dialog box, the Find dialog box, and the Internet Options dialog box in an application that hosts the WebBrowser control.

IN THIS TASK

 * INTRODUCTION
 * Requirements
 * Define the IOleCommandTarget interface
 * Define the Command GUID for the CGID_IWebBrowser control
 * Call the Exec method
 * REFERENCES



INTRODUCTION
You can invoke various dialog boxes for a Microsoft WebBrowser control. Three of these dialog boxes are: View Source, Find, and Internet Options. Before you can invoke these dialog boxes by means of a hosted UserControl object, you have to define the IOleCommandTarget interface and then implement the methods that are exposed in that interface. This step-by-step article outlines the steps to follow to invoke these three dialog boxes.

Warning This sample uses an undocumented command-group GUID that is subject to change in the future. Although this sample was tested to work correctly with Internet Explorer 6 and earlier, there is no guarantee that these techniques will continue to work successfully in future versions.

back to the top



Requirements
The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:
 * Microsoft Visual C++ .NET 2003 or Microsoft Visual C++ 2005
 * Microsoft .NET Framework 1.1
 * Microsoft Internet Explorer 6.0

This article assumes that you are familiar with the following topics:
 * Programming with Microsoft Visual C++ .NET or Microsoft Visual C++ 2005
 * Hosting the WebBrowser control (Shdocvw.dll)

back to the top

Define the IOleCommandTarget interface
To define a .NET interface to obtain a reference to a Component Object Model (COM) interface (IOleCommandTarget), follow these steps:  Open your UserControl library project that is hosting the WebBrowser control. In Solution Explorer, right-click the project node, and then click Add Reference.

Note In Visual Studio 2005, Add Reference is changed to Reference. In the Add Reference dialog box, click the COM tab. To add items to the Selected Components list, double-click both Microsoft HTML Object Library and Microsoft Internet Controls in the list of COM components, and then click OK.  Include the IOleCommandTarget interface declaration inside the namespace declaration of your control to add a reference to the Microsoft HTML (MSHTML) IOleCommandTarget interface. To do this, insert the following code before the UserControl class definition: [StructLayout(LayoutKind::Sequential)] public __gc struct OLECMDTEXT { public: unsigned int cmdtextf; unsigned int cwActual; unsigned int cwBuf; char rgwz; };

[StructLayout(LayoutKind::Sequential)] public __gc struct OLECMD { public: long cmdID; UInt64 cmdf; }; // Interop definition for IOleCommandTarget. [ComImport, Guid(&quot;b722bccb-4e68-101b-a2bc-00aa00404770&quot;), InterfaceType(ComInterfaceType::InterfaceIsIUnknown)] public __gc __interface IOleCommandTarget {    //IMPORTANT: The order of the methods is critical here. You will perform //early binding in most cases, and therefore, the order of the methods //here MUST match the order of their vtable layout (which is determined   //by their layout in IDL). The interop calls key off the vtable ordering, //not off the symbolic names, and therefore, if you switched these method //declarations and tried to call the Exec function on an IOleCommandTarget //interface from your application, it would translate into a call to //QueryStatus instead. void QueryStatus(Guid* pguidCmdGroup, UInt32 cCmds, [MarshalAs(UnmanagedType::LPArray, SizeParamIndex=1)] OLECMD* prgCmds, OLECMDTEXT* CmdText); void Exec(Guid* pguidCmdGroup, long nCmdId, long nCmdExecOpt, Object* pvaIn, Object* pvaOut); }; Note You must add the common language runtime support compiler option (/clr:oldSyntax) in Visual C++ 2005 to successfully compile the previous code sample. To add the common language runtime support compiler option in Visual C++ 2005, follow these steps: <ol style="list-style-type: lower-alpha;"> Click Project, and then click  Properties.

Note  is a placeholder for the name of the project.</li> Expand Configuration Properties, and then click General.</li> Click to select Common Language Runtime Support, Old Syntax (/clr:oldSyntax) in the Common Language Runtime support project setting in the right pane, click Apply, and then click OK.</li></ol>

For more information about the common language runtime support compiler option, visit the following Microsoft Web site:

/clr (Common Language Runtime Compilation)

http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx

These steps apply to the whole article.

Note You have to assign to the interface the GUID of the appropriate COM interface. Also, you have to include type declarations for all the methods of the interface. </li>  Add a ComSourceInterfaces attribute to the UserControl class to identify the list of interfaces that are exposed as COM event sources. To do this, insert the following code before the UserControl class definition: //Add a ComSourceInterfaces attribute to the control class to //identify the list of interfaces that are exposed as COM event sources. [ClassInterface(ClassInterfaceType::None),ComSourceInterfaces(__typeof(IOleCommandTarget))] </li></ol>

back to the top

Define the Command GUID for the CGID_IWebBrowser control
You must also define the GUID for CGI_IWebBrowser to inform MSHTML how to process your command IDs. Use the Microsoft .NET Framework class GUID to declare the GUID. To do this, follow these steps: <ol>  Add the following code in your UserControl class: private: //Define the command group GUID for the WebBrowser control Guid cmdGuid; </li>  Insert the following code in the UserControl class constructor, after the call to the InitializeComponent function: cmdGuid = Guid(S&quot;ED016940-BD5B-11CF-BA4E-00C04FD70816&quot;); </li></ol>

Also, define the command IDs that are used for each of the commands. To do this, insert the following code in the UserControl class: private: // Constants for the commands that are named earlier __value enum MiscCommandTarget {       Find = 1, ViewSource, Options }; Also, define an mshtml::HTMLDocument member variable to implement the Document property of the WebBrowser control. To do this, insert the following variable declaration in the UserControl class: private: // The current instance of MSHTML mshtml::HTMLDocument *document; back to the top

Call the Exec method
Implement a property getter function to return the document property. To do this, insert the following code after the InitializeComponent function: public: __property mshtml::HTMLDocument* get_Document {       try {           //mshtml::IHTMLDocument2* doc; document = __try_cast<mshtml::HTMLDocument*>(axWebBrowser1->Document); return document; }       catch(Exception* e)        { System::Windows::Forms::MessageBox::Show(e->Message->ToString); }   } Finally, encapsulate the calls to the Exec method in three separate method calls. To do this, insert the following code in the UserControl class: public: void viewsource {       IOleCommandTarget* cmdt; Object * o = new Object; // If the doc object is not set to anything, or if there is       // some bizarre error in accessing IOleCommandTarget, // exit gracefully. try {           cmdt = __try_cast<IOleCommandTarget*>(get_Document); cmdt->Exec(&cmdGuid, (long)MiscCommandTarget::ViewSource, (long)Interop::SHDocVw::OLECMDEXECOPT::OLECMDEXECOPT_DODEFAULT, o, o); }       catch(Exception* e)         { System::Windows::Forms::MessageBox::Show(e->Message->ToString); }   }

void find {       IOleCommandTarget* cmdt; Object * o = new Object;

// If the doc object is not set to anything, or if there is       // some bizarre error in accessing IOleCommandTarget, // exit gracefully. try {           cmdt = __try_cast<IOleCommandTarget*>(get_Document); cmdt->Exec(&cmdGuid, (long)MiscCommandTarget::Find, (long)Interop::SHDocVw::OLECMDEXECOPT::OLECMDEXECOPT_DODEFAULT, o, o); }       catch(Exception * e)        { System::Windows::Forms::MessageBox::Show(e->Message->ToString); }   }    void options {           IOleCommandTarget* cmdt; Object * o = new Object; try {           cmdt = __try_cast<IOleCommandTarget*>(get_Document); cmdt->Exec(&cmdGuid, (long)MiscCommandTarget::Options, (long)Interop::SHDocVw::OLECMDEXECOPT::OLECMDEXECOPT_DODEFAULT, o, o); }       catch(Exception * e)        { // NOTE: Because of the way that this CMDID is handled in Internet Explorer, // this catch block will always fire, even though the dialog box // and its operations completed successfully. You can suppress this // error without causing any damage to your host. String * s = e->Message->ToString; }   } back to the top

<div class="references_section">