[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool SetWindowPos(
IntPtr hWnd, // 窗口句柄
IntPtr hWndInsertAfter, // Z-order 參考窗口
int X, int Y, // 新位置
int cx, int cy, // 新尺寸
uint uFlags // 操作標誌位組合
);
// hWndInsertAfter 特殊值
static readonly IntPtr HWND_TOP = new IntPtr(0); // 置頂
static readonly IntPtr HWND_BOTTOM = new IntPtr(1); // 置底
static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); // 永久置頂
static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2); // 取消永久置頂
// uFlags 常用組合
const uint SWP_NOSIZE = 0x0001; // 保持原尺寸
const uint SWP_NOMOVE = 0x0002; // 保持原位置
const uint SWP_NOZORDER = 0x0004; // 保持原 Z-order
const uint SWP_NOACTIVATE = 0x0010; // 不激活窗口
const uint SWP_SHOWWINDOW = 0x0040; // 顯示窗口
// 在 Form_Load 中
SetWindowPos(this.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
var frm = new Form2();
frm.Show();
// 獲取剛激活的前台窗口並置頂
SetWindowPos(GetForegroundWindow(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
輔助 API:
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
SetWindowPos(hWnd, IntPtr.Zero, 100, 100, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 800, 600, SWP_NOMOVE | SWP_NOZORDER);
SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
public static class WindowPositionHelper {
[DllImport("user32.dll", SetLastError = true)]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
int X, int Y, int cx, int cy, uint uFlags);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
private static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
private const uint SWP_NOSIZE = 0x0001;
private const uint SWP_NOMOVE = 0x0002;
private const uint SWP_NOZORDER = 0x0004;
public static void SetTopMost(IntPtr hWnd, bool topMost) {
SetWindowPos(hWnd, topMost ? HWND_TOPMOST : HWND_NOTOPMOST,
0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
public static void MoveWindow(IntPtr hWnd, int x, int y) {
SetWindowPos(hWnd, IntPtr.Zero, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
public static void ResizeWindow(IntPtr hWnd, int width, int height) {
SetWindowPos(hWnd, IntPtr.Zero, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER);
}
public static void SetBounds(IntPtr hWnd, int x, int y, int width, int height) {
SetWindowPos(hWnd, IntPtr.Zero, x, y, width, height, SWP_NOZORDER);
}
public static void BringToFrontAndActivate(IntPtr hWnd) {
SetWindowPos(hWnd, new IntPtr(0), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
}
| 問題 | 原因 | 解決 |
|---|---|---|
| 置頂不生效 | 旗標衝突或句柄無效 | 確保 Handle 已創建(在 Load/Shown 事件中調用),檢查返回值 |
| 位置偏移 | DPI 縮放、多顯示器座標系 | 使用邏輯像素,或 SetProcessDpiAwarenessContext |
| 閃爍/重繪異常 | 缺少 SWP_NOREDRAW 或衝突 | 添加 SWP_NOREDRAW = 0x0008 或處理 WM_WINDOWPOSCHANGING |
| 模態對話框置頂失效 | 模態循環阻塞 | 在 ShowDialog 前設置 Owner,或用 HWND_TOPMOST |
Form.TopMost = true、Form.BringToFront()、Form.Location/SizeWindow.Topmost、Window.WindowStartupLocation、Window.Left/Top/Width/Height