Skip to content

Instantly share code, notes, and snippets.

@daiplusplus
Last active July 11, 2018 02:21
Show Gist options
  • Save daiplusplus/3e19bbab3c0a9a307e6b83bcfc57dd75 to your computer and use it in GitHub Desktop.
Save daiplusplus/3e19bbab3c0a9a307e6b83bcfc57dd75 to your computer and use it in GitHub Desktop.
RedGate .NET Reflector - Toolbar and panel border fix
// I use Redgate .NET Reflector ( https://www.red-gate.com/products/dotnet-development/reflector/index ) regularly and there's just a couple of things about it that irritate me:
// 1. The toolbars at the top are on two lines which wastes space. This program automatically moves the toolbar next to the menubar to save space.
// 2. The left-hand-side tree-view has a 1px black border set for some reason, this looks ugly. This program removes the border.
// Instructions:
// 1. Save this file somewhere.
// 2. Create a new C# Class-library (DLL) project in Visual Studio. Use AnyCPU.
// 3. Add a reference to Reflector.exe
// 4. Build.
// 5. Open reflector and add the output assembly to its add-ins list.
// 6. Restart Reflector. You'll observe the toolbars and tree-view and fixed during the window's initialization.
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Windows.Forms;
using Reflector;
namespace MyPackage
{
public class ReflectorToolbarsFixPackage : IPackage
{
private Form mainForm;
private IWindowManager windowManager;
private ICommandBarManager barManager;
public void Load(IServiceProvider serviceProvider)
{
this.windowManager = (IWindowManager) serviceProvider.GetService( typeof(IWindowManager) );
this.barManager = (ICommandBarManager)serviceProvider.GetService( typeof(ICommandBarManager) );
this.mainForm = (Form)this.windowManager;
this.windowManager.Load += this.WindowManager_Load;
}
private IAsyncResult afterLoadResult;
private void WindowManager_Load(Object sender, EventArgs e)
{
this.afterLoadResult = this.mainForm.BeginInvoke( new Action( this.AfterLoaded ) );
}
private void AfterLoaded()
{
this.RemovePanelBorders();
this.MoveRebarBands();
this.mainForm.EndInvoke( this.afterLoadResult );
this.afterLoadResult = null;
}
private void RemovePanelBorders()
{
Form mainForm = (Form)this.windowManager;
List<Panel> panels = new List<Panel>();
FindControls( panels, mainForm, p => p.BorderStyle == BorderStyle.FixedSingle );
foreach( Panel p in panels )
{
p.BorderStyle = BorderStyle.None;
}
}
private void MoveRebarBands()
{
// Reflector is using a Win32 Rebar control directly by subclassing Control and using CreateParams to create the control.
Control barManagerControl = (Control)this.barManager;
// 1. Remove "Break" and "FixedSize" from the toolbar band (index 1) and add "TopAlign" (it's the only way I know to make it share a row with the menubar band)
{
REBARBANDINFO bandInfo = RebarUtility.GetBandInfo( barManagerControl.Handle, bandIndex: 1 );
RebarInfoStyle unsetMask = ~( RebarInfoStyle.Break /* | RebarInfoStyle.FixedSize */ );
bandInfo.fStyle = bandInfo.fStyle & unsetMask; // https://stackoverflow.com/questions/3920307/how-can-i-remove-a-flag-in-c
//bandInfo.fStyle |= RebarInfoStyle.TopAlign;
bandInfo.fMask = RebarInfoFlags.Style;
RebarUtility.SetBandInfo( barManagerControl.Handle, 1, bandInfo );
}
// 2: Resize the menubar band to its ideal size:
{
REBARBANDINFO bandInfo = RebarUtility.GetBandInfo( barManagerControl.Handle, bandIndex: 0 );
UInt32 idealWidth = (UInt32)bandInfo.cxIdeal;
RebarUtility.MaximizeBand( barManagerControl.Handle, 0, idealWidth );
}
// 3: Minimize the toolbar band to its ideal size:
// {
// REBARBANDINFO bandInfo = RebarUtility.GetBandInfo( barManagerControl.Handle, bandIndex: 1 );
//
// UInt32 idealWidth = (UInt32)bandInfo.cxIdeal;
//
// RebarUtility.MaximizeBand( barManagerControl.Handle, 1, idealWidth );
// }
}
public void Unload()
{
}
private static void FindControls<TControl>(List<TControl> controls, Control control, Func<TControl,Boolean> predicate)
where TControl : Control
{
if( control is TControl match && predicate( match ) )
{
controls.Add( match );
}
foreach( Control child in control.Controls )
{
FindControls( controls, child, predicate );
}
}
}
internal static class RebarUtility
{
public static Int32 GetBandCount( IntPtr hWnd )
{
IntPtr result = NativeMethods.SendMessage( hWnd, (UInt32)RebarMessages.GetBandCount, IntPtr.Zero, IntPtr.Zero );
return result.ToInt32();
}
public static Int32 GetRowCount( IntPtr hWnd )
{
IntPtr result = NativeMethods.SendMessage( hWnd, (UInt32)RebarMessages.GetRowCount, IntPtr.Zero, IntPtr.Zero );
return result.ToInt32();
}
public static Boolean MoveBand( IntPtr hWnd, UInt32 fromIndex, UInt32 toIndex )
{
IntPtr result = NativeMethods.SendMessage( hWnd, (UInt32)RebarMessages.MoveBand, new IntPtr( fromIndex ), new IntPtr( toIndex ) );
return result == IntPtr.Zero;
}
public static void MaximizeBand( IntPtr hWnd, UInt32 bandIndex )
{
MaximizeBand( hWnd, 0 );
}
public static void MaximizeBand( IntPtr hWnd, UInt32 bandIndex, UInt32 idealWidth )
{
IntPtr result = NativeMethods.SendMessage( hWnd, (UInt32)RebarMessages.MaximizeBand, new IntPtr( bandIndex ), new IntPtr( idealWidth ) );
// return value is ignored.
}
public static void MinimizeBand( IntPtr hWnd, UInt32 bandIndex )
{
IntPtr result = NativeMethods.SendMessage( hWnd, (UInt32)RebarMessages.MaximizeBand, new IntPtr( bandIndex ), IntPtr.Zero );
// return value is ignored.
}
public static REBARBANDINFO GetBandInfo( IntPtr hWnd, UInt32 bandIndex )
{
Int32 size = Marshal.SizeOf<REBARBANDINFO>();
REBARBANDINFO buffer = new REBARBANDINFO();
buffer.cbSize = size;
buffer.fMask = RebarInfoFlags._All;
IntPtr result = NativeMethods.SendMessage( hWnd, (UInt32)RebarMessages.GetBandInfoW, new IntPtr( bandIndex ), ref buffer );
if( result == IntPtr.Zero ) throw new Win32Exception();
return buffer;
}
public static void SetBandInfo( IntPtr hWnd, Int32 bandIndex, REBARBANDINFO info )
{
Int32 size = Marshal.SizeOf<REBARBANDINFO>();
info.cbSize = size;
IntPtr result = NativeMethods.SendMessage( hWnd, (UInt32)RebarMessages.SetBandInfoW, new IntPtr( bandIndex ), ref info );
if( result == IntPtr.Zero ) throw new Win32Exception();
}
}
internal enum RebarMessages : UInt32
{
WM_USER = 0x400,
InsertBandA = WM_USER + 1,
DeleteBand = WM_USER + 2,
GetBarInfo = WM_USER + 3,
SetBarInfo = WM_USER + 4,
SetBandInfoA = WM_USER + 6,
SetParent = WM_USER + 7,
HitTest = WM_USER + 8,
GetRect = WM_USER + 9,
InsertBandW = WM_USER + 10,
SetBandInfoW = WM_USER + 11,
GetBandCount = WM_USER + 12,
GetRowCount = WM_USER + 13,
GetRowHeight = WM_USER + 14,
IdToIndex = WM_USER + 16,
GetTooltips = WM_USER + 17,
SetTooltips = WM_USER + 18,
SetBackColor = WM_USER + 19,
GetBackColor = WM_USER + 20,
SetTextColor = WM_USER + 21,
GetTextColor = WM_USER + 22,
SizeToRect = WM_USER + 23,
SetColorScheme = 0x2000 + 2,
GetColorScheme = 0x2000 + 3,
BeginDrag = WM_USER + 24,
EndDrag = WM_USER + 25,
DragMove = WM_USER + 26,
GetBarHeight = WM_USER + 27,
GetBandInfoW = WM_USER + 28,
GetBandInfoA = WM_USER + 29,
MinimizeBand = WM_USER + 30,
MaximizeBand = WM_USER + 31,
GetDropTarget = 0x2000 + 4,
GetBandBorders = WM_USER + 24,
ShowBand = WM_USER + 35,
SetPalette = WM_USER + 37,
GetPalette = WM_USER + 38,
MoveBand = WM_USER + 39,
GetBandMargins = WM_USER + 40,
SetWindowTheme = 0x2000 + 0xB,
PushChevron = WM_USER + 43,
SetBandWidth = WM_USER + 44
}
internal static class NativeMethods
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "SendMessageW" )]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 wMsg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "SendMessageW" )]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref REBARBANDINFO lParam);
}
[StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
public Int32 Left;
public Int32 Top;
public Int32 Right;
public Int32 Bottom;
}
[StructLayout(LayoutKind.Sequential)]
internal struct REBARINFO
{
public UInt32 cbSize;
public UInt32 fMask;
public IntPtr himl;
}
[StructLayout(LayoutKind.Sequential)]
internal struct REBARBANDINFO
{
public Int32 cbSize;
public RebarInfoFlags fMask;
public RebarInfoStyle fStyle;
public Int32 clrFore;
public Int32 clrBack;
[MarshalAs(UnmanagedType.LPWStr)]
public String lpText;
public Int32 cch;
public Int32 iImage;
public IntPtr hwndChild;
public Int32 cxMinChild;
public Int32 cyMinChild;
public Int32 cx;
public IntPtr hbmBack;
public Int32 wID;
public Int32 cyChild;
public Int32 cyMaxChild;
public Int32 cyIntegral;
public Int32 cxIdeal;
public Int32 lParam;
public Int32 cxHeader;
public RECT rcChevronLocation;
public UInt32 uChevronState;
}
[Flags]
internal enum RebarInfoFlags : UInt32
{
None = 0x0000,
Style = 0x0001,
Colors = 0x0002,
Text = 0x0004,
Image = 0x0008,
Child = 0x0010,
ChildSize = 0x0020,
Size = 0x0040,
Background = 0x0080,
Id = 0x0100,
IdealSize = 0x0200,
HeaderSize = 0x0800,
ChevronLocation = 0x1000,
ChevronState = 0x2000,
_All = Style | Colors | Text | Image | Child | ChildSize | Size | Background | Id | IdealSize | HeaderSize | ChevronLocation | ChevronState
}
[Flags]
internal enum RebarInfoStyle : UInt32
{
None = 0x0000,
Break = 0x0001,
FixedSize = 0x0002,
ChildEdge = 0x0004,
Hidden = 0x0008,
NoVertical = 0x0010,
FixedBitmap = 0x0020,
VariableHeight = 0x0040,
GripperAlways = 0x0080,
NoGripper = 0x0100,
UseChevron = 0x0200,
HideTitle = 0x0400,
TopAlign = 0x0800
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment