Skip to content

Commit c57c9b8

Browse files
committed
fixed conflicts of #2708
2 parents 5e230fb + 12a6e8b commit c57c9b8

File tree

10 files changed

+113
-89
lines changed

10 files changed

+113
-89
lines changed

RetailCoder.VBE/App.cs

Lines changed: 49 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ public App(IVBE vbe,
6363
_version = version;
6464
_checkVersionCommand = checkVersionCommand;
6565

66-
VBEEvents.SelectionChanged += _vbe_SelectionChanged;
67-
VBEEvents.WindowFocusChange += _vbe_FocusChanged;
66+
VBENativeServices.SelectionChanged += _vbe_SelectionChanged;
67+
VBENativeServices.WindowFocusChange += _vbe_FocusChanged;
6868

6969
_configService.SettingsChanged += _configService_SettingsChanged;
7070
_parser.State.StateChanged += Parser_StateChanged;
@@ -73,6 +73,9 @@ public App(IVBE vbe,
7373
UiDispatcher.Initialize();
7474
}
7575

76+
//TODO - This should be able to move to the appropriate handling classes now.
77+
#region Statusbar
78+
7679
private void State_StatusMessageUpdate(object sender, RubberduckStatusMessageEventArgs e)
7780
{
7881
var message = e.Message;
@@ -92,95 +95,79 @@ private void _vbe_SelectionChanged(object sender, SelectionChangedEventArgs e)
9295

9396
private void _vbe_FocusChanged(object sender, WindowChangedEventArgs e)
9497
{
95-
if (e.EventType == WindowChangedEventArgs.FocusType.GotFocus)
98+
if (e.EventType == FocusType.GotFocus)
9699
{
97100
switch (e.Window.Type)
98101
{
99102
case WindowKind.Designer:
103+
//Designer or control on designer form selected.
100104
RefreshSelection(e.Window);
101105
break;
102106
case WindowKind.CodeWindow:
107+
//Caret changed in a code pane.
103108
RefreshSelection(e.CodePane);
104109
break;
105110
}
106-
}
111+
}
112+
else if (e.EventType == FocusType.ChildFocus)
113+
{
114+
//Treeview selection changed in project window.
115+
RefreshSelection();
116+
}
107117
}
108118

109119
private ParserState _lastStatus;
110120
private Declaration _lastSelectedDeclaration;
111121
private void RefreshSelection(ICodePane pane)
112122
{
113-
Declaration selectedDeclaration = null;
114-
if (!pane.IsWrappingNullReference)
115-
{
116-
selectedDeclaration = _parser.State.FindSelectedDeclaration(pane);
117-
var refCount = selectedDeclaration == null ? 0 : selectedDeclaration.References.Count();
118-
var caption = _stateBar.GetContextSelectionCaption(_vbe.ActiveCodePane, selectedDeclaration);
119-
_stateBar.SetContextSelectionCaption(caption, refCount);
120-
}
121-
122-
var currentStatus = _parser.State.Status;
123-
if (ShouldEvaluateCanExecute(selectedDeclaration, currentStatus))
123+
if (pane == null || pane.IsWrappingNullReference)
124124
{
125-
_appMenus.EvaluateCanExecute(_parser.State);
126-
_stateBar.EvaluateCanExecute(_parser.State);
125+
return;
127126
}
128127

129-
_lastStatus = currentStatus;
130-
_lastSelectedDeclaration = selectedDeclaration;
128+
var selectedDeclaration = _parser.State.FindSelectedDeclaration(pane);
129+
var caption = _stateBar.GetContextSelectionCaption(_vbe.ActiveCodePane, selectedDeclaration);
130+
UpdateStatusbarAndCommandState(caption, selectedDeclaration);
131131
}
132132

133133
private void RefreshSelection(IWindow window)
134134
{
135-
if (window.IsWrappingNullReference || window.Type != WindowKind.Designer)
135+
if (window == null || window.IsWrappingNullReference || window.Type != WindowKind.Designer)
136136
{
137137
return;
138138
}
139-
var caption = String.Empty;
140-
var refCount = 0;
141139

142-
WindowKind windowKind = _vbe.ActiveWindow.Type;
143-
var pane = _vbe.ActiveCodePane;
144140
var component = _vbe.SelectedVBComponent;
145-
var activeMDI = _vbe.ActiveMDIChild();
146-
147-
Declaration selectedDeclaration = null;
148-
149-
//TODO - Reinstate these lines once the host stops crashing - need to theck ParentProject doesn't return null
150-
////TODO - I doubt this is the best way to check if the SelectedVBComponent and the ActiveCodePane are the same component.
151-
//if (windowKind == WindowKind.CodeWindow || (!_vbe.SelectedVBComponent.IsWrappingNullReference
152-
// && component.ParentProject.ProjectId == pane.CodeModule.Parent.ParentProject.ProjectId
153-
// && component.Name == pane.CodeModule.Parent.Name))
154-
//{
155-
// selectedDeclaration = _parser.State.FindSelectedDeclaration(pane);
156-
// refCount = selectedDeclaration == null ? 0 : selectedDeclaration.References.Count();
157-
// caption = _stateBar.GetContextSelectionCaption(_vbe.ActiveCodePane, selectedDeclaration);
158-
//}
159-
//else
160-
if (windowKind == WindowKind.Designer)
141+
var caption = GetComponentControlsCaption(component);
142+
//TODO: Need to find the selected declaration for the Form\Control.
143+
UpdateStatusbarAndCommandState(caption, null);
144+
}
145+
146+
private void RefreshSelection()
147+
{
148+
var caption = string.Empty;
149+
var component = _vbe.SelectedVBComponent;
150+
if (component == null || component.IsWrappingNullReference)
161151
{
162-
caption = GetComponentControlsCaption(component);
152+
//The user might have selected the project node in Project Explorer
153+
//If they've chosen a folder, we'll return the project anyway
154+
caption = !_vbe.ActiveVBProject.IsWrappingNullReference
155+
? _vbe.ActiveVBProject.Name
156+
: null;
163157
}
164158
else
165159
{
166-
if (_vbe.SelectedVBComponent.IsWrappingNullReference)
167-
{
168-
//The user might have selected the project node in Project Explorer
169-
//If they've chosen a folder, we'll return the project anyway
170-
caption = !_vbe.ActiveVBProject.IsWrappingNullReference
171-
? _vbe.ActiveVBProject.Name
172-
: null;
173-
}
174-
else
175-
{
176-
caption = component.Type == ComponentType.UserForm
177-
&& component.HasOpenDesigner
178-
&& component.DesignerWindow().Caption == activeMDI.Caption
179-
? GetComponentControlsCaption(component)
180-
: String.Format("{0}.{1} ({2})", component.ParentProject.Name, component.Name, component.Type);
181-
}
160+
caption = component.Type == ComponentType.UserForm && component.HasOpenDesigner
161+
? GetComponentControlsCaption(component)
162+
: string.Format("{0}.{1} ({2})", component.ParentProject.Name, component.Name, component.Type);
182163
}
164+
//TODO: Need to find the selected declaration for the selected treeview item.
165+
UpdateStatusbarAndCommandState(caption, null);
166+
}
183167

168+
private void UpdateStatusbarAndCommandState(string caption, Declaration selectedDeclaration)
169+
{
170+
var refCount = selectedDeclaration == null ? 0 : selectedDeclaration.References.Count();
184171
_stateBar.SetContextSelectionCaption(caption, refCount);
185172

186173
var currentStatus = _parser.State.Status;
@@ -191,7 +178,7 @@ private void RefreshSelection(IWindow window)
191178
}
192179

193180
_lastStatus = currentStatus;
194-
_lastSelectedDeclaration = selectedDeclaration;
181+
_lastSelectedDeclaration = selectedDeclaration;
195182
}
196183

197184
private string GetComponentControlsCaption(IVBComponent component)
@@ -220,6 +207,8 @@ private bool ShouldEvaluateCanExecute(Declaration selectedDeclaration, ParserSta
220207
(selectedDeclaration == null && _lastSelectedDeclaration != null);
221208
}
222209

210+
#endregion
211+
223212
private void _configService_SettingsChanged(object sender, ConfigurationChangedEventArgs e)
224213
{
225214
_config = _configService.LoadConfiguration();
@@ -371,8 +360,8 @@ public void Dispose()
371360
_parser.State.StatusMessageUpdate -= State_StatusMessageUpdate;
372361
}
373362

374-
VBEEvents.SelectionChanged += _vbe_SelectionChanged;
375-
VBEEvents.WindowFocusChange += _vbe_FocusChanged;
363+
VBENativeServices.SelectionChanged += _vbe_SelectionChanged;
364+
VBENativeServices.WindowFocusChange += _vbe_FocusChanged;
376365

377366
if (_configService != null)
378367
{

RetailCoder.VBE/Extension.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public void OnConnection(object Application, ext_ConnectMode ConnectMode, object
5656
{
5757
var vbe = (Microsoft.Vbe.Interop.VBE) Application;
5858
_ide = new VBEditor.SafeComWrappers.VBA.VBE(vbe);
59-
VBEEvents.HookEvents(_ide);
59+
VBENativeServices.HookEvents(_ide);
6060

6161
var addin = (Microsoft.Vbe.Interop.AddIn)AddInInst;
6262
_addin = new VBEditor.SafeComWrappers.VBA.AddIn(addin) { Object = this };
@@ -221,7 +221,7 @@ private void Startup()
221221

222222
private void ShutdownAddIn()
223223
{
224-
VBEEvents.UnhookEvents();
224+
VBENativeServices.UnhookEvents();
225225

226226
var currentDomain = AppDomain.CurrentDomain;
227227
currentDomain.AssemblyResolve -= LoadFromSameFolder;

Rubberduck.VBEEditor/Events/VBEEvents.cs renamed to Rubberduck.VBEEditor/Events/VBENativeServices.cs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
namespace Rubberduck.VBEditor.Events
1111
{
12-
public static class VBEEvents
12+
public static class VBENativeServices
1313
{
1414
private static User32.WinEventProc _eventProc;
1515
private static IntPtr _eventHandle;
@@ -66,7 +66,10 @@ public static void UnhookEvents()
6666
public static void VbeEventCallback(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild,
6767
uint dwEventThread, uint dwmsEventTime)
6868
{
69-
if (hwnd != IntPtr.Zero && idObject == (int)ObjId.Caret && eventType == (uint)WinEvent.ObjectLocationChange && hwnd.ToWindowType() == WindowType.VbaWindow)
69+
if (hwnd != IntPtr.Zero &&
70+
idObject == (int)ObjId.Caret &&
71+
(eventType == (uint)WinEvent.ObjectLocationChange || eventType == (uint)WinEvent.ObjectCreate) &&
72+
hwnd.ToWindowType() == WindowType.VbaWindow)
7073
{
7174
OnSelectionChanged(hwnd);
7275
}
@@ -83,6 +86,17 @@ public static void VbeEventCallback(IntPtr hWinEventHook, uint eventType, IntPtr
8386
DetachWindow(hwnd);
8487
}
8588
}
89+
else if (eventType == (uint)WinEvent.ObjectFocus && idObject == (int)ObjId.Client)
90+
{
91+
//Test to see if it was a selection change in the project window.
92+
var parent = User32.GetParent(hwnd);
93+
if (parent != IntPtr.Zero && parent.ToWindowType() == WindowType.Project)
94+
{
95+
FocusDispatcher(_vbe, new WindowChangedEventArgs(parent, null, null, FocusType.ChildFocus));
96+
}
97+
}
98+
//This is an output window firehose, leave this here, but comment it out when done.
99+
//if (idObject != (int)ObjId.Cursor) Debug.WriteLine("Hwnd: {0:X4} - EventType {1:X4}, idObject {2}, idChild {3}", (int)hwnd, eventType, idObject, idChild);
86100
}
87101

88102
private static void AttachWindow(IntPtr hwnd)
@@ -176,15 +190,21 @@ public enum WindowType
176190
{
177191
Indeterminate,
178192
VbaWindow,
179-
DesignerWindow
193+
DesignerWindow,
194+
Project
180195
}
181196

182197
public static WindowType ToWindowType(this IntPtr hwnd)
198+
{
199+
WindowType id;
200+
return Enum.TryParse(hwnd.ToClassName(), true, out id) ? id : WindowType.Indeterminate;
201+
}
202+
203+
public static string ToClassName(this IntPtr hwnd)
183204
{
184205
var name = new StringBuilder(128);
185206
User32.GetClassName(hwnd, name, name.Capacity);
186-
WindowType id;
187-
return Enum.TryParse(name.ToString(), out id) ? id : WindowType.Indeterminate;
207+
return name.ToString();
188208
}
189209
}
190210
}

Rubberduck.VBEEditor/Events/WindowChangedEventArgs.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33

44
namespace Rubberduck.VBEditor.Events
55
{
6-
public class WindowChangedEventArgs : EventArgs
6+
public enum FocusType
77
{
8-
public enum FocusType
9-
{
10-
GotFocus,
11-
LostFocus
12-
}
8+
GotFocus,
9+
LostFocus,
10+
ChildFocus
11+
}
1312

13+
public class WindowChangedEventArgs : EventArgs
14+
{
1415
public IntPtr Hwnd { get; private set; }
1516
public IWindow Window { get; private set; }
1617
public ICodePane CodePane { get; private set; }

Rubberduck.VBEEditor/Rubberduck.VBEditor.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@
125125
<Compile Include="Events\ProjectEventArgs.cs" />
126126
<Compile Include="Events\ProjectRenamedEventArgs.cs" />
127127
<Compile Include="Events\SelectionChangedEventArgs.cs" />
128-
<Compile Include="Events\VBEEvents.cs" />
128+
<Compile Include="Events\VBENativeServices.cs" />
129129
<Compile Include="Events\WindowChangedEventArgs.cs" />
130130
<Compile Include="Extensions\MSAccessComponentTypeExtensions.cs" />
131131
<Compile Include="SafeComWrappers\Abstract\ISafeComWrapper.cs" />

Rubberduck.VBEEditor/WindowsApi/CodePaneSubclass.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ internal CodePaneSubclass(IntPtr hwnd, ICodePane pane) : base(hwnd)
1616
_pane = pane;
1717
}
1818

19-
protected override void DispatchFocusEvent(WindowChangedEventArgs.FocusType type)
19+
protected override void DispatchFocusEvent(FocusType type)
2020
{
21-
var window = VBEEvents.GetWindowInfoFromHwnd(Hwnd);
21+
var window = VBENativeServices.GetWindowInfoFromHwnd(Hwnd);
2222
if (window == null)
2323
{
2424
return;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,26 @@
11
using System;
2+
using System.Diagnostics;
3+
using Rubberduck.Common.WinAPI;
4+
using Rubberduck.VBEditor.Events;
25

36
namespace Rubberduck.VBEditor.WindowsApi
47
{
58
internal class DesignerWindowSubclass : FocusSource
69
{
710
//Stub for designer window replacement. :-)
811
internal DesignerWindowSubclass(IntPtr hwnd) : base(hwnd) { }
12+
13+
public override int SubClassProc(IntPtr hWnd, IntPtr msg, IntPtr wParam, IntPtr lParam, IntPtr uIdSubclass, IntPtr dwRefData)
14+
{
15+
//Any time the selected control changes in the hosted userform, the F3 Overlay has to be redrawn. This is a good proxy
16+
//for child control selections, so raise a focus event.
17+
if ((int) msg == (int)WM.ERASEBKGND)
18+
{
19+
DispatchFocusEvent(FocusType.GotFocus);
20+
}
21+
//This is an output window firehose, leave this here, but comment it out when done.
22+
//Debug.WriteLine("WM: {0:X4}, wParam {1}, lParam {2}", msg, wParam, lParam);
23+
return base.SubClassProc(hWnd, msg, wParam, lParam, uIdSubclass, dwRefData);
24+
}
925
}
1026
}

Rubberduck.VBEEditor/WindowsApi/FocusSource.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ protected void OnFocusChange(WindowChangedEventArgs eventArgs)
1717
}
1818
}
1919

20-
protected virtual void DispatchFocusEvent(WindowChangedEventArgs.FocusType type)
20+
protected virtual void DispatchFocusEvent(FocusType type)
2121
{
22-
var window = VBEEvents.GetWindowInfoFromHwnd(Hwnd);
22+
var window = VBENativeServices.GetWindowInfoFromHwnd(Hwnd);
2323
if (window == null)
2424
{
2525
return;
@@ -33,10 +33,10 @@ public override int SubClassProc(IntPtr hWnd, IntPtr msg, IntPtr wParam, IntPtr
3333
{
3434
case (uint)WM.SETFOCUS:
3535

36-
DispatchFocusEvent(WindowChangedEventArgs.FocusType.GotFocus);
36+
DispatchFocusEvent(FocusType.GotFocus);
3737
break;
3838
case (uint)WM.KILLFOCUS:
39-
DispatchFocusEvent(WindowChangedEventArgs.FocusType.LostFocus);
39+
DispatchFocusEvent(FocusType.LostFocus);
4040
break;
4141
}
4242
return base.SubClassProc(hWnd, msg, wParam, lParam, uIdSubclass, dwRefData);

Rubberduck.VBEEditor/WindowsApi/NativeMethods.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,6 @@ public static string GetWindowText(this IntPtr windowHandle)
7979
return result;
8080
}
8181

82-
/// <summary> Gets the parent window of this item. </summary>
83-
///
84-
/// <param name="hWnd"> The window handle. </param>
85-
/// <returns> The parent window IntPtr handle. </returns>
86-
[DllImport("User32.dll")]
87-
internal static extern IntPtr GetParent(IntPtr hWnd);
88-
89-
90-
9182
/// <summary>Activates the window by simulating a click.</summary>
9283
///
9384
/// <param name="windowHandle"> Handle of the window to be activated. </param>

Rubberduck.VBEEditor/WindowsApi/User32.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,12 @@ public static class User32
6666
/// <returns>The length of the returned class name (without the null terminator), zero on error.</returns>
6767
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
6868
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
69+
70+
/// <summary> Gets the parent window of this item. </summary>
71+
///
72+
/// <param name="hWnd"> The window handle. </param>
73+
/// <returns> The parent window IntPtr handle. </returns>
74+
[DllImport("User32.dll")]
75+
internal static extern IntPtr GetParent(IntPtr hWnd);
6976
}
7077
}

0 commit comments

Comments
 (0)