WPF 閉じるボタンのみを非表示にしたウィンドウの作り方

諸事情で閉じるボタン(いわゆる×ボタン)を非表示にしつつ、最小化ボタンのみを残す必要がありました。

たったこれだけのことなのに、結構複雑な処理を実装しないといけなかったので、備忘録として残しておきます。

参考サイト

今回、予想以上に処理が複雑であったため、基本的に参考サイト様のものを組み合わせる形で実現しました。

なので、まず参考サイトを載せておきます。

kuwayoshi.com

social.msdn.microsoft.com

blog.xin9le.net

できあがったもの

もうソースで語らせていただきます。

public partial class MainWindow : Window
{
    [DllImport("user32.dll")]
    private static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

    [DllImport("user32.dll")]
    private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

    [DllImport("user32.dll")]
    private static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);
    const int GWL_STYLE = -16;
    const int WS_MAXIMIZEBOX = 0x10000;
    const int WS_MINIMIZEBOX = 0x20000;
    private const uint MF_BYCOMMAND = 0x00000000;
    private const uint MF_GRAYED = 0x00000001;
    private const uint MF_ENABLED = 0x00000000;
    private const uint SC_CLOSE = 0xF060;
    private const int WM_SHOWWINDOW = 0x00000018;
    private const int WM_SYSCOMMAND = 0x112;
    private const int WM_CLOSE = 0x10;
    private HwndSource hwndSource = null;

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);

        hwndSource = PresentationSource.FromVisual(this) as HwndSource;
        if (hwndSource != null)
        {
            hwndSource.AddHook(new HwndSourceHook(this.hwndSourceHook));
        }

        var handle = new WindowInteropHelper(this).Handle;
        int style = GetWindowLong(handle, GWL_STYLE);
        style = style & (~WS_MAXIMIZEBOX);  // 最小化も消したければ WS_MINIMIZEBOX を指定
        SetWindowLong(handle, GWL_STYLE, style);
    }

    private IntPtr hwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == WM_SHOWWINDOW)
        {
            IntPtr hMenu = GetSystemMenu(hwnd, false);
            if (hMenu != IntPtr.Zero)
            {
                EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
            }
        }
        else if (msg == WM_SYSCOMMAND && (wParam.ToInt32() & 0xFFF0) == SC_CLOSE)
        {
            handled = true;
        }
        return IntPtr.Zero;
    }

    public MainWindow()
    {
        InitializeComponent();
    }
}

コメント

タイトルとURLをコピーしました