using System.Diagnostics;

Stopwatch sw = new Stopwatch();
sw.Start();

for (int i = 0; i < 1000000; i++) ;

sw.Stop();
Console.WriteLine("{0}ms", sw.ElapsedMilliseconds);

닷넷 2.0 이상에서만 지원한다.

'닷넷 프레임워크' 카테고리의 다른 글

memset in c#  (0) 2009.12.20
UDP 통신  (0) 2009.11.26
MDB에서 쿼리문에 이상이 없는데도 구문 오류가 발생할 경우  (0) 2009.09.24
텍스트 박스 유효성 체크  (0) 2009.09.22
C# Thread 이야기  (0) 2009.09.22

이상이 생기는 sql 구문
string sql = @"insert into PowerData(EquipCode,PowerState,Time) values(@equipcode, @powerstate, @time) ";

뭐가 문젠지 한참을 고민했다. 분명히 SQL 구문는 정상인데..
이럴 경우 테이블명과 필드명에 [, ] 로 묶어준다.


이상이 없는 sql 구문
string sql = @"insert into [PowerData]([EquipCode],[PowerState],[Time]) values(@equipcode, @powerstate, @time) ";

'닷넷 프레임워크' 카테고리의 다른 글

UDP 통신  (0) 2009.11.26
[C#] 실행시간 측정  (0) 2009.10.20
텍스트 박스 유효성 체크  (0) 2009.09.22
C# Thread 이야기  (0) 2009.09.22
Creating a splash screen  (0) 2009.07.15

using System.Text.RegularExpressions;

// 텍스트박스에 한글만 입력하기


private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)

{

    if((Char.IsPunctuation(e.KeyChar) || Char.IsDigit(e.KeyChar) || Char.IsLetter 

          (e.KeyChar) || Char.IsSymbol(e.KeyChar)) && e.KeyChar != 8)

    {

        e.Handled = true;

    }

}

 

// 텍스트 박스에 영문만 입력하기

private void textBox1_Leave(object sender, System.EventArgs e)

{

    Regex emailregex = new Regex(@"[a-zA-Z]");

    Boolean ismatch = emailregex.IsMatch(textBox1.Text);

    if (!ismatch)

    {

        MessageBox.Show("영문자만 입력해 주세요.");

    }

}

// 텍스트 박스에 숫자만 입력하기
// textBox1의 문자 중 숫자를 없앤다.
string str = Regex.Replace(this.textBox1.Text, @"[0-9]", "");
if(str.Length > 0)
     MessageBox.Show(“숫자외 문자가 존재합니다.“);
else
     MessageBox.Show(“숫자로만 구성되어있습니다.“);

'닷넷 프레임워크' 카테고리의 다른 글

[C#] 실행시간 측정  (0) 2009.10.20
MDB에서 쿼리문에 이상이 없는데도 구문 오류가 발생할 경우  (0) 2009.09.24
C# Thread 이야기  (0) 2009.09.22
Creating a splash screen  (0) 2009.07.15
DataGridView 소개  (1) 2009.07.13

C# 쓰레드 이야기: 1. 쓰레드는 무엇인가?

http://network.hanbitbook.co.kr/view.php?bi_id=229

 

C# 쓰레드 이야기: 2. 다중 쓰레드

http://network.hanbitbook.co.kr/view.php?bi_id=231

 

C# 쓰레드 이야기: 3. 쓰레드 제어

http://network.hanbitbook.co.kr/view.php?bi_id=233

 

C# 쓰레드 이야기: 4. 쓰레드 기본 개념

http://network.hanbitbook.co.kr/view.php?bi_id=239

 

C# 쓰레드 이야기: 5. NT vs UNIX

http://network.hanbitbook.co.kr/view.php?bi_id=243

 

C# 쓰레드 이야기: 6. 쓰레드 예외 처리

http://network.hanbitbook.co.kr/view.php?bi_id=246

 

C# 쓰레드 이야기: 7. C#으로 만드는 WinTop

http://network.hanbitbook.co.kr/view.php?bi_id=255

 

C# 쓰레드 이야기: 8. 동기화

http://network.hanbitbook.co.kr/view.php?bi_id=318

 

C# 쓰레드 이야기: 9. 임계 영역

http://network.hanbitbook.co.kr/view.php?bi_id=330

 

C# 쓰레드 이야기: 10. 뮤텍스(Mutex)

http://network.hanbitbook.co.kr/view.php?bi_id=332

 

C# 쓰레드 이야기: 11. 이벤트(Event)

http://network.hanbitbook.co.kr/view.php?bi_id=360

 

C# 쓰레드 이야기 - 12. 식사하는 철학자

http://network.hanbitbook.co.kr/view.php?bi_id=377

 

C# 쓰레드 이야기 - 13. Interlocked, Heap

http://network.hanbitbook.co.kr/view.php?bi_id=379

 

C# 쓰레드 이야기 - 14. 마지막 이야기

http://network.hanbitbook.co.kr/view.php?bi_id=426

옵션만기일은 매월 두번째 목요일이구요,

선물만기일은 3,6,9,12월 두번째 목요일입니다.

선물만기일은 옵션만기일과 항상 겹치게 됩니다.

또한 동시만기일에는 주식옵션을 포함하면 3가지가 겹치게 되는데

영어로 트리플 위칭데이라 합니다

 이번회에서는 MSTK-2440 보드에서 동작하는 Startup code를 작성하기 위해서 알아야하는 기본적인 하드웨어 부분(가장 중요한 부분 이라고 생각한다)을 분석하도록한다. 분석 할 부분들은 s3c2440 CPU의 Operating Mode를 결정하는 부분과 NAND 메모리 설정, SDRAM 인터페이스 부분들이다. 나머지 부분들은 필요할 때마다 언급하도록 하겠다.

1. MSTK-2440 메모리 맵

 s3c2440는 총 27개의 어드레스 라인(ADDR26:0)과 8개의 뱅크를 가지고 있다. 각 뱅크당 128Mbytes 공간을 가진다(이는 어드레스 라인이 27개이기 때문이다. 2의 27승은 127MBytes). MSTK-2440 보드는 8개의 뱅크중 5개를 사용하고 있다. 각 뱅크를 선택하는 Chip select 선이 있는데 nGCS0 ~ 7까지 존재 한다. nGCS0은 Nor 플래시 메모리가 연결되어있고, nGCS1에는 CPLD, nGCS3에는 CS8900A(이더넷 칩), nGCS6,7에는 SDRAM이 연결 되어있다. 나머지 nGCS2,4,5들은 사용하지 않는다.

s3c2440은 Nor 플래시(Boot ROM) 부팅과 Nand 플래시 부팅을 지원한다. Nor플래시 부팅 모드일 경우 0x0000_0000번지에 Nor플래시가 연결되어 있기 때문에 별다른 어려움 없이 사용할 수 있다(Nor 플래시 인터페이스는 어드레싱 방식, 꼭 Nor 플래시가 아니더래도 Boot ROM 종류면 사용 가능하다). 하지만 NAND 플래시 메모리는 어드레스 접근 방식이 아니라 페이지 접근 방식이라 Nor 플래시 접근 하듯이 주소로 접근할 수 가 없다. 따라서 Nand 플래시 부팅 모드일 경우에는 내부적 4KB짜리 SRAM을 사용한다. NAND 플래시 앞쪽 영역에서 4KB만큼만 SRAM에 복사하여 Boot ROM처럼 사용한다. 요즘은 Win CE, Embedded Linux등 대용량 OS를 많이 사용하기 때문에 NAND 플래시 부팅은 필수적이다.


2. BANK0(nGCS0) BUS WIDTH / NAND CONFIG
OM[1:0] 부분을 보자. 자세히 보면 OM0은 3.3v 풀업 저항 처리 되어있다. JP1(스위치)의 on/off 값에 따라 OM0값이 변화된다. OM1 부분은 풀다운 저항 처리 되어 항상 0이다(4.7KUNLOAD되어 있는 부분은 보드 PCB에 저항이 실장되어있지 않은 부분이다). s3c2440 데이터 시트를 보자.
여기서 OM1은 항상 0으로 고정되어 있고 OM0 부분만 0, 1로 변화 된다. 이 말은 Booting ROM Data width가 OM1이 0, OM0이 0일 경우 Nand Flash Mode이고, OM1이 0, OM0이 1일 경우 16비트 Nor Flash Mode이다.

OM[1:0] = 00일 경우 NAND 플래시 메모리 부트 모드 이다. Nand 플래시 메모리 부트 모드를 사용하기 위해서는 하드웨어 적으로 핀 설정을 해줘야 한다. 위 회로의 NCON, EINT21, EINT22, EINT23 부분을 보자. EINT21는 GPIO13과 핀이 동일하다(EINT22 = GPIO14, EINT23 = GPIO15). NCON은 풀다운 처리가 되어 항상 0이다. EINT21은 풀업 처리로 항상 1이다. EINT22는 풀업처리로 항상 1이다. 마지막으로 EINT23은 풀다운 처리되어 항상 0이다. 다시 s3c2440 데이터 시트를 보자. 아래의 내용은 데이터 시트에서 발췌한 내용이다. bold 처리된 부분이 위 회로에서 적용된 내용이다.

NCON: NAND flash memory selection(Normal / Advance)
0: Normal NAND flash(256Words/512Bytes page size, 3/4 address cycle)
1: Advance NAND flash(1KWords/2KBytes page size, 4/5 address cycle)

GPG13(EINT21): NAND flash memory page capacitance selection
0: Page=256Words(NCON = 0) or Page=1KWords(NCON = 1)
1: Page=512Bytes(NCON = 0) or Page=2KBytes(NCON = 1)

GPG14(EINT22): NAND flash memory address cycle selection
0: 3 address cycle(NCON = 0) or 4 address cycle(NCON = 1)
1: 4 address cycle(NCON = 0) or 5 address cycle(NCON = 1)

GPG15(EINT23): NAND flash memory bus width selection
0: 8-bit bus width
1: 16-bit bus width


정리하자면, 현재 하드웨어적으로 설정된 내용은 Nand 플래시의 페이지당 사이즈가 512Bytes, 메모리 어드레스 사이클은 4 어드레스 사이클, Nand 플래시 메모리 버스 폭은 8비트이다.


3. SDRAM 인터페이스
 MSTK-2440보드에서는 128MB(32MB * 4) 램 용량을 가진다(K4S561632E-TL75(16M * 16)을 4개를 사용한다). s3c2440에는 SDRAM 콘트롤러가 존재한다. 이는  nGCS6, nGCS7와 어드래스 라인, 데이터 라인등에 의해서 제어된다. K4S561632E-TL75는 16비트 데이터 버스와 A0~A12까지 13개의 어드레스 라인을 가지고 있다. 13개의 어드레스 라인이면 2의 13승으로 총 8K * 16의 용량을 가질 수 있다. 하지만 조금 이상하다. K4S561632E 칩은 데이터 시트에서도 보듯이 16M * 16의 용량(32MB)을 가진다. 어떻게 된 것일까? 데이터 시트에서 K4S561632E의 블록 다이어그램을 살펴 보자.



 위 두개의 블록다이어그램을 살펴보면 Bank Select, Row Decoder, Column Decoder가 존재한다. 그리고 Address Register 블럭이 하나 존재한다. Address Register로 클럭에 동기화되어 주소(ADD)가 들어오면 거기서 Row Address, Column Address, Bank Select를 사용 하는 것 처럼 보인다. 메모리 용량이 커지면 커질수록 메모리 번지를 어드레싱하는 어드레스 라인이 늘어나게 된다. 여기서 128MB 용량을 가지는데 정상적으로 제어하기 위해서는 A0 ~ A26로 27개가 필요하다. SDRAM용량이 커지면 이 개수는 더 늘어날 수 밖에 없다. 이제야 Bank Select, Row Decoder, Column Decoder가 왜 존재하는지 감이 온다. 어드레스를 제어할 때 일반적인 방법은 1차원적인 방법으로 제어한다. 하지만 SDRAM은 3차원 적인 방법으로 어드레스를 제어한다. Column Address, Row Address, Bank Address를 이용하면 작은 수의 어드래스 핀으로 많은 용량을 제어할 수 있다. 실제로  한 어드레스 라인을 사용하여 Column Address, Row Address를 입력한다. 이것이 가능한 이유는 이 두 주소간에 시간 차이를 두어 A0 ~ A12핀에다가 주소를 입력한다.


 여기서는 16비트 모드를 사용하기 때문에 16M * 16 부분을 위의 표에서 살펴 봐야된다. Row Address는 A0 ~ A12가 사용되고 Column Address는 A0 ~ A8까지 사용된다. 2의 13승 * 2의 9승 = 8K * 512 = 4M이다. K4S561632E칩에 보면 Bank Address가 2개있다(BA0, BA1). 각 뱅크당 크기가 4M이고 16비트 데이터 버스 폭을 가지므로 4M * 16비트, 총 256M bits(32MB)의 용량이 된다. SDRAM에 대한 기본 설명을 여기까지 하고(SDRAM에 대한 제어 스퀀스나 복잡한 구조는 알 필요가 없다. SDRAM 콘트롤러가 다 알아서 해주기 때문에 프로그래머 입장에서는 램 인터페이스 방법과 s3c2440의 SDRAM  콘트롤러 제어 레지스터만 알면된다. 하지만 여유가 된다면 SDRAM에 대해서 자세한 공부도 필요할 것 같다) 아래의 회로를 보자.


 MSTK-2440 보드는 총 128MB(뱅크당 64MB)의 SDRAM용량을 가진다. K4S561632E 칩을 4개를 사용한다. 그러면 32MB SDRAM을 가지고 어떻게 각 뱅크당 64MB를 할당 할 수 있을까?(아마 컴퓨터 구조를 공부했던 독자라면 한번쯤 배웠을 내용이다) 위 회로를 보면 해답이 나와있다. 지금 K4S561632E 칩을 살펴보면 데이터 버스 폭이 16비트이다. s3c2440에서 사용하는 32비트 데이터 버스 폭(ARM 모드로 프로그램을 하기 때문에 32비트 데이터 버스 폭 사용, THUMB 모드일 경우에는 16비트만 사용)을 만들기 위해서는 K4S561632E 칩을 병렬로 연결해야 한다. 위 회로에 LDATA[15:0] 라인을 첫 번째 K4S561632E칩의 데이터 라인(DQ[15:0])에 연결하였다(U2 부분 참조). 그리고 LDATA[31:16] 라인을 두 번째 K4S561632E칩의 데이터 라인(DQ[15:0])에 연결하였다(U3 부분 참조). 이는 총 64MB 영역 중에 상위 32MB 램 영역은 U3부분이고, 하위 32MB 램 영역은 U2부분을 의미한다. 상위 램영역과 하위 램영역을 제어할 수있는 핀이 U2, U3에서 LSCLK0(U2의 SCLK), LnWBE0(U2의 LDQM과 연결), LnWBE1(U2의 UDQM과 연결)과 LSCLK1(U3의 SCLK), LnWBE2(U3의 LDQM과 연결), LnWBE3(U3의 UDQM과 연결)이다. 나머지 U2, U3의 어드래스 라인과 nGCS6등은 공통적으로 묶인다. 어드레스 라인을 보면 한가지 의문점이 생긴다. 왜 K4S561632E의 A0자리에 s3c2440의 LADDR0부터 연결을 하지않고 LADDR2부터 연결 했을까? 또 왜 K4S561632E의 BA0, BA1에 LADDR24, LADDR25를 연결했을 까? 이는 s3c2440 데이터 시트를 보면 알 수 있다. SDRAM은 s3c2440의 SDRAM콘트롤러에 의해서 제어된다고 했다. 이는 SDRAM의 용량에 따라서 s3c2440에 주소 라인에 인터페이스하는 방법이 달라지는데 s3c2440의 데이터시트를 참조 해야된다( s3c2440 CPU 설계자가 이렇게 설계한것이기 때문에 이런 것에 대해서 심각하게 생각할 필요가 없다).
s3c2440 데이터 시트에서 SDRAM Memory Interface Examples부분을 살펴 보면 16비트 SDRAM 2개를 인터페이스 할경우의 예제를 보여준다(벤더에서 시키는 대로만 하면된다). nGCS7에 연결된 SDRAM 2개들도 동일하게 적용되는 내용이다(U6, U7 부분).


참고 할 만한 사이트 : http://kelp.or.kr/korweblog/stories.php?story=04/12/15/5293387&topic=30


4. NOR FLASH 인터페이스

ROM Memory Interface Examples



5. NAND FLASH 인터페이스




'ARM > MSTK-2440' 카테고리의 다른 글

MSTK2440 보드 테스트  (0) 2010.03.18
MSTK-2440 보드 소개  (0) 2009.08.21


보드 정보
네이버 카페 : http://cafe.naver.com/armpower.cafe
보드 제조사 : http://www.allstech.co.kr/sub2_2.php?PHPSESSID=fa6d14283353248d138f2596e3a4955c
보드 판매처 1 : http://www.edigitalworld.co.kr/index_item_view.html?pgCode=006351-000001
보드 판매처 2 : http://www.devicemart.co.kr/mart7/mall.php?cat=004019000&query=view&no=16825
교재 정보 : http://www.yes24.com/24/goods/1992901

 작년 말이였나 한참 보드 수집(?)에 열을 올리고 있을 때, 당근이 카페에서 중고로 싼가격에 좋은 물건이 올라왔다. 이미 "개발자를 위한 ARM 프로세서"라는 책을 가지고 있었다. 이책으로 공부를 할 때 보드를 가지고 있었다는 생각이 많이 들었는데 디바이스 마트에서 보드 가격을 보고 기절하는 줄 알았다. 뭔 2440 보드가 80만원씩이나.. 더구나 책까지 포함했을 경우에는 88만원에 파는 곳도 있었다. 결국 중고로 보드를 낼름 사버렸다. 여태껏 고이 모셔놓다가 공부할 일이 생겨서 꺼내 봤다. 테스트 프로그램을 램에 올리고 실행을 시켰는데 잘된다. ㅋ 당연히 잘되야지. 암튼 싼가격에 보드를 구입했는데 보드까지 이상이 없으니 기분이 좋다. 공부하는 김에 차근 차근 자료를 강좌 형식으로 정리할 생각이다. 언제 끝날지는 모르겠지만 첫번째 목표는 MSTK-2440 보드의 모든 내용(주변장치)을 펌웨어로 직접 제어하는 것 까지이다.

아래는 보드 스팩이다. 자세한 하드웨어 분석은 다음 강좌에서 할 생각이다.


1. CPU
 Samsung S3C2440A-40 (ARM920T with MMU)
 CPU Operation Frequency : Up to 400MHz

2. Boot ROM
 AM29LV800 Nor Flash (1MByte)
 K9F1208 Nand Flash (64MByte)

3. SDRAM
 K4S561632E 4EA (128MByte)

4. LCD
 2.8" LTP280QV-E01 (240× 320 Size TFT LCD, Touch Screen)

5. Peripheral
 IDE & CF Interface : XC95144XL-TQ100 (각각 1 Port)
 Ethernet : CS8900A (10 Based-T 1 Port)
   SD/MMC : 1 Slot
   Audio : UDA1341TS (Audio Jack)
   Serial : RS-232 2 Port
   USB : Host & Device
   Speaker : 0.25W/20mm
   JTAG : 20 Pin Box Header
   Infrared Receiver : KSM603LM
   Key Pad : 4EA & 1 External Interrupt SW
   Connector : Data, Address, Camera, IrDA, External Interrupt, GPIO
   Internal Function : IIC-AT24C16 EEPROM, Timer, Watch-Dog, RTC, ADC(10bit 8:1 Mux CH & Pen Drag)



'ARM > MSTK-2440' 카테고리의 다른 글

MSTK2440 보드 테스트  (0) 2010.03.18
MSTK-2440 보드 회로 분석  (0) 2009.08.21


feel 받아서 새벽에 완성한 라인트레이서 바디.
이제 콘트롤 보드, 적외선 센서 보드만 만들면 끝.
로봇 만들기 참 쉽죠잉~~.
그냥 가볍게 읽으시길...

 일상 생활 속에서 가끔 대처하기 어려운 난처한 부탁을 하는 사람을 가끔 접하게 되는데
 그런 상황에서 어떻게 해결하시는가요?
 이때  사람마다 대처하는 방법이 다릅니다.
 어떤이는 순간적 재치로 상대방 기분을 상하지 않게 걸하는 분도 있고
 부탁을 거절하는게 어려워 수락했다가
 한동안 또는 평생을 그로부터 못벗어나는 분도있습니다.
 이때 평소 그런것 특히 금전적이거나 재산상에 손해를 끼칠 수있는 부탁 에 대한 생각을 미리 해두었다면
 대처가 좀 쉬웠으리라 생각됩니다.
 대표적인게 보증이지요.

 주식에서도  자신이 보유한 종목이 좋아보이기는 한데 오늘같이 음봉이 나오면 내일 그리고다음주는
 더빠지지 않을까  결국 폭락하면 어덯게하지라는 걱정이 밀려오게되는데
 이런 걸 극복하고 여유롭게 지켜 볼려면 다음과 같이 해보시면 조금은 도움이 되실겁니다.
 

 우선 챠트의 이평선들을 단순히 주가를 평균한 점들을 연결한 선이라 보지 마시고
 시장에 참여한 외인 기관 개인들의 심리의 집합선이라 보시고
 
 1.과거 주식 시장에서 회자되었던  상승퓰 높은 종목 2~30종목을 선별합니다.
    (저가 급등주는 제외하고 주로 실적 성장주위주로)

 2.1차 상승후 조정기간동안  큰 자금 운용하는 자들의 거래행태를 시나리오 식으로  연결해봅니다.
    물론 들여다 봐도 전혀 감이 안오시는 분도 있으실태고
    몇 종목하다 보면 아하! 하고 무릎을 치는 분도 계실겁니다.
    단 한분이라도 무릎을 치시는 분이 있기를 바라는 마음에서 이 글을 씁니다.
    이 과정에서 거래량.  이평의 움직임 . 반복되는 기관 외인의 매수매도의 속뜻
    그리고 외인 기관 개인 큰손 들이 이평를 어떻게 이용하는지
    개인들의 매수매도를 어떻게 유도하는지
   그리고 조정끝에 매수 매도의 양은 어떻게 변하는지
   그리고   결과적으로 챠트상에 어떻게 조정끝이 나오고  이후 어떤 그림이 나오는지 살펴봅니다.
   필히 주봉도 함께봅니다.

 3.2번을 수없이 여러종목 반복하다 보면  정형화 시킬 수있는 몇개의 패턴이 나옵니다.
    물론 최적 매수시점이 나오고요.그다음 2차상승할때의 패턴도 자연스레 몇개가 도출됩니다.

 4.순서가 바끠었습니다. 첫번 째 언급했어야 하는데..
    종목선정때  반드시  재무안정성 수익성 성장성이 담보된 종목에 한합니다.
    이런 사항이 담보되지않고 챠트만 유사한 종목에 적용하면 필패입니다.

 5.자그러면 실전으로가서

    무릎을 몇번 치신 분이라면 자신이 보유한 종목의 향후 전개될 그림이 몇가지 나올겁니다.
    이때 주가의 흐름이 예상해던 그림중의 하나로 만들어 진다면
    이제 당신을 그림을 즐기면 됩니다.

 
  시간 날때 틈틈이 해보십시요.
  빠뜨린 부분이 있다면 추후 덧붙이겠습니다.

        모든 분 성투하시여 뜻하는 바 그대로 이루어 지길 바랍니다.


***** 서반 장투께 한마디 *****

  주가가 3만대 중반이면 현재   2007년 무증을 고려하면 역사적 고점 부근입니다.
  모든 여건이 좋지만 신 고가로 넘어가기엔 시간이 좀더 필요하 겁니다.
  적어도 한 두달정도........
  급하게 생각하면 장투로 절대 못갑니다.
  왜냐하면 황금이 같은 부류들이 길길이 날뛸 정도의
  인내심 테스트가 반듯이  있을 겁니다.
  그런 것없이 신고로 넘어가는 경우는 별로 없습니다.
  모든 분들의 성투를 바랍니다.
  장투중  대세장이 무너지거나 해당 종목에 펀더맨탈이 기존예상에 현저히 벗어나거나  돌발 악재가 출현할때
  기술적 분석으로 종목챠트가 환전히 하락 전환할때
  어떻게 대처하실 건지 항상 준비하시고 장투에 임하시면 좋은 결과가 있을겁니다.
  어떤 종목도 100%완벽한 장투 종목은 없기 때문입니다.
  추후 필요할때 글 올리겠습니다.

원문 :
http://board5.moneta.co.kr/cgi-bin/paxBulletin/bulView.cgi?mode=list&boardid=046890&code=046890&frame=analysis&page=1&billId=124892365629271


'재태크' 카테고리의 다른 글

주식 매매시 확인해야 될 사항들.  (0) 2010.07.19
도올 선생의 주식강좌 ㅋ  (0) 2010.05.10
매수의 3신호 / 프로들의 기술 지표  (0) 2010.02.27
주식 캔들 이해  (0) 2009.09.23
옵션 만기일  (0) 2009.09.10


아놔 윈도우를 새로 설치하는 과정에서 분명 윈도우 하드만 포맷을 했는데...
500GB 데이터 하드가 날라갔다..
파티션 자체가 지워짐.
-_-.. 내 데이터들.. 몇년동안 모은 데이터들..
소스자료도많은데..
Finaldata 라는 프로그램을 사용해서 복구 기능을 눌렀다.
제발 복구되어야 할텐데..
근데 복구에 앞써 클러스터 스캐닝 작업만 무려-_- 85시간이 남았다..

'It`s me.' 카테고리의 다른 글

2009 개발 언어 순위  (2) 2009.12.13
더디어 성공.  (1) 2009.11.03
4주 훈련을 끝내고 돌아오다.  (3) 2009.07.12
경래 군생활 1주차  (1) 2009.06.22
전주 35사단  (2) 2009.06.14

이메일 계정 탭

사용자 이름: (선택사항)
이메일 주소: ('@gmail.com'을 포함한 Gmail 주소)
받는 메일 서버(POP3): pop.gmail.com
보내는 메일 서버(SMTP): smtp.gmail.com
사용자 이름: ('@gmail.com'을 포함한 Gmail 주소)
비밀번호: (자신의 Gmail 비밀번호)
비밀번호 기억: (선택사항)
보안암호 인증으로 로그인: 사용 안함

추가 설정: 보내는 메일 서버 탭

보내는 메일 서버(SMTP) 인증 필요: 사용
받는 메일 서버와 동일한 설정 사용: 선택

추가 설정: 고급 탭

받는 메일 서버(POP3): 995
보안 연결(SSL) 필요 사용
보내는 메일 서버(SMTP): 587
다음 암호화된 연결 유형 사용 TLS
서버 시간제한 (1분 이상이어야 하며 5분을 권장함)
메일 사본을 서버에 보관 사용 안함

 

Let's start by creating a new C# Windows Application ( File -> New -> Project -> Visual C# Projects -> Windows Application ). Name the project SplashScreen.

   Let's leave the current form the way it is and add to our project another form. To do this, go to Project menu and click Add Windows Form. Name the class Splash.cs and click OK.

   Visual Studio .NET has created another form for you. Let's work a little on our new form. Let's set it's FormBorderStyle to None its StartPosition to CenterScreen. In the attached archive, I've created a simple image witch we will set as the BackgoundImage for our current form. Resize the form until it displays the full image. Now set the TransparencyKey property of our form to the background color of our image. As you can see, the color is Black. Also, it would be nice that this form would not be displayed in the taskbar. So set the ShowInTaskbar property to false.

   Now go back to Form1 class, created by default by Visual Studio .NET. We must add some code in this class to show the Splash form before initializing Form1.

   Let's go to Form1() method. That method is the constructor of the class and it executes before any other method. Let's add here the following code, right bellow the call to InitializeComponent method:

Thread th = new Thread(new ThreadStart(DoSplash));
th.Start();
Thread.Sleep(3000);
th.Abort();
Thread.Sleep(1000);

   Let's see what is done here. Fist, we declare a thread and tell him that when he starts, to execute the DoSplash method. The next line starts the thread. Now the started thread executes in parallel with the main application thread. To prevent the main form from appearing before the thread exits, we put the main thread to sleep for 3 seconds( 3000 milliseconds ).To be sure that the second thread will exit, we’ll leave him an extra 1 second to cleanup. . Let’s take a look at the DoSplash method that our second thread executes:

Splash sp = new Splash();
sp.ShowDialog();


   Let's see what is happening here. We declared an instance of our Splash class and displayed it. When we'll call the abort method of the thread, all the variable declared or instantiated in that thread will be disposed.

   Run the application now and see what happens. On my computer, the image is displayed correctly only if I set the color depth of my computer to 16 bits. This is a bug from Microsoft. After a few searches on google, you will find there is a fix for that. So let's fix it.

   Go to the Splash class constructor, and add the following code, after the InitializeComponent method:

Bitmap b = new Bitmap(this.BackgroundImage);
b.MakeTransparent(b.GetPixel(1,1));
this.BackgroundImage = b;
 

   What our code does is get the image we set as BackgroundImage and creates a Bitmap object as a copy of the same image. Next, we call MakeTransparent method of the Bitmap class that gets a color as an argument and makes it transparent. The argument that we pass is the color of the pixel at coordinates 1,1(these coordinates are not the only ones that you can use. You can use as well 0,0 and any other.).

   Here is the splash on my machine.



That's about it. Until next time, I wish you luck and happy programming.
[출처]
CodeSource.net

'닷넷 프레임워크' 카테고리의 다른 글

텍스트 박스 유효성 체크  (0) 2009.09.22
C# Thread 이야기  (0) 2009.09.22
DataGridView 소개  (1) 2009.07.13
MySQL 5.1과 C# 연동  (0) 2009.05.31
Thread 상태 전이도  (0) 2009.05.20

새 데이터 표 소개

Matthew MacDonald
새로운 DataGridView는 .NET 1.x의 표준이었으며 안타깝게도 제 역할을 하지 못한 DataGrid 컨트롤에 대해 .NET 2.0이 제시하는 해결책입니다. Matthew MacDonald가 아래에서 설명할 많은 개선 사항 중에서도 DataGridView는 광범위한 사용자 지정 및 세부적인 서식 지정, 유연한 크기 조정 및 선택, 뛰어난 성능 그리고 다양한 이벤트 모델을 지원합니다.
 
.NET Framework의 처음 두 릴리스(.NET 1.0 및 .NET 1.1)는 데이터 바인딩 부문에서 명백한 차이를 남겼습니다. 개발자들은 거의 모든 컨트롤을 거의 모든 데이터 원본에 연결할 수 있는 유연하고 구성 가능한 모델을 가지고 있었지만 전체 정보 테이블을 표시하기 위한 실질적인 방법은 없었습니다. 이를 위해 포함된 유일한 도구는 DataGrid 컨트롤로, 간단한 데모에서는 원활하게 작동했지만 실제 코드에서는 턱없이 부족한 성능을 나타냈습니다.
Microsoft는 이러한 격차를 줄이는 것을 .NET 2.0의 핵심 목표로 삼아 완전히 새로운 표 컨트롤인 DataGridView로 문제를 해결했습니다. DataGridView의 주요 원칙은 두 가지입니다. 먼저, 이 컨트롤은 단 몇 줄의 코드만 작성하여 마스터-세부 목록, 유효성 검사 및 데이터 서식 지정 같은 일반적인 작업을 지원하는 것을 목표로 합니다. 또한 무엇보다도 낮은 수준의 해킹 및 "편법" 프로그래밍에 의지하지 않고 필요한 특수 기능을 통합할 수 있도록 처음부터 확장성을 염두에 두고 디자인되었습니다.


기본적인 데이터 바인딩

DataGridView에 익숙해지는 가장 효과적인 방법은 속성을 하나도 구성하지 않고 직접 사용해 보는 것입니다. DataGrid와 마찬가지로 DataSource 속성을 사용하여 DataTable 개체(또는 DataTable에서 파생된 개체)를 바인딩할 수 있습니다.

          Dim ds As DataSet = GetDataSet()
          DataGridView1.DataSource = ds.Tables("Customers")
          
          
DataGrid와 달리 DataGridView는 테이블을 한 번에 하나씩만 나타낼 수 있습니다. 전체 DataSet를 바인딩하는 경우 나타낼 테이블 이름으로 DataMember 속성을 설정하지 않으면 아무런 데이터도 표시되지 않습니다.
          DataGridView1.DataSource = ds
          DataGridView1.DataMember = "Customers"
          
          
기본적인 DataGridView 표시는 다음과 같은 몇 가지 간단한 규칙을 따릅니다.
  • 데이터 원본의 각 필드에 대해 한 열씩 만듭니다.
  • 필드 이름을 사용하여 열 헤더를 만듭니다. 열 헤더는 고정되어 있어 사용자가 목록 아래로 이동해도 계속 볼 수 있습니다.
  • Windows XP 방식의 표시 스타일을 지원합니다. 열 헤더는 세련된 평면 모양이며 사용자가 헤더 위로 마우스를 이동하면 강조 표시됩니다.
쉽게 눈에 띄지는 않지만 DataGridView에는 다음과 같은 다양한 기본 동작이 포함되어 있습니다.
  • 현재 위치 내 편집이 가능합니다. 사용자는 셀을 두 번 클릭하거나 F2 키를 눌러 현재 값을 수정할 수 있습니다. 유일한 예외는 필드의 DataColumn.ReadOnly가 true로 설정되어 있는 경우입니다(예: 현재 예제의 OrderID 필드).
  • 자동 정렬을 지원합니다. 사용자는 열 헤더를 한 번 또는 두 번 클릭하여 해당 필드의 값을 기반으로 값 순서를 오름차순 또는 내림차순으로 정할 수 있습니다. 기본적으로 정렬은 데이터 형식을 고려하며 사전순 또는 숫자 순서대로 이루어집니다. 사전순 정렬은 대/소문자를 구분합니다.
  • 다양한 형식을 선택할 수 있습니다. 사용자는 클릭하여 끌어 오는 방식으로 하나 이상의 셀 또는 여러 행을 강조 표시할 수 있습니다. DataGridView 왼쪽 위에 있는 사각형을 클릭하면 전체 테이블이 선택됩니다.
  • 자동 크기 조정 기능을 지원합니다. 사용자가 헤더 사이의 열 구분선을 두 번 클릭하면 왼쪽 열이 셀 내용에 맞게 자동으로 확장 또는 축소됩니다.

 

멋진 모양의 DataGridView 만들기

DataGridView의 기본 모양은 DataGrid에 비해 약간 개선되었습니다. 하지만 몇 가지 간단한 세부 작업을 통해 모양을 멋지게 다듬을 수 있습니다.

한 가지 문제는 열이 해당 데이터에 맞게 자동으로 확장되지 않는다는 것입니다. 이 문제는 DataGridView.AutoSizeColumns() 메서드와 DataGridViewAutoSizeColumnCriteria 열거형 값 중 하나를 사용하여 해결할 수 있습니다. 열의 크기는 헤더 텍스트 너비, 현재 표시된 행 또는 테이블의 모든 행을 기반으로 조정하도록 선택할 수 있습니다.
          ' 헤더에서 가장 큰 텍스트의 너비
          ' 또는 이 열의 행 중 하나에 대해
          ' 열 크기를 조정합니다.
          DataGridView1.AutoSizeColumns( _
            DataGridViewAutoSizeColumnCriteria.HeaderAndRows)
          
                  '자동 셀 크기 조정
                  dv1.AutoResizeColumns()
                  dv1.AutoResizeRows()
          
           
          

(참고: 프로그래머 코멘트는 샘플 프로그램 파일에는 영문으로 제공되며 기사에는 설명을 위해 번역문으로 제공됩니다.)

이 메서드는 데이터 바인딩이 끝난 후 호출해야 하며 그렇지 않으면 어떤 영향도 미치지 않습니다. 또한 사용자가 편집한 후에 사용하는 경우도 있습니다(DataGridView.CellValueChanged 같은 이벤트에 대한 응답으로).
이에 맞게 열 크기를 넓히는 대신 행 크기를 변경할 수도 있습니다. 기본적으로 열의 텍스트는 여러 줄에 겹치게 됩니다. DataGridView.AutoSizeRows() 메서드를 사용하는 경우 행은 내용에 맞게 높이가 조정됩니다. 특히 필드에 텍스트의 양이 많은 경우에는 이 메서드를 사용하기 전에 열 크기를 넓혀야 할 수 있습니다. 예를 들어 다음 코드 조각은 Descript-xion 열의 크기를 네 배로 늘린 다음 내용에 맞게 행의 크기를 조정합니다.
          DataGridView.Columns("Descript-xion").Width *= 4
          DataGridView.AutoSizeRows( _
            DataGridViewAutoSizeRowsMode.HeaderAndColumnsAllRows)
          
          
그림 1에서는 DataGridView의 크기를 자동으로 조정하는 서로 다른 접근 방식을 비교합니다.
또 다른 적절한 변화 중 하나로 각 열에 나타나는 헤더 텍스트를 변경하는 기능을 들 수 있습니다. 예를 들어 필드 이름인 "OrderDate"보다는 "Order Date"라는 제목을 붙이는 것이 보다 전문적인 느낌을 줍니다. 이러한 변화는 매우 간단하게 이루어집니다. 다음과 같이 DataGridView.Columns 컬렉션에서 적절한 DataGridViewColumn을 검색한 다음 해당 HeaderText 속성을 수정하면 됩니다.
          DataGridView.Columns("OrderID").HeaderText = "Order ID"
          
          

DataGridView를 사용하여 셀 선택

DataGridView를 사용하면 기본적으로 자유로운 선택이 가능합니다. 사용자는 개별 셀, 셀 그룹, 모든 셀을 한 번에(표 오른쪽 위의 사각형을 클릭하여) 또는 하나 이상의 행(헤더 열의 행을 클릭하여)을 강조 표시할 수 있습니다. 선택 모드에 따라 사용자는 열 헤더를 선택하여 하나 이상의 열을 선택할 수도 있습니다. 이 동작을 제어하려면 다음 설명과 같이 DataGridViewSelectionMode 열거형 값 중 하나로 DataGridView.SelectionMode 속성을 선택합니다.
  • CellSelect 셀은 선택할 수 있지만 전체 행 또는 헤더는 선택할 수 없습니다. DataGridView.MultiSelect가 True이면 여러 개의 셀을 선택할 수 있습니다.
  • FullColumnSelect 열 헤더를 클릭하여 전체 열만 선택할 수 있습니다. DataGridView.MultiSelect가 True이면 여러 개의 열을 선택할 수 있습니다. 이 모드를 사용하면 열 헤더를 클릭해도 표가 정렬되지 않습니다.
  • FullRowSelect 행 헤더를 클릭하여 전체 행만 선택할 수 있습니다. DataGridView.MultiSelect가 True이면 여러 개의 행을 선택할 수 있습니다.
  • ColumnHeaderSelect CellSelect 또는 FullColumnSelect 선택 모드를 사용할 수 있습니다. 이 모드를 사용하면 열 헤더를 클릭해도 표가 정렬되지 않습니다.
  • RowHeaderSelect CellSelect 또는 FullRowSelect 선택 모드를 사용할 수 있습니다. 이것이 기본 선택 모드입니다.
DataGridView는 다음 세 가지 속성을 사용하여 선택한 셀을 손쉽게 검색할 수 있도록 해줍니다. SelectedCells, SelectedRows 및 SelectedColumns. SelectedCells는 사용하는 선택 모드에 관계 없이 DataGridViewCell 개체의 컬렉션을 반환합니다. 반면 SelectedRows는 행 헤더를 선택하여 전체 행을 선택한 경우 정보만 반환하며 SelectedColumns는 열 헤더를 사용하여 전체 열을 선택한 경우 정보만 반환합니다.
예를 들어 다음 코드 조각은 선택한 전체 행을 확인합니다. 행을 찾으면 다음과 같이 메시지 상자에 CustomerID 열의 해당 값을 표시합니다.
          For Each SelectedRow As DataGridViewRow In _
            DataGridView1.SelectedRows
              MessageBox.Show( _
                SelectedRow.Cells("CustomerID").Value)
          Next
          
          
이 작업은 CurrentCell 또는 CurrentCellAddress 속성을 사용하여 현재 셀에 대한 참조를 검색하는 것만큼이나 간단합니다. DataGridView를 사용하면 현재 셀이 검정 점선 사각형 모양의 포커스 영역으로 둘러싸입니다. 이 영역이 현재 사용자의 위치입니다.
CurrentCellAddress 속성은 읽기 전용이지만 CurrentCell을 사용하면 현재 위치를 프로그래밍 방식으로 변경할 수 있습니다. 그런 후에 현재 위치가 표시되도록 DataGridView가 스크롤됩니다.
          ' 11번째 행의 네 번째 셀로 이동합니다.
          DataGridView.CurrentCell = _
            DataGridView.Rows(10).Cells(3)
          
          
DataGridView 개체

지금까지는 현재 선택한 행, 셀 및 열 집합과 상호 작용하는 방법을 확인했습니다. DataGridView는 전체 데이터 집합을 작업할 수 있게 해주는 두 개의 주요 컬렉션을 제공합니다. 이들은 Columns(DataGridViewColumn 개체의 컬렉션) 및 Rows(각각 DataGridViewCell 개체의 컬렉션을 참조하는 DataGridViewRow 개체의 컬렉션)로 나타납니다. 그림 2는 개체 모델을 보여 줍니다.

일반적으로 열 표시 속성, 서식 지정 및 헤더 텍스트를 구성하려면 DataGridViewColumn 개체를 사용합니다. 또한 DataGridViewRow 및 DataGridViewCell 개체는 바인딩된 레코드에서 실제 데이터를 검색하는 데 사용합니다. DataGridViewCell의 데이터를 수정하면 다음과 같이 사용자가 편집하는 것과 동일한 방식으로 처리됩니다. 적절한 DataGridView 변경 이벤트가 발생되면 기본 DataTable이 수정됩니다.
이제 DataGridView 개체 모델을 이해했으므로 테이블을 순환하는 코드를 쉽게 만들 수 있습니다. 행, 열 또는 셀을 선택하기 위해 해야 할 일은 해당하는 DataGridViewRow, DataGridViewColumn 또는 DataGridViewCell 개체를 찾아 IsSelected 속성을 true로 설정하는 것뿐입니다.
다음 예제는 OrderID 필드가 100 미만인 모든 행을 프로그래밍 방식으로 선택합니다.
          For Each Row As DataGridViewRow In DataGridView1.Rows
              If Row.Cells("OrderID").Value < 100 Then
                  Row.Selected = True
              End If
          Next
          
          
DataGridViewColumn에서 여러 개의 서로 다른 클래스가 파생되는 것에는 신경쓰지 않아도 됩니다. 이러한 클래스는 셀에서 값을 그리고 편집하는 방식을 제어할 수 있습니다. .NET에는 다음과 같은 5개의 미리 빌드된 DataGridView 열 클래스가 포함되어 있습니다. DataGridViewButtonColumn, DataGridViewCheckBoxColumn, DataGridViewComboBoxColumn, DataGridViewImageColumn 및 DataGridViewTextBoxColumn.

 

DataGridView 스타일

DataGridView를 디자인하는 데 발생하는 한 가지 문제는 서로 다른 수준의 서식 지정을 적용할 만큼 유연하면서 매우 큰 테이블에 대해서도 효과적인 서식 지정 시스템을 만드는 것이었습니다. 유연성을 고려할 경우 최상의 접근 방식은 개발자가 각 셀을 개별적으로 구성할 수 있게 하는 것입니다. 그러나 효율성 측면에서 보면 이 접근 방식은 매우 열악하다고 할 수 있습니다. 테이블에 행이 수천 개면 셀은 수만 개가 되므로 셀마다 개별적으로 서식 지정을 관리한다는 것은 보나마나 많은 양의 메모리만 낭비하는 헛수고가 될 것입니다.

이 문제를 해결하기 위해 DataGridView는 DataGridViewCellStyle 개체를 사용하는 다계층 모델을 사용합니다. DataGridViewCellStyle 개체는 셀의 스타일을 나타내며 색, 글꼴, 맞춤, 줄 바꿈 및 데이터 서식 지정 같은 세부 사항이 포함되어 있습니다. 단일 DataGridViewCellStyle을 만들면 전체 테이블의 기본 서식을 지정할 수 있습니다. 또한 열, 행 및 개별 셀에 대해 기본 서식을 지정할 수 있습니다. 서식을 보다 세부적으로 지정할수록 더 많은 DataGridViewCellStyle 개체를 만들며 솔루션의 확장 가능성은 떨어지게 됩니다. 그러나 주로 열 기반 및 행 기반 서식 지정을 사용하고 개별 셀의 서식은 가끔씩 지정하는 경우 DataGridView의 메모리가 DataGrid보다 훨씬 많을 필요는 없습니다.
DataGridView는 서식 지정을 적용할 때 다음과 같은 우선 순위를 따릅니다(내림차순으로).
1. DataGridViewCell.Style
2. DataGridViewRow.DefaultCellStyle
3. DataGridView.AlternatingRowsDefaultCellStyle
4. DataGridView.RowsDefaultCellStyle
5. DataGridViewColumn.DefaultCellStyle
6. DataGridView.DefaultCellStyle
여기서 이해해야 할 부분은 스타일 개체가 전혀 적용되지 않는다는 점입니다. 대신 DataGridView는 각 개별 속성을 확인합니다. 예를 들어 DataGridViewCell.Style 속성을 사용하여 사용자 지정 글꼴을 적용하지만 사용자 지정 전경색은 설정하지 않는 셀이 있다고 가정합시다. 이렇게 되면 글꼴 설정은 다른 모든 스타일 개체의 글꼴 정보보다 우선하여 적용되지만 전경색은 null이 아닌 경우 계층 구조의 다음 스타일 개체에서 상속됩니다(이 경우 DataGridViewRow.DefaultCellStyle).
DataGridViewCellStyle은 다음과 같은 두 가지 유형의 서식 지정을 정의합니다. 데이터 및 모양. 데이터 서식 지정이란 데이터 바인딩된 값이 표시되기 전에 수정되는 방식을 지정하는 것을 말합니다. 여기에는 일반적으로 서식 지정 문자열을 사용하여 숫자 또는 날짜 값을 텍스트로 전환하는 작업이 포함됩니다. 데이터 서식 지정을 사용하려면 DataGridViewCellStyle.Format 속성을 사용하여 형식 지정자 또는 사용자 지정 형식 문자열을 설정하면 됩니다.
예를 들어 다음 코드 조각은 UnitCost 필드에 있는 모든 숫자의 서식을 지정하여 이들 숫자가 통화 값으로 표시되고 두 개의 소수 자릿수와 적절한 통화 기호가 로캘 설정에 정의됩니다.
          DataGridView1.Columns("UnitCost"). _
            DefaultCellStyle.Format = "C"
          
          
모양 서식 지정에는 색 및 글꼴 같은 표면적인 묘사가 포함되어 있습니다. 예를 들어 다음 코드는 UnitCost 필드를 오른쪽으로 맞추고 굵은 글꼴을 적용하며 셀 배경을 노랑으로 변경합니다.
          DataGridView1.Columns("UnitCost"). _
            DefaultCellStyle.Font = _
            New Font(DataGridView.Font, FontStyle.Bold)
          DataGridView1.Columns("UnitCost"). _
            DefaultCellStyle.Alignment = _
            DataGridViewContentAlignment.MiddleRight
          DataGridView1.Columns("UnitCost"). _
            DefaultCellStyle.BackColor = Color.LightYellow
          
          
다른 서식 지정 관련 속성에는 ForeColor, SelectionForeColor, SelectionBackColor, WrapMode(공간이 허용되는 경우 텍스트를 여러 줄에 겹치게 할지 잘라낼지 여부를 제어) 및 NullValue(null 값을 대체하는 값)가 있습니다.
또한 DataGridView에는 디자인 타임에 열 스타일을 구성할 수 있게 해주는 디자이너가 포함되어 있습니다. 속성 창에서 DataGridView Properties 링크를 선택하거나 AutoFormat을 선택하여 다양한 미리 빌드된 스타일 설정에서 선택하면 됩니다.

 

사용자 지정 셀 서식 지정

셀의 서식을 지정하기 위해 첫 번째로 선택할 사항은 상위 DataGridView, DataGridViewColumn 및 DataGridViewRow 속성을 통해 작업하는 것입니다. 그러나 때로는 특정 개별 셀의 스타일을 설정해야 하는 경우도 있습니다. 예를 들어 열의 데이터가 특정 값보다 크거나 작으면 데이터를 플래그해야 하는 경우가 있습니다. 이에 대한 한 가지 예는 프로젝트 일정 목록에서 기한이 경과된 만기일 또는 매출 분석에서 마이너스 수익률을 강조 표시하는 것입니다. 위의 두 경우 모두 개별 셀의 서식을 지정해야 합니다.

DataGridView 개체 모델에 대한 지식을 활용하여 값을 강조 표시할 것으로 예상되는 특정 열에서 셀의 컬렉션을 반복하고 싶을 수도 있습니다. 이러한 접근 방식은 사용할 수는 있지만 최선의 선택은 아닙니다. 여기서 중요한 문제는 사용자가 데이터를 편집하거나 코드가 바인딩된 데이터 원본을 변경하는 경우 셀 강조 표시가 일치하도록 업데이트되지 않는다는 것입니다.
다행히도 DataGridView는 이를 위해 CellFormatting 이벤트를 제공합니다. CellFormatting은 셀 값이 그려지기 직전에 발생되며 내용을 기반으로 셀 스타일을 업데이트할 수 있습니다. 다음은 특정 고객을 확인하여 그에 따라 셀을 플래그하는 예제입니다.
          Private Sub DataGridView1_CellFormatting( _
            ByVal sender As System.Object, _
            ByVal e As System.Windows.Forms. _
            DataGridViewCellFormattingEventArgs) _
            Handles DataGridView1.CellFormatting
          
              ' 맞는 열인지 확인합니다.
              If DataGridView1.Columns(e.ColumnIndex).Name = _
                "CustomerID" Then
                  ' 맞는 값인지 확인합니다.
                  If e.Value = "ALFKI" Then
                      e.CellStyle.ForeColor = Color.Red
                      e.CellStyle.BackColor = Color.Yellow
                  End If
              End If
          End Sub
          
          
표의 모양에 영향을 주는 세부 사항은 스타일뿐만이 아닙니다. 사용자가 오른쪽으로 스크롤하더라도 계속 표시되도록 열을 숨기고 위치를 이동하며 잠글 수도 있습니다. 이러한 기능은 모두 다음 설명과 같이 DataGridViewColumn 클래스의 속성을 통해 제공됩니다.
  • DisplayIndex DataGridView에서 열이 표시되는 위치를 설정합니다. 예를 들어 DisplayIndex가 0인 열은 가장 왼쪽 열에 자동으로 표시됩니다. DisplayIndex가 동일한 열이 둘 이상이면 컬렉션의 첫 번째 열이 가장 먼저 표시됩니다. 따라서 DisplayIndex를 사용하여 열을 왼쪽으로 옮기는 경우 가장 왼쪽 열의 DisplayIndex도 오른쪽으로 옮기도록 설정해야 합니다. 처음에 DisplayIndex는 DataGridView.Columns 컬렉션의 DataGridViewColumn 개체의 인덱스와 일치합니다.
  • Frozen True인 경우 사용자가 추가 열을 확인하기 위해 오른쪽으로 스크롤해도 테이블 왼쪽에 표시된 상태로 고정됩니다.
  • HeaderText 열 헤더에 표시되는 텍스트를 설정합니다.
  • Resizable 및 MinimumWidth Resizable을 False로 설정하여 사용자가 열 크기를 조정하지 못하게 하거나 MinimumWidth를 최소 허용 픽셀 수로 설정합니다.
  • Visible False로 설정하여 열을 숨깁니다.

단추 열

DataGridView를 위해 제공되는 열 형식 중 하나는 모든 항목 옆에 단추를 표시하는 DataGridViewButtonColumn입니다. 이 단추의 클릭에 응답하는 것은 물론 이를 사용하여 다른 작업을 시작하거나 새 폼을 표시할 수도 있습니다.

다음은 단추 텍스트가 "Details..."인 간단한 단추 열을 만드는 예제입니다.
          ' 단추 열을 만듭니다.
          Dim Details As New DataGridViewButtonColumn()
          Details.Name = "Details"
          
          ' 데이터 바인딩을 해제하고 정적 텍스트를 표시합니다.
          ' (대신 DataPropertyName 속성을 설정하여
          ' 테이블의 속성을 사용할 수도 있습니다.)
          Details.DisplayTextAsFormattedValue = False
          Details.Text = "Details..."
          
          ' 헤더를 지웁니다.
          Details.HeaderText = ""
          
          ' 열을 추가합니다.
          DataGridView1.Columns.Insert( _
            DataGridView1.Columns.Count, Details)
          
          
그림 3은 새 열이 표시된 표를 보여 줍니다. 다음은 모든 열에서 단추 클릭에 반응하여 해당되는 레코드 정보를 표시하는 코드입니다.
          Private Sub DataGridView1_CellClick( _
            ByVal sender As System.Object, _
            ByVal e As System.Windows.Forms. _
            DataGridViewCellEventArgs) _
            Handles DataGridView1.CellClick
          
              If DataGridView1.Columns(e.ColumnIndex).Name = _
                "Details" Then
                  MessageBox.Show("You picked " & _
                    DataGridView1.Rows(e.RowIndex). _
                    Cells("CustomerID").Value)
              End If
          End Sub
          
          
좀 더 현실적인 시나리오에서는 여기서 새 창을 만들고 표시한 다음 선택한 레코드에 대한 정보를 새 창으로 전달하여 전체 정보를 쿼리하고 표시할 수 있도록 합니다.

이미지 열

DataGridView를 위해 제공되는 또 다른 열 형식은 셀 범위에 그림을 표시하는 DataGridViewImageColumn입니다. DataGridViewImageColumn.Layout 속성을 설정하면 크기에 맞게 늘이든 너무 큰 경우 그냥 잘라내든 간에 셀에 그림이 표시되는 방법을 구성할 수 있습니다.

DataGridViewImageColumn은 다음 두 가지 방법으로 사용할 수 있습니다. 먼저, DataGridViewButtonColumn과 동일한 방식으로 직접 이를 만들어 추가할 수 있습니다. 이 방법은 DataSet에 제공되지 않는 관련된 이미지 데이터를 표시하려는 경우에 유용합니다. 예를 들어 파일 이름(예: ProductPic002.gif)을 가져와 네트워크 드라이브에서 해당 파일을 읽은 다음 이를 표에 표시하는 경우가 있습니다. 이를 수행하려면 CellFormatting처럼 DataGridView 이벤트에 반응해야 하며, 이 때 열의 Value 속성을 사용하여 해당하는 행의 그림을 읽고 이미지 데이터를 가져오며 이를 삽입합니다.
DataSet에 수작업이 필요 없는 이진 그림 데이터가 들어 있으면 상황은 훨씬 간단해집니다. 이에 대한 한 가지 예는 회사 로고가 포함되어 있는 SQL Server pubs 데이터베이스의 pub_info 테이블입니다. 이 테이블에 바인딩할 때는 추가 단계를 수행할 필요 없이 DataGridView가 현재 이미지를 사용하고 있음을 자동으로 인식하여 필요한 DataGridViewImageColumn을 만들어 줍니다. (이 기법의 예제는 이 기사의 다운로드를 참조하십시오.)

DataGridView를 사용하는 편집

DataGrid는 사용자 입력에 유연성이 떨어지기로 악명 높아 셀의 유효성을 검사하고 오류를 보고하는 방식을 사용자 지정하기가 거의 불가능했습니다. 반면 DataGridView를 사용하면 편집 프로세스의 모든 단계에서 발생하는 수많은 서로 다른 단계에 반응하여 동작을 제어할 수 있습니다.

기본적으로 DataGridView 셀은 사용자가 마우스로 셀을 두 번 클릭하거나 F2 키를 누르면 편집 모드로 들어갑니다. 또한 DataGridView.EditCellOnEnter 속성을 true로 설정하면 사용자가 셀로 이동하자마자 편집 모드로 전환되도록 DataGridView를 구성할 수 있습니다. DataGridView의 BeginEdit(), CancelEdit(), CommitEdit() 및 EndEdit() 메서드를 사용하여 셀 편집을 프로그래밍 방식으로 시작 및 중단할 수도 있습니다. 사용자가 셀을 편집하면 행 헤더에 연필 모양의 편집 아이콘이 표시됩니다.
사용자가 Esc 키를 누르면 편집을 취소할 수 있습니다. EditCellOnEnter 속성을 true로 설정하면 셀이 편집 모드로 유지되지만 모든 변경 내용이 삭제됩니다. 변경을 커밋하려면 사용자가 새로운 셀로 이동하거나 포커스를 다른 컨트롤로 변경하면 됩니다. 코드에서 현재 셀 위치를 옮기면 변경 내용도 함께 커밋됩니다.
셀을 편집하지 못하게 하려면 DataGridViewCell, DataGridViewColumn, DataGridViewRow 또는 DataGridView의 ReadOnly 속성을 설정하면 됩니다(변경하지 못하게 하려는 대상이 해당 셀인지, 해당 열의 모든 셀인지, 해당 행의 모든 셀인지 또는 테이블의 모든 셀인지에 따라 다름). DataGridView는 또한 시도한 편집을 취소하기 위해 처리할 수 있는 CellBeginEdit 이벤트를 노출합니다.

오류 처리

기본적으로 DataGridViewTextBoxColumn을 사용하면 사용자가 현재 셀에 허용되지 않을 수 있는 문자를 포함하여 모든 문자를 입력할 수 있습니다. 예를 들어 사용자가 숫자 필드에 숫자가 아닌 문자를 입력하거나 DataSet에 정의된 ForeignKeyConstraint 또는 UniqueConstraint를 위반하는 값을 지정할 수도 있습니다. DataGridView는 이러한 문제를 다음과 같이 다양한 방식으로 처리합니다.

  • 편집한 값을 필요한 데이터 형식으로 변환할 수 있으면(예: 사용자가 숫자 열에 텍스트를 입력한 경우) 사용자는 변경 내용을 커밋하거나 다른 행으로 이동할 수 없게 됩니다. 대신 변경 내용을 취소하거나 값을 편집해야 합니다.
  • 편집한 값이 DataSet의 제약 조건을 위반하는 경우 사용자가 다른 행으로 이동하거나 Enter 키를 눌러 이를 커밋하고 나면 바로 변경 내용이 취소됩니다.
이처럼 명백한 기본값은 대부분의 시나리오에서 원활하게 적용됩니다. 그러나 필요한 경우 DataGridView가 데이터 원본에서 오류를 차단할 때 발생하는 DataGridView.DataError 이벤트에 응답하여 오류 처리에 참가할 수도 있습니다.

입력 유효성 검사

유효성 검사는 오류 처리와는 약간 다른 작업입니다. 오류 처리의 경우 DataSet를 통해 보고되는 문제를 처리합니다. 하지만 유효성 검사의 경우 DataSet에는 허용될 수 있지만 응용 프로그램에는 적절하지 않은 데이터 같은 고유한 사용자 지정 오류 조건을 찾아냅니다.

사용자가 새로운 셀로 이동하여 변경 내용을 커밋하면 DataGridView 컨트롤은 CellValidating 및 CellValidated 이벤트를 발생시킵니다. 또한 이러한 이벤트 다음에는 RowValidating 및 RowValidated 이벤트가 발생됩니다. 여러분은 이러한 이벤트에 응답하고 사용자가 입력한 값이 올바른지 확인하며 필요한 처리 후 작업을 수행할 수 있습니다. 값이 올바르지 않으면 일반적으로 변경 내용 및 셀 탐색을 취소하거나(EventArgs 개체의 Cancel 속성을 true로 설정하여) 사용자에게 알려줄 몇 가지 오류 텍스트를 설정하여 응답하게 됩니다. 오류 텍스트는 다른 컨트롤에 배치하거나 다음과 같이 해당하는 DataGridViewRow 및 DataGridViewCell의 ErrorText 속성을 사용하여 DataGrid에 표시할 수 있습니다.
  • DataGridViewCell.ErrorText를 설정하면 셀에 느낌표 아이콘이 표시됩니다. 마우스로 이 아이콘을 가리키면 오류 메시지가 표시됩니다.
  • DataGridViewRow.ErrorText를 설정하면 행 왼쪽의 행 헤더에 느낌표 아이콘이 표시됩니다. 마우스로 이 아이콘을 가리키면 오류 메시지가 표시됩니다.
일반적으로 이들 속성은 모두 함께 사용하며 행과 셀 모두에 오류 메시지를 설정하게 됩니다. 다음은 CompanyName 필드의 너무 긴 텍스트 항목을 확인하는 예제입니다. 문제가 되는 값을 발견하면 문제가 설명된 도구 설명 텍스트와 함께 오류 그림(빨강 느낌표 표시)이 셀에 추가됩니다.
          Private Sub DataGridView1_CellValidating( _
            ByVal sender As System.Object, _
            ByVal e As System.Windows.Forms. _
            DataGridViewCellValidatingEventArgs) _
            Handles DataGridView1.CellValidating
          
              If DataGridView1.Columns(e.ColumnIndex).Name = _
                "CompanyName" Then
                  If CType(e.FormattedValue, String).Length > _
                    50 Then
                      DataGridView1.Rows( _
                        e.RowIndex).Cells(e.ColumnIndex). _
                        ErrorText = _
                        "회사 이름이 너무 깁니다."
                  End If
              End If
          End Sub
          
          
목록 열로 선택 사항 제한

유효성 검사를 사용하면 모든 오류 조건을 잡아낼 수 있습니다. 그러나 이 접근 방식을 사용하면 잘못된 내용을 입력한 다음 이를 사후에 수정할 수 있기 때문에 반드시 최선의 방법이라고 할 수는 없습니다. 보다 바람직한 방법은 우선 사용자가 잘못된 내용을 입력하지 못하도록 하는 것입니다.

한 가지 일반적인 예는 열을 미리 정의한 값 목록으로 제한해야 하는 경우에 나타납니다. 이 시나리오에서는 사용자가 직접 입력하기보다 목록에서 올바른 값을 선택하는 것이 가장 쉽습니다. 무엇보다도 DataGridViewComboBoxColumn을 사용하면 이 디자인을 가장 손쉽게 구현할 수 있습니다.
DataGridViewComboBoxColumn의 항목 목록은 ListBox에서처럼 항목 컬렉션을 사용하여 직접 추가할 수 있습니다. 또한 DataGridViewComboBoxColumn을 또 다른 데이터 원본에 바인딩할 수 있습니다. 이 경우 DataSource 속성을 사용하여 데이터 원본을 지정하고 DisplayMember 속성을 사용하여 열에 표시해야 하는 값을 나타내며 ValueMember 속성을 사용하여 기본 열 값에 사용해야 하는 값을 나타냅니다.
이에 대한 데모로 Products 테이블에 작업하는 다음 예제를 살펴보겠습니다. 이 테이블의 모든 레코드는 해당 CategoryID 필드를 통해 Categories 테이블의 레코드에 연결되어 있습니다. 제품의 범주를 변경하려면 사용자는 올바른 ID를 기억하여 CategoryID 필드에 입력해야 합니다. 보다 나은 방법은 Categories 테이블에 바인딩되는 DataGridViewComboBoxColumn을 사용하는 것입니다. 이 열은 CategoryName을 표시 멤버로 사용하지만 실제 기본 값으로 CategoryID를 갖게 됩니다. 또한 이 열은 DataProperyName 속성을 통해 Products 테이블에 계속 바인딩되어 사용자가 목록에서 새 Category를 선택하면 제품 레코드의 CategoryID 필드가 자동으로 변경됩니다.
다음은 이 테이블을 구성하는 데 필요한 코드입니다.
          ' 자동으로 생성된 CategoryID 열을 제거합니다.
          DataGridView1.Columns.Remove("CategoryID")
          
          ' CategoryID의 목록 열을 만듭니다.
          Dim List As New DataGridViewComboBoxColumn()
          List.DisplayIndex = 0
          List.HeaderText = "Category"
          
          ' 이 열은
          ' Products.CategoryID 필드에 바인딩됩니다.
          List.DataPropertyName = "CategoryID"
          
          ' Categories 테이블에서 목록을 채웁니다.
          List.DataSource = ds.Tables("Categories")
          List.DisplayMember = "CategoryName"
          List.ValueMember = "CategoryID"
          
          ' 열을 추가합니다.
          DataGridView1.Columns.Add(List)
          
          
결론
이 기사에서는 .NET에서 가장 기대되는 새로운 컨트롤 중 하나인 DataGridView의 개요를 설명했습니다. DataGrid와 달리 DataGridView는 데이터 바인딩 및 사용자 편집 시나리오와 정적 테스트의 표시와만 관련된 시나리오를 포함하여 다양한 실제 시나리오에서 올바르게 작동합니다. 머지 않아 .NET Framework가 설치된 통합 기능 데이터 솔루션이자 Windows Forms 개발자들이 .NET 2.0으로 업그레이드하려는 가장 큰 이유 중 하나인 DataGridView를 직접 경험할 수 있을 것입니다.

'닷넷 프레임워크' 카테고리의 다른 글

C# Thread 이야기  (0) 2009.09.22
Creating a splash screen  (0) 2009.07.15
MySQL 5.1과 C# 연동  (0) 2009.05.31
Thread 상태 전이도  (0) 2009.05.20
wav 파일 재생하기  (0) 2009.04.29




4주동안 훈련소안에서는 많은 일이 있었다.
정말 느낀 것도 많았고, 두번 다시는 경험하기 싫은 일도 있었고, 여러 사람들을 많이 만났었다.
결론은 짧게 아주 짧게 ㅋ 한번쯤은 다녀올만 하지만 두번 다시는 가기 싫다는 것.
짧은 기간이였지만 안에서는 4주도 정말 긴 시간이였다.
통제된 생활 속에서 사회와의 단절.
위에서 시키는데로만 해야된다는게 얼마나 답답한 일인지.
나처럼 창조적인 일을 하는 사람에겐ㅋ 정말 ㅋ답답한 곳이였다.
아직도 밖에 나와있는게 믿기지 않을 정도로 많이 익숙해졌었는데.
이젠 다시 일상속으로 돌아왔다.
사회에 있을 땐 이등병 나부랭이라고 무시했었는데, 훈련병때 이병이 왜 그렇게 높아 보이던지 ㅋ
앞으로는 무시하지 않겠어.
35사단 신병 교육대대 독수리 5중대 09 - 6기 13생활관 동기들 다시 만났음 좋겠다.
즐거웠어 전우들.

'It`s me.' 카테고리의 다른 글

더디어 성공.  (1) 2009.11.03
대형 사고를 치다.  (0) 2009.07.19
경래 군생활 1주차  (1) 2009.06.22
전주 35사단  (2) 2009.06.14
서울반도체 신세길 회장의 경영메모 성공을 만드는 4P 프로그램  (0) 2009.06.02


BOOT.INI 파일에서 수정.

/noexecute=optin 항목을   /noexecute=alwaysoff 로 변경 



전주 35사단 독수리5중대 3소대 13생활관 209번 훈련병 조경래

군생활 1주차 .
아저씨 경래 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ


변태외계인 이티체형 경래 . 과연 사람의 몸으로 훈련소를 나올 수 있을 것인가 ! 두둥 !

'It`s me.' 카테고리의 다른 글

대형 사고를 치다.  (0) 2009.07.19
4주 훈련을 끝내고 돌아오다.  (3) 2009.07.12
전주 35사단  (2) 2009.06.14
서울반도체 신세길 회장의 경영메모 성공을 만드는 4P 프로그램  (0) 2009.06.02
그리운 사람.  (0) 2009.05.26



아 이제 몇 시간 안남았네.
심숭생숭하지만 4주만 다녀오면 되니깐.
이거 한달동안 사회와 disconnect 되어있을 생각하니깐 답답하구만.
그동안에 서반이가 잘 컸으면 좋겠고.
제발 다녀오면 4만원이상 가 있었음 좋겠네.

몸건강히 잘 다녀올께.


7월 10일. 나옴 .. 금방갔다오니깐 안심각해져도됨ㅋㅋ

 
통신 프로그램 만들기
제1장 통신 프로그램 만들기
본 장에서는 RS232C 포트 즉 직렬(serial) 포트를 통해서 데이터를 전송하는 방법
에 대해서 설명을 하겠습니다. 직렬 포트는 보통 COM 포트라고 합니다. 컴퓨터에서
는 두 개의 직렬 포트를 설정할 수 있으며 그것을 COM1, COM2라고 합니다. 모뎀을
장착했을 경우에는 COM3, COM4도 사용 가능하지만 실질적으로는 2개의 컴포트밖에
는 사용하지 못합니다. 예를 들어 마우스를 COM1에 사용하고 모뎀을 COM4에 사용하
면 COM2와 COM3가 남은 것 같으나 실질적으로 COM1과 COM3가 같은 인터럽트를 사용
하고 COM4와 COM2가 같은 인터럽트를 사용하기 때문에 COM2를 사용하면 COM4와 충돌
하고 COM3를 사용하면 COM1과 충돌합니다.
본 장에서는 모뎀을 직접 컨트롤하는 명령어는 사용하지 않고 단순히 직렬 포트에
데이터를 넣고 직렬 포트에서 데이터를 읽어 오는 방법에 대해서 설명합니다. 모뎀
을 컨트롤하는 것은 직렬 포트에 모뎀 제어 명령문을 넣으면 됩니다. 이 명령문을
헤이즈 모뎀의 명령어라고 하지요. 예를 들어, 모뎀 초기화 명령 "Atz"라고 하여 모
뎀이 연결된 포트에 입력을 하면 이 명령문을 모뎀이 읽고 "OK"라고 응답합니다. 다
음 "Atdt 36792000"이라고 하면 3679-2000번으로 모뎀이 전화를 겁니다. 전화를 건
후 통신이 연결되면 모뎀은 전화선으로 들어온 데이터를 그대로 포트 디바이스에 넣
고 사용자가 그 포트에 있는 데이터를 읽어 오고 다시 보낼 데이터를 포트 디바이스
에 넣으면 모뎀은 포트에 들어온 데이터를 그대로 전화선을 통해서 상대 컴퓨터에
전송할 뿐입니다.
따라서 모뎀 제어까지 하지 않아도 전화를 이용한 통신 프로그램을 작성할 수 있습
니다.
보통 공장자동화에서 많은 제어 장치 중 컴퓨터가 로봇을 제어하기 위한 명령문을
받는 창구의 하나로 직렬 포트를 두고 있습니다. 그렇기 때문에 모뎀이 달려 있지
않은 직렬 포트에 데이터를 전송할 경우에 있어서도 본 장이 필요할 것입니다. 본
장은 윈도에서 직렬 커뮤니케이션을 할 수 있는 기법을 다루고 있습니다.
 

q 통신을 하는 함수 전체 보기
1.RS232C에 사용되는 신호
본장에서 사용하는 함수들은 Win32API에서 RS232C를 사용합니다. 이때 나오는 신호
용어 들을 미리 정의 합니다.
RTS(Rquest to Send) , CTS(Clear to Send): 직렬 포트와 모뎀이 연결되었을 경우
하드웨어 적으로 처리를 할 경우 사용되는 것입니다. 요즘 나온 14400이나 28800 또
는 그이상의 전송속도를 가지고 있는 모뎀들은 하드웨어적인 처리를 합니다.
DSR(Data Set Read) : 데이터를 읽기 위해 준비가 되었다는 플러그 인데 만일 모뎀
이 다른 모뎀과 설정되었을경우 이 신호는 1이되고 그렇지 않으면 0이됩니다.
DTR(Data Terminal Ready) : 두 대의 모뎀사이를 관리하기 위한 신호인데 만일 두
개의 모뎀이 연결되어 있다면 1 그렇지 않으면 0이됩니다.
통신을 할 때 사용하는 방법은 우선 컴포트를 열고, 데이터를 읽고, 데이터를 쓰고
컴포트를 닫는 것이 전부입니다. 사실 매우 간단하죠. 함수가 약간 복잡하지만 아래
에 설명을 했습니다. 이 책에서 함수 설명이 자세히 안 되어 있는 것은 도움말을 참
조하세요.

2.RS232C 포트에 접속하기
통신을 하기 위한 방식이 윈도 95로 넘어가면서 파일 개념으로 변화되었습니다. 즉
통신 포트를 하나의 파일로 놓고 파일을 열고 그 파일 안에 데이터를 넣고 그 파일
에서 데이터를 읽어 오게 하면 되는 식으로 바뀌었다는 것입니다. 그러니까 굉장히
사용하기 쉽게 컴포트에 접근할 수 있게 되었습니다.
포트를 파일처럼 여는 함수가 CreateFile입니다.

HANDLE CreateFile(
LPCTSTR lpFileName, // 파일명
DWORD dwDesiredAccess, // 접근 모드 읽기쓰기인가 읽기전용인가
DWORD dwShareMode, // 다른 프로그램과 공유를 할 것인가 아닌가
LPSECURITY_ATTRIBUTES lpSecurityAttributes, //보안에 관한 속성
DWORD dwCreationDistribution, // 어떻게 열 것인가
DWORD dwFlagsAndAttributes, // 파일 속성
HANDLE hTemplateFile // 템플레이트 파일 핸들러
);

위 함수는 포트만 여는 데 사용하는 함수가 아닌 일반적인 파일이나 또는 디바이스
를 여는 데도 사용하기 때문에 여러 인자가 있습니다. 위 함수에서 우리가 사용하
는 인자들만 가지고 설명을 하겠습니다.
lpFileName의 인자에는 컴포트 이름을 넣으면 됩니다. 만일 COM1이면 그냥 "COM1"이
라고 설정해 주면 되지요. 그럼 COM3이면 무엇일까요? "COM3"이겠지요.
dwDesireAccess란 접근 모드입니다. GENERIC_READ, GENERIC_WRITE 등이 있는데 컴포
트에 읽고 쓰고 해야 하니까 두 개를 합치면 되겠지요. GENERIC_ READ
|GENERIC_WRITE하면 됩니다.
보안에 관한 속성이란 현재 개방된 파일이 다른 사람들에게 오픈되지 못하게 잠그
는 속성을 말합니다.
그렇지만 컴포트는 그런 것이 필요없으므로 NULL로 해주면 됩니다.
파일을 어떻게 열 것인가?하는 문제는 새로 만들 것인가 아니면 항상 기존의 파일
을 열 것인가 등 여러 인자가 있습니다. 컴포트는 존재하므로 새로 만들 필요는 없
습니다. 결국 기존에 있는 것을 열면 되지요. 기존에 있는 파일을 열 때는
OPEN_EXISTING을 설정합니다. 파일 속성이란 보통 파일이면서 Overlapped가 되어야
겠죠. 이 때는 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED라고 설정해 줍니다. 템
플레이트 파일 핸들러는 필요가 없으므로 NULL로 합니다.
위의 함수를 사용하여 COM3 포트를 열 경우 다음과 같이 하면 됩니다.

HANDLE idComDev ;
idComDev=CreateFile( "COM3", GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security attrs
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_OVERLAPPED, // overlapped I/O
NULL );

이 곳에서 파일이 열리면 열려진 핸들이 바로 idComDev에 설정됩니다. 이 핸들러는
계속 사용하므로 기억하시기 바랍니다.

이벤트 설정과 체크

통신 포트를 통해서 들어오는 데이터는 많은 종류가 있습니다. 글자가 들어오는 경
우도 있겠지만 전화벨 데이터의 검출, 통신 에러 검출 등도 통신 함수를 통해서 모
두 검출할 수 있는 내용입니다. 이중에서 우리가 필요가 없는 데이터도 있고 필요
가 있는 데이터도 있습니다. 통신포트에 들어오는 데이터중 우리가 필요한 데이터
만 흡수할필요가 있습니다. 즉 모뎀에게 "문자가 수신되거나 출력버퍼에 마지막 문
자가 보내졌다"라는 내용만 오게 하고자 한다면 이해 해당하는 마스크를 설정하면됩
니다. 이함수가 SetCommMask입니다.
BOOL SetCommMask(HANDLE hFile,DWORD dwEvent);
hFile는 CreateFile에 의해서 리턴된 값이고 dwEvent는 표1과 같은 파라미터를 설정
하는 것입니다.
표1 dwEvent에 설정하는 값
이벤트 마스트
 내용
 
EV_RXCHAR
 문자가 수신되었음
 
EV_BREAK
 입력시에 갑자기 중단이 되었음
 
EV_CTS
 CTS 신호가 변경되었음
 
EV_DSR
 DSR 신호가 변경되었음
 
EV_ERR
 에러가 감지 되었음
 
EV_RING
 전화벨이 울렸음
 
EV_RXFLAG
 DCB구조체의 EvtChar 의 문자가 수신되어 입력버퍼에
저장되었음
 
EV_TXEMPTY
 출력 버퍼로 마지막 문자가 전송되었음
 
 
예를 들어서 문자가 수신되었다는 것을 마스크로 설정하고자 한다면 다음과 같습니
다.
SetCommMask(idComDev, EV_RXCHAR);

이런 데이터들이 들어오는지를 검사하는 함수가 WaitCommEvent인데 이 함수는 통신
포트를 통해서 데이터가 들어오기를 기다립니다. 위와 같이
SetCommMask(idComDer, EV_RXCHAR)라고 하고 WaitCommEvent 함수를 호출하면
WaitCommEvent 함수는 문자가 들어오기를 기다립니다.

WaitCommEvent(idComDev, &dwEvtMask, NULL );
 
위의 함수의 2번째 인자는 OVERLAPPED구조체 입니다. 보통 통신을 할 경우 동기화
를 하기 때문에 이구조체를 사용하지 않고 NULL로 설정합니다. SetCommMask를 단
한 개만 설정하지는 않습니다. 필요하면 여러개을 설정할 수가 있습니다. 위와 같
이 EV_RXCHAR를 설정하고 EV_TXEMPTY를 설정하였을 경우 WaitCommEvent함수를 실행
하면 EV_RXCHAR과 EV_TXEMPTY두개의 이벤트에 반응합니다. 두 번째 인자는 지금 어
떤 이벤트가 설정되어 있는 가에 대한 값을 저장합니다. idComDev는 위에서 만든 파
일 핸들러 입니다. 문자열이 입력되었을 때 어떤 행동을 하고 문자를 보냈을 때 행
동을 하라고 하고자 한다면 다음과 같이 하면 됩니다.

SetCommMask(idComDev, EV_RXCHAR|EV_TXEMPTY);
WaitCommEvent(idComDev, &dwEvtMask, NULL );
if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
{
문자열이 들어왔을 때 수행하는 내용
else if((dwEvtMask & EV_TXEMPTY) ==EV_TXEMPTY)
{
문자열을 출력했을 때 수행하는 내용
}

통신 버퍼 초기화

통신 디바이스 데이터가 들어오는데 컴퓨터가 계속 감시할 수도 있지만 여러 일을
동시에 할 경우 놓칠 수도 있지요. 너무 빠르게 데이터가 들어오기 때문에요. 이렇
기 때문에 포트로 들어오는 데이터를 무조건 버퍼에 채워 넣고 우리는 그 버퍼에 들
어 있는 데이터만 읽어 오면 되게끔 시스템이 설정되어 있습니다. 그렇다고 들어오
는 데이터를 무조건 넣으라고는 할 수 없지요. 어느 정도까지는 버퍼에 채우고 또
데이터가 들어오면 가장 앞단의 데이터를 삭제하게끔 하자는 이야기이죠. 이것이 큐
입니다. 포트 디바이스 버퍼 크기를 input과 output 버퍼로 설정하는 함수가 있습니
다. 이 함수가 SetupComm 함수입니다.
input, output 버퍼를 모두 4096이라고 설정하려 한다면 다음과 같이 하면 됩니다.

SetupComm( idComDev, 4096, 4096 ) ;

버퍼를 설정해 놓으면 그 버퍼 안에 쓰레기가 있을 수도 있어 초기 통신에 문제가
될 수 있으니까 버퍼를 모두 깨끗하게 청소해 놓고 또한 포트 디바이스를 초기화해
주어야 합니다. 이 때 사용하는 함수가 PurgeComm입니다. 다음과 같이 설정합니다.

PurgeComm( idComDev, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
PurgeComm은 데이터 입력을 받은후에 현재 버퍼를 지울때도 사용을 합니다.
이렇게 함으로써 실질적인 컴포트가 열렸는데 컴포트를 통해서 데이터를 교환하려
면 여러 조건이 필요합니다. 몇 bps로 할 것인가, XON/XOFF을 설정할 것인가 아닌
가, 데이터 비트는 몇 비트인가, 패리티 검사를 할 것인가 아닌가, 정지 비트를 어
떻게 할 것인가 등을 이런 것을 정의해 주어야 합니다. 이야기를 사용하는 사람은
baram.exe를 실행하여 통신을 설정할 때 위와 같은 내용을 본 적이 있을 것입니다.
윈도의 컴포트 통신도 마찬가지로 위와 같은 내용을 설정해 주어야 합니다. 그럼 이
런 것을 설정할 구조체가 필요한데 그 구조체가 DCB입니다. 도움말을 이용해 DCB 구
조체 안의 맴버를 보면 참 많은 것을 설정하는구나 느낄 겁니다.

typedef struct _DCB { // dcb
DWORD DCBlength; // DCB구조체의 크기
DWORD BaudRate; // 현재 보오 속도
// binary mode설정 1로 설정하면 binary mode가능
DWORD fBinary: 1;
// 패리티 검사 기능 유무
DWORD fParity: 1;
//CTS 지정 플러그 1이면 CTS가 1이 될 때까지 기다린다.
DWORD fOutxCtsFlow:1;
//DSR 지정 플러그 1이면 DSR이 1이 될 때 까지 기다린다.
DWORD fOutxDsrFlow:1;
//DTR 지정 플러그 DTR_CONTROL_DISBLE로 설정시 DTR이 OFF되고
// DTR_CONTROL_ENABLE 를 설정하면 DTR은 ON이된다.
DWORD fDtrControl:2;
// 이값이 1이면 DSR이 OFF동안 받은 데이터는 무시한다.
DWORD fDsrSensitivity:1;
//수신 버퍼가 꽉차있고 XoffChar 문자를 전송했을 경우
//전송 중단을 할것인가를 지정하는 플러그 들
DWORD fTXContinueOnXoff:1;
// 이값이 1이면 XoffChar문자 수신시 중단
DWORD fOutX: 1; // XON/XOFF out flow control
// 이값이 1이면 XoffChar문자는 수신 버퍼가 XoffLim바이트
// 안에 있을 경우 보내지고 XonChar 무자는 XonLim안에 있을 때
// 보내진다.
DWORD fInX: 1; // XON/XOFF in flow control
//이값이 1이고 fParity가 1이면 패리티 오류와 함께 수신된
// 바이트들은 ErrorChar멤버에 의해 지정된 문자로 대체
//된다.
DWORD fErrorChar: 1; // enable error replacement
//이값이 1이면 널값은 무시한다.
DWORD fNull: 1; // enable null stripping
//RTS는 이값이 RTS_CONTROL_DISABLE로 설정시 0이되고
// RTS_CONTROL_ENABLE로 설정될 때 ON이 된다.
DWORD fRtsControl:2; // RTS flow control
//이값이 1이면 오류가 발생하였을 때 읽기와 쓰기 작동이
//중단된다.
DWORD fAbortOnError:1; // abort reads/writes on error
DWORD fDummy2:17; // reserved
WORD wReserved; // not currently used
//XON 문자가 보내지기 전에 수신 버퍼에서 허용되는 최소 바이트
WORD XonLim; // transmit XON threshold
//XOFF문자가 보내지기전에 수신 버퍼에서 허용되는 사용가능한
//최소 바이트
WORD XoffLim; // transmit XOFF threshold
//포트에 의해 현재 사용되는 데이터 비스수
BYTE ByteSize; // number of bits/byte, 4-8
//패리티
BYTE Parity; // 0-4=no,odd,even,mark,space
//정지비트
BYTE StopBits; // 0,1,2 = 1, 1.5, 2
//XON,XOFF문자 지정
char XonChar; // Tx and Rx XON character
char XoffChar; // Tx and Rx XOFF character
//오류에 의해 전달된 문자 전환
char ErrorChar; // error replacement character
//binary 모드가 아닐 경우 데이터의 끝을 나타내는 문자
char EofChar; // end of input character
//이문자가 수신될 때 이벤트가 발생
char EvtChar; // received event character
WORD wReserved1; // reserved; do not use
} DCB;

위의 것을 전부 설정한다기보다 우리가 필요한 부분만 설정하면 나머지는 기본적으
로 정의된 값이 사용됩니다. 위의 DCB를 컴포트 파일 핸들러로 설정된 idCo- mDev
와 함께 GetCommState를 사용하여 기본적인 인자를 받습니다.

DCB dcb;
GetCommState( idComDev, &dcb ) ;

이제 DCB를 이용하여 이야기처럼 몇 가지는 간단하게 정의해 주어야 합니다.
dcb.BaudRate = CBR_14400;//전송 속도
dcb.ByteSize = 8 ;//데이터 비트
dcb.Parity = 0;//패리티 체크
dcb.StopBits = 0 ;//스톱비트

다음 이 DCB를 idComDev에 연결시킵니다.

SetCommState( idComDev, &dcb ) ;

포트에서 데이터를 읽고 있을 경우 다른 작업을 하는 것이 좋습니다. 이런 것을 비
동기라고 하지요. CreateFile 에서 FILE_FLAG_OVERLAPPED라는 OVERAPPED옵션을 설정
하면 이렇게 비동기가 됩니다. 이렇게 비동기가 되면 데이터를 주고 받는 구조체를
할당하여 이할당된 구조체에게 작업을 맏겨야 합니다.
이런 구조체가 바로 OVERLAPPED입니다.

OVERLAPPED osWrite, osRead ;

다음 이 구조체를 초기화하고

osWrite.Offset = 0 ;
osWrite.OffsetHigh = 0 ;
osRead.Offset = 0 ;
osRead.OffsetHigh = 0 ;

이벤트를 설정합니다.

osRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ) ;
osWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ) ;

이렇게 함으로써 COM 포트에의 접속이 끝났습니다.

 
데이터 쓰기
데이터를 쓰는 것은 파일에 쓰듯이 WriteFile 함수를 사용합니다.

WriteFile( idComDev, lpByte, dwBytesToWrite, &dwBytesWritten, &osWrite ) ;

첫번째 인자는 파일 핸들러이고, 두 번째 인자는 써야 할 데이터, 세 번째 인자는
써야 할 바이트의 수, 네 번째 인자는 써야 할 바이트수가 들어 있는 번지, 다섯 번
째 인자는 위에서 만든 osWrite입니다.

 
데이터 읽기
데이터를 읽는 것은 위의 데이터를 쓰는 함수와 비슷합니다. 함수명은 ReadFile입니
다.

ReadFile( idComDev, lpszBlock,dwLength, &dwLength, &osRead ) ;

 
컴포트 닫기
컴포트를 닫는 것은 파일 닫듯이 닫으면 됩니다.

CloseHandle( idComDev ) ;

다음 데이터 구조체를 만들었으니까 만든 구조체를 해제해 줍니다.

CloseHandle( osRead.hEvent ) ;
CloseHandle( osWrite.hEvent ) ;

 
데이터 큐
컴포트에서는 데이터가 어쩔 때는 1개씩, 어쩔 때는 수십 개씩 한꺼번에 들어옵니
다. 즉 여러 개가 들어올 경우와 한 개가 들어올 경우 등 여러 경우가 있다는 것이
죠. 물론 디바이스에도 4096 정도로 큐를 만들어 놓았으나 프로그램 제작자가 데이
터를 읽고 적절하게 컨버트해야 합니다. 한 가지 예를 든다면 컴포트에 "안녕하세요
[0x11번캐릭터][0x13번캐릭터]이곳은 천리안입니다" 라고 들어왔을 경우 0x11과
0x13은 개행 캐릭터입니다. 따라서, 화면에는
"안녕하세요
이곳은 천리안입니다"
이렇게 표시를 해주어야 합니다. 그런데 들어오는 대로 화면에 표시하면 위와 같이
표시하기가 힘들어집니다.
0x11다음 0x13이 안 오고 0x44가 올 수도 있지 않습니까? 즉 들어오는 뒤의 데이터
를 보고 앞의 데이터를 생각할 경우도 있다는 것입니다. 그렇기 때문에 데이터를 받
아 두는 큐가 필요하고 이 큐를 어떻게 사용할지는 독자들의 마음입니다.
본 장의 예제에서는 큐를 사용하지 않고 그냥 에디터 상자에 데이터를 들어오는 대
로 넣었습니다.

w COMM 클래스 만들기

통신은 매우 많이 쓰이는 분야 중 하나입니다. 또한 많이 쓰지 않아도 클래스로 만
들어 놓고 필요할 때 적절하게 쓰기 좋은 분야입니다. 컴포트를 열고, 읽고, 쓰고,
닫고 이 4가지 말고는 없기 때문이죠. 본 장에서 제작하는 클래스는 CComm입니다.
이 클래스에서는 위의 4가지 외에도 클래스에서 현재 윈도에 메시지를 보내는 함
수, 읽은 데이터를 보관하는 함수, 그 외 필요한 여러 가지 함수를 만들었습니다.

 

CComm 헤더
 

//Comm.h
//Rs232c를 하기 위한 클래스 헤더
#define MAXBLOCK 80
 
#define MAXPORTS 4
 
// Flow control flags

#define FC_DTRDSR 0x01
#define FC_RTSCTS 0x02
#define FC_XONXOFF 0x04

// ascii definitions

#define ASCII_BEL 0x07
#define ASCII_BS 0x08
#define ASCII_LF 0x0A
#define ASCII_CR 0x0D
#define ASCII_XON 0x11
#define ASCII_XOFF 0x13
#define WM_RECEIVEDATA WM_USER+1

// global stuff
 

// function prototypes (private)
 
/////////////////////////////////////////////////////////////////////////////
// CComm window

class CComm : public CObject
{

DECLARE_DYNCREATE( CComm )
public:
HANDLE idComDev ;//컴포트 디바이스 연결 핸들
BOOL fConnected;//컴포트가 연결되면 1로 설정
BYTE abIn[ MAXBLOCK + 1] ;//컴포트에서 들어오는 데이터
HWND m_hwnd;//메시지를 전달할 윈도 플래그

// Construction
public:
CComm( );
void SetXonOff(BOOL chk);//XonOff 설정
//컴포트를 설정함.
void SetComPort(int port,DWORD rate,BYTE bytesize,BYTE stop,BYTE parity);
//Dtr Rts 설정
void SetDtrRts(BYTE chk);
//comm 포트를 만든다.
BOOL CreateCommInfo();
//comm 포트를 해제한다.
BOOL DestroyComm();
//컴포트에서 데이터를 받는다.
int ReadCommBlock( LPSTR, int ) ;
//컴포트에 데이터를 넣는다.
BOOL WriteCommBlock( LPSTR, DWORD);
BOOL OpenComPort( ) ;//컴포트를 열고 연결을 시도한다.
//포트를 연결한다.
BOOL SetupConnection( ) ;
//연결을 해제한다.
BOOL CloseConnection( ) ;
//읽은 데이터를 버퍼에 저장한다.
void SetReadData(LPSTR data);
//메시지를 보낼 윈도 플래그를 설정한다.
void SetHwnd(HWND hwnd);
 
// Attributes
public:
BYTE bPort;
BOOL fXonXoff;

BYTE bByteSize, bFlowCtrl, bParity, bStopBits ;
DWORD dwBaudRate ;
HANDLE hWatchThread;
HWND hTermWnd ;
DWORD dwThreadID ;
OVERLAPPED osWrite, osRead ;

// Operations
public:

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CComm)
//}}AFX_VIRTUAL

// Implementation
public:
virtual ~CComm();

// Generated message map functions
// DECLARE_MESSAGE_MAP()
protected:
};
 
/////////////////////////////////////////////////////////////////////////////

 

CComm 소스
 

//Comm.cpp Rs232c 통신을 하기 위한 클래스
#include "stdafx.h"
#include "comm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

IMPLEMENT_DYNCREATE(CComm, CObject)
 

CComm::CComm( )
{
idComDev=NULL;
bFlowCtrl= FC_XONXOFF ;
fConnected = FALSE ;
}

CComm::~CComm( )
{
DestroyComm();
}

//BEGIN_MESSAGE_MAP(CComm, CObject)
//{{AFX_MSG_MAP(CComm)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
//END_MESSAGE_MAP()
 
/////////////////////////////////////////////////////////////////////////////
// CComm message handlers
//CommWatchProc()
//통신을 하는 프로시저, 즉 데이터가 들어왔을 때 감시하는
//루틴. 본 루틴은 OpenComPort 함수 실행시 프로시저로 연결됨.
//OpenComPort 함수 참조
DWORD CommWatchProc(LPVOID lpData)
{
DWORD dwEvtMask ;
OVERLAPPED os ;
CComm* npComm = (CComm*) lpData ;
char InData[MAXBLOCK + 1];
int nLength ;
//idCommDev라는 핸들에 아무런 컴포트가 안 붙어 있으면
//에러 리턴
if ( npComm == NULL ||
!npComm-IsKindOf( RUNTIME_CLASS( CComm ) ) )
return (DWORD)(-1);

memset( &os, 0, sizeof( OVERLAPPED ) ) ;
 
os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset

NULL ) ; // no name
if ( os.hEvent == NULL )
{
MessageBox( NULL, "Failed to create event for thread!", "comm Error!",
MB_ICONEXCLAMATION | MB_OK ) ;
return ( FALSE ) ;
}

if (!SetCommMask(npComm-idComDev, EV_RXCHAR ))
return ( FALSE ) ;

while (npComm-fConnected )
{
dwEvtMask = 0 ;

WaitCommEvent(npComm-idComDev, &dwEvtMask, NULL );

if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
{

do
{
memset(InData,0,80);
if (nLength = npComm-ReadCommBlock((LPSTR) InData, MAXBLOCK ))
{
npComm-SetReadData(InData);
//이곳에서 데이터를 받는다.
}
}
while ( nLength  0 ) ;
}
}
 
CloseHandle( os.hEvent ) ;
 
return( TRUE ) ;

}
//데이터를 읽고 데이터를 읽었다는
//메시지를 리턴한다.
void CComm::SetReadData(LPSTR data)
{

lstrcpy((LPSTR)abIn,(LPSTR)data);
//ConverData
//설정된 윈도에 WM_RECEIVEDATA 메시지를
//날려 주어 현재 데이터가 들어왔다는 것을
//알려준다.
SendMessage(m_hwnd,WM_RECEIVEDATA,0,0);
}
//메시지를 전달할 hwnd 설정
void CComm::SetHwnd(HWND hwnd)
{
m_hwnd=hwnd;
}
//컴포트를 설정한다.
void CComm::SetComPort(int port,DWORD rate,BYTE bytesize,BYTE stop,BYTE
parity)
{
bPort=port;
dwBaudRate=rate;
bByteSize=bytesize;
bStopBits=stop;
bParity=parity;
}
//XonOff, 즉 리턴값 더블 설정
void CComm::SetXonOff(BOOL chk)
{
fXonXoff=chk;
}
void CComm::SetDtrRts(BYTE chk)
{
bFlowCtrl=chk;
}
//컴포트 정보를 만든다.
//이것을 만들 때 이전에
// SetComPort(); - SetXonOff() -SetDtrRts()한 다음 설정한다.
BOOL CComm::CreateCommInfo()
{
 
osWrite.Offset = 0 ;
osWrite.OffsetHigh = 0 ;
osRead.Offset = 0 ;
osRead.OffsetHigh = 0 ;

//이벤트 창구 설정

osRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ) ;
if (osRead.hEvent == NULL)
{
return FALSE ;
}
osWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ) ;
if (NULL == osWrite.hEvent)
{
CloseHandle( osRead.hEvent ) ;
return FALSE;
}
 
return TRUE ;

}

//컴포트를 열고 연결을 시도한다.
//OpenComport()
BOOL CComm::OpenComPort( )
{
char szPort[ 15 ] ;
BOOL fRetVal ;
COMMTIMEOUTS CommTimeOuts ;
 
if (bPort  MAXPORTS)
lstrcpy( szPort, "\\.\TELNET" ) ;
else
wsprintf( szPort, "COM%d", bPort ) ;

// COMM device를 파일 형식으로 연결한다.

if ((idComDev =
CreateFile( szPort, GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security attrs
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_OVERLAPPED, // overlapped I/O
NULL )) == (HANDLE) -1 )
return ( FALSE ) ;
else
{

//컴포트에서 데이터를 교환하는 방법을 char 단위를 기본으로 설정
//하자.
SetCommMask( idComDev, EV_RXCHAR ) ;
SetupComm( idComDev, 4096, 4096 ) ;
//디바이스에 쓰레기가 있을지 모르니까 깨끗이 청소를 하자.
PurgeComm( idComDev, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
 
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;
CommTimeOuts.ReadTotalTimeoutConstant = 1000 ;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0 ;
CommTimeOuts.WriteTotalTimeoutConstant = 1000 ;
SetCommTimeouts( idComDev, &CommTimeOuts ) ;
}

fRetVal = SetupConnection() ;

if (fRetVal)//연결이 되었다면 fRetVal TRUE이므로
{
fConnected = TRUE ;//연결되었다고 말해 줌.
//프로시저를 CommWatchProc에 연결하니까 나중에 데이터가 왔다갔다
//하면 모든 내용은 CommWatchProc가 담당한다.
AfxBeginThread((AFX_THREADPROC)CommWatchProc,(LPVOID)this);
}
else
{
fConnected = FALSE ;
CloseHandle( idComDev) ;
}

return ( fRetVal ) ;

}

//파일로 설정된 컴포트와 실질 포트를 연결시킨다.
//SetupConnection 이전에 CreateComPort를 해주어야 한다.
BOOL CComm::SetupConnection()
{
BOOL fRetVal ;
BYTE bSet ;
DCB dcb ;
 
dcb.DCBlength = sizeof( DCB ) ;

GetCommState( idComDev, &dcb ) ;//dcb의 기본값을 받는다.
 
//이 부분을 수정해야 한다.
dcb.BaudRate = dwBaudRate;//전송 속도
dcb.ByteSize = bByteSize ;//데이터 비트
dcb.Parity = bParity;//패리티 체크
dcb.StopBits = bStopBits;//스톱 비트

dcb.fOutxDsrFlow =0 ;//Dsr Flow
dcb.fDtrControl = DTR_CONTROL_ENABLE ;//Dtr Control
dcb.fOutxCtsFlow = 0 ;//Cts Flow
dcb.fRtsControl = RTS_CONTROL_ENABLE ; //Ctr Control
dcb.fInX = dcb.fOutX = 1 ; //XON/XOFF 관한 것
dcb.XonChar = ASCII_XON ;
dcb.XoffChar = ASCII_XOFF ;
dcb.XonLim = 100 ;
dcb.XoffLim = 100 ;
dcb.fBinary = TRUE ;
dcb.fParity = TRUE ;
 

dcb.fBinary = TRUE ;
dcb.fParity = TRUE ;

fRetVal = SetCommState( idComDev, &dcb ) ; //변경된 Dcb 설정

return ( fRetVal ) ;

}

//컴포트로부터 데이터를 읽는다.
int CComm::ReadCommBlock(LPSTR lpszBlock, int nMaxLength )
{
BOOL fReadStat ;
COMSTAT ComStat ;
DWORD dwErrorFlags;
DWORD dwLength;

// only try to read number of bytes in queue
ClearCommError( idComDev, &dwErrorFlags, &ComStat ) ;

dwLength = min( (DWORD) nMaxLength, ComStat.cbInQue ) ;

if (dwLength  0)
{
fReadStat = ReadFile( idComDev, lpszBlock,
dwLength, &dwLength, &osRead ) ;
if (!fReadStat)
{
//이곳에 에러를 넣다.
//즉 ReadFile했을 때 데이터가 제대로 안 나오면 fReadState에 여러
//에러 코드를 리턴한다. 이 때 복구할 수 있으면 좋지만 실질적인
//복구가 불가능하다. 따라서, 재송출을 해달라는 메시지를 해주는 것이
//좋다.
}
}

return ( dwLength ) ;

}
//컴포트를 완전히 해제한다.

BOOL CComm::DestroyComm()
{
 
if (fConnected)
CloseConnection( ) ;
 
CloseHandle( osRead.hEvent ) ;
CloseHandle( osWrite.hEvent ) ;

return ( TRUE ) ;

}

//연결을 닫는다.
BOOL CComm::CloseConnection()
{

// set connected flag to FALSE

fConnected = FALSE ;
 
// disable event notification and wait for thread
// to halt

SetCommMask( idComDev, 0 ) ;
 

EscapeCommFunction( idComDev, CLRDTR ) ;
 
PurgeComm( idComDev, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
CloseHandle( idComDev ) ;
return ( TRUE ) ;

}
 

BOOL CComm::WriteCommBlock( LPSTR lpByte , DWORD dwBytesToWrite)
{

BOOL fWriteStat ;
DWORD dwBytesWritten ;
 
fWriteStat = WriteFile( idComDev, lpByte, dwBytesToWrite,
&dwBytesWritten, &osWrite ) ;
 
if (!fWriteStat)
{
//컴포트에 데이터를 제대로 써넣지 못했을 경우이다.
//이 때는 어떻게 할까. 그것은 사용자 마음이다.
//다시 보내고 싶으면 재귀송출을 하면 된다.
//그러나 무한 루프를 돌 수 있다는 점을 주의하자.
}
return ( TRUE ) ;

}

 
e 통신 프로그램 예제 CommEx 프로그램

CommEx 프로그램은 위에서 만든 CComm 클래스를 사용하여 통신을 하는 아주 간단한
통신 프로그램 예제입니다.
그림 1은 CommEx을 실행한 모습입니다. FormView로 작성하여 에디터 상자에는 현재
포트에서 읽히는 데이터를 출력하고 밑의 콤보 상자에서는 컴포트에 데이터를 출력
하게끔 했습니다.
 

 
 
 그림 1
 
 

 
CommEx 프로그램 실행 모습
 
 

밑의 콤보 상자에서 "Atz"를 치고 "Atdt 36792000"하여 천리안에 접속을 했을 때 출
력되는 화면입니다. 출력되는 데이터에 여러 기호키들이 옆으로 보일 것입니다. 본
프로그램은 단지 컴포트에서 데이터를 입력받아 출력하는 기능만 만들었기에 통신
라인에서 들어오는 특수 기호들이 그대로 화면에 출력됩니다.
이 부분은 독자 여러분들이 수정하여 새로운 프로그램으로 만들어 보기 바랍니다.
본 프로그램을 제작한 부분에 대해서는 뷰 부분의 소스만 기재합니다. 전에 모두
다 설명한 내용이므로 소스만 읽어 보아도 이해가 될 것입니다.

 

프로그램 소스
 
// CommExView.h : interface of the CCommExView class
//
/////////////////////////////////////////////////////////////////////////////
#include "mycombo.h"
#include "comm.h"

#if !defined
(AFX_COMMEXVIEW_H__C930616E_474D_11D1_9A0C_0000E81C79AB__INCLUDED_)
#define AFX_COMMEXVIEW_H__C930616E_474D_11D1_9A0C_0000E81C79AB__INCLUDED_

#if _MSC_VER = 1000
#pragma once
#endif // _MSC_VER = 1000

class CCommExView : public CFormView
{
protected: // create from serialization only
CCommExView();
DECLARE_DYNCREATE(CCommExView)

public:
//{{AFX_DATA(CCommExView)
enum{ IDD = IDD_COMMEX_FORM };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA

// Attributes
public:
CCommExDoc* Getdoc-ument();
CMyCombo m_pComboBox;
CString m_strEdit;
//컴 클래스
CComm m_pComm;

// Operations
public:

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CCommExView)
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnPrint(CDC* pDC, CPrintInfo*);
//}}AFX_VIRTUAL

// Implementation
public:
virtual ~CCommExView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
//{{AFX_MSG(CCommExView)
afx_msg void OnSelchangeCombo1();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnClose();
//}}AFX_MSG
afx_msg LONG OnReceiveData(UINT,LONG);
DECLARE_MESSAGE_MAP()
};

#ifndef _DEBUG // debug version in CommExView.cpp
inline CCommExDoc* CCommExView::Getdoc-ument()
{ return (CCommExDoc*)m_pdoc-ument; }
#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately
before the previous line.

#endif // !defined
(AFX_COMMEXVIEW_H__C930616E_474D_11D1_9A0C_0000E81C79AB__INCLUDED_)
 
// CommExView.cpp : implementation of the CCommExView class
//

#include "stdafx.h"
#include "CommEx.h"

#include "CommExDoc.h"
#include "CommExView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CCommExView

IMPLEMENT_DYNCREATE(CCommExView, CFormView)

BEGIN_MESSAGE_MAP(CCommExView, CFormView)
//{{AFX_MSG_MAP(CCommExView)
ON_CBN_SELCHANGE(IDC_COMBO1, OnSelchangeCombo1)
ON_WM_CREATE()
ON_WM_CHAR()
ON_WM_CLOSE()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CFormView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CFormView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CFormView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCommExView construction/destruction

CCommExView::CCommExView()
: CFormView(CCommExView::IDD)
{
//{{AFX_DATA_INIT(CCommExView)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// TODO: add construction code here

}

CCommExView::~CCommExView()
{
}

void CCommExView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCommExView)
DDX_Control(pDX,IDC_COMBO1,m_pComboBox);
DDX_Text(pDX,IDC_EDIT1,m_strEdit);
//}}AFX_DATA_MAP
}

BOOL CCommExView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs

return CFormView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CCommExView printing

BOOL CCommExView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}

void CCommExView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}

void CCommExView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}

void CCommExView::OnPrint(CDC* pDC, CPrintInfo*)
{
// TODO: add code to print the controls
}

/////////////////////////////////////////////////////////////////////////////
// CCommExView diagnostics

#ifdef _DEBUG
void CCommExView::AssertValid() const
{
CFormView::AssertValid();
}

void CCommExView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}

CCommExDoc* CCommExView::Getdoc-ument() // non-debug version is inline
{
ASSERT(m_pdoc-ument-IsKindOf(RUNTIME_CLASS(CCommExDoc)));
return (CCommExDoc*)m_pdoc-ument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CCommExView message handlers

int CCommExView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFormView::OnCreate(lpCreateStruct) == -1)
return -1;
m_strEdit="AtzrnOk";
//콤보박스에서 키를 누르면 그 키값이
//본 윈도우에 전달할수 있도록 HWND를 전달한다.
m_pComboBox.SetHwnd(this-m_hWnd);
//컴포트를 맞춘다.
m_pComm.SetComPort(4,28800,8,0,0);
//컴포트의 정보를 만든다.
m_pComm.CreateCommInfo();
//컴토포트를 연다
m_pComm.OpenComPort();
//컴포트에서 이벤트가 생기면 현재 윈도우로 메세지를
//넘길수 있도록 HWND를 넘긴다.
m_pComm.SetHwnd(this-m_hWnd);
return 0;
}

void CCommExView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
//키를 누르면 크 키값을 컴포트에 넘긴다.
m_pComm.WriteCommBlock((LPSTR)&nChar ,1);
CFormView::OnChar(nChar, nRepCnt, nFlags);
}
LONG CCommExView::OnReceiveData(UINT WParam,LONG LParam)
{
//컴포트에서 데이타를 받으면 받은 데이타를
//Edit 박스에 넘긴다.
UpdateData(TRUE);
m_strEdit+=(LPSTR)m_pComm.abIn;
UpdateData(FALSE);
return TRUE;
}

void CCommExView::OnClose()
{
//컴포트를 닫는다.
m_pComm.DestroyComm();
CFormView::OnClose();
}

void CCommExView::OnSelchangeCombo1()
{
}

'Win32 API / MFC' 카테고리의 다른 글

[MFC] CWnd 클래스  (0) 2010.04.20
Extern "C"  (0) 2009.11.03
헝가리언 표기법  (0) 2009.05.08
코드로 lib 파일 추가하기  (0) 2009.05.08
Windows Data Type  (0) 2009.05.08

  알맞은 조건에 맞는 객체만을 생성해서 사용하는 방법에는 어떤 것이 있을까?

문제
해당 장비에 맞는 제어 프로그램을 만들어야 한다. 이 제어 프로그램에는 데이터를 송/수신 하는 부분과 송수신된 데이터를 파싱(parsing)하는 부분, 그리고 파싱된 데이터를 처리하는 부분으로 나뉜다. 현재에는 A장비와, B장비만 제어한다. 하지만 추후에 제어 되는 장비가 더 추가되거나 제거될 수 가 있다.
DataSender : 데이터를 송신하는 객체
DataReceiver : 데이터를 수신하는 객체
DataParser : 데이터를 파싱하는 객체
DataProc : 파싱된 데이터를 처리하는 객체  


해결1
프로그램 곳곳에 조건 비교 문장을 넣어 조건에 해당하는 객체를 생성한다(조건 비교 방식).

if(A장비인가?)
{
EquipADataSender eaSender = new EquipADataSender();
EquipADataReceiver eaReceiver = new EquipADataReceiver();
EquipADataParser eaParser = EquipADataParser();
EquipADataProc eaProc = EquipADataProc();
}
else if(B 장비인가?)
{
EquipBDataSender ebSender = new EquipBDataSender ();
EquipBDataReceiver ebReceiver = new EquipBDataReceiver ();
EquipBDataParser ebParser = EquipBDataParser ();
EquipBDataProc ebProc = EquipBDataProc ();
}
// 장비 C , 장비 B 가 추가 된다면? 계속해서 조건 문을 이어 나가야 한다.
// 또한 소스 코드 여러 부분에 걸쳐 이런 조건 문을 사용할 가능성이 매우 높다. 

 해결1에 대한 문제점
프로그램 곳곳에 조건 비교 문장이 존재하기 때문에, 새로운 조건을 추가할 일이 발생하면 프로그램 전체를 찾아 다니며 일일이 수정해야 하는 커다란 문제가 생긴다. 이는 곧 프로그램 전체를 다시 개발하는 것과 비슷한 노력이나 비용이 들 수 있음을 의미한다. 프로그램 전체를 찾아 다니며 비교 문장이 존재하는 곳을 모두 수정해야 할 것이다. 조건 비교 방식의 가장 큰 단점은 비교 문장이 프로그램 전역에 퍼져 있을 경우, 이에 대한 변경 비용이 많이 든다는 것이다. 문제의 원인은 변경될 가능성이 높은 코드(공통된 기능을 하는 코드)들이 프로그램 전역 곳곳에 퍼져 있다는 것이다. 이 문제를 해결하기 위해서는 변경될 가능성이 높은 코드들을 한 곳에 모아, 변경이 필요할 경우 그 부분만 고치면 원하는 작업을 수행할 수 있게 만들어 주는 것이다. 이처럼 객체 지향 설계의 핵심적인 접근 방법은 바로 변경이 예상되는 부분을 한 곳에 모아 관리 하도록 하는 것이다. 


해결2(Factory Pattern)
 프로그램 전역에 조건 비교 문장 없이 원하는 객체를 생성하기 위해서는 객체 생성을 전담하는 클래스(Factory class)를 활용하면 된다. 이는 시스템 환경에 따른 조건 비교 문장이 Factory 클래스 내부에만 존재하기 때문에 새로운 조건이 추가되거나 이전 조건을 변경시켜야 할 경우 프로그램 전체를 찾아 다니며 수정 해야 하는 부담을 덜 수 있다. 이렇게 객체 생성을 Factory class를 활용하는 방식을 Factory Pattern이라고 한다.





샘플 소스 (C#)

        static void Main(string[] args)
        {
            EquipFactory equipFactory = new EquipFactory();  // 팩토리 클래스 생성
            equipFactory.EEquipType = EEquipType.EquipA;   // 장비 선택

// Factory에서 해당 객체 생성
// 장비 종류에 관계 없이 동일한 방법으로 생성한다.

IDataSender sender = equipFactory.CreateDataSender();
            IDataReceiver receiver = equipFactory.CreateDataReceiver();
            IDataParser parser = equipFactory.CreateDataParser();
            IDataProc proc = equipFactory.CreateDataProc();

sender.Send();
            receiver.Receive();
            parser.Parse();
            proc.Proc();
        }

Visual Studio 2008, C#

해결2에 대한 문제점
 여전히 Factory 클래스 내의 소스코드에는 비교 문장이 존재한다는 것이다. 새로운 조건을 추가할 경우 이전 소스 코드를 면밀히 분석해서 수정해야 한다. 이는 새로운 조건의 추가를 이전 소스 코드와 무관하게 독립적으로 수행할 수 없다는 의미이다(이
전 소스 코드와 독립적으로 새로운 부분을 추가, 수정하기가 힘들다).


해결 3 (Abstract Factory Pattern)
 해결2에서 EquipFactory 클래스 내부에는 장비 종류에 따는 객체를 생성할 수 있게 조건문이 존재한다.
ex) EquipFactory의 CreateDataSender 메소드
public IDataSender CreateDataSender()
{
      switch (_eEquipType) // 장비에 따른 객체 생성
      {
            case EEquipType.EquipA: return new EquipADataSender();
            case EEquipType.EquipB: return new EquipBDataSender();
       }

       return null;
 }

 프로그램이 커지면, 이런 조건문 때문에 이전 코드와 독립적으로 새로운 부분을 추가, 수정하기가 힘들어 진다. 이를 해결 하기 위해서는 장비 별로 Factory 클래스를 생성한다. 그 후 장비 별 Factory 클래스에서 공통 메소드들을 뽑아내어 공통 인터페이스(IEquipFactory)로 만든다. 장비 별 Factory 클래스에서 이 공통 인터페이스를 상속 받아 구현하면 조건문을 사용하지 않고도 문제를 해결할 수 있다. 장비를 추가하거나 삭제할 경우, 이전 소스 코드를 수정하지 않고도 독립적으로 변경이 가능하다. 이런 방식을 Abstract Factory Pattern이라고 한다.






샘플 소스 (C#)

          IEquipFactory equipFactory = null;
            EEquipType equipType = EEquipType.EquipB;

// 처음 한번은 어떤 장비를 생성할 것인지 구별하기 위해서 조건문이 사용되었다.
// 하지만 Factory 클래스들은 장비 별로 독립적으로 구현되어 있다.
            switch (equipType)
            {
                case EEquipType.EquipA: equipFactory = new EquipAFactory(); break;
                case EEquipType.EquipB: equipFactory = new EquipBFactory(); break;
            }

            if (equipFactory == null) return;
           
            IDataSender sender = equipFactory.CreateDataSender();
            IDataReceiver receiver = equipFactory.CreateDataReceiver();
            IDataParser parser = equipFactory.CreateDataParser();
            IDataProc proc = equipFactory.CreateDataProc();

            sender.Send();
            receiver.Receive();
            parser.Parse();
            proc.Proc();


Visual Studio 2008, C#

1. 상위 클래스가 여러 하위 클래스들의 공통된 데이터를 추출해서 관리하도록 만든다.
2. 상위 클래스 전반적인 자료형을 대표하면서 외부에 공통된 인터페이스를 제공하고, 하위 클래스들은 각기 다른 구현 내용을 가지도록 만들어 준다.

 이 때 2번의 목적으로 클래스 상속을 이용하게 되면 상속 구조 내의 클래스를 사용하는 입장에서는 자료형과 인터페이스는 최상위 클래스를 참조하면서 구체적으로 실행되는 구현 내용은 다형성에 따라 결정되도록 만들 수 있다. 따라서 새로운 구현 내용이 추가된다 하더라도 새로운 하위 클래스만 정의해서 사용하면 기존 소스코드의 변경을 최소화하면서 새로운 구현 내용을 적용할 수 있게 되는 것이다.

'디자인 패턴' 카테고리의 다른 글

Abstract Factory Pattern  (0) 2009.06.09
Template Method Pattern [C#]  (0) 2009.05.28

서울반도체 신세길 회장의 경영메모
성공을 만드는 4P 프로그램
  
1. Pratice(연습)
연습을 많이 할 수록 성공이 나타날 확률은 높아진다. 연습은 성공을 기술로 바꾸어준다.

2. Persistence(끈기)
마지막 1%에 올인하는 끈기가 성공을 창조한다.

3. Preparation(준비)
매사에 철저한 준비가 성공을 만든다.

4. Positive Outlook(긍정적인 전망)
성공한 경험을 기억하라.
성공할 것이라 믿는다면 성공한다.

 

'It`s me.' 카테고리의 다른 글

경래 군생활 1주차  (1) 2009.06.22
전주 35사단  (2) 2009.06.14
그리운 사람.  (0) 2009.05.26
어학연수에 대한 생각  (1) 2009.05.19
인도에 부는 한국어 열풍.  (3) 2009.04.29

sprintf(str, "AT*KTF*MOREQ=0,%s,%s,4098,%s%c", 보내고 싶은 번호,보내는 번호, 메시지, '\r');
str를 잡힌 모뎀 포트로 내보내면 잘 보내면 'OK'를 그렇지 않으면 'ERROR'를 보낸다.
명령어 형식은 폰의 버전마다 종류마다 다를 수 있습니다.

AT*SKT*MOREQ=0,%s,%s,4098,%s%c
AT*LGT*MOREQ=0,%s,%s,4098,%s%c
AT*KTF*MOREQ=0,%s,%s,4098,%s%c


파이썬 소스 예제)
※다른 언어로 구현할 경우에는, 시리얼 전송부분만 따로 구현하고 아래의 소스에서 사용된 AT 명령어을 그대로 사용하면 된다.

import serial
 
ser = serial.Serial('/dev/ttyS0', 115200, timeout=1) # 시리얼포트 연결
ser.write("AT*ESMS=1\r") # 문자보내기 기능을 활성화 한다.
serial_result = ser.readlines()
ser.write("ATE0\r")
serial_result = ser.readlines()
ser.write("ATV1\r")
serial_result = ser.readlines()
ser.write("AT+CHV\r") # 호연결 끊기
serial_result = ser.readlines()
ser.write("AT+CSQ?\r") # 장비 테스트
serial_result = ser.readlines()
ser.write("AT+CDV *0661\r") # 호에 연결
serial_result = ser.readlines()
serial_result = ser.readlines()
ser.write("AT*MOREQ 0,0113872176,0162348765,4098,첫번째문자보내기\r") # 첫번째문자 보내기
serial_result = ser.readlines()
ser.write("AT*MOREQ 1,0113872176,0162348765,4098,두번째문자보내기\r") # 두번째문자 보내기
serial_result = ser.readlines()
ser.write("AT+CHV\r") # 호연결 끊기
serial_result = ser.readlines()
ser.close() # 시리얼포트 끊기



Serial port 캡처

SMS을 보낼 때 사용되는 AT명령어를 알기 위해서는 통신사에서 제공하는 프로그램을 설치한다. 그 후 핸드폰을 연결한 후 SMS을 보낼 떄 주고 받는 내용을 시리얼 포트에서 캡쳐해내야 한다. 이때 사용하는 프로그램이 Agg Software의 Advanced Serial Port Monitor이다. 아래의 사이트에서 트라이얼 버전을 다운로드하여 사용한다(일정 기간 동안만 사용 가능).

http://www.aggsoft.com/serial-port-monitor/



AT Command 참고

 

MySQL Server 5.1 설치편
http://ocplay.tistory.com/41

 

1. MySQL Connector/Net 6.0 다운로드

C#에서 MySQL을 사용하기 위해서는 Connecter driver가 필요하다. MySQL Connector/Net 6.0을 설치함으로써 닷넷 프레임워크에서 MySQL을 사용 할 수 있다.

다운로드 URL : http://dev.mysql.com/get/Downloads/Connector-Net/mysql-connector-net-6.0.3.zip/from/pick#mirrors

URL이 바뀌었을 경우 MySQL 홈페이지에서 다운 받으면 된다.

 

2. MySQL Connector/Net 6.0 설치하기


Next버튼을 누른다.

 


Complete 버튼을 누른다.

 


Install 버튼을 누른다.

 


설치중인 화면이다.


Finish버튼을 누르면 설치가 완료된다.

 

3. C#과 MySQL 연동 샘플 소스

사용환경 : Visual Studio 2005(C#)

새로운 콘솔 프로젝트를 생성한다. 그리고 MySQL.Data를 참조 추가한다.

 

 


using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using MySql.Data;
using MySql.Data.MySqlClient;

namespace MySQL_Test
{

class Program
{

static void Main(string[] args)
{

string connStr = String.Format("server=localhost;user id=root; password=1339; database=test"); MySqlConnection conn = new MySqlConnection(connStr);
conn = new MySqlConnection(connStr); 

try
{

conn.Open();
Console.WriteLine("MySQL DB 연결");

}
catch { }
finally
{

conn.Close();
Console.WriteLine("MySQL DB 연결 닫기");  

}

}

}

}

 



결과
 

'닷넷 프레임워크' 카테고리의 다른 글

Creating a splash screen  (0) 2009.07.15
DataGridView 소개  (1) 2009.07.13
Thread 상태 전이도  (0) 2009.05.20
wav 파일 재생하기  (0) 2009.04.29
랜덤 파일명 생성하기  (1) 2009.04.29

 

1. MySQL 5.1.34 다운로드

http://www.mysql.com/ 에서 MySQL 최신 버전을 다운받는다. 여기서는 MySQL Community Server 5.1.34 (Windows MSI Installer x86, 97.6MB) 으로 다운 받았다.

http://dev.mysql.com/get/Downloads/MySQL-5.1/mysql-5.1.34-win32.msi/from/http://mysql.byungsoo.net/

URL이 바뀌었을 경우 MySQL 홈페이지에서 다운 받으면 된다.

 

2. MySQL 5.1.34 설치

Next 버튼을 누른다.

 


Complete을 선택하고 Next 버튼을 누른다.

 


Install 버튼을 누른다.

 


설치중

 


설치가 끝나고 위의 창이 뜰 경우 Next 버튼을 누른다.

 


Next버튼을 누른다.

 


Configure the MySQL Server now를 체크하고 Finish 버튼을 누른다.

 


Next버튼을 누른다.

 


Detailed Configuration을 선택하고, Next버튼을 누른다.

 


Developer Machine을 체크하고, Next 버튼을 누른다.

 


Multifunctional Database를 체크하고, Next 버튼을 누른다.

 


Next버튼을 누른다.

 


Next 버튼을 누른다.

 


Add firewall exception for this port를 체크하고, Next버튼을 누른다.

 


Standard Character Set을 체크하고, Next버튼을 누른다.

 


Include Bin Directory in Windows PATH를 체크하고, Next버튼을 누른다.

 

비밀번호를 입력하고, Next버튼을 누른다.

 


Excute버튼을 누르고, 설정이 끝나면 위의 화면이 뜬다. 이때 Finish 버튼을 누르면 MySQL 설치가 끝난다.

 

3. MySQL 사용하기


윈도우키 à 모든 프로그램 à MySQL à MySQL Server 5.1 à MySQL CommandLine Client 를 실행한다.

 


MySQL CommandLine Client 프로그램이 실행되면, 설치할 때 할 때 입력한 Root 패스워드를 입력한다. 로그인이 성공 되면 "mysql>" 이라는 프롬프트가 나타난다.

이때 "show databases;" 를 입력해보자. 위의 그림처럼 나오면 성공적으로 MySQL Sever가 설치가 되었다. "Mysql>" 프롬프트에 SQL 쿼리를 입력하면 결과가 출력된다.

 전반적인 처리 과정이 동일하고, 세부적인 구현만 다소 다른 경우 서로 독립된 클래스 형태로 프로그램을 구현하게 되면 똑같은 프로그램을 반복해서 구현해야 하는 문제가 발생한다. 이렇게 구현된 프로그램은 유지, 보수 시에도 동일한 수정 사항을 반복 적용해야 되는 문제가 있다.

해결 : 동일한 처리 과정에 해당하는 모듈은 하나로 합쳐서 작성, 관리하고 서로 다른 부분은 각자의 자식 클래스에서 구현하게 함으로써 구현에 따른 부담도 줄이고, 동일한 모듈을 반복해서 수정해야 하는 문제도 없앨 수 있다(클래스 상속 관계를 이용).

클래스에 상관없이 동일한 처리 과정을 수행하는 맴버 함수는 상위 클래스에만 정의한다. 이는 클래스 상속 관계의 특성 상 상위 클래스에 정의된 맴버 함수는 하위 클래스에서도 사용할 수 있기 때문이다. 클래스 마다 구현 내용이 달라져야 하는 모듈의 경우에는 클래스 상속 관계에서 Overriding을 활용해서 상위 클래스에서 정의한 모듈을 하위 클래스에서 재정의 한다. 이 경우 하위 클래스 객체에 대해 해당 모듈이 호출되면 다형성 규칙에 의해 상위 클래스에서 정의한 모듈이 아닌 하위 클래스에서 정의한 모듈이 불려지게 된다.

이처럼 클래스 상속 관계를 이용하면 구체적인 구현은 다르나 큰 틀에서 알고리즘의 기본 골격이 동일한 경우, 동일한 기본 골격을 상위 클래스에서 하나의 모듈로 작성, 관리할 수 있게 되는데 이를 Template Method라고 한다. Template Method를 포함하는 클래스 구조를 Template Method 패턴이라고 한다.

사용 예제
요구사항 : 오피스 프로그램을 제작하는데 한글 문서(hwp), MSWORD 문서(doc)를 저장하는 기능을 구현해야 한다. 추후에 저장을 할 수 있는 문서 포맷이 늘어 날 수 있다.

문서를 저장하는 순서
step1. 문서를 연다.
step2. 문서를 저장한다.
step3. 문서를 닫는다.

소스 코드

using System;
using System.Collections.Generic;
using System.Text;
namespace TemplateMethodPattern
{
    class Document
    {
        // template method
        // 문서 파일 저장
        public bool DocSave()
        {
            // step1. 문서를 연다.
            if (!DocFileOpen()) return false;
            // step2. 문서를 저장한다.
            if (!DocFileSave()) return false;
            // step3. 문서를 닫는다.
            if (!DocFileClose()) return false;
            // 저장 성공
            return true;
        }
        protected virtual bool DocFileOpen() { return true; }
        protected virtual bool DocFileSave() { return true; }
        protected virtual bool DocFileClose() { return true; }
    }
    class HWPDocument : Document
    {
        protected override bool DocFileOpen()
        {
            // todo : HWP 문서 열기 처리 로직
            Console.WriteLine("한글 문서 열기.");
            return true;
        }
        protected override bool DocFileSave()
        {
            // todo : HWP 문서 저장 처리 로직
            Console.WriteLine("한글 문서 저장.");
            return true;
        }
        protected override bool DocFileClose()
        {
            // todo : HWP 문서 닫기 처리 로직
            Console.WriteLine("한글 문서 닫기.");
            return true;
        }
    }
    class MSWORDDocument : Document
    {
        protected override bool DocFileOpen()
        {
            // todo : MS Word 문서 열기 처리 로직
            Console.WriteLine("MS word 문서 열기.");
            return true;
        }
        protected override bool DocFileSave()
        {
            // todo : MS Word 문서 저장 처리 로직
            Console.WriteLine("MS word 문서 저장.");
            return true;
        }
        protected override bool DocFileClose()
        {
            // todo : MS Word 문서 닫기 처리 로직
            Console.WriteLine("MS word 문서 닫기.");
            return true;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // MS Word 문서 저장
            MSWORDDocument msword = new MSWORDDocument();
            msword.DocSave();
            // HWP 문서 저장
            HWPDocument hwp = new HWPDocument();
            hwp.DocSave();
        }
    }
}

'디자인 패턴' 카테고리의 다른 글

Abstract Factory Pattern  (0) 2009.06.09
객체지향 설계에서 클래스 상속의 두가지 목적  (0) 2009.06.08

 
역사상 가장 서민다운 대통령이 나왔을 때 너무 나도 기뻤다.
노란 손수건, 노란 풍선. 아직도 그때가 기억에 선한데..
퇴임후 그저 조용히 고향에서 농사 짓고 사시겠다던 우리 대통령.
그런 결정을 내리셨을 때 나는 또 한번 감탄했다.
역시 내가 존경하는 분. 역대 대통령 중에 저런 결정을 한 사람이 있었던가.
하지만 평화로웠던 생활도 잠시... 지금은 고인이 되어 우리 곁에 없으시다.
부디 거기서는 담배 한대 피우시고 편안하게 지내세요.
한 나라의 대통령이 죽었을 때 국민들이 서럽게 우는 걸 이해하지 못했다.
하지만 지금은 그 심정을 알게 되었다.
정말 한참을 울고 멍하니 사진만 봐라 봤다. 저런 옆집 아저씨 같은 대통령이 나올 수 있을까..


노무현 대통령님 편안하게 쉬세요. 보고싶습니다.

'It`s me.' 카테고리의 다른 글

전주 35사단  (2) 2009.06.14
서울반도체 신세길 회장의 경영메모 성공을 만드는 4P 프로그램  (0) 2009.06.02
어학연수에 대한 생각  (1) 2009.05.19
인도에 부는 한국어 열풍.  (3) 2009.04.29
블로그 오픈.!  (0) 2007.10.16

'닷넷 프레임워크' 카테고리의 다른 글

DataGridView 소개  (1) 2009.07.13
MySQL 5.1과 C# 연동  (0) 2009.05.31
wav 파일 재생하기  (0) 2009.04.29
랜덤 파일명 생성하기  (1) 2009.04.29
txt 파일로 저장하기  (0) 2009.04.28
잠깜 머리도 식힐 겸 네이버에서 "어학연수"에 대한 글들을 검색하기 시작했다.
거기서 인상 깊은 블로그를 찾아냈는데.
뭐하는 사람인지는 모르지겠지만 세계 일주 프로젝트를 하고 있었다.
영어연수에 대한 마음에 와닿는 좋은 조언이 있었다.

http://blog.naver.com/happinomics/20066372476

영어 공부 할꺼면 한국에서 해라!
그리고 가서는 절대로 절대로 절대로 모범생으로 지내지 말아라.

자세한 내용을 모르고 이말을 들으면 저런 된장같은 자식이있나 싶겠지만은 저 사람이 적은 글을 자세히 읽으면 공감이 되는 말 같다. 저 사람이 말하는 요점은 "한국 학원들도 영어를 진짜 잘가르친다. 한국에서 토익 800점은 만들어라. 귀도 다 뚫고 외국 방송 어느 정도 말귀를 다 알아 들을 수 있을 때 어학연수를 가라." 이다. 비싼 돈 주고 어학연수가서 집-학원-집-학원 밖에 안하는 생활은 정말 비효율적인 것 같다. 저런 생활은 한국에서도 얼마든지 할 수 있지 않는가. 멀리 외국까지 저런 생활만 한다고 생각하니깐 끔찍한 것 같다. 수업은 파트타임으로만 듣고, 수업에 가서 열심히 말하는 연습하고, 외국 친구들도 많이 사귀고, 주말이면 여기 저기 놀러 다니고, 주변 국가들도 가보고, 자원봉사도 해보고 이것 저것 해보라. 돌아다니면서 말하고, 새로운거 구경하면서 말하고, 외국에서 말하는 연습을을 많이 해라. 라는 말이 너무 와닿았다. 정말 큰돈 들여서 가는거 라면 우리나라에서 쉽게 할 수없는 일들을 많이 하고 오는게 좋지 않을까.
"막상 주변의 친구들을 보면 가서 열심히 해야지" 하는데 다녀온 친구들의 조언에 의하면 한국에서 공부를 열심히 하고 가야 외국가서 얻는게 많다는 소릴 많이 듣는다. 나도 남은 병특기간 열심히 영어공부해서 재미있게 어학연수 다녀와야지.









'It`s me.' 카테고리의 다른 글

전주 35사단  (2) 2009.06.14
서울반도체 신세길 회장의 경영메모 성공을 만드는 4P 프로그램  (0) 2009.06.02
그리운 사람.  (0) 2009.05.26
인도에 부는 한국어 열풍.  (3) 2009.04.29
블로그 오픈.!  (0) 2007.10.16
데브피아 서핑중 구인구직의 Windows system programmer를 뽑는다는 글이 올라왔다.
거기에다가 병특 전직도 가능. 
하지만 우대 조건을 보고 바로 절망 ㅋㅋ
젠장 ㅋ 저기서 아는 단어라곤  System callC/C++ .. 무식한게 죄다.
어떻게 프로그램을 몇 년 해왔는데.. 지금 생각해보면 윈도우 껍데기 만드는 요령만 얻은 것 같다. 잘하는 것이 없다.
항상 시스템 프로그래머를 동경해 왔는데. 조금씩 준비해서 도전해봐야겠다.

   - Windows System Call 능숙한 분
   - C/C++ 능숙한 분
   - Ntdll.dll의 의미, 기능 등을 잘 이해 하는 분
   - PE(Portable Executable) 능숙한 분 우대
   - API hook(IAT, Code, SSDT patch등) 유 경험자 우대
   - IFS KIT, TDI, NDIS 유 경험자 우대

+ Recent posts