ウィンドウのサイズを「水平方向のみ」または「垂直方向のみ」に変更したくありません。これを強制できるウィンドウに設定できるプロパティはありますか、それとも使用できる気の利いたコード ビハインド トリックはありますか?
9 に答える
WM_WINDOWPOSCHANGING メッセージはいつでも処理できます。これにより、サイズ変更プロセス中にウィンドウのサイズと位置を制御できます (ユーザーがサイズ変更を終了した後に問題を修正するのではなく)。
WPF で行う方法は次のとおりです。いくつかのソースからこのコードを組み合わせたので、構文エラーが含まれている可能性があります。
internal enum WM
{
WINDOWPOSCHANGING = 0x0046,
}
[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 void Window_SourceInitialized(object sender, EventArgs ea)
{
HwndSource hwndSource = (HwndSource)HwndSource.FromVisual((Window)sender);
hwndSource.AddHook(DragHook);
}
private static IntPtr DragHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handeled)
{
switch ((WM)msg)
{
case WM.WINDOWPOSCHANGING:
{
WINDOWPOS pos = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS));
if ((pos.flags & (int)SWP.NOMOVE) != 0)
{
return IntPtr.Zero;
}
Window wnd = (Window)HwndSource.FromHwnd(hwnd).RootVisual;
if (wnd == null)
{
return IntPtr.Zero;
}
bool changedPos = false;
// ***********************
// Here you check the values inside the pos structure
// if you want to override tehm just change the pos
// structure and set changedPos to true
// ***********************
if (!changedPos)
{
return IntPtr.Zero;
}
Marshal.StructureToPtr(pos, lParam, true);
handeled = true;
}
break;
}
return IntPtr.Zero;
}
WPF の ViewBox を使用して、幅と高さが固定されたコントロールを使用して、コンテンツの縦横比を確保できます。
これを試してみましょう。ViewBox の "Stretch" 属性を変更して、異なる結果を体験できます。
これが私のスクリーンショットです:
<Window x:Class="TestWPF.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Viewbox Stretch="Uniform">
<StackPanel Background="Azure" Height="400" Width="300" Name="stackPanel1" VerticalAlignment="Top">
<Button Name="testBtn" Width="200" Height="50">
<TextBlock>Test</TextBlock>
</Button>
</StackPanel>
</Viewbox>
</Window>
これが私の解決策でした。
これをコントロール/ウィンドウ タグに追加する必要があります。
Loaded="Window_Loaded"
そして、これをコード ビハインドに配置する必要があります。
private double aspectRatio = 0.0;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
aspectRatio = this.ActualWidth / this.ActualHeight;
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
if (sizeInfo.WidthChanged)
{
this.Width = sizeInfo.NewSize.Height * aspectRatio;
}
else
{
this.Height = sizeInfo.NewSize.Width * aspectRatio;
}
}
Viewbox のトリックを試しましたが、気に入りませんでした。ウィンドウの境界を特定のサイズにロックしたかったのです。これはウィンドウ コントロールでテストされましたが、境界線でも機能すると思います。
コードサンプルでは:
if (sizeInfo.WidthChanged)
{
this.Width = sizeInfo.NewSize.Height * aspectRatio;
}
else
{
this.Height = sizeInfo.NewSize.Width * aspectRatio;
}
2番目の計算は次のようにする必要があると思います:
this.Height = sizeInfo.NewSize.Width * (1/aspectRatio);
「SizeChanged」イベント ハンドラーでこの作業のバリエーションを作成しました。幅を制御する寸法にしたかったので、次の形式の計算を使用して高さを強制的に一致させました。
if (aspectRatio > 0)
// enforce aspect ratio by restricting height to stay in sync with width.
this.Height = this.ActualWidth * (1 / aspectRatio);
アスペクト比 > 0 のチェックに気付くかもしれませんが、これを行ったのは、「Load」メソッドがアスペクト比を割り当てる前に、サイズ変更を行ったハンドラを呼び出す傾向があることがわかったためです。
これは少し遅いかもしれませんが、コードビハインドに簡単に入れることができます....
Private Sub UserControl1_SizeChanged(ByVal sender As Object, ByVal e As System.Windows.SizeChangedEventArgs) Handles Me.SizeChanged
If e.HeightChanged Then
Me.Width = Me.Height
Else
Me.Height = Me.Width
End If
End Sub
Flash Video の Web サイトでよく見かける効果を再現してみてください。ブラウザー ウィンドウを好きなように拡大できますが、高さまたは幅の最小に収まるようにプレゼンテーション エリアのみを引き伸ばすことができます。
たとえば、ウィンドウを垂直方向に拡大しても、アプリケーションのサイズは変更されません。表示領域の上部と下部に黒いバーを追加し、垂直方向の中央に配置するだけです。
これは、WPF では可能な場合と不可能な場合があります。知らない。
縦横比を維持するために、値コンバーターを使用して幅を高さに双方向にバインドできると思っていました。コンバーターのパラメーターとしてアスペクト比を渡すと、より汎用的なものになります。
だから、私はこれを試しました-最初にコンバーターなしのバインディング:
<Window
...
Title="Window1" Name="Win" Height="500"
Width="{Binding RelativeSource={RelativeSource self},
Path=Height, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<StackPanel>
<TextBlock>Width:</TextBlock>
<TextBlock Text="{Binding ElementName=Win, Path=Width}" />
<TextBlock>Height:</TextBlock>
<TextBlock Text="{Binding ElementName=Win, Path=Height}" />
</StackPanel>
</Window>
奇妙なことに、バインドは一方向のように動作し、報告されたウィンドウの幅 (TextBlock に示されている) は画面上のサイズと一致しません!
このアイデアは追求する価値があるかもしれませんが、最初にこの奇妙な動作を整理する必要があります。
それが役立つことを願っています!