wpfscrollviewerwindowsformshost

ScrollViewer is not working in WPF WindowsFormHost


enter image description hereI have WindowsFormHost with a RichTextBox in my WPF form, i have given ScrollViewer for that WindowsFormHost but its not working, WindowsFormHost going outside of ScrollViewer...

My XAML is..

<ScrollViewer Background="DarkOrange" VerticalScrollBarVisibility="Auto" Height="80" MaxHeight="85" Margin="11,243,12,218" Width="756">
        <Canvas Height="100" Name="canvas1" Width="auto" >
            <WindowsFormsHost ClipToBounds="True" Height="120" Width="715" Margin="10,5,0,0" Name="winHostTEst" Background="Gray">
                <wf:RichTextBox BackColor="Cornsilk" Text="RichTextBox" x:Name="richTbTest" BorderStyle="None" Enabled="True" ForeColor="Black" Width="550" Multiline="True" ReadOnly="True" />
            </WindowsFormsHost>
        </Canvas>
    </ScrollViewer>

Here are two links with solution of this problem, but i am not able to implement that.. Please have a look to these links also and solve my problem..

links are:

http://blogs.msdn.com/b/ryanvog/archive/2009/01/20/clipping-legacy-content-hosted-inside-a-wpf-scrolling-region.aspx

http://www.mycsharp.de/wbb2/thread.php?threadid=76625

Thanks in advance..


Solution

  • Finally got the solution

    Create this Class in your solution for above problem, and take new class control (ScrollViewerWindowsFormsHost) instead of WindowsFormsHost

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms.Integration;
    using System.Windows.Media;
    using System.Runtime.InteropServices;
    using System.Windows;
    using System.Windows.Controls;
    
    namespace WPFRichTextBox
    {
    class ScrollViewerWindowsFormsHost: WindowsFormsHost
    {
    
        protected override void OnWindowPositionChanged(Rect rcBoundingBox)
        {
            base.OnWindowPositionChanged(rcBoundingBox);
    
            if (ParentScrollViewer == null)
                return;
    
            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);
        }
    
        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);
    }
    

    }

    XAML Code:

    <Window x:Class="WPFRichTextBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
        xmlns:swfh="clr-namespace:WPFRichTextBox"
        Title="MainWindow" Height="600" Width="800" Background="LightBlue">
    <Grid Loaded="Grid_Loaded">
    
        <ScrollViewer  Background="DarkOrange" VerticalScrollBarVisibility="Auto" Height="100"  Margin="11,160,12,301" Width="756" Name="scrollViewer1">
            <Canvas Height="200" Name="canvas1" Width="auto" >
          <swfh:ScrollableWindowsFormsHost ClipToBounds="True" Height="194" Width="715" Margin="10,5,0,0" Background="Gray">
                    <wf:RichTextBox BackColor="Cornsilk" Text="RichTextBox" x:Name="richTbTest" BorderStyle="None" Enabled="True" ForeColor="Black" Width="550" Multiline="True" ReadOnly="True" />
          </swfh:ScrollableWindowsFormsHost>
            </Canvas>
        </ScrollViewer>
    </Grid>