"주소록의 Setup파일 생성하기"도 앞서 했던 "DotNetCalc의 Setup파일 생성하기"의 과정과 거의 동일하다. "주소록의 Setup파일 생성하기"에서는 아주 조금만 다르게 Setup파일을 생성한다.


이전에 만들었던 "주소록"프로젝트(주소록.sln)를 열어서 --> [파일] -> [추가] -> [새 프로젝트] 클릭 --> [새 프로젝트 추가] 창에서 '프로젝트 형식'을 [기타 프로젝트 형식]으로 선택하면 [설치 및 배포] 선택 --> 오른쪽 창의 'Visual Studio에 설치되어 있는 템플릿'에서 [설치 프로젝트] 선택하고 파일'이름'은 "AddressSetup"으로 하고 저장'위치'는 "C:\...\주소록"으로 지정한 후 '확인'버튼 클릭

--> 생성된 [파일 시스템 (AddressSetup)] 창에서 [응용 프로그램 폴더]에 마우스 우클릭 ->[추가] ->[폴더] 클릭하고 '새 폴더'의 이름은 [주소록]으로 지정한다. --> [사용자 프로그램 메뉴]에도 [응용 프로그램 폴더]에서 "새 폴더"를 추가했던 방식과 똑같은 방식으로 '새 폴더'를 추가하여 이름은 [Psh주소록]으로 지정한다. --> [사용자 바탕 화면]에서는 "새 폴더"를 추가하지 않는다.

--> [응용 프로그램 폴더]의 [주소록]폴더를 마우스로 선택한 후 오른쪽에 있는 창을 '우클릭'하여 [추가] -> [프로젝트 출력] 클릭 -->[프로젝트 출력 그룹 추가]창에서 "기본 출력/지역화된 리소스/디버그 기호/콘텐츠 파일/소스 파일/문서 파일/XML Serialization 어셈블리"를 마우스로 모두 긁어서 선택하고 '확인'버튼 클릭하면 다음과 같이 나온다.



--> 위 그림의 오른쪽 창에서 "주소록의 기본 출력"파일은 실행파일인 "exe"파일과 같으며 "주소록의 소스 파일"은 "Program.cs"와 같은 "*.cs"파일과 같다. 여기서는 [프로젝트 출력]으로 파일을 추가하는 방식을 사용한 점이 앞에서 해봤던 "DotNetCalcSetup"프로젝트에서 [응용 프로그램 폴더]의 하위폴더에 파일을 추가한 방식([추가] -> [파일] 클릭)과 다른점이다. 그리고 여기서는 [프로젝트 출력 그룹 추가]창에서 모든 항목을 선택해서 모든 파일이 [응용 프로그램 폴더]의 [주소록]폴더에 추가된 것이다.

--> [솔루션 탐색기]에서도 "AddressSetup"파일 내에 모든 파일이 추가된 것을 볼 수 있다.


--> [사용자 프로그램 메뉴]의 [Psh주소록]에서는 "바로가기"만 하나 만들건데 --> [사용자 프로그램 메뉴]의 [Psh주소록]을 마우스로 선택한 후 오른쪽에 있는 창을 '우클릭'하여 [새 바로 가기 만들기] 클릭 --> [프로젝트에서 항목 선택] 창에서 '찾는 위치'를 [응용 프로그램 폴더] -> [주소록] -> [주소록의 기본 출력(활성)]을 선택하고 '확인'버튼 클릭하면 "주소록의 기본 출력(활성) 바로 가기"로 초기이름이 설정될 때 "주소록"으로 바로가기 '이름' 변경

--> [파일 시스템(AddressSetup)]의 [사용자 바탕 화면]에서는 하위에 "새 폴더" 추가하지 않고 바로 "바로가기"를 만들건데 --> [사용자 바탕 화면]을 마우스로 선택한 후 오른쪽에 있는 창을 '우클릭'하여 [새 바로 가기 만들기] 클릭 --> [프로젝트에서 항목 선택] 창에서 '찾는 위치'를 [응용 프로그램 폴더] -> [주소록] -> [주소록의 기본 출력(활성)]을 선택하고 '확인'버튼 클릭하면 "주소록의 기본 출력(활성) 바로 가기"로 초기이름이 설정될 때 "Psh주소록"으로 바로가기 '이름' 변경(윗단락에서 만든 바로가기인 "주소록"바로가기와 지금 만든 "Psh주소록"바로가기의 이름은 다르지만 같은 파일(바로가기)이다.)

--> 윗단락까지는 "DotNetCalcSetup"파일만들기와 거의 비슷한데, "주소록"프로젝트에서는 여기에 더하여 "아이콘(Icon)"파일을 만들어서 폼과 바로가기에 아이콘그림이 삽입되어 보여지도록 할 것이다. 우선 이제 만들 아이콘 파일을 이전에 만들었던 "주소록"프로젝트에 추가한다.

. "아이콘(Icon)"파일 만들기(파일이름은 "Address.ico"로 지정)



--> 위 그림에서 "새 항목"을 추가하면 아래 그림과 같이 "새 항목 추가 - 주소록"창이 나오고 여기서 '템플릿'에서 "아이콘 파일"을 선택 후 파일이름을 "Address.ico"로 지정 후 "추가"버튼 클릭 



--> [솔루션 탐색기]의 "주소록"프로젝트에 저장한 "Address.ico"파일이 추가된 것을 볼 수 있다.



--> 아래 그림과 같이 아이콘 이미지를 그린 후 저장한다. (그림에서 "16 * 16  4비트"그림은 '폼'의 타이틀바 및 '윈도우즈 [시작]키'에서의 [사용자 프로그램 메뉴] - [Psh주소록]폴더내에 "[주소록]바로가기"아이콘에 들어가는 이미지이며 / "32 * 32  4비트" 그림은 바탕화면의 "[Psh주소록]바로가기"아이콘에 들어가는 이미지이다. 여기서는 16 * 16, 32 * 32 모두 그림을 똑같이 그렸다.)



. "주소록"프로그램 폼(MainForm.cs [디자인])의 속성에 내가 만들어서 저장한 "Address.ico"아이콘 파일을 넣어서 "주소록"프로그램 실행시 폼의 Title출력되는 곳에 저장한 아이콘 출력하기

--> MainForm.cs [디자인]에서 "속성"에서 "Icon"속성을 클릭하여 들어가면 -->"열기"창이 뜨는데 내가 만들어서 저장한 아이콘파일(Address.ico)이 저장된 위치(C:\...\주소록\주소록\Address.ico)를 찾아서 선택하여 "열기"버튼 클릭 --> MainForm.cs [디자인]에서 '폼'을 클릭하고 실행(F5)해보면 아래 그림과 같이 '폼'의 타이틀바에 '아이콘이미지'가 나온다.




. "폼의 타이틀바" 에 아이콘이미지 추가하기를 실행해보았으니, 이번에는 '윈도우즈 [시작]키'에서의 [사용자 프로그램 메뉴] - [Psh주소록]폴더내에 "[주소록]바로 가기" 아이콘에 이미지 추가와 / 바탕화면의 "[Psh주소록]바로 가기"에 "아이콘 이미지" 추가하기.

--> [파일 시스템]에서 [응용 프로그램 폴더] - [주소록]을 마우스로 선택하고 오른쪽 창 우클릭 -> [추가] -> [파일] 클릭 -> [파일 추가]창에서 "C:\...\주소록\주소록\Address.ico"선택하여 '열기'버튼 클릭하면 아래그림과 같이 "Address.ico"파일이 오른쪽 창에 추가된 것을 볼 수 있다.



--> [파일 시스템]에서 [사용자 프로그램 메뉴] - [Psh주소록]을 마우스로 선택 후 오른쪽 창에 있는 [주소록](바로 가기) 마우스로 선택하면 [속성]창 -> [Icon]에서 "(찾아보기..)"클릭 -> [아이콘]창 에서 "찾아보기"버튼 클릭 -> [프로젝트에서 항목 선택]창에서 [응용 프로그램 폴더] -> [주소록] -> "Address.ico"선택 후 '확인'버튼 클릭하면 -> 다시 [아이콘]창에서 선택한 아이콘이미지(Address.ico)가 나오며 이를 선택하고 '확인'버튼 클릭하면 아래그림과 같이 [Icon]속성창에 아이콘이미지가 추가된다.



--> [파일 시스템]에서 [사용자 바탕 화면]에도 바로 위에서와 똑같이 아이콘 이미지를 추가한다. -> [파일 시스템]에서 [사용자 바탕 화면]을 마우스로 선택 후 오른쪽 창에 있는 [Psh주소록](바로 가기) 마우스로 선택하면 [속성]창 -> [Icon]에서 "(찾아보기..)"클릭 -> [아이콘]창 에서 "찾아보기"버튼 클릭 -> [프로젝트에서 항목 선택]창에서 [응용 프로그램 폴더] -> [주소록] -> "Address.ico"선택 후 '확인'버튼 클릭하면 -> 다시 [아이콘]창에서 선택한 아이콘이미지(Address.ico)가 나오며 이를 선택하고 '확인'버튼 클릭하면 윗그림과 같이 [Icon]속성창에 아이콘이미지가 추가된다.(다만 아이콘이미지를 추가하는 파일(위치)만 다를 뿐이다.) --> 이로써 "Address.ico"파일 이미지를 '윈도우즈 [시작]키'에서의 [사용자 프로그램 메뉴] - [Psh주소록]폴더내에 "[주소록]바로 가기"와 / 바탕화면의 "[Psh주소록]바로 가기"에 추가하는 과정은 끝났다.


. "빌드"를 해서 "AddressSetup"실행(exe/msi)파일 생성하고 "AddressSetup"파일을 실행하여 "주소록 프로그램"설치 및 "Address.ico"파일 이미지가 '윈도우즈 [시작]키'에서의 [사용자 프로그램 메뉴] - [Psh주소록]폴더내에 "[주소록]바로 가기"와 / 바탕화면의 "[Psh주소록]바로 가기"에 추가된 것 확인하기.

--> [솔루션 탐색기]에서 [AddressSetup] 마우스 우클릭 -> [빌드] 클릭하면 아래그림과 같이 "AddressSetup.msi" 파일과 "setup.exe"파일이 C:\주소록\AddressSetup\Debug폴더에 생성된다.



--> "AddressSetup.msi" 파일 또는 "setup.exe"파일을 실행하여 "주소록 프로그램"바로 가기를 아래그림과 같이 생성한다.





-->바탕화면에 "[Psh주소록]바로 가기"가 설치 된 화면(아이콘이미지도 추가되었음.)


--> '윈도우즈'[시작] - [모든 프로그램] - [Psh주소록]폴더에 "[주소록]바로 가기"가 설치 된 화면(역시 아이콘이미지가 추가된 것을 볼 수 있다.) 


--> "바탕화면"에 있는 "[Psh주소록]바로가기"나 "'윈도우즈'[시작] - [모든 프로그램] - [Psh주소록]에 "[주소록]바로 가기"를 실행하면 아래그림과 같이 "주소록 프로그램 V0.1"이 실행된다. 




// 참고

--> [내 컴퓨터] - [제어판] - [프로그램 추가/제거]에 설치되어있는 "AddressSetup"파일을 제거하면 "바탕화면"에 있는 "[Psh주소록]바로가기"가 삭제되고 / '윈도우즈'[시작] - [모든 프로그램]에서도 [Psh주소록]폴더가 삭제되는데, "C:\주소록\AddressSetup\Debug폴더"에 생성되었었던 "AddressSetup.msi" 파일과 "setup.exe"파일은 남아있는다.




Posted by holland14
:

지난번에 만들었던 간단한 계산기 프로그램인 "DotNetCalc"프로젝트(DotNetCalc.sln)를 열어서 --> [파일] -> [추가] -> [새 프로젝트] 클릭 --> [새 프로젝트 추가] 창에서 '프로젝트 형식'을 [기타 프로젝트 형식]으로 선택하면 [설치 및 배포] 선택 --> 오른쪽 창의 'Visual Studio에 설치되어 있는 템플릿'에서 [설치 프로젝트] 선택하고 파일'이름'은 "DotNetCalcSetup"으로 하고 저장'위치'는 "C:\...\DotNetCalc"로 지정한 후 '확인'버튼 클릭

-->생성된 [파일 시스템 (DotNetCalcSetup)] 창에서 [사용자 바탕 화면]에 마우스 우클릭 ->[추가] ->[폴더] 클릭하고 '새 폴더'의 이름은 [DotNetCalc]로 지정한다. [사용자 바탕 화면] 아래에 있는 [사용자 프로그램 메뉴]와 [응용 프로그램 폴더]도 같은 방식으로 '새 폴더'를 추가하여 폴더이름도 동일하게 [DotNetCalc]로 한다.

--> [응용 프로그램 폴더]의 [DotNetCalc]를 마우스로 선택한 후 오른쪽에 있는 창을 '우클릭'하여 [추가] -> [파일] 클릭 --> [파일 추가] 창에서 C:\...\DotNetCalc폴더에서 [bin] -> [Debug]폴더 내의 DotNetCalc.exe 파일을 선택하여 "열기"버튼 클릭(이 과정을 통해 "응용 프로그램 폴더" 내에 실행파일인 "exe파일"이 추가된 것이다.  이것은 보통 프로그램을 깔면 C드라이브의 "Program Files"폴더 안에 '해당프로그램 폴더'와 '그 폴더 안에 exe파일'이 들어있는 것과 같은 원리라고 할 수 있다.)

--> [사용자 프로그램 메뉴]의 [DotNetCalc]폴더 마우스로 선택한 후 오른쪽에 있는 창을 '우클릭'하여 [새 바로 가기 만들기] 클릭 --> [프로젝트에서 항목 선택] 창에서 '찾는 위치'를 [응용 프로그램 폴더] -> [DotNetCalc] -> [DotNetCalc.exe] 선택하고 '확인'버튼 클릭하면 "DotNetCalc.exe 바로 가기"로 초기이름이 설정될 때 "DotNetCalc"로 이름 변경(이 과정은 '윈도우즈'의 "시작"버튼 - "모든 프로그램"을 클릭하면 나오는 '폴더'로 들어있는 "(프로그램)바로가기"와 폴더없이 아이콘과 (프로그램)바로가기를 만드는 과정이다. 여기서는 폴더를 생성하여 폴더 안에 바로가기를 하였다. '찾는 위치'를 [응용 프로그램 폴더] -> [DotNetCalc] -> [DotNetCalc.exe]로 선택하는 과정은 실제 실행파일인 exe파일이 들어있는 C드라이브 내 [응용 프로그램 폴더]에서 [DotNetCalc] ->[DotNetCalc.exe]로 링크를 (바로가기에) 걸어준 것이라 할 수 있다.)

--> [사용자 바탕 화면]의 [DotNetCalc]폴더 마우스로 선택한 후 오른쪽에 있는 창을 '우클릭'하여 [새 바로 가기 만들기] 클릭 --> 바로 위와 마찬가지로 [프로젝트에서 항목 선택] 창에서 '찾는 위치'를 [응용 프로그램 폴더] -> [DotNetCalc] -> [DotNetCalc.exe] 선택하고 '확인'버튼 클릭하면 "DotNetCalc.exe 바로 가기"로 초기이름이 설정될 때 "DotNetCalc"로 이름 변경                  --> 파일을 추가하기 위해서 [사용자 바탕 화면]의 [DotNetCalc]폴더 마우스로 선택한 후 오른쪽에 있는 창을 '우클릭'하여 [추가] -> [파일] 클릭 --> [파일 추가] 창에서 C:\...\DotNetCalc폴더에서 [bin] -> [Debug]폴더 내의 DotNetCalc.exe 파일을 선택하여 "열기"버튼 클릭하면 "DotNetCalc.exe"파일이 추가된다.(여기에서는 바탕화면에 생성될 "DotNetCalc"폴더 안에 "바로가기"와 "exe"파일을 만드는 과정을 한 것이다.)

--> [응용 프로그램 폴더], [사용자 프로그램 메뉴], [사용자 바탕 화면]에 각각 [DotNetCalc]폴더를 만들고 각각 바로가기 및 exe파일을 추가(만든)한 후 [솔루션 탐색기]의 [DotNetCalcSetup] 마우스 우클릭 -> [빌드] 클릭("빌드"까지 하면 "C:\...\DotNetCalc\DotNetCalcSetup"폴더의 "Debug"폴더 안에 "DotNetCalcSetup.msi"파일과 "setup.exe"파일이 생성된다.) (참고로 "DotNetCalcSetup.msi" 파일과 "setup.exe"파일은 같은 폴더에 있거나 또는 함께 있어야 한다. 윈도우즈 운영체제에서 *.msi파일은 setup.exe파일과 다른 위치에 있어도 단독으로 실행되어 설치를 진행하지만, 반대로 setup.exe파일은 msi파일과 따로 존재하는 경우 실행되지 않는다. 그런데 setup.exe파일이 *.msi파일과 같은 폴더에 있거나 함께 있는 경우에는 setup.exe파일을 실행해보면 정상적으로 실행되어 설치가 진행된다. 결론적으로 윈도우즈 운영체제에서 setup.exe파일은 *.msi파일이 실행되기위한 도우미 같은 역할을 한다고 생각할 수 있다.)

--> "빌드"를 통해 "C:\...\DotNetCalc\DotNetCalcSetup\Debug"폴더에 생성된 "DotNetCalcSetup.msi"파일 또는 "setup.exe"파일을 실행하면 '설치마법사' 창이 뜨면서 설치가 진행되며, 설치가 다 된 후에는 "바탕화면"에 "DotNetCalc"폴더와 그 안에는 "DotNetCalc.exe"와 "DotNetCalc 바로가기"가 설치되며, 윈도우즈의 [시작] -> [모든 프로그램]에 "DotNetCalc"폴더와 그 안에 "DotNetCalc 바로가기"가 만들어진다. 


/* 실습으로 설치된 "DotNetCalcSetup"파일은 [내 컴퓨터] ->[제어판] ->[프로그램 추가/제거]에 들어가서 찾아서 삭제할 것 */





< 실행결과 >

--> "빌드"한 후에 "C:\...\DotNetCalc\DotNetCalcSetup\Debug"폴더에 "DotNetCalcSetup.msi"파일과 "setup.exe"파일이 생성되었다.





--> 위에서 빌드후 생성된 "DotNetCalcSetup.msi"파일 또는 "setup.exe"파일 둘 중 하나를 실행하여 '설치마법사'창에서 설치를 완료하면, "바탕화면"에 "DotNetCalc"폴더가 만들어지고, 이 폴더안에 "DotNetCalc 바로가기"와 "DotNetCalc.exe"파일이 만들어진다.




--> '윈도우즈'의 "시작"에 "모든 프로그램"을 보면 "DotNetCalc"폴더와 그 폴더 안에 "DotNetCalc 바로가기"가 설치된 것을 볼 수 있다.




--> "바탕화면"에 설치된 "DotNetCalc"폴더 내의 "DotNetCalc 바로가기" 또는 "DotNetCalc.exe"파일을 실행하거나 / "시작 - 모든 프로그램"에 설치된 "DotNetCalc"폴더 안의 "DotNetCalc 바로가기"를 실행하면 아래와 같이 계산기 프로그램이 실행된다.




Posted by holland14
:


==> Program.cs


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

namespace DotNetCalc
{
    static class Program
    {
        /// <summary>
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
}



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




==> MainForm.cs



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DotNetCalc
{
    public partial class MainForm : Form
    {
        private string buffer; // 입력된 문자열들을 묶어줄 그릇

        public MainForm()
        {
            InitializeComponent();
        }
               
        private void btnCommand_Click(object sender, EventArgs e)
        {
            Button btn = sender as Button;

    #region 각각의 버튼 클릭시 해당 문자열을 buffer에 담기

  if (btn == btnOne)
         {
          buffer += "1";
         }
            else if (btn == btnTwo)
         {
                buffer += "2";
         }
            else if (btn == btnThree)
         {
                buffer += "3";
         }
            else if (btn == btnFour)
         {
                buffer += "4";
         }
            else if (btn == btnFive)
         {
                buffer += "5";
         }
            else if (btn == btnSix)
         {
                buffer += "6";
         }
            else if (btn == btnSeven)
         {
                buffer += "7";
         }
            else if (btn == btnEight)
         {
                buffer += "8";
         }
            else if (btn == btnNine)
         {
                buffer += "9";
         }
                else if (btn == btnZero)
         {
                buffer += "0";
         }
            else if (btn == btnLeft)
         {
                buffer += "(";
         }
            else if (btn == btnRight)
         {
                buffer += ")";
         }
            else if (btn == btnPlus)
         {
                buffer += " + ";
         }
            else if (btn == btnMinus)
         {
                buffer += " - ";
         }
            else if (btn == btnMultiply)
         {
                buffer += " * ";
         }
            else if (btn == btnDivide)
         {
                buffer += " / ";
         }
            else if (btn == btnPoint)
         {
                buffer += ".";
         }

 #endregion

            txtExpression.Text = buffer;
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            buffer = String.Empty;
            txtExpression.Text = "";
        }

        private void btnBackspace_Click(object sender, EventArgs e)
        {
            if (buffer.Length > 0)
            {
                // 마지막 한자리 삭제
                buffer = buffer.Substring(0, buffer.Length - 1);
                txtExpression.Text = buffer;
            }
        }

        // 문자열로 지정된 수식을 실제 수식으로 변환 후 결과값 계산
        private void btnEnter_Click(object sender, EventArgs e)
        {
            // 문자열 수식에서 공백 제거
            string temp = txtExpression.Text.Replace(" ", "");
            if (String.IsNullOrEmpty(temp))
            {
                MessageBox.Show("수식을 입력하시오.");
                return;
            }
            this.txtExpression.Text += " = \r\n\r\n" + MakeExpression(ref temp).ToString();
            buffer = ""; // 버퍼 초기화(= 최상위 buffer는 널값으로 초기화)
        }


       
        // MakeExpression : 결과값 텍스트박스에 출력, 공백이 제거되어 넘겨져온 수식을 계산한다.
        /// <summary>
        /// [4] 문자열로 지정된 계산식을 실제 계산식으로 변경
        /// </summary>
        /// <param name="str">3 * (2 + 3)</param>
        /// <returns>15</returns>
        public double MakeExpression(ref string str)
        {
            int index = 0; // 문자 위치
            // 구문 결과값 가져오기
            double value = Sentence(ref str, ref index);
            while (index < str.Length)
            {
                switch (str[index])
                {
                    case '+':
                        ++(index);
                        value += Sentence(ref str, ref index);
                        break;
                    case '-':
                        ++(index);
                        value -= Sentence(ref str, ref index);
                        break;
                    default: // 엉뚱한 값이 들어오는 경우
                        MessageBox.Show("잘못된 구문입니다.");
                        break;
                }
            }
            return value;
        }


        /// <summary>
        /// [3] 하나의 완성된 수식을 계산하는 메서드
        ///     (3 * 5) = 15
        /// </summary>
        /// <param name="str">(3 * 5)</param>
        /// <param name="index">0</param>
        /// <returns>15</returns>
        public double Sentence(ref string str, ref int index)
        {
            double value = GetNumber(ref str, ref index); // 첫번째 숫자
            while (index < str.Length)
            {
                if (str[index] == '*')
                {
                    ++(index);
                    value *= GetNumber(ref str, ref index);
                }
                else if (str[index] == '/')
                {
                    ++(index);
                    value /= GetNumber(ref str, ref index);
                }
                else
                    break;
            }
            return value;
        }
       
       
        /// <summary>
        /// [2] 문자열에서 첫번째 나오는 숫자형을 실제 숫자형으로 변환시켜주는 함수
        /// </summary>
        /// <param name="str">(12.34+3)</param>
        /// <param name="index">1</param>
        /// <returns>12.34(숫자형)</returns>       
        public double GetNumber(ref string str, ref int index)
        {
            double value = 0.0;

            // GetSubstring함수 호출해서 괄호안에 있는 문자열만 가져오기
            if (str[index] == '(')
         {
                ++(index);
                string substr = GetSubstring(ref str, ref index);
                return MakeExpression(ref substr); // 괄호안의 수식만 먼저 계산
         }
            while ((index < str.Length) && Char.IsDigit(str, index))
            {
                value = 10.0 * value + Char.GetNumericValue(str[(index)]);
                ++(index);
            }
            if ((index == str.Length) || str[index] != '.') return value;
         double factor = 1.0;
            ++(index);

            while ((index < str.Length) && Char.IsDigit(str, index))
            {
                factor *= 0.1;
                value = value + Char.GetNumericValue(str[index]) * factor;
                ++(index);
            }

            return value;
        }
        

        //[1] 괄호안에 있는 하위 문자열을 추출(하는 함수 만들기) : (123+5) => 123+5만 추출
        public string GetSubstring(ref string str, ref int index) // GetSubstring : 괄호안의 문자열을 추출하는 함수
        {
            string substr = ""; // 하위 문자열 저장
            int numL = 0; // 왼쪽 괄호의 개수
            int bufindex = index; // 인덱스의 시작 값
            while (index < str.Length)
            {
                switch (str[index])
             {
                    case ')' :
                        if (numL == 0)
                     {
                            char[] substrChars = new char[index - bufindex];
                            str.CopyTo(bufindex, substrChars, 0, substrChars.Length);
                            substr = new String(substrChars);
                            ++(index);
                            return substr;
                     }
                        else
                            numL--; // 왼쪽 괄호와 일치하는 오른쪽 괄호가 나타날 시 감소
                        break;

                    case '(' :
                        numL++;
                        break;
                }
                ++(index);
            }
            MessageBox.Show("잘못된 구문입니다.");
            return substr;
     }
    }
}

 




< 실행결과 >








Posted by holland14
:


* 입력/출력/수정/삭제/검색/저장/종료/백업 기능을 WinForm에서 만듦.



==> Program.cs



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

namespace 주소록
{
    static class Program
    {
        /// <summary>
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
}




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



==> Address.cs



using System;

namespace 주소록
{
    class Address
    {
        public int Num { get; set; }
        public string Name { get; set; }
        public string Mobile { get; set; }
        public string Email { get; set; }
    }
}




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



==> MainForm.cs



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace 주소록
{
    public partial class MainForm : Form
    {
        private List<Address> addr;
        private string dir = System.IO.Path.Combine(    // Path.Combine : 경로 묶어준다.
                Application.StartupPath, "MyAddress.txt"); // Application.StartupPath : exe파일과 같은 경로로 지정해준다.

        public MainForm()
        {
            InitializeComponent();
            addr = new List<Address>();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            if (File.Exists(dir))
            {
                LoadData();
            }
            this.sslCount.Text = "등록수 : " + addr.Count.ToString();
            if (addr.Count > 0)
            {
                ShowRecord(0); // 첫번째 데이터를 표시
                btnAdd.Text = "추가";
            }
        }

        private void LoadData()
        {
            StreamReader sr = new StreamReader(dir, Encoding.Default); // StreamReader의 생성자를 통해 파일을 연다.(-> open)

            while (sr.Peek() >= 0) // -1 : 더 이상 읽을 문자가 없을 때
            {
                string[] arr = sr.ReadLine().Trim().Split(',');

                if (arr[0] != "" && arr[0] != null)
                {
                    Address a = new Address();
                    a.Num = Convert.ToInt32(arr[0]); // 번호 : 인덱스 + 1
                    a.Name = arr[1];
                    a.Mobile = arr[2];
                    a.Email = arr[3];

                    addr.Add(a); 
                }
            }
            sr.Close(); // StreamReader를 통해 파일을 열었으면 꼭 닫아줘야 한다!
            sr.Dispose(); // 해제
            DisplayData();           
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            if (btnAdd.Text == "입력")
            {
                Address a = new Address();
                a.Num = addr.Count + 1; //
                a.Name = txtName.Text.Trim();
                a.Mobile = txtMobile.Text.Trim();
                a.Email = txtEmail.Text.Trim();

                addr.Add(a);
                DisplayData(); // 출력
            }
            else
            {               
                btnAdd.Text = "입력";
            }
            ClearTextBox();
        }

        // Clear관련
        private void ClearTextBox()
        {
            txtName.Text = txtMobile.Text = txtEmail.Text = String.Empty;
        }

        // 출력관련
        private void DisplayData()
        {
            var q = (from a in addr select a).ToList();
            this.dgvAddress.DataSource = q;
        }

        // 검색전용
        private void DisplayData(string query)
        {
            var q = (from a in addr
                     where
                         a.Name == query ||
                         a.Mobile == query ||
                         a.Email == query
                     select a).ToList();
            this.dgvAddress.DataSource = q;
        }

        // 저장관련 -> 텍스트파일에 저장함.
        private void btnSave_Click(object sender, EventArgs e)
        {
            if (addr.Count > 0)
            {
                SaveData();
            }
        }

        private void SaveData()
        {     

            //if (!File.Exists(dir)) // 파일이 없으면 생성
            //{
            //    File.Create(dir); // 해당경로에 파일이 없으면 생성
            //}

            // 레코드는 엔터구분, 필드는 콤마구분으로 저장
            StringBuilder sb = new StringBuilder();
            int index = 0;
            foreach (Address a in addr)
            {
                sb.AppendLine(String.Format("{0},{1},{2},{3}"
                , ++index, a.Name, a.Mobile, a.Email)); // 번호 : 인덱스 + 1
            }
            StreamWriter sw = new StreamWriter(dir, false, Encoding.Default); // "StreamWriter"는 파일이 없으면 만들어서 저장한다.
            sw.Write(sb.ToString());
            sw.Close(); // 닫기
            sw.Dispose(); // 해제
            MessageBox.Show("저장되었습니다.");
        }

        // 백업 관련
        private void miBackup_Click(object sender, EventArgs e)
        {
            string name = Path.GetFileNameWithoutExtension(dir);
            string ext = Path.GetExtension(dir).Replace(".", "");

            // MyAddress20100101.txt로 저장가능하도록
            string newDir =
                Path.Combine(Application.StartupPath,
                   String.Format("{0}{1}.{2}"
                       , name
                       , String.Format("{0}{1:0#}{2}"
                           , DateTime.Now.Year
                           , DateTime.Now.Month
                           , DateTime.Now.Day.ToString().PadLeft(2, '0')
                         )
                       , ext
                   )
               );

            if (File.Exists(dir))
            {
                File.Copy(dir, newDir, true); // 원본을 복사해서 백업해놓는다.
            }
        }

        private void miExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private int currentIndex = -1;
        private void dgvAddress_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            //currentIndex = e.RowIndex; // 현재 인덱스를 필드에 보관
            DataGridViewCell dgvc = dgvAddress.Rows[e.RowIndex].Cells[0];
            currentIndex = Convert.ToInt32(dgvc.Value.ToString()) - 1;
            if (currentIndex != -1)
            {
                ShowRecord(currentIndex);
            }
        }

        private void ShowRecord(int index)
        {
            // 현재 선택된 인덱스 + 1을 번호 출력
            this.txtNum.Text = (index + 1).ToString();
            this.txtName.Text = addr[index].Name;
            this.txtMobile.Text = addr[index].Mobile;
            this.txtEmail.Text = addr[index].Email;

            btnAdd.Text = "추가";
            txtGo.Text = txtNum.Text; // 현재 선택된 인덱스 값 출력
        }

        private void btnModify_Click(object sender, EventArgs e)
        {
            if (currentIndex != -1 && blnModified == true) // currentIndex != -1 : 선택된 데이터가 있다면
            {
                // 변경된 데이터로 addr 개체의 현재 인덱스 데이터 변경
                addr[currentIndex].Name = txtName.Text;
                addr[currentIndex].Mobile = txtMobile.Text;
                addr[currentIndex].Email = txtEmail.Text;

                MessageBox.Show("수정되었습니다.", "수정완료");

                DisplayData();
                blnModified = false; // 다시 초기화
            }           
        }

        // 3개 텍스트박스에서 KeyPress 이벤트 발생시 호출
        private bool blnModified = false;
        private void txtModify_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (txtNum.Text != "") // 데이터가 로드된 상태에서만
            {
                blnModified = true; // 변경되었다...
            }
        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            if (txtNum.Text != "" && currentIndex != -1) // txtNum.Text != "" : 널값이 아니라면... / currentIndex != -1 : 선택된 상태가 아니라면...
            {
                DialogResult dr =
                        MessageBox.Show("정말로 삭제하시겠습니까?", "삭제확인"
                            , MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                               
                if (dr != DialogResult.No)
                {
                    // 메모리 상에서 현재 레코드 삭제
                    addr.RemoveAt(currentIndex);
                    DisplayData();
                }
            }
        }

        // 처음, 이전, 다음, 마지막 버튼에 대한 공통 이벤트
        private void btnMove_Click(object sender, EventArgs e)
        {
            Button btn = sender as Button;

            if (btn == btnFirst)
            {
                if (currentIndex > 0)
                {
                    currentIndex = 0; // 0번째 인덱스로 표시                   
                }
            }
            else if (btn == btnPrev)
            {
                if (currentIndex > 0)
                {
                    currentIndex--;
                }
            }
            else if (btn == btnNext)
            {
                if (currentIndex < addr.Count - 1)
                {
                    currentIndex++;
                }
            }
            else if (btn == btnLast)
            {
                if (currentIndex != -1) // 데이터가 있다면
                {
                    currentIndex = addr.Count - 1;
                }
            }

            ShowRecord(currentIndex); // 다시 데이터 표시
        }

        private void btnGo_Click(object sender, EventArgs e)
        {
            if (txtGo.Text != "" && Convert.ToInt32(txtGo.Text) > 0
                    && Convert.ToInt32(txtGo.Text) <= addr.Count)
            {
                ShowRecord(Convert.ToInt32(txtGo.Text) - 1);
            }
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            DisplayData(txtSearch.Text);
        }
    }
}





< 실행결과 >



--> 4명의 데이터가 존재하는 상황에서 '폼'을 새로 load했을 때 초기화면(데이터가 존재하고 있을 때는 '폼' load시에 초기화면이 "입력"버튼이 "추가"버튼으로 바뀌어져 나온다.) '폼'의 '이름', '휴대폰', '이메일' TextBox에 데이터를 입력한 후 "추가"버튼을 누르면 '폼'아래의 'DataGridView'에 데이터가 출력되고 "저장"버튼을 누르면 "저장되었습니다."라고 'MessageBox'가 나오며, 데이터가 "텍스트파일(메모장)"로 저장된다.  





--> '폼'의 '이름', '휴대폰', '이메일' TextBox에 데이터를 입력한 후 '저장'하였을 때 해당폴더(.exe파일이 있는 'Debug'폴더)에 "텍스트파일(메모장)"형태로 데이터가 저장된다.





--> "추가"버튼을 누르면 "추가"버튼의 텍스트가 "입력"으로 바뀌면서 동시에 '이름'/'휴대폰'/'이메일'의 TextBox가 Clear되어진다.('번호'의 TextBox'속성'은 "Readonly"로 설정해서 값을 변경할 수 없다.)








Posted by holland14
:


* MainForm.cs [디자인]에서 '속성' 중 "이벤트" 속성에서 "FormClosing -> MainForm_FormClosing"으로 설정 후 더블클릭 --> 'MainForm.cs'내에 더블클릭으로 생성된 이벤트핸들러 코드에 아래 형광펜으로 칠해진 부분으로 코드작성.





==> Program.cs



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

namespace MyWinForms
{
    static class Program
    {
        /// <summary>
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MyWinForms.MainForm());
        }
    }
}




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




==> MainForm.cs



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MyWinForms.Sample;

namespace MyWinForms
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private void miExit_Click(object sender, EventArgs e)
        {
            // 현재 프로그램 종료
            Application.Exit();
        }

        private void miAbout_Click(object sender, EventArgs e)
        {
            // 모달 폼 : 현재 창을 닫아야지만, 메인으로 이동 가능
            FrmAbout fa = new FrmAbout();
            fa.ShowDialog();
        }

        private void miButton_Click(object sender, EventArgs e)
        {
            // 모달리스 폼 : 독립적인 하나의 폼
            MyWinForms.Controls.FrmButton fb =
                new MyWinForms.Controls.FrmButton();
            fb.MdiParent = this; // MDI 컨테이너를 현재 폼(메인)으로 설정
            fb.Show();
        }


        #region 컨텍스트메뉴
        private void cmsAbout_Click(object sender, EventArgs e)
        {
            //FrmAbout fa = new FrmAbout();
            //fa.ShowDialog();
            miAbout_Click(null, null); // 재 사용
        }

        private void cmsExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
        #endregion

        private void miLable_Click(object sender, EventArgs e)
        {
            MyWinForms.Controls.FrmButtonLableTextBox blt = new MyWinForms.Controls.FrmButtonLableTextBox();
            blt.MdiParent = this;
            blt.Show();
        }

        private void miCheckBoxRadioButton_Click(object sender, EventArgs e)
        {
            MyWinForms.Controls.FrmCheckBoxRadioButton cbrb = new MyWinForms.Controls.FrmCheckBoxRadioButton();
            cbrb.MdiParent = this;
            cbrb.Show();
        }

        private void miTextBox_Click(object sender, EventArgs e)
        {
            MyWinForms.Controls.FrmTextBox ftb = new MyWinForms.Controls.FrmTextBox();
            ftb.MdiParent = this;
            ftb.Show();
        }

        private void miMessageBox_Click(object sender, EventArgs e)
        {
            // 메시지 박스의 주요 모양
            // MSDN 온라인 적극 활용
            // 코드조각 : mbox
            MessageBox.Show("기본");
            MessageBox.Show("캡션", "제목");
            MessageBox.Show("버튼의 종류", "버튼", MessageBoxButtons.OKCancel);
            MessageBox.Show("아이콘의 종류", "아이콘"
                , MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }

        private void miComboListBox_Click(object sender, EventArgs e)
        {
            MyWinForms.Controls.FrmComboListBox clb = new MyWinForms.Controls.FrmComboListBox();
            clb.MdiParent = this;
            clb.Show();
        }

        private void miGroupBox_Click(object sender, EventArgs e)
        {
            MyWinForms.Controls.FrmGroupBox gb = new MyWinForms.Controls.FrmGroupBox();
            gb.MdiParent = this;
            gb.Show();
        }

        private void miDialogResult_Click(object sender, EventArgs e)
        {
            MyWinForms.Class.FrmDialogResult fdr = new MyWinForms.Class.FrmDialogResult();
            fdr.Show();
        }

        // 컨트롤 - 대화상자 - 폰트
        private void miFont_Click(object sender, EventArgs e)
        {
            MyWinForms.Controls.FrmFontDialog ffd = new MyWinForms.Controls.FrmFontDialog();
            ffd.MdiParent = this;
            ffd.Show();
        }

        // 컨트롤 - 대화상자 - 파일 및 폴더
        private void miFileFolder_Click(object sender, EventArgs e)
        {
            MyWinForms.Controls.FrmFileFolder fff = new MyWinForms.Controls.FrmFileFolder();
            fff.MdiParent = this;
            fff.Show();
        }

        // 초간단 노트패드
        private void miNotepad_Click(object sender, EventArgs e)
        {
            FrmNotepad fn = new FrmNotepad();
            fn.MdiParent = this;
            fn.Show();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            // 스테이터스바의 3번째 레이블에 현재 시간 출력
            sslTime.Text =
                String.Format("{0}시 {1:0#}분 {2}초",
                    DateTime.Now.Hour
                    , DateTime.Now.Minute
                        , DateTime.Now.Second.ToString().PadLeft(2, '0'));
        }

        private void miExplorer_Click(object sender, EventArgs e)
        {
            FrmExplorer ie = new FrmExplorer();
            ie.Show();
        }

        #region 창 메뉴 관련
        private void miWindowClose_Click(object sender, EventArgs e)
        {
            Form frm = ActiveMdiChild; // 현재 열려있는 폼 가져오기
            if (frm != null)
            {
                frm.Close(); // 닫기
            }
        }
        private void miWindowCascade_Click(object sender, EventArgs e)
        {
            this.LayoutMdi(MdiLayout.Cascade); // 계단식
        }
        private void miWindowHorizontal_Click(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.TileHorizontal); // 수평 바둑판
        }
        private void miWindowVertical_Click(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.TileVertical); // 수직 바둑판
        }
        #endregion

        private void miCheckedListBox_Click(object sender, EventArgs e)
        {
            // 생성과 동시에 오픈
            (new MyWinForms.Controls.FrmCheckedListBox()).Show();
        }

        private void miImageViewer_Click(object sender, EventArgs e)
        {
            (new FrmImageViewer()).Show();
        }

        private void miTabControl_Click(object sender, EventArgs e)
        {
            (new MyWinForms.Controls.FrmTabControl()).Show();
        }

        private void miToolTip_Click(object sender, EventArgs e)
        {
            (new MyWinForms.Controls.FrmToolTip()).Show();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            // 폼을 닫을건지 취소할건지 결정
            DialogResult dr = MessageBox.Show("종료하시겠습니까?", "종료확인"
                                    , MessageBoxButtons.YesNo
                                    , MessageBoxIcon.Information);
            if (dr == DialogResult.No)
            {
                e.Cancel = true; // 취소
            }
        }
    }
}





< 실행결과 >

--> "MainForm"의 "닫기(X버튼)"버튼을 클릭하면... 





--> "폼"을 닫을지 확인하는 'MessageBox'가 나오고 "예(Y)"를 누르면 '폼'이 종료되고, '아니요(N)'를 누르면 멈춤.(= '폼 닫기' 취소 중지).





Posted by holland14
:


교재 623P. CurveList예제 참조(내가 마우스로 그렸던 그림이 캡쳐링되어 다시 패인팅(그려짐)) 되는 동작임. 눈으로 보기에는 폼에 내가 마우스로 그린 그림의 화면이 다른 폼에 의해 손실되지 않는 듯한 것으로 보이는 기능임.) "FrmMouseDown.cs" [디자인]에서 "폼"의 '속성' 중 이벤트 속성에서 "Paint -> FrmMouseDown_Paint"으로 설정하고 더블클릭 --> 생성된 "FrmMouseDown_Paint"이벤트핸들러 코드에 아래 "FrmMouseDown.cs"의 형광펜으로 칠해진 부분으로 코드작성.

* "ArrayList"형 객체 생성하여 좌표값(들)을 보관 / "foreach"문을 사용하여 저장된 좌표값 다시 그리기





==> Program.cs



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

namespace MyWinForms
{
    static class Program
    {
        /// <summary>
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Mouse.FrmMouseDown());
        }
    }
}



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




==> FrmMouseDown.cs




using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace MyWinForms.Mouse
{
    public partial class FrmMouseDown : Form
    {
        private ArrayList al;
        public FrmMouseDown()
        {
            InitializeComponent();
            al = new ArrayList();
        }

        private void FrmMouseDown_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button== MouseButtons.Right)
            {
                // 그래픽 객체 생성
                Graphics g = CreateGraphics();
                // 원 그리기
                g.DrawEllipse(Pens.Red, e.X, e.Y, 10, 10);
                // 객체 해제
                g.Dispose();
            }
            p.X = e.X; p.Y = e.Y;
        }

        private Point p; // 좌표
        private void FrmMouseDown_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Graphics g = this.CreateGraphics();
                g.DrawLine(Pens.Blue, p.X, p.Y, e.X, e.Y);

                // 좌표값 보관
                al.Add(Rectangle.FromLTRB(p.X, p.Y, e.X, e.Y));

                p.X = e.X; p.Y = e.Y; // 재설정
                g.Dispose();
            }
        }

        private void FrmMouseDown_Paint(object sender, PaintEventArgs e)
        {
            // 저장된 좌표값 다시 그리기
            foreach (Rectangle r in al)
            {
                e.Graphics.DrawLine(Pens.Blue, r.Left, r.Top, r.Right, r.Bottom);
            }

        }
    }
}





< 실행결과 >

--> 마우스로 '폼'에 그림(선)을 그림 





--> "메모장"을 내가 그림을 그린 '폼' 위로 올려놓음.




--> 내가 그림을 그린 '폼'위의 "메모장" 치우면 그림이 손상되지 않고 원래 상태대로 보여진다.(좌표값(들)을 저장하였다가(캡쳐링같은 역할) 저장된 좌표값을 다시 그리는(Paint) 동작을 하여, 우리가 눈으로 보기에는 '폼'에 그린 그림이 손실되지 않고 그대로 있는 것으로 보이는 것이다. ) 




Posted by holland14
:


* "마우스다운(MouseDown)" 이벤트는 마우스 "우클릭" --> 폼(Form)에서 원 만들기
   "마우스무브(MouseMove)" 이벤트는 마우스 "좌클릭"하여 "드래그" --> 폼(Form)에서 선그리기
* 이 예제에서는 'MyWinForms'에 따로 폴더 추가하여 "Mouse"로 이름 지정한 후  이 폴더에 "FrmMouseDown.cs"를 만들었다.




==> Program.cs



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

namespace MyWinForms
{
    static class Program
    {
        /// <summary>
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Mouse.FrmMouseDown());
        }
    }
}



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




==> FrmMouseDown.cs




using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MyWinForms.Mouse
{
    public partial class FrmMouseDown : Form
    {
        public FrmMouseDown()
        {
            InitializeComponent();
        }

        private void FrmMouseDown_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button== MouseButtons.Right) // 마우스 우클릭
            {
                // 그래픽 객체 생성
                Graphics g = CreateGraphics();
                // 원 그리기
                g.DrawEllipse(Pens.Red, e.X, e.Y, 10, 10);
                // 객체 해제
                g.Dispose();
            }
            p.X = e.X; p.Y = e.Y;
        }

        private Point p; // 좌표
        private void FrmMouseDown_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left) // 마우스 좌클릭
            {
                Graphics g = this.CreateGraphics();
                g.DrawLine(Pens.Blue, p.X, p.Y, e.X, e.Y);
                p.X = e.X; p.Y = e.Y; // 재설정
                g.Dispose();
            }
        }
    }
}





< 실행결과 >

--> 마우스 "우클릭"으로 "마우스다운(MouseDown)" 이벤트 실행하여 폼(Form)안에 빨간색 원을 그렸고 / 마우스 "좌클릭" 후 '드래그'해서 "마우스무브(MouseMove)"이벤트 실행하여 파란색 선을 그렸다.





Posted by holland14
:


==> Program.cs



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

namespace MyWinForms
{
    static class Program
    {
        /// <summary>
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Sample.FrmKeyDown());
        }
    }
}




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




==> FrmKeyDown.cs



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MyWinForms.Sample
{
    public partial class FrmKeyDown : Form
    {
        private Point p;
        public FrmKeyDown()
        {
            InitializeComponent();
            p.X = 10; p.Y = 10;
        }

        // 폼이 그려질 때 발생하는 이벤트
        private void FrmKeyDown_Paint(object sender, PaintEventArgs e)
        {
            // 원 그리기
            e.Graphics.FillEllipse(Brushes.Black, p.X - 8, p.Y - 8, 16, 16);
        }

        // 폼에서 키보드가 타이핑 될 때
        private void FrmKeyDown_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Left: p.X -= 10; Invalidate(); break;
                case Keys.Right: p.X += 10; Invalidate(); break;
                case Keys.Up: p.Y -= 10; Invalidate(); break;
                case Keys.Down: p.Y += 10; Invalidate(); break;
                default:
                    break;
            }
        }
    }
}





< 실행결과 >

--> 처음 실행 때 화면





--> "화살표 키"로 방향 이동





Posted by holland14
:


==> Program.cs



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

namespace MyWinForms
{
    static class Program
    {
        /// <summary>
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Sample.FrmKeyboard());
        }
    }
}




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




==> FrmKeyboard.cs




using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MyWinForms.Sample
{
    public partial class FrmKeyboard : Form
    {
        public FrmKeyboard()
        {
            InitializeComponent();
        }

        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            // 엔터키를 타이핑했을 때 다음 텍스트박스로 이동
            if (e.KeyChar == (char)Keys.Enter)
            {
                textBox2.Focus();
            }
        }

        private void textBox2_KeyDown(object sender, KeyEventArgs e)
        {
            // 엔터키 입력시 확인 버튼으로 포커스
            if (e.KeyCode == Keys.Enter)
            {
                button1.Focus();
            }
        }
    }
}





< 실행결과 >

--> '국어'점수의 "TextBox"에 텍스트(100) 입력 후, 엔터키를 타이핑했을 때 다음 텍스트박스로 이동





--> '영어'점수의 "TextBox"에 텍스트(90) 입력 후, 엔터키 입력시 "확인" 버튼으로 포커스() 맞춰짐.





Posted by holland14
:


* '도구상자 - 인쇄'에서 "PrintPreviewDialog"를 폼에 드래그&드롭



==> Program.cs



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

namespace DotNetNote
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new DotNetNote());
        }
    }
}




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




==> DotNetNote.cs



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Microsoft.Win32;

namespace DotNetNote
{
    public partial class DotNetNote : Form
    {
        #region Constructors
        public DotNetNote()
        {
            InitializeComponent();
        }
        #endregion

        #region Private Member Variables
        private bool _IsTextChanged; // 텍스트 변경 여부
        #endregion

        #region Private Methods
        /// <summary>
        /// 파일을 저장할지 결정 메서드
        /// </summary>
        private void SaveText()
        {
            if (this.Text == "제목 없음 - 메모장")
            {
                DialogResult objDr = sfdDotNetNote.ShowDialog();
                if (objDr != DialogResult.Cancel)
                {
                    string strFileName = sfdDotNetNote.FileName;
                    SaveFile(strFileName);
                }
            }
            else
            {
                string strFileName = this.Text; // 파일 전체 이름
                SaveFile(strFileName);
            }
        }

        /// <summary>
        /// 실제 파일을 저장하는 메서드
        /// </summary>
        /// <param name="strFileName">저장될 파일의 전체 경로</param>
        private void SaveFile(string strFileName)
        {
            StreamWriter objSw = new StreamWriter(strFileName, false, System.Text.Encoding.Default);
            objSw.Write(this.txtMain.Text);
            objSw.Flush();
            objSw.Close();

            _IsTextChanged = false;
            this.Text = strFileName; // 제목에 파일명 출력
        }

        /// <summary>
        /// 텍스트 박스의 내용 비우기
        /// </summary>
        private void ClearText()
        {
            this.txtMain.ResetText(); // 텍스트박스 리셋   
            this.Text = "제목 없음 - 메모장";
            _IsTextChanged = false;
        }

        // 저장 또는 텍스트박스 클리어 또는 취소 기능 메서드
        private void SaveOrClearOrCancel(string strFlag)
        {
            DialogResult objDr = MessageBox.Show(
                this.Text + " " +
                " 파일의 내용이 변경되었습니다.\r\n" +
                "변경된 내용을 저장하시겠습니까?",
                "메모장",
                MessageBoxButtons.YesNoCancel,
                MessageBoxIcon.Exclamation);
            switch (objDr)
            {
                case DialogResult.Yes:
                    SaveText(); // 텍스트 저장
                    if (strFlag == "New")
                        ClearText(); // 텍스트 클리어(리셋)
                    else
                        OpenText(); // 열기
                    break;
                case DialogResult.No:
                    if (strFlag == "New")
                        ClearText(); // 텍스트 클리어(리셋)
                    else
                        OpenText(); // 열기
                    break;
                case DialogResult.Cancel:
                    break;
            }
        }

        // 열기 기능 메서드
        private void OpenText()
        {
            DialogResult objDr = ofdDotNetNote.ShowDialog();
            if (objDr != DialogResult.Cancel)
            {
                string strFileName = ofdDotNetNote.FileName;
                StreamReader objSr = new StreamReader(strFileName, System.Text.Encoding.Default);
                this.txtMain.Text = objSr.ReadToEnd();
                objSr.Close();

                _IsTextChanged = false;
                this.Text = strFileName; // 제목에 파일명 출력
            }
        }
        #endregion

        #region Event Handlers
        // 폼 로드 이벤트
        private void DotNetNote_Load(object sender, EventArgs e)
        {
            this.Width = 600;
            this.Height = 400;

            if (Registry.GetValue(@"HKEY_CURRENT_USER\Software\Hawaso\DotNetNote\", "Font-Family", "") != null)
            {
                // 레지스트리에 저장된 폰트 정보 가져오기
                Font fnt = new Font(
                  Convert.ToString(
                    Registry.GetValue(@"HKEY_CURRENT_USER\Software\Hawaso\DotNetNote\", "Font-Family", ""))
                  , Convert.ToSingle(Registry.GetValue(@"HKEY_CURRENT_USER\Software\Hawaso\DotNetNote\", "Font-Size", "")));
                this.txtMain.Font = fnt;
            }

        }

        // 새로 만들기 메뉴
        private void miNew_Click(object sender, EventArgs e)
        {
            if (_IsTextChanged)
            {
                SaveOrClearOrCancel("New");
            }
            else
            {
                ClearText();
            }
        }

        // 텍스트 내용 변경시 발생
        private void txtMain_TextChanged(object sender, EventArgs e)
        {
            _IsTextChanged = true; // 텍스트 변경 적용
            miUndo.Enabled = true; // 취소 메뉴 활성화
            miCut.Enabled = true; // 잘라내기 메뉴 활성화
            miCopy.Enabled = true; // 복사 메뉴 활성화 
            miDel.Enabled = true; // 삭제 메뉴 활성화
            miFind.Enabled = true; // 찾기 메뉴 활성화
            miFindNext.Enabled = true; // 다음 찾기 메뉴 활성화
            miGo.Enabled = true; // 이동 메뉴 활성화
            if (txtMain.Text.Length == 0)
            {
              _IsTextChanged = false; 
            }
        }

        // 열기 메뉴
        private void miOpen_Click(object sender, EventArgs e)
        {
            if (_IsTextChanged)
            {
                SaveOrClearOrCancel("Open");
            }
            else
            {
                OpenText();
            }
        }

        // 저장 메뉴
        private void miSave_Click(object sender, EventArgs e)
        {
            SaveText(); // 저장 메서드 호출
        }

        // 다른 이름으로 저장
        private void miSaveAs_Click(object sender, EventArgs e)
        {
            DialogResult objDr = sfdDotNetNote.ShowDialog();
            if (objDr != DialogResult.Cancel)
            {
                string strFileName = sfdDotNetNote.FileName;
                SaveFile(strFileName);
            }
        }

        // 페이지 설정 메뉴
        private void miPageSetup_Click(object sender, EventArgs e)
        {
            //[1] PrintDocument.DocumentName = 문서 지정
            dnnPrintDocument.DocumentName = txtMain.Text;
            //[2] PageSetupDialog.Document = PrintDocument
            psdDotNetNote.Document = this.dnnPrintDocument;
            //[3] 페이지 설정 창 띄우기
            psdDotNetNote.ShowDialog();
        }

        // 인쇄 메뉴
        private void miPrint_Click(object sender, EventArgs e)
        {
            dnnPrintDocument.DocumentName = txtMain.Text;
            if (pdDotNetNote.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    dnnPrintDocument.Print();
                }
                catch
                {
                    MessageBox.Show(
                        "인쇄하는 도중에 에러가 발생했습니다.",
                        "인쇄 오류",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                }

            }
        }

        // 페이지 인쇄 이벤트 핸들러
        private void dnnPrintDocument_PrintPage(
            object sender,
            System.Drawing.Printing.PrintPageEventArgs e)
        {
            StringReader objSr = new StringReader(this.txtMain.Text);

            // 현재 문서의 글꼴과 사이즈
            Font printFont =
                new Font(txtMain.Font.Name, txtMain.Font.Size);
            float linesPerPage = 0; // 페이지의 라인 수
            float yPos = 0; // 페이지 상단에서 떨어진 위치(문자열 출력)
            int count = 0; // 페이지 줄 번호

            float leftMargin = e.MarginBounds.Left; // 왼쪽 여백
            float topMargin = e.MarginBounds.Top; // 오른쪽 여백

            string line = null; // 각 행의 데이터 저장
            linesPerPage = // 페이지 당 라인 수 계산
                e.MarginBounds.Height /
                    printFont.GetHeight(e.Graphics);

            while (count < linesPerPage &&
                ((line = objSr.ReadLine()) != null))
            {
                yPos = topMargin +
                    (count * printFont.GetHeight(e.Graphics));
                e.Graphics.DrawString(
                    line,
                    printFont,
                    Brushes.Black,
                    leftMargin, yPos,
                    new StringFormat());
                count++;
            }

            if (line != null)
            {
                e.HasMorePages = true;
            }
            else
            {
                e.HasMorePages = false;
            }
            objSr.Close();
        }

        // 끝내기 메뉴
        private void miExit_Click(object sender, EventArgs e)
        {
            if (_IsTextChanged)
            {
                DialogResult objDr = MessageBox.Show(
                    this.Text + " " +
                    "파일의 내용이 변경되었습니다.\r\n" +
                    "변경된 내용을 저장하시겠습니까?",
                    "메모장",
                    MessageBoxButtons.YesNoCancel,
                    MessageBoxIcon.Exclamation);
                switch (objDr)
                {
                    case DialogResult.Yes:
                        SaveText(); // 텍스트 저장
                        this.Close(); // 종료
                        break;
                    case DialogResult.No:
                        this.Close(); // 종료
                        break;
                    case DialogResult.Cancel:
                        break;
                }   
            }
            else
            {
                Application.Exit(); // this.Close();
            }
        }

        // 실행 취소 메뉴
        private void miUndo_Click(object sender, EventArgs e)
        {
            if (this.txtMain.CanUndo)
            {
                this.txtMain.Undo();
            }
        }

        // 잘라내기 메뉴 구현
        private void miCut_Click(object sender, EventArgs e)
        {
            this.txtMain.Cut();
            //Clipboard.SetDataObject(txtMain.SelectedText);
            //txtMain.SelectedText = String.Empty;
        }

        // 복사 메뉴 구현
        private void miCopy_Click(object sender, EventArgs e)
        {
            this.txtMain.Copy();
            //Clipboard.SetDataObject(txtMain.SelectedText); // 복사
        }

        // 붙여넣기 메뉴 구현
        private void miPaste_Click(object sender, EventArgs e)
        {
            this.txtMain.Paste(); // 붙여넣기
            //[!] 클립보드의 내용이 텍스트 형식인지 검사 후 붙여넣기
            //if (Clipboard.GetDataObject().GetDataPresent(
            //    DataFormats.Text))
            //{
            //    // 클립보드의 내용을 텍스트 형식으로 변환 후 반환
            //    this.txtMain.SelectedText =
            //        Clipboard.GetDataObject().GetData(
            //        DataFormats.Text, true).ToString();
            //}
        }

        // 삭제 메뉴 구현
        private void miDel_Click(object sender, EventArgs e)
        {
            this.txtMain.SelectedText = String.Empty;
        }

        // 찾기 메뉴 구현
        private void miFind_Click(object sender, EventArgs e)
        {
            FrmFind f = new FrmFind(this);
            f.Show();
        }

        // 다음 찾기 메뉴 구현
        private void miFindNext_Click(object sender, EventArgs e)
        {
            miFind_Click(null, null);
        }

        // 바꾸기 메뉴 구현
        private void miReplace_Click(object sender, EventArgs e)
        {
            (new FrmReplace(this)).Show();
            //FrmReplace r = new FrmReplace(this);
            //r.Show();
        }

        // 이동 메뉴
        private void miGo_Click(object sender, EventArgs e)
        {
            int intLineLength = //전체 라인수
                this.txtMain.Lines.Length;
            int intCurrentLine = //현재 라인수
                Library.GetLineAndColumn(this.txtMain).Line;

            FrmGo go = new FrmGo(intLineLength, intCurrentLine);
            if (go.ShowDialog() == DialogResult.OK)
            {
                int intLineNum = 0;
                if (go.GetLine() != 1)
                {
                    for (int i = 0; i < go.GetLine() - 1; i++)
                    {
                        intLineNum +=
                            txtMain.Lines[i].Length + 2;
                    }
                }
                txtMain.SelectionStart = intLineNum;
                txtMain.ScrollToCaret();
            }
        }

        // 전체 선택 메뉴
        private void miSelectAll_Click(object sender, EventArgs e)
        {
            this.txtMain.SelectAll();
        }

        // 시간/날짜 메뉴 구현
        private void miTimeDate_Click(object sender, EventArgs e)
        {
          // 마우스 커서(캐럿) 자리에 시간/날짜 출력
          txtMain.SelectedText =
            String.Format("{0} {1}"
              , DateTime.Now.ToShortTimeString()
              , DateTime.Now.ToShortDateString());
        }

        // 자동 줄 바꿈 메뉴
        private void miWordWrap_Click(object sender, EventArgs e)
        {

            this.txtMain.WordWrap = !(this.txtMain.WordWrap);
            this.miWordWrap.Checked = !(this.miWordWrap.Checked);
            // 자동 줄 바꿈 체크 : 상태 표시줄 비활성화
            if (miWordWrap.Checked)
            {
              miStatus.Enabled = false;
            }
            else
            {
              miStatus.Enabled = true;
            }
        }
       
        // 글꼴 메뉴
        private void miFont_Click(object sender, EventArgs e)
        {
          fdDotNetNote.Font = txtMain.Font; // 폰트 다이얼로그 컨트롤에 현재 텍스트박스 글꼴 선택
          if (fdDotNetNote.ShowDialog() != DialogResult.Cancel)
          {
            txtMain.Font = fdDotNetNote.Font;
            // 윈도우 레지스트리에 현재 설정된 글꼴 저장
            Registry.SetValue(@"HKEY_CURRENT_USER\Software\Hawaso\DotNetNote\", "Font-Size", fdDotNetNote.Font.Size);
            Registry.SetValue(@"HKEY_CURRENT_USER\Software\Hawaso\DOtNetNOte\", "Font-Family", fdDotNetNote.Font.FontFamily.Name);
          }
        }

        // 상태 표시줄 메뉴
        private void miStatus_Click(object sender, EventArgs e)
        {
            if (this.dnnStatusStrip.Visible)
            {
                this.dnnStatusStrip.Visible = false;
                this.miStatus.Checked = false;
                this.txtMain.Height = this.Height - 55;
            }
            else
            {
                this.dnnStatusStrip.Visible = true;
                this.miStatus.Checked = true;
                int intLine =
                    Library.GetLineAndColumn(txtMain).Line;
                int intColumn =
                    Library.GetLineAndColumn(txtMain).Column;

                string strMsg = String.Format(
                    "Ln {0}, Col {1}", intLine, intColumn);

                this.toolStripStatusLabel2.Text = strMsg;
                this.txtMain.Height = this.txtMain.Height - 25;
            }
        }

        // 키보드 키 누른 후에 발생
        private void txtMain_KeyUp(object sender, KeyEventArgs e)
        {
            int intLine =
                Library.GetLineAndColumn(txtMain).Line;
            int intColumn =
                Library.GetLineAndColumn(txtMain).Column;

            string strMsg = String.Format(
                "Ln {0}, Col {1}", intLine, intColumn);

            this.toolStripStatusLabel2.Text = strMsg;
        }

        //[!] 도움말 항목 메뉴
        private void miHelp_Click(object sender, EventArgs e)
        {
            // 시스템(Windows) 디렉터리 경로
            string strDirectory =
                System.Environment.SystemDirectory;
            // Help 폴더 안의 Notepad.chm 파일 경로 : Parent
            strDirectory = // 한 단계 상위 경로 폴더 뽑아내기
                strDirectory.Substring(
                    0, strDirectory.LastIndexOf("\\"));
            strDirectory += @"\Help\Notepad.chm"; // Combine()
            // 파일이 있는지 확인 후 도움말 띄우기
            if (System.IO.File.Exists(strDirectory))
            {
                Help.ShowHelp(this, strDirectory);
            }
            else
            {
                MessageBox.Show(strDirectory +
                    "도움말 파일이 없습니다.",
                    "메모장",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }
 
        //[!] 메모장 정보 메뉴
        private void miAbout_Click(object sender, EventArgs e)
        {
          // FrmAbout 윈폼의 인스턴스 생성
          FrmAbout about = new FrmAbout();
          // 윈폼 개체의 showDialog() 메서드로 윈폼 띄우기
          about.ShowDialog(); // 모달(Modal) 폼
        }

        // 파일 드롭 지원 : txtMain.AllowDrop = true로 설정해야 함.
        private void txtMain_DragOver(object sender, DragEventArgs e)  {
          if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
            e.Effect = DragDropEffects.Copy;
          }
        }
        private void txtMain_DragDrop(object sender, DragEventArgs e) {
          if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
            string[] strFiles = (string[])e.Data.GetData(DataFormats.FileDrop);
            StreamReader objSr = new StreamReader(
                strFiles[0], Encoding.Default);
            this.txtMain.Clear();
            this.txtMain.Text = objSr.ReadToEnd();
            objSr.Close();
          }
        }
        private void txtMain_QueryContinueDrag(object sender, QueryContinueDragEventArgs e) {
            if (e.EscapePressed) {
                e.Action = DragAction.Cancel;
            }
        }
        #endregion

        private void miPreview_Click(object sender, EventArgs e)
        {
            // 미리보기
            this.dnnPrintPreviewDialog.Document = this.dnnPrintDocument;
            this.dnnPrintPreviewDialog.ShowDialog();
        }

    }
}





< 실행결과 >





--> DotNetNote.cs에서 형광펜으로 색칠된 부분의 2줄 코드를 작성하여 "인쇄 미리 보기" 기능을 구현함.





Posted by holland14
: