; 用法:截屏到剪贴板或者文件,可以加入开机脚本中热键调用
;
; 类似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)