1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
23 // Peter Bartok (pbartok@novell.com)
32 using System.Runtime.InteropServices;
33 using System.Collections;
34 using System.Collections.Specialized;
35 using System.ComponentModel;
37 namespace System.Windows.Forms {
38 public sealed class Clipboard {
39 #region Local Variables
40 #endregion // Local Variables
45 #endregion // Constructors
47 #region Private Methods
48 private static bool ConvertToClipboardData(ref int type, object obj, out byte[] data) {
53 private static bool ConvertFromClipboardData(int type, IntPtr data, out object obj) {
55 if (data == IntPtr.Zero) {
60 #endregion // Private Methods
62 #region Public Static Methods
64 public static void Clear ()
66 IntPtr clipboard_handle;
68 clipboard_handle = XplatUI.ClipboardOpen (false);
69 XplatUI.ClipboardStore (clipboard_handle, null, 0, null);
72 public static bool ContainsAudio ()
74 return ClipboardContainsFormat (DataFormats.WaveAudio);
77 public static bool ContainsData (string format)
79 return ClipboardContainsFormat (format);
82 public static bool ContainsFileDropList ()
84 return ClipboardContainsFormat (DataFormats.FileDrop);
87 public static bool ContainsImage ()
89 return ClipboardContainsFormat (DataFormats.Bitmap);
92 public static bool ContainsText ()
94 return ClipboardContainsFormat (DataFormats.Text, DataFormats.UnicodeText);
97 public static bool ContainsText (TextDataFormat format)
100 case TextDataFormat.Text:
101 return ClipboardContainsFormat (DataFormats.Text);
102 case TextDataFormat.UnicodeText:
103 return ClipboardContainsFormat (DataFormats.UnicodeText);
104 case TextDataFormat.Rtf:
105 return ClipboardContainsFormat (DataFormats.Rtf);
106 case TextDataFormat.Html:
107 return ClipboardContainsFormat (DataFormats.Html);
108 case TextDataFormat.CommaSeparatedValue:
109 return ClipboardContainsFormat (DataFormats.CommaSeparatedValue);
115 public static Stream GetAudioStream ()
117 IDataObject data = GetDataObject ();
122 return (Stream)data.GetData (DataFormats.WaveAudio, true);
125 public static Object GetData (string format)
127 IDataObject data = GetDataObject ();
132 return data.GetData (format, true);
136 public static IDataObject GetDataObject ()
138 return GetDataObject (false);
142 public static StringCollection GetFileDropList ()
144 IDataObject data = GetDataObject ();
149 return (StringCollection)data.GetData (DataFormats.FileDrop, true);
152 public static Image GetImage ()
154 IDataObject data = GetDataObject ();
159 return (Image)data.GetData (DataFormats.Bitmap, true);
162 public static string GetText ()
164 return GetText (TextDataFormat.UnicodeText);
167 public static string GetText (TextDataFormat format)
169 if (!Enum.IsDefined (typeof (TextDataFormat), format))
170 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for TextDataFormat", format));
172 IDataObject data = GetDataObject ();
180 case TextDataFormat.Text:
182 retval = (string)data.GetData (DataFormats.Text, true);
184 case TextDataFormat.UnicodeText:
185 retval = (string)data.GetData (DataFormats.UnicodeText, true);
187 case TextDataFormat.Rtf:
188 retval = (string)data.GetData (DataFormats.Rtf, true);
190 case TextDataFormat.Html:
191 retval = (string)data.GetData (DataFormats.Html, true);
193 case TextDataFormat.CommaSeparatedValue:
194 retval = (string)data.GetData (DataFormats.CommaSeparatedValue, true);
198 return retval == null ? string.Empty : retval;
201 public static void SetAudio (byte[] audioBytes)
203 if (audioBytes == null)
204 throw new ArgumentNullException ("audioBytes");
206 MemoryStream ms = new MemoryStream (audioBytes);
211 public static void SetAudio (Stream audioStream)
213 if (audioStream == null)
214 throw new ArgumentNullException ("audioStream");
216 SetData (DataFormats.WaveAudio, audioStream);
219 [MonoInternalNote ("Does not use requested format")]
220 public static void SetData (string format, Object data)
223 throw new ArgumentNullException ("data");
225 SetDataObject (data);
229 public static void SetDataObject(object data) {
230 SetDataObject(data, false); // MSDN says default behavior is to place non-persistent data to clipboard
233 public static void SetDataObject(object data, bool copy) {
234 SetDataObject(data, copy, 10, 100); // MSDN says default behavior is to try 10 times with 100 ms delay
237 internal static void SetDataObjectImpl(object data, bool copy) {
238 IntPtr clipboard_handle;
239 XplatUI.ObjectToClipboard converter;
241 DataFormats.Format item_format;
243 converter = new XplatUI.ObjectToClipboard(ConvertToClipboardData);
245 clipboard_handle = XplatUI.ClipboardOpen(false);
246 XplatUI.ClipboardStore(clipboard_handle, null, 0, null); // Empty clipboard
250 if (data is IDataObject) {
253 formats = ((IDataObject)data).GetFormats();
254 for (int i = 0; i < formats.Length; i++) {
255 item_format = DataFormats.GetFormat(formats[i]);
256 if ((item_format != null) && (item_format.Name != DataFormats.StringFormat)) {
257 native_format = item_format.Id;
260 XplatUI.ClipboardStore(clipboard_handle, ((IDataObject)data).GetData(formats[i]), native_format, converter);
263 item_format = DataFormats.Format.Find(data.GetType().FullName);
264 if ((item_format != null) && (item_format.Name != DataFormats.StringFormat)) {
265 native_format = item_format.Id;
268 XplatUI.ClipboardStore(clipboard_handle, data, native_format, converter);
270 XplatUI.ClipboardClose(clipboard_handle);
278 static void SetDataObject(object data, bool copy, int retryTimes, int retryDelay)
281 throw new ArgumentNullException("data");
283 throw new ArgumentOutOfRangeException("retryTimes");
285 throw new ArgumentOutOfRangeException("retryDelay");
287 // MS implementation actually puts data to clipboard even when retryTimes == 0
295 SetDataObjectImpl(data, copy);
296 } catch (ExternalException) {
300 Threading.Thread.Sleep(retryDelay);
302 } while (retry && retryTimes > 0);
306 [MonoInternalNote ("Needs additional checks for valid paths, see MSDN")]
307 public static void SetFileDropList (StringCollection filePaths)
309 if (filePaths == null)
310 throw new ArgumentNullException ("filePaths");
312 SetData (DataFormats.FileDrop, filePaths);
315 public static void SetImage (Image image)
318 throw new ArgumentNullException ("image");
320 SetData (DataFormats.Bitmap, image);
323 public static void SetText (string text)
325 if (string.IsNullOrEmpty (text))
326 throw new ArgumentNullException ("text");
328 SetData (DataFormats.UnicodeText, text);
331 public static void SetText (string text, TextDataFormat format)
333 if (string.IsNullOrEmpty (text))
334 throw new ArgumentNullException ("text");
335 if (!Enum.IsDefined (typeof (TextDataFormat), format))
336 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for TextDataFormat", format));
339 case TextDataFormat.Text:
340 SetData (DataFormats.Text, text);
342 case TextDataFormat.UnicodeText:
343 SetData (DataFormats.UnicodeText, text);
345 case TextDataFormat.Rtf:
346 SetData (DataFormats.Rtf, text);
348 case TextDataFormat.Html:
349 SetData (DataFormats.Html, text);
351 case TextDataFormat.CommaSeparatedValue:
352 SetData (DataFormats.CommaSeparatedValue, text);
357 #endregion // Public Static Methods
359 #region Internal Static Methods
360 internal static IDataObject GetDataObject (bool primary_selection)
362 DataObject clipboard;
363 IntPtr clipboard_handle;
364 int[] native_formats;
365 DataFormats.Format item_format;
366 object managed_clipboard_item;
367 XplatUI.ClipboardToObject converter;
369 converter = new XplatUI.ClipboardToObject (ConvertFromClipboardData);
371 clipboard_handle = XplatUI.ClipboardOpen (primary_selection);
372 native_formats = XplatUI.ClipboardAvailableFormats (clipboard_handle);
373 if (native_formats == null) {
374 return null; // Clipboard empty
377 // Build the IDataObject
378 clipboard = new DataObject ();
379 for (int i = 0; i < native_formats.Length; i++) {
380 // We might get a format we don't understand or know
381 item_format = DataFormats.GetFormat (native_formats[i]);
383 if (item_format != null) {
384 managed_clipboard_item = XplatUI.ClipboardRetrieve (clipboard_handle, native_formats[i], converter);
386 if (managed_clipboard_item != null) {
387 clipboard.SetData (item_format.Name, managed_clipboard_item);
388 // We don't handle 'bitmap' since it involves handles, so we'll equate it to dib
389 if (item_format.Name == DataFormats.Dib) {
390 clipboard.SetData (DataFormats.Bitmap, managed_clipboard_item);
396 XplatUI.ClipboardClose (clipboard_handle);
401 internal static bool ClipboardContainsFormat (params string[] formats)
403 IntPtr clipboard_handle;
404 int[] native_formats;
405 DataFormats.Format item_format;
407 clipboard_handle = XplatUI.ClipboardOpen (false);
408 native_formats = XplatUI.ClipboardAvailableFormats (clipboard_handle);
410 if (native_formats == null)
413 foreach (int i in native_formats) {
414 // We might get a format we don't understand or know
415 item_format = DataFormats.GetFormat (i);
417 if (item_format != null)
418 if (((IList)formats).Contains (item_format.Name))