Developfordummies 01

Ubuntu Korea Community Wiki
둘러보기로 이동 검색으로 이동

문제 발생[편집]

  • 이거 프로그램을 짜서 돌리면 제대로 돌아가기나 할까?

문제점 분석[편집]

  • 아주 기본적인 프로그램을 작성하여 돌려보도록 하자.

해결 방안[편집]

  1. 그냥 단순한 텍스트가 출력되는지 보자.
  2. 그냥 단순한 창 같은 거 하나 띄워보자.
  3. 그냥 단순한 텍스트 나열을 보자.
  • 사실 Hello World라는건 동작 확인에 쓰이는 것이다.
  • 내가 프로그래밍을 해서 Hello World가 화면에 찍히기까지 많은 일이 준비되어 있다는 거다.
  • 프로그래머야 그냥 쉽게 확인한다고 생각하지만, 여러 가지가 전제되어 있는 환경이 이미 구축되어 있는 것이다.
  • 하지만 프로토타입 설계할 때 그런 건 신경쓰지 말자. 괜시리 설계만 쓸데없이 커진다.
  • 사실 Hello World의 경우 굳이 프로그래밍할 때 순서도를 작성하지 않아도 되는 유일한 프로그램일 것이다.
  • 일반적인 경우 무조건 플로챠트를 그리길 권한다.
  • 물론 이 문서에서 다음 챕터부터는 플로챠트가 꼭 등장한다.
  • 먼저, 인터넷에서(검색엔진이 무엇이 되었든) Hello World를 검색한다.
  • Hello World 어플리케이션은 대부분의 언어에서 샘플로 제공할 것이다. 그걸 쓰면 된다.
  • 가장 많이 이야기되는 C언어를 보자.

<syntaxhighlight lang="c">

  1. include <stdio.h>

int main(int argc, char* argv[]) {

 printf("Hello World!\n");
 return 0;

} </syntaxhighlight>

  • 잘 보면 printf가 핵심이라는걸 알 수 있을 것이다.
  • 하지만 요즘 세상에 누가 Console 화면을 볼 것인가?
  • (물론 필자나, 리눅스 유저들은 Console 화면을 좋아하지만, 대부분의 유저들은 좋아하지 않는다)
  • 그러므로 뭐 Window라도 하나 띄워보는 것이 좋겠다.
  • Window를 띄우는 함수는 Windows의 MFC를 사용하도록 하겠다.

<syntaxhighlight lang="c">

  1. include <afxwin.h> // include MFC library

// // CHelloView is an subclass of MFC CWnd class which prints "Hello World!" into the center of its window instance. // class CHelloView : public CWnd { public:

   CHelloView() {};
   virtual ~CHelloView() {};
   // An callback function that draws the content of the window into the given device context.
   // One of the alternatives to this method may be OnPaint. However, OnDraw is recommended since it supports being sent to the printer.
   void OnDraw(CDC* dc)
   {
       // Here, via the 'TextOut' function, we draw the infamous Hello, world! message into the center of the window.
       CRect rect;
       GetClientRect(&rect); // Queries size and position of client area of the window into 'rect' variable.
       dc.TextOut(rect.right/2 - 40,rect.bottom/2 - 10,"Hello, world!"); // This assumes the text is 80 pixels wide and 40 pixels tall, but this needs some workaround since many different system provides different default font faces.
   }        
   DECLARE_MESSAGE_MAP() // A message map is required for every window class to override the window procedure.

};

// // A main window frame which places 'Hello, world!' view inside itself. // class CMainFrame : public CFrameWnd { public:

   CMainFrame() {};
   virtual ~CMainFrame() {};

protected:

   CHelloView m_wndView;
   // Overrides WM_CREATE.
   int OnCreate(LPCREATESTRUCT lpCreateStruct)
   {
       // OnCreate requires call of parent function
       if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;
       
       // Create a child window which will eventually occupy entire area of the main frame.
       if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
           CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL)) return -1;
       
       return 0;
   }
   virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
   {
       // Pass every WM_COMMAND message to our child window.
       if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
           return TRUE;
   
       // Use default handling if the child window has nothing to do with it.
       return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
   }        
   DECLARE_MESSAGE_MAP() // A message map is required for every window class to override the window procedure.

};

// // Application is the entry point of almost every single MFC program // class Application : public CWinApp { public:

   Application() {};
   
   virtual BOOL InitInstance() // Initalize the app instance. Called by MFC.
   {        
       // This creates a main window object which will be set to be this application's main window.
       CMainFrame* pFrame = new CMainFrame;
       m_pMainWnd = pFrame;
       // Creates, and shows the main frame window.
       pFrame->Create(NULL,"Hello World Application");
       pFrame->ShowWindow(SW_SHOW);
       return TRUE;
   };

};

BEGIN_MESSAGE_MAP(CHelloView,CWnd) // leave this blank as we don't have any messages to process. Default implementation does all the thing. END_MESSAGE_MAP()

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)

   ON_WM_CREATE()    // Maps WM_CREATE message to our custom callback.

END_MESSAGE_MAP()

// Create out global application object // Notice we have no WinMain, because the MFC library // implements one for us Application theApp; </syntaxhighlight>

  • 자, 그냥 하나 띄우는데에도 코드가 엄청 커졌다는걸 느낄거다. (사실 그냥 메인 윈도우에서 그리면 될 걸 굳이 클래스 또 만들어서 그런 탓도 크다)
  • 그러니까 책들에서 웬만하면 GUI가 안 나오는거다..
  • 예전에는 저걸 전부 외우거나 책을 보고 타이핑을 했어야 하지만, 요즘은 그렇게 프로그래밍하면 효율적이지 않다는 이야기를 듣게 될 것이다.
  • 각 컴파일러에서 제공하는 예제를 보고, 어느 부분이 핵심인지 파악하는게 중요하다.
  • 즉, 여기서는 CreateWM 부분이 중요하며, MFC는 먼저 윈도우를 띄우고 나서 내용을 채워넣는 방식이라는걸 알 수 있다.
  • 의외로, 많은 책들이 코드를 보는 방법에 대해서는 잘 가르쳐주지 않는 것 같다.
  • WinApi 를 쓰면 MFC보다는 실행 속도가 빠를 수 있겠지만 여전히 짧지 않다.

<syntaxhighlight lang="c">

  1. include <windows.h>
  2. include <tchar.h>

LRESULT CALLBACK WndProc (HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) {

   HDC hdc; PAINTSTRUCT ps;
   switch (nMsg) {
   case WM_PAINT:
       hdc = BeginPaint (hWnd, &ps);
       TextOut (hdc, 0, 0, _T("Hello, world!"), 13);
       EndPaint (hWnd, &ps);
       break;
   case WM_DESTROY:
       PostQuitMessage(0);
       break;
   default:
       return DefWindowProc (hWnd, nMsg, wParam, lParam);
   }
   return 1;

}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {

   WNDCLASS wndClass = {0, WndProc, 0, 0, hInstance, NULL, NULL, (HBRUSH) (COLOR_WINDOW + 1), NULL, _T("HelloWorld")};
   HWND hWnd; MSG msg; ATOM atom;
   wndClass.hCursor = LoadCursor (NULL, IDC_ARROW);
   if (!(atom = RegisterClass (&wndClass))) return 1;
   if (!(hWnd = CreateWindow (MAKEINTATOM(atom), wndClass.lpszClassName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_DESKTOP, NULL, hInstance, NULL))) return 1;
   ShowWindow (hWnd, nShowCmd);
   UpdateWindow (hWnd);
   while (GetMessage (&msg, NULL, WM_NULL, WM_NULL)) {
       TranslateMessage (&msg);
       DispatchMessage (&msg);
   }
   UnregisterClass(MAKEINTATOM(atom), hInstance);
   return (int) msg.wParam;

} </syntaxhighlight>

  • 이제, Hello World는 찍어봤으니, 이걸 다른걸로 바꿔서 한 번 해보자.
  • 그냥 몇줄 정도 찍어보도록 한다.

<syntaxhighlight lang="c">

  1. include <stdio.h>

int main(int argc, char* argv[]) {

 for(int loop1 = 0; loop1 < 5; loop1++)
 {
   for(int loop2 = 0; loop2 < 5; loop2++)
     printf("*");
   printf("\n");
 }
 return 0;

} </syntaxhighlight>

  • 이렇게, 플로챠트도 필요없을 정도로 단순한 프로그래밍은 이제 다들 할 수 있을거라 생각한다.

연습문제[편집]

  • 네모를 봤으면 세모도 찍어봐야지.
  • 세모 별찍기를 해보자.