Artifact Content

Not logged in

Artifact 619c2be4e23fbad6a30915626f30119d63ac384a


     1  //--- K.I.LIB ---
     2  // kl_wnd.cpp : window information manager
     3  
     4  #include "stdafx.h"
     5  #include "kilib.h"
     6  
     7  
     8  //-------- Windowを作成時に HWND に kiWindow* をセットするための処理 -------//
     9  
    10  
    11  kiWindow* kiWindow::st_pCurInit = NULL;
    12      HHOOK kiWindow::st_hHook    = NULL;
    13  
    14  void kiWindow::init()
    15  {
    16  	// CreateWindow 用フック設置
    17  	st_hHook = ::SetWindowsHookEx( WH_CBT, &CBTProc, NULL, ::GetCurrentThreadId() );
    18  }
    19  
    20  void kiWindow::finish()
    21  {
    22  	// CreateWindow 用フック解除
    23  	::UnhookWindowsHookEx( st_hHook );
    24  }
    25  
    26  LRESULT CALLBACK kiWindow::CBTProc( int code, WPARAM wp, LPARAM lp )
    27  {
    28  	if( code == HCBT_CREATEWND )
    29  	{
    30  		if( st_pCurInit )
    31  		{
    32  			// k.i.lib のウインドウが CreateWindow された場合
    33  			st_pCurInit->setHwnd( (HWND)wp );
    34  			::SetWindowLong( (HWND)wp, GWL_USERDATA, (LONG)st_pCurInit );
    35  			st_pCurInit = NULL;
    36  		}
    37  		else
    38  			::SetWindowLong( (HWND)wp, GWL_USERDATA, 0 );
    39  	}
    40  
    41  	return ::CallNextHookEx( st_hHook, code, wp, lp );
    42  }
    43  
    44  void kiWindow::detachHwnd()
    45  {
    46  	::SetWindowLong( hwnd(), GWL_USERDATA, 0 );
    47  	if( this == app()->mainwnd() )
    48  		app()->setMainWnd( NULL );
    49  	setHwnd( NULL );
    50  }
    51  
    52  
    53  //------------ Window にまつわるエトセトラな処理 (static) ---------------//
    54  
    55  
    56  bool kiWindow::loopbreaker = false;
    57  
    58  void kiWindow::msg()
    59  {
    60  	for( MSG msg; ::PeekMessage( &msg,NULL,0,0,PM_REMOVE ); )
    61  		::TranslateMessage( &msg ), ::DispatchMessage( &msg );
    62  }
    63  
    64  void kiWindow::msgLoop( msglooptype type )
    65  {
    66  	kiWindow* wnd;
    67  	MSG msg;
    68  	while( !loopbreaker &&
    69  		  type==GET ?  ::GetMessage( &msg,NULL,0,0 )
    70  					: ::PeekMessage( &msg,NULL,0,0,PM_REMOVE ) )
    71  	{
    72  		if( wnd = app()->mainwnd() )
    73  		{
    74  			if( wnd->m_hAccel )
    75  				if( ::TranslateAccelerator( wnd->hwnd(), wnd->m_hAccel, &msg ) )
    76  					continue;
    77  			if( msg.message!=WM_CHAR && wnd->isDlgMsg( &msg ) )
    78  				continue;
    79  		}
    80  		::TranslateMessage( &msg ), ::DispatchMessage( &msg );
    81  	}
    82  	loopbreaker = false;
    83  }
    84  
    85  void kiWindow::setFront( HWND wnd )
    86  {
    87  	const OSVERSIONINFO& v = app()->osver();
    88  
    89  	// Win2000 以上 or Win98 以上
    90  	if( ( v.dwPlatformId==VER_PLATFORM_WIN32_NT && v.dwMajorVersion>=5 )
    91  	 || ( v.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS &&
    92  							v.dwMajorVersion*100+v.dwMinorVersion>=410 ) )
    93  	{
    94  		DWORD pid;
    95  		DWORD th1 = ::GetWindowThreadProcessId( ::GetForegroundWindow(), &pid );
    96  		DWORD th2 = ::GetCurrentThreadId();
    97  		::AttachThreadInput( th2, th1, TRUE );
    98  		::SetForegroundWindow( wnd );
    99  		::AttachThreadInput( th2, th1, FALSE );
   100  		::BringWindowToTop( wnd );
   101  	}
   102  	else  // 古いWin
   103  		::SetForegroundWindow( wnd );
   104  
   105  	// Special Thanks To kazubon !! ( the author of TClock )
   106  }
   107  
   108  void kiWindow::setCenter( HWND wnd, HWND rel )
   109  {
   110  	RECT rc,pr;
   111  	::GetWindowRect( wnd, &rc );
   112  
   113  	if( rel )
   114  		::GetWindowRect( rel, &pr );
   115  	else
   116  		::SystemParametersInfo( SPI_GETWORKAREA, 0, &pr, 0 );
   117  
   118  	::SetWindowPos( wnd, 0,
   119  		pr.left + ( (pr.right-pr.left)-(rc.right-rc.left) )/2,
   120  		pr.top  + ( (pr.bottom-pr.top)-(rc.bottom-rc.top) )/2,
   121  		0, 0, SWP_NOSIZE|SWP_NOZORDER );
   122  }
   123  
   124  
   125  //------------------ Windowベースクラスとしての処理 ----------------------//
   126  
   127  
   128  kiWindow::kiWindow()
   129  {
   130  	m_hWnd = NULL;
   131  	m_hAccel = NULL;
   132  	app()->shellInit();
   133  }
   134  
   135  kiWindow::~kiWindow()
   136  {
   137  	if( m_hWnd && ::IsWindow( m_hWnd ) )
   138  	{
   139  		::SetWindowLong( m_hWnd, GWL_USERDATA, 0 );
   140  		::DestroyWindow( m_hWnd );
   141  	}
   142  }
   143  
   144  void kiWindow::loadAccel( UINT id )
   145  {
   146  	m_hAccel = ::LoadAccelerators( app()->inst(), MAKEINTRESOURCE(id) );
   147  }
   148  
   149  
   150  //---------------- スタンドアロンのWindowの処理 ---------------------//
   151  
   152  // …未完成…
   153  
   154  //---------------------------- Dialog -----------------------------//
   155  
   156  
   157  kiDialog::kiDialog( UINT id )
   158  {
   159  	m_Rsrc = id;
   160  }
   161  
   162  void kiDialog::doModal( HWND parent )
   163  {
   164  	setState( true );
   165  	preCreate( this );
   166  
   167  	::DialogBoxParam( app()->inst(), MAKEINTRESOURCE(m_Rsrc),
   168  						parent, commonDlg, (LPARAM)this );
   169  }
   170  
   171  void kiDialog::createModeless( HWND parent )
   172  {
   173  	setState( false );
   174  	preCreate( this );
   175  
   176  	::CreateDialogParam( app()->inst(), MAKEINTRESOURCE(m_Rsrc),
   177  						parent, commonDlg, (LPARAM)this );
   178  
   179  	::ShowWindow( hwnd(), SW_SHOW );
   180  	::UpdateWindow( hwnd() );
   181  }
   182  
   183  void kiDialog::end( UINT endcode )
   184  {
   185  	setEndCode( endcode );
   186  
   187  	if( isModal() )
   188  		::EndDialog( hwnd(), getEndCode() );
   189  	else
   190  		::DestroyWindow( hwnd() );
   191  }
   192  
   193  BOOL kiDialog::commonDlg( HWND dlg, UINT msg, WPARAM wp, LPARAM lp )
   194  {
   195  	// kiDialog インターフェイスへのポインタを取得
   196  	kiDialog* ptr = (kiDialog*)::GetWindowLong( dlg, GWL_USERDATA );
   197  	if( !ptr ) return FALSE;
   198  
   199  	// WM_INITDIALOG なら onInit を呼ぶ
   200  	if( msg == WM_INITDIALOG )
   201  		return ptr->onInit();
   202  
   203  	// OK / Cancel 処理
   204  	else if( msg == WM_COMMAND )
   205  	{
   206  		switch( LOWORD(wp) )
   207  		{
   208  		case IDOK:
   209  			if( ptr->onOK() )
   210  				ptr->end( IDOK );
   211  			return TRUE;
   212  		case IDCANCEL:
   213  			if( ptr->onCancel() )
   214  				ptr->end( IDCANCEL );
   215  			return TRUE;
   216  		}
   217  	}
   218  
   219  	// 普通のメッセージ
   220  	BOOL ans = ptr->proc( msg, wp, lp );
   221  
   222  	// WM_DESTORY ならウインドウハンドル切り離し
   223  	if( msg == WM_DESTROY )
   224  		ptr->detachHwnd();
   225  
   226  	return ans;
   227  }
   228  
   229  
   230  //------------------------ PropertySheet -------------------------//
   231  
   232  
   233  kiPropSheet* kiPropSheet::st_CurInitPS = NULL;
   234  
   235  kiPropSheet::kiPropSheet() : kiDialog( 0 )
   236  {
   237  	ki_memzero( &m_Header, sizeof(m_Header) );
   238  	m_Header.dwSize      = sizeof(m_Header);
   239  	m_Header.dwFlags     |=PSH_USECALLBACK | PSH_PROPSHEETPAGE;
   240  	m_Header.pfnCallback = main_initProc;
   241  	m_Header.hInstance   = app()->inst();
   242  	m_Header.nStartPage  = 0;
   243  }
   244  
   245  void kiPropSheet::begin()
   246  {
   247  	int l = m_Pages.len();
   248  	PROPSHEETPAGE* ppsp = new PROPSHEETPAGE[ l ];
   249  	ki_memzero( ppsp, sizeof(PROPSHEETPAGE)*l );
   250  
   251  	for( int i=0; i<l; i++ )
   252  	{
   253  		ppsp[i].dwSize      = sizeof( PROPSHEETPAGE );
   254  		ppsp[i].hInstance   = app()->inst();
   255  		ppsp[i].pfnCallback = page_initProc;
   256  		ppsp[i].pfnDlgProc  = page_cmmnProc;
   257  		ppsp[i].dwFlags     = PSP_USECALLBACK | PSP_HASHELP;
   258  		m_Pages[i]->setInfo( ppsp+i );
   259  	}
   260  
   261  	m_Header.ppsp   = ppsp;
   262  	m_Header.nPages = l;
   263  
   264  	st_CurInitPS = this;
   265  	PropertySheet( &m_Header );
   266  	delete [] ppsp;
   267  }
   268  
   269  void kiPropSheet::doModal( HWND parent )
   270  {
   271  	m_Header.dwFlags &= (~PSH_MODELESS);
   272  	setState( true );
   273  	begin();
   274  }
   275  
   276  void kiPropSheet::createModeless( HWND parent )
   277  {
   278  	m_Header.dwFlags |= PSH_MODELESS;
   279  	setState( false );
   280  	begin();
   281  }
   282  
   283  void kiPropSheet::end( UINT endcode )
   284  {
   285  	// 終了コードセット
   286  	setEndCode( endcode );
   287  
   288  	// サブクラス化解除
   289  	::SetWindowLong( hwnd(), GWL_WNDPROC, (LONG)m_DefProc );
   290  
   291  	// 終了
   292  	if( isModal() ) // サブクラス化解除してるので、再度 end が呼ばれることはないはず。
   293  		::PostMessage( hwnd(), WM_COMMAND, IDCANCEL, 0 );
   294  	else
   295  		::DestroyWindow( hwnd() );
   296  
   297  	// WM_DESTROY時相当の動作
   298  	detachHwnd();
   299  }
   300  
   301  LRESULT CALLBACK kiPropSheet::main_cmmnProc( HWND dlg, UINT msg, WPARAM wp, LPARAM lp )
   302  {
   303  	kiPropSheet* ptr = (kiPropSheet*)::GetWindowLong( dlg, GWL_USERDATA );
   304  	if( !ptr )
   305  		return 0;
   306  
   307  	// まずデフォルトの処理
   308  	LRESULT result = ::CallWindowProc( ptr->m_DefProc, dlg, msg, wp, lp );
   309  
   310  	// ×ボタンはキャンセル扱い
   311  	if( msg==WM_SYSCOMMAND && wp==SC_CLOSE )
   312  		::PostMessage( dlg, WM_COMMAND, IDCANCEL, 0 );
   313  
   314  	// コマンド処理
   315  	else if( msg==WM_COMMAND )
   316  	{
   317  		switch( LOWORD(wp) )
   318  		{
   319  		case IDOK:
   320  			if( ptr->onOK() )
   321  				ptr->end( IDOK );
   322  			return TRUE;
   323  		case IDCANCEL:
   324  			if( ptr->onCancel() )
   325  				ptr->end( IDCANCEL );
   326  			return TRUE;
   327  		case IDAPPLY:
   328  			ptr->onApply();
   329  			break;
   330  		case ID_KIPS_HELP:
   331  			ptr->onHelp();
   332  			break;
   333  		default:
   334  			ptr->onCommand( LOWORD(wp) );
   335  			break;
   336  		}
   337  	}
   338  
   339  	// ドラッグ&ドロップ
   340  	else if( msg==WM_DROPFILES )
   341  		ptr->onDrop( (HDROP)wp );
   342  
   343  	return result;
   344  }
   345  
   346  struct DLGTEMPLATEEX
   347  {
   348      WORD dlgVer;
   349      WORD signature;
   350      DWORD helpID;
   351      DWORD exStyle;
   352      DWORD style;
   353      WORD cDlgItems;
   354      short x;
   355      short y;
   356      short cx;
   357      short cy;
   358  };
   359  
   360  int CALLBACK kiPropSheet::main_initProc( HWND dlg, UINT msg, LPARAM lp )
   361  {
   362  	if( msg == PSCB_PRECREATE )
   363  	{
   364  		// スタイルを指すDWORDのアドレスを取得
   365  		DWORD* pst = ( 0xffff==((DLGTEMPLATEEX*)lp)->signature ) ? 
   366  						&(((DLGTEMPLATEEX*)lp)->style) : &(((DLGTEMPLATE*)lp)->style);
   367  		// ヘルプボタンを消して最小化ボタンを付ける
   368  		(*pst) &= ~DS_CONTEXTHELP;
   369  		(*pst) |=  WS_MINIMIZEBOX;
   370  
   371  		preCreate( st_CurInitPS );
   372      }
   373  	else if( msg == PSCB_INITIALIZED )
   374  	{
   375  		// 何故か出来てしまう余計なメニューを削除
   376  		HMENU sysm = ::GetSystemMenu( dlg, FALSE );
   377  		::DeleteMenu( sysm, SC_SIZE, MF_BYCOMMAND );
   378  		::DeleteMenu( sysm, SC_MAXIMIZE, MF_BYCOMMAND );
   379  
   380  		// 起動時はウインドウを必ず前面へ
   381  		setFront( dlg );
   382  
   383  		//サブクラス化する
   384  		st_CurInitPS->m_DefProc = (WNDPROC)::SetWindowLong( dlg, GWL_WNDPROC, (LONG)main_cmmnProc );
   385  		st_CurInitPS->onInit();
   386  	}
   387  	return 0;
   388  }
   389  
   390  BOOL kiPropSheet::page_cmmnProc( HWND dlg, UINT msg, WPARAM wp, LPARAM lp )
   391  {
   392  	kiPropSheetPage* ptr = (kiPropSheetPage*)::GetWindowLong( dlg, GWL_USERDATA );
   393  	if( !ptr )
   394  		return FALSE;
   395  
   396  	// ここで、共通処理
   397  	switch( msg )
   398  	{
   399  	case WM_INITDIALOG:
   400  		return ptr->onInit();
   401  
   402  	case WM_NOTIFY:
   403  		switch( ((NMHDR*)lp)->code )
   404  		{
   405  		case PSN_APPLY:
   406  			ptr->onOK();
   407  			return TRUE;
   408  		}
   409  		break;
   410  
   411  	case WM_COMMAND:
   412  		if( lp )
   413  			switch( HIWORD(wp) )
   414  			{
   415  			case BN_CLICKED:
   416  			if((HWND)lp==::GetFocus())
   417  			case EN_CHANGE:
   418  			case CBN_SELCHANGE:
   419  				PropSheet_Changed( ptr->parent()->hwnd(), dlg );
   420  			}
   421  		break;
   422  
   423  	case WM_DESTROY:
   424  		BOOL ans=ptr->proc( msg, wp, lp );
   425  		ptr->detachHwnd();
   426  		return ans;
   427  	}
   428  
   429  	return ptr->proc( msg, wp, lp );
   430  }
   431  
   432  UINT CALLBACK kiPropSheet::page_initProc( HWND dlg, UINT msg, LPPROPSHEETPAGE ppsp )
   433  {
   434  	if( msg == PSPCB_CREATE )
   435  		preCreate( (kiWindow*)(ppsp->lParam) );
   436  	return TRUE;
   437  }
   438  
   439  void kiPropSheetPage::setInfo( PROPSHEETPAGE* p )
   440  {
   441  	p->pszTemplate = MAKEINTRESOURCE( getRsrcID() );
   442  	p->lParam      = (LPARAM)this;
   443  
   444  	if( m_hIcon )
   445  	{
   446  		p->dwFlags|= PSP_USEHICON;
   447  		p->hIcon = m_hIcon;
   448  	}
   449  }
   450