반응형

간단히 화면을 캡쳐해 보자.

 

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
using System.Windows.Forms;
using System.Drawing;
 
namespace CS
{
    class Program
    {
        static void Main(string[] args)
        {
            Bitmap screen = GetScreen();
            screen.Save("screen.png"System.Drawing.Imaging.ImageFormat.Png);
        }
 
        static Bitmap GetScreen()
        {
            Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            Graphics g = Graphics.FromImage(bitmap);
            g.CopyFromScreen(0000, bitmap.Size);
            g.Dispose();
 
            return bitmap;
        }
    }
}
 

 

소스를 입력하고 빌드한다.

 

실행하면 Output 폴더에 screen.png 파일이 생성된다.

 

반응형
Posted by J-sean
:
반응형

아래 링크의 프로그램과 비슷하지만 바탕화면(Desktop)이 아닌 폼에 이미지를 출력해 바탕화면에 출력한 것처럼 보이는 프로그램을 만들어 보자.

 

2021.11.27 - [C#] - C# Desktop Image Display Program - 바탕화면 이미지 출력 프로그램

 

폼과 버튼을 적당히 배치한다.

폼에는
FormBorderStyle - None
ShowInTaskBar - False
TopMost - True
등의 조건을 준다.

 

이미지, 음악등 리소스를 추가한다.

 

Images.zip
2.32MB

 

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
using System.Runtime.InteropServices;
using System.Media;
 
namespace Christmas
{
    public partial class Form1 : Form
    {
        int screenWidth;
        int screenHeight;
 
        Random R;   // 눈 위치 지정
        int snowflakeCount;
 
        // 대부분 이미지 파일은 화면과 해상도가 달라서 작거나 크게 표시된다.
        // Image로 받지 말고 비트맵으로 변환해 사용하면 된다.
        Bitmap[] snowflakes;
        Bitmap tree;                
        Bitmap leftTop;
        Bitmap rightTop;
        Bitmap rightDeer;
        Bitmap cane;
        Bitmap bulb;
        Bitmap snowMan;
        Bitmap merry;
        Bitmap screen;  // 프로그램 시작 전 전체 화면
        Bitmap buffer;  // 더블 버퍼링
 
        public Form1()
        {
            InitializeComponent();
 
            screenWidth = Screen.PrimaryScreen.Bounds.Width;
            screenHeight = Screen.PrimaryScreen.Bounds.Height;
 
            R = new Random();
            snowflakeCount = 0;
 
            snowflakes = new Bitmap[] { Properties.Resources.snowflake1, Properties.Resources.snowflake2,
                Properties.Resources.snowflake3, Properties.Resources.snowflake4 };
            tree = new Bitmap(Properties.Resources.tree1);
            rightDeer = new Bitmap(Properties.Resources.RightDeer);
            leftTop = new Bitmap(Properties.Resources.LeftTop);
            rightTop = new Bitmap(Properties.Resources.RightTop);
            cane = new Bitmap(Properties.Resources.cane);
            bulb = new Bitmap(Properties.Resources.bulb);
            snowMan = new Bitmap(Properties.Resources.BottomSnowMan);
            merry = new Bitmap(Properties.Resources.Merry);
            screen = ScreenCapture.Capture();
            buffer = new Bitmap(screenWidth, screenHeight);
        }
                
        private void Form1_Load(object sender, EventArgs e)
        {
            // 폼의 시작 위치를 생성자에서 설정하면 크기가 줄어드는 등 비정상적으로 동작한다.
            StartPosition = FormStartPosition.Manual;            
            Location = new Point(00);
            Size = new Size(screenWidth, screenHeight);
 
            button1.Location = new Point(screenWidth - button1.Size.Width - 10, screenHeight - button1.Size.Height - button2.Size.Height - 20);
            button2.Location = new Point(screenWidth - button2.Size.Width - 10, screenHeight - button2.Size.Height - 10);
 
            // Gets or sets a value indicating whether the form will receive key events before the event is passed to the control that has focus.
            // true if the form will receive all key events; false if the currently selected control on the form receives key events. The default is false.
            // 키가 눌렸을때 포커스를 갖고 있는 컨트롤보다 폼이 먼저 키 이벤트를 받을 수 있게 한다. 단축키 지정을 위해.
            KeyPreview = true;
 
            // 탭 스탑이 가능하면 포커스된 버튼에 파란색 테두리가 보인다.
            button1.TabStop = false;
            button2.TabStop = false;
 
            // 항상 위.
            TopMost = true;
 
            // 타이머 실행.
            timer1.Enabled = true;
            timer1.Interval = 100;
 
            drawBuffer();
 
            SoundPlayer p = new SoundPlayer();
            p.Stream = Properties.Resources.Song;
            p.Play();            
        }
 
        private void drawBuffer()
        {
            using (Graphics G = Graphics.FromImage(buffer))
            {
                G.DrawImage(screen, 00);
                G.DrawImage(bulb, screenWidth - rightDeer.Width - bulb.Width, 0);
                G.DrawImage(leftTop, 00);
                G.DrawImage(rightTop, screenWidth - rightTop.Width, 0);
                G.DrawImage(rightDeer, screenWidth - rightDeer.Width, (screenHeight - rightDeer.Height) / 2);
                G.DrawImage(cane, cane.Width / 4, (screenHeight - cane.Height) / 2);
                G.DrawImage(snowMan, 0, screenHeight - snowMan.Height);
                G.DrawImage(merry, screenWidth - merry.Width, screenHeight - merry.Height - 40);
                G.DrawImage(tree, (screenWidth - tree.Width) / 240);
            }
        }
 
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Escape:
 
                case Keys.Q:
                    Close();
                    break;
 
                case Keys.B:
                    TopMost = false;
                    System.Diagnostics.Process.Start("https://s-engineer.tistory.com/");
                    break;
 
                default:
                    break;
            }
        }
        
        private void button1_Click(object sender, EventArgs e)
        {
            Close();
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            TopMost = false;
            System.Diagnostics.Process.Start("https://s-engineer.tistory.com/");
        }
 
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            if (buffer != null)
            {
                e.Graphics.DrawImage(buffer, 00);
            }
        }
 
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            // 전체 화면에 대해 더블 버퍼링을 하므로 배경화면을 다시 그리지 않도록 이 함수를 빈 함수로 재정의.
            //base.OnPaintBackground(e);
        }
 
        private void timer1_Tick(object sender, EventArgs e)
        {
            using (Graphics G = CreateGraphics())
            {
                G.DrawImage(snowflakes[R.Next(4)], R.Next(screenWidth), R.Next(screenHeight));
                snowflakeCount++;
            }
 
            // snowflake를 처음 100개 까지만 빨리 그리기
            if (snowflakeCount > 100 && timer1.Interval != 1000)
            {
                timer1.Interval = 1000;
            }
        }
    }
 
    public class ScreenCapture
    {
        [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
        private static extern IntPtr GetDC(IntPtr hWnd);
 
        [DllImport("user32.dll", ExactSpelling = true)]
        private static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
 
        [DllImport("gdi32.dll", ExactSpelling = true)]
        private static extern IntPtr BitBlt(IntPtr hDestDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);
 
        [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
        private static extern IntPtr GetDesktopWindow();
 
        public static Bitmap Capture()
        {
            int screenWidth = Screen.PrimaryScreen.Bounds.Width;
            int screenHeight = Screen.PrimaryScreen.Bounds.Height;
 
            Bitmap screenBmp = new Bitmap(screenWidth, screenHeight);
            Graphics g = Graphics.FromImage(screenBmp);
 
            IntPtr desktopDC = GetDC(GetDesktopWindow());
            IntPtr hDC = g.GetHdc();
 
            BitBlt(hDC, 00, screenWidth, screenHeight, desktopDC, 000x00CC0020);    //SRCCOPY (DWORD)0x00CC0020
 
            ReleaseDC(GetDesktopWindow(), desktopDC);
            g.ReleaseHdc(hDC);
            g.Dispose();
 
            return screenBmp;
        }
    }
}
 

 

소스를 입력하고 빌드한다.

 

 

실행하면 현재 화면이 캡쳐되어 리소스들과 함께 표시된다.

 

2021.12.23 - [C#] - C# Desktop(Screen) Capture - 스크린 캡쳐

 

반응형
Posted by J-sean
:
반응형

바탕화면에 이미지를 출력하고 움직여 보자.

 

폼과 버튼을 적당히 배치한다.

 

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
using System.Runtime.InteropServices;
 
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
        private static extern IntPtr GetDC(IntPtr hWnd);
 
        [DllImport("user32.dll", ExactSpelling = true)]
        private static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            int step = 1;   // 이동 스텝
 
            Rectangle targetRect = new Rectangle(100150400400);   // 표시할 그림 사이즈(Horizontal: 100~499(400) pixel, Vertical: 150~549(400) pixel) 
            Point outPoint = new Point(500300);   // 모니터의 표시 위치(x, y)
 
            //Image img = Image.FromFile("Barbara.jpg");  // Resolution Horizontal: 300, Vertical: 300  
            // 이렇게 하면 이미지 파일과 아래 buffer 비트맵의 해상도(96, 96)가 달라서 (사이즈가) 제대로 표시되지 않는다.
            Bitmap img = new Bitmap(Image.FromFile("Barbara.jpg")); // Resolution Horizontal: 96, Vertical: 96
            Bitmap scr = ScreenCapture.Capture();
            Bitmap buffer = new Bitmap(targetRect.Width + step, targetRect.Height + step);
            IntPtr desktopDC = GetDC(IntPtr.Zero);
 
            Graphics dG = Graphics.FromHdc(desktopDC);
            Graphics bG = Graphics.FromImage(buffer);
            
            for (int i = 0, j = 0; i < 100; i += step, j += step)
            {
                bG.DrawImage(scr, 00new Rectangle(outPoint.X + i, outPoint.Y + j, targetRect.Width + step , targetRect.Height + step ), GraphicsUnit.Pixel);
                bG.DrawImage(img, step, step, targetRect, GraphicsUnit.Pixel);                
                dG.DrawImage(buffer, outPoint.X + i, outPoint.Y + j);
            }
 
            for (int i = 100, j = 100; i > 0; i -= step, j -= step)
            {
                bG.DrawImage(scr, 00new Rectangle(outPoint.X + i, outPoint.Y + j, targetRect.Width + step, targetRect.Height + step), GraphicsUnit.Pixel);
                bG.DrawImage(img, 00, targetRect, GraphicsUnit.Pixel);
                dG.DrawImage(buffer, outPoint.X + i, outPoint.Y + j);
            }
 
            dG.Dispose();
            bG.Dispose();
            ReleaseDC(IntPtr.Zero, desktopDC);
        }
    }
 
    public class ScreenCapture
    {
        [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
        private static extern IntPtr GetDC(IntPtr hWnd);
 
        [DllImport("user32.dll", ExactSpelling = true)]
        private static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
 
        [DllImport("gdi32.dll", ExactSpelling = true)]
        private static extern IntPtr BitBlt(IntPtr hDestDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);
 
        [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
        private static extern IntPtr GetDesktopWindow();
 
        public static Bitmap Capture()
        {
            int screenWidth = Screen.PrimaryScreen.Bounds.Width;
            int screenHeight = Screen.PrimaryScreen.Bounds.Height;
 
            Bitmap screenBmp = new Bitmap(screenWidth, screenHeight);
            Graphics g = Graphics.FromImage(screenBmp);
 
            IntPtr desktopDC = GetDC(GetDesktopWindow());
            IntPtr hDC = g.GetHdc();
 
            BitBlt(hDC, 00, screenWidth, screenHeight, desktopDC, 000x00CC0020);    //SRCCOPY (DWORD)0x00CC0020
 
            ReleaseDC(GetDesktopWindow(), desktopDC);
            g.ReleaseHdc(hDC);
            g.Dispose();
 
            return screenBmp;
        }
    }
}
 

 

소스를 입력하고 빌드한다.

Barbara.jpg
0.05MB

 

실행하고 버튼을 클릭한다.

 

지정된 위치에 이미지가 출력되고 움직인다.

 

반응형
Posted by J-sean
:
반응형

C#으로 스크린을 캡쳐 해 보자.

 

폼과 버튼을 적당히 배치한다.

 

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
using System.Runtime.InteropServices;
 
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();            
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            Bitmap bm = ScreenCapture.Capture();
 
            Graphics g = CreateGraphics();
            g.DrawImage(bm, 1040new Rectangle(100100450250), GraphicsUnit.Pixel);
            g.Dispose();
        }
    }
 
    public class ScreenCapture
    {
        [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
        private static extern IntPtr GetDC(IntPtr hWnd);
 
        [DllImport("user32.dll", ExactSpelling = true)]
        private static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
 
        [DllImport("gdi32.dll", ExactSpelling = true)]
        private static extern IntPtr BitBlt(IntPtr hDestDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);
 
        [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
        private static extern IntPtr GetDesktopWindow();
 
        public static Bitmap Capture()
        {
            int screenWidth = Screen.PrimaryScreen.Bounds.Width;
            int screenHeight = Screen.PrimaryScreen.Bounds.Height;
 
            Bitmap screenBmp = new Bitmap(screenWidth, screenHeight);
            Graphics g = Graphics.FromImage(screenBmp);
 
            IntPtr desktopDC = GetDC(GetDesktopWindow());
            IntPtr hDC = g.GetHdc();
 
            BitBlt(hDC, 00, screenWidth, screenHeight, desktopDC, 000x00CC0020);    //SRCCOPY (DWORD)0x00CC0020
 
            ReleaseDC(GetDesktopWindow(), desktopDC);
            g.ReleaseHdc(hDC);
            g.Dispose();
 
            return screenBmp;
        }
    }
}
 

 

소스를 입력하고 빌드한다.

 

실행하면 버튼만 하나 나타난다. 클릭하자.

 

지정한 위치의 화면이 캡쳐되어 표시된다.

 

반응형
Posted by J-sean
:
반응형

보통 캡쳐 보드는 저렴한 제품도 10만원 정도이고 비싼건 30만원이 넘어 간다. 하지만 이 제품은 알리 익스프레스에서 배송비 포함 $14.26에 구매 가능 하다.


매뉴얼, 캡쳐 보드, 전원 케이블, USB 케이블이 포함되어 있다.


Specification:

Input & Loop out: 4K 30Hz

Video capture: 1080p 30Hz

HDMI

USB 2.0

Windows, Linux, macOS

VLC, OBS Studio, AMCap, and etc.

https://www.aliexpress.com/item/4001012071298.html?spm=a2g0s.9042311.0.0.35614c4dqqehTp


스트리밍 PC와 연결할 USB 2.0 포트와 Loop out용 Output 포트

(USB 3.0도 판매 한다)



전원 연결용 5VDC 단자와 소스 입력용 Input 포트


케이블 연결 다이어그램


실제 연결 사진


테스트는 영상으로 확인 하자.


반응형
Posted by J-sean
:
반응형

Screen capture with Windows API and OpenCV.


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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <Windows.h>
#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
 
using namespace std;
using namespace cv;
 
class hWnd2Mat
{
public:
    hWnd2Mat(HWND hWindow, float scale = 1);
    virtual ~hWnd2Mat();
    virtual void Read();
    Mat capture;
 
private:
    HWND hWnd;
    HDC hWindowDC, hWindowCompatibleDC;
    int height, width, srcHeight, srcWidth;
    HBITMAP hBitmap;
    BITMAPINFOHEADER bi;
};
 
hWnd2Mat::hWnd2Mat(HWND hWindow, float scale)
{
    hWnd = hWindow;
    hWindowDC = GetDC(hWnd);
    hWindowCompatibleDC = CreateCompatibleDC(hWindowDC);
    SetStretchBltMode(hWindowCompatibleDC, COLORONCOLOR);
 
    RECT windowsize;    // get the height and width of the screen
    GetClientRect(hWnd, &windowsize);
 
    srcHeight = windowsize.bottom;
    srcWidth = windowsize.right;
    height = (int)(windowsize.bottom * scale);
    width = (int)(windowsize.right * scale);
 
    capture.create(height, width, CV_8UC4);
 
    // create a bitmap
    hBitmap = CreateCompatibleBitmap(hWindowDC, width, height);
    bi.biSize = sizeof(BITMAPINFOHEADER);    // http://msdn.microsoft.com/en-us/library/windows/window/dd183402%28v=vs.85%29.aspx
    bi.biWidth = width;
    bi.biHeight = -height;  //this is the line that makes it draw upside down or not
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;
 
    // use the previously created device context with the bitmap
    SelectObject(hWindowCompatibleDC, hBitmap);
};
 
void hWnd2Mat::Read()
{
    // copy from the window device context to the bitmap device context
    StretchBlt(hWindowCompatibleDC, 00, width, height, hWindowDC, 00, srcWidth, srcHeight, SRCCOPY);
    //change SRCCOPY to NOTSRCCOPY for wacky colors!
    GetDIBits(hWindowCompatibleDC, hBitmap, 0, height, capture.data, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
    //copy from hWindowCompatibleDC to hBitmap
};
 
hWnd2Mat::~hWnd2Mat()
{
    DeleteObject(hBitmap);
    DeleteDC(hWindowCompatibleDC);
    ReleaseDC(hWnd, hWindowDC);
};
 
int main()
{
    HWND hWndDesktop = GetDesktopWindow();
    hWnd2Mat desktop(hWndDesktop, 1);    // scale = 1
 
    cout << "Screen capure in 3 seconds." << endl;
    
    for (int i = 3; i > 0; i--)
    {
        cout << i << ".." << endl;
        Sleep(1000);
    }
 
    desktop.Read();
    imshow("Capture", desktop.capture);
 
    waitKey();
 
    return 0;
}



It captures your desktop image in 3 seconds.


반응형
Posted by J-sean
: