33
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Unity で Windows の透過ウィンドウを作る(操作も透過)

Last updated at Posted at 2019-02-08

はじめに

VTuber的な、3Dモデルと画面のキャプチャを統合する方法を考えたときに以下があると思う。※実際の方法・最適解は知らない
・ モデルと画面を別撮りして、編集で合成する方法
・ 画面のキャプチャとモデルを並列して表示するアプリケーション

そんな統合方法の内、先に画面へモデルを表示しようというコンセプトがこの記事。

この方法を使うと、モデルを表示するアプリケーションは独立しつつも、キャプチャ画面と同時にモデルをディスプレイに表示できる。

動作環境

WindowsAPIを使用しているので、Windows限定

確認環境

・Windows10
・Unity(2018.3.2f1)

使用例

こんなことができますよって
wa.gif
(前面にUnityのアプリケーションを実行しつつも、裏のUnityも操作できる。)

使用方法

  1. CameraClear FlagsSolid Colorにする
  2. CameraBackgroundを黒色にする

TransparentWindow.csを適当なオブジェクトにアタッチする

※ソースコードは(TransparentWindow.cs)からダウンロード

※Unity Editor上での動作は把握していない(WindowsAPIを使用している)ので、EXE形式にビルドしてから実行する。

解説

詳しくは、MSDNを見れば解決!! ・・・ とはいかないかも?

GetActiveWindow

GetActiveWindow
IntPtr windowHandle = GetActiveWindow();

これから操作を行うウィンドウハンドルを取得する。

SetWindowLong

SetWindowLong
const int GWL_STYLE   = -16;
const int GWL_EXSTYLE = -20;
const uint WS_POPUP = 0x80000000;
const uint WS_EX_LAYERD = 0x080000;
const uint WS_EX_TRANSPARENT = 0x00000020;

SetWindowLong(windowHandle, GWL_STYLE, WS_POPUP);
SetWindowLong(windowHandle, GWL_EXSTYLE, WS_EX_LAYERD | WS_EX_TRANSPARENT);
変数名 意味合い
GWL_STYLE ウィンドウスタイルの設定
GWL_EXSTYLE ウィンドウ拡張スタイルの設定
WS_POPUP ポップアップウィンドウにする
WS_EX_LAYERD マウスイベントを貫通させる
WS_EX_TRANSPARENT ウィンドウの裏にある画面の描画

SetWindowPos

SetWindowPos
IntPtr HWND_TOPMOST = new IntPtr(-1);
const uint SWP_NOSIZE = 0x0001;
const uint SWP_NOMOVE = 0x0002;
const uint SWP_NOACTIVE = 0x0010;
const uint SWP_SHOWWINDOW = 0x0040;

SetWindowPos(windowHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVE | SWP_SHOWWINDOW);

HWND_TOPMOST でウィンドウを最前面に表示し続けるように設定する。

DwmExtendFrameIntoClientArea

DwmExtendFrameIntoClientArea
MARGINS margins = new MARGINS()
{
    cxLeftWidth = -1
};

DwmExtendFrameIntoClientArea(windowHandle, ref margins);

ウィンドウのフレームをクライアントエリアに拡張させる。
cxLeftWidth = -1の時はクライアントエリア全体に影響が及ぶ。

試した所感

上の説明はMSDNから概要(自己解釈)を取ってきただけで、実際にその通りに動く感じはなかった(少なくとも自分の環境では)。

ウィンドウのフレームを消し、透明にする

WS_POPUP + DwmExtendFrameIntoClientArea
ポップアップウィンドウで消えたフレームを、クライアントエリアに拡張するイメージ。
自分の場合、この設定でウィンドウを透明にできた。

ウィンドウのマウスイベントを透過する

WS_EX_LAYERD + WS_EX_TRANSPARENT
WS_EX_LAYERDだけでもよさそうだが、どちらも設定しないとマウスイベントをウィンドウが吸ってしまっていた。

マウスイベントを拾わないようになったのですぐに非アクティブになるが、非アクティブ時でも前面に表示するためにHWND_TOPMOSTを設定する。

おわりに

使用例こそショボいけど、制限は黒色を使えないだけなので、使い方次第ではデスクトップに常駐したゲームとか作れるかもしれないし、アイディア次第ではもっと面白いアプリケーションが作れるかもしれない。

33
20
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
33
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?