クリップボードを操作する

見出しを読んだ後、あなたはおそらく非常に驚くでしょう。

結局のところ、すべてが非常に単純なように思えます-Clipboardオブジェクトがあり、その静的メソッド(SetText / SetDataやGetText / GetDataなど)があり、幸福のために他に何が必要ですか?



ただし、実際には、テキストやビットマップイメージなどの基本的なオブジェクトのみをコピーまたは貼り付ける限り、すべてが単純です。 より複雑な構造で操作する必要がある場合はどうなりますか?



個人的には、最近「ハイパーリンク」をコピーする必要がありました。これをWord / Outlook /他のプログラムに簡単に挿入する必要があります。 さらに、受信側プログラム自体が挿入されたテキスト内のリンクを決定し、それを目的の形式に変換しないという事実に依存することなく したがって、ハイパーリンクの例に関する作業を検討します(他の形式のアクションのアルゴリズムも同様です)。



それで、どこから始めますか?



開始するには、これらのデータやその他のデータの形式を確認する必要があります。 調べる方法はいくつかありますが、最も明白な方法はおそらく小さなClipSpyユーティリティです。 目的のオブジェクトをどこからでもコピーして、クリップボードに作成される形式とその内容を決定します。



実験が示すように、TEXT、UNICODETEXT、およびHTML形式は通常、ハイパーリンク用に作成されます。 1番目と2番目には、ハイパーリンクのテキスト表現(ノートブックなどに挿入されるもの)が含まれます。 HTML形式は私たちにとって最も興味深いものです。これには、ハイパーリンクとしてターゲットプログラムに挿入されるHTMLフラグメントが含まれています。 次のようになります。

 バージョン:1.0
 StartHTML:XXXXXXXX
 EndHTML:YYYYYYYY
 StartFragment:ZZZZZZZZ
 EndFragment:TTTTTTTT
 <html ....
 <a href="http://some.site.com/target">一部のターゲット</a>
 ... </ html> 
XXXXXXXXはhtmlコンテンツの開始オフセット(実際には、ヘッダーの長さ)です。

YYYYYYYY-したがって、htmlコンテンツの最後のオフセット(実際には、コンテンツ全体の長さ)、

ZZZZZZZZおよびTTTTTTTT-ハイパーリンクを持つフラグメントの開始と終了。



さて、フォーマットを決定しました。 目的のコンテンツを作成することは技術的な問題です。 それまでは、目的のコンテンツを(いくつかの形式で)クリップボードに送信する方法を検討します。



Google(すべての人に愛されているアドバイザー)は、原則として、次のソリューションを提供します。

  void CopyLink(Uriターゲット、文字列タイトル)
 {
	 var htmlContent = MakeLink(ターゲット、タイトル);
	 var data = new DataObject();
	 data.SetData(DataFormats.Text、true、target.ToString());
	 data.SetData(DataFormats.Unicode、true、html_content);
	 data.SetData(DataFormats.Html、true、formatted_buffer);
	 Clipboard.SetDataObject(data、true);
 } 


そして、それが1つの「ではない」ものであれば、すべては問題ありません。そのようなソリューションでは、htmlコンテンツを設定するときにエンコードを制御することはできません。 そのため、たとえば、タイトルにロシア語のテキストが含まれるリンクが誤って挿入され、受信者プログラムの「クラッシュ」までのさまざまな興味深い効果につながります。



このメモでは、純粋に管理されたコードを記述するという考えは銅の流域で覆われていたため、WinAPIに頼らなければなりませんでした。 その結果、それほど美しくはありませんでしたが、非常に効率的でした。

  [DllImport( "user32.dll")]
 private static extern IntPtr SetClipboardData(uint uFormat、IntPtr hMem);
 [DllImport( "user32.dll")]
 private static extern bool OpenClipboard(IntPtr hWndNewOwner);
 [DllImport( "user32.dll")]
 private static extern bool EmptyClipboard();
 [DllImport( "user32.dll")]
 private static extern bool CloseClipboard();
 [DllImport( "user32.dll"、SetLastError = true)]
 private static extern uint RegisterClipboardFormat(文字列lpszFormat);

 void CopyLink(Uriターゲット、文字列タイトル)
 {
	 var htmlContent = MakeLink(target、title、Encoding.UTF8);

	 if(!OpenClipboard(IntPtr.Zero))
		新しい例外をスローします(「クリップボードを開けませんでした」)。
	 EmptyClipboard();
        
	 var pText = IntPtr.Zero;
	 var pHtml = IntPtr.Zero;
	試してみる
	 {
		 pText = Marshal.StringToHGlobalAnsi(target.ToString());
		 SetClipboardData(1 / * CF_TEXT * /、pText);  // TEXTおよびUNICODETEXTの場合

		 var bytes = Encoding.UTF8.GetBytes(htmlContent);
		 pHtml = Marshal.AllocHGlobal(bytes.Length);
		 Marshal.Copy(bytes、0、pHtml、bytes.Length);
		 SetClipboardData(RegisterClipboardFormat(DataFormats.Html)、pHtml);
	 }
	ついに 
	 {
		 CloseClipboard();
		 if(pText!= IntPtr.Zero)
			 Marshal.FreeHGlobal(pText);
		 if(pHtml!= IntPtr.Zero)
			 Marshal.FreeHGlobal(pHtml);
	 }
 } 


さて、画像を完成させるために、MakeLinkのソースコード:

 文字列MakeLink(Uriターゲット、文字列タイトル、エンコードエンコーディング)
 {
	 const int numberLengthWithCr = 11;
	 var htmlIntro = "<html> \ n <head> \ n <meta http-equiv = \" Content-Type \ "content = \" text / html; 文字セット= " 
		 + encoding.WebName + "\" /> \ n </ head> \ n <body> \ n <!-StartFragment-> ";
	 var htmlOutro = "<!-EndFragment-> \ n </ body> \ n </ html>";
	 var htmlLink = string.Format( "<a href=\"{0}\"> {1} </a>"、ターゲット、タイトル);

	 var startHtmlIndex = 57 + 4 * numberLengthWithCr;
	 var startFragmentIndex = startHtmlIndex + encoding.GetByteCount(htmlIntro);
	 var endFragmentIndex = startFragmentIndex + encoding.GetByteCount(htmlLink);
	 var endHtmlIndex = endFragmentIndex + encoding.GetByteCount(htmlOutro);

	 var buff = new StringBuilder();
	 buff.AppendFormat( "バージョン:1.0 \ n");
	 buff.AppendFormat( "StartHTML:{0:0000000000} \ n"、startHtmlIndex);
	 buff.AppendFormat( "EndHTML:{0:0000000000} \ n"、endHtmlIndex);
	 buff.AppendFormat( "StartFragment:{0:0000000000} \ n"、startFragmentIndex);
	 buff.AppendFormat( "EndFragment:{0:0000000000} \ n"、endFragmentIndex);
	 buff.Append(htmlIntro).Append(htmlLink).Append(htmlOutro);
	 return buff.ToString();
 } 




PSところで、質問は次のとおりです。オートフォーマットと手動の改行を無効にすることなく、通常のコードを書くことは可能ですか? そして、オートフォーマットで
 行間隔は単なるキラーです。
 </ habracut> 



All Articles