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: }