次の方法で共有


クリップボード操作

ウィンドウでは、データの切り取り、コピー、貼り付け時にクリップボードを使用する必要があります。 ウィンドウは、切り取りとコピーの操作のためにクリップボードにデータを配置し、貼り付け操作のためにクリップボードからデータを取得します。 次のセクションでは、これらの操作と関連する問題について説明します。

クリップボードにデータを配置したり、クリップボードからデータを取得したりするには、最初に OpenClipboard関数を使用してクリップボード開く必要があります。 一度にクリップボードを開くことができるウィンドウは 1 つだけです。 クリップボードが開いているウィンドウを調べるには、GetOpenClipboardWindow 関数を呼び出します。 完了したら、ウィンドウで CloseClipboard 関数を呼び出してクリップボードを閉じる必要があります。

このセクションでは、次のトピックについて説明します。

切り取りとコピーの操作

クリップボードに情報を配置するには、まず、EmptyClipboard関数を使用して、以前のクリップボードの内容を消去。 この関数は、WM_DESTROYCLIPBOARD メッセージを以前のクリップボード所有者に送信し、クリップボード上のデータに関連付けられているリソースを解放し、クリップボードを開いているウィンドウにクリップボードの所有権を割り当てます。 クリップボードを所有しているウィンドウを調べるには、GetClipboardOwner関数呼び出します。

クリップボードを空にすると、最もわかりやすいクリップボード形式から最もわかりやすい形式の順に、可能な限り多くのクリップボード形式でデータがクリップボードに配置されます。 各形式について、ウィンドウは setClipboardData関数呼び出し、形式識別子とグローバル メモリ ハンドルを指定します。 メモリ ハンドルには NULL を指定できます。これは、ウィンドウが要求時にデータをレンダリングすることを示します。 詳細については、「遅延レンダリング」を参照してください。

貼り付け操作

クリップボードから貼り付け情報を取得するには、最初に取得するクリップボードの形式がウィンドウによって決定されます。 通常、ウィンドウは、EnumClipboardFormats関数使用して使用可能なクリップボード形式を列挙し、認識する最初の形式を使用します。 このメソッドは、データがクリップボードに配置されたときに設定された優先順位に従って、使用可能な最適な形式を選択します。

または、ウィンドウで GetPriorityClipboardFormat関数使用することもできます。 この関数は、指定された優先順位に従って、使用可能な最適なクリップボード形式を識別します。 1 つのクリップボード形式のみを認識するウィンドウでは、IsClipboardFormatAvailable 関数を使用して、その形式を使用できるかどうかを判断できます。

使用するクリップボード形式を決定した後、ウィンドウは GetClipboardData関数を呼び出します。 この関数は、指定した形式のデータを含むグローバル メモリ オブジェクトにハンドルを返します。 ウィンドウでは、データを調べたりコピーしたりするために、メモリ オブジェクトを簡単にロックできます。 ただし、ウィンドウでオブジェクトを解放したり、長期間ロックしたままにしたりしないでください。

クリップボードの所有権

クリップボード所有者 は、クリップボードの情報に関連付けられているウィンドウです。 ウィンドウは、クリップボードにデータを配置するときにクリップボードの所有者になります。具体的には、EmptyClipboard 関数を呼び出すときです。 ウィンドウが閉じられるか、別のウィンドウがクリップボードを空にするまで、ウィンドウはクリップボードの所有者のままです。

クリップボードが空になると、クリップボードの所有者は WM_DESTROYCLIPBOARD メッセージを受け取ります。 ウィンドウでこのメッセージが処理される理由を次に示します。

  • 1 つ以上のクリップボード形式のウィンドウ遅延レンダリング。 WM_DESTROYCLIPBOARD メッセージに応答して、ウィンドウは、要求時にデータをレンダリングするために割り当てたリソースを解放する可能性があります。 データのレンダリングの詳細については、「遅延レンダリング」を参照してください。
  • ウィンドウは、プライベート クリップボード形式でクリップボードにデータを配置しました。 プライベート クリップボード形式のデータは、クリップボードが空になったときにシステムによって解放されません。 そのため、クリップボードの所有者は、WM_DESTROYCLIPBOARD メッセージを受信したときにデータを解放する必要があります。 プライベート クリップボード形式の詳細については、「クリップボード形式」を参照してください。
  • CF_OWNERDISPLAY クリップボード形式を使用して、ウィンドウがクリップボードにデータを配置しました。 WM_DESTROYCLIPBOARD メッセージに応答して、ウィンドウはクリップボード ビューアー ウィンドウに情報を表示するために使用したリソースを解放する可能性があります。 この代替形式の詳細については、「所有者表示形式の」を参照してください。

遅延レンダリング

クリップボード形式をクリップボードに配置すると、データが必要になるまで、ウィンドウでその形式のデータのレンダリングが遅れる可能性があります。 これを行うには、SetClipboardData 関数の hData パラメーター NULL を指定できます。 これは、アプリケーションが複数のクリップボード形式をサポートしている場合に便利です。その一部またはすべてがレンダリングに時間がかかる場合です。 NULL ハンドルを渡すことにより、ウィンドウは必要な場合にのみ複雑なクリップボード形式をレンダリングします。

ウィンドウがクリップボード形式のレンダリングを遅らせる場合は、クリップボードの所有者である限り、要求に応じて形式をレンダリングするように準備する必要があります。 システムは、レンダリングされていない特定の形式の要求を受信したときに、クリップボードの所有者に WM_RENDERFORMAT メッセージを送信します。 このメッセージを受信すると、ウィンドウは setClipboardData関数呼び出して、要求された形式でクリップボードにグローバル メモリ ハンドルを配置する必要があります。

WM_RENDERFORMAT メッセージに応答して SetClipboardData呼び出す前に、アプリケーションでクリップボードを開く必要があります。 クリップボードを開く必要はありません。また、形式のレンダリングを要求したアプリケーションがクリップボードを開いたままにしているため、この操作を試みると失敗します。

クリップボードの所有者が破棄されようとしていて、一部またはすべてのクリップボード形式のレンダリングが遅れている場合は、WM_RENDERALLFORMATS メッセージを受け取ります。 このメッセージを受け取ると、ウィンドウはクリップボードを開き、GetClipboardOwner 関数を持つクリップボードの所有者であることを確認し、提供されるすべてのクリップボード形式の有効なメモリ ハンドルをクリップボードに配置します。 これにより、クリップボードの所有者が破棄された後も、これらの形式を使用できます。

WM_RENDERFORMATとは異なり、WM_RENDERALLFORMATS に応答するアプリケーションは、SetClipboardData を呼び出してクリップボードにグローバル メモリ ハンドルを配置する前に、クリップボードを開く必要があります。

WM_RENDERALLFORMATS メッセージに応答してレンダリングされないクリップボード形式は、他のアプリケーションで使用できなくなり、クリップボード関数によって列挙されなくなります。

遅延レンダリング ガイダンス

遅延レンダリングはパフォーマンス機能であり、アプリケーションは、要求されない形式でクリップボード データをレンダリングする作業を回避できます。 ただし、遅延レンダリングを使用するには、次のトレードオフを考慮する必要があります。

  • 遅延レンダリングを使用すると、アプリケーションが複雑化し、前述のように 2 つのレンダリング ウィンドウ メッセージを処理する必要があります。
  • 遅延レンダリングを使用すると、データのレンダリングに十分な時間がかかるため、アプリケーションは UI の応答性を維持するオプションを失います。 遅延レンダリングでは、データが最終的に必要になった場合、前述のように、ウィンドウはレンダリング ウィンドウ メッセージの処理中にデータをレンダリングする必要があります。 その結果、データのレンダリングに非常に時間がかかる場合は、レンダリング ウィンドウ メッセージの処理中に他のウィンドウ メッセージを処理できないので、レンダリングの実行中にアプリケーションが目に見えて応答しなくなる (ハングする) 可能性があります。 遅延レンダリングを使用しないアプリケーションでは、代わりに、レンダリングの実行中に UI 応答を維持するために、バックグラウンド スレッドでデータをレンダリングすることを選択できます。たとえば、遅延レンダリングを使用する場合は使用できない進行状況またはキャンセル オプションを提供します。
  • 遅延レンダリングを使用すると、最終的にデータが必要になった場合、わずかなオーバーヘッドが発生します。 遅延レンダリングを使用する場合、ウィンドウは最初に SetClipboardData 関数を NULL ハンドルで呼び出します。データが後で必要な場合は、ウィンドウ メッセージに応答し、SetClipboardData 関数を 2 回目に呼び出し、レンダリングされたデータへのハンドルを使用する必要があります。 その結果、データが最終的に必要になった場合、遅延レンダリングを使用すると、ウィンドウ メッセージを処理し、SetClipboardData 関数を 2 回目に呼び出すコストが増えます。 このコストは小さいが、ゼロではない。 アプリケーションが 1 つのクリップボード形式のみをサポートし、データが常に要求される場合、遅延レンダリングを使用すると、このわずかなオーバーヘッドが追加されます (コストはハードウェアによって異なります。見積もりは 10 ~ 100 マイクロ秒です)。 ただし、データが小さい場合、遅延レンダリングを使用するオーバーヘッドがデータをレンダリングするコストを超える可能性があり、遅延レンダリングを使用してパフォーマンスを向上させる目的が低下する可能性があります。 (テストでは、既に最終形式のデータの場合、遅延レンダリングを使用するオーバーヘッドが、データが 100 KiB 以下の場合にデータをクリップボードにコピーするコストを一貫して超えました。このテストには、データをレンダリングするコストは含まれません。これは、レンダリング後にデータをコピーするためだけに含まれます)。
  • 遅延レンダリングは、オーバーヘッドを増やすよりも多くの時間を節約する場合、パフォーマンス上の利点となります。 遅延レンダリングのオーバーヘッドを判断するには、測定が最適ですが、10 ~ 100 マイクロ秒は見積もりです。 各クリップボード形式で遅延レンダリングを使用する場合の節約を計算するには、その形式でデータをレンダリングするコストを測定し、(上記のウィンドウ メッセージに基づいて) その形式が最終的に要求される頻度を決定します。 データをレンダリングするコストに、データが最終的に要求されない時間の割合 (クリップボードが空になるまで、またはその内容が変更される前) を乗算して、各クリップボード形式の遅延レンダリングの節約を決定します。 遅延レンダリングは、節約がオーバーヘッド コストを超える場合に、パフォーマンス上の利点となります。
  • 具体的なガイドラインとして、テキストなど、1 つのクリップボード形式のみをサポートするアプリケーションでは、データのサイズが 4 KiB 以下の場合は、データをクリップボードに直接配置することを検討してください。

メモリとクリップボード

クリップボードに配置するメモリ オブジェクトは、GlobalAlloc 関数と GMEM_MOVEABLE フラグを使用して割り当てる必要があります。

メモリ オブジェクトがクリップボードに配置されると、そのメモリ ハンドルの所有権がシステムに転送されます。 クリップボードが空になり、メモリ オブジェクトに次のいずれかのクリップボード形式がある場合、システムは指定された関数を呼び出してメモリ オブジェクトを解放します。

オブジェクトを解放する関数 クリップボードの形式
DeleteMetaFile
CF_DSPENHMETAFILE
CF_DSPMETAFILEPICT
CF_ENHMETAFILE
CF_METAFILEPICT
DeleteObject
CF_BITMAP
CF_DSPBITMAP
CF_PALETTE
GlobalFree
CF_DIB
CF_DIBV5
CF_DSPTEXT
CF_OEMTEXT
CF_TEXT
CF_UNICODETEXT
何一つ
CF_OWNERDISPLAY
CF_OWNERDISPLAY オブジェクトのクリップボードが空になると、アプリケーション自体がメモリ オブジェクトを解放する必要があります。