« ごみ箱から指定のファイルを「元に戻す」方法 | トップページ | 専門語辞書参照サービス »

2005年1月28日 (金)

元に戻す

元に戻すを実装しようとして四苦八苦。
元に戻すはごみ箱からの復元だけでなく、コピーや移動の処理も取り消せる。
ということは結果的にIDragDropやMoveFileExを利用する方法は使えず、IContextMenuを利用して元に戻すを実行するしかないと考えて組んでみたものの。
以下のようなコードを実行したけれど元に戻すのメニューは取得できなかった。


int __stdcall	WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
	IMalloc*	pMalloc;
	TB_ENFORCE( NotEqualFail( S_OK ), CoGetMalloc( 1, &pMalloc ) );
	LPITEMIDLIST	pIdList;
	TB_ENFORCE( NotEqualFail( S_OK ), SHGetFolderLocation( NULL, CSIDL_DESKTOP, NULL, NULL, &pIdList ) );

	IShellFolder*	pDesktop;
	TB_ENFORCE( NotEqualFail( NOERROR ), SHGetDesktopFolder( &pDesktop ) );
	// IContextMenuを取得します。
	// m_pDFolderはデスクトップフォルダを示すIShellFolderです。
	IContextMenu*	pContextMenu;
	TB_ENFORCE( NotEqualFail( S_OK ), pDesktop->GetUIObjectOf( NULL, 1, (LPCITEMIDLIST*)(&pIdList), IID_IContextMenu, 0, reinterpret_cast< void ** >( &pContextMenu ) ) );

	HMENU	hMenu = TB_ENFORCE( API< HMENU >( NULL ), ::CreatePopupMenu() );

	// メニューを取得します。
	HRESULT	re = pContextMenu->QueryContextMenu( hMenu, 0, 1, 0xffff, CMF_NORMAL );
	Uint	itemIndex = UINT_MAX;
	//
	TB_LOOP_1( GetMenuItemCount( hMenu ) )
	{
		StringReceiver	receiver;
		if( 0 != GetMenuString( hMenu, index, receiver.Lock( 255 ), 254, MF_BYPOSITION ) )
		{
			//文字列が取得できた。
			if( std::string::npos != receiver.UnLock().find("元に戻す") )
			{
				itemIndex = index;
				break;
			}
		}
	}

	if( UINT_MAX == itemIndex )
	{
		//「元に戻す」がない==削除や移動をしていなくて元に戻すファイルがない。
		return 0L;
	}

	// コマンドを実行します。
	CMINVOKECOMMANDINFO	invokeInfo = { sizeof( CMINVOKECOMMANDINFO ) };
	invokeInfo.fMask = 0;
	invokeInfo.hwnd = NULL;
	invokeInfo.lpVerb = MAKEINTRESOURCE( itemIndex );//MAKEINTRESOURCE( iCommand - 1 );
	invokeInfo.lpParameters = NULL;
	invokeInfo.lpDirectory = NULL;
	invokeInfo.nShow = SW_SHOWNORMAL;
	invokeInfo.dwHotKey = 0;
	invokeInfo.hIcon = NULL;

	TB_ENFORCE( NotEqualFail( NOERROR ), pContextMenu->InvokeCommand( &invokeInfo ) );

	window.Wait();
	pContextMenu->Release();
	pDesktop->Release();
	pMalloc->Free( pIdList );
	pMalloc->Release();

	return 0L;
}


エクスプローラー(&X)とかは取れるんだけどなぁ。
フォルダの拡張メニューはIShellFolderからGetUIObjectOfしたのではだめなのかもしれない。


上の記事の後に前進があったのでメモ

・CoInitializeとCoUninitializeを忘れてた。追加したら突如としてQueryContextMenuが以前より多い数のメニューを登録してきた。
謎。エラーになってるなら最初からエラー終了してほしい。

・フォルダのコンテキストメニューは無事取得成功。
したのはいいんだけど冷静になって考えると「元に戻す」があるのはフォルダの右クリックメニューではなくて、エクスプローラーの右ペインの何も無いところを右クリックしたときに出てくるメニュー。
これをとるためにIShellViewをとって、それのGetItemObjectを使った。
無事コンテキストメニューが取れた…のだが。

ない。狙ったように元に戻すの項目だけメニューに追加されてこない。
QueryContextMenuのパラメーターをいろいろといじるものの二進も三進も行かず。
IContextMenuでInvokeCommandすればいいなんて言い出したのは誰なんだ…。教えてほしい(^^;
とりあえずいったんあきらめた次第。

・IShellViewのメソッドをにらむにTranslateAcceleratorというのがある。これでCTRL+Zを送ってやろうかと思ったものの失敗。
MSG構造体を偽造するのは難しい。

int __stdcall	WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
	CoInitialize( NULL );

	IMalloc*	pMalloc;
	TB_ENFORCE( NotEqualFail( S_OK ), CoGetMalloc( 1, &pMalloc ) );
	LPITEMIDLIST	pIdList;
	TB_ENFORCE( NotEqualFail( S_OK ), SHGetFolderLocation( NULL, CSIDL_DESKTOPDIRECTORY, NULL, NULL, &pIdList ) );

	IShellFolder*	pDesktop;
	TB_ENFORCE( NotEqualFail( NOERROR ), SHGetDesktopFolder( &pDesktop ) );

	// IContextMenuを取得します。
	IContextMenu*	pContextMenu;
	IShellView*		pView;
	TB_ENFORCE( NotEqualFail( S_OK ), pDesktop->CreateViewObject( NULL, IID_IShellView, reinterpret_cast< void ** >( &pView ) ) );
	TB_ENFORCE( NotEqualFail( S_OK ), pView->GetItemObject( SVGIO_BACKGROUND, IID_IContextMenu, reinterpret_cast< void ** >( &pContextMenu ) ) );

	// IContextMenu2へQueryInterface
	IContextMenu3*	pContextMenu2;
	TB_ENFORCE( NotEqualFail( S_OK ), pContextMenu->QueryInterface( IID_IContextMenu3, reinterpret_cast< void ** >( &pContextMenu2 ) ) );
	pContextMenu->Release();

	HMENU	hMenu = TB_ENFORCE( API< HMENU >( NULL ), ::CreatePopupMenu() );

	// メニューを取得します。
	HRESULT	re = pContextMenu2->QueryContextMenu( hMenu, 0, 1, 0xffff, CMF_NODEFAULT );
	Uint	itemIndex = UINT_MAX;
	//
	TB_LOOP_1( GetMenuItemCount( hMenu ) )
	{
		StringReceiver	receiver;
		if( 0 != GetMenuString( hMenu, index, receiver.Lock( 255 ), 254, MF_BYPOSITION ) )
		{
			//文字列が取得できた。
			if( std::string::npos != receiver.UnLock().find("元に戻す") )
			{
				itemIndex = index;
				break;
			}
		}
	}

	if( UINT_MAX == itemIndex )
	{
		//「元に戻す」がない==削除や移動をしていなくて元に戻すファイルがない。
		return 0L;
	}

	// コマンドを実行します。
	CMINVOKECOMMANDINFO	invokeInfo = { sizeof( CMINVOKECOMMANDINFO ) };
	invokeInfo.fMask = 0;
	invokeInfo.hwnd = NULL;
	invokeInfo.lpVerb = MAKEINTRESOURCE( 7 );//itemIndex );//MAKEINTRESOURCE( iCommand - 1 );
	invokeInfo.lpParameters = NULL;
	invokeInfo.lpDirectory = NULL;
	invokeInfo.nShow = SW_SHOWNORMAL;
	invokeInfo.dwHotKey = 0;
	invokeInfo.hIcon = NULL;

	TB_ENFORCE( NotEqualFail( NOERROR ), pContextMenu2->InvokeCommand( &invokeInfo ) );

	pContextMenu2->Release();
	pDesktop->Release();
	pMalloc->Free( pIdList );
	pMalloc->Release();

	CoUninitialize();

	return 0L;
}

|

« ごみ箱から指定のファイルを「元に戻す」方法 | トップページ | 専門語辞書参照サービス »

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



« ごみ箱から指定のファイルを「元に戻す」方法 | トップページ | 専門語辞書参照サービス »