image 설명.. -> 나중에.
..
그리고, MFC를 하기전에 꼭 한번씩 나오는 SDK로 하는 windows programming. source.
MFC자체는 이런
WinMain이나
WndProc 는 감추지만 밑단에서 이런 식으로 돌아간다는 것을 조금이라도 알게 하기 위해서 포함. 무시해도 상관 없음. ㅋㅋ
~cpp
// 주석 없음.. 그냥.. WinMain과 WndProc가 있구나만 보고 넘어 가시길.. 키키
// 궁금하면 찾아 보시라우~
#include <windows.h>
int WINAPI WndProc (HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
WNDCLASS wc;
HWND hWnd;
MSG msg;
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon (NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = _T("MyWndClass");
RegisterClass (&wc);
hwnd = CreateWindow (_T("MyWndClass"), "SDK Application",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
HWND_DESKTOP,
NULL,
hInstance,
NULL ); // window를 만들었지만 보이지는 않는다.
ShowWindow (hWnd, nCmdShow); // window 보여주기. --;
UpdateWindow (hWnd);
while (GetMessage (&msg, NULL, 0, 0))
{ // 무한 루프를 돌면서 message 큐에 있는 message를 가져온다.
// WM_QUIT message가 발생하면 GetMessage가 0을 반환하여 프로그램 종료.
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// 이렇게 안보이는 곳에 WinMain과 WndProc라는 것이 존재해서, message를 받아서 처리한다.
// 자세한것은 charles petzold의 Programming Windows라는 책에 보면 엄청 잘나와 있다. --;
// 그 책도 다시 한번 훌터 봐야 겠다. T-T 처음에 제대로 볼걸.. 다시 보게 되다니.. T-T
그럼 이제 이 책에서 처음 나오는 MFC programming source를.. 공개 한다. Dialog based로 프로젝트를 연후 Dialog에 관한 class는 project에서 뺀후 App클래스내에 이 source를 쳐주면 될것이다. - 신기 하게도 App class와
MainWindow클래스만 있다. 이런 source는 처음 봐서 생소 했지만, MFC에서 제공해주는 source보다는 깔끔해 보였다.-
~cpp
// hello.h
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance ();
};
class CMainWindow : public CFrameWnd
{
public:
CMainWindow ();
protected:
afx_msg void OnPaint ();
DECLARE_MESSAGE_MAP ()
};
// hello.cpp
#include <afxwin.h>
#include "Hello.h"
CMyApp myApp;
/////////////////////////////////////////////////////////////////////////
// CMyApp member functions
// 프로그램을 초기화 할수 있는 가장 적절한 장소. --a
// CWinApp::InitInstance를 override한 가상함수이다.
BOOL CMyApp::InitInstance ()
{
m_pMainWnd = new CMainWindow; // 윈도우 생성
m_pMainWnd->ShowWindow (m_nCmdShow); //
m_pMainWnd->UpdateWindow ();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// CMainWindow message map and member functions
BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
ON_WM_PAINT ()
END_MESSAGE_MAP ()
CMainWindow::CMainWindow ()
{
Create (NULL, _T ("The Hello Application"));
}
void CMainWindow::OnPaint ()
{
CPaintDC dc (this);
CRect rect;
GetClientRect (&rect);
dc.DrawText (_T ("Hello, MFC"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
떡하니 source를 보면 어떻게 돌아가는 거야.. --; 라는 생각이 든다.. 나도 잘모른다. 그런데 가장 중요한것은 global영역에 myApp라는 변수가 선언되어 있다는 사실이다. myApp 라는 instance가 이 프로그램의 instance이다. --a (최초의 프로그램으로 인스턴스화..) 그리고,
CWinApp를 상속한
CMyApp에 있는 유일한 함수 initInstance 에서 실제 window를 만들어준다.(
InitInstance함수는 응용 프로그램이 처음 생길 때, 곡 window가 생성되기전, 응용 프로그램이 시작한 바로 다음에 호출된다) 이 부분에서
CMainWindow의 instance를 만들어 멤버 변수인 m_pMainWnd로 pointing한다. 이제 window는 생성 되었다. 그렇지만, 기억해야 할 것이 아직 window는 보이지 않는다는 사실이다. 그래서,
CMainWindow의 pointer(m_pMainWindow)를 통해서
ShowWindow와
UpdateWindow를 호출해 준다. 그리고 TRUE를 return 함으로써 다음 작업으로 진행 할 수 있게 해준다.... 흘. 영서라 뭔소린지 하나도 모르겠네~ 캬캬..
to be continue..
...
그리고, 그 다음으로 진행되는 것이.
CMainWindow에 있는
OnPaint라는 함수. window의 client 영역에 무언가를 그리는 함수가 호출된다. (그 전에 이것 저것 많이 있겠지만... 뭐 매크로를 통해 messagemap 관련 entry라던지.. 이런것들을 선언해 주는 작업.. --a) 그래서,
DrawText를 이용해 화면 중앙에 "Hello, MFC"를 그린다. 그러면 이 프로그램의 기능(?)은 끝이다.