Sitat av
simchris
Takker og bukker
Se der ja, dette virker jo langt mer omfattende enn hva jeg hadde sett for meg
Hmm, kanskje det finnes et annet program som allerede kan gjøre dette, og som jeg kan calle fra Python med cmd-kommandoer f.eks?
Fant ikke noe som passet med det du har beskrevet, så jeg skreiv et kjapt og gæli til deg. Ikke helt etter din kravspec, men det klarer du helt sikkert å fikse selv, samt gjøre dette om til noe mer akseptabel python. Samt fikse tykkelse og farge. Kan helt sikkert dokumentere litt valgene jeg gjør i opprettinga av vinduet (de spesifike bitmaskene), men det får eventuelt bli i morgen.
Hva med noe slikt? Resultatet er linje som ikke er interaktiv og som ikke tar i mot mouse-events. Alt som er transparent i vinduet unngår også å snappe opp events. Vinduet/linjen vil alltid være i forgrunnen, bortsett fra om du kjører fullscreen applikasjon. Da må en nok hooke seg opp i directx.
Med litt kjapp omskriving av koden så kan du jo gjøre det slik at du kan enten sende inn en struktur med flere points for å tegne flere linjer, eller hente ut LineTo mm. for å lage en draw-funksjon for det. Her har du jo også gode muligheter for å lage deg en "game-loop", og utføre animasjoner. Mange muligheter her.
Du må installere pywin32 (
https://sourceforge.net/projects/pywin32) for å kjøre dette.
Kode
"""
A non-euclidean, hyperdimentional, cross-platform (win/osx/linux/bsd/quantum computers/etc)
drawing package with extendend support for brownian motions and impossible colours - myoxocephalus
"""
import win32api, win32con, win32gui
class m0bsMagiskeTegneLib:
def __init__(self, x0, y0, x1, y1):
self.x0, self.y0, self.x1, self.y1 = x0, y0, x1, y1
self.wndClass = win32gui.WNDCLASS()
self.wndClass.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW
self.wndClass.lpfnWndProc = self.wndProc
self.wndClass.hInstance = win32api.GetModuleHandle()
self.wndClass.hCursor = win32gui.LoadCursor(None, win32con.IDC_ARROW)
self.wndClass.hbrBackground = win32gui.GetStockObject(win32con.WHITE_BRUSH)
self.wndClass.lpszClassName = "TransparentNonInteractiveWindow"
self.hWindow = win32gui.CreateWindowEx(
win32con.WS_EX_COMPOSITED | win32con.WS_EX_LAYERED | win32con.WS_EX_NOACTIVATE | win32con.WS_EX_TOPMOST | win32con.WS_EX_TRANSPARENT,
win32gui.RegisterClass(self.wndClass),
None,
win32con.WS_DISABLED | win32con.WS_POPUP | win32con.WS_VISIBLE,
0,
0,
win32api.GetSystemMetrics(win32con.SM_CXSCREEN),
win32api.GetSystemMetrics(win32con.SM_CYSCREEN),
None,
None,
self.wndClass.hInstance,
None
)
win32gui.SetLayeredWindowAttributes(self.hWindow, 0x00ffffff, 255, win32con.LWA_COLORKEY | win32con.LWA_ALPHA)
win32gui.SetWindowPos(self.hWindow, win32con.HWND_TOPMOST, 0, 0, 0, 0,
win32con.SWP_NOACTIVATE | win32con.SWP_NOMOVE | win32con.SWP_NOSIZE | win32con.SWP_SHOWWINDOW)
win32gui.PumpMessages()
@staticmethod
def getScreenSize():
return win32api.GetSystemMetrics(win32con.SM_CXSCREEN), win32api.GetSystemMetrics(win32con.SM_CYSCREEN)
def wndProc(self, hWnd, message, wParam, lParam):
if message == win32con.WM_PAINT:
hdc, paint = win32gui.BeginPaint(hWnd)
self.x0, self.y0 = win32gui.ScreenToClient(hWnd, (self.x0, self.y0))
self.x1, self.y1 = win32gui.ScreenToClient(hWnd, (self.x1, self.y1))
pen = win32gui.CreatePen(win32con.PS_SOLID, 5, win32api.RGB(255,0,0))
win32gui.SelectObject(hdc, pen)
win32gui.MoveToEx(hdc, self.x0, self.y0)
win32gui.LineTo(hdc, self.x1, self.y1)
win32gui.ReleaseDC(hWnd,hdc)
win32gui.EndPaint(hWnd, paint)
return 0
elif message == win32con.WM_DESTROY:
win32gui.PostQuitMessage(0)
return 0
else:
return win32gui.DefWindowProc(hWnd, message, wParam, lParam)
if __name__ == '__main__':
screenSize = m0bsMagiskeTegneLib.getScreenSize()
m0bsMagiskeTegneLib(0, (screenSize[1]/2), screenSize[0], (screenSize[1]/2))
Nytt innlegg:
Jeg skreiv en liten update. Et lite problem med forrige implementasjon er at du ikke vil kunne tegne opp flere linjer ved å kalle drawLine-metoden flere ganger, løser det ved å threade createWindow-metoden slik at callbacken og følgelig render-metoden kjøres separat fra drawLine. Ved andre kjøring av drawLine vil den sjekke om vinduet er initialisert og om det er det, så vil den invalidere vinduet slik at man får en ny WM_PAINT-message.
Denne implementasjonen lager et kryss over hele skjermen.
Kode
"""
A non-euclidean, hyperdimentional, cross-platform (win/osx/linux/bsd/quantum computers/etc)
drawing package with extendend support for brownian motions and impossible colours - myoxocephalus
"""
import win32api
import win32con
import win32gui
from threading import Thread
class m0bsMagiskeTegneLib(object):
def __init__(self):
self.lines = []
self.initialized = False
Thread(target=self.createWindow).start() # Yolo
def createWindow(self):
self.wndClass = win32gui.WNDCLASS()
self.wndClass.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW
self.wndClass.lpfnWndProc = self.wndProc
self.wndClass.hInstance = win32api.GetModuleHandle()
self.wndClass.hCursor = win32gui.LoadCursor(None, win32con.IDC_ARROW)
self.wndClass.hbrBackground = win32gui.GetStockObject(win32con.WHITE_BRUSH)
self.wndClass.lpszClassName = "TransparentNonInteractiveWindow"
self.hWindow = win32gui.CreateWindowEx(
win32con.WS_EX_COMPOSITED | win32con.WS_EX_LAYERED | win32con.WS_EX_NOACTIVATE | win32con.WS_EX_TOPMOST | win32con.WS_EX_TRANSPARENT,
win32gui.RegisterClass(self.wndClass),
None,
win32con.WS_DISABLED | win32con.WS_POPUP | win32con.WS_VISIBLE,
0,
0,
win32api.GetSystemMetrics(win32con.SM_CXSCREEN),
win32api.GetSystemMetrics(win32con.SM_CYSCREEN),
None,
None,
self.wndClass.hInstance,
None)
win32gui.SetLayeredWindowAttributes(self.hWindow, 0x00ffffff, 255, win32con.LWA_COLORKEY | win32con.LWA_ALPHA)
win32gui.SetWindowPos(self.hWindow, win32con.HWND_TOPMOST, 0, 0, 0, 0,
win32con.SWP_NOACTIVATE | win32con.SWP_NOMOVE | win32con.SWP_NOSIZE | win32con.SWP_SHOWWINDOW)
win32gui.PumpMessages()
self.initialized = True
@staticmethod
def getScreenSize():
return win32api.GetSystemMetrics(win32con.SM_CXSCREEN), win32api.GetSystemMetrics(win32con.SM_CYSCREEN)
def drawLine(self, start, end, color, width):
line = {'start' : start, 'end' : end, 'color' : color, 'width' : width }
self.lines.append(line)
if self.initialized:
win32gui.InvalidateRect(self.hWnd, None, True)
win32gui.UpdateWindow(self.hWnd)
def toScreenCoord(self, hWnd, start, end):
return win32gui.ScreenToClient(hWnd, (start[0], start[1])), win32gui.ScreenToClient(hWnd, (end[0], end[1]))
def render(self, hWnd):
for line in self.lines:
(x0, y0), (x1, y1) = self.toScreenCoord(hWnd, line['start'], line['end'])
pen = win32gui.CreatePen(win32con.PS_SOLID, line['width'], win32api.RGB(line['color'][0], line['color'][1], line['color'][2]))
win32gui.SelectObject(self.hdc, pen)
win32gui.MoveToEx(self.hdc, x0, y0)
win32gui.LineTo(self.hdc, x1, y1)
def wndProc(self, hWnd, message, wParam, lParam):
if message == win32con.WM_PAINT:
self.hdc, paint = win32gui.BeginPaint(hWnd)
self.render(hWnd)
win32gui.ReleaseDC(hWnd, self.hdc)
win32gui.EndPaint(hWnd, paint)
return 0
elif message == win32con.WM_DESTROY:
win32gui.PostQuitMessage(0)
return 0
else:
return win32gui.DefWindowProc(hWnd, message, wParam, lParam)
if __name__ == '__main__':
# Hent skjermstørrelse
screenSize = m0bsMagiskeTegneLib.getScreenSize()
drawPos0 = [0, 0] # Venstre, Topp
drawPos1 = [screenSize[0], screenSize[1]] # Høyre, Bunn
drawPos2 = [screenSize[0], 0] # Høyre, Topp
drawPos3 = [0, screenSize[1]] # Venstre, Bunn
mtl = m0bsMagiskeTegneLib()
mtl.drawLine(start=drawPos0, end=drawPos1, color=(255, 0, 0), width=5)
mtl.drawLine(start=drawPos2, end=drawPos3, color=(255, 0, 0), width=5)
Sist endret av m0b; 25. august 2016 kl. 13:48.
Grunn: Automatisk sammenslåing med etterfølgende innlegg.