반응형

C# 코드를 난독화 해 보자.

 

Tools - NuGet Package Manager - Manage NuGet Packages for Solution... 선택

 

Browse에서 Obfuscar 검색 후 설치

 

Project - XXX Properties 선택

 

Build Events - Post-build event command line: 에 위와같이 작성한다.

"$(Obfuscar)" obfuscar.xml

 

 

Hello World!를 출력하는 소스를 입력한다.

 

Output 폴더에 obfuscar.xml 파일을 만들고 아래와 같이 작성한다.

 

간단한 obfuscar.xml 파일 내용

더 많은 세팅값은 아래 링크에서 확인할 수 있다.

Configuration

 

프로젝트를 빌드하면 난독화 되지 않은 실행파일과 함께 Obfuscator_Output 폴더가 생성된다.

 

 

Obfuscator_Output 폴더에는 난독화된 실행파일이 생성된다.

 

반응형
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
:
반응형

트레이 아이콘에 간단한 메뉴를 등록해 보자.

 

NotifyIcon, ContextMenuStrip, Timer를 폼에 배치한다.

 

ContextMenuStrip을 위와 같이 편집한다.

 

NotifyIcon의 Properties를 위와 같이 편집한다.

Icon - 원하는 아이콘 선택

ContextMenuStrip - 폼에 배치한 contexMenuStrip1 선택

Visible - 처음 실행 시 보이지 않도록 False

 

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
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;
 
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            timer1.Enabled = true;
            timer1.Interval = 10000;
        }
 
        private void showToolStripMenuItem_Click(object sender, EventArgs e)
        {
            notifyIcon1.Visible = false;
            Show();
        }
 
        private void hideToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Hide 메뉴의 의미는 없다.
            notifyIcon1.Visible = true;
            Hide();
        }
 
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Close()로 종료를 시도하면 Form1_FormClosing() 때문에 종료되지 않는다.
            Application.Exit();
        }
 
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            // 폼의 종료 아이콘 클릭시 종료하지 않고 숨김, 트레이 아이콘 활성화.
            notifyIcon1.Visible = true;
            
            if (e.CloseReason == CloseReason.UserClosing)
            {
                Hide();
                e.Cancel = true;
            }
        }
 
        private void timer1_Tick(object sender, EventArgs e)
        {
            // 타이머 인터벌이 10초 이므로 트레이 아이콘이 활성화 되어 있을때 10초마다 2초간 알림.
            if (notifyIcon1.Visible == true)
            {
                notifyIcon1.ShowBalloonTip(2000"알림""트레이에 숨어 있습니다!!", ToolTipIcon.Info);
            }            
        }
    }
}
 

 

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

 

실행하면 폼만 나타난다. 종료 아이콘(X)을 클릭해 보자.

 

트레이 아이콘이 나타난다.

 

매 10초마다 알림이 나타난다.

 

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

빌드 후 생성될 파일의 아이콘을 바꿔보자.

 

Project - XXX Properties 선택

 

Application - Resources - Icon and manifest - Icon - Browse... 버튼 클릭

 

원하는 아이콘을 선택한다.

 

프로젝트를 빌드하면 생성파일에 아이콘이 적용된다.

 

반응형
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
:
반응형

실행중인 모든 프로세스와 현재 포커스를 갖고 있는 프로세스를 조사하고 각 프로세스의 윈도우 사이즈를 구해 보자.

 

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
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.Diagnostics;
using System.Runtime.InteropServices;
 
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll")]
        private static extern IntPtr FindWindow(string className, string windowName);
        // 이 예제에서는 쓰이지 않았지만 Findwindow()는 아래와 같이 사용하면 된다.
        // IntPtr hwnd = FindWindow(className, windowName);
        // windowName = proc.ProcessName;
        // className = proc.MainWindowTitle;
 
        [DllImport("user32.dll")]
        private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
 
        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();
 
        [DllImport("user32.dll")]
        private static extern int GetWindowRect(IntPtr hWnd, out Rectangle rect);
 
        [DllImport("dwmapi.dll")]
        private static extern int DwmGetWindowAttribute(IntPtr hWnd, int dwAttribute, out Rectangle pvAttribute, int cbAttribute);
        
        public Form1()
        {
            InitializeComponent();
 
            timer1.Interval = 5000// 5초마다 갱신
        }
        
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Process[] processes = Process.GetProcesses();            
            Rectangle rect;
            // GetWindowRect(), DwmGetWindowAttribute()에 의해 rect에는 아래와 같은 값이 들어간다.
            // rect.X = 좌상단 X 좌표
            // rect.Y = 좌상단 T 좌표
            // rect.Width = 우하단 X 좌표 (너비가 아니다)
            // rect.Height = 우하단 Y 좌표 (높이가 아니다)
            int rectangleSize = Marshal.SizeOf(typeof(Rectangle));
            int index;  // Process.GetProcesses()로 조사된 모든 프로세스 중 몇 번째 인지 나타낼 인덱스.
            int row = 0;    // 내용 표시 Y 위치
            string str;
 
            foreach (Process p in processes)
            { 
                // A process has a main window associated with it only if the process has a graphical interface. If the associated process
                // does not have a main window, the MainWindowHandle value is zero. The value is also zero for processes that have been hidden,
                // that is, processes that are not visible in the taskbar. This can be the case for processes that appear as icons in the
                // notification area, at the far right of the taskbar.
                // 테스크 바에 표시되는(보이는) 프로세스만 조사. 윈도우 핸들이 0(IntPtr.Zero)이 아닌 윈도우인데 그렇다고 다 보이는 건 아니다.
                if (p.MainWindowHandle != IntPtr.Zero)
                {
                    index = Array.IndexOf(processes, p); // 비효율적인 배열의 인덱스 가져오기. foreach()말고 for(;;)를 쓰는게 낫다.
                    DwmGetWindowAttribute(p.MainWindowHandle, 9out rect, rectangleSize);
                    // 9 = DWMWA_EXTENDED_FRAME_BOUNDS
                    str = string.Format("[{0}] {1}: ({2}, {3}, {4}, {5})", index, p.ProcessName, rect.X, rect.Y, rect.Width, rect.Height);
                    e.Graphics.DrawString(str, Font, Brushes.Black, 0, row);
                    row += 15;
                }
            }
            
            // 포커스를 갖고 있는 윈도우(Foreground window) 조사
            uint foregroundProcessID = 0;
            IntPtr foregroundHWnd = GetForegroundWindow(); // Get foreground window handle
            uint threadID = GetWindowThreadProcessId(foregroundHWnd, out foregroundProcessID); // Get PID from window handle
            Process foregroundProcess = Process.GetProcessById(Convert.ToInt32(foregroundProcessID)); // Get it as a C# obj.
 
            // 윈도우 사이즈 조사
            DwmGetWindowAttribute(foregroundHWnd, 9out rect, rectangleSize);
            // 9 = DWMWA_EXTENDED_FRAME_BOUNDS            
            str = string.Format("[Foreground] {0}: ({1}, {2}, {3}, {4})", foregroundProcess.ProcessName, rect.X, rect.Y, rect.Width, rect.Height);
            e.Graphics.DrawString(str, Font, Brushes.Black, 0, row);
            row += 30;
 
            // Windows 10 has thin invisible borders on left, right, and bottom, it is used to grip the mouse for resizing.
            // The borders might look like this: 7, 0, 7, 7(left, top, right, bottom)
            // 윈도우 사이즈 조사 시 예전과 같이 GetWindowRect()를 사용하면 보통 7픽셀의 resizing을 위한 테두리가 포함된다.
            e.Graphics.DrawString("[Foreground window with invisible border]", Font, Brushes.Red, 0, row);
            row += 15;
            GetWindowRect(foregroundHWnd, out rect);
            str = string.Format("[Foreground] {0}: ({1}, {2}, {3}, {4})", foregroundProcess.ProcessName, rect.X, rect.Y, rect.Width, rect.Height);
            e.Graphics.DrawString(str, Font, Brushes.Black, 0, row);
        }
 
        private void timer1_Tick(object sender, EventArgs e)
        {
            Invalidate();
        }
    }
}
 

 

소스를 입력하고 실행한다.

 

인덱스를 확인하면 수백개의 프로세스가 실행중임을 알 수 있다.

 

GetWindowRect()로 윈도우 사이즈를 구하면 resizing을 위한 보이지 않는 테두리가 포함 되므로 눈에 보이는 정확한 사이즈는 DwmGetWindowAttribute()로 구하자.

 

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

버튼이나 다른 컨트롤이 있는 폼에서 특정 키를 눌렀을때 원하는 동작을 하게 하기 위해 Form KeyDown 이벤트 핸들러를 작성해도 포커스를 갖고 있는 컨트롤이 먼저 키 이벤트를 처리하기 때문에 원하는 동작을 처리할 수 없다.

 

폼이 먼저 이벤트를 받기 위해서는 KeyPreview 프로퍼티를 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
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;
 
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            //button1.TabStop = false;
            //button2.TabStop = false;
            // TabStop = false로 하면 처음엔 제대로 작동하는거 같지만
            // 버튼을 한 번 클릭하고 나서는 버튼이 계속 포커스를 갖기
            // 때문에 제대로 작동하지 않는다.
 
            // 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;
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Button1");
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Button2");
        }
 
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.F1:
                    MessageBox.Show("F1");
                    break;
 
                default:
                    break;
            }
        }
    }
}
 

 

버튼이 포커스를 갖고 있는 상태에서 F1키를 눌러도 폼이 KeyDown 이벤트를 먼저 처리한다.

 

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

이미지 파일을 어떻게 불러오는지에 따라 해상도가 다르게 적용될 수 있다.

 

Reindeer.png
0.08MB

 

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
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;
 
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Image i = Image.FromFile("Reindeer.png");
            Bitmap b1 = (Bitmap)Bitmap.FromFile("Reindeer.png");
            Bitmap b2 = new Bitmap(Image.FromFile("Reindeer.png"));
            
            // 100 pixel 간격
            e.Graphics.DrawImage(i, 00);
            e.Graphics.DrawImage(b1, 1000);
            e.Graphics.DrawImage(b2, 2000);
 
            // 해상도 출력
            string str = string.Format("i: {0}X{1}, b1: {2}X{3}, b2: {4}X{5}", i.HorizontalResolution, i.VerticalResolution,
                b1.HorizontalResolution, b1.VerticalResolution, b2.HorizontalResolution, b2.VerticalResolution);
            e.Graphics.DrawString(str, Font, Brushes.Black ,100510);
        }
    }
}
 

 

같은 파일(Reindeer.png)을 세 가지 방법으로 불러와서 100 픽셀 간격으로 출력해 보자.

 

i, b1과 b2의 해상도가 다르다.

 

예상한 것과 다른 방식으로 출력된다. 다른 이미지 뷰어에 표시되는 사이즈와 동일한 방식은 b2다. i, b1은 약간 확대(96/72=1.3배) 되었다. 이미지 파일을 사용할 때는 어떤식으로 불러올지 잘 선택하자.

 

파일에 따라 어떻게 불러와도 같은 사이즈로 표시되기도 한다.

 

반응형
Posted by J-sean
: