안녕하세요. 저는 C# 프로그램에 마우스 포인터를 중심으로 반경 한 100px정도를 화면에 실시간으로 나타내고 싶은데 어떤 방법을 사용해야 하나요?
요런식으로 만들고 싶습니다
카테고리를 WPF Q&A로 변경하였습니다. 혹시 WPF가 아니라면 말씀 주세요.
조금 더 구체적으로 질문 주시면 답변에 도움이 될 것 같은데요,
- 사용하는 UI 프레임워크
- 마우스 커서 위치 캡쳐에 대한 질문인지?
- 화면 캡쳐 방법에 대한 질문인지?
Mouse.Capture()
를 이용하면 테두리 안에 없어도 마우스 위치에 대한 이벤트를 수신할 수 있고요, 화면 캡쳐 관련된 자료는 검색을 통해 충분히 찾으실 수 있어요.
Winform에서 color picker앱을 만들고 싶은데 마우스를 움직일 때 마우스 를 중심으로 화면을 배율해서 panel이나 picturebox에 띄우고 싶습니다. 캡처보다는 계속 캡처를 해서 갱신을 한다고 할까요?
Graphics에서 제공하는 CopyFromScreen메소드가 있습니다. 이것을 통해 마우스 커서 이동 시 이벤트를 잡아 그 위치의 영역을 캡쳐하면 되는데요, 한번 해보고 잘 안되면 샘플 코드 만들어서 공유할께요.
간단하게 대충 구현은 해봤는데
원하시는게 이런게 맞는건가요?
맞으시다면 코드 공유하겠습니다.
넵 맞습니다! 감사합니다!!
감사합니다!!
엇 저도 이 메소드 생각했는데 CopyFromScreen 이네요
wpf인데 윈폼도 똑같습니다.
마우스 포인트의 정중앙 부분 계산, 멀티 모니터 등등 좌표계 처리는 추가적으로 필요할 수 도 있을 것 같습니다.
단순 샘플로 해본거라 실무로 사용하기엔 추가 보강 작업이 더 필요 할 듯 합니다.
또한 제 기억으론 단순 CopyFromScreen 화면 캡쳐로는 DX로 직접 렌더링 되는 게임이나 영상 화면은 아예 캡쳐가 안되었던 것 같구요
일단 코드는 다음과 같이 해봤습니다.
[xaml]
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Image x:Name="xImg" Grid.Row="0" />
<Button Grid.Row="1" Content="Start" Click="Button_Click"/>
</Grid>
[cs]
private BitmapImage Capture(System.Drawing.Point mousePoint)
{
Bitmap bitmap = new Bitmap(50, 50, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(bitmap))
{
int currPosXOnCenter = (int)mousePoint.X - 25;
int currPosyOnCenter = (int)mousePoint.Y - 25;
g.CopyFromScreen(currPosXOnCenter <= 0 ? 0 : currPosXOnCenter, currPosyOnCenter <= 0 ? 0 : currPosyOnCenter, 0, 0, bitmap.Size);
//g.CopyFromScreen(0, 0, 0, 0, bitmap.Size);
using (MemoryStream memory = new MemoryStream())
{
bitmap.Save(memory, ImageFormat.Bmp);
memory.Position = 0;
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
return bitmapImage;
}
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Task captureTask = Task.Factory.StartNew(async () =>
{
while (true)
{
this.xImg.Dispatcher.BeginInvoke(new Action(() =>
{
this.xImg.Source = this.Capture(System.Windows.Forms.Cursor.Position);
}));
await Task.Delay(50);
}
}, TaskCreationOptions.LongRunning);
}
^^; @aroooong 님도 답글을 주셨네요.
저는 윈폼 버젼으로 만들어봤습니다.
윈폼에서 윈도 밖의 마우스 이벤트 수신이 안되어서 라이브러리를 이용했습니다. 참고 바래요
정말 감사합니다!!
감사합니다!
오우 굿! 입니당 ㅋㅅㅋ/
근데 한 가지 핥작핥짝 해보자면, Task 내부에서 async / await 을 사용할 경우
TaskCreationOptions.LongRunning
요 인자의 효과가 거의 없게 됩니닷 =ㅂ=;;
처음 호출해서 await 을 만나기 전까지만 별도의 스레드에서 동작하고, 그 이후부터는 지정된SynchronizationContext
에 Post()
를 호출하게 되지요.
근데 지금 여기서 Task 를 생성할 때 별도의 SychronizationContext 를 할당하지 않았기 때문에
처음 await 이전까지만 별도의 스레드에서 동작하고
await Task.Delay(50);
이후 반복부터는 매번 스레드풀에서 실행되니까
사실상 처음 호출로 별도의 스레드에서 진입하는 것을 제외하면
TaskCreationOptions.LongRunning 을 사용하지 않는 것과 큰 차이가 없어집니닷 ㅇㅅㅇ/
여기서 그렇게 중요한 건 아니구욤…
그냥 그렇다구욜 ㅋㅅㅋ
(틀린 내용 있으면 지적질 해주세용 ~ㅁ~)
네 맞는 답변 해주셨습니다 ㅎ
스레드풀 사용 하지 않으려고 LongRunning 옵션을 주어놓고서
생각없이 그냥 await Task.Delay 를 사용했네요! ㅎ …ㅠ
다른 분들에게도 도움될것 같습니다
답변 감사합니다.
옙~ㅂ~
아, 그리고 추가로 혹시나 단일 스레드로 async/await 을 사용하고 싶다면
별도의 SynchronizationContext 를 만들어서 Task 내부에서 할당하면 됩니당. ㅇㅅㅇ/
뭐… 사실 이 본문과는 상관없는 주제라…
그냥 지나가셔도 괜춘하긴해욤 ~ㅁ~/
네 말씀하시는거 관련해서는 아주 예전에 포스팅 하신 글 봤었습니다.