Last active
July 11, 2018 02:21
-
-
Save daiplusplus/3e19bbab3c0a9a307e6b83bcfc57dd75 to your computer and use it in GitHub Desktop.
RedGate .NET Reflector - Toolbar and panel border fix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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