557 lines
27 KiB
C#
557 lines
27 KiB
C#
// Copyright (C) 2018 logonkhi@gmail.com - All Rights Reserved
|
|
// Version 1.0.0
|
|
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using UnityEngine;
|
|
using UVC.Core;
|
|
|
|
|
|
namespace UVC.Util
|
|
{
|
|
public enum GWLWindowStyles : long
|
|
{
|
|
GWL_EXSTYLE = -20, // 새로운 확장 창 스타일을 설정합니다.
|
|
GWL_HINSTANCE = -6, // 새로운 애플리케이션 인스턴스 핸들을 설정합니다.
|
|
GWL_ID = -12, // 자식 창의 새로운 식별자를 설정합니다. 창은 최상위 창일 수 없습니다.
|
|
GWL_STYLE = -16, // 새로운 창 스타일을 설정합니다.
|
|
GWL_USERDATA = -21, // 창과 연관된 사용자 데이터를 설정합니다. 이 데이터는 창을 생성한 애플리케이션에서 사용하기 위한 것입니다. 초기 값은 0입니다.
|
|
GWL_WNDPROC = -4 // 창 프로시저의 새로운 주소를 설정합니다. 호출 스레드와 동일한 프로세스에 속하지 않는 창의 속성은 변경할 수 없습니다.
|
|
}
|
|
|
|
public enum WindowStyles : long
|
|
{
|
|
WS_BORDER = 0x00800000, // 창에 얇은 선의 테두리가 있습니다.
|
|
WS_CAPTION = 0x00C00000, // 창에 제목 표시줄이 있습니다(WS_BORDER 스타일 포함).
|
|
WS_CHILD = 0x40000000, // 창이 자식 창입니다. 이 스타일을 가진 창은 메뉴 표시줄을 가질 수 없습니다. 이 스타일은 WS_POPUP 스타일과 함께 사용할 수 없습니다.
|
|
WS_CHILDWINDOW = 0x40000000, // WS_CHILD 스타일과 동일합니다.
|
|
WS_CLIPCHILDREN = 0x02000000, // 부모 창 내에서 그리기가 발생할 때 자식 창이 차지하는 영역을 제외합니다. 이 스타일은 부모 창을 생성할 때 사용됩니다.
|
|
WS_CLIPSIBLINGS = 0x04000000, // 자식 창을 서로 상대적으로 클리핑합니다. 특정 자식 창이 WM_PAINT 메시지를 받을 때 WS_CLIPSIBLINGS 스타일은 다른 겹치는 자식 창을 업데이트할 영역에서 제외합니다.
|
|
WS_DISABLED = 0x08000000, // 창이 처음에 비활성화됩니다. 비활성화된 창은 사용자로부터 입력을 받을 수 없습니다.
|
|
WS_DLGFRAME = 0x00400000, // 창에 대화 상자 스타일의 테두리가 있습니다. 이 스타일을 가진 창은 제목 표시줄을 가질 수 없습니다.
|
|
WS_GROUP = 0x00020000, // 창이 컨트롤 그룹의 첫 번째 컨트롤입니다. 그룹은 이 첫 번째 컨트롤과 WS_GROUP 스타일이 있는 다음 컨트롤까지 정의된 모든 컨트롤로 구성됩니다.
|
|
WS_HSCROLL = 0x00100000, // 창에 가로 스크롤바가 있습니다.
|
|
WS_ICONIC = 0x20000000, // 창이 처음에 최소화됩니다. WS_MINIMIZE 스타일과 동일합니다.
|
|
WS_MAXIMIZE = 0x01000000, // 창이 처음에 최대화됩니다.
|
|
WS_MAXIMIZEBOX = 0x00010000, // 창에 최대화 버튼이 있습니다. WS_EX_CONTEXTHELP 스타일과 함께 사용할 수 없습니다.
|
|
WS_MINIMIZE = 0x20000000, // 창이 처음에 최소화됩니다. WS_ICONIC 스타일과 동일합니다.
|
|
WS_MINIMIZEBOX = 0x00020000, // 창에 최소화 버튼이 있습니다. WS_EX_CONTEXTHELP 스타일과 함께 사용할 수 없습니다. WS_SYSMENU 스타일도 지정해야 합니다.
|
|
WS_OVERLAPPED = 0x00000000, // 창이 겹쳐진 창입니다. 겹쳐진 창은 제목 표시줄과 테두리를 가집니다. WS_TILED 스타일과 동일합니다.
|
|
WS_OVERLAPPEDWINDOW = 0x00000000 | 0x00C00000 | 0x00080000 | 0x00040000 | 0x00020000 | 0x00010000, // 창이 겹쳐진 창입니다. WS_TILEDWINDOW 스타일과 동일합니다.
|
|
WS_POPUP = 0x80000000, // 창이 팝업 창입니다. 이 스타일은 WS_CHILD 스타일과 함께 사용할 수 없습니다.
|
|
WS_POPUPWINDOW = 0x80000000 | 0x00800000 | 0x00080000, // 창이 팝업 창입니다. WS_CAPTION 및 WS_POPUPWINDOW 스타일을 결합하여 창 메뉴를 표시할 수 있습니다.
|
|
WS_SIZEBOX = 0x00040000, // 창에 크기 조정 테두리가 있습니다. WS_THICKFRAME 스타일과 동일합니다.
|
|
WS_SYSMENU = 0x00080000, // 창의 제목 표시줄에 시스템 메뉴가 있습니다. WS_CAPTION 스타일도 지정해야 합니다.
|
|
WS_TABSTOP = 0x00010000, // 창이 사용자가 TAB 키를 눌렀을 때 키보드 포커스를 받을 수 있는 컨트롤입니다. TAB 키를 누르면 WS_TABSTOP 스타일이 있는 다음 컨트롤로 키보드 포커스가 이동합니다.
|
|
WS_THICKFRAME = 0x00040000, // 창에 크기 조정 테두리가 있습니다. WS_SIZEBOX 스타일과 동일합니다.
|
|
WS_TILED = 0x00000000, // 창이 겹쳐진 창입니다. 겹쳐진 창은 제목 표시줄과 테두리를 가집니다. WS_OVERLAPPED 스타일과 동일합니다.
|
|
WS_TILEDWINDOW = 0x00000000 | 0x00C00000 | 0x00080000 | 0x00040000 | 0x00020000 | 0x00010000, // 창이 겹쳐진 창입니다. WS_OVERLAPPEDWINDOW 스타일과 동일합니다.
|
|
WS_VISIBLE = 0x10000000, // 창이 처음에 표시됩니다.
|
|
WS_VSCROLL = 0x00200000 // 창에 세로 스크롤바가 있습니다.
|
|
}
|
|
|
|
public enum ExtendedWindowStyles : long
|
|
{
|
|
WS_EX_ACCEPTFILES = 0x00000010, // 창이 드래그 앤 드롭 파일을 허용합니다.
|
|
WS_EX_APPWINDOW = 0x00040000, // 창이 보일 때 최상위 창을 작업 표시줄에 강제로 표시합니다.
|
|
WS_EX_CLIENTEDGE = 0x00000200, // 창에 오목한 가장자리 테두리가 있습니다.
|
|
WS_EX_COMPOSITED = 0x02000000, // 모든 하위 창을 이중 버퍼링을 사용하여 아래에서 위로 그립니다.
|
|
WS_EX_CONTEXTHELP = 0x00000400, // 창의 제목 표시줄에 물음표가 포함됩니다. 사용자가 물음표를 클릭하면 커서가 물음표와 포인터로 변경됩니다. 사용자가 자식 창을 클릭하면 WM_HELP 메시지를 받습니다.
|
|
WS_EX_CONTROLPARENT = 0x00010000, // 창 자체가 대화 상자 탐색에 참여해야 하는 자식 창을 포함합니다.
|
|
WS_EX_DLGMODALFRAME = 0x00000001, // 창에 이중 테두리가 있습니다. 선택적으로 WS_CAPTION 스타일을 dwStyle 매개변수에 지정하여 제목 표시줄을 생성할 수 있습니다.
|
|
WS_EX_LAYERED = 0x00080000, // 창이 레이어드 창입니다.
|
|
WS_EX_LAYOUTRTL = 0x00400000, // 셸 언어가 히브리어, 아랍어 또는 읽기 순서 정렬을 지원하는 다른 언어인 경우 창의 수평 원점이 오른쪽 가장자리에 있습니다. 수평 값을 증가시키면 왼쪽으로 이동합니다.
|
|
WS_EX_LEFT = 0x00000000, // 창에 일반적인 왼쪽 정렬 속성이 있습니다. 기본값입니다.
|
|
WS_EX_LEFTSCROLLBAR = 0x00004000, // 셸 언어가 히브리어, 아랍어 또는 읽기 순서 정렬을 지원하는 다른 언어인 경우 수직 스크롤바(있는 경우)가 왼쪽에 있습니다.
|
|
WS_EX_LTRREADING = 0x00000000, // 창 텍스트가 왼쪽에서 오른쪽 읽기 순서 속성을 사용하여 표시됩니다. 기본값입니다.
|
|
WS_EX_MDICHILD = 0x00000040, // 창이 MDI 자식 창입니다.
|
|
WS_EX_NOACTIVATE = 0x08000000, // 이 스타일로 생성된 최상위 창은 사용자가 클릭해도 포그라운드 창이 되지 않습니다.
|
|
WS_EX_NOINHERITLAYOUT = 0x00100000, // 창이 창 레이아웃을 자식 창에 전달하지 않습니다.
|
|
WS_EX_NOPARENTNOTIFY = 0x00000004, // 이 스타일로 생성된 자식 창은 생성되거나 삭제될 때 WM_PARENTNOTIFY 메시지를 부모 창에 보내지 않습니다.
|
|
WS_EX_NOREDIRECTIONBITMAP = 0x00200000, // 창이 리디렉션 표면에 렌더링되지 않습니다. 이는 보이는 콘텐츠가 없거나 표면 이외의 메커니즘을 사용하여 시각적 콘텐츠를 제공하는 창에 해당합니다.
|
|
WS_EX_OVERLAPPEDWINDOW = 0x00000300, // 창이 겹쳐진 창입니다.
|
|
WS_EX_PALETTEWINDOW = 0x00000188, // 창이 팔레트 창입니다. 이는 명령 배열을 제공하는 모달리스 대화 상자입니다.
|
|
WS_EX_RIGHT = 0x00001000, // 창에 일반적인 "오른쪽 정렬" 속성이 있습니다. 이는 창 클래스에 따라 다릅니다.
|
|
WS_EX_RIGHTSCROLLBAR = 0x00000000, // 수직 스크롤바(있는 경우)가 클라이언트 영역의 오른쪽에 있습니다. 기본값입니다.
|
|
WS_EX_RTLREADING = 0x00002000, // 셸 언어가 히브리어, 아랍어 또는 읽기 순서 정렬을 지원하는 다른 언어인 경우 창 텍스트가 오른쪽에서 왼쪽 읽기 순서 속성을 사용하여 표시됩니다.
|
|
WS_EX_STATICEDGE = 0x00020000, // 창에 사용자 입력을 받지 않는 항목에 사용하기 위한 3차원 테두리 스타일이 있습니다.
|
|
WS_EX_TOOLWINDOW = 0x00000080, // 창이 플로팅 도구 모음으로 사용되도록 의도되었습니다. 도구 창은 일반 제목 표시줄보다 짧은 제목 표시줄을 가지며 창 제목은 더 작은 글꼴로 그려집니다.
|
|
WS_EX_TOPMOST = 0x00000008, // 창이 모든 비최상위 창 위에 배치되며 비활성화되더라도 그 위에 유지됩니다. 이 스타일을 추가하거나 제거하려면 SetWindowPos 함수를 사용하십시오.
|
|
WS_EX_TRANSPARENT = 0x00000020, // 창이 동일한 스레드에서 생성된 아래의 형제 창이 그려질 때까지 그려지지 않습니다. 창은 투명하게 보입니다.
|
|
WS_EX_WINDOWEDGE = 0x00000100 // 창에 돌출된 가장자리 테두리가 있습니다.
|
|
}
|
|
|
|
public enum WindowToolsFlags : long
|
|
{
|
|
SWP_NOSIZE = 0x0001, //Binary: 0000 0000 0000 0001
|
|
SWP_NOMOVE = 0x0002, //Binary: 0000 0000 0000 0010
|
|
SWP_NOZORDER = 0x0004, //Binary: 0000 0000 0000 0100
|
|
SWP_DRAWFRAME = 0x0020, //Binary: 0000 0000 0010 0000
|
|
SWP_HIDEWINDOW = 0x0080, //Binary: 0000 0000 1000 0000
|
|
SWP_NOACTIVATE = 0x0010, //Binary: 0000 0000 0001 0000
|
|
SWP_SHOWWINDOW = 0x0040 //Binary: 0000 0000 0100 0000
|
|
}
|
|
|
|
public enum WindowToolsAlphaFlag : long
|
|
{
|
|
LWA_ALPHA = 0x00000002, //Binary: 0000 0000 0000 0000 0000 0000 0000 0010
|
|
LWA_COLORKEY = 0x00000001 //Binary: 0000 0000 0000 0000 0000 0000 0000 0001
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// WindowTools 클래스는 Unity 애플리케이션에서 창의 위치, 크기, 스타일 등을 제어하는 기능을 제공합니다.
|
|
/// 이 클래스는 Windows API를 활용하여 창의 속성을 변경하며, Unity 환경에서 실행 시 유용한 창 관리 기능을 제공합니다.
|
|
/// </summary>
|
|
public class WindowTools : Singleton<WindowTools>
|
|
{
|
|
[Serializable]
|
|
public class WindowInfoData
|
|
{
|
|
public enum WindowInfoDataWindowState
|
|
{
|
|
FullScreen = 0, // 전체 화면 모드
|
|
Default = 1, // 기본 창 모드
|
|
Minimized = 2, // 최소화된 창 모드
|
|
Maximized = 3 // 최대화된 창 모드
|
|
}
|
|
|
|
public enum WindowInfoDataWindowHAlign
|
|
{
|
|
Left = 0, // 왼쪽 정렬
|
|
Center = 1, // 중앙 정렬
|
|
Right = 2, // 오른쪽 정렬
|
|
}
|
|
|
|
public enum WindowInfoDataWindowVAlign
|
|
{
|
|
Top = 0, // 상단 정렬
|
|
Center = 1, // 중앙 정렬
|
|
Bottom = 2, // 하단 정렬
|
|
}
|
|
|
|
// 전체 화면 모드에서 사용할 해상도
|
|
public Vector2Int fullScreenResolution = new Vector2Int(1920, 1080);
|
|
|
|
// 창 크기
|
|
public Vector2Int size = new Vector2Int(1920, 1080);
|
|
|
|
// 창을 항상 최상위로 유지할지 여부
|
|
public bool alwaysTop = false;
|
|
|
|
// 창 테두리 표시 여부
|
|
public bool showBorder = true;
|
|
|
|
// 창의 초기 상태 (풀스크린, 기본, 최소화, 최대화)
|
|
public WindowInfoDataWindowState initWindowState = WindowInfoDataWindowState.FullScreen;
|
|
|
|
// 가로 정렬
|
|
public WindowInfoDataWindowHAlign hAlign = WindowInfoDataWindowHAlign.Center;
|
|
|
|
// 세로 정렬
|
|
public WindowInfoDataWindowVAlign vAlign = WindowInfoDataWindowVAlign.Center;
|
|
|
|
// 새 타이틀 명 (비어있으면 반영안됨)
|
|
public string title = "Octopus";
|
|
}
|
|
|
|
private WindowInfoData WindowInfo;
|
|
|
|
private IntPtr _hwnd; // 창 핸들
|
|
private long _old; // 이전 창 스타일
|
|
private int screenWidth; // 화면 너비
|
|
private int screenHeight; // 화면 높이
|
|
|
|
/// <summary>
|
|
/// 창의 초기 위치와 크기를 설정합니다.
|
|
/// </summary>
|
|
public void Init(WindowInfoData windowInfo)
|
|
{
|
|
|
|
this.WindowInfo = windowInfo;
|
|
|
|
#if !UNITY_EDITOR || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN
|
|
|
|
// 풀스크린인지 확인
|
|
if (WindowInfo.initWindowState == WindowInfoData.WindowInfoDataWindowState.FullScreen)
|
|
{
|
|
Screen.SetResolution(WindowInfo.fullScreenResolution.x, WindowInfo.fullScreenResolution.y, true);
|
|
Screen.fullScreenMode = FullScreenMode.FullScreenWindow;
|
|
return;
|
|
}
|
|
|
|
Initialize();
|
|
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// 창 초기화 작업을 수행합니다.
|
|
/// </summary>
|
|
private void Initialize()
|
|
{
|
|
//if (!Application.isEditor && Application.platform == RuntimePlatform.WindowsPlayer)
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|
_hwnd = GetWindowHandle();//FindWindow("UnityWndClass", Application.productName);
|
|
_old = GetWindowLong(_hwnd, (long)GWLWindowStyles.GWL_STYLE);
|
|
|
|
int hWndInsertAfter = (this.WindowInfo.alwaysTop) ? -1 : 0;
|
|
|
|
|
|
Rect winRect = new Rect(0, 0, WindowInfo.size.x, WindowInfo.size.y);
|
|
|
|
//정렬된 창 크기 설정
|
|
switch (WindowInfo.hAlign)
|
|
{
|
|
case WindowInfoData.WindowInfoDataWindowHAlign.Left:
|
|
winRect.x = 0;
|
|
break;
|
|
case WindowInfoData.WindowInfoDataWindowHAlign.Center:
|
|
winRect.x = (Screen.width - winRect.width) / 2;
|
|
break;
|
|
case WindowInfoData.WindowInfoDataWindowHAlign.Right:
|
|
winRect.x = Screen.width - winRect.width;
|
|
break;
|
|
}
|
|
|
|
switch (WindowInfo.vAlign)
|
|
{
|
|
case WindowInfoData.WindowInfoDataWindowVAlign.Top:
|
|
winRect.y = 0;
|
|
break;
|
|
case WindowInfoData.WindowInfoDataWindowVAlign.Center:
|
|
winRect.y = (Screen.height - winRect.height) / 2;
|
|
break;
|
|
case WindowInfoData.WindowInfoDataWindowVAlign.Bottom:
|
|
winRect.y = Screen.height - winRect.height;
|
|
break;
|
|
}
|
|
|
|
SetActiveWindow(_hwnd);
|
|
|
|
if (!WindowInfo.showBorder)
|
|
{
|
|
SetWindowLong(_hwnd, (int)GWLWindowStyles.GWL_STYLE, 1);
|
|
}
|
|
|
|
SetWindowPos(_hwnd, hWndInsertAfter, (int)winRect.x, (int)winRect.y, (int)winRect.width, (int)winRect.height, (uint)WindowToolsFlags.SWP_SHOWWINDOW);
|
|
|
|
if (!string.IsNullOrEmpty(WindowInfo.title.Trim()))
|
|
{
|
|
SetWindowTitle(WindowInfo.title);
|
|
}
|
|
|
|
if (WindowInfo.initWindowState == WindowInfoData.WindowInfoDataWindowState.Minimized)
|
|
{
|
|
MinimizeWindow();
|
|
}
|
|
else if (WindowInfo.initWindowState == WindowInfoData.WindowInfoDataWindowState.Maximized)
|
|
{
|
|
MaximizeWindow();
|
|
}
|
|
else
|
|
{
|
|
NormalizeWindow();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 윈도우 창의 위치를 지정합니다.
|
|
/// </summary>
|
|
/// <param name="x">창의 X 좌표</param>
|
|
/// <param name="y">창의 Y 좌표</param>
|
|
public void SetWindowPosition(int x, int y)
|
|
{
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|
int hWndInsertAfter = (this.WindowInfo.alwaysTop) ? -1 : 0;
|
|
SetWindowPos(_hwnd, hWndInsertAfter, x, y, 0, 0, (UInt32)(WindowToolsFlags.SWP_NOSIZE | WindowToolsFlags.SWP_NOZORDER | WindowToolsFlags.SWP_DRAWFRAME));
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// 윈도우 창의 크기를 지정합니다.
|
|
/// </summary>
|
|
/// <param name="w">창의 너비</param>
|
|
/// <param name="h">창의 높이</param>
|
|
public void SetWindowSize(int w, int h)
|
|
{
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|
int hWndInsertAfter = (this.WindowInfo.alwaysTop) ? -1 : 0;
|
|
SetWindowPos(_hwnd, hWndInsertAfter, 0, 0, w, h, (UInt32)(WindowToolsFlags.SWP_NOMOVE | WindowToolsFlags.SWP_NOZORDER | WindowToolsFlags.SWP_DRAWFRAME));
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// 윈도우 창의 크기를 화면 해상도에 맞게 최대 크기로 설정합니다.
|
|
/// </summary>
|
|
public void SetWindowMaxSize()
|
|
{
|
|
SetWindowSize(screenWidth, screenHeight);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 윈도우 창의 테두리를 활성화합니다.
|
|
/// </summary>
|
|
public void ShowBorder()
|
|
{
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|
SetActiveWindow(_hwnd);
|
|
SetWindowLong(_hwnd, (int)GWLWindowStyles.GWL_STYLE, (int)_old);
|
|
RefreshWindow();
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// 윈도우 창의 테두리를 숨깁니다.
|
|
/// </summary>
|
|
public void HideBorder()
|
|
{
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|
SetActiveWindow(_hwnd);
|
|
SetWindowLong(_hwnd, (int)GWLWindowStyles.GWL_STYLE, 1);
|
|
RefreshWindow();
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// 윈도우 창을 새로고침하여 변경 사항을 적용합니다.
|
|
/// </summary>
|
|
private void RefreshWindow()
|
|
{
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|
int hWndInsertAfter = (this.WindowInfo.alwaysTop) ? -1 : 0;
|
|
|
|
Rect2 windowRect = new Rect2();
|
|
GetWindowRect(_hwnd, ref windowRect);
|
|
|
|
int screenW = (int)Screen.width;
|
|
int screenH = (int)Screen.height;
|
|
SetWindowPos(_hwnd, hWndInsertAfter, (int)windowRect.Left, (int)windowRect.Top, screenW, screenH, (int)(WindowToolsFlags.SWP_SHOWWINDOW));
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// 윈도우 창을 기본 상태로 설정합니다.
|
|
/// </summary>
|
|
public void NormalizeWindow()
|
|
{
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|
ShowWindowAsync(_hwnd, 1);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// 윈도우 창을 최소화합니다.
|
|
/// </summary>
|
|
public void MinimizeWindow()
|
|
{
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|
ShowWindowAsync(_hwnd, 2);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// 윈도우 창을 최대화합니다.
|
|
/// </summary>
|
|
public void MaximizeWindow()
|
|
{
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|
ShowWindowAsync(_hwnd, 3);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// 윈도우 창의 제목을 설정합니다.
|
|
/// </summary>
|
|
/// <param name="newTitle">새로운 창 제목</param>
|
|
public void SetWindowTitle(string newTitle)
|
|
{
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|
SetWindowText(_hwnd, newTitle);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// 윈도우 창의 투명도를 설정합니다.
|
|
/// </summary>
|
|
/// <param name="opacity">투명도 값 (0.0 ~ 1.0)</param>
|
|
public void SetAlphaWindow(float opacity)
|
|
{
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|
opacity = Mathf.Clamp01(opacity);
|
|
int alpha = Mathf.RoundToInt(opacity * 255);
|
|
SetWindowLong(_hwnd, (int)GWLWindowStyles.GWL_EXSTYLE, GetWindowLong(_hwnd, (long)GWLWindowStyles.GWL_EXSTYLE) | (long)ExtendedWindowStyles.WS_EX_LAYERED);
|
|
SetLayeredWindowAttributes(_hwnd, 0, (byte)alpha, (uint)WindowToolsAlphaFlag.LWA_ALPHA);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// 메시지 박스를 표시합니다.
|
|
/// </summary>
|
|
/// <param name="title">메시지 박스 제목</param>
|
|
/// <param name="message">메시지 내용</param>
|
|
/// <param name="type">메시지 박스 유형 (AbortRetryIgnore, CancelTryContinue, Help, OK, OkCancel, RetryCancel, YesNo, YesNoCancel)</param>
|
|
/// <returns>사용자가 선택한 버튼의 결과 (OK, CANCEL, ABORT, RETRY, IGNORE, YES, NO, TRY AGAIN)</returns>
|
|
public static string Alert(string title, string message, string type = "OK")
|
|
{
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|
try
|
|
{
|
|
string DialogResult = string.Empty;
|
|
uint MB_ABORTRETRYIGNORE = (uint)(0x00000002L | 0x00000010L);
|
|
uint MB_CANCELTRYCONTINUE = (uint)(0x00000006L | 0x00000030L);
|
|
uint MB_HELP = (uint)(0x00004000L | 0x00000040L);
|
|
uint MB_OK = (uint)(0x00000000L | 0x00000040L);
|
|
uint MB_OKCANCEL = (uint)(0x00000001L | 0x00000040L);
|
|
uint MB_RETRYCANCEL = (uint)0x00000005L;
|
|
uint MB_YESNO = (uint)(0x00000004L | 0x00000040L);
|
|
uint MB_YESNOCANCEL = (uint)(0x00000003L | 0x00000040L);
|
|
int intresult = -1;
|
|
string strResult = string.Empty;
|
|
|
|
switch (type)
|
|
{
|
|
case "AbortRetryIgnore":
|
|
intresult = MessageBox(GetWindowHandle(), message, title, MB_ABORTRETRYIGNORE);
|
|
break;
|
|
case "CancelTryContinue":
|
|
intresult = MessageBox(GetWindowHandle(), message, title, MB_CANCELTRYCONTINUE);
|
|
break;
|
|
case "Help":
|
|
intresult = MessageBox(GetWindowHandle(), message, title, MB_HELP);
|
|
break;
|
|
case "OK":
|
|
intresult = MessageBox(GetWindowHandle(), message, title, MB_OK);
|
|
break;
|
|
case "OkCancel":
|
|
intresult = MessageBox(GetWindowHandle(), message, title, MB_OKCANCEL);
|
|
break;
|
|
case "RetryCancel":
|
|
intresult = MessageBox(GetWindowHandle(), message, title, MB_RETRYCANCEL);
|
|
break;
|
|
case "YesNo":
|
|
intresult = MessageBox(GetWindowHandle(), message, title, MB_YESNO);
|
|
break;
|
|
case "YesNoCancel":
|
|
intresult = MessageBox(GetWindowHandle(), message, title, MB_YESNOCANCEL);
|
|
break;
|
|
default:
|
|
intresult = MessageBox(GetWindowHandle(), message, title, (uint)(0x00000000L | 0x00000010L));
|
|
break;
|
|
}
|
|
|
|
switch (intresult)
|
|
{
|
|
case 1:
|
|
strResult = "OK";
|
|
break;
|
|
case 2:
|
|
strResult = "CANCEL";
|
|
break;
|
|
case 3:
|
|
strResult = "ABORT";
|
|
break;
|
|
case 4:
|
|
strResult = "RETRY";
|
|
break;
|
|
case 5:
|
|
strResult = "IGNORE";
|
|
break;
|
|
case 6:
|
|
strResult = "YES";
|
|
break;
|
|
case 7:
|
|
strResult = "NO";
|
|
break;
|
|
case 10:
|
|
strResult = "TRY AGAIN";
|
|
break;
|
|
default:
|
|
strResult = "OK";
|
|
break;
|
|
|
|
}
|
|
|
|
return strResult;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return string.Empty;
|
|
}
|
|
#endif
|
|
return string.Empty;
|
|
}
|
|
|
|
|
|
private static System.IntPtr GetWindowHandle()
|
|
{
|
|
return GetActiveWindow();
|
|
}
|
|
|
|
#region User32
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
|
|
|
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
|
|
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern IntPtr GetForegroundWindow();
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern long GetWindowText(IntPtr hWnd, StringBuilder text, int count);
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern bool SetWindowText(System.IntPtr hwnd, System.String lpString);
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern IntPtr SetWindowLong(IntPtr hwnd, long nIndex, long dwNewLong);
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern IntPtr SetWindowLong(IntPtr hwnd, int _nIndex, int dwNewLong);
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern long GetWindowLong(IntPtr hwnd, long nIndex);
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
|
|
|
|
[DllImport("user32")]
|
|
static extern int SetActiveWindow(IntPtr hwnd);
|
|
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern bool GetWindowRect(IntPtr hwnd, ref Rect2 rectangle);
|
|
|
|
|
|
|
|
public struct Rect2
|
|
{
|
|
public int Left { get; set; }
|
|
public int Top { get; set; }
|
|
public int Right { get; set; }
|
|
public int Bottom { get; set; }
|
|
}
|
|
#endif
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern IntPtr GetActiveWindow();
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
static extern int MessageBox(IntPtr hwnd, String lpText, String lpCaption, uint uType);
|
|
#endregion
|
|
}
|
|
} |