채팅 추가

This commit is contained in:
2026-09-01 14:40:02 +09:00
parent cab0d772b1
commit a5a1f1d9e9
50 changed files with 3843 additions and 1124 deletions

View File

@@ -47,6 +47,7 @@ internal static class Win32
public const int SW_SHOW = 5;
public const int VK_LBUTTON = 0x01;
public const int VK_ESCAPE = 0x1B;
public const int VK_SHIFT = 0x10;
public const int VK_CONTROL = 0x11;
public const int VK_MENU = 0x12; // Alt
@@ -105,6 +106,47 @@ public struct RECT
[DllImport("user32.dll")] public static extern bool SetLayeredWindowAttributes(IntPtr hWnd, uint crKey, byte bAlpha, uint dwFlags);
[DllImport("dwmapi.dll")] public static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset);
// --- 포커스 ---
[DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")] public static extern IntPtr SetFocus(IntPtr hWnd);
[DllImport("user32.dll")] public static extern bool IsWindow(IntPtr hWnd);
[DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")] public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("kernel32.dll")] public static extern uint GetCurrentThreadId();
public static bool IsKeyDown(int vKey) => (GetAsyncKeyState(vKey) & 0x8000) != 0;
/// <summary>
/// 창을 확실히 활성화한다.
///
/// SetForegroundWindow 는 그냥 부르면 자주 무시된다. 윈도우는 포그라운드를
/// 가로채는 것을 막으려고 "마지막 입력을 받은 프로세스"만 허용하는데, 우리 창은
/// WS_EX_NOACTIVATE 라 그 판정에서 밀리는 경우가 있다. 현재 포그라운드 창의
/// 입력 큐에 잠깐 붙었다 떼면 같은 스레드로 취급돼 통과한다.
/// </summary>
public static void ForceForeground(IntPtr hwnd)
{
if (hwnd == IntPtr.Zero) return;
IntPtr foreground = GetForegroundWindow();
if (foreground == hwnd)
{
SetFocus(hwnd);
return;
}
uint currentThread = GetCurrentThreadId();
uint foregroundThread = foreground != IntPtr.Zero
? GetWindowThreadProcessId(foreground, out _)
: currentThread;
bool attached = foregroundThread != 0 && foregroundThread != currentThread &&
AttachThreadInput(currentThread, foregroundThread, true);
SetForegroundWindow(hwnd);
SetFocus(hwnd);
if (attached) AttachThreadInput(currentThread, foregroundThread, false);
}
}
#endif