본문 바로가기
코스웨어/11년 내장형하드웨어

[내장형]백길남_2011년 8월 23일_일일보고서

by 알 수 없는 사용자 2011. 8. 23.
728x90
반응형

                                                [ C언어 ]

[ Continue ]


-> 문은 while 문 , do-whlie 문 , for문 등의 반복문의 실행중에 제어를 반복문의 시작으로 옮기는 역활을 한다.

[ Do-whlie ]

-> while 문에서 반복 조건이 먼저 컴토된 다음 명령문을 실행하는 것에 비해 do-whlie 문에서는 명령문을 먼저 실행한 다음 반복여부를 결정하는 점이 다른다.

Do-whlie 문은 조건식에는 맞지 않아도 최소 한번은 실행되는 셈이다.

<do-whlie 문의 구문형식>


do 명령문 whlie (논리식);

키워드 Do 다음에 반복 실행될 명령 문이 오고 , 그뒤에 예약어 whlie 과 괄호에 둘러 싸인 논리식이 온 뒤, 세미콜론으로 끝이 난다.


[ label 과 goto문 ]

-> goto 문은 가장 윈시적인 프로그램의 제어 방법으로서 아무조거없이 프로그램의 제어 를 변경시키기 때문에 프로그램의 논리적 체계를 흩뜨려 프로그램을 이해하기

힘들게 만든다. goto문은 이전에 베이직이나 포트란 프로그래밍에 많이 사용 되었지만 프로그램의 논리적 구조를 해치기 떄문에 파스칼이나 C 프로그램에서는 더 이상

사용하지 않는 것이 원칙이다.

예)

   1:  TEST:
   2:  printf("하이\n");
   3:  goto TEST;
   4:   
   5:  ->    goto문을 사용하면
   6:       
   7:          코드상에서 느려지고 , 분기가 많아서 찾기가 힘들다.
   1:  whlie ( ch = getch())
   2:  {
   3:           if(!isalpha (ch)) goto error; // error가 레이블이된다.
   4:           printf("%c",ch);
   5:  }
   6:  error : printf("wrong input\n");
   7:   
   8:  ->   goto error 이 whlie 문에서 탈출 용으로 쓸수가 있다.



[조건부 컴파일]

선행 처리 지시자를 이용하여 원시 프로그램의 일부분이 조건을 만족하는 경우에만 선택적으로 컴파일 하는 것을

조건부 컴파일이라고 한다.

<일반형식>

#if 조건 수식

     명령문 1

#else

     명령문 2

#endif

#if 지시자는 #endif 지시자로 끝나야한다.

예)

   1:  #include <stdio.h>
   2:   
   3:  #define SMALL 10
   4:  #define LARGE 50
   5:  #define HUGE 100
   6:   
   7:  #define SIZE SMALL
   8:  #if(SIZE == SMALL)
   9:  int list[SMALL];
  10:  #elif(SIZE == LARGE)
  11:  int list[LARGE];
  12:  #elif(SIZE == HUGE)
  13:  int list[HUGE];
  14:  #endif
  15:   
  16:  int main()
  17:  {
  18:      printf("%d\n",sizeof(list));
  19:      return 0;
  20:   
  21:  }

위 소스에서 define 되어 있는 값들을 조건부 컴파일을 이용하여 선택해주는 소스입니다.

위 소스에서는 SIZE 가 SMALL 로 이미 정해져 있기 때문에 출력은 SMALL 로 되게 됩니다.

하지만 SIZE 를 주석 처리를 하고 컴파일시 define 값을 넣어 줄수 도 있습니다.

예)

image

컴파일시 define 값을 넣어주는 모습입니다.

SIZE 에 100 이라는 값을 넣어주고 있으므로 출력은 400 이됩니다.

컴파일시 define 값을 넣어주는 것은 –D 입니다.

[ARTmega makefile 실행시 Define 되어 있는 값을 보여주는 화면]

define 되어있는 값을  makefile 에서 찾아가는 모습입니다.

image

image

image

image


[ 매크로 함수 ]

앞에서 #define 지시자가 상수를 정의 하는 것을 보았습니다. #define 지시자는 상수 뿐만 아니라.

함수도 정의 할 수 있습니다.


<구문형식>

#define  매크로 이름 (인수)(문자열)


예)

   1:  #include <stdio.h>
   2:   
   3:  #define CUBE(x) ((x)+(x)+(x))
   4:  //#define SUM(x,y) ((x)+(y))
   5:  int main()
   6:  {
   7:      int a,b;
   8:      a = 3;
   9:      b = CUBE(a);
  10:   
  11:      printf("The cube of %d is %d.\n",a,b);
  12:      return 0;
  13:  }

[결과]

image

[소스의 .i 파일에서 실행되는 모습을 확인 할 수 있습니다.]

image


매크로 함수를 만들어서 실행을 많이 하면 일반 함수처럼 호출해서 사용하는 것이 아니라서 실행속도는 빠르긴하지만

전체적인 코드의 무게가 무거워 집니다. 왜냐하면 매크로 함수 를 사용하면 #define 되어 있는 함수를 복사하여 계속하용하기 때문에

코드의 길이가 길어 지기 때문입니다.

일반 함수를 사용하는 것이 좋은지 매크로 함수를 사용하는 것이 좋은지는 그때 그때 선택해서 사용하는 것이 좋을것같습니다.

중요)매크로 함수를 사용할때 괄호 사용을 잘 하도록 합시다.!



[ #undef ]

#undef 지시자는 정의된 매크로를 해제하는 지시자이다. 동일한 매크로를 여러 번 정의 하였을 경우 , #undef 을 이용하면 가장최근에 정의한 것이 취소가 되고

그 바로 번의 정의가 효력을 갖는다.


예)

   1:  #define PI 3.1416
   2:  #define PI 3.14
   3:   
   4:                area1 =  5  *  5  * PI;
   5:   
   6:  #undef PI
   7:   
   8:                area2 =  5  *  5  * PI;


위 의 경우 area1 의 경우는 PI 값이 3.14로 제한되고 , area2 의 경우는 PI 값이 3.1416 으로 계산됩니다.

                                               [WIN_API]

예제)

   1:   
   2:  #include <windows.h>
   3:   
   4:  LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
   5:  HINSTANCE g_hInst;
   6:  LPSTR lpszClass="First";
   7:   
   8:  int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
   9:            ,LPSTR lpszCmdParam,int nCmdShow)
  10:  {
  11:      HWND hWnd;
  12:      MSG Message; //MSG 구조체 사용 
  13:      WNDCLASS WndClass; // WNDCLASS 구조체 사용 
  14:      g_hInst=hInstance; // 이 윈도우클래스를 등록하는 프로그램의 번호 
  15:   
  16:      //WndClass 정의
  17:      WndClass.cbClsExtra=0;
  18:      WndClass.cbWndExtra=0;
  19:      //WndClass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); //배경화면색깔을 바꿀수 있다.
  20:      //WndClass.hbrBackground=CreateSolidBrush(RGB(241,245,182));//RGB 값을 이용하여 배경화면 색깔을 바꿀수가 
있다.
  21:      WndClass.hbrBackground=CreateHatchBrush(HS_CROSS,RGB(209,19,69));//배경화면의 배경을 추가 할 수가 있다.
  22:      WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);// 커서 모양을 바꿀수가 있다.
  23:      WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);// 아이콘 모양을 바꿀수가 있다.
  24:      WndClass.hInstance=hInstance;
  25:      WndClass.lpfnWndProc=(WNDPROC)WndProc;//메세지 처리 함수를 지정  
  26:      WndClass.lpszClassName=lpszClass;//윈도우 클래스 이름이 들어감 
  27:      WndClass.lpszMenuName=NULL;// 여기선 메뉴 사용 안함 
  28:      WndClass.style=CS_HREDRAW | CS_VREDRAW;
  29:      //클래스 등록
  30:      RegisterClass(&WndClass); //Wndclass 구조체의 번지를 전달 
  31:      //메모리상에 윈도우 생성
  32:      hWnd=CreateWindow(lpszClass,TEXT("바보클래스"),WS_OVERLAPPEDWINDOW|WS_VSCROLL|WS_HSCROLL,
  33:              100,100,200,200,  
  34:          //CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
  35:            NULL,(HMENU)NULL,hInstance,NULL);
  36:      //1번쨰 인자 윈도우 클래스 이름
  37:      //2번째 인자 타이틀 바에 나타날 이름 예)Test("Test") 하면 타이틀에 Test가 나옵니다.
  38:      //3번째 인자 윈도우 스타일을 변경 할 수 있다.
  39:      //4번쨰 ~5번째  윈도우창의 위치 를 선택 할수 있다.
  40:      //6번째 ~7번째  윈도우 창의 크기를 선택 할 수 있다.
  41:      
  42:      //윈도우 화면에 출력
  43:      ShowWindow(hWnd,nCmdShow);
  44:      //메시지를 처리해서 WndProc함수로 보냄
  45:      while(GetMessage(&Message,0,0,0)) {//메세지 큐에 메세지를 읽어옴 
  46:                                          //WN_QUIT 면 False 리턴 
  47:          TranslateMessage(&Message);   //키보드 입력 처리 
  48:          DispatchMessage(&Message);    //큐에서 꺼낸 메시지를 WndProc 함수의  iMessage 로 전달 
  49:      }
  50:      return Message.wParam; //메세지 루프 종료후 이 프로그램을 실행시킨 OS 로 리턴 
  51:  }
  52:      //메시지 처리
  53:  //CALLBACK 이 있으면 운영체제가 호출하는 함수 이다.
  54:  LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
  55:  {
  56:      switch(iMessage) {
  57:      case WM_DESTROY:
  58:          PostQuitMessage(0);//Wn_QUIT 메세지를 보냄 
  59:      case WM_LBUTTONDOWN:
  60:          MessageBeep(0);
  61:          return 0;
  62:      }
  63:      //Switch 문맥에서 처리하지 않은 메새지를 처리 
  64:      return(DefWindowProc(hWnd,iMessage,wParam,lParam));
  65:  }
  66:   
  67:   

우리가 만든 예제의 배경색은 흰색이었다. 왜 배경색이 흰색이 되었는가 하면

WndClass의 멤버중 배경색상을 지정하는 hbrBackground가 흰색 브러시로 지정되어 있기 때문이다.

WndClass.hbrBackground=GetStockObject(WHITE_BRUSH);

여기서 사용된 GetStockObject 함수는 윈도우즈가 기본적으로 제공하는 브러시, 펜 등의 핸들을 구해주는 함수인데

이 함수의 인수로 WHITE_BRUSH가 사용되었기 때문에 배경색을 칠하는 데 흰색 브러시가 사용되었다.

이 값을 BLACK_BRUSH로 변경하면 검정색이 배경색으로 사용되며 LTGRAY_BRUSH로 변경하면 옅은 회색 배경이 만들어진다.


WndClass.hbrBackground=CreateSolidBrush(RGB(241,245,182));//RGB 값을 이용하여 배경화면 색깔을 바꿀수가 있다.

RGB 값을 이용하여 다양한 색깔로 배경색을 지정 할 수 가 있다.




WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);

hCursor 멤버는 윈도우가 기본적으로 사용할 커서를 지정하며 LoadCursor 함수는 커서를 읽어오는 함수이다.

HCURSOR LoadCursor( HINSTANCE hInstance, LPCTSTR lpCursorName );

첫번째 인수 hInstance는 커서를 가지고 있는 프로그램의 인스턴스 핸들이되 윈도우즈가 제공하는 디폴트 커서를 사용하려면

이 인수를 NULL로 지정하면 된다. 두번째 인수 lpCursorName은 사용하고자 하는 커서의 이름을 지정한다.

윈도우즈가 디폴트로 제공하는 커서에는 다음과 같은 종류가 있다.

설명

IDC_ARROW

화살표 모양

IDC_CROSS

십자 모양

IDC_IBEAM

I자 모양

IDC_NO

원안에 빗금이 쳐진 모양

IDC-WAIT

모래시계 모양



윈도우의 타이틀을 바꾸기 위해서는

hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
	  CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 
	  NULL,(HMENU)NULL,hInstance,NULL);

에서 두번째 인자를





Text(“ 적을단어 “) 로 바꾸어주면 윈도우 타이틀이 바뀌게 된다.
나머지 인자들은 주석으로 달려있으므로 주석을 참고하자.



 

CreateWindow함수의 네번째 인수 dwStyle은 윈도우즈의 여러가지 속성을 정의하는 32비트 정수값이며

이 값을 변경함에 따라 다양한 모양의 윈도우를 만들 수 있다. 일단 dwStyle에 사용될 수 있는 값들을 보자.

이 값들을 OR연산자로 연결하여 여러가지 속성을 한꺼번에 지정한다.

설명

WS_CAPTION

타이틀 바를 가진다.

WS_HSCROLL

수평 스크롤 바를 가진다.

WS_VSCROLL

수직 스크롤 바를 가진다.

WS_MAXIMIZEBOX

최대화 버튼을 가진다.

WS_MINIMIZEBOX

최소화 버튼을 가진다.

WS_SYSMENU

시스템 메뉴를 가진다.

WS_THICKFRAME

크기를 조절할 수 있는 경계선을 가진다.

이 외에도 여러가지 속성값들이 있지만 한꺼번에 다 설명하기는 어려우므로 일단 이 값들만을 사용하여 윈도우 스타일을 변경해 보자. First예제에서 사용하는 WS_OVERLAPPEDWINDOW는 다음과 같이 정의되어 있다.

#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | \

WS_CAPTION | \

WS_SYSMENU | \

WS_THICKFRAME | \

WS_MINIMIZEBOX | \

WS_MAXIMIZEBOX)

여기서 WS_OVERLAPPED는 실제로 0이므로 아무런 의미가 없으며 타이틀 바,

시스템 메뉴, 크기조절이 가능한 경계선, 최소, 최대 버튼 등의 스타일이 한꺼번에 정의되어 있다.



[결과]

 

위 의 여러가지 기능으로 윈도우 타이틀 과 배경 ,색 등을 바꾸어 본 모습이다.







[출력]

 

<DC>

윈도우즈는 세 가지 동적 연결 라이브러리로 구성되어 있는데 메모리를 관리하고 프로그램을 실행시키는

KERNEL, 유저 인터페이스와 윈도우를 관리하는 USER, 그리고 화면 처리와 그래픽을 담당하는 GDI이다.

윈도우즈 API 함수의 대부분이 이 세 가지 DLL에 의해 제공되고 있다. 출력을 하려면 우리는 GDI(Graphic Device Interface)모듈에 특별히 관심을 기울여야 한다.

화면으로 출력되는 모든 글자와 그림은 GDI를 통해야 하기 때문이다.

DC(Device Context)란 출력에 필요한 모든 정보를 가지는 데이터 구조체이며 GDI 모듈에 의해 관리된다.

어떤 폰트를 사용할 것인가, 선의 색상과 굵기, 채움 무늬와 색상, 출력 방법 등등이 모두 출력에 필요한 정보들이다.



DC 는 현재 상황에서 어떤 영역이 출력 허가도니 영역인가 를 계산하여 허가된 영역에만 출력을 내 보낸다.그래서 원도우 끼리 겹치더라도 다른 윈도우 영역을

침범하지 않도록 보장한다. 이때 DC 는 윈도우 까리의 출력 결과가 서로 방해 하지 않도록 완충역활을 한다.


<문자열 출력>

예)

/ 위 소스와 비슷하므로 다른 부분만 표시 /

   1:  LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
   2:  {
   3:      HDC hdc;
   4:      
   5:      switch(iMessage) {
   6:      case WM_DESTROY:
   7:          PostQuitMessage(0);//Wn_QUIT 메세지를 보냄 
   8:          return 0;
   9:      case WM_LBUTTONDOWN:
  10:          hdc = GetDC(hWnd); //GetDC 를 이용하여 DC 의 핸들을 hdc 에 넣는다.
  11:          TextOut(hdc,100 ,100,TEXT("Beautiful Korea"),15);
  12:          ReleaseDC(hWnd , hdc);//hdc 를 해제 시켜주기위한 소스 
  13:          return 0;
  14:          
  15:      }
[결과]

 

 

마우스 왼쪽을 클릭 하였을 경우 “Beautiful Korea” 문자 가 나타나 도록 되어 있다.

하지만 여기에 큰 문제가 있다. 어떤 문제인가 하면 출력된 문자열이 그자리 그대로 있지 않다는 점이다. 문자열이 출력된 윈도우 를 다른 윈도우로 살짝 가렸다가 다시

드러나도록 하거나 윈도우의 크기를 변경하면 출력되어 있던 문자열이 사라지게 될것이다. 왜냐하면 운영체제가 개별 윈도우 의 화면을 보관및 복구해 주지않기 때문이다.


윈도우즈는 가려졌던 윈도우의 화면을 보관 및 복구하는 책임을 지지 않으며 지원진 화면을 복고 하는 책임은 전적으로 프로그램 자신에게 있다.

마우스 왼쪽버튼을 누르면 문자열을 출력하는 것이 아니라 화면이 지워질때 마다 문자열을 출력해야한다.

WM_PAINT 를 사용하면 이 문제를 해결 할 수 가 있다.

WM_PAINT 는 윈도우의 일부가 지워졌다는 사실을 프로그램으로 즉각 알리며 그 방법은 WM_PAINT 메시지를 보내주는 것이다.WM_PAINT 메시지는 “ 너의 작업영역이

일부 지워졌으니 빨리 다시 그려라” 는 뜻이다.


[WM_PAINT]

   1:  LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
   2:  {
   3:      HDC hdc;
   4:      PAINTSTRUCT ps;
   5:      switch(iMessage) {
   6:      case WM_DESTROY:
   7:          PostQuitMessage(0);//Wn_QUIT 메세지를 보냄 
   8:          return 0;
   9:      case WM_PAINT:
  10:          hdc = BeginPaint(hWnd,&ps); //BeginPaint 를 이용하여 DC 의 핸들을 hdc 에 넣는다.
  11:          TextOut(hdc,100 ,100,TEXT("Beautiful Korea"),15);
  12:          EndPaint(hWnd,&ps); //hdc 를 해제 시켜주기위한 소스 
  13:          return 0;
  14:          
  15:      }

WM_PAINT 를 적용한 모습이다.

적용을 시키면 출력된 문자열이 더이상 지워지지 않는다는 것을 확인할 수 있다.






더욱 자세한 내용을 원하신다면 책을 보시거나 http://www.winapi.co.kr 사이트 를 참조해주세요.

728x90