- C# 코드로 WinForm 윈도우 만들기
- Application 클래스
- 윈도우를 표현하는 Form 클래스
- 폼 디자이너를 이용한 WinForm UI 구성
- 사용자 인터페이스와 비동기 작업
[ C#코드로 WinForm 윈도우 만들기 ]
[ 개요 ]
- WinForm에서 제공하는 폼 디자이너 툴은 프로그래머가 그림을 그리듯 사용자 인터페이스를 만들게 한다 .
- 위즈윅 ( What You See Is What You Get )방식의 개발을 지원한다 .
- 비주얼 스튜디오의 도움 없이 C# 코드만으로 GUI를 구성할 수도 있다 .
[ WinForm 클래스를 이용한 윈도우 생성 절차 ]
- System.Windows.Forms.Form 클래스에서 파생된 윈도우 폼 클래스를 선언한다 .
- 클래스의 인스턴스를 System.Windows.Forms.Application.Run()메소드에 인수로 넘겨 호출한다 .
- 아래과정을 통해 윈도우를 생성해보자 .
- 콘솔앱 템플릿으로 새 프로젝트 생성후 최상위문 사용 안함을 체크한다
- 솔루션 탐색기의 SimpleWindow 더블클릭 .csproj를 코드 편집기로 불러들인다 .
- <TargetFramework>net8.0-windows</TargetFramework>으로 변경
- <UseWindowsForms>true</UseWindowsForms> 추가
- <ImplicitUsings>enable</ImplicitUsings> 제거로 전역 using의 암시적 전체사용을 해제 .
- MainApp으로 명칭 변경후 아래의 코드로 컴파일해서 실행
namespace SimpleWindow
{
//MainApp이 System.Windows.Forms.From 클래스로부터 상속받도록 선언한다
class MainApp:System.Windows.Forms.Form
{
static void Main(string[] args)
{
//Application.Run() 메소드에 MainApp의 인스턴스를 인수로 넘겨 호출
System.Windows.Forms.Application.Run(new MainApp());
}
}
}
- 다음과 같이 쉽게 윈도우를 생성한다 .
- System.Window.Forms.Form 클래스 / System.Windows.Forms.Appliciation 두 클래스에 대해 알아보자 .
[ Application 클래스 ]
using System;
using System.Windows.Forms;
namespace SimpleWindow
{
class MainApp:Form
{
static void Main(string[] args)
{
MainApp form = new MainApp();
//from 클래스는 여러 이벤트 정의 , click 이벤트는 윈도우 클릭시 발생
form.Click += new EventHandler(
(sendler, eventArgs) =>
{
Console.WriteLine("Closing Windows");
Application.Exit();
});
Console.WriteLine("Starting Window Application");
Application.Run(form);
Console.WriteLine("Exiting Window Application");
}
}
}
- Application 클래스는 1 . 윈도우 응용 프로그램의 시작과 종료 메서드 제공 / 2 . 윈도우 메시지를 처리하는 것 을 한다
- Exit() 메소드가 호출된다해서 응용 프로그램이 바로 종료되는게 아니다 .
- 메소드는 응용 프로그램이 갖고 있는 모든 윈도우 닫은뒤 Run() 메소드가 반환되게 하는 것이다 .
- Run 메소드 뒤에 자원을 정리하는 코드가 있다면 우아하게 응용프로그램을 정리 할 수 있다 .
[ 메시지 필터링 ]
[ 메시지 ]
- 윈도우 기반의 응용 프로그램들은 갑자기 일어나는 이벤트에 반응,코드가 실행되는 이벤트 기반 방식으로 만들어진다 .
- 윈도우 프로그램이 받아들이는 이벤트는 마우스 클릭,키보드 입력등이 있다 .
- 이벤트들은 사용자가 직접 응용 프로그램에 대해 일으킨것 같지만 , 윈도우 OS 가 일으킨 것이다 .
- 마우스등의 하드웨어 제어 - 인터럽트 발생 - 윈도우 OS 가 받음 - 인터럽트 바탕,윈도우 메시지 만듬 - 응용프로그램받음
[ 메시지 필터링 ]
- 윈도우 응용 프로그램은 마우스 이동등 시스템에 미리 정의된 메시지를 받는다 .
- 또한 다른 응용 프로그램이 정의한 많은 메시지도 받을 수 있다 .
- Application 클래스는 응용프로그램이 받는 메시지 중 관심있는 메시지만 거르는 메시지 필터링 기능이 있다 .
[ 메시지 필터링 과정 ]
- 윈도우 OS 에서 정의하는 메시지는 식별번호 (ID)가 붙어있다 . ex)WM_LBUTTONDOWN - 0x201
- Application 클래스는 특정 ID를 가진 메시지를 걸러내는 필터를 함께 등록해뒀다가 응용 프로그램에 메시지가 전달되면 해당 필터를 동작시킨다 .
- 메시지의 ID 가 필터가 관심있는 값이라면 필터는 메시지를 요리 / 아니라면 메시지를 거르지 않고 메시지를 받아야 하는 폼/ 컨트롤로 보내서 이벤트를 발생시킨다 .
[ Application.AddMessageFilter ]
public class MessageFilter : IMessageFilter
{
public bool PreFilterMessage(ref Message m)
{
if(m.MSG >= 0x200 && m.Msg <= 0x20E)
{
Console.WriteLine("발생한 메시지 : " + m.Msg);
return true;
}
return false;
}
}
- Application.AddMessageFileter()메소드는 응용 프로그램에 메시지 필터를 설치한다
- 해당 메소드는 IMessageFilter 인터페이스를 구현하는 파생 클래스의 인스턴스를 인수로 받는다 .
- IMessageFilter는 PreFilterMessage() 메소드를 구현할 것을 요구한다 .
- 위 코드는 입력받은 메시지를 처리했으니 응용 프로그램은 관심 가질 필요가 없다는 의미로 True를 반환
- 메시지를 건들지 않았으니 응용프로그램에 처리하라하는 false를 반환한다 .
- 매개변수로 받아지는 Message 구조체는 다음과 같은 프로퍼티를 가지고 있다 .
프로퍼티 | 설명 |
HWnd | 메시지를 받는 윈도우의 핸들 . 윈도우의 인스턴스를 식별 , 관리를 위해 운영체제가 붙인 번호가 핸들 . |
Msg | 메시지 ID |
LParam | 메시지를 처리하는데 필요한 정보가 담김 |
WParam | 메시지를 처리하는데 필요한 부가정보가 담김 |
Result | 메시지 처리에 대한 응답으로 윈도우 OS에 반환되는 값을 지정한다 . |
using System;
using System.Windows.Forms;
namespace SimpleWindow
{
class MessageFilger : IMessageFilter
{
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == 0x0F || m.Msg == 0xA0 ||
m.Msg == 0x200 || m.Msg == 0x113)
return false;
Console.WriteLine($"{m.ToString()} : {m.Msg}");
if(m.Msg==0x201)
Application.Exit();
return true;
}
}
class MainApp:Form
{
static void Main(string[] args)
{
Application.AddMessageFilter(new MessageFilger());
Application.Run(new MainApp());
}
}
}
- WM_PAINT(0x0f) / WM_MOUSEMOVE(0x200) / WM_TIMER(0x113)을 제외하고 모든 메시지를 출력한다 .
- WM_LBUTTONDOWN(0x201)메시지가 도착하면 종료한다 .
- 이 메시지들은 WinForm의 각 윈도우와 컨트롤에 전달 , 윈도우와 컨트롤들은 이 메시지를 받으면 미리 정의된 이벤트 발생 , 각 이벤트는 프로그래머가 등록한 이벤트 처리기를 호출한다 .
[ 윈도우를 표현하는 From 클래스 ]
[ 작업 개요 ]
- Form(과 컨트롤)에 정의된 이벤트와 이벤트 처리기 연결하기
- Form의 프로퍼티를 조절하여 윈도우 모양 바꾸기
- Form 위에 컨트롤 올리기
[ Form에 정의된 이벤트와 이벤트 처리기 연결하기 ]
- Form 클래스는 운영체제가 보내는 메시지 중 일부에 대해 이벤트를 구현하고 있다 .
- ex ) Form의 인스턴스 , 즉 윈도우 위에서 마우스 좌클릭시 WM_BUTTONDOWN 메시지가 Form 객체로 전달,객체는 MouseDown 이벤트를 발생시킨다 .
- WinForm 으로 응용 프로그램을 만드는 동안 윈도우 메시지를 직접 요리할 경우는 거의 없다.
- Form을 비롯한 WinForm의 윈도우와 컨트롤 클래스들이 윈도우 메시지를 포장하여 이벤트로 구현했기 때문이다 .
- 미리 정의된 이벤트에 이벤트 처리기 메소드를 선언 , 등록하기만 하면 된다 .
class MyForm : Form
{
//이벤트 처리기 선언
private void Form_MouseDown(object sender,System.Windows.Forms.MouseEventArgs e)
{
MessageBox.Show("안녕하세요!");
}
public MyForm
{
this.MouseDown+=new System.Windows.Forms.MouseEventHandler(this.Form_MouseDown)
}
}
- 이벤트 처리기를 등록 , 호출하는 메커니즘은 모든 폼과 컨트롤이 동일하다 .
//이벤트는 대리자 기반으로 선언
public event MouseEventHandler MouseDown;
//대리자
public delegate void MouseEventHandler(objetc sender,MouseEventArgs e);
- 이 선언코드로 이벤트 처리기가 어떤 매개변수를 가지고 어떤 형식을 반환하는지 알 수 있다 .
- Sender 는 발생한 객체 . Form 클래스의 이벤트 처리기에 대해 알아보니 sender는 Form 객체 자신이다 .
- MouseEventArgs는 다음의 프로퍼티를 제공하여 마우스 이벤트의 상세 정보를 제공한다 .
프로퍼티 | 설명 |
Button | 마우스의 어떤 버튼에서 이벤트가 발생했는지 나타낸다 . |
Clicks | 마우스의 버튼을 클릭한 횟수 . |
Delta | 마우스 휠의 회전 방향과 회전한 거리 |
X | 마우스 이벤트가 발생한 폼 또는 컨트롤 상의 x 좌표 |
Y | 마우스 이벤트가 발생한 폼 또는 컨트롤 상의 y 좌표 |
using System;
using System.Runtime.CompilerServices;
using System.Windows.Forms;
namespace SimpleWindow
{
class MainApp:Form
{
public void MyMouseHandler(object sender, MouseEventArgs e)
{
Console.WriteLine($"Sender : {((Form)sender).Text}");
Console.WriteLine($"X : {e.X} Y : {e.Y}");
Console.WriteLine($"Button { e.Button} , Clicks { e.Clicks} ");
Console.WriteLine();
}
public MainApp(string title)
{
this.Text = title;
this.MouseDown += new MouseEventHandler(MyMouseHandler);
}
static void Main(string[] args)
{
Application.Run(new MainApp("Mouse Event Test"));
}
}
}
[ Form프로퍼티를 조절 , 윈도우 모양 바꾸기 ]
- Form 클래스는 윈도우 모양을 결정짓는 크기 , 배경색 , 전경색 , 투명도 ,제목 ,폰트 등 여러 프로퍼티를 가지고 있다 .
종류 | 프로퍼티 | 설명 |
크기 | Width | 창의 너비 |
Height | 창의 높이 | |
색깔 | BackColor | 창의 배경 색깔 |
BackgroundImage | 창의 배경 이미지 | |
Opacity | 창의 투명도 | |
스타일 | MaximizeBox | 최대화 버튼 설치 여부 |
MinimizeBox | 최소화 버튼 설치 여부 | |
Text | 창의 제 |
using System;
using System.Runtime.CompilerServices;
using System.Windows.Forms;
namespace SimpleWindow
{
class MainApp:Form
{
static void Main(string[] args)
{
MainApp form = new MainApp();
form.Width = 300;
form.Height = 200;
form.MouseDown += new MouseEventHandler(form_MouseDown);
Application.Run(form);
}
static void form_MouseDown(object sender, MouseEventArgs e)
{
Form form = (Form)sender;
int oldWidth = form.Width;
int oldHeight = form.Height;
if(e.Button == MouseButtons.Left)
{
if(oldWidth<oldHeight)
{
form.Height = oldWidth;
form.Width = oldHeight;
}
}
else if(e.Button == MouseButtons.Right)
{
if(oldHeight<oldWidth)
{
form.Height = oldWidth;
form.Width = oldHeight;
}
}
Console.WriteLine("윈도우의 크기가 변경");
Console.WriteLine($"Width : {form.Width}/Heigjt : {form.Height}");
}
}
}
//창의 배경색은 BackColor 프로퍼티를 통해 바꿀 수 있다 .
//System.Drawing.Color 형식이기에 Color 클래스의 정적 메소드 / 미리 정의된 상숫값 이용
Form form = new Form();
//Color 구조체에는 다양한 색상이 미리 정의
form.BackColor = Color.Red;
//정확한 값의 지정
form.BackColor = Color.FromArgb(255,255,0,0);
- 창의 배경색은 BackColor 프로퍼티를 통해 바꿀 수 있다 .
Form form = new Form();
form.Opacity = 1.00;
form.Opacity = 0.87
- 창의 투명도는 Opacity 프로퍼티를 통해 바꿀 수 있다 .
Form form = new Form()'
form.BackgroundImage = Image.FromFile("MyImage.JPG");
- 창의 배경 이미지는 BackgroundImage 프로퍼티에 Image 형식의 인스턴스를 할당하여 바꾼다 .
using System;
using System.Drawing;
using System.Windows.Forms;
namespace SimpleWindow
{
class MainApp:Form
{
Random rand;
public MainApp()
{
rand = new Random();
this.MouseWheel += new MouseEventHandler(MainApp_MouseWheel);
this.MouseDown += new MouseEventHandler(MainApp_MouseDown);
}
void MainApp_MouseDown(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
Color oldColor = this.BackColor;
this.BackColor=Color.FromArgb(rand.Next(0,255),
rand.Next(0,255),
rand.Next(0,255));
}
else if(e.Button == MouseButtons.Right)
{
if(this.BackgroundImage!=null)
{
this.BackgroundImage = null;
return;
}
string file = "Sample.png";
if (System.IO.File.Exists(file) == false)
MessageBox.Show("이미지 파일이 없습니다");
else
this.BackgroundImage=Image.FromFile(file);
}
}
void MainApp_MouseWheel(object sender,MouseEventArgs e)
{
this.Opacity = this.Opacity + (e.Delta > 0 ? 0.1 : -0.1);
Console.WriteLine($"Opacity : {this.Opacity}");
}
static void Main(string[] args)
{
Application.Run(new MainApp());
}
}
}
- 위 예제는 마우스 왼쪽 버튼을 누르면 렌덤하게 창의 배경색을 바꾸고 , 오른쪽 버튼을 누르면 배경 이미지 표시 , 휠을 굴리면 투명도를 바꿔준다 .
- 이때 , 실행파일 위치에 이미지가 있어야 한다 .
[ Form프로퍼티를 조절 , 최대 / 최소화 버튼 활성과 제목 바꾸기 ]
using System;
using System.Drawing;
using System.Windows.Forms;
namespace SimpleWindow
{
class MainApp:Form
{
static void Main(string[] args)
{
MainApp form = new MainApp();
form.Width = 400;
form.MouseDown += new MouseEventHandler(form_MouseDown);
Application.Run(form);
}
static void form_MouseDown(object sender, MouseEventArgs e)
{
Form form = (Form)sender;
if(e.Button==MouseButtons.Left)
{
form.MaximizeBox = true;
form.MinimizeBox = true;
form.Text = "최소화/최대화 버튼이 활성화";
}
else if(e.Button==MouseButtons.Right)
{
form.MaximizeBox = false;
form.MinimizeBox = false;
form.Text = "최소화/최대화 버튼이 비활성화";
}
}
}
}
- 좌클릭시 최소/최대 버튼이 활성화되고 우클릭시 최소/최대 버튼이 비활성화 된다 .
[ Form 위에 컨트롤 올리기 ]
[ 컨트롤 ]
- 컨트롤은 윈도우 OS 가 제공하는 UI 요소 . (응용 프로그램을 제어하는데 사용하는 도구) ex ) 버튼/텍스트 박스
- 윈도우 OS 는 UI를 위해 메뉴 , 콤보박스 , 리스트뷰 , 버튼 , 텍스트 박스등의 표준 컨트롤을 제공한다 .
- 컨트롤의 인스턴스 생성
- 컨트롤의 프로퍼티에 값 지정
- 컨트롤의 이벤트에 이벤트 처리기 등록
- 폼에 컨트롤 추가
위의 과정을 거쳐 Form 위에 컨트롤을 올린다 .
[ 1 . 컨트롤의 인스턴스 생성 ]
- WinForm의 모든 컨트롤은 System.Windows.Forms.Control 을 상속한다 .
- 해당 형식이 모든 윈도우 컨트롤이 지원해야 하는 그래픽,동작,이벤트를 제공하기에 이 컨트롤로부터 상속받는 어떤 클래스라도 Form 위에 올려서 윈도우 UI 요소로 사용할 수 있다 .
- 버튼은 다음과 같이 인스턴스를 생성한다 .
Button button = new Button();
[ 2 . 컨트롤의 프로퍼티에 값 지정 ]
- 인스턴스를 만들었으면 각 프로퍼티에 값을 지정 , 컨트롤의 모양을 결정한다 .
button.Text = "Click ME";
button.Left = 100;
button.Top = 50;
[ 3 . 컨트롤의 이벤트에 이벤트 처리기 등록 ]
- 컨트롤은 애플리케이션의 정보를 표시하기도 하지만 , 사용자로부터 입력을 받는 창구이기도 하다 .
- 사용자가 버튼 클릭시 메시지 박스를 띄우도록 이벤트 처리기 선언후 이벤트에 등록한다 .
button.Click+=
(object sender,EventArgs e)=>
{
Message.ShowBox("딸깍!");
}
[ 4 . 폼에 컨트롤 추가 ]
- Form의 인스턴스를 생성 , Contorls 프로퍼티의 Add 메서드로 button 객체를 Form에 올린다 .
MainApp form = new MainApp();
form.Controls.Add(button);
[ 실습 ]
using System;
using System.Drawing;
using System.Windows.Forms;
namespace SimpleWindow
{
class MainApp:Form
{
static void Main(string[] args)
{
Button button = new Button();
button.Text = "Click Me!";
button.Left = 100;
button.Top = 50;
button.Click +=
(object sender, EventArgs e) =>
{
MessageBox.Show("딸깍");
};
MainApp form = new MainApp();
form.Text = "Form & Control";
form.Height = 150;
form.Controls.Add(button);
Application.Run(form);
}
}
}
[ 폼 디자이너를 이용한 WinForm UI 구성 ]
[ 폼 디자이너 ]
- 비주얼 스튜디오 IDE의 일부로 앞서 코드를 통해 해왔던 작업이 마우스 클릭만으로 가능하다 .
- 폼 디자이너는 도구상자 (컨트롤 팔레트)와 함께 사용해야 한다 .
[ 새 프로젝트 만들기 ]
- Windows Forms 앱을 생성해준다 .
- Form1.cs를 MainForm.cs으로 명칭을 변경해준다 .
[ Form ]
- 속성창에서 Text를 변경해준다 .
[ Group Box / Label / Combo Box / Check Box / Text Box ]
- 위와 같이 컨트롤을 배치한다 .
- 각 컨트롤에 이벤트에 대한 처리기를 등록한다 .MainForm/cboFont / chkBold/chkItalic 에 아래의 이벤트 처리기를 등록 .
namespace UsingControls
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
void MainForm_Load(object sender, EventArgs e)
{
var Fonts = FontFamily.Families;//운영 체제에 설치되어 있는 폰트 목록 검색
foreach (FontFamily font in Fonts)
cboFont.Items.Add(font.Name);
}
void ChangeFont()
{
//cboFont에서 선택한 항목이 없으면 메소드 종료
if (cboFont.SelectedIndex < 0)
return;
FontStyle style = FontStyle.Regular;//FontStyle 객체를 초기화
if(chkBold.Checked )
style|= FontStyle.Bold;
if( chkItalic.Checked )
style|= FontStyle.Italic;
txtSampleText.Font = new Font((string)cboFont.SelectedItem, 10, style);
}
void cboFont_SelectedIndexChanged(object sender, EventArgs e) { ChangeFont(); }
void chkBold_CheckedChanged(object sender, EventArgs e) { ChangeFont(); }
void chkItalic_CheckedChanged(object sender, EventArgs e) { ChangeFont(); }
}
}
- f5를 눌러 테스트를 해본다 .
[ Track Bar / ProgrssBar ]
- 위와 같이 컨트롤을 배치한다 .
void tbDummy_Scroll(object sender, EventArgs e)
{
pgDummy.Value=tbDummy.Value;
}
- tbDummy에 다음의 이벤트 처리기를 등록한다 .
[ Button / Form / Dialog ]
- 위와 같이 컨트롤을 배치한다 .
void btnModal_Click(object sender, EventArgs e)
{
Form frm=new Form();
frm.Text = "Modal Form";
frm.Width = 300;
frm.Height = 100;
frm.BackColor = Color.Red;
frm.ShowDialog();//Modal 창을 띄움
}
void btnModaless_Click(object sender, EventArgs e)
{
Form frm = new Form();
frm.Text = "Modaless Form";
frm.Width = 300;
frm.Height = 300;
frm.BackColor = Color.Green;
frm.Show();//Modaless 창을 띄움
}
void btnMsgBox_Click(object sender, EventArgs e)
{
MessageBox.Show(txtSampleText.Text, "MessageBox Text", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
- 다음의 이벤트 처리기를 등록한다 .
[ TreeView / List View ]
- 위와 같이 컨트롤을 배치한다 .
Random random = new Random(37);
- 난수 생성을 위해 MainForm.cs 에 추가
void TreeToList()
{
lvDummy.Items.Clear();
foreach (TreeNode node in tvDummy.Nodes)
TreeToList(node);
}
void TreeToList(TreeNode Node)
{
lvDummy.Items.Add(
new ListViewItem(
//TreeNode 형식의 FullPath 프로퍼티는 루트 노드부터 현재 노드까지의 경로를 나타냄
//각 경로는 \로 구분
new string[] { Node.Text, Node.FullPath.Count(f => f == '\\').ToString() }));
foreach (TreeNode node in Node.Nodes)
TreeToList(node);
}
void btnAddRoot_Click(object sender, EventArgs e)
{
tvDummy.Nodes.Add(random.Next().ToString());
TreeToList();
}
void btnAddChild_Click(object sender, EventArgs e)
{
if (tvDummy.SelectedNode == null)
{
MessageBox.Show("선택된 노드가 없습니다 .","TreeView List", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
tvDummy.SelectedNode.Nodes.Add(random.Next().ToString());
tvDummy.SelectedNode.Expand();
TreeToList();
}
- 다음의 이벤트 처리기를 등록한다
[ 사용자 인터페이스와 비동기 작업 ]
[ 폼 디자이너 ]
- 위와 같이 설정한다
using System.Security.Cryptography;
namespace AsyncFileIOWinForm
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
#region CopyMethod
async Task<long> CopyAsync(string FromPath, string ToPath)
{
btnSyncCopy.Enabled = false;
long totalCopied = 0;
using(FileStream fromStream=new FileStream(FromPath,FileMode.Open))
{
using (FileStream toStream = new FileStream(ToPath, FileMode.Create))
{
byte[] buffer = new byte[1024 * 1024];
int nRead = 0;
while ((nRead = await fromStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
await toStream.WriteAsync(buffer,0,nRead);
totalCopied += nRead;
pbCopy.Value=(int)(((double)totalCopied/(double)fromStream.Length)*pbCopy.Maximum);
}
}
}
btnSyncCopy.Enabled = true;
return totalCopied;
}
long CopySync(string FromPath, string ToPath)
{
btnSyncCopy.Enabled = false;
long totalCopied = 0;
using (FileStream fromStream = new FileStream(FromPath, FileMode.Open))
{
using (FileStream toStream = new FileStream(ToPath, FileMode.Create))
{
byte[] buffer = new byte[1024 * 1024];
int nRead = 0;
while ((nRead = fromStream.Read(buffer, 0, buffer.Length)) != 0)
{
toStream.Write(buffer, 0, nRead);
totalCopied += nRead;
pbCopy.Value = (int)(((double)totalCopied / (double)fromStream.Length) * pbCopy.Maximum);
}
}
}
btnSyncCopy.Enabled = true;
return totalCopied;
}
#endregion
void btnFindSource_Click(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
if(dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
txtSource.Text = dlg.FileName;
}
}
void btnFindTarget_Click(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
txtTarget.Text = dlg.FileName;
}
}
async void btnAsyncCopy_Click(object sender, EventArgs e)
{
long totalCopied = await CopyAsync(txtSource.Text,txtTarget.Text);
}
void btnSyncCopy_Click(Object sender, EventArgs e)
{
long totalCopied=CopySync(txtSource.Text,txtTarget.Text);
}
void btnCancel_Click(object sender, EventArgs e)
{
MessageBox.Show("UI 반응 테스트 성공");
}
}
}
using System.Security.Cryptography;
namespace AsyncFileIOWinForm
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
#region CopyMethod
async Task<long> CopyAsync(string FromPath, string ToPath)
{
btnSyncCopy.Enabled = false;
long totalCopied = 0;
using(FileStream fromStream=new FileStream(FromPath,FileMode.Open))
{
using (FileStream toStream = new FileStream(ToPath, FileMode.Create))
{
byte[] buffer = new byte[1024 * 1024];
int nRead = 0;
while ((nRead = await fromStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
await toStream.WriteAsync(buffer,0,nRead);
totalCopied += nRead;
pbCopy.Value=(int)(((double)totalCopied/(double)fromStream.Length)*pbCopy.Maximum);
}
}
}
btnSyncCopy.Enabled = true;
return totalCopied;
}
long CopySync(string FromPath, string ToPath)
{
btnSyncCopy.Enabled = false;
long totalCopied = 0;
using (FileStream fromStream = new FileStream(FromPath, FileMode.Open))
{
using (FileStream toStream = new FileStream(ToPath, FileMode.Create))
{
byte[] buffer = new byte[1024 * 1024];
int nRead = 0;
while ((nRead = fromStream.Read(buffer, 0, buffer.Length)) != 0)
{
toStream.Write(buffer, 0, nRead);
totalCopied += nRead;
pbCopy.Value = (int)(((double)totalCopied / (double)fromStream.Length) * pbCopy.Maximum);
}
}
}
btnSyncCopy.Enabled = true;
return totalCopied;
}
#endregion
void btnFindSource_Click(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
if(dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
txtSource.Text = dlg.FileName;
}
}
void btnFindTarget_Click(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
txtTarget.Text = dlg.FileName;
}
}
async void btnAsyncCopy_Click(object sender, EventArgs e)
{
long totalCopied = await CopyAsync(txtSource.Text,txtTarget.Text);
}
void btnSyncCopy_Click(Object sender, EventArgs e)
{
long totalCopied=CopySync(txtSource.Text,txtTarget.Text);
}
void btnCancel_Click(object sender, EventArgs e)
{
MessageBox.Show("UI 반응 테스트 성공");
}
}
}
'C# > 이것이 C#이다' 카테고리의 다른 글
[ 이것이 C#이다 ] Chapter 22. 가비지 컬렉션 (0) | 2024.04.22 |
---|---|
[ 이것이 C#이다 ] Chapter 19. 스레드와 태스크 (0) | 2024.04.12 |
[ 이것이 C#이다 ] Chapter 18. 파일 다루기 (0) | 2024.04.11 |
[ 이것이 C#이다 ] Chapter 16 . 리플렉션과 애트리뷰트 (0) | 2024.04.02 |
[ 이것이 C#이다 ] Chapter 15 . LINQ (0) | 2024.03.27 |