wxPython实现截图功能(一)

截图的原理很简单,首先将当前整个屏幕的图像给保存下来,再将截取的位图贴到全屏,然后通过鼠标的控制,来绘制选中区域的高亮和未选中区域的阴暗背景。


父窗口通过以下函数截取整个屏幕

def Get_Screen_Bmp(self):
        s = wx.GetDisplaySize()
        bmp = wx.EmptyBitmap(s.x, s.y)
        dc = wx.ScreenDC()
        memdc = wx.MemoryDC()
        memdc.SelectObject(bmp)
        memdc.Blit(0,0, s.x, s.y, dc, 0,0)
        memdc.SelectObject(wx.NullBitmap)
        return bmp

子窗口类:


class GrabFrame(wx.Frame):
    def __init__(self, frame):
        wx.Frame.__init__(self, frame, wx.NewId(), pos = (0, 0),
                          size=wx.GetDisplaySize(), style=wx.NO_BORDER | wx.STAY_ON_TOP)

        ###################################全局变量########################################
        self.firstPoint = wx.Point(0, 0)#记录截图的第一个点
        self.lastPoint  = wx.Point(0, 0)#记录截图的最后一个点
        self.Started = False            #记录是否按下鼠标左键
        self.frame = frame

        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_LEFT_DOWN, self.On_Mouse_LeftDown)
        self.Bind(wx.EVT_LEFT_UP, self.On_Mouse_LeftUp)
        self.Bind(wx.EVT_MOTION, self.On_Mouse_Move)

    def OnPaint(self, evt):
        dc = wx.GCDC(wx.BufferedPaintDC(self))
        self.PaintUpdate(dc)

    def PaintUpdate(self, dc):
        rect = self.GetClientRect()
        color = wx.Colour(0, 0, 0, 120)

        #设置绘制截图区域时矩形的点
        minX, minY = min(self.firstPoint.x, self.lastPoint.x), min(self.firstPoint.y, self.lastPoint.y)
        maxX, maxY = max(self.firstPoint.x, self.lastPoint.x), max(self.firstPoint.y, self.lastPoint.y)

        #画出整个屏幕的截图
        dc.DrawBitmap(self.frame.grabBmp, 0, 0)

        #画出阴影部分(截取的部分不需要画)
        dc.SetPen(wx.Pen(color))
        dc.SetBrush(wx.Brush(color))
        dc.DrawRectangle(0, 0, maxX, minY)
        dc.DrawRectangle(maxX, 0, rect.width - maxX, maxY)
        dc.DrawRectangle(minX, maxY, rect.width - minX, rect.height - maxY)
        dc.DrawRectangle(0, minY, minX, rect.height - minY)

        if(self.Started == True):

            #画出截图区域的边框
            dc.SetPen(wx.Pen(wx.Colour(255, 0, 0)))
            dc.SetBrush(wx.Brush(color, wx.TRANSPARENT))
            dc.DrawRectangle(minX, minY, maxX - minX, maxY - minY)

            #显示信息
            dc.SetBrush(wx.Brush(wx.Colour(255,0,0)))
            dc.DrawRectangleList([
                (minX - 2, minY - 2, 5, 5),
                (maxX / 2 + minX / 2 - 2, minY - 2, 5, 5),
                (maxX - 2, minY - 2, 5, 5),
                (maxX - 2, maxY / 2 + minY / 2 - 2, 5, 5),
                (maxX - 2, maxY - 2, 5, 5),
                (maxX / 2 + minX / 2 - 2, maxY - 2, 5, 5),
                (minX - 2, maxY - 2, 5, 5),
                (minX - 2, maxY / 2 + minY / 2 - 2, 5, 5)
                ])
            color = wx.Colour(0,0,0,180)
            dc.SetPen(wx.Pen(color))
            dc.SetBrush(wx.Brush(color, wx.SOLID))
            w,h = 140, 43
            s = u'区域大小:'+str(maxX - minX)+'*'+str(maxY - minY)
            s += u'\n鼠标位置:('+str(self.lastPoint.x)+','+str(self.lastPoint.y)+')'
            dc.DrawRectangle(minX, minY-h-5 if minY -5 > h else minY+5, w, h)
            dc.SetTextForeground(wx.Colour(255,255,255))
            dc.DrawText(s, minX+5, (minY-h-5 if minY-5 > h else minY + 5)+5)



    def On_Mouse_LeftDown(self, evt):
        self.Started = True
        self.firstPoint = evt.GetPosition()
        self.lastPoint = evt.GetPosition()
        
    def On_Mouse_LeftUp(self, evt):
        if(self.Started):
            self.lastPoint = evt.GetPosition()
            if(self.firstPoint.x == self.lastPoint.x)&(self.firstPoint.y == self.lastPoint.y):
                wx.MessageBox(u"区域设置不正确", "Error", wx.OK | wx.ICON_ERROR, self)
                self.Started = False
                self.firstPoint = wx.Point(0, 0)#记录截图的第一个点
                self.lastPoint  = wx.Point(0, 0)#记录截图的最后一个点
                
            else:
                self.frame.bmp = self.frame.grabBmp.GetSubBitmap(wx.Rect(
                    min(self.firstPoint.x, self.lastPoint.x),
                    min(self.firstPoint.y, self.lastPoint.y),
                    abs(self.firstPoint.x - self.lastPoint.x),
                    abs(self.firstPoint.y - self.lastPoint.y)
                    ))

                self.Close()
                self.frame.Show()
        
    def On_Mouse_Move(self, evt):
        if(self.Started):
            self.lastPoint = evt.GetPosition()
            self.NewUpdate()

    def NewUpdate(self):
        self.RefreshRect(self.GetClientRect(), True)
        self.Update()
声明一下,这个实际上那个是创建了一个没有边框、置顶的窗口,整个截图实际上就是在客户区(整个屏幕)中贴图再选择区域。这里的frame是其父窗口
dc.DrawBitmap(self.frame.grabBmp, 0, 0)
将父窗口得到的全屏的位图贴到客户区

最后就是通过wx.Bitmap的GetSubBitmap函数来选取整张位图的其中一个区域


父窗口通过以下函数截取整个屏幕

def Get_Screen_Bmp(self):
        s = wx.GetDisplaySize()
        bmp = wx.EmptyBitmap(s.x, s.y)
        dc = wx.ScreenDC()
        memdc = wx.MemoryDC()
        memdc.SelectObject(bmp)
        memdc.Blit(0,0, s.x, s.y, dc, 0,0)
        memdc.SelectObject(wx.NullBitmap)
        return bmp

你可能感兴趣的:(wxPython,截图,屏幕截图,全屏截图)