// Copyright Pavel Zolnikov, 2002
//
// BandObject - implements generic Band Object functionality.
// http://www.codeproject.com/KB/shell/dotnetbandobjects.aspx
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using SHDocVw;
using System.Reflection;
using System.Diagnostics;
using System.Drawing;
using System.ComponentModel;
using Microsoft.Win32;
namespace BandObjectLib
{
///
/// Implements generic Band Object functionality.
///
///
/// [Guid("YOURGUID-GOES-HERE-YOUR-GUIDGOESHERE")]
/// [BandObject("Hello World Bar", BandObjectStyle.Horizontal | BandObjectStyle.ExplorerToolbar , HelpText = "Shows bar that says hello.")]
/// public class HelloWorldBar : BandObject
/// { /*...*/ }
///
public class BandObject : UserControl, IObjectWithSite, IDeskBand, IDockingWindow, IOleWindow, IInputObject
{
///
/// Reference to the host explorer.
///
protected WebBrowserClass Explorer;
protected IInputObjectSite BandObjectSite;
///
/// This event is fired after reference to hosting explorer is retreived and stored in Explorer property.
///
public event EventHandler ExplorerAttached;
public BandObject()
{
InitializeComponent();
}
private void InitializeComponent()
{
//
// ExplorerBar
//
this.Name = "BandObject";
}
///
/// Title of band object. Displayed at the left or on top of the band object.
///
[Browsable(true)]
[DefaultValue("")]
public String Title
{
get
{
return _title;
}
set
{
_title = value;
}
}String _title;
///
/// Minimum size of the band object. Default value of -1 sets no minimum constraint.
///
[Browsable(true)]
[DefaultValue(typeof(Size), "-1,-1")]
public Size MinSize
{
get
{
return _minSize;
}
set
{
_minSize = value;
}
}Size _minSize = new Size(-1, -1);
///
/// Maximum size of the band object. Default value of -1 sets no maximum constraint.
///
[Browsable(true)]
[DefaultValue(typeof(Size), "-1,-1")]
public Size MaxSize
{
get
{
return _maxSize;
}
set
{
_maxSize = value;
}
}Size _maxSize = new Size(-1, -1);
///
/// Says that band object's size must be multiple of this size. Defauilt value of -1 does not set this constraint.
///
[Browsable(true)]
[DefaultValue(typeof(Size), "-1,-1")]
public Size IntegralSize
{
get
{
return _integralSize;
}
set
{
_integralSize = value;
}
}Size _integralSize = new Size(-1, -1);
public virtual void GetBandInfo(
UInt32 dwBandID,
UInt32 dwViewMode,
ref DESKBANDINFO dbi)
{
dbi.wszTitle = this.Title;
dbi.ptActual.X = this.Size.Width;
dbi.ptActual.Y = this.Size.Height;
dbi.ptMaxSize.X = this.MaxSize.Width;
dbi.ptMaxSize.Y = this.MaxSize.Height;
dbi.ptMinSize.X = this.MinSize.Width;
dbi.ptMinSize.Y = this.MinSize.Height;
dbi.ptIntegral.X = this.IntegralSize.Width;
dbi.ptIntegral.Y = this.IntegralSize.Height;
dbi.dwModeFlags = DBIM.TITLE | DBIM.ACTUAL | DBIM.MAXSIZE | DBIM.MINSIZE | DBIM.INTEGRAL;
}
///
/// Called by explorer when band object needs to be showed or hidden.
///
///
public virtual void ShowDW(bool fShow)
{
if (fShow)
Show();
else
Hide();
}
///
/// Called by explorer when window is about to close.
///
public virtual void CloseDW(UInt32 dwReserved)
{
Dispose(true);
}
///
/// Not used.
///
public virtual void ResizeBorderDW(IntPtr prcBorder, Object punkToolbarSite, bool fReserved) { }
public virtual void GetWindow(out System.IntPtr phwnd)
{
phwnd = Handle;
}
public virtual void ContextSensitiveHelp(bool fEnterMode) { }
public virtual void SetSite(Object pUnkSite)
{
if (BandObjectSite != null)
Marshal.ReleaseComObject(BandObjectSite);
if (Explorer != null)
{
Marshal.ReleaseComObject(Explorer);
Explorer = null;
}
BandObjectSite = (IInputObjectSite)pUnkSite;
if (BandObjectSite != null)
{
//pUnkSite is a pointer to object that implements IOleWindowSite or something similar
//we need to get access to the top level object - explorer itself
//to allows this explorer objects also implement IServiceProvider interface
//(don't mix it with System.IServiceProvider!)
//we get this interface and ask it to find WebBrowserApp
_IServiceProvider sp = BandObjectSite as _IServiceProvider;
Guid guid = ExplorerGUIDs.IID_IWebBrowserApp;
Guid riid = ExplorerGUIDs.IID_IUnknown;
try
{
object w;
sp.QueryService(
ref guid,
ref riid,
out w);
//once we have interface to the COM object we can create RCW from it
Explorer = (WebBrowserClass)Marshal.CreateWrapperOfType(
w as IWebBrowser,
typeof(WebBrowserClass)
);
OnExplorerAttached(EventArgs.Empty);
}
catch (COMException)
{
//we anticipate this exception in case our object instantiated
//as a Desk Band. There is no web browser service available.
}
}
}
public virtual void GetSite(ref Guid riid, out Object ppvSite)
{
ppvSite = BandObjectSite;
}
///
/// Called explorer when focus has to be chenged.
///
public virtual void UIActivateIO(Int32 fActivate, ref MSG Msg)
{
if (fActivate != 0)
{
Control ctrl = GetNextControl(this, true);//first
if (ModifierKeys == Keys.Shift)
ctrl = GetNextControl(ctrl, false);//last
if (ctrl != null) ctrl.Select();
this.Focus();
}
}
public virtual Int32 HasFocusIO()
{
return this.ContainsFocus ? 0 : 1; //S_OK : S_FALSE;
}
///
/// Called by explorer to process keyboard events. Undersatands Tab and F6.
///
///
/// S_OK if message was processed, S_FALSE otherwise.
public virtual Int32 TranslateAcceleratorIO(ref MSG msg)
{
if (msg.message == 0x100)//WM_KEYDOWN
if (msg.wParam == (uint)Keys.Tab || msg.wParam == (uint)Keys.F6)//keys used by explorer to navigate from control to control
if (SelectNextControl(
ActiveControl,
ModifierKeys == Keys.Shift ? false : true,
true,
true,
false)
)
return 0;//S_OK
return 1;//S_FALSE
}
///
/// Override this method to handle ExplorerAttached event.
///
///
protected virtual void OnExplorerAttached(EventArgs ea)
{
if (ExplorerAttached != null)
ExplorerAttached(this, ea);
}
///
/// Notifies explorer of focus change.
///
protected override void OnGotFocus(System.EventArgs e)
{
base.OnGotFocus(e);
BandObjectSite.OnFocusChangeIS(this as IInputObject, 1);
}
///
/// Notifies explorer of focus change.
///
protected override void OnLostFocus(System.EventArgs e)
{
base.OnLostFocus(e);
if (ActiveControl == null)
BandObjectSite.OnFocusChangeIS(this as IInputObject, 0);
}
///
/// Called when derived class is registered as a COM server.
///
[ComRegisterFunctionAttribute]
public static void Register(Type t)
{
string guid = t.GUID.ToString("B");
RegistryKey rkClass = Registry.ClassesRoot.CreateSubKey(@"CLSID\" + guid);
RegistryKey rkCat = rkClass.CreateSubKey("Implemented Categories");
BandObjectAttribute[] boa = (BandObjectAttribute[])t.GetCustomAttributes(
typeof(BandObjectAttribute),
false);
string name = t.Name;
string help = t.Name;
BandObjectStyle style = 0;
if (boa.Length == 1)
{
if (boa[0].Name != null)
name = boa[0].Name;
if (boa[0].HelpText != null)
help = boa[0].HelpText;
style = boa[0].Style;
}
rkClass.SetValue(null, name);
rkClass.SetValue("MenuText", name);
rkClass.SetValue("HelpText", help);
if (0 != (style & BandObjectStyle.Vertical))
rkCat.CreateSubKey("{00021493-0000-0000-C000-000000000046}");
else
if (rkCat.OpenSubKey("{00021493-0000-0000-C000-000000000046}") != null) rkCat.DeleteSubKey("{00021493-0000-0000-C000-000000000046}");
if (0 != (style & BandObjectStyle.Horizontal))
rkCat.CreateSubKey("{00021494-0000-0000-C000-000000000046}");
else
if (rkCat.OpenSubKey("{00021494-0000-0000-C000-000000000046}") != null) rkCat.DeleteSubKey("{00021494-0000-0000-C000-000000000046}");
if (0 != (style & BandObjectStyle.TaskbarToolBar))
rkCat.CreateSubKey("{00021492-0000-0000-C000-000000000046}");
else
if (rkCat.OpenSubKey("{00021492-0000-0000-C000-000000000046}") != null) rkCat.DeleteSubKey("{00021492-0000-0000-C000-000000000046}");
if (0 != (style & BandObjectStyle.ExplorerToolbar))
Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Internet Explorer\Toolbar").SetValue(guid, name);
if (0 != (style & BandObjectStyle.ExplorerBar))
Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Internet Explorer\Explorer Bars").CreateSubKey(guid);
else
if (Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Internet Explorer\Explorer Bars").OpenSubKey(guid) != null) Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Internet Explorer\Explorer Bars").DeleteSubKey(guid);
}
///
/// Called when derived class is unregistered as a COM server.
///
[ComUnregisterFunctionAttribute]
public static void Unregister(Type t)
{
string guid = t.GUID.ToString("B");
BandObjectAttribute[] boa = (BandObjectAttribute[])t.GetCustomAttributes(
typeof(BandObjectAttribute),
false);
BandObjectStyle style = 0;
if (boa.Length == 1) style = boa[0].Style;
if (0 != (style & BandObjectStyle.ExplorerToolbar))
Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Internet Explorer\Toolbar").DeleteValue(guid, false);
Registry.ClassesRoot.CreateSubKey(@"CLSID").DeleteSubKeyTree(guid);
}
}
}