블로그 이미지
인생의무한루프
인생에 무한루프.....

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

Tag

Recent Post

Archive

Recent Comment

Recent Trackback

2008. 12. 16. 23:26 Appication/VC++_Control

간단한 색상 보기. ( MFC Scroll 예제 )

지금까지 진행한 내용을 바탕으로 간단한 색상보기 샘플을 제작해 보겠습니다.
실행한 모양은 아래 처럼 됩니다.



설정 조건
1. 스크롤바를 3개 만들고 모든 범위는 0 - 255 까지이다.
2. 각각 좌측부터 Red, Green, Blue의 삼원색을 제어한다.
3. 오른쪽 사각영역에 주어진 RGB 컬러대로 색칠을 해준다.

-----------------------------------------------------------------------------------
허데 파일의 내용.. 발췌

// Dialog Data
    //{{AFX_DATA(CSampleDlg)

    enum { IDD = IDD_SAMPLE_DIALOG };
    CScrollBar m_scroll3;
    CScrollBar m_scroll2;
    CScrollBar m_scroll;

    //}}AFX_DATA

    // 색칠할 사각형 영역
    CRect m_rect;
    // 색상값
    COLORREF m_rgb;
    void ChangeColorBox(CScrollBar* pBar, UINT nPos);

-----------------------------------------------------------------------------------
소스 파일의 내용.. 발췌

// RGB 단위 값의 최소/최대
#define SCROLL_MIN  0
#define SCROLL_MAX  255

// COLORREF의 부분값을 변경하기 위한 제작된 매크로
#define
SetRValue(rgb, r)      ((rgb&=0xFFFFFF00)|=(BYTE)r)
#define SetGValue(rgb, g)      ((rgb&=0xFFFF00FF)|=((BYTE)g)<<8)
#define SetBValue(rgb, b)      ((rgb&=0xFF00FFFF)|=((BYTE)b)<<16)

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

    // 스크롤바와 연결된 컨트롤 3개에 대하여 모두 기본값들을 설정한다.
    m_scroll.SetScrollRange(SCROLL_MIN, SCROLL_MAX);
    m_scroll.SetScrollPos(0);
    m_scroll.EnableScrollBar(ESB_ENABLE_BOTH);
 
    m_scroll2.SetScrollRange(SCROLL_MIN, SCROLL_MAX);
    m_scroll2.SetScrollPos(0);
    m_scroll2.EnableScrollBar(ESB_ENABLE_BOTH);
 
    m_scroll3.SetScrollRange(SCROLL_MIN, SCROLL_MAX);
    m_scroll3.SetScrollPos(0);
    m_scroll3.EnableScrollBar(ESB_ENABLE_BOTH);
 
    // 화면에 그릴 영역의 사각 크기를 구한다.
    GetDlgItem(IDC_STATIC1)->GetWindowRect(m_rect);
    ScreenToClient(m_rect);

    // 기본 색상은 검은색이다.
    m_rgb = RGB(0,0,0);

    return TRUE;
}

// 정해진 색상으로 지정된 위치에 색칠한다.

void CSampleDlg::OnPaint()
{
    CPaintDC dc(this);
    dc.FillSolidRect(m_rect, m_rgb);
}

// 스크롤 이벤트 핸들러
void CSampleDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    if(!pScrollBar || !pScrollBar->m_hWnd)
        return;

    UINT nCurPos = pScrollBar->GetScrollPos();
    switch(nSBCode)
    {
    case SB_BOTTOM:
        pScrollBar->SetScrollPos(SCROLL_MAX);
        break;

    // 중간 생략...

     case SB_TOP:
        pScrollBar->SetScrollPos(SCROLL_MIN);
        break;
    }
 
    // 색상값에 변경이 있으면 다시 색칠을 해야지..
   ChangeColorBox(pScrollBar, nCurPos);

    CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}

// 색상값이 변경되면 어떤 스크롤바가 값이 얼마인지 계산을 해서
// RGB를 다시 계산한 후 색칠한다.

void CSampleDlg::ChangeColorBox(CScrollBar* pBar, UINT nPos)
{
    UINT nID = pBar->GetDlgCtrlID();
    switch(nID)
    {
    case IDC_SCROLLBAR5:
        SetRValue(m_rgb, nPos);
        break;
    case IDC_SCROLLBAR6:
        SetGValue(m_rgb, nPos);
        break;
    case IDC_SCROLLBAR7:
        SetBValue(m_rgb, nPos);
        break;
    }

    CClientDC dc(this);
    dc.FillSolidRect(m_rect, m_rgb);
}




이렇게 간단하게 나마 스크롤바에 대하여 공부해 보았습니다.
실상 알고 보면 크게 어렵거나 한 부분은 거의 없습니다. 자료가 부족할 뿐 ^^;

다음에는 리스트 컨트를을 진행해 보도록 하겠습니다.
즐거운 한주 되세요.. ^^;

Posted by 까막백(홈페이지 이동)
posted by 인생의무한루프
2008. 12. 16. 23:23 Appication/VC++_Control

스크롤바의 최대크기는 32767??? ( MFC Scroll 예제 )

스크롤바를 사용하다 보면 32767 unsigned short의 양의값을 넘어가는 경우가
간혹 발생할 수 있다.

그래픽 디자인 프로그램과 같은 것들을 설계할 때야 줌 팩터등을 이용하여 따로 처리하니
별 문제가 없겠지만 간단한 먼가를 만들 때 100000의 값을 써야한다면 먼가 설계를 해야하나?

그렇다면 우선 MSDN을 살펴보자.

CScrollBar::SetScrollRange
Set nMinPos and nMaxPos to 0 to hide standard scroll bars.
Do not call this function to hide a scroll bar while processing a scroll-bar notification message.

If a call to SetScrollRange immediately follows a call to the SetScrollPos member function, set bRedraw in SetScrollPos to 0 to prevent the scroll bar from being redrawn twice.

The difference between the values specified by nMinPos and nMaxPos must not be greater
than 32,767
. The default range for a scroll-bar control is empty

일단 스크롤바의 SetScrollRange의 인자는 int 값인데, 어쩌구 저쩌구한 이유로 32767이 최대
라고 한다. 인자가 int라면 그렇다면 먼가를 처리하면 최대 양수 20억까지 쓸수 있다는 야근데..


SetScrollRange Function Win32API
However, because the SetScrollInfo, SetScrollPos, SetScrollRange, GetScrollInfo,
GetScrollPos, and GetScrollRange
functions support 32-bit scroll bar position data,
there is a way to circumvent the 16-bit barrier of the WM_HSCROLL and WM_VSCROLL
messages. See GetScrollInfo for a description of the technique.

MSDN에서 API의 도움말을 살펴보았다. Remark를 자세히 보다보니 32비트를 쓸 수 있는데
16비트 베리어에 쌓여 있단다.. 그렇다면 위의 두 메시지에서 오는 UINT nPos 가 정수
범위임에도 불구하고 쇼트크기를 가진다면 저걸 않쓰면 가능하지 않을까...

(16비트 베리어라는 의미는 내부적으로 먼가를 처리할 때 아무생각 없이 16비트를 썼다는
내용을 아주 점잔하게 표시한 것으로 추측된다.. 즉, 16비트 머신의 잔제가 남았다는 거겠죠.)

--------------------------------------------------------------------------------------

일단 여기까지 살펴보면 32비트를 쓸 수 있는데도 불구하고, 메시지 WM_VSCROLL과
WM_HSCROLL의 UINT nPOS는 16비트 최대값을 가진다고 결론을 내릴 수있다.
즉, 저걸 않쓰면 된다는 이야기겠고..

그럼 저걸 않쓰고 프로그램을 구성하면 되겠죠..
이전 장에 있던 샘플은 0 부터 100까지 크기를 가지는 샘플이었습니다.
이걸 그럼 위의 지식을 기반으로 0부터 1000000 크기를 가지는 샘플로 바꿔보죠.

#define SCROLL_MIN   0
#define SCROLL_MAX  1000000

마이스크롤.SetScrollRange(SCROLL_MIN, SCROLL_MAX);
마이스크롤.SetScrollPos(50);
마이스크롤.EnableScrollBar(ESB_ENABLE_BOTH);

요렇게 설정을 해놓고 WM_VSCROLL 핸들러를 다음과 같이 수정해봅니다.
어짜피 이전 샘플에서도 nPos를 쓰는데는 스크롤바를 트래킹할 때만 썻으므로
이 샘플에서도 바뀌는 부분은 거기 밖에는 없습니다.

void CSampleDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    UINT nCurPos;
    if(pScrollBar->GetDlgCtrlID() == IDC_SCROLLBAR5)
    {
        nCurPos = pScrollBar->GetScrollPos();
        switch(nSBCode)
        {
        // 중간 생략.. 원본과 다른바 없음.
       case SB_THUMBPOSITION:
       {
          SCROLLINFO si = {0};
          si.cbSize = sizeof(SCROLLINFO);
          si.fMask = SIF_TRACKPOS;
          ::GetScrollInfo(pScrollBar->m_hWnd, SB_CTL, &si);

          // 메시지의 nPos 대신에 그냥 트랙포스를 가져다 쓴다.
          pScrollBar->SetScrollPos(si.nTrackPos);
       }
       break;

       case SB_THUMBTRACK:
       {
          SCROLLINFO si = {0};
          si.cbSize = sizeof(SCROLLINFO);
          si.fMask = SIF_TRACKPOS;
          ::GetScrollInfo(pScrollBar->m_hWnd, SB_CTL, &si);

          // 메시지의 nPos 대신에 그냥 트랙포스를 가져다 쓴다.
          pScrollBar->SetScrollPos(si.nTrackPos);
       }
       break;

      // 아래도 생략.. 원본과 같음
    }
 
    CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}

헉.. 그냥 않쓰면 되네.. ㅜㅜ;;;

그럼 수고하세요..

사용자 삽입 이미지














Posted by 까막백(홈페이지 이동)
posted by 인생의무한루프
2008. 12. 16. 23:19 Appication/VC++_Control

체크 박스와 라디오 버튼 ( MFC Check & Radio 예제 )

첵크 박스와 라디오 버튼은 CButton 에서 기능이 특화된 두 부류이다.
이전 강좌에서 CStatic를 Text와 Picture로 나누어 특화시킨것과 마찬가지이고...
물론 CButton 컨트롤을 동적생성해서 위 두 속성을 주어 변경하는 것도 당연히 가능하다..


위 그림은 첵크 박스의 사용 목적을 일목 요연하게 보여줄 수 있는 것이라 생각하고 캡처해 보았다.
그림에서 처럼 다양한 어떤 기능이나 옵션을 제공할 때 원하는 것을 하나 혹은 여러개를 선택할 수 있도록 사용자 인터페이스를 제공해 주는 목적을 가진다.
( 물론 위 그림처럼 트리와 첵크박스를 저렇게 이뿌게 조합할려면 노가다가 필수다 -_-;;;)
( 필자 생각으로는 UI는 노가다의 산물이 아닐까 라고 가끔 생각해 본다.. ㅎㅎ)


위의 그림은 곰플레이어의 옵션 다이알로그의 한 페이지를 캡처한 화면이다.
[자동으로 계속하기 설정]이라고 써있는 부분을 보면 3가지 기능이 나열되어 있고, 그 중에 하나를
선택할 수 있도록 되어있다.
위 처럼 하나의 주요한 기능를 여러가지 관점에서 바라 볼 수 있고, 사용자가 그 중에 하나를 선택하여 동작하도록 제공해주는 인터페이스가 라디오 버튼이다.

비슷하면서도 큰 차이점이..
첵크박스는 여러가지 옵션을 다양하게 선택할 수 있도록 해주는 반면
라디오 버튼은 하나의 관점에서 특화된 옵션을 다양한 각도로 선택할 수 있도록 제공해준다.


이제부터 리소스 편집창을 살펴보자.

왼쪽의 빨강 똥그라미는 첵크박스, 오른쪽의 파랑 똥그라미는 라디오 버튼이다.

이제 부터 각 컨트롤의 속성 페이지를 살펴보자.

우선 첵크박스의 프로퍼티중 스타일을 살펴본다. 나머지 탭들은 기존의 설명과 중복되어 생략한다.

1. Auto - 사용자가 마우스로 첵크박스의 사각형 부분을 선택하면 상태가 자동으로 토글된다.
  이 옵션을 꺼놓으면 사용자가 직접 상태를 모두 변경시켜주어야한다.
2. Left Text - 글자가 왼쪽으로 가고 첵크박스가 오른쪽으로 간다.
3. Tri State - 첵크/언첵크 외에 첵크된 상태에서 배경이 회색으로 바뀐다. 즉 3가지 상태를 가진다.

4. Push Like - 일반적인 푸쉬버튼과 같은 형태를 가진다.

5. Multiline - 글자를 다중 라인으로 작성할 수 있다.

6. Notify - 상태 변경등의 정보를 부모윈도우로 전달해준다.
7. Flat - 플랫한 모양으로 바뀐다.

8. Icon - 글자대신 아이콘을 넣을 수 있다.

9. Bitmap - 글자대신 비트맵을 넣을 수 있다.

10. Horizontal alignment - 수평 글자 정렬
11. Vertical alignment - 수직 글자 정렬

라디오 버튼의 속성을 살펴보자.

첵크박스의 속성과 대부분 같고, Tri State만 없는 것을 볼 수 있을 것이다.
모든 속성의 설명은 첵크박스와 같다..
당연한가? 모두 버튼이니까..
그렇다면? ...
...
그렇다 리소스상의 버튼의 속성중에 위와 중복되는 속성은 모두 동일하게 사용할 수 있다.

여기까지는 그냥 기본 속성의 설명이었을 뿐이고, 라디오 버튼은 General 페이지에 있는
Group라는 옵션에 지대한 영향을 받는다...

지금까지 다룬 다른 컨트롤들은 저 속성을 거의 그냥 무시하고 지나갔다.
[사실 필자도 다른 컨트롤에서 저 그룹 속성이 어떤 동작 특성을 가지는지는 잘 모른다 -_-]

지금까지 이해해온 대로라면 라디오 버튼은 비슷한 기능을 가진 옵션들을 모아놓고 그중에 하나를 선택하는 기능을 제공해준다고 하였다.

또한 Ctrl+D를 눌러 라디오 버튼을 순서대로 정렬해 놓으면 실행시킨 후에 선택할 수 있는 라이오 버튼 항목은 단 1개이다.

그렇다면 하나의 다이알로그 폼에 그런 선택속성을 가진 그룹이 여러개 존재한다면???

위의 빨간 글중에 파랑색으로 표기한 그룹이라는 단어가 눈에 띄일것이다....

그렇다, 저걸 첵크 해놓으면 저걸 첵크해놓은 라디오 버튼 중에 탭 오더가 낮은 것들은 자동으로 하나의 선택그룹으로 묶이게 된다.

여러개의 라디오 버튼을 여러개의 그룹으로 묶으려면? 중간에 특성이 갈라지는 놈의 속성 페이지를 열어서 저걸 첵크해놓으면 된다..

이렇게 첵크박스와 라디오 버튼의 속성을 간단하게 살펴보았다.
다음에는 우선 저 속성을 설명하면서 나타난 화면을 직접 구현해 보는 시간을 가져보고자 한다..


Posted by 까막백(홈페이지 이동)
posted by 인생의무한루프
2008. 12. 16. 23:15 Appication/VC++_Control

체크 박스의 속성 관찰 - Tri State ( MFC Check & Radio 예제 )

이전에 이어 첵크박스가 가지고 있던 속성중에 주요한 속성들을 살펴보겠다.
속성 페이지의 Styles 에서 기존에 못보던 Tri State라는  속성을 보았을 것이다.

사용자 삽입 이미지



샘플을 수행한 화면이다.
아래 상위의 두개 첵크 박스는 모두 Tri State 속성을 부여하였고, 나머지는 아니다.
사용자 삽입 이미지













일반적으로는 첵크상태(BST_CHECKED)와 막연한 상태???(BST_INDETERMINATE) 및
언첵크 상태(BST_UNCHECKED)로 구분되며...
이번 장에서는 BST_INDETERMINATE에 대하여 자세히 살펴본다.

우선 장을 진행하기에 앞서 살펴보아야할 것들에 대하여 나열해 보겠다.
ON_COMMAND_RANGE
IsDlgButtonChecked
EnableWindow
CheckDlgButton

중요한 내용들이며 각각 다음과 같은 기능을 제공한다. 특히나 ON_COMMAND_RANGE 는 UI를 다룰 경우 상당히 유용한 매크로이므로 알아두면 써먹을 곳이 많다.

1. ON_COMMAND_RANGE
제시 : 만약에 버튼이 100개 있다면? OnButton1 ~ OnButton100 까지 100개를 다 만들것인가?
MFC에서 제공해주는 아주 유용한 매크로로 여러개의 컨트롤 아이디를 하나의 함수로 매핑해주는
 기능을 제공한다. 이 기능을 이용하면 연속적인 아이디를 가진 컨트롤을 몽땅 한 함수에서 처리할
 수 있으므로 불필요한 함수의 증가를 막고, 코드 관리에 아주 유용하다.
단, 기능에서 보아 짐작할 수 있겠지만.. 저 매크로는 자동화로 제공되지 않으므로 개발자가 직접
손수 타이핑해주어야 한다.

2. IsDlgButtonChecked
첵크 박스의 첵크 상태를 읽어내는 함수로 CWnd의 멤버 함수이다.

3. EnableWindow
CWnd를 상속한 컨트롤의 활성화/비활성화를 처리해주는 멤버 함수이다.

4. CheckDlgButton
첵크 박스의 여러가지 첵크 상태를 임의로 변경해 줄 수 있는 CWnd의 멤버함수이다.

---------------------------------------------------------------------------------
다이알로그 헤더에 추가될 코드

 // 프로토콜 상위 첵크박스 상태.
 BOOL m_protocol;
 // 프로토콜 하위 첵크박스들의 상태.
 UINT m_protocol_sub;
 // 서포트 상위 첵크박스 상태
 BOOL m_support;
 // 서포트 하위 첵크박스들의 상태
 UINT m_support_sub;

 // 두개 그룹의 첵크 박스의 이벤트 핸들러를 묶어 놓은 Range 함수 2개.
 // 리턴값은 LRESULT 이고, 인자는 UINT 타입의 인자 1개이다. 잘 기억해두자.
 afx_msg LRESULT OnCheckProtocolRange(UINT nID);
 afx_msg LRESULT OnCheckSupportRange(UINT nID);

---------------------------------------------------------------------------------
다이알로그 소스에 추가될 코드

// 변수 초기화
CSssDlg::CSssDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSssDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CSssDlg)
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
   
    m_protocol = FALSE;
    m_support = FALSE;
    m_protocol_sub = 0;
    m_support_sub = 0;
}

// 메시지 등록
BEGIN_MESSAGE_MAP(CSssDlg, CDialog)
    //{{AFX_MSG_MAP(CSssDlg)
    //}}AFX_MSG_MAP
   
    // 메시지 맵에는 아래와 같은 용법으로 등록한다.
    // 첫번째는 시작되는 컨트롤 아이디,
    // 두번째는 마지막 컨트롤 아이디.
    // 세번째는 멤버함수 이름

    ON_COMMAND_RANGE(IDC_CHECK1, IDC_CHECK3, OnCheckProtocolRange)
    ON_COMMAND_RANGE(IDC_CHECK4, IDC_CHECK7, OnCheckSupportRange)

END_MESSAGE_MAP()


// 프로토콜 그룹의 첵크박스 핸들러
// 위 메시지 맵에 처럼 등록해 놓으면 IDC_CHECK1, IDC_CHDEK2, IDC_CHECK3 첵크시
// 모든 이벤트가 아래 함수로 온다. 물론 어떤 컨트롤을 건드렸는지는 nID 에 넘어온다.

LRESULT CSssDlg::OnCheckProtocolRange(UINT nID)
{
    // 어떤 놈을 건드렸나?
    switch(nID)
    {
    // 나는 상위 프로토콜 그룹 첵크 박스
    case IDC_CHECK1:
        {
            // IDC_CHECK1 이 첵크되어있나?
            // 이 코드는 Tri State를 가진 첵크 박스는 첵크를 하면 3가지 상태를 모두 토글하므로
            // IDC_CHECK1을 사용자가 직접 클릭했늘 경우는 CHECK/UNCHECK상태만을
            // 가지도록 처리해주는 루틴이다.

            BOOL bChecked = IsDlgButtonChecked(IDC_CHECK1);
            if(m_protocol == FALSE && bChecked)
                CheckDlgButton(IDC_CHECK1, BST_CHECKED),
                m_protocol = TRUE;
            else if(m_protocol == TRUE && bChecked)
                CheckDlgButton(IDC_CHECK1, BST_UNCHECKED),
                m_protocol = FALSE;
           
            // IDC_CHECK1 이 첵크되어 있다면 하부 첵크박스를 모두 활성화 시킨다.
            // 아니라면 모두 비활성화 시키지...

            GetDlgItem(IDC_CHECK2)->EnableWindow(m_protocol);
            GetDlgItem(IDC_CHECK3)->EnableWindow(m_protocol);
            return 0;
        }
    // IDC_CHECK1을 제외한 모든 첵크박스
    default:
        {
            // 현재 첵크박스가 몇번째 것인지 구한다.
            int n = nID - IDC_CHECK2;
            // 현재 첵크박스의 상태를 구한다.
            BOOL bChecked = IsDlgButtonChecked(nID);

            // 첵크 상태에 따라 m_protocol_sub 을 설정한다.
            if(bChecked)
                m_protocol_sub |= 0x01 << n;
            else
                m_protocol_sub &= ~(0x01 << n);
           
            // 상태에 따라 IDC_CHECK1의 첵크 상태를 변경시킨다.
            if(m_protocol_sub)
                CheckDlgButton(IDC_CHECK1, BST_INDETERMINATE);
            else
                CheckDlgButton(IDC_CHECK1, BST_CHECKED);
        }
    }
   
    return 0;
}

// 서포트 그룹의 첵크박스 핸들러
// 코드의 내부 기능 및 동작은 OnCheckProtocolRange 와 동일하다.
// 단지 구분하기 위하여 따로 놓았을 뿐...

LRESULT CSssDlg::OnCheckSupportRange(UINT nID)
{
    switch(nID)
    {
    case IDC_CHECK4:
        {
            BOOL bChecked = IsDlgButtonChecked(IDC_CHECK4);
            if(m_support == FALSE && bChecked)
                CheckDlgButton(IDC_CHECK4, BST_CHECKED),
                m_support = TRUE;
            else if(m_support == TRUE && bChecked)
                CheckDlgButton(IDC_CHECK4, BST_UNCHECKED),
                m_support = FALSE;
           
            GetDlgItem(IDC_CHECK5)->EnableWindow(m_support);
            GetDlgItem(IDC_CHECK6)->EnableWindow(m_support);
            GetDlgItem(IDC_CHECK7)->EnableWindow(m_support);
            return 0;
        }
    default:
        {
            int n = nID - IDC_CHECK5;
            BOOL bChecked = IsDlgButtonChecked(nID);
            if(bChecked)
                m_support_sub |= 0x01 << n;
            else
                m_support_sub &= ~(0x01 << n);
           
            if(m_support_sub)
                CheckDlgButton(IDC_CHECK4, BST_INDETERMINATE);
            else
                CheckDlgButton(IDC_CHECK4, BST_CHECKED);
        }
    }
   
    return 0;
}

------------------------------------------------------------------------------------
모두 7개의 첵크 박스를 하나씩 다 제어하려면 함수도 많아지고, 이만 저만 귀찬은 것이 아닐겁니다.
복잡한 UI는 수집개의 버튼과 수십개의 첵크박스, 에디트, 라디오, 에디트.. 를 동반하는데
일일이 하나씩 모두 할 필요는 없겠죠? ^^;

구지 함수를 2개가 아닌 1개로 해도 되지만, 이를 나눈 이유는 코드 수를 줄이는 것도 중요하지만
서로 다른 그룹임을 구분해 주는 것이 나중에 코드를 수정하거나 보완할때 수월하기 때문입니다.




Posted by 까막백(홈페이지 이동)
posted by 인생의무한루프
2008. 12. 16. 23:13 Appication/VC++_Control

첵크와 라디오의 공통속성 ( MFC Check & Radio 예제 )

첵크 박스의 Tri State는 라디오에는 없는 단독 속성이라 따로 설명을 하였다.
저 속성은 옵션 다이알로그를 만들거나 복합 옵션들을 구현할 때 사용되는, 상당히 직관적인 속성이다.

다음은, 첵크와 라디오가 가지는 공통속성 중에서 특별하게 다루어야할 만한 것들 을 골라보았다.
머 그래봤자 남는거라고는 멀티라인, 아이콘, 이미지 정도이다.



그림의 아래쪽에 보이는 색상 변경 부분은 그동안 다루었던 에디트와 스태틱 컨트로에서 사용되었던 배경 투명화와 색상 변경하기 기법을 적용하였다.
매 컨트롤마다 써먹으면 식상(?)하니 한군데 몰아부처 이렇게도 사용할 수 있음을 예시한다.

1. 아이콘 로딩.
첵크 박스나 라디오 버튼에서 Styles 페이지에서 Icon 속성을 첵크한다.

// 첫번째 첵크박스의 포인터를 얻은 후 CButton으로 형변환한다.
CButton* pButton = (CButton*)GetDlgItem(IDC_CHECK1);
// 아이콘을 로딩한 후 SetIcon 메서드를 이용하여 아이콘을 넣어준다.
pButton->SetIcon(::LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME)));

2. 비트맵 로딩.
첵크 박스나 라디오 버튼에서 Styles 페이지에서 Bitmap 속성을 첵크한다.
// 첫번째 첵크박스의 포인터를 얻은 후 CButton으로 형변환한다.
CButton* pButton = (CButton*)GetDlgItem(IDC_CHECK1);
// 비트맵을 로딩한 후 SetBitmap 메서드를 이용하여 비트맵을 넣어준다.
pButton->SetBitmap(::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP3)));

3. Pushlike
첵크 박스나 라디오 버튼에서 Styles 페이지에서 Pushlike속성을 첵크한다.
이 속성은 별거 없어보이지만, 이걸 이용하면 버튼을 2가지 상태로 (눌린상태, 아닌상태)로 아주 쉽게 구분하여 하나의 버튼을 다양하게 이용할 수 있다.

만약 파워버튼이라고 가정하면..
1. 튀어 나와있을 때 - 캡션 파워오프
2. 눌려져 있을 때 - 캡션 파워온
등.. 상태를 표현할 경우는 그냥 CButton보다 쉽게 접근하여 사용이 가능하다.

4. Multiline
첵크 박스나 라디오 버튼에서 Styles 페이지에서 Multiline 속성을 첵크한다.
표현 해주고자 하는 캡션이 길 때 사용한다.

5. 배경의 투명화와 색상 변경.
// 아래 코드는 이제 설명하지 쉽게 이해할 수 있을 것이다.
HBRUSH CSssDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
 
    if(pWnd->GetDlgCtrlID() == IDC_CHECK8 || pWnd->GetDlgCtrlID() == IDC_RADIO9)
    {
        pDC->SetTextColor(RGB(255, 0, 0));
        pDC->SetBkColor(RGB(0, 255, 0));
    }
    else if(pWnd->GetDlgCtrlID() == IDC_CHECK9 || pWnd->GetDlgCtrlID() == IDC_RADIO10)
    {
        pDC->SetTextColor(RGB(255, 0, 0));
        pDC->SetBkColor(RGB(0, 255, 0));
        return m_brh;
    }
    else if(pWnd->GetDlgCtrlID() == IDC_CHECK10 || pWnd->GetDlgCtrlID() == IDC_RADIO11)
    {
        pDC->SetTextColor(RGB(255, 0, 0));
        pDC->SetBkMode(TRANSPARENT);
        return (HBRUSH)GetStockObject(NULL_BRUSH);
    }
 
    // TODO: Return a different brush if the default is not desired
    return hbr;
}





Posted by 까막백(홈페이지 이동)
posted by 인생의무한루프