1414//
1515#endregion
1616
17+ using Serilog . Debugging ;
1718using System ;
19+ using System . Collections . Generic ;
1820using System . Diagnostics ;
1921using System . IO ;
2022using System . Linq ;
23+ using System . Runtime . InteropServices ;
2124using System . Text ;
22- using Serilog . Debugging ;
2325
2426namespace Serilog . Sinks . Notepad . Interop
2527{
@@ -55,7 +57,10 @@ public override void Flush()
5557 // No instances of Notepad found... Nothing to do
5658 return ;
5759 }
60+ }
5861
62+ if ( _currentNotepadEditorHandle == IntPtr . Zero )
63+ {
5964 var notepadWindowHandle = currentNotepadProcess . MainWindowHandle ;
6065
6166 var notepadEditorHandle = FindNotepadEditorHandle ( notepadWindowHandle ) ;
@@ -80,7 +85,16 @@ public override void Flush()
8085 // Write the log message to Notepad
8186 User32 . SendMessage ( _currentNotepadEditorHandle , User32 . EM_REPLACESEL , ( IntPtr ) 1 , message ) ;
8287
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 ( ) ;
8498 }
8599
86100 protected override void Dispose ( bool disposing )
@@ -120,6 +134,13 @@ private static IntPtr FindNotepadEditorHandle(IntPtr notepadWindowHandle)
120134 return richEditHandle ;
121135 }
122136
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+
123144 return User32 . FindWindowEx ( notepadWindowHandle , IntPtr . Zero , "Edit" , null ) ;
124145 }
125146
@@ -130,5 +151,49 @@ private void EnsureNotDisposed()
130151 throw new ObjectDisposedException ( GetType ( ) . Name ) ;
131152 }
132153 }
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+ }
133198 }
134199}
0 commit comments