에디트에 대한 기초강좌를 마무리한 시점에서 질문이 하나 들어왔다..
지금까지의 내용을 기초로 에디트의 전체 배경을 바꾸었는데.. 깜빡이거나 먼가 이상하다...??

지난 강좌를 찾아보니, 에디트에 대한 배경 처리가 제대로 마무리 되지 못한 상태에서
강좌를 마쳐 혼란을 가져온것일 수 있을꺼 같아..
질문을 토대로 배경처리 기능을 마무리 하려고 한다.

위 그림은 두가지로 그 기능이 분류된다.

1. 왼쪽 에디트
-> 글자 바탕과 배경색상을 모두 녹색으로 처리한 것
2. 오른쪽 에디트
-> 글자 바탕은 TRANSPARENT 시키고, 바탕에는 HATCH 브러쉬를 뿌린것이다.

위 두가지 구현에는 다음과 같은 차이가 있다.
1번은 글자와 배경을 모두 그려주므로, 글씨를 쓸때 잔상이 남거나 깜빡임이 전혀없다.
2번은 글자는 쓰되 배경을 그려주지 않으므로 글씨를 쓸때 깜빡임은 없으나 잔상이 남는다.
이러한 이유로 두가지의 구현 부분에 조금 차이를 가지게 된다.

기본적인 코드는 브러쉬를 2개 만든다는 점만 빼고는 헤더에 추가할 내용은 없다.
BOOL CSssDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // 솔리드, 해치 브러쉬를 각각만든다.
    m_brush1.CreateSolidBrush(RGB(0, 255, 0));
    m_brush2.CreateHatchBrush(HS_DIAGCROSS, RGB(0, 255, 0));

    return TRUE;
}

// 클래스 위저드에서 WM_CTLCOLOR 이벤트 핸들러를 추가한다.
HBRUSH CSssDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

    switch (nCtlColor)
    {
    case CTLCOLOR_EDIT:
        pDC->SetTextColor(RGB(255, 0, 0));
        if (pWnd->GetDlgCtrlID() == IDC_EDIT1)
        {
            // 글자 바탕을 녹색으로 하고, 녹색 솔리드 브러쉬를 리턴한다.
            // 이게 전부다.
            pDC->SetBkColor(RGB(0, 255, 0));
            return m_brush1;
        }
        else if (pWnd->GetDlgCtrlID() == IDC_EDIT2)
        {
            // 글자의 배경을 그려주게 되면 바탕의 해치브러쉬 영역에 글자뒷 부분은
            // 녹색 사각형이 그려지게 된다.
            // 이를 막아주기 위하여, 배경그리는 기능을 제거한다. TRANSPARENT
            pDC->SetBkMode(TRANSPARENT);

            // 에디트 컨트롤 영역을 구한 후에
            // 브러쉬로 색칠해준다.
            CRect rc;
            GetDlgItem(IDC_EDIT2)->GetWindowRect(rc);
            ScreenToClient(rc);
            pDC->FillRect(rc, &m_brush2);

            return m_brush2;
        }
    }
    return hbr;
}

클래스위저드에서 IDC_EDIT2의 EN_CHANGE 이벤트 핸들러를 추가한다.
이 핸들러를 추가하는 이유는 두번째 에디트는 글자의 배경이 뒤에 그려지는 해치 브러쉬의
패턴을 덥어쓰는 걸 막아주기 위하여 TRANSPARENT 속성을 주었으므로, 글씨의 뒷부분을
그려주지 않게된다. 그러므로 잔상이 남게되어 글자에 대한 변경이 발생하면
배경을 다시 그려주도록 하기 위해서이다.
void CSssDlg::OnChangeEdit2()
{
    CRect rc;
    GetDlgItem(IDC_EDIT2)->GetWindowRect(rc);
    ScreenToClient(rc);
    InvalidateRect(rc);
}

49.zip
0.06MB

지금까지 진행해 왔던 과정을 돌이켜 보고, 몇가지 정리를 하면서 이러한 기능을 대부분 수용하는 샘플을 만들어 보았다.

1. 부모 다이알로그와 자식 다이알로그간의 데이터 전달.
2. 입력된 데이터의 올바른지 판단여부.
3. 최대 입력 수 재한
4. 데이터의 저장 및 비교
5. 글자 색상 변경
6. 다이알로그 배경색 변경

처음 프로그램을 실행 시키면 뜨는 화면

우선 가입하기 버튼을 누르면 조인할 수 있는 창이 뜬다.

우선 아이디를 입력한다. 아이디는 4-8자리 까지 제한이 있고,
영문과 숫자만 입력받는다.
[한글을 넣으면 오동작을 할 수 있다. 한글 처리는 여기서 다루지 않는다.]

아이디를 입력하고 중복 확인을 누른다.

암호를 입력하는 창이 활성화 되고 가입 버튼이 함께 활성화 된다.
적당하게 암호를 입력하고 가입을 누른다.

로그인 버튼이 활성화 되었다. 로그인 버튼을 눌러 보자.

아까전에 넣었던 정보를 정확하게 입력하면 모든 과정이 완료된다.

그러면 아래와 같은 환영 메시지가 출력되면서 모든 기능이 완료된다.

26.zip
0.05MB

그림과 같이 에디트 컨트롤이 5개 있는 화면이라고 가정해 보자..
위 화면에서 시리얼 키를 입력받는 다고 가정할 때.. 숫자영어로 조합된 5개 문자씩을 각각의
에디트에 입력받으려면 어떻게 구현해야 할까?

또한 에디트 하나에 5개의 문자가 입력되면 어떻게 자동으로 다음 에디트로 넘어갈까?
요런 자동화가 되어있지 않다면 하나씩 입력하고 5개 확인하고 탭 누르고 또 입력하고 탭 누르고..


그렇게 간단한건 아니지만 사용자 편의를 제공해야 하는 입장이라면 구현해야 할것이다.
아래는 WM_KEYDOWN메시지 하나로 몽땅 처리한 구조이다.
여러가지 방법이 존재하겠지만.. 이렇게도 구현할 수 있음을 보여주는 샘플이므로 참조해보자.

코드 자체가 난해하거나 어려운것이 아니므로, 하나씩 의미를 파악해 보면서 이렇게도 사용할 수 있구나
라는 것을 즐겨보자.. ^^;

BOOL CSssDlg::PreTranslateMessage(MSG* pMsg)
{
    if(pMsg->message == WM_KEYDOWN)
    {
        CWnd* pWnd = CWnd::FromHandle(pMsg->hwnd);
        CString str;
       
        if(isalnum(pMsg->wParam))
        {
            switch(pWnd->GetDlgCtrlID())
            {
            case IDC_EDIT1:
            case IDC_EDIT2:
            case IDC_EDIT3:
            case IDC_EDIT4:
            case IDC_EDIT5:
                GetDlgItemText(pWnd->GetDlgCtrlID(), str);
                if(str.GetLength() == 5)
                {
                    CEdit* pEdit = (CEdit*)pWnd;
                    int s, e;
                   
                    pEdit->GetSel(s, e);
                    if(s != e)
                        return CDialog::PreTranslateMessage(pMsg);
                   
                    if(pWnd->GetDlgCtrlID() != IDC_EDIT5)
                    {
                        GetDlgItem(pWnd->GetDlgCtrlID()+1)->SetFocus();
                        ((CEdit*)GetDlgItem(pWnd->GetDlgCtrlID()+1))->SetSel(0, -1);
                    }
                   
                    if(pWnd->GetDlgCtrlID() != IDC_EDIT5)
                        GetDlgItem(pWnd->GetDlgCtrlID()+1)->PostMessage(WM_KEYDOWN, pMsg->wParam, pMsg->lParam);
                   
                    return TRUE;
                }
                break;
            }
        }
        else if(pMsg->wParam == VK_BACK)
        {
            switch(pWnd->GetDlgCtrlID())
            {
            case IDC_EDIT1:
            case IDC_EDIT2:
            case IDC_EDIT3:
            case IDC_EDIT4:
            case IDC_EDIT5:
                GetDlgItemText(pWnd->GetDlgCtrlID(), str);
                if(str.GetLength() == 0)
                {
                    if(pWnd->GetDlgCtrlID() != IDC_EDIT1)
                        GetDlgItem(pWnd->GetDlgCtrlID()-1)->SetFocus();
                    return TRUE;
                }
                break;
            }
        }
        else
        {
            switch(pMsg->wParam)
            {
            case VK_HOME:
            case VK_END:
            case VK_UP:
            case VK_DOWN:
            case VK_LEFT:
            case VK_RIGHT:
            case VK_TAB:
                break;
            default:
                return TRUE;
            }
        }
    }
   
    return CDialog::PreTranslateMessage(pMsg);
}

아래는 구현된 샘플입니다.

17.zip
0.04MB

대부분의 컨트롤을 다룰 때 초기에는 별 필요성이 없다가, 이것 저것 기능을 처리할려다 보면 꼭 필요한
것들이 바로 이벤트를 핸들링 하는 일이다.
정확한 개념 이해를 위해서 MSDN의 원문을 첨가한다. 물론 딸려오는 한글 설명은 번역한 내용을 기술하는 것이 아니고, 그냥 정리된 개념을 서술하는 것이다.

에디트 컨트롤에 특화되어 제공되는 이벤트는 다음과 같이 8개가 있다.

1. EN_CHANGE
The EN_CHANGE notification message is sent when the user has taken an action that may have altered text in an edit control. Unlike the EN_UPDATE notification message, this notification message is sent after the system updates the screen. The parent window of the edit control receives this notification message through a WM_COMMAND message.

위 이벤트는 에디트 박스에서 데이터를 입력하거나 수정, 제거 등의 행동을 취하면 발생하는 이벤트이다.
이런걸 사용하는 이유는 방금 입력되거나 수정된 데이터가 올바른지, 혹은 어떤 정해논 범위의 캐릭터가 들어오는지, 아니면 범위를 초과하는지 등등등.. 변화에 민감하게 바로 바로 처리할 수 있도록 할 때 사용한다.

예를 들면 입력을 16진수로만 받아 들인다고 가정했을 때 입력 받을 수 있는 범위는
012345678ABCDEFX이다. 방금 입력된 값이 저 범위에 들어가지 않는다면 삑 소리를 내주거나 메시지 박스등을 뛰워 사용자로 부터 잘못된 입력이 있음을 경고해 줄 수도 있다.

2. EN_ERRSPACE
The EN_ERRSPACE notification message is sent when an edit control cannot allocate enough memory to meet a specific request. The parent window of the edit control receives this notification message through a WM_COMMAND message.

개발하면서 사실상 한번도 써본적이 없는 메시지이다. 에디트에 어떤 입력이 있을 경우 당연히 그것을 저장할 공간이 할당되어야 한다. 그런데 너무 많이 데이터를 넣어서 더이상 처리될 공간이 없을 때 발생하는 메시지이다. 요즘 윈도우에선 사실상 걸어놔도 걸릴지 의문이다 -_-;

3. EN_HSCROLL, EN_VSCROLL
The EN_HSCROLL notification message is sent when the user clicks an edit control's horizontal scroll bar. The parent window of the edit control receives this notification message through a WM_COMMAND message. The parent window is notified before the screen is updated.

데이터를 입력하면서 수평/수직 스크롤바에 크기 변경이 생기거나, 사용자가 에디트 박스의 수평/수직 스크롤바를 이동시키면 발생하는 이벤트이다. 이 이벤트 또한 사용자가 에디트 내부를 직접 건드리거나 하지 않는 이상 자주 사용되지 않는다. 샘플을 기준으로 간단하게 어떻게 저 정보를 이용하는지 코드를 적어본다.

void CSssDlg::OnHscrollEdit1()
{
    SCROLLINFO info;
    GetDlgItem(IDC_EDIT1)->GetScrollInfo(

SB_HORZorSB_VERTorSB_BOTH

, &info);
}
위와 같이 현재 에디트 컨트롤의 포인터를 얻어와서 GetScrollInfo에 인자를 채운후 호출하게 되면 info라는 구조체에 현재 스크롤바의 모든 정보가 들어오게 된다.

4. EN_SETFOCUS, EN_KILLFOCUS
The EN_SETFOCUS notification message is sent when an edit control receives the keyboard focus. The parent window of the edit control receives this notification message through a WM_COMMAND message.

사용자가 마우스나 TAB버튼을 이용하여, 에디트 컨트롤에 포커스가 갔을 경우나, 혹은 포커스가 있는 상태에서 다른 컨트롤등으로 포커스가 이동할 경우에 발생하는 이벤트이다. 요런걸 어떨 때 사용하냐면..
검색창등에 있는 에디트 컨트롤을 보면..
<검색어를 입력하세요> 라고 써있어서, 마우스로 콕 찍으면 저 문자열이 사라지고 글자를 입력할 수 있는 상태가 되는걸 본적이 있을 것이다. 기타 등등의 이유가 많겠지만..

5. EN_MAXTEXT
The EN_MAXTEXT notification message is sent when the current text insertion has exceeded the specified number of characters for the edit control. The text insertion has been truncated.

에디트 컨트롤을 변수로 연결할 하고 나서, 클래스 위저드를 열 은 후에..


IDC_EDIT1 을 m_data라고 하는 CString 변수에 연결 한 후.. Memver Variable 라는 탭을 열어 보면 현재 다얄로그 폼에 존재하는 컨트롤과 어떤 변수가 연결되어 있는지 쭈욱 항목이 나온다.
거기서 Maximum Characters : 라는 곳에 5라고 넣었다.
의미는 현재 에디트 IDC_EDIT1에는 최대 5개까지의 문자를 입력 받을 수 있도록 제한을 걸었다는 것이다.

저렇게 제한을 걸어 놓았을 경우 6번째 문자가 입력되면 EN_MAXTEXT이벤트가 발생하게 된다.
void CSssDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CSssDlg)
    DDX_Text(pDX, IDC_EDIT1, m_data);

    DDV_MaxChars(pDX, m_data, 5);


    //}}AFX_DATA_MAP
}
라고 추가되는 것이 보일 것이다.
개념을 다시 되 집어 보면, 저걸 직접 손으로 코딩해도 하등 문제가 없다는 이야기이다.
DoDataExchange 에 변수와 컨트롤을 연결하는 DDX_ , DDV_ 계열의 매크로는 상당히 다양하지만 현재 그렇게 까지 자세하게 설명하진 않을 것이다. [궁금하면 콕 찍은 다음 F12를 눌러 보아라]

6. EN_UPDATE
The EN_UPDATE notification message is sent when an edit control is about to redraw itself. This notification message is sent after the control has formatted the text, but before it displays the text. This makes it possible to resize the edit control window, if necessary. The parent window of the edit control receives this notification message through a WM_COMMAND message.

이 이벤트는 에디트 컨트롤을 다시 그려야할 필요가 있는 모든 경우에 발생하는 이벤트이다. EN_CHANGE는 문자열에 대한 변과하 있을 때만 발생하지만, 컨트롤의 크기가 변경된다던가 스타일을 바꾼다던가.. 외관상 및 내부 데이터가 바뀔 때 모두 발생한다는 점이 다르다..

아래 그림은 예제 샘플의 화면이다. 위에 나온 내용중에 몇가지를 구현하여 보았다.

16.zip
0.04MB

에디트 컨트롤의 배경을 투명하게 만드는 건 쉬운일이 아니다..

www.codeguru.com(이하 그루)이나 www.codeproject.com (이하 플젝)에 찾아보면..
그나마 플젝 사이트에나 쓸만한거 하나 건질 수 있다.

버뜨... 에디트 컨트롤 배경하나 투명하게 만들자고.. 클래스 나부랭이를 자꾸 추가하는건..
전혀 입맞에 맞는일이 못된다.
작업하다 보면 늘어나는 클래스에 골머리 뽀사지고, 이기능 넣느라 이 클래스 추가하고
저 기능 넣느라 저거 추가하고.. ㅜㅜ

그냥 다얄로그에 몇줄 추가해서 해결할 방법이 있을까? 당연히 있다.. ㅎㅎ
좀 귀찬긴 하지만 원하는 기능을 만드는 즐거움을 어떤것에 비할까..

이전의 샘플 sample2.zip 프로젝트를 조금 변화 시켜보았다.
배경에 그림을 하나 깔고.. 에디트를 올려서 처리하는 것이다.



이전의 IDC_EDIT9 에디트가 글자가 빨강 색으로 나오는걸 타겟으로 잡았다.

다아일로그에서 클래스 위저드를 띄운 후..
1. PreTranslateMessage 이벤트 핸들러를 추가한다.
2. Object IDs: IDC_EDIT9를 선택하고 EN_CHANGE 이벤트 핸들러를 추가한다.

그리고 코드를 다음과 같이 수정한다.

HBRUSH CSssDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
   
    switch(nCtlColor)
    {
    case CTLCOLOR_EDIT:
        {
            if(pWnd->GetDlgCtrlID() == IDC_EDIT9)
            {
                pDC->SetTextColor(RGB(255, 0, 0));
               

                pDC->SetBkMode(TRANSPARENT);
                pDC->SelectStockObject(NULL_BRUSH);
                return NULL;

            }
        }
    }
   
    // TODO: Return a different brush if the default is not desired
    return hbr;
}

BOOL CSssDlg::PreTranslateMessage(MSG* pMsg)
{
   

if(::GetDlgCtrlID(pMsg->hwnd) == IDC_EDIT9)
    {
        // 에디트 컨트롤 IDC_EDIT9 번의 이벤트 중에서 아래 이벤트가 발생하면
        // 에디트 컨트롤 영역만큼 부모 윈도우의 화면을 갱신한다.

        switch(pMsg->message)
        {
        case WM_LBUTTONDOWN:
        case WM_LBUTTONUP:
        case WM_KILLFOCUS:
            {
                CRect rc;
                CWnd* pWnd = GetDlgItem(IDC_EDIT9);
                pWnd->GetWindowRect(rc);
                ScreenToClient(rc);
                InvalidateRect(rc);
            }
        }
    }

   
    return CDialog::PreTranslateMessage(pMsg);
}

// 이 것을 PreTranslateMessage 에서 처리하지 못하는 이유는
// 이벤트를 잡을 수 없기 때문이다.
// 이 전체 기능을 CEdit서브클래싱하여 구현하여 놓은 것이 플젝사이트의 샘플이라고 봐도 무방하다.


void CSssDlg::OnChangeEdit9()
{

    // 에디트 컨트롤에서 글자에 변화가 생기면.
    // 에디트 컨트롤 영역만큼 부모 윈도우의 화면을 갱신한다.

   

    CRect rc;
    CWnd* pWnd = GetDlgItem(IDC_EDIT9);
    pWnd->GetWindowRect(rc);
    ScreenToClient(rc);
    InvalidateRect(rc);

}


샘플을 실행하면 화면이 좀 구리지만.. 참고하는데는 문제 없다 -_-;;;

18.zip
0.04MB

에디트 컨트롤의 글자는 보통 윈도우의 기본 화면체를 따르게 된다.
울나라 한글 윈도우는 - 글씨체:굴림, 크기 9pt이다.

위의 그림은 아이디쪽의 폰트는 이탤릭 스타일을 넣어 보았고,
일기장의 글씨는 크기를 20pt로 키워보았다.

글씨체.. 즉,  FONT는 MFC에서도 CFont라고 하는 잘 관리된 클래스로 기능을 제공한다.
여기서 할일은 CFont라는 객체를 생성해서 위에서 나오는것과 같은 속성을 부여한 다음에
컨트롤에다가 이 폰트를 쓰거라... 라고 해주면 끝난다.

두가지 스타일이므로 
다이알로그의 헤더에 다음과 같이 폰트를 선언하였다.
 CFont m_bigfont;
 CFont m_stylefont;

이제는 소스에서 저 폰트를 각 속성별로 생성하여 에디트에 연결해 주어야한다.

BOOL CSssDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // 중략

     // 큰크기의 폰트를 만든다.
     m_bigfont.CreatePointFont(200, "굴림");
     // IDC_EDIT8 컨트롤에 이 폰트를 써라라고 알려준다.
     GetDlgItem(IDC_EDIT8)->SetFont(&m_bigfont);

     // 윈도우에서 제공해주는 폰트의 여러가지 속성을 정리한 구조체.
     LOGFONT log;

    // 다이알로그가 가진 기본 폰트 정보를 얻어 온후 그 속성을 log 변수에 담는다.
     GetFont()->GetLogFont(&log);
     // 글자의 이탤릭 속성을 활성화 시킨다.
     log.lfItalic = TRUE;

     // 주어진 로그 폰트 속성을 이용하여 폰트를 생성한다.
     m_stylefont.CreateFontIndirect(&log);
     // IDC_EDIT8 컨트롤에 이 폰트를 써라라고 알려준다.
     GetDlgItem(IDC_EDIT1)->SetFont(&m_stylefont);

    // 중략
}

CFont 나  LOGFONT를 오늘 처음 접하신 분들이나 대충 책에서만 보아왔던 사람이라면
소스에서 마우스로 클릭하고 F12를 눌러 보아라.
그러면 자동으로 그 선언부로 이동하여 어떤 구조를 가지고 있는지 자세히 보여줄 것이다.
또한  MSDN을 참조하여 그 설명을 살펴보아두면 다음에, 다른 컨트롤이나 윈도우의 글씨체나
속성을 변경할 때 큰 도움이 될것이다.

또한 GetDlgItem 함수와 SetFont, GetFont와 같은 기본 함수도 외워두면 좋다.

 

14.zip
0.03MB






저번에 이어 에디트 컨트롤을 사용하면서 글자색이나 배경색을 바꾸는 것에 대하여 알아보자.
이 기능은 에디트 컨트롤 뿐만 아니라, 거의 모든 문자열 입출력이 있는 컨트롤에 해당하는 기능이므로
잘 알아두면 다른 컨트롤에서도 쉽게 사용할 수 있다.

다이알로그의 이벤트 중에 WM_CTLCOLOR 라는 이벤트가 있습니다.

저걸 추가하고 나면 화면상에 다음과 같은 코드가 자동으로 추가됩니다.

HBRUSH CSssDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
   
    // TODO: Return a different brush if the default is not desired
    return hbr;
}

1. CDC* pDC - MFC에서 제공하는 디바이스 컨텍스트
2. CWnd* pWnd - 대상이 되는 다이알로그에 올려진 컨트롤 윈도우
3. UINT nCtlColor -  대상이 되는 컨트롤의 구분 타입.

3번의 대상이 되는 컨트롤의 구분 타입은 다음과 같습니다.
이는 winuser.h에 선언되어 있구요.
#define CTLCOLOR_MSGBOX         0
#define CTLCOLOR_EDIT                1
#define CTLCOLOR_LISTBOX          2
#define CTLCOLOR_BTN                 3
#define CTLCOLOR_DLG                 4
#define CTLCOLOR_SCROLLBAR     5
#define CTLCOLOR_STATIC             6

나는 에디트 컨트롤을 대상으로 작업을 하므로 CTLCOLOR_EDIT 를 사용할 것입니다.
그럼 다음과 같은 코드를 추가해 봅니다.

HBRUSH CSssDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
   
    switch(nCtlColor)
    {
    case CTLCOLOR_EDIT:
        {
           if(pWnd->GetDlgCtrlID() == IDC_EDIT9)
                pDC->SetTextColor(RGB(255, 0, 0));
           else if(pWnd->GetDlgCtrlID() == IDC_EDIT14)
                pDC->SetBkColor(RGB(0, 255, 0));
        }
    }
    // TODO: Return a different brush if the default is not desired
    return hbr;
}

의미를 해석해보면 IDC_EDIT9번을 가진 에디트 컨트롤의 글자색을 빨간색 RGB(255,0,0))으로
IDC_EDIT14번을 가진 에디트 컨트롤의 글자 배경색을 녹색 RGB(0,255,0)으로 바꿔라 입니다.

여러개를 한꺼번에 바꾸거나, 그런건 머 위의 코드를 약간 수정하면 될테니 그건 손수 한번 해보세요.

다음에는 에디트 컨트롤의 폰트를 한번 변경해 보도록 하겠습니다.

13.zip
0.03MB

일단 외부에서 입력을 받는 모든 곳에서 사용할 수 있습니다.
또한 입력해 놓은 값을 살펴볼 때, 편집할 때 모두 사용가능하죠..

아이디와 암호를 입력 받는다던가, 주소록을 기록할 때, 어떤 계측 장비의 설정값을 입력할 때
제품 시리얼 키를 입력할 때, 전자 일기장을 쓰고 편집한다던지.. 먼가 문자를 기록하는 모든 곳에
사용된다고 보시면 됩니다. notepad도 CEdit컨트롤을 이용하면 간단하게나마 만들어 볼 수도 있습니다.


위에서 보는것 처럼 에디트의 활용은 엄청나고 거의 모든 윈도우 폼에 사용된다.
저렇게 여러가지 기능을 에디트로 쉽고 편리하게 사용할 수 있다.

그렇다면 폼에는 저렇게 올렸는데, 프로그램에서 저 값들을 어떻게 읽고, 업데이트 하고 하는 것들을
처리할 수 있는가?

MFC에서는 에디트 컨트롤을 프로그램에서 사용하기 위하여 여러가지 방법을 제공해준다.
[팁. MFC에서는 컨트롤을 올리고 어떤 작업을 취하기 않고서도 컨트롤의 모든 기능을 프로그램에서
쉽게 사용할 수 있도록 그 기능을 제공해준다. 특별하게 책에 나온것 처럼 변수나 컨트롤에 연결하지
않아도 CTempWnd라는 임시 윈도우로 연결되어 CWnd의 모든 기능을 가져다 쓸수도 있다
.]

1. 변수와 연결하여 UpdateData(TRUE | FALSE)를 이용하여 값을 읽고 쓴다.
2. CEdit컨트롤에 연결하여 컨트롤의 내부 기능을 이용하여 값을 읽고 쓴다.
3. 그대로 놓고 위의 팁처럼 CWnd의 기능을 이용하여 값을 읽고 쓴다.

우선 저런 기능을 하기 위하여 가장 쉽게 클래스 위저드를 이용하여 처리해 봅시다.
리소스 폼에서 Ctrl+W를 누르거나 오른쪽 마우스의 메뉴를 이용하여 띄운다.


Object ID: 현재 선택된 다이알로그 폼의 클래스와, 거기에 올려져 있는 컨트롤의 ID목록이 함께 나온다.
Messages : 오브젝트 ID를 선택하면 해당 컨트롤에서 사용할 수 있는 필터링된 이벤트 목록이 나온다.
Member functions : 현재 폼에서 이미 사용되고 있는 멤버 가상함수와 이벤트 핸들러 목록이 나온다.
Add Class : 현재 프로젝트에 새로운 클래스를 추가할 수있는 워저드를 제공한다.
Add Function : 선택된 이벤트의 핸들러를 추가하거나 제공되는 가상함수를 오버라이딩한다.
Delete Function : 맴버 펑션에 선택된 아이템을 제거한다. (구현부는 직접 지워줘야한다.)
Edit Code : 선택된 멤버 펑션함수를 에디팅 상태로 편집창에 보여준다.

대충 설명을 달았는데, 이건 현재 세션의 관심사가 아니므로 그냥 그런가 보다 해도 지장없다.
[사실 저런 기능은 대부분 책을 보고 참조하는게 더 좋고 빠르다. 책이 좋지.. ㅎ~]

위 화면의 두번째 탭 Member Variables 선택해보자.
그리고, IDC_EDIT1을 선택한 후 Add Variable이라는 버튼을 클릭한 화면이다.


Member Variable Name: 변수의 이름
Category : 선택된 컨트롤ID를 변수에 연결할 건지, 컨트롤에 연결할 것인지를 결정한다.
Variable Type : 변수로 선택하면 선택 가능한 변수 타입이 나오고, 컨트롤을 연결하면 연결 가능한 컨트롤 클래스가 나열된다.

카테고리에서 변수의 값과 컨트롤로 연결하는 2가지가 나오는데.. 이건 나중에 다루자.
[보통 폼에서 값을 단순하게 받아들이는 형태일 경우는 변수 값으로 대부분 사용하고
에디트 컨트롤의 외양에 먼가 변화를 줄 때는 컨트롤로 많이 연결한다.
]

멤버 변수 이름에 m_first라고 입력한 후 OK를 눌러보자.
그러면 다음과 같은 것이 새로 생겨있을 것이다.


위의 빨간 똥그라미 부분은 컨트롤로 연결할 때는 보이지 않으며 변수로 연결할 경우 특수한 값에 따라 보여지거나 그 형태를 달리한다.
현재는 변수가 CString 형태로 연결되었으므로 입력되는 최대 제한 길이를 설정할 수 있도록 도와주고 있다.
그리고 다시 OK를 눌러 편집창으로 돌아온다.

그러고 나면 다이알로그의 헤더파일과 소스 파일에 m_first라는 글자가 3곳 추가되어 있을 것이다.
1. 헤더에서는 변수의 선언부에.
2. 소스 생성자에서 초기화 하는 부분
3. 소스 DoDataExchange 메서드에서 컨트롤 아이디와 변수를 자동으로 연결 시켜주는 부분.

이렇게 하면 컨트롤에 어떤 글자를 입력하고 그것을 받아서 응용프로그램에서 관리할 수 있는 준비는
모두 끝난것이다.

화면에 입력한 값을 읽어 올 때는
UpdateData(TRUE);

변수에 내가 값을 집어 넣고, 그게 화면에 반영되도록 할 경우는
UpdateData(FALSE);

이 간단한 로직으로 CString 타입의 m_first라는 변수를 마음대로 사용할 수 있다.

다음에 시간나면 첫번째 그림에서 전압에 글씨가빨간색으로

거리비의 배경이 녹색으로 나온것에 대하여 설명할 것이다. 모든지 뽀대가 나야지 ㅎㅎ~

의미.
지금 글을 보여주는 것과 같이 사용자로 부터, 어떠한 글을 입력받거나 혹은 입력된 글을 보여주거나
하는 기능을 제공한다.

기본기능.
1. 글을입력한다.
2. 복사-잘라내기-붙히기 등의 기본 기능과 메뉴를 제공한다.
3. 저장된 글을 불러와 편집가능하도록 제공되거나 읽기 전용으로 사용할 수 있다.

워크스페이스에서 리소스 편집창을 열면 오른쪽에 동그라미 처진 것이 에디트 컨트롤이다.

다이알로그에 에디트 컨트롤을 올리기 위해서는 드래그&드랍을 이용하거나, 툴바에서 에디트 컨트롤을 클릭하고, 다시 다이알로그의 적당한 위치에서 클릭하면 그 위치에 에디트 컨트롤이 생성된다.
위의 그림은 대표적인 4가지 속성의 에디트 컨트롤을 보여준다.
1. 일반적인 상태
2. Disable 된 상태
3. Password 입력 상태
4. 읽기 전용 상태.
그 밖의 여러가지 상태가 있지만 보통 기본적으로 저런 형태로 가장 많이 사용된다.

그렇다면 저 에디트 컨트롤은 어떠 어떠한 속성값을 가지고 있을까?
에디트 컨트롤을 선택한 다음 Alt+Enter를 누르거나, 오른쪽 마우스로 메뉴를 띄운 후 프로퍼티를 선택하자

1. ID - 개별 컨트롤을 구별하는 하나의 리소스 창에서 유일하게 구분되어지는 키 값.
    (다이알로그 몇개 있을 때, 각각의 다이알로그 마다 IDC_EDIT1을 가질 수 있다.)
2. Visible - 초기에 컨트롤이 자동으로 사용자 눈에 보이게 한다.(당연히 첵크 박스를 없애면 않보인다.)
3. Group - 그룹 속성으로 나중에 그룹박스 컨트롤편에서 다루게 될것이다.
4. Help ID - 도움말 기능을 추가하게되면 해당 아이디를 도움말의 구분 키로 사용하게 된다.
5. Disable - 초기에 컨트롤이 사용 불가능하게 된다.
6. Tab Stop - 다이알로그 위에 올려진 콤포넌트는 TAB(shift+TAB)키를 이용하여 전환이 가능하다.
   (이걸 꺼 놓으면 탭으로의 이동이 불가능하고 사용자가 직접 클릭해야한다.)

스타일 페이지는 말 그대로 에디트 컨트롤의 스타일을 변경할 수있도록 해준다.

1. Align Text - 말 그대로 문자열이 left, center, right로 정렬되어 보여진다.
2. Multiline - 쓰여진 문자열이 화면 폭을 넘어갈때 여러줄로 보여줄지를 결정한다.
3. Number - 말그대로 숫자만 입력할 수 있도록 설정된다.
4. Horizontal Scroll - 수평 스크롤 바를 보여준다.
5. Auto HScroll - 글자가 화면너비을 넘어갈 경우 자동으로 스크롤바를 활성화 하여 스크롤 가능하게 한다.
6. Vertical Scroll - 수직 스크롤 바를 보여준다.
7. Auto VScroll - 글자가 화면폭을 넘어갈 경우 자동으로 스크롤바를 활성화 하여 스크롤 가능하게 한다.
8. Password -  글자를 입력하면 **** 와 같이 보여주도록 하여 주요글자가 시작적으로 노출되지 안도록한다.
9. No hide selection - 에디트 컨트롤에서 문자열을 선택하였을 경우, 다른 윈도우가 활성화 되면 선택하여 표시해 놓은 마크가 보여지지 않게 된다. 물론 다시 창을 활성화 하면 보여지게 되지만, 이 옵션을 켜 놓으면 항상 언제나 선택한 드래그 영역을 볼 수있다.
10. OEM Convert - 국가 설정에 맞도록 자동으로 문자열 타입을 변환(문자열 종류가 여러가지다)
11. Want Return -  컨트롤 내부에서 Enter키를 이용하여 줄바꿈을 할 수 있도록 지원한다.
12. Border - 컨트롤에 외곽 검은색 그림자 테두리를 보여준다.
13. Uppercase - 말 그대로 입력된 모든 글자를 대문자로 보여준다(실제 입력된 글자체는 그대로다.)
14. Lowercase - 입력된 글자를 모두 소문자로 보여준다.
15. read-only - 이미 저장된 내용을 보고 선택하고 복사할 수는 있지만 편집할 수는 없다.

요건 확장 스타일이라는 건데.. 나중에 알게 되겠지만 보통 WS_EX_...로 시작되는 넘들이다.
1. Client edge - 컨트롤의 클라이언트 영역, 즉 내부영역에 그림자 외곽 박스를 그린다.
2. Static edge - 1번과 비슷하지만 왼쪽과 상단부의 그림자만 그린다.
3. Modal Frame - 다얄로그의 외곽처럼 툭 튀어나오게 그린다.
4. Transparent - 배경을 그리지 않는다.
5. Accept files - 파일을 드래그 하여 놓았을 때, 그 정보를 인지할수 있다.
6. Right aligned text - 입력한 글자가 오른쪽에 정렬되어 보여진다.
7. Right-to-left reading order - 외국에는 입력을 한국과 다르게 하는 나라 들이 있다. 그리하여 글자를 입력하면 오른쪽부터 왼쪽으로 보여지며 입력하게 된다.
8. left scroll bar - 수직 스크롤바가 생길 때 왼쪽에 생기도록 한다.

이상으로 아주 간단하게 나마, 윈도우 폼에서 사용되는 에디트 컨트롤의 기본 속성에 대하여 살펴보았다.
다음에 시간이 되면 간단한 활용부터 응용까지 쭈욱 한번 달려보자.

+ Recent posts