harupy / snipping-tool

Snipping tool in Python
83 stars 39 forks source link

Multiple monitors #6

Open HenriqueArgentieri opened 3 years ago

HenriqueArgentieri commented 3 years ago

Hi Harupy, your snipping-tool is really good, I am using a lot to summarize videos creating presentations. I am using 2 monitors, however I just can capture the main monitor. How to select the second monitor??? Thanks

tterebko commented 8 months ago

Hi @HenriqueArgentieri, @harupy , I added support for my two monitors+laptop configuration in Windows 10 by making several relatively small changes as follow.

1) Geometry of several monitors in Tkinter

In SnippingTool.py we have to tell tkinter that geometry 0, 0, tk.Tk().winfo_screenwidth(), tk.Tk().winfo_screenheight() is not good enough. Because other than main monitor go to above and beyond this box. Let's introduce new function that enhance multiple screen case.

    def get_geometry(self, tkinter: tk.Tk):
        screens = QtGui.QGuiApplication.screens()

        if len(screens) == 1:
            return 0, 0, tkinter.winfo_screenwidth(), tkinter.winfo_screenheight()

        x_min = y_min = +100_000
        x_max = y_max = -100_000
        for s in screens:
            g = s.geometry()
            x_min = min(x_min, g.x())
            y_min = min(y_min, g.y())
            x_max = max(x_max, g.x() + g.width())
            y_max = max(y_max, g.y() + g.height())
        return x_min, y_min, x_max - x_min, y_max - y_min

And feed this box into root tkinter


 def __init__(self, parent=None):
        super(SnippingWidget, self).__init__()
        self.parent = parent
        self.setWindowFlags(Qt.WindowStaysOnTopHint)

        root = tk.Tk()
        g = self.get_geometry(root)
        self.setGeometry(*g)

2) Grabbing an image - PIL is NOK, switch to MSS

I checked stackoverflow. It seems that PIL doesn't support several monitors with grabbing. So I imported and installed MSS package. And switched from img = ImageGrab.grab(bbox=(x1, y1, x2, y2)) in mouseReleaseEvent(self, event) to:


        with mss.mss() as sct:
            sct_img = sct.grab(bbox)
            img = PIL.Image.frombytes("RGB", sct_img.size, sct_img.bgra, "raw", "BGRX")
        # add to the snips list the object that opens a window of the image
        SnippingMenu.Menu(img, SnippingWidget.num_snip, (x1, y1, x2, y2))
Hierosme commented 5 months ago

I use the snipping-tool for a helloSystem Grab.app

I have found a fixe for the multiple monitor.

The tips is to take a screenshot of the entire Desktop ans ask for the size of the screenshot. With it size the snipping window can have a imposed size it take all monitor.

I have test with only two monitors

https://github.com/Hierosme/Utilities/blob/2ffdf443d127be9c15376de6031d36c77e9a552f/Under%20Construction/Grab.app/Resources/widget_snapping.py#L86 https://github.com/Hierosme/Utilities/blob/2ffdf443d127be9c15376de6031d36c77e9a552f/Under%20Construction/Grab.app/Resources/widget_snapping.py#L100 https://github.com/Hierosme/Utilities/blob/2ffdf443d127be9c15376de6031d36c77e9a552f/Under%20Construction/Grab.app/Resources/widget_snapping.py#L45

That clearly create a multimonitor support

i can send a Pull Reauest if need