[MWF] Implement multi-display support on Linux (Fixes #325669)
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / XplatUIWin32.cs
index efe1ed16040ed4ef26a0757e511b44b6ffec4b2b..e541b1fdb97e8ac428e21922b014da5a404fed6f 100644 (file)
@@ -35,6 +35,7 @@ using System.Diagnostics;
 using System.IO;
 using System.Runtime.InteropServices;
 using System.Text;
+using System.Threading;
 
 
 /// Win32 Version
@@ -52,7 +53,6 @@ namespace System.Windows.Forms {
                internal static Rectangle       grab_area;
                internal static WndProc         wnd_proc;
                internal static IntPtr          prev_mouse_hwnd;
-               internal static IntPtr          override_cursor;
                internal static bool            caret_visible;
 
                internal static bool            themes_enabled;
@@ -275,6 +275,15 @@ namespace System.Windows.Forms {
                        internal short wParamH;
                }
 
+               [StructLayout (LayoutKind.Sequential)]
+               internal struct ICONINFO {
+                       internal bool fIcon;
+                       internal Int32 xHotspot;
+                       internal Int32 yHotspot;
+                       internal IntPtr hbmMask;
+                       internal IntPtr hbmColor;
+               }    
+               
                [StructLayout(LayoutKind.Explicit)]
                internal struct INPUT {
                        [FieldOffset(0)]
@@ -643,11 +652,7 @@ namespace System.Windows.Forms {
                        internal int                            uTimeoutOrVersion;
                        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)]
                        internal string                         szInfoTitle;
-#if NET_2_0
                        internal ToolTipIcon            dwInfoFlags;
-#else
-                       internal int                            dwInfoFlags;
-#endif
                }
 
                [Flags]
@@ -833,6 +838,9 @@ namespace System.Windows.Forms {
                        mouse_state = MouseButtons.None;
                        mouse_position = Point.Empty;
 
+                       grab_confined = false;
+                       grab_area = Rectangle.Empty;
+
                        message_queue = new Queue();
 
                        themes_enabled = false;
@@ -1179,6 +1187,14 @@ namespace System.Windows.Forms {
                        }
                }
 
+               public override Size MenuButtonSize {
+                       get {
+                               return new Size (
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CXMENUSIZE),
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CYMENUSIZE));
+                       }
+               }
+
                internal override int MenuShowDelay {
                        get { return GetSystemParametersInfoInt (SPIAction.SPI_GETMENUSHOWDELAY); }
                }
@@ -1191,7 +1207,6 @@ namespace System.Windows.Forms {
                        get { return GetSystemParametersInfoBool (SPIAction.SPI_GETMENUDROPALIGNMENT) == true ? LeftRightAlignment.Left : LeftRightAlignment.Right; }
                }
 
-#if NET_2_0
                internal override PowerStatus PowerStatus {
                        get {
                                SYSTEMPOWERSTATUS p = new SYSTEMPOWERSTATUS ();
@@ -1203,7 +1218,6 @@ namespace System.Windows.Forms {
                                return ps;
                        }
                }
-#endif
 
                internal override int SizingBorderWidth {
                        get { return Win32GetSystemMetrics (SystemMetrics.SM_CXSIZEFRAME); }
@@ -1491,13 +1505,39 @@ namespace System.Windows.Forms {
                        }
                }
 
+               [MonoTODO]
+               internal override Screen[] AllScreens {
+                       get {
+                               // To support multiples, we need to use GetMonitorInfo API on Win32
+                               return null;
+                       }
+               }
+
                internal override bool ThemesEnabled {
                        get {
                                return XplatUIWin32.themes_enabled;
                        }
                }
 
+               internal override bool RequiresPositiveClientAreaSize {
+                       get {
+                               return false;
+                       }
+               }
+
+               public override int ToolWindowCaptionHeight {
+                       get {
+                               return Win32GetSystemMetrics (SystemMetrics.SM_CYSMCAPTION);
+                       }
+               }
+
+               public override Size ToolWindowCaptionButtonSize {
+                       get {
+                               return new Size (
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CXSMSIZE),
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CYSMSIZE));
+                       }
+               }
                #endregion      // Static Properties
 
                #region Singleton Specific Code
@@ -1530,8 +1570,27 @@ namespace System.Windows.Forms {
                        Console.WriteLine("Xplat version $revision: $");
                }
 
-               internal override void AudibleAlert() {
-                       Win32PlaySound("Default", IntPtr.Zero, SndFlags.SND_ALIAS | SndFlags.SND_ASYNC | SndFlags.SND_NOSTOP | SndFlags.SND_NOWAIT);
+               string GetSoundAlias (AlertType alert)
+               {
+                       switch (alert) {
+                               case AlertType.Error:
+                                       return "SystemHand";
+                               case AlertType.Question:
+                                       return "SystemQuestion";
+                               case AlertType.Warning:
+                                       return "SystemExclamation";
+                               case AlertType.Information:
+                                       return "SystemAsterisk";
+                               default:
+                                       return "SystemDefault";
+                       }
+               }
+
+               internal override void AudibleAlert(AlertType alert) {
+                       Win32PlaySound(GetSoundAlias (alert), IntPtr.Zero, SndFlags.SND_ALIAS_ID | SndFlags.SND_ASYNC | SndFlags.SND_NOSTOP | SndFlags.SND_NOWAIT);
+               }
+
+               internal override void BeginMoveResize (IntPtr handle) {
                }
 
                internal override void GetDisplaySize(out Size size) {
@@ -1576,6 +1635,11 @@ namespace System.Windows.Forms {
                        string class_name = RegisterWindowClass (cp.ClassStyle);
                        HwndCreating = hwnd;
 
+                       // We cannot actually send the WS_EX_MDICHILD flag to Windows because we
+                       // are faking MDI, not uses Windows' version.
+                       if ((cp.WindowExStyle & WindowExStyles.WS_EX_MDICHILD) == WindowExStyles.WS_EX_MDICHILD)
+                               cp.WindowExStyle ^= WindowExStyles.WS_EX_MDICHILD;
+                               
                        WindowHandle = Win32CreateWindow (cp.WindowExStyle, class_name, cp.Caption, cp.WindowStyle, location.X, location.Y, cp.Width, cp.Height, ParentHandle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
 
                        HwndCreating = null;
@@ -1587,7 +1651,7 @@ namespace System.Windows.Forms {
                        }
 
                        hwnd.ClientWindow = WindowHandle;
-
+                       hwnd.Mapped = true;
                        Win32SetWindowLong(WindowHandle, WindowLong.GWL_USERDATA, (uint)ThemeEngine.Current.DefaultControlBackColor.ToArgb());
 
                        return WindowHandle;
@@ -1602,7 +1666,7 @@ namespace System.Windows.Forms {
                        create_params.Width = Width;
                        create_params.Height = Height;
 
-                       create_params.ClassName=XplatUI.DefaultClassName;
+                       create_params.ClassName=XplatUI.GetDefaultClassName (GetType ());
                        create_params.ClassStyle = 0;
                        create_params.ExStyle=0;
                        create_params.Parent=IntPtr.Zero;
@@ -1661,8 +1725,12 @@ namespace System.Windows.Forms {
                        Win32SetWindowLong(handle, WindowLong.GWL_STYLE, (uint)cp.Style);
                        Win32SetWindowLong(handle, WindowLong.GWL_EXSTYLE, (uint)cp.ExStyle);
 
-                       if ((cp.ExStyle & (int) WindowExStyles.WS_EX_TOOLWINDOW) > 0 || 
-                               ((cp.WindowStyle & (WindowStyles.WS_CAPTION)) != WindowStyles.WS_CAPTION && cp.control is Form))
+                       // From MSDN:
+                       // Certain window data is cached, so changes you make using SetWindowLong
+                       // will not take effect until you call the SetWindowPos function. Specifically, 
+                       // if you change any of the frame styles, you must call SetWindowPos with
+                       // the SWP_FRAMECHANGED flag for the cache to be updated properly.
+                       if (cp.control is Form)
                                XplatUI.RequestNCRecalc (handle);
                }
 
@@ -1746,39 +1814,41 @@ namespace System.Windows.Forms {
                        ps = new PAINTSTRUCT();
 
                        hwnd = Hwnd.ObjectFromHandle(msg.HWnd);
-
+                       
                        if (client) {
                                if (Win32GetUpdateRect(msg.HWnd, ref rect, false)) {
-                                       hdc = Win32BeginPaint(handle, ref ps);
-
-                                       // We need to validate the window where the paint message
-                                       // was generated, otherwise we'll never stop getting paint 
-                                       // messages.
                                        if (handle != msg.HWnd) {
-                                               ps.rcPaint = rect;
-                                               Win32ValidateRect (msg.HWnd, ref ps.rcPaint);
+                                               // We need to validate the window where the paint message
+                                               // was generated, otherwise we'll never stop getting paint 
+                                               // messages.
+                                               Win32GetClientRect (msg.HWnd, out rect);
+                                               Win32ValidateRect (msg.HWnd, ref rect);
+                                               hdc = Win32GetDC (handle);
+                                       } else {
+                                               hdc = Win32BeginPaint (handle, ref ps);
+                                               rect = ps.rcPaint;
                                        }
-
-                                       hwnd.drawing_stack.Push (ps);
-
-                                       clip_rect = new Rectangle(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right-ps.rcPaint.left, ps.rcPaint.bottom-ps.rcPaint.top);
                                } else {
                                        hdc = Win32GetDC(handle);
-
-                                       hwnd.drawing_stack.Push (hdc);
-
-                                       clip_rect = new Rectangle(rect.top, rect.left, rect.right-rect.left, rect.bottom-rect.top);
                                }
+                               clip_rect = rect.ToRectangle ();
                        } else {
                                hdc = Win32GetWindowDC (handle);
 
-                               hwnd.drawing_stack.Push (hdc);
-
                                // HACK this in for now
                                Win32GetWindowRect (handle, out rect);
-                               clip_rect = new Rectangle(0, 0, rect.right-rect.left, rect.bottom-rect.top);
+                               clip_rect = new Rectangle (0, 0, rect.Width, rect.Height);
                        }
 
+                       // If we called BeginPaint, store the PAINTSTRUCT,
+                       // otherwise store hdc, so that PaintEventEnd can know
+                       // whether to call EndPaint or ReleaseDC.
+                       if (ps.hdc != IntPtr.Zero) {
+                               hwnd.drawing_stack.Push (ps);
+                       } else {
+                               hwnd.drawing_stack.Push (hdc);
+                       }
+                       
                        Graphics dc = Graphics.FromHdc(hdc);
                        hwnd.drawing_stack.Push (dc);
 
@@ -1795,20 +1865,13 @@ namespace System.Windows.Forms {
                        Graphics dc = (Graphics)hwnd.drawing_stack.Pop();
                        dc.Dispose ();
 
-                       if (client) {
-                               object o = hwnd.drawing_stack.Pop();
-                               if (o != null) {
-                                       if (o is PAINTSTRUCT) {
-                                               PAINTSTRUCT ps = (PAINTSTRUCT)o;
-                                               Win32EndPaint(handle, ref ps);
-                                       } else if (o is IntPtr) {
-                                               IntPtr hdc = (IntPtr) o;
-                                               Win32ReleaseDC (handle, hdc);
-                                       }
-                               }
-                       } else {
-                               IntPtr hdc = (IntPtr)hwnd.drawing_stack.Pop();
-                               Win32ReleaseDC(handle, hdc);
+                       object o = hwnd.drawing_stack.Pop();
+                       if (o is IntPtr) {
+                               IntPtr hdc = (IntPtr) o;
+                               Win32ReleaseDC (handle, hdc);
+                       } else if (o is PAINTSTRUCT) {
+                               PAINTSTRUCT ps = (PAINTSTRUCT) o;
+                               Win32EndPaint (handle, ref ps);
                        }
                }
 
@@ -1845,6 +1908,16 @@ namespace System.Windows.Forms {
 
                internal override void Activate(IntPtr handle) {
                        Win32SetActiveWindow(handle);
+                       // delayed timer enabled
+                       lock (timer_list) {
+                               foreach (Timer t in timer_list.Values) {
+                                       if (t.Enabled && t.window == IntPtr.Zero) {
+                                               t.window = handle;
+                                               int id = t.GetHashCode ();
+                                               Win32SetTimer(handle, id, (uint)t.Interval, IntPtr.Zero);
+                                       }
+                               }
+                       }
                }
 
                internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
@@ -1892,11 +1965,12 @@ namespace System.Windows.Forms {
                internal override void DoEvents() {
                        MSG msg = new MSG();
 
-                       if (override_cursor != IntPtr.Zero) {
-                               Cursor.Current = null;
-                       }
-
                        while (GetMessage(ref msg, IntPtr.Zero, 0, 0, false)) {
+                               Message m = Message.Create (msg.hwnd, (int)msg.message, msg.wParam, msg.lParam);
+
+                               if (Application.FilterMessage (ref m))
+                                       continue;
+
                                XplatUI.TranslateMessage(ref msg);
                                XplatUI.DispatchMessage(ref msg);
                        }
@@ -2011,6 +2085,8 @@ namespace System.Windows.Forms {
                                        if (msg.hwnd != prev_mouse_hwnd) {
                                                TRACKMOUSEEVENT tme;
 
+                                               mouse_state = Control.FromParamToMouseButtons ((int)msg.lParam.ToInt32());
+
                                                // The current message will be sent out next time around
                                                StoreMessage(ref msg);
 
@@ -2032,7 +2108,9 @@ namespace System.Windows.Forms {
                                case Msg.WM_NCMOUSEMOVE: {
                                        if (wm_nc_registered == null || !wm_nc_registered.Contains (msg.hwnd))
                                                break;
-                                               
+
+                                       mouse_state = Control.FromParamToMouseButtons ((int)msg.lParam.ToInt32 ());
+
                                        TRACKMOUSEEVENT tme;
 
                                        tme = new TRACKMOUSEEVENT ();
@@ -2151,6 +2229,11 @@ namespace System.Windows.Forms {
                internal override bool IsEnabled(IntPtr handle) {
                        return IsWindowEnabled (handle);
                }
+
+               internal override bool IsKeyLocked (VirtualKeys key)
+               {
+                       return (Win32GetKeyState (key) & 1) == 1;
+               }
                
                internal override bool IsVisible(IntPtr handle) {
                        return IsWindowVisible (handle);
@@ -2202,6 +2285,11 @@ namespace System.Windows.Forms {
                        return Win32GetParent(handle);
                }
 
+               // This is a nop on win32 and x11
+               internal override IntPtr GetPreviousWindow(IntPtr handle) {
+                       return handle;
+               }
+
                internal override void GrabWindow(IntPtr hWnd, IntPtr ConfineToHwnd) {
                        grab_hwnd = hWnd;
                        Win32SetCapture(hWnd);
@@ -2365,10 +2453,15 @@ namespace System.Windows.Forms {
 
                [MonoTODO]
                internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
+                       ICONINFO ii = new ICONINFO ();
+                       
+                       if (!Win32GetIconInfo (cursor, out ii))
+                               throw new Win32Exception ();
+                               
                        width = 20;
                        height = 20;
-                       hotspot_x = 0;
-                       hotspot_y = 0;
+                       hotspot_x = ii.xHotspot;
+                       hotspot_y = ii.yHotspot;
                }
 
                internal override void SetCursorPos(IntPtr handle, int x, int y) {
@@ -2482,7 +2575,10 @@ namespace System.Windows.Forms {
                                timer_list[index]=timer;
                        }
 
-                       Win32SetTimer(FosterParent, index, (uint)timer.Interval, IntPtr.Zero);
+                       if (Win32SetTimer(FosterParent, index, (uint)timer.Interval, IntPtr.Zero) != IntPtr.Zero)
+                               timer.window = FosterParent;
+                       else
+                               timer.window = IntPtr.Zero;
                }
 
                internal override void KillTimer (Timer timer)
@@ -2491,7 +2587,7 @@ namespace System.Windows.Forms {
 
                        index = timer.GetHashCode();
 
-                       Win32KillTimer(FosterParent, index);
+                       Win32KillTimer(timer.window, index);
 
                        lock (timer_list) {
                                timer_list.Remove(index);
@@ -2646,7 +2742,6 @@ namespace System.Windows.Forms {
                        Win32Shell_NotifyIcon(NotifyIconMessage.NIM_DELETE, ref nid);
                }
 
-#if NET_2_0
                internal override void SystrayBalloon(IntPtr hwnd, int timeout, string title, string text, ToolTipIcon icon)
                {
                        NOTIFYICONDATA  nid;
@@ -2664,7 +2759,6 @@ namespace System.Windows.Forms {
                        
                        Win32Shell_NotifyIcon(NotifyIconMessage.NIM_MODIFY, ref nid);
                }
-#endif
 
                internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
                        // Nothing to do on Win32
@@ -2677,10 +2771,19 @@ namespace System.Windows.Forms {
 
                internal override Point GetMenuOrigin(IntPtr handle) {
                        Form form = Control.FromHandle (handle) as Form;
+                       
                        if (form != null) {
-                               Hwnd.Borders borders = Hwnd.GetBorders (form.GetCreateParams (), null);
-                               return new Point(borders.left, borders.top);
+                               if (form.FormBorderStyle == FormBorderStyle.None)
+                                       return Point.Empty;
+                                       
+                               int bordersize = (form.Width - form.ClientSize.Width) / 2;
+                                       
+                               if (form.FormBorderStyle == FormBorderStyle.FixedToolWindow || form.FormBorderStyle == FormBorderStyle.SizableToolWindow)
+                                       return new Point (bordersize, bordersize + SystemInformation.ToolWindowCaptionHeight);
+                               else
+                                       return new Point (bordersize, bordersize + SystemInformation.CaptionHeight);
                        }
+                       
                        return new Point(SystemInformation.FrameBorderSize.Width, SystemInformation.FrameBorderSize.Height + ThemeEngine.Current.CaptionHeight);
                }
 
@@ -2813,10 +2916,9 @@ namespace System.Windows.Forms {
 
                }
 
-               internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
-                       byte[]  data;
-                       IntPtr  hmem;
-                       IntPtr  hmem_ptr;
+               internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter, bool copy)
+               {
+                       byte[]  data = null;
 
                        if (handle != clip_magic) {
                                throw new ArgumentException("handle is not a valid clipboard handle");
@@ -2838,52 +2940,106 @@ namespace System.Windows.Forms {
                        }
 
                        if (type == DataFormats.GetFormat(DataFormats.Rtf).Id) {
-                               hmem = Marshal.StringToHGlobalAnsi((string)obj);
-                               if (Win32SetClipboardData((uint)type, hmem) == IntPtr.Zero )
-                                       throw new ExternalException("Win32SetClipboardData");
-                               return;
+                               data = StringToAnsi ((string)obj);
                        } else switch((ClipboardFormats)type) {
                                case ClipboardFormats.CF_UNICODETEXT: {
-                                       hmem = Marshal.StringToHGlobalUni((string)obj);
-                                       if (Win32SetClipboardData((uint)type, hmem) == IntPtr.Zero)
-                                               throw new ExternalException("Win32SetClipboardData");
-                                       return;
+                                       data = StringToUnicode ((string)obj);
+                                       break;
                                }
 
                                case ClipboardFormats.CF_TEXT: {
-                                       hmem = Marshal.StringToHGlobalAnsi((string)obj);
-                                       if (Win32SetClipboardData((uint)type, hmem) == IntPtr.Zero)
-                                               throw new ExternalException("Win32SetClipboardData");
-                                       return;
+                                       data = StringToAnsi ((string)obj);
+                                       break;
                                }
 
                                case ClipboardFormats.CF_BITMAP:
                                case ClipboardFormats.CF_DIB: {
-                                       data = ImageToDIB((Image)obj);
-
-                                       hmem = Win32GlobalAlloc(GAllocFlags.GMEM_MOVEABLE | GAllocFlags.GMEM_DDESHARE, data.Length);
-                                       hmem_ptr = Win32GlobalLock(hmem);
-                                       Marshal.Copy(data, 0, hmem_ptr, data.Length);
-                                       Win32GlobalUnlock(hmem);
-                                       if (Win32SetClipboardData((uint)ClipboardFormats.CF_DIB, hmem) == IntPtr.Zero)
-                                               throw new ExternalException("Win32SetClipboardData");
-                                       return;
+                                       data = ImageToDIB ((Image)obj);
+                                       type = (int)ClipboardFormats.CF_DIB;
+                                       break;
                                }
 
                                default: {
-                                       if (converter != null && converter(ref type, obj, out data)) {
-                                               hmem = Win32GlobalAlloc(GAllocFlags.GMEM_MOVEABLE | GAllocFlags.GMEM_DDESHARE, data.Length);
-                                               hmem_ptr = Win32GlobalLock(hmem);
-                                               Marshal.Copy(data, 0, hmem_ptr, data.Length);
-                                               Win32GlobalUnlock(hmem);
-                                               if (Win32SetClipboardData((uint)type, hmem) == IntPtr.Zero)
-                                                       throw new ExternalException("Win32SetClipboardData");
+                                       if (converter != null && !converter(ref type, obj, out data)) {
+                                               data = null; // ensure that a failed conversion leaves null.
                                        }
-                                       return;
+                                       break;
                                }
                        }
+                       if (data != null) {
+                               SetClipboardData ((uint)type, data);
+                       }
                }
 
+               internal static byte[] StringToUnicode (string text)
+               {
+                       return Encoding.Unicode.GetBytes (text + "\0");
+               }
+
+               internal static byte[] StringToAnsi (string text)
+               {
+                       // FIXME, follow the behaviour of the previous code using UTF-8,
+                       // but this should be 'ANSI' on Windows, i.e. the current code page.
+                       // Does Encoding.Default work on Windows?
+                       return Encoding.UTF8.GetBytes (text + "\0");
+               }
+
+               private void SetClipboardData (uint type, byte[] data)
+               {
+                       if (data.Length == 0)
+                               // Shouldn't call Win32SetClipboard with NULL, as, from MSDN:
+                               // "This parameter can be NULL, indicating that the window provides data 
+                               //  in the specified clipboard format (renders the format) upon request."
+                               // and I don't think we support that...
+                               // Note this is unrelated to the fact that passing a null obj to 
+                               // ClipboardStore is actually a request to empty the clipboard!
+                               return;
+                       IntPtr hmem = CopyToMoveableMemory (data);
+                       if (hmem == IntPtr.Zero)
+                               // As above, should not call with null.
+                               // (Not that CopyToMoveableMemory should ever return null!)
+                               throw new ExternalException ("CopyToMoveableMemory failed.");
+                       if (Win32SetClipboardData (type, hmem) == IntPtr.Zero)
+                               throw new ExternalException ("Win32SetClipboardData");
+               }
+
+               /// <summary>
+               /// Creates a memory block with GlobalAlloc(GMEM_MOVEABLE), copies the data 
+               /// into it, and returns the handle to the memory.
+               /// </summary>
+               /// -
+               /// <param name="data">The data.  Must not be null or zero-length &#x2014; 
+               /// see the exception notes.</param>
+               /// -
+               /// <returns>The *handle* to the allocated GMEM_MOVEABLE block.</returns>
+               /// -
+               /// <exception cref="T:System.ArgumentException">The data was null or zero 
+               /// length.  This is disallowed since a zero length allocation can't be made
+               /// </exception>
+               /// <exception cref="T:System.ComponentModel.Win32Exception">The allocation, 
+               /// or locking (handle->pointer) failed.
+               /// Either out of memory or the handle table is full (256 max currently).
+               /// Note Win32Exception is a subclass of ExternalException so this is OK in 
+               /// the documented Clipboard interface.
+               /// </exception>
+               internal static IntPtr CopyToMoveableMemory (byte[] data)
+               {
+                       if (data == null || data.Length == 0)
+                               // detect this before GlobalAlloc does.
+                               throw new ArgumentException ("Can't create a zero length memory block.");
+
+                       IntPtr hmem = Win32GlobalAlloc (GAllocFlags.GMEM_MOVEABLE | GAllocFlags.GMEM_DDESHARE, data.Length);
+                       if (hmem == IntPtr.Zero)
+                               throw new Win32Exception ();
+                       IntPtr hmem_ptr = Win32GlobalLock (hmem);
+                       if (hmem_ptr == IntPtr.Zero) // If the allocation was valid this shouldn't occur.
+                               throw new Win32Exception ();
+                       Marshal.Copy (data, 0, hmem_ptr, data.Length);
+                       Win32GlobalUnlock (hmem);
+                       return hmem;
+               }
+
+
                internal override void SetAllowDrop(IntPtr hwnd, bool allowed) {
                        if (allowed) {
                                Win32DnD.RegisterDropTarget(hwnd);
@@ -3170,6 +3326,11 @@ namespace System.Windows.Forms {
                        Win32DeleteDC (wb.hdc);
                }
 
+               internal override void SetForegroundWindow (IntPtr handle)
+               {
+                       Win32SetForegroundWindow(handle);
+               }
+
                internal override event EventHandler Idle;
                #endregion      // Public Static Methods
 
@@ -3345,7 +3506,7 @@ namespace System.Windows.Forms {
                private extern static uint Win32GetLayeredWindowAttributes (IntPtr hwnd, out COLORREF pcrKey, out byte pbAlpha, out LayeredWindowAttributes pwdFlags);
 
                [DllImport ("gdi32.dll", EntryPoint="DeleteObject", CallingConvention=CallingConvention.StdCall)]
-               private extern static bool Win32DeleteObject(IntPtr o);
+               public extern static bool Win32DeleteObject(IntPtr o);
 
                [DllImport ("user32.dll", EntryPoint="GetKeyState", CallingConvention=CallingConvention.StdCall)]
                private extern static short Win32GetKeyState(VirtualKeys nVirtKey);
@@ -3566,6 +3727,12 @@ namespace System.Windows.Forms {
 
                [DllImport ("kernel32.dll", EntryPoint = "GetSystemPowerStatus", CallingConvention = CallingConvention.StdCall)]
                internal static extern Boolean Win32GetSystemPowerStatus (SYSTEMPOWERSTATUS sps);
+
+               [DllImport ("user32.dll", EntryPoint = "GetIconInfo", CallingConvention = CallingConvention.StdCall)]
+               internal static extern bool Win32GetIconInfo (IntPtr hIcon, out ICONINFO piconinfo);
+
+               [DllImport ("user32.dll", EntryPoint="SetForegroundWindow", CallingConvention=CallingConvention.StdCall)]
+               extern static bool Win32SetForegroundWindow(IntPtr hWnd);
                #endregion
        }
 }