Snipping Tool과 동일한 기능을 수행하는 .NET 코드 (화면 영역 캡처)를 찾고 있습니다. 나는 그것이 후크를 사용한다고 생각한다. 선택한 조각을 어떻게 강조 할 수 있는지 아는 것이 재미있을 것입니다.Snipping Tool에 해당하는 .NET
업데이트 : 발견 http://www.codeproject.com/KB/vb/Screen_Shot.aspx. 사람들은 적절한 편집을 위해 몇 가지 중요한 파일이 누락되었다고 말합니다.
Snipping Tool과 동일한 기능을 수행하는 .NET 코드 (화면 영역 캡처)를 찾고 있습니다. 나는 그것이 후크를 사용한다고 생각한다. 선택한 조각을 어떻게 강조 할 수 있는지 아는 것이 재미있을 것입니다.Snipping Tool에 해당하는 .NET
업데이트 : 발견 http://www.codeproject.com/KB/vb/Screen_Shot.aspx. 사람들은 적절한 편집을 위해 몇 가지 중요한 파일이 누락되었다고 말합니다.
Windows Forms에서 스니핑 도구 효과를 구현하기가 어렵지 않습니다. 프로젝트에 새 양식을 추가하고 이름을 "SnippingTool"로 지정하십시오. 이 같은 코드의 모양을 확인하십시오
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace WindowsFormsApplication1 {
public partial class SnippingTool : Form {
public static Image Snip() {
var rc = Screen.PrimaryScreen.Bounds;
using (Bitmap bmp = new Bitmap(rc.Width, rc.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb)) {
using (Graphics gr = Graphics.FromImage(bmp))
gr.CopyFromScreen(0, 0, 0, 0, bmp.Size);
using (var snipper = new SnippingTool(bmp)) {
if (snipper.ShowDialog() == DialogResult.OK) {
return snipper.Image;
}
}
return null;
}
}
public SnippingTool(Image screenShot) {
InitializeComponent();
this.BackgroundImage = screenShot;
this.ShowInTaskbar = false;
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
this.DoubleBuffered = true;
}
public Image Image { get; set; }
private Rectangle rcSelect = new Rectangle();
private Point pntStart;
protected override void OnMouseDown(MouseEventArgs e) {
// Start the snip on mouse down
if (e.Button != MouseButtons.Left) return;
pntStart = e.Location;
rcSelect = new Rectangle(e.Location, new Size(0, 0));
this.Invalidate();
}
protected override void OnMouseMove(MouseEventArgs e) {
// Modify the selection on mouse move
if (e.Button != MouseButtons.Left) return;
int x1 = Math.Min(e.X, pntStart.X);
int y1 = Math.Min(e.Y, pntStart.Y);
int x2 = Math.Max(e.X, pntStart.X);
int y2 = Math.Max(e.Y, pntStart.Y);
rcSelect = new Rectangle(x1, y1, x2 - x1, y2 - y1);
this.Invalidate();
}
protected override void OnMouseUp(MouseEventArgs e) {
// Complete the snip on mouse-up
if (rcSelect.Width <= 0 || rcSelect.Height <= 0) return;
Image = new Bitmap(rcSelect.Width, rcSelect.Height);
using (Graphics gr = Graphics.FromImage(Image)) {
gr.DrawImage(this.BackgroundImage, new Rectangle(0, 0, Image.Width, Image.Height),
rcSelect, GraphicsUnit.Pixel);
}
DialogResult = DialogResult.OK;
}
protected override void OnPaint(PaintEventArgs e) {
// Draw the current selection
using (Brush br = new SolidBrush(Color.FromArgb(120, Color.White))) {
int x1 = rcSelect.X; int x2 = rcSelect.X + rcSelect.Width;
int y1 = rcSelect.Y; int y2 = rcSelect.Y + rcSelect.Height;
e.Graphics.FillRectangle(br, new Rectangle(0, 0, x1, this.Height));
e.Graphics.FillRectangle(br, new Rectangle(x2, 0, this.Width - x2, this.Height));
e.Graphics.FillRectangle(br, new Rectangle(x1, 0, x2 - x1, y1));
e.Graphics.FillRectangle(br, new Rectangle(x1, y2, x2 - x1, this.Height - y2));
}
using (Pen pen = new Pen(Color.Red, 3)) {
e.Graphics.DrawRectangle(pen, rcSelect);
}
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
// Allow canceling the snip with the Escape key
if (keyData == Keys.Escape) this.DialogResult = DialogResult.Cancel;
return base.ProcessCmdKey(ref msg, keyData);
}
}
}
사용법 :
var bmp = SnippingTool.Snip();
if (bmp != null) {
// Do something with the bitmap
//...
}
전체 화면 스크린 샷을 찍은 다음 (아마도) 복사하고 반투명 효과 &을 적용하여 표시합니다. 클릭하고 드래그하면 원래 캡처에서 해당 영역을 오버레이 할 수 있습니다.
CopyFromScreen()
을 사용하거나 GDI API을 사용하여 스크린 샷을 얻을 수 있습니다.
감사합니다. 그건 의미가 있습니다. "희게하는"효과를 비트 맵에 어떻게 적용 할 수 있을지 알고있을 것입니다. – SharpAffair
이것은 여러 대의 모니터와 호환되며 Windows 7 및 Windows 10에서 테스트 DPI 스케일링 (잘 작동 한스의 버전 @ 수정).
public sealed partial class SnippingTool : Form
{
public static event EventHandler Cancel;
public static event EventHandler AreaSelected;
public static Image Image { get; set; }
private static SnippingTool[] _forms;
private Rectangle _rectSelection;
private Point _pointStart;
public SnippingTool(Image screenShot, int x, int y, int width, int height)
{
InitializeComponent();
BackgroundImage = screenShot;
BackgroundImageLayout = ImageLayout.Stretch;
ShowInTaskbar = false;
FormBorderStyle = FormBorderStyle.None;
StartPosition = FormStartPosition.Manual;
SetBounds(x, y, width, height);
WindowState = FormWindowState.Maximized;
DoubleBuffered = true;
Cursor = Cursors.Cross;
TopMost = true;
}
private void OnCancel(EventArgs e)
{
Cancel?.Invoke(this, e);
}
private void OnAreaSelected(EventArgs e)
{
AreaSelected?.Invoke(this, e);
}
private void CloseForms()
{
for (int i = 0; i < _forms.Length; i++)
{
_forms[i].Dispose();
}
}
public static void Snip()
{
var screens = ScreenHelper.GetMonitorsInfo();
_forms = new SnippingTool[screens.Count];
for (int i = 0; i < screens.Count; i++)
{
int hRes = screens[i].HorizontalResolution;
int vRes = screens[i].VerticalResolution;
int top = screens[i].MonitorArea.Top;
int left = screens[i].MonitorArea.Left;
var bmp = new Bitmap(hRes, vRes, PixelFormat.Format32bppPArgb);
using (var g = Graphics.FromImage(bmp))
{
g.CopyFromScreen(left, top, 0, 0, bmp.Size);
}
_forms[i] = new SnippingTool(bmp, left, top, hRes, vRes);
_forms[i].Show();
}
}
#region Overrides
protected override void OnMouseDown(MouseEventArgs e)
{
// Start the snip on mouse down
if (e.Button != MouseButtons.Left)
{
return;
}
_pointStart = e.Location;
_rectSelection = new Rectangle(e.Location, new Size(0, 0));
Invalidate();
}
protected override void OnMouseMove(MouseEventArgs e)
{
// Modify the selection on mouse move
if (e.Button != MouseButtons.Left)
{
return;
}
int x1 = Math.Min(e.X, _pointStart.X);
int y1 = Math.Min(e.Y, _pointStart.Y);
int x2 = Math.Max(e.X, _pointStart.X);
int y2 = Math.Max(e.Y, _pointStart.Y);
_rectSelection = new Rectangle(x1, y1, x2 - x1, y2 - y1);
Invalidate();
}
protected override void OnMouseUp(MouseEventArgs e)
{
// Complete the snip on mouse-up
if (_rectSelection.Width <= 0 || _rectSelection.Height <= 0)
{
CloseForms();
OnCancel(new EventArgs());
return;
}
Image = new Bitmap(_rectSelection.Width, _rectSelection.Height);
var hScale = BackgroundImage.Width/(double)Width;
var vScale = BackgroundImage.Height/(double)Height;
using (Graphics gr = Graphics.FromImage(Image))
{
gr.DrawImage(BackgroundImage,
new Rectangle(0, 0, Image.Width, Image.Height),
new Rectangle((int)(_rectSelection.X * hScale), (int)(_rectSelection.Y * vScale), (int)(_rectSelection.Width * hScale), (int)(_rectSelection.Height * vScale)),
GraphicsUnit.Pixel);
}
CloseForms();
OnAreaSelected(new EventArgs());
}
protected override void OnPaint(PaintEventArgs e)
{
// Draw the current selection
using (Brush br = new SolidBrush(Color.FromArgb(120, Color.White)))
{
int x1 = _rectSelection.X;
int x2 = _rectSelection.X + _rectSelection.Width;
int y1 = _rectSelection.Y;
int y2 = _rectSelection.Y + _rectSelection.Height;
e.Graphics.FillRectangle(br, new Rectangle(0, 0, x1, Height));
e.Graphics.FillRectangle(br, new Rectangle(x2, 0, Width - x2, Height));
e.Graphics.FillRectangle(br, new Rectangle(x1, 0, x2 - x1, y1));
e.Graphics.FillRectangle(br, new Rectangle(x1, y2, x2 - x1, Height - y2));
}
using (Pen pen = new Pen(Color.Red, 2))
{
e.Graphics.DrawRectangle(pen, _rectSelection);
}
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
// Allow canceling the snip with the Escape key
if (keyData == Keys.Escape)
{
Image = null;
CloseForms();
OnCancel(new EventArgs());
}
return base.ProcessCmdKey(ref msg, keyData);
}
#endregion
}
사용법 :
SnippingTool.AreaSelected += OnAreaSelected;
SnippingTool.Snip();
private static void OnAreaSelected(object sender, EventArgs e)
{
var bmp = SnippingTool.Image;
// Do something with the bitmap
//...
}
참고하면 실제 모니터 해상도를 얻을 DPI 스케일링 문제를 방지하기 위해 도우미 클래스가 필요합니다. 이 코드입니다 : 여기
public class DeviceInfo
{
public string DeviceName { get; set; }
public int VerticalResolution { get; set; }
public int HorizontalResolution { get; set; }
public Rectangle MonitorArea { get; set; }
}
public static class ScreenHelper
{
private const int DektopVertRes = 117;
private const int DesktopHorzRes = 118;
[StructLayout(LayoutKind.Sequential)]
internal struct Rect
{
public int left;
public int top;
public int right;
public int bottom;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct MONITORINFOEX
{
public int Size;
public Rect Monitor;
public Rect WorkArea;
public uint Flags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DeviceName;
}
private delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData);
[DllImport("user32.dll")]
private static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateDC(string lpszDriver, string lpszDevice, string lpszOutput, IntPtr lpInitData);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFOEX lpmi);
[DllImport("User32.dll")]
private static extern int ReleaseDC(IntPtr hwnd, IntPtr dc);
[DllImport("gdi32.dll")]
private static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
private static List<DeviceInfo> _result;
public static List<DeviceInfo> GetMonitorsInfo()
{
_result = new List<DeviceInfo>();
EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, MonitorEnum, IntPtr.Zero);
return _result;
}
private static bool MonitorEnum(IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData)
{
var mi = new MONITORINFOEX();
mi.Size = Marshal.SizeOf(typeof(MONITORINFOEX));
bool success = GetMonitorInfo(hMonitor, ref mi);
if (success)
{
var dc = CreateDC(mi.DeviceName, mi.DeviceName, null, IntPtr.Zero);
var di = new DeviceInfo
{
DeviceName = mi.DeviceName,
MonitorArea = new Rectangle(mi.Monitor.left, mi.Monitor.top, mi.Monitor.right-mi.Monitor.right, mi.Monitor.bottom-mi.Monitor.top),
VerticalResolution = GetDeviceCaps(dc, DektopVertRes),
HorizontalResolution = GetDeviceCaps(dc, DesktopHorzRes)
};
ReleaseDC(IntPtr.Zero, dc);
_result.Add(di);
}
return true;
}
}
이 좋은 답변을 전체
source code
작동하지만 이미지를 snipping하는 동안 높은 Dpi에서 흐리게하고 저장하면 이미지가 너무 작아서 고치려고했으나 할 수 없었습니다. @ thepirat000 – Arvand
@Arvand DPI 구성은 무엇입니까? – thepirat000
텍스트 크기가 250 %로 설정된 3840x2160 [4K 디스플레이] – Arvand
굉장 !! 고마워 sooo 많이! – SharpAffair
한스,이 도구를 보조 모니터와 호환되도록 만들 수 있습니까? 화면 매개 변수를 추가하고 그에 따라 스니퍼 위치를 조정하려고 시도했지만 예기치 않은 결과가 발생했습니다. – SharpAffair
"예기치 않은 결과"로 내가 무엇을 기대합니까? 새로운 질문을 시작하고 문제를 문서화하십시오. –