diff --git a/RetailCoder.VBE/App.cs b/RetailCoder.VBE/App.cs
index 78f6f1f1d6..4ab03cd999 100644
--- a/RetailCoder.VBE/App.cs
+++ b/RetailCoder.VBE/App.cs
@@ -63,8 +63,8 @@ public App(IVBE vbe,
_version = version;
_checkVersionCommand = checkVersionCommand;
- VBEEvents.SelectionChanged += _vbe_SelectionChanged;
- VBEEvents.WindowFocusChange += _vbe_FocusChanged;
+ VBENativeServices.SelectionChanged += _vbe_SelectionChanged;
+ VBENativeServices.WindowFocusChange += _vbe_FocusChanged;
_configService.SettingsChanged += _configService_SettingsChanged;
_parser.State.StateChanged += Parser_StateChanged;
@@ -73,6 +73,9 @@ public App(IVBE vbe,
UiDispatcher.Initialize();
}
+ //TODO - This should be able to move to the appropriate handling classes now.
+ #region Statusbar
+
private void State_StatusMessageUpdate(object sender, RubberduckStatusMessageEventArgs e)
{
var message = e.Message;
@@ -92,90 +95,79 @@ private void _vbe_SelectionChanged(object sender, SelectionChangedEventArgs e)
private void _vbe_FocusChanged(object sender, WindowChangedEventArgs e)
{
- if (e.EventType == WindowChangedEventArgs.FocusType.GotFocus)
+ if (e.EventType == FocusType.GotFocus)
{
switch (e.Window.Type)
{
case WindowKind.Designer:
+ //Designer or control on designer form selected.
RefreshSelection(e.Window);
break;
case WindowKind.CodeWindow:
+ //Caret changed in a code pane.
RefreshSelection(e.CodePane);
break;
}
- }
+ }
+ else if (e.EventType == FocusType.ChildFocus)
+ {
+ //Treeview selection changed in project window.
+ RefreshSelection();
+ }
}
private ParserState _lastStatus;
private Declaration _lastSelectedDeclaration;
private void RefreshSelection(ICodePane pane)
{
- Declaration selectedDeclaration = null;
- if (!pane.IsWrappingNullReference)
+ if (pane == null || pane.IsWrappingNullReference)
{
- selectedDeclaration = _parser.State.FindSelectedDeclaration(pane);
- var refCount = selectedDeclaration == null ? 0 : selectedDeclaration.References.Count();
- var caption = _stateBar.GetContextSelectionCaption(_vbe.ActiveCodePane, selectedDeclaration);
- _stateBar.SetContextSelectionCaption(caption, refCount);
- }
-
- var currentStatus = _parser.State.Status;
- if (ShouldEvaluateCanExecute(selectedDeclaration, currentStatus))
- {
- _appMenus.EvaluateCanExecute(_parser.State);
- _stateBar.EvaluateCanExecute(_parser.State);
+ return;
}
- _lastStatus = currentStatus;
- _lastSelectedDeclaration = selectedDeclaration;
+ var selectedDeclaration = _parser.State.FindSelectedDeclaration(pane);
+ var caption = _stateBar.GetContextSelectionCaption(_vbe.ActiveCodePane, selectedDeclaration);
+ UpdateStatusbarAndCommandState(caption, selectedDeclaration);
}
private void RefreshSelection(IWindow window)
{
- if (window.IsWrappingNullReference || window.Type != WindowKind.Designer)
+ if (window == null || window.IsWrappingNullReference || window.Type != WindowKind.Designer)
{
return;
}
- var caption = String.Empty;
- var refCount = 0;
- WindowKind windowKind = _vbe.ActiveWindow.Type;
- var pane = _vbe.ActiveCodePane;
var component = _vbe.SelectedVBComponent;
+ var caption = GetComponentControlsCaption(component);
+ //TODO: Need to find the selected declaration for the Form\Control.
+ UpdateStatusbarAndCommandState(caption, null);
+ }
- Declaration selectedDeclaration = null;
-
- //TODO - I doubt this is the best way to check if the SelectedVBComponent and the ActiveCodePane are the same component.
- if (windowKind == WindowKind.CodeWindow || (!_vbe.SelectedVBComponent.IsWrappingNullReference
- && component.ParentProject.ProjectId == pane.CodeModule.Parent.ParentProject.ProjectId
- && component.Name == pane.CodeModule.Parent.Name))
- {
- selectedDeclaration = _parser.State.FindSelectedDeclaration(pane);
- refCount = selectedDeclaration == null ? 0 : selectedDeclaration.References.Count();
- caption = _stateBar.GetContextSelectionCaption(_vbe.ActiveCodePane, selectedDeclaration);
- }
- else if (windowKind == WindowKind.Designer)
+ private void RefreshSelection()
+ {
+ var caption = string.Empty;
+ var component = _vbe.SelectedVBComponent;
+ if (component == null || component.IsWrappingNullReference)
{
- caption = GetComponentControlsCaption(component);
+ //The user might have selected the project node in Project Explorer
+ //If they've chosen a folder, we'll return the project anyway
+ caption = !_vbe.ActiveVBProject.IsWrappingNullReference
+ ? _vbe.ActiveVBProject.Name
+ : null;
}
else
{
- if (_vbe.SelectedVBComponent.IsWrappingNullReference)
- {
- //The user might have selected the project node in Project Explorer
- //If they've chosen a folder, we'll return the project anyway
- caption = !_vbe.ActiveVBProject.IsWrappingNullReference
- ? _vbe.ActiveVBProject.Name
- : null;
- }
- else
- {
- caption = component.Type == ComponentType.UserForm && component.HasOpenDesigner
- ? GetComponentControlsCaption(component)
- : String.Format("{0}.{1} ({2})", component.ParentProject.Name, component.Name, component.Type);
- }
+ caption = component.Type == ComponentType.UserForm && component.HasOpenDesigner
+ ? GetComponentControlsCaption(component)
+ : string.Format("{0}.{1} ({2})", component.ParentProject.Name, component.Name, component.Type);
}
+ //TODO: Need to find the selected declaration for the selected treeview item.
+ UpdateStatusbarAndCommandState(caption, null);
+ }
+ private void UpdateStatusbarAndCommandState(string caption, Declaration selectedDeclaration)
+ {
+ var refCount = selectedDeclaration == null ? 0 : selectedDeclaration.References.Count();
_stateBar.SetContextSelectionCaption(caption, refCount);
var currentStatus = _parser.State.Status;
@@ -186,7 +178,7 @@ private void RefreshSelection(IWindow window)
}
_lastStatus = currentStatus;
- _lastSelectedDeclaration = selectedDeclaration;
+ _lastSelectedDeclaration = selectedDeclaration;
}
private string GetComponentControlsCaption(IVBComponent component)
@@ -215,6 +207,8 @@ private bool ShouldEvaluateCanExecute(Declaration selectedDeclaration, ParserSta
(selectedDeclaration == null && _lastSelectedDeclaration != null);
}
+ #endregion
+
private void _configService_SettingsChanged(object sender, ConfigurationChangedEventArgs e)
{
_config = _configService.LoadConfiguration();
@@ -366,8 +360,8 @@ public void Dispose()
_parser.State.StatusMessageUpdate -= State_StatusMessageUpdate;
}
- VBEEvents.SelectionChanged += _vbe_SelectionChanged;
- VBEEvents.WindowFocusChange += _vbe_FocusChanged;
+ VBENativeServices.SelectionChanged += _vbe_SelectionChanged;
+ VBENativeServices.WindowFocusChange += _vbe_FocusChanged;
if (_configService != null)
{
diff --git a/RetailCoder.VBE/Extension.cs b/RetailCoder.VBE/Extension.cs
index b53012ff34..4da14b26e5 100644
--- a/RetailCoder.VBE/Extension.cs
+++ b/RetailCoder.VBE/Extension.cs
@@ -56,7 +56,7 @@ public void OnConnection(object Application, ext_ConnectMode ConnectMode, object
{
var vbe = (Microsoft.Vbe.Interop.VBE) Application;
_ide = new VBEditor.SafeComWrappers.VBA.VBE(vbe);
- VBEEvents.HookEvents(_ide);
+ VBENativeServices.HookEvents(_ide);
var addin = (Microsoft.Vbe.Interop.AddIn)AddInInst;
_addin = new VBEditor.SafeComWrappers.VBA.AddIn(addin) { Object = this };
@@ -221,7 +221,7 @@ private void Startup()
private void ShutdownAddIn()
{
- VBEEvents.UnhookEvents();
+ VBENativeServices.UnhookEvents();
var currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve -= LoadFromSameFolder;
diff --git a/RetailCoder.VBE/UI/Refactorings/ExtractInterfaceDialog.Designer.cs b/RetailCoder.VBE/UI/Refactorings/ExtractInterfaceDialog.Designer.cs
index b303ce54ad..7c294dd60f 100644
--- a/RetailCoder.VBE/UI/Refactorings/ExtractInterfaceDialog.Designer.cs
+++ b/RetailCoder.VBE/UI/Refactorings/ExtractInterfaceDialog.Designer.cs
@@ -56,21 +56,19 @@ private void InitializeComponent()
this.flowLayoutPanel2.Controls.Add(this.OkButton);
this.flowLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Bottom;
this.flowLayoutPanel2.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;
- this.flowLayoutPanel2.Location = new System.Drawing.Point(0, 364);
- this.flowLayoutPanel2.Margin = new System.Windows.Forms.Padding(4);
+ this.flowLayoutPanel2.Location = new System.Drawing.Point(0, 296);
this.flowLayoutPanel2.Name = "flowLayoutPanel2";
- this.flowLayoutPanel2.Padding = new System.Windows.Forms.Padding(11, 10, 0, 10);
- this.flowLayoutPanel2.Size = new System.Drawing.Size(572, 53);
+ this.flowLayoutPanel2.Padding = new System.Windows.Forms.Padding(8, 8, 0, 8);
+ this.flowLayoutPanel2.Size = new System.Drawing.Size(459, 43);
this.flowLayoutPanel2.TabIndex = 28;
//
// CancelDialogButton
//
this.CancelDialogButton.BackColor = System.Drawing.SystemColors.ButtonFace;
this.CancelDialogButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.CancelDialogButton.Location = new System.Drawing.Point(457, 14);
- this.CancelDialogButton.Margin = new System.Windows.Forms.Padding(4);
+ this.CancelDialogButton.Location = new System.Drawing.Point(373, 11);
this.CancelDialogButton.Name = "CancelDialogButton";
- this.CancelDialogButton.Size = new System.Drawing.Size(100, 28);
+ this.CancelDialogButton.Size = new System.Drawing.Size(75, 23);
this.CancelDialogButton.TabIndex = 5;
this.CancelDialogButton.Text = "Cancel";
this.CancelDialogButton.UseVisualStyleBackColor = false;
@@ -79,10 +77,9 @@ private void InitializeComponent()
//
this.OkButton.BackColor = System.Drawing.SystemColors.ButtonFace;
this.OkButton.DialogResult = System.Windows.Forms.DialogResult.OK;
- this.OkButton.Location = new System.Drawing.Point(349, 14);
- this.OkButton.Margin = new System.Windows.Forms.Padding(4);
+ this.OkButton.Location = new System.Drawing.Point(292, 11);
this.OkButton.Name = "OkButton";
- this.OkButton.Size = new System.Drawing.Size(100, 28);
+ this.OkButton.Size = new System.Drawing.Size(75, 23);
this.OkButton.TabIndex = 4;
this.OkButton.Text = "Ok";
this.OkButton.UseVisualStyleBackColor = false;
@@ -90,8 +87,7 @@ private void InitializeComponent()
// InvalidNameValidationIcon
//
this.InvalidNameValidationIcon.Image = global::Rubberduck.Properties.Resources.cross_circle;
- this.InvalidNameValidationIcon.Location = new System.Drawing.Point(549, 102);
- this.InvalidNameValidationIcon.Margin = new System.Windows.Forms.Padding(4);
+ this.InvalidNameValidationIcon.Location = new System.Drawing.Point(412, 83);
this.InvalidNameValidationIcon.Name = "InvalidNameValidationIcon";
this.InvalidNameValidationIcon.Size = new System.Drawing.Size(16, 16);
this.InvalidNameValidationIcon.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
@@ -100,19 +96,17 @@ private void InitializeComponent()
//
// InterfaceNameBox
//
- this.InterfaceNameBox.Location = new System.Drawing.Point(16, 112);
- this.InterfaceNameBox.Margin = new System.Windows.Forms.Padding(4);
+ this.InterfaceNameBox.Location = new System.Drawing.Point(12, 91);
this.InterfaceNameBox.Name = "InterfaceNameBox";
- this.InterfaceNameBox.Size = new System.Drawing.Size(541, 22);
+ this.InterfaceNameBox.Size = new System.Drawing.Size(437, 20);
this.InterfaceNameBox.TabIndex = 0;
//
// NameLabel
//
this.NameLabel.AutoSize = true;
- this.NameLabel.Location = new System.Drawing.Point(13, 91);
- this.NameLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.NameLabel.Location = new System.Drawing.Point(10, 74);
this.NameLabel.Name = "NameLabel";
- this.NameLabel.Size = new System.Drawing.Size(49, 17);
+ this.NameLabel.Size = new System.Drawing.Size(38, 13);
this.NameLabel.TabIndex = 29;
this.NameLabel.Text = "Name:";
//
@@ -120,20 +114,20 @@ private void InitializeComponent()
//
this.TitleLabel.AutoSize = true;
this.TitleLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Bold);
- this.TitleLabel.Location = new System.Drawing.Point(20, 11);
- this.TitleLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.TitleLabel.Location = new System.Drawing.Point(15, 9);
this.TitleLabel.Name = "TitleLabel";
- this.TitleLabel.Padding = new System.Windows.Forms.Padding(3, 2, 3, 2);
- this.TitleLabel.Size = new System.Drawing.Size(137, 22);
+ this.TitleLabel.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2);
+ this.TitleLabel.Size = new System.Drawing.Size(115, 19);
this.TitleLabel.TabIndex = 2;
this.TitleLabel.Text = "Extract Interface";
//
// InstructionsLabel
//
- this.InstructionsLabel.Location = new System.Drawing.Point(20, 30);
+ this.InstructionsLabel.Location = new System.Drawing.Point(15, 24);
+ this.InstructionsLabel.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.InstructionsLabel.Name = "InstructionsLabel";
- this.InstructionsLabel.Padding = new System.Windows.Forms.Padding(4);
- this.InstructionsLabel.Size = new System.Drawing.Size(549, 34);
+ this.InstructionsLabel.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
+ this.InstructionsLabel.Size = new System.Drawing.Size(412, 28);
this.InstructionsLabel.TabIndex = 3;
this.InstructionsLabel.Text = "Please specify interface name and members.";
//
@@ -144,9 +138,8 @@ private void InitializeComponent()
this.DescriptionPanel.Controls.Add(this.InstructionsLabel);
this.DescriptionPanel.Dock = System.Windows.Forms.DockStyle.Top;
this.DescriptionPanel.Location = new System.Drawing.Point(0, 0);
- this.DescriptionPanel.Margin = new System.Windows.Forms.Padding(4);
this.DescriptionPanel.Name = "DescriptionPanel";
- this.DescriptionPanel.Size = new System.Drawing.Size(572, 84);
+ this.DescriptionPanel.Size = new System.Drawing.Size(459, 68);
this.DescriptionPanel.TabIndex = 33;
//
// MembersGroupBox
@@ -157,11 +150,11 @@ private void InitializeComponent()
this.MembersGroupBox.Controls.Add(this.InterfaceMembersGridView);
this.MembersGroupBox.Controls.Add(this.DeselectAllButton);
this.MembersGroupBox.Controls.Add(this.SelectAllButton);
- this.MembersGroupBox.Location = new System.Drawing.Point(16, 142);
- this.MembersGroupBox.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
+ this.MembersGroupBox.Location = new System.Drawing.Point(12, 115);
+ this.MembersGroupBox.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.MembersGroupBox.Name = "MembersGroupBox";
- this.MembersGroupBox.Padding = new System.Windows.Forms.Padding(3, 2, 3, 2);
- this.MembersGroupBox.Size = new System.Drawing.Size(541, 214);
+ this.MembersGroupBox.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2);
+ this.MembersGroupBox.Size = new System.Drawing.Size(436, 174);
this.MembersGroupBox.TabIndex = 1;
this.MembersGroupBox.TabStop = false;
this.MembersGroupBox.Text = "Members";
@@ -175,8 +168,8 @@ private void InitializeComponent()
this.InterfaceMembersGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.InterfaceMembersGridView.ColumnHeadersVisible = false;
this.InterfaceMembersGridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnEnter;
- this.InterfaceMembersGridView.Location = new System.Drawing.Point(7, 26);
- this.InterfaceMembersGridView.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
+ this.InterfaceMembersGridView.Location = new System.Drawing.Point(5, 21);
+ this.InterfaceMembersGridView.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.InterfaceMembersGridView.MultiSelect = false;
this.InterfaceMembersGridView.Name = "InterfaceMembersGridView";
this.InterfaceMembersGridView.RowHeadersVisible = false;
@@ -184,25 +177,25 @@ private void InitializeComponent()
this.InterfaceMembersGridView.RowTemplate.Height = 24;
this.InterfaceMembersGridView.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.InterfaceMembersGridView.ShowEditingIcon = false;
- this.InterfaceMembersGridView.Size = new System.Drawing.Size(427, 174);
+ this.InterfaceMembersGridView.Size = new System.Drawing.Size(320, 141);
this.InterfaceMembersGridView.TabIndex = 1;
//
// DeselectAllButton
//
- this.DeselectAllButton.Location = new System.Drawing.Point(441, 64);
- this.DeselectAllButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
+ this.DeselectAllButton.Location = new System.Drawing.Point(331, 52);
+ this.DeselectAllButton.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.DeselectAllButton.Name = "DeselectAllButton";
- this.DeselectAllButton.Size = new System.Drawing.Size(93, 32);
+ this.DeselectAllButton.Size = new System.Drawing.Size(100, 26);
this.DeselectAllButton.TabIndex = 3;
this.DeselectAllButton.Text = "Deselect All";
this.DeselectAllButton.UseVisualStyleBackColor = true;
//
// SelectAllButton
//
- this.SelectAllButton.Location = new System.Drawing.Point(441, 26);
- this.SelectAllButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
+ this.SelectAllButton.Location = new System.Drawing.Point(331, 21);
+ this.SelectAllButton.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.SelectAllButton.Name = "SelectAllButton";
- this.SelectAllButton.Size = new System.Drawing.Size(93, 32);
+ this.SelectAllButton.Size = new System.Drawing.Size(100, 26);
this.SelectAllButton.TabIndex = 2;
this.SelectAllButton.Text = "Select All";
this.SelectAllButton.UseVisualStyleBackColor = true;
@@ -210,10 +203,10 @@ private void InitializeComponent()
// ExtractInterfaceDialog
//
this.AcceptButton = this.OkButton;
- this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.CancelDialogButton;
- this.ClientSize = new System.Drawing.Size(572, 417);
+ this.ClientSize = new System.Drawing.Size(459, 339);
this.Controls.Add(this.MembersGroupBox);
this.Controls.Add(this.DescriptionPanel);
this.Controls.Add(this.InvalidNameValidationIcon);
@@ -222,7 +215,7 @@ private void InitializeComponent()
this.Controls.Add(this.flowLayoutPanel2);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
- this.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
+ this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "ExtractInterfaceDialog";
diff --git a/Rubberduck.VBEEditor/Events/VBEEvents.cs b/Rubberduck.VBEEditor/Events/VBENativeServices.cs
similarity index 83%
rename from Rubberduck.VBEEditor/Events/VBEEvents.cs
rename to Rubberduck.VBEEditor/Events/VBENativeServices.cs
index 661d1bd067..2391e5c652 100644
--- a/Rubberduck.VBEEditor/Events/VBEEvents.cs
+++ b/Rubberduck.VBEEditor/Events/VBENativeServices.cs
@@ -9,7 +9,7 @@
namespace Rubberduck.VBEditor.Events
{
- public static class VBEEvents
+ public static class VBENativeServices
{
private static User32.WinEventProc _eventProc;
private static IntPtr _eventHandle;
@@ -66,7 +66,10 @@ public static void UnhookEvents()
public static void VbeEventCallback(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild,
uint dwEventThread, uint dwmsEventTime)
{
- if (hwnd != IntPtr.Zero && idObject == (int)ObjId.Caret && eventType == (uint)WinEvent.ObjectLocationChange && hwnd.ToWindowType() == WindowType.VbaWindow)
+ if (hwnd != IntPtr.Zero &&
+ idObject == (int)ObjId.Caret &&
+ (eventType == (uint)WinEvent.ObjectLocationChange || eventType == (uint)WinEvent.ObjectCreate) &&
+ hwnd.ToWindowType() == WindowType.VbaWindow)
{
OnSelectionChanged(hwnd);
}
@@ -83,6 +86,17 @@ public static void VbeEventCallback(IntPtr hWinEventHook, uint eventType, IntPtr
DetachWindow(hwnd);
}
}
+ else if (eventType == (uint)WinEvent.ObjectFocus && idObject == (int)ObjId.Client)
+ {
+ //Test to see if it was a selection change in the project window.
+ var parent = User32.GetParent(hwnd);
+ if (parent != IntPtr.Zero && parent.ToWindowType() == WindowType.Project)
+ {
+ FocusDispatcher(_vbe, new WindowChangedEventArgs(parent, null, null, FocusType.ChildFocus));
+ }
+ }
+ //This is an output window firehose, leave this here, but comment it out when done.
+ //if (idObject != (int)ObjId.Cursor) Debug.WriteLine("Hwnd: {0:X4} - EventType {1:X4}, idObject {2}, idChild {3}", (int)hwnd, eventType, idObject, idChild);
}
private static void AttachWindow(IntPtr hwnd)
@@ -176,15 +190,21 @@ public enum WindowType
{
Indeterminate,
VbaWindow,
- DesignerWindow
+ DesignerWindow,
+ Project
}
public static WindowType ToWindowType(this IntPtr hwnd)
+ {
+ WindowType id;
+ return Enum.TryParse(hwnd.ToClassName(), true, out id) ? id : WindowType.Indeterminate;
+ }
+
+ public static string ToClassName(this IntPtr hwnd)
{
var name = new StringBuilder(128);
User32.GetClassName(hwnd, name, name.Capacity);
- WindowType id;
- return Enum.TryParse(name.ToString(), out id) ? id : WindowType.Indeterminate;
+ return name.ToString();
}
}
}
diff --git a/Rubberduck.VBEEditor/Events/WindowChangedEventArgs.cs b/Rubberduck.VBEEditor/Events/WindowChangedEventArgs.cs
index 0d0bf99611..6357f23824 100644
--- a/Rubberduck.VBEEditor/Events/WindowChangedEventArgs.cs
+++ b/Rubberduck.VBEEditor/Events/WindowChangedEventArgs.cs
@@ -3,14 +3,15 @@
namespace Rubberduck.VBEditor.Events
{
- public class WindowChangedEventArgs : EventArgs
+ public enum FocusType
{
- public enum FocusType
- {
- GotFocus,
- LostFocus
- }
+ GotFocus,
+ LostFocus,
+ ChildFocus
+ }
+ public class WindowChangedEventArgs : EventArgs
+ {
public IntPtr Hwnd { get; private set; }
public IWindow Window { get; private set; }
public ICodePane CodePane { get; private set; }
diff --git a/Rubberduck.VBEEditor/Rubberduck.VBEditor.csproj b/Rubberduck.VBEEditor/Rubberduck.VBEditor.csproj
index bb6b162fe0..672bc3ae6a 100644
--- a/Rubberduck.VBEEditor/Rubberduck.VBEditor.csproj
+++ b/Rubberduck.VBEEditor/Rubberduck.VBEditor.csproj
@@ -125,7 +125,7 @@
-
+
diff --git a/Rubberduck.VBEEditor/SafeComWrappers/Abstract/IVBE.cs b/Rubberduck.VBEEditor/SafeComWrappers/Abstract/IVBE.cs
index 0478864e60..5c1aa50b79 100644
--- a/Rubberduck.VBEEditor/SafeComWrappers/Abstract/IVBE.cs
+++ b/Rubberduck.VBEEditor/SafeComWrappers/Abstract/IVBE.cs
@@ -21,6 +21,7 @@ public interface IVBE : ISafeComWrapper, IEquatable
IWindows Windows { get; }
IHostApplication HostApplication();
+ IWindow ActiveMDIChild();
bool IsInDesignMode { get; }
}
diff --git a/Rubberduck.VBEEditor/SafeComWrappers/VB6/VBE.cs b/Rubberduck.VBEEditor/SafeComWrappers/VB6/VBE.cs
index 10515004fd..9277e8f2fe 100644
--- a/Rubberduck.VBEEditor/SafeComWrappers/VB6/VBE.cs
+++ b/Rubberduck.VBEEditor/SafeComWrappers/VB6/VBE.cs
@@ -109,6 +109,11 @@ public IHostApplication HostApplication()
return null;
}
+ public IWindow ActiveMDIChild()
+ {
+ throw new NotImplementedException();
+ }
+
public bool IsInDesignMode
{
get { return VBProjects.All(project => project.Mode == EnvironmentMode.Design); }
diff --git a/Rubberduck.VBEEditor/SafeComWrappers/VBA/VBE.cs b/Rubberduck.VBEEditor/SafeComWrappers/VBA/VBE.cs
index 57fef9c3ea..11cf2309a0 100644
--- a/Rubberduck.VBEEditor/SafeComWrappers/VBA/VBE.cs
+++ b/Rubberduck.VBEEditor/SafeComWrappers/VBA/VBE.cs
@@ -3,11 +3,13 @@
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
+using System.Text;
using Rubberduck.VBEditor.Application;
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
using Rubberduck.VBEditor.SafeComWrappers.MSForms;
using Rubberduck.VBEditor.SafeComWrappers.Office.Core;
using Rubberduck.VBEditor.SafeComWrappers.Office.Core.Abstract;
+using Rubberduck.VBEditor.WindowsApi;
using VB = Microsoft.Vbe.Interop;
namespace Rubberduck.VBEditor.SafeComWrappers.VBA
@@ -279,6 +281,33 @@ public IHostApplication HostApplication()
return null;
}
+ /// Returns the topmost MDI child window.
+ public IWindow ActiveMDIChild()
+ {
+ const string mdiClientClass = "MDIClient";
+ const int maxCaptionLength = 512;
+
+ IntPtr mainWindow = (IntPtr)MainWindow.HWnd;
+
+ IntPtr mdiClient = NativeMethods.FindWindowEx(mainWindow, IntPtr.Zero, mdiClientClass, string.Empty);
+
+ IntPtr mdiChild = NativeMethods.GetTopWindow(mdiClient);
+ StringBuilder mdiChildCaption = new StringBuilder();
+ int captionLength = NativeMethods.GetWindowText(mdiChild, mdiChildCaption, maxCaptionLength);
+
+ if (captionLength > 0)
+ {
+ try
+ {
+ return Windows.FirstOrDefault(win => win.Caption == mdiChildCaption.ToString());
+ }
+ catch
+ {
+ }
+ }
+ return null;
+ }
+
/// Returns whether the host supports unit tests.
public bool HostSupportsUnitTests()
{
diff --git a/Rubberduck.VBEEditor/WindowsApi/CodePaneSubclass.cs b/Rubberduck.VBEEditor/WindowsApi/CodePaneSubclass.cs
index 5eee5941bf..46bb11e003 100644
--- a/Rubberduck.VBEEditor/WindowsApi/CodePaneSubclass.cs
+++ b/Rubberduck.VBEEditor/WindowsApi/CodePaneSubclass.cs
@@ -16,9 +16,9 @@ internal CodePaneSubclass(IntPtr hwnd, ICodePane pane) : base(hwnd)
_pane = pane;
}
- protected override void DispatchFocusEvent(WindowChangedEventArgs.FocusType type)
+ protected override void DispatchFocusEvent(FocusType type)
{
- var window = VBEEvents.GetWindowInfoFromHwnd(Hwnd);
+ var window = VBENativeServices.GetWindowInfoFromHwnd(Hwnd);
if (window == null)
{
return;
diff --git a/Rubberduck.VBEEditor/WindowsApi/DesignerWindowSubclass.cs b/Rubberduck.VBEEditor/WindowsApi/DesignerWindowSubclass.cs
index 9edf56ec2b..799d184b0b 100644
--- a/Rubberduck.VBEEditor/WindowsApi/DesignerWindowSubclass.cs
+++ b/Rubberduck.VBEEditor/WindowsApi/DesignerWindowSubclass.cs
@@ -1,4 +1,7 @@
using System;
+using System.Diagnostics;
+using Rubberduck.Common.WinAPI;
+using Rubberduck.VBEditor.Events;
namespace Rubberduck.VBEditor.WindowsApi
{
@@ -6,5 +9,18 @@ internal class DesignerWindowSubclass : FocusSource
{
//Stub for designer window replacement. :-)
internal DesignerWindowSubclass(IntPtr hwnd) : base(hwnd) { }
+
+ public override int SubClassProc(IntPtr hWnd, IntPtr msg, IntPtr wParam, IntPtr lParam, IntPtr uIdSubclass, IntPtr dwRefData)
+ {
+ //Any time the selected control changes in the hosted userform, the F3 Overlay has to be redrawn. This is a good proxy
+ //for child control selections, so raise a focus event.
+ if ((int) msg == (int)WM.ERASEBKGND)
+ {
+ DispatchFocusEvent(FocusType.GotFocus);
+ }
+ //This is an output window firehose, leave this here, but comment it out when done.
+ //Debug.WriteLine("WM: {0:X4}, wParam {1}, lParam {2}", msg, wParam, lParam);
+ return base.SubClassProc(hWnd, msg, wParam, lParam, uIdSubclass, dwRefData);
+ }
}
}
diff --git a/Rubberduck.VBEEditor/WindowsApi/FocusSource.cs b/Rubberduck.VBEEditor/WindowsApi/FocusSource.cs
index 9c6539a543..9b4e1f35f4 100644
--- a/Rubberduck.VBEEditor/WindowsApi/FocusSource.cs
+++ b/Rubberduck.VBEEditor/WindowsApi/FocusSource.cs
@@ -17,9 +17,9 @@ protected void OnFocusChange(WindowChangedEventArgs eventArgs)
}
}
- protected virtual void DispatchFocusEvent(WindowChangedEventArgs.FocusType type)
+ protected virtual void DispatchFocusEvent(FocusType type)
{
- var window = VBEEvents.GetWindowInfoFromHwnd(Hwnd);
+ var window = VBENativeServices.GetWindowInfoFromHwnd(Hwnd);
if (window == null)
{
return;
@@ -33,10 +33,10 @@ public override int SubClassProc(IntPtr hWnd, IntPtr msg, IntPtr wParam, IntPtr
{
case (uint)WM.SETFOCUS:
- DispatchFocusEvent(WindowChangedEventArgs.FocusType.GotFocus);
+ DispatchFocusEvent(FocusType.GotFocus);
break;
case (uint)WM.KILLFOCUS:
- DispatchFocusEvent(WindowChangedEventArgs.FocusType.LostFocus);
+ DispatchFocusEvent(FocusType.LostFocus);
break;
}
return base.SubClassProc(hWnd, msg, wParam, lParam, uIdSubclass, dwRefData);
diff --git a/Rubberduck.VBEEditor/WindowsApi/NativeMethods.cs b/Rubberduck.VBEEditor/WindowsApi/NativeMethods.cs
index 43f7dd7846..8b537f05b3 100644
--- a/Rubberduck.VBEEditor/WindowsApi/NativeMethods.cs
+++ b/Rubberduck.VBEEditor/WindowsApi/NativeMethods.cs
@@ -49,6 +49,16 @@ public static class NativeMethods
internal static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
+ /// Gets the child window at the top of the Z order.
+ ///
+ /// The window handle.
+ /// The child window IntPtr handle.
+ [DllImport("user32.dll")]
+ internal static extern IntPtr GetTopWindow(IntPtr hWnd);
+
+ [DllImport("user32.dll", CharSet = CharSet.Unicode)]
+ internal static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);
+
/// Gets window caption text by handle.
///
/// Handle of the window to be activated.
@@ -69,15 +79,6 @@ public static string GetWindowText(this IntPtr windowHandle)
return result;
}
- /// Gets the parent window of this item.
- ///
- /// The window handle.
- /// The parent window IntPtr handle.
- [DllImport("User32.dll")]
- internal static extern IntPtr GetParent(IntPtr hWnd);
-
-
-
/// Activates the window by simulating a click.
///
/// Handle of the window to be activated.
diff --git a/Rubberduck.VBEEditor/WindowsApi/User32.cs b/Rubberduck.VBEEditor/WindowsApi/User32.cs
index dc6a2f1170..9b182a2d70 100644
--- a/Rubberduck.VBEEditor/WindowsApi/User32.cs
+++ b/Rubberduck.VBEEditor/WindowsApi/User32.cs
@@ -66,5 +66,12 @@ public static class User32
/// The length of the returned class name (without the null terminator), zero on error.
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
+
+ /// Gets the parent window of this item.
+ ///
+ /// The window handle.
+ /// The parent window IntPtr handle.
+ [DllImport("User32.dll")]
+ internal static extern IntPtr GetParent(IntPtr hWnd);
}
}