ScrollViewer is not working in WPF WindowsFormHost

前端 未结 6 887
半阙折子戏
半阙折子戏 2020-12-14 23:00

\"enterI have WindowsFormHost with a RichTextBox in my WPF form, i have given ScrollViewer for

6条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-14 23:40

    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.

提交回复
热议问题