kyuseo의 게임 프로그래밍

Screen Mode Change :: 스크린(화면) 모드 변경 프로젝트 강좌 본문

C++ 개발

Screen Mode Change :: 스크린(화면) 모드 변경 프로젝트 강좌

kyuseo 2008. 1. 11. 19:01

개요..

 

게임 개발을 하면 다양한 해상도의 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;

}