mirror of
https://github.com/0ldsk00l/nestopia.git
synced 2025-04-02 10:31:51 -04:00
190 lines
4.8 KiB
C++
190 lines
4.8 KiB
C++
////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Nestopia - NES/Famicom emulator written in C++
|
|
//
|
|
// Copyright (C) 2003-2008 Martin Freij
|
|
//
|
|
// This file is part of Nestopia.
|
|
//
|
|
// Nestopia is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Nestopia is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Nestopia; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "language/resource.h"
|
|
#include "NstObjectPod.hpp"
|
|
#include "NstApplicationException.hpp"
|
|
#include "NstWindowParam.hpp"
|
|
#include "NstWindowDynamic.hpp"
|
|
|
|
namespace Nestopia
|
|
{
|
|
namespace Window
|
|
{
|
|
Dynamic::Instances Dynamic::instances;
|
|
|
|
Dynamic::Dynamic()
|
|
{
|
|
Initialize();
|
|
}
|
|
|
|
Dynamic::~Dynamic()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
void Dynamic::Initialize()
|
|
{
|
|
Messages().Add( WM_NCDESTROY, this, &Dynamic::OnNcDestroy );
|
|
}
|
|
|
|
void Dynamic::Create(Context& create)
|
|
{
|
|
NST_ASSERT( create.className && *create.className );
|
|
|
|
Object::Pod<WNDCLASSEX> winClass;
|
|
|
|
winClass.cbSize = sizeof(winClass);
|
|
winClass.style = create.classStyle;
|
|
winClass.lpfnWndProc = WndProcCreate;
|
|
winClass.hInstance = ::GetModuleHandle(NULL);
|
|
winClass.hCursor = create.hCursor;
|
|
winClass.hbrBackground = create.hBackground;
|
|
winClass.lpszClassName = create.className;
|
|
winClass.hIcon =
|
|
winClass.hIconSm = create.hIcon;
|
|
|
|
if (!RegisterClassEx( &winClass ))
|
|
throw Application::Exception( IDS_ERR_FAILED, L"RegisterClassEx()" );
|
|
|
|
className = create.className;
|
|
|
|
CreateWindowEx
|
|
(
|
|
create.exStyle,
|
|
create.className,
|
|
create.windowName,
|
|
create.winStyle,
|
|
create.x,
|
|
create.y,
|
|
create.width,
|
|
create.height,
|
|
create.hParent,
|
|
create.hMenu,
|
|
::GetModuleHandle(NULL),
|
|
this
|
|
);
|
|
|
|
if (!hWnd)
|
|
throw Application::Exception( IDS_ERR_FAILED, L"CreateWindowEx()" );
|
|
}
|
|
|
|
void Dynamic::Destroy()
|
|
{
|
|
Custom::Destroy();
|
|
|
|
if (className.Length())
|
|
{
|
|
UnregisterClass( className.Ptr(), ::GetModuleHandle(NULL) );
|
|
className.Clear();
|
|
}
|
|
}
|
|
|
|
void Dynamic::OnCreate(HWND const handle)
|
|
{
|
|
NST_ASSERT( handle && !hWnd );
|
|
|
|
hWnd = handle;
|
|
instances.PushBack( this );
|
|
|
|
const LONG_PTR ptr = reinterpret_cast<LONG_PTR>( instances.Size() == 1 ? WndProcSingle : WndProcMulti );
|
|
|
|
if (!::SetWindowLongPtr( hWnd, GWLP_WNDPROC, ptr ))
|
|
throw Application::Exception( IDS_ERR_FAILED, L"SetWindowLongPtr()" );
|
|
}
|
|
|
|
ibool Dynamic::OnNcDestroy(Param&)
|
|
{
|
|
NST_ASSERT( hWnd );
|
|
|
|
Instances::Iterator instance;
|
|
|
|
for (instance = instances.Ptr(); (*instance)->hWnd != hWnd; ++instance);
|
|
|
|
instances.Erase( instance );
|
|
hWnd = NULL;
|
|
|
|
return false;
|
|
}
|
|
|
|
#ifdef NST_MSVC_OPTIMIZE
|
|
#pragma optimize("t", on)
|
|
#endif
|
|
|
|
LRESULT CALLBACK Dynamic::WndProcSingle(HWND const hWnd,const uint uMsg,WPARAM const wParam,LPARAM const lParam)
|
|
{
|
|
if (const MsgHandler::Item* const item = instances.Front()->msgHandler( uMsg ))
|
|
{
|
|
Param param = {wParam,lParam,0,hWnd};
|
|
|
|
if (item->callback( param ))
|
|
return param.lResult;
|
|
}
|
|
|
|
return ::DefWindowProc( hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
LRESULT CALLBACK Dynamic::WndProcMulti(HWND const hWnd,const uint uMsg,WPARAM const wParam,LPARAM const lParam)
|
|
{
|
|
Instances::ConstIterator instance;
|
|
|
|
for (instance = instances.Ptr(); (*instance)->hWnd != hWnd; ++instance);
|
|
|
|
if (const MsgHandler::Item* const item = (*instance)->msgHandler( uMsg ))
|
|
{
|
|
Param param = {wParam,lParam,0,hWnd};
|
|
|
|
if (item->callback( param ))
|
|
return param.lResult;
|
|
}
|
|
|
|
return ::DefWindowProc( hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
#ifdef NST_MSVC_OPTIMIZE
|
|
#pragma optimize("", on)
|
|
#endif
|
|
|
|
LRESULT CALLBACK Dynamic::WndProcCreate(HWND const hWnd,const uint uMsg,WPARAM const wParam,LPARAM const lParam)
|
|
{
|
|
if (uMsg == WM_CREATE && lParam)
|
|
{
|
|
if (Dynamic* const instance = static_cast<Dynamic*>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams))
|
|
{
|
|
instance->OnCreate( hWnd );
|
|
|
|
if (const MsgHandler::Item* const item = instance->msgHandler( uMsg ))
|
|
{
|
|
Param param = {wParam,lParam,0,hWnd};
|
|
|
|
if (item->callback( param ))
|
|
return param.lResult;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ::DefWindowProc( hWnd, uMsg, wParam, lParam );
|
|
}
|
|
}
|
|
}
|