WPF 로 개발을 할때 종종 WindowsFormsHost 를 이용해 Winfrom Control 을 올려놓고 사용할 때가 있습니다.
그런데 화면에 내용이 많아 스크롤이 생긴 경우 스크롤을 하게되면
WindowsFormsHost 가 WPF 컨트롤을 가리면서 Overflow 되어 표시되는 경우가 생깁니다.
이때는 Scrolling 을 해결한 새로운 WindowsFormHost 를 만들어 사용하면 해결됩니다.
아래 코드를 보면 알수 있듯이 Win32 API를 사용하여 HWND 영역을 새로 그려주도록 하면됩니다.
아래 코드를 참고하여 ScrollViewerWindowsFormsHost 를 추가합니다.
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms.Integration;
using System.Windows.Media;
namespace Yournamespace
{
public class ScrollViewerWindowsFormsHost : WindowsFormsHost
{
private PresentationSource _presentationSource;
public ScrollViewerWindowsFormsHost()
{
PresentationSource.AddSourceChangedHandler(this, SourceChangedEventHandler);
}
protected override void OnWindowPositionChanged(Rect rcBoundingBox)
{
base.OnWindowPositionChanged(rcBoundingBox);
if (ParentScrollViewer == null)
return;
GeneralTransform tr = RootVisual.TransformToDescendant(ParentScrollViewer);
var scrollRect = new Rect(new Size(ParentScrollViewer.ViewportWidth, ParentScrollViewer.ViewportHeight));
var intersect = Rect.Intersect(scrollRect, tr.TransformBounds(rcBoundingBox));
if (!intersect.IsEmpty)
{
tr = ParentScrollViewer.TransformToDescendant(this);
intersect = tr.TransformBounds(intersect);
}
else
intersect = new Rect();
int x1 = (int)Math.Round(intersect.Left);
int y1 = (int)Math.Round(intersect.Top);
int x2 = (int)Math.Round(intersect.Right);
int y2 = (int)Math.Round(intersect.Bottom);
SetRegion(x1, y1, x2, y2);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
PresentationSource.RemoveSourceChangedHandler(this, SourceChangedEventHandler);
}
private void SourceChangedEventHandler(Object sender, SourceChangedEventArgs e)
{
ParentScrollViewer = FindParentScrollViewer();
}
private ScrollViewer FindParentScrollViewer()
{
DependencyObject vParent = this;
ScrollViewer parentScroll = null;
while (vParent != null)
{
parentScroll = vParent as ScrollViewer;
if (parentScroll != null)
break;
vParent = LogicalTreeHelper.GetParent(vParent);
}
return parentScroll;
}
private void SetRegion(int x1, int y1, int x2, int y2)
{
SetWindowRgn(Handle, CreateRectRgn(x1, y1, x2, y2), true);
}
Visual RootVisual
{
get
{
if (_presentationSource == null)
_presentationSource = PresentationSource.FromVisual(this);
return _presentationSource.RootVisual;
}
}
ScrollViewer ParentScrollViewer { get; set; }
[DllImport("User32.dll", SetLastError = true)]
static extern int SetWindowRgn(IntPtr hWnd, IntPtr hRgn, bool bRedraw);
[DllImport("gdi32.dll")]
static extern IntPtr CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
}
}
XAML 단에서 WindowsFormsHost 대신 ScrollViewerWindowsFormsHost 를 사용하면
Scrolling 시 화면을 가리는 문제가 해결됩니다.
C# ExpandObject 사용하여 동적 데이터 다루기 (0) | 2024.02.23 |
---|---|
.NET 랜덤 한 X,Y 축 값 도출하기 (0) | 2024.02.18 |
TChart Legend 클릭 시 잘못된 Series Index 반환하는 버그 수정 (0) | 2024.02.16 |
TChart Legend 클릭 시 선택한 Series 강조하기 (0) | 2024.02.15 |
WPF WindowsFormsHost 사용 시 Scroll 문제와 DPI (0) | 2024.02.15 |