- PR -

Clipboardの監視はできない?

投稿者投稿内容
けい
常連さん
会議室デビュー日: 2001/09/12
投稿数: 48
投稿日時: 2001-09-12 21:45
はじめまして、横浜市在住のけいと申します。
私も、WebServiceを使って何か作ってみたくなり、
「クリップボードにコピーした単語をICD WebServiceで自動的に検索して表示」
ってのに挑戦してみました。
で、WebServiceへのアクセスはいとも簡単にできてしまったのですが、
クリップボードの監視って簡単にする方法はないものでしょうか?

今のところ、Timerをおいて、100ミリ秒ごとにチェックするという方法を見つけたのですが、
もう少しスマートに出来そうな気が(^^;
Kiwamu
会議室デビュー日: 2001/07/27
投稿数: 5
投稿日時: 2001-09-12 22:43
 うろ覚えで恐縮なんですが、Windowsでは、クリップボードの内容が変化したときに、メッセージを受け取れるようにできたと思います。これはC#では使えないということでしょうか?

 100ミリ秒ごとにポーリングってのは、重くないですか?
autumn
大ベテラン
会議室デビュー日: 2001/07/27
投稿数: 215
投稿日時: 2001-09-13 16:07
確かにクリップボードのクラスを見ると、クリップボードの変化を通知する手段は無いように見えますね。
思想なのか、実装の都合なのか、時間の都合なのかは分かりませんが。
機会があれば真意を聞いてみたいような気もします。
当面は、ポーリングするしかないかもしれませんね。
(でなければunsafeな世界に行くか)

_________________
けい
常連さん
会議室デビュー日: 2001/09/12
投稿数: 48
投稿日時: 2001-09-13 23:20
> Windowsでは、クリップボードの内容が変化したときに、メッセージを受け取れるようにできたと思います。
SetClipboardViewerですね。できれば、unsafeコードは書きたくないもので...

> 当面は、ポーリングするしかないかもしれませんね。
そうですね。
100ミリ秒毎のポーリングでも思ったほど重くもなく、
レスポンスも気になるほどでもないので、
とりあえずこれで実装してみました。今のところ快適に動いてます。
NothingBut.NETFX
大ベテラン
会議室デビュー日: 2001/09/13
投稿数: 102
投稿日時: 2001-09-14 10:34
>SetClipboardViewerですね。できれば、unsafeコードは書きたくないもので...

Win32API(user32.dll)の呼び出しは、unmanagedコードを呼び出すということであってunsafeコードを書くということではありません。
現状、C#はunsafeコードが書けますが、VB .NETではunsafeコードは書けません。しかし、VB .NETはWin32APIをP/Invokeで呼び出すことができます。つまり、P/Invokeはunsafeではない(safeである)ということです。

ちなみに、C#でClipboardViewer実装してみました。興味のある人が読んでるかも
しれないので、載せてみます。
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

class GoshItsReallyFun : Form {
public TextBox Text1 = new TextBox();
public Label Label1 = new Label();
private IntPtr NextHandle;
private const int WM_DRAWCLIPBOARD = 0x0308;
private const int WM_CHANGECBCHAIN = 0x030D;

[DllImport("user32")]
public static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);
[DllImport("user32", CharSet=CharSet.Auto)]
public extern static int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

[STAThread]
static void Main() {
Application.Run(new GoshItsReallyFun());
}

public GoshItsReallyFun() {
this.Text = "My first Windows app!";
Label1.Location = new Point(0, 0);
Label1.Size = new Size(100, 100);
Label1.Text = "Label!";
this.Controls.Add(Label1);
Text1.Location = new Point(100, 0);
Text1.Size = new Size(100, 100);
Text1.Text = "TextBox!";
this.Controls.Add(Text1);
NextHandle = SetClipboardViewer(this.Handle);
}

protected override void WndProc(ref Message msg) {
switch (msg.Msg) {
case WM_DRAWCLIPBOARD:
Text1.Text = (string)Clipboard.GetDataObject().GetData(DataFormats.Text);
if((int)NextHandle != 0)
SendMessage(NextHandle, msg.Msg, msg.WParam, msg.LParam);
break;
case WM_CHANGECBCHAIN:
NextHandle = (IntPtr)msg.LParam;
if((int)NextHandle != 0)
SendMessage(NextHandle, msg.Msg, msg.WParam, msg.LParam);
break;
}
base.WndProc(ref msg);
}
}
Kiwamu
会議室デビュー日: 2001/07/27
投稿数: 5
投稿日時: 2001-09-14 11:03
 少々脱線しますが、「unmanage code」はCLR(Common Language Runtime)ではないネイティブなWin32 APIなどを呼び出すコードのことですよね。「unsafe」とはどのようなコードを指すのでしょうか?
NothingBut.NETFX
大ベテラン
会議室デビュー日: 2001/09/13
投稿数: 102
投稿日時: 2001-09-14 12:34
>「unmanage code」はCLR(Common Language Runtime)ではない
>ネイティブなWin32 APIなどを呼び出すコードのことですよね。

違います。user32.dllのように、CLR上で実行されないコードのことをunmanagedコードと
呼びます。「呼び出すコード」ではありません。「呼び出されているコード」のほうが
unmanagedコードです。
.NET Frameworkと同時にマイクロソフトが提供している言語の中で、unmanagedコードが書けるのは、C++だけです。

>「unsafe」とはどのようなコードを指すのでしょうか?

CLRがタイプセーフティをべリファイできない(<何語?)コードのことをunsafeコードと言います。unmanagedコードは、CLRで動作しない以上、暗黙のうちにunsafeです。あたりまえですが。C#では以下のコードはunsafeです。

using System;

class VBCantDoThis {
static void Main() {
int[] ArrayOfInt = new int[10];
for (int i = 0; i < 10; i++)
ArrayOfInt[i] = i;
Console.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}",
ArrayOfInt[0],ArrayOfInt[1],ArrayOfInt[2],ArrayOfInt[3],
ArrayOfInt[4],ArrayOfInt[5],ArrayOfInt[6],ArrayOfInt[7],
ArrayOfInt[8],ArrayOfInt[9]);
Modify(ref ArrayOfInt);
Console.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}",
ArrayOfInt[0],ArrayOfInt[1],ArrayOfInt[2],ArrayOfInt[3],
ArrayOfInt[4],ArrayOfInt[5],ArrayOfInt[6],ArrayOfInt[7],
ArrayOfInt[8],ArrayOfInt[9]);
}
unsafe static void Modify(ref int[] ArrayOfInt) {
fixed(int* PointerToArrayOfInt = ArrayOfInt) {
int* p = PointerToArrayOfInt;
for (int i = 0; i < 10; i++) {
*p = *p * 2;
p++;
}
}
}
}


Mainメソッドのループの境界値を11にすると、IndexOutOfBoundsExceptionが
発生しますが、Modifyメソッドのループの境界値を11にしても例外は発生しません。これは配列の要素数が10だという、もとのタイプの情報を利用できないからです。タイプセーフティをべリファイできないわけです。
けい
常連さん
会議室デビュー日: 2001/09/12
投稿数: 48
投稿日時: 2001-09-14 19:34
> Win32API(user32.dll)の呼び出しは、unmanagedコードを呼び出すということであってunsafeコードを書くということではありません。
なるほど、Win32APIの呼び出しをそれほど嫌がることはないのですね。

> C#でClipboardViewer実装してみました。
ありがとうございます。早速参考にして組んでみたいと思います。

> [DllImport("user32")]
Win32APIの呼び出しってそんなに簡単だったのですね。知りませんでした(^^;

ところで、
case WM_CHANGECBCHAIN:
のなかは、
if((HWND)wParam == NextHandle) {
NextHandle = (IntPtr)msg.LParam;
} else if((int)NextHandle != 0) {
SendMessage(NextHandle, msg.Msg, msg.WParam, msg.LParam);
}
ですよね。あと、終了時に自分をチェインからはずすための、
ChangeClipboardChain
も必要ですね。

スキルアップ/キャリアアップ(JOB@IT)