728x90
반응형
728x170
▶ IconFactory.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace TestProject
{
/// <summary>
/// 아이콘 헬퍼
/// </summary>
public class IconHelper
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Import
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Private
#region SH 변경 통지하기 - SHChangeNotify(eventID, flag, item1Handle, item2Handle)
/// <summary>
/// SH 변경 통지하기
/// </summary>
/// <param name="eventID">이벤트 ID</param>
/// <param name="flag">플래그</param>
/// <param name="item1Handle">항목 1 핸들</param>
/// <param name="item2Handle">항목 2 핸들</param>
[DllImport("shell32.dll")]
private static extern void SHChangeNotify
(
SHChangeNotifyEventID eventID,
SHChangeNotifyFlag flag,
IntPtr item1Handle,
IntPtr item2Handle
);
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Enumeration
////////////////////////////////////////////////////////////////////////////////////////// Private
#region SH 변경 통지 이벤트 ID - SHChangeNotifyEventID
/// <summary>
/// SH 변경 통지 이벤트 ID
/// </summary>
[Flags]
private enum SHChangeNotifyEventID
{
/// <summary>
/// SHCNE_ALLEVENTS
/// </summary>
SHCNE_ALLEVENTS = 0x7FFFFFFF,
/// <summary>
/// SHCNE_ASSOCCHANGED
/// </summary>
SHCNE_ASSOCCHANGED = 0x08000000,
/// <summary>
/// SHCNE_ATTRIBUTES
/// </summary>
SHCNE_ATTRIBUTES = 0x00000800,
/// <summary>
/// SHCNE_CREATE
/// </summary>
SHCNE_CREATE = 0x00000002,
/// <summary>
/// SHCNE_DELETE
/// </summary>
SHCNE_DELETE = 0x00000004,
/// <summary>
/// SHCNE_DRIVEADD
/// </summary>
SHCNE_DRIVEADD = 0x00000100,
/// <summary>
/// SHCNE_DRIVEADDGUI
/// </summary>
SHCNE_DRIVEADDGUI = 0x00010000,
/// <summary>
/// SHCNE_DRIVEREMOVED
/// </summary>
SHCNE_DRIVEREMOVED = 0x00000080,
/// <summary>
/// SHCNE_EXTENDED_EVENT
/// </summary>
SHCNE_EXTENDED_EVENT = 0x04000000,
/// <summary>
/// SHCNE_FREESPACE
/// </summary>
SHCNE_FREESPACE = 0x00040000,
/// <summary>
/// SHCNE_MEDIAINSERTED
/// </summary>
SHCNE_MEDIAINSERTED = 0x00000020,
/// <summary>
/// SHCNE_MEDIAREMOVED
/// </summary>
SHCNE_MEDIAREMOVED = 0x00000040,
/// <summary>
/// SHCNE_MKDIR
/// </summary>
SHCNE_MKDIR = 0x00000008,
/// <summary>
/// SHCNE_NETSHARE
/// </summary>
SHCNE_NETSHARE = 0x00000200,
/// <summary>
/// SHCNE_NETUNSHARE
/// </summary>
SHCNE_NETUNSHARE = 0x00000400,
/// <summary>
/// SHCNE_RENAMEFOLDER
/// </summary>
SHCNE_RENAMEFOLDER = 0x00020000,
/// <summary>
/// SHCNE_RENAMEITEM
/// </summary>
SHCNE_RENAMEITEM = 0x00000001,
/// <summary>
/// SHCNE_RMDIR
/// </summary>
SHCNE_RMDIR = 0x00000010,
/// <summary>
/// SHCNE_SERVERDISCONNECT
/// </summary>
SHCNE_SERVERDISCONNECT = 0x00004000,
/// <summary>
/// SHCNE_UPDATEDIR
/// </summary>
SHCNE_UPDATEDIR = 0x00001000,
/// <summary>
/// SHCNE_UPDATEIMAGE
/// </summary>
SHCNE_UPDATEIMAGE = 0x00008000,
}
#endregion
#region SH 변경 통지 플래그 - SHChangeNotifyFlag
/// <summary>
/// SH 변경 통지 플래그
/// </summary>
private enum SHChangeNotifyFlag : uint
{
/// <summary>
/// SHCNF_IDLIST
/// </summary>
SHCNF_IDLIST = 0x0000,
/// <summary>
/// SHCNF_PATHA
/// </summary>
SHCNF_PATHA = 0x0001,
/// <summary>
/// SHCNF_PRINTERA
/// </summary>
SHCNF_PRINTERA = 0x0002,
/// <summary>
/// SHCNF_DWORD
/// </summary>
SHCNF_DWORD = 0x0003,
/// <summary>
/// SHCNF_PATHW
/// </summary>
SHCNF_PATHW = 0x0005,
/// <summary>
/// SHCNF_PRINTERW
/// </summary>
SHCNF_PRINTERW = 0x0006,
/// <summary>
/// SHCNF_TYPE
/// </summary>
SHCNF_TYPE = 0x00FF,
/// <summary>
/// SHCNF_FLUSH
/// </summary>
SHCNF_FLUSH = 0x1000,
/// <summary>
/// SHCNF_FLUSHNOWAIT
/// </summary>
SHCNF_FLUSHNOWAIT = 0x2000,
/// <summary>
/// SHCNF_PATH
/// </summary>
SHCNF_PATH = SHCNF_PATHW,
/// <summary>
/// SHCNF_PRINTER
/// </summary>
SHCNF_PRINTER = SHCNF_PRINTERW
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 최대 아이콘 너비
/// </summary>
public const int MAXIMUM_ICON_WIDTH = 256;
/// <summary>
/// 최대 아이콘 높이
/// </summary>
public const int MAXIMUM_ICON_HEIGHT = 256;
/// <summary>
/// 헤더 예약
/// </summary>
private const ushort HEADER_RESERVED = 0;
/// <summary>
/// 헤더 아이콘 타입
/// </summary>
private const ushort HEADER_ICON_TYPE = 1;
/// <summary>
/// 헤더 길이
/// </summary>
private const byte HEADER_LENGTH = 6;
/// <summary>
/// 엔트리 예약
/// </summary>
private const byte ENTRY_RESERVED = 0;
/// <summary>
/// 엔트리 길이
/// </summary>
private const byte ENTRY_LENGTH = 16;
/// <summary>
/// 팔레트 내 PNG 색상 수
/// </summary>
private const byte PNG_COLOR_COUNT_IN_PALETTE = 0;
/// <summary>
/// PNG 색상 플레인 수
/// </summary>
private const ushort PNG_COLOR_PLANE_COUNT = 1;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 저장하기 - Save(bitmapEnumerable, stream, notifySystem)
/// <summary>
/// 저장하기
/// </summary>
/// <param name="bitmapEnumerable">비트맵 열거 가능형</param>
/// <param name="stream">스트림</param>
/// <param name="notifySystem">시스템 통지 여부</param>
public static void Save(IEnumerable<Bitmap> bitmapEnumerable, Stream stream, bool notifySystem)
{
Bitmap[] bitmapArray = bitmapEnumerable.OrderBy(i => i.Width).ThenBy(i => i.Height).ToArray();
using(BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(HEADER_RESERVED);
writer.Write(HEADER_ICON_TYPE);
writer.Write((ushort)bitmapArray.Length);
Dictionary<uint, byte[]> dictionary = new Dictionary<uint, byte[]>();
uint lengthSummary = 0;
uint baseOffset = (uint)(HEADER_LENGTH * ENTRY_LENGTH * bitmapArray.Length);
for(int i = 0; i < bitmapArray.Length; i++)
{
Bitmap bitmap = bitmapArray[i];
byte[] byteArray = GetBitmapByteArray(bitmap);
uint offset = baseOffset + lengthSummary;
writer.Write(GetIconWidth(bitmap));
writer.Write(GetIconHeight(bitmap));
writer.Write(PNG_COLOR_COUNT_IN_PALETTE);
writer.Write(ENTRY_RESERVED);
writer.Write(PNG_COLOR_PLANE_COUNT);
writer.Write((ushort)Image.GetPixelFormatSize(bitmap.PixelFormat));
writer.Write((uint)byteArray.Length);
writer.Write(offset);
lengthSummary += (uint)byteArray.Length;
dictionary.Add(offset, byteArray);
}
foreach(KeyValuePair<uint, byte[]> keyValuePair in dictionary)
{
writer.BaseStream.Seek(keyValuePair.Key, SeekOrigin.Begin);
writer.Write(keyValuePair.Value);
}
}
if(notifySystem)
{
SHChangeNotify
(
SHChangeNotifyEventID.SHCNE_ASSOCCHANGED,
SHChangeNotifyFlag.SHCNF_IDLIST,
IntPtr.Zero,
IntPtr.Zero
);
}
}
#endregion
#region 저장하기 - Save(bitmapEnumerable)
/// <summary>
/// 저장하기
/// </summary>
/// <param name="bitmapEnumerable">비트맵 열거 가능형</param>
/// <returns>아이콘</returns>
public static Icon Save(IEnumerable<Bitmap> bitmapEnumerable)
{
using(MemoryStream stream1 = new MemoryStream())
{
Save(bitmapEnumerable, stream1, false);
using(MemoryStream stream2 = new MemoryStream(stream1.ToArray()))
{
return new Icon(stream2);
}
}
}
#endregion
#region 저장하기- Save(bitmapEnumerable, filePath, notifySystem)
/// <summary>
/// 저장하기
/// </summary>
/// <param name="bitmapEnumerable">비트맵 열거 가능형</param>
/// <param name="filePath">파일 경로</param>
/// <param name="notifySystem">시스템 통지 여부</param>
public static void Save(IEnumerable<Bitmap> bitmapEnumerable, string filePath, bool notifySystem)
{
using(FileStream stream = new FileStream(filePath, FileMode.Create))
{
Save(bitmapEnumerable, stream, notifySystem);
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Private
#region 비트맵 바이트 배열 구하기 - GetBitmapByteArray(bitmap)
/// <summary>
/// 비트맵 바이트 배열 구하기
/// </summary>
/// <param name="bitmap">비트맵</param>
/// <returns>비트맵 바이트 배열</returns>
private static byte[] GetBitmapByteArray(Bitmap bitmap)
{
using(MemoryStream stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Png);
return stream.ToArray();
}
}
#endregion
#region 아이콘 너비 구하기 - GetIconWidth(bitmap)
/// <summary>
/// 아이콘 너비 구하기
/// </summary>
/// <param name="bitmap">비트맵</param>
/// <returns>아이콘 너비</returns>
private static byte GetIconWidth(Bitmap bitmap)
{
if(bitmap.Width >= MAXIMUM_ICON_WIDTH)
{
return 0;
}
return (byte)bitmap.Width;
}
#endregion
#region 아이콘 높이 구하기 - GetIconHeight(bitmap)
/// <summary>
/// 아이콘 높이 구하기
/// </summary>
/// <param name="bitmap">비트맵</param>
/// <returns>아이콘 높이</returns>
private static byte GetIconHeight(Bitmap bitmap)
{
if(bitmap.Height >= MAXIMUM_ICON_HEIGHT)
{
return 0;
}
return (byte)bitmap.Height;
}
#endregion
}
}
728x90
▶ MainForm.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace TestProject
{
/// <summary>
/// 메인 폼
/// </summary>
public partial class MainForm : Form
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
Load += Form_Load;
this.openMenuItem.Click += openMenuItem_Click;
this.saveAsMenuItem.Click += saveAsMenuItem_Click;
this.exitMenuItem.Click += exitMenuItem_Click;
this.clearMenuItem.Click += clearMenuItem_Click;
this.listView.KeyDown += listView_KeyDown;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 폼 로드시 처리하기 - Form_Load(sender, e)
/// <summary>
/// 폼 로드시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void Form_Load(object sender, EventArgs e)
{
this.imageList.ImageSize = new Size(64, 64);
this.listView.View = View.Tile;
this.listView.LargeImageList = this.imageList;
}
#endregion
#region 열기 메뉴 항목 클릭시 처리하기 - openMenuItem_Click(sender, e)
/// <summary>
/// 열기 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void openMenuItem_Click(object sender, EventArgs e)
{
if(this.openFileDialog.ShowDialog() == DialogResult.OK)
{
foreach(string filePath in openFileDialog.FileNames)
{
Bitmap bitmap = new Bitmap(filePath);
this.imageList.Images.Add(bitmap);
this.listView.Items.Add(filePath, this.imageList.Images.Count - 1);
}
this.saveAsMenuItem.Enabled = (this.listView.Items.Count > 0);
}
}
#endregion
#region 다른 이름으로 저장 메뉴 항목 클릭시 처리하기 - saveAsMenuItem_Click(sender, e)
/// <summary>
/// 다른 이름으로 저장 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void saveAsMenuItem_Click(object sender, EventArgs e)
{
if(this.saveFileDialog.ShowDialog() == DialogResult.OK)
{
List<Bitmap> bitmapList = new List<Bitmap>();
foreach(ListViewItem item in this.listView.Items)
{
bitmapList.Add(new Bitmap(item.Text));
}
IconHelper.Save(bitmapList, this.saveFileDialog.FileName, true);
Icon = new Icon(this.saveFileDialog.FileName);
}
}
#endregion
#region 종료 메뉴 항목 클릭시 처리하기 - exitMenuItem_Click(sender, e)
/// <summary>
/// 종료 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void exitMenuItem_Click(object sender, EventArgs e)
{
Close();
}
#endregion
#region 지우기 메뉴 항목 클릭시 처리하기 - clearMenuItem_Click(sender, e)
/// <summary>
/// 지우기 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void clearMenuItem_Click(object sender, EventArgs e)
{
this.listView.Items.Clear();
this.imageList.Images.Clear();
this.saveAsMenuItem.Enabled = (this.listView.Items.Count > 0);
}
#endregion
#region 리스트 뷰 키 DOWN 처리하기 - listView_KeyDown(sender, e)
/// <summary>
/// 리스트 뷰 키 DOWN 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void listView_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Delete)
{
foreach(ListViewItem item in listView.SelectedItems)
{
item.Remove();
}
if(this.listView.Items.Count == 0)
{
this.saveAsMenuItem.Enabled = false;
this.imageList.Images.Clear();
}
}
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > WinForm' 카테고리의 다른 글
[C#/WINFORM] Control 클래스 : 로딩 패널 사용하기 (0) | 2020.09.14 |
---|---|
[C#/WINFORM] PrinterSettings 클래스 : InstalledPrinters 정적 속성을 사용해 설치 프린터 리스트 구하기 (0) | 2020.08.26 |
[C#/WINFORM] Form 클래스 : TopLevel 속성을 사용해 Form 객체를 컨트롤처럼 사용하기 (0) | 2020.08.26 |
[C#/WINFORM] Panel 클래스 : MouseDown/MouseMove 이벤트를 사용해 이동시키기 (0) | 2020.08.25 |
[C#/WINFORM/.NETCORE] WPF XAML 데이터 정규화 하기 (0) | 2020.08.10 |
[C#/WINFORM] Icon 클래스 : 아이콘 파일 만들기 (0) | 2020.08.10 |
[C#/WINFORM] Graphics 클래스 : FillPath/DrawPath 메소드를 사용해 라운드 사각형 그리기 (0) | 2020.08.10 |
[C#/WINFORM] Graphics 클래스 : DrawRectangle 메소드를 사용해 사각형 그리기 (0) | 2020.08.10 |
[C#/WINFORM] Bitmap 클래스 : 비트맵 바이트 배열 구하기 (0) | 2020.08.10 |
[C#/WINFORM] 디지털 시계 표시하기 (0) | 2020.08.09 |
댓글을 달아 주세요