Skip to content

Commit 6d911af

Browse files
committed
Partial Excel 2010 support
1 parent 35c1896 commit 6d911af

File tree

10 files changed

+229
-52
lines changed

10 files changed

+229
-52
lines changed

Source/ExcelDna.IntelliSense.Host/AddIn.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ public class AddIn : IExcelAddIn
1414
public void AutoOpen()
1515
{
1616
IntelliSenseServer.Register();
17-
ExcelDna.Logging.LogDisplay.Show();
18-
ExcelDna.Logging.LogDisplay.DisplayOrder = ExcelDna.Logging.DisplayOrder.NewestFirst;
17+
//ExcelDna.Logging.LogDisplay.Show();
18+
//ExcelDna.Logging.LogDisplay.DisplayOrder = ExcelDna.Logging.DisplayOrder.NewestFirst;
1919
}
2020

2121
public void AutoClose()

Source/ExcelDna.IntelliSense/IntelliSenseDisplay.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ void UpdateFormulaEditWindow(IntPtr formulaEditWindow)
184184
_formulaEditWindow = formulaEditWindow;
185185
if (_argumentsToolTip != null)
186186
{
187+
// Rather ChangeParent...?
187188
_argumentsToolTip.Dispose();
188189
_argumentsToolTip = null;
189190
}
@@ -194,7 +195,7 @@ void UpdateFormulaEditWindow(IntPtr formulaEditWindow)
194195
}
195196
else
196197
{
197-
Debug.Fail("Unexpected null FormulaEditWindow...");
198+
// Debug.Fail("Unexpected null FormulaEditWindow...");
198199
}
199200
}
200201
}
@@ -242,6 +243,13 @@ void FormulaEditEnd()
242243
// Runs on the main thread
243244
void FormulaEditMove(Rect editWindowBounds, Rect excelTooltipBounds)
244245
{
246+
Debug.Print($"IntelliSenseDisplay - FormulaEditMove");
247+
Debug.Assert(_argumentsToolTip != null);
248+
if (_argumentsToolTip == null)
249+
{
250+
Logger.Display.Warn("FormulaEditMode Unexpected null Arguments ToolTip!?");
251+
return;
252+
}
245253
_argumentsToolTip.MoveToolTip((int)editWindowBounds.Left, (int)editWindowBounds.Bottom + 5);
246254
}
247255

Source/ExcelDna.IntelliSense/IntelliSenseServer.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ public static void Register()
119119
// We don't expect DomainUnload to run when Excel is shutting down.
120120
static void CurrentDomain_DomainUnload(object sender, EventArgs e)
121121
{
122+
// Early shutdown notification
123+
XlCall.ShutdownStarted();
124+
122125
UnpublishRegistration();
123126
if (_isActive)
124127
{

Source/ExcelDna.IntelliSense/SingleThreadSynchronizationContext.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public override void Send(SendOrPostCallback d, object state)
4747
public void RunOnCurrentThread()
4848
{
4949
_threadId = Thread.CurrentThread.ManagedThreadId;
50-
Debug.Print($"SingleThreadSynchronizationContext Running (Thread {_threadId})!");
50+
Logger.Monitor.Info($"SingleThreadSynchronizationContext Running (Thread {_threadId})!");
5151
foreach (var workItem in _queue.GetConsumingEnumerable())
5252
{
5353
try
@@ -56,11 +56,11 @@ public void RunOnCurrentThread()
5656
}
5757
catch (Exception ex)
5858
{
59-
Debug.Print($"### Unhandled exception on SingleThreadSynchronizationContext (Thread {_threadId}) - {ex.ToString()}");
59+
Logger.Monitor.Warn($"SingleThreadSynchronizationContext ### Unhandled exception (Thread {_threadId}) - {ex}");
6060
}
6161
}
6262

63-
Debug.Print("SingleThreadSynchronizationContext Complete!");
63+
Logger.Monitor.Info("SingleThreadSynchronizationContext Complete!");
6464
}
6565

6666
/// <summary>Notifies the context that no more work will arrive.</summary>

Source/ExcelDna.IntelliSense/UIMonitor/FormulaEditWatcher.cs

Lines changed: 155 additions & 25 deletions
Large diffs are not rendered by default.

Source/ExcelDna.IntelliSense/UIMonitor/PopupListWatcher.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ namespace ExcelDna.IntelliSense
1010
// We ignore the reason for showing, and match purely on the text of the selected item.
1111
class PopupListWatcher : IDisposable
1212
{
13-
// AutomationElement _mainWindow;
1413
IntPtr _hwndPopupList;
1514
AutomationElement _popupList;
1615
AutomationElement _selectedItem;
@@ -30,7 +29,6 @@ public PopupListWatcher(WindowWatcher windowWatcher, SynchronizationContext sync
3029
{
3130
_syncContextAuto = syncContextAuto;
3231
_windowWatcher = windowWatcher;
33-
// _windowWatcher.MainWindowChanged += _windowWatcher_MainWindowChanged;
3432
_windowWatcher.PopupListWindowChanged += _windowWatcher_PopupListWindowChanged;
3533
}
3634

@@ -160,12 +158,14 @@ void PopupListBoundsChanged(object sender, AutomationPropertyChangedEventArgs e)
160158
// Runs on an automation event thread
161159
void PopupListElementSelectedHandler(object sender, AutomationEventArgs e)
162160
{
163-
// Debug.Print($">>>> PopupListWatcher.PopupListElementSelectedHandler on thread {Thread.CurrentThread.ManagedThreadId}");
161+
Logger.WindowWatcher.Verbose($"PopupList PopupListElementSelectedHandler on thread {Thread.CurrentThread.ManagedThreadId}");
164162
UpdateSelectedItem(sender as AutomationElement);
165163
}
166164

165+
// Runs on our automation thread
167166
void InstallEventHandlers()
168167
{
168+
Logger.WindowWatcher.Verbose($"PopupList Installing event handlers on thread {Thread.CurrentThread.ManagedThreadId}");
169169
try
170170
{
171171
Automation.AddAutomationEventHandler(
@@ -185,7 +185,10 @@ void InstallEventHandlers()
185185
void UpdateSelectedItem()
186186
{
187187
if (_popupList == null)
188+
{
189+
Logger.WindowWatcher.Verbose($"PopupList UpdateSelectedItem ignored: PopupList is null");
188190
return;
191+
}
189192

190193
Condition patCondition = new PropertyCondition(
191194
AutomationElement.IsSelectionPatternAvailableProperty, true);
@@ -202,13 +205,13 @@ void UpdateSelectedItem()
202205
}
203206
catch (Exception ex)
204207
{
205-
Logger.WindowWatcher.Warn($"PopupList.UpdateSelectedItem error {ex}");
208+
Logger.WindowWatcher.Warn($"PopupList UpdateSelectedItem error {ex}");
206209
}
207210
}
208211
}
209212
else
210213
{
211-
Logger.WindowWatcher.Warn("PopupList.UpdateSelectedItem - No descendent has SelectionPatter !?");
214+
Logger.WindowWatcher.Warn("PopupList UpdateSelectedItem - No descendent has SelectionPattern !?");
212215
}
213216
}
214217

@@ -347,8 +350,7 @@ void UpdateSelectedItem(AutomationElement newSelectedItem)
347350
// Raises the event on the automation thread (but the SyncContext.Post here is redundant)
348351
void OnSelectedItemChanged()
349352
{
350-
Debug.Print("POPUPLISTWATCHER WINDOW SELECTEDITEM CHANGED");
351-
353+
Logger.WindowWatcher.Verbose($"PopupList SelectedItemChanged {SelectedItemText}");
352354
_syncContextAuto.Post(_ => SelectedItemChanged(this, EventArgs.Empty), null);
353355
}
354356

Source/ExcelDna.IntelliSense/UIMonitor/UIMonitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ void _formulaEditWatcher_StateChanged(object sender, FormulaEditWatcher.StateCha
498498
Logger.Monitor.Verbose($"!> FormulaEdit StateChanged ({args.StateChangeType})");
499499
//Logger.Monitor.Verbose("!> " + ReadCurrentState().ToString());
500500

501-
if (args.StateChangeType == FormulaEditWatcher.StateChangeType.TextChangedOnly &&
501+
if (args.StateChangeType == FormulaEditWatcher.StateChangeType.TextChange &&
502502
CurrentState is UIState.FormulaEdit)
503503
{
504504
var newState = ((UIState.FormulaEdit)CurrentState).WithFormulaPrefix(_formulaEditWatcher.CurrentPrefix);

Source/ExcelDna.IntelliSense/UIMonitor/WinEvents.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ void HandleWinEvent(IntPtr hWinEventHook, WinEvent eventType, IntPtr hWnd,
117117
void OnWinEventReceived(object winEventArgsObj)
118118
{
119119
var winEventArgs = (WinEventArgs)winEventArgsObj;
120-
Logger.WinEvents.Verbose($"{winEventArgs.EventType} - Window {winEventArgs.WindowHandle:X} ({Win32Helper.GetClassName(winEventArgs.WindowHandle)} - Object/Child {winEventArgs.ObjectId} / {winEventArgs.ChildId} - Thread {winEventArgs.EventThreadId} at {winEventArgs.EventTimeMs}");
120+
// Logger.WinEvents.Verbose($"{winEventArgs.EventType} - Window {winEventArgs.WindowHandle:X} ({Win32Helper.GetClassName(winEventArgs.WindowHandle)} - Object/Child {winEventArgs.ObjectId} / {winEventArgs.ChildId} - Thread {winEventArgs.EventThreadId} at {winEventArgs.EventTimeMs}");
121121
WinEventReceived?.Invoke(this, winEventArgs);
122122
}
123123

Source/ExcelDna.IntelliSense/UIMonitor/WindowWatcher.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ void _windowStateChangeHook_WinEventReceived(object sender, WinEventHook.WinEven
182182
// }
183183
// break;
184184
default:
185+
if (e.EventType == WinEventHook.WinEvent.EVENT_OBJECT_FOCUS)
186+
{
187+
Logger.WindowWatcher.Verbose($"FOCUS! on {className}");
188+
}
185189
//InCellEditWindowChanged(this, EventArgs.Empty);
186190
break;
187191
}

Source/ExcelDna.IntelliSense/UIMonitor/XlCall.cs

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Diagnostics;
3+
using System.Runtime.ExceptionServices;
34
using System.Runtime.InteropServices;
45

56
namespace ExcelDna.IntelliSense
@@ -29,22 +30,51 @@ struct FmlaInfo
2930
public int ichCaret; // char offset to blinking caret
3031
}
3132

33+
// This give a global mechanism to indicate shutdown as early as possible
34+
// Maybe helps with debugging...
35+
static bool _shutdownStarted = false;
36+
public static void ShutdownStarted()
37+
{
38+
_shutdownStarted = true;
39+
}
40+
3241
// Returns null if not in edit mode
3342
// TODO: What do we know about the threading constraints on this call?
43+
44+
// NOTE: I've only seen this crash during shutdown
45+
// We enable handling of the AccessViolation as best we can
46+
[HandleProcessCorruptedStateExceptions]
3447
public static string GetFormulaEditPrefix()
3548
{
36-
var fmlaInfo = new FmlaInfo();
37-
var result = LPenHelper(xlGetFmlaInfo, ref fmlaInfo);
38-
if (result != 0)
39-
throw new InvalidOperationException("LPenHelper failed. Result: " + result);
40-
if (fmlaInfo.wPointMode == xlModeReady)
41-
return null;
42-
43-
// Debug.Print("LPenHelper Status: PointMode: {0}, Formula: {1}, First: {2}, Last: {3}, Caret: {4}",
44-
// fmlaInfo.wPointMode, Marshal.PtrToStringUni(fmlaInfo.lpch, fmlaInfo.cch), fmlaInfo.ichFirst, fmlaInfo.ichLast, fmlaInfo.ichCaret);
45-
46-
var prefixLen = Math.Min(Math.Max(fmlaInfo.ichCaret, fmlaInfo.ichLast), fmlaInfo.cch); // I've never seen ichLast > cch !?
47-
return Marshal.PtrToStringUni(fmlaInfo.lpch, prefixLen);
49+
if (_shutdownStarted)
50+
return null;
51+
52+
try
53+
{
54+
var fmlaInfo = new FmlaInfo();
55+
var result = LPenHelper(xlGetFmlaInfo, ref fmlaInfo);
56+
if (result != 0)
57+
{
58+
Logger.WindowWatcher.Warn($"LPenHelper Failed. Result: {result}");
59+
throw new InvalidOperationException("LPenHelper Failed. Result: " + result);
60+
}
61+
if (fmlaInfo.wPointMode == xlModeReady)
62+
{
63+
// Logger.WindowWatcher.Verbose($"LPenHelper PointMode Ready");
64+
return null;
65+
}
66+
67+
//Logger.WindowWatcher.Verbose("LPenHelper Status: PointMode: {0}, Formula: {1}, First: {2}, Last: {3}, Caret: {4}",
68+
// fmlaInfo.wPointMode, Marshal.PtrToStringUni(fmlaInfo.lpch, fmlaInfo.cch), fmlaInfo.ichFirst, fmlaInfo.ichLast, fmlaInfo.ichCaret);
69+
70+
var prefixLen = Math.Min(Math.Max(fmlaInfo.ichCaret, fmlaInfo.ichLast), fmlaInfo.cch); // I've never seen ichLast > cch !?
71+
return Marshal.PtrToStringUni(fmlaInfo.lpch, prefixLen);
72+
}
73+
catch (AccessViolationException)
74+
{
75+
Logger.WindowWatcher.Warn("LPenHelper Access Violation!");
76+
return null;
77+
}
4878
}
4979
}
5080
}

0 commit comments

Comments
 (0)