2016. 11. 18. 02:59

윈도우의 일반적인 세가지 특징


1. 윈도우는 화면상에 존재한다

메모리상에만 내부적으로 존재하는 것이 아니라 화면상에 나타나며 사용자의 눈에 보인다

숨겨지거나 가려지거나 일시적으로 가시 영역을 벗어나는 경우가 없지는 않지만 이 경우에도 당장 보이지 않을 뿐 여전히 화면 상에 있다


2. 그 모양은 반드시 직사각형이다

즉, 화면상의 좌상단 좌표를 가지고 높이 와 폭이 있으며 각 변끼리는 수직을 이룬다

둥근 모양이나 세모 모양의 윈도우도 만들 수 있지만 이 경우도 나머지 부분이 투명할 뿐이지 결국은 직사각형이다


3. 윈도우는 독립적으로 사용자와 상호작용을 할 수 있다

실행 결과를 화면에 출력하기도 하고 사용자로부터 입력을 받기도 한다

사용자로부터 명령을 처리하여 다시 화면으로 출력을 내보내거나 다른 윈도우로 재 입력을 보내기도 한다

윈도우가 상호작용을 한다는 말은 단순히 존재하기만 하는 것이 아니라 능동적인 동작을 한다는 얘기며 문법적으로 하자면 사용자로부터 또는 시스템으로부터 입력된 명령과 신호를 처리하는 메시지 처리 능력이 있다는 뜻이다


2016. 11. 18. 00:13

컨트롤

프로그래밍/MFC 2016. 11. 18. 00:13

* 컨트롤


- 사용자와의 인터페이스를 이루는 도구


- 인터페이스를 이룬다는 말은 사용자로부터 명령과 입력을 받아들이고 출력결과를 보여준다

- 컨트롤은 입출력도구


- 프로그램은 실행 중에 끊임없이 사용자와 통신

- 컨트롤에 명령과 정보를 받아들이고 또한 컨트롤을 통해 실행 결과를 사용자에게 보고


- 버튼, 에디트, 리스트 박스, 콤보 박스, 스크롤 바, 스태틱


- 컨트롤도 하나의 윈도우

- 화면의 일정한 영역을 차지

- 자신의 고유 메시지를 처리할 수 있는 능력

- 메모장이나 탐색기 같은 진짜 윈도우처럼 타이틀 바나 경계선을 가지고 독립적으로 사용되는 것은 아님

- 보통 대화상자의 차일드 윈도우로 존재


- 윈도우를 만들 때는 WNDCLASS 형의 구조체를 정의하고 RegisterClass 함수로 등록한 후 CreateWindow 함수를 호출


- 그러나 컨트롤은 윈도우즈가 운영체제 차원에서 제공하기 때문에 윈도우 클래스를 등록할 필요 없이 미리 등록되어 있는 윈도우 클래스를 사용하기만 하면 된다


2016. 11. 17. 23:40

* GDI 오브젝트


- 그래픽 출력에 사용되는 도구

- GDI 가 그래픽을 출력할 때 GDI 오브젝트를 사용

- 그래서 사용자는 그래픽을 그리기 전에 DC에 적절한 오브젝트를 선택


- 예를 들어 파란색 펜을 만들어 DC에 선택한 후 그으면 GDI는 이 파란색 펜을 사용하므로 파란색 선이 그려지게 된다

- GDI 오브젝트는 GDI가 그래픽 출력을 위해 사용하는 도구임과 동시에 사용자가 GDI의 출력을 조정할 수 있는 도구

2016. 11. 17. 22:37

DC의 필요성

프로그래밍/MFC 2016. 11. 17. 22:37

* 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 에는 그리기 속도를 비약적으로 향상시킬 수 있는 정보들이 있음

- 이 정보를 활용하는 방법에 대해서는 다음에 자세하게 배울 것

2016. 8. 30. 14:50

* 리스트 컨트롤의 스타일과 구성

- 리스트 박스와 달리 아이콘과 문자열로 항목이 구성

- 스타일에 따라 여러 문자열

- 컬럼 헤더를 버튼처럼 활용하여 항목을 정렬

- 항목의 아이콘은 스타일에 따라 다른 크기의 이미지를 가짐

- 여러 이미지 목록을 설정해서 사용

- 내부적으로 에디트 컨트롤과 헤더 컨트롤 내장


* 리스트 컨트롤의 생성과 활용


- InsertItem() 메서드는 네 가지로 다중 정의되며 가장 간단한 타입은 다음과 같다


m_List.InsertItem(0, "1th item");


- 첫 번째 인자는 추가할 항목의 인덱스이고, 두 번째 인자는 추가할 항목의 문자열

- 리스트 박스와 달리 문자열이 한 행을 차지하는 것이 아니라 정해진 범위에 표시'



* 스타일의 변경

- 리스트 컨트롤은 크게 세가지 (큰 아이콘, 작은 아이콘, 리포트) 스타일을 가질 수 있음

- 리스트 컨트롤의 스타일은 속성창에서 변경하는 방법과 윈도우 탐색기처럼 동적으로 변경하는 방법



* 리포트 스타일

- InsertColumn() 메서드는 리스트 컨트롤이 리포트 스타일일 때 각 컬럼의 제목이 되는 헤더 컨트롤을 추가하는 함수

- 첫 번째는 추가할 컬럼의 인덱스, 두 번째 인자는 컬럼의 문자열

- 세번째 인자는 컬럼 헤더의 문자열을 어떻게 맞출지 명시하는 것

- LVCFMT_LEFT는 왼쪽으로 맞추도록 함

- 네 번째 인자는 컬럼 헤더의 폭(픽셀 단위)


* ModifyStyle() 

-  컨트롤 윈도우의 기본 스타일을 변경하는 함수

- 이 함수의 첫 번째 인자는 기존 스타일

- 두 번째 인자는 새로 적용할 스타일

- 윈도우 탐색기처럼 스타일을 동적으로 바꾸려면 이 함수를 호출하는 코드를 작성


* SetItemText()

- 리스트 컨트롤에 등록된 항목의 문자열을 변경

- 첫 번째 인자는 변경할 항목의 인덱스

- 두 번째 인자는 첫 번째 인자에 해당하는 항목의 하위 항목의 인덱스

- 세 번째 인자는 변경할 새 문자열이 저장된 버퍼의 주소



* 항목 문자열의 동적 변경

- 윈도우 탐색기에서 기존 선택된 파일이나 폴더 항목을 누르면 에디트 컨트롤이 출력되어 사용자가 문자열을 변경할 수 있도록 함

- 리스트 컨트롤이 내장 에디트 컨트롤을 갖고 있기 때문

- 리스트 컨트롤의 Edit Labels 속성을 True로 변경

- 그리고 에디트 컨트롤의 편집이 끝나면 리스트 컨트롤의 LVN_ENDLABELEDIT 통지 메시지 발생




2016. 8. 29. 10:48

OnPaint에서 부모 다이얼로그 OnPaint()를 호출할 때 호출을 먼저하고 나서

자신의 그림을 그린다


반대로 그리면 그림이 사라진다





2016. 2. 3. 02:32

* Windows 탐색기와 같은 기능

- 레이블과 함께 아이콘의 배열을 표시

- 아이콘 없이 텍스트 열 목록을 표시

- 이럴 경우에 리스트 컨트롤을 사용


* 리스트 컨트롤의 4가지 가능햔 뷰

- MFC 뷰와는 다른 이름

- 아이콘 뷰

- 작은 아이콘 뷰

- 목록 뷰

- 보고서 뷰

- 일부 뷰에서는 사용자가 다른 위치로 아이콘을 끌거나 아이콘 레이블을 편집

- 비대화상자 창에 리스트 컨트롤을 사용하는 Windows 탐색기의 오른쪽 창

- 탐색기의 보기 메뉴에서 사용할 수 있는 뷰를 시험


* 리스트 컨트롤 및 목록 뷰

- CListCtrl 객체를 대화상자 클래스에 포함시켜 직접적으로 사용

- CListView 클래스를 사용하여 간접적으로 사용

- 이 뷰는 컨트롤이며, CListView로 캐스팅


- CListView 객체는 CCtrlView와 해당 기본 클래스에서 상속하고 멤버 함수를 추가하여 내부 리스트 컨트롤을 검색

- 뷰 멤버를 사용하여 해당 뷰를 뷰로 사용

- GetListCtrl 멤버 함수를 사용하여 리스트 컨트롤의 멤버 함수에 접근

- 목록에 있는 "항목" 추가, 삭제 또는 조작

- 리스트 컨트롤 특성 설정 또는 가져오기


2015. 9. 17. 13:24

#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;

2015. 9. 3. 17:30

CWnd 클래스

- 모든 MFC 클래스의 부모라 불리는 CObject 클래스와 CCmdTarget 클래스를 상속받은 클래스

- 윈도우 자체를 객체화한 클래스

- 객체를 선언하여 초기화하고 생성하면 화면에 윈도우가 하나 만들어진다


CCmdTarget 클래스

- MFC의 메시지 맵과 관련된 코드가 구현된 클래스

- 메시지 맵은 윈도우 프로시저 함수의 switch case 문을 대체하고자 도입된 MFC의 구조


* 초기화 관련 메서드

- Create( )/CreateEx( ) : 윈도우 생성 함수

- PreCreateWindow( ) : 윈도우를 생성하기 직전에 호출되는 가상함수

                           재정의하여 생성되는 윈도우의 속성을 변경하는 

                           코드를 추가

- GetStyle( )/GetExStyle( ) : 윈도우의 기본 스타일과 확장 스타일을 

                                반환하는 함수

- PreSubclassWindow() : 서브 클래싱 직전에 호출되는 가상함수

- GetSafeHwnd( ) : 생성된 윈도우의 핸들을 반환하는 함수



2015. 9. 3. 12:47

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 문자가 입력되었다는 메시지를 만들어 낸다.

2015. 1. 28. 10:15

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);