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(0, 0);
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, 0, 0);
G.DrawImage(bulb, screenWidth - rightDeer.Width - bulb.Width, 0);
G.DrawImage(leftTop, 0, 0);
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) / 2, 40);
}
}
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, 0, 0);
}
}
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, 0, 0, screenWidth, screenHeight, desktopDC, 0, 0, 0x00CC0020); //SRCCOPY (DWORD)0x00CC0020
ReleaseDC(GetDesktopWindow(), desktopDC);
g.ReleaseHdc(hDC);
g.Dispose();
return screenBmp;
}
}
}