A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

143 lines
4.5 KiB

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Perspex.Designer.AppHost
{
class WindowHost : UserControl
{
private readonly bool _supportScroll;
public WindowHost(bool supportScroll)
{
_supportScroll = supportScroll;
if (_supportScroll)
{
AutoScroll = true;
VerticalScroll.Enabled = true;
HorizontalScroll.Enabled = true;
}
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
Controls.Add(_windowHost);
_windowHost.Anchor = AnchorStyles.None;
if (!supportScroll)
_windowHost.Visible = false;
_timer.Tick += delegate
{
ReloadSettings();
FixWindow();
};
}
private void ReloadSettings()
{
var bkg = Settings.Background;
var color = System.Drawing.ColorTranslator.FromHtml(bkg);
if (BackColor != color)
BackColor = color;
}
private readonly Control _windowHost = new Control() {Text = "WindowWrapper"};
private readonly Timer _timer = new Timer {Enabled = true, Interval = 50};
private IntPtr _hWnd;
private int _desiredWidth;
private int _desiredHeight;
private const int WM_HSCROLL = 0x114;
private const int WM_VSCROLL = 0x115;
protected override void WndProc(ref Message m)
{
if ((m.Msg == WM_HSCROLL || m.Msg == WM_VSCROLL)
&& (((int) m.WParam & 0xFFFF) == 5))
{
// Change SB_THUMBTRACK to SB_THUMBPOSITION
m.WParam = (IntPtr) (((int) m.WParam & ~0xFFFF) | 4);
}
base.WndProc(ref m);
}
protected override void OnPaint(PaintEventArgs e)
{
using (var b = new SolidBrush(BackColor))
e.Graphics.FillRectangle(b, e.ClipRectangle);
}
void FixPosition()
{
var newScrollSize = new Size(_desiredWidth, _desiredHeight);
if (AutoScrollMinSize != newScrollSize)
AutoScrollMinSize = newScrollSize;
var width = Width - AutoScrollMargin.Width;
var height = Height - AutoScrollMargin.Height;
var x = Math.Max(0, (width - _windowHost.Width)/2);
var y = Math.Max(0, (height - _windowHost.Height)/2);
var newLoc = new Point(x - HorizontalScroll.Value, y - VerticalScroll.Value);
if(_windowHost.Location != newLoc)
_windowHost.Location = newLoc;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_timer.Dispose();
}
base.Dispose(disposing);
}
public void SetWindow(IntPtr hWnd)
{
if (_hWnd != IntPtr.Zero)
WinApi.SendMessage(_hWnd, WinApi.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
_hWnd = hWnd;
if (_hWnd != IntPtr.Zero)
{
WinApi.SetParent(hWnd, _supportScroll ? _windowHost.Handle : Handle);
FixWindow();
}
}
void FixWindow()
{
if (_hWnd != IntPtr.Zero)
{
if (_supportScroll)
{
WinApi.RECT rc;
WinApi.GetWindowRect(_hWnd, out rc);
_desiredWidth = rc.Right - rc.Left;
_desiredHeight = rc.Bottom - rc.Top;
var pt = _windowHost.PointToClient(new Point(rc.Left, rc.Top));
if (
!(pt.Y == 0 && pt.X == 0 && _desiredWidth == _windowHost.Width &&
_desiredHeight == _windowHost.Height))
{
_windowHost.Width = _desiredWidth;
_windowHost.Height = _desiredHeight;
WinApi.MoveWindow(_hWnd, 0, 0, _desiredWidth, _desiredHeight, true);
}
FixPosition();
}
else
{
WinApi.MoveWindow(_hWnd, 0, 0, Width, Height, true);
}
}
}
protected override void OnResize(EventArgs e)
{
FixWindow();
base.OnResize(e);
}
}
}