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); //} }