Entwickler-Ecke

WPF / Silverlight - XAML Elemente passen nicht exact ins Fenster


m-s - So 09.08.15 20:48
Titel: XAML Elemente passen nicht exact ins Fenster
Ich wusste nicht so recht wie ich das genauer betiteln soll.

Erkläre es mal.

Ich habe ein WPF Window ohne WindowStyle, Größe 204 x 90
Darin gibt es eine ViewBox, darin ein Grid mit zwei Spalten. Eine Spalte ist in der Breite definiert.darin sind zwei Bildern positioniert. In der anderen Spalte ist ein Label, steht auf Fill.


XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
<Window x:Class="Uhrzeit.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Uhrzeit"
        mc:Ignorable="d"        
        
        Title="MainWindow" Height="90" Width="204" Loaded="Window_Loaded" MouseMove="Window_MouseMove" ResizeMode="CanResizeWithGrip" Closing="Window_Closing" ShowInTaskbar="False" WindowStyle="None" SnapsToDevicePixels="True">

    <Viewbox Margin="0">

        <Grid  Margin="0" Width="202" Height="88">
            <Grid.ColumnDefinitions >
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="30" />
            </Grid.ColumnDefinitions>

            <Rectangle Grid.Column="1" OpacityMask="LightSkyBlue" Fill="LightGray"/>

            <Label x:Name="lbl_Uhrzeit" Content="Uhrzeit" FontSize="40.333"/>


            <Image x:Name="hamburger" HorizontalAlignment="Center" Height="22" Margin="0,4,0,0" VerticalAlignment="Top" Width="18" Grid.Column="1" Source="resourcen/hamburgermenue.jpg" MouseDown="hamburger_MouseDown">
            </Image>
            <Image x:Name="ausschalten" HorizontalAlignment="Center" Height="20" Margin="0,28,0,0" VerticalAlignment="Top" Width="20" Grid.Column="1" Source="resourcen/Shutdown-64.png" MouseDown="ausschalten_MouseDown">
            </Image>

        </Grid>

    </Viewbox>


OK so oder so ähnlich, geht mir auch mit anderen Programmen so.

Wenn ich die Anwendung starte, dann sieht man oben einen schmalen Balken nachdem das Grid erst anfängt. Den bekomme ich nicht weg.
Ich habe dann noch eine Methode, die dafür sorgt, dass das Fenster immer mit dem gleichen Ratio gezoomt wird (Problem besteht aber auch wenn die nicht vorhanden ist). Wenn ich dann zoome verändert sich auch der Rand. Nicht nur im Verhältnis, sondern mal taucht er dann auch unten auf usw.

Offensichtlich fehlt mir eine grundlegende Information, denn egal auf welche Werte ich die Objekte in der Viewbox setze, die passen nie wirklich in das Programmfenster.

Ich hoffe da weiß jemand was ich falsch mache.
Danke fürs Lesen . . .


jfheins - Mo 10.08.15 19:26

Ein Bild wäre noch hilfreich gewesen ;-)

Ich habe das XAML mal bei mir probiert, und es tauchen weiße Ränder links und rechts auf. Ich vermute, das Problem liegt daran, dass das Fenster seine Höhe und Breite auf die Außenmaße bezieht.

Schreib mal in das Window lieber sowas:Title="MainWindow" Width="204" SizeToContent="Height" Loaded="Window_Loaded"

Dann sollte die ViewBox das Window komplett ausfüllen.


m-s - Di 11.08.15 11:01

user profile iconjfheins hat folgendes geschrieben Zum zitierten Posting springen:
Ein Bild wäre noch hilfreich gewesen ;-)

Ich habe das XAML mal bei mir probiert, und es tauchen weiße Ränder links und rechts auf. Ich vermute, das Problem liegt daran, dass das Fenster seine Höhe und Breite auf die Außenmaße bezieht.

Schreib mal in das Window lieber sowas:Title="MainWindow" Width="204" SizeToContent="Height" Loaded="Window_Loaded"

Dann sollte die ViewBox das Window komplett ausfüllen.

Ja stimmt Bild hätte ich auch drauf kommen können :)

Ich habe SizeToContent="Height" jetzt eingefügt und drei Sachen festgestellt.
1. Der Rand oben bleibt.
2. Wenn ich die Uhr starte sieht die Spalte rechts am unteren und rechten Rand immer richtig aus. (das kommt durch Deine Änderung)
3. Wenn ich raus oder reinzoome nicht mehr. Wenn ich die Uhr dann in der Größe speichere und wieder starte dann sieht der graue Balken wieder richtig aus.

Das heißt also, in der Methode zu Zoomen im Ratio ist ein "Fehler" ist. Die Methode habe ich aus dem Internet und verstehe nicht wirklich was sie macht.


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
using System;
using System.Windows;
using System.Windows.Interop;
using System.Runtime.InteropServices;


internal class WindowAspectRatio
{
    private double _ratio;
    private WindowAspectRatio(Window window)
    {
        _ratio = window.Width / window.Height;
        ((HwndSource)HwndSource.FromVisual(window)).AddHook(DragHook);
    }
    public static void Register(Window window)
    {
        new WindowAspectRatio(window);
    }
    internal enum WM
    {
        WINDOWPOSCHANGING = 0x0046,
    }
    [Flags()]
    public enum SWP
    {
        NoMove = 0x2,
    }
    [StructLayout(LayoutKind.Sequential)]
    internal struct WINDOWPOS
    {
        public IntPtr hwnd;
        public IntPtr hwndInsertAfter;
        public int x;
        public int y;
        public int cx;
        public int cy;
        public int flags;
    }
    private IntPtr DragHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handeled)
    {
        if ((WM)msg == WM.WINDOWPOSCHANGING)
        {
            WINDOWPOS position = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS));
            if ((position.flags & (int)SWP.NoMove) != 0 ||
                            HwndSource.FromHwnd(hwnd).RootVisual == null)
                return IntPtr.Zero;
            position.cx = (int)(position.cy * _ratio);
            Marshal.StructureToPtr(position, lParam, true);
            handeled = true;
        }
        return IntPtr.Zero;
    }
}


Aufruf im XAML ist

XML-Daten
1:
SourceInitialized="Window_SourceInitialized"                    


Im Code behind

C#-Quelltext
1:
2:
3:
4:
        private void Window_SourceInitialized(object sender, EventArgs ea)
        {
            WindowAspectRatio.Register((Window)sender);
        }


m-s - Mi 19.08.15 19:17

Kann es vielleicht sein, dass die Methode für den Zoom im Ratio falsch rechnet, weil oben die paar Pixel Rand bleiben, die ja eigentlich nicht da sein sollten?


jfheins - Mi 19.08.15 20:06

Schwerer wiegt imho, dass deine Methode

C#-Quelltext
1:
_ratio = window.Width / window.Height;                    

immer noch auf die Außenmaße zugreift. Du möchtest ja eigentlich das Verhältnis der Innenmaße konstant halten.

Ich meine, die Viewbox sollte Properties wie .RenderSize.Height haben, damit solltest du es mal probieren.

Vielleicht hilft dir auch diese Frage auf SO: http://stackoverflow.com/questions/2471867/resize-a-wpf-window-but-maintain-proportions


m-s - Fr 02.10.15 15:14

Ich habe es jetzt aus versehen geschafft.

Und zwar musste ich im Fenster bei BorderBrusch die Option AllowsTransperency aktivieren.
Dadurch verschwindet der obere Rand.