프로젝트/Nand2Tetris
1장 프로젝트
cyphen156
2023. 7. 7. 13:09
우선 윈도우 API를 통한 기본 프로젝트 부터 생성한다.
변경된 부분은 다음과 같이 애플리케이션 메세지 루프구문이다.
Nand2Tetris.cpp
while (1)
{
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
break;
}
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
// 메시지가 없을 때 수행할 작업이 있다면 여기에 작성합니다.
// 예: 애니메이션 업데이트, 게임 루프 등
}
}
// Nand2Tetris.cpp : 애플리케이션에 대한 진입점을 정의합니다.
//
#include "framework.h"
#include "Nand2Tetris.h"
#define MAX_LOADSTRING 100
// 전역 변수:
HINSTANCE hInst; // 현재 인스턴스입니다.
WCHAR szTitle[MAX_LOADSTRING]; // 제목 표시줄 텍스트입니다.
WCHAR szWindowClass[MAX_LOADSTRING]; // 기본 창 클래스 이름입니다.
// 이 코드 모듈에 포함된 함수의 선언을 전달합니다:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 여기에 코드를 입력합니다.
// 전역 문자열을 초기화합니다.
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_NAND2TETRIS, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 애플리케이션 초기화를 수행합니다:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_NAND2TETRIS));
MSG msg;
// 기본 메시지 루프입니다:
while (1)
{
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
break;
}
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
// 메시지가 없을 때 수행할 작업이 있다면 여기에 작성합니다.
// 예: 애니메이션 업데이트, 게임 루프 등
}
}
return (int) msg.wParam;
}
//
// 함수: MyRegisterClass()
//
// 용도: 창 클래스를 등록합니다.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_NAND2TETRIS));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_NAND2TETRIS);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// 함수: InitInstance(HINSTANCE, int)
//
// 용도: 인스턴스 핸들을 저장하고 주 창을 만듭니다.
//
// 주석:
//
// 이 함수를 통해 인스턴스 핸들을 전역 변수에 저장하고
// 주 프로그램 창을 만든 다음 표시합니다.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 함수: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 용도: 주 창의 메시지를 처리합니다.
//
// WM_COMMAND - 애플리케이션 메뉴를 처리합니다.
// WM_PAINT - 주 창을 그립니다.
// WM_DESTROY - 종료 메시지를 게시하고 반환합니다.
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// 메뉴 선택을 구문 분석합니다:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 여기에 hdc를 사용하는 그리기 코드를 추가합니다...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// 정보 대화 상자의 메시지 처리기입니다.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
그리고 나서는 CH1에 대한 초기 소스코드를 작성했다.
초기 소스코드는 1개 비트에 대한 논리 연산식을 사용했다.
CH01_Boolean.cpp
#include "CH01_boolean.h"
bool CH01_boolean::And(bool a, bool b)
{
return a && b;
}
bool CH01_boolean::OR(bool a, bool b)
{
return a || b;
}
bool CH01_boolean::Not(bool a)
{
return !a;
}
bool CH01_boolean::Xor(bool a, bool b)
{
return a != b;
}
bool CH01_boolean::Nor(bool a, bool b)
{
return !OR(a, b);
}
bool CH01_boolean::Nand(bool a, bool b)
{
return !And(a, b);
}
이제 이 코드를 모두 Nand하나만 가지고 비트 연산이 될 수 있도록 구성해야 한다.
다시한번 Nand의 특징을 짚어보자.
Nand는 둘 모두 참일때만 거짓을 반환하고, 나머지 경우에는 모두 참을 반환한다.
그렇다면 Nand함수는 다음과 같이 변환될 수 있을 것이다.
bool CH01_boolean::Nand(bool a, bool b)
{
if (a == 1 && b == 1)
{
return false;
}
return true;
}
그리고 이 코드는 비트 연산자에 의해 다음과 같이 표현될 수 있다.
return !(a & b);
이걸 이제 다른 모든 함수들에 대입하면 다음과 같이 소스코드가 수정된다.
#include "CH01_boolean.h"
bool CH01_boolean::And(bool a, bool b)
{
return Not(Nand(a, b));
}
bool CH01_boolean::OR(bool a, bool b)
{
return Nand(Nand(a, a), Nand(b, b));
}
bool CH01_boolean::Not(bool a)
{
return Nand(a, a);
}
bool CH01_boolean::Xor(bool a, bool b)
{
bool nand_ab = Nand(a, b);
bool left = Nand(a, nand_ab);
bool right = Nand(b, nand_ab);
return Nand(left, right);
}
bool CH01_boolean::Nor(bool a, bool b)
{
return Not(OR(a, b));
}
bool CH01_boolean::Nand(bool a, bool b)
{
return !(a & b);
}
이제 남은것은 MUX와 DEMUX를 구현하는 것이다.
// MUX: Multiplexer
// 선택 신호(sel)에 따라 입력 a 또는 b를 출력하는 함수
bool CH01_boolean::MUX(bool a, bool b, bool sel)
{
bool notSel = Not(sel);
bool aAnd = And(a, notSel);
bool bAnd = And(b, sel);
return Or(aAnd, bAnd);
}
// DEMUX: Demultiplexer
// 입력 in을 선택 신호(sel)에 따라 a 또는 b로 분배하는 함수
void CH01_boolean::Demux(bool in, bool sel, bool& a, bool& b)
{
bool notSel = Not(sel);
a = And(in, notSel);
b = And(in, sel);
}
CH01_boolean.cpp
#include "CH01_boolean.h"
bool CH01_boolean::And(bool a, bool b)
{
return Not(Nand(a, b));
}
bool CH01_boolean::Or(bool a, bool b)
{
return Nand(Nand(a, a), Nand(b, b));
}
bool CH01_boolean::Not(bool a)
{
return Nand(a, a);
}
bool CH01_boolean::Xor(bool a, bool b)
{
bool nand_ab = Nand(a, b);
bool left = Nand(a, nand_ab);
bool right = Nand(b, nand_ab);
return Nand(left, right);
}
bool CH01_boolean::Nor(bool a, bool b)
{
return Not(Or(a, b));
}
bool CH01_boolean::Nand(bool a, bool b)
{
return !(a & b);
}
// MUX: Multiplexer
// 선택 신호(sel)에 따라 입력 a 또는 b를 출력하는 함수
bool CH01_boolean::MUX(bool a, bool b, bool sel)
{
bool notSel = Not(sel);
bool aAnd = And(a, notSel);
bool bAnd = And(b, sel);
return Or(aAnd, bAnd);
}
// DEMUX: Demultiplexer
// 입력 in을 선택 신호(sel)에 따라 a 또는 b로 분배하는 함수
void CH01_boolean::Demux(bool in, bool sel, bool& a, bool& b)
{
bool notSel = Not(sel);
a = And(in, notSel);
b = And(in, sel);
}
그리고 확인할 수 있도록 화면에 입력을 받고, 결과를 출력해주는 것을 만들자
Resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++에서 생성한 포함 파일입니다.
// 다음에서 사용 Nand2Tetris.rc
#define IDS_APP_TITLE 103
#define IDR_MAINFRAME 128
#define IDD_NAND2TETRIS_DIALOG 102
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDI_NAND2TETRIS 107
#define IDI_SMALL 108
#define IDC_NAND2TETRIS 109
// Coustom controls
#define ID_BTN_INPUT_A 1001
#define ID_BTN_INPUT_B 1002
#define ID_BTN_AND 1003
#define ID_BTN_OR 1004
#define ID_BTN_NOT 1005
#define ID_BTN_XOR 1006
#define ID_BTN_NOR 1007
#define ID_BTN_NAND 1008
#define ID_BTN_MUX 1009 // MUX 연산 버튼
#define ID_BTN_DEMUX 1010
#define ID_STATIC_OUTPUT 1011 // 메인 출력창
#define ID_BTN_SEL_TOGGLE 1015 // SEL 토글 버튼
#define ID_STATIC_MUX_OUTPUT 1016 // MUX 출력 static (선택 사항)
#define ID_STATIC_DEMUX_A 1017
#define ID_STATIC_DEMUX_B 1018
#define IDC_MYICON 2
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif
// 다음은 새 개체에 사용할 기본값입니다.
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 130
#define _APS_NEXT_RESOURCE_VALUE 129
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif
Nand2Tetris.cpp
// Nand2Tetris.cpp : 애플리케이션에 대한 진입점을 정의합니다.
//
#include "framework.h"
#include "Nand2Tetris.h"
#include "CH01_boolean.h"
#define MAX_LOADSTRING 100
// 전역 변수:
HINSTANCE hInst; // 현재 인스턴스입니다.
WCHAR szTitle[MAX_LOADSTRING]; // 제목 표시줄 텍스트입니다.
WCHAR szWindowClass[MAX_LOADSTRING]; // 기본 창 클래스 이름입니다.
// 커스텀 변수를 정의합니다.
bool inputA = false;
bool inputB = false;
bool result = false;
bool inputSel = false;
bool result_or = false;
bool result_not = false;
bool result_xor = false;
bool result_nor = false;
bool result_nand = false;
bool result_mux = false;
bool result_demux_a = false;
bool result_demux_b = false;
// 이 코드 모듈에 포함된 함수의 선언을 전달합니다:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 여기에 코드를 입력합니다.
// 전역 문자열을 초기화합니다.
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_NAND2TETRIS, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 애플리케이션 초기화를 수행합니다:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_NAND2TETRIS));
MSG msg;
// 기본 메시지 루프입니다:
while (1)
{
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
break;
}
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
// 메시지가 없을 때 수행할 작업이 있다면 여기에 작성합니다.
// 예: 애니메이션 업데이트, 게임 루프 등
}
}
return (int) msg.wParam;
}
//
// 함수: MyRegisterClass()
//
// 용도: 창 클래스를 등록합니다.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_NAND2TETRIS));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_NAND2TETRIS);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// 함수: InitInstance(HINSTANCE, int)
//
// 용도: 인스턴스 핸들을 저장하고 주 창을 만듭니다.
//
// 주석:
//
// 이 함수를 통해 인스턴스 핸들을 전역 변수에 저장하고
// 주 프로그램 창을 만든 다음 표시합니다.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 함수: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 용도: 주 창의 메시지를 처리합니다.
//
// WM_COMMAND - 애플리케이션 메뉴를 처리합니다.
// WM_PAINT - 주 창을 그립니다.
// WM_DESTROY - 종료 메시지를 게시하고 반환합니다.
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
// 입력 버튼
CreateWindowW(L"button", L"A : 0", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 20, 20, 100, 25, hWnd, (HMENU)ID_BTN_INPUT_A, hInst, NULL);
CreateWindowW(L"button", L"B : 0", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 20, 60, 100, 25, hWnd, (HMENU)ID_BTN_INPUT_B, hInst, NULL);
CreateWindowW(L"button", L"SEL = 0", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 20, 100, 100, 25, hWnd, (HMENU)ID_BTN_SEL_TOGGLE, hInst, NULL);
// 연산 버튼
CreateWindowW(L"button", L"AND", WS_CHILD | WS_VISIBLE, 140, 20, 240, 25, hWnd, (HMENU)ID_BTN_AND, hInst, NULL);
CreateWindowW(L"button", L"OR", WS_CHILD | WS_VISIBLE, 140, 60, 240, 25, hWnd, (HMENU)ID_BTN_OR, hInst, NULL);
CreateWindowW(L"button", L"NOT(A)", WS_CHILD | WS_VISIBLE, 140, 100, 240, 25, hWnd, (HMENU)ID_BTN_NOT, hInst, NULL);
CreateWindowW(L"button", L"XOR", WS_CHILD | WS_VISIBLE, 140, 140, 240, 25, hWnd, (HMENU)ID_BTN_XOR, hInst, NULL);
CreateWindowW(L"button", L"NOR", WS_CHILD | WS_VISIBLE, 140, 180, 240, 25, hWnd, (HMENU)ID_BTN_NOR, hInst, NULL);
CreateWindowW(L"button", L"NAND", WS_CHILD | WS_VISIBLE, 140, 220, 240, 25, hWnd, (HMENU)ID_BTN_NAND, hInst, NULL);
CreateWindowW(L"button", L"MUX", WS_CHILD | WS_VISIBLE, 140, 260, 240, 25, hWnd, (HMENU)ID_BTN_MUX, hInst, NULL);
CreateWindowW(L"button", L"DEMUX", WS_CHILD | WS_VISIBLE, 140, 300, 240, 25, hWnd, (HMENU)ID_BTN_DEMUX, hInst, NULL);
// 출력 Static
CreateWindowW(L"static", L"출력", WS_CHILD | WS_VISIBLE, 420, 20, 200, 25, hWnd, (HMENU)ID_STATIC_OUTPUT, hInst, NULL);
CreateWindowW(L"static", L"MUX 결과", WS_CHILD | WS_VISIBLE, 420, 60, 200, 25, hWnd, (HMENU)ID_STATIC_MUX_OUTPUT, hInst, NULL);
CreateWindowW(L"static", L"DEMUX A", WS_CHILD | WS_VISIBLE, 420, 100, 200, 25, hWnd, (HMENU)ID_STATIC_DEMUX_A, hInst, NULL);
CreateWindowW(L"static", L"DEMUX B", WS_CHILD | WS_VISIBLE, 420, 140, 200, 25, hWnd, (HMENU)ID_STATIC_DEMUX_B, hInst, NULL);
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// 메뉴 선택을 구문 분석합니다:
switch (wmId)
{
case ID_BTN_INPUT_A:
inputA = !inputA;
SetWindowText(GetDlgItem(hWnd, ID_BTN_INPUT_A), inputA ? L"A : 1" : L"A : 0");
break;
case ID_BTN_INPUT_B:
inputB = !inputB;
SetWindowText(GetDlgItem(hWnd, ID_BTN_INPUT_B), inputB ? L"B : 1" : L"B : 0");
break;
case ID_BTN_SEL_TOGGLE:
inputSel = !inputSel;
SetWindowText(GetDlgItem(hWnd, ID_BTN_SEL_TOGGLE), inputSel ? L"SEL=A" : L"SEL=B");
break;
case ID_BTN_AND:
result = CH01_boolean::And(inputA, inputB);
SetWindowText(GetDlgItem(hWnd, ID_STATIC_OUTPUT), result ? L"AND = 1" : L"AND = 0");
break;
case ID_BTN_OR:
result_or = CH01_boolean::Or(inputA, inputB);
SetWindowText(GetDlgItem(hWnd, ID_STATIC_OUTPUT), result_or ? L"OR = 1" : L"OR = 0");
break;
case ID_BTN_NOT:
result_not = CH01_boolean::Not(inputA);
SetWindowText(GetDlgItem(hWnd, ID_STATIC_OUTPUT), result_not ? L"NOT(A) = 1" : L"NOT(A) = 0");
break;
case ID_BTN_XOR:
result_xor = CH01_boolean::Xor(inputA, inputB);
SetWindowText(GetDlgItem(hWnd, ID_STATIC_OUTPUT), result_xor ? L"XOR = 1" : L"XOR = 0");
break;
case ID_BTN_NOR:
result_nor = CH01_boolean::Nor(inputA, inputB);
SetWindowText(GetDlgItem(hWnd, ID_STATIC_OUTPUT), result_nor ? L"NOR = 1" : L"NOR = 0");
break;
case ID_BTN_NAND:
result_nand = CH01_boolean::Nand(inputA, inputB);
SetWindowText(GetDlgItem(hWnd, ID_STATIC_OUTPUT), result_nand ? L"NAND = 1" : L"NAND = 0");
break;
case ID_BTN_MUX:
result_mux = CH01_boolean::MUX(inputA, inputB, inputSel);
SetWindowText(GetDlgItem(hWnd, ID_STATIC_MUX_OUTPUT), result_mux ? L"MUX = 1" : L"MUX = 0");
break;
case ID_BTN_DEMUX:
CH01_boolean::Demux(inputA, inputSel, result_demux_a, result_demux_b);
SetWindowText(GetDlgItem(hWnd, ID_STATIC_DEMUX_A), result_demux_a ? L"DEMUX A = 1" : L"DEMUX A = 0");
SetWindowText(GetDlgItem(hWnd, ID_STATIC_DEMUX_B), result_demux_b ? L"DEMUX B = 1" : L"DEMUX B = 0");
break;
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 여기에 hdc를 사용하는 그리기 코드를 추가합니다...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// 정보 대화 상자의 메시지 처리기입니다.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
//모든 자료들은 Nand2Tetris홈페이지에서 찾을 수 있습니다.
또는 다음 주소에서 찾으실 수 있습니다.
https://github.com/cyphen156/Nand2Tetris
GitHub - cyphen156/Nand2Tetris: 운영체제 공부용
운영체제 공부용. Contribute to cyphen156/Nand2Tetris development by creating an account on GitHub.
github.com