private static IntPtr clip_magic = new IntPtr(27051977);
private static int scroll_width;
private static int scroll_height;
+ private static Hashtable wm_nc_registered;
private static Win32DnD DnD;
#endregion // Local Variables
private enum TMEFlags {
TME_HOVER = 0x00000001,
TME_LEAVE = 0x00000002,
+ TME_NONCLIENT = 0x00000010,
TME_QUERY = unchecked((int)0x40000000),
TME_CANCEL = unchecked((int)0x80000000)
}
Win32SetWindowLong(handle, WindowLong.GWL_EXSTYLE, (uint)cp.ExStyle);
}
-
+ internal override double GetWindowTransparency(IntPtr handle)
+ {
+ LayeredWindowAttributes lwa;
+ COLORREF clrRef;
+ byte alpha;
+
+ if (0 == Win32GetLayeredWindowAttributes (handle, out clrRef, out alpha, out lwa))
+ return 1.0;
+
+ return ((double)alpha) / 255.0;
+ }
+
internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
LayeredWindowAttributes lwa = LayeredWindowAttributes.LWA_ALPHA;
byte opacity = (byte)(transparency*255);
Win32SetLayeredWindowAttributes(handle, clrRef, opacity, lwa);
}
- internal override bool SupportsTransparency() {
- // We might check with the OS, but I think we're only >=W2k
- return true;
+ TransparencySupport support;
+ bool queried_transparency_support;
+ internal override TransparencySupport SupportsTransparency() {
+ if (queried_transparency_support)
+ return support;
+
+ bool flag;
+ support = TransparencySupport.None;
+
+ flag = true;
+ try {
+ Win32SetLayeredWindowAttributes (IntPtr.Zero, new COLORREF (), 255, LayeredWindowAttributes.LWA_ALPHA);
+ }
+ catch (EntryPointNotFoundException) { flag = false; }
+ catch { /* swallow everything else */ }
+
+ if (flag) support |= TransparencySupport.Set;
+
+ flag = true;
+ try {
+ LayeredWindowAttributes lwa;
+ COLORREF clrRef;
+ byte alpha;
+
+ Win32GetLayeredWindowAttributes (IntPtr.Zero, out clrRef, out alpha, out lwa);
+ }
+ catch (EntryPointNotFoundException) { flag = false; }
+ catch { /* swallow everything else */ }
+
+ if (flag) support |= TransparencySupport.Get;
+
+ queried_transparency_support = true;
+ return support;
}
internal override void UpdateWindow(IntPtr handle) {
if (Win32GetUpdateRect(handle, ref rect, false)) {
hdc = Win32BeginPaint(handle, ref ps);
- hwnd.user_data = (object)ps;
+ 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);
// FIXME: Add the DC to internal list
+
+ hwnd.drawing_stack.Push (null);
+
clip_rect = new Rectangle(rect.top, rect.left, rect.right-rect.left, rect.bottom-rect.top);
}
} else {
hdc = Win32GetWindowDC (handle);
- hwnd.user_data = (object)hdc;
+
+ 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);
}
- hwnd.client_dc = Graphics.FromHdc(hdc);
- paint_event = new PaintEventArgs(hwnd.client_dc, clip_rect);
+ Graphics dc = Graphics.FromHdc(hdc);
+ hwnd.drawing_stack.Push (dc);
+
+ paint_event = new PaintEventArgs(dc, clip_rect);
return paint_event;
}
internal override void PaintEventEnd(IntPtr handle, bool client) {
Hwnd hwnd;
- PAINTSTRUCT ps;
hwnd = Hwnd.ObjectFromHandle(handle);
- hwnd.client_dc.Dispose();
+
+ Graphics dc = (Graphics)hwnd.drawing_stack.Pop();
+ dc.Dispose ();
if (client) {
- if (hwnd.user_data != null) {
- ps = (PAINTSTRUCT)hwnd.user_data;
+ object o = hwnd.drawing_stack.Pop();
+ if (o != null) {
+ PAINTSTRUCT ps = (PAINTSTRUCT)o;
Win32EndPaint(handle, ref ps);
- hwnd.user_data = null;
}
} else {
- if (hwnd.user_data != null) {
- Win32ReleaseDC(handle, (IntPtr)hwnd.user_data);
- hwnd.user_data = null;
- }
+ IntPtr hdc = (IntPtr)hwnd.drawing_stack.Pop();
+ Win32ReleaseDC(handle, hdc);
}
}
Win32InvalidateRect(handle, ref rect, clear);
}
+
+ internal override void InvalidateNC (IntPtr handle)
+ {
+ // found this gem at
+ // http://www.dotnet247.com/247reference/msgs/58/292037.aspx
+ Win32SetWindowPos(handle, IntPtr.Zero,
+ 0, 0, 0, 0,
+ SetWindowPosFlags.SWP_NOMOVE |
+ SetWindowPosFlags.SWP_NOSIZE |
+ SetWindowPosFlags.SWP_NOZORDER |
+ SetWindowPosFlags.SWP_NOACTIVATE |
+ SetWindowPosFlags.SWP_DRAWFRAME);
+ }
+
internal override IntPtr DefWndProc(ref Message msg) {
msg.Result=Win32DefWindowProc(msg.HWnd, (Msg)msg.Msg, msg.WParam, msg.LParam);
return msg.Result;
Win32PostQuitMessage(exitCode);
}
+ internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
+ {
+ if (wm_nc_registered == null)
+ wm_nc_registered = new Hashtable ();
+
+ TMEFlags flags = TMEFlags.TME_NONCLIENT;
+ if (hover)
+ flags |= TMEFlags.TME_HOVER;
+ if (leave)
+ flags |= TMEFlags.TME_LEAVE;
+
+ if (flags == TMEFlags.TME_NONCLIENT) {
+ if (wm_nc_registered.Contains (hwnd)) {
+ wm_nc_registered.Remove (hwnd);
+ }
+ } else {
+ if (!wm_nc_registered.Contains (hwnd)) {
+ wm_nc_registered.Add (hwnd, flags);
+ } else {
+ wm_nc_registered [hwnd] = flags;
+ }
+ }
+ }
+
internal override void RequestNCRecalc(IntPtr handle) {
Win32SetWindowPos(handle, IntPtr.Zero, 0, 0, 0, 0, SetWindowPosFlags.SWP_FRAMECHANGED | SetWindowPosFlags.SWP_NOOWNERZORDER | SetWindowPosFlags.SWP_NOSIZE | SetWindowPosFlags.SWP_NOMOVE);
}
break;
}
+ case Msg.WM_NCMOUSEMOVE: {
+ if (wm_nc_registered == null || !wm_nc_registered.Contains (msg.hwnd))
+ break;
+
+ TRACKMOUSEEVENT tme;
+
+ tme = new TRACKMOUSEEVENT ();
+ tme.size = Marshal.SizeOf(tme);
+ tme.hWnd = msg.hwnd;
+ tme.dwFlags = (TMEFlags)wm_nc_registered[msg.hwnd];
+ Win32TrackMouseEvent (ref tme);
+ return result;
+ }
+
case Msg.WM_DROPFILES: {
return Win32DnD.HandleWMDropFiles(ref msg);
}
return true;
}
- internal override bool SetVisible(IntPtr handle, bool visible) {
+ internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
+ {
if (visible) {
- if (Control.FromHandle(handle) is Form) {
+ if (Control.FromHandle (handle) is Form) {
Form f;
- f = (Form)Control.FromHandle(handle);
+ f = (Form)Control.FromHandle (handle);
+ WindowPlacementFlags flags = WindowPlacementFlags.SW_SHOWNORMAL;
switch (f.WindowState) {
- case FormWindowState.Normal: Win32ShowWindow(handle, WindowPlacementFlags.SW_SHOWNORMAL); break;
- case FormWindowState.Minimized: Win32ShowWindow(handle, WindowPlacementFlags.SW_MINIMIZE); break;
- case FormWindowState.Maximized: Win32ShowWindow(handle, WindowPlacementFlags.SW_MAXIMIZE); break;
+ case FormWindowState.Normal: flags = WindowPlacementFlags.SW_SHOWNORMAL; break;
+ case FormWindowState.Minimized: flags = WindowPlacementFlags.SW_MINIMIZE; break;
+ case FormWindowState.Maximized: flags = WindowPlacementFlags.SW_MAXIMIZE; break;
}
- } else {
- Win32ShowWindow(handle, WindowPlacementFlags.SW_SHOWNORMAL);
+
+ if (Hwnd.ObjectFromHandle (handle).no_activate)
+ flags |= WindowPlacementFlags.SW_SHOWNOACTIVATE;
+
+ Win32ShowWindow (handle, flags);
}
- } else {
- Win32ShowWindow(handle, WindowPlacementFlags.SW_HIDE);
+ else {
+ if (Hwnd.ObjectFromHandle (handle).no_activate)
+ Win32ShowWindow (handle, WindowPlacementFlags.SW_SHOWNOACTIVATE);
+ else
+ Win32ShowWindow (handle, WindowPlacementFlags.SW_SHOWNORMAL);
+ }
+ }
+ else {
+ Win32ShowWindow (handle, WindowPlacementFlags.SW_HIDE);
}
return true;
}
}
internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
- return Win32SetParent(handle, parent);
+ Control c = Control.FromHandle (handle);
+ if (parent == IntPtr.Zero) {
+ if (!(c is Form)) {
+ Win32ShowWindow(handle, WindowPlacementFlags.SW_HIDE);
+ }
+ }
+ else
+ SetVisible (handle, c.is_visible, true);
+
+ if (parent == IntPtr.Zero)
+ return Win32SetParent (handle, FosterParent);
+ else
+ return Win32SetParent(handle, parent);
}
+ // If we ever start using this, we should probably replace FosterParent with IntPtr.Zero
internal override IntPtr GetParent(IntPtr handle) {
return Win32GetParent(handle);
}
Win32SetROP2(hdc, ROP2DrawMode.R2_NOT);
oldpen = Win32SelectObject(hdc, pen);
- // We might need to add clipping to the WindowRect of 'handle' - right now we're drawing on the desktop
+ Control c = Control.FromHandle (handle);
+ if (c != null) {
+ Region r = new Region(new Rectangle(c.PointToScreen (c.Location), c.Size));
+
+ Win32ExtSelectClipRgn(hdc, r.GetHrgn (Graphics.FromHdc (hdc)), (int) ClipCombineMode.RGN_AND);
+ }
Win32MoveToEx(hdc, pt.x + rect.Left, pt.y + rect.Top, IntPtr.Zero);
if ((rect.Width > 0) && (rect.Height > 0)) {
Win32SelectObject(hdc, oldpen);
Win32DeleteObject(pen);
+ if (c != null)
+ Win32ExtSelectClipRgn(hdc, IntPtr.Zero, (int) ClipCombineMode.RGN_COPY);
+
Win32ReleaseDC(IntPtr.Zero, hdc);
}
internal override event EventHandler Idle;
- // Santa's little helper
- static void Where() {
- Console.WriteLine("Here: {0}", new StackTrace().ToString());
- }
#endregion // Public Static Methods
#region Win32 Imports
[DllImport ("user32.dll", EntryPoint="SetLayeredWindowAttributes", CallingConvention=CallingConvention.StdCall)]
private extern static uint Win32SetLayeredWindowAttributes (IntPtr hwnd, COLORREF crKey, byte bAlpha, LayeredWindowAttributes dwFlags);
+ [DllImport ("user32.dll", EntryPoint="GetLayeredWindowAttributes", CallingConvention=CallingConvention.StdCall)]
+ 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);
[DllImport ("gdi32.dll", EntryPoint="CreateHatchBrush", CallingConvention=CallingConvention.StdCall)]
internal extern static IntPtr Win32CreateHatchBrush(HatchStyle fnStyle, ref COLORREF color);
+ [DllImport("gdi32.dll", EntryPoint = "ExcludeClipRect", CallingConvention = CallingConvention.StdCall)]
+ internal extern static int Win32ExcludeClipRect (IntPtr hdc, int left, int top, int right, int bottom);
+
+ [DllImport ("gdi32.dll", EntryPoint="ExtSelectClipRgn", CallingConvention=CallingConvention.StdCall)]
+ internal extern static int Win32ExtSelectClipRgn(IntPtr hdc, IntPtr hrgn, int mode);
+
[DllImport ("winmm.dll", EntryPoint="PlaySoundW", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode)]
internal extern static IntPtr Win32PlaySound(string pszSound, IntPtr hmod, SndFlags fdwSound);