; 用法:截屏到剪贴板或者文件,可以加入开机脚本中热键调用 ; ; 类似QQ微信的阴影截屏 By FeiYue ; 用手动调用截图,先选择范围然后保存到剪贴板或文件 F1:: SnapShot() ; 用命令行调用截图,文件参数为 0 或空就保存到剪贴板 F2:: file:="c:\1.bmp" SnapShot( file, [0, 0, A_ScreenWidth, A_ScreenHeight] ) Run, % file return SnapShot(args*) { return (new SnapShotClass).SnapShot(args*) } Class SnapShotClass { ;// 类开始 ; 参 数: 文件名 和 范围数组 [x,y,w,h],都为空可以手动选择范围 ; 返回值: 手动选择的范围数组 [x,y,w,h] SnapShot(file:="", range:="") { local ; 如果范围参数 range 是数组,就命令行调用 if IsObject(range) { hBM:=this.BitmapFromScreen(range*) this.SaveBitmapToFile(file, hBM) DllCall("DeleteObject", "Ptr",hBM) return } ; 屏蔽热键的执行代码 static Gui_Off:="", hk if (!Gui_Off) Gui_Off:=Func(A_ThisFunc).Bind(this, "<Off>") if (file="<Off>") return hk:=Trim(A_ThisHotkey, "*") ; 截屏到内存图像 hBM hBM:=this.BitmapFromScreen(zx:=0, zy:=0, zw:=0, zh:=0) ; 显示静态画布,兼做热键的条件 Gui, SnapShot_HotkeyIf: New ; WS_EX_NOACTIVATE:=0x08000000 Gui, +AlwaysOnTop -Caption +ToolWindow -DPIScale +E0x08000000 Gui, Margin, 0, 0 Gui, Add, Pic, w%zw% h%zh%, % "HBITMAP:*" hBM Gui, Show, NA x%zx% y%zy% w%zw% h%zh%, SnapShot_HotkeyIf this.DarkenRange(1) ; 生成保存按钮 Gui, SnapShot_Box: New Gui, +Hwndbox_id +AlwaysOnTop -Caption +ToolWindow -DPIScale +E0x08000000 Gui, Margin, 0, 0 Gui, Font, s12 For k,v in StrSplit("重选|存文件|仅范围|存剪贴板", "|") Gui, Add, Button, % (k=1 ? "":"x+0") " Hwndid", %v% GuiControlGet, p, Pos, %id% box_w:=pX+pW+10, box_h:=pH+10 Gui, Show, Hide, SnapShot_Box ; 设定屏蔽热键 key:="LButton" KeyWait, RButton Hotkey, IfWinExist, SnapShot_HotkeyIf keys:=key "|Esc|Up|Down|Left|Right" For k,v in StrSplit(keys, "|") { KeyWait, %v% Hotkey, *%v%, %Gui_Off%, On UseErrorLevel } Hotkey, IfWinExist ; 开始选择范围 Critical % (cri:=A_IsCritical)?"Off":"Off" CoordMode, Mouse Loop { ;// 用于重选 tip:="左键拖动选择范围,方向键微调`n右键或ESC仅范围,双击存剪贴板" hk:="", oldx:=oldy:="", ok:=0, d:=10, oldt:=0, oldf:="" Loop { Sleep 20 if (hk="Esc") || GetKeyState("Esc","P") || GetKeyState("RButton","P") { x:=y:=w:=h:=0 Break 2 } MouseGetPos, x1, y1 if (oldx=x1 && oldy=y1) Continue oldx:=x1, oldy:=y1 ToolTip %tip% } Until (hk=key) || GetKeyState(key,"P") Loop { Sleep 20 MouseGetPos, x2, y2 ;------------- x:=Min(x1,x2), y:=Min(y1,y2), w:=Abs(x1-x2)+1, h:=Abs(y1-y2)+1 this.DarkenRange(x, y, w, h) ;------------- if (oldx=x2 && oldy=y2) Continue oldx:=x2, oldy:=y2 ToolTip %tip% } Until !GetKeyState(key,"P") hk:="" Loop { Sleep 20 MouseGetPos, x3, y3 x1:=x, y1:=y, x2:=x+w-1, y2:=y+h-1 , d1:=Abs(x3-x1)<=d, d2:=Abs(x3-x2)<=d , d3:=Abs(y3-y1)<=d, d4:=Abs(y3-y2)<=d , d5:=x3>x1+d && x3<x2-d, d6:=y3>y1+d && y3<y2-d , f:=(d1 && d3 ? 1 : d2 && d3 ? 2 : d1 && d4 ? 3 : d2 && d4 ? 4 : d5 && d3 ? 5 : d5 && d4 ? 6 : d6 && d1 ? 7 : d6 && d2 ? 8 : d5 && d6 ? 9 : 0) if (oldf!=f) oldf:=f, this.SetCursor(f=1 || f=4 ? "SIZENWSE" : f=2 || f=3 ? "SIZENESW" : f=5 || f=6 ? "SIZENS" : f=7 || f=8 ? "SIZEWE" : f=9 ? "SIZEALL" : "ARROW") ;-------------- if (hk="Up") || GetKeyState("Up","P") hk:="", y-- else if (hk="Down") || GetKeyState("Down","P") hk:="", y++ else if (hk="Left") || GetKeyState("Left","P") hk:="", x-- else if (hk="Right") || GetKeyState("Right","P") hk:="", x++ else if (hk="Esc") || GetKeyState("Esc","P") || GetKeyState("RButton","P") Break else if (hk=key) || GetKeyState(key,"P") { MouseGetPos,,, id, class if (id=box_id) && (class="Button1") { KeyWait, % key Gui, SnapShot_Box: Hide this.DarkenRange(1) Continue 2 } if (id=box_id) && (ok:=class="Button2" ? 2 : class="Button4" ? 1:100) Break Gui, SnapShot_Box: Hide ToolTip Loop { Sleep 20 MouseGetPos, x4, y4 x1:=x, y1:=y, x2:=x+w-1, y2:=y+h-1, dx:=x4-x3, dy:=y4-y3 , (f=1 ? (x1+=dx, y1+=dy) : f=2 ? (x2+=dx, y1+=dy) : f=3 ? (x1+=dx, y2+=dy) : f=4 ? (x2+=dx, y2+=dy) : f=5 ? y1+=dy : f=6 ? y2+=dy : f=7 ? x1+=dx : f=8 ? x2+=dx : f=9 ? (x1+=dx, y1+=dy, x2+=dx, y2+=dy) : 0) , (f) && this.DarkenRange(Min(x1,x2), Min(y1,y2), Abs(x1-x2)+1, Abs(y1-y2)+1) } Until !GetKeyState(key,"P") hk:="", x:=Min(x1,x2), y:=Min(y1,y2), w:=Abs(x1-x2)+1, h:=Abs(y1-y2)+1 if (f=9) && Abs(dx)<2 && Abs(dy)<2 && (ok:=(-oldt)+(oldt:=A_TickCount)<400) Break } this.DarkenRange(x, y, w, h) x1:=x+w-box_w, (x1<10 && x1:=10), (x1>zx+zw-box_w && x1:=zx+zw-box_w) , y1:=y+h+10, (y1>zy+zh-box_h && y1:=y-box_h), (y1<10 && y1:=10) Gui, SnapShot_Box: Show, NA x%x1% y%y1% ;------------- if (oldx=x3 && oldy=y3) Continue oldx:=x3, oldy:=y3 ToolTip %tip% } Break } ;// 用于重选 this.SetCursor() ToolTip this.DarkenRange() Gui, SnapShot_Box: Destroy KeyWait, RButton Hotkey, IfWinExist, SnapShot_HotkeyIf For k,v in StrSplit(keys, "|") { KeyWait, %v% Hotkey, *%v%, %Gui_Off%, Off UseErrorLevel } Hotkey, IfWinExist Gui, SnapShot_HotkeyIf: Destroy Critical %cri% ; 保存内存图像到剪贴板或文件 w:=Min(x+w,zx+zw), x:=Max(x,zx), w-=x h:=Min(y+h,zy+zh), y:=Max(y,zy), h-=y if (ok=1) this.SaveBitmapToFile(0, hBM, x-zx, y-zy, w, h) else if (ok=2) { FileSelectFile, file, S18, %A_Desktop%\1.bmp, 另存为, 图片 (*.bmp) this.SaveBitmapToFile(file, hBM, x-zx, y-zy, w, h) } ; 删除内存图像 hBM DllCall("DeleteObject", "Ptr",hBM) return [x, y, w, h] } BitmapFromScreen(ByRef x:=0, ByRef y:=0, ByRef w:=0, ByRef h:=0) { local x:=Floor(x), y:=Floor(y), w:=Floor(w), h:=Floor(h) if (w<1 || h<1) { SysGet, x, 76 SysGet, y, 77 SysGet, w, 78 SysGet, h, 79 } hBM:=this.CreateDIBSection(w, h, 32) mDC:=DllCall("CreateCompatibleDC", "Ptr",0, "Ptr") oBM:=DllCall("SelectObject", "Ptr",mDC, "Ptr",hBM, "Ptr") ;------------- hDC:=DllCall("GetWindowDC", "Ptr",win:=DllCall("GetDesktopWindow", "Ptr"), "Ptr") DllCall("BitBlt", "Ptr",mDC, "int",0, "int",0, "int",w, "int",h , "Ptr",hDC, "int",x, "int",y, "uint",0xCC0020|0x40000000) DllCall("ReleaseDC", "Ptr",win, "Ptr",hDC) ;------------- DllCall("SelectObject", "Ptr",mDC, "Ptr",oBM) DllCall("DeleteDC", "Ptr",mDC) return hBM } CreateDIBSection(w, h, bpp:=32, ByRef ppvBits:=0) { local VarSetCapacity(bi, 40, 0), NumPut(40, bi, 0, "int") , NumPut(w, bi, 4, "int"), NumPut(-h, bi, 8, "int") , NumPut(1, bi, 12, "short"), NumPut(bpp, bi, 14, "short") return DllCall("CreateDIBSection", "Ptr",0, "Ptr",&bi , "int",0, "Ptr*",ppvBits:=0, "Ptr",0, "int",0, "Ptr") } GetBitmapWH(hBM, ByRef w, ByRef h) { local VarSetCapacity(bm, size:=(A_PtrSize=8 ? 32:24)) , DllCall("GetObject", "Ptr",hBM, "int",size, "Ptr",&bm) , w:=NumGet(bm,4,"int"), h:=Abs(NumGet(bm,8,"int")) } CopyHBM(hBM1, x1, y1, hBM2, x2, y2, w, h) { local if (w<1 || h<1 || !hBM1 || !hBM2) return mDC1:=DllCall("CreateCompatibleDC", "Ptr",0, "Ptr") oBM1:=DllCall("SelectObject", "Ptr",mDC1, "Ptr",hBM1, "Ptr") mDC2:=DllCall("CreateCompatibleDC", "Ptr",0, "Ptr") oBM2:=DllCall("SelectObject", "Ptr",mDC2, "Ptr",hBM2, "Ptr") DllCall("BitBlt", "Ptr",mDC1, "int",x1, "int",y1, "int",w, "int",h , "Ptr",mDC2, "int",x2, "int",y2, "uint",0xCC0020) DllCall("SelectObject", "Ptr",mDC1, "Ptr",oBM1) DllCall("DeleteDC", "Ptr",mDC1) DllCall("SelectObject", "Ptr",mDC2, "Ptr",oBM2) DllCall("DeleteDC", "Ptr",mDC2) } DrawHBM(hBM, lines) { local mDC:=DllCall("CreateCompatibleDC", "Ptr",0, "Ptr") DllCall("SaveDC", "Ptr",mDC) DllCall("SelectObject", "Ptr",mDC, "Ptr",hBM) oldc:="" For k,v in lines if IsObject(v) { if (oldc!=v[5]) { c:=((c:=v[5])&0xFF)<<16|c&0xFF00|(c>>16)&0xFF pen:=DllCall("CreatePen", "Int",0, "Int",1, "UInt",c, "Ptr") pen:=DllCall("SelectObject", "Ptr",mDC, "Ptr",pen) (oldc!="") && DllCall("DeleteObject", "Ptr",pen) brush:=DllCall("CreateSolidBrush", "UInt", c, "Ptr") brush:=DllCall("SelectObject", "Ptr",mDC, "Ptr",brush) (oldc!="") && DllCall("DeleteObject", "Ptr",brush) oldc:=v[5] } DllCall("Rectangle", "Ptr",mDC, "Int",v[1], "Int",v[2], "Int",v[1]+v[3], "Int",v[2]+v[4]) } DllCall("RestoreDC", "Ptr",mDC, "Int",-1) DllCall("DeleteObject", "Ptr",mDC) } BitmapToWindow(hwnd, x1, y1, hBM, x2, y2, w, h) { local mDC:=DllCall("CreateCompatibleDC", "Ptr",0, "Ptr") oBM:=DllCall("SelectObject", "Ptr",mDC, "Ptr",hBM, "Ptr") hDC:=DllCall("GetDC", "Ptr",hwnd, "Ptr") DllCall("BitBlt", "Ptr",hDC, "int",x1, "int",y1, "int",w, "int",h , "Ptr",mDC, "int",x2, "int",y2, "uint",0xCC0020) DllCall("ReleaseDC", "Ptr",hwnd, "Ptr",hDC) DllCall("SelectObject", "Ptr",mDC, "Ptr",oBM) DllCall("DeleteDC", "Ptr",mDC) } SetCursor(cursor:="") { local static init:="", tab if (!init) { init:=1, tab:=[], ID:=Object("ARROW",32512, "SIZENWSE",32642 , "SIZENESW",32643, "SIZEWE",32644, "SIZENS",32645, "SIZEALL",32646) , OnExit(Func(A_ThisFunc).Bind(this,"")), this.SetCursor() For k,v in ID tab[k]:=DllCall("CopyImage", "Ptr", DllCall("LoadCursor" , "Ptr",0, "Ptr",v, "Ptr"), "int",2, "int",0, "int",0, "int",0, "Ptr") } if (cursor!="") && tab.HasKey(cursor) DllCall("SetSystemCursor", "Ptr", DllCall("CopyImage", "Ptr",tab[cursor] , "int",2, "int",0, "int",0, "int",0, "Ptr"), "int",32512) else DllCall("SystemParametersInfo", "int",0x57, "int",0, "Ptr",0, "int",0) } DarkenRange(x:=0, y:=0, w:=0, h:=0) { local static id:="", hBM1, hBM2, hBM3, zx, zy, zw, zh, oldx, oldy, oldw, oldh if (x=0 && y=0 && w=0 && h=0) { if (!id) return id:="" Gui, DarkenRange: Destroy DllCall("DeleteObject", "Ptr",hBM1) DllCall("DeleteObject", "Ptr",hBM2) DllCall("DeleteObject", "Ptr",hBM3) return } Gui, DarkenRange: +LastFoundExist IfWinNotExist { oldx:=oldy:=oldw:=oldh:=0 hBM1:=this.BitmapFromScreen(zx:=0, zy:=0, zw:=0, zh:=0) ;------------ Gui, DarkenRange: New Gui, +Hwndid +LastFound +AlwaysOnTop -Caption +ToolWindow -DPIScale Gui, Color, Black WinSet, Transparent, 100 Gui, Show, NA x%zx% y%zy% w%zw% h%zh% Sleep 100 ;------------ hBM2:=this.BitmapFromScreen(zx,zy,zw,zh) hBM3:=DllCall("CopyImage","Ptr",hBM2,"int",0,"int",0,"int",0,"uint",0x2000,"Ptr") this.BitmapToWindow(id,0,0,hBM3,0,0,zw,zh) WinSet, Transparent, 255 } if (oldx=x && oldy=y && oldw=w && oldh=h) return 1 oldx:=x, oldy:=y, oldw:=w, oldh:=h x-=zx, y-=zy, d:=2, i:=1, j:=2*d+i, c:=0x3399FF lines:=[ 0 , [x-i, y-i, w+i*2, i, c] ; 上横线 , [x-i, y+h, w+i*2, i, c] ; 下横线 , [x-i, y-i, i, h+i*2, c] ; 左竖线 , [x+w, y-i, i, h+i*2, c] ; 右竖线 , [x-i-d, y-i-d, j, j, c] ; 上左点 , [x+w//2-d, y-i-d, j, j, c] ; 上中点 , [x+w-d, y-i-d, j, j, c] ; 上右点 , [x-i-d, y+h//2-d, j, j, c] ; 中左点 , [x+w-d, y+h//2-d, j, j, c] ; 中右点 , [x-i-d, y+h-d, j, j, c] ; 下左点 , [x+w//2-d, y+h-d, j, j, c] ; 下中点 , [x+w-d, y+h-d, j, j, c] ; 下右点 , 0 ] this.CopyHBM(hBM3,0,0,hBM2,0,0,zw,zh) this.CopyHBM(hBM3,x,y,hBM1,x,y,w,h) this.DrawHBM(hBM3, lines) this.BitmapToWindow(id,0,0,hBM3,0,0,zw,zh) return 1 } ; if file = 0 or "", Save to Clipboard SaveBitmapToFile(file, hBM_or_file, x:=0, y:=0, w:=0, h:=0) { local if hBM_or_file is Number hBM_or_file:="HBITMAP:*" hBM_or_file if !hBM:=DllCall("CopyImage", "Ptr",LoadPicture(hBM_or_file) , "int",0, "int",0, "int",0, "uint",0x2008) return if (file) || (w!=0 && h!=0) { (w=0 || h=0) && this.GetBitmapWH(hBM, w, h) hBM2:=this.CreateDIBSection(w, -h, bpp:=(file ? 24 : 32)) this.CopyHBM(hBM2, 0, 0, hBM, x, y, w, h) DllCall("DeleteObject", "Ptr",hBM), hBM:=hBM2 } VarSetCapacity(dib, dib_size:=(A_PtrSize=8 ? 104:84)) , DllCall("GetObject", "Ptr",hBM, "int",dib_size, "Ptr",&dib) , pbi:=&dib+(bitmap_size:=A_PtrSize=8 ? 32:24) , size:=NumGet(pbi+20, "uint"), pBits:=NumGet(pbi-A_PtrSize, "Ptr") if (!file) { hdib:=DllCall("GlobalAlloc", "uint",2, "Ptr",40+size, "Ptr") pdib:=DllCall("GlobalLock", "Ptr",hdib, "Ptr") DllCall("RtlMoveMemory", "Ptr",pdib, "Ptr",pbi, "Ptr",40) DllCall("RtlMoveMemory", "Ptr",pdib+40, "Ptr",pBits, "Ptr",size) DllCall("GlobalUnlock", "Ptr",hdib) DllCall("OpenClipboard", "Ptr",0) DllCall("EmptyClipboard") if !DllCall("SetClipboardData", "uint",8, "Ptr",hdib) DllCall("GlobalFree", "Ptr",hdib) DllCall("CloseClipboard") } else { VarSetCapacity(bf, 14, 0), NumPut(0x4D42, bf, "short") NumPut(54+size, bf, 2, "uint"), NumPut(54, bf, 10, "uint") f:=FileOpen(file, "w"), f.RawWrite(bf, 14) , f.RawWrite(pbi+0, 40), f.RawWrite(pBits+0, size), f.Close() } DllCall("DeleteObject", "Ptr",hBM) } } ;// 类结束
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。
评论(0)