2012-06-16 41 views
8

Làm cách nào để nhận trạng thái cửa sổ (maximized, minimized) của một quy trình khác đang chạy?Lấy trạng thái cửa sổ của một quá trình khác

Tôi muốn thử bằng cách sử dụng này:

Process[] procs = Process.GetProcesses(); 

     foreach (Process proc in procs) 
     { 

      if (proc.ProcessName == "notepad") 
      { 
       MessageBox.Show(proc.StartInfo.WindowStyle.ToString()); 

      } 
     } 

Nhưng nếu quá trình là Maximized hoặc Minimized, nó bao giờ trả Normal.

Cách sửa lỗi này?

Trả lời

17

Bạn cần sử dụng Win32 thông qua P/Invoke để kiểm tra trạng thái của cửa sổ khác. Dưới đây là một số mã mẫu:

static void Main(string[] args) 
{ 
    Process[] procs = Process.GetProcesses(); 

    foreach (Process proc in procs) 
    { 
     if (proc.ProcessName == "notepad") 
     { 
      var placement = GetPlacement(proc.MainWindowHandle); 
      MessageBox.Show(placement.showCmd.ToString()); 
     } 
    } 
} 

private static WINDOWPLACEMENT GetPlacement(IntPtr hwnd) 
{ 
    WINDOWPLACEMENT placement = new WINDOWPLACEMENT(); 
    placement.length = Marshal.SizeOf(placement); 
    GetWindowPlacement(hwnd, ref placement); 
    return placement; 
} 

[DllImport("user32.dll", SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
internal static extern bool GetWindowPlacement(
    IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl); 

[Serializable] 
[StructLayout(LayoutKind.Sequential)] 
internal struct WINDOWPLACEMENT 
{ 
    public int length; 
    public int flags; 
    public ShowWindowCommands showCmd; 
    public System.Drawing.Point ptMinPosition; 
    public System.Drawing.Point ptMaxPosition; 
    public System.Drawing.Rectangle rcNormalPosition; 
} 

internal enum ShowWindowCommands : int 
{ 
    Hide = 0, 
    Normal = 1, 
    Minimized = 2, 
    Maximized = 3, 
} 

Định nghĩa biếu không của pinvoke.net.

+0

Trong trường hợp của tôi, 'showCmd' luôn là giá trị ban đầu, và giữ nguyên, ngay cả khi' ShowWindow (showCmd! = 1) 'được gọi,' GetWindowPlacement' vẫn trả về 'showCmd = 1' trong cấu trúc' WINDOWPLACEMENT'. Vì vậy, nó là nghĩa đen về thời điểm cửa sổ được 'đặt'? –

+0

Hãy nhớ thêm tham chiếu vào 'System.Drawing' – LazerSharks

6

Bạn đang sử dụng proc.StartInfo, không chính xác. Nó không phản ánh phong cách cửa sổ thời gian chạy của quá trình đích. Nó chỉ là thông tin khởi động mà bạn có thể thiết lập và sau đó có thể được chuyển sang tiến trình khi nó khởi động.

C# chữ ký là:

[DllImport("user32.dll", SetLastError=true)] 
static extern int GetWindowLong(IntPtr hWnd, int nIndex); 

Bạn cần phải sử dụng p/gọi và gọi GetWindowLong (hWnd, GWL_STYLE), và vượt qua proc.MainWindowHandle như tham số hWnd.

Bạn có thể kiểm tra nếu cửa sổ được giảm thiểu/tối đa bằng cách làm một cái gì đó như:

int style = GetWindowLong(proc.MainWindowHandle, GWL_STYLE); 
if((style & WS_MAXIMIZE) == WS_MAXIMIZE) 
{ 
    //It's maximized 
} 
else if((style & WS_MINIMIZE) == WS_MINIMIZE) 
{ 
    //It's minimized 
} 

LƯU Ý: Các giá trị cho cờ (WS_MINIMIZE, vv), có thể được tìm thấy trong trang này: http://www.pinvoke.net/default.aspx/user32.getwindowlong

Nhờ Kakashi đã chỉ ra lỗi của chúng tôi khi kiểm tra kết quả.

+1

Đừng quên rằng C# .NET chấp nhận biểu thức chỉ boolean nhập nếu/cho/trong khi-báo cáo. Nếu bạn muốn kiểm tra 'WS_MAXIMIZE' giá trị thái lát từ' style' là chính nó, bằng cách sử dụng '&' bạn nên làm '(kiểu & WS_MAXIMIZE) == WS_MAXIMIZE'. – Kakashi

+0

Đúng. Đã cập nhật câu trả lời. –

+1

Và cũng cần thiết '()' hoặc bạn sẽ nhận được 'Toán tử '&' không thể được áp dụng cho toán hạng kiểu 'int' và 'bool'' – Kakashi

2

Hai Window Kỳ (tối đa/tối thiểu hóa) có thể được nhận bằng cách gọi WinAPI IsIconic()/IsZoomed() như thế này:

[DllImport("user32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    public static extern bool IsIconic(IntPtr hWnd); 

    [DllImport("user32.dll")] 
    public static extern bool ShowWindowAsync(IntPtr hWnd, ShowWindowCommands cmdShow); 

    if (IsIconic(_helpWindow.MainWindowHandle)) { 
     ShowWindowAsync(_helpWindow.MainWindowHandle, ShowWindowCommands.SW_RESTORE); 
    } 

Định nghĩa của ShowWindowCommands enum và các chức năng khác được lấy từ www.PInvoke.net

0

trong Windows PowerShell, bạn có thể làm điều này bằng đoạn mã sau:

Add-Type -AssemblyName UIAutomationClient 
$prList = Get-Process -Name "<ProcessNamesWhichHaveWindow>" 
$prList | % { 
    $ae = [System.Windows.Automation.AutomationElement]::FromHandle($_.MainWindowHandle) 
    $wp = $ae.GetCurrentPattern([System.Windows.Automation.WindowPatternIdentifiers]::Pattern) 
    echo "Window title: $($_.MainWindowTitle)" 
    echo "Window visual state: $($wp.Current.WindowVisualState)" 
} 
+0

Nhưng điều này sẽ chỉ hoạt động trên Windows 7 trở lên. – Ladislav

Các vấn đề liên quan