我不是专家,我试图在屏幕上显示一个矩形,它跟随鼠标从一个固定的起点移动,就像你在文字或绘画中选择什么一样。我带着这个密码来的:
import win32gui
m=win32gui.GetCursorPos()
while True:
n=win32gui.GetCursorPos()
for i in range(n[0]-m[0]):
win32gui.SetPixel(dc, m[0]+i, m[1], 0)
win32gui.SetPixel(dc, m[0]+i, n[1], 0)
for i in range(n[1]-m[1]):
win32gui.SetPixel(dc, m[0], m[1]+i, 0)
win32gui.SetPixel(dc, n[0], m[1]+i, 0)
如您所见,代码将绘制矩形,但前面的矩形将一直保持到屏幕更新。
我提出的唯一解决方案是,在将像素值设置为黑色之前,将其设置为黑色,并每次重新绘制它们,但这会使我的代码非常慢。有没有一种简单的方法可以更快地更新屏幕以防止这种情况发生?
..。
用溶液编辑。
正如@Torxed所建议的那样,使用win32gui.InvalidateRect解决了更新问题。然而,我发现只设置我需要设置的点的颜色比要求一个矩形更便宜。第一种解决方案相当干净,而第二种解决方案仍然有一点小问题。最后,对我来说最有效的代码是:
import win32gui
m=win32gui.GetCursorPos()
dc = win32gui.GetDC(0)
while True:
n=win32gui.GetCursorPos()
win32gui.InvalidateRect(hwnd, (m[0], m[1], GetSystemMetrics(0), GetSystemMetrics(1)), True)
back=[]
for i in range((n[0]-m[0])//4):
win32gui.SetPixel(dc, m[0]+4*i, m[1], 0)
win32gui.SetPixel(dc, m[0]+4*i, n[1], 0)
for i in range((n[1]-m[1])//4):
win32gui.SetPixel(dc, m[0], m[1]+4*i, 0)
win32gui.SetPixel(dc, n[0], m[1]+4*i, 0)
除法和乘四是必要的,以避免闪烁,但在视觉上与使用DrawFocusRect相同。
这将只有当你保持低沉和右从你的最初立场,但这正是我所需要的。不难改进,接受任何次要职位。
发布于 2021-09-11 01:42:46
我已经根据这里的一些答案进行了一段时间的工作,这是我的解决方案。
这将等待鼠标被按下和拖动,并创建一个从按下位置到拖动位置的矩形。在鼠标释放时,它将清除矩形并输出单击和释放的位置,并关闭所有钩子。
有几个问题我想解决(一些轻微的闪烁和边框太薄),所以如果有人知道这些我会感谢一些帮助(win32ui文档真的很糟糕)
如果您想要纯色,只需将FrameRect((x,y,a,b),brush)
更改为FillRect((x,y,a,b), brush)
即可。
from win32gui import GetDC, WindowFromPoint, SetPixel, InvalidateRect
from win32ui import CreateDCFromHandle, CreateBrush
from win32api import GetSystemMetrics, GetSysColor
from PyHook3 import HookManager
import ctypes
class Draw_Screen_Rect:
def __init__(self):
self.pos = [0, 0, 0, 0]
dc = GetDC(0)
self.dcObj = CreateDCFromHandle(dc)
self.hwnd = WindowFromPoint((0,0))
self.monitor = (0, 0, GetSystemMetrics(0), GetSystemMetrics(1))
self.clicked = False
self.b1 = CreateBrush()
self.b1.CreateSolidBrush(GetSysColor(255))
self.final_rect = None
self.refresh_frames = 0
self.refresh_after = 10
def _draw_rect_func(self):
self.dcObj.FrameRect(tuple(self.pos), self.b1)
def _refresh_rect(self):
InvalidateRect(self.hwnd, self.monitor, True)
def _OnMouseEvent(self, event):
if event.Message == 513:
self.clicked = True
self.pos[0], self.pos[1] = event.Position
elif event.Message == 514:
self.clicked = False
self.pos[2], self.pos[3] = event.Position
self._draw_rect_func()
self._refresh_rect()
self.final_rect = self.pos
self._destroy_hooks()
elif event.Message == 512:
if self.clicked:
self.pos[2], self.pos[3] = event.Position
if self.refresh_frames%2 ==0:
self._draw_rect_func()
self.refresh_frames+=1
if self.refresh_frames > self.refresh_after:
self.refresh_frames = 0
self._refresh_rect()
return True
def create_hooks(self):
self.hm = HookManager()
self.hm.MouseLeftDown = self._OnMouseEvent
self.hm.MouseLeftUp = self._OnMouseEvent
self.hm.MouseMove = self._OnMouseEvent
self.hm.HookMouse()
self.hm.HookKeyboard()
def _destroy_hooks(self):
self.hm.UnhookMouse()
ctypes.windll.user32.PostQuitMessage(0)
def output(self):
return self.final_rect
if __name__ == '__main__':
app = Draw_Screen_Rect()
app.create_hooks()
from pythoncom import PumpMessages
PumpMessages()
out = app.output()
print(out)
https://stackoverflow.com/questions/62341134
复制相似问题