こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

VC++2008 で クリップボードの監視を行いたい

いつもおせわになっております。

ただいま、Visual C++ 2008 Express Edition を使いまして、クリップボード拡張アプリを作っております。

実装したい機能として・・・
 A.クリップボードにデータがコピーされる度に、クリップボードのデータを取得する。
 B.ただし、クリップボード上のデータは消さない。

というものがあります。

この使用を実装するために、下記のようにデータ存在の有無をタイマーな
どでポーリングすれば良いと考えました。

>IDataObject^data = System::Windows::Forms::Clipboard::GetDataObject();
>pictureShowPicture->Image->Dispose();
>if(data->GetDataPresent(DataFormats::Bitmap) == true){

しかし、この方法だと、一回でもデータがクリップボードにコピーされると、その後もずっと「データが存在する」状態となってしまい、新しいデータが来たのかどうか判断が出来ません。
クリップボード上のデータを消せば、「データが存在しない」状態となり、次にデータがコピーされたことが分かるのですが、クリップボード上のデータは消さない実装としたいのです。


このため、下記のようにすれば問題が解決できると思いました。
 1.何らかの方法でクリップボードにデータがコピーされたという通知を受け取る。
 2.現在のデータが直前のデータと同じか異なるかを判断する。
   (ポーリングしておいて、データが異なれば新規データと判断)

上記1,2について、実現方法をご存知の方は教えていただけませんでしょうか。

ちなみに、受け取りたいデータ形式は、ビットマップ形式画像およびテキスト形式です。

お忙しいところ恐縮ですが、よろしくお願いいたします。

投稿日時 - 2009-05-18 19:13:50

QNo.4969883

困ってます

質問者が選んだベストアンサー

 こんばんは。

 win32APIを呼び出して良ければ、こういった手段があります。
 http://wisdom.sakura.ne.jp/system/winapi/win32/win92.html

 以下は、クリップボードが変更される度に、メッセージボックスを出します。参考程度に。

//メンバ変数
private: HWND m_hWndNext;

//自分をクリップボードビューワに登録
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e)
{
this->m_hWndNext = ::SetClipboardViewer(static_cast<HWND>(this->Handle.ToPointer()));
}

//自分をクリップボードビューワから解除
private: System::Void Form1_FormClosed(System::Object^ sender, System::Windows::Forms::FormClosedEventArgs^ e)
{
::ChangeClipboardChain(static_cast<HWND>(this->Handle.ToPointer()), this->m_hWndNext);
}

//ウィンドウプロシージャのオーバーライド
public: virtual System::Void WndProc(System::Windows::Forms::Message% m) override
{
switch(m.Msg)
{
//クリップボードが更新されると此処に飛び込んでくる
case WM_DRAWCLIPBOARD:
{
//クリップボードを開く
::OpenClipboard(static_cast<HWND>(this->Handle.ToPointer()));

//クリップボードフォーマットを総当りで調べて、何か見つかれば直に中断
HANDLE hClipboard = NULL;
for(UINT uFormat = ::EnumClipboardFormats(0); uFormat != 0; uFormat = ::EnumClipboardFormats(uFormat))
{
hClipboard = ::GetClipboardData(uFormat);
//クリップボード内にデータを発見
if(hClipboard)break;
}

//クリップボードを閉じる
::CloseClipboard();

if(hClipboard != NULL)
System::Windows::Forms::MessageBox::Show("クリップボードにデータが来ました");

::SendMessage(this->m_hWndNext, m.Msg, m.WParam.ToInt32(), m.LParam.ToInt32());
}
break;

case WM_CHANGECBCHAIN:
if(this->m_hWndNext == static_cast<HWND>(m.WParam.ToPointer()))
this->m_hWndNext = static_cast<HWND>(m.LParam.ToPointer());
else if(this->m_hWndNext != NULL)
::SendMessage(this->m_hWndNext, m.Msg, m.WParam.ToInt32(), m.LParam.ToInt32());
break;
}
this->Form::WndProc(m);
}

投稿日時 - 2009-05-18 21:16:33

補足

ご回答ありがとうございます。

さっそくやってみました。
結果は・・・・いちおう思っていたことが実現できました。
ありがとうございます。

若干、コードを変えたりしたので、その部分も含めて書いて置きます。

***stdafx.h
#include <windows.h>
#pragma comment(lib, "user32.lib")
//このライブラリを使うように指示。これがないとリンクしてくれない。

***Form1.h
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {

//クリップボードビュワーに登録。
this->m_hWndNext = ::SetClipboardViewer(static_cast<HWND>(this->Handle.ToPointer()));
}

public: virtualSystem::Void WndProc(System::Windows::Forms::Message% m) override
{
System::Windows::Forms::IDataObject^data = System::Windows::Forms::Clipboard::GetDataObject();

this->Form::WndProc(m); //ここにおかないとエラーになる。なぜだろう???

switch(m.Msg)
{
case WM_DRAWCLIPBOARD:
if(data->GetDataPresent(DataFormats::Bitmap) == true)
{
textHashCode->Text = data->GetHashCode().ToString();
pictureShowPicture->Image = (Image^)data->GetData(DataFormats::Bitmap);
//フォルダの最後の文字を "\" にする。
if( textFolderDestination->Text[textFolderDestination->Text->Length - 1] != '\\'){
textFolderDestination->Text = textFolderDestination->Text + "\\";
}
}

pictureShowPicture->Image->Save(textFolderDestination->Text + textHashCode->Text + ".jpg");

::SendMessage(this->m_hWndNext, m.Msg, m.WParam.ToInt32(), m.LParam.ToInt32());
break;

case WM_CHANGECBCHAIN:

if(this->m_hWndNext == static_cast<HWND>(m.WParam.ToPointer())){

this->m_hWndNext = static_cast<HWND>(m.LParam.ToPointer());
}
else if(this->m_hWndNext != NULL){
::SendMessage(this->m_hWndNext, m.Msg, m.WParam.ToInt32(), m.LParam.ToInt32());
}
break;




}
}

投稿日時 - 2009-05-18 23:55:32

お礼

早速のご回答ありがとうございます。
さっそくやってみます。

投稿日時 - 2009-05-18 23:06:16

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(1)