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 { /// /// Contains main desk band functionality /// /// /// 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){} /// /// 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 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 /// /// 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 } #endregion #region EventHandlers /// /// 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); } #endregion #region COM_Bookkeeping /// /// 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}"); 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); } /// /// 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); } #endregion #region Properties /// /// 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; } } /// /// 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; } } /// /// 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; } } /// /// 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; } } #endregion #region Member Variables /// /// This event is fired after reference to hosting explorer is retreived and stored in Explorer property. /// 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 } }