次の方法で共有


Window の手動サイズ変更だけを不可にしたい

質問

2013年6月28日金曜日 10:01

WPFのWindowでユーザーのドラッグ操作によるサイズ変更だけを不可にする方法がわからなくて困っています。

ResizeModeの設定では最小化のみ可か、サイズ変更不可しか指定できませんし、

WindowのREsoureceでResizeGripのEnableをFalseに設定してみたのですがWindowには反映されませんでした。

枠の最小化・最大化・元に戻すの操作は使用できて、ドラッグによるサイズ変更を不可という

内容を実現するにはどのようにすればいいのでしょうか?

すべての返信 (20)

2013年7月1日月曜日 1:57 ✅回答済み | 1 票

とりあえずですが、以下のような感じですよね。

Enable Maximize, Minimize and Restore Window in WPF (Manual Resize is disable)
http://stackoverflow.com/questions/2175712/enable-maximize-minimize-and-restore-window-in-wpf-manual-resize-is-disable

本当は、ResizeModeがNoResizeで、最小化と最大化のボタンが現れれば理想なのでしょうが・・・

★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/


2013年7月1日月曜日 2:12 ✅回答済み

ご回答ありがとうございます。

試してみたのですがMinHeight・MaxHeight・MinWidth・MaxWidth を設定すると

最大化・最小化ボタンを押下しても、設定されたサイズ以上・以下にはなりませんでした。

ひらぽんさんの想定された使い方とは違うのでしょうか・・・

思った以上に厄介なようで少し考えてみました。以下のような感じでドラッグによるサイズ変更を無効にできるかと・・・サイズは 525 x 350 で固定にしてます。XAML では MaxHeight 等の固定はせず、フック内で設定します。ただし検;してないので、このまま使うと何らかの副作用があるかも知れません。

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;

namespace WpfApplication1 {
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window {

        private static readonly int SYSCOMMAND  = 0x0112;
        private static readonly int SC_MINIMIZE = 0xf020;
        private static readonly int SC_MAXIMIZE = 0xF030;
        private static readonly int SC_RESTORE  = 0xf120;
        
        public MainWindow() {
            InitializeComponent();
            this.SourceInitialized ;= Window1_SourceInitialized;
        }

        void Window1_SourceInitialized(object sender, EventArgs e) {
            HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
            source.AddHook(new HwndSourceHook(WndProc));
        }

        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
            // 元のサイズに戻す
            if (msg == SYSCOMMAND && SC_RESTORE == wParam.ToInt32()) {
                this.MaxHeight = this.MinHeight = 350;
                this.MaxWidth = this.MinWidth = 525;
            }

            // 最小化
            if (msg == SYSCOMMAND && SC_MINIMIZE == wParam.ToInt32()) {
                this.MaxHeight = this.MaxWidth = int.MaxValue;
                this.MinHeight = this.MinWidth = 0.0;
            }

            // 最大化
            if (msg == SYSCOMMAND && SC_MAXIMIZE == wParam.ToInt32()) {
                this.MaxHeight = this.MaxWidth = int.MaxValue;
                this.MinHeight = this.MinWidth = 0.0;
            }
            handled = false;
            return IntPtr.Zero;
        }
    }
}

しかし WPF って WindowsState 変更時のイベントハンドラはないのですね。ちょっとどうかなと思わずにいられません(汗

ひらぽん http://d.hatena.ne.jp/hilapon/


2013年7月1日月曜日 5:01 ✅回答済み

m_isDuringMaximizingが利用方法がわからなくて止まってしまってます。

ローカル変数です。自分で定義すればOKです。

★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/


2013年7月2日火曜日 2:06 ✅回答済み

> VB.NETでも同様に取得できるのでしょうか?

VB.NET でもやることは全く変わりません。以下のようになります。

Class MainWindow
    Private _isDuringMaximizing As Boolean

    Protected Overrides Sub OnStateChanged(e As EventArgs)
        If WindowState = WindowState.Maximized Then
            MinWidth = 0
            MinHeight = 0
            MaxWidth = Int32.MaxValue
            MaxHeight = Int32.MaxValue

            If Not _isDuringMaximizing Then
                _isDuringMaximizing = True
                WindowState = WindowState.Normal
                WindowState = WindowState.Maximized
                _isDuringMaximizing = False
            End If

        ElseIf Not _isDuringMaximizing Then
            MinWidth = 1024
            MinHeight = 768
            MaxWidth = 1024
            MaxHeight = 768
        End If

        MyBase.OnStateChanged(e)
    End Sub
End Class

ちなみに Int32 = Integer です。

ひらぽん http://d.hatena.ne.jp/hilapon/


2013年7月2日火曜日 2:23 ✅回答済み

ついでにフック操作による画面サイズ固定の VB 版も上げときます。何かの参考になれば幸いです。

Imports System.Runtime.InteropServices
Imports System.Windows
Imports System.Windows.Interop

Class MainWindow
    Private Shared ReadOnly SYSCOMMAND As Int32 = &H112
    Private Shared ReadOnly SC_MINIMIZE As Int32 = &HF020
    Private Shared ReadOnly SC_MAXIMIZE As Int32 = &HF030
    Private Shared ReadOnly SC_RESTORE As Int32 = &HF120

    Public Sub New()
        InitializeComponent()
        AddHandler Me.SourceInitialized, AddressOf Window1_SourceInitialized
    End Sub

    Private Sub Window1_SourceInitialized(sender As Object, e As EventArgs)
        Dim source = HwndSource.FromHwnd(New WindowInteropHelper(Me).Handle)
        source.AddHook(New HwndSourceHook(AddressOf WndProc))
    End Sub

    Private Function WndProc(hwnd As IntPtr, msg As Int32,
        wParam As IntPtr, lParam As IntPtr, ByRef handled As Boolean) As IntPtr

        ' 元のサイズに戻す
        If (msg = SYSCOMMAND And SC_RESTORE = wParam.ToInt32()) Then
            Me.MaxHeight = 350 : Me.MinHeight = 350
            Me.MaxWidth = 525 : Me.MinWidth = 525
        End If

        ' 最小化
        If (msg = SYSCOMMAND And SC_MINIMIZE = wParam.ToInt32()) Then
            Me.MaxHeight = Int32.MaxValue : Me.MaxWidth = Int32.MaxValue
            Me.MinHeight = 0.0 : Me.MinWidth = 0.0
        End If

        ' 最大化
        If (msg = SYSCOMMAND And SC_MAXIMIZE = wParam.ToInt32()) Then
            Me.MaxHeight = Int32.MaxValue : Me.MaxWidth = Int32.MaxValue
            Me.MinHeight = 0.0 : Me.MinWidth = 0.0
        End If

        handled = False
        Return IntPtr.Zero
    End Function
End Class

ひらぽん http://d.hatena.ne.jp/hilapon/


2013年6月28日金曜日 11:24

試してませんが MinHeight・MaxHeight・MinWidth・MaxWidth の設定でできないですか?

ひらぽん http://d.hatena.ne.jp/hilapon/


2013年7月1日月曜日 0:23

ご回答ありがとうございます。

試してみたのですがMinHeight・MaxHeight・MinWidth・MaxWidth を設定すると

最大化・最小化ボタンを押下しても、設定されたサイズ以上・以下にはなりませんでした。

ひらぽんさんの想定された使い方とは違うのでしょうか・・・


2013年7月1日月曜日 2:29

しかし WPF って WindowsState 変更時のイベントハンドラはないのですね。ちょっとどうかなと思わずにいられません(汗

Protected メンバなら OnStateChanged メソッドありましたね(汗
ただし、以下はうまく動作しませんでした。最大化ボタンクリックしてもサイズ変わらなかったり... f(^^;

public partial class MainWindow : Window {
 protected override void OnStateChanged(EventArgs e) {
        if (WindowState == WindowState.Normal) {
            this.MaxHeight = this.MinHeight = 350;
            this.MaxWidth = this.MinWidth = 525;
        }
        else  {
            MinWidth = MinHeight = 0;
            MaxHeight = MaxWidth = int.MaxValue;
        }

        base.OnStateChanged(e);
    }
}

trapemiyaさん
> 本当は、ResizeModeがNoResizeで、最小化と最大化のボタンが現れれば理想なのでしょうが・・・

ですね。これは Connect に要望出した方がいいかも (^^;

ひらぽん http://d.hatena.ne.jp/hilapon/


2013年7月1日月曜日 4:05

返信ありがとうございます 

サイトを参考にして実際に動作をと思ったのですが

VB.NETでしか作成できなくて 

m_isDuringMaximizingが利用方法がわからなくて止まってしまってます。

質問を重ねて申し訳ないのですがm_isDuringMaximizingって何に該当する値でしょう?

VB.NETでも同様に取得できるのでしょうか?


2013年7月1日月曜日 4:29

ひらぽんさんご回答ありがとうございます。

試してみましたがおっしゃる通り、最大化で変わらないですね

シンプルに書けるので上手いこと動けばこんな感じでやりたいのですが・・

WPFで色々簡単にできるのに、こんな所が結構難しかったりするんですね

ちなみに、参考までにConnectってなんのことでしょうか?


2013年7月1日月曜日 4:40

> ちなみに、参考までにConnectってなんのことでしょうか?

Microsoft 製品のフィードバックを行えるサイトです。再現性のある不具合は MS の開発チームへ情報が送られ検;したり、賛同が非常に多い要望は次期バージョンへの反映が検討されることもあります。

Microsoft Connect Visual Studio 日本語ホームページ

Visual Studio のメニュー「ヘルプ」→「バグの報告」でも Connet にアクセスできます。

日本語で不具合報告や要望提出ができますが、Microsoft からの返信は英語となります。提出されたフィードバック一覧はこちらをご覧ください。

https://connect.microsoft.com/VisualStudio/Feedback

ひらぽん http://d.hatena.ne.jp/hilapon/


2013年7月1日月曜日 5:04 | 1 票

ただし、以下はうまく動作しませんでした。最大化ボタンクリックしてもサイズ変わらなかったり... f(^^;

あれ? 私の方ではうまく動いていますよ。WPF4の環境ですが・・・

(追記)
Windows 7 ; WPF4.5の環境でも同様にうまく動くことを確認しました。

★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/


2013年7月1日月曜日 6:16

あれ?動いてますか?こちらは Win7(x64) ; VS2010 SP1 ですが、なんでだろう(謎)

こちらだと、起動→最小化→元に戻す→最大化で変わらないですね。ちょっと調べてみます。

ひらぽん http://d.hatena.ne.jp/hilapon/


2013年7月1日月曜日 6:22

あれ?動いてますか?こちらは Win7(x64) ; VS2010 SP1 ですが、なんでだろう(謎)

こちらだと、起動→最小化→元に戻す→最大化で変わらないですね。ちょっと調べてみます。

ちなみに最初のフックを使った方法では問題なく動作します。

ひらぽん http://d.hatena.ne.jp/hilapon/


2013年7月1日月曜日 6:35

追記です。Visual Studio 2012 フィードバック ツール というものもあります。

ひらぽん http://d.hatena.ne.jp/hilapon/


2013年7月2日火曜日 1:56

やはり、私が書いた OnStateChanged のコードだと、 「最小化→元に戻す→最大化」 の流れのうち、最大化するタイミングで各プロパティが設定されませんね。

とりあえずですが、以下のような感じですよね。

Enable Maximize, Minimize and Restore Window in WPF (Manual Resize is disable)
http://stackoverflow.com/questions/2175712/enable-maximize-minimize-and-restore-window-in-wpf-manual-resize-is-disable

こちらは正常な動作が確認できました。ちょっともやもやしますが OnStateChanged を使う場合、再帰的に呼び出すしかないようですね。フックを使った場合、綺麗に(?)設定できるだけになんとも謎です。

ひらぽん http://d.hatena.ne.jp/hilapon/


2013年7月2日火曜日 2:46

ありがとうございます 丁度VBで書き換えるのに苦心していた所でしたので

使用させて頂きます。


2013年7月2日火曜日 2:47

ありがとうございます。

C#にうといものでして、とても助かります両方書いてみて

色々と動かしてみます


2013年7月2日火曜日 10:30

ご回答ありがとうございます。

どちらも試してみました。

マウスを画面の端に置くとドラッグできるように変わるのが見た目違和感がありますが

それ以外は思った通りでした。

フック操作だと、AddHandler  で設定できるので、外側から設定できそうで

何か変更あれば楽にできそうなのでこちらを利用することにしました。

丁寧なご回答ありがとうございました。

助かりました。


2013年7月2日火曜日 11:01

どちらも試してみました。マウスを画面の端に置くとドラッグできるように変わるのが見た目違和感がありますがそれ以外は思った通りでした。

フック操作だと、AddHandler  で設定できるので、外側から設定できそうで何か変更あれば楽にできそうなのでこちらを利用することにしました。

お役に立てたようで何よりです。

trapemiya さんの最初の回答と、私の C# のフックを使ったコードでの回答は、いずれも今後このスレッドを見る方の参考になると思われますので、私の方で回答マークを付けさせて頂きました。

頑張ってください。

ひらぽん http://d.hatena.ne.jp/hilapon/