0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Unity】Unityでウィンドウを最前面にしたりする

Posted at

はじめに

Unityで作った画面を強制的に最前面にしたい!という場面がありました。

そこで

  • ウィンドウを最前面にする
  • 右上の最小化、最大化、閉じるボタンを消す

という普段ゲームを作っていたら作らない機能を実装しました。
これを作るためにChatGPTを使用したため、知らないことをアウトプットするためにまとめてみます。

ソースコード

ウィンドウを最前面にするコードはこちら

ウィンドウのボタンを消すコードはこちら

ウィンドウを最前面にする

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

[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();

[DllImport("user32.dll")]
private static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, uint uFlags);

Windowsにある画面を設定するメソッドたちをUnityでも使用できるようにします。
DllImportで使用するdllの名前を指定するとそこにある関数を使えるようになります。
普段見かけないexternは外部で実装されるメソッドを宣言するために使用するらしいです。

DllImportを使う場合はstaticにする必要性があるようです。

SetForegroundWindow

SetForegroundWindowは指定したウィンドウをフォアグラウンドウィンドウに設定します。
フォアグラウンドウィンドウは、ユーザーが現在操作しているウィンドウであり、ユーザーからの入力(キーボードやマウスの操作)を受け取ることができます。

GetActiveWindow

GetActiveWindowは現在アクティブなウィンドウのハンドルを取得するために使用します。

SetWindowPos

SetWindowPosはウィンドウのサイズ、位置、ウィンドウの前後関係を変更するために使います。

constたち

private const uint SWP_NOMOVE = 0x0002;  // 現在位置を保持します
private const uint SWP_NOSIZE = 0x0001;  // 現在のサイズを保持します
private const uint SWP_NOZORDER = 0x0010;  // 現在の Z オーダーを保持します
private const uint SWP_SHOWWINDOW = 0x0040; // ウィンドウが表示されます。
private const int HWND_TOPMOST = -1;  // 最上位以外のすべてのウィンドウの上にウィンドウをPlacesします。
private const int HWND_NOTOPMOST = -2; // 最上位以外のすべてのウィンドウ (つまり、すべての最上位ウィンドウの背後) の上にウィンドウをPlacesします。

SetWindowPosに入れるための値です。これの最後の引数にはフラグをいくつか組み合わせて設定を渡します。
これらの値が何を表しているのかはドキュメントに書いてあります。

メソッド

public void SetWindowOnTop(bool isOnTop)
{
    IntPtr hWnd = GetActiveWindow();
    if (isOnTop)
    {
        SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW);
    }
    else
    {
        SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
    }

    // アクティブウィンドウに戻す
    SetForegroundWindow(hWnd);
}

まず、GetActiveWindowを使用してアクティブなウィンドウを取得します。

最前面にするかの部分でSetWindowPosに入れる引数がHWND_TOPMOSTを使うか、代わりにHWND_NOTOPMOSTを使うかの違いです。この値がウィンドウを最前面にするかの設定を変えます。

最後に設定したウィンドウをユーザーの操作を受け付ける状態にするためにSetForegroundWindowを使います。

これでウィンドウを最前面にできます!

ウィンドウのボタンを消す方法

[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();

[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);

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

GetWindowLong

ウィンドウのスタイル情報を取得します。

SetWindowLong

ウィンドウのスタイル情報を設定します。

const

private const int GWL_STYLE = -16;  // ウィンドウスタイルを取得 します。
private const int WS_MINIMIZEBOX = 0x00020000;  // 最小化ボタンのスタイル
private const int WS_MAXIMIZEBOX = 0x00010000;  // 最大化ボタンのスタイル
private const int WS_SYSMENU = 0x00080000;  // システムメニュー(閉じるボタン)のスタイル

スタイルのボタンには定数が決まってるらしいのでそれを宣言します。

メソッド

public void SetWindowButtonHide(bool isHide)
{
    IntPtr windowHandle = GetActiveWindow();
    int style = GetWindowLong(windowHandle, GWL_STYLE);

    if (isHide)
    {
        style &= ~WS_MINIMIZEBOX;  // 最小化ボタンを無効化
        style &= ~WS_MAXIMIZEBOX;  // 最大化ボタンを無効化
        style &= ~WS_SYSMENU;      // システムメニュー(閉じるボタン)を無効化
    }
    else
    {
        style |= WS_MINIMIZEBOX;  // 最小化ボタンを有効化
        style |= WS_MAXIMIZEBOX;  // 最大化ボタンを有効化
        style |= WS_SYSMENU;      // システムメニュー(閉じるボタン)を有効化
    }

    SetWindowLong(windowHandle, GWL_STYLE, style);
}

まず、GetActiveWindowを使用してアクティブなウィンドウを取得します。
次にGetWindowLongを使うとウィンドウのスタイルを取得できるので取得します。
ボタンにビット演算で無効化したり、有効化したりします。

無効化
&はAND演算子です。ビットが両方とも1の場合にだけ1になります。
~はNOT演算子です。ビットを反転させます。

つまり、ボタンを無効化するときは
styleのビット値と反転したWS_MINIMIZEBOXをAND演算し、WS_MINIMIZEBOXに対応するビットをクリアします。残りのパラメータも同じように処理します。

style00000000 11111111 00000000 00000000
WS_MINIMIZEBOX00000000 00000010 00000000 00000000

~WS_MINIMIZEBOXは反転するので11111111 11111101 11111111 11111111
ANDすると00000000 11111101 00000000 00000000となります。

有効化
|はOR演算子です。ビットにどちらかが1なら1になります。
つまり、ボタンを有効化するときは
styleのビット値とWS_MINIMIZEBOXをOR演算し、WS_MINIMIZEBOXに対応するビットをセットします。
残りのパラメータも同じように処理します。

一度無効化されてるのでstyle00000000 11111101 00000000 00000000です。
WS_MINIMIZEBOX00000000 00000010 00000000 00000000なので
ORすると00000000 11111111 00000000 00000000になります。

そして決まった設定をSetWindowLongでセットしています。

これでウィンドウのボタンを消せます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?