I have WindowsFormHost with a RichTextBox in my WPF form, i have given ScrollViewer for
If your WindowsFormsHost is to be placed inside a UserControl, then the answer presented by Avinash may not work. So I had to tweak the ScrollViewerWindowsFormsHost class as follows.
public class ScrollViewerWindowsFormsHost : WindowsFormsHost
{
protected override void OnWindowPositionChanged(Rect rcBoundingBox)
{
base.OnWindowPositionChanged(rcBoundingBox);
if (ParentScrollViewer == null)
//return; // Instead, you set the ParentScrollViewr by calling the following method.
SetParentScrollViewer();
GeneralTransform tr = ParentScrollViewer.TransformToAncestor(MainWindow);
var scrollRect = new Rect(new Size(ParentScrollViewer.ViewportWidth, ParentScrollViewer.ViewportHeight));
scrollRect = tr.TransformBounds(scrollRect);
var intersect = Rect.Intersect(scrollRect, rcBoundingBox);
if (!intersect.IsEmpty)
{
tr = MainWindow.TransformToDescendant(this);
intersect = tr.TransformBounds(intersect);
}
SetRegion(intersect);
}
// This is new a new method. This is called from the above method.
private void SetParentScrollViewer()
{
if (ParentScrollViewer is ScrollViewer)
return; // that means its already set;
var p = Parent as FrameworkElement;
while (p != null)
{
if (p is ScrollViewer)
{
ParentScrollViewer = (ScrollViewer)p;
break;
}
p = p.Parent as FrameworkElement;
}
}
// Just comment out this method, you dont need this any more. You set the parent Scroll Viewer by calling SetParentScrollViewer Method.
//protected override void OnVisualParentChanged(DependencyObject oldParent)
//{
// base.OnVisualParentChanged(oldParent);
// ParentScrollViewer = null;
// var p = Parent as FrameworkElement;
// while (p != null)
// {
// if (p is ScrollViewer)
// {
// ParentScrollViewer = (ScrollViewer)p;
// break;
// }
// p = p.Parent as FrameworkElement;
// }
//}
private void SetRegion(Rect intersect)
{
using (var graphics = System.Drawing.Graphics.FromHwnd(Handle))
SetWindowRgn(Handle, (new System.Drawing.Region(ConvertRect(intersect))).GetHrgn(graphics), true);
}
static System.Drawing.RectangleF ConvertRect(Rect r)
{
return new System.Drawing.RectangleF((float)r.X, (float)r.Y, (float)r.Width, (float)r.Height);
}
private Window _mainWindow;
Window MainWindow
{
get
{
if (_mainWindow == null)
_mainWindow = Window.GetWindow(this);
return _mainWindow;
}
}
ScrollViewer ParentScrollViewer { get; set; }
[DllImport("User32.dll", SetLastError = true)]
public static extern int SetWindowRgn(IntPtr hWnd, IntPtr hRgn, bool bRedraw);
}
Thats it. Every thing remains the same.