File Annotation

Not logged in
dcdd144598 2011-02-23        kinaba: #include "stdafx.h"
dcdd144598 2011-02-23        kinaba: #include "app.h"
dcdd144598 2011-02-23        kinaba: #include "window.h"
dcdd144598 2011-02-23        kinaba: using namespace ki;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //=========================================================================
dcdd144598 2011-02-23        kinaba: // IMEに関するあれこれ
dcdd144598 2011-02-23        kinaba: //=========================================================================
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: IMEManager* IMEManager::pUniqueInstance_;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: IMEManager::IMEManager()
dcdd144598 2011-02-23        kinaba: #ifdef USEGLOBALIME
dcdd144598 2011-02-23        kinaba: 	: immApp_( NULL )
dcdd144598 2011-02-23        kinaba: 	, immMsg_( NULL )
dcdd144598 2011-02-23        kinaba: #endif
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	#ifdef USEGLOBALIME
dcdd144598 2011-02-23        kinaba: 		// 色々面倒なのでWin95ではGlobalIME無し
dcdd144598 2011-02-23        kinaba: 		if( !app().isWin95() )
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			app().InitModule( App::OLE );
dcdd144598 2011-02-23        kinaba: 			if( S_OK == ::CoCreateInstance(
dcdd144598 2011-02-23        kinaba: 					CLSID_CActiveIMM, NULL, CLSCTX_INPROC_SERVER,
dcdd144598 2011-02-23        kinaba: 					IID_IActiveIMMApp, (void**)&immApp_ ) )
dcdd144598 2011-02-23        kinaba: 			{
dcdd144598 2011-02-23        kinaba: 				immApp_->QueryInterface(
dcdd144598 2011-02-23        kinaba: 					IID_IActiveIMMMessagePumpOwner, (void**)&immMsg_ );
dcdd144598 2011-02-23        kinaba: 			}
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 	#endif
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 唯一のインスタンスは私です
dcdd144598 2011-02-23        kinaba: 	pUniqueInstance_ = this;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: IMEManager::~IMEManager()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	#ifdef USEGLOBALIME
dcdd144598 2011-02-23        kinaba: 		if( immMsg_ != NULL )
dcdd144598 2011-02-23        kinaba: 			immMsg_->Release();
dcdd144598 2011-02-23        kinaba: 		if( immApp_ != NULL )
dcdd144598 2011-02-23        kinaba: 			immApp_->Release();
dcdd144598 2011-02-23        kinaba: 	#endif
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void IMEManager::EnableGlobalIME( bool enable )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	#ifdef USEGLOBALIME
dcdd144598 2011-02-23        kinaba: 		if( immApp_ )
dcdd144598 2011-02-23        kinaba: 			if( enable ) immApp_->Activate( TRUE );
dcdd144598 2011-02-23        kinaba: 			else         immApp_->Deactivate();
dcdd144598 2011-02-23        kinaba: 	#endif
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void IMEManager::FilterWindows( ATOM* lst, UINT siz )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	#ifdef USEGLOBALIME
dcdd144598 2011-02-23        kinaba: 		if( immApp_ )
dcdd144598 2011-02-23        kinaba: 			immApp_->FilterClientWindows( lst, siz );
dcdd144598 2011-02-23        kinaba: 	#endif
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: inline void IMEManager::TranslateMsg( MSG* msg )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	#ifdef USEGLOBALIME
dcdd144598 2011-02-23        kinaba: 		if( immMsg_ )
dcdd144598 2011-02-23        kinaba: 			if( S_OK == immMsg_->OnTranslateMessage( msg ) )
dcdd144598 2011-02-23        kinaba: 				return;
dcdd144598 2011-02-23        kinaba: 	#endif
dcdd144598 2011-02-23        kinaba: 	::TranslateMessage( msg );
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: inline LRESULT IMEManager::DefProc( HWND h, UINT m, WPARAM w, LPARAM l )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	#ifdef USEGLOBALIME
dcdd144598 2011-02-23        kinaba: 		if( immApp_ )
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			LRESULT res;
dcdd144598 2011-02-23        kinaba: 			if( S_OK == immApp_->OnDefWindowProc( h,m,w,l,&res ) )
dcdd144598 2011-02-23        kinaba: 				return res;
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 	#endif
dcdd144598 2011-02-23        kinaba: 	return ::DefWindowProc( h, m, w, l );
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: inline void IMEManager::MsgLoopBegin()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	#ifdef USEGLOBALIME
dcdd144598 2011-02-23        kinaba: 		if( immMsg_ )
dcdd144598 2011-02-23        kinaba: 			immMsg_->Start();
dcdd144598 2011-02-23        kinaba: 	#endif
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: inline void IMEManager::MsgLoopEnd()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	#ifdef USEGLOBALIME
dcdd144598 2011-02-23        kinaba: 		if( immMsg_ )
dcdd144598 2011-02-23        kinaba: 			immMsg_->End();
dcdd144598 2011-02-23        kinaba: 	#endif
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void IMEManager::SetFont( HWND wnd, const LOGFONT& lf )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	HIMC ime;
dcdd144598 2011-02-23        kinaba: 	LOGFONT* plf = const_cast<LOGFONT*>(&lf);
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	#ifdef USEGLOBALIME
dcdd144598 2011-02-23        kinaba: 	if( immApp_ )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		immApp_->GetContext( wnd, &ime );
dcdd144598 2011-02-23        kinaba: 		#ifdef _UNICODE
dcdd144598 2011-02-23        kinaba: 			immApp_->SetCompositionFontW( ime, plf );
dcdd144598 2011-02-23        kinaba: 		#else
dcdd144598 2011-02-23        kinaba: 			immApp_->SetCompositionFontA( ime, plf );
dcdd144598 2011-02-23        kinaba: 		#endif
dcdd144598 2011-02-23        kinaba: 		immApp_->ReleaseContext( wnd, ime );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	else
dcdd144598 2011-02-23        kinaba: 	#endif
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		ime = ::ImmGetContext( wnd );
dcdd144598 2011-02-23        kinaba: 		::ImmSetCompositionFont( ime, plf );
dcdd144598 2011-02-23        kinaba: 		::ImmReleaseContext( wnd, ime );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void IMEManager::SetPos( HWND wnd, int x, int y )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	HIMC ime;
dcdd144598 2011-02-23        kinaba: 	COMPOSITIONFORM cf;
dcdd144598 2011-02-23        kinaba: 	cf.dwStyle = CFS_POINT;
dcdd144598 2011-02-23        kinaba: 	cf.ptCurrentPos.x  = x;
dcdd144598 2011-02-23        kinaba: 	cf.ptCurrentPos.y  = y;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	#ifdef USEGLOBALIME
dcdd144598 2011-02-23        kinaba: 	if( immApp_ )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		immApp_->GetContext( wnd, &ime );
dcdd144598 2011-02-23        kinaba: 		immApp_->SetCompositionWindow( ime, &cf );
dcdd144598 2011-02-23        kinaba: 		immApp_->ReleaseContext( wnd, ime );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	else
dcdd144598 2011-02-23        kinaba: 	#endif
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		ime = ::ImmGetContext( wnd );
dcdd144598 2011-02-23        kinaba: 		::ImmSetCompositionWindow( ime, &cf );
dcdd144598 2011-02-23        kinaba: 		::ImmReleaseContext( wnd, ime );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void IMEManager::GetString( HWND wnd, unicode** str, ulong* len )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	*str = NULL;
dcdd144598 2011-02-23        kinaba: 	HIMC ime;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	#ifdef USEGLOBALIME
dcdd144598 2011-02-23        kinaba: 	if( immApp_ )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		long s=0;
dcdd144598 2011-02-23        kinaba: 		immApp_->GetContext( wnd, &ime );
dcdd144598 2011-02-23        kinaba: 		immApp_->GetCompositionStringW( ime, GCS_RESULTSTR, 0, &s, NULL );
dcdd144598 2011-02-23        kinaba: 		*str = new unicode[ (*len=s/2)+1 ];
dcdd144598 2011-02-23        kinaba: 		immApp_->GetCompositionStringW( ime, GCS_RESULTSTR, s, &s, *str );
dcdd144598 2011-02-23        kinaba: 		immApp_->ReleaseContext( wnd, ime );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	else
dcdd144598 2011-02-23        kinaba: 	#endif
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		ime = ::ImmGetContext( wnd );
dcdd144598 2011-02-23        kinaba: 		long s = ::ImmGetCompositionStringW( ime,GCS_RESULTSTR,NULL,0 );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 		#ifndef _UNICODE
dcdd144598 2011-02-23        kinaba: 			if( s <= 0 )
dcdd144598 2011-02-23        kinaba: 			{
dcdd144598 2011-02-23        kinaba: 				s = ::ImmGetCompositionStringA(ime,GCS_RESULTSTR,NULL,0);
dcdd144598 2011-02-23        kinaba: 				if( s > 0 )
dcdd144598 2011-02-23        kinaba: 				{
dcdd144598 2011-02-23        kinaba: 					char* tmp = new char[s];
dcdd144598 2011-02-23        kinaba: 					*str = new unicode[*len=s*2];
dcdd144598 2011-02-23        kinaba: 					::ImmGetCompositionStringA( ime,GCS_RESULTSTR,tmp,s );
dcdd144598 2011-02-23        kinaba: 					*len = ::MultiByteToWideChar(
dcdd144598 2011-02-23        kinaba: 						CP_ACP, MB_PRECOMPOSED, tmp, s, *str, *len );
dcdd144598 2011-02-23        kinaba: 					delete [] tmp;
dcdd144598 2011-02-23        kinaba: 				}
dcdd144598 2011-02-23        kinaba: 			}
dcdd144598 2011-02-23        kinaba: 			else
dcdd144598 2011-02-23        kinaba: 		#endif
dcdd144598 2011-02-23        kinaba: 			{
dcdd144598 2011-02-23        kinaba: 				*str = new unicode[ (*len=s/2)+1 ];
dcdd144598 2011-02-23        kinaba: 				::ImmGetCompositionStringW( ime, GCS_RESULTSTR, *str, s );
dcdd144598 2011-02-23        kinaba: 			}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 		::ImmReleaseContext( wnd, ime );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //=========================================================================
dcdd144598 2011-02-23        kinaba: // Windowに関するあれこれ
dcdd144598 2011-02-23        kinaba: //=========================================================================
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: Window::Window()
dcdd144598 2011-02-23        kinaba: 	: wnd_      (NULL)
dcdd144598 2011-02-23        kinaba: 	, isLooping_(false)
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void Window::SetHwnd( HWND wnd )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	wnd_ = wnd;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void Window::MsgLoop()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// thisをメインウインドウとして、
dcdd144598 2011-02-23        kinaba: 	// メインメッセージループを回す
dcdd144598 2011-02-23        kinaba: 	isLooping_ = true;
dcdd144598 2011-02-23        kinaba: 	ime().MsgLoopBegin();
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	for( MSG msg; ::GetMessage( &msg, NULL, 0, 0 ); )
dcdd144598 2011-02-23        kinaba: 		if( !PreTranslateMessage( &msg ) )
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 			ime().TranslateMsg( &msg );
dcdd144598 2011-02-23        kinaba: 			::DispatchMessage( &msg );
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	ime().MsgLoopEnd();
dcdd144598 2011-02-23        kinaba: 	isLooping_ = false;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void Window::ProcessMsg()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// こっちはグローバル関数。
dcdd144598 2011-02-23        kinaba: 	// 未処理メッセージを一掃
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	ime().MsgLoopBegin();
dcdd144598 2011-02-23        kinaba: 	for( MSG msg; ::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ); )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		ime().TranslateMsg( &msg );
dcdd144598 2011-02-23        kinaba: 		::DispatchMessage( &msg );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	ime().MsgLoopEnd();
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void Window::SetCenter( HWND hwnd, HWND rel )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 自分のサイズを取得
dcdd144598 2011-02-23        kinaba: 	RECT rc,pr;
dcdd144598 2011-02-23        kinaba: 	::GetWindowRect( hwnd, &rc );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 親の位置、ないしは全画面の位置を取得
dcdd144598 2011-02-23        kinaba: 	if( rel != NULL )
dcdd144598 2011-02-23        kinaba: 		::GetWindowRect( rel, &pr );
dcdd144598 2011-02-23        kinaba: 	else
dcdd144598 2011-02-23        kinaba: 		::SystemParametersInfo( SPI_GETWORKAREA, 0, &pr, 0 );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 中央を計算
dcdd144598 2011-02-23        kinaba: 	::SetWindowPos( hwnd, 0,
dcdd144598 2011-02-23        kinaba: 		pr.left + ( (pr.right-pr.left)-(rc.right-rc.left) )/2,
dcdd144598 2011-02-23        kinaba: 		pr.top  + ( (pr.bottom-pr.top)-(rc.bottom-rc.top) )/2,
dcdd144598 2011-02-23        kinaba: 		0, 0, SWP_NOSIZE|SWP_NOZORDER );
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void Window::SetFront( HWND hwnd )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// kazubon氏の TClock のソースを参考にしました。感謝!
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	if( app().isNewTypeWindows() )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		DWORD pid;
dcdd144598 2011-02-23        kinaba: 		HWND  fore= ::GetForegroundWindow();
dcdd144598 2011-02-23        kinaba: 		DWORD th1 = ::GetWindowThreadProcessId( fore, &pid );
dcdd144598 2011-02-23        kinaba: 		DWORD th2 = ::GetCurrentThreadId();
dcdd144598 2011-02-23        kinaba: 		::AttachThreadInput( th2, th1, TRUE );
dcdd144598 2011-02-23        kinaba: 		::SetForegroundWindow( hwnd );
dcdd144598 2011-02-23        kinaba: 		::AttachThreadInput( th2, th1, FALSE );
dcdd144598 2011-02-23        kinaba: 		::BringWindowToTop( hwnd );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	else
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		::SetForegroundWindow( hwnd );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //=========================================================================
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: WndImpl::WndImpl( LPCTSTR className, DWORD style, DWORD styleEx )
dcdd144598 2011-02-23        kinaba: 	: className_( className )
dcdd144598 2011-02-23        kinaba: 	, style_    ( style )
dcdd144598 2011-02-23        kinaba: 	, styleEx_  ( styleEx )
dcdd144598 2011-02-23        kinaba: 	, thunk_    ( static_cast<byte*>(
dcdd144598 2011-02-23        kinaba: 	                ::VirtualAlloc( NULL, THUNK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE )) )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: WndImpl::~WndImpl()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// ウインドウを破棄し忘れてたら閉じる
dcdd144598 2011-02-23        kinaba: 	// …が、この時点で既に vtable は破棄されかかっているので
dcdd144598 2011-02-23        kinaba: 	// 正しい on_destroy が呼ばれる保証は全くない。あくまで
dcdd144598 2011-02-23        kinaba: 	// 緊急脱出用(^^; と考えること。
dcdd144598 2011-02-23        kinaba: 	Destroy();
dcdd144598 2011-02-23        kinaba: 	::VirtualFree( thunk_, 0, MEM_RELEASE );
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void WndImpl::Destroy()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	if( hwnd() != NULL )
dcdd144598 2011-02-23        kinaba: 		::DestroyWindow( hwnd() );
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: ATOM WndImpl::Register( WNDCLASSEX* cls )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// WndImpl派生クラスで使うWndClassを登録。
dcdd144598 2011-02-23        kinaba: 	// プロシージャはkilib謹製のものに書き換えちゃいます。
dcdd144598 2011-02-23        kinaba: 	cls->cbSize      = sizeof(WNDCLASSEX);
dcdd144598 2011-02-23        kinaba: 	cls->hInstance   = app().hinst();
dcdd144598 2011-02-23        kinaba: 	cls->lpfnWndProc = StartProc;
dcdd144598 2011-02-23        kinaba: 	return ::RegisterClassEx( cls );
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: struct ThisAndParam
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// ユーザ指定のパラメータ以外にも渡したいモノが少々…
dcdd144598 2011-02-23        kinaba: 	WndImpl* pThis;
dcdd144598 2011-02-23        kinaba: 	void*   pParam;
dcdd144598 2011-02-23        kinaba: };
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: bool WndImpl::Create(
dcdd144598 2011-02-23        kinaba: 	LPCTSTR wndName, HWND parent, int x, int y, int w, int h, void* param )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// ここでthisポインタを忍び込ませておく
dcdd144598 2011-02-23        kinaba: 	ThisAndParam z = { this, param };
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	LOGGER("WndImpl::Create before CreateWindowEx API call");
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	return (NULL != ::CreateWindowEx(
dcdd144598 2011-02-23        kinaba: 		styleEx_, className_, wndName, style_,
dcdd144598 2011-02-23        kinaba: 		x, y, w, h, parent, NULL, app().hinst(), &z
dcdd144598 2011-02-23        kinaba: 	));
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: LRESULT CALLBACK WndImpl::StartProc(
dcdd144598 2011-02-23        kinaba: 	HWND wnd, UINT msg, WPARAM wp, LPARAM lp )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// WM_CREATE以外はスルーの方針で
dcdd144598 2011-02-23        kinaba: 	if( msg != WM_CREATE )
dcdd144598 2011-02-23        kinaba: 		return ::DefWindowProc( wnd, msg, wp, lp );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	LOGGER("WndImpl::StartProc WM_CREATE kitaaaaa!!");
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// 忍ばせて置いたthisポインタを取り出し
dcdd144598 2011-02-23        kinaba: 	CREATESTRUCT* cs   = reinterpret_cast<CREATESTRUCT*>(lp);
dcdd144598 2011-02-23        kinaba: 	ThisAndParam* pz   = static_cast<ThisAndParam*>(cs->lpCreateParams);
dcdd144598 2011-02-23        kinaba: 	WndImpl*   pThis   = pz->pThis;
dcdd144598 2011-02-23        kinaba: 	cs->lpCreateParams = pz->pParam;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// サンク
dcdd144598 2011-02-23        kinaba: 	pThis->SetUpThunk( wnd );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// WM_CREATE用メッセージを呼ぶ
dcdd144598 2011-02-23        kinaba: 	pThis->on_create( cs );
dcdd144598 2011-02-23        kinaba: 	return 0;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void WndImpl::SetUpThunk( HWND wnd )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	SetHwnd( wnd );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	// ここで動的にx86の命令列
dcdd144598 2011-02-23        kinaba: 	//   | mov dword ptr [esp+4] this
dcdd144598 2011-02-23        kinaba: 	//   | jmp MainProc
dcdd144598 2011-02-23        kinaba: 	// あるいはAMD64の命令列
dcdd144598 2011-02-23        kinaba: 	//   | mov rcx this
dcdd144598 2011-02-23        kinaba: 	//   | mov rax MainProc
dcdd144598 2011-02-23        kinaba: 	//   | jmp rax
dcdd144598 2011-02-23        kinaba: 	// を生成し、メッセージプロシージャとして差し替える。
dcdd144598 2011-02-23        kinaba: 	//
dcdd144598 2011-02-23        kinaba: 	// これで次回からは、第一引数が hwnd のかわりに
dcdd144598 2011-02-23        kinaba: 	// thisポインタになった状態でMainProcが呼ばれる
dcdd144598 2011-02-23        kinaba: 	// …と見なしたプログラムが書ける。
dcdd144598 2011-02-23        kinaba: 	//
dcdd144598 2011-02-23        kinaba: 	// 参考資料:ATLのソース
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: #ifdef _M_AMD64
dcdd144598 2011-02-23        kinaba: 	*reinterpret_cast<dbyte*>   (thunk_+ 0) = 0xb948;
dcdd144598 2011-02-23        kinaba: 	*reinterpret_cast<WndImpl**>(thunk_+ 2) = this;
dcdd144598 2011-02-23        kinaba: 	*reinterpret_cast<dbyte*>   (thunk_+10) = 0xb848;
dcdd144598 2011-02-23        kinaba: 	*reinterpret_cast<void**>   (thunk_+12) = MainProc;
dcdd144598 2011-02-23        kinaba: 	*reinterpret_cast<dbyte*>   (thunk_+20) = 0xe0ff;
dcdd144598 2011-02-23        kinaba: #else
dcdd144598 2011-02-23        kinaba: 	*reinterpret_cast<qbyte*>   (thunk_+0) = 0x042444C7;
dcdd144598 2011-02-23        kinaba: 	*reinterpret_cast<WndImpl**>(thunk_+4) = this;
dcdd144598 2011-02-23        kinaba: 	*reinterpret_cast< byte*>   (thunk_+8) = 0xE9;
dcdd144598 2011-02-23        kinaba: 	*reinterpret_cast<qbyte*>   (thunk_+9) =
dcdd144598 2011-02-23        kinaba: 		reinterpret_cast<byte*>((void*)MainProc)-(thunk_+13);
dcdd144598 2011-02-23        kinaba: #endif
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	::FlushInstructionCache( ::GetCurrentProcess(), thunk_, THUNK_SIZE );
dcdd144598 2011-02-23        kinaba: 	::SetWindowLongPtr( wnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&thunk_[0]) );
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: LRESULT CALLBACK WndImpl::MainProc(
dcdd144598 2011-02-23        kinaba: 	WndImpl* ptr, UINT msg, WPARAM wp, LPARAM lp )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	if( msg == WM_COMMAND )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		if( !ptr->on_command( LOWORD(wp), (HWND)lp ) )
dcdd144598 2011-02-23        kinaba: 			return ::DefWindowProc( ptr->hwnd(), msg, wp, lp );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	else if( msg == WM_DESTROY )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		ptr->on_destroy();
dcdd144598 2011-02-23        kinaba: 		::SetWindowLongPtr( ptr->hwnd(), GWLP_WNDPROC,
dcdd144598 2011-02-23        kinaba: 			reinterpret_cast<LONG_PTR>(StartProc) );
dcdd144598 2011-02-23        kinaba: 		if( ptr->isMainWnd() )
dcdd144598 2011-02-23        kinaba: 			::PostQuitMessage( 0 );
dcdd144598 2011-02-23        kinaba: 		ptr->SetHwnd(NULL);
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 	else
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		return ptr->on_message( msg, wp, lp );
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	return 0;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void WndImpl::on_create( CREATESTRUCT* cs )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 何もしない
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void WndImpl::on_destroy()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 何もしない
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: bool WndImpl::on_command( UINT, HWND )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 何もしない
dcdd144598 2011-02-23        kinaba: 	return false;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: LRESULT WndImpl::on_message( UINT msg, WPARAM wp, LPARAM lp )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 何もしない
dcdd144598 2011-02-23        kinaba: 	return ime().DefProc( hwnd(), msg, wp, lp );
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: bool WndImpl::PreTranslateMessage( MSG* )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 何もしない
dcdd144598 2011-02-23        kinaba: 	return false;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //=========================================================================
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: DlgImpl::DlgImpl( UINT id )
dcdd144598 2011-02-23        kinaba: 	: rsrcID_( id )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: DlgImpl::~DlgImpl()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// ウインドウを破棄し忘れてたら閉じる
dcdd144598 2011-02-23        kinaba: 	if( hwnd() != NULL )
dcdd144598 2011-02-23        kinaba: 		End( IDCANCEL );
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void DlgImpl::End( UINT code )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	endCode_ = code;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	if( type() == MODAL )
dcdd144598 2011-02-23        kinaba: 		::EndDialog( hwnd(), code );
dcdd144598 2011-02-23        kinaba: 	else
dcdd144598 2011-02-23        kinaba: 		::DestroyWindow( hwnd() );
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void DlgImpl::GoModal( HWND parent )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	type_ = MODAL;
dcdd144598 2011-02-23        kinaba: 	::DialogBoxParam( app().hinst(), MAKEINTRESOURCE(rsrcID_), parent,
dcdd144598 2011-02-23        kinaba: 		(DLGPROC)MainProc, reinterpret_cast<LPARAM>(this) );
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void DlgImpl::GoModeless( HWND parent )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	type_ = MODELESS;
dcdd144598 2011-02-23        kinaba: 	::CreateDialogParam( app().hinst(), MAKEINTRESOURCE(rsrcID_), parent,
dcdd144598 2011-02-23        kinaba: 		(DLGPROC)MainProc, reinterpret_cast<LPARAM>(this) );
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: BOOL CALLBACK DlgImpl::MainProc(
dcdd144598 2011-02-23        kinaba: 	HWND dlg, UINT msg, WPARAM wp, LPARAM lp )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	if( msg == WM_INITDIALOG )
dcdd144598 2011-02-23        kinaba: 	{
dcdd144598 2011-02-23        kinaba: 		::SetWindowLongPtr( dlg, GWLP_USERDATA, lp );
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 		DlgImpl* ptr = reinterpret_cast<DlgImpl*>(lp);
dcdd144598 2011-02-23        kinaba: 		ptr->SetHwnd( dlg );
dcdd144598 2011-02-23        kinaba: 		ptr->on_init();
dcdd144598 2011-02-23        kinaba: 		return FALSE;
dcdd144598 2011-02-23        kinaba: 	}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	DlgImpl* ptr =
dcdd144598 2011-02-23        kinaba: 		reinterpret_cast<DlgImpl*>(::GetWindowLongPtr(dlg,GWLP_USERDATA));
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	if( ptr != NULL )
dcdd144598 2011-02-23        kinaba: 		switch( msg )
dcdd144598 2011-02-23        kinaba: 		{
dcdd144598 2011-02-23        kinaba: 		case WM_COMMAND:
dcdd144598 2011-02-23        kinaba: 			switch( LOWORD(wp) )
dcdd144598 2011-02-23        kinaba: 			{
dcdd144598 2011-02-23        kinaba: 			case IDOK:
dcdd144598 2011-02-23        kinaba: 				if( ptr->on_ok() )
dcdd144598 2011-02-23        kinaba: 					ptr->End( IDOK );
dcdd144598 2011-02-23        kinaba: 				return TRUE;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 			case IDCANCEL:
dcdd144598 2011-02-23        kinaba: 				if( ptr->on_cancel() )
dcdd144598 2011-02-23        kinaba: 					ptr->End( IDCANCEL );
dcdd144598 2011-02-23        kinaba: 				return TRUE;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 			default:
dcdd144598 2011-02-23        kinaba: 				return ptr->on_command( HIWORD(wp), LOWORD(wp),
dcdd144598 2011-02-23        kinaba: 					reinterpret_cast<HWND>(lp) ) ? TRUE : FALSE;
dcdd144598 2011-02-23        kinaba: 			}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 		case WM_DESTROY:
dcdd144598 2011-02-23        kinaba: 			ptr->on_destroy();
dcdd144598 2011-02-23        kinaba: 			if( ptr->isMainWnd() )
dcdd144598 2011-02-23        kinaba: 				::PostQuitMessage( 0 );
dcdd144598 2011-02-23        kinaba: 			ptr->SetHwnd(NULL);
dcdd144598 2011-02-23        kinaba: 			break;
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 		default:
dcdd144598 2011-02-23        kinaba: 			return ptr->on_message( msg, wp, lp ) ? TRUE : FALSE;
dcdd144598 2011-02-23        kinaba: 		}
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 	return FALSE;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: //-------------------------------------------------------------------------
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void DlgImpl::on_init()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 何もしない
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: void DlgImpl::on_destroy()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 何もしない
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: bool DlgImpl::on_ok()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 何もしない
dcdd144598 2011-02-23        kinaba: 	return true;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: bool DlgImpl::on_cancel()
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 何もしない
dcdd144598 2011-02-23        kinaba: 	return true;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: bool DlgImpl::on_command( UINT, UINT, HWND )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 何もしない
dcdd144598 2011-02-23        kinaba: 	return false;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: bool DlgImpl::on_message( UINT, WPARAM, LPARAM )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// 何もしない
dcdd144598 2011-02-23        kinaba: 	return false;
dcdd144598 2011-02-23        kinaba: }
dcdd144598 2011-02-23        kinaba: 
dcdd144598 2011-02-23        kinaba: bool DlgImpl::PreTranslateMessage( MSG* msg )
dcdd144598 2011-02-23        kinaba: {
dcdd144598 2011-02-23        kinaba: 	// モードレスの時用。ダイアログメッセージ処理。
dcdd144598 2011-02-23        kinaba: 	return (FALSE != ::IsDialogMessage( hwnd(), msg ));
dcdd144598 2011-02-23        kinaba: }