1

У меня очень простой пример воспроизведения RenderTargetBitmap.RenderAsync, перегружающий масштабирование WebView. Все, что я на MainPage является WebView и кнопка:RenderTargetBitmap испортил масштабирование WebView

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <WebView Source="http://bing.com"></WebView> 
    <Button Content="Render me" 
      HorizontalAlignment="Right" 
      VerticalAlignment="Bottom" 
      Click="ButtonBase_OnClick" /> 
</Grid> 

В коде позади есть только простой обработчик события

private async void ButtonBase_OnClick(object sender, RoutedEventArgs e) 
{ 
    RenderTargetBitmap rtb = new RenderTargetBitmap(); 
    await rtb.RenderAsync(this, 1280, 720); 
} 

Это то, что страница выглядит как прежде RenderAsync вызова:

Before RenderAsync

и это то, что происходит после вызова:

After RenderAsync

Любая идея, почему и как предотвратить это? Обратите внимание, что это происходит только, если я позвоню

await rtb.RenderAsync(this, 1280, 720); 

но если я называю перегрузку без масштабирования

await rtb.RenderAsync(this); 

EDIT: Из-за первый ответ я получил, я хотел бы уточнить, почему соотношение сторон здесь не проблема, а только служит доказательству того, что на самом деле проблема. Подумайте о следующем сценарии - очень высоком экране DPI, где требуется только снимок экрана более низкого разрешения - даже если вы масштабируете его с помощью соотношения RIGHT, он по-прежнему запутывает WebView. Кроме того, для моего сценария изменение размера снимка вручную вручную не является вариантом - перегрузка RenderAsync с масштабированными измерениями намного быстрее, и я бы предпочел использовать этот метод.

+1

Конечно, это ошибка, единственное обходное решение - маленькая мерцающая вещь. MainWebView.Visibility = Visibility.Collapsed; ждут Task.Delay (10); MainWebView.Visibility = Visibility.Visible; –

+0

@JuanPabloGarciaCoello спасибо, вы и Питер предложили аналогичное решение. :) –

+0

Почему вручную изменить размер растрового изображения не является для вас вариантом? Если вы делаете это с переднего плана (а не «XamlRenderingBackgroundTask»), вы можете использовать ускоренные подходы с графическим процессором, такие как Win2D, чтобы сделать это очень быстро. – r2d2rigo

ответ

0

Вместо использования фиксированных значений используйте VisibleBounds, чтобы получить текущий размер окна.

Вот код:

private async void pressMe_Click(object sender, RoutedEventArgs e) 
{ 
    var windowBounds = ApplicationView.GetForCurrentView().VisibleBounds; 
    RenderTargetBitmap rtb = new RenderTargetBitmap(); 
    await rtb.RenderAsync(this, (int)windowBounds.Width, (int)windowBounds.Height); 
} 
+0

Да, я знаю об этом, поэтому я использовал случайный размер, чтобы продемонстрировать эффект. Другая причина заключается в том, что проблема также возникает, если вы пытаетесь масштабировать изображение на высоких экранах DPI. И даже если результат изображения будет испорчен (я бы ожидал, что если отношение неверно), я бы не ожидал, что содержимое WebView перепутается. –

+0

Думал, что вы искали быстрое исправление. Вы очень правы; он не должен влиять на представление, даже если соотношение сторон не соответствует. Кажется, что 'RenderAsync()' масштабирует представление перед его рендерингом. –

1

Очень странное поведение ... я нашел один очень грязный исправить на это (!). Я в основном скрываю и снова показываю webview (wv).

private async void ButtonBase_OnClick(object sender, RoutedEventArgs e) 
{ 
    RenderTargetBitmap rtb = new RenderTargetBitmap(); 
    await rtb.RenderAsync(wv, 1280, 720); 
    wv.Visibility = Visibility.Collapsed; 
    await Task.Delay(100); 
    wv.Visibility = Visibility.Visible; 
} 

Я не горжусь этим раствором и Webview вспышек, но, по крайней мере, это не «взорван» больше ...

+0

Спасибо, Питер, это действительно имеет значение, но, к сожалению, для моего сценария это действительно не решение. : (Upvoting, но надеясь, что будут другие идеи ... –

1

Это немного рубить, но я нашел что если вы установите содержимое другого элемента управления через WebViewBrush и затем визуализируете это управление, то источник WebView не получит никакого масштабирования. Я изменил код XAML вы предоставили так это выглядит следующим образом:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*" /> 
     <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 

    <Border x:Name="Target" Width="1280" Height="720" /> 
    <WebView x:Name="webView" Source="http://bing.com" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></WebView> 

    <Button Content="Render me" Grid.Row="1" 
     HorizontalAlignment="Right" 
     VerticalAlignment="Bottom" 
     Click="ButtonBase_OnClick" /> 

</Grid> 

В вашем случае, вы должны выбрать, чтобы установить контроль над Border позади WebView (однако, сделать не изменения его Visibility или положить его вне границ окна, так как RenderAsync не удастся).Затем, на коде позади, установите Background целевого управления для экземпляра WebViewBrush, который подает на WebView:

private async void ButtonBase_OnClick(object sender, RoutedEventArgs e) 
    { 
     WebViewBrush brush = new WebViewBrush(); 
     brush.SetSource(webView); 
     Target.Background = brush; 
     Target.InvalidateMeasure(); 
     Target.InvalidateArrange(); 

     RenderTargetBitmap rtb = new RenderTargetBitmap(); 
     await rtb.RenderAsync(Target, 1280, 720); 
     var pixels = await rtb.GetPixelsAsync(); 
    } 

Вы получите окончательное изображение без каких-либо проблем, вызванных к источнику WebView (однако, обратите внимание, что окончательное изображение будет искажено, так как пропорции не совпадают). Однако это связано с несколькими предостережениями, самым важным из которых является то, что размер WebView должен соответствовать размеру RenderTargetBitmap, или вы получите пустые области.

Смежные вопросы