제 목적은 windowsForm 을 사용하여 window 10 캡처 도구 같은 스크린샷 프로그램을 만들려고 합니다.
일단 제가 생각한 프로그램 구성입니다.
- 스크린샷 버튼을 누르면 전체화면 으로 한번 찍고 사진을 맨 위에 띄움
- 전체적으로 화면이 밝아짐
- drag해서 영역을 만듬 영역 안쪽은 원래 색상으로 돌아오게 해서 구분감을 준다
- 상자 영역 캡처
3번 부분이 막혔습니다. 개인적으로 생각했던 방법은
- 픽셀 단위로 제어해서 밝기를 제어한다.
- 밝은 사진과 원래 사진을 각각 찍어서 drag를 하면 원래 사진을 보여준다
로 생각하고 작업하고 있으나 둘 다 마땅치 않아서 혹시 다른 방법이 있을까 하고 질문 드립니다.
- 추가적으로 window 10 캡처 도구 의 drag캡처 방식이 어떻게 되어있는지 도 질문 드립니다.
감사합니당
2개의 좋아요
먼저 Windows 10 캡쳐 도구의 Drag 캡쳐 방식이 어떻게 되어있는지는 모르겠습니다.
Windows Forms의 GDI+를 이용해서 달성하는 가장 쉬운 방법은 아마도 진행하신 것 처럼 전체 화면을 비트맵으로 저장한 후, 드래깅 하는 영역을 Alpha 값을 적절히 줘서 반투명으로 가득한 박스를 그리는 방법인것 같습니다. 드래깅 중에는 저장한 비트맵을 이용해 영역을 복구해주면, 원하는 결과가 나올 것 같네요.
이 때 갱신되어야 할 영역만 복구하는게 핵심이 될 것 같습니다. 이렇게 구현한다면 상당히 빠른 속도로 영역지정 효과를 만들 수 있을 것입니다.
2개의 좋아요
선택영역을 Control로 구현하는것도 괜찮은 전략 같네요. 그러니까 전체 캡쳐한 것을 스타일 없는 폼의 배경으로 그리고 컨트롤로 선택영역을 처리한다면 쉽게 구현이 될 것 같습니다. 도움이 되게 간단히 샘플 만들어 볼께요
2개의 좋아요
대략 이런 느낌으로…

public partial class Form1 : Form
{
private Image capture;
//private Selector selector;
private bool isDrag;
private Rectangle selectRect;
private Brush darkBrush = new SolidBrush(Color.FromArgb(150, Color.Black));
public Form1()
{
InitializeComponent();
capture = (Bitmap)Image.FromFile(@"Images\capture.png");
}
protected override void OnMouseDown(MouseEventArgs e)
{
if (isDrag == false)
{
Invalidate(selectRect);
Refresh();
selectRect.Location = e.Location;
selectRect.Size = new Size(0, 0);
isDrag = true;
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (isDrag == true)
{
//selector.Size = new Size(e.X - selector.Location.X, e.Y - selector.Location.Y);
Invalidate(selectRect);
selectRect.Size = new Size(e.X - selectRect.Location.X, e.Y - selectRect.Location.Y);
Invalidate(selectRect);
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
if (isDrag == true)
{
Refresh();
isDrag = false;
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
}
protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
g.DrawImage(capture, 0, 0);
g.FillRectangle(darkBrush, ClientRectangle);
if (isDrag == true)
{
g.DrawImage(capture, selectRect.X, selectRect.Y, selectRect, GraphicsUnit.Pixel);
g.DrawRectangle(Pens.White, selectRect.X, selectRect.Y, selectRect.Width - 1, selectRect.Height - 1);
}
}
}
2개의 좋아요
Resion을 이용하면 성능을 좀 더 개선할 수 있어요
2개의 좋아요
소스코드에서 Refresh()
가 아닌 Update()
입니다.
2개의 좋아요
아래와 같이 바꾸면 드래깅 속도가 빨라집니다.
※ 참고로 Form
은 DoubleBuffered = true
로 해야 깜빡임 없이 빠르게 표현됩니다.
※ 최종적으로 OnMouseMove
의 Invalidate
영역을 selectRect
가 아닌 변화된 가로, 세로의 딱 그 영역만 두번 Invalidate
하면 더 빨라지겠죠.
protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
g.DrawImage(capture, 0, 0);
if (isDrag == true)
{
g.DrawRectangle(Pens.White, selectRect.X, selectRect.Y, selectRect.Width - 1, selectRect.Height - 1);
g.ExcludeClip(selectRect);
}
g.FillRectangle(darkBrush, ClientRectangle);
//if (isDrag == true)
//{
// g.DrawImage(capture, selectRect.X, selectRect.Y, selectRect, GraphicsUnit.Pixel);
// g.DrawRectangle(Pens.White, selectRect.X, selectRect.Y, selectRect.Width - 1, selectRect.Height - 1);
//}
}
2개의 좋아요
너무 성의 있게 답변해 주셔서 감사드립니다!!!
한번 적용 해보겠습니다!!! (
_
)
2개의 좋아요
네 성의있게 질문해주셔서 거기에 맞는 ^^ 답변드렸습니다. 앞으로 많은 활동 부탁드리고요. 유용한 정보 있으시면 많이 올려주세요.
4개의 좋아요
@Arkingco 환영합니다!
@dimohy 저도 WPF에서 적용해보고 싶은 기능이었는데 감사합니다 