CanvasControl.ClearColor property

This gives control over the color that the CanvasControl is cleared to before the Draw event is raised.
This commit is contained in:
Damyan Pepper 2014-10-29 14:40:15 -07:00
Родитель 460b22abd2
Коммит beba8c5df4
20 изменённых файлов: 329 добавлений и 84 удалений

Просмотреть файл

@ -21,17 +21,13 @@ To give you a flavor of what the code looks like, here is a snippet of XAML:
xmlns:canvas="using:Microsoft.Graphics.Canvas"
<Grid>
<canvas:CanvasControl x:Name="canvasControl" />
<canvas:CanvasControl x:Name="canvasControl" Draw="canvasControl_Draw" ClearColor="CornflowerBlue" />
</Grid>
```
and C#:
```cs
canvasControl.Draw += canvasControl_Draw;
```
```cs
void canvasControl_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
args.DrawingSession.Clear(Colors.CornflowerBlue);
args.DrawingSession.DrawEllipse(155, 115, 80, 30, Colors.Black, 3);
args.DrawingSession.DrawText("Hello, world!", 100, 100, Colors.Yellow);
}

Просмотреть файл

@ -54,8 +54,6 @@ namespace ExampleGallery
{
var ds = args.DrawingSession;
ds.Clear(Color.FromArgb(0, 0, 0, 0));
// If the window size has changed, (re)create the text bitmap.
var newCanvasSize = new Size(sender.ActualWidth, sender.ActualHeight);
if (oldCanvasSize != newCanvasSize)

Просмотреть файл

@ -55,8 +55,6 @@ namespace ExampleGallery
private void DrawCanvasState(CanvasControl canvas, CanvasDrawingSession ds, int drawCount)
{
ds.Clear(Color.FromArgb(0, 0, 0, 0));
ds.DrawLine(0, 0, (float)canvas.ActualWidth, (float)canvas.ActualHeight, Colors.Aqua);
ds.DrawLine(0, (float)canvas.ActualHeight, (float)canvas.ActualWidth, 0, Colors.Aqua);

Просмотреть файл

@ -82,7 +82,6 @@ namespace ExampleGallery
private void Canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
var ds = args.DrawingSession;
ds.Clear(Color.FromArgb(0, 0, 0, 0));
if (!isLoaded)
return;
@ -758,7 +757,7 @@ namespace ExampleGallery
using (var ds = renderTarget.CreateDrawingSession())
{
ds.Clear(Colors.Transparent);
ds.Clear(Color.FromArgb(0, 0, 0, 0));
ds.DrawText("This text is drawn onto a rendertarget", 10, 10, Colors.White);
ds.DrawText("with a different color per line,", 10, 40, Colors.Red);
@ -850,7 +849,7 @@ namespace ExampleGallery
using (var ds = textOverlay.CreateDrawingSession())
{
ds.Clear(Colors.Transparent);
ds.Clear(Color.FromArgb(0, 0, 0, 0));
ds.DrawText(effect.GetType().Name.Replace("Effect", ""), 0, 0, Colors.White);
}

Просмотреть файл

@ -81,8 +81,6 @@ namespace ExampleGallery
}
}
args.DrawingSession.Clear(Color.FromArgb(0, 0, 0, 0));
// Display the current surface.
invertEffect.Source = currentSurface;
transformEffect.TransformMatrix = GetDisplayTransform();

Просмотреть файл

@ -61,7 +61,6 @@ namespace ExampleGallery
void Canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
var ds = args.DrawingSession;
ds.Clear(Color.FromArgb(0,0,0,0));
var shape = this.Shapes.SelectedItem as Shape;
if (shape == null)

Просмотреть файл

@ -62,8 +62,6 @@ namespace ExampleGallery
var ds = args.DrawingSession;
ds.Clear(Color.FromArgb(0, 0, 0, 0));
var width = (float)sender.ActualWidth;
var height = (float)sender.ActualHeight;

Просмотреть файл

@ -46,8 +46,6 @@ under the License.
<code>
void myWidget_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
args.DrawingSession.Clear(Colors.CornflowerBlue);
if (isLoaded)
{
args.DrawingSession.DrawImage(cat, new Point(42, 42));

Просмотреть файл

@ -34,7 +34,7 @@ under the License.
<p>Add a CanvasControl to the page:</p>
<code>
&lt;Grid&gt;
&lt;canvas:CanvasControl x:Name="myWidget"/&gt;
&lt;canvas:CanvasControl x:Name="myWidget" CreateResources="myWidget_CreateResources" Draw="myWidget_Draw" ClearColor="CornFlowerBlue"/&gt;
&lt;/Grid&gt;
</code>
<p>Edit MainPage.xaml.cs, and add some drawing code:</p>
@ -46,9 +46,6 @@ under the License.
public MainPage()
{
this.InitializeComponent();
myWidget.CreateResources += myWidget_CreateResources;
myWidget.Draw += myWidget_Draw;
}
void myWidget_CreateResources(CanvasControl sender, object args)
@ -59,7 +56,6 @@ under the License.
void myWidget_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
args.DrawingSession.Clear(Colors.CornflowerBlue);
args.DrawingSession.DrawEllipse(155, 115, 80, 30, Colors.Black, 3);
args.DrawingSession.DrawText("Hello, world!", 100, 100, Colors.Yellow);
}
@ -106,6 +102,18 @@ under the License.
so you can draw different things each time.</p>
</remarks>
</member>
<member name="P:Microsoft.Graphics.Canvas.CanvasControl.ClearColor">
<summary>The color that the control is cleared to before the Draw event is raised.</summary>
<remarks>
<p>
ClearColor defaults to transparent black, that is Color.FromArgb(0,0,0,0).
</p>
<p>
Modifying ClearColor will cause the control to redraw, as if
Invalidate() was called.
</p>
</remarks>
</member>
<member name="T:Microsoft.Graphics.Canvas.CanvasDrawEventArgs">
@ -118,6 +126,5 @@ under the License.
<summary>Gets the drawing session for use by the current event handler.
This provides methods to draw lines, rectangles, text etc.</summary>
</member>
</members>
</doc>

Просмотреть файл

@ -37,7 +37,6 @@ under the License.
<code>
void myWidget_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
args.DrawingSession.Clear(Colors.CornflowerBlue);
args.DrawingSession.DrawImage(blendEffect, new Point(42, 42));
}
</code>

Просмотреть файл

@ -34,7 +34,6 @@ under the License.
<code>
void myWidget_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
args.DrawingSession.Clear(Colors.CornflowerBlue);
args.DrawingSession.DrawImage(compositeEffect, new Point(42, 42));
}
</code>

Просмотреть файл

@ -35,7 +35,6 @@ under the License.
<code>
void myWidget_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
args.DrawingSession.Clear(Colors.CornflowerBlue);
args.DrawingSession.DrawImage(blurEffect, new Point(42, 42));
}
</code>

Просмотреть файл

@ -35,7 +35,6 @@ under the License.
<code>
void myWidget_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
args.DrawingSession.Clear(Colors.CornflowerBlue);
args.DrawingSession.DrawImage(saturationEffect, new Point(42, 42));
}
</code>

Просмотреть файл

@ -35,7 +35,6 @@ under the License.
<code>
void myWidget_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
args.DrawingSession.Clear(Colors.CornflowerBlue);
args.DrawingSession.DrawImage(transformEffect, new Point(42, 42));
}
</code>

Просмотреть файл

@ -53,6 +53,14 @@ namespace Microsoft.Graphics.Canvas
[eventremove] HRESULT Draw([in] EventRegistrationToken token);
//
// Before the Draw event is raised, the control is cleared to
// ClearColor. ClearColor defaults to transparent black (0,0,0,0).
// Setting ClearColor to a different value triggers a Draw.
//
[propput] HRESULT ClearColor([in] Windows.UI.Color value);
[propget] HRESULT ClearColor([out, retval] Windows.UI.Color* value);
HRESULT Invalidate();
}

Просмотреть файл

@ -183,16 +183,17 @@ namespace ABI { namespace Microsoft { namespace Graphics { namespace Canvas
handler);
}
virtual ComPtr<CanvasImageSource> CreateCanvasImageSource(ICanvasDevice* device, int width, int height) override
virtual ComPtr<CanvasImageSource> CreateCanvasImageSource(ICanvasDevice* device, int width, int height, CanvasBackground backgroundMode) override
{
ComPtr<ICanvasResourceCreator> resourceCreator;
ThrowIfFailed(device->QueryInterface(resourceCreator.GetAddressOf()));
ComPtr<ICanvasImageSource> imageSource;
ThrowIfFailed(m_canvasImageSourceFactory->Create(
ThrowIfFailed(m_canvasImageSourceFactory->CreateWithBackground(
resourceCreator.Get(),
width,
height,
height,
backgroundMode,
&imageSource));
// Since we know that CanvasImageSourceFactory will only ever return
@ -298,6 +299,7 @@ namespace ABI { namespace Microsoft { namespace Graphics { namespace Canvas
, m_needToHookCompositionRendering(false)
, m_imageSourceNeedsReset(false)
, m_isLoaded(false)
, m_clearColor{}
, m_currentWidth(0)
, m_currentHeight(0)
{
@ -446,7 +448,8 @@ namespace ABI { namespace Microsoft { namespace Graphics { namespace Canvas
m_canvasImageSource = m_adapter->CreateCanvasImageSource(
m_canvasDevice.Get(),
width,
height);
height,
m_clearColor.A == 255 ? CanvasBackground::Opaque : CanvasBackground::Transparent);
m_currentWidth = width;
m_currentHeight = height;
@ -471,7 +474,7 @@ namespace ABI { namespace Microsoft { namespace Graphics { namespace Canvas
return;
}
auto drawingSession = m_canvasImageSource->CreateDrawingSessionWithDpi(Color{}, m_adapter->GetLogicalDpi());
auto drawingSession = m_canvasImageSource->CreateDrawingSessionWithDpi(m_clearColor, m_adapter->GetLogicalDpi());
ComPtr<CanvasDrawEventArgs> drawEventArgs = Make<CanvasDrawEventArgs>(drawingSession.Get());
CheckMakeResult(drawEventArgs);
@ -591,6 +594,41 @@ namespace ABI { namespace Microsoft { namespace Graphics { namespace Canvas
});
}
IFACEMETHODIMP CanvasControl::put_ClearColor(Color value)
{
return ExceptionBoundary(
[&]
{
if (m_clearColor.A == value.A &&
m_clearColor.R == value.R &&
m_clearColor.G == value.G &&
m_clearColor.B == value.B)
{
return;
}
bool wasOpaque = (m_clearColor.A == 255);
bool isOpaque = (value.A == 255);
auto invalidateReason = InvalidateReason::Default;
if (wasOpaque != isOpaque)
invalidateReason = InvalidateReason::ImageSourceNeedsReset;
m_clearColor = value;
InvalidateImpl(invalidateReason);
});
}
IFACEMETHODIMP CanvasControl::get_ClearColor(Color* value)
{
return ExceptionBoundary(
[&]
{
CheckInPointer(value);
*value = m_clearColor;
});
}
HRESULT CanvasControl::OnCompositionRendering(IInspectable*, IInspectable*)
{
return ExceptionBoundary(
@ -611,8 +649,20 @@ namespace ABI { namespace Microsoft { namespace Graphics { namespace Canvas
bool CanvasControl::IsWindowVisible()
{
boolean visible;
ThrowIfFailed(m_window->get_Visible(&visible));
return !!visible;
HRESULT hr = m_window->get_Visible(&visible);
if (hr == E_FAIL)
{
// In design mode get_Visible will return E_FAIL. In this case we
// just treat the window as visible.
return true;
}
else
{
ThrowIfFailed(hr);
return !!visible;
}
}
@ -630,7 +680,7 @@ namespace ABI { namespace Microsoft { namespace Graphics { namespace Canvas
{
std::lock_guard<std::mutex> lock(m_drawLock);
if (reason == InvalidateReason::SurfaceContentsLost)
if (reason == InvalidateReason::ImageSourceNeedsReset)
m_imageSourceNeedsReset = true;
if (m_renderingEventRegistration)
@ -734,7 +784,7 @@ namespace ABI { namespace Microsoft { namespace Graphics { namespace Canvas
return ExceptionBoundary(
[&]
{
InvalidateImpl(InvalidateReason::SurfaceContentsLost);
InvalidateImpl(InvalidateReason::ImageSourceNeedsReset);
});
}

Просмотреть файл

@ -61,7 +61,7 @@ namespace ABI { namespace Microsoft { namespace Graphics { namespace Canvas
virtual RegisteredEvent AddCompositionRenderingCallback(IEventHandler<IInspectable*>*) = 0;
virtual RegisteredEvent AddSurfaceContentsLostCallback(IEventHandler<IInspectable*>*) = 0;
virtual RegisteredEvent AddVisibilityChangedCallback(IWindowVisibilityChangedEventHandler*, IWindow*) = 0;
virtual ComPtr<CanvasImageSource> CreateCanvasImageSource(ICanvasDevice* device, int width, int height) = 0;
virtual ComPtr<CanvasImageSource> CreateCanvasImageSource(ICanvasDevice* device, int width, int height, CanvasBackground backgroundMode) = 0;
virtual ComPtr<IImage> CreateImageControl() = 0;
virtual float GetLogicalDpi() = 0;
@ -133,6 +133,8 @@ namespace ABI { namespace Microsoft { namespace Graphics { namespace Canvas
bool m_imageSourceNeedsReset;
bool m_isLoaded;
Color m_clearColor;
int m_currentWidth;
int m_currentHeight;
@ -160,6 +162,10 @@ namespace ABI { namespace Microsoft { namespace Graphics { namespace Canvas
IFACEMETHODIMP remove_Draw(
EventRegistrationToken token);
IFACEMETHODIMP put_ClearColor(Color value);
IFACEMETHODIMP get_ClearColor(Color* value);
//
// ICanvasResourceCreator
//
@ -202,7 +208,7 @@ namespace ABI { namespace Microsoft { namespace Graphics { namespace Canvas
enum class InvalidateReason
{
Default,
SurfaceContentsLost
ImageSourceNeedsReset
};
void InvalidateImpl(InvalidateReason reason = InvalidateReason::Default);

Просмотреть файл

@ -28,7 +28,7 @@ public:
ComPtr<MockEventSourceUntyped> CompositionRenderingEventSource;
ComPtr<MockEventSourceUntyped> SurfaceContentsLostEventSource;
ComPtr<MockEventSource<IEventHandler<SuspendingEventArgs*>>> SuspendingEventSource;
CALL_COUNTER(CreateCanvasImageSourceMethod);
CALL_COUNTER_WITH_MOCK(CreateCanvasImageSourceMethod, ComPtr<CanvasImageSource>(ICanvasDevice*, int, int, CanvasBackground));
CanvasControlTestAdapter()
: m_mockWindow(Make<MockWindow>())
@ -83,9 +83,15 @@ public:
ThrowIfFailed(SurfaceContentsLostEventSource->InvokeAll(sender, arg));
}
virtual ComPtr<CanvasImageSource> CreateCanvasImageSource(ICanvasDevice* device, int width, int height) override
virtual ComPtr<CanvasImageSource> CreateCanvasImageSource(
ICanvasDevice* device,
int width,
int height,
CanvasBackground backgroundMode) override
{
CreateCanvasImageSourceMethod.WasCalled();
auto result = CreateCanvasImageSourceMethod.WasCalled(device, width, height, backgroundMode);
if (result)
return result;
auto sisFactory = Make<MockSurfaceImageSourceFactory>();
sisFactory->MockCreateInstanceWithDimensionsAndOpacity =
@ -108,7 +114,7 @@ public:
resourceCreator.Get(),
width,
height,
CanvasBackground::Transparent,
backgroundMode,
sisFactory.Get(),
dsFactory);
}

Просмотреть файл

@ -305,12 +305,12 @@ TEST_CLASS(CanvasControlTests_SizeTests)
return m_imageControl;
}
virtual ComPtr<CanvasImageSource> CreateCanvasImageSource(ICanvasDevice* device, int width, int height) override
virtual ComPtr<CanvasImageSource> CreateCanvasImageSource(ICanvasDevice* device, int width, int height, CanvasBackground backgroundMode) override
{
Assert::AreEqual(m_expectedImageSourceWidth, width, L"ExpectedImageSourceWidth");
Assert::AreEqual(m_expectedImageSourceHeight, height, L"ExpectedImageSourceHeight");
return __super::CreateCanvasImageSource(device, width, height);
return __super::CreateCanvasImageSource(device, width, height, backgroundMode);
}
};
@ -375,61 +375,84 @@ TEST_CLASS(CanvasControlTests_SizeTests)
};
};
class CanvasControlTestAdapter_InjectDeviceContext : public CanvasControlTestAdapter
{
ComPtr<ID2D1DeviceContext> m_deviceContext;
public:
CanvasControlTestAdapter_InjectDeviceContext(ID2D1DeviceContext* deviceContext)
: m_deviceContext(deviceContext)
{
}
virtual ComPtr<CanvasImageSource> CreateCanvasImageSource(
ICanvasDevice* device,
int width,
int height,
CanvasBackground backgroundMode) override
{
auto result = CreateCanvasImageSourceMethod.WasCalled(device, width, height, backgroundMode);
if (result)
return result;
auto sisFactory = Make<MockSurfaceImageSourceFactory>();
sisFactory->MockCreateInstanceWithDimensionsAndOpacity =
[&](int32_t actualWidth, int32_t actualHeight, bool isOpaque, IInspectable* outer)
{
auto mockSurfaceImageSource = Make<MockSurfaceImageSource>();
mockSurfaceImageSource->BeginDrawMethod.AllowAnyCall(
[&](RECT const&, IID const& iid, void** updateObject, POINT*)
{
return m_deviceContext.CopyTo(iid, updateObject);
});
mockSurfaceImageSource->SetDeviceMethod.AllowAnyCall();
mockSurfaceImageSource->EndDrawMethod.AllowAnyCall();
return mockSurfaceImageSource;
};
auto dsFactory = std::make_shared<CanvasImageSourceDrawingSessionFactory>();
ComPtr<ICanvasResourceCreator> resourceCreator;
ThrowIfFailed(device->QueryInterface(resourceCreator.GetAddressOf()));
return Make<CanvasImageSource>(
resourceCreator.Get(),
width,
height,
backgroundMode,
sisFactory.Get(),
dsFactory);
}
};
TEST_CLASS(CanvasControlTests_Dpi)
{
class CanvasControlTestAdapter_VerifyDpi : public CanvasControlTestAdapter
class CanvasControlTestAdapter_VerifyDpi : public CanvasControlTestAdapter_InjectDeviceContext
{
public:
float m_dpi;
int m_lastImageSourceWidth;
int m_lastImageSourceHeight;
int m_imageSourceCount;
ComPtr<ID2D1DeviceContext> m_d2dDeviceContext;
CanvasControlTestAdapter_VerifyDpi(ID2D1DeviceContext* d2dDeviceContext)
: m_dpi(DEFAULT_DPI)
CanvasControlTestAdapter_VerifyDpi(ID2D1DeviceContext* deviceContext)
: CanvasControlTestAdapter_InjectDeviceContext(deviceContext)
, m_dpi(DEFAULT_DPI)
, m_lastImageSourceWidth(0)
, m_lastImageSourceHeight(0)
, m_d2dDeviceContext(d2dDeviceContext)
, m_imageSourceCount(0)
{}
virtual ComPtr<CanvasImageSource> CreateCanvasImageSource(ICanvasDevice* device, int width, int height) override
virtual ComPtr<CanvasImageSource> CreateCanvasImageSource(ICanvasDevice* device, int width, int height, CanvasBackground backgroundMode) override
{
m_lastImageSourceWidth = width;
m_lastImageSourceHeight = height;
m_imageSourceCount++;
auto sisFactory = Make<MockSurfaceImageSourceFactory>();
sisFactory->MockCreateInstanceWithDimensionsAndOpacity =
[&](int32_t actualWidth, int32_t actualHeight, bool isOpaque, IInspectable* outer)
{
auto mockSurfaceImageSource = Make<MockSurfaceImageSource>();
mockSurfaceImageSource->BeginDrawMethod.AllowAnyCall(
[&](RECT const& updateRect, IID const& iid, void** updateObject, POINT* offset)
{
return m_d2dDeviceContext.CopyTo(iid, updateObject);
});
mockSurfaceImageSource->SetDeviceMethod.AllowAnyCall();
mockSurfaceImageSource->EndDrawMethod.AllowAnyCall();
return mockSurfaceImageSource;
};
auto dsFactory = std::make_shared<CanvasImageSourceDrawingSessionFactory>();
ComPtr<ICanvasResourceCreator> resourceCreator;
ThrowIfFailed(device->QueryInterface(resourceCreator.GetAddressOf()));
return Make<CanvasImageSource>(
resourceCreator.Get(),
width,
height,
CanvasBackground::Transparent,
sisFactory.Get(),
dsFactory);
return __super::CreateCanvasImageSource(device, width, height, backgroundMode);
}
virtual float GetLogicalDpi() override
@ -454,6 +477,7 @@ TEST_CLASS(CanvasControlTests_Dpi)
for (auto dpiCase : dpiCases)
{
auto adapter = std::make_shared<CanvasControlTestAdapter_VerifyDpi>(deviceContext.Get());
adapter->CreateCanvasImageSourceMethod.AllowAnyCall();
int expectedImageSourceCount = 0;
@ -727,3 +751,163 @@ private:
}
};
TEST_CLASS(CanvasControl_ClearColor)
{
ComPtr<MockD2DDeviceContext> m_deviceContext;
std::shared_ptr<CanvasControlTestAdapter> m_adapter;
ComPtr<CanvasControl> m_control;
ComPtr<StubUserControl> m_userControl;
MockEventHandler<DrawEventHandlerType> m_onDraw;
public:
TEST_METHOD_INITIALIZE(Init)
{
m_deviceContext = Make<MockD2DDeviceContext>();
m_deviceContext->ClearMethod.AllowAnyCall();
m_deviceContext->SetTransformMethod.AllowAnyCall();
m_deviceContext->SetDpiMethod.AllowAnyCall();
m_adapter = std::make_shared<CanvasControlTestAdapter_InjectDeviceContext>(m_deviceContext.Get());
m_control = Make<CanvasControl>(m_adapter);
m_userControl = dynamic_cast<StubUserControl*>(As<IUserControl>(m_control).Get());
m_onDraw = MockEventHandler<DrawEventHandlerType>(L"Draw");
EventRegistrationToken ignoredToken;
ThrowIfFailed(m_control->add_Draw(m_onDraw.Get(), &ignoredToken));
m_adapter->CreateCanvasImageSourceMethod.AllowAnyCall();
m_userControl->LoadedEventSource->InvokeAll(nullptr, nullptr);
m_onDraw.SetExpectedCalls(1);
RaiseAnyNumberOfCompositionRenderingEvents();
}
TEST_METHOD(CanvasControl_DefaultClearColorIsTransparentBlack)
{
Color expectedColor{ 0, 0, 0, 0 };
Color actualColor{ 0xFF, 0xFF, 0xFF, 0xFF };
ThrowIfFailed(m_control->get_ClearColor(&actualColor));
Assert::AreEqual(expectedColor, actualColor);
}
TEST_METHOD(CanvasControl_ClearColorValueIsPersisted)
{
Color anyColor{ 1, 2, 3, 4 };
ThrowIfFailed(m_control->put_ClearColor(anyColor));
Color actualColor{ 0xFF, 0xFF, 0xFF, 0xFF };
ThrowIfFailed(m_control->get_ClearColor(&actualColor));
Assert::AreEqual(anyColor, actualColor);
}
TEST_METHOD(CanvasControl_SettingDifferentClearColorTriggersRedraw)
{
Color currentColor;
ThrowIfFailed(m_control->get_ClearColor(&currentColor));
Color differentColor = currentColor;
differentColor.R = 255 - differentColor.R;
ThrowIfFailed(m_control->put_ClearColor(differentColor));
m_onDraw.SetExpectedCalls(1);
RaiseAnyNumberOfCompositionRenderingEvents();
Expectations::Instance()->Validate();
}
TEST_METHOD(CanvasControl_SettingClearColorToCurrentValueDoesNotTriggerRedraw)
{
Color currentColor;
ThrowIfFailed(m_control->get_ClearColor(&currentColor));
ThrowIfFailed(m_control->put_ClearColor(currentColor));
m_onDraw.SetExpectedCalls(0);
RaiseAnyNumberOfCompositionRenderingEvents();
Expectations::Instance()->Validate();
}
TEST_METHOD(CanvasControl_DeviceContextIsClearedToCorrectColorBeforeDrawHandlerIsCalled)
{
Color anyColor{ 1, 2, 3, 4 };
m_onDraw.SetExpectedCalls(0);
m_deviceContext->ClearMethod.SetExpectedCalls(1,
[&](D2D1_COLOR_F const* color)
{
Assert::AreEqual(ToD2DColor(anyColor), *color);
m_onDraw.SetExpectedCalls(1);
});
ThrowIfFailed(m_control->put_ClearColor(anyColor));
RaiseAnyNumberOfCompositionRenderingEvents();
Expectations::Instance()->Validate();
}
TEST_METHOD(CanvasControl_WhenClearColorBecomesOpaque_SurfaceImageSourceIsCreatedWithOpaqueBackgroundMode)
{
m_onDraw.AllowAnyCall();
// The default clear color is transparent
Color defaultClearColor;
ThrowIfFailed(m_control->get_ClearColor(&defaultClearColor));
Assert::AreNotEqual<uint8_t>(255, defaultClearColor.A);
Color anyOpaqueColor{ 255, 1, 2, 3 };
ThrowIfFailed(m_control->put_ClearColor(anyOpaqueColor));
m_adapter->CreateCanvasImageSourceMethod.SetExpectedCalls(1,
[&](ICanvasDevice*, int, int, CanvasBackground backgroundMode)
{
Assert::AreEqual(CanvasBackground::Opaque, backgroundMode);
return nullptr;
});
RaiseAnyNumberOfCompositionRenderingEvents();
Expectations::Instance()->Validate();
}
TEST_METHOD(CanvasControl_WhenClearColorBecomesTransparent_SurfaceImageSourceIsCreatedWithTransparentBackgroundMode)
{
m_onDraw.AllowAnyCall();
// First ensure we have an opaque color set
Color anyOpaqueColor{ 255, 1, 2, 3};
ThrowIfFailed(m_control->put_ClearColor(anyOpaqueColor));
RaiseAnyNumberOfCompositionRenderingEvents();
// Now set it to transparent
Color anyTransparentColor{ 254, 1, 2, 3 };
ThrowIfFailed(m_control->put_ClearColor(anyTransparentColor));
m_adapter->CreateCanvasImageSourceMethod.SetExpectedCalls(1,
[&](ICanvasDevice*, int, int, CanvasBackground backgroundMode)
{
Assert::AreEqual(CanvasBackground::Transparent, backgroundMode);
return nullptr;
});
RaiseAnyNumberOfCompositionRenderingEvents();
Expectations::Instance()->Validate();
}
private:
void RaiseAnyNumberOfCompositionRenderingEvents()
{
int anyNumberOfTimes = 5;
for (auto i = 0; i < anyNumberOfTimes; ++i)
m_adapter->RaiseCompositionRenderingEvent();
}
};

Просмотреть файл

@ -374,7 +374,7 @@ private:
// eg:
//
// auto onDraw = MockEventHandler<DrawEventHandlerType>(L"Draw");
// onDraw.SetExpectedInvokes(1);
// onDraw.SetExpectedCalls(1);
// ThrowIfFailed(m_control->add_Draw(onDraw.Get(), &m_ignoredToken));
//
// The expectations are validated on destruction.
@ -413,6 +413,11 @@ public:
return m_callback.Get();
}
void AllowAnyCall()
{
m_callCounter.AllowAnyCall();
}
void SetExpectedCalls(int value)
{
m_callCounter.SetExpectedCalls(value);