質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.12%

【Unity】タイトルバーを非表示にする

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 363

aaachi

score 55

いつもお世話になっております。

Unity で タイトルバーを非表示にする スクリプトを実装したところ、
タイトルバーの高さが短くなったものの、完全に消えきることが出来ません。

詳しい方いられましたら、ご教示頂けますと幸いです。

実装したいこと

exeで
・タイトルバーの非表示
・位置をディスプレイの左上端にする

実装スクリプト

こちらのスクリプトを引っ張ってきました。
https://qiita.com/gatosyocora/items/b9bc12b4d56ac763e8c0
http://tvmllab.com/unity%E3%81%A7dll%E3%82%92%E4%BD%BF%E3%81%86/

①WindowsControl.cs

using UnityEngine;
using System.Collections;

using System;
using System.Runtime.InteropServices;

namespace Utils {

    // ここからコードを拝借させてもらいました!
    // http://answers.unity3d.com/questions/13523/is-there-a-way-to-set-the-position-of-a-standalone.html
    // http://stackoverflow.com/questions/2825528/removing-the-title-bar-of-external-application-using-c-sharp

    /*
     * 注意点!
     * 実行するアプリケーションはfullscreenではなく、windowedの状態にしておく必要がある。
     */
    public class WindowControl : MonoBehaviour {

        [SerializeField] string windowName = "demo";
        [SerializeField] int x = 0;
        [SerializeField] int y = 0;
        [SerializeField] int width = 1920;
        [SerializeField] int height = 1080;
        [SerializeField] bool hideTitleBar = true;

        [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
        private static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);

        [DllImport("user32.dll", EntryPoint = "FindWindow")]
        public static extern IntPtr FindWindow(System.String className, System.String windowName);

        // Sets window attributes
        [DllImport("user32.dll")]
        public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

        // Gets window attributes
        [DllImport("user32.dll")]
        public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

        // assorted constants needed
        public static int GWL_STYLE = -16;
        public static int WS_CHILD = 0x40000000; //child window
        public static int WS_BORDER = 0x00800000; //window with border
        public static int WS_DLGFRAME = 0x00400000; //window with double border but no title
        public static int WS_CAPTION = WS_BORDER | WS_DLGFRAME; //window with a title bar

        void Awake () {
            var window = FindWindow(null, windowName);
            if(hideTitleBar) {
                int style = GetWindowLong(window, GWL_STYLE);
                SetWindowLong(window, GWL_STYLE, (style & ~WS_CAPTION));
            }
            SetWindowPos(window, 0, x, y, width, height, width * height == 0 ? 1 : 0);
        }

    }

}

②user32.dll  を Pluginsフォルダにおく

extern "C" __declspec(dllexport) int Add(int a, int b)
{
     return(a + b);
}

現在起きている状況

イメージ説明
上図のように、タイトルバーが少し残ってしまいます。

何卒宜しくお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

「Project Settings...」の「Player」→「Resolution and Presentation」→「Standalone Player Options」の「Resizable Window」のチェックボックスがオンの場合、オフにしてみるのはどうでしょうか。

ただし、私の試したところですと上部のみならず外周全部が消え、枠なしウィンドウになってしまいました(そしてウィンドウサイズも変えられません...)。

もしリサイズできるようにしたい場合、Resizable Windowはオンのままで、スクリプトを下記のようにしてみるとどうでしょうか?
すみませんが、コードを自動整形した結果ご質問者さんのコードと若干レイアウトが変わってしまいました。
やっていることとしては単にウィンドウ上端をちょっとずらしているだけです。ずらし量は多分6ピクセルでちょうどいいと思うのですが、適宜調整してみてください。
また、私はWindows APIを直にいじることには慣れておらず、はたしてこれで妥当なのかちょっと自信がありませんので、異常がないか詳しく検証していただくことをおすすめします...

using System;
using System.Runtime.InteropServices;
using UnityEngine;

namespace Utils
{
    public class WindowControl : MonoBehaviour
    {
        // assorted constants needed
        public static int GWL_WNDPROC = -4;
        public static int GWL_STYLE = -16;
        public static int WS_CHILD = 0x40000000; //child window
        public static int WS_BORDER = 0x00800000; //window with border
        public static int WS_DLGFRAME = 0x00400000; //window with double border but no title
        public static int WS_CAPTION = WS_BORDER | WS_DLGFRAME; //window with a title bar
        public static uint WM_NCCALCSIZE = 0x0083;

        [SerializeField] private string windowName = "demo";
        [SerializeField] private int x;
        [SerializeField] private int y;
        [SerializeField] private int width = 1920;
        [SerializeField] private int height = 1080;
        [SerializeField] private bool hideTitleBar = true;

        private Func<IntPtr, uint, IntPtr, IntPtr, IntPtr> customWndProcDelegate;
        private IntPtr defaultWndProcPtr;

        private void Awake()
        {
            #if UNITY_STANDALONE_WIN
            var window = FindWindow(null, this.windowName);
            if (this.hideTitleBar)
            {
                var style = GetWindowLong(window, GWL_STYLE);
                SetWindowLong(window, GWL_STYLE, style & ~WS_CAPTION);

                // ウィンドウプロシージャを独自のメソッドに差し替えて、返ってきた本来のプロシージャを覚えておく
                this.customWndProcDelegate = this.CustomWndProc;
                this.defaultWndProcPtr = SetWindowLongPtr(
                    window,
                    GWL_WNDPROC,
                    Marshal.GetFunctionPointerForDelegate(this.customWndProcDelegate));
            }

            SetWindowPos(
                window,
                0,
                this.x,
                this.y,
                this.width,
                this.height,
                (this.width * this.height) == 0 ? 1 : 0);
            #endif
        }

        #if UNITY_STANDALONE_WIN
        // 独自のウィンドウプロシージャ
        private IntPtr CustomWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
        {
            // まずデフォルトのプロシージャを実行し、結果を受け取る
            var result = CallWindowProc(this.defaultWndProcPtr, hWnd, msg, wParam, lParam);

            // 非クライアント領域サイズ計算メッセージが飛んできたら...
            if ((msg == WM_NCCALCSIZE) && ((int)wParam == 1))
            {
                // 上端を6ピクセルずらす
                var ncCalcSizeParams = Marshal.PtrToStructure<NCCALCSIZE_PARAMS>(lParam);
                ncCalcSizeParams.rgrc[0].Top -= 6;
                Marshal.StructureToPtr(ncCalcSizeParams, lParam, false);
            }

            return result;
        }
        #endif

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left, Top, Right, Bottom;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct WINDOWPOS
        {
            public IntPtr hwnd;
            public IntPtr hwndInsertAfter;
            public int x;
            public int y;
            public int cx;
            public int cy;
            public uint flags;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct NCCALCSIZE_PARAMS
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
            public readonly RECT[] rgrc;
            public WINDOWPOS lppos;
        }

        #if UNITY_STANDALONE_WIN
        [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
        private static extern bool SetWindowPos(
            IntPtr hWnd,
            int hWndInsertAfter,
            int x,
            int Y,
            int cx,
            int cy,
            int wFlags);

        [DllImport("user32.dll", EntryPoint = "FindWindow")]
        public static extern IntPtr FindWindow(string className, string windowName);

        // Sets window attributes
        [DllImport("user32.dll")]
        public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

        // Gets window attributes
        [DllImport("user32.dll")]
        public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

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

        // 使っていないが、一応Setと対になるGetも宣言
        [DllImport("user32.dll")]
        private static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll")]
        private static extern IntPtr CallWindowProc(
            IntPtr lpPrevWndFunc,
            IntPtr hWnd,
            uint Msg,
            IntPtr wParam,
            IntPtr lParam);
        #endif
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/22 11:38

    Bongo様 いつもお世話になっております。

    ありがとうございます!
    今回、枠も消し、リサイズを受け付けないようにしたかったので、
    「Resizable Window」のチェックボックス オフにすることで
    無事解決致しました!

    リサイズしたくなった場合にも
    スクリプト参考にさせて頂きます!

    本当にありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる