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 를 사용했네요! ㅎ …ㅠ

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

4개의 좋아요

옙~ㅂ~

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

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

4개의 좋아요

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

7개의 좋아요