Developfordummies 01
문제 발생
- 이거 프로그램을 짜서 돌리면 제대로 돌아가기나 할까?
문제점 분석
- 아주 기본적인 프로그램을 작성하여 돌려보도록 하자.
해결 방안
- 그냥 단순한 텍스트가 출력되는지 보자.
- 그냥 단순한 창 같은 거 하나 띄워보자.
- 그냥 단순한 텍스트 나열을 보자.
- 사실 Hello World라는건 동작 확인에 쓰이는 것이다.
- 내가 프로그래밍을 해서 Hello World가 화면에 찍히기까지 많은 일이 준비되어 있다는 거다.
- 프로그래머야 그냥 쉽게 확인한다고 생각하지만, 여러 가지가 전제되어 있는 환경이 이미 구축되어 있는 것이다.
- 하지만 프로토타입 설계할 때 그런 건 신경쓰지 말자. 괜시리 설계만 쓸데없이 커진다.
- 사실 Hello World의 경우 굳이 프로그래밍할 때 순서도를 작성하지 않아도 되는 유일한 프로그램일 것이다.
- 일반적인 경우 무조건 플로챠트를 그리길 권한다.
- 물론 이 문서에서 다음 챕터부터는 플로챠트가 꼭 등장한다.
- 먼저, 인터넷에서(검색엔진이 무엇이 되었든) Hello World를 검색한다.
- Hello World 어플리케이션은 대부분의 언어에서 샘플로 제공할 것이다. 그걸 쓰면 된다.
- 가장 많이 이야기되는 C언어를 보자.
<syntaxhighlight lang="c">
- 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">
- include <afxwin.h> // include MFC library
// // CHelloView is paints into the center of its window, "Hello World!" // class CHelloView : public CWnd { public:
CHelloView() {};
virtual ~CHelloView() {};
void OnPaint() // on paint lets us draw into the view
{
// Output hello world in middle of the window
CPaintDC dc(this); // device context for painting
CRect rect;
GetClientRect(&rect);
dc.TextOut(rect.right/2 - 40,rect.bottom/2 - 10,"Hello World!");
}
DECLARE_MESSAGE_MAP() // need message map to handle PAINT message
};
// // CMainFrame is our main frame window which holds our hello view // class CMainFrame : public CFrameWnd { public:
CMainFrame() {};
virtual ~CMainFrame() {};
protected:
CHelloView m_wndView;
int OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// create our frame window first
if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;
// create a view to occupy the client area of the 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)
{
// let the view have first crack at the command
if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
// otherwise, do default handling
return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
DECLARE_MESSAGE_MAP() // need message map to handle CREATE message
};
// // Application is our entry point into our MFC program // class Application : public CWinApp { public:
Application() {};
virtual BOOL InitInstance() // our entry point into MFC application
{
// To create the main window, this code creates a new frame window
// object and then sets it as the application's main window object.
CMainFrame* pFrame = new CMainFrame;
m_pMainWnd = pFrame;
// create and load the frame with its resources
pFrame->Create(NULL,"Hello World Application");
pFrame->ShowWindow(SW_SHOW);
return TRUE;
};
};
BEGIN_MESSAGE_MAP(CHelloView,CWnd )
ON_WM_PAINT() // paint message
END_MESSAGE_MAP()
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE() // create message
END_MESSAGE_MAP()
// Create out global application object Application theApp;
// Notice we have no WinMain, because the MFC library // implements one for us Application theApp; </syntaxhighlight>
- 자, 그냥 하나 띄우는데에도 코드가 엄청 커졌다는걸 느낄거다.
- 그러니까 책들에서 웬만하면 GUI가 안 나오는거다..
- 예전에는 저걸 전부 외우거나 책을 보고 타이핑을 했어야 하지만, 요즘은 그렇게 프로그래밍하면 효율적이지 않다는 이야기를 듣게 될 것이다.
- 각 컴파일러에서 제공하는 예제를 보고, 어느 부분이 핵심인지 파악하는게 중요하다.
- 즉, 여기서는 CreateWM 부분이 중요하며, MFC는 먼저 윈도우를 띄우고 나서 내용을 채워넣는 방식이라는걸 알 수 있다.
- 의외로, 많은 책들이 코드를 보는 방법에 대해서는 잘 가르쳐주지 않는 것 같다.
- WinApi 를 쓰면 MFC보다는 실행 속도가 빠를 수 있겠지만 여전히 짧지 않다.
<syntaxhighlight lang="c">
- include <windows.h>
- 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">
- 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>
- 이렇게, 플로챠트도 필요없을 정도로 단순한 프로그래밍은 이제 다들 할 수 있을거라 생각한다.
연습문제
- 네모를 봤으면 세모도 찍어봐야지.
- 세모 별찍기를 해보자.