C#에서 마우스 주위를 화면에 실시간으로 띄우는 방법

안녕하세요. 저는 C# 프로그램에 마우스 포인터를 중심으로 반경 한 100px정도를 화면에 실시간으로 나타내고 싶은데 어떤 방법을 사용해야 하나요?
image
요런식으로 만들고 싶습니다

좋아요 2

카테고리를 WPF Q&A로 변경하였습니다. 혹시 WPF가 아니라면 말씀 주세요.

좋아요 2

조금 더 구체적으로 질문 주시면 답변에 도움이 될 것 같은데요,

  1. 사용하는 UI 프레임워크
  2. 마우스 커서 위치 캡쳐에 대한 질문인지?
  3. 화면 캡쳐 방법에 대한 질문인지?

Mouse.Capture()를 이용하면 테두리 안에 없어도 마우스 위치에 대한 이벤트를 수신할 수 있고요, 화면 캡쳐 관련된 자료는 검색을 통해 충분히 찾으실 수 있어요.

좋아요 2

Winform에서 color picker앱을 만들고 싶은데 마우스를 움직일 때 마우스 를 중심으로 화면을 배율해서 panel이나 picturebox에 띄우고 싶습니다. 캡처보다는 계속 캡처를 해서 갱신을 한다고 할까요?

좋아요 2

Graphics에서 제공하는 CopyFromScreen메소드가 있습니다. 이것을 통해 마우스 커서 이동 시 이벤트를 잡아 그 위치의 영역을 캡쳐하면 되는데요, 한번 해보고 잘 안되면 샘플 코드 만들어서 공유할께요.

좋아요 3

간단하게 대충 구현은 해봤는데

원하시는게 이런게 맞는건가요?

test

맞으시다면 코드 공유하겠습니다.

좋아요 5

넵 맞습니다! 감사합니다!!

좋아요 2

감사합니다!!

좋아요 2

엇 저도 이 메소드 생각했는데 CopyFromScreen 이네요

좋아요 3

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);
}
좋아요 5

^^; @aroooong 님도 답글을 주셨네요.
저는 윈폼 버젼으로 만들어봤습니다.

image

소스코드

윈폼에서 윈도 밖의 마우스 이벤트 수신이 안되어서 라이브러리를 이용했습니다. 참고 바래요

좋아요 5

정말 감사합니다!!

좋아요 2

감사합니다!

좋아요 2

오우 굿! 입니당 ㅋㅅㅋ/

근데 한 가지 핥작핥짝 해보자면, Task 내부에서 async / await 을 사용할 경우
TaskCreationOptions.LongRunning 요 인자의 효과가 거의 없게 됩니닷 =ㅂ=;;

처음 호출해서 await 을 만나기 전까지만 별도의 스레드에서 동작하고, 그 이후부터는 지정된SynchronizationContextPost() 를 호출하게 되지요.

근데 지금 여기서 Task 를 생성할 때 별도의 SychronizationContext 를 할당하지 않았기 때문에
처음 await 이전까지만 별도의 스레드에서 동작하고
await Task.Delay(50); 이후 반복부터는 매번 스레드풀에서 실행되니까
사실상 처음 호출로 별도의 스레드에서 진입하는 것을 제외하면
TaskCreationOptions.LongRunning 을 사용하지 않는 것과 큰 차이가 없어집니닷 ㅇㅅㅇ/

여기서 그렇게 중요한 건 아니구욤…
그냥 그렇다구욜 ㅋㅅㅋ

(틀린 내용 있으면 지적질 해주세용 ~ㅁ~)

좋아요 5

네 맞는 답변 해주셨습니다 ㅎ

스레드풀 사용 하지 않으려고 LongRunning 옵션을 주어놓고서

생각없이 그냥 await Task.Delay 를 사용했네요! ㅎ …ㅠ

다른 분들에게도 도움될것 같습니다
답변 감사합니다.

좋아요 3

옙~ㅂ~

아, 그리고 추가로 혹시나 단일 스레드로 async/await 을 사용하고 싶다면
별도의 SynchronizationContext 를 만들어서 Task 내부에서 할당하면 됩니당. ㅇㅅㅇ/

뭐… 사실 이 본문과는 상관없는 주제라…
그냥 지나가셔도 괜춘하긴해욤 ~ㅁ~/

좋아요 3

네 말씀하시는거 관련해서는 아주 예전에 포스팅 하신 글 봤었습니다.

좋아요 6