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

ただいま、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について、実現方法をご存知の方は教えていただけませんでしょうか。

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

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

このQ&Aに関連する最新のQ&A

A 回答 (1件)

 こんばんは。



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

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

//メンバ変数
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);
}

この回答への補足

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

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

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

***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
    • good
    • 0
この回答へのお礼

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

お礼日時:2009/05/18 23:06

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qクリップボードの不要な登録内容を一括削除するには

クリップボードは使いやすいのですがコピーする度に次々と登録されてしまうのでややそこが---そこで登録語句の削除ですが一つ一つは面倒です。不要な登録内容を一括削除する方法はありますか ご指導ください

Aベストアンサー

通知領域にあるCliborのアイコンを右クリック。
表示されたメニューの上部にある[履歴を全てクリア]を選択すれば、登録
されている履歴がすべて消えます。

その少し下にある[クリップボード履歴の複数選択]を選択すれば、個々に
選択もできますし、エクスプローラーのように[ Ctrl ]キーなどで範囲を
選択することもできます。不要な履歴を選択して[削除]ボタンを押せば、
必要なものだけを残すことができます。

Qクリップボードへのコピー

あるHPのコードを参考に文字をクリップボードへ
コピーするコードを書いてみましたが、エラーが
できます。なにかおかしいかご指摘いただけないでしょうか?

HGLOBAL hText;
wchar_t *pText;
hText = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 4);
pText = (wchar_t*)GlobalLock(hText);
lstrcpy(pText, L"abc");
GlobalUnlock(hText);
OpenClipboard(NULL);
EmptyClipboard();
SetClipboardData(CF_TEXT, hText);//ここでヒープが壊れていると起こられます。
CloseClipboard();

もっとも単純なテストコードです。
いろいろとチェックを手抜きしてますが、とりあえずOKとします。

Aベストアンサー

GlobalAllocで割り当てサイズとして「4」を指定していますが、これは「4バイト」を意味します。

ところが、lstrcpyでコピーしているL"abc"は4文字=8バイトを占有するので、確保したメモリの量を超えてメモリを書き換え(=破壊)してしまっています。

これが原因ではないでしょうか。

Qクリップボードに保存された画像を削除したい

PC初心者です。
Windowsの機能でPrintScreenキーで画面を撮影できると聞いて
1枚ためしに撮ってみたはいいものの、クリップボードに保存された
画像はファイルとして残らないとのことで、どうやったら削除できる
のかわかりません、教えてください!
それと、この機能では複数枚撮影することは出来ないのでしょうか?

初心者のため非常に困っています。宜しくお願いします!

Aベストアンサー

Windowsの機能ではクリップボードには一つしか保存されないので、また何かをコピーすれば古いのは消えます。
複数残したいのであれば、なんらかのユーティリティソフトを利用することになると思います。
クリップボードの機能を拡張するものもありますし、画面のキャプチャーをするソフトもあります。

画像に対応したクリップボード拡張ソフトの一例
http://www.vector.co.jp/vpack/browse/pickup/pw6/pw006121.html

キャプチャーソフトの一例
http://www.vector.co.jp/vpack/browse/pickup/pw5/pw005151.html

Qテキストファイルの一列目から順にクリップボードにコピー

初歩的な質問でしたらすいません。

現在スクリプトの勉強をしているのですが、

あらかじめテキストファイル(.txt)に単語を一行ずつ入力しておき、
そのファイルの一行目から順にクリップボードに単語をコピーしていくスクリプトを作りたいと思っています。

どなたか作り方もしくはヒントを下さい。

Aベストアンサー

>現在スクリプトの勉強をしているのですが

Java Scriptでしょうか?
VB Scriptでしょうか?

いずれにしても、質問される場所が違うと思うのですが...

Qクリップボードの削除処理のエラーについて

クリップボードの削除ですが、検索すると、ファイル名を実行して行なうことが記載されており、
実際に行なったところ下記のメッセージが出て、処理ができません

どのようにしたらよいのでしょうか

メッセージ
 Clip Book
  「サービスは使用できないか、または開始されていません。システム管理者にこのサービスの
   開始を依頼してください。」

   職場で使用しているパソコンです。 Win Xp Sp3 Excel2003 です。

Aベストアンサー

ファイル名を指定して実行>「clipbrd」と入力>編集>削除 で削除エラーがでるのですか?

WinXPのクリップボードビューアはどこへ行った?
http://trendy.nikkeibp.co.jp/article/tec/winxp/20030520/104699/

QC#で画像をクリップボードへのコピーと貼り付けについて

GraphicsオブジェクトのDrawImageメソッドを使って画像を表示させています。
この画像をクリップボードへコピーしてほかのところに貼り付けしたいのですが、クリップボードへはClipboard.SetDataObject()を使用すればよいと思っています。
しかし、どのように使ったらいいのかよくわかりません。現在のソースは以下のようになっています。
//Bitmapオブジェクトの作成(画像ファイルを読み込む)
Bitmap bmap = new Bitmap(@"C:\test2.bmp");
//元の画像からの切り取り範囲の指定
RectangleF rectSrc = new RectangleF                 (pointX,pointY,WidthX,WidthY);
//貼り付け先を指定範囲の指定
RectangleF rectDst =
new RectangleF(0, 0, DstX,DstY);
//PictureBox1のGraphicsオブジェクトの作成
Graphics g= pictureBox1.CreateGraphics();
//画像の描画
g.DrawImage(bmap, rectDst,rectSrc,GraphicsUnit.Pixel);
//クリップボードへのコピー
Clipboard.SetDataObject(g);
よろしくおねがいいたします。

GraphicsオブジェクトのDrawImageメソッドを使って画像を表示させています。
この画像をクリップボードへコピーしてほかのところに貼り付けしたいのですが、クリップボードへはClipboard.SetDataObject()を使用すればよいと思っています。
しかし、どのように使ったらいいのかよくわかりません。現在のソースは以下のようになっています。
//Bitmapオブジェクトの作成(画像ファイルを読み込む)
Bitmap bmap = new Bitmap(@"C:\test2.bmp");
//元の画像からの切り取り範囲の指定
RectangleF rectSrc = ...続きを読む

Aベストアンサー

Bitmap bmp = new Bitmap("C:\\test2.bmp");

RectangleF rectDst =
new RectangleF(0, 0, bmp.Width ,bmp.Height);

Clipboard.SetDataObject(
bmp.Clone(rectDst, bmp.PixelFormat) , true);

// Clipboard.SetDataObject(bmp,true);

QMac:クリップボードのデータを削除したい

PowerMacG4で、OS9.2でフォトショップ7.0とイラレ8.0を使っています。
画像をコピペなどの操作をしたあとで、他のアプリケーションを使うときに「クリップボードを何とか何とかに変換しています…」的なメッセージが出てしばらく待っていないといけないことがあります。
急いでいるときにそれが起こるとイライラしてしまいます。
だからそういうときはなるべく軽いテキストなどをコピーしてから他のアプリに移ったりしているのですが、そんなめんどくさいことをしなくてもクリップボードのデータをパッと消す方法ってありますか?

Aベストアンサー

Photoshopは、編集>メモリをクリア>クリップボード
で消去できますが、Illustratorはわかりません。

他にたとえばこんなのもあります。
http://www.vector.co.jp/soft/mac/util/se097729.html
http://www.vector.co.jp/soft/mac/util/se245230.html

QC++/CLIを用いて画像をクリップボードにコピー

VC++でC++/CLIでアプリケーションを作成しています。
そこで,pictureBox1の画像を,クリップボードにコピーしたいのですが,方法が分からず困っています。
Clipboard::SetDataObject();
の () の中に何を渡せばいいのでしょうか?

Aベストアンサー

まず最初に訂正です。

Clipboard::SetData("Bitmap",this->pictureBox1->Image);

でも良いのですが、

Clipboard::SetDataObject( this->pictureBox1->Image );

でも良かったみたいです。


で、pictureBox1(グラフを描画した方)のイメージを貼り付けできない理由ですが、

Graphics ^g = this->pictureBox1->CreateGraphics();

を使用して描画した内容は pictureBox1->Image には反映されないので、pictureBox1->Image が空になっているためだと思います。
これについては

http://dobon.net/vb/dotnet/graphics/pictureboximageanddrawimage.html

なんかが参考になると思います。

上のリンク先では

・PictureBoxのImageプロパティを一切使用しない。
・PictureBoxのGraphicsオブジェクト(PictureBox.PaintイベントとPictureBox.CreateGraphicsメソッド)を一切使用しない。

のどちらかにしなければならない、ということが書かれていますが、それは .NET に限った話であって、API を使用すれば問題ありません。
次のようにするとの内容

Graphics ^g = this->pictureBox1->CreateGraphics();

を使用して描画した内容もクリップボードにコピーすることができます。

// stdafx.h
#include <windows.h>
#pragma comment( lib, "user32.lib" )
#pragma comment( lib, "gdi32.lib" )

// フォームのコード
HWND hwnd = (HWND)pictureBox1->Handle.ToInt32();
HDC hdcSrc = GetDC( hwnd );
Bitmap ^bmp = gcnew Bitmap( pictureBox1->Width, pictureBox1->Height );
Graphics ^g = Graphics::FromImage( bmp );
HDC hdcDst = (HDC)g->GetHdc().ToInt32();
BitBlt( hdcDst, 0, 0, pictureBox1->Width, pictureBox1->Height, hdcSrc, 0, 0, SRCCOPY );
IntPtr p = IntPtr(hdcDst);
g->ReleaseHdc(p);
ReleaseDC( hwnd, hdcSrc );
Clipboard::SetDataObject( bmp );

IntPtr を HWND や HDC にキャストしようとするとエラーになってしまったので、ToInt32() を使用しています。が、64bit アプリケーションの場合は ToInt64 に変更する必要があると思います。

まず最初に訂正です。

Clipboard::SetData("Bitmap",this->pictureBox1->Image);

でも良いのですが、

Clipboard::SetDataObject( this->pictureBox1->Image );

でも良かったみたいです。


で、pictureBox1(グラフを描画した方)のイメージを貼り付けできない理由ですが、

Graphics ^g = this->pictureBox1->CreateGraphics();

を使用して描画した内容は pictureBox1->Image には反映されないので、pictureBox1->Image が空になっているためだと思います。
これについては

http://dobon.net/vb/dotnet/gra...続きを読む

Qクリップボードの削除について

エクセルで「クリップボードを空にできません」のメッセージがでるので、
ファイル名を実行し、「clipbrd」と入力すると下記のメッセージが出でます。

どのようにしたらよいのでしょうか

一応、クリップブックが開き(データは残っていないみたいですが)
その上にメッセージが出ている感じです。


メッセージ
 Clip Book
  「サービスは使用できないか、または開始されていません。システム管理者にこのサービスの
   開始を依頼してください。」

   職場で使用しているパソコンです。 Win Xp Sp3 Excel2003 です。

 よろしくお願いいたします。

Aベストアンサー

まず、clipbrd.exeに関しては、
「サービスは使用できないか、または開始されていません。」というのは、Administration 権限で用いるものではないでしょうか。もともと、Officeのクリップボードと、Windowsのクリップボードは互換性はあっても、別の機能を使っています。Office は独自の設定になっています。

>Win Xp Sp3 Excel2003 です。

そこで、簡単な方法としては、編集--Office クリップボード--作業ウィンドウを出していただいて、[クリップボード]ウィンドウから、[すべてクリア]ボタンで、クリアすることは出来ないでしょうか。

もう一つは、
 ツール --オプション--[計算方法]-[計算方法]を[手動]にして、一旦、閉じます。

これで回避できない場合は、Windowsを再起動すれば、おそらく、この問題は改善されるはずです。

QSystem::Drawing::Color::XXXXを変数に代入可能?

連続で質問するのも申し訳ないのですが・・・

VS2005 C++ Expressを使ってWindowsフォームアプリケーションを作っています。(C++/CLI)

ボタンなどのフォームのプロパティに、色を指定するものがあると思いますが、例えばBackColorを白に変更したい場合、
this->button1->BackColor = System::Drawing::Color::White;
のように書けると思います。

この、「System::Drawing::Color::White」の部分を変数のようにして記述したいのですが、どのように宣言した型を使用すればよいのでしょうか?
例えば仮に「System::Drawing::Color::White」がString文字列であれば、
void func1(int choice){
String^ hoge;

  if(!choice){
    hoge = System::Drawing::Color::White;
  } else {
    hoge = System::Drawing::Color::Red;
  }
  this->button1->BackColor = hoge;
}
こんな風にすると、func1(0);と呼ばれるとボタンの背景が白くなり、0以外の引数だと赤くなると思います。
ですが、System::Drawing::Color::XXXはStringではないのでできません。

この場合、hogeをどのような形で定義すればいいのでしょうか?
あるいは別の方法がありますでしょうか?

よろしくお願いします。

連続で質問するのも申し訳ないのですが・・・

VS2005 C++ Expressを使ってWindowsフォームアプリケーションを作っています。(C++/CLI)

ボタンなどのフォームのプロパティに、色を指定するものがあると思いますが、例えばBackColorを白に変更したい場合、
this->button1->BackColor = System::Drawing::Color::White;
のように書けると思います。

この、「System::Drawing::Color::White」の部分を変数のようにして記述したいのですが、どのように宣言した型を使用すればよいのでしょうか?
例えば仮...続きを読む

Aベストアンサー

#1です。
すいません。
System::Drawing::Color^ hoge;
ではなく
System::Drawing::Color hoge;
でした。


void func1(int choice){
System::Drawing::Color hoge;
  if(!choice){
    hoge = System::Drawing::Color::White;
  } else {
    hoge = System::Drawing::Color::Red;
  }
  this->button1->BackColor = hoge;
}


人気Q&Aランキング