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.Runtime.Serialization;
34 using System.Collections;
35 using System.Collections.Specialized;
36 using System.ComponentModel;
38 namespace System.Windows.Forms {
39 public sealed class Clipboard {
40 #region Local Variables
41 #endregion // Local Variables
46 #endregion // Constructors
48 #region Private Methods
49 private static bool ConvertToClipboardData(ref int type, object obj, out byte[] data) {
54 private static bool ConvertFromClipboardData(int type, IntPtr data, out object obj) {
56 if (data == IntPtr.Zero) {
61 #endregion // Private Methods
63 #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, false);
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);
135 public static IDataObject GetDataObject ()
137 return GetDataObject (false);
140 public static StringCollection GetFileDropList ()
142 IDataObject data = GetDataObject ();
147 return (StringCollection)data.GetData (DataFormats.FileDrop, true);
150 public static Image GetImage ()
152 IDataObject data = GetDataObject ();
157 return (Image)data.GetData (DataFormats.Bitmap, true);
160 public static string GetText ()
162 return GetText (TextDataFormat.UnicodeText);
165 public static string GetText (TextDataFormat format)
167 if (!Enum.IsDefined (typeof (TextDataFormat), format))
168 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for TextDataFormat", format));
170 IDataObject data = GetDataObject ();
178 case TextDataFormat.Text:
180 retval = (string)data.GetData (DataFormats.Text, true);
182 case TextDataFormat.UnicodeText:
183 retval = (string)data.GetData (DataFormats.UnicodeText, true);
185 case TextDataFormat.Rtf:
186 retval = (string)data.GetData (DataFormats.Rtf, true);
188 case TextDataFormat.Html:
189 retval = (string)data.GetData (DataFormats.Html, true);
191 case TextDataFormat.CommaSeparatedValue:
192 retval = (string)data.GetData (DataFormats.CommaSeparatedValue, true);
196 return retval == null ? string.Empty : retval;
199 public static void SetAudio (byte[] audioBytes)
201 if (audioBytes == null)
202 throw new ArgumentNullException ("audioBytes");
204 MemoryStream ms = new MemoryStream (audioBytes);
209 public static void SetAudio (Stream audioStream)
211 if (audioStream == null)
212 throw new ArgumentNullException ("audioStream");
214 SetData (DataFormats.WaveAudio, audioStream);
217 public static void SetData (string format, Object data)
220 throw new ArgumentNullException ("data");
222 DataObject data_object = new DataObject (format, data);
223 SetDataObject (data_object);
226 public static void SetDataObject(object data) {
227 SetDataObject(data, false); // MSDN says default behavior is to place non-persistent data to clipboard
230 public static void SetDataObject(object data, bool copy) {
231 SetDataObject(data, copy, 10, 100); // MSDN says default behavior is to try 10 times with 100 ms delay
234 internal static void SetDataObjectImpl(object data, bool copy) {
235 IntPtr clipboard_handle;
236 XplatUI.ObjectToClipboard converter;
238 DataFormats.Format item_format;
240 converter = new XplatUI.ObjectToClipboard(ConvertToClipboardData);
242 clipboard_handle = XplatUI.ClipboardOpen(false);
243 XplatUI.ClipboardStore(clipboard_handle, null, 0, null, copy); // Empty clipboard
247 if (data is IDataObject) {
250 IDataObject data_object = data as IDataObject;
251 formats = data_object.GetFormats();
252 for (int i = 0; i < formats.Length; i++) {
253 item_format = DataFormats.GetFormat(formats[i]);
254 if ((item_format != null) && (item_format.Name != DataFormats.StringFormat)) {
255 native_format = item_format.Id;
258 object obj = data_object.GetData (formats [i]);
260 // this is used only by custom formats
261 if (IsDataSerializable (obj))
262 item_format.is_serializable = true;
264 XplatUI.ClipboardStore(clipboard_handle, obj, native_format, converter, copy);
267 item_format = DataFormats.Format.Find(data.GetType().FullName);
268 if ((item_format != null) && (item_format.Name != DataFormats.StringFormat)) {
269 native_format = item_format.Id;
272 XplatUI.ClipboardStore(clipboard_handle, data, native_format, converter, copy);
274 XplatUI.ClipboardClose(clipboard_handle);
277 static bool IsDataSerializable (object obj)
279 if (obj is ISerializable)
282 AttributeCollection attrs = TypeDescriptor.GetAttributes (obj);
283 return attrs [typeof (SerializableAttribute)] != null;
286 public static void SetDataObject(object data, bool copy, int retryTimes, int retryDelay)
289 throw new ArgumentNullException("data");
291 throw new ArgumentOutOfRangeException("retryTimes");
293 throw new ArgumentOutOfRangeException("retryDelay");
295 // MS implementation actually puts data to clipboard even when retryTimes == 0
303 SetDataObjectImpl(data, copy);
304 } catch (ExternalException) {
308 Threading.Thread.Sleep(retryDelay);
310 } while (retry && retryTimes > 0);
313 [MonoInternalNote ("Needs additional checks for valid paths, see MSDN")]
314 public static void SetFileDropList (StringCollection filePaths)
316 if (filePaths == null)
317 throw new ArgumentNullException ("filePaths");
319 SetData (DataFormats.FileDrop, filePaths);
322 public static void SetImage (Image image)
325 throw new ArgumentNullException ("image");
327 SetData (DataFormats.Bitmap, image);
330 public static void SetText (string text)
332 if (string.IsNullOrEmpty (text))
333 throw new ArgumentNullException ("text");
335 SetData (DataFormats.UnicodeText, text);
338 public static void SetText (string text, TextDataFormat format)
340 if (string.IsNullOrEmpty (text))
341 throw new ArgumentNullException ("text");
342 if (!Enum.IsDefined (typeof (TextDataFormat), format))
343 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for TextDataFormat", format));
346 case TextDataFormat.Text:
347 SetData (DataFormats.Text, text);
349 case TextDataFormat.UnicodeText:
350 SetData (DataFormats.UnicodeText, text);
352 case TextDataFormat.Rtf:
353 SetData (DataFormats.Rtf, text);
355 case TextDataFormat.Html:
356 SetData (DataFormats.Html, text);
358 case TextDataFormat.CommaSeparatedValue:
359 SetData (DataFormats.CommaSeparatedValue, text);
363 #endregion // Public Static Methods
365 #region Internal Static Methods
366 internal static IDataObject GetDataObject (bool primary_selection)
368 DataObject clipboard;
369 IntPtr clipboard_handle;
370 int[] native_formats;
371 DataFormats.Format item_format;
372 object managed_clipboard_item;
373 XplatUI.ClipboardToObject converter;
375 converter = new XplatUI.ClipboardToObject (ConvertFromClipboardData);
377 clipboard_handle = XplatUI.ClipboardOpen (primary_selection);
378 native_formats = XplatUI.ClipboardAvailableFormats (clipboard_handle);
379 if (native_formats == null) {
380 return null; // Clipboard empty
383 // Build the IDataObject
384 clipboard = new DataObject ();
385 for (int i = 0; i < native_formats.Length; i++) {
386 // We might get a format we don't understand or know
387 item_format = DataFormats.GetFormat (native_formats[i]);
389 if (item_format != null) {
390 managed_clipboard_item = XplatUI.ClipboardRetrieve (clipboard_handle, native_formats[i], converter);
392 if (managed_clipboard_item != null) {
393 clipboard.SetData (item_format.Name, managed_clipboard_item);
394 // We don't handle 'bitmap' since it involves handles, so we'll equate it to dib
395 if (item_format.Name == DataFormats.Dib) {
396 clipboard.SetData (DataFormats.Bitmap, managed_clipboard_item);
402 XplatUI.ClipboardClose (clipboard_handle);
407 internal static bool ClipboardContainsFormat (params string[] formats)
409 IntPtr clipboard_handle;
410 int[] native_formats;
411 DataFormats.Format item_format;
413 clipboard_handle = XplatUI.ClipboardOpen (false);
414 native_formats = XplatUI.ClipboardAvailableFormats (clipboard_handle);
416 if (native_formats == null)
419 foreach (int i in native_formats) {
420 // We might get a format we don't understand or know
421 item_format = DataFormats.GetFormat (i);
423 if (item_format != null)
424 if (((IList)formats).Contains (item_format.Name))