Programmer:)
[Unity] user32.dll을 이용한 윈도우 컨트롤 (feat.Title bar 제거) 본문
반응형
Unity에서 fullScreen mode 가 아닌 window mode 에서 윈도우 상단바(타이틀 바)를 제거하고 싶었다.
using System;
using System.Runtime.InteropServices; //user32.dll 임포트
using UnityEngine;
public class Window : MonoBehaviour
{
#region DLLstuff
const int SWP_HIDEWINDOW = 0x80;
const int SWP_SHOWWINDOW = 0x40;
const int SWP_NOMOVE = 0x0002;
const int SWP_NOSIZE = 0x0001;
const uint WS_SIZEBOX = 0x00040000;
const int GWL_STYLE = -16;
const int WS_MINIMIZE = 0x20000000;
const int WS_MAXMIZE = 0x01000000;
const int WS_BORDER = 0x00800000;
const int WS_DLGFRAME = 0x00400000;
const int WS_CAPTION = WS_BORDER | WS_DLGFRAME;
const int WS_SYSMENU = 0x00080000;
const int WS_MAXIMIZEBOX = 0x00010000;
const int WS_MINIMIZEBOX = 0x00020000;
[DllImport("user32.dll")]
static extern System.IntPtr GetActiveWindow();
[DllImport("user32.dll")]
static extern int FindWindow(string lpClassName, string lpWindowName);
/// <summary>
/// window 크기와 위치변경
/// </summary>
/// <param name="hWnd">변경할 window handle</param>
/// <param name="hWndInsertAfter"> Z순서상 변경할 handle 앞에 올 handle</param>
/// HWND_BOTTOM : Z순서의 맨 아래에 위도우를 놓는다.
/// HWND_NOTOPMOST : 맨 위에있는 모든 윈도우 뒤에 윈도우를 놓는다.
/// HWND_TOP : Z순서상 맨 위에 윈도우를 놓는다.
/// HWND_TOPMOST : 최상위 위치를 유지(비활성와 되어도)
/// <param name="X"></param>
/// <param name="Y"></param>
/// <param name="cx">넓이</param>
/// <param name="cy">높이</param>
/// <param name="uFlags">플래그</param>
/// SWP_SHOWWINDOW : 윈도우 표시(이동 크기변경 무시)
/// SWP_HIDEWINDOW : 윈도우를 숨김(이동 크기변경 무시)
/// SWP_DRAWFRAME : 윈도우 주변에 프레임을 그림
/// SWP_NOACTIVATE : 크기 변경 후 윈도우를 활성화 시키지 않음
/// SWP_NOMOVE : 현재위치 유지
/// SWP_NOSIZE : 현재크기 유지
/// SWP_NOZORDER : 현재 Z순서를 그대로 유지
/// <returns></returns>
[DllImport("user32.dll")]
static extern bool SetWindowPos(
System.IntPtr hWnd, //window handle
System.IntPtr hWndInsertAfter, // window 배치 순서
short X, // x position
short Y, // y position
short cx, // window width
short cy, // window height
uint uFlags // window flags.
);
/// <summary>
/// 특정 윈도우 속성 변경 (32,64bit 모두 호환)
/// </summary>
/// <param name="hWnd">window handle</param>
/// <param name="nIndex">변경할 속성 설정</param>
/// GWL_EXSTYLE : 새로운 확장 윈도우 스타일 설정
/// GWL_HINSTANCE : window를 생성한 응용프로그램의 인스턴스 핸들을 변경
/// GWL_ID : window control ID 변경
/// GWL_STYLE : 새로운 스타일 설정
/// GWL_USERDATA : 연관된 32bit 값을 변경
/// GWL_WNDPROC : window WndProc(프로시저)의 주소를 변경
/// <param name="dwNewLong"></param>
/// WS_BORDER : 테두리있음
/// WS_CAPTION : 제목 표시줄 있음
/// WS_HSCROL : 가로 스크록 막대가 있음
/// WS_ICONIC / WS_MINIMIZE : 최소화로 시작
/// WS_MAXIMIZE : 최대화로 시작
/// WS_MAXIMIZEBOX : 최대화 버튼 있음
/// WS_MINIMIZEBOX : 최소화 버튼 있음
/// WS_SIZEBOX / WS_THICKFRAME : 크기조정 테두리가 있음
/// WS_SYSMENU : 제목 표시줄에는 창 메뉴가 있음
/// <returns></returns>
[DllImport("user32.dll")]
static extern System.IntPtr SetWindowLong(
System.IntPtr hWnd, // window handle
int nIndex,
uint dwNewLong
);
/// <summary>
/// 윈도우 정보를 가져온다
/// </summary>
/// <param name="hWnd">window handle</param>
/// <param name="nIndex">어느 값을 가져올지</param>
/// GWL_EXSTYLE : 확장 윈도우 스타일을 가져옴
/// GWL_HINSTANCE : 응용프로그램 인스턴스 핸들
/// GWL_ID : windowID
/// GWL_STYLE : 윈도우 스타일
/// GWL_USERDATA : 윈도우와 관련된 사용자 정보
/// GWL_WNDPROC : window Proc
/// <returns></returns>
[DllImport("user32.dll")]
static extern System.IntPtr GetWindowLong(
System.IntPtr hWnd,
int nIndex
);
System.IntPtr hWnd;
System.IntPtr HWND_TOP = new System.IntPtr(0);
System.IntPtr HWND_TOPMOST = new System.IntPtr(-1);
System.IntPtr HWND_NOTOPMOST = new System.IntPtr(-2);
#endregion
[SerializeField] bool hideOnStart = false;
public void ShowWindowBorders(bool value)
{
if (Application.isEditor) return;
int style = GetWindowLong(hWnd, GWL_STYLE).ToInt32();
if (value)
{
SetWindowLong(hWnd, GWL_STYLE, (uint)(style | WS_CAPTION | WS_SIZEBOX));
SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
}
else //remove title bar
{
SetWindowLong(hWnd, GWL_STYLE, (uint)(style &~(WS_CAPTION | WS_SIZEBOX)));
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
}
//버튼선택영역이 틀어졌을경우 해상도에 맞춰 호출
//Screen.SetResolution(X, Y, false);
}
private void Awake()
{
hWnd = GetActiveWindow();
}
private void Start()
{
if (hideOnStart) ShowWindowBorders(false);
}
}
위 코드가 간헐적인 titlebar 미제거 현상이 발생
using System;
using UnityEngine;
using System.Runtime.InteropServices;
public class BorderlessWindow
{
public static bool framed = true;
[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);
[DllImport("user32.dll")]
private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hwnd, out WinRect lpRect);
private struct WinRect { public int left, top, right, bottom; }
private const int GWL_STYLE = -16;
private const int SW_MINIMIZE = 6;
private const int SW_MAXIMIZE = 3;
private const int SW_RESTORE = 9;
private const uint WS_VISIBLE = 0x10000000;
private const uint WS_POPUP = 0x80000000;
private const uint WS_BORDER = 0x00800000;
private const uint WS_OVERLAPPED = 0x00000000;
private const uint WS_CAPTION = 0x00C00000;
private const uint WS_SYSMENU = 0x00080000;
private const uint WS_THICKFRAME = 0x00040000; // WS_SIZEBOX
private const uint WS_MINIMIZEBOX = 0x00020000;
private const uint WS_MAXIMIZEBOX = 0x00010000;
private const uint WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
// This attribute will make the method execute on game launch, after the Unity Logo Splash Screen.
//[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
public static void InitializeOnLoad()
{
#if !UNITY_EDITOR && UNITY_STANDALONE_WIN // Dont do this while on Unity Editor!
SetFramelessWindow();
#endif
}
public static void SetFramelessWindow()
{
var hwnd = GetActiveWindow();
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
framed = false;
}
public static void SetFramedWindow()
{
var hwnd = GetActiveWindow();
SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
framed = true;
}
public static void MinimizeWindow()
{
var hwnd = GetActiveWindow();
ShowWindow(hwnd, SW_MINIMIZE);
}
public static void MaximizeWindow()
{
var hwnd = GetActiveWindow();
ShowWindow(hwnd, SW_MAXIMIZE);
}
public static void RestoreWindow()
{
var hwnd = GetActiveWindow();
ShowWindow(hwnd, SW_RESTORE);
}
public static void MoveWindowPos(Vector2 posDelta, int newWidth, int newHeight)
{
var hwnd = GetActiveWindow();
var windowRect = GetWindowRect(hwnd, out WinRect winRect);
var x = winRect.left + (int)posDelta.x;
var y = winRect.top - (int)posDelta.y;
MoveWindow(hwnd, x, y, newWidth, newHeight, false);
}
}
반응형
'DEV > Unity' 카테고리의 다른 글
[Unity] Android Build StatusBar and NavigationBar Visible/Hidden 안드로이드 상태바 네비게이션바 컨트롤 (0) | 2022.01.27 |
---|---|
[Unity] Vuforia SDK 셋팅법 (Unity 2019.2 이후 버전) (0) | 2022.01.07 |
[Unity] Android TEST 방법 Unity Remote 5 (0) | 2021.03.11 |
[Unity] Zxing을 이용한 QR코드 생성방법 (0) | 2021.03.10 |
[Unity] Path정리 (0) | 2021.03.10 |
Comments