kyuseo의 게임 프로그래밍
Screen Mode Change :: 스크린(화면) 모드 변경 프로젝트 강좌 본문
개요.. |
게임 개발을 하면 다양한 해상도의 800x600, 1024x768등의 전체 화면 모드로 개발을 할 경우가 많습니다.
전체 화면 변경을 쉽게 하는 클래스와 프로젝트를 강의 합니다.
스크린샷 |
강좌 |
1. MFC 로 Dialog 기반 프로젝트를 생성합니다.
2. 다음과 같은 윈도우 컨트롤을 배치합니다.
3. OnInitDialog() 함수에서 화면 모드를 가져와서 리스트에 추가하는 코드를 추가합니다.
// 화면모드를모두가져오기 // 모드가얼마나존재하는지알아오기 DEVMODE temp_dev; for( int i=0; ; i++ ) { if( EnumDisplaySettings( NULL, i, &temp_dev ) == FALSE ) break; }
CString str; m_aDevMode = new DEVMODE[i+1]; for( i=0; ; i++ ) { if( EnumDisplaySettings( NULL, i, &m_aDevMode[i] ) == FALSE ) break;
str.Format( "%d x %d x %d (%dhz)", m_aDevMode[i].dmPelsWidth, m_aDevMode[i].dmPelsHeight, m_aDevMode[i].dmBitsPerPel, m_aDevMode[i].dmDisplayFrequency ); int index = m_lb.AddString( str );
m_lb.SetItemDataPtr( index, &m_aDevMode[i] ); } |
4. 리스트 더블 클릭 또는 확인 버튼을 클릭하면 해상도를 변경하는 코드를 추가합니다.
// OK 버튼클릭으로모드변환 void CScreenModeChangeDlg::OnOK() { int index = m_lb.GetCurSel(); if( index == -1 ) return;
DEVMODE* pMode = (DEVMODE*) m_lb.GetItemDataPtr( index ); ASSERT( pMode ); m_SM.ModeChange( pMode ); }
// 리스트더블클릭으로모드변환 void CScreenModeChangeDlg::OnDblclkList2() { OnOK(); }
// 모드복구 void CScreenModeChangeDlg::OnButtonRestore() { m_SM.ModeChange( FALSE ); }
// 입력된값으로모드변경 void CScreenModeChangeDlg::OnBtnChange() { UpdateData();
m_SM.SetMode( CScreenMode::API, m_nWidth, m_nHeight, m_nColor, m_nHZ ); m_SM.ModeChange( TRUE ); } |
핵심 클래스 소스 |
CScreenMode.h
//=========================================================================== // // Project: CScreenMode // 제 목: 스크린모드변경클래스 // // 제작자: 채경석(kyuseo99@chollian.net) SkySoft(C) // 시작일: 02/12/02 // //===========================================================================
#if !defined(AFX_SCREENMODE_H__C5E86E75_2EDC_4E3F_B6D6_B1658F777148__INCLUDED_) #define AFX_SCREENMODE_H__C5E86E75_2EDC_4E3F_B6D6_B1658F777148__INCLUDED_
#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000
// // CScreenMode // class CScreenMode { public: CScreenMode(); virtual ~CScreenMode();
enum MODE{ DIRECT_X, API };
// 아직DIRECT_X 지원안함 // 모드설정( hz : 0=디폴트, 1=자동, ETC:주어진해상도) BOOL SetMode( MODE mode, DWORD width, DWORD height, DWORD pixel, DWORD hz = 1 ); BOOL ModeChange( BOOL bFull ); // 모드전환 BOOL ModeChange( DEVMODE* pDevMode ); // 모드전환
protected: BOOL DXModeChange(); // 모드전환 BOOL DXRestore();
BOOL APIModeChange(); // 모드전환 BOOL APIRestore();
protected: MODE m_Mode; // 모드 BOOL m_bFull; // 현재풀스크린인가?
DEVMODE m_DevMode; };
#endif // !defined(AFX_SCREENMODE_H__C5E86E75_2EDC_4E3F_B6D6_B1658F777148__INCLUDED_) |
CScreenMode.cpp
//=========================================================================== // // Project: CScreenMode // 제 목: 스크린모드변경클래스 // // 제작자: 채경석(kyuseo99@chollian.net) SkySoft(C) // 시작일: 02/12/02 // //===========================================================================
#include "stdafx.h" #include "ScreenMode.h"
#ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif
////////////////////////////////////////////////////////////////////// // Construction/Destruction //////////////////////////////////////////////////////////////////////
CScreenMode::CScreenMode() { m_Mode = API; m_bFull = FALSE; ZeroMemory( &m_DevMode, sizeof( DEVMODE ) ); }
CScreenMode::~CScreenMode() { if( m_bFull == TRUE ) ModeChange( FALSE ); }
// 모드설정 BOOL CScreenMode::SetMode( MODE mode, DWORD width, DWORD height, DWORD pixel, DWORD hz ) { if( m_bFull == TRUE ) ModeChange( FALSE ); ASSERT( mode == API ); mode = API; m_Mode = mode;
DEVMODE DevModeTemp; DEVMODE DevModeSelect; ZeroMemory( &DevModeSelect, sizeof( DEVMODE ) ); for( int i=0; ; i++ ) { if( EnumDisplaySettings( NULL, i, &DevModeTemp ) == FALSE ) break;
if( DevModeTemp.dmPelsWidth == width && DevModeTemp.dmPelsHeight == height && DevModeTemp.dmBitsPerPel == pixel ) { if( hz == 0 ) { memcpy( &DevModeSelect, &DevModeTemp, sizeof( DEVMODE ) ); } else if( hz == 1 ) { if( DevModeTemp.dmDisplayFrequency > DevModeSelect.dmDisplayFrequency ) memcpy( &DevModeSelect, &DevModeTemp, sizeof( DEVMODE ) ); } else { if( DevModeTemp.dmDisplayFrequency == hz ) memcpy( &DevModeSelect, &DevModeTemp, sizeof( DEVMODE ) ); } } }
// 못찾았다. if( DevModeSelect.dmPelsWidth == 0 ) return FALSE;
memcpy( &m_DevMode, &DevModeSelect, sizeof( DEVMODE ) ); m_DevMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
if( hz != 0 ) m_DevMode.dmFields |= DM_DISPLAYFREQUENCY;
return TRUE; }
// 모드전환 BOOL CScreenMode::ModeChange( BOOL bFull ) { ASSERT( m_bFull != bFull ); if( m_bFull == bFull ) return FALSE;
if( bFull == TRUE ) { ASSERT( m_DevMode.dmPelsWidth != 0 ); if( m_DevMode.dmPelsWidth == 0 ) return FALSE; }
BOOL rtn; if( m_Mode == API ) { if( bFull == TRUE ) rtn = ( ChangeDisplaySettings( &m_DevMode, CDS_FULLSCREEN ) == DISP_CHANGE_SUCCESSFUL ); else rtn = ( ChangeDisplaySettings( NULL,0 ) == DISP_CHANGE_SUCCESSFUL ); } else { if( bFull == TRUE ) rtn = FALSE; else rtn = FALSE; }
if( rtn == TRUE ) m_bFull = bFull;
return rtn; }
// 모드전환 BOOL CScreenMode::ModeChange( DEVMODE* pDevMode ) { if( m_bFull == TRUE ) ModeChange( FALSE );
BOOL rtn = ( ChangeDisplaySettings( pDevMode, CDS_FULLSCREEN ) == DISP_CHANGE_SUCCESSFUL ); if( rtn == TRUE ) m_bFull = TRUE; return rtn; } |