I created a simple white control with a black border derived from HwndHost (named LightGrid) and added it to ScrollViewer along with some other controls (replaced with “…”) as shown below:
<ScrollViewer HorizontalScrollBarVisibility="Disabled">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
...
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
...
</Grid.RowDefinitions>
...
<Border Grid.Row="6" Grid.ColumnSpan="2" Visibility="Visible" Height="200">
<nc:LightGrid />
</Border>
</Grid>
</ScrollViewer>
It looks correctly in the lower scroll position, and it even can scroll inside ScrollViewer (it moves when I move the scroll bar), but when scrolled, it is not clipped so it obscures other controls:
There is some solution in the internet based on handling ScrollChangedEvent and manipulation with window region via SetWindowRgn Win32 function. It looks a bit scary and probably in practice it can produce some specific effects, so we should avoid using HwndHost inside ScrollViewer.
Below I provided all the source code of HwndHost based control, it uses some MFC control CHybridCtrl internally:
#pragma once
#include "GridCtrl.h"
using namespace System;
using namespace System::Windows;
using namespace System::Windows::Interop;
using namespace System::Runtime::InteropServices;
namespace NativeControls
{
public ref class LightGrid : public HwndHost //,IKeyboardInputSink
{
public:
protected:
virtual HandleRef BuildWindowCore(HandleRef hwndParent) override;
virtual void DestroyWindowCore(HandleRef hwnd) override;
//virtual void OnWindowPositionChanged(Rect rcBoundingBox) override;
private:
CHybridCtrl * pGrid = nullptr;
};
}
#include "stdafx.h"
#include "LightGrid.h"
#include "resource.h"
namespace NativeControls
{
HandleRef LightGrid::BuildWindowCore(HandleRef hwndParent)
{
pGrid = new CHybridCtrl();
//pGrid->SetStyles(SharedObjects::GetStyles());
//pGrid->SetTool(ID_EDIT_CELL_SELECT_TOOL);
HWND hParent = (HWND)hwndParent.Handle.ToPointer();
if (!pGrid->CreateEx(0, WS_CHILD | WS_VISIBLE | WS_BORDER,
hParent, 1000))
{
throw gcnew InvalidOperationException("Can not create CHybridCtrl.");
}
return HandleRef(this, IntPtr(pGrid->m_hWnd));
}
void LightGrid::DestroyWindowCore(HandleRef hwnd)
{
// hwnd will be disposed for us
delete pGrid;
}
//void LightGrid::OnWindowPositionChanged(Rect rcBoundingBox)
//{
// CRect rc(rcBoundingBox.Left, rcBoundingBox.Top, rcBoundingBox.Right, rcBoundingBox.Bottom);
//
// pGrid->MoveWindow(&rc);
//}
}

