이번에는 스크린을 캡처할 영역을 그릴 Canvas 를 만들어 보도록 하겠습니다.

코드가 길기 때문에 핵심적인 부분만 설명토록 하겠습니다.


[Canvas 로 사용할 Dialog 생성]
 
 


보시는것 처럼 '리소스 뷰' 에서 Dialog 를 하나 만들어 줍니다.
그리고나서 아래처럼 타이틀바, 시스템버튼 등등을 모두 없애 줍니다. 물론 Border 도 없애야겠죠.



기본적인 설정은 끝났습니다.


[창 투명하게 설정하기]

이제 창이 반투명하게 보여지도록 설정하도록 하겠습니다.
그래야 캡처할때, 영역을 보고 지정할 수 있겠지요.

'리소스 뷰' 에서 다이얼로그를 마우스 우클릭을 하면, '클래스 추가' 를 하실 수 있습니다.
저는 CanvasDlg 라는 이름으로 추가하였습니다.

자동으로 만들어진 CanvasDlg.h 에 창을 투명하게 만들기때 사용할 값을 헤더를 추가해 주었습니다.

#define WS_EX_LAYERED  0x00080000  //Dialog Alpha define

#define LWA_ALPHA   0x00000002


그리고 OnInitDialog() 를 재정의 하였습니다.


BOOL CanvasDlg::OnInitDialog()
{
	// 창 size 를 최대로 설정
	int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
	int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
	MoveWindow(0,0,nScreenWidth,nScreenHeight);


	// 투명도 조절
	typedef BOOL(WINAPI *SLWA)(HWND,COLORREF,BYTE,DWORD);
	SLWA pSetLayeredWindowAttributes = NULL;

	HWND hwnd = this->m_hWnd;
	SetWindowLong(hwnd, GWL_EXSTYLE,GetWindowLong(hwnd,GWL_EXSTYLE) | WS_EX_LAYERED);
	SetLayeredWindowAttributes(0, 150, LWA_ALPHA);

	CDialog::OnInitDialog();

	return TRUE;
}





[마우스로 영역 지정하기 및 표시하기] 

이제 마우스로 캡처할 영역을 그리면, 표시해 주도록 해 보겠습니다.
속성창에 메세지를 이용해서 아래 함수들을 추가해 주었습니다.

public:

afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);

afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

afx_msg void OnMouseMove(UINT nFlags, CPoint point);

afx_msg void OnLButtonUp(UINT nFlags, CPoint point);

afx_msg void OnPaint();

 
그리고 나중에 캡처영역 정보를 넘겨줄 함수와 내부적으로 사용할 좌표값 변수들을 추가해 주었습니다.

public:

RECT GetClipRect();


private:

LONG m_OrgX;

LONG m_OrgY;

LONG m_DstX;

LONG m_DstY;

 

[코드] 

최종적으로 만들어진 CanvasDlg.cpp, CanvasDlg.h 파일은 아래와 같습니다.

    [CanvasDlg.h]


#pragma once

#define WS_EX_LAYERED  0x00080000  //Dialog Alpha define
#define LWA_ALPHA   0x00000002

// CanvasDlg 대화 상자입니다.

class CanvasDlg : public CDialog
{
	DECLARE_DYNAMIC(CanvasDlg)

public:
	CanvasDlg(CWnd* pParent = NULL);   // 표준 생성자입니다.
	virtual ~CanvasDlg();

// 대화 상자 데이터입니다.
	enum { IDD = IDD_CANVAS };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 지원입니다.

	DECLARE_MESSAGE_MAP()

protected:
	BOOL OnInitDialog();
public:
	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnPaint();

public:
	RECT GetClipRect();

private:
	LONG m_OrgX;
	LONG m_OrgY;
	LONG m_DstX;
	LONG m_DstY;
public:
	afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg void OnKillFocus(CWnd* pNewWnd);
};




    [CanvasDlg.cpp]


// anvasDlg.cpp : 구현 파일입니다.
//

#include "stdafx.h"
#include "EasyClipper.h"
#include "CanvasDlg.h"


// CanvasDlg 대화 상자입니다.

IMPLEMENT_DYNAMIC(CanvasDlg, CDialog)

CanvasDlg::CanvasDlg(CWnd* pParent /*=NULL*/)
: CDialog(CanvasDlg::IDD, pParent)
{
	m_OrgX = m_OrgY = m_DstX = m_DstY = 0;
}

CanvasDlg::~CanvasDlg()
{
}

void CanvasDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CanvasDlg, CDialog)
	ON_WM_WINDOWPOSCHANGING()
	ON_WM_CTLCOLOR()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONUP()
	ON_WM_PAINT()
	ON_WM_KEYDOWN()
	ON_WM_KILLFOCUS()
END_MESSAGE_MAP()




BOOL CanvasDlg::OnInitDialog()
{
	// 창 size 를 최대로 설정
	int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
	int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
	MoveWindow(0,0,nScreenWidth,nScreenHeight);


	// 투명도 조절
	typedef BOOL(WINAPI *SLWA)(HWND,COLORREF,BYTE,DWORD);
	SLWA pSetLayeredWindowAttributes = NULL;

	HWND hwnd = this->m_hWnd;
	SetWindowLong(hwnd, GWL_EXSTYLE,GetWindowLong(hwnd,GWL_EXSTYLE) | WS_EX_LAYERED);
	SetLayeredWindowAttributes(0, 150, LWA_ALPHA);

	// 최상위 윈도우
	::SetWindowPos(GetSafeHwnd(),  HWND_TOPMOST , 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);


	CDialog::OnInitDialog();
	return TRUE;
}

// CanvasDlg 메시지 처리기입니다.


HBRUSH CanvasDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

	// TODO:  여기서 DC의 특성을 변경합니다.
	switch(nCtlColor) {
		case CTLCOLOR_DLG:
			hbr = (HBRUSH)GetStockObject(WHITE_BRUSH);
			break;
	}
	// TODO:  기본값이 적당하지 않으면 다른 브러시를 반환합니다.
	return hbr;
}

void CanvasDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
	m_OrgX = m_DstX = point.x;
	m_OrgY = m_DstY = point.y;
	
	CDialog::OnLButtonDown(nFlags, point);
}

void CanvasDlg::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
	if((GetAsyncKeyState(VK_LBUTTON) & 0x8000) == 0x8000) {
		m_DstX = point.x;
		m_DstY = point.y;

		Invalidate(TRUE);
	}

	CDialog::OnMouseMove(nFlags, point);
}

void CanvasDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.

	m_DstX = point.x;
	m_DstY = point.y;

	CDialog::OnLButtonUp(nFlags, point);

	::SendMessage(this->m_hWnd, WM_CLOSE, NULL, NULL);
}

void CanvasDlg::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO: 여기에 메시지 처리기 코드를 추가합니다.

	// Color Setting
	CPen pen;
	pen.CreatePen( PS_SOLID, 1, RGB(255,0,0));
	dc.SelectObject(&pen);

	// 사각틀 잡기
	LONG x1 = m_OrgX, x2 = m_DstX, y1 = m_OrgY, y2 = m_DstY;
	if(x1 > x2) { x1 = m_DstX; x2 = m_OrgX; }
	if(y1 > y2) { y1 = m_DstY; y2 = m_OrgY; }


	dc.Rectangle(x1, y1, x2, y2);
	// 그리기 메시지에 대해서는 CDialog::OnPaint()을(를) 호출하지 마십시오.
}



RECT CanvasDlg::GetClipRect()
{
	RECT rect;

	// 클릭만 한 경우
	if(m_OrgX == m_DstX || m_OrgY == m_DstY) { 
		rect.bottom = rect.left = rect.right = rect.top = 0;
		return rect;
	}

	// 사각틀 잡기
	LONG x1 = m_OrgX, x2 = m_DstX, y1 = m_OrgY, y2 = m_DstY;
	if(x1 > x2) { x1 = m_DstX; x2 = m_OrgX; }
	if(y1 > y2) { y1 = m_DstY; y2 = m_OrgY; }

	rect.left = x1;
	rect.right = x2;
	rect.top = y1;
	rect.bottom = y2;

	return rect;
}


void CanvasDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.

	CDialog::OnKeyDown(nChar, nRepCnt, nFlags);

	// 키를 입력하면 Canvas 를 숨김(취소)	
	//::SendMessage(this->m_hWnd, WM_CLOSE, NULL, NULL);
}

void CanvasDlg::OnKillFocus(CWnd* pNewWnd)
{
	CDialog::OnKillFocus(pNewWnd);

	// TODO: 여기에 메시지 처리기 코드를 추가합니다.
	// 키를 입력하면 Canvas 를 숨김(취소)	
	::SendMessage(this->m_hWnd, WM_CLOSE, NULL, NULL);
}




 


신고

'개발 프로그램 > EasyClipper' 카테고리의 다른 글

Easy Clipper ver 2.0  (0) 2015.05.27
EasyClipper - 화면 캡처프로그램  (0) 2011.12.15
EasyClipper 개발 - 마무리  (1) 2011.12.15
EasyClipper 개발 - Canvas  (0) 2011.12.14
EasyClipper 개발 - Hooking  (0) 2011.12.13
EasyClipper 기획  (0) 2011.12.13