반응형

아래 링크의 프로그램과 비슷하지만 바탕화면(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
:
반응형

2021.11.29 - [C#] - C# Desktop Capture and Image Display Program - 바탕화면 캡쳐 & 이미지 출력 프로그램

 

바탕화면에 이미지를 출력하는 크리스마스 프로그램 예제.

 

폼, 버튼, 링크 레이블등을 적당히 배치하고 리소스를 등록한다.

 

Images.zip
2.28MB

폼에는

FormBorderStyle - None

ShowInTaskBar - False

TopMost - True

등의 조건을 준다.

 

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
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
    {
        [DllImport("User32.dll")]
        public static extern IntPtr GetDC(IntPtr hwnd);
 
        [DllImport("user32.dll")]
        public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
 
        // 바탕화면 refresh
        [DllImport("Shell32.dll")]
        private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
 
        int screenWidth;
        int screenHeight;
 
        IntPtr desktopPtr;
 
        // 이미지 파일은 화면과 해상도가 달라서 작거나 크게 표시될 수 있다.
        // Image로 받지 말고 비트맵으로 변환해 사용하면 된다.
        Bitmap tree;                
        Bitmap leftTop;
        Bitmap rightTop;
        Bitmap rightDeer;
        Bitmap cane;
        Bitmap bulb;
        Bitmap snowMan;
        Bitmap merry;
 
        public Form1()
        {
            InitializeComponent();
 
            screenWidth = Screen.PrimaryScreen.Bounds.Width;
            screenHeight = Screen.PrimaryScreen.Bounds.Height;
 
            desktopPtr = GetDC(IntPtr.Zero);
 
            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);
        }
 
        ~Form1()
        {
            ReleaseDC(IntPtr.Zero, desktopPtr);
        }
        
        private void Form1_Load(object sender, EventArgs e)
        {
            // 폼의 시작 위치를 생성자에서 설정하면 크기가 줄어드는 등 비정상적으로 동작한다.
            StartPosition = FormStartPosition.Manual;
            Location = new Point(screenWidth - Size.Width, screenHeight - Size.Height - 40);
 
            // 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;
 
            // 타이머를 작동시키면 반투명 이미지 부분이 계속 진해진다. 필요하면 작동시키자.
            //timer1.Enabled = true;
 
            SoundPlayer p = new SoundPlayer();
            p.Stream = Properties.Resources.Song;
            p.Play();
            
            using (Graphics g = Graphics.FromHdc(desktopPtr))
            {
                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.R:
                    Reload();
                    break;
 
                case Keys.H:
                    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)
        {
            Reload();
        }
        private void Reload()
        {
            using (Graphics g = Graphics.FromHdc(desktopPtr))
            {
                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 timer1_Tick(object sender, EventArgs e)
        {
            using (Graphics g = Graphics.FromHdc(desktopPtr))
            {
                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_FormClosing(object sender, FormClosingEventArgs e)
        {
            // 바탕화면 refresh
            SHChangeNotify(0x80000000x1000IntPtr.Zero, IntPtr.Zero);
        }
 
        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            linkLabel1.LinkVisited = true;
            System.Diagnostics.Process.Start("https://s-engineer.tistory.com/");
        }
    }
}
 

 

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

 

실행하면 바탕화면에 이미지가 표시된다.

 

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

초등학교 시절이었나? 그때쯤 크리스마스 트리를 두어 번 만들어 보고 그 이후로는 한 번도 만들어 본적이 없는거 같다. 어차피 크리스마스가 내게 의미 있는 날도 아니고, 선물을 주고 받거나 뭔가 의미 있는걸 하는 사람은 영화에만 존재했으니 별 상관 없었던거 같다. 어쩌면 우리 가족의 그런 분위기가 날 그렇게 생각하게 만들었을지도 모른다는 생각도 든다.



그러다 몇년 전 부터 연말쯤 되면 크리스마스 트리가 생각나곤 했다. 거실에 두고 온 가족이 볼 만큼 큰거 말고 그냥 내방 구석에 한 자리 잡고 연말을 같이 보낼 작고 귀여운 트리.


올해는 무슨 생각이었는지 바로 검색을 시작 했다. 생각보다 많은 종류의 트리와 장식, 전구들.. 사실 이젠 더 이상 전구가 아닌거 같다. 대부분 LED를 이용한 저전력, 저발열의 제품들이 많이 나와 있었다. 분명 내 기억엔 시간이 지나면 뜨거워 지는 작은 전구들이었는데.. 어쨌든 맘에 드는걸 하나 발견 했고 주문 했다.


높이가 60cm 라고 했으니 그쯤 되는 상자에 담겨 온 듯 하다.


나뭇가지들은 모두 위로 말려있고 장식과 전구는 따로 포장, 지지대 3개는 분리된채 상자에 들어 있었다. 별거 없어 보이지만 있어야 할 건 다 있었다.



사방에서 보는걸 감안하고 장식을 달면 부족할거 같아 한쪽 방향에서만 볼 수 있게 트리를 배치하기로 하고 장식들을 한쪽으로 적당히 몰아 주었다. 졸려서 전구도 대충 빨리 감아주고 USB를 컴퓨터에 연결 했다. 가정용 220V 전원을 사용하는게 아닌 컴퓨터 USB 포트에서 작동 한다. 컴퓨터용 USB포트는 보통 500mA정도의 전류가 나오는데 충분한가 보다.


불을 껐다. 생각보다 굉장히 밝은 전구에 살짝 당황했다.


이런건 역시 동영상으로 확인해야 제대로 알 수 있다. 한밤중에 갑자기 만든 크리스마스 트리라 신경써서 장식을 배치하고 예쁘게 전구를 감지는 못했지만 꽤 괜찮은 모양이 나온다.


저렴한 가격에 간단한 장식부터 전구까지 모두 포함이면 나쁘지 않은 선택 이었던거 같다. 더 싸고 좋은게 있을지 모르겠지만, 사실 잘산거 같다고 생각하는 중이다.


정말 오랜만에 만들어본 크리스마스 트리. 나중에 유튜브 영상 찍을때 배경으로 사용할 생각부터 드는 난 이제 진정한 유튜버.


반응형
Posted by J-sean
: