ÀÌ ¼½¼ÇÀÇ ¿¹Á¦¿¡´Â ÀÀ¿ë ÇÁ·Î±×·¥ ¼ö Űº¸µå¿¡¼ ¹®ÀÚ¸¦ ¼ö½Å âÀÇ Å¬¶óÀÌ¾ðÆ® ¿µ¿ª¿¡ Ç¥½Ã ¹× ÀÔ·Â ÇÑ °¢ ¹®Àڴ ij·µÀÇ À§Ä¡¸¦ ¾÷µ¥ÀÌÆ® ÇÏ´Â ¹æ¹ýÀ» º¸¿© ÁÝ´Ï´Ù. ¶ÇÇÑ ¿ÞÂÊµÈ È»ìÇ¥, ¿À¸¥ÂÊ È»ìÇ¥, °¡Á¤ ¹× ÃÖÁ¾ Ű¿¡ ´ë ÇÑ ÀÀ´ä¿¡¼ ij·µÀ» À̵¿ ÇÏ´Â ¹æ¹ýÀ» º¸¿© ÁÝ´Ï´Ù. ¹× shift + ¿À¸¥ÂÊ È»ìÇ¥ Ű Á¶ÇÕÀ» ÀÀ´ä¿¡¼ ¼±ÅÃÇÑ ÅØ½ºÆ®¸¦ °Á¶ Ç¥½Ã ÇÏ´Â ¹æ¹ýÀ» º¸¿© ÁÝ´Ï´Ù.
WM_CREATE ¸Þ½ÃÁö¸¦ ó¸® ÇÏ´Â µ¿¾È ¿¹Á¦¿¡ Ç¥½Ã µÈ â ÇÁ·Î½ÃÀú´Â Űº¸µå ÀÔ·ÂÀ» ÀúÀå Çϱâ À§ÇÑ 64 K ¹öÆÛ¸¦ ÇÒ´ç ÇÕ´Ï´Ù. ¶ÇÇÑ ±Û²Ã¿¡¼ ¹®ÀÚÀÇ Æò±Õ ³Êºñ¿Í ³ôÀÌ ÀúÀå ÇÏ´Â ÇöÀç ·Îµå µÈ ±Û²ÃÀÇ Åë°è¸¦ °Ë»ö ÇÕ´Ï´Ù. ³ôÀÌ ³Êºñ ¼± ±æÀÌ ¹× Ŭ¶óÀÌ¾ðÆ® ¿µ¿ª Å©±â¸¦ ±â¹ÝÀ¸·Î ÇÏ´Â ÁÙÀÇ ÃÖ´ë ¼ö¸¦ °è»ê ÇÏ·Á¸é WM_SIZE ¸Þ½ÃÁö¸¦ 󸮿¡ »ç¿ë µË´Ï´Ù.
â ÇÁ·Î½ÃÀú ¸¸µé°í WM_SETFOCUS ¸Þ½ÃÁö¸¦ ó¸®ÇÒ ¶§ ij·µÀ» Ç¥½Ã ÇÕ´Ï´Ù. ±×°ÍÀº ¼û°ÜÁö°í WM_KILLFOCUS ¸Þ½ÃÁö¸¦ ó¸®ÇÒ ¶§ ij·µÀ» »èÁ¦.
WM_CHAR ¸Þ½ÃÁö¸¦ ó¸®ÇÒ ¶§ â ÇÁ·Î½ÃÀú ¹®ÀÚ Ç¥½Ã ÀÔ·ÂµÈ ¹öÆÛ¿¡ ÀúÀå ÇÏ °í ij·µ À§Ä¡¸¦ ¾÷µ¥ÀÌÆ® ÇÕ´Ï´Ù. â ÇÁ·Î½ÃÀú´Â ¶ÇÇÑ 4 °³ÀÇ ¿¬¼Ó µÈ °ø¹é ¹®ÀÚ¸¦ ÅÇ ¹®ÀÚ¸¦ º¯È¯ÇÕ´Ï´Ù. ¹é½ºÆäÀ̽º, ÁÙ ¹Ù²Þ, ¹× À̽ºÄÉÀÌÇÁ ¹®ÀÚ¸¦ °æ°íÀ½À» »ý¼º ÇÏÁö¸¸ ±×·¸Áö ¾ÊÀ¸¸é ó¸® µÇÁö ¾Ê½À´Ï´Ù.
â ÇÁ·Î½ÃÀú WM_KEYDOWN ¸Þ½ÃÁö¸¦ ó¸®ÇÒ ¶§ ¿ÞÂÊ, ¿À¸¥ÂÊ, ³¡, ¹× Ȩ ij·µ ¿òÁ÷ÀÓÀ» ¼öÇà ÇÕ´Ï´Ù. ¿À¸¥ÂÊ È»ìÇ¥ ŰÀÇ µ¿ÀÛÀ» ó¸® ÇÏ´Â µ¿¾È â ÇÁ·Î½ÃÀú shift ŰÀÇ »óŸ¦ È®ÀÎ, ´Ù¿î °æ¿ì ij·µ À̵¿ ij·µÀÇ ¿À¸¥ÂÊ ¹®ÀÚ ¼±ÅÃ.
Note À¯´ÏÄÚµå ¶Ç´Â ANSI·Î ÄÄÆÄÀÏÇÒ ¼ö ÀÖµµ·Ï ´ÙÀ½ Äڵ带 ÀÛ¼º ÇÕ´Ï´Ù. ¹®ÀÚ¿À» À¯´ÏÄÚµå ¹®ÀÚ·Î; ó¸® ¼Ò½º Äڵ忡¼ À¯´ÏÄڵ带 Á¤ÀÇ ÇÏ´Â °æ¿ì ±×·¸Áö ¾ÊÀ¸¸é, ±×µéÀº ANSI ¹®ÀڷΠó¸® µË´Ï´Ù.
#define BUFSIZE 65535
#define SHIFTED 0x8000
LONG APIENTRY MainWndProc(HWND hwndMain, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hdc; // handle to device context
TEXTMETRIC tm; // structure for text metrics
static DWORD dwCharX; // average width of characters
static DWORD dwCharY; // height of characters
static DWORD dwClientX; // width of client area
static DWORD dwClientY; // height of client area
static DWORD dwLineLen; // line length
static DWORD dwLines; // text lines in client area
static int nCaretPosX = 0; // horizontal position of caret
static int nCaretPosY = 0; // vertical position of caret
static int nCharWidth = 0; // width of a character
static int cch = 0; // characters in buffer
static int nCurChar = 0; // index of current character
static PTCHAR pchInputBuf; // address of input buffer
int i, j; // loop counters
int cCR = 0; // count of carriage returns
int nCRIndex = 0; // index of last carriage return
int nVirtKey; // virtual-key code
TCHAR szBuf[128]; // temporary buffer
TCHAR ch; // current character
PAINTSTRUCT ps; // required by BeginPaint
RECT rc; // output rectangle for DrawText
SIZE sz; // string dimensions
COLORREF crPrevText; // previous text color
COLORREF crPrevBk; // previous background color
switch (uMsg)
{
case WM_CREATE:
// Get the metrics of the current font.
hdc = GetDC(hwndMain);
GetTextMetrics(hdc, &tm);
ReleaseDC(hwndMain, hdc);
// Save the average character width and height.
dwCharX = tm.tmAveCharWidth;
dwCharY = tm.tmHeight;
// Allocate a buffer to store keyboard input.
pchInputBuf = (LPTSTR) GlobalAlloc(GPTR,
BUFSIZE * sizeof(TCHAR));
return 0;
case WM_SIZE:
// Save the new width and height of the client area.
dwClientX = LOWORD(lParam);
dwClientY = HIWORD(lParam);
// Calculate the maximum width of a line and the
// maximum number of lines in the client area.
dwLineLen = dwClientX - dwCharX;
dwLines = dwClientY / dwCharY;
break;
case WM_SETFOCUS:
// Create, position, and display the caret when the
// window receives the keyboard focus.
CreateCaret(hwndMain, (HBITMAP) 1, 0, dwCharY);
SetCaretPos(nCaretPosX, nCaretPosY * dwCharY);
ShowCaret(hwndMain);
break;
case WM_KILLFOCUS:
// Hide and destroy the caret when the window loses the
// keyboard focus.
HideCaret(hwndMain);
DestroyCaret();
break;
case WM_CHAR:
switch (wParam)
{
case 0x08: // backspace
case 0x0A: // linefeed
case 0x1B: // escape
MessageBeep(0xFFFFFFFF);
return 0;
case 0x09: // tab
// Convert tabs to four consecutive spaces.
for (i = 0; i < 4; i++)
SendMessage(hwndMain, WM_CHAR, 0x20, 0);
return 0;
case 0x0D: // carriage return
// Record the carriage return and position the
// caret at the beginning of the new line.
pchInputBuf[cch++] = 0x0D;
nCaretPosX = 0;
nCaretPosY += 1;
break;
default: // displayable character
ch = (TCHAR) wParam;
HideCaret(hwndMain);
// Retrieve the character's width and output
// the character.
hdc = GetDC(hwndMain);
GetCharWidth32(hdc, (UINT) wParam, (UINT) wParam,
&nCharWidth);
TextOut(hdc, nCaretPosX, nCaretPosY * dwCharY,
&ch, 1);
ReleaseDC(hwndMain, hdc);
// Store the character in the buffer.
pchInputBuf[cch++] = ch;
// Calculate the new horizontal position of the
// caret. If the position exceeds the maximum,
// insert a carriage return and move the caret
// to the beginning of the next line.
nCaretPosX += nCharWidth;
if ((DWORD) nCaretPosX > dwLineLen)
{
nCaretPosX = 0;
pchInputBuf[cch++] = 0x0D;
++nCaretPosY;
}
nCurChar = cch;
ShowCaret(hwndMain);
break;
}
SetCaretPos(nCaretPosX, nCaretPosY * dwCharY);
break;
case WM_KEYDOWN:
switch (wParam)
{
case VK_LEFT: // LEFT ARROW
// The caret can move only to the beginning of
// the current line.
if (nCaretPosX > 0)
{
HideCaret(hwndMain);
// Retrieve the character to the left of
// the caret, calculate the character's
// width, then subtract the width from the
// current horizontal position of the caret
// to obtain the new position.
ch = pchInputBuf[--nCurChar];
hdc = GetDC(hwndMain);
GetCharWidth32(hdc, ch, ch, &nCharWidth);
ReleaseDC(hwndMain, hdc);
nCaretPosX = max(nCaretPosX - nCharWidth,
0);
ShowCaret(hwndMain);
}
break;
case VK_RIGHT: // RIGHT ARROW
// Caret moves to the right or, when a carriage
// return is encountered, to the beginning of
// the next line.
if (nCurChar < cch)
{
HideCaret(hwndMain);
// Retrieve the character to the right of
// the caret. If it's a carriage return,
// position the caret at the beginning of
// the next line.
ch = pchInputBuf[nCurChar];
if (ch == 0x0D)
{
nCaretPosX = 0;
nCaretPosY++;
}
// If the character isn't a carriage
// return, check to see whether the SHIFT
// key is down. If it is, invert the text
// colors and output the character.
else
{
hdc = GetDC(hwndMain);
nVirtKey = GetKeyState(VK_SHIFT);
if (nVirtKey & SHIFTED)
{
crPrevText = SetTextColor(hdc,
RGB(255, 255, 255));
crPrevBk = SetBkColor(hdc,
RGB(0,0,0));
TextOut(hdc, nCaretPosX,
nCaretPosY * dwCharY,
&ch, 1);
SetTextColor(hdc, crPrevText);
SetBkColor(hdc, crPrevBk);
}
// Get the width of the character and
// calculate the new horizontal
// position of the caret.
GetCharWidth32(hdc, ch, ch, &nCharWidth);
ReleaseDC(hwndMain, hdc);
nCaretPosX = nCaretPosX + nCharWidth;
}
nCurChar++;
ShowCaret(hwndMain);
break;
}
break;
case VK_UP: // UP ARROW
case VK_DOWN: // DOWN ARROW
MessageBeep(0xFFFFFFFF);
return 0;
case VK_HOME: // HOME
// Set the caret's position to the upper left
// corner of the client area.
nCaretPosX = nCaretPosY = 0;
nCurChar = 0;
break;
case VK_END: // END
// Move the caret to the end of the text.
for (i=0; i < cch; i++)
{
// Count the carriage returns and save the
// index of the last one.
if (pchInputBuf[i] == 0x0D)
{
cCR++;
nCRIndex = i + 1;
}
}
nCaretPosY = cCR;
// Copy all text between the last carriage
// return and the end of the keyboard input
// buffer to a temporary buffer.
for (i = nCRIndex, j = 0; i < cch; i++, j++)
szBuf[j] = pchInputBuf[i];
szBuf[j] = TEXT('\0');
// Retrieve the text extent and use it
// to set the horizontal position of the
// caret.
hdc = GetDC(hwndMain);
GetTextExtentPoint32(hdc, szBuf, lstrlen(szBuf),
&sz);
nCaretPosX = sz.cx;
ReleaseDC(hwndMain, hdc);
nCurChar = cch;
break;
default:
break;
}
SetCaretPos(nCaretPosX, nCaretPosY * dwCharY);
break;
case WM_PAINT:
if (cch == 0) // nothing in input buffer
break;
hdc = BeginPaint(hwndMain, &ps);
HideCaret(hwndMain);
// Set the clipping rectangle, and then draw the text
// into it.
SetRect(&rc, 0, 0, dwLineLen, dwClientY);
DrawText(hdc, pchInputBuf, -1, &rc, DT_LEFT);
ShowCaret(hwndMain);
EndPaint(hwndMain, &ps);
break;
// Process other messages.
case WM_DESTROY:
PostQuitMessage(0);
// Free the input buffer.
GlobalFree((HGLOBAL) pchInputBuf);
UnregisterHotKey(hwndMain, 0xAAAA);
break;
default:
return DefWindowProc(hwndMain, uMsg, wParam, lParam);
}
return NULL;
}