I have written a wx application to draw a rectangle around a section of the screen and subsequently OCR that section an put the resulting text on the clipboard. The section is defined by clicking the mouse down at the start of the desired rectangle and releasing it once the mouse has been moved to the opposite corner. This works. But, for example, if I do this over the developer studio’s window, I find I am selecting text in the developer studio as well as drawing the rectangle. So what is CaptureMouse doing? Note that I can draw the rectangle and grab the section without using CaptureMouse. I only use it because I thought it would stop mouse events going to other windows. But it doesn’t seem to do so. Here’s the code:
import wx
from enum import Enum, auto
class State(Enum):
WAITING = auto()
INITIAL = auto()
MOUSE_DOWN = auto()
CLOSE = auto()
class ScreenGrabber(wx.Frame):
def __init__(self):
super().__init__(None)
self.state = State.WAITING
self.origin = wx.Point()
self.current = wx.Point()
self.Bind(wx.EVT_MOUSE_CAPTURE_CHANGED,self.OnMouseCaptureChangedEvent)
self.Bind(wx.EVT_MOUSE_CAPTURE_LOST,self.OnMouseCaptureLostEvent)
self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvent)
self.wantCapture = False
self.log = []
def Start(self):
self.state = State.INITIAL
def Stop(self):
self.state = State.CLOSE
def Log(self, text):
self.log.append(text)
def OnTimer(self):
if self.wantCapture and not self.HasCapture():
self.Log('CaptureMouse re-called')
self.CaptureMouse()
mouseState : wx.MouseState = wx.GetMouseState()
if self.state == State.WAITING:
wx.CallLater(500, self.OnTimer)
elif self.state == State.INITIAL:
if mouseState.LeftIsDown():
self.Log('CaptureMouse called')
self.CaptureMouse()
self.wantCapture = True
self.origin = self.current = mouseState.GetPosition()
self.state = State.MOUSE_DOWN
wx.CallLater(20, self.OnTimer)
elif self.state == State.MOUSE_DOWN:
self.current = mouseState.GetPosition()
self.DrawSection()
if mouseState.LeftIsDown():
wx.CallLater(20, self.OnTimer)
else:
self.GrabScreenSection()
self.state = State.WAITING
self.origin = wx.Point()
self.current = wx.Point()
self.ReleaseMouse()
self.Log('ReleaseMouse called')
self.wantCapture = False
wx.CallLater(20, self.OnTimer)
elif self.state == State.CLOSE:
self.Close()
else:
wx.CallLater(20, self.OnTimer)
def OnMouseCaptureChangedEvent(self, event):
self.Log('OnMouseCaptureChangedEvent occurred')
pass
def OnMouseCaptureLostEvent(self, event):
self.ReleaseMouse()
self.Log('OnMouseCaptureLostEvent called: mouse released')
pass
def OnMouseEvent(self, event):
if self.wantCapture:
self.Log('OnMouseEvent called')
pass
def DrawSection(self):
dc = wx.ScreenDC()
dc.SetBrush(wx.Brush('white', wx.BRUSHSTYLE_TRANSPARENT))
dc.StartDrawingOnTop()
dc.DrawRectangle(x=self.origin[0], y=self.origin[1], width=abs(self.origin[0] - self.current[0]),
height=abs(self.origin[1] - self.current[1]))
dc.EndDrawingOnTop()
pass
def GrabScreenSection(self):
print('Screen section grabbed')
pass
if __name__ == "__main__":
app = wx.App(None)
grabber = ScreenGrabber()
grabber.Show()
grabber.Start()
grabber.OnTimer()
app.MainLoop()
pass
type or paste code here