14
14
//
15
15
#endregion
16
16
17
+ using Serilog . Debugging ;
17
18
using System ;
19
+ using System . Collections . Generic ;
18
20
using System . Diagnostics ;
19
21
using System . IO ;
20
22
using System . Linq ;
23
+ using System . Runtime . InteropServices ;
21
24
using System . Text ;
22
- using Serilog . Debugging ;
23
25
24
26
namespace Serilog . Sinks . Notepad . Interop
25
27
{
@@ -55,7 +57,10 @@ public override void Flush()
55
57
// No instances of Notepad found... Nothing to do
56
58
return ;
57
59
}
60
+ }
58
61
62
+ if ( _currentNotepadEditorHandle == IntPtr . Zero )
63
+ {
59
64
var notepadWindowHandle = currentNotepadProcess . MainWindowHandle ;
60
65
61
66
var notepadEditorHandle = FindNotepadEditorHandle ( notepadWindowHandle ) ;
@@ -80,7 +85,16 @@ public override void Flush()
80
85
// Write the log message to Notepad
81
86
User32 . SendMessage ( _currentNotepadEditorHandle , User32 . EM_REPLACESEL , ( IntPtr ) 1 , message ) ;
82
87
83
- buffer . Clear ( ) ;
88
+ // Get how many characters are in the Notepad editor after putting in new text
89
+ var textLengthAfter = User32 . SendMessage ( _currentNotepadEditorHandle , User32 . WM_GETTEXTLENGTH , IntPtr . Zero , IntPtr . Zero ) ;
90
+
91
+ // If no change in textLength, reset editor handle to try to find it again.
92
+ if ( textLengthAfter == textLength )
93
+ _currentNotepadEditorHandle = IntPtr . Zero ;
94
+
95
+ // Otherwise, we clear the buffer
96
+ else
97
+ buffer . Clear ( ) ;
84
98
}
85
99
86
100
protected override void Dispose ( bool disposing )
@@ -120,6 +134,13 @@ private static IntPtr FindNotepadEditorHandle(IntPtr notepadWindowHandle)
120
134
return richEditHandle ;
121
135
}
122
136
137
+ // Issue #59 - Alternate way of finding the RichEditD2DPT class:
138
+ if ( FindEditorHandleThroughChildWindows ( notepadWindowHandle ) is var richEditHandleFromChildren
139
+ && richEditHandleFromChildren != IntPtr . Zero )
140
+ {
141
+ return richEditHandleFromChildren ;
142
+ }
143
+
123
144
return User32 . FindWindowEx ( notepadWindowHandle , IntPtr . Zero , "Edit" , null ) ;
124
145
}
125
146
@@ -130,5 +151,49 @@ private void EnsureNotDisposed()
130
151
throw new ObjectDisposedException ( GetType ( ) . Name ) ;
131
152
}
132
153
}
154
+
155
+ private static string GetClassNameFromWindow ( IntPtr handle )
156
+ {
157
+ StringBuilder sb = new StringBuilder ( 256 ) ;
158
+ var ret = User32 . GetClassName ( handle , sb , sb . Capacity ) ;
159
+ return ret != 0 ? sb . ToString ( ) : string . Empty ;
160
+ }
161
+
162
+ private static bool EnumWindow ( IntPtr handle , IntPtr pointer )
163
+ {
164
+ GCHandle gch = GCHandle . FromIntPtr ( pointer ) ;
165
+ List < IntPtr > list = gch . Target as List < IntPtr > ;
166
+ if ( list == null )
167
+ {
168
+ throw new InvalidCastException ( "GCHandle Target could not be cast as List<IntPtr>" ) ;
169
+ }
170
+
171
+ if ( string . Equals ( GetClassNameFromWindow ( handle ) , "RichEditD2DPT" , StringComparison . OrdinalIgnoreCase ) )
172
+ {
173
+ list . Add ( handle ) ;
174
+
175
+ // Stop enumerating - we found the one.
176
+ return false ;
177
+ }
178
+
179
+ return true ;
180
+ }
181
+
182
+ private static IntPtr FindEditorHandleThroughChildWindows ( IntPtr notepadWindowHandle )
183
+ {
184
+ List < IntPtr > result = new List < IntPtr > ( 1 ) ;
185
+ GCHandle listHandle = GCHandle . Alloc ( result ) ;
186
+ try
187
+ {
188
+ User32 . Win32Callback childProc = new User32 . Win32Callback ( EnumWindow ) ;
189
+ User32 . EnumChildWindows ( notepadWindowHandle , childProc , GCHandle . ToIntPtr ( listHandle ) ) ;
190
+ }
191
+ finally
192
+ {
193
+ if ( listHandle . IsAllocated )
194
+ listHandle . Free ( ) ;
195
+ }
196
+ return result . FirstOrDefault ( ) ;
197
+ }
133
198
}
134
199
}
0 commit comments