반응형

view클래스::OnInitialUpdate()
{

 
 CComboBox * pWnd=(CComboBox*)(GetDlgItem(IDC_COMBO1));
  //->InsertString((CComboBox*)(::GetDlgItem(m_hWnd,IDC_COMBO1))->GetCount(), str);

 
 CString str;
 str.Format(L"첫번째아이템");
 pWnd->InsertString(pWnd->GetCount(), str);

 

 

...

}


반응형
반응형

다른것은 동일한데 새로운 사용자 정의 클래스에서

 

doc 클래스와 view 클래스를 include 한다 이때 순서가 중요한데

 

doc클래스 다음에 view 클래스를 include 해야한다

 

 

하지만 뷰클래스에 위에 설명한 클래스를 포함하려면 에러가 나는데

이럴거면 차라리 뷰클래스 아래 클래스를 작성하고 뷰클래스를 그대로 상속 받기만 해도 상속이 되며

 

사용자 정의 클래스를 뷰 클래스 상단에 선언문만 작성해 놓고 쓰면 에러를 피할 수 있다

반응형
반응형

단점 실시간으로 이미지에 선을 그리고 렌더링하는것을 반복하기에는 부적합하다

because 너무느리다

http://roter.pe.kr/263

MFC에서 더블버퍼링 사용하기.
이걸 왜 지금까지 안올려놨었지 -.-?;;

일단 제일 중요한건 헤더 파일에
CBitmap m_Bitmap;
를 선언 하는 것.
이 비트맵에 객체를 생성하고 이것저것 해줄 것임.

우선 아래와 같이 Bitmap에 그림을 그려줌.

void CDlgXXX::MakeMemBitmap(void)
{
	CClientDC dc(this); //실제 dc
	
	CBitmap* pOldBmp; //oldbmp

	CDC MemDC; //메모리DC
	
	m_Bitmap.DeleteObject(); //기존꺼 지워줌
	m_Bitmap.CreateCompatibleBitmap(&dc, 500, 200); //새로 만들어줌
	MemDC.CreateCompatibleDC(&dc); //memDC도 새로 만들어줌
	pOldBmp = MemDC.SelectObject(&m_Bitmap); //memDC의 비트맵 선택
	
	MemDC.MoveTo(0,0); 
	MemDC.LineTo(500,200); //memDC에 그린다.(비트맵 위에 그려진다)
	MemDC.SelectObject(pOldBmp); //oldbmp 선택
	MemDC.DeleteDC(); //memDC를 지운다.
}
 
void CDlgXXX::OnPaint()
{
	CPaintDC dc(this); // device context for painting	
	CDC MemDC;
	
	CBitmap* pOldBmp;

	MemDC.CreateCompatibleDC(&dc);
	pOldBmp = MemDC.SelectObject(&m_Bitmap);
	
	
	dc.BitBlt(0,0,500,200, &MemDC, 0,0,SRCCOPY);
	

	MemDC.SelectObject(pOldBmp);
	MemDC.DeleteDC();
}
 

반응형
반응형

http://ryumin13.tistory.com/129

 

mfc를 쓰다보면, CString으로 editbox의 값을 입력 받았다가, 숫자로 변환하여 쓰는 경우가 많다. 그럴때 숫자로 변환하는 방법이다.
(물론 다른 방법도 있다. float 일때 이렇게 사용된다. )

CString strValue;
GetDlgItemText( IDC_EDIT1, strValue);
float fValue = _tstof( strValue );

 

반응형
반응형

 CCmdUI 클래스 : 사용자 인터페이스 갱신  MFC 라이브러리

2009/02/11 10:17

복사http://blog.naver.com/origin26/40061989342

■ CCmdUI 클래스

。기능

- 사용자 인터페이스 갱신과 관련된 기능을 수행하며 ON_UPDATE_COMMAND_UI 매크로로 연결되는 이벤트 처리기에 사용한다.

- 연결된 이벤트 처리기는 ON_COMMAND로 이미 등록되어 있는 이벤트 상태에 변경이 있을 때 이를 업데이트 시킨다.

 

- 연결된 이벤트 처리기는 이 클래스의 인스턴스 포인터를 매개변수로 넘겨받는다.

- 이벤트명이 ID_BEGIN이라면 이를 갱신하는 이벤트 처리기는 OnUpdateBegin()이 된다.

 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)

     . . .

     ON_UPDATE_COMMAND_UI( ID_BEGIN, OnUpdateBegin)

     ON_UPDATE_COMMAND_UI( ID_END, OnUpdateEnd)

 END_MESSAGE_MAP()

 

 void CCmdUIView::OnUpdateBegin(CCmdUI *pCmdUI)

 {

   pCmdUI->Enable(!m_bStart) ;

 } 

 void CCmdUIView::OnUpdateEnd(CCmdUI *pCmdUI)

 {

   pCmdUI->Enable(!m_bStart) ;

 }

 

。주요 멤버변수 : 갱신할 사용자 인터페이스의 이벤트 ID를 나타내는 UNIT 형의 m_nID가 있다.

。주요 멤버 함수

 멤버 함수 기능 
 Enable BOOL형 매개변수를 받아 사용자 인터페이스를 활성화/비활성화 시킴.
 SetText 사용자 인터페이스의 텍스트를 변경시킴.
 SetCheck int형 매개변수를 받아 체크 표시를 하거나 없앰.
 SetRadio SetCheck 함수와 비슷한 기능. 단, 체크 표시대신 점이 찍힘.

 

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

 

- 우선 다음과 같은 이벤트 처리기가 정의되어 있다고 가정한다.

 BEGIN_ MESSAGE_MAP(CCmdUIView, CView)

      ...

      ON_COMMNAD( ID_BEGIN, OnBegin )

      ON_COMMAND( ID_END, OnEnd )

 END_MESSAGe_MAP()

 

 void CCmdUIView::OnBegin()

 {

     m_bStart = TRUE ;

 }

 

 void CCmdUIView::OnEnd()

 {

     m_bStart = FALSE ;

 }

 

 

■ Enable 함수

- 메뉴 항목을 상황에 다라 활성화 시키거나 비활성화 시킨다.

 

。상태변수 만들기

- 활성화인지 비활성화 인지의 상황을 기억하는 상태 변수가 필요하다.

 class CCmdUIView : public CView

 {   ...

     BOOL m_bStart ;

 }

 

- 상태 변수를 클래스 생성자 함수에서 초기화 해 준다.

 CCmdUIView::CCmdUIView()

 {  ...

     m_bStart = FALSE ;

 }

 

。사용자 인터페이스 갱신 메세지 처리기 등록  

- ON_UPDATE_COMMAND_UI로 등록한다.

 BEGIN_ MESSAGE_MAP(CCmdUIView, CView)

      ...

      ON_UPDATE_COMMNAD_UI( ID_BEGIN, OnBegin )

      ON_UPDATE_COMMNAD_UI( ID_END, OnEnd )

 END_MESSAGe_MAP()

 

。메세지 처리기 활성/비활성 상태 제어

- Enable 함수를 호출하여 매개변수로 TRUE(활성화) 또는 FLASE(비활성화)를 넘긴다.

- 이벤트 처리기에 넘겨지는 매객변수 pCmdUI에는 메뉴 항목에 대한 정보가 담겨 있다.

- CCmdUI 클래스의 멤버 함수들을 호출하면 해당 메뉴 항목을 제어할 수 있다.

 void CCmdUIView::OnUpdateBegin(CCmdUI *pCmdUI)

 {

     pCmdUI->Enable(!m_bStart) ;

 }

 void CCmdUIView::OnUpdateEnd(CCmdUI *pCmdUI)

 {

     pCmdUI->Enable(!m_bStart) ;

 }


반응형

'프로그래밍(Programming) > MFC&API' 카테고리의 다른 글

더블버퍼링  (0) 2012.11.01
CString 을 float 로 변환  (0) 2012.11.01
EditBox 가 CString 일때 비활성화(회색으로) 시키기  (0) 2012.11.01
UpdateData 함수  (0) 2012.11.01
스크롤바 기능, 사용하기  (0) 2012.11.01
반응형

 

해당 다이얼로그에 OnInitDialog

를 추가 시킨후

 

bool 값을 미리 판정 받아

 

OnInitDialog(){

//이 안에서

    GetDlgItem(IDC_XCOUNT_EDIT)->EnableWindow(mbshow);

 //적용 시키면 된다

}


반응형
반응형

UpdateData 함수를 이용한 데이터 전송
UpdateData 함수는 매개변수를 이용하여 양방향 전송을 제어합니다.
아래의 그림에 보인 바와 같이 UpdateData 함수의 매개변수로 TRUE를 주면
사용자가 컨트롤에 입력한 값이 Value형 멤버 변수로 전송되고,
UpdateData 함수의 매개변수로FALSE를 주면 Value형 멤버 변수에 설정되어 있는 값이
컨트롤로 전송되어 이 값이 화면에 출력 됩니다.

※  CDialog 클래스에서 기본적으로 호출하고 있는 UpdateData 함수
CDialog 클래스에서는 프로그래머들의 편의를 위해, 기본적으로 UpdateData 함수를 두 번 호출해 주고 있습니다.
OnInitDialog 함수 안에서 UpdateData(FALSE)를 호출해주고, OnOK 함수 안에서 UpdateData(TRUE)를 호출해줍니다.
CDialog 클래스는 왜 이러한 일을 해 주고 있을까요?

  • 대화상자 시작 시 UpdateData(FALSE) 호출
    OnInitDialog 함수는 대화상자를 초기화 하기 위해 호출되는 함수입니다.
    이때, UpdateData(FALSE)가 호출되면, Value형 멤버 변수에 설정된 값이 컨트롤로 전송되어 화면에 나타나게 됩니다.
    즉, 대화상자가 화면에 나타나는 순간에 Value형 멤버 변수에 설정된 초기값이 화면에 출력되는 것이지요.
  • 대화상자 종료 시 UpdateData(TRUE) 호출
    OnOK 함수는 입력을 마치고 대화상자가 종료될 때 호출되는 함수입니다.
    이때, UpdateData(TRUE)가 호출되면, 사용자가 컨트롤에 입력해 놓은 값이 Value형 멤버 변수에 저장됩니다.

※ 주의
대화상자를 처리할 때 주의할 점은 사용자가 컨트롤에 입력한 값과 이 컨트롤에 연결된 Value형 멤버 변수에
저장된 값이 항상 같은 상태로 유지되는 것은 아니라는 점입니다. 즉, 사용자가 컨트롤에 어떤 값을 입력하면
컨트롤에 입력된 값은 변경되지만, 이 값이 바로 Value형 멤버 변수에 반영되는 것은 아니라는 것입니다.
UpdateData(TRUE)를 호출하고 난 다음에야 비로소, 컨트롤에 입력된 값이 Value형 멤버 변수에 저장됩니다.
물론, OnOK 함수에서 UpdateData(TRUE)가 호출되고 있으므로 확인 버튼을 눌러 대화상자가 종료된 후에는
컨트롤에 입력되었던 값이 Value형 멤버 변수에 저장된 상태가 됩니다.
하지만, 만약 그 전에 컨트롤에 입력된 값을 Value형 멤버 변수에 반영되도록 하고 싶으면 UpdateData(TRUE)를 명시적으로 호출해 주어야 합니다.


반응형
반응형

http://ospace.tistory.com/tag/%EC%8A%A4%ED%81%AC%EB%A1%A4%EB%B0%94

 


 

GetScrollPos => int GetScrollPos(HWND hWnd, int nBar);
설명 : 스크롤 바 컨트롤의 현재 값을 조사한다. 이 값은 스크롤 바 썸의 위치이다. 스크롤 바 메시지인 M_HSCROLL, WM_VSCROLL 메시지는 HIWORD(wParam)으로 현재 위치를 전달해 주기 때문에 16비트 범위의 값 이상을 표현할 수 없지만 이 함수를 사용하면 32비트 범위의 스크롤 값을 조사할 수 있다.
 
SetScrollPos => int SetScrollPos(HWND hWnd, int nBar, int nPos, BOOL bRedraw);  
설명 : 스크롤 바위 현재 위치, 즉 스크롤 바의 값을 설정한다. 통상 이 함수는 WM_HSCROLL, WM_VSCROLL 등의 스크롤 바 메시지 처리 루틴에서 스크롤 바의 위치값을 변경하기 위해 호출한다. 범위를 지정하는 nPos는 32비트의 정수이나 메시지로 전달되는 스크롤 바 위치는 16비트값이기 때문에 위치값은 16비트로 제한된다. 그러나 메시지의 인수를 참조하지 않고 GetScrollInfo 등의 함수로 스크롤 바의 위치를 직접 조사하면 32비트의 스크롤 위치값을 지정할 수도 있다.


인수 설명 : 
hWnd : 스크롤 바 컨트롤의 핸들. 이 값의 의미는 두번째 인수 nBar에 따라 달라진다.

nBar : 위치를 설정할 스크롤 바를 지정한다. 다음 세가지 값중의 하나를 가진다.
          SB_CTL 별도의 스크롤 바 컨트롤이며 hWnd는 스크롤 바 컨트롤의 핸들을 나타낸다. 
          SB_HORZ 표준 수평 스크롤 바이며 hWnd는 스크롤 바를 가진 윈도우의 핸들이다. (int 0)
          SB_VERT 표준 수직 스크롤 바이며 hWnd는 스크롤 바를 가진 윈도우의 핸들이다. (int 1)

nPos : 스크롤 바위 새로운 위치를 지정한다. 이 위치는 반드시 스크롤 바위 범위내에 있어야 하므로 값을 변경할 때 범위 내부인지를 점검한 후 값을 변경해야 한다.

bRedraw : 위치를 변경한 후 스크롤 바를 다시 그릴 것인지를 지정한다. 실행중에 위치를 변경할 경우 이 값을 TRUE로 지정하여 썸을 다시 그리도록 해 주어야 한다. 그러나 최초 스크롤 바 초기화시에는 다시 그릴 필요가 없으며 또한 실행중에라도 스크롤 바위 범위와 위치를 동시에 변경할 때는 둘 중 한 함수에서만 다시 그리기를 지정하면 된다. 이 경우 통상 SetScrollRange에서만 bRedraw를 TRUE로 설정하며 SetScrollPos의 bRedraw는 FALSE로 지정한다.


 

 

 

[컨트롤이야기] 아무도 말해주지않은 스크롤바 기능

작성자: Ospace (ospace114 at naver.com)http://ospace.tistory.com

스크롤바는 상당히 많이 사용하고 있는 컨트롤 중에 하나이다. 내용을 한 화면에 표시하지 못할 경우 그 일부를 표시하고 나머지 내용은 스크롤 바로 상하, 혹은 좌우로 이동하면서 볼 수 있게 한다.
또는 일정 정수 구간 값을 이동하면서 원하는 지점의 정수 값을 가져올 수도 있다.

먼저 스크롤 바의 기본적인 이야기를 하고 후반에 좀더 깊이 다루겠다.

Note: 예제 코드는 거의 없기에 간단하게 스크롤바를 작성하는 강좌를 보고 읽는게 이해하기 쉽다. 스크롤바에 대한 실사용을 보려면 아래 기타강좌를 참고하시길 바란다.



스크롤바 들어가기


사용자 삽입 이미지

Fig 1. Scroll Bar (from Windows XP)


위의 그림은 Windows XP에 있는 스크롤 바이다. 그전 스크롤바보다 이쁘게 변했다. ^^;
MS에서는 이렇게 스킨을 어떻게 했길래 선택적으로 바뀔 수 있지. 컨트롤 스킨 변경하려면 수많은 코드와 삽질을 해야만 되는데.. OTL

아래는 실제 스크롤 바에 구성요소들이다.

사용자 삽입 이미지

Fig 2. Scroll Bar 구성요소



스크롤바는 많이 사용해서 각 기능이야 대충 알고 있지만, 다시 대충 살표보자.

좌우에 삼각형 모양의 버튼이 보인다. 이는 좌후로  1 발자국(step)씩 움직인다. 이는 스크롤바 전체 값 범위에서 실제 1값을 의미의한다.
예를 들어 스크롤바 값 범위가 1~100 혹은 1~1000이든 상관없이 무조건 1을 의미한다.

가운데 홀로 떨어진 스크롤박스가 보인다. 이는 MSDN의 스크롤바 설명을 참조했다. 이를 이용해 값을 찾아간다. 좌우측에 빈 페이지가 보인다.

스크롤바의 정보를 가져오는 API로 GetScrollInfo 함수가 있다. 그리고 정보를 설정하는 API는 SetScrollInfo 함수가 있다.

스크롤바는 100% 수동적인 컨트롤이다. 이말은 모든 부분을 프로그래머가 제어해줘야한다.
예를 들어 가운데 스크롤박스를 움직이면 끝나는 것이 아니라. 그때 스크롤바 위치를 얻고, 해당 값을 다시 스크롤바에 갱신하고 화면을 다시 그리게 한다는 의미이다.주의하길 바란다!

스크롤바 값은 정수형이다. 실수는 사용할 수 없다. 사용하려면 값변환을 통해서 사용해야 한다. 최대 최소값을 지정하지 않으면 기본 범위는 0~100을 가진다. 일단 정확히 지정해주는게 좋다.

예를 들어 문서를 불러와서 표시하려 한다. 총 줄수가 150개라고 하면, 스크롤바 값 범위는 0~150으로 설정한다. 이건 고정된 값은 아니다. 스크롤바 범위는 300, 450도 가능하고 200도 가능하다.
단지 스크롤바 1스텝이 라인 1줄에 해당하는 형태로 일치시키기 위해서이다.

이렇게 최대 최소 값을 지정하는건 그다지 큰 문제가 없고 다른 사이트에서 많이 다루는 예제이다. 


스크롤바 깊게 들어가기


지금은 스크롤바 페이지에 대해서 보도록 하겠다. 페이지는 스크롤바 가운데 있는 스크롤상자 크기에 대한 이야기이다. 스크롤상자는 때에 따라서 커지고 작아지기도 한다. 손오공 여의봉처럼 마음대로 커지고 마음대로 작아지는 놈일까?
그렇지 않다. 사용 목적이 있기 때문에 크기가 그에 따라 변경이된다.

스크롤바 크기는 페이지 크기이다. 한페이지에 들어가는 값 개수이다. 어차피 정수이니 한페이지에 들어가는 정수값 크기라고 보면 된다.

페이지 크기라고 하면 감이 안잡힌다. 예를 들어 책을 살펴보는게 쉽게 이해할 수 있다.
책에는 방대한 양의 글자들이 들어가 있다. (물론 그림, 사진 등도 있다^^;) 모든 내용을 하나의 종이메 모두 담지 못했기에 페이지 단위로 나눠서 표시한다.

예를 들어, 총 1234줄의 내용이 있고 한페이지에 들어가는 줄수는 100줄이라고 가정하면 총 페이지 수는 얼마가될까?

답은 13 페이지
마지막 12페이지를 꽉채우고 34줄이 남지만 한 페이지는 반으로 나눌 수는 없기에 1페이지로 만들어서 넣는다. 추가로 표지, 목차, 속지, 인지 등을 포함하면 더 늘어날 수 있지만 ㅡ.ㅡㅋ

마찬가지로 컴퓨터 화면도 방대한 내용을 한화면에 모두 표시할 수 없기에 페이지 단위로 나눠서 표시한다. 책과 다른 점은 컴퓨터는 연속적으로 페이지를 볼 수 있다.

앞의 책의 예를 일반 텍스트 문서라고 가정해서 스크롤바 설정을 해보자.

최대 최소 값 범위: 0~1234
페이지크기(스크롤박스 크기): 100


너무 쉬어 보인다. 내가 설명을 잘해서인가? ㅋㅋㅋ

그러나 주의할 점이 있다. 바로 스크롤박스가 움직일 수 있는 최대값이 스크롤바 최대값과는 틀리다.
이는 스크롤박스 크기에 따라 가변적이기에 주의해야한다.

사용자 삽입 이미지

Fig 3. Scroll Bar 값들

위 그림은 스크롤바에서 사용되는 값을 표시하였다.
스크롤박스 왼쪽 경계가 현재 값이다. (Current Position)
스크롤바 양쪽 버튼을 제외한 영역이 스크롤바 전체 값 범위이다.(MAX Range Value)
그리고, 양쪽 버튼과 스크롤박스 크기를 제외한 나머지 영역이 스크롤박스가 움직일 수 있는 범위이다.(MAX Scroll Pos)

여기서 중요한 값이 MAX Scroll Pos이다. 현재 위치(Current Position)이 MAX Scroll Pos값을 넘을 수 없다. 단, 최소값은 항상 0으로 가정한다.

0 <= Current Position <= MAX Scroll Pos

그럼 MAX Scroll Pos을 구하는게 중요하다.

MAX Scroll Pos = MAXRangeValue - (Page Size - 1)

Page Size에서 -1은 당연히 Page Size 왼쪽 경계까지 값 범위이기 때문이다. 이를 앞에 책의 예를 이용해서 다시 스크롤바 설정을 해보자.

최대 최소 값 범위: 0~1234
페이지크기(스크롤박스 크기): 100
스크롤박스 이동 범위: 0 ~ 1135




스크롤바 전문가 과정

좀더 스크롤바를 깊게 들어가자. 지금 부터 조금 머리 아파질 수 있으니, 지금 머리가 조금 아프신 분들은 창문가서 밖같 하늘 한번 구경하자.

지금 다를 내용은 크게 두가지 이다. 하나는 프로그램 크기(resize)와 데이터 변경되는 경우와 다른하나는 스크롤을 좀더 세밀하기 하기 위해 스크롤바 최대 최소 범위를 변경하는 경우이다.


프로그램 크기와 데이터 변경

먼저 프로그램 크기와 데이터가 변경되는 경우를 살펴보자.
프로그램 크기가 변경되는 의미는 내용이 나타나는 화면 크기가 바뀌었다는 의미이고 스크롤 바에서는 한 화면에 표시되는 크기를 가리키는 스크롤박스 크기가 달라졌다는 의미이다.

앞의 책의 예를 보면 한페이지에 표시할 수 있는 줄수가 100줄에서 130줄 혹은 50줄로 커지거나 작아졌다는 의미이다.
일단 내용 변경이 없다면 스크롤바 최대 최소 값 범위은 변경되지 않고 페이지 크기가 변경되었고, 즉, 스크롤박스가 이동할 수 있는 범위가 변경되었다는 의미이다.

책의 예제에서 한페이지(한화면)에서 표시할 수 있는 줄수가 100줄에서 130줄로 변경되었다면 스크롤바 설정을 살펴보자.

스크롤바 최대 최소 값 범위: 0 ~ 1234
페이지크기(스크롤박스 크기): 100 -> 130 (변경)
스크롤박스 이동 범위: 1234 - (130 - 1) = 1103 (변경)
페이지수: 10 페이지 (이는 스크롤바 설정 값은 아니다.)


그리고 데이터가 변경되었다면 어떻게 될까?
일단 스크롤바 최대 최소 값 범위가 변경된다. 페이지 크기는 고정이지만, 스크롤 박스 이동 범위도 바뀌게 된다. 즉, 전체 크기가 변경되었으므로 이동가능한 범위도 변경되었다는 의미이다. 그럼 마찬가지로 앞의 책의 예로 계산해보자.
가정은 데이터 량이 1234줄에서 1500줄로 늘어낳고 한 페이지 크기는 130줄로 계산해보자.

스크롤바 최대 최소 값 범위: 0 ~ 1500 (변경)
페이지크기(스크롤박스 크기): 130
스크롤박스 이동 범위: 1500 - (130 - 1) = 1371 (변경)
페이지수: 12 페이지 (이는 스크롤바 설정 값은 아니다.)


화면 크기 혹은 데이터 크기 변경은 각각 페이지 크기 변경 혹은 스크롤바 최대 값 변화가 따로 생기지만 스크롤박스 이동 범위는 둘 다 새로 계산해야 된다.


스크롤바 정밀도 조절하기

데이터 크기와 스크롤바 크기가 일치하지 않은 경우를 살펴보자.
앞에서는 텍스트 한줄이 스크롤바 한스텝과 일치한다. 스크롤바에서 3값이 움직이면 텍스트에서 3줄이 움직인다.

간혹 1 스텝 이동이 1/2 줄 이동이나 1 스텝 이동이 2줄 이동으로 할 경우도 있다.

사용자 삽입 이미지

Fig 4. 1스텝 이동시 반줄 이동


이 그림은 1 스텝 이동은 반 줄 이동하는 예를 보여둔다. 즉 2 스텝 이동해야 한 줄이 이동된다는 의미이다. 즉 한 스텝 이동하면 글자 반정도 크기만 움직이고 화면 경계에 있다면 반은 보이고 반은 가려서 보이지 않게된다. 한 스텝이 글자 반 정도 움직이는 느린 스크롤이 된다.

사용자 삽입 이미지

Fig 5. 1스텝 이동시 2줄 이동



이 그림은 1 스템 이동이 2줄 이동하는 예이다. 즉, 반 스텝 이동이 한줄 이동이지만 반 스텝 이동은 없다. 스크롤 바는 정수 값만 사용하기 때문이다.
한스텝 이동은 2줄이 한꺼번에 움직이므로 빠른 화면 스크롤을 볼 수 있다.

그러면 위와 같은 경우 스크롤바 값 설정은 어떻게 될 것인다.
간단하게 계산하기 위해서 텍스트 줄수는 100줄이고 한화면 표시되는 페이지 크기는 10라고 하자.


1스텝에 1/2줄 이동

먼저 한 스텝에 반 줄 이동하는 예를 보자.
즉, 한줄이 2스텝을 차지하므로 총 100줄이므로,

100줄 x 2 스텝 / 줄 = 200 스텝

결국 스크롤바 값 범위가 0 ~ 200를 가진다. 좀더 생각을 하면 앞에서 스크롤바는 정수값만 사용한다고 했지만, 위의 값의 범위는 0~100줄은 0.5줄 단위까지 잘라서 얻을 수 있다는 의미이다.
페이지 크기가 10는 스템 수가 아닌 화면에 나타나는 줄 수 이다. 그러면 페이지 크기는

10줄 x 2 스텝 / 줄 = 20 스텝

페이지 크기는 20스텝이 된다.
그러면 스크롤박스 최대 이동 가능한 값이 계산된다.

스크롤박스 최대 이동 값 = 200 - (20 - 1) = 181

스크롤박스 최대 이동 값은 181이 된다.


1스텝에 2줄 이동

다음으로 1스텝이 2줄 이동하는 예를 살펴보자. 앞의 계산 법의 확인일 뿐이다.
앞의 계산 법에 의해서 단위 줄에 변하는 스텝 값은 1/2이 된다.

스크롤바 최대값: 100줄 x 1/2 스텝/줄 = 50 스텝
페이지 크기: 10줄 x 1/2 스텝/줄 = 5 스텝
스크롤박스 최대 이동 값: 50 - (5 - 1) = 46


계산 방법은 동일하다. 이부분은 텍스트를 예로 들어서 설명했지만, 그래픽 처리에서 상당히 유용하리라 생각한다.

 

기타강좌:
스크롤바 강좌: http://www.winapi.co.kr/win32lec/lec7/lec7-5-1.htm

반응형
반응형

hci2-lecture5-ch5[1].pdf


비클라이언트 영역 메세지

함수, 메세지

반응형
반응형

툴바를 주석처리해야 메세지가 제대로 들어온다

반응형
반응형

http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=50&MAEULNo=20&no=820288&ref=820288

Feature Pack sample 중에 RibbonGadgets 라는 sample이 있습니다.

(아래 그림 참조) 리본바에서 color를 지정하고 나서 어떻게 색상 값을 받아와야 할지 모르겠네요?

 

 

 

 

<페널에 CMFCRibbonColorButton 추가>

 

bNameValid = strTemp.LoadString(IDS_RIBBON_PEN3);
 ASSERT(bNameValid);
CMFCRibbonColorButton* pBtnPen3 = new CMFCRibbonColorButton(ID_OBJECT_PEN3, strTemp, 2);
 pBtnPen3->EnableAutomaticButton(_T("&Automatic"), RGB(0, 0, 0));
 pBtnPen3->EnableOtherButton(_T("&More Colors..."), _T("More Colors"));
 pBtnPen3->SetColumns(10);
 pBtnPen3->SetColorBoxSize(CSize(17, 17));
 pBtnPen3->AddColorsGroup(_T("Theme Colors"), m_lstMainColors);
 pBtnPen3->AddColorsGroup(_T(""), m_lstAdditionalColors, TRUE);
 pBtnPen3->AddColorsGroup(_T("Standard Colors"), m_lstStandardColors);
 pPanelObject->Add(pBtnPen3);

 

<ID_OBJECT_PEN3 메뉴 버튼 에서>

void CMainFrame::OnObjectPen3()
{
 // TODO: Add your command handler code hee

// 여기서 처리를 어떻게 해야 하는지요?

// 요거 저거 해도 안되는군요...

CMFCColorButton m_wndColor;

 CString str;
 COLORREF color = m_wndColor.GetColor();
 str.Format(_T("%d,%d,%d"), GetRValue(color), GetGValue(color), GetBValue(color));
 SetOutput(str);
}

 

void CMainFrame::OnUpdateObjectPen3(CCmdUI *pCmdUI)
{
 // TODO: Add your command update UI handler code here
}

 

시원한 답변 부탁드립니다.

이 글에 답변 등록하기
[채택답변] 상콤한 답변 -_-
0
2010-03-18 오전 1:12:12
 질문자 인사 :답변 갑사합니다.
처음에는 안되서 왜 그런가 했는데..
제가 SDI라서 CMDIFrameWndEx를 CFrameWndEx로 변경하니 
잘 됩니다..
정말 감사합니다.
  오새롬 (diebuster)  오새롬님께 메시지 보내기오새롬님을 내 주소록에 추가합니다.오새롬님의 개인게시판 가기번호: 820292  

    CMFCRibbonBar* pRibbon = ((CMDIFrameWndEx*) AfxGetMainWnd())->GetRibbonBar(); 
    ASSERT_VALID(pRibbon); 


    CMFCRibbonColorButton* pColor = DYNAMIC_DOWNCAST( CMFCRibbonColorButton, pRibbon->FindByID(ID_OBJECT_PEN3));
    // Get the selected color 
    COLORREF color = pColor->GetColor();

 

 [답변]상콤한 답변 -_-2010-03-17 오후 11:58:36
오새롬 (diebuster)  오새롬님께 메시지 보내기오새롬님을 내 주소록에 추가합니다.오새롬님의 개인게시판 가기번호: 820292  추천:0  

    CMFCRibbonBar* pRibbon = ((CMDIFrameWndEx*) AfxGetMainWnd())->GetRibbonBar(); 
    ASSERT_VALID(pRibbon); 


    CMFCRibbonColorButton* pColor = DYNAMIC_DOWNCAST( CMFCRibbonColorButton, pRibbon->FindByID(ID_OBJECT_PEN3));
    // Get the selected color 
    COLORREF color = pColor->GetColor();

 

이 글에 답변 등록하기
         [답변]에러가 발생합니다.2010-03-18 오전 12:44:55
김정곤 (fdsdasom)  김정곤님께 메시지 보내기김정곤님을 내 주소록에 추가합니다.김정곤님의 개인게시판 가기번호: 820297  추천:0  

늦은시간인데 이렇게 답변 주셔서 감사합니다.

 

님께서 말씀 하신 방법을  적용 했습니다. 색을 선택하면 에러가 발생합니다.

 

디버깅 해 보니  CXX0030: Error: expression cannot be evaluated  이런 에러가 발생하네요!

 

그리고 저는 SDI에서 하고 있는데요 CMDIFrameWndEx* 이게 사용 가능 한건가요?

 

void CMainFrame::OnObjectPen3()
{

CString str;

 CMFCRibbonBar* pRibbon = ((CMDIFrameWndEx*) AfxGetMainWnd())->GetRibbonBar(); 
 ASSERT_VALID(pRibbon); 


 CMFCRibbonColorButton* pColor = DYNAMIC_DOWNCAST( CMFCRibbonColorButton, pRibbon->FindByID(ID_OBJECT_PEN3));


 // Get the selected color 
 COLORREF color = pColor->GetColor();


 str.Format(_T("%d,%d,%d"), GetRValue(color), GetGValue(color), GetBValue(color));
 SetOutput(str);


}

 

소스를 보면 color가 크게 두가지 정도로 분류가 됩니다.

 

한가지는 펼처진 경우 보여지는 색상이구요, 다른 한가지는 other나 more 를 선택했을 때 나오는 ColorDlg입니다.

 

이둘을 같이 사용 하고 있는데 둘 중에 어떤것이 선택 되었는지도 알 수 가 없습니다. 이 것도 알 수 있는 방법이 없을 까요?

이 글에 답변 등록하기
                 [답변]CFrameWndEx2010-03-18 오전 1:33:30
오새롬 (diebuster)  오새롬님께 메시지 보내기오새롬님을 내 주소록에 추가합니다.오새롬님의 개인게시판 가기번호: 820299  추천:0  

CMFCRibbonBar* pRibbon = ((CFrameWndEx*) AfxGetMainWnd())->GetRibbonBar(); 


반응형
반응형

MFC에서 Doc/View 구조가 아닌 프로젝트를 생성하여, MainFrame에서 View클래스의 포인터를 얻기 위해 GetActiveView()함수를 사용하니 NULL을 반환

그냥, 
View.cpp 파일에서 전역변수로 선언하고 OnCreate시에 자기를 할당하고, MainFrame에서는 extern으로 받아서 사용하니 동작됨. 하지만, 좀 더 안전이 보장되는 방법을 알아야 할 필요성이 있음

Example.
MainView.cpp
CMainView * pMainView;
int CMainView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
...
pMainView = this;
}


MainFrm.cpp
extern CMainView * pMainView;

// 함수내에서
pMainView->SetTranslationDirection(Y, m_bTranslation[Y]);




알아냄. CMainFrame class내에 view의 객체가 존재함 -_-;
저작자 표시 비영리
if(/MSIE [0-6]\./.test(navigator.userAgent)){for(var i=0;i<2;i++){var el=document.getElementById('ccl-icon-23-'+i);el.style.filter='progid:DXImageTransform.Microsoft.AlphaImageLoader(src="'+el.src+'",sizingMethod="image")';el.src='http://cfs.tistory.com/static/admin/form/s.gif';}}
 [출처 : http://chaoskcuf.com]

1. 개요 

MFC 9.0 Beta 버전에 포함된 Office 2007 스타일의 Ribbon Bar를 만드는 방법을 알아본다. 
(Application Wizard가 자동으로 생성하는 코드에 대한 이해를 목적으로 한다.)

 

2. 프로젝트 생성


  ProjectStyleSetting 
[그림 1 Application Type]

a) [그림 1]과 같이 Project Style을 Office로 선택하고 마음에 드는 Style Thema를 선택한다. 
(여기서 주의할 점이 있는데 Enable visual style switching 체크를 해제하게 되면 컴파일 에러가 나게 되는데, 물론 쉽게 에러나는 곳을 고칠 수 있으나 성가신 사항이므로 일단 체크를 하자. 컴파일 에러에 관한 내용은 다음 기회에 포스팅할 예정이다.)


ProjectUIFeatures 
[그림 2 User Interface Features]

b) [그림 2] 와 같이 User Interface Features의 옵션을 선택하는 부분에서 우리는 Ribbon Bar를 사용하여야 하기 때문에 User a ribbon 라디오 버튼에 체크하자. (뭐 기본 선택사항이니 가만히 두어도 된다)


 ProjectAdvancedFeatures 
[그림 3 Advanced Features]

c) [그림 3]에 보면 Advanced docking panes 옵션을 보면 5가지를 추가로 선택할 수 있다. 
위의 3개의 체크 박스는 Visual Studio Style의 프로젝트를 만들때 흔히 쓰일 듯한 옵션이다. 
4번째의 Navigation pane은 쉘 폴더 트리뷰와 달력 뷰가 샘플로 들어가는 옵션인데 일단 지금은 Ribbon Bar에 집중하기 위해서 일단 체크를 해제하도록 한다. 5번째의 Caption bar는 Ribbon bar 밑에 나오는 녀석으로 사용자에게 간단한 메세지를 출력해주는 기능을 하는 것으로 예를 들면 IE에서 보안설정으로 파업차단, ActiveX  설치시 삑 하고 나타나는 영역이라고 생각하면 되겠다.

d) 여기까지 했다면 Finish 버튼을 클릭하면 프로젝트를 생성할 수 있는데, 바로 빌드를 해보면 [그림 4]와 같이 정말 Office 2007스러운 미려한 디자인의 프로그램을 만날 수 있다.

SampleUI 
[그림 4 샘플]

 

3. Application Wizard가 생성한 코드 이해하기


a) CMainFrame의 OnCreate 이해 하기

MFC 8.0 이하의 버전에서는 MDI 프로젝트에서 CMainFrame 클래스는 CFrameWnd를 상속받았었다. 그러나 리본바를 사용하기 위해서는 CFrameWnd 클래스 대신에 이의 확장 버전인 CMDIFrameWndEx 클래스를 상속받고 있다. 아래의 코드는 Wizard가 자동으로 생성해주는 코드인데 MFC 8.0 이하 버전과의 차이점을 중심으로만 살펴보기로 하겠다.

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 

    if (CMDIFrameWndEx::OnCreate(lpCreateStruct) == -1) 
        return -1; 
    // set the visual manager and style based on persisted value 
    OnApplicationLook(theApp.m_nAppLook); 

    CMDITabInfo mdiTabParams; 
    mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D_ONENOTE; // other styles available... 
    mdiTabParams.m_bActiveTabCloseButton = TRUE;      // set to FALSE to place close button at right of tab area 
    mdiTabParams.m_bTabIcons = FALSE;    // set to TRUE to enable document icons on MDI taba 
    mdiTabParams.m_bAutoColor = TRUE;    // set to FALSE to disable auto-coloring of MDI tabs 
    mdiTabParams.m_bDocumentMenu = TRUE; // enable the document menu at the right edge of the tab area 
    EnableMDITabbedGroups(TRUE, mdiTabParams); 

    m_wndRibbonBar.Create(this); 
    InitializeRibbon(); 

    if (!m_wndStatusBar.Create(this)) 
    { 
        TRACE0("상태 표시줄을 만들지 못했습니다.\n"); 
        return -1;      // 만들지 못했습니다. 
    } 

    CString strTitlePane1; 
    CString strTitlePane2; 
    strTitlePane1.LoadString(IDS_STATUS_PANE1); 
    strTitlePane2.LoadString(IDS_STATUS_PANE2); 
    m_wndStatusBar.AddElement(new CMFCRibbonStatusBarPane(ID_STATUSBAR_PANE1, strTitlePane1, TRUE), strTitlePane1); 
    m_wndStatusBar.AddExtendedElement(new CMFCRibbonStatusBarPane(ID_STATUSBAR_PANE2, strTitlePane2, TRUE), strTitlePane2); 

    // enable Visual Studio 2005 style docking window behavior 
    CDockingManager::SetDockingMode(DT_SMART); 
    // enable Visual Studio 2005 style docking window auto-hide behavior 
    EnableAutoHidePanes(CBRS_ALIGN_ANY); 

    // Create a caption bar: 
    if (!CreateCaptionBar()
    { 
        TRACE0("Failed to create caption bar\n"); 
        return -1;      // 만들지 못했습니다. 
    }

    // Enable enhanced windows management dialog 
    EnableWindowsDialog(ID_WINDOW_MANAGER, IDS_WINDOWS_MANAGER, TRUE);

    return 0; 
}

  • 처음 부분에 등장하는 생소한 함수가 보일 것이 바로 OnApplicationLook()라는 함수인데, 이 함수는 바로 Look & Feel을 선택할 수 있게 해주는 CMDIFrameWndEx 의 센스쟁이 멤버 함수이다. 파라미터로 넘어가는 thhApp.m_nAppLook 은 CMainFrame의 생성자에서 대입된다. 아래와 같이 정의된 값을 대입해보면서 스타일이 어떻게 변하는지 직접 느껴보기 바란다.
    • ID_VIEW_APPLOOK_WIN_2000
    • ID_VIEW_APPLOOK_OFF_XP
    • ID_VIEW_APPLOOK_WIN_XP
    • ID_VIEW_APPLOOK_OFF_2003
    • ID_VIEW_APPLOOK_VS_2005
    • ID_VIEW_APPLOOK_OFF_2007_BLUE
    • ID_VIEW_APPLOOK_OFF_2007_BLACK
    • ID_VIEW_APPLOOK_OFF_2007_SILVER
    • ID_VIEW_APPLOOK_OFF_2007_AQUA

EnableMDITabbedGroups  
[그림 5 예전 MDI 방식]

  • MDI 형식의 프로젝트이기 때문에 여러개의 문서를 어떤 식으로 표시를 해줄 것인지를 결정하는 함수가 EnableMDITabbedGroups() 이다. 첫번째 파라미터를 FALSE로 넘기면 Tab 방식으로 문서를 정렬하는 방식이 아닌 [그림 5]와 같이 예전 MDI 방식으로 사용할 수 있다. 
    두번째 파라미터로 넘기는 CMDITabInfo 클래스는 아래와 멤버 변수를 public으로 가지고 있다.

class CMDITabInfo 

public: 
    CMDITabInfo(); 
    void Serialize(CArchive& ar);

    CMFCTabCtrl::Location m_tabLocation;    // Tab에 위치를 아래에 둘지 위의 둘지 선택 (기본 위) 
    CMFCTabCtrl::Style    m_style;                // Tab Look & Feel 선택 (아래 참조)

    BOOL m_bTabIcons;                              // Tab에 아이콘을 표시할 것 인지 
    BOOL m_bTabCloseButton;                     // Tab에 닫기 버튼을 표시할 것 인지  (m_bActiveTabCloseButton 가 FALSE 일 때)

    BOOL m_bTabCustomTooltips; 
    BOOL m_bAutoColor;                             // 새로운 문서가 추가될 때 마다 Tab의 색상이 바뀔것 인지 
    BOOL m_bDocumentMenu;                     // 문서가 많이 열렸을 때 좌우 스크롤을 할지 Menu에 표시할 지       
    BOOL m_bEnableTabSwap;                    // 드래그 앤 드랍으로 탭의 위치를 변경할 수 있게 만들지 
    BOOL m_bFlatFrame;                             // Frame 의 모습 
    BOOL m_bActiveTabCloseButton;            // 활성화된 Tab에 닫기 버튼이 표시되게 할 지 Tab영역 오른쪽 가장자리에  표시할 지 
    int  m_nTabBorderSize;                          // Frame Border의 굵기 
};

  • CMdITabInfo의 m_style이라는 멤버 변수는 아래와 같은 값을 가질 수 있다.
    • STYLE_3D
    • STYLE_FLAT
    • STYLE_FLAT_SHARED_HORZ_SCROLL
    • STYLE_3D_SCROLLED
    • STYLE_3D_ONENOTE       
    • STYLE_3D_VS2005       
    • STYLE_3D_ROUNDED                     
    • STYLE_3D_ROUNDED_SCROLL
  • InitializeRibbon() 함수에 리본바를 구성하는 모든 코드들이 속해있다. (기본적으로 Wizard가 샘플로 만들어 놓은 함수이다)

 

b) Main Category 부분 구성하기

MainPanel(desc) 
[그림 6 Main Category의 구성]

MFC 9.0과 같이 나온 미려한(?) 디자인의 MFC이 아이콘이 속해있는 버튼이 보이는가? 그 버튼을 누르면 위의 [그림 6]처럼 Main Category라는 익숙한 창이 나타나게 되는데 일단 MainCategory를 뛰워주게 하는 이 Application Button이라고 부르는 녀석을 먼저 살펴보도록 한다. 

CMainFrame는 멤버 변수로 CMFCRibbonApplicationButton class의 객체를 m_MainButton라는 이름으로 가지고 있다. 이 버튼의 이미지는 Bitmap파일의 리소스 아이디를 SetImage함수를 통해 전달해 주면 된다. 

그리고 Alt 키를 누르면 각각의 Ribbon Element들이 가지는 단축키들이 표시되는데, 이 단축키를 세팅해주는 방식 두가지가 있다.

m_MainButton.SetText(_T("\nf"));  // Element의 이름과 단축키를 동시에 설정하는 방법 
m_MainButton.SetKeys(_T("f"));      // 단축키 값만을 설정하는 방법


그런데 한가지 의문점이 든다. SetText의 문자열이 개행문자로 시작하는 부분이다. 
CMFCRibbonApplicationButton의 멤버함수(정확히는 CMFCRibbonBaseElement의 멤버함수) SetText 함수는 단축키와 표시될 이름을 동시에 설정하는 함수이다. 단, 위와 같이 '\n' 개행문자를 구분자로 표시될 이름과 단축키가 한 문자열로 전달되어야 한다. m_MainButton에 SetText를 하는 것은 약간 이례적인 경우인데, Application Button(m_MainButton)은 [그림 6]을 보다시피 문자열로 표현되는 부분이 없다. 그래서 SetText함수를 사용하여

m_MainButton.SetText(_T("MainButton!\nf"));


위와 같이 코딩하여도  '\n' 앞의 문자열 MainButton은 쓰여질 곳은 없기 때문에 굳이 넣지 않아도 된다
이제 의문이 해소되었는가? 
아직도 이상하다고 생각되면 그냥 SetKeys함수를 사용하여 그 의미를 명확하게 하자.

참고로 사실 Application Wizard가 생성해주는 코드에 저 부분이 들어있어서 설명해주고 싶었다. 
ApplicationButton의 경우 이상하다고 느낄지는 모르겠지만 예를 들어 다른 Ribbon Element 들을 만들때 생성자로

CMFCRibbonButton* pBtnPaste = new CMFCRibbonButton(ID_EDIT_PASTE, _T("Paste\nV"), 0, 0);


와 같이 두번째 파라미터로 문자열 값을 넣었을 때 생성자 내부에서 CMFCRibbonBaseElement의 SetText함수를 호출하게 되어 있어서 그 Element는 Paste라는 이름을 가지게 되고 단축키는 V를 가지게 된다. 
주의할 점은 소문자를 넣어도 Alt를 눌렀을 때의 모든 단축키의 모습은 아래 그림과 같이 대문자로 나온다는 것이다.

Keys 
[그림 7 단축키 표현 방식]

마지막으로 버튼이라면 마우스가 오버 했을 때 툴팁을 뛰워주야하지 않겠는가? 그래서 그 툴팁 텍스트를 설정하는 부분이 바로

m_MainButton.SetToolTipText(_T("File"));


SetToolTipText 함수를 사용하는 부분이다.

이렇게 하면 Button에 대한 속성은 거의 다 정해준 것 같다. 
그러나 여기까지는 그냥 버튼을 하나 생성시켜서 메모리 어느 공간에 있을 뿐이다. 
이 버튼이 ApplicationButton이다!! 라고 설정을 시켜주어야 한다.

OnCreate 함수에서 Create 시켜주었던 RibbonBar 객체가 생각나는가? 그 RibbonBar에다 이 버튼이 Application이고 버튼 크기는 얼마였으면 좋겠다라고 등록시켜주는 함수가 있다.

m_wndRibbonBar.SetApplicationButton(&m_MainButton, CSize (45, 45)); //가로 45px, 세로 45px 크기로 ApplicationButton으로 등록


위의 코드처럼 SetApplicationButton이라는 함수인데, 만약에 위와 같이 m_MainButton을 RibbonBar에 저 함수를 통해 등록하지 않으면 어떻게 될까?

WithoutAppButton 
[그림 8 Application Button이 없는 리본바]

[그림 8] 처럼 ApplicationButton이 없는 UI가 나타난다. 
경우에 따라  ApplicationButton이 없는 경우를 선호할 때는 CMFCRibbonApplicationButton 을 설정하고 RibbonBar에 등록하는 부분을 주석처리하면 그 뿐인 것이다.

길게 길게 ApplicationButton에 대해서 설명을 했다. 
그렇다면 이번에는 [그림 6] 처럼 MainCategory에 New Open 처럼 항목을 집어 넣는 부분을 살펴보자. 
일단 MainCategory는 좀 특이하다. 
RibbonBar에 항상 나타나 있는 것이 아니라 ApplicationButton을 통해서 나타나는 것도 그렇고, 기본적으로 MDI 프로그램에 꼭 필요한 항목들만 들어 있다. 그래서인지 RibbonBar에서는 AddMainCategory 함수가 따로 존재한다. 
(뒤에 보면 알겠지만 그냥 AddCategory 함수가 있다. AddCategory는 여러 카테고리를 추가할 수 있지만, AddMainCategory는 당연히 한번만 호출 되어서 하나의 MainCategory만 존재해야 한다.)

CMFCRibbonMainPanel* AddMainCategory( 
   LPCTSTR lpszName,                           // 메인카테고리의 이름 
   UINT uiSmallImagesResID,                   // 작은 이미지 리소스 아이디 
   UINT uiLargeImagesResID,                   // 큰 이미지 리소스 아이디 
   CSize sizeSmallImage=CSize(16, 16) ,  // 작은 이미지 하나의 크기 
   CSize sizeLargeImage=CSize(32, 32)   // 큰 이미지 하나의 크기 
);


너무나 당연한 이야기지만, 리소스에 포함된 이미지는 파라미터로 넘겨주는 크기의 이미지 조각을 연속적으로 붙여놓은 하나의 이미지여야한다.

CMFCRibbonMainPanel* pMainPanel = m_wndRibbonBar.AddMainCategory(_T("File"), IDB_FILESMALL, IDB_FILELARGE);

그런데 여기서 질문.

  1. 메인 카테고리 이름이라고 준 File 이라는 문자열이 Application을 눌러봐도 나오는 부분이 없는 것 같다
  2. MainCategory창에는 전부 큰 이미지(Large Icon)만 보이는데 굳이 작은 이미지를 넣을 필요가 있는가?

차근 차근 위의 질문에 대한 답을 찾아보자. 
정답은 QAT(Quick Access Toolbar)의 지원때문이라고 간단히 말할 수도 있겠다.

CustomizeQAT 
[그림 9 QAT]

Office UX에서 사용자가 가장 자주 쓰는 기능을 ApplicationButton 옆에 보이는 QAT로 모아서 편리하게 쓸 수 있게끔 하는 것이 있다. 
그 옆에  아래로 향하는 화살표 부분을 클릭하면 QAT를 Customize할 수 있는 메뉴가 나타난다.

QATMenu

반응형
반응형

http://zeroone.tistory.com/tag/Ribbon

////////////////////////////////////////////////////////////////////////////////////

 

 

 

 

 

 

출처 - http://zeroone.tistory.com/entry/How-To-%EA%B8%B0%EC%A1%B4-MFC-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-Ribbon-UI-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0

 

기존 MFC Scribble Sample에 VS2008 Feature Pack에 포함된 MFC의 Ribbon UI를 적용해 보겠습니다.

Visual C++ 2008 Feature Pack Download
Visual C++ 2008 Feature Pack Documentaion

우선 기존 Scribble Sample을 가져 와서
 VS 2008 로 Open 합니다.
\Microsoft Visual Studio 9.0\Samples\1033\AllVCLanguageSamples\C++\MFC\ole 에 위치해 있습니다.

1.
 afxcontrolbars.h 헤더 추가
우선 리본을 적용하기 위해서 헤더를 포함하여야 합니다. 
stdafx.h 파일을 열어 상단에 afxcontrolbars.h 를 include합니다.

#ifndef WINVER
#define WINVER 0x0600
#endif
#include <afxcontrolbars.h>


2008에서 부터는 WINVER가 Default로 Define되어 있지 않습니다.  따라서 WINVER를 명시적으로 선언하지 않으면 Warning을 표시하고 Default로 0x0600 (Vista)로 선언됩니다. 

class CScribbleApp : public CWinAppEx
{
scribble.cpp 를 열어 다음을 추가 합니다.

LoadStdProfileSettings();  // Load standard INI file options (including MRU)
SetRegistryKey(_T("MFCNext\\Samples\\Scribble2"));
SetRegistryBase(_T("Settings"));

기존 Scribble프로젝트 에서는 ini방식을 사용하므로 자동으로 저장되는 프로그램설정을 위해 레지스트리를 사용하도록 변경합니다.

3. MainFrame 클래스 변경
mainfrm.h를 열어 CMDIFrameWnd를 CMDIFrameWndEx로 변경합니다.

class CMainFrame : public CMDIFrameWndEx
{

상속클래스가 변경되었으니 mainfrm.cpp를 열어 모든 CMDIFrameWnd를 CMDIFrameWndEx로 변경하여야 겠지요?  변경합니다.  
CMDIFrameWnd를 CMDIFrameWndEx로 한번에 Replace하는것이 빠르겠지요..

변경되는 코드 모두 펼치기


4. ChildWnd 클래스 변경 하기
childfrm.h를 열어 CMDIChildWnd을 CMDIChildWndEx로 변경합니다.

class CChildFrame : public CMDIChildWndEx
{

childfrm.cpp를 열어 모든 CMDIChildWnd를 CMDIChildWndEx로 변경합니다.

변경되는 모든 코드


5. CToolBar, CStatusBar, CMenuBar
mainfrm.h을 열어 CToolBar는 CMFCToolBar로 CStatusBar는 CMFCStatusBar로 변경하고 CMenuBar는 삭제하도록 합니다.  리본을 적용하면 CMenuBar는 사용하지 않습니다.

protected:  // control bar embedded members
    CMFCStatusBar  m_wndStatusBar;
    CMFCToolBar    m_wndToolBar;
    HICON m_hIcon;

mainfrm.cpp를 열어 변경된 클래스의 함수를 적용하여 줍니다.  SetBarStyle -> SetPaneStyle로 GetBarStyle -> GetPaneStyle로 적용합니다. 

    // TODO: Remove this if you don't want tool tips
    m_wndToolBar.SetPaneStyle(m_wndToolBar.GetPaneStyle() |
        CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

또한 DockControlBar를 DockPane으로 변경합니다.

DockPane(&m_wndToolBar);


컴파일이 될것입니다.  실행하면 기존과 동일하게 동작합니다.

6. Ribbon Bar 추가
mainfrm.h에 RibbonBar를 추가 합니다.

    CMFCRibbonBar                     m_wndRibbonBar;  // Ribbon bar for the application
    CMFCRibbonApplicationButton m_MainButton;       // The application button for the ribbon
    CMFCToolBarImages              m_PanelImages;     // Ribbon Panel Icons


7. 리본에서 사용할 아이콘 Import하기
리본을 테스트 하기 위해서 우선은 3가지 Bitmap이 필요로 합니다.

사용자 삽입 이미지


<- Main Application 버튼에 넣을 이미지  ( IDB_RIBBON_MAIN )

사용자 삽입 이미지


<- Large Panel Icon ( IDB_RIBBONLARGE )

사용자 삽입 이미지

<- Small Panel Icon ( IDB_RIBBONSMALL )

위와 같은 이미지를 리소스에 Import하여 주세요..

8. Ribbon Create하고 Main Application을 추가
이제 드디어 Ribbon을 추가 합니다. OnCreate 함수 상단에 다음의 코드를 추가 합니다.

    if (CMDIFrameWndEx::OnCreate(lpCreateStruct) == -1)
        return -1;

    // Create the ribbon bar
    if (!m_wndRibbonBar.Create(this))
    {
        return -1;   //Failed to create ribbon bar
    }

Ribbon Bar가 생성되었습니다.  이제 Main Button을 등록합니다.

    // application button
    m_MainButton.SetImage(IDB_RIBBON_MAIN);
    m_MainButton.SetToolTipText(_T("File"));
    m_MainButton.SetText(_T("\nf"));

    // Attach it to ribbon
    m_wndRibbonBar.SetApplicationButton(&m_MainButton, CSize(45,45));

RibbonBar에 MainButton을 설정하였습니다.  컴파일을 하여 실행하면 아래와 같이 실행됩니다.

사용자 삽입 이미지


리본바가 나타납니다.  그런데 어딘가 이상하죠?  코드를 수정해 나가면서 점점 모습을 갖추어 갈것입니다. 

9. 메인 Category 추가 하기
메 인버튼을 클릭하면 나오는 Main Category을 등록합니다.  AddMainCategory인데 MainPanel을 리턴하는군요 ^__^;... 그다음 버튼들을 추가 합니다.  리본 메인 Panel안에 위치할 버튼들입니다.  보통 File 관련 메뉴들이 위치하게 되겠지요..  여기서 Command ID들은 기존 메뉴 또는 ToolBar에서 사용하는것을 그대로 사용하면 됩니다.  메인 Panel에 넣은 두개의 Bitmap으로 각 버튼의 큰아이콘과 작은 아이콘을 결정할수 있습니다.

    // Main Category
    CMFCRibbonMainPanel* pMainPanel = m_wndRibbonBar.AddMainCategory(_T("File"),                  IDB_RIBBONSMALL, IDB_RIBBONLARGE);
    pMainPanel->Add(new CMFCRibbonButton(ID_FILE_NEW, _T("&New"), 0, 0 ));
    pMainPanel->Add(new CMFCRibbonButton(ID_FILE_OPEN, _T("&Open"), 0, 0 ));
    pMainPanel->Add(new CMFCRibbonButton(ID_FILE_CLOSE, _T("&Close"), 0, 0 ));
    pMainPanel->Add(new CMFCRibbonButton(ID_FILE_SAVE, _T("&Save"), 0, 0 ));
    pMainPanel->Add(new CMFCRibbonButton(ID_FILE_SAVE_AS, _T("Save &As..."), 0, 0 ));

자, 컴파일 하고 실행해 볼까요?

사용자 삽입 이미지

메인 버튼을 클릭하면 메뉴가 나타납니다.  메인 Panel이 생겨났네요..

이제 Print 관련 버튼을 설정합니다.  Print관련 버튼은 새로운 Sub메뉴가 생겨나는 버튼이기 때문에 서브버튼을 넣습니다.

    // Add Print Button
    CMFCRibbonButton* pBtnPrint = new CMFCRibbonButton( ID_FILE_PRINT, _T("&Print"), 4, 4 );
    pBtnPrint->AddSubItem( new CMFCRibbonLabel(_T("Preview and print the document") ) );
    pBtnPrint->AddSubItem( new CMFCRibbonButton( ID_FILE_PRINT, _T("&Print"), 4, 4, TRUE ) );
    pBtnPrint->AddSubItem( new CMFCRibbonButton( ID_FILE_PRINT_PREVIEW, _T("Print Pre&view"), 6, 6, TRUE ) );
    pBtnPrint->SetKeys( _T("p"), _T("w") );
   
    // Add Print Button To Main Panel
    pMainPanel->Add( pBtnPrint );
    pMainPanel->AddSeparator();
    pMainPanel->Add( new CMFCRibbonButton(ID_FILE_CLOSE, _T("&Close"), 5, 5));

컴파일 해서 실행하면 아래와 같이 나타납니다.

사용자 삽입 이미지

Print 버튼이 들어갔습니다.  Label과 버튼 두개가 보이시죠?

이제 Recent File List컨트롤을 넣겠습니다. 

    // Add Recent File List & Exit Button
    pMainPanel->AddRecentFilesList( _T("Recent Documents") );
    pMainPanel->AddToBottom( new CMFCRibbonButton( ID_APP_EXIT, _T("E&xit"), 8));


사용자 삽입 이미지

Recent Document 영역이 생겼습니다.  추가 Exit 버튼도 넣었습니다.

9. Category 넣기
Ribbon 영역에 Category를 넣겠습니다.  Category에 Panel을 생성하고 Element들을 넣을수 있게됩니다.

    // Load Images for ribbon panels
    m_PanelImages.SetImageSize(CSize(16,16));
    m_PanelImages.Load(IDB_RIBBONSMALL);

    // Add a "Home" category to the ribbonbar
    CMFCRibbonCategory* pCategory = m_wndRibbonBar.AddCategory( _T("Home"), IDB_RIBBONSMALL, IDB_RIBBONLARGE );

    CMFCRibbonPanel* pPanelClipboard = pCategory->AddPanel( _T("Clipboard"), m_PanelImages.ExtractIcon(0) ) ;
    pPanelClipboard->Add( new CMFCRibbonButton(ID_EDIT_PASTE, _T("Paste"), 1, 1 ) );
    pPanelClipboard->Add( new CMFCRibbonButton(ID_EDIT_CUT, _T("Cut"), 2, 2 ) );
    pPanelClipboard->Add( new CMFCRibbonButton(ID_EDIT_CLEAR, _T("Clear"), 3, 3 ) );

m_PanelImages는 Panel에서 사용하게될 CMFCToolBarImages입니다.  Category를 넣고 거기에 Panel을 Add하고 Element들을 Add 하면 됩니다. 

사용자 삽입 이미지

어느 정도 모양이 갖추어 졌네요..  여기서 Visual Manager를 적용하면 Modern한 UI로 됩니다.

    // Set the default manager to Office 2007
    CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));
    CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);


이제 Application Look이 적용되었습니다.

사용자 삽입 이미지

그리 어렵지 않게 기존 Scribble 프로젝트에 Ribbon UI 를 적용하였습니다.
툴바가 같이 나오네요..  툴바를 Create하는 구문을 Comment Out 하시면 나오지 않게 되겠죠?  이제 다음 포스트에서 리본에 여러가지 기능을 적용해 보겠습니다.


반응형
반응형

http://cafe.naver.com/opendori.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=25355

 

=================================================================================================

 

http://cafe.naver.com/cyberzone/401





스크롤바는 윈도우의 문서의 스크롤을 도와주는 컨트롤이다. 각 부분은 다음과 같은 명칭을 갖는다.

최근에는 스크롤바에의한 스크롤보다는 마우스 휠에의한 스크롤이 더 편리하게 여겨지고 있다.

스크롤바의 생성

스크롤 바는 두가지 방법으로 만들 수 있다. 첫 번째 방법은 window class에 WS_HSCROLL, WS_VSCROLL 스타일을 주어서 만드는 것이고, 둘째 방법은 CreateWindow 함수로 "scrollbar"라는 이미 등록되어 있는 WNDCLASS를 찍어내어 만든다.

스크롤바는 다음과 같은 스타일을 가질 수 있다.

스타일

설명

SBS_HORZ

수평 스크롤바

SBS_VERT

수직 스크롤바

SBS_BOTTOMALIGN

크기가 크더라도 일정한 크기로 아래에 붙여버림

SBS_TOPALIGN

크기가 크더라도 일정한 크기로 위에 붙여버림

SBS_LEFTALIGN

크기가 크더라도 일정한 크기로 왼쪽에 붙여버림

SBS_RIGHTALIGN

크기가 크더라도 일정한 크기로 오른쪽에 붙여버림

스크롤바의 메시지

스크롤 바 혹은 스크롤 윈도우는 WM_HSCROLL, WM_VSCROLL 메시지를 받는다. 각 경우 모두 동일하게 처리되며 인자들은 다음과 같다.

인수

설명

LOWORD(wParam)

스크롤 코드

HIWORD(wParam)

썸의 위치값이다. 이 값은 사용자가 썸을 드랙할 때만 세팅된다.

lParam

스크롤 바의 HWND, 표준 스크롤 바일 경우는 NULL

이들 메시지 처리 방법은 스크롤 코드인 LOWORD(wParam)을 기준으로 다음과 같이 한다.

스크롤 코드

처리 방법

SB_LINEUP

사용자가 위쪽 arrow를 눌렀다. 한 줄 위로 올려준다.

SB_LINEDOWN

사용자가 아래쪽 arrow를 눌렀다. 한 줄 아래로 내려준다.

SB_PAGEUP

사용자가 위쪽 shaft를 눌렀다. 한 페이지 위로 올려준다.

SB_PAGEDOWN

사용자가 아래쪽 shaft를 눌렀다. 한 페이지 아래로 내려준다.

SB_ENDSCROLL

스크롤이 종료되었다.

SB_TOP

제일 위쪽으로 스크롤 되었다.

SB_BOTTOM

제일 아래쪽으로 스크롤 되었다.

SB_THUMBTRACK

사용자가 썸을 드랙하고 있다. 변경된 스크롤 값에 맞게 되면을 다시 그린다.

SB_THUMBPOSITION

사용자가 썸을 드랙한 후 마우스를 놓았다. 변경된 스크롤 값에 맞게 화면을 다시 그린다.

제일 아래 두 코드는 상호 대체성이 있기 때문에 둘 중의 하나만 달아주면 된다.

만일 키보드를 지원하고 싶다면 아래 코드를 추가하라.

case WM_KEYDOWN:
	switch(wParam)
	{
	case VK_UP: SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_LINEUP, 0), 0); break;
	case VK_DOWN: SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_LINEDOWN, 0), 0); break;
	case VK_PRIOR: SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0); break;
	case VK_NEXT: SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0); break;
	case VK_HOME: SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_TOP, 0), 0); break;
	case VK_END: SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_BOTTOM, 0), 0); break;
	}

스크롤바 관련 함수

  • BOOL SetScrollRange(HWND hwnd, int bar, int min, int max, BOOL redraw)

스크롤바의 범위는 표준 스크롤바의 경우는 0~100, 스크롤바 컨트롤의 경우에는 0~0이다. 이 값은 SetScrollRange 함수로 변경할 수 있다.

첫 번째 인자가 윈도우의 핸들일 경우 bar에는 SB_HORZ나 SB_VERT가 와야 한다. 첫 번째 인자가 스크롤바 컨트롤일 경우에는 SB_CTL이 와야한다.

만일 min==max이면 스크롤바는 숨겨진다.

스크롤바의 범위를 세팅할 때는 한가지 주의해야 할 점이 있다. 문서의 height와 같게 range를 설정하면 안된다는 것이다. 그 경우에는 현재 화면의 가장 위가 0이고 마지막 화면의 가장 위가 height가될 때 까지 스크롤 되므로, 맨 마지막에 한 화면 만큼의 빈 공간이 들어가게 된다.

  • BOOL GetScrollRange(HWND hwnd, int bar, LPINT lpmin, LPINT lpmax)

이 함수의 첫 번째 두 개의 인자는 위의 SetScrollRange와 같다. 나머지 두 인자는 정수값을 얻어올 주소이다.

  • int SetScrollPos(HWND hwnd, int bar, int pos, BOOL redraw)

이 함수는 스크롤바의 현재 위치를 세팅해 준다. 기존값이 리턴된다.

  • int GetScrollPos(HWND hwnd, int bar)

스크롤바의 현재 위치를 얻어온다.

다음은 Win32에서 추가된 스크롤바 함수들이다.

  • int SetScrollInfo(HWND hwnd, int bar, LPSCROLLINFO lpsi, BOOL redraw)

이 함수는 위의 많은 일들을 한번에 처리하는 함수이다. 세 번째 인자는 다음 구조체로 설정한다.

typedef struct tag SCROLLINFO
{
	UINT cbSize;
	UINT fMask;
	int nMin;
	int nMax;
	UINT nPage;
	int nPos;
	int nTrackPos;
} SCROLLINFO;
typedef SCROLLINFO FAR* LPSCROLLINFO;

cbSize에는 sizeof(SCROLLINFO)를 대입해 주면 된다.

fMask에는 설정할 값을 지정한다. 다음 값들중의 하나이다.

설명

SIF_DISABLENOSCROLL

범위가 0이 되더라도 스크롤바를 숨기지 않고 사용 금지 시킨다.

SIF_PAGE

nPage로 페이지의 크기를 정한다.

SIF_POS

nPos값으로 위치를 정한다.

SIF_RANGE

nMin, nMax값으로 range를 설정한다.

SIF_ALL

모든 플래그의 조합

nPage에 관한 것이 새로 추가된 것으로 썸의 크기를 결정하는데 사용하는 한 페이지의 크기를 말한다.

SetScrollInfo 함수는 nTrackPos를 사용하지 않는다.

  • BOOL GetScrollInfo(HWND hwnd, int bar, LPSCROLLINFO lpsi)

스크롤바에 관한 모든 정보를 한번에 얻어온다. nTrackPos 맴버는 SB_THUMBTRACK 메시지에서 드래그 중의 썸의 위치를 넘긴다.

  • BOOL ShowScrollBar(HWND hwnd, int bar, BOOL show)

이 함수는 스크롤바를 보이거나 보이지 않게 한다.

  • BOOL EnableScrollBar(HWND hwnd, int bar, UINT arrow)

이 함수는 스크롤바를 보이거나 보이지 않게 한다. arrow에는 다음 값들이 올 수 있다.

arrow 값

설명

ESB_DISABLE_BOTH

모든 버튼을 금지

ESB_DISABLE_DOWN

아래쪽 버튼을 금지

ESB_DISABLE_LEFT

왼쪽 버튼을 금지

ESB_DISABLE_LTUP

왼쪽, 위 버튼을 금지

ESB_DISABLE_RIGHT

오른쪽 버튼을 금지

ESB_DISABLE_RTDN

오른쪽, 아래쪽 버튼을 금지

ESB_DISABLE_UP

위쪽 버튼을 금지

ESB_ENABLE_BOTH

모든 버튼을 허가

반응형
반응형

http://cafe.naver.com/opendori/4949




Scrolling credits using CStatic

 

 
Download 
source file or demo project.

This static subclass is based on the Scrolling credits dialog by Mark Findlay. I have made some modifications to enable the use of resource strings, and added some functionality to make the background look more professional. By implementing the functionality through a CStatic subclass it is no longer dependant on a dialog and can more easily be used in different circumstances.

The control lets you scroll text and bitmaps in an like you see in movies. It will continue to loop the text for as long as it is active. The speed of the scrolling can be set by the programmer. The control has the following features:

  • The text/bitmap sequence can be set using a character string or through am ID to a string table entry.
  • The text/bitmap sequence is formatted with different colours and fonts through using special characters in the text. The mapping between the special characters and given colours and fonts can be set by the programmer 

    NB! The bitmaps are given as quoted bitmap resources (ID as "IDB_BITMAP" instead of just IDB_BITMAP).
  • The background can be given a special colour or a background bitmap can be set. 

    NB! While bitmaps in the text/bitmap sequence are restricted to 16 colours, the background bitmap have no such restriction.) 

    If a solid colour background is used, it can be given a gradient to black or white, left-to-right or vice-versa.
  • The background of the bitmaps in the text/bitmap sequence can be made transparent to allow for non-square shapes. By setting a flag, the parts of the bitmaps that have the standard dialog colour (RGB(192,192,192)) will be transparent. 

    NB! There is a slight difference in how this functionality is implemented when using a background image instead of colour. Because of the way the addition of a background image is implemented all parts of the text/sequence that have the standard dialog colour will be transparent, not only the bitmaps. Also, when the transparent colour is _not_ set, all parts of the text/bitmap sequence that match the otherwise not active background colour, will be transparent as well. So, to disallow transparency when using a background image, set the background colour so an unused colour. 

    NB! Because there is several bitblt's involved when using a background image, the scrolling is slowed down considerably. But it does look good!! (If anyone can find ways of speeding up this process, please contact me!)
  • If not scrolling is started, a still picture of the text/bitmap sequence is displayed (That's how the figure was created). 

    Beware of the following differences between this implementation and the one of Mark Findlay:
  • Instead of an array of strings, this control uses a single string. This is to allow the use of resource strings. 

    A delimiter character (standard '|') is given to mark the beginning of a new line.
  • The special character denoting "normal" text has been removed. A line without any special character will be formatted according to the "normal text" rules.
  • Several of the default special characters have been changed, This was necessary because the string table resources did not understand all the original escape sequences.

To use CCreditStatic a member variable must be added to the dialog:

protected:
CCreditStatic m_static;

In OnInitDialog the static control is subclassed and the credit text is added. Optionally a background image can be added:

char *pArrCredit = { "NETBAS FOR WINDOWS NT\t||Copyright (c) 1998|"
        "Test Data AS|All Rights Reserved||"
        "BITMAP1^|||"    // this is a quoted bitmap resource 
        "Project Lead\r||Kjetil Kvamme|||"
        "Technical Lead\r||Kjetil Kvamme|||"
        "Engineering Lead\r||Paul K. Tonder|||"
        "Product Lead\r||Tom Rotting|||"
        "Engineering\r||Paul K. Tonder,  Rolf T. Wold,  Sigbjorn Helset|"
        "Reidar Ognedal,  Kjetil Kvamme, Arne Bakken|||"
        "BITMAP2^|||"  // this is a quoted bitmap resource 
        "QA\r||Mary Hech,  Sam Bamnm,  Ron Fonn,  Steve Waeve|"
        "Igor Borisnoff,  FellaB |||"
        "Documentation\r||"
        "Arvid Molnvik,  Joanne Hone,  Annette Fune|||"
        "Technical Program Office\r||Burf Murphy, Foll Roller||||"
        "Systems Support\r||Bendy Land|||"
        "Administrative Support\r||Donna Fonna|||"
        "* * * * * * * * *\t|||"
        "BITMAP3^||"
        "Project Manager\r||Dwain Kinghorn|||"
        "Engineering\r||"
        "Hank Bank,  Ray Fay,  Bill Sill,  Mark Dark,  Peter Leter|"
        "Lev Bef|||Quality Assurance\r||"
        "Biff Bin||||"
        "BITMAP4^|||||"
        };

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

        m_static.SubclassDlgItem(IDC_DISPLAY_STATIC,this);
        m_static.SetCredits(pArrCredit);
        // m_static.SetCredits(IDS_CREDITS);  // Use with string resource
        m_static.SetSpeed(DISPLAY_FAST);
        m_static.SetColor(BACKGROUND_COLOR, RGB(0, 0, 255)); // Background Colour
        m_static.SetTransparent(); // Set parts of bitmaps with RGB(192,192,192) transparent
        m_static.SetGradient(GRADIENT_RIGHT_DARK);  // Background goes from blue to black from left to right
        // m_static.SetBkImage(IDB_BITMAP1); // Background image
        m_static.StartScrolling();
        return TRUE;  // return TRUE unless you set the focus to a control
                      // EXCEPTION: OCX Property Pages should return FALSE
}

Note: Keith Rule was kind enough to fix a number of resource leaks that can bring the App down on Windows95. The fixes have mostly been to select the original GDI objects back into the device context.

The example project shows one use of the control. A Credits dialog is displayed when the user double-click in the view window. In addition to showing the basics for using the control, the project also shows how cycling of background images can be implemented. The background image is periodically switched (every 5 seconds). This background image cycling management is implemented in the dialog box rather than in the control itself. The background image is switched through repeated calls to the BkImage method of the CCreditStatic object.

 

반응형
반응형

http://cafe.naver.com/bc6783232/1347




MFC 강의 - 4 컨트롤 다루기 -버튼


일단 처음은 대화상자 기반으로 만듭니다.(컨트롤을 만들고 배치하기 편하기 때문에...)
1.
처음에 생성되는 버튼들을 전부 지웁니다.

도구상자에 있는 버튼을 클릭해서

이렇게 가운데 하나를 배치하고 아래에 세 개를 배치합니다.

배튼 한 개씩 클릭해서 옆에 있는 속성창의 caption과 ID를 수정합니다.
순서는 달라고 되니까 ID와 CAPTION이 일치하도록 해주세요.

제목 바꾸기 - IDC_BUTTON_TITLE
숨기기        - IDC_BUTTON_SHOW
사용하지 못하게 함 - IDC_BUTTON_DISABLE

그 다음 MFC 클래스 마법사를 실행하면 (오른쪽 클릭 후 클래스 마법사항목 선택)
개체 ID와 메시지라는 항목이 나옵니다.
메시지 항목은 왼쪽의 클릭된 객체의 메시지(버튼이 클릭되었을 경우라던가...)입니다.
우리가 만들었던 버튼들 중 IDC_BUTTON_TITLE를 빼고 전부 BN_CLICKED메시지를 클릭하여 처리기를 추가합니다.
이렇게 하면 버튼들이 클릭되었을 때(이벤트) 운영체제에서 해당 버튼이 클릭 되었다는 메시지(BN_CLICKED)를 보내는 처리기(함수)를 설정해 주는 것 입니다.



코드 창을 보면 클래스의 메소드 3개가 추가되어있는 것을 확인할 수 있습니다.

그럼 우선 OnClickedButtonDisable()이란 함수를 수정해 보도록 하겠습니다.
"사용하지 못하게 함"이라 써져 있던 버튼이 클릭되어 있을 때 실행되는 메소드입니다.

void CMFC4Dlg::OnClickedButtonDisable()
{
//현재 버튼이 어떤 상태인지를 기억하기 위한 변수를 선언합니다. 함수가 종료더라도 상태
//은 기억되야 하므로 정적변수로 선언합니다.
//처음 실행될 때의 상태는 사용할 수 있으므로 true로...
static bool bEnable = true;
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
//누르면 상태가 바뀌어야 하므로 !연산자을 한 자기 자신을 대입합니다.
bEnable = !bEnable;
//GetDlgItem()은 해당 ID인 컨트롤인 클래스의 주소를 반환합니다. 클래스의 메
//소드를 이용하여 컨트롤의 상태를 조절할 수 있습니다.
//컨트롤 클래스의 메소드인 EnableWindow()는 bool변수를 인수로 가지며,
//true일 경우 버튼을 사용할 수 있게, false일 경우 버튼을 사용불가로 만듭니
//다.
GetDlgItem(IDC_BUTTON_TAGET)->EnableWindow(bEnable);
if(bEnable)
{
//SetWindowText()메소드는 버튼의 텍스트를 설정하는 메소트입니다.

GetDlgItem(IDC_BUTTON_DISABLE)->SetWindowText(_T("사용하지 못하게
                함"));
}
else
{
GetDlgItem(IDC_BUTTON_DISABLE)->SetWindowText(_T("사용하게 함"));
}
}
다음은 "숨기기"라 써져있던 버튼이 클릭되었을 때 실행되는 메소드를 수정해 보겠습니다.
OnClickedButtonShow이란 메소드입니다.

void CMFC4Dlg::OnClickedButtonShow()
{
static bool bShow=true;
bShow = !bShow;
GetDlgItem(IDC_BUTTON_TAGET)->ShowWindow(bShow);
if(bShow)
{
GetDlgItem(IDC_BUTTON_SHOW)->SetWindowText(_T("숨기기"));
}
else
{
GetDlgItem(IDC_BUTTON_SHOW)->SetWindowText(_T("보이기"));
}
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
}
내용은 거의 같습니다. 다만 EnableWindow(bEnable)이 아닌  ShowWindow(bShow)인데
인수가 true면 보이는 상태로 false면 보이지 않는 상태로 변경합니다.

이제 제목 바꾸기 라는 버튼이 클릭되었을 때 실행되는 메소드를 수정해 보겠습니다.
OnClickedButtonTitle이란 메소드 입니다.


void CMFC4Dlg::OnClickedButtonTitle()
{
static bool bTitle =true;
bTitle = !bTitle;
if(bTitle)
{
GetDlgItem(IDC_BUTTON_TAGET)->SetWindowTextW(_T("바뀌었다."));
}
else
{
GetDlgItem(IDC_BUTTON_TAGET)->SetWindowTextW(_T("실험체"));
}
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
}
참고로 버튼(컨트롤)의 상태를 변경하는 메소드가 Window라고 써져있는 이유는
사실 컨트롤들은 일종의 윈도창입니다. 자세한 것은 인터넷에 검색해 보시길...

반응형
반응형

http://blog.naver.com/intencelove?Redirect=Log&logNo=20102281965



DE: MSVS2005 - dialog based

갑자기 슬라이더 컨트롤을 사용할 일이 생겼서 오랜만에 사용하다 보니 헷갈리는 부분이 있어, 조금 헤맸습니다. 그래서 이렇게 잊어 버리지 않기 위해 포스팅을 해요!!

 

 

Dialog에 slider control을 붙인다.

위의 그림은 defualt값이 아니라 속성을 추가 하여 준것입니다. (orientation, point 2개의 속성 추가)

 

그리고 slider bar의 ID를 IDC_SLIDER_* 로 설정한 후 (* 표시는 사용자의 임의로 정합니다.)

멤버 변수를 control type인 CSliderCtrl 로 해준다.

멤버변수의 추가는 우선 슬라이더 컨트롤에서 마우스 오른쪽 키를 누른다. 그럼 아래의 그림처럼 속성이 보일 것입니다.

 

6.0을 사용하시는 분은 ctrl + w (class wizard 단축키)를 통해 추가 하시면 될 것같습니다.

그럼 아래와 같은 그림을 통해서 추가 하시면 여러분의 헤더파일에 CSliderCtrl m_ctrlSlider라고 생길 거예요^^

 

그리고 여러분의 *.C 파일에 OnInitDialog()에 아래 부분의 소스를 추가 해주시면 됩니다.

혹시나 slider bar의 인자들이 궁금하시다면 아래 포스팅을 참조 하세요^^

http://blog.naver.com/intencelove/20102277196 

 // slider control
 m_ctrlSlider.SetRange(0, 255); // slider 전체 크기
 m_ctrlSlider.SetPos(100);  // slider 초기 위치 
 m_ctrlSlider.SetTicFreq(10); // slider 눈금 간격
 m_ctrlSlider.SetSelection(40, 200);// slider focus range

 

그리고 나서 슬라이더가 이동했을때 발생하는 이벤트

OnNMReleasedcaptureSlider를 추가해주셔야 합니다. 다시 한번 슬라이더 컨트롤로 이동(리소스뷰)에서 슬라이더 컨트롤을 누르면 (2005의 경우 오른쪽에 아래그림과 같이 화면이 나타 납니다.)

6.0같은 경우 class wizard에서 이벤트 메시지를 추가해주면 될것같아요

 

 

그리고 난 후 슬라이더의 현재위치를 알기 위해 추가된 함수에 코딩을 하면 됩니다.

 

void CImageDlg::OnNMReleasedcaptureSliderThreshold(NMHDR *pNMHDR, LRESULT *pResult)
{
      m_ctrlSlider.GetPos(); //현재 슬라이더의 위치를 가져 옴
      *pResult = 0;
}

반응형
반응형

WS_CAPTION 만 수정해서는 원하는 결과를 얻을수없다.

  • 타이틀바 보이기
    • ModifyStyle(0, WS_CAPTION, SWP_FRAMECHANGED);
  • 타이틀바 감추기
    • ModifyStyle(WS_CAPTION | WS_BORDER, 0);

API를 사용한다면

GetWindowLong 함수와 SetWindowLong 함수를 사용하여 스타일을 변경하고

SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);

를 호출해주면되겠다.

반응형
반응형

 written by http://www.winapi.co.kr



2-3-나. 커서 바꾸기

예제의 윈도우위에 마우스 커서를 위치시키면 화살표 모양의 커서가 나타난다. 이 커서가 사용되는 이유는 WndClass에서 커서를 지정하는 멤버가 다음과 같이 정의되어 있기 때문이다.

WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);

hCursor 멤버는 윈도우가 기본적으로 사용할 커서를 지정하며 LoadCursor 함수는 커서를 읽어오는 함수이다.

HCURSOR LoadCursor( HINSTANCE hInstance, LPCTSTR lpCursorName ); 

첫번째 인수 hInstance는 커서를 가지고 있는 프로그램의 인스턴스 핸들이되 윈도우즈가 제공하는 디폴트 커서를 사용하려면 이 인수를 NULL로 지정하면 된다. 두번째 인수 lpCursorName은 사용하고자 하는 커서의 이름을 지정한다. 윈도우즈가 디폴트로 제공하는 커서에는 다음과 같은 종류가 있다.

설명
IDC_ARROW화살표 모양
IDC_CROSS십자 모양
IDC_IBEAMI자 모양
IDC_NO원안에 빗금이 쳐진 모양
IDC-WAIT모래시계 모양

LoadCursor 함수의 두번째 인수로 이 값들을 지정해보고 다시 컴파일하여 커서를 직접 변경해 보도록 하자. 윈도우즈가 제공하는 디폴트 커서외에 자신이 직접 커서를 만들어 사용하는 방법도 있는데 이 방법은 5장에 가서 알아보도록 하자.


목록 보기  다음 강좌           

 

 

 

LoadCursor(NULL,IDC_ARROW);

::SendMessage(pView->m_hWnd, WM_SETCURSOR ,1,0);

 

 

 

BOOL CSTool_mapv10MFCView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
 // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
  
 if(m_hCursor){
  ::SetCursor(m_hCursor);
  return TRUE;
 }

 return CView::OnSetCursor(pWnd, nHitTest, message);
}

 

 

 

 

 

 

 

 

커서종류

IDC_ARROW

표준 화살표 커서

IDC_IBEAM

I 모양의 문자열 삽입 커서

IDC_WAIT

모래 시계 커서

IDC_CROSS

십자 모양 커서

IDC_UPARROW

위쪽 화살표 커서

IDC_SIZE

윈도우의 크기를 조정할 때 사용하는 커서

IDC_ICON

파일을 드래그할 때 사용하는 커서

IDC_SIZENWSE

좌상단, 우하단 화살표 커서

IDC_SIZENESW

좌하단, 우상단 화살표 커서

IDC_SIZEWE

수평 크기 조절 커서

IDC_SIZENS

수직 크기 조절 커서

 

 

 


반응형
반응형

http://blog.naver.com/donkey612?Redirect=Log&logNo=70045525967

 

 

 

 

CMenu  m_ContextMenu;  //반대 메뉴버튼

CMenu* GetContextMenu(){ return &m_ContextMenu; }

 

 

 

RECT ClientRect;
   POINT Point={0,0};
   ::GetClientRect( m_hWnd, &ClientRect );
   ::ClientToScreen( m_hWnd, &Point );
   ::GetCursorPos( &Point );
   CSTool_mapv10MFCView* view=((CSTool_mapv10MFCView*)((CMainFrame*)AfxGetMainWnd())->GetActiveView());
   view->GetContextMenu()->GetSubMenu( RIGHTMENUINDEX )->TrackPopupMenu(
    TPM_LEFTALIGN | TPM_RIGHTBUTTON,Point.x+ClientRect.left,Point.y + ClientRect.top
    ,view->GetParentFrame());


반응형
반응형


BOOL CSDICtrlApp::InitInstance()

{

    // 생략

    // 메뉴를 표시하지않음

    m_pMainWnd->SetMenu(NULL);

    // 창 하나만 초기화되었으므로 이를 표시하고 업데이트합니다.

    m_pMainWnd->ShowWindow(SW_SHOW);

    m_pMainWnd->UpdateWindow();


    return TRUE;

}

 

 

 

// 메인 프레임에서 메뉴 되돌리기

HMENU hMenu = ::LoadMenu(theApp.m_hInstance, MAKEINTRESOURCE(IDR_MAINFRAME));

::SetMenu(m_hWnd, hMenu);


반응형
반응형

툴바와 상태바는 모두 콘트롤 바에서 상속받은 것으로, SDI나 MDI의 경우 기본적으로 나타나도록 되어 있습니다. 메인 프레임 클래스에 보면 이들이 멤버 변수로 설정되어 있는 것을 볼 수 있습니다.

CStatusBar  m_wndStatusBar;

CToolBar    m_wndToolBar;

 

기본적으로 "보기" 메뉴에 이들을 보이거나 숨기는 기능이 있지만 사용자가  새로운 컨트롤바를 첨가하였을 경우에는 이를 직접 처리해주어야 합니다.

 

툴바를 보이거나 숨기도록 해보겠습니다.

먼저 메뉴의 "보기"에 "새 도구모음"이라는 메뉴 항목을 만듭니다. 그리고 현재 툴바의 상태를 저장하기 위한 변수를 선언합니다.

BOOL m_bShowToolBar;

 

메뉴에 대한 COMMAND와 UPDATE_COMMAND_UI에 각각의 핸들러를 작성합니다.

콘트롤 바를 보이거나 숨기는 함수는 ShowControlBar로 이는 메인 프레임 클래스의 멤버 함수입니다. 메뉴 COMMAND에서 이를 조절합니다.

void CMainFrame::OnShowToolbar() 
{

    // TODO: Add your command handler code here
    if(m_bShowToolBar){
        m_bShowToolBar = FALSE;
        ShowControlBar(&m_wndToolBar, 
FALSE
, FALSE); // 숨기기
    }
    else{
        m_bShowToolBar = TRUE;
        ShowControlBar(&m_wndToolBar, 
TRUE
, FALSE); // 보이기
        }
}

 

 다음은 콘트롤 바가 보이는 경우 메뉴에 체크 표시를 해야 합니다. 이는 메뉴의

UPDATE_COMMAND_UI에서 해주면 됩니다.

 

void CMainFrame::OnUpdateShowToolbar(CCmdUI* pCmdUI) 
{
        // TODO: Add your command update UI handler code here
        BOOL visible = m_wndToolBar.IsWindowVisible();

 

        if(visible) pCmdUI->SetCheck(TRUE);
        else pCmdUI->SetCheck(FALSE);
}

 

콘트롤 바는 CWnd 클래스에서 상속을 받아 만들어졌기 때문에 IsWindowVisible 함수로 보이는 지의 여부를 알아낼 수 있습니다.

 

새로운 메뉴 항목은 기존의 "보기->도구모음" 메뉴 항목과 동일하게 동작합니다.


 

상태바나 사용자가 첨가한 툴바의 경우에도 같은 방법으로 처리가 가능합니다.

반응형
반응형

현재 마우스 위치의 윈도우 핸들 얻기 - WindowFromPoint()

등록자 : 유광희, 05-08-05 01:29:37

google_protectAndRun("render_ads.js::google_render_ad", google_handleError, google_render_ad); POINT  Point;
char ClassName[128];

GetCursorPos(&Point);

HWND hWnd = WindowFromPoint(Point);

GetClassName(hWnd, (char *)&ClassName, 128);

if (*ClassName)
OutputDebugString(ClassName);

반응형

'프로그래밍(Programming) > MFC&API' 카테고리의 다른 글

메뉴바 숨기기  (0) 2012.11.01
툴바,상태바 보이기/숨기기  (0) 2012.11.01
현재 마우스 좌표얻기  (0) 2012.11.01
AfxMessageBox 인자 총정리  (0) 2012.11.01
파일 세이브 다이얼로그  (0) 2012.11.01
반응형

GetCursorPos( &ptCursor );
 ScreenToClient( m_hWnd, &ptCursor );


반응형
반응형

http://blog.naver.com/cysatan?Redirect=Log&logNo=10051502240



1. MSDN 설명

int AfxMessageBox(
   LPCTSTR lpszText,
   UINT nType = MB_OK,
   UINT nIDHelp = 0 
);
int AFXAPI AfxMessageBox(
   UINT nIDPrompt,
   UINT nType = MB_OK,
   UINT nIDHelp = (UINT) -1 
);
lpszText

Points to a CString object or null-terminated string containing the message to be displayed in the message box.

nType

The style of the message box. Apply any of the < >message-box :Track(?ctl00_MainContent_cpe90361_c|ctl00_MainContent_ctl05?,this);?>to the box.

nIDHelp

The Help context ID for the message; 0 indicates the application's default Help context will be used.

nIDPrompt

A unique ID used to reference a string in the string table.

 

2 . 기본설정

 

int AfxMessageBox(LPCTSTR lpszText, UINT nType = MB_OK, UINT nIDHelp = 0);

 

MessageBox와는 달리 제목을 넣는 부분은 사라졌습니다.

 

Example)

 

AfxMessageBox(“메시지 박스 테스트”, MB_OK | MB_ICONEXCLAMATION);

 

 

nType은 다음 중에서 각각 하나씩 조합해서 사용할 수 있습니다.

 

버튼 스타일                                    의미

MB_ABORTRETRYIGNORE                [취소], [재시도], [무시]

MB_OK                                           [확인]

MB_OKCANCEL                               [확인], [취소]

MB_RETRYCANCEL                         [재시도], [취소]

MB_YESNO                                     [], [아니오]

MB_YESNOCANCEL                         [], [아니오], [취소]

 

 

아이콘 스타일                                  의미

MB_ICONEXCLAMATION                   [느낌표]

MB_ICONINFORMATION                    [느낌표]

MB_ICONQUESTION                          [물음표]

MB_ICONSTOP                                 [X]

 

 

디폴트 버튼                                     의미

MB_DEFBUTTON1                             첫 번째 버튼

MB_DEFBUTTON2                             두 번째 버튼

MB_DEFBUTTON3                             세 번째 버튼

 

 

모달리티                                         의미

MB_APPLMODAL                              메시지 박스를 종료시켜야 프로그램을 계속 진행할 수 있음

MB_SYSTEMMODAL                          메시지 박스를 종료시켜야 시스템을 사용할 수 있음

 

 

반환값                                            의미

IDABORT                                         [취소(Abort)]가 눌러 졌음

IDCANCEL                                       [취소(Cancel)]이 눌러 졌음

IDIGNORE                                        [무시]가 눌러 졌음

IDNO                                               [아니오]가 눌러 졌음

IDOK                                               [확인]이 눌러 졌음

IDRETRY                                          [재시도]가 눌러 졌음

IDYES                                             []가 눌러 졌음

3. 추가 옵션

 

CString temp;

int nScore;

nScore = 99;

 

temp.Format(_T("당신의 점수는 %d점입니다."), nScore);

AfxMessageBox(temp);

 

참고 : http://blog.naver.com/cysatan/10047219216

 

4. 기타

 

일일이 창띄워서 확인을 해야한다면 모르겠지만 아니라면

 

TRACE(""); 함수를 써도 괜찮은거같다.

 

괄호 안의 형식은 Afxmessagebox와 비슷하며 출력은 Output창에 표시된다.

 

 

 

출처: 0. http://msdn.microsoft.com/en-us/library/as6se7cb.aspx

1. AfxMessageBox()를 써 보자

2.  http://kin.naver.com/detail/detail.php?d1id=1&dir_id=10104&eid=uFAjiv1k4JmCyEjQuiylTjEnq1MrK8xU&qb=YWZ4bWVzc2FnZWJveA==&enc=utf8&section=kin&rank=1&sort=0&spq=0&pid=fCbs6doi5UNsscSEda0sss--387710&sid=SkFx15BeQUoAAAr4MIk

반응형
반응형

// TODO: 여기에 명령 처리기 코드를 추가합니다.
 CFileDialog  ofn(FALSE);  //false : 저장 true 불러오기
 CString selectedFilePath;
 char szFilter[] = "3DS files (*.3DS)\0*.3DS\0\0";

 ofn.m_ofn.lpstrFilter = szFilter;
 ofn.m_ofn.Flags |= OFN_NOCHANGEDIR;
 if( ofn.DoModal() == IDOK)
 {
  selectedFilePath = ofn.GetPathName();
  C3dsExporter export3DS;
  selectedFilePath+=".3DS";
  char* fname=(LPSTR)(LPCSTR)selectedFilePath;
  export3DS.save3ds( C3DSParser::GetInstancePtr()->Get3DModel(), fname);
  


 }

반응형
반응형

char szFilter[] = "Image Files(*.BMP, *.GIF, *.JPG, *.TIF)|*.BMP;*.GIF;*.JPG;*.TIF|All Files(*.*)|*.*||";

 CFileDialog fileDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, szFilter);
 if(IDOK == fileDlg.DoModal())
 {
  CString fpath =  fileDlg.GetPathName();
  OpenDocumentFile(fileDlg.GetPathName());
 }

반응형
반응형

과거 클래스 위자드에서 어떤 이벤트 메시지를 추가하면 적당한 위치에 알맞게 잘 들어갔던 반면, 지금은 추가를 하게 되면 코드의 가독성도 꽝이고, 무엇보다 전혀 의도하지 않은 위치에 들어가버린다. 그 중 메시지 맵에서 이벤트 메시지를 추가할 때 매우 조심스럽게 해야할 부분이 있어 글을 남긴다.


사용자가 이벤트 핸들러 함수를 추가 했을 경우, 또는 재정의 했을 경우 반드시 아래의 굵게 표시한 곳으로 옮기던지, 이전의 동일한 아이디의 핸들러 함수를 주석처리하여야 사용자의 함수가 정상적으로 호출된다.


BEGIN_MESSAGE_MAP(CMyToolApp, CWinApp)
    ON_COMMAND(ID_APP_ABOUT, &CMyToolApp::OnAppAbout)
    ON_COMMAND(ID_FILE_OPEN, &CMyToolApp::OnFileOpen)
    // 표준 파일을 기초로 하는 문서 명령입니다.
    ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
    //ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
    ON_COMMAND(ID_FILE_OPEN, &CMyToolApp::OnFileOpen)
END_MESSAGE_MAP()





CWinApp 를 상속받은 사용자 App 클래스가 있다고 하자. 그 클래스를 CMyToolApp 라고 하자. 그리고 프로그램에서 파일을 열고 새 파일을 만드는 아이디를 각각 ID_FILE_OPEN 과 ID_FILE_NEW 처럼 기본으로 정의되어 있는 아이디를 사용한다고 하자.

이때 ID_FILE_OPEN 을 재정의하여 몇가지 기능을 추가한다고 한다면 클래스 뷰에서 CMyToolApp 에서 속성창을 열고, 속성창에서 이벤트 아이콘을 누른 후 이벤트 핸들러 함수로 만들 아이디 ID_FILE_OPEN 에서 COMMAND 이벤트 헨들러 함수를 추가하면 자동으로 코드가 추가가된다.

그 중 아래의 메시지 맵에서 매우 조심해야하는 부분이 있다.


BEGIN_MESSAGE_MAP(CMyToolApp, CWinApp)
    ON_COMMAND(ID_APP_ABOUT, &CMyToolApp::OnAppAbout)
    // 표준 파일을 기초로 하는 문서 명령입니다.
    ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
    ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
    ON_COMMAND(ID_FILE_OPEN, &CMyToolApp::OnFileOpen)
END_MESSAGE_MAP()


자동으로 추가가 되는 위치가 위에서 굵게 표시한 곳이다.
하지만 저곳에 추가가 되면 다음과 같은 문제가 생긴다.

우리가 새롭게 재정의한, 추가한, OnFileOpen() 함수가 호출되지 않고 CWinApp 의 OnFileOpen() 함수가 호출이 되어버린다.

즉, 동일한 아이디는 가장 먼저 만나는, 소스 코드 상에서 위쪽에 있는 것만을 실행시키고 메시지 맵을 벗어나버린다. 마치 switch() 문에서 동일한 케이스가 있다면 위쪽의 case만 되는 것과 같다.

과거 VC++ 6.0 일 때는 위와 같은 상황에서 메시지 맵이 추가가 되는 부분이 정해져있었다.


BEGIN_MESSAGE_MAP(CMyToolApp, CWinApp)
    //{{AFX_MSG_MAP(CMyToolApp)
    ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
    ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
    //}}AFX_MSG_MAP
    // Standard file based document commands
    ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
    ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
END_MESSAGE_MAP()


위에서 굵게 되어 있는 블럭 안에 사용자 이벤트 핸들러 함수를 자동으로 추가를 시켜줬었다. 항상 상위 클래스의 것보다 자신의 클래스의 핸들러 함수가 위쪽에 추가되었기 때문에 문제가 없었다.


반응형
반응형

mainframe 에서 ..

 

ON_COMMAND(ID_BUTTON_MAINMENU, OnMainMenu) //메시지맵에 툴바버튼 아이디와 함수를 넣어준다.

 

afx_msg void OnMainMenu(); //헤더파일에 함수를 선언한다

 

void CMainFrame::OnMainMenu() //소스파일에 함수를 정의한다.

{

 

}

반응형
반응형

해당 핸들을 제일 상단에 배치시킨다


::SetForegroundWindow(g_hWnd);

반응형

+ Recent posts