*다이얼로그 기반의 프로그래밍에서
MFC에서 제공하는 메세지맵을 이용하기 보다는 직접 코드를 작성하도록 한다.
커맨드 메세지에 대한 일괄적인 정의를 받기 위해서는 ON_COMMAND_RANGE(id1, id2, memberFxn )를 이용하고
버튼의 이벤트처리를 윟새넌 ON_CONTROL_RANGE(wNotifyCode, id1, id2, memberFxn )
를 이용하도록 한다.
*Format의 다양한 옵션을 알도록 한다.
특히 %.15G라는 옵션은 double형 변수를 15자리 이내에서 값이 있는 자리까지만 출력한다.
*atof(char *)
_wtof(wchar *)
되도록 TCHAR형을 쓰도록 한다.
*변수의 갯수는 가능한한 줄이고 각 변수에 대한 기능도 최대한 중복되거나 겹치지 않게 한다
*Create 란 윈도우자식을 만들어 Cwnd 객체에 붙이는 것
*OnCreate 란 WM_CREATE라는 메세지를 받았을때 베이스클래스에서 상속받은 클래스를 호출하는 것.
*각종 콘트롤도 결국에는 하위 윈도우인 것이다.
콘트롤을 상속받은 클래스의 경우 또한 마찬가지이다. 그러므로 각각의 변형된 콘트롤클래스를 생성하면
윈도우 핸들이 생성되고 일반 윈도우를 사용하듯이 onCreate에서 초기화를 해주고
onPaint에서 그려주는 방식으로 구현하면 된다. 여기서 중요한 것은 클래스를 정의하고 메세지에 대한 정의를 할때
메세지맵을 잘 이용하는 것이 중요하다. 그리고 클래스 추가할때 VS의 도움을 받으면 쉽게 할수 있다.(추가->클래스->MFC클래스->...)
*상속받은 클래스의 경우 클래스 선언부에서 클래스 이름을 클릭하게 되면 우측에 처리가능한 메세지에 뜬다.(VC6.0의 클래스위자드처럼)
*인자의 값이 바뀌었을때 클래스의 초기화에 대한 부분을 정확하게 이해하고 있어야 한다.
예를 들어 개인버튼클래스를 만드는 과제의 경우 버튼의 위치를 바꾸어주는 함수를 구현할때 시작위치만 바꾸어줄 것이 아니라 버튼이미지가 그려지는 리전도 함께 옮겨주어야 한다.
나는 setskin이라는 함수에 리전 옮기는 함수가 있어서 그곳에서만 집착을 했지만 막상 리전을 옮겨주는 함수는 버튼의 위치를 바꾸어주는 함수를 호출했을때 아무 영향도 받지 않았다!?!
*비트맵 출력을 하려고 하는 경우에 메모리에 먼저 그려준 다음에 그려주게 되는데 메모리에 그려주는 위치는 화면상의 위치가 아니라 메모리상의 상대적 위치임을 잊지 말고 있어야 한다.
*WM_CREATE 라는 메세지가 올때.
The framework calls this member function when an application requests that the Windows window be created by calling the Create or CreateEx member function.
윈도우가 생성되어 보여주기 직전에 OnCreate라는 함수가 호출된다.
*WM_PAINT라는 메세지가 올때
OnPaint라는 함수를 호출하게 된다. WM_PAINT메세지는 UpdateWindow | RedrawWindow멤버함수가 호출될때 보내온다.
*PreSubclassWindow 라는 버츄얼 함수는 윈도우가 서브클래싱되기전에 필요한 서브클래싱이 일어나게 하려고 호출된다.
*owner-drawn버튼의 시각적인 요소가 변할때 호출된다.
*보통은 OnPaint와 OnCreate가 쌍이고 PreSubclassWindow와 DrawItem이 쌍으로 작동하게 된다. DrawItem과 OnPaint는 그려주는 영역이 미묘하게 다르다.
우리네 작업에서는 앞의 쌍을 주로 쓰게 된다.
*Owner-drawn이란? 기존에 있는 윈도우 클래스들-ex. 버튼. 정적. 리스트박스 등등-를 상속받아 유사한 속성의 새로운 클래스를 만들 경우 이 임의의 클래스를 owner-drawn class라고 한다.
*리소스의 경우 리소스뷰에서 편집가능한 경우와 코드상에서만 존재해서 수정하려면 리소뷰에서 편집못하고 코드로만 수정가능한 경우 두가지가 있다.
*CWnd클래스의 멤버함수중에 Create라는 함수가 있다. 클래스를 동적 생성하는 함수인데. 마지막 인자 UINT nID는 적당하게 큰수를 주는 것이 좋다. 왜냐하면 특히 다이얼로그 기반의 프로그램일경우
ID 중복으로 인해서 원치 않는 메세지 처리가 일어날수 있다. 예를 들어 아이디가 1일경우 확인 혹은 취소버튼과 아이디가 같은 확률이 아주 높다- 확인 | 취소버튼이 있다면- 그러면 새롭게 생성한 버튼에
서-특히나 owner-drawn일 경우는 더더욱- 메세지가 발생했을 경우에 확인|취소버튼의 메세지처리부와 연결되서 프로그램이 자동 종료될수도 있게 된다. 그러므로 nID는 200이상으로 넉넉하게 주는 것이
좋다. 아니면 메세지 처리를 일일이 해주어도 좋고.
*클래스의 초기회는 항상 신경을 써주어야 할 부분이다. 특히 한 클래스의 객체가 여러개 있을 경우 확실한 초기화 코드가 없다면 중복 생성후에 실행시 메모리 오류가 날 확률이 아주 높다.
윈도우 클래스라면 OnCreate에서, 다이얼로그 기반이라면 InitDialog에서 꼭!꼭!꼭!해주어야 한다.
*MFC SDI형태의 프로그램을 시작하기 위해서는 CView클래스를 상속받은 OnCreate함수를 통해서 일단 빈문서가 생성가능한지 여부를 타진한 다음에 -1이 반환되지 않으면 프로그램이 시작하게 된다.!! 뽀인트는 CView 클래스가 있다는 사실!
*표준콘트롤은 WM_CREATE류의 메세지를 받아서 실행되는 곳에서 Create를 해주어야 한다. SDI경우 view생성자가 아닌 OnCreate에서 생성해주어야 한다.
*윈도우를 새로 그리게 되는경우(invalidate(true))인 상황에서 윈도우는 두가지 메세지를 만들게 된다.
배경을 지우기 위한 WM_ERAGSEBKGND : 이 메세지를 받게 되면 윈도우는 배경용 브러쉬를 이용해서 윈도우를 그리게 된다. 그것이 일종의 지워지는 효과를 내는 것이다. 호출함수는 OnEraseBkgnd
지워진 배경에 그림을 그리기 위한 WM_PAINT : 이 메세지는 윈도우에 원하는 내용을 새로 그리게 되는 메시지이다. 호출함수는 프레임이 윈도우 그려줄때는 OnPaint, 윈도우가
다큐먼트 그려줄때는 OnDraw.
*MFC SDI에서 원하는 윈도우로 활성화시키는 코드 app.c에서 수정해야 함.
m_pMainWnd->MoveWindow(0,0,880,1000); //윈도우 크기를 재정의한다.
m_pMainWnd->CenterWindow(); //상위 윈도우를 기준으로 중앙에 윈도우를 생성한다.
m_pMainWnd->ShowWindow(SW_SHOW); //윈도우를 일정한 크기로 보여준다(min, max에 반해서)
m_pMainWnd->UpdateWindow();
///////////////////////////////////////////////////////////////////////////////
*더블버퍼핑의 구현개념. 메모리에 비트맵을 생성하여 그 비트맵정보에 화면에 그리듯 그린 다음에 윈도우에 그려줘야 할때 메모리에 저장된 비트맵 정보를 한번에 BitBlt함으로써 완성이 된다. 단, WM_ERAGEBKGND메세지에 주의할것.
구현예)
CRect rect;
GetClientRect(&rect); //비트맵을 그려줄 영역을 위한 Rect
m_dcMem.CreateCompatibleDC(pDC); //메모리 DC를 생성한다.
CBitmap bitMem; //메모리에 그릴 비트맵변수를 선언
bitMem.CreateCompatibleBitmap(pDC,1916, 1060); //메모리에 비트맵을 설정한다. 그림으로 치면 도화지를 만드는 개념인것.
m_dcMem.SelectObject(&bitMem); //생성한 비트멥을 메모리에 셋팅해준다.
CBrush brush(RGB(255,255,255));
m_dcMem.FillRect(rect, &brush); //단지 배경을 흰색으로 만들어주기 위해서 메모리에 한번 그려준 것일뿐 필요에 따라 얼마든지 바뀔수 있는 부분이고 전체적으로는 메모리에 한번 그려준것뿐이다.
DrawKeyboard(&m_dcMem); //일련의 그림을 메모리에 그려주고 있다.
pDC->BitBlt(0, 0, 1916, 1060, &m_dcMem,0 , 0, SRCCOPY); //윈도우에 보여주어야 하는 순간에 BitBlt한다.
m_dcMem.DeleteDC(); //항상 BitBlt한 이후에는 DC를 삭제해주어야 한다.
bitMem.DeleteObject();
그리고 WM_ERAGEBKGND에서는 return TRUE;를 추가해준다.
///////////////////////////////////////////////////////////////////////////////////
*해당하는 포인터를 포함하는 윈도우 핸들을 구하는 방법
1. CWnd* A = WindowFromPoint(&point);
A->m_hWnd;
A->GetSafehwnd();
2. HWND B = WindowFromPoint(&point)
의미상 같아 보이나 반드시 두번째 방법을 써야 한다.CWnd 구조체를 사용하는 것은 메모리 애러에 대한 보장을 해주지 못할 가능성이 아주 크다.
*현재 포커스가 있는 윈도우 기준이 아닌 스크린 기준의 좌표를 구하는 함수 GetCursorPos(&point);
*define 단어를 만들어 사용할 경우 왠만하면 예약어는 사용하지 않도록 한다.
VS의 단어바꾸기는 대소문자를 구별하지 않기때문에 낭패를 볼수있고 전체솔루션 옵션도 사용하지 않도록 한다.
*dll의 클래스를 다른 플젝에서도 사용할수 있게 하기 위한 것 : class AFX_EXT_CLASS class이름.....
*dll 클래스 작성시 클래스 이름 앞에는 AFX_EXT_CLASS를 넣어주고 클래스 선언 안에는 DECLARE_DYNAMIC(CSPYWINDlg)을
클래스 구현 앞에는 IMPLEMENT_DYNAMIC(CSPYWINDlg, CDialog)을 넣어주어야 한다.
*dll의 출력이름을 바꾸어줄 경우 .def에서 LIBRARY 앞에 ";"를 붙여줘야 한다.
*CTreeCtrl은 트리콘트롤이다. 일반적인 사용은 CString 텍스트를 만들어서 각 아이템에 삽입하고 삭제하는 방식으로 사용한다.
하지만 이것은 화면에 보여지는 것에 대한 정보를 다루는 방법이다. 각 아이템에 정보를 저장해서 보여지는 방법과 다르게 다루어야 할때는
SetItemData와 GetItemData를 사용하여야 한다. 가가 아이템의 HTREEITEM 이름을 가지고 데이터를 삽입하고 삭제하거나 접근이 가능할수 있게되는
함수이다. 트리콘트롤은 각 아이템별로 DWORD 값을 하나 가질수 있는 여지를 만들어 놓았다. 그래서 이 DWORD에 어떤 데이터 혹은 데이터를 가진
구조체의 포인터를 넘겨준다면 어떤 형태의 데이터로 각 아이템이 가질수 있게 되는 것이다. 다음은 각 아이템이 핸들을 가질수 있게 만든 코드이다.
ex) 데이터를 삽입할때
HTREEITEM leaf = m_pTree.InsertItem(str,0,1,linked,TVI_LAST);
DWORD item = (DWORD)present->m_hWnd;
m_pTree.SetItemData(leaf,item);
데이터를 획득할때
HTREEITEM hItem = m_pTree.GetSelectedItem();
if(hItem != NULL)
{
DWORD item = m_pTree.GetItemData(hItem);
m_selected = (HWND)item;
}
와 같이 사용할수 있다.
*::OutputDebugString(_T("..........")) - 디버깅상태에서 출력창에 메세지를 출력하게 해줄수 있고, 실행상태에서는 디버거에 메세지를 출력할수 있게 해주는 함수
- 디버깅시에 아주 유용함.(현재 디버그뷰 라는 프로그램을 깔았다)
*%appdata% -> 응용프로그램이 실행되면서 필요한 자료를 받을수 있도록 기본경로가 되는 것. 이것으로 각기 다른 환경에서도 프로그램은 원하는 정보를 찾을수 있다.
*::GetCursorPos -> 현재 마우스 위치를 받아오는 함수
Sort와 stable_sort의 차이
일반 sort는 같은 리스트를 연속으로 키가 같은 경우 sort된 내용이 계속 바뀌게 된다. 하지만 stable_sort는 키가 같은 경우 키를 구별할수 있는 무언가를 찾아낸다
그래서 항상 일정한 sort 결과를 만들어 낼수 있다.
참고 stable_sort에 대한 msdn의 설명이다.
Arranges the elements in a specified range into a nondescending order or according to an ordering criterion specified by a binary predicate and
preserves the relative ordering of equivalent elements.
-------------------------------------------------------------------------------------
출처 :
http://blog.naver.com/bmwe3?Redirect=Log&logNo=50026775509
Posted by 모니터에습기찼어