476 lines
14 KiB
C#
476 lines
14 KiB
C#
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;
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
[assembly: AssemblyVersion("1.0.0.0")]
|
|
|
|
namespace Foo.Deskband.BandObject
|
|
{
|
|
/// <summary>
|
|
/// Contains main desk band functionality
|
|
/// </summary>
|
|
/// <example>
|
|
/// </example>
|
|
public class BandObjectBase : UserControl, IObjectWithSite, IDeskBand, IDeskBand2, IDockingWindow, IOleWindow, IInputObject
|
|
{
|
|
[DllImport("user32.dll")]
|
|
public static extern Int32 GetWindowLong(IntPtr hwnd, int nIndex);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern Int32 SetWindowLong(IntPtr hwnd, int nIndex, Int32 dwNewLong);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern bool SetLayeredWindowAttributes(IntPtr hwnd, Int32 crKey, int bAlpha, uint dwFlags);
|
|
|
|
public const int GWL_EXSTYLE = -20;
|
|
public const int LWA_COLORKEY = 0x00000001;
|
|
public const int WS_EX_LAYERED = 0x00080000;
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
struct COLORREF
|
|
{
|
|
public byte R;
|
|
public byte G;
|
|
public byte B;
|
|
}
|
|
|
|
public BandObjectBase()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
private void InitializeComponent()
|
|
{
|
|
this.SuspendLayout();
|
|
//
|
|
// BandObjectBase
|
|
//
|
|
this.BackColor = System.Drawing.Color.Black;
|
|
this.Margin = new System.Windows.Forms.Padding(0);
|
|
this.Name = "BandObjectBase";
|
|
this.Size = new System.Drawing.Size(24, 24);
|
|
this.MinimumSize = new System.Drawing.Size(24, 24);
|
|
this.MaximumSize = new System.Drawing.Size(24, 24);
|
|
this.ResumeLayout(false);
|
|
this.HandleCreated += new System.EventHandler(Band_HandleCreated);
|
|
this.HandleDestroyed += new System.EventHandler(Band_HandleDestroyed);
|
|
}
|
|
|
|
private void Band_HandleCreated(object sender, EventArgs e)
|
|
{
|
|
IntPtr hWnd = this.Handle;
|
|
SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
|
|
SetLayeredWindowAttributes(hWnd, 0x00000000, 0, LWA_COLORKEY);
|
|
}
|
|
|
|
private void Band_HandleDestroyed(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
#region IObjectWithSite
|
|
|
|
public virtual void GetSite(ref Guid riid, out Object ppvSite)
|
|
{
|
|
ppvSite = BandObjectSite;
|
|
}
|
|
|
|
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.
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IDeskband
|
|
|
|
public virtual void GetWindow(out System.IntPtr phwnd)
|
|
{
|
|
phwnd = Handle;
|
|
}
|
|
|
|
public virtual void ContextSensitiveHelp(bool fEnterMode){}
|
|
|
|
/// <summary>
|
|
/// Called by explorer when band object needs to be showed or hidden.
|
|
/// </summary>
|
|
/// <param name="fShow"></param>
|
|
public virtual void ShowDW(bool fShow)
|
|
{
|
|
if (fShow)
|
|
Show();
|
|
else
|
|
Hide();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called by explorer when window is about to close.
|
|
/// </summary>
|
|
public virtual void CloseDW(UInt32 dwReserved)
|
|
{
|
|
Dispose(true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Not used.
|
|
/// </summary>
|
|
public virtual void ResizeBorderDW(IntPtr prcBorder, Object punkToolbarSite, bool fReserved) { }
|
|
|
|
public virtual void GetBandInfo(UInt32 dwBandID, UInt32 dwViewMode, ref DESKBANDINFO dbi)
|
|
{
|
|
|
|
if ((dbi.dwMask & DBIM.MINSIZE) != 0)
|
|
{
|
|
dbi.ptMinSize.X = MinSize.Width;
|
|
dbi.ptMinSize.Y = MinSize.Height;
|
|
}
|
|
|
|
if ((dbi.dwMask & DBIM.MAXSIZE) != 0)
|
|
{
|
|
dbi.ptMaxSize.X = MaxSize.Width;
|
|
dbi.ptMaxSize.Y = MaxSize.Height;
|
|
}
|
|
|
|
if ((dbi.dwMask & DBIM.INTEGRAL) != 0)
|
|
{
|
|
dbi.ptIntegral.X = IntegralSize.Width;
|
|
dbi.ptIntegral.Y = IntegralSize.Height;
|
|
}
|
|
|
|
if ((dbi.dwMask & DBIM.ACTUAL) != 0)
|
|
{
|
|
dbi.ptActual.X = Size.Width;
|
|
dbi.ptActual.Y = Size.Height;
|
|
}
|
|
|
|
if ((dbi.dwMask & DBIM.TITLE) != 0)
|
|
{
|
|
dbi.wszTitle = Title;
|
|
}
|
|
|
|
//Use the default background color by removing this flag
|
|
dbi.dwMask &= ~DBIM.BKCOLOR;
|
|
|
|
//COLORREF bkColor;
|
|
//bkColor.R = Color.Black.R;
|
|
//bkColor.G = Color.Black.G;
|
|
//bkColor.B = Color.Black.B;
|
|
//Color.to
|
|
//dbi.crBkgnd = Int32.MaxValue;
|
|
//dbi.crBkgnd = 0xDEDEDE;
|
|
|
|
dbi.dwModeFlags = (DBIMF)DBIM.TITLE | (DBIMF)DBIM.ACTUAL | (DBIMF)DBIM.MAXSIZE | (DBIMF)DBIM.MINSIZE | (DBIMF)DBIM.INTEGRAL;
|
|
dbi.dwModeFlags = dbi.dwModeFlags | DBIMF.ALWAYSGRIPPER | DBIMF.VARIABLEHEIGHT | DBIMF.ADDTOFRONT;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IDeskBand2
|
|
|
|
public void CanRenderComposited(ref bool pfCanRenderComposited)
|
|
{
|
|
pfCanRenderComposited = true;
|
|
}
|
|
|
|
public void GetCompositionState(ref bool pfCompositionEnabled)
|
|
{
|
|
pfCompositionEnabled = _compositionEnabled;
|
|
}
|
|
|
|
public void SetCompositionState(bool fCompositionEnabled)
|
|
{
|
|
_compositionEnabled = fCompositionEnabled;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IInputObject
|
|
|
|
/// <summary>
|
|
/// Called explorer when focus has to be chenged.
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called by explorer to process keyboard events. Undersatands Tab and F6.
|
|
/// </summary>
|
|
/// <param name="msg"></param>
|
|
/// <returns>S_OK if message was processed, S_FALSE otherwise.</returns>
|
|
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
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region EventHandlers
|
|
|
|
/// <summary>
|
|
/// Override this method to handle ExplorerAttached event.
|
|
/// </summary>
|
|
/// <param name="ea"></param>
|
|
protected virtual void OnExplorerAttached(EventArgs ea)
|
|
{
|
|
if ( ExplorerAttached != null )
|
|
ExplorerAttached(this, ea);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Notifies explorer of focus change.
|
|
/// </summary>
|
|
protected override void OnGotFocus(System.EventArgs e)
|
|
{
|
|
base.OnGotFocus(e);
|
|
BandObjectSite.OnFocusChangeIS(this as IInputObject, 1);
|
|
}
|
|
/// <summary>
|
|
/// Notifies explorer of focus change.
|
|
/// </summary>
|
|
protected override void OnLostFocus(System.EventArgs e)
|
|
{
|
|
base.OnLostFocus(e);
|
|
if( ActiveControl == null )
|
|
BandObjectSite.OnFocusChangeIS(this as IInputObject, 0);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region COM_Bookkeeping
|
|
|
|
/// <summary>
|
|
/// Called when derived class is registered as a COM server.
|
|
/// </summary>
|
|
[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}");
|
|
|
|
if( 0 != (style & BandObjectStyle.Horizontal) )
|
|
rkCat.CreateSubKey("{00021494-0000-0000-C000-000000000046}");
|
|
|
|
if( 0 != (style & BandObjectStyle.TaskbarToolBar) )
|
|
rkCat.CreateSubKey("{00021492-0000-0000-C000-000000000046}");
|
|
|
|
if( 0 != (style & BandObjectStyle.ExplorerToolbar) )
|
|
Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Internet Explorer\Toolbar").SetValue(guid,name);
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when derived class is unregistered as a COM server.
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
/// <summary>
|
|
/// Title of band object. Displayed at the left or on top of the band object.
|
|
/// </summary>
|
|
[Browsable(true)]
|
|
[DefaultValue("")]
|
|
public String Title
|
|
{
|
|
get
|
|
{
|
|
return _title;
|
|
}
|
|
set
|
|
{
|
|
_title = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Minimum size of the band object. Default value of -1 sets no minimum constraint.
|
|
/// </summary>
|
|
[Browsable(true)]
|
|
[DefaultValue(typeof(Size), "-1,-1")]
|
|
public Size MinSize
|
|
{
|
|
get
|
|
{
|
|
return _minSize;
|
|
}
|
|
set
|
|
{
|
|
_minSize = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Maximum size of the band object. Default value of -1 sets no maximum constraint.
|
|
/// </summary>
|
|
[Browsable(true)]
|
|
[DefaultValue(typeof(Size), "-1,-1")]
|
|
public Size MaxSize
|
|
{
|
|
get
|
|
{
|
|
return _maxSize;
|
|
}
|
|
set
|
|
{
|
|
_maxSize = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Says that band object's size must be multiple of this size. Defauilt value of -1 does not set this constraint.
|
|
/// </summary>
|
|
[Browsable(true)]
|
|
[DefaultValue(typeof(Size), "-1,-1")]
|
|
public Size IntegralSize
|
|
{
|
|
get
|
|
{
|
|
return _integralSize;
|
|
}
|
|
set
|
|
{
|
|
_integralSize = value;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Member Variables
|
|
|
|
/// <summary>
|
|
/// This event is fired after reference to hosting explorer is retreived and stored in Explorer property.
|
|
/// </summary>
|
|
public event EventHandler ExplorerAttached;
|
|
|
|
protected WebBrowserClass Explorer;
|
|
protected IInputObjectSite BandObjectSite;
|
|
|
|
private bool _compositionEnabled = true;
|
|
private String _title;
|
|
private Size _minSize = new Size(-1, -1);
|
|
private Size _integralSize = new Size(-1, -1);
|
|
private Size _maxSize = new Size(-1, -1);
|
|
|
|
#endregion
|
|
}
|
|
} |