검색결과 리스트
프로그래밍/MFC 에 해당되는 글 41건
- 2016.11.18 윈도우의 정의
- 2016.11.18 컨트롤
- 2016.11.17 GDI 오브젝트
- 2016.11.17 DC의 필요성
- 2016.08.30 리스트 컨트롤
- 2016.08.29 OnPaint() 에서 제대로된 함수 호출 방법
- 2016.02.03 CListCtrl 사용
- 2015.09.17 Gdiplus 초기화 클래스
- 2015.09.03 CWnd 클래스
- 2015.09.03 메시지 함수
- 2015.01.28 error C2440: 'static_cast' 에러 2
윈도우의 일반적인 세가지 특징
1. 윈도우는 화면상에 존재한다
메모리상에만 내부적으로 존재하는 것이 아니라 화면상에 나타나며 사용자의 눈에 보인다
숨겨지거나 가려지거나 일시적으로 가시 영역을 벗어나는 경우가 없지는 않지만 이 경우에도 당장 보이지 않을 뿐 여전히 화면 상에 있다
2. 그 모양은 반드시 직사각형이다
즉, 화면상의 좌상단 좌표를 가지고 높이 와 폭이 있으며 각 변끼리는 수직을 이룬다
둥근 모양이나 세모 모양의 윈도우도 만들 수 있지만 이 경우도 나머지 부분이 투명할 뿐이지 결국은 직사각형이다
3. 윈도우는 독립적으로 사용자와 상호작용을 할 수 있다
실행 결과를 화면에 출력하기도 하고 사용자로부터 입력을 받기도 한다
사용자로부터 명령을 처리하여 다시 화면으로 출력을 내보내거나 다른 윈도우로 재 입력을 보내기도 한다
윈도우가 상호작용을 한다는 말은 단순히 존재하기만 하는 것이 아니라 능동적인 동작을 한다는 얘기며 문법적으로 하자면 사용자로부터 또는 시스템으로부터 입력된 명령과 신호를 처리하는 메시지 처리 능력이 있다는 뜻이다
* 컨트롤
- 사용자와의 인터페이스를 이루는 도구
- 인터페이스를 이룬다는 말은 사용자로부터 명령과 입력을 받아들이고 출력결과를 보여준다
- 컨트롤은 입출력도구
- 프로그램은 실행 중에 끊임없이 사용자와 통신
- 컨트롤에 명령과 정보를 받아들이고 또한 컨트롤을 통해 실행 결과를 사용자에게 보고
- 버튼, 에디트, 리스트 박스, 콤보 박스, 스크롤 바, 스태틱
- 컨트롤도 하나의 윈도우
- 화면의 일정한 영역을 차지
- 자신의 고유 메시지를 처리할 수 있는 능력
- 메모장이나 탐색기 같은 진짜 윈도우처럼 타이틀 바나 경계선을 가지고 독립적으로 사용되는 것은 아님
- 보통 대화상자의 차일드 윈도우로 존재
- 윈도우를 만들 때는 WNDCLASS 형의 구조체를 정의하고 RegisterClass 함수로 등록한 후 CreateWindow 함수를 호출
- 그러나 컨트롤은 윈도우즈가 운영체제 차원에서 제공하기 때문에 윈도우 클래스를 등록할 필요 없이 미리 등록되어 있는 윈도우 클래스를 사용하기만 하면 된다
* DC (Device Context)
- 출력에 필요한 모든 정보를 가지는 데이터 구조체
* DC를 얻는 방법
1. GetDC() 를 사용하여 DC를 얻고 사용 후 ReleaseDC() 로 해제
- DC는 주로 하나의 윈도우와 연관되는 출력 정보를 가진다
- 그래서 인수로 어떤 윈도우에 대한 DC가 필요한가를 알려주어야 함
- GetDC() 는 hWnd가 가리키는 윈도우에 적당한 DC를 만들어 그 핸들을 리턴
- DC도 메모리를 차지하므로 할당 후 해제 원칙이 반드시 준수
HDC hdc = GetDC(hWnd);
각종 출력
ReleaseDC(hWnd, hdc);
2. 두 번째 얻는 방법은 WM_PAINT 메시지 루틴에서만 사용 가능
- BeginPaint()로 얻으며 핸들을 해제할 때는 EndPaint() 함수 사용
- PAINTSTRUCT 형의 구조체를 지역 변수로 선언하고 다음과 같이 사용
PAINTSTRUCT paintStruct;
HDC hdc;
WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
각종 출력
EndPaint(hWnd, &ps);
- PAINTSTRUCT 에는 그리기 속도를 비약적으로 향상시킬 수 있는 정보들이 있음
- 이 정보를 활용하는 방법에 대해서는 다음에 자세하게 배울 것
* 리스트 컨트롤의 스타일과 구성
- 리스트 박스와 달리 아이콘과 문자열로 항목이 구성
- 스타일에 따라 여러 문자열
- 컬럼 헤더를 버튼처럼 활용하여 항목을 정렬
- 항목의 아이콘은 스타일에 따라 다른 크기의 이미지를 가짐
- 여러 이미지 목록을 설정해서 사용
- 내부적으로 에디트 컨트롤과 헤더 컨트롤 내장
* 리스트 컨트롤의 생성과 활용
- InsertItem() 메서드는 네 가지로 다중 정의되며 가장 간단한 타입은 다음과 같다
m_List.InsertItem(0, "1th item");
- 첫 번째 인자는 추가할 항목의 인덱스이고, 두 번째 인자는 추가할 항목의 문자열
- 리스트 박스와 달리 문자열이 한 행을 차지하는 것이 아니라 정해진 범위에 표시'
* 스타일의 변경
- 리스트 컨트롤은 크게 세가지 (큰 아이콘, 작은 아이콘, 리포트) 스타일을 가질 수 있음
- 리스트 컨트롤의 스타일은 속성창에서 변경하는 방법과 윈도우 탐색기처럼 동적으로 변경하는 방법
* 리포트 스타일
- InsertColumn() 메서드는 리스트 컨트롤이 리포트 스타일일 때 각 컬럼의 제목이 되는 헤더 컨트롤을 추가하는 함수
- 첫 번째는 추가할 컬럼의 인덱스, 두 번째 인자는 컬럼의 문자열
- 세번째 인자는 컬럼 헤더의 문자열을 어떻게 맞출지 명시하는 것
- LVCFMT_LEFT는 왼쪽으로 맞추도록 함
- 네 번째 인자는 컬럼 헤더의 폭(픽셀 단위)
* ModifyStyle()
- 컨트롤 윈도우의 기본 스타일을 변경하는 함수
- 이 함수의 첫 번째 인자는 기존 스타일
- 두 번째 인자는 새로 적용할 스타일
- 윈도우 탐색기처럼 스타일을 동적으로 바꾸려면 이 함수를 호출하는 코드를 작성
* SetItemText()
- 리스트 컨트롤에 등록된 항목의 문자열을 변경
- 첫 번째 인자는 변경할 항목의 인덱스
- 두 번째 인자는 첫 번째 인자에 해당하는 항목의 하위 항목의 인덱스
- 세 번째 인자는 변경할 새 문자열이 저장된 버퍼의 주소
* 항목 문자열의 동적 변경
- 윈도우 탐색기에서 기존 선택된 파일이나 폴더 항목을 누르면 에디트 컨트롤이 출력되어 사용자가 문자열을 변경할 수 있도록 함
- 리스트 컨트롤이 내장 에디트 컨트롤을 갖고 있기 때문
- 리스트 컨트롤의 Edit Labels 속성을 True로 변경
- 그리고 에디트 컨트롤의 편집이 끝나면 리스트 컨트롤의 LVN_ENDLABELEDIT 통지 메시지 발생
OnPaint에서 부모 다이얼로그 OnPaint()를 호출할 때 호출을 먼저하고 나서
자신의 그림을 그린다
반대로 그리면 그림이 사라진다
* Windows 탐색기와 같은 기능
- 레이블과 함께 아이콘의 배열을 표시
- 아이콘 없이 텍스트 열 목록을 표시
- 이럴 경우에 리스트 컨트롤을 사용
* 리스트 컨트롤의 4가지 가능햔 뷰
- MFC 뷰와는 다른 이름
- 아이콘 뷰
- 작은 아이콘 뷰
- 목록 뷰
- 보고서 뷰
- 일부 뷰에서는 사용자가 다른 위치로 아이콘을 끌거나 아이콘 레이블을 편집
- 비대화상자 창에 리스트 컨트롤을 사용하는 Windows 탐색기의 오른쪽 창
- 탐색기의 보기 메뉴에서 사용할 수 있는 뷰를 시험
* 리스트 컨트롤 및 목록 뷰
- CListCtrl 객체를 대화상자 클래스에 포함시켜 직접적으로 사용
- CListView 클래스를 사용하여 간접적으로 사용
- 이 뷰는 컨트롤이며, CListView로 캐스팅
- CListView 객체는 CCtrlView와 해당 기본 클래스에서 상속하고 멤버 함수를 추가하여 내부 리스트 컨트롤을 검색
- 뷰 멤버를 사용하여 해당 뷰를 뷰로 사용
- GetListCtrl 멤버 함수를 사용하여 리스트 컨트롤의 멤버 함수에 접근
- 목록에 있는 "항목" 추가, 삭제 또는 조작
- 리스트 컨트롤 특성 설정 또는 가져오기
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib, "gdiplus")
class CGdiPlusStarter
{
private:
ULONG_PTR m_gpToken;
public:
bool m_bSuccess;
CGdiPlusStarter() {
GdiplusStartupInput gpsi;
m_bSuccess=(GdiplusStartup(&m_gpToken,&gpsi,NULL) == Ok);
}
~CGdiPlusStarter() {
GdiplusShutdown(m_gpToken);
}
};
CGdiPlusStarter g_gps;
CWnd 클래스
- 모든 MFC 클래스의 부모라 불리는 CObject 클래스와 CCmdTarget 클래스를 상속받은 클래스
- 윈도우 자체를 객체화한 클래스
- 객체를 선언하여 초기화하고 생성하면 화면에 윈도우가 하나 만들어진다
CCmdTarget 클래스
- MFC의 메시지 맵과 관련된 코드가 구현된 클래스
- 메시지 맵은 윈도우 프로시저 함수의 switch case 문을 대체하고자 도입된 MFC의 구조
* 초기화 관련 메서드
- Create( )/CreateEx( ) : 윈도우 생성 함수
- PreCreateWindow( ) : 윈도우를 생성하기 직전에 호출되는 가상함수
재정의하여 생성되는 윈도우의 속성을 변경하는
코드를 추가
- GetStyle( )/GetExStyle( ) : 윈도우의 기본 스타일과 확장 스타일을
반환하는 함수
- PreSubclassWindow() : 서브 클래싱 직전에 호출되는 가상함수
- GetSafeHwnd( ) : 생성된 윈도우의 핸들을 반환하는 함수
GetMessage(&msg, NULL, 0, 0);
- 메시지 큐에서 메시지를 가져옴 ( 메시지가 없으면 대기 : 동기식)
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
- 메시지 큐에서 메시지를 가져옴 ( 메시지 큐에 메시지가 없어도 동작)
- 비동기
- PM_REMOVE : 메시지를 읽은 후 메시지 큐에서 제거
DispatchMessage(&msg);
- 윈도우 프로시저(콜백, 처리함수)에게 메시지를 전달
TranslateMessage(&msg)
- 키보드 입력 메시지를 가공하여 프로그램에서 쉽게 쓸 수 있도록 해 줌
윈도우즈는 키보드의 어떤 키가 눌러졌다거나 떨어졌을 때
키보드 메시지를 발생시키는데
이 함수는 키보드의 눌림(WM_KEYDOWN)과 떨어짐(WM_KEYUP)이
연속적으로 발생할 때
문자가 입력되었다는 메시지(WM_CHAR)를 만드는 역할을 한다.
예를 들어 A키를 누른 후 다시 A키를 떼면
A 문자가 입력되었다는 메시지를 만들어 낸다.
VC 6.0에서 VS 2010으로 변환했을 때 다음과 같은 에러가 발생했다
error C2440: 'static_cast' :
'UINT (__thiscall CSkinDlg::* )(CPoint)'에서
'LRESULT (__thiscall CWnd::* )(CPoint)'(으)로 변환할 수 없습니다.
그래서 에러난 곳을 확인해보니...
메시지 맵에서 ON_WM_NCHITTEST()에서 에러가 났다..
정의를 찾아가 보니...
#define ON_WM_NCHITTEST() \
{ WM_NCHITTEST, 0, 0, 0, AfxSig_l_p, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(CPoint) > (&ThisClass :: OnNcHitTest)) },
다음과 같은 코드라 수정이 불가능했다..
그런데...
저 메시지 맵과 연관된 함수 OnNcHitTest()의 선언을 찾아가니...
afx_msg UINT OnNcHitTest(CPoint point);
위와 같이 되어 있고 UINT가 LRESULT로 바꿀 수 없다는 에러 메시지가 나서
리턴형 UINT를 LRESULT로 바꾸니 에러가 해결 되었다 ^^
afx_msg LRESULT OnNcHitTest(CPoint point);