본문 바로가기
C#/C# Windows Form

C# 비활성창 스크린샷

by TcTT 2017. 11. 10.
반응형

C# 비활성창 스크린샷


매크로를 만들기위해서 지금 특정창의 이미지를 가져오는게 기초가됩니다..

오토핫키가 보편화된이유가 특정창의 이미지를가지고와 찾고자하는 이미지와 비교하는방법이

비교적 쉽기 때문에 많이 보편화된거같습니다.


C#으로 이미지서치를위해선 오토핫키dll 또는 오토잇dll을 사용하거나, 다른 라이브러리나 직접 구현하는방법등 다양한 방법이있습니다.

제가 앞으로 포스팅할 방식은 OpencvSharp 라이브러리 참조 방식과 AForge 라이브러리 참조 방식이있습니다.

두 라이브러리다 다양한 함수가 내장되어있어 편리하게 사용할 수 있습니다.


OpencvSharp 은 C기반인 Opencv를 C#에서 사용할 수 있도록 컨버팅한거고,

AForge는 C#에서 사용할 수 있도록 작성된 라이브러리입니다.


오늘은 우선 특정창의 이미지를 얻어오는것부터 시작합니다!

우선 이미지를 가져온 결과입니다.. 실제 스크린샷찍을 계산기는 제 블로그 글쓰기와 프로그램으로인해 우측, 하단이 짤려보이는데,

프로그램을통해 얻어온 이미지는 계산기 전체의 이미지가 짤린부분 없이 잘 나오죠!

       


특정 클라이언트에 이미지를 얻어오기위해 윈도우에서 제공하는 라이브러리를 사용합니다.

user32.dll  : https://en.wikipedia.org/wiki/Windows_USER

gdi32.dll  :  https://en.wikipedia.org/wiki/Graphics_Device_Interface


user32 (Windows USER) : 특정창을 검색 및 차후에 포스팅할 키보드마우스 후킹, 데이터 전송등에 쓰일예정입니다.

위에있는 url에서 보시면 제가 적어둔 설명 외 다양한 기능이 있습니다.

gdi32 (Graphics Device Interface) : 여기선 특정창이 gdi를통해 그려지면 그 창의 크기등을 가지고오기위해 사용합니다.

특정창의 크기를 가져오면 user32에서 그창의 크기만큼 이미지를 그려주는형식으로 구현했습니다..


분명 더 좋은 방식이 있을거같은데 이부분은 천천히 생각을 해봅시다!



사용하는 함수 목록입니다.

user32.dll

FindWindow (특정창이 프로세스 상에 있는지 확인)

PrintWindow (프로세스에 특정창이 있으면 그화면 프린트)

GetWindowRgn (특정창의 크기 가져오기)


gdi32.dll

CreateRectRgn (그래픽상의 크기 가져오기)


뭔가 설명이좀 이상합니다..

PrintWindow 상의 파라미터를 변경해주면 DirectX 렌더링 화면을 캡쳐해올 수 있습니다.



소스입니다.

1. 버튼을 클릭하여 textBox1 에있는 클라이언트이름으로 검색합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
        private void button2_Click(object sender, EventArgs e)
        {
            Clienthwnd = Client_Connection(textBox1.Text);
            if (Clienthwnd.Equals(0))
            {
                MessageBox.Show("클라이언트 검색 실패");
                return;
            }
            else
            {
                MessageBox.Show("클라이언트 검색 성공");
                button1.Enabled = true;
            }
        }
cs


2. 검색에 성공했다면 가져온 핸들값으로 연결합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        public IntPtr Client_Connection(string clientname)
        {
            IntPtr iResulthwnd = new IntPtr();
 
            int inthwnd = FindWindow(null, clientname);
            if (inthwnd == 0)
            {
                iResulthwnd = new IntPtr(inthwnd);
            }
            else
            {
                iResulthwnd = new IntPtr(inthwnd);
            }
            return iResulthwnd;
        }

cs


3.연결 후 연결된 핸들의 클라이언트를 이미지화해서 저장합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
   private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                Rectangle rc = Rectangle.Empty;
                Graphics gfxWin = Graphics.FromHwnd(Clienthwnd);
                rc = Rectangle.Round(gfxWin.VisibleClipBounds);
 
                Bitmap bmp = new Bitmap(rc.Width, rc.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                Graphics gfxBmp = Graphics.FromImage(bmp);
                IntPtr hdcBitmap = gfxBmp.GetHdc();
                bool succeeded = PrintWindow(Clienthwnd, hdcBitmap, 3);
 
                gfxBmp.ReleaseHdc(hdcBitmap);
                if (!succeeded)
                {
                    gfxBmp.FillRectangle(new SolidBrush(Color.Gray), new Rectangle(System.Drawing.Point.Empty, bmp.Size));
                }
                IntPtr hRgn = CreateRectRgn(0000);
                GetWindowRgn(Clienthwnd, hRgn);
                Region region = Region.FromHrgn(hRgn);
                if (!region.IsEmpty(gfxBmp))
                {
                    gfxBmp.ExcludeClip(region);
                    gfxBmp.Clear(Color.Transparent);
                }
 
                System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(Application.StartupPath + "//images//");
                if (di.Exists)
                {
                }
                else
                {
                    di.Create();
                }
                gfxBmp.Dispose();
                bmp.Save(Application.StartupPath + "//images//" + System.DateTime.Now.ToString("yyyy년MM월dd일 hh시 mm분 ss초"+ ".bmp"System.Drawing.Imaging.ImageFormat.Bmp);
                MessageBox.Show("스냅샷 찰영 완료");
            }
            catch (Exception err)
            {
                MessageBox.Show("스냅샷 찰영 오류");
            }
        }
cs


천천히 읽어보시고 왜 이런곳에 이걸썻을까 조금만 고민해본다면 어렵지않게 구현 할 수 있습니다.


데모 프로그램 :

ClientSearch.zip



참고한 블로그 : http://lesomnus.tistory.com/10

반응형

'C# > C# Windows Form' 카테고리의 다른 글

C# mp4 Play  (0) 2019.12.20
C# 무료 스프레드 툴  (0) 2018.06.10
C# 마방진  (0) 2017.10.13
C# string To DateTime  (2) 2017.09.18
C# 하드번호  (0) 2017.08.09