파일 등을 드래그 & 드롭으로 가져올 수 있는 코드입니다.

dropFiles 는 해당 파일의 경로를 불러오게 됩니다.

 

파일/폴더를 마우스 드래그로 가져올 수 있습니다.

 

using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            listBox1.AllowDrop = true; //drag & drop 허용
        }

        private void listBox1_DragDrop(object sender, DragEventArgs e)
        {
            //드래그 드롭 파일 (여러 개 가능)
            string[] dropFiles = (string[])e.Data.GetData(DataFormats.FileDrop);
            
            foreach (string file in dropFiles)
            {
                listBox1.Items.Add(file);
            }
        }

        private void listBox1_DragEnter(object sender, DragEventArgs e)
        {
            //마우스 커서 표현
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Copy;
            }
        }
    }
}

종료 되었지만 남아있는 tray 아이콘

 

C# 에서 정상적으로 프로그램이 종료되면 Tray 아이콘이 제거 되긴 합니다만,

프로세스 킬, 비정상적인 종료 방법이라면 위와 같이 트레이 아이콘이 남는 경우가 있습니다.

 

해당 아이콘은 mouse hover 이벤트 시 윈도우 내부적으로 해당 프로그램이 동작하고 있는지 판별하기에

mouse move 이벤트를 통해 해당 tray들을 정리할 수 있습니다. 아래는 코드!

 

[생성, 정리 후]

생성 버튼 클릭 (8번)
정리 버튼 클릭

 

 

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        class TrayRefresher
        {
            [StructLayout(LayoutKind.Sequential)]
            struct RECT
            {
                public int Left;
                public int Top;
                public int Right;
                public int Bottom;
            }

            [DllImport("user32.dll")]
            static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowName);

            [DllImport("user32.dll")]
            static extern bool GetWindowRect(IntPtr hWnd, out RECT rect);

            [DllImport("user32.dll")]
            static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

            const int WM_MOUSEMOVE = 0x0200;
            
            public void RefreshTray()
            {
                /*
                Shell_TrayWnd (하단의 작업 표시줄)
                 ├─ TrayNotifyWnd (시스템 트레이 영역 - 시계, 네트워크 아이콘, 볼륨 조절 등)
                 │    └─ SysPager (아이콘을 스크롤하거나 관리)
                 │         └─ ToolbarWindow32 (보이는 트레이 아이콘들)
                 │
                 └─ NotifyIconOverflowWindow (숨겨진 아이콘 영역) - 숨기기/펼치기 영역
                      └─ ToolbarWindow32 (숨겨진 아이콘들)
                */

                //보여지는 영역
                IntPtr toolbar = FindToolbar("Shell_TrayWnd", "TrayNotifyWnd", "SysPager", "ToolbarWindow32");
                SendMouseMove(toolbar);

                //감춰진 영역도 추가
                toolbar = FindToolbar("NotifyIconOverflowWindow", "ToolbarWindow32");
                SendMouseMove(toolbar);
            }

            private IntPtr FindToolbar(params string[] targets)
            {
                IntPtr hWnd = IntPtr.Zero;

                foreach (string target in targets)
                {
                    hWnd = FindWindowEx(hWnd, IntPtr.Zero, target, null);

                    if (hWnd == null)
                    {
                        break;
                    }
                }

                return hWnd;
            }

            private void SendMouseMove(IntPtr hWnd)
            {
                if (hWnd == null)
                {
                    return;
                }

                if (GetWindowRect(hWnd, out RECT rect))
                {
                    int width = rect.Right - rect.Left;
                    int height = rect.Bottom - rect.Top;
                    int offset = 5; //아이콘 간격

                    for (int x = 0; x < width; x += offset)
                    {
                        for (int y = 0; y < height; y += offset)
                        {
                            //4byte lParam에 2byte씩 마우스 위치를 넣어줍니다.
                            //mouse y 2byte, mouse x 2byte
                            IntPtr lParam = (IntPtr)((y << 16) | (x & 0xFFFF));
                            SendMessage(hWnd, WM_MOUSEMOVE, IntPtr.Zero, lParam);
                        }
                    }
                }
            }
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Task.Run(async () => //테스트용 트레이 아이콘 생성!
            {
                //테스트용 프로그램            
                Process process = Process.Start(@"...\trayTest.exe");
                await Task.Delay(1000);
                process.Kill(); //강제 종료 시 트레이 아이콘이 남습니다.
            });
        }

        private void button2_Click(object sender, EventArgs e)
        {
            new TrayRefresher().RefreshTray(); //트레이 아이콘 정리!
        }
    }
}

크롬이나 엣지를 감지하여 따라다니는 프로그램 샘플입니다.

여러 개인 경우는 다르게 처리가 필요합니다 기능이 재미있어서 게시 해둬봅니다!

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class FollowForm : Form
    {
        // EnumWindows 콜백 델리게이트
        private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

        [DllImport("user32.dll")]
        private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);

        //SetLastError 설정하면 아래와 같이 에러 타입 가져올 수 있습니다.
        //int errorCode = Marshal.GetLastWin32Error();
        [DllImport("user32.dll", SetLastError = true)]
        private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool SetWindowPos(IntPtr hWnd, 
                                                IntPtr hWndInsertAfter,
                                                int X, 
                                                int Y, 
                                                int cx, 
                                                int cy, 
                                                uint uFlags);

        [DllImport("user32.dll")]
        private static extern bool IsWindowVisible(IntPtr hWnd);

        const uint SWP_NOMOVE = 0x0002;
        const uint SWP_NOSIZE = 0x0001;

        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        //EntryPoint를 통해 C#에서 사용할 이름을 커스텀 할 수 있습니다.
        [DllImport("user32.dll", EntryPoint = "GetWindowRect")]
        private static extern bool GetWindowRect22(IntPtr hWnd, out RECT lpRect);

        private bool isRunning = true;

        public FollowForm()
        {
            InitializeComponent();
        }

        private void FollowForm_Load(object sender, EventArgs e)
        {
            IntPtr myHwnd = this.Handle;

            Task.Run(async () =>
            {
                while (isRunning)
                {
                    await Task.Delay(10);

                    EnumWindows((hWnd, lParam) => //최상위 윈도우 값들을 가져옵니다.
                    {
                        if (IsWindowVisible(hWnd)) //윈도우 보여지는지 여부
                        {
                            StringBuilder title = new StringBuilder(256);
                            GetWindowText(hWnd, title, title.Capacity); //윈도우 텍스트를 가져옵니다.
                            string windowTitle = title.ToString();

                            //크롬이나 엣지를 감지합니다.
                            if (windowTitle.Contains("Chrome") || windowTitle.Contains("Edge"))
                            {
                                Console.WriteLine(windowTitle);

                                SetWindowPos(hWnd, myHwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); //해당 위치를 조정해줍니다.

                                RECT rect;
                                GetWindowRect22(hWnd, out rect); //위치를 가져옵니다. GetWindowRect

                                Invoke((MethodInvoker)delegate
                                {
                                    this.Location = new Point(rect.Left, rect.Top);
                                });
                            }
                        }
                        return true;
                    }, IntPtr.Zero);
                }
            });
        }
        
        private void FollowForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            isRunning = false;
        }
    }
}

코드 및 디자이너는 아래와 같습니다.. 디자이너에서 트레이 아이콘 설정을 해주면 완료!

 

+) 추가적으로 보이지 않지만 특정 위치에 파일 다이얼로그, 프린트 등 기능을 보여주기 위해서

위치 값을 조정할 때가 있습니다. WindowState 와 Visible 처리를 통해 해당 위치 제어가 가능!

using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Tray : Form
    {
        public Tray()
        {
            InitializeComponent();

            this.ShowInTaskbar = false; //하단 테스트바에서 보이지 않도록 설정
            this.Visible = false; //화면에 보이지 않도록 설정
            this.WindowState = FormWindowState.Minimized; //최소화
            this.Opacity = 0; //투명하게 하여 타이틀도 안보이게 설정
            this.FormBorderStyle = FormBorderStyle.FixedToolWindow; //Alt + Tab 에서도 보이지 않도록

            //this.종료ToolStripMenuItem.Click += new System.EventHandler(this.종료ToolStripMenuItem_Click);

            //잠시 특정 위치 활성화
            this.WindowState = FormWindowState.Normal;
            this.Visible = true;
            //new OpenFileDialog().ShowDialog();

            //다시 특정 위치 해제
            this.WindowState = FormWindowState.Minimized;
            this.Visible = false;
        }

        private void 종료ToolStripMenuItem_Click(object sender, System.EventArgs e)
        {
            Close();
        }
    }
}

 

notifyIcon 및 contextMenuStrip 을 설정해줍니다.

notifyIcon 설정

 

ContextMenuStrip 설정 (이벤트도 추가 해주기)

 

결과 Tray Icon

 

.NET Framework / .NET 6 이상
[App.config] 파일

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <appSettings>
    <add key="ServerUrl" value="127.0.0.1"/>
    <add key="ServerPort" value="5000"/>
  </appSettings>
</configuration>

//코드에서 호출방법
System.Configuration.ConfigurationManager.AppSettings["ServerUrl"]
System.Configuration.ConfigurationManager.AppSettings["ServerPort"]

==============================================

.NET Core / .NET 5
[appsettings.json] 파일

{
  "ServerUrl": "https://example.com/api",
  "ServerPort": "5"
}

//코드에서 호출
var config = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();

string apiUrl = config["ServerUrl"];
string apiPort = config["ServerPort"];

32bit 환경에서 2GB 이상 사용하게 되면 out of memory 가 발생되게 됩니다.

기본 플랫폼 대상이 x86 (32bit)

 

c++ 도구 중 editbin.exe 라는 프로그램이 있는데 64bit 환경에서 32bit 프로그램의 메모리 사용량을 4GB 가량으로 늘려주는 기능이 있습니다.

Visual Studio Installer 에서 C++ MSVC를 설치하면..!

 

아래 경로에 editbin.exe 파일이 설치됩니다. (각 버전에 따라 위치가 변경 될 수 있습니다.)
C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x86\

                                                                           (버전) (타입)                                        (버전)

editbin.exe

 

빌드 후 이벤트에 해당 프로그램을 넣어주어 exe 메모리 사용량 변경이 가능합니다.

프로젝트 빌드 후 이벤트에 추가

 

"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x86\editbin.exe" /LARGEADDRESSAWARE "$(TargetPath)"

 

※ $(TargetPath) 는 프로그램 exe 경로입니다.

 

===========================

 

메모리 사용량 확인

디버그 -> 성능 프로파일러 -> 메모리 사용량 -> 시작

비주얼 스튜디오 툴바

 

 

메모리 사용량 체크

 

editbin 메모리 증가

적용 전 (1.2GB 정도 사용 후 다운) 적용 후 (3.0GB 정도 사용 후 다운)

 

 

하위 form2, form3 은 항상 form1보다 앞에 위치!

(Winform) 하위 form2, form3이 form1 앞에 위치


(WPF에 Winform 삽입) form1이 MainWindow 앞에 위치

 

Form 앞쪽에 고정 시키고 싶은 Form이 있는 경우입니다.

Winform에서는 Owner 속성을 지정해주면 해당 Form보다 항상 앞에 위치하게 됩니다.

WPF에서는 창의 Handle 값을 가져와서 Winform에서 Show 할 때 지정해줄 수 있습니다.

 

[Winform]

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private Form2 form2 = new Form2();
        private Form3 form3 = new Form3();
        private int titleSize = 30;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            form2.Owner = this; //Form3은 Form1 앞에 위치
            form3.Owner = this; //Form3은 Form1 앞에 위치

            form2.Size = new Size(this.Width / 2, this.Height - titleSize);
            form3.Size = new Size(this.Width / 2, this.Height - titleSize);

            form2.Show();
            form3.Show();

            form2.Location = new Point(this.Location.X, this.Location.Y + titleSize);
            form3.Location = new Point(this.Location.X + form2.Size.Width, this.Location.Y + titleSize);
        }

        private void Form1_Move(object sender, EventArgs e)
        {
            form2.Location = new Point(this.Location.X, this.Location.Y + titleSize);
            form3.Location = new Point(this.Location.X + form2.Size.Width, this.Location.Y + titleSize);
        }
    }
}

 

[WPF 에서 Winform]

using System;
using System.Windows;
using System.Windows.Interop;

namespace WpfApp1
{
    /// <summary>
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Form1 form1 = new Form1();

            WindowInteropHelper helper = new WindowInteropHelper(this);
            IntPtr handle = helper.Handle; //WPF 핸들값 가져오기

            form1.Show(new Win32Window(handle)); //form1이 항상 윗쪽에!
        }
    }

    class Win32Window : System.Windows.Forms.IWin32Window
    {
        private IntPtr handle;
        public IntPtr Handle
        {
            get
            {
                return handle;
            }
        }

        public Win32Window(IntPtr handle)
        {
            this.handle = handle;
        }
    }
}

IPC (Inter Process Communication) 방식 중 네임드파이프 통신이 있습니다.

서로 다른 프로그램에서 정의된 파이프 이름만 알면 통신이 가능한 방식입니다.

아래는 결과와 소스코드!

 

왼쪽은 A_Pipe, 오른쪽은 B_Pipe

 

using System;
using System.IO;
using System.IO.Pipes;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class NamedPipe : Form
    {
        private const string myName = "A_Pipe"; //이름만 바꿔서 사용 가능
        private const string targetName = "B_Pipe"; //이름만 바꿔서 사용 가능

        private bool isOpen = true;

        public NamedPipe()
        {
            InitializeComponent();

            this.FormClosing += Form1_FormClosing;
            button1.Click += button1_Click;

            Task.Run(() =>
            {
                Receive();
            });
        }

        private void Receive()
        {
            while (isOpen)
            {
                try
                {
                    NamedPipeServerStream namedPipeServerStream = new NamedPipeServerStream(myName, PipeDirection.InOut, 10);
                    namedPipeServerStream.WaitForConnection(); //데이터 받을때까지 기다립니다.

                    StreamReader streamReader = new StreamReader(namedPipeServerStream);
                    string line = streamReader.ReadLine();

                    AddListItem(line);

                    streamReader.Close();
                    namedPipeServerStream.Close();
                }
                catch (Exception ex)
                {
                    AddListItem("Receive Error : " + ex.Message);
                }
            }
        }

        private void AddListItem(string message)
        {
            Invoke((MethodInvoker)delegate
            {
                listBox1.Items.Add(message);
            });
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                NamedPipeClientStream namedPipeClientStream = new NamedPipeClientStream(".", targetName, PipeDirection.InOut);
                namedPipeClientStream.Connect(10000); //10초

                StreamWriter streamWriter = new StreamWriter(namedPipeClientStream);

                streamWriter.WriteLine(textBox1.Text);
                streamWriter.Flush();

                streamWriter.Close();
                namedPipeClientStream.Close();
            }
            catch (Exception ex)
            {
                AddListItem("Send Error : " + ex.Message);
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            isOpen = false;
        }
    }
}

현재 영역에 대해서만 그려주기! (4개만 보이는 상태)

 

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form, IMessageFilter
    {
        private const int buttonOffset = 10;

        private List<Button> buttonList = new List<Button>();
        private List<Control> focusedList = new List<Control>();
        private int scrollPosition;

        public Form1()
        {
            InitializeComponent();

            panel1.AutoScroll = true; //스크롤 활성화

            //스크롤 이벤트 등록
            this.panel1.Resize += new System.EventHandler(this.panel1_Resize);
            this.panel1.Scroll += new System.Windows.Forms.ScrollEventHandler(this.panel1_Scroll);

            //버튼 이벤트 등록
            this.button_add.Click += new EventHandler(this.button_add_Click);

            Application.AddMessageFilter(this); //IMessageFilter 사용하기 위해 등록!
        }

        public bool PreFilterMessage(ref Message m) //IMessageFilter 콜백
        {
            if (m.Msg == 0x20a) // WM_MOUSEWHEEL (마우스 휠)
            {
                if (panel1.Bounds.Contains(PointToClient(Cursor.Position)))
                {
                    short x = (short)(((int)m.WParam >> 16) & 0xffff);

                    if (x < 0)
                    {
                        ScrollMove(20);
                    }
                    else
                    {
                        ScrollMove(-20);
                    }

                    return true;
                }
            }

            return false;
        }

        private void ScrollMove(int move)
        {
            int preValue = scrollPosition;

            scrollPosition += move;
            scrollPosition = Math.Max(scrollPosition, 0);
            scrollPosition = Math.Min(panel1.DisplayRectangle.Width - panel1.Width, scrollPosition);

            panel1.HorizontalScroll.Value = scrollPosition;

            //기존 값과 같다면 동작하지 않게 합니다.
            if (preValue == scrollPosition)
            {
                return;
            }

            UpdateThumbnail(scrollPosition);
        }

        private void button_add_Click(object sender, EventArgs e)
        {
            Button button = new Button();

            button.Text = buttonList.Count.ToString("D4");
            button.Hide();

            panel1.Controls.Add(button);
            panel1.AutoScrollMinSize = new Size(panel1.AutoScrollMinSize.Width + button.Width + buttonOffset, 0);

            buttonList.Add(button);
            UpdateThumbnail(scrollPosition);
        }

        private void UpdateThumbnail(int startPosition)
        {
            int totalWidth = 0;

            //돌면서 그려줘야 할 영역에 대해서만 그려주기!
            for (int i = 0; i < buttonList.Count; ++i)
            {
                totalWidth += buttonList[i].Width + buttonOffset;

                //처음으로 커지는 구간을 찾기! 시작 지점!
                if (totalWidth >= startPosition)
                {
                    int showPositionX = totalWidth - startPosition - buttonList[i].Width - buttonOffset;

                    List<Control> newFocusList = new List<Control>();

                    for (int j = i; j < buttonList.Count; ++j)
                    {
                        Point position = new Point(showPositionX, 0);
                        showPositionX += buttonList[j].Width + buttonOffset;

                        buttonList[j].Location = position;
                        buttonList[j].Show();

                        newFocusList.Add(buttonList[j]);

                        if (this.Width <= showPositionX)
                        {
                            break;
                        }
                    }

                    //현재 영역에 들어있지 않은 기존 항목은 제거해줍니다.
                    foreach (Control item in focusedList)
                    {
                        if (newFocusList.Contains(item) == false)
                        {
                            item.Hide();
                        }
                    }

                    //현재 항목을 갱신합니다.
                    focusedList = newFocusList;

                    break;
                }
            }
        }

        private void panel1_Scroll(object sender, ScrollEventArgs e)
        {
            scrollPosition = e.NewValue;
            Console.WriteLine("scrollPosition : " + scrollPosition);
            UpdateThumbnail(scrollPosition);
        }

        private void panel1_Resize(object sender, EventArgs e)
        {
            if (panel1.AutoScrollMinSize.Width - panel1.Width <= scrollPosition)
            {
                Console.WriteLine("*************************** 크기 변경!!!");

                scrollPosition = Math.Max(0, panel1.AutoScrollMinSize.Width - panel1.Width);
                panel1.HorizontalScroll.Value = scrollPosition;
            }

            UpdateThumbnail(scrollPosition);
        }
    }
}

 

이미지 회전에 따른 여백 생성!

 

우선은 코드만 올립니다..

using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private string workFolder = Path.Combine(Application.StartupPath, "workFolder");
        private int sequence = 0;

        public Form1()
        {
            InitializeComponent();

            //이미지 확인을 위해 오토사이즈로 해줍니다.
            pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
            pictureBox2.SizeMode = PictureBoxSizeMode.AutoSize;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();

            //파일을 불러옵니다.
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                pictureBox1.Image = Image.FromFile(ofd.FileName);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (Directory.Exists(workFolder) == false)
            {
                Directory.CreateDirectory(workFolder);
            }

            sequence++; //돌린 횟수! (파일명 겹치지 않도록 해줍니다.)
            Image originImage = pictureBox1.Image; //사용될 원본 이미지!

            for (int rotation = 1; rotation <= 360; ++rotation) //360도 회전시켜줍니다.
            {
                int maxAngle = 91;

                int width = originImage.Width;
                int height = originImage.Height;

                int rot; //항상 0 ~ 90도로 만들어줍니다.

                if (90 < rotation && rotation <= 181) //해당 구간에서는 반전이 필요합니다.
                {
                    rot = 180 - rotation;
                }
                else if (270 < rotation && rotation <= 360) //해당 구간에서는 반전이 필요합니다.
                {
                    rot = 360 - rotation;
                }
                else
                {
                    rot = rotation % maxAngle;
                }

                double widthRadian = rot * Math.PI / 180;
                double heightRadian = (90 - rot) * Math.PI / 180; //90도 기준으로 반전 시켜줍니다.

                double w = Math.Cos(widthRadian) * width + Math.Sin(widthRadian) * height;
                double h = Math.Cos(heightRadian) * width + Math.Sin(heightRadian) * height;

                //기존 이미지 기준으로 돌려줍니다.
                DrawImage(originImage,
                          pictureBox1,
                          rotation,
                          width,
                          height,
                          width,
                          height,
                          "origin_");

                //크기가 확장 된 이미지 기준으로 돌려줍니다.
                DrawImage(originImage,
                          pictureBox2,
                          rotation,
                          (int)w,
                          (int)h,
                          width,
                          height,
                          "extend_");
            }

            originImage.Dispose();

            Process.Start(workFolder);
        }

        private void DrawImage(Image originImage,
                                PictureBox pictureBox,
                                int rotation,
                                int width,
                                int height,
                                int centerX,
                                int centerY,
                                string imageType)
        {
            Color backgroundColor = Color.FromArgb(255, 255, 0, 0);      //빨강 배경 (알파값을 통해 투명하게 가능!)

            Bitmap bitmap = new Bitmap(width, height);
            Graphics graphics = Graphics.FromImage(bitmap);

            graphics.Clear(backgroundColor);                             //배경 칠해주기
            graphics.TranslateTransform(width / 2, height / 2);          //이미지 가운데로 이동
            graphics.RotateTransform(rotation);                          //가운데에서 회전
            graphics.DrawImage(originImage, centerX / -2, centerY / -2); //이미지를 가운데 그려줍니다.

            string fileName = string.Format("{0}_{1}{2}.png", sequence.ToString("D4"), imageType, rotation.ToString("D4"));
            string savePath = Path.Combine(workFolder, fileName);

            bitmap.Save(savePath);

            graphics.Dispose();
            bitmap.Dispose();

            pictureBox.Image = Image.FromFile(savePath);
            pictureBox.Update();
        }
    }
}

 

 

+ Recent posts