如何使用 Windows.media.ocr 和计时器控件避免文本闪烁

How to avoid text to flicker using Windows.media.ocr and timer control

我在计时器控制下使用 Windows.Media.Ocr 扫描屏幕中的一些文本,每 200 毫秒触发一次 tick 事件。 然后我在一个不幸闪烁的 richtextbox 中显示输出..

我做了一个 gif 来显示这个问题(ocr 是故意只扫描带有 M 的值)

有什么办法可以阻止这种行为吗?谢谢

我在计时器内部使用的代码是:

 Dim softwareBmp As Windows.Graphics.Imaging.SoftwareBitmap
        Using bmp As Bitmap = New Bitmap(PictureBox1.Width, PictureBox1.Height)
            Using g As Graphics = Graphics.FromImage(bmp)
                Dim pt As Point = Me.PointToScreen(New Point(PictureBox1.Left, PictureBox1.Top))
                g.CopyFromScreen(pt.X, pt.Y, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy)
                Using memStream = New Windows.Storage.Streams.InMemoryRandomAccessStream()
                    bmp.Save(memStream.AsStream(), System.Drawing.Imaging.ImageFormat.Bmp)
                    Dim decoder As Windows.Graphics.Imaging.BitmapDecoder = Await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(memStream)
                    softwareBmp = Await decoder.GetSoftwareBitmapAsync(decoder.BitmapPixelFormat, BitmapAlphaMode.Ignore)
                End Using
            End Using
        End Using
        Dim ocrEng = OcrEngine.TryCreateFromLanguage(New Windows.Globalization.Language("en-US"))
        Dim languages As IReadOnlyList(Of Windows.Globalization.Language) = ocrEng.AvailableRecognizerLanguages
        For Each language In languages
            Console.WriteLine(language.LanguageTag)
        Next
        Dim r = ocrEng.RecognizerLanguage
        Dim n = ocrEng.MaxImageDimension
        Dim ocrResult = Await ocrEng.RecognizeAsync(softwareBmp)

        RichTextBox1.Clear()

        Dim wordList As List(Of cText) = New List(Of cText)()
        Dim lines As IReadOnlyList(Of OcrLine) = ocrResult.Lines
        For Each line In lines
            For Each word In line.Words
                Dim nY As Double = CLng(word.BoundingRect.Bottom / 10) * 10
                wordList.Add(New cText() With {.Text = word.Text, .LocY = nY, .LocX = word.BoundingRect.Left})
            Next
        Next

        wordList.Sort(New WordComparer())

        Dim oldLocY As Double = 0
        For Each item As cText In wordList
            If (item.LocY > oldLocY And oldLocY <> 0) Then
                RichTextBox1.Text += Environment.NewLine
            End If
            RichTextBox1.Text += (item.Text + " ") 
            oldLocY = item.LocY
        Next

我用WM_SETREDRAW

解决了
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
     Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr) As Integer
     End Function
    
     Public Const WM_SETREDRAW As Integer = &HB

添加行之前(before RichTextBox1.Clear())

  If (RichTextBox1.IsHandleCreated) Then
             SendMessage(RichTextBox1.Handle, WM_SETREDRAW, 0, IntPtr.Zero)
         End If

添加行后:

 If (RichTextBox1.IsHandleCreated) Then
             SendMessage(RichTextBox1.Handle, WM_SETREDRAW, 1, IntPtr.Zero)
             RichTextBox1.Invalidate()
         End If