From 933c75df63ed48e4c118af877b22b7189aa73548 Mon Sep 17 00:00:00 2001 From: SFPGMR Date: Sat, 23 Apr 2011 15:30:11 +0900 Subject: [PATCH] =?utf8?q?=E5=9F=BA=E6=9C=AC=E3=83=95=E3=82=A1=E3=82=A4?= =?utf8?q?=E3=83=AB=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- sfwasapi.sln | 1 + sfwasapi/code_converter.cpp | 34 +++ sfwasapi/code_converter.h | 79 ++++++ sfwasapi/dout.h | 78 ++++++ sfwasapi/exception.cpp | 88 +++++++ sfwasapi/exception.h | 34 +++ sfwasapi/logger.cpp | 115 +++++++++ sfwasapi/logger.h | 37 +++ sfwasapi/message_loop.h | 70 ++++++ sfwasapi/sf_com.h | 100 ++++++++ sfwasapi/sf_memory.h | 100 ++++++++ sfwasapi/sf_windows.cpp | 517 ++++++++++++++++++++++++++++++++++++++ sfwasapi/sf_windows.h | 350 ++++++++++++++++++++++++++ sfwasapi/sfwasapi.vcxproj | 23 +- sfwasapi/sfwasapi.vcxproj.filters | 30 ++- sfwasapi/singleton.h | 55 ++++ sfwasapi/stdafx.cpp | 8 + sfwasapi/stdafx.h | 118 +++++++++ sfwasapi/winmain.cpp | 33 +++ 19 files changed, 1857 insertions(+), 13 deletions(-) create mode 100644 sfwasapi/code_converter.cpp create mode 100644 sfwasapi/code_converter.h create mode 100644 sfwasapi/dout.h create mode 100644 sfwasapi/exception.cpp create mode 100644 sfwasapi/exception.h create mode 100644 sfwasapi/logger.cpp create mode 100644 sfwasapi/logger.h create mode 100644 sfwasapi/message_loop.h create mode 100644 sfwasapi/sf_com.h create mode 100644 sfwasapi/sf_memory.h create mode 100644 sfwasapi/sf_windows.cpp create mode 100644 sfwasapi/sf_windows.h create mode 100644 sfwasapi/singleton.h create mode 100644 sfwasapi/stdafx.cpp create mode 100644 sfwasapi/stdafx.h create mode 100644 sfwasapi/winmain.cpp diff --git a/sfwasapi.sln b/sfwasapi.sln index 04014e0..3cbeb92 100644 --- a/sfwasapi.sln +++ b/sfwasapi.sln @@ -10,6 +10,7 @@ Global EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {4ADABFBD-B4BB-4E2A-BE95-8C604DC783D3}.Debug|Win32.ActiveCfg = Debug|x64 + {4ADABFBD-B4BB-4E2A-BE95-8C604DC783D3}.Debug|Win32.Build.0 = Debug|x64 {4ADABFBD-B4BB-4E2A-BE95-8C604DC783D3}.Release|Win32.ActiveCfg = Release|x64 {4ADABFBD-B4BB-4E2A-BE95-8C604DC783D3}.Release|Win32.Build.0 = Release|x64 EndGlobalSection diff --git a/sfwasapi/code_converter.cpp b/sfwasapi/code_converter.cpp new file mode 100644 index 0000000..5de5e82 --- /dev/null +++ b/sfwasapi/code_converter.cpp @@ -0,0 +1,34 @@ +#include "stdafx.h" + +namespace sf +{ + + code_converter::code_converter(const char*p) + { + int len = ::MultiByteToWideChar(CP_ACP,0,p,-1,NULL,0); + m_dest.reset(new wchar_t[len]); + ::MultiByteToWideChar(CP_ACP,0,p,-1,&m_dest[0],len); + }; + + code_converter::code_converter(const std::string& p) + { + int len = ::MultiByteToWideChar(CP_ACP,0,p.c_str(),-1,NULL,0); + m_dest.reset(new wchar_t[len]); + ::MultiByteToWideChar(CP_ACP,0,p.c_str(),-1,&m_dest[0],len); + }; + + code_converter::code_converter(const wchar_t*p) + { + int len = ::WideCharToMultiByte(CP_ACP,0,p,-1,NULL,0,NULL,NULL); + m_dest.reset(new char[len]); + ::WideCharToMultiByte(CP_ACP,0,p,-1,&m_dest[0],len,NULL,NULL); + }; + + code_converter::code_converter(const std::wstring & p) + { + int len = ::WideCharToMultiByte(CP_ACP,0,p.c_str(),-1,NULL,0,NULL,NULL); + m_dest.reset(new char[len]); + ::WideCharToMultiByte(CP_ACP,0,p.c_str(),-1,&m_dest[0],len,NULL,NULL); + }; + +}; \ No newline at end of file diff --git a/sfwasapi/code_converter.h b/sfwasapi/code_converter.h new file mode 100644 index 0000000..d9c398c --- /dev/null +++ b/sfwasapi/code_converter.h @@ -0,0 +1,79 @@ +#pragma once + + +/** @file + * @author S.F. (Satoshi Fujiwara) + * @brief wchar_t <--> char ‚Ì•ÏŠ·ƒ†[ƒeƒBƒŠƒeƒB + * ˆø”‚Æ‚µ‚Ä•¶Žš—ñ‚ðˆø‚«“n‚·ÛA•ÏŠ·‚ª•K—v‚ȏꍇA‰º‹L‚̂悤‚ɃAƒ_ƒvƒ^“I‚ÉŽg—p‚·‚邱‚Æ‚ð‘z’肵‚Ä‚¢‚éB + * std::wstring a(L"abcd"); + * std::wstring b((sf::code_converter(a))); + * + *@ŒãAATLƒR[ƒh·‚µ‘Ö‚¦—p‚Ìtypedef‚à—pˆÓ‚µ‚Ä‚¢‚éB + * ‚±‚ê‚́AƒAƒ_ƒvƒ^‚Æ‚µ‚Ä‚Ì—˜—p‚Ì‚Ý‚ÉŒÀ’肳‚ê‚éB + * sf::ct2a hoge_(L"abcef"); // ‘z’肵‚Ä‚¢‚È‚¢i“®ì‚·‚éê‡‚à‚ ‚邵Aƒ_ƒ‚ȏꍇ‚à‚ ‚éj + */ + +namespace sf +{ + /** —Œ` */ + template + struct code_converter + { + public: + explicit code_converter(SrcChar* p); + explicit code_converter(std::basic_string & p); + operator DestChar*(); + }; + + /** char -> wchar_t‚Ö‚Ì•ÏŠ· */ + template <> + struct code_converter + { + explicit code_converter(const char* p); + explicit code_converter(const std::string& p); + + operator wchar_t*() const {return m_dest.get();} + private: + boost::scoped_array m_dest; + }; + + /** wchar_t -> char */ + template <> + struct code_converter + { + explicit code_converter(const wchar_t* p); + explicit code_converter(const std::wstring& p); + operator char* () const {return m_dest.get();} + private: + boost::scoped_array m_dest; + }; + + /** ATLƒR[ƒh·‚µ‘Ö‚¦‚Ì‚½‚߂̃GƒCƒŠƒAƒX */ + typedef sf::code_converter ca2w; + + /** ATLƒR[ƒh·‚µ‘Ö‚¦‚Ì‚½‚߂̃GƒCƒŠƒAƒX */ + typedef sf::code_converter cw2a; + + #ifdef _UNICODE + + /** ATLƒR[ƒh·‚µ‘Ö‚¦‚Ì‚½‚߂̃GƒCƒŠƒAƒX */ + typedef sf::code_converter ca2t; + /** ATLƒR[ƒh·‚µ‘Ö‚¦‚Ì‚½‚߂̃GƒCƒŠƒAƒX */ + typedef sf::code_converter ct2a; + + /** ATLƒR[ƒh·‚µ‘Ö‚¦‚Ì‚½‚߂̃GƒCƒŠƒAƒX */ + inline const wchar_t* ct2w(const wchar_t* p) { return p;}; + /** ATLƒR[ƒh·‚µ‘Ö‚¦‚Ì‚½‚߂̃GƒCƒŠƒAƒX */ + inline const wchar_t* cw2t(const wchar_t* p) { return p;}; + + #else + + /** ATLƒR[ƒh·‚µ‘Ö‚¦‚Ì‚½‚߂̃GƒCƒŠƒAƒX */ + inline const char* ct2a(const char* p) { return p;}; + /** ATLƒR[ƒh·‚µ‘Ö‚¦‚Ì‚½‚߂̃GƒCƒŠƒAƒX */ + inline const char* ca2t(const char* p) { return p;}; + + #endif +} + + diff --git a/sfwasapi/dout.h b/sfwasapi/dout.h new file mode 100644 index 0000000..a7dbe01 --- /dev/null +++ b/sfwasapi/dout.h @@ -0,0 +1,78 @@ +#pragma once + +/* http://vision.kuee.kyoto-u.ac.jp/~nob/doc/win32/win32.html#doc1_42 + ‚æ‚è”qŽØ +*/ + + +#ifndef STDX_DSTREAM_H + +#define STDX_DSTREAM_H + +namespace sf +{ + +// VC++ ‚Å STLport ‚¾‚Æ using std::char_traits; ‚Ý‚½‚¢‚È‚Ì‚ª•K—v‚©‚à +template > +class basic_dbg_streambuf: public std::basic_stringbuf +{ +public: + basic_dbg_streambuf() + { +#ifndef STDX_DSTREAM_BUFFERING + setbuf(0,0); +#endif + } + + virtual ~basic_dbg_streambuf() + { + sync(); + } + +protected: + int sync(void) + { + dbg_out(str().c_str()); + pbump(static_cast(pbase() - pptr())); + return 0; + } + + void dbg_out(const Ch_T*); +}; + +template <> +inline void basic_dbg_streambuf::dbg_out(const char *str) +{ + ::OutputDebugStringA(str); +} + +template <> +inline void basic_dbg_streambuf::dbg_out(const wchar_t *str) +{ + ::OutputDebugStringW(str); +} + +template > +class basic_dbg_ostream: public std::basic_ostream +{ +public: + basic_dbg_ostream() : std::basic_ostream(new basic_dbg_streambuf()) + { + } + + virtual ~basic_dbg_ostream() + { + // flush(); // •s—v‚炵‚¢Dhttp://www.tietew.jp/cppll/archive/607 + delete rdbuf(); + } +}; + +typedef basic_dbg_streambuf wdbg_streambuf; +typedef basic_dbg_ostream wdstream; + +// ‚±‚ê‚ð’è‹`‚µ‚Ä‚¨‚­‚ƁC dout ‚̐錾‚ª‚¢‚ç‚È‚­‚È‚éD +static wdstream wdout; + +} + +#endif // STDX_DSTREAM_ \ No newline at end of file diff --git a/sfwasapi/exception.cpp b/sfwasapi/exception.cpp new file mode 100644 index 0000000..0c0e586 --- /dev/null +++ b/sfwasapi/exception.cpp @@ -0,0 +1,88 @@ +#include "stdafx.h" +#include "exception.h" +#include +#include +#include +#include +#include +#include +#include + + + +#define BOOST_ASSIGN_MAX_PARAMS 7 +#include +#include +#include +#include +#include "sf_memory.h" + +using namespace boost; + +namespace sf +{ +//typedef CComPtr IAudioClientPtr; +std::map com_error_ = boost::assign::list_of > + (E_POINTER,L"E_POINTER") + (E_INVALIDARG,L"E_INVALIDARG") + (DWRITE_E_FILEFORMAT,L"DWRITE_E_FILEFORMAT") + (DWRITE_E_UNEXPECTED,L"DWRITE_E_UNEXPECTED") + (DWRITE_E_NOFONT,L"DWRITE_E_NOFONT") + (DWRITE_E_FILENOTFOUND,L"DWRITE_E_FILENOTFOUND") + (DWRITE_E_FILEACCESS,L"DWRITE_E_FILEACCESS") + (DWRITE_E_FONTCOLLECTIONOBSOLETE,L"DWRITE_E_FONTCOLLECTIONOBSOLETE") + (DWRITE_E_ALREADYREGISTERED,L"DWRITE_E_ALREADYREGISTERED") + (AUDCLNT_E_NOT_INITIALIZED,L"AUDCLNT_E_NOT_INITIALIZED") + (AUDCLNT_E_ALREADY_INITIALIZED,L"AUDCLNT_E_ALREADY_INITIALIZED") + (AUDCLNT_E_WRONG_ENDPOINT_TYPE,L"AUDCLNT_E_WRONG_ENDPOINT_TYPE") + (AUDCLNT_E_DEVICE_INVALIDATED,L"AUDCLNT_E_DEVICE_INVALIDATED") + (AUDCLNT_E_NOT_STOPPED,L"AUDCLNT_E_NOT_STOPPED") + (AUDCLNT_E_BUFFER_TOO_LARGE,L"AUDCLNT_E_BUFFER_TOO_LARGE") + (AUDCLNT_E_OUT_OF_ORDER,L"AUDCLNT_E_OUT_OF_ORDER") + (AUDCLNT_E_UNSUPPORTED_FORMAT,L"AUDCLNT_E_UNSUPPORTED_FORMAT") + (AUDCLNT_E_INVALID_SIZE,L"AUDCLNT_E_INVALID_SIZE") + (AUDCLNT_E_DEVICE_IN_USE,L"AUDCLNT_E_DEVICE_IN_USE") + (AUDCLNT_E_BUFFER_OPERATION_PENDING,L"AUDCLNT_E_BUFFER_OPERATION_PENDING") + (AUDCLNT_E_THREAD_NOT_REGISTERED,L"AUDCLNT_E_THREAD_NOT_REGISTERED") + (AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED,L"AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED") + (AUDCLNT_E_ENDPOINT_CREATE_FAILED,L"AUDCLNT_E_ENDPOINT_CREATE_FAILED") + (AUDCLNT_E_SERVICE_NOT_RUNNING,L"AUDCLNT_E_SERVICE_NOT_RUNNING") + (AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED,L"AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED") + (AUDCLNT_E_EXCLUSIVE_MODE_ONLY,L"AUDCLNT_E_EXCLUSIVE_MODE_ONLY") + (AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL,L"AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL") + (AUDCLNT_E_EVENTHANDLE_NOT_SET,L"AUDCLNT_E_EVENTHANDLE_NOT_SET") + (AUDCLNT_E_INCORRECT_BUFFER_SIZE,L"AUDCLNT_E_INCORRECT_BUFFER_SIZE") + (AUDCLNT_E_BUFFER_SIZE_ERROR,L"AUDCLNT_E_BUFFER_SIZE_ERROR") + (AUDCLNT_S_BUFFER_EMPTY,L"AUDCLNT_S_BUFFER_EMPTY") + (AUDCLNT_S_THREAD_ALREADY_REGISTERED,L"AUDCLNT_S_THREAD_ALREADY_REGISTERED"); + + +win32_error_exception::win32_error_exception(boost::uint32_t hr) +: std::exception("HRESULT ERROR"),hresult_(hr) +{ + local_memory mem; + DWORD 結果 = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,hr,0,(LPWSTR)&mem,0,0); + if(結果 != 0){ + error_ = mem.get(); + } else { + std::map::iterator it = com_error_.find(hr); + if(it != com_error_.end()) + { + error_ = it->second; + } else { + error_ = (boost::wformat(L"0x%x 不明なCOMエラー") % hr).str(); + } + + } +}; + +win32_error_exception::win32_error_exception() +{ + hresult_ = ::GetLastError(); + local_memory mem; + DWORD rv = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,hresult_,0,(LPWSTR)&mem,0,0); + error_ = mem.get(); + //Logger::outputDebugPrintf(L"Win32 Error %x %s",hresult_,mem.Get() ); +}; + +} \ No newline at end of file diff --git a/sfwasapi/exception.h b/sfwasapi/exception.h new file mode 100644 index 0000000..41965ea --- /dev/null +++ b/sfwasapi/exception.h @@ -0,0 +1,34 @@ +#pragma once + +namespace sf +{ +///Exception + class exception : public std::exception + { + public: + explicit exception(const std::wstring& reason) + { + m_reason = reason; + }; + const wchar_t * what() {return m_reason.c_str();}; + const std::wstring& what_str() { return m_reason;}; + protected: + std::wstring m_reason; + }; + + class win32_error_exception : std::exception + { + public: + win32_error_exception(boost::uint32_t hr); + win32_error_exception(); + + virtual ~win32_error_exception() {}; + boost::uint32_t hresult() {return hresult_;} + std::wstring& error() {return error_;} + private: + boost::uint32_t hresult_; + std::wstring error_; + }; + + +} \ No newline at end of file diff --git a/sfwasapi/logger.cpp b/sfwasapi/logger.cpp new file mode 100644 index 0000000..60f9922 --- /dev/null +++ b/sfwasapi/logger.cpp @@ -0,0 +1,115 @@ +/* +============================================================================== + +This file is part of the S.F.Tracker +Copyright 2005-7 by Satoshi Fujiwara. + +S.F.Tracker can be redistributed and/or modified 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. + +S.F.Tracker 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 S.F.Tracker; if not, visit www.gnu.org/licenses or write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, +Boston, MA 02111-1307 USA + +============================================================================== +*/ +/** @file +* @author S.F. (Satoshi Fujiwara) +*/ + +#include "stdafx.h" + +namespace sf { + + struct logger::impl + { + impl() : m_log_file("sftracker.log",std::ios_base::out | std::ios_base::trunc ){}; + ~impl() {m_log_file.close();} + + void write(const boost::wformat & fmt) + { + write(fmt.str()); + }; + + void write(const std::wistream & st) + { + { + //mutex_type::scoped_lock lock_(m_mutex); + m_log_file << st << std::endl; + } + boost::gregorian::date dt = boost::gregorian::day_clock::local_day(); + + }; + + void write(const std::wstring & mes) + { + write(mes.c_str()); + } + + void write(const TCHAR * mes) + { + //mutex_type::scoped_lock lock_(m_mutex); + m_log_file << mes << std::endl; + m_log_file.flush(); + } + private: + std::wofstream m_log_file; + //mutex_type m_mutex; + }; + + logger::logger() : m_impl(new logger::impl()) + { + } + void logger::write(const boost::wformat & fmt) + { + m_impl->write(fmt); + }; + + void logger::write(const std::wstring & mes) + { + m_impl->write(mes); + } + + void logger::write(const TCHAR * mes) + { + m_impl->write(mes); + } + + void logger::write(const std::wistream & st) + { + m_impl->write(st); + } + + logger::~logger() + { + + } + + void debug_out(const char * file_name,const int line,boost::wformat& fmt) + { + OutputDebugString((boost::wformat(_T("%s(%d) %s \n")) % std::wstring(sf::code_converter(file_name)) % line % fmt).str().c_str()); + }; + + void debug_out(const char * file_name,const int line,const std::wstring& str) + { + OutputDebugString((boost::wformat(_T("%s(%d) %s \n")) % std::wstring(sf::code_converter(file_name)) % line % str).str().c_str()); + }; + + void debug_out(const char * file_name,const int line,const char* str) + { + OutputDebugString((boost::wformat(_T("%s(%d) %s \n")) % std::wstring(sf::code_converter(file_name)) % line % sf::code_converter(str)).str().c_str()); + } + + void debug_outW(const char * file_name,const int line,const wchar_t* str) + { + OutputDebugString((boost::wformat(_T("%s(%d) %s \n")) % std::wstring(sf::code_converter(file_name)) % line % str).str().c_str()); + }; + +} diff --git a/sfwasapi/logger.h b/sfwasapi/logger.h new file mode 100644 index 0000000..8d6a396 --- /dev/null +++ b/sfwasapi/logger.h @@ -0,0 +1,37 @@ +#pragma once + +#include "boost/date_time/gregorian/gregorian.hpp" +#include "boost/date_time/posix_time/posix_time.hpp" +#include "singleton.h" + +namespace sf { + + struct logger : public singleton + { + public: + logger(); + ~logger(); + void write(const boost::wformat & fmt); + void write(const std::wstring & mes); + void write(const TCHAR * mes); + void write(const std::wistream & st); + private: + struct impl; + boost::shared_ptr m_impl; + }; + + void debug_out(const char * file_name,const int line,boost::wformat& fmt); + void debug_out(const char * file_name,const int line,const std::wstring& str); + void debug_out(const char * file_name,const int line,const char* str); + void debug_out(const char * file_name,const int line,const wchar_t* str); +} + +#define WRITE_LOG(s) \ + sf::logger::instance()->write(boost::wformat(_T("%s %s %6d %s")) % boost::posix_time::second_clock::local_time() % (TCHAR*)sf::ca2t(__FILE__) % __LINE__ % (s)) + +#ifdef _DEBUG +#define SFTRACE(x) sf::debug_out(__FILE__,__LINE__,(x)) +#else +#define SFTRACE(x) +#endif + diff --git a/sfwasapi/message_loop.h b/sfwasapi/message_loop.h new file mode 100644 index 0000000..28c5e56 --- /dev/null +++ b/sfwasapi/message_loop.h @@ -0,0 +1,70 @@ +#pragma once +/* + ============================================================================== + + This file is part of the S.F.Tracker + Copyright 2005-7 by Satoshi Fujiwara. + + S.F.Tracker can be redistributed and/or modified 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. + + S.F.Tracker 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 S.F.Tracker; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ============================================================================== +*/ +/** @file + * @brief + * @author S.F. (Satoshi Fujiwara) + */ +namespace sf { + struct run_message_loop + { + run_message_loop(){}; + inline WPARAM operator()() + { + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return msg.wParam; + } + + ~run_message_loop(void){}; + }; + + struct peek_message_loop + { + typedef boost::function func_type; + explicit peek_message_loop(func_type func) {func_ = func;}; + inline WPARAM operator()() + { + MSG msg = {0}; + while( WM_QUIT != msg.message ) + { + if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) + { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + else + { + func_(); // Do some rendering + } + } + return msg.wParam; + }; + private: + func_type func_; + }; +} diff --git a/sfwasapi/sf_com.h b/sfwasapi/sf_com.h new file mode 100644 index 0000000..ff2a8a0 --- /dev/null +++ b/sfwasapi/sf_com.h @@ -0,0 +1,100 @@ +#pragma once +/* + ============================================================================== + + This file is part of the Shooting3 + Copyright 2005-7 by Satoshi Fujiwara. + + S.F.Tracker can be redistributed and/or modified 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. + + S.F.Tracker 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 S.F.Tracker; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ============================================================================== +*/ +/** @file + * @brief util + * @author S.F. (Satoshi Fujiwara) + */ +#include "objbase.h" +namespace sf +{ + enum com_init + { + multi_threaded = 0x0, + apartment_threaded = 0x2, + disable_ole1dde = 0x4, + speed_over_memory = 0x8 + }; + + struct com_initialize + { + struct impl; + com_initialize(void * reserved = NULL,unsigned int init = multi_threaded); + ~com_initialize() {}; + private: + boost::shared_ptr m_impl; + }; + + template + boost::intrusive_ptr create_instance() + { + ComInterface * com_ptr; + CoCreateInstance( __uuidof(ComClass), NULL, + CLSCTX_ALL, __uuidof(ComInterface), + (void**)&com_ptr); + return boost::intrusive_ptr(com_ptr,false); + + }; + template + struct IUnknownImpl : public COMInterface + { + IUnknownImpl() : ref_(1) {}; + virtual ~IUnknownImpl() {}; + ULONG __stdcall AddRef() + { + return InterlockedIncrement(&ref_); + } + + ULONG __stdcall Release() + { + ULONG ref = InterlockedDecrement(&ref_); + if (0 == ref) + { + delete this; + } + return ref; + } + + HRESULT __stdcall QueryInterface(REFIID riid, VOID **ppObj) + { + if (IID_IUnknown == riid) + { + AddRef(); + *ppObj = (IUnknown*)this; + } + else if (__uuidof(COMInterface) == riid) + { + AddRef(); + *ppObj = (COMInterface*)this; + } + else + { + *ppObj = NULL; + return E_NOINTERFACE; + } + return S_OK; + } + private: + LONG ref_; + }; +} \ No newline at end of file diff --git a/sfwasapi/sf_memory.h b/sfwasapi/sf_memory.h new file mode 100644 index 0000000..24d02fb --- /dev/null +++ b/sfwasapi/sf_memory.h @@ -0,0 +1,100 @@ +#pragma once +namespace sf { +// policy class +struct heap_memory_free_policy +{ +template< typename T > +void operator()( const T* AMemory ) const +{ +if( NULL != AMemory ) +::HeapFree( ::GetProcessHeap(), 0, AMemory ); +} +}; +// policy class +struct local_memory_free_policy +{ +template< typename T > +void operator()( const T* AMemory ) const +{ +if( NULL != AMemory ) +::LocalFree( AMemory ); +} +}; +// policy class +struct co_task_memory_free_policy +{ +template< typename T > +void operator()( const T* AMemory ) const +{ +if( NULL != AMemory ) +::CoTaskMemFree( AMemory ); +} +}; +// base guard class +template< typename T,class TFreePolicy > +class base_memory +{ +private: +T *FMemory; + +public: +base_memory( T* AMemory = NULL ) +: FMemory( AMemory ) {} + +virtual ~base_memory( void ) +{ reset(); } + +T* release( void ) +{ +T *tmp = FMemory; +FMemory = NULL; +return tmp; +} + +void reset( T* AMemory = NULL ) +{ +if( AMemory != FMemory ) +{ +if( NULL != FMemory ) +TFreePolicy( FMemory ); + +FMemory = AMemory; +} +} + +T* get( void ) +{ return FMemory; } + +T** operator&( void ) +{ return &FMemory; } + +}; +template< typename T > +class heap_memory : public base_memory< T, +heap_memory_free_policy > +{ +public: +heap_memory( T* AMemory = NULL ) +: base_memory< T, heap_memory_free_policy >( AMemory ) +{ } +}; +template< typename T > +class local_memory : public base_memory< T, +local_memory_free_policy > +{ +public: +local_memory( T* AMemory = NULL ) +: base_memory< T, local_memory_free_policy >( AMemory ) +{ } +}; +template< typename T > +class co_task_memory : public base_memory< T, +co_task_memory_free_policy > +{ +public: +co_task_memory( T* AMemory = NULL ) +: base_memory< T, co_task_memory_free_policy >( AMemory ) +{ } +}; + +}; diff --git a/sfwasapi/sf_windows.cpp b/sfwasapi/sf_windows.cpp new file mode 100644 index 0000000..56764cd --- /dev/null +++ b/sfwasapi/sf_windows.cpp @@ -0,0 +1,517 @@ +#include "stdafx.h" +#define BOOST_ASSIGN_MAX_PARAMS 7 +#include +#include +#include +#include +#include "sf_windows.h" +#include "exception.h" + +#define エラーなら例外を投げる(hres) \ + if (FAILED(hres)) { throw sf::win32_error_exception(hres); } + +#ifndef HINST_THISCOMPONENT +EXTERN_C IMAGE_DOS_HEADER __ImageBase; +#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) +#endif + +namespace sf +{ + LRESULT base_window::window_proc(HWND hwnd,boost::uint32_t message, WPARAM wParam, LPARAM lParam) + { + + LRESULT 結果 = 0; + switch (message) + { + case WM_CREATE: + { + // TODO: + create_device(); + break; + } + case WM_SIZE: + { + //if (render_target_) + //{ + // D2D1_SIZE_U size; + // size.width = lParam & 0xFFFF; + // size.height = (lParam >> 16) & 0xFFFF; ; + + // // Note: This method can fail, but it's okay to ignore the + // // error here -- it will be repeated on the next call to + // // EndDraw. + // //render_target_->Resize(size); + //} + } + case WM_PAINT: + { + //create_device(); + + paint_struct begin_paint(hwnd); + + //if (!(render_target_->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED)) + //{ + // // Retrieve the size of the render target. + // D2D1_SIZE_F renderTargetSize = render_target_->GetSize(); + // try { + // //render_target_->BeginDraw(); + // base_->on_render(); + // //エラーなら例外を投げる(render_target_->EndDraw()); + // } catch (sf::win32_error_exception& e ) + // { + // if(e.hresult() == D2DERR_RECREATE_TARGET) + // { + // discard_device(); + // } else { + // throw; + // } + // } + //} + return FALSE; + } + case WM_DISPLAYCHANGE: + { + ::InvalidateRect(hwnd, NULL, FALSE); + } + case WM_ERASEBKGND: + { + return FALSE; + } + case WM_MOUSEMOVE: + { + // on_mouse_move(GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam),wParam); + } + case WM_LBUTTONDOWN: + { + } + } + return ::DefWindowProcW(hwnd,message,wParam,lParam); + }; + + + void base_window::create_device_independent_resources() + { + + // Direct2DFactory の生成 + + if(!factory_){ +#if defined(DEBUG) || defined(_DEBUG) + D2D1_FACTORY_OPTIONS options; + options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION ; + エラーなら例外を投げる(D2D1CreateFactory( + D2D1_FACTORY_TYPE_SINGLE_THREADED, + options, + &factory_ + )); +#else + エラーなら例外を投げる(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory_)); +#endif + + } + + if(!write_factory_){ + エラーなら例外を投げる(::DWriteCreateFactory( + DWRITE_FACTORY_TYPE_SHARED, + __uuidof(IDWriteFactory), + reinterpret_cast(&write_factory_) + )); + } + + + //wic_imaging_factory_.CreateInstance(CLSID_WICImagingFactory); + + //thunk_proc_ = (WNDPROC)thunk_.getCode(); + + }; + + void base_window::register_class ( + wchar_t * menu_name, + boost::uint32_t style , + boost::int32_t cbClsExtra, + HICON hIcon , + HCURSOR hCursor, + HBRUSH hbrBackground , + HICON hIconSm + ) + { + wnd_class_.reset(new sf::window_class_ex(menu_name,名前_,HINST_THISCOMPONENT,thunk_proc_,style,cbClsExtra,hIcon,hCursor,hbrBackground,hIconSm)); + } + + /** デフォルト設定 */ + void base_window::register_class() + { + wnd_class_.reset(new sf::window_class_ex(0,名前_,HINST_THISCOMPONENT,thunk_proc_)); + } + + void base_window::create_window() + { + // Create the application window. + // + // Because the CreateWindow function takes its size in pixels, we + // obtain the system DPI and use it to scale the window size. + FLOAT dpiX, dpiY; + //factory_->GetDesktopDpi(&dpiX, &dpiY); + + + // Windowを作成する + CreateWindow( + 名前_.c_str(), + title_.c_str(), + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + static_cast(ceil(width_ /** dpiX / 96.f*/)), + static_cast(ceil(height_ /** dpiY / 96.f*/)), + NULL, + NULL, + HINST_THISCOMPONENT, + this + ); + } + + void base_window::create_device() + { + + // 入力_.reset(new input(HINST_THISCOMPONENT,hwnd_)); + HRESULT hr = S_OK; + + + //ウィンドウの現在の幅、高さを求める + RECT rc; + GetClientRect( hwnd_, &rc ); + boost::uint32_t width = rc.right - rc.left; + boost::uint32_t height = rc.bottom - rc.top; + + { + //wic_imaging_factory_.CreateInstance(CLSID_WICImagingFactory); + // bitmap_ = load_bitmap_from_file(render_target_,wic_imaging_factory_,L"myship.png"); + } + + if(!render_target_) + { + RECT rc; + GetClientRect(hwnd_, &rc); + + D2D1_SIZE_U size = D2D1::SizeU( + rc.right - rc.left, + rc.bottom - rc.top + ); + + エラーなら例外を投げる(factory_->CreateHwndRenderTarget( + D2D1::RenderTargetProperties(), + D2D1::HwndRenderTargetProperties(hwnd_, size,D2D1_PRESENT_OPTIONS_IMMEDIATELY), + &render_target_ + )); + // Create a DC render target + //D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties( + // D2D1_RENDER_TARGET_TYPE_DEFAULT, + // D2D1::PixelFormat( + // DXGI_FORMAT_B8G8R8A8_UNORM, + // D2D1_ALPHA_MODE_IGNORE + // ) , 0.0, 0.0, + // D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE + // ); + + //エラーなら例外を投げる(factory_->CreateDCRenderTarget( + // &props, + // &render_target_ + // )); + } + } + + + void base_window::discard_device() + { + /* if(render_target_) + { + render_target_.Release(); + }*/ + } + + void base_window::show(boost::uint32_t show_flag) + { + //HRESULT hr = S_OK; + //BOOL enable; + //DwmIsCompositionEnabled (&enable); + //if(enable){ + // //Create and populate the BlurBehind structre + // DWM_BLURBEHIND bb = {0}; + // //Enable Blur Behind and Blur Region; + // bb.dwFlags = DWM_BB_ENABLE; + // bb.fEnable = true; + // bb.hRgnBlur = NULL; + + // //Enable Blur Behind + // hr = DwmEnableBlurBehindWindow(hwnd_, &bb); + //} + ::ShowWindow(hwnd_,show_flag); + } + void base_window::update() {::UpdateWindow(hwnd_);} + + base_window::~base_window() + { + safe_release(factory_); + safe_release(write_factory_); + + } + + + base_window::base_window(const std::wstring& title,const std::wstring& name,bool fit_to_display,float width,float height) + : title_(title),名前_(name),fit_to_display_(fit_to_display), + width_(width),height_(height),thunk_(this,base_window::WndProc),hwnd_(0) + { + thunk_proc_ = (WNDPROC)thunk_.getCode(); + //create_device_independent_resources(); + } + + + + base_window::operator HWND() + { + return hwnd_; + }; + + //ID2D1FactoryPtr base_window::factory() { return impl_->factory();}; + //ID2D1HwndRenderTargetPtr base_window::render_target() { return impl_->render_target();}; + //IDWriteFactoryPtr base_window::write_factory() {return impl_->write_factory();}; + + toplevel_window_ptr create_toplevel_window + ( + const std::wstring& menu_name, + const std::wstring& name, + const boost::uint32_t show_flag, + bool fit_to_display, + float width, + float height + ) + { + toplevel_window* p = new toplevel_window(menu_name,name,fit_to_display,width,height); + p->create_device_independent_resources(); + p->register_class(); + p->create_window(); + p->show(show_flag); + p->update(); + return toplevel_window_ptr(p); + } + + LRESULT toplevel_window::window_proc(HWND hwnd,boost::uint32_t message, WPARAM wParam, LPARAM lParam) + { + + + switch (message) + { + case WM_CREATE: + { + // TODO: + create_device(); + break; + } + case WM_SIZE: + { + //if (render_target_) + //{ + // D2D1_SIZE_U size; + // size.width = lParam & 0xFFFF; + // size.height = (lParam >> 16) & 0xFFFF; ; + + // // Note: This method can fail, but it's okay to ignore the + // // error here -- it will be repeated on the next call to + // // EndDraw. + // render_target_->Resize(size); + //} + } + case WM_PAINT: + { + //create_device(); + + { + paint_struct begin_paint(hwnd); + // 描画コードの呼び出し + render(); + } + return FALSE; + } + case WM_DISPLAYCHANGE: + { + ::InvalidateRect(hwnd, NULL, FALSE); + } + case WM_ERASEBKGND: + { + return FALSE; + } + case WM_MOUSEMOVE: + { + // on_mouse_move(GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam),wParam); + } + case WM_LBUTTONDOWN: + { + } + } + + if(message == WM_CLOSE) + { + // 後始末 + discard_device(); + // レンダーターゲットのリリース + safe_release(render_target_); + // Windowの破棄 + BOOL ret(::DestroyWindow(hwnd)); + BOOST_ASSERT(ret != 0); + } + + if(message == WM_DESTROY) + { + ::PostQuitMessage(0); + return 0; + } + + return ::DefWindowProcW(hwnd,message,wParam,lParam); + } + + void toplevel_window::main_loop() + { + render(); + } + + void toplevel_window::render() + { + + static float t = 0.0f; + + if (render_target_) + { + // Retrieve the size of the render target. + D2D1_SIZE_F renderTargetSize = render_target_->GetSize(); + try { + render_target_->BeginDraw(); + render_target_->Clear(D2D1::ColorF(D2D1::ColorF::White)); + render_target_->SetTransform(D2D1::Matrix3x2F::Identity()); + //render_target_->Clear(D2D1::ColorF(D2D1::ColorF::White)); + ID2D1SolidColorBrushPtr brush; + render_target_->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &brush); + ID2D1SolidColorBrushPtr brushr; + render_target_->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red), &brushr); + + D2D1_RECT_F layoutRect = D2D1::RectF(50.f, 50.f, 600.f, 200.f); + IDWriteTextFormatPtr write_text_format; + // Text Formatの作成 + エラーなら例外を投げる(write_factory_->CreateTextFormat( + L"メイリオ", // Font family name. + NULL, // Font collection (NULL sets it to use the system font collection). + DWRITE_FONT_WEIGHT_REGULAR, + DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, + 48.0f, + L"ja-jp", + &write_text_format + )); + // Actually draw the text at the origin. + std::wstring m(L"こんにちは、64Bitの世界!By S.F."); + render_target_->DrawTextW( + m.c_str(), + m.size(), + write_text_format, + layoutRect, + brush); + エラーなら例外を投げる(render_target_->EndDraw()); + + } catch(...) { + throw; + } + } + }; + + // + // Creates a Direct2D bitmap from the specified + // file name. + // + ID2D1BitmapPtr load_bitmap_from_file( + ID2D1HwndRenderTargetPtr render_target, + IWICImagingFactoryPtr wic_factory, + std::wstring uri, + boost::uint32_t destination_width, + boost::uint32_t destination_height + ) + { + HRESULT hr = S_OK; + + IWICBitmapDecoderPtr decoder; + IWICBitmapFrameDecodePtr decoder_source; + IWICStreamPtr stream; + IWICFormatConverterPtr converter; + IWICBitmapScalerPtr scaler; + ID2D1BitmapPtr bitmap; + + エラーなら例外を投げる(wic_factory->CreateDecoderFromFilename( + uri.c_str(), + NULL, + GENERIC_READ, + WICDecodeMetadataCacheOnLoad, + &decoder + )); + + // Create the initial frame. + エラーなら例外を投げる(decoder->GetFrame(0, &decoder_source)); + + // Convert the image format to 32bppPBGRA + // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED). + エラーなら例外を投げる(hr = wic_factory->CreateFormatConverter(&converter)); + + // If a new width or height was specified, create an + // IWICBitmapScaler and use it to resize the image. + if (destination_width != 0 || destination_height != 0) + { + boost::uint32_t originalWidth, originalHeight; + エラーなら例外を投げる(decoder_source->GetSize((UINT*)&originalWidth, (UINT*)&originalHeight)); + if (destination_width == 0) + { + FLOAT scalar = static_cast(destination_height) / static_cast(originalHeight); + destination_width = static_cast(scalar * static_cast(originalWidth)); + } + else if (destination_height == 0) + { + FLOAT scalar = static_cast(destination_width) / static_cast(originalWidth); + destination_height = static_cast(scalar * static_cast(originalHeight)); + } + + エラーなら例外を投げる(wic_factory->CreateBitmapScaler(&scaler)); + エラーなら例外を投げる(scaler->Initialize( + decoder_source, + destination_width, + destination_height, + WICBitmapInterpolationModeCubic + )); + エラーなら例外を投げる(converter->Initialize( + scaler.GetInterfacePtr(), + GUID_WICPixelFormat32bppPBGRA, + WICBitmapDitherTypeNone, + NULL, + 0.f, + WICBitmapPaletteTypeMedianCut + )); + } + else // Don't scale the image. + { + エラーなら例外を投げる(converter->Initialize( + decoder_source.GetInterfacePtr(), + GUID_WICPixelFormat32bppPBGRA, + WICBitmapDitherTypeNone, + NULL, + 0.f, + WICBitmapPaletteTypeMedianCut + )); + } + + // Create a Direct2D bitmap from the WIC bitmap. + エラーなら例外を投げる(render_target->CreateBitmapFromWicBitmap( + converter.GetInterfacePtr(), + NULL, + &bitmap + )); + + return bitmap; + } + + +} + diff --git a/sfwasapi/sf_windows.h b/sfwasapi/sf_windows.h new file mode 100644 index 0000000..04c1f19 --- /dev/null +++ b/sfwasapi/sf_windows.h @@ -0,0 +1,350 @@ +#pragma once +/* +*/ +// Windows Header Files: +#include "exception.h" +#define XBYAK64 +#include "xbyak.h" +// DLLのリンク +#pragma comment(lib,"d2d1.lib") +#pragma comment(lib,"winmm.lib") +#pragma comment(lib,"dwrite.lib") +#pragma comment(lib,"dwmapi.lib") + +//#include "input.h" + +_COM_SMARTPTR_TYPEDEF(ID2D1Factory,__uuidof(ID2D1Factory)); +_COM_SMARTPTR_TYPEDEF(IWICImagingFactory, __uuidof(IWICImagingFactory)); +_COM_SMARTPTR_TYPEDEF(IDWriteFactory , __uuidof(IDWriteFactory)); +_COM_SMARTPTR_TYPEDEF(IDWriteGdiInterop , __uuidof(IDWriteGdiInterop)); +_COM_SMARTPTR_TYPEDEF(IDWriteFontFace , __uuidof(IDWriteFontFace)); +_COM_SMARTPTR_TYPEDEF(IDWriteFont , __uuidof(IDWriteFont)); +_COM_SMARTPTR_TYPEDEF(IDWriteFontFamily , __uuidof(IDWriteFontFamily)); +_COM_SMARTPTR_TYPEDEF(IDWriteFontCollection , __uuidof(IDWriteFontCollection)); +_COM_SMARTPTR_TYPEDEF(IDWriteLocalizedStrings , __uuidof(IDWriteLocalizedStrings)); +_COM_SMARTPTR_TYPEDEF(ID2D1HwndRenderTarget , __uuidof(ID2D1HwndRenderTarget)); +_COM_SMARTPTR_TYPEDEF(ID2D1BitmapRenderTarget , __uuidof(ID2D1BitmapRenderTarget)); +_COM_SMARTPTR_TYPEDEF(ID2D1GdiInteropRenderTarget , __uuidof(ID2D1GdiInteropRenderTarget)); +_COM_SMARTPTR_TYPEDEF(IDWriteTextFormat, __uuidof(IDWriteTextFormat)); +_COM_SMARTPTR_TYPEDEF(IDWriteTextLayout, __uuidof(IDWriteTextLayout)); +_COM_SMARTPTR_TYPEDEF(ID2D1PathGeometry , __uuidof(ID2D1PathGeometry)); +_COM_SMARTPTR_TYPEDEF(ID2D1LinearGradientBrush , __uuidof(ID2D1LinearGradientBrush)); +_COM_SMARTPTR_TYPEDEF(ID2D1GradientStopCollection , __uuidof(ID2D1GradientStopCollection)); +_COM_SMARTPTR_TYPEDEF(ID2D1SolidColorBrush , __uuidof(ID2D1SolidColorBrush)); +_COM_SMARTPTR_TYPEDEF(ID2D1BitmapBrush , __uuidof(ID2D1BitmapBrush)); +_COM_SMARTPTR_TYPEDEF(ID2D1Bitmap , __uuidof(ID2D1Bitmap)); +_COM_SMARTPTR_TYPEDEF(IWICBitmapDecoder,__uuidof(IWICBitmapDecoder)); +_COM_SMARTPTR_TYPEDEF(IWICBitmapFrameDecode,__uuidof(IWICBitmapFrameDecode)); +_COM_SMARTPTR_TYPEDEF(IWICStream,__uuidof(IWICStream)); +_COM_SMARTPTR_TYPEDEF(IWICFormatConverter,__uuidof(IWICFormatConverter)); +_COM_SMARTPTR_TYPEDEF(IWICBitmapScaler,__uuidof(IWICBitmapScaler)); + +template inline void safe_release(COM_SMART_PTR& ptr) +{ + if(ptr) + { + ptr.Release(); + } +}; + +namespace sf{ + + ID2D1BitmapPtr load_bitmap_from_file( + ID2D1HwndRenderTargetPtr render_target, + IWICImagingFactoryPtr wic_factory, + std::wstring uri, + boost::uint32_t destination_width = 0, + boost::uint32_t destination_height = 0 + ); + + /** WNDCLASSEXラッパクラス */ + struct window_class_ex + { + window_class_ex( + const wchar_t* menu_name , + const std::wstring& class_name , + HINSTANCE hInstance = NULL, + WNDPROC lpfnWndProc = ::DefWindowProcW, + boost::uint32_t style = CS_HREDRAW | CS_VREDRAW, + boost::int32_t cbClsExtra = 0, + HICON hIcon = ::LoadIcon(NULL,IDI_APPLICATION), + HCURSOR hCursor = ::LoadCursor(NULL, IDC_ARROW), + HBRUSH hbrBackground = ::CreateSolidBrush(0xff000000), + HICON hIconSm = NULL + ) : is_register_(false) + { + + if(::GetClassInfoExW(hInstance,class_name.c_str(),&wndclass_) == 0) + { + if(::GetLastError() == ERROR_CLASS_DOES_NOT_EXIST) + { + ::ZeroMemory(&wndclass_,sizeof(wndclass_)); + wndclass_.lpszMenuName = (LPCWSTR)menu_name; + wndclass_.lpszClassName = class_name.c_str(); + wndclass_.cbSize = sizeof(::WNDCLASSEXW); + wndclass_.cbWndExtra = sizeof(LONG_PTR); + wndclass_.hInstance = hInstance; + wndclass_.lpfnWndProc = lpfnWndProc; + wndclass_.style = style; + wndclass_.cbClsExtra = cbClsExtra; + wndclass_.hIcon = hIcon; + wndclass_.hCursor = hCursor; + wndclass_.hbrBackground = hbrBackground; + wndclass_.hIconSm = hIconSm; + atom_ = ::RegisterClassExW(&wndclass_) ; + BOOST_ASSERT(atom_ != 0); + is_register_ = true; + } else { + throw win32_error_exception(); + } + } else { + is_register_ = false; + } + }; + + ~window_class_ex() + { + if(is_register_){ + ::UnregisterClassW(wndclass_.lpszClassName,wndclass_.hInstance); + } + } + + private: + bool is_register_; + ATOM atom_; + ::WNDCLASSEXW wndclass_; + }; + + + + struct get_dc { + get_dc(HWND hwnd) : hwnd_(hwnd),hdc_(GetDC(hwnd)) {} + HDC get(){return hdc_;} + ~get_dc(){::ReleaseDC(hwnd_,hdc_);} + private: + HDC hdc_; + HWND hwnd_; + }; + + struct compatible_dc { + compatible_dc(HDC hdc) : hdc_(::CreateCompatibleDC(hdc)){}; + ~compatible_dc(){::DeleteDC(hdc_);}; + HDC get() { return hdc_;}; + private: + HDC hdc_; + }; + + struct ref_dc { + ref_dc(HDC& hdc) : hdc_(hdc) {}; + ~ref_dc(){}; + HDC get() { return hdc_;}; + private: + HDC& hdc_; + }; + + struct d2_dc { + d2_dc(ID2D1GdiInteropRenderTargetPtr& ptr,D2D1_DC_INITIALIZE_MODE mode) :hdc_(0),ptr_(ptr) + { + hr_ = ptr->GetDC(mode,&hdc_); + }; + ~d2_dc(){ptr_->ReleaseDC(NULL);}; + HDC get() { return hdc_;}; + private: + HRESULT hr_; + HDC hdc_; + ID2D1GdiInteropRenderTargetPtr& ptr_; + }; + + template + struct device_context + { + explicit device_context(Holder* holder) : holder_(holder){}; + ~device_context() {} + operator HDC(){return holder_->get();} + private: + boost::scoped_ptr holder_; + }; + + typedef device_context d2_dc_type; + + struct paint_struct + { + paint_struct(HWND hwnd) : hwnd_(hwnd) + { + ::BeginPaint(hwnd,&paintstruct_); + } + ~paint_struct() {::EndPaint(hwnd_,&paintstruct_);} + PAINTSTRUCT* operator->(){return &paintstruct_;} + private: + HWND hwnd_; + PAINTSTRUCT paintstruct_; + }; + + template + struct begin_draw + { + begin_draw(T& render_target) : render_target_(render_target) ,is_end_(false) {render_target->BeginDraw();} + HRESULT end_draw() + { + HRESULT hr = S_OK; + if(!is_end_) { + hr = render_target_->EndDraw(); + is_end_ = true; + } + + return hr; + }; + ~begin_draw(){ if(!is_end_) { render_target_->EndDraw();}} + private: + T& render_target_; + bool is_end_; + }; + + struct mouse + { + mouse() : x_(0.0f),y_(0.0f),left_button_(false),middle_button_(false),right_button_(false){} + private: + float x_,y_; + bool left_button_,middle_button_,right_button_; + }; + + /** window ベースクラス */ + struct base_window + { + typedef boost::signals2::signal on_message_type; + on_message_type on_message; + typedef boost::signals2::signal on_render_type; + on_render_type on_render; + operator HWND(); + protected: + base_window( + const std::wstring& title, + const std::wstring& name,bool fit_to_display, + float width,float height); + ~base_window(); + void register_class ( + wchar_t* menu_name, + boost::uint32_t style, + boost::int32_t cbClsExtra = 0, + HICON hIcon = ::LoadIcon(NULL,IDI_APPLICATION), + HCURSOR hCursor = ::LoadCursor(NULL, IDC_ARROW), + HBRUSH hbrBackground = ::CreateSolidBrush(0xff000000), + HICON hIconSm = NULL + ); + + /** デフォルト設定 */ + void register_class(); + void create_window(); + void update(); + void show(boost::uint32_t show_flag); + virtual void discard_device(); + virtual void create_device(); + virtual void create_device_independent_resources(); + public: + virtual LRESULT window_proc(HWND hwnd,boost::uint32_t message, WPARAM wParam, LPARAM lParam); + protected: + static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) + { + base_window* ptr = reinterpret_cast(hwnd); + hwnd = ptr->hwnd_; + return ptr->window_proc(hwnd,message,wParam,lParam); + }; + + // thisとhwndをつなぐthunkクラス + struct hwnd_this_thunk : public Xbyak::CodeGenerator { + hwnd_this_thunk(base_window* impl,WNDPROC proc) + { + // rcxにhwndが格納されているので、それをimpl->hwndに保存 + mov(qword[&(impl->hwnd_)],rcx); + // 代わりにthisのアドレスをrcxに格納 + mov(rcx,(LONG_PTR)impl); + // r10にproc(Window プロシージャ)へのアドレスを格納 + mov(r10,(LONG_PTR)proc); + // Window プロシージャへへジャンプ + jmp(r10); + } + }; + + HWND hwnd_; + ID2D1FactoryPtr factory_; + ID2D1HwndRenderTargetPtr render_target_; + IDWriteFactoryPtr write_factory_; + IWICImagingFactoryPtr wic_imaging_factory_; + hwnd_this_thunk thunk_; + std::wstring title_; + std::wstring 名前_; + float width_,height_; + bool fit_to_display_; + boost::shared_ptr wnd_class_; + WNDPROC thunk_proc_; + }; + + struct toplevel_window; + typedef boost::shared_ptr toplevel_window_ptr; + + /** toplevel_window を生成する関数 */ + toplevel_window_ptr create_toplevel_window ( + const std::wstring& menu_name, + const std::wstring& name, + const boost::uint32_t show_flag = SW_SHOWNORMAL, + bool fit_to_display = false, + float width = 640, + float height = 480 + ); + + + + /** toplevel ウィンドウクラス */ + /* このクラスは、create_toplevel_window 関数からのみ生成可能 */ + struct toplevel_window : public base_window + { + friend toplevel_window_ptr create_toplevel_window + ( + const std::wstring& menu_name, + const std::wstring& name, + const boost::uint32_t show_flag, + bool fit_to_display , + float width , + float height + ); + void main_loop(); + protected: + void render(); + toplevel_window(const std::wstring& menu_name,const std::wstring& name,bool fit_to_display,float width = 640,float height = 480) : base_window(menu_name,name,fit_to_display,width,height) + { + on_render.connect(boost::bind(&toplevel_window::render,this)); + }; + public: + LRESULT toplevel_window::window_proc(HWND hwnd,boost::uint32_t message, WPARAM wParam, LPARAM lParam); + }; + + struct av_mm_thread_characteristics + { + av_mm_thread_characteristics(std::wstring& str) : task_name_(str) + { + handle_ = ::AvSetMmThreadCharacteristicsW(str.c_str(),(LPDWORD)&task_index_); + } + + bool set_priority(AVRT_PRIORITY p){return (::AvSetMmThreadPriority(handle_,p) == TRUE);} + + ~av_mm_thread_characteristics() + { + ::AvRevertMmThreadCharacteristics(handle_); + } + + private: + std::wstring task_name_; + boost::uint32_t task_index_; + HANDLE handle_; + }; + + struct widget + { + void draw(); + float x_,y_; + }; + + typedef sf::begin_draw begin_draw_bitmap; + typedef sf::begin_draw begin_draw_hwnd; + +} \ No newline at end of file diff --git a/sfwasapi/sfwasapi.vcxproj b/sfwasapi/sfwasapi.vcxproj index 4f9f455..21c06ec 100644 --- a/sfwasapi/sfwasapi.vcxproj +++ b/sfwasapi/sfwasapi.vcxproj @@ -18,7 +18,8 @@ Application true - MultiByte + Unicode + Windows7.1SDK Application @@ -62,6 +63,26 @@ + + + + + + + + + + + + + + + + + + Create + + diff --git a/sfwasapi/sfwasapi.vcxproj.filters b/sfwasapi/sfwasapi.vcxproj.filters index 3cd58cb..9831c91 100644 --- a/sfwasapi/sfwasapi.vcxproj.filters +++ b/sfwasapi/sfwasapi.vcxproj.filters @@ -1,17 +1,23 @@  - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sfwasapi/singleton.h b/sfwasapi/singleton.h new file mode 100644 index 0000000..298dff8 --- /dev/null +++ b/sfwasapi/singleton.h @@ -0,0 +1,55 @@ +#pragma once +/* + ============================================================================== + + This file is part of the S.F.Tracker + Copyright 2005-7 by Satoshi Fujiwara. + + S.F.Tracker can be redistributed and/or modified 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. + + S.F.Tracker 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 S.F.Tracker; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ============================================================================== +*/ +/** @file + * @brief + * @author S.F. (Satoshi Fujiwara) + */ +#include +#include +namespace sf { + template class PointerType = boost::shared_ptr > struct singleton + { + typedef PointerType ptr; + friend BaseClass; + + static ptr& instance() + { + boost::call_once(init,flag_); + return instance_; + }; + + + singleton(){}; + private: + singleton(const singleton& ); + static void init(){instance_.reset(new BaseClass);}; + static PointerType instance_; + static boost::once_flag flag_; + }; + + template class PointerType> boost::once_flag singleton::flag_ = BOOST_ONCE_INIT; + template class PointerType> PointerType singleton::instance_; +}; + + diff --git a/sfwasapi/stdafx.cpp b/sfwasapi/stdafx.cpp new file mode 100644 index 0000000..afed109 --- /dev/null +++ b/sfwasapi/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : 標準インクルードのみを含むソース ファイルです。 +// STed2.pch は、プリコンパイル済みヘッダーになります。 +// stdafx.obj にはプリコンパイル型情報が含まれます。 + +#include "stdafx.h" + +// TODO: このファイルではなく、STDAFX.H で必要な +// 追加ヘッダーを参照してください。 diff --git a/sfwasapi/stdafx.h b/sfwasapi/stdafx.h new file mode 100644 index 0000000..4224df2 --- /dev/null +++ b/sfwasapi/stdafx.h @@ -0,0 +1,118 @@ +// stdafx.h : 標準のシステム インクルード ファイルのインクルード ファイル、または +// 参照回数が多く、かつあまり変更されない、プロジェクト専用のインクルード ファイル +// を記述します。 +// + + +#pragma once +#include + +#ifndef UNICODE +#define UNICODE +#endif +// STL +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows 7 or later. +#define WINVER 0x0700 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows 7 or later. +#define _WIN32_WINNT 0x0700 // Change this to the appropriate value to target other versions of Windows. +#endif +#define DIRECTINPUT_VERSION 0x0800 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Boost +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +//#include "serialization.h" +#include +#include +#include +#include "sf_com.h" +//#include +//#include +//#include +//#include +//#include +#include "dinput.h" +#include +#include +#include +#include +#include + +#include +#include "avrt.h" +#include "mmsystem.h" +#include +#include +#include +#include "dwmapi.h" +//#include +//#include +//#include +//#include +//#include "exception.h" +//#include "singleton.h" +//#include "code_converter.h" +//#include "logger.h" + + +// TODO: プログラムに必要な追加ヘッダーをここで参照してください。 +#include "code_converter.h" +#include "logger.h" +#include "dout.h" diff --git a/sfwasapi/winmain.cpp b/sfwasapi/winmain.cpp new file mode 100644 index 0000000..6e6a6a6 --- /dev/null +++ b/sfwasapi/winmain.cpp @@ -0,0 +1,33 @@ +#include "stdafx.h" +#include "sf_windows.h" +#include "message_loop.h" +#include "sf_com.h" + +void MIDIメッセージ到着時(const boost::uint32_t wMsg,const boost::uint32_t midi_message,const boost::uint32_t time_stamp); + +/** WinMain */ +int APIENTRY _tWinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) +{ + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + std::wcout.imbue(std::locale("")); + + // COMの初期化 + sf::com_initialize init(); + + // ウィンドウの作成 + sf::toplevel_window_ptr + window( + sf::create_toplevel_window( + std::wstring(L"Test Window"),std::wstring(L"Test Window"))); + + // メッセージループの実行 + + WPARAM ret = sf::run_message_loop()(); + + return ret; +} -- 2.11.0