diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/1.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/1.png new file mode 100644 index 0000000..db083a1 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/1.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/10.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/10.png new file mode 100644 index 0000000..566743a Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/10.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/11.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/11.png new file mode 100644 index 0000000..96fb177 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/11.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/12.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/12.png new file mode 100644 index 0000000..4c38ce5 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/12.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/13.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/13.png new file mode 100644 index 0000000..8bf43f4 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/13.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/14.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/14.png new file mode 100644 index 0000000..7b03a48 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/14.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/15.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/15.png new file mode 100644 index 0000000..f9752ff Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/15.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/2.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/2.png new file mode 100644 index 0000000..06986b4 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/2.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/3.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/3.png new file mode 100644 index 0000000..3a1f3fe Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/3.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/4.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/4.png new file mode 100644 index 0000000..10e38d3 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/4.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/5.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/5.png new file mode 100644 index 0000000..bb02bd5 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/5.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/6.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/6.png new file mode 100644 index 0000000..d7d53b2 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/6.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/7.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/7.png new file mode 100644 index 0000000..35645f2 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/7.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/8.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/8.png new file mode 100644 index 0000000..fd9e4b4 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/8.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/9.png b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/9.png new file mode 100644 index 0000000..3c15d01 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/images/9.png differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/index.md b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/index.md new file mode 100644 index 0000000..2fcc33c --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/index.md @@ -0,0 +1,88 @@ +# Anchor, Dock을 이용한 컨트롤 레이아웃 디자인 +Windows Forms에서는 Anchor 및 Dock 속성을 통해 컨트롤 배치에 대한 제어를 할 수 있습니다. 의외로 Anchor와 Dock의 기능에 대해서 모르시는 분들이 많은데요, 이 기능을 이용하면 어떤 편리함이 생기는지 알아봅시다. + +![Anchor, Dock 속성](images/1.png) + +## 테스트 환경 +- Visual Studio 2019 +- .NET 5, C# 9 +- Windows Forms + +## 왜 필요하지? +`Form`에 컨트롤들을 배치하게 되면 프로그램이 완성되었을 때 작은 프로그램이라 하더라도 대략 50여개 이상의 컨트롤이 배치가 됩니다. 그런데 원래 800x600 사이즈의 요청으로 만들어졌는데, 화면이 작다고 1024x1080 사이즈로 바꾸라고 할 때 여러분은 컨트롤들을 변경된 화면 사이즈에 맞게 일일이 옮기셨나요? 그랬다면, Anchor와 Dock 속성을 알아야만 합니다. + +![사용하지 않는다면1](images/2.png "자 늘려보자") + +![사용하지 않는다면2](images/3.png "이런!") + +## Anchor에 대해 알아보자 +`Anchor`속성은 부모 컨테이너의 사이즈가 변경되었을 때 컨트롤의 위치와 사이즈가 어떻게 반응할지를 결정합니다. Anchor로 설정할 수 있는 값은 총 4개이며 `Left, Top, Right, Bottom`인데요, Form에 아무 컨트롤이나 배치한 후 `Anchor`속성을 보면 `Left, Top`임을 알 수 있습니다. + +![Anchor속성](images/4.png "Left, Top") + +Anchor 속성을 변경하려 할 때 다음의 화면을 볼 수 있는데요, + +![Anchor설정](images/5.png "Left, Top이 설정된 모습") + +이 의미는 Left와 Top의 위치를 고정하겠다는 것입니다. 즉, `Form`의 사이즈를 늘리거나 줄여도 그 자리 그대로 있는 컨트롤을 배치할 수 있습니다. + +그렇다면 Right와 Bottom으로 `Anchor`속성을 주었을때는 어떻게 될까요? 네. 컨트롤은 사이즈는 고정이되 늘어난 `Form` 만큼 따라 움직이는 것을 알 수 있습니다. + +![Right, Bottom을 준 저장, 불러오기 버튼](images/6.png "저장, 불러오기 버튼이 따라 움직임") + +- `Anchor`에 아무런 설정이 없을 경우 사이즈는 변하지 않지만 위치가 따라 변합니다. +- `Anchor`에 `Left, Top, Right, Bottom`을 모두 주었을 경우 위치는 변하지 않고 컨트롤 사이즈가 따라 변합니다. + +![다양한 Anchor적용1](images/7.png "Form 사이즈 조정 전") + +![다양한 Anchor적용2](images/8.png "Form 사이즈 조정 후") + +## Dock에 대해 알아보자 +`Dock`속성은 컨트롤을 부모 컨테이너의 `Left, Top, Right, Bottom, 또는 Fill`의 값으로 왼쪽, 상단, 오른족, 하단 또는 전체에 배치할 수 있게 합니다. 즉, `Dock`을 사용하면 위치를 사용하지 않고 사이즈만 사용하게 되는데요, `Fill` 설정의 경우 사이즈도 사용하지 않게 됩니다. + +- `Dock`이 `Left`일 경우 + + ![Dock이 Left일 때](images/9.png) + +- `Dock`이 `Top`일 경우 + + ![Dock이 Top일 때](images/10.png) + +- `Dock`이 `Right`일 경우 + + ![Dock이 Right일 떄](images/11.png) + +- `Dock`이 `Bottom`일 경우 + + ![Dock이 Bottom일 때](images/12.png) + +- `Dock`이 `Fill`일 경우 + + ![Dock이 Fill일 때](images/13.png) + +`Dock`은 특히 컨트롤의 순서에 따라 중첩될 수 있습니다. 사실 이 특징을 이용해 다양한 응용을 할 수 있게 됩니다. + +- 상단, 하단 고정, 중앙 반응사이즈로 하고 싶을 경우, + + ![상단, 하단 고정, 중앙 반응사이즈](images/14.png) + +- 입력 폼을 이쁘게 배치하고 싶을 경우 + + ![입력폼을 이쁘게](images/15.png) + + +## 어떨 때 Anchor를 쓰고 Dock을 쓰면 될까? +- `Form` 사이즈를 자유롭게 움직여도 여전히 보기좋은 컨트롤 배치를 원할 때 `Anchor`를 씁니다. +- `Form`에 다양한 고정 분할 구성을 하고 싶을 때 `Dock`을 씁니다. + - 분할 구성을 위해 `SplitContainer`를 대신 쓸 수 도 있습니다. +- 보기좋게 컨트롤들을 행으로 표현하고 싶을 때 `Dock`을 씁니다. + +## 정리 +이제 `Anchor`, `Dock` 기능을 이용해서 컨트롤 배치를 효율적이고 보기좋게 할 수 있음을 알게 되었습니다. 특히 `Dock`의 경우 분할 레이아웃을 구성하거나 컨트롤들을 행으로 일관되게 보여지게 할 수 있음을 알게 되었습니다. + +## 샘플 +- 위의 화면은 샘플에서 직접 확인할 수 있습니다. + - [예제 샘플](sample/sample.zip) + +## 문서 기여자 +- 작성한 사람: 디모이(dimohy) diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/.gitattributes b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/.gitignore b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/.gitignore new file mode 100644 index 0000000..9491a2f --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/.gitignore @@ -0,0 +1,363 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample.sln b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample.sln new file mode 100644 index 0000000..fb1ad32 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31105.61 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sample", "sample\sample.csproj", "{28D8F50F-0075-4139-AC61-7A341CA3626F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {28D8F50F-0075-4139-AC61-7A341CA3626F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28D8F50F-0075-4139-AC61-7A341CA3626F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28D8F50F-0075-4139-AC61-7A341CA3626F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28D8F50F-0075-4139-AC61-7A341CA3626F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B1B9F3C3-D7B9-4273-818C-41D59EE6F6D0} + EndGlobalSection +EndGlobal diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample.zip b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample.zip new file mode 100644 index 0000000..d5e3f83 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample.zip differ diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form1.Designer.cs b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form1.Designer.cs new file mode 100644 index 0000000..78124e3 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form1.Designer.cs @@ -0,0 +1,138 @@ + +namespace sample +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.dataGridView1 = new System.Windows.Forms.DataGridView(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); + this.SuspendLayout(); + // + // button1 + // + this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.button1.Location = new System.Drawing.Point(452, 348); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(92, 29); + this.button1.TabIndex = 0; + this.button1.Text = "저장"; + this.button1.UseVisualStyleBackColor = true; + // + // button2 + // + this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.button2.Location = new System.Drawing.Point(550, 348); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(92, 29); + this.button2.TabIndex = 1; + this.button2.Text = "불러오기"; + this.button2.UseVisualStyleBackColor = true; + // + // dataGridView1 + // + this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dataGridView1.Location = new System.Drawing.Point(12, 35); + this.dataGridView1.Name = "dataGridView1"; + this.dataGridView1.RowTemplate.Height = 25; + this.dataGridView1.Size = new System.Drawing.Size(534, 167); + this.dataGridView1.TabIndex = 2; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 17); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(59, 15); + this.label1.TabIndex = 3; + this.label1.Text = "직원 목록"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(12, 229); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(101, 15); + this.label2.TabIndex = 4; + this.label2.Text = "현재 시각 : 08:55"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(338, 229); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(101, 15); + this.label3.TabIndex = 4; + this.label3.Text = "출근 기준 : 09:00"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(445, 229); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(101, 15); + this.label4.TabIndex = 4; + this.label4.Text = "퇴근 기준 : 18:00"; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(654, 389); + this.Controls.Add(this.label4); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.dataGridView1); + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.Name = "Form1"; + this.Text = "직원 근태관리"; + ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.DataGridView dataGridView1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + } +} + diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form1.cs b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form1.cs new file mode 100644 index 0000000..1a5e56c --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form1.cs @@ -0,0 +1,21 @@ +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 sample +{ + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + } + + } +} diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form1.resx b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form1.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form1.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form2.Designer.cs b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form2.Designer.cs new file mode 100644 index 0000000..b861609 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form2.Designer.cs @@ -0,0 +1,101 @@ + +namespace sample +{ + partial class Form2 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.button4 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(12, 12); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(147, 46); + this.button1.TabIndex = 0; + this.button1.Text = "Anchor 기본 (Left, Top)"; + this.button1.UseVisualStyleBackColor = true; + // + // button2 + // + this.button2.Anchor = System.Windows.Forms.AnchorStyles.None; + this.button2.Location = new System.Drawing.Point(83, 131); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(147, 46); + this.button2.TabIndex = 1; + this.button2.Text = "Anchor 없음"; + this.button2.UseVisualStyleBackColor = true; + // + // button3 + // + this.button3.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.button3.Location = new System.Drawing.Point(193, 36); + this.button3.Name = "button3"; + this.button3.Size = new System.Drawing.Size(430, 268); + this.button3.TabIndex = 2; + this.button3.Text = "Anchor 전체 (Left, Top, Right, Bottom)"; + this.button3.UseVisualStyleBackColor = true; + // + // button4 + // + this.button4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.button4.Location = new System.Drawing.Point(544, 339); + this.button4.Name = "button4"; + this.button4.Size = new System.Drawing.Size(147, 46); + this.button4.TabIndex = 3; + this.button4.Text = "Anchor (Right, Bottom)"; + this.button4.UseVisualStyleBackColor = true; + // + // Form2 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(703, 397); + this.Controls.Add(this.button2); + this.Controls.Add(this.button4); + this.Controls.Add(this.button3); + this.Controls.Add(this.button1); + this.Name = "Form2"; + this.Text = "Form2"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.Button button4; + } +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form2.cs b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form2.cs new file mode 100644 index 0000000..6ddb269 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form2.cs @@ -0,0 +1,20 @@ +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 sample +{ + public partial class Form2 : Form + { + public Form2() + { + InitializeComponent(); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form2.resx b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form2.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form2.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form3.Designer.cs b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form3.Designer.cs new file mode 100644 index 0000000..9bd3c43 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form3.Designer.cs @@ -0,0 +1,61 @@ + +namespace sample +{ + partial class Form3 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.button1 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // button1 + // + this.button1.Dock = System.Windows.Forms.DockStyle.Fill; + this.button1.Location = new System.Drawing.Point(0, 0); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(397, 271); + this.button1.TabIndex = 0; + this.button1.Text = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // Form3 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(397, 271); + this.Controls.Add(this.button1); + this.Name = "Form3"; + this.Text = "Form3"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button button1; + } +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form3.cs b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form3.cs new file mode 100644 index 0000000..62d40bc --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form3.cs @@ -0,0 +1,20 @@ +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 sample +{ + public partial class Form3 : Form + { + public Form3() + { + InitializeComponent(); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form3.resx b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form3.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form3.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form4.Designer.cs b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form4.Designer.cs new file mode 100644 index 0000000..daec982 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form4.Designer.cs @@ -0,0 +1,90 @@ + +namespace sample +{ + partial class Form4 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label1 + // + this.label1.BackColor = System.Drawing.Color.DarkOrange; + this.label1.Dock = System.Windows.Forms.DockStyle.Top; + this.label1.Location = new System.Drawing.Point(0, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(512, 100); + this.label1.TabIndex = 3; + this.label1.Text = "Dock: Top"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // label2 + // + this.label2.BackColor = System.Drawing.Color.DarkOrchid; + this.label2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.label2.Location = new System.Drawing.Point(0, 292); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(512, 100); + this.label2.TabIndex = 4; + this.label2.Text = "Dock: Bottom"; + this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // label3 + // + this.label3.BackColor = System.Drawing.Color.Turquoise; + this.label3.Dock = System.Windows.Forms.DockStyle.Fill; + this.label3.Location = new System.Drawing.Point(0, 100); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(512, 192); + this.label3.TabIndex = 5; + this.label3.Text = "Dock: Fill"; + this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // Form4 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(512, 392); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Name = "Form4"; + this.Text = "Form4"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + } +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form4.cs b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form4.cs new file mode 100644 index 0000000..f6166ad --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form4.cs @@ -0,0 +1,20 @@ +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 sample +{ + public partial class Form4 : Form + { + public Form4() + { + InitializeComponent(); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form4.resx b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form4.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form4.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form5.Designer.cs b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form5.Designer.cs new file mode 100644 index 0000000..9fadd05 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form5.Designer.cs @@ -0,0 +1,189 @@ + +namespace sample +{ + partial class Form5 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.panel1 = new System.Windows.Forms.Panel(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.panel2 = new System.Windows.Forms.Panel(); + this.textBox4 = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.panel1.SuspendLayout(); + this.panel2.SuspendLayout(); + this.SuspendLayout(); + // + // panel1 + // + this.panel1.Controls.Add(this.textBox2); + this.panel1.Controls.Add(this.label3); + this.panel1.Controls.Add(this.textBox1); + this.panel1.Controls.Add(this.label2); + this.panel1.Dock = System.Windows.Forms.DockStyle.Top; + this.panel1.Location = new System.Drawing.Point(10, 74); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(565, 24); + this.panel1.TabIndex = 0; + // + // textBox2 + // + this.textBox2.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBox2.Location = new System.Drawing.Point(210, 0); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(355, 23); + this.textBox2.TabIndex = 3; + // + // label3 + // + this.label3.Dock = System.Windows.Forms.DockStyle.Left; + this.label3.Location = new System.Drawing.Point(155, 0); + this.label3.Name = "label3"; + this.label3.Padding = new System.Windows.Forms.Padding(10, 0, 0, 0); + this.label3.Size = new System.Drawing.Size(55, 24); + this.label3.TabIndex = 2; + this.label3.Text = "나이"; + this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // textBox1 + // + this.textBox1.Dock = System.Windows.Forms.DockStyle.Left; + this.textBox1.Location = new System.Drawing.Point(55, 0); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(100, 23); + this.textBox1.TabIndex = 1; + // + // label2 + // + this.label2.Dock = System.Windows.Forms.DockStyle.Left; + this.label2.Location = new System.Drawing.Point(0, 0); + this.label2.Name = "label2"; + this.label2.Padding = new System.Windows.Forms.Padding(10, 0, 0, 0); + this.label2.Size = new System.Drawing.Size(55, 24); + this.label2.TabIndex = 0; + this.label2.Text = "이름"; + this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // label1 + // + this.label1.BackColor = System.Drawing.SystemColors.ActiveCaption; + this.label1.Dock = System.Windows.Forms.DockStyle.Top; + this.label1.Location = new System.Drawing.Point(10, 10); + this.label1.Name = "label1"; + this.label1.Padding = new System.Windows.Forms.Padding(10, 0, 0, 0); + this.label1.Size = new System.Drawing.Size(565, 32); + this.label1.TabIndex = 1; + this.label1.Text = "기본정보"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // panel2 + // + this.panel2.Controls.Add(this.textBox4); + this.panel2.Controls.Add(this.label5); + this.panel2.Dock = System.Windows.Forms.DockStyle.Top; + this.panel2.Location = new System.Drawing.Point(10, 46); + this.panel2.Name = "panel2"; + this.panel2.Size = new System.Drawing.Size(565, 24); + this.panel2.TabIndex = 2; + // + // textBox4 + // + this.textBox4.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBox4.Location = new System.Drawing.Point(55, 0); + this.textBox4.Name = "textBox4"; + this.textBox4.Size = new System.Drawing.Size(510, 23); + this.textBox4.TabIndex = 1; + // + // label5 + // + this.label5.Dock = System.Windows.Forms.DockStyle.Left; + this.label5.Location = new System.Drawing.Point(0, 0); + this.label5.Name = "label5"; + this.label5.Padding = new System.Windows.Forms.Padding(10, 0, 0, 0); + this.label5.Size = new System.Drawing.Size(55, 24); + this.label5.TabIndex = 0; + this.label5.Text = "이메일"; + this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // label4 + // + this.label4.Dock = System.Windows.Forms.DockStyle.Top; + this.label4.Location = new System.Drawing.Point(10, 70); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(565, 4); + this.label4.TabIndex = 3; + // + // label6 + // + this.label6.Dock = System.Windows.Forms.DockStyle.Top; + this.label6.Location = new System.Drawing.Point(10, 42); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(565, 4); + this.label6.TabIndex = 4; + // + // Form5 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(585, 437); + this.Controls.Add(this.panel1); + this.Controls.Add(this.label4); + this.Controls.Add(this.panel2); + this.Controls.Add(this.label6); + this.Controls.Add(this.label1); + this.Name = "Form5"; + this.Padding = new System.Windows.Forms.Padding(10); + this.Text = "Form5"; + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.panel2.ResumeLayout(false); + this.panel2.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Panel panel2; + private System.Windows.Forms.TextBox textBox4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label6; + } +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form5.cs b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form5.cs new file mode 100644 index 0000000..f17a792 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form5.cs @@ -0,0 +1,20 @@ +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 sample +{ + public partial class Form5 : Form + { + public Form5() + { + InitializeComponent(); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form5.resx b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form5.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Form5.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Program.cs b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Program.cs new file mode 100644 index 0000000..a25a85c --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/Program.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace sample +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.SetHighDpiMode(HighDpiMode.SystemAware); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + //Application.Run(new Form1()); + //Application.Run(new Form2()); + //Application.Run(new Form3()); + Application.Run(new Form5()); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/sample.csproj b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/sample.csproj new file mode 100644 index 0000000..a2d4310 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/1.DesignControlLayout/sample/sample/sample.csproj @@ -0,0 +1,9 @@ + + + + WinExe + net5.0-windows + true + + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/.vscode/launch.json b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/.vscode/launch.json new file mode 100644 index 0000000..64195d9 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/.vscode/launch.json @@ -0,0 +1,27 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/sample/ConsoleSample/ConsoleSample/bin/Debug/net5.0/ConsoleSample.dll", + "args": [], + "cwd": "${workspaceFolder}/sample/ConsoleSample/ConsoleSample", + // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ] +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/.vscode/tasks.json b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/.vscode/tasks.json new file mode 100644 index 0000000..705c3f2 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/.vscode/tasks.json @@ -0,0 +1,42 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/sample/ConsoleSample/ConsoleSample/ConsoleSample.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/sample/ConsoleSample/ConsoleSample/ConsoleSample.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "${workspaceFolder}/sample/ConsoleSample/ConsoleSample/ConsoleSample.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/1.png b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/1.png new file mode 100644 index 0000000..14e74d3 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/1.png differ diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/2.png b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/2.png new file mode 100644 index 0000000..058714c Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/2.png differ diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/3.png b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/3.png new file mode 100644 index 0000000..2b98668 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/3.png differ diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/4.png b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/4.png new file mode 100644 index 0000000..2c05d7e Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/4.png differ diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/5.png b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/5.png new file mode 100644 index 0000000..fbed861 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/5.png differ diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/6.png b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/6.png new file mode 100644 index 0000000..44c448a Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/6.png differ diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/7.png b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/7.png new file mode 100644 index 0000000..fce586f Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/images/7.png differ diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/index.md b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/index.md new file mode 100644 index 0000000..581e9cd --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/index.md @@ -0,0 +1,316 @@ +# 디자인패턴을 이용한 DLL 동적 로딩 +이번 장에서는 `디자인패턴을 이용해 DLL을 동적 로딩`하는 방법을 알아보고자 합니다. + +## 테스트 환경 +- Visual Studio 2019 +- .NET 5, C# 9 +- Console, Windows Forms + +## 왜 필요하지? +플러그인 또는 확장기능을 들어보셨다면, 바로 그 기능을 구현할 수 있다고 이해하시면 되겠습니다. 몇가지 예를 들어볼께요. +- 이미지 편집 프로그램을 만들었는데, 다양한 필터링 효과를 플러그인으로 제공하고 싶다. +- 모터를 이용하는 프로그램을 만들었는데, 다른 회사의 제품을 사용할 일이 생겼다. 그리고 계속 그럴일이 많을 것 같고 프로그램은 수정하고 싶지 않다. +- 응용 어플리케이션의 각 메뉴를 DLL 로 구성하고 싶다. 그리고 업데이트는 DLL 만 해도 되게 만들고 싶다. + +간단히 예를 들어보았는데요, 이런 기능을 구현하기 위해서 DLL을 동적으로 로딩해서 연결하는 구현을 해야 합니다. + +## DLL 동적로딩 +.NET 라이브러리에서 DLL(Dynamic Linked Library)를 `Assembly`로 동적 로딩하는 기능을 제공합니다. + +```csharp +var assembly = Assembly.LoadFrom(assemblyPath); +``` + +위의 메소드를 이용해도 되지만 `assembly`를 언로드 할 수 없어서 `AssemblyLoadContext`를 이용하는게 좋습니다. `AssemblyLoadContext`를 이용해 언로드 기능을 사용하기 위해서는 다음의 글을 참고하면 도움이 됩니다. + +> [.NET Core에서 어셈블리 언로드 기능을 사용하고 디버그하는 방법](https://docs.microsoft.com/ko-kr/dotnet/standard/assembly/unloadability) + +`AssemblyLoadContext`를 상속받아 적절히 구현한 후, + +```csharp +var assembly = myAssemblyLoadContext.LoadFromAssemblyPath(assemblypath); +``` + +그런다음 `assembly`를 통해 `Activator.CreateInstance(type)`등으로 클래스의 인스턴스를 생성할 수 있게 됩니다. + +그리고 동적 로딩한 어셈블리들을 `AssemblyLoadContext`단위로 `Unload`를 통해 로딩을 해제 할 수 있습니다. + +```csharp +myAssemblyLoadingContext.Unload(); +``` + +`Assembly`까지 얻어오면 이후 `Type`을 알면 동적으로 생성할 수 있는데요, 이때 디자인패턴 중 생성패턴을 이용해야 좀 더 범용적인 구조를 설계할 수 있습니다. + +## 디자인 패턴이란? +[디자인 패턴](https://ko.wikipedia.org/wiki/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4_%EB%94%94%EC%9E%90%EC%9D%B8_%ED%8C%A8%ED%84%B4)은 소프트웨어 디자인에서 공통으로 발생하는 문제를 구조적으로 해결하기 위한 프로그래밍 패턴 입니다. 특히 [GoF의 디자인패턴](https://ko.wikipedia.org/wiki/%EB%94%94%EC%9E%90%EC%9D%B8_%ED%8C%A8%ED%84%B4_(%EC%B1%85))에 의해 프로그래머에게 알려지게 되었습니다. + +디자인 패턴은 `생성패턴`, `구조패턴`, `행동패턴`으로 나눠 다양한 패턴들을 설명하고 있으며, 필요한 패턴을 코딩에 적용할 수 있습니다. + +처음 `디자인패턴`을 접하면, 어떻게 적용할지 막막할 수 있는데요, 제 경험으로는 `인터페이스`를 통해 코드와 코드간의 응집력을 최소화 하는 노력의 일환이라고 이해하면 좋을 것 같습니다. 그 관점으로 필요한 만큼 구조를 차용해서 쓰면 모듈화가 좀 더 되지 않을까 생각해 봅니다. + +## 빨리 확인해봅시다 +플러그인 구조를 빨리 확인하기 위해 콘솔 어플리케이션으로 진행을 해볼텐데요, [콘솔 예제](sample/ConsoleSample.zip)를 통해 다음과 같은 구조를 확인하실 수 있는데요, + +![솔루션 구조](images/1.png) + +``` + ConsoleSample - 테스트 프로그램 + MotorDriver - MotorDriverFactory, IMotorDriverFactory, IMotor + | + +- AMotorDriver - AMotorDriverFactory, AMotor + | + +- BMotorDriver - BMotorDriverFactory, BMotor +``` + +```csharp + /// + /// MotorDriver 인스턴스를 생성하는 팩토리 인터페이스 + /// + public interface IMotorDriverFactory + { + string DriverName { get; } + + IMotor Create(int id); + } + + /// + /// MotorDriver 인터페이스 + /// + public interface IMotor + { + int Id { get; } + + double Position { get; } + Task MoveAsync(double position); + Task ResetAsync(); + } +``` + +`AMotorDriver`와 `BMotorDriver`에서 각각 `IMotor`, `IMotorDriverFactory`를 구현합니다. + +```csharp + public class AMotor : IMotor + { + public int Id { get; private set; } + + public AMotor(int id) + { + this.Id = id; + } + + public double Position { get; private set; } + + public async Task MoveAsync(double position) + { + var sp = this.Position; + var ep = position; + + for (var i = sp; i <= ep; i++) + { + this.Position = i; + Console.WriteLine($"{i} 찌잉~"); + await Task.Delay(100); + } + } + + public async Task ResetAsync() + { + await Task.Yield(); + Position = 0; + } + } + + public class AMotorDriverFactory : IMotorDriverFactory + { + public string DriverName => "A Motor Driver"; + + public IMotor Create(int id) => new AMotor(id); + } +``` + +BMotorDriver는 AMotorDriver에 비해 움직이는 속도가 다르다는 것을 다음처럼 표현했습니다. `MoveAsync(position)`에서 +```csharp + ... + Console.WriteLine($"{i} 퓨웅~"); + await Task.Delay(10); + ... +``` + +그리고 드라이브명이 달라야 하므로, BMotorDriverFactory에서 `DriverName`이 +```csharp + public string DriverName => "B Motor Driver"; +``` + +이부분만 다르고 나머지는 동일합니다. + +실제 모터의 구동은 모터 운동 가감속도, 영점, 상태, 기어비 등 좀 더 복잡하고 다양한 예외처리가 필요하겠지만, 구조를 표현하기 위해 기능은 구분될 정도로만 간단하게 표현했습니다. + +이제 `IMotorFactory`를 구현한 DLL을 읽는 `MotorFactor`를 구현해야 하는데요, 소스코드는 다음과 같습니다. + +```csharp + public class MotorFactory + { + private Dictionary motorFactoryMap; + + public MotorFactory(string driverPath) + { + Load(driverPath); + } + + public IMotor Create(string driverName, int id) + { + var bResult = motorFactoryMap.TryGetValue(driverName, out var motorFactory); + if (bResult == true) + return motorFactory.Create(id); + + return null; + } + + private void Load(string driverPath) + { + motorFactoryMap = new(); + + var motorDriverDlls = Directory.GetFiles(driverPath, "*.dll"); + foreach (var motorDriverDll in motorDriverDlls) + { + var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(motorDriverDll); + var factoryType = assembly.GetTypes().Where(x => typeof(IMotorDriverFactory).IsAssignableFrom(x) == true).FirstOrDefault(); + if (factoryType == default) + continue; + + var factory = Activator.CreateInstance(factoryType) as IMotorDriverFactory; + motorFactoryMap[factory.DriverName] = factory; + } + } + + public IEnumerable GetDriverNames() => motorFactoryMap.Keys; + } +``` + +MotorDriverFactory는 DLL에서 `IMotorFactory`를 구현한 클래스를 찾아 인스턴스를 만들고, `Create` 메소드를 호출할 때 해당 인스턴스를 통해 해당 DLL의 모터 인스턴스를 생성해서 반환할 수 있게 됩니다. + +### 테스트 코드 +```csharp +using System; +using System.IO; +using System.Reflection; +using MotorDriver; + + +var driverPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Driver"); +var motorDriverFactory = new MotorFactory(driverPath); + +// 총 두개의 모터 드라이버 검색 됨 +foreach (var driverName in motorDriverFactory.GetDriverNames()) + Console.WriteLine(driverName); + +// 각각의 모터 드라이버에서 모터 생성 +var motor1 = motorDriverFactory.Create("A Motor Driver", 1); +var motor2 = motorDriverFactory.Create("B Motor Driver", 2); + +// 모터 이동 +await motor1.MoveAsync(20); +await motor2.MoveAsync(20); +``` +### 실행화면 +![실행화면](images/2.png) + +## Windows Forms에도 DLL에서 동적으로 화면을 가져올 수 있을까요? +당연히 가능합니다. UI 어플리케이션에서 플러그인을 추가하면 설정메뉴에서 해당 플러그인의 설정이 추가된다던가, 플러그인에서 제공하면 화면이 추가된다던가 하는것을 보셨을 텐데요, 원리는 위의 콘솔 예제와 동일합니다. + +`UserControl` 형태로 플러그인에서 화면을 만들고, 콘솔 예제와 동일한 팩토리패턴을 이용해 본 어플리케이션에서 인스턴스를 생성할 수 있게 해주면 되는데요, 위의 예제를 수정해서 간단히 구현해보도록 합시다. + +코드가 중복되므로 중요 내용만 보도록 합시다. + +### 화면구성 +![화면구성](images/3.png) + +`플러그인 로딩` 버튼을 클릭하면 왼쪽과 오른쪽 패널에 각각 로딩된 페이지가 표시되도록 구성합니다. + +`AMotorPage`는 간단히 라벨로 표현했습니다. + +![AMotorPage](images/4.png) + +`BMotorPage`도 간단히 라벨로 표현했습니다. + +![BMotorPage](images/5.png) + +`MotorPageFactor`및 `IMotorPage` 인터페이스 +```csharp + /// + /// IMotorPage 인스턴스를 생성하는 팩토리 인터페이스 + /// + public interface IMotorPageFactory + { + string DriverName { get; } + + IMotorPage Create(int id); + } + + /// + /// MotorDriver 인터페이스 + /// + public interface IMotorPage + { + int Id { get; } + + UserControl Page { get; } + } +``` + +`AMotor.cs`에서 `UserControl` 페이지를 반환하는 것으로 수정 +```csharp + public class AMotor : IMotorPage + { + public int Id { get; } + + public UserControl Page { get; } + + public AMotor(int id) + { + this.Id = id; + this.Page = new AMotorPage(); + } + } + + public class AMotorDriverFactory : IMotorPageFactory + { + public string DriverName => "A Motor Driver"; + + public IMotorPage Create(int id) => new AMotor(id); + } +``` + +`WinFormsSample`에서 버튼을 눌렀을 때 페이지를 로딩하여 화면에 보여주는 이벤트 +```csharp + private void button1_Click(object sender, EventArgs e) + { + var driverNames = factory.GetDriverNames(); + + var motor1Page = factory.Create(driverNames.First(), 1); + var motor2Page = factory.Create(driverNames.Last(), 2); + + motor1Page.Page.Dock = DockStyle.Fill; + splitContainer1.Panel1.Controls.Add(motor1Page.Page); + motor2Page.Page.Dock = DockStyle.Fill; + splitContainer1.Panel2.Controls.Add(motor2Page.Page); + } +``` + +### 실행화면 +초기 페이지 로딩 전 + +![초기 페이지 로딩 전](images/6.png) + +`플러그인 로딩` 버튼 클릭 후 + +![페이지로딩 후](images/7.png) + + +## 샘플 +- 위의 예제에 대한 완전한 소스코드는 다음의 링크로 다운로드 받아 실행해 보실 수 있습니다. + - [콘솔 예제](sample/ConsoleSample.zip) + - [윈폼 예제](sample/WinFormsSample.zip) + +## 문서 기여자 +- 작성한 사람: 디모이(dimohy) diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample.zip b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample.zip new file mode 100644 index 0000000..60491a5 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample.zip differ diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/.gitattributes b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/.gitignore b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/.gitignore new file mode 100644 index 0000000..9491a2f --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/.gitignore @@ -0,0 +1,363 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/AMotorDriver/AMotor.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/AMotorDriver/AMotor.cs new file mode 100644 index 0000000..5922b73 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/AMotorDriver/AMotor.cs @@ -0,0 +1,45 @@ +using Driver; + +using System; +using System.Threading.Tasks; + +namespace AMotorDriver +{ + public class AMotor : IMotor + { + public int Id { get; private set; } + + public AMotor(int id) + { + this.Id = id; + } + + public double Position { get; private set; } + + public async Task MoveAsync(double position) + { + var sp = this.Position; + var ep = position; + + for (var i = sp; i <= ep; i++) + { + this.Position = i; + Console.WriteLine($"{i} 찌잉~"); + await Task.Delay(100); + } + } + + public async Task ResetAsync() + { + await Task.Yield(); + Position = 0; + } + } + + public class AMotorDriverFactory : IMotorDriverFactory + { + public string DriverName => "A Motor Driver"; + + public IMotor Create(int id) => new AMotor(id); + } +} diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/AMotorDriver/AMotorDriver.csproj b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/AMotorDriver/AMotorDriver.csproj new file mode 100644 index 0000000..c0cfbe8 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/AMotorDriver/AMotorDriver.csproj @@ -0,0 +1,11 @@ + + + + net5.0 + + + + + + + diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/BMotorDriver/BMotor.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/BMotorDriver/BMotor.cs new file mode 100644 index 0000000..b7d717b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/BMotorDriver/BMotor.cs @@ -0,0 +1,45 @@ +using Driver; + +using System; +using System.Threading.Tasks; + +namespace BMorterDriver +{ + public class BMotor : IMotor + { + public int Id { get; private set; } + + public BMotor(int id) + { + this.Id = id; + } + + public double Position { get; private set; } + + public async Task MoveAsync(double position) + { + var sp = this.Position; + var ep = position; + + for (var i = sp; i <= ep; i++) + { + this.Position = i; + Console.WriteLine($"{i} 퓨웅~"); + await Task.Delay(10); + } + } + + public async Task ResetAsync() + { + await Task.Yield(); + Position = 0; + } + } + + public class BMotorDriverFactory : IMotorDriverFactory + { + public string DriverName => "B Motor Driver"; + + public IMotor Create(int id) => new BMotor(id); + } +} diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/BMotorDriver/BMotorDriver.csproj b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/BMotorDriver/BMotorDriver.csproj new file mode 100644 index 0000000..c0cfbe8 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/BMotorDriver/BMotorDriver.csproj @@ -0,0 +1,11 @@ + + + + net5.0 + + + + + + + diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample.sln b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample.sln new file mode 100644 index 0000000..2a42236 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31112.23 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleSample", "ConsoleSample\ConsoleSample.csproj", "{48B8AE29-BBD8-48D7-A27D-DF7C3BABD9BF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AMotorDriver", "AMotorDriver\AMotorDriver.csproj", "{F420A199-80A1-4C93-A7FA-A354A9625FD6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BMotorDriver", "BMotorDriver\BMotorDriver.csproj", "{3623835A-7848-4BD1-882D-6526EF339E97}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MotorDriver", "MotorDriver\MotorDriver.csproj", "{FCA9CE03-CB8D-4456-A9D7-4563DCB2A89A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {48B8AE29-BBD8-48D7-A27D-DF7C3BABD9BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {48B8AE29-BBD8-48D7-A27D-DF7C3BABD9BF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48B8AE29-BBD8-48D7-A27D-DF7C3BABD9BF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {48B8AE29-BBD8-48D7-A27D-DF7C3BABD9BF}.Release|Any CPU.Build.0 = Release|Any CPU + {F420A199-80A1-4C93-A7FA-A354A9625FD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F420A199-80A1-4C93-A7FA-A354A9625FD6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F420A199-80A1-4C93-A7FA-A354A9625FD6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F420A199-80A1-4C93-A7FA-A354A9625FD6}.Release|Any CPU.Build.0 = Release|Any CPU + {3623835A-7848-4BD1-882D-6526EF339E97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3623835A-7848-4BD1-882D-6526EF339E97}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3623835A-7848-4BD1-882D-6526EF339E97}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3623835A-7848-4BD1-882D-6526EF339E97}.Release|Any CPU.Build.0 = Release|Any CPU + {FCA9CE03-CB8D-4456-A9D7-4563DCB2A89A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FCA9CE03-CB8D-4456-A9D7-4563DCB2A89A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FCA9CE03-CB8D-4456-A9D7-4563DCB2A89A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FCA9CE03-CB8D-4456-A9D7-4563DCB2A89A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {48574564-5697-4679-95F9-48552C60082F} + EndGlobalSection +EndGlobal diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample/ConsoleSample.csproj b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample/ConsoleSample.csproj new file mode 100644 index 0000000..081ab10 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample/ConsoleSample.csproj @@ -0,0 +1,21 @@ + + + + Exe + net5.0 + + + + + + + + + PreserveNewest + + + PreserveNewest + + + + diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample/Driver/AMotorDriver.dll b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample/Driver/AMotorDriver.dll new file mode 100644 index 0000000..bf1e46d Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample/Driver/AMotorDriver.dll differ diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample/Driver/BMotorDriver.dll b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample/Driver/BMotorDriver.dll new file mode 100644 index 0000000..902b762 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample/Driver/BMotorDriver.dll differ diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample/Program.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample/Program.cs new file mode 100644 index 0000000..1f74fb3 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/ConsoleSample/Program.cs @@ -0,0 +1,20 @@ +using System; +using System.IO; +using System.Reflection; +using MotorDriver; + + +var driverPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Driver"); +var motorDriverFactory = new MotorFactory(driverPath); + +// 총 두개의 모터 드라이버 검색 됨 +foreach (var driverName in motorDriverFactory.GetDriverNames()) + Console.WriteLine(driverName); + +// 각각의 모터 드라이버에서 모터 생성 +var motor1 = motorDriverFactory.Create("A Motor Driver", 1); +var motor2 = motorDriverFactory.Create("B Motor Driver", 2); + +// 모터 이동 +await motor1.MoveAsync(20); +await motor2.MoveAsync(20); diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/MotorDriver/IMotor.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/MotorDriver/IMotor.cs new file mode 100644 index 0000000..ceb6d49 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/MotorDriver/IMotor.cs @@ -0,0 +1,27 @@ +using System; +using System.Threading.Tasks; + +namespace Driver +{ + /// + /// MotorDriver 인스턴스를 생성하는 팩토리 인터페이스 + /// + public interface IMotorDriverFactory + { + string DriverName { get; } + + IMotor Create(int id); + } + + /// + /// MotorDriver 인터페이스 + /// + public interface IMotor + { + int Id { get; } + + double Position { get; } + Task MoveAsync(double position); + Task ResetAsync(); + } +} diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/MotorDriver/MotorDriver.csproj b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/MotorDriver/MotorDriver.csproj new file mode 100644 index 0000000..f208d30 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/MotorDriver/MotorDriver.csproj @@ -0,0 +1,7 @@ + + + + net5.0 + + + diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/MotorDriver/MotorFactory.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/MotorDriver/MotorFactory.cs new file mode 100644 index 0000000..5c21662 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/ConsoleSample/MotorDriver/MotorFactory.cs @@ -0,0 +1,47 @@ +using Driver; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Loader; + +namespace MotorDriver +{ + public class MotorFactory + { + private Dictionary motorFactoryMap; + + public MotorFactory(string driverPath) + { + Load(driverPath); + } + + public IMotor Create(string driverName, int id) + { + var bResult = motorFactoryMap.TryGetValue(driverName, out var motorFactory); + if (bResult == true) + return motorFactory.Create(id); + + return null; + } + + private void Load(string driverPath) + { + motorFactoryMap = new(); + + var motorDriverDlls = Directory.GetFiles(driverPath, "*.dll"); + foreach (var motorDriverDll in motorDriverDlls) + { + var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(motorDriverDll); + var factoryType = assembly.GetTypes().Where(x => typeof(IMotorDriverFactory).IsAssignableFrom(x) == true).FirstOrDefault(); + if (factoryType == default) + continue; + + var factory = Activator.CreateInstance(factoryType) as IMotorDriverFactory; + motorFactoryMap[factory.DriverName] = factory; + } + } + + public IEnumerable GetDriverNames() => motorFactoryMap.Keys; + } +} diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample.zip b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample.zip new file mode 100644 index 0000000..7590830 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample.zip differ diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/.gitattributes b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/.gitignore b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/.gitignore new file mode 100644 index 0000000..9491a2f --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/.gitignore @@ -0,0 +1,363 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotor.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotor.cs new file mode 100644 index 0000000..aed1724 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotor.cs @@ -0,0 +1,28 @@ +using Driver; + +using System; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace AMotorDriver +{ + public class AMotor : IMotorPage + { + public int Id { get; } + + public UserControl Page { get; } + + public AMotor(int id) + { + this.Id = id; + this.Page = new AMotorPage(); + } + } + + public class AMotorDriverFactory : IMotorPageFactory + { + public string DriverName => "A Motor Driver"; + + public IMotorPage Create(int id) => new AMotor(id); + } +} diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotorDriver.csproj b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotorDriver.csproj new file mode 100644 index 0000000..bb0ffbc --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotorDriver.csproj @@ -0,0 +1,12 @@ + + + + net5.0-windows + true + + + + + + + diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotorPage.Designer.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotorPage.Designer.cs new file mode 100644 index 0000000..37e9df6 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotorPage.Designer.cs @@ -0,0 +1,60 @@ + +namespace AMotorDriver +{ + partial class AMotorPage + { + /// + /// 필수 디자이너 변수입니다. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 사용 중인 모든 리소스를 정리합니다. + /// + /// 관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 구성 요소 디자이너에서 생성한 코드 + + /// + /// 디자이너 지원에 필요한 메서드입니다. + /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label1 + // + this.label1.Dock = System.Windows.Forms.DockStyle.Fill; + this.label1.Location = new System.Drawing.Point(0, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(408, 284); + this.label1.TabIndex = 0; + this.label1.Text = "A Motor Page"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // AMotorPage + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.label1); + this.Name = "AMotorPage"; + this.Size = new System.Drawing.Size(408, 284); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label label1; + } +} diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotorPage.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotorPage.cs new file mode 100644 index 0000000..9c84b7f --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotorPage.cs @@ -0,0 +1,20 @@ +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 AMotorDriver +{ + public partial class AMotorPage : UserControl + { + public AMotorPage() + { + InitializeComponent(); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotorPage.resx b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotorPage.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/AMotorDriver/AMotorPage.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotor.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotor.cs new file mode 100644 index 0000000..8ab03a2 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotor.cs @@ -0,0 +1,28 @@ +using Driver; + +using System; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace BMotorDriver +{ + public class BMotor : IMotorPage + { + public int Id { get; } + + public UserControl Page { get; } + + public BMotor(int id) + { + this.Id = id; + this.Page = new BMotorPage(); + } + } + + public class BMotorDriverFactory : IMotorPageFactory + { + public string DriverName => "B Motor Driver"; + + public IMotorPage Create(int id) => new BMotor(id); + } +} diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotorDriver.csproj b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotorDriver.csproj new file mode 100644 index 0000000..c6314f7 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotorDriver.csproj @@ -0,0 +1,18 @@ + + + + net5.0-windows + true + + + + + + + + + UserControl + + + + diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotorPage.Designer.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotorPage.Designer.cs new file mode 100644 index 0000000..0f37c99 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotorPage.Designer.cs @@ -0,0 +1,60 @@ + +namespace BMotorDriver +{ + partial class BMotorPage + { + /// + /// 필수 디자이너 변수입니다. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 사용 중인 모든 리소스를 정리합니다. + /// + /// 관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 구성 요소 디자이너에서 생성한 코드 + + /// + /// 디자이너 지원에 필요한 메서드입니다. + /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label1 + // + this.label1.Dock = System.Windows.Forms.DockStyle.Fill; + this.label1.Location = new System.Drawing.Point(0, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(408, 284); + this.label1.TabIndex = 0; + this.label1.Text = "B Motor Page"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // AMotorPage + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.label1); + this.Name = "AMotorPage"; + this.Size = new System.Drawing.Size(408, 284); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label label1; + } +} diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotorPage.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotorPage.cs new file mode 100644 index 0000000..a1188c0 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotorPage.cs @@ -0,0 +1,20 @@ +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 BMotorDriver +{ + public partial class BMotorPage : UserControl + { + public BMotorPage() + { + InitializeComponent(); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotorPage.resx b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotorPage.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/BMotorDriver/BMotorPage.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/MotorDriver/IMotorPage.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/MotorDriver/IMotorPage.cs new file mode 100644 index 0000000..42b64bd --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/MotorDriver/IMotorPage.cs @@ -0,0 +1,26 @@ +using System; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Driver +{ + /// + /// IMotorPage 인스턴스를 생성하는 팩토리 인터페이스 + /// + public interface IMotorPageFactory + { + string DriverName { get; } + + IMotorPage Create(int id); + } + + /// + /// MotorDriver 인터페이스 + /// + public interface IMotorPage + { + int Id { get; } + + UserControl Page { get; } + } +} diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/MotorDriver/MotorDriver.csproj b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/MotorDriver/MotorDriver.csproj new file mode 100644 index 0000000..f30fa1b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/MotorDriver/MotorDriver.csproj @@ -0,0 +1,8 @@ + + + + net5.0-windows + true + + + diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/MotorDriver/MotorFactory.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/MotorDriver/MotorFactory.cs new file mode 100644 index 0000000..72ebb07 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/MotorDriver/MotorFactory.cs @@ -0,0 +1,47 @@ +using Driver; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Loader; + +namespace MotorDriver +{ + public class MotorFactory + { + private Dictionary motorFactoryMap; + + public MotorFactory(string driverPath) + { + Load(driverPath); + } + + public IMotorPage Create(string driverName, int id) + { + var bResult = motorFactoryMap.TryGetValue(driverName, out var motorFactory); + if (bResult == true) + return motorFactory.Create(id); + + return null; + } + + private void Load(string driverPath) + { + motorFactoryMap = new(); + + var motorDriverDlls = Directory.GetFiles(driverPath, "*.dll"); + foreach (var motorDriverDll in motorDriverDlls) + { + var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(motorDriverDll); + var factoryType = assembly.GetTypes().Where(x => typeof(IMotorPageFactory).IsAssignableFrom(x) == true).FirstOrDefault(); + if (factoryType == default) + continue; + + var factory = Activator.CreateInstance(factoryType) as IMotorPageFactory; + motorFactoryMap[factory.DriverName] = factory; + } + } + + public IEnumerable GetDriverNames() => motorFactoryMap.Keys; + } +} diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample.sln b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample.sln new file mode 100644 index 0000000..a117343 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31112.23 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AMotorDriver", "AMotorDriver\AMotorDriver.csproj", "{F420A199-80A1-4C93-A7FA-A354A9625FD6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BMotorDriver", "BMotorDriver\BMotorDriver.csproj", "{3623835A-7848-4BD1-882D-6526EF339E97}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MotorDriver", "MotorDriver\MotorDriver.csproj", "{FCA9CE03-CB8D-4456-A9D7-4563DCB2A89A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinFormsSample", "WinFormsSample\WinFormsSample.csproj", "{DFB9F100-7C85-4168-8422-F2247088F6EC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F420A199-80A1-4C93-A7FA-A354A9625FD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F420A199-80A1-4C93-A7FA-A354A9625FD6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F420A199-80A1-4C93-A7FA-A354A9625FD6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F420A199-80A1-4C93-A7FA-A354A9625FD6}.Release|Any CPU.Build.0 = Release|Any CPU + {3623835A-7848-4BD1-882D-6526EF339E97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3623835A-7848-4BD1-882D-6526EF339E97}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3623835A-7848-4BD1-882D-6526EF339E97}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3623835A-7848-4BD1-882D-6526EF339E97}.Release|Any CPU.Build.0 = Release|Any CPU + {FCA9CE03-CB8D-4456-A9D7-4563DCB2A89A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FCA9CE03-CB8D-4456-A9D7-4563DCB2A89A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FCA9CE03-CB8D-4456-A9D7-4563DCB2A89A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FCA9CE03-CB8D-4456-A9D7-4563DCB2A89A}.Release|Any CPU.Build.0 = Release|Any CPU + {DFB9F100-7C85-4168-8422-F2247088F6EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DFB9F100-7C85-4168-8422-F2247088F6EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DFB9F100-7C85-4168-8422-F2247088F6EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DFB9F100-7C85-4168-8422-F2247088F6EC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {48574564-5697-4679-95F9-48552C60082F} + EndGlobalSection +EndGlobal diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Driver/AMotorDriver.dll b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Driver/AMotorDriver.dll new file mode 100644 index 0000000..b99d16a Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Driver/AMotorDriver.dll differ diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Driver/BMotorDriver.dll b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Driver/BMotorDriver.dll new file mode 100644 index 0000000..3e965ee Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Driver/BMotorDriver.dll differ diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Form1.Designer.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Form1.Designer.cs new file mode 100644 index 0000000..4a2865b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Form1.Designer.cs @@ -0,0 +1,79 @@ + +namespace WinFormsSample +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.button1 = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + this.splitContainer1.Size = new System.Drawing.Size(966, 521); + this.splitContainer1.SplitterDistance = 460; + this.splitContainer1.TabIndex = 0; + // + // button1 + // + this.button1.Dock = System.Windows.Forms.DockStyle.Top; + this.button1.Location = new System.Drawing.Point(0, 0); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(966, 53); + this.button1.TabIndex = 1; + this.button1.Text = "플러그인 로딩"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(966, 521); + this.Controls.Add(this.button1); + this.Controls.Add(this.splitContainer1); + this.Name = "Form1"; + this.Text = "Form1"; + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.Button button1; + } +} + diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Form1.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Form1.cs new file mode 100644 index 0000000..dc3a233 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Form1.cs @@ -0,0 +1,42 @@ +using MotorDriver; + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace WinFormsSample +{ + public partial class Form1 : Form + { + private MotorFactory factory; + + public Form1() + { + InitializeComponent(); + + var driverPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Driver"); + factory = new MotorFactory(driverPath); + } + + private void button1_Click(object sender, EventArgs e) + { + var driverNames = factory.GetDriverNames(); + + var motor1Page = factory.Create(driverNames.First(), 1); + var motor2Page = factory.Create(driverNames.Last(), 2); + + motor1Page.Page.Dock = DockStyle.Fill; + splitContainer1.Panel1.Controls.Add(motor1Page.Page); + motor2Page.Page.Dock = DockStyle.Fill; + splitContainer1.Panel2.Controls.Add(motor2Page.Page); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Form1.resx b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Form1.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Form1.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Program.cs b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Program.cs new file mode 100644 index 0000000..60464c3 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/Program.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace WinFormsSample +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.SetHighDpiMode(HighDpiMode.SystemAware); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/WinFormsSample.csproj b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/WinFormsSample.csproj new file mode 100644 index 0000000..73ab978 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/2.DynamicLinkedLibrary/sample/WinFormsSample/WinFormsSample/WinFormsSample.csproj @@ -0,0 +1,22 @@ + + + + WinExe + net5.0-windows + true + + + + + + + + + PreserveNewest + + + PreserveNewest + + + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/1.png b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/1.png new file mode 100644 index 0000000..bd556e9 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/1.png differ diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/10.png b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/10.png new file mode 100644 index 0000000..293095a Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/10.png differ diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/11.png b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/11.png new file mode 100644 index 0000000..c59cac3 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/11.png differ diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/2.png b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/2.png new file mode 100644 index 0000000..912a213 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/2.png differ diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/3.png b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/3.png new file mode 100644 index 0000000..208c236 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/3.png differ diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/4.png b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/4.png new file mode 100644 index 0000000..f728331 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/4.png differ diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/5.png b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/5.png new file mode 100644 index 0000000..f263ef9 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/5.png differ diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/6.png b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/6.png new file mode 100644 index 0000000..d2685b5 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/6.png differ diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/7.png b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/7.png new file mode 100644 index 0000000..639cd6d Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/7.png differ diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/8.png b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/8.png new file mode 100644 index 0000000..57937a2 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/8.png differ diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/9.png b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/9.png new file mode 100644 index 0000000..bafaa13 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/images/9.png differ diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/index.md b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/index.md new file mode 100644 index 0000000..3328cb7 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/index.md @@ -0,0 +1,336 @@ +# GDI+를 사용해 보자 +이번 장에서는 Windows Forms에서 GDI+를 자유롭게 이용할 수 있도록 사용법을 살펴봐 보도록 하겠습니다. + +## 테스트 환경 +- Visual Studio 2019 +- .NET 5, C# 9 +- Windows Forms + +## GDI+ 많이는 들어봤는데... +Windows 초창기 부터 그래픽 장치 인터페이스(GDI) API를 제공 했었는데요, Windows XP 운영체제부터 Windows GDI+를 사용할 수 있게 되었습니다. GDI+는 GDI에 비해 그라데이션 브러쉬 및 알파 블렌딩과 같은 새로운 기능이 추가되었고, 친숙한 개체지향 스타일로 각종 기능을 사용할 수 있게 되었습니다. + +## Windows Forms에서 GDI+를 사용하려면? +두가지 방식이 있습니다. Windows Forms의 화면에 보여지는 모든 컨트롤들은 `OnPaintBackground()`및 `OnPaint()` 메소드를 재정의 할 수 있습니다. 이때, `e` 인자의 Graphics 개체를 통해 GDI+ 기능을 이용할 수 있습니다. +두번째 방법은 `CreateGraphics()` 메소드를 통해 `Graphics` 개체를 생성한 후 사용하는 방법입니다. +아, 한가지 방법이 더 있군요. `Bitmap` 개체를 `Graphics.FromImage()` 메소드를 통해 `Graphics`를 획득해서 사용할 수 있습니다. + +## `Graphics`는 화면 출력 용으로만 사용하나요? +아닙니다. GDI+는 장치 컨텍스트에 독립적입니다. 그렇기 때문에 프린트 출력을 할때에도 `Graphics`를 사용하게 됩니다. + +## 한번 해봅시다 +먼저 `.NET 5`로 `Windows Forms` 응용 어플리케이션 템플릿으로 프로젝트를 생성한 후, 아무 컨트롤이나 폼에 배치해봅니다. + +![기본 폼에 컨트롤 배치](images/1.png) + +예시로 `CheckBox`를 생성해봤는데요, Windows Forms에서는 화면에 보이는 모든 컨트롤은 `Control`에서 상속받도록 되어 있습니다. 한번 추적해보죠. + +```csharp +public class CheckBox : ButtonBase {} +public abstract class ButtonBase : Control {} +``` + +`OnPaintBackground()`및 `OnPaint()` 메소드는 `Control`의 메소드 이므로, Windows Forms의 보여지는 모든 컨트롤은 그리기 기능이 존재하는 샘입니다. + +그렇다면 `Control`에서 상속받아 구현을 해볼까요? 이름을 `CanvasControl`이라고 하겠습니다. + +```csharp + public class CanvasControl : Control + { + protected override void OnPaintBackground(PaintEventArgs pevent) + { + var g = pevent.Graphics; + + g.Clear(Color.Black); + } + + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + } + } +``` + +폼 디자이너에서 컨트롤이 구분되도록 배경색을 검정색으로 칠하는 코드만 넣었습니다. 그런 다음 폼 디자이너에서 `CanvasControl`을 추가하면 다음처럼 보이게 됩니다. + +![폼에 CanvasControl1](images/2.png) + +실행화면1 + +![CanvasControl 실행화면](images/3.png) + +컨트롤이 화면에 보여져야 할 때 먼저 `OnPaintBackground()`가 호출되어 배경을 그릴 수 있도록 하고, 그다음 `OnPaint()`가 호출되어 내용을 그릴 수 있게 되어 있습니다. 이런식으로 Windows Forms 컨트롤이 화면에 보여지게 되는거죠. + +그런데 검정 배경화면만 있으니 `BackColor`에 검정 지정한 것 마냥 차이가 없습니다. 검정색 배경에 도형을 그려보도록 합시다. + +```csharp + protected override void OnPaint(PaintEventArgs e) + { + var g = e.Graphics; + var rect = ClientRectangle; + var clipRect = e.ClipRectangle; + + // 선 + g.DrawLine(Pens.Red, 50, 50, 100, 100); + + // 면 + g.DrawRectangle(Pens.Green, 10, 10, 30, 30); + + // 원 + g.DrawEllipse(Pens.Blue, 100, 100, 50, 50); + } +``` + +실행화면2 + +![CanvasControl 실행화면](images/4.png) + +원하는대로 잘 그려지는군요. 그런데 한가지 궁금한 점이 생깁니다. + +## `OnPaint()`는 정확히 언제 호출될까요? +Windows Forms는 나름 효과적으로 컨트롤을 그리도록 최적화 되어 있는데요, 화면에 새로 보여질 때만 호출된다는 점입니다. 다음의 코드로 이를 확인해봅시다. + +```csharp + private bool firstDraw = true; + protected override void OnPaint(PaintEventArgs e) + { + var g = e.Graphics; + var rect = ClientRectangle; + + // 선 + g.DrawLine(Pens.Red, 50, 50, 100, 100); + + // 면 + g.DrawRectangle(Pens.Green, 10, 10, 30, 30); + + // 원 + g.DrawEllipse(Pens.Blue, 100, 100, 50, 50); + + if (firstDraw == false) + g.FillRectangle(Brushes.LightGray, rect); + + firstDraw = false; + } +``` + +`firstDraw`에 의해 두번째 그리기부터는 전체 영역을 회색으로 그리도록 했는데요, + +최초화면 + +![최초화면](images/5.png) + +폼의 사이즈를 작게 조절해서 다음과 같이 줄인 후, + +![폼사이즈줄임](images/6.png) + +![폼사이즈늘림](images/7.png) + +신기합니다. 분명히 컨트롤 전체 영역에 갈색으로 칠해져야 할 텐데요, 다시 그려져야 할 영역만 칠하고 있습니다. `OnPaint()` 메소드가 호출될 때의 `Graphics`는 갱신되어야 할 영역만 그려지도록 클리핑(Clipping) 됨을 알 수 있습니다. + +```csharp + protected override void OnPaint(PaintEventArgs e) + { + var g = e.Graphics; + var rect = ClientRectangle; + + g.FillEllipse(Brushes.Green, rect); + } +``` + +위와 같이 수정한 후 `CanvasControl`을 폼에 `Dock.Fill` 해 봅시다. + +실행화면 + +![녹색원](images/8.png) + +`ClientRectangle`은 컨트롤의 그릴 수 있는 영역입니다. 예상했던 대로 녹색으로 가득 찬 원이 그려졌는데요, 사이즈를 한번 늘려봅시다. + +![이상한 녹색원](images/9.png) + +원이 크기에 맞게 늘어나거나 줄어드는 예상과 달리 Windows Forms의 효율적 그리기로 인해서 이상하게 보입니다. + +컨트롤의 사이즈가 변경되었을 때 전체를 다시 그려야 할 경우, + +```csharp + public CanvasControl() + { + ResizeRedraw = true; + } +``` +이렇게 `ResizedRedraw` 속성에 `true`를 적용하면, + +![괜찮은 녹색원](images/10.png) + +컨트롤의 사이즈가 변경됐을 때 전체 영역을 다시 그리게 됩니다. + +## GDI+ 개체에 대해 알아봅시다 +Windows Forms에서 제공하는 GDI+ 기능은 대부분 Windows GDI+의 레퍼 기능이며, 컨트롤에서 생성하거나, 이미지에서 생성하거나, `OnPaint()` 인자로 받는 `Graphics`를 통해 GDI+ 기능을 사용할 수 있게 됩니다. +GDI+ 에서 제공하는 개체는 다음과 같습니다. + +- Graphics + - GDI+ 그리기 화면을 캡슐화 합니다. 이 개체를 통해 GDI+ 기능을 이용하게 됩니다. +- Image + - Bitmap 및 Metafile 서브클레스에 기능을 제공하는 추상 기본 클래스입니다. +- Bitmap + - 그래픽 이미지의 픽셀 데이터와 그 특성으로 구성되는 GDI+ 비트맵을 캡슐화 합니다. Bitmap은 픽셀 데이터로 정의된 이미지에서 작업하는 데 사용하는 개체가 됩니다. +- Metafile + - 그래픽 메타피일입니다. 메타파일은 일종의 벡터 이미지 이며, 생성과 표시할 수 있는 그래픽 작업 시퀀스를 설명하는 레코드로 구성됩니다. +- Font + - 글꼴, 크기 및 스타일 특성을 포함하여 텍스트의 특정 형식을 정의합니다. +- Brush + - 사각형, 타원, 파이, 다각형 및 경로와 같은 그래픽 도형의 내부 면을 채우는데 사용하는 개체입니다. +- Color + - 알파, 빨강, 녹색, 파랑(ARGB)를 나타냅니다. +- Matrix + - 기하학정 변환을 나타내는 상관 매트릭스를 캡슐화 합니다. +- TextRenderer + - GDI의 텍스트 기능을 제공합니다. + +`IDisposable` 인터페이스가 구현된 개체는 반드시 사용이 완료되면 `Dispose`해야 하며 그 이유는 내부적으로 비관리 헨들을 사용해 운영체제의 자원이 사용되기 때문입니다. + +## GDI+의 좌표체계 및 변환 +GDI+는 그릴 항목을 회전, 크기 조정, 변환등을 할 수 있도록 좌표 변환 체계를 가지고 있습니다. +- World 좌표 : world는 그리기 원래(상대) 좌표입니다. +- Page 좌표 : page는 전체 페이지를 기준으로 하는 절대 좌표입니다. +- Device 좌표 : page와 device의 단위가 다를 경우 좌표가 변환됩니다. + +예제의 `Draw()`메소드에서 world 좌표 공간을 사용합니다. `TranslateTransform()`등의 Matrix 기능을 이용하면 이것을 Page 좌표로 변환할 수 있습니다. 즉, 좌표 (0,0)을 기준 (또는 사용자의 임의)에 의해 구성된 항목을 회전, 크기 조정, 위치 조정을 할 수 있게 됩니다. + +```csharp + protected override void OnPaint(PaintEventArgs e) + { + Sample3(e); + } + + private void Sample3(PaintEventArgs e) + { + var g = e.Graphics; + var rect = ClientRectangle; + + g.TranslateTransform(100, 50); + Draw(g, Font); + + g.TranslateTransform(130, 130); + Draw(g, Font); + + g.TranslateTransform(130, 130); + g.ScaleTransform(1.5f, 1.5f); + g.RotateTransform(45); + Draw(g, Font); + + //// + + static void Draw(Graphics g, Font font) + { + using var glPen = new Pen(Color.White) + { + }; + using var sPen = new Pen(Color.White); + + g.DrawLine(glPen, 0, 0, 150, 0); + g.DrawLine(sPen, 50, -5, 50, 5); + g.DrawLine(sPen, 100, -5, 100, 5); + g.DrawString("50", font, Brushes.White, 41, -24); + g.DrawString("100", font, Brushes.White, 88, -24); + g.DrawString("x", font, Brushes.White, 160, -8); + + g.DrawLine(glPen, 0, 0, 0, 100); + g.DrawLine(sPen, -5, 50, 5, 50); + g.DrawString("50", font, Brushes.White, -26, 42); + g.DrawString("y", font, Brushes.White, -6, 110); + + g.DrawLine(Pens.Red, 0, 0, 160, 80); + } + } +``` + +![좌표계](images/11.png) + +위의 예제에서 소개되지 않은 기능을 포함한 관련 GDI+ 기능은 다음과 같습니다. 간단히 예제를 만들어 결과를 확인하면 어떻게 동작하는지를 알 수 있습니다. + +- Transform + - Transform에 의해 World 좌표를 Page 좌표로 매핑합니다. +- TransformPoints + - World 및 Page, Device 좌표간의 변화 계산을 합니다. +- TranslateClip + - 가로, 세로로 지정된 클립 영역을 변환합니다. +- TranslateTransform + - 좌표계의 원점을 변경합니다. +- MultiplyTransform + - Graphics의 Transform(Matrix)와 지정된 Matrix를 곱합니다. +- ResetTransform + - Transform을 초기화 합니다. +- RotateTransform + - 회전을 적용합니다. +- ScaleTransform + - 크기 조정을 적용합니다. + +## 그리기의 깜빡임을 없애봅시다 +화면 Graphics를 이용하면 즉각적으로 화면에 항목이 그려집니다. 그런데 항목을 이동해야 하는 등 전체 영역을 다시 그려야 할 경우 지우는 작업에 의해 화면이 깜빡이게 되는데요, 여기서는 `Bitmap`을 통해서 깜빡임을 없애는 방법에 대해서 설명하겠습니다. + +```csharp + private Bitmap buffer; + private Graphics bg; + protected override void OnResize(EventArgs e) + { + base.OnResize(e); + + if (buffer != null) + buffer.Dispose(); + + buffer = new Bitmap(ClientSize.Width, ClientSize.Height); + bg = Graphics.FromImage(buffer); + } + + protected override void OnPaintBackground(PaintEventArgs pevent) + { + } + + protected override void OnPaint(PaintEventArgs e) + { + Sample4(e); + + Invalidate(); + } + + private int x, y; + private void Sample4(PaintEventArgs e) + { + var g = e.Graphics; + + x++; + if (x > ClientSize.Width) + { + x = 0; + y += 20; + } + bg.TranslateTransform(x, y); + + bg.ScaleTransform(0.3f, 0.3f); + Draw(bg); + bg.ResetTransform(); + + g.DrawImage(buffer, 0, 0); + + // ---- + void Draw(Graphics g) + { + g.Clear(Color.Black); + + g.FillEllipse(Brushes.Green, ClientRectangle); + } + } +``` + +컨트롤의 ClientSize만큼의 Bitmap을 생성한 후, 영역을 `OnPaintBackground()`에서 지우는 대신 Bitmap에서 획득한 Graphics를 지워줍니다. 그리기 작업 후, `OnPaint()`에서는 Bitmap을 `DrawImage`하는 것으로 메모리에서 작업한 항목을 그려서 깜빡임을 없앨 수 있게 되었습니다. + +## 샘플 +위의 예제에 대한 샘플 소스코드는 다음의 링크로 다운로드 받아 실행해 볼 수 있습니다. + +- [샘플 소스코드](sample/GDIPlusSample.zip) + +## 참고 +- [.NET Windows Forms / GitHub](https://github.com/dotnet/winforms) +- [Windows Forms의 그래픽 및 그리기](https://docs.microsoft.com/ko-kr/dotnet/desktop/winforms/advanced/graphics-and-drawing-in-windows-forms?view=netframeworkdesktop-4.8) + +## 문서 기여자 +- 작성한 사람: 디모이(dimohy) diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample.zip b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample.zip new file mode 100644 index 0000000..a2ec2c0 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample.zip differ diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/.gitattributes b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/.gitignore b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/.gitignore new file mode 100644 index 0000000..9491a2f --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/.gitignore @@ -0,0 +1,363 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample.sln b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample.sln new file mode 100644 index 0000000..190605f --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31112.23 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GDIPlusSample", "GDIPlusSample\GDIPlusSample.csproj", "{C66C3A13-A52C-41F4-9362-DE058C64F3DC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C66C3A13-A52C-41F4-9362-DE058C64F3DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C66C3A13-A52C-41F4-9362-DE058C64F3DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C66C3A13-A52C-41F4-9362-DE058C64F3DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C66C3A13-A52C-41F4-9362-DE058C64F3DC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {82A37DFE-0572-4164-B4A7-009820F0589B} + EndGlobalSection +EndGlobal diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/CanvasControl.cs b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/CanvasControl.cs new file mode 100644 index 0000000..28d5c57 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/CanvasControl.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace GDIPlusSample +{ + public class CanvasControl : Control + { + private bool firstDraw = true; + + public CanvasControl() + { + ResizeRedraw = true; + } + + private Bitmap buffer; + private Graphics bg; + protected override void OnResize(EventArgs e) + { + base.OnResize(e); + + if (buffer != null) + buffer.Dispose(); + + buffer = new Bitmap(ClientSize.Width, ClientSize.Height); + bg = Graphics.FromImage(buffer); + } + + protected override void OnPaintBackground(PaintEventArgs pevent) + { + } + + protected override void OnPaint(PaintEventArgs e) + { + Sample4(e); + + Invalidate(); + } + + private int x, y; + private void Sample4(PaintEventArgs e) + { + var g = e.Graphics; + + x++; + if (x > ClientSize.Width) + { + x = 0; + y += 20; + } + bg.TranslateTransform(x, y); + + bg.ScaleTransform(0.3f, 0.3f); + Draw(bg); + bg.ResetTransform(); + + g.DrawImage(buffer, 0, 0); + + // ---- + void Draw(Graphics g) + { + g.Clear(Color.Black); + + g.FillEllipse(Brushes.Green, ClientRectangle); + } + } + + private void Sample3(PaintEventArgs e) + { + var g = e.Graphics; + var rect = ClientRectangle; + + g.TranslateTransform(100, 50); + Draw(g, Font); + + g.TranslateTransform(130, 130); + Draw(g, Font); + + g.TranslateTransform(130, 130); + g.ScaleTransform(1.5f, 1.5f); + g.RotateTransform(45); + Draw(g, Font); + + //// + + static void Draw(Graphics g, Font font) + { + // g.Transform + // g.TransformPoints + // g.TranslateClip + // g.TranslateTransform + // g.MultiplyTransform() + // g.ResetTransform + // g.RotateTransform + // g.ScaleTransform + + + using var glPen = new Pen(Color.White) + { + }; + using var sPen = new Pen(Color.White); + + g.DrawLine(glPen, 0, 0, 150, 0); + g.DrawLine(sPen, 50, -5, 50, 5); + g.DrawLine(sPen, 100, -5, 100, 5); + g.DrawString("50", font, Brushes.White, 41, -24); + g.DrawString("100", font, Brushes.White, 88, -24); + g.DrawString("x", font, Brushes.White, 160, -8); + + g.DrawLine(glPen, 0, 0, 0, 100); + g.DrawLine(sPen, -5, 50, 5, 50); + g.DrawString("50", font, Brushes.White, -26, 42); + g.DrawString("y", font, Brushes.White, -6, 110); + + g.DrawLine(Pens.Red, 0, 0, 160, 80); + } + } + + private void Sample1(PaintEventArgs e) + { + var g = e.Graphics; + var rect = ClientRectangle; + var clipRect = e.ClipRectangle; + + // 선 + g.DrawLine(Pens.Red, 50, 50, 100, 100); + + // 면 + g.DrawRectangle(Pens.Green, 10, 10, 30, 30); + + // 원 + g.DrawEllipse(Pens.Gray, 100, 100, 50, 50); + + if (firstDraw == false) + { + g.FillRectangle(Brushes.Gray, rect); + } + + firstDraw = false; + } + + private void Sample2(PaintEventArgs e) + { + var g = e.Graphics; + var rect = ClientRectangle; + + g.FillEllipse(Brushes.Green, rect); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/Form1.Designer.cs b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/Form1.Designer.cs new file mode 100644 index 0000000..517993a --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/Form1.Designer.cs @@ -0,0 +1,61 @@ + +namespace GDIPlusSample +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.canvasControl1 = new GDIPlusSample.CanvasControl(); + this.SuspendLayout(); + // + // canvasControl1 + // + this.canvasControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.canvasControl1.Location = new System.Drawing.Point(0, 0); + this.canvasControl1.Name = "canvasControl1"; + this.canvasControl1.Size = new System.Drawing.Size(638, 526); + this.canvasControl1.TabIndex = 0; + this.canvasControl1.Text = "canvasControl1"; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(638, 526); + this.Controls.Add(this.canvasControl1); + this.Name = "Form1"; + this.Text = "Form1"; + this.ResumeLayout(false); + + } + + #endregion + + private CanvasControl canvasControl1; + } +} + diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/Form1.cs b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/Form1.cs new file mode 100644 index 0000000..ed26cf4 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/Form1.cs @@ -0,0 +1,21 @@ +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 GDIPlusSample +{ + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + } + + } +} diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/Form1.resx b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/Form1.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/Form1.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/GDIPlusSample.csproj b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/GDIPlusSample.csproj new file mode 100644 index 0000000..a2d4310 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/GDIPlusSample.csproj @@ -0,0 +1,9 @@ + + + + WinExe + net5.0-windows + true + + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/Program.cs b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/Program.cs new file mode 100644 index 0000000..8c21b1b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/3.LetsUseGDIPlus/sample/GDIPlusSample/GDIPlusSample/Program.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace GDIPlusSample +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.SetHighDpiMode(HighDpiMode.SystemAware); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/images/1.png b/docs/for-win-developers/Windows-Forms/4.Localizing/images/1.png new file mode 100644 index 0000000..0070258 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/images/1.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/images/10.png b/docs/for-win-developers/Windows-Forms/4.Localizing/images/10.png new file mode 100644 index 0000000..e0293d5 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/images/10.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/images/11.png b/docs/for-win-developers/Windows-Forms/4.Localizing/images/11.png new file mode 100644 index 0000000..4fb9b59 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/images/11.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/images/12.png b/docs/for-win-developers/Windows-Forms/4.Localizing/images/12.png new file mode 100644 index 0000000..e61ed29 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/images/12.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/images/13.png b/docs/for-win-developers/Windows-Forms/4.Localizing/images/13.png new file mode 100644 index 0000000..172070b Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/images/13.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/images/2.png b/docs/for-win-developers/Windows-Forms/4.Localizing/images/2.png new file mode 100644 index 0000000..69fb661 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/images/2.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/images/3.png b/docs/for-win-developers/Windows-Forms/4.Localizing/images/3.png new file mode 100644 index 0000000..973a864 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/images/3.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/images/4.png b/docs/for-win-developers/Windows-Forms/4.Localizing/images/4.png new file mode 100644 index 0000000..91f516a Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/images/4.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/images/5.png b/docs/for-win-developers/Windows-Forms/4.Localizing/images/5.png new file mode 100644 index 0000000..dd75d70 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/images/5.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/images/6.png b/docs/for-win-developers/Windows-Forms/4.Localizing/images/6.png new file mode 100644 index 0000000..d58ef63 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/images/6.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/images/7.png b/docs/for-win-developers/Windows-Forms/4.Localizing/images/7.png new file mode 100644 index 0000000..9e29d69 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/images/7.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/images/8.png b/docs/for-win-developers/Windows-Forms/4.Localizing/images/8.png new file mode 100644 index 0000000..6a7be53 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/images/8.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/images/9.png b/docs/for-win-developers/Windows-Forms/4.Localizing/images/9.png new file mode 100644 index 0000000..f25da99 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/images/9.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/index.md b/docs/for-win-developers/Windows-Forms/4.Localizing/index.md new file mode 100644 index 0000000..cbecf66 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/index.md @@ -0,0 +1,119 @@ +# 지역화 기능을 이용한 다국어 지원하기 +Windows Forms에서 제공하는 폼 기반 리소스를 이용화면 화면에 보이는 텍스트 및 각종 리소스를 언어 별로 별도 처리 할 수 있게 됩니다. +폼 기반 리소스와 함께 프로젝트 리소스 방식을 이용할 수 있습니다. + +- 폼 기반 리소스 + - 폼의 텍스트 및 이미지와 같은 지역화 가능한 UI 요소에 대한 리소스 파일을 생성합니다. 이후 리소스 파일이 어셈플리에 내장되게 됩니다. 이를 폼 기반 리소스라고 합니다. +- 프로젝트 리소스 + - 리소스 파일 템플릿을 추가한 다음 XML 디자이너를 통해 리소스를 편집합니다. 그런 후 코드를 통해 리소스에 접근하는 방식을 프로젝트 리소스라고 합니다. + +일반적으로 Windows Forms 응용 프로그램에서 UI 요소와 관련된 대부분의 리소스에 폼 기반 리소스를 사용해야 편리합니다. 그러나 오류 메시지와 같은 비형태 기반의 사용자 인터페이스 문자열 및 이미지의 경우 프로젝트 리소스를 이용해야 합니다. + +## 테스트 환경 +- Visual Studio 2019 +- .NET 5, C# 9 +- Windows Forms + +## 폼 기반 리소스를 이용한 지역화 + +Windows Forms은 `Localizable` 속성을 통해 지역화 대상 리소스를 자동 생성하는 기능이 있습니다. 이 속성을 `True`로 변경합시다. + +![Localizable 속성 변경](images/1.png) + +`Language`속성에 `한국어`를 입력한 후 저장합니다. + +![한국어 입력 저장 후](images/2.png) + +영어에 맞게 화면을 구성합니다. + +![영어 리소스](images/3.png) + +그리고 한국어에 맞게 화면을 구성합니다. + +![한국어 리소스](images/4.png) + +이때, 주의해야 할 것은 문자열 뿐만 아니라 컨트롤의 속성도 리소스로 관리하게 되므로 컨트롤의 좌표 등 모든 리소스가 별도 저장이 됩니다. 그래서 되도록이면 `default` 폼을 완성 한 후 `Language`속성에 다른 언어를 입력하여 리소스를 생성하는게 좋습니다. 그렇지 않으면 리소스 별도 컨트롤을 일일히 조정해야 하는 불편함이 생깁니다. + +지역화 된 리소스는 다음의 코드를 통해 적용됩니다. + +```csharp + var name = "ko-KR"; + var cultureInfo = new CultureInfo(name); + Thread.CurrentThread.CurrentUICulture = cultureInfo; + Thread.CurrentThread.CurrentCulture = cultureInfo; +``` + +그러면 폼은 `CurrentUICulture` 속성에 맞는 리소스를 찾아 적용하게 됩니다. + +### 실행화면 + +한국어의 경우, + +![한국어 적용](images/5.png) + +영어의 경우, + +![영어 적용](images/6.png) + +## 프로젝트에 리소스를 수동으로 추가 +폼 종속적인 다양한 정적 리소스는 폼의 `Languages` 속성으로 생성되는 리소스 파일로 관리하는게 좋습니다. 그러나 폼에 직접적인 관련이 없는 정적 리소스나 상황에 따라 다르게 표현되어야 하는 동적 리소스의 경우 프로젝트에 수동으로 리소스를 추가하여 관리하게 됩니다. + +프로젝트에 `추가/새 항목`을 통해 새로운 리소스 파일을 추가 합니다. + +![새로운 리소스 파일 추가](images/7.png) + +생성해야 하는 리소스 파일의 구성은 다음과 같습니다. + + - Resource1.resx : 기본 리소스 파일이 되며, 해당 지역의 언어 리소스가 없을 경우 선택됩니다. + - Resource1.ko-KR.resx : 한국어(한국) 리소스 파일입니다. + - Resource1.ko.resx : 한국어 리소스 파일입니다. + +현 지역이 한국어(한국)인 경우, 최초 `Resource1.ko-KR.resx` 파일을 찾게 되고 없을 경우, 그 다음으로 `Resource1.ko.resx` 파일을, 이 파일도 없을 경우, `Resource1.resx` 이 파일을 리소스 파일로 선택하게 됩니다. + +폼에 버튼을 배치하고 지역에 따라 버튼 `Text` 속성을 다르게 줍니다. + +한국어, + +![한국어 버튼](images/8.png) + +영어, + +![영어 버튼](images/9.png) + +그리고 `Resource1.resx`, `Resource1.ko-KR.resx` 및 `Resources1.en-US.resx`를 다음과 같이 입력합니다. + +Resource1.ko-KR.resx + +![한국어 Resource1](images/10.png) + +Resource1.resx 및 Resource1.en-US.resx + +![영어 Resource1](images/11.png) + +버튼 클릭 이벤트를 다음과 같이 코딩합니다. + +```csharp + private void button1_Click(object sender, EventArgs e) + { + MessageBox.Show(Resource1.QuestionContent, Resource1.QuestionTitle, MessageBoxButtons.OK, MessageBoxIcon.Question); + } +``` + +### 실행화면 + +한국어 선택 시, + +![한국어 선택 시](images/12.png) + +영어 선택 시, + +![영어 선택 시](images/13.png) + + +## 샘플 +위의 예제에 대한 샘플 소스코드는 다음의 링크로 다운로드 받아 실행해 볼 수 있습니다. + +- [샘플 소스코드](sample/sample.zip) + +## 문서 기여자 +- 작성한 사람: 디모이(dimohy) \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/.gitattributes b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/.gitignore b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/.gitignore new file mode 100644 index 0000000..9491a2f --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/.gitignore @@ -0,0 +1,363 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.Designer.cs b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.Designer.cs new file mode 100644 index 0000000..ee54c7d --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.Designer.cs @@ -0,0 +1,90 @@ +namespace sample +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.label1 = new System.Windows.Forms.Label(); + this.button1 = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // pictureBox1 + // + resources.ApplyResources(this.pictureBox1, "pictureBox1"); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.TabStop = false; + // + // comboBox1 + // + resources.ApplyResources(this.comboBox1, "comboBox1"); + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Items.AddRange(new object[] { + resources.GetString("comboBox1.Items"), + resources.GetString("comboBox1.Items1")}); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // button1 + // + resources.ApplyResources(this.button1, "button1"); + this.button1.Name = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // Form1 + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.button1); + this.Controls.Add(this.label1); + this.Controls.Add(this.comboBox1); + this.Controls.Add(this.pictureBox1); + this.Name = "Form1"; + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button button1; + } +} + diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.cs b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.cs new file mode 100644 index 0000000..2735d69 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace sample +{ + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + + comboBox1.SelectedIndex = GetCultureIndex(Thread.CurrentThread.CurrentUICulture.Name); + } + + private static string GetCultureName(int index) => index switch { 0 => "ko-KR", 1 => "en-US", _ => "ko-KR" }; + private static int GetCultureIndex(string name) => name switch { "ko-KR" => 0, "en-US" => 1, _ => 0 }; + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + var name = GetCultureName(comboBox1.SelectedIndex); + Properties.Settings.Default.Locale = name; + Properties.Settings.Default.Save(); + + var cultureInfo = new CultureInfo(name); + + if (Thread.CurrentThread.CurrentUICulture.Name != cultureInfo.Name) + Application.Restart(); + } + + private void button1_Click(object sender, EventArgs e) + { + MessageBox.Show(Resource1.QuestionContent, Resource1.QuestionTitle, MessageBoxButtons.OK, MessageBoxIcon.Question); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.en.resx b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.en.resx new file mode 100644 index 0000000..c47f017 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.en.resx @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + + + + + 575, 12 + + + + True + + + 맑은 고딕, 30pt + + + 205, 54 + + + Be happy! + + + 520, 339 + + + 93, 40 + + + 3 + + + Question + + + 837, 469 + + + + CenterScreen + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.ko.resx b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.ko.resx new file mode 100644 index 0000000..a61dc0c --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.ko.resx @@ -0,0 +1,395 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + w3H+Px0dxORBgtm1AAAAAElFTkSuQmCC + + + + 한국어 + + + 영어 + + + + 575, 12 + + + 맑은 고딕, 30pt + + + 474, 136 + + + 행복하세요! + + + 93, 40 + + + 질문 + + + 837, 469 + + + + CenterScreen + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.resx b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.resx new file mode 100644 index 0000000..35aa284 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Form1.resx @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Form1 + + + + 100, 23 + + + $this + + + System.Windows.Forms.Form, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 520, 207 + + + 1 + + + 922, 12 + + + + 3 + + + 2 + + + 0 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 7, 15 + + + $this + + + $this + + + English + + + 1084, 516 + + + 0 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 150, 23 + + + Korean + + + + + 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 + + + + 2 + + + pictureBox1 + + + label1 + + + button1 + + + comboBox1 + + + $this + + + 520, 339 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 368, 455 + + + 1 + + + 3 + + + 0, 0 + + + True + + + en + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Program.cs b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Program.cs new file mode 100644 index 0000000..62285bd --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Program.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace sample +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + var name = Properties.Settings.Default.Locale; + var cultureInfo = new CultureInfo(name); + Thread.CurrentThread.CurrentUICulture = cultureInfo; + Thread.CurrentThread.CurrentCulture = cultureInfo; + + Application.SetHighDpiMode(HighDpiMode.SystemAware); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Properties/Resources.Designer.cs b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Properties/Resources.Designer.cs new file mode 100644 index 0000000..7c74335 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 이 코드는 도구를 사용하여 생성되었습니다. +// 런타임 버전:4.0.30319.42000 +// +// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면 +// 이러한 변경 내용이 손실됩니다. +// +//------------------------------------------------------------------------------ + +namespace sample.Properties { + using System; + + + /// + /// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다. + /// + // 이 클래스는 ResGen 또는 Visual Studio와 같은 도구를 통해 StronglyTypedResourceBuilder + // 클래스에서 자동으로 생성되었습니다. + // 멤버를 추가하거나 제거하려면 .ResX 파일을 편집한 다음 /str 옵션을 사용하여 ResGen을 + // 다시 실행하거나 VS 프로젝트를 다시 빌드하십시오. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("sample.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 이 강력한 형식의 리소스 클래스를 사용하여 모든 리소스 조회에 대해 현재 스레드의 CurrentUICulture 속성을 + /// 재정의합니다. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Properties/Resources.resx b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Properties/Resources.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Properties/Resources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Properties/Settings.Designer.cs b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Properties/Settings.Designer.cs new file mode 100644 index 0000000..2fb1430 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Properties/Settings.Designer.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// +// 이 코드는 도구를 사용하여 생성되었습니다. +// 런타임 버전:4.0.30319.42000 +// +// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면 +// 이러한 변경 내용이 손실됩니다. +// +//------------------------------------------------------------------------------ + +namespace sample.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("ko-KR")] + public string Locale { + get { + return ((string)(this["Locale"])); + } + set { + this["Locale"] = value; + } + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Properties/Settings.settings b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Properties/Settings.settings new file mode 100644 index 0000000..b4afe69 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Properties/Settings.settings @@ -0,0 +1,9 @@ + + + + + + ko-KR + + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Resource1.Designer.cs b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Resource1.Designer.cs new file mode 100644 index 0000000..f4c2946 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Resource1.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// 이 코드는 도구를 사용하여 생성되었습니다. +// 런타임 버전:4.0.30319.42000 +// +// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면 +// 이러한 변경 내용이 손실됩니다. +// +//------------------------------------------------------------------------------ + +namespace sample { + using System; + + + /// + /// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다. + /// + // 이 클래스는 ResGen 또는 Visual Studio와 같은 도구를 통해 StronglyTypedResourceBuilder + // 클래스에서 자동으로 생성되었습니다. + // 멤버를 추가하거나 제거하려면 .ResX 파일을 편집한 다음 /str 옵션을 사용하여 ResGen을 + // 다시 실행하거나 VS 프로젝트를 다시 빌드하십시오. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resource1 { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resource1() { + } + + /// + /// 이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("sample.Resource1", typeof(Resource1).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 이 강력한 형식의 리소스 클래스를 사용하여 모든 리소스 조회에 대해 현재 스레드의 CurrentUICulture 속성을 + /// 재정의합니다. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// I'm curious about your birthday What month's your birthday?과(와) 유사한 지역화된 문자열을 찾습니다. + /// + internal static string QuestionContent { + get { + return ResourceManager.GetString("QuestionContent", resourceCulture); + } + } + + /// + /// Question과(와) 유사한 지역화된 문자열을 찾습니다. + /// + internal static string QuestionTitle { + get { + return ResourceManager.GetString("QuestionTitle", resourceCulture); + } + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Resource1.en-US.resx b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Resource1.en-US.resx new file mode 100644 index 0000000..4230626 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Resource1.en-US.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + I'm curious about your birthday What month's your birthday? + + + Question + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Resource1.ko-KR.resx b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Resource1.ko-KR.resx new file mode 100644 index 0000000..eb76805 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Resource1.ko-KR.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 당신의 생일이 궁금해요. 생일이 몇달이에요? + + + 질문 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Resource1.resx b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Resource1.resx new file mode 100644 index 0000000..4230626 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/Resource1.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + I'm curious about your birthday What month's your birthday? + + + Question + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/images/img_en.png b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/images/img_en.png new file mode 100644 index 0000000..a23346c Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/images/img_en.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/images/img_kr.png b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/images/img_kr.png new file mode 100644 index 0000000..c01e0a2 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/images/img_kr.png differ diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/sample.csproj b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/sample.csproj new file mode 100644 index 0000000..ee1ae0b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/sample.csproj @@ -0,0 +1,54 @@ + + + + WinExe + net5-windows + true + + + + + + + + + + + + + + True + True + Resources.resx + + + True + True + Settings.settings + + + True + True + Resource1.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + ResXFileCodeGenerator + Resource1.Designer.cs + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/sample.sln b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/sample.sln new file mode 100644 index 0000000..ac2aac8 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/sample.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31025.218 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sample", "sample.csproj", "{E113EB0C-2D2C-42AC-919C-F5F9BB9C16E7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E113EB0C-2D2C-42AC-919C-F5F9BB9C16E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E113EB0C-2D2C-42AC-919C-F5F9BB9C16E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E113EB0C-2D2C-42AC-919C-F5F9BB9C16E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E113EB0C-2D2C-42AC-919C-F5F9BB9C16E7}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0E9419E4-E6EA-4820-BC96-5337E8353364} + EndGlobalSection +EndGlobal diff --git a/docs/for-win-developers/Windows-Forms/4.Localizing/sample/sample.zip b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/sample.zip new file mode 100644 index 0000000..fa1ed0a Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/4.Localizing/sample/sample.zip differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/images/1.png b/docs/for-win-developers/Windows-Forms/5.Customizing/images/1.png new file mode 100644 index 0000000..b717262 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/images/1.png differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/images/2.png b/docs/for-win-developers/Windows-Forms/5.Customizing/images/2.png new file mode 100644 index 0000000..85da93f Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/images/2.png differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/images/3.png b/docs/for-win-developers/Windows-Forms/5.Customizing/images/3.png new file mode 100644 index 0000000..03abb06 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/images/3.png differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/images/4.png b/docs/for-win-developers/Windows-Forms/5.Customizing/images/4.png new file mode 100644 index 0000000..9ec0e9b Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/images/4.png differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/images/5.png b/docs/for-win-developers/Windows-Forms/5.Customizing/images/5.png new file mode 100644 index 0000000..5f11d8c Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/images/5.png differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/images/6.png b/docs/for-win-developers/Windows-Forms/5.Customizing/images/6.png new file mode 100644 index 0000000..f8aa709 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/images/6.png differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/images/7.png b/docs/for-win-developers/Windows-Forms/5.Customizing/images/7.png new file mode 100644 index 0000000..8b38dd8 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/images/7.png differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/index.md b/docs/for-win-developers/Windows-Forms/5.Customizing/index.md new file mode 100644 index 0000000..585b700 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/index.md @@ -0,0 +1,90 @@ +# 컨트롤 커스터마이징 (UserControl, CustomControl, Form) +Windows Forms에서는 여러 컨트롤들을 조합해서 하나의 컨트롤로 만드는 `UserControl`과 Control를 확장하여 다양한 그리기 효과를 추가할 수 있는 `CustomControl`, 그리고 Form을 폼 디자이너를 통해서 자신만의 폼 형태를 만드는 `From` 확장을 통해 자신만의 컨트롤 커스터마이징을 할 수 있습니다. + +다음으로 각각을 특징에 대해서 짚어보겠습니다. + +- UserControl: `ContainerControl`에서 구현되었으므로 여러 컨트돌들을 포함할 수 있습니다. 또한, `UserControlDocumentDesigner` 및 `ControlDesigner`를 통해 Form처럼 UI 디자이너를 이용해 내부 컨트롤들을 배치하고 구성할 수 있습니다. +- UserControl: UserControl은 `Control`을 부모 클래스로 구현하는 클래스입니다. 일반적으로 `OnPaint()` 메소드를 통해 자신만의 컨트롤 형태를 만들 때 사용할 수 있는데요, `Control` 뿐만 아니라 `Button`등 `Control`에서 파생된 다양한 Windows Forms 컨트롤에서 파생하여 구현한다면 `UserControl`이라고 할 수 있습니다. +- Form: Windows Forms로 개발하는 프로그래머라면 항상 폼 디자이너에서 폼을 디자인 하는 것으로 코딩을 시작할 것 같습니다. Form은 `FormDocumentDesigner`를 통해 UI 디자이너로 컨트롤들을 배치하고 구성할 수 있습니다. 또한, `Form`를 부모 클래스로 해서 자신만의 사용자 폼을 구성할 수 도 있습니다. + +## 테스트 환경 +- Visual Studio 2019 +- .NET 5, C# 9 +- Windows Forms + +## UserControl + +![](images/1.png) + +UI 디자이너를 이용해 폼 디자이너와 유사하게 컨트롤을 배치하면서 화면을 구성할 수 있습니다. + +컴파일을 하게 되면 다음과 같이 해당 UserControl을 선택할 수 있도록 등록이 됩니다. + +![](images/2.png) + +이것을 폼에 끌어다가 붙이면 다음처럼 배치가 되는데요, + +![](images/3.png) + +이렇게 컨트롤들을 하나의 `UserControl`로 묶어서 관리하는 것은 파일선택 컨트롤이나 달력 등, 여러 컨트롤들을 하나로 묶어 한가지 목표를 달성하는 새로운 컨트롤로 만들 때 유용하고, 페이지 단위로 관리하고자 할 때 `UserControl`로 만드는것이 좋습니다. + +## CustomControl + +`Control`및 Control을 부모로 하는 클래스를 상속받아 구현한 컨트롤을 `CustomControl`이라고 합니다. 일반적으로는 그리기 동작을 자신만의 방식으로 바꾸고자 할 때 종종 쓰입니다. + +다음처럼 Control을 상속하여 구현했을 때, + +```csharp + public partial class CustomControl1 : Control + { + public CustomControl1() + { + InitializeComponent(); + } + + protected override void OnPaint(PaintEventArgs pe) + { + base.OnPaint(pe); + + pe.Graphics.DrawEllipse(Pens.White, ClientRectangle); + } + } +``` + +컴파일 후 다음처럼 도구 상자에서 선택할 수 있도록 목록에 나타나게 되는데요, + +![](images/4.png) + +이것을 드래깅하여 배치하면 다음처럼 여러개의 컨트롤로 배치할 수 있게 됩니다. + +![](images/5.png) + +## Form + +Form도 UserControl 처럼 자신만의 형태로 만든 후 재사용할 수 있습니다. 다음과 같이 폼을 만든 후, + +![](images/6.png) + +폼을 새로 만들 때 다음처럼, 위의 폼에서 상속받아 만들면, + +```csharp + public partial class CustomForm1 : CustomForm + { + public CustomForm1() + { + InitializeComponent(); + } + } +``` + +![](images/7.png) + +커스터마이징 된 폼을 사용할 수 있게 됩니다. + +## 샘플 +위의 예제에 대한 샘플 소스코드는 다음의 링크로 다운로드 받아 실행해 볼 수 있습니다. + +- [샘플 소스코드](sample/CustomizingControlSample.zip) + +## 문서 기여자 +- 작성한 사람: 디모이(dimohy) \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample.zip b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample.zip new file mode 100644 index 0000000..433e0fd Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample.zip differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/.vs/CustomizingControlSample/DesignTimeBuild/.dtbcache.v2 b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/.vs/CustomizingControlSample/DesignTimeBuild/.dtbcache.v2 new file mode 100644 index 0000000..42e6c1a Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/.vs/CustomizingControlSample/DesignTimeBuild/.dtbcache.v2 differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/.vs/CustomizingControlSample/v16/.suo b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/.vs/CustomizingControlSample/v16/.suo new file mode 100644 index 0000000..2d5090d Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/.vs/CustomizingControlSample/v16/.suo differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample.sln b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample.sln new file mode 100644 index 0000000..30631b8 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31205.134 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomizingControlSample", "CustomizingControlSample\CustomizingControlSample.csproj", "{8C14AD36-A7F3-4734-BCBE-4AE2BA39A0A1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8C14AD36-A7F3-4734-BCBE-4AE2BA39A0A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C14AD36-A7F3-4734-BCBE-4AE2BA39A0A1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C14AD36-A7F3-4734-BCBE-4AE2BA39A0A1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8C14AD36-A7F3-4734-BCBE-4AE2BA39A0A1}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {33D4A402-C79F-4906-B83A-36AB12256751} + EndGlobalSection +EndGlobal diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomControl1.Designer.cs b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomControl1.Designer.cs new file mode 100644 index 0000000..4c1526f --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomControl1.Designer.cs @@ -0,0 +1,37 @@ + +namespace CustomizingControlSample +{ + partial class CustomControl1 + { + /// + /// 필수 디자이너 변수입니다. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 사용 중인 모든 리소스를 정리합니다. + /// + /// 관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 구성 요소 디자이너에서 생성한 코드 + + /// + /// 디자이너 지원에 필요한 메서드입니다. + /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + } + + #endregion + } +} diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomControl1.cs b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomControl1.cs new file mode 100644 index 0000000..7cd42c3 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomControl1.cs @@ -0,0 +1,27 @@ +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 CustomizingControlSample +{ + public partial class CustomControl1 : Control + { + public CustomControl1() + { + InitializeComponent(); + } + + protected override void OnPaint(PaintEventArgs pe) + { + base.OnPaint(pe); + + pe.Graphics.DrawEllipse(Pens.White, ClientRectangle); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm.Designer.cs b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm.Designer.cs new file mode 100644 index 0000000..850c99a --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm.Designer.cs @@ -0,0 +1,110 @@ + +namespace CustomizingControlSample +{ + partial class CustomForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.titleLabel = new System.Windows.Forms.Label(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel(); + this.toolStripStatusLabel2 = new System.Windows.Forms.ToolStripStatusLabel(); + this.toolStripStatusLabel3 = new System.Windows.Forms.ToolStripStatusLabel(); + this.statusStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // titleLabel + // + this.titleLabel.BackColor = System.Drawing.SystemColors.ActiveCaption; + this.titleLabel.Dock = System.Windows.Forms.DockStyle.Top; + this.titleLabel.Font = new System.Drawing.Font("맑은 고딕", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.titleLabel.Location = new System.Drawing.Point(0, 0); + this.titleLabel.Name = "titleLabel"; + this.titleLabel.Size = new System.Drawing.Size(646, 36); + this.titleLabel.TabIndex = 0; + // + // statusStrip1 + // + this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripStatusLabel1, + this.toolStripStatusLabel2, + this.toolStripStatusLabel3}); + this.statusStrip1.Location = new System.Drawing.Point(0, 384); + this.statusStrip1.Name = "statusStrip1"; + this.statusStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional; + this.statusStrip1.Size = new System.Drawing.Size(646, 22); + this.statusStrip1.TabIndex = 1; + this.statusStrip1.Text = "statusStrip1"; + // + // toolStripStatusLabel1 + // + this.toolStripStatusLabel1.Name = "toolStripStatusLabel1"; + this.toolStripStatusLabel1.Size = new System.Drawing.Size(121, 17); + this.toolStripStatusLabel1.Text = "toolStripStatusLabel1"; + // + // toolStripStatusLabel2 + // + this.toolStripStatusLabel2.Name = "toolStripStatusLabel2"; + this.toolStripStatusLabel2.Size = new System.Drawing.Size(121, 17); + this.toolStripStatusLabel2.Text = "toolStripStatusLabel2"; + // + // toolStripStatusLabel3 + // + this.toolStripStatusLabel3.Name = "toolStripStatusLabel3"; + this.toolStripStatusLabel3.Size = new System.Drawing.Size(121, 17); + this.toolStripStatusLabel3.Text = "toolStripStatusLabel3"; + // + // CustomForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.Control; + this.ClientSize = new System.Drawing.Size(646, 406); + this.ControlBox = false; + this.Controls.Add(this.statusStrip1); + this.Controls.Add(this.titleLabel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "CustomForm"; + this.ShowIcon = false; + this.statusStrip1.ResumeLayout(false); + this.statusStrip1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label titleLabel; + private System.Windows.Forms.StatusStrip statusStrip1; + private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1; + private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel2; + private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel3; + } +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm.cs b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm.cs new file mode 100644 index 0000000..834fd8e --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm.cs @@ -0,0 +1,26 @@ +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 CustomizingControlSample +{ + public partial class CustomForm : Form + { + public override string Text + { + get => titleLabel?.Text ?? ""; + set => titleLabel.Text = value; + } + + public CustomForm() + { + InitializeComponent(); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm.resx b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm1.Designer.cs b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm1.Designer.cs new file mode 100644 index 0000000..af576dc --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm1.Designer.cs @@ -0,0 +1,62 @@ + +namespace CustomizingControlSample +{ + partial class CustomForm1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.textBox1 = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // textBox1 + // + this.textBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBox1.Location = new System.Drawing.Point(0, 15); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(784, 367); + this.textBox1.TabIndex = 2; + // + // CustomForm1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(784, 404); + this.Controls.Add(this.textBox1); + this.Name = "CustomForm1"; + this.Text = "CustomForm1"; + this.Controls.SetChildIndex(this.textBox1, 0); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox textBox1; + } +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm1.cs b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm1.cs new file mode 100644 index 0000000..31c56e3 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm1.cs @@ -0,0 +1,20 @@ +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 CustomizingControlSample +{ + public partial class CustomForm1 : CustomForm + { + public CustomForm1() + { + InitializeComponent(); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm1.resx b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm1.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomForm1.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomizingControlSample.csproj b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomizingControlSample.csproj new file mode 100644 index 0000000..a2d4310 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomizingControlSample.csproj @@ -0,0 +1,9 @@ + + + + WinExe + net5.0-windows + true + + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomizingControlSample.csproj.user b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomizingControlSample.csproj.user new file mode 100644 index 0000000..e75794a --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/CustomizingControlSample.csproj.user @@ -0,0 +1,20 @@ + + + + + Component + + + Form + + + Form + + + Form + + + UserControl + + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/MainForm.Designer.cs b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/MainForm.Designer.cs new file mode 100644 index 0000000..2095497 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/MainForm.Designer.cs @@ -0,0 +1,107 @@ + +namespace CustomizingControlSample +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.customControl11 = new CustomizingControlSample.CustomControl1(); + this.customControl12 = new CustomizingControlSample.CustomControl1(); + this.customControl13 = new CustomizingControlSample.CustomControl1(); + this.userControl12 = new CustomizingControlSample.UserControl1(); + this.button1 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // customControl11 + // + this.customControl11.BackColor = System.Drawing.Color.Blue; + this.customControl11.Location = new System.Drawing.Point(75, 43); + this.customControl11.Name = "customControl11"; + this.customControl11.Size = new System.Drawing.Size(194, 105); + this.customControl11.TabIndex = 1; + this.customControl11.Text = "customControl11"; + // + // customControl12 + // + this.customControl12.BackColor = System.Drawing.Color.Blue; + this.customControl12.Location = new System.Drawing.Point(327, 43); + this.customControl12.Name = "customControl12"; + this.customControl12.Size = new System.Drawing.Size(194, 105); + this.customControl12.TabIndex = 1; + this.customControl12.Text = "customControl11"; + // + // customControl13 + // + this.customControl13.BackColor = System.Drawing.Color.Blue; + this.customControl13.Location = new System.Drawing.Point(567, 43); + this.customControl13.Name = "customControl13"; + this.customControl13.Size = new System.Drawing.Size(194, 105); + this.customControl13.TabIndex = 2; + this.customControl13.Text = "customControl11"; + // + // userControl12 + // + this.userControl12.Location = new System.Drawing.Point(117, 154); + this.userControl12.Name = "userControl12"; + this.userControl12.Size = new System.Drawing.Size(566, 329); + this.userControl12.TabIndex = 0; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(36, 222); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 3; + this.button1.Text = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(786, 460); + this.Controls.Add(this.button1); + this.Controls.Add(this.customControl13); + this.Controls.Add(this.customControl12); + this.Controls.Add(this.customControl11); + this.Controls.Add(this.userControl12); + this.Name = "MainForm"; + this.Text = "Form1"; + this.ResumeLayout(false); + + } + + #endregion + private CustomControl1 customControl11; + private CustomControl1 customControl12; + private CustomControl1 customControl13; + private UserControl1 userControl12; + private System.Windows.Forms.Button button1; + } +} + diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/MainForm.cs b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/MainForm.cs new file mode 100644 index 0000000..be520c1 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/MainForm.cs @@ -0,0 +1,26 @@ +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 CustomizingControlSample +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + + private void button1_Click(object sender, EventArgs e) + { + var form = new CustomForm1(); + form.ShowDialog(); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/MainForm.resx b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/MainForm.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/MainForm.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/Program.cs b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/Program.cs new file mode 100644 index 0000000..711df43 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/Program.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CustomizingControlSample +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.SetHighDpiMode(HighDpiMode.SystemAware); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + //Application.Run(new MainForm()); + Application.Run(new CustomForm1()); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/UserControl1.Designer.cs b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/UserControl1.Designer.cs new file mode 100644 index 0000000..9579bf0 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/UserControl1.Designer.cs @@ -0,0 +1,96 @@ + +namespace CustomizingControlSample +{ + partial class UserControl1 + { + /// + /// 필수 디자이너 변수입니다. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 사용 중인 모든 리소스를 정리합니다. + /// + /// 관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 구성 요소 디자이너에서 생성한 코드 + + /// + /// 디자이너 지원에 필요한 메서드입니다. + /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요. + /// + private void InitializeComponent() + { + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(67, 75); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 60); + this.button1.TabIndex = 0; + this.button1.Text = "button1"; + this.button1.UseVisualStyleBackColor = true; + // + // button2 + // + this.button2.Location = new System.Drawing.Point(67, 141); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(75, 60); + this.button2.TabIndex = 0; + this.button2.Text = "button2"; + this.button2.UseVisualStyleBackColor = true; + // + // button3 + // + this.button3.Location = new System.Drawing.Point(67, 207); + this.button3.Name = "button3"; + this.button3.Size = new System.Drawing.Size(75, 60); + this.button3.TabIndex = 0; + this.button3.Text = "button3"; + this.button3.UseVisualStyleBackColor = true; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(161, 75); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(321, 192); + this.textBox1.TabIndex = 1; + this.textBox1.Text = "Text"; + // + // UserControl1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.textBox1); + this.Controls.Add(this.button3); + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.Name = "UserControl1"; + this.Size = new System.Drawing.Size(558, 341); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.TextBox textBox1; + } +} diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/UserControl1.cs b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/UserControl1.cs new file mode 100644 index 0000000..bc22753 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/UserControl1.cs @@ -0,0 +1,20 @@ +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 CustomizingControlSample +{ + public partial class UserControl1 : UserControl + { + public UserControl1() + { + InitializeComponent(); + } + } +} diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/UserControl1.resx b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/UserControl1.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/UserControl1.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.deps.json b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.deps.json new file mode 100644 index 0000000..cb396ac --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.deps.json @@ -0,0 +1,23 @@ +{ + "runtimeTarget": { + "name": ".NETCoreApp,Version=v5.0", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETCoreApp,Version=v5.0": { + "CustomizingControlSample/1.0.0": { + "runtime": { + "CustomizingControlSample.dll": {} + } + } + } + }, + "libraries": { + "CustomizingControlSample/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + } + } +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.dll b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.dll new file mode 100644 index 0000000..2e6550e Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.dll differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.exe b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.exe new file mode 100644 index 0000000..636b5ec Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.exe differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.pdb b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.pdb new file mode 100644 index 0000000..7f44e56 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.pdb differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.runtimeconfig.dev.json b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.runtimeconfig.dev.json new file mode 100644 index 0000000..ac69ce5 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.runtimeconfig.dev.json @@ -0,0 +1,10 @@ +{ + "runtimeOptions": { + "additionalProbingPaths": [ + "C:\\Users\\dimohy\\.dotnet\\store\\|arch|\\|tfm|", + "C:\\Users\\dimohy\\.nuget\\packages", + "p:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages", + "C:\\Program Files (x86)\\Microsoft\\Xamarin\\NuGet" + ] + } +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.runtimeconfig.json b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.runtimeconfig.json new file mode 100644 index 0000000..dae617c --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/CustomizingControlSample.runtimeconfig.json @@ -0,0 +1,9 @@ +{ + "runtimeOptions": { + "tfm": "net5.0", + "framework": { + "name": "Microsoft.WindowsDesktop.App", + "version": "5.0.0" + } + } +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/ref/CustomizingControlSample.dll b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/ref/CustomizingControlSample.dll new file mode 100644 index 0000000..eddc876 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/bin/Debug/net5.0-windows/ref/CustomizingControlSample.dll differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/CustomizingControlSample.csproj.nuget.dgspec.json b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/CustomizingControlSample.csproj.nuget.dgspec.json new file mode 100644 index 0000000..1351938 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/CustomizingControlSample.csproj.nuget.dgspec.json @@ -0,0 +1,71 @@ +{ + "format": 1, + "restore": { + "W:\\Github\\dotnet-books\\docs\\for-win-developers\\Windows-Forms\\5.Customizing\\sample\\CustomizingControlSample\\CustomizingControlSample\\CustomizingControlSample.csproj": {} + }, + "projects": { + "W:\\Github\\dotnet-books\\docs\\for-win-developers\\Windows-Forms\\5.Customizing\\sample\\CustomizingControlSample\\CustomizingControlSample\\CustomizingControlSample.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "W:\\Github\\dotnet-books\\docs\\for-win-developers\\Windows-Forms\\5.Customizing\\sample\\CustomizingControlSample\\CustomizingControlSample\\CustomizingControlSample.csproj", + "projectName": "CustomizingControlSample", + "projectPath": "W:\\Github\\dotnet-books\\docs\\for-win-developers\\Windows-Forms\\5.Customizing\\sample\\CustomizingControlSample\\CustomizingControlSample\\CustomizingControlSample.csproj", + "packagesPath": "C:\\Users\\dimohy\\.nuget\\packages\\", + "outputPath": "W:\\Github\\dotnet-books\\docs\\for-win-developers\\Windows-Forms\\5.Customizing\\sample\\CustomizingControlSample\\CustomizingControlSample\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [ + "p:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages", + "C:\\Program Files (x86)\\Microsoft\\Xamarin\\NuGet\\" + ], + "configFilePaths": [ + "C:\\Users\\dimohy\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Xamarin.Offline.config" + ], + "originalTargetFrameworks": [ + "net5.0-windows7.0" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net5.0-windows7.0": { + "targetAlias": "net5.0-windows", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + } + }, + "frameworks": { + "net5.0-windows7.0": { + "targetAlias": "net5.0-windows", + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + }, + "Microsoft.WindowsDesktop.App.WindowsForms": { + "privateAssets": "none" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\5.0.203\\RuntimeIdentifierGraph.json" + } + } + } + } +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/CustomizingControlSample.csproj.nuget.g.props b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/CustomizingControlSample.csproj.nuget.g.props new file mode 100644 index 0000000..224de19 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/CustomizingControlSample.csproj.nuget.g.props @@ -0,0 +1,20 @@ + + + + True + NuGet + $(MSBuildThisFileDirectory)project.assets.json + $(UserProfile)\.nuget\packages\ + C:\Users\dimohy\.nuget\packages\;p:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages;C:\Program Files (x86)\Microsoft\Xamarin\NuGet\ + PackageReference + 5.9.1 + + + + + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/CustomizingControlSample.csproj.nuget.g.targets b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/CustomizingControlSample.csproj.nuget.g.targets new file mode 100644 index 0000000..53cfaa1 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/CustomizingControlSample.csproj.nuget.g.targets @@ -0,0 +1,6 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/.NETCoreApp,Version=v5.0.AssemblyAttributes.cs b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/.NETCoreApp,Version=v5.0.AssemblyAttributes.cs new file mode 100644 index 0000000..2f7e5ec --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/.NETCoreApp,Version=v5.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v5.0", FrameworkDisplayName = "")] diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.AssemblyInfo.cs b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.AssemblyInfo.cs new file mode 100644 index 0000000..419d710 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.AssemblyInfo.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------------------------ +// +// 이 코드는 도구를 사용하여 생성되었습니다. +// 런타임 버전:4.0.30319.42000 +// +// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면 +// 이러한 변경 내용이 손실됩니다. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("CustomizingControlSample")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] +[assembly: System.Reflection.AssemblyProductAttribute("CustomizingControlSample")] +[assembly: System.Reflection.AssemblyTitleAttribute("CustomizingControlSample")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] +[assembly: System.Runtime.Versioning.TargetPlatformAttribute("Windows7.0")] +[assembly: System.Runtime.Versioning.SupportedOSPlatformAttribute("Windows7.0")] + +// MSBuild WriteCodeFragment 클래스에서 생성되었습니다. + diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.AssemblyInfoInputs.cache b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.AssemblyInfoInputs.cache new file mode 100644 index 0000000..3bf05e9 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +cf5e85b056d8c753b2997a234b2f512beb9fef38 diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.CustomForm.resources b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.CustomForm.resources new file mode 100644 index 0000000..6c05a97 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.CustomForm.resources differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.CustomForm1.resources b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.CustomForm1.resources new file mode 100644 index 0000000..6c05a97 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.CustomForm1.resources differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.GeneratedMSBuildEditorConfig.editorconfig b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 0000000..7694274 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,8 @@ +is_global = true +build_property.TargetFramework = net5.0-windows +build_property.TargetPlatformMinVersion = 7.0 +build_property.UsingMicrosoftNETSdkWeb = +build_property.ProjectTypeGuids = +build_property.PublishSingleFile = +build_property.IncludeAllContentForSelfExtract = +build_property._SupportedPlatformList = Android,iOS,Linux,macOS,Windows diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.MainForm.resources b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.MainForm.resources new file mode 100644 index 0000000..6c05a97 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.MainForm.resources differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.UserControl1.resources b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.UserControl1.resources new file mode 100644 index 0000000..6c05a97 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.UserControl1.resources differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.assets.cache b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.assets.cache new file mode 100644 index 0000000..132c4b3 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.assets.cache differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.csproj.CoreCompileInputs.cache b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..5b948e2 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +3ab09369498c52afca5754a134f23bf071354c3a diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.csproj.FileListAbsolute.txt b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..3c5d42a --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.csproj.FileListAbsolute.txt @@ -0,0 +1,21 @@ +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\bin\Debug\net5.0-windows\CustomizingControlSample.exe +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\bin\Debug\net5.0-windows\CustomizingControlSample.deps.json +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\bin\Debug\net5.0-windows\CustomizingControlSample.runtimeconfig.json +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\bin\Debug\net5.0-windows\CustomizingControlSample.runtimeconfig.dev.json +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\bin\Debug\net5.0-windows\CustomizingControlSample.dll +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\bin\Debug\net5.0-windows\ref\CustomizingControlSample.dll +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\bin\Debug\net5.0-windows\CustomizingControlSample.pdb +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\obj\Debug\net5.0-windows\CustomizingControlSample.csprojAssemblyReference.cache +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\obj\Debug\net5.0-windows\CustomizingControlSample.UserControl1.resources +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\obj\Debug\net5.0-windows\CustomizingControlSample.csproj.GenerateResource.cache +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\obj\Debug\net5.0-windows\CustomizingControlSample.GeneratedMSBuildEditorConfig.editorconfig +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\obj\Debug\net5.0-windows\CustomizingControlSample.AssemblyInfoInputs.cache +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\obj\Debug\net5.0-windows\CustomizingControlSample.AssemblyInfo.cs +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\obj\Debug\net5.0-windows\CustomizingControlSample.csproj.CoreCompileInputs.cache +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\obj\Debug\net5.0-windows\CustomizingControlSample.dll +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\obj\Debug\net5.0-windows\ref\CustomizingControlSample.dll +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\obj\Debug\net5.0-windows\CustomizingControlSample.pdb +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\obj\Debug\net5.0-windows\CustomizingControlSample.genruntimeconfig.cache +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\obj\Debug\net5.0-windows\CustomizingControlSample.CustomForm.resources +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\obj\Debug\net5.0-windows\CustomizingControlSample.MainForm.resources +W:\Github\dotnet-books\docs\for-win-developers\Windows-Forms\5.Customizing\sample\CustomizingControlSample\CustomizingControlSample\obj\Debug\net5.0-windows\CustomizingControlSample.CustomForm1.resources diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.csproj.GenerateResource.cache b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.csproj.GenerateResource.cache new file mode 100644 index 0000000..4086c02 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.csproj.GenerateResource.cache differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.csprojAssemblyReference.cache b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.csprojAssemblyReference.cache new file mode 100644 index 0000000..9b60897 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.csprojAssemblyReference.cache differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.designer.deps.json b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.designer.deps.json new file mode 100644 index 0000000..74b9003 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.designer.deps.json @@ -0,0 +1,11 @@ +{ + "runtimeTarget": { + "name": ".NETCoreApp,Version=v5.0", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETCoreApp,Version=v5.0": {} + }, + "libraries": {} +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.designer.runtimeconfig.json b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.designer.runtimeconfig.json new file mode 100644 index 0000000..086f149 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.designer.runtimeconfig.json @@ -0,0 +1,18 @@ +{ + "runtimeOptions": { + "tfm": "net5.0", + "framework": { + "name": "Microsoft.WindowsDesktop.App", + "version": "5.0.0" + }, + "additionalProbingPaths": [ + "C:\\Users\\dimohy\\.dotnet\\store\\|arch|\\|tfm|", + "C:\\Users\\dimohy\\.nuget\\packages", + "p:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages", + "C:\\Program Files (x86)\\Microsoft\\Xamarin\\NuGet" + ], + "configProperties": { + "Microsoft.NETCore.DotNetHostPolicy.SetAppPaths": true + } + } +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.dll b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.dll new file mode 100644 index 0000000..2e6550e Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.dll differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.genruntimeconfig.cache b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.genruntimeconfig.cache new file mode 100644 index 0000000..904a761 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.genruntimeconfig.cache @@ -0,0 +1 @@ +ad18c44be411bc585f2469c1d83c7dfd3f9cf54e diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.pdb b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.pdb new file mode 100644 index 0000000..7f44e56 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/CustomizingControlSample.pdb differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/apphost.exe b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/apphost.exe new file mode 100644 index 0000000..636b5ec Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/apphost.exe differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/ref/CustomizingControlSample.dll b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/ref/CustomizingControlSample.dll new file mode 100644 index 0000000..eddc876 Binary files /dev/null and b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/Debug/net5.0-windows/ref/CustomizingControlSample.dll differ diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/project.assets.json b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/project.assets.json new file mode 100644 index 0000000..3a9f69f --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/project.assets.json @@ -0,0 +1,78 @@ +{ + "version": 3, + "targets": { + "net5.0-windows7.0": {} + }, + "libraries": {}, + "projectFileDependencyGroups": { + "net5.0-windows7.0": [] + }, + "packageFolders": { + "C:\\Users\\dimohy\\.nuget\\packages\\": {}, + "p:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {}, + "C:\\Program Files (x86)\\Microsoft\\Xamarin\\NuGet\\": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "W:\\Github\\dotnet-books\\docs\\for-win-developers\\Windows-Forms\\5.Customizing\\sample\\CustomizingControlSample\\CustomizingControlSample\\CustomizingControlSample.csproj", + "projectName": "CustomizingControlSample", + "projectPath": "W:\\Github\\dotnet-books\\docs\\for-win-developers\\Windows-Forms\\5.Customizing\\sample\\CustomizingControlSample\\CustomizingControlSample\\CustomizingControlSample.csproj", + "packagesPath": "C:\\Users\\dimohy\\.nuget\\packages\\", + "outputPath": "W:\\Github\\dotnet-books\\docs\\for-win-developers\\Windows-Forms\\5.Customizing\\sample\\CustomizingControlSample\\CustomizingControlSample\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [ + "p:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages", + "C:\\Program Files (x86)\\Microsoft\\Xamarin\\NuGet\\" + ], + "configFilePaths": [ + "C:\\Users\\dimohy\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Xamarin.Offline.config" + ], + "originalTargetFrameworks": [ + "net5.0-windows7.0" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net5.0-windows7.0": { + "targetAlias": "net5.0-windows", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + } + }, + "frameworks": { + "net5.0-windows7.0": { + "targetAlias": "net5.0-windows", + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + }, + "Microsoft.WindowsDesktop.App.WindowsForms": { + "privateAssets": "none" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\5.0.203\\RuntimeIdentifierGraph.json" + } + } + } +} \ No newline at end of file diff --git a/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/project.nuget.cache b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/project.nuget.cache new file mode 100644 index 0000000..1d36b48 --- /dev/null +++ b/docs/for-win-developers/Windows-Forms/5.Customizing/sample/CustomizingControlSample/CustomizingControlSample/obj/project.nuget.cache @@ -0,0 +1,8 @@ +{ + "version": 2, + "dgSpecHash": "i8VgZenEHfhqQ0Rp02QlzCEaNCJUnZrt0K+qBCbmVLIn4E/CUJlGC7P4sMTw7Ys/UpU7Wo2JHFo78F7MwihatQ==", + "success": true, + "projectFilePath": "W:\\Github\\dotnet-books\\docs\\for-win-developers\\Windows-Forms\\5.Customizing\\sample\\CustomizingControlSample\\CustomizingControlSample\\CustomizingControlSample.csproj", + "expectedPackageFiles": [], + "logs": [] +} \ No newline at end of file diff --git a/docs/for-win-developers/index.md b/docs/for-win-developers/index.md new file mode 100644 index 0000000..bf59924 --- /dev/null +++ b/docs/for-win-developers/index.md @@ -0,0 +1,17 @@ +# Windows 애플리케이션 개발자를 위한 닷넷 + +## Windows Forms +- [Anchor, Dock을 이용한 컨트롤 레이아웃 디자인](Windows-Forms/1.DesignControlLayout/index.md) +- DataTable 바인딩, BindingList 바인딩 +- 스레드 / 타이머 / Task 및 비동기 키워드 +- Invoke 및 BegineInvoke +- MDI 및 다중 폼 사용시 유용한 기술 +- [GDI+를 사용해보자](Windows-Forms/3.LetsUseGDIPlus/index.md) +- 리플렉션 +- 스마트하게 코딩 - 리팩토링 +- [컨트롤 커스터마이징 (UserControl, CustomControl, Form)](Windows-Forms/5.Customizing/index.md) +- 열거형과 어트리뷰트를 이용한 전략패턴 만들어보기 +- 유닛테스트 사용해보기 (xunit, nunit) +- 디자인 타임을 사용하지 않고 윈폼 개발 +- [디자인패턴을 이용한 DLL 동적 로딩](Windows-Forms/2.DynamicLinkedLibrary/index.md) +- [지역화 기능을 이용한 다국어 지원하기](Windows-Forms/4.Localizing/index.md)