2015-11-01 3 views
2

время назад я задал этот вопрос, она была решена здесь:Установите состояние окна скрытого окна

Но теперь, и по неизвестным причинам, C# или Vb.Net код при условии, что он не работает, и я не понимаю, почему нет.

Я внес некоторые изменения в исходный код, предоставленный там, но я протестировал оригиналы и не работал.

Что происходит, так это то, что я не могу скрыть скрытый процесс, я не уверен, где я терплю неудачу. На первый взгляд я думаю, что дескриптор, который я получаю с FindWindowEx, действительно не соответствует дескриптору, который я хочу.

Это мои P/инициировавшего вызов функции подписи и ShowWindow перечисление:

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto, 
      BestFitMapping:=False, ThrowOnUnmappablechar:=True)> 
Friend Shared Function FindWindow(
       ByVal lpClassName As String, 
       ByVal lpWindowName As String 
) As IntPtr 
End Function 

<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto, 
      BestFitMapping:=False, ThrowOnUnmappablechar:=True)> 
Friend Shared Function FindWindowEx(
       ByVal hwndParent As IntPtr, 
       ByVal hwndChildAfter As IntPtr, 
       ByVal strClassName As String, 
       ByVal strWindowName As String 
) As IntPtr 
End Function 

<DllImport("user32.dll")> 
Friend Shared Function GetWindowThreadProcessId(
       ByVal hWnd As IntPtr, 
       ByRef processId As Integer 
) As Integer 
End Function 

<DllImport("User32", SetLastError:=False)> 
Friend Shared Function ShowWindow(
       ByVal hwnd As IntPtr, 
       ByVal nCmdShow As ProcessUtil.WindowState 
) As <MarshalAs(UnmanagedType.Bool)> Boolean 
End Function 

Public Enum WindowState As Integer 
    Hide = 0 
    Normal = 1 
    ShowMinimized = 2 
    Maximize = 3 
    ShowMaximized = Maximize 
    ShowNoActivate = 4 
    Show = 5 
    Minimize = 6 
    ShowMinNoActive = 7 
    ShowNA = 8 
    Restore = 9 
    ShowDefault = 10 
    ForceMinimize = 11 
End Enum 

Функция:

Public Function SetWindowState(ByVal p As Process, 
           ByVal windowState As ProcessUtil.WindowState) As Boolean 

    Dim pHandle As IntPtr = IntPtr.Zero 
    Dim pid As Integer 

    ' If window is visible then... 
    If (p.MainWindowHandle <> IntPtr.Zero) Then 
     Return ProcessUtil.NativeMethods.ShowWindow(p.MainWindowHandle, windowState) 

    Else ' window is hidden. 

     ' Check all open windows (not only the process we are looking), 
     ' begining from the child of the desktop. 
     While (pid <> p.Id) 

      ' Get child handle of window who's handle is "pHandle". 
      pHandle = NativeMethods.FindWindowEx(IntPtr.Zero, pHandle, Nothing, Nothing) 

      ' Get PID from "pHandle". 
      NativeMethods.GetWindowThreadProcessId(pHandle, pid) 

     End While 

     Return NativeMethods.ShowWindow(pHandle, windowState) 

    End If 

End Function 

И так, что я пытаюсь проверить функцию, где первый I скрыть окно процесса блокнота, затем я попытаюсь показать его.

Dim p As Process = Process.GetProcessesByName("notepad").First 
ProcessUtil.SetWindowState(p, ProcessUtil.WindowState.Hide) 

' I find again the process to renew the "p.MainWindowHandle" as IntPtr.Zero. 
p = Process.GetProcessesByName("notepad").First 
ProcessUtil.SetWindowState(p, ProcessUtil.WindowState.Restore) 
+0

Вы пробовали установить WindowState в Normal? – Nemo

+0

@Nemo Спасибо за комментарий. Да, я пробовал каждое значение перечисления, но он не восстанавливает скрытое окно. Я сравнил результирующий дескриптор 'FindWindowEx' после цикла ** While ** заканчивается дескриптором, который дает мне приложение командной строки CMDOW, и он отличается (ну, CMDOW дает мне основной HWND), но тот же самый код работал время назад, я не понимаю, почему теперь это происходит. – ElektroStudios

+0

@ElektroStudios Вы пытались использовать Process.GetProcessesByName («блокнот») и Process.MainWindowHandle? –

ответ

2

Проблема с блокнотом в том, что он имеет 3 окна (Spy ++, имена классов):

1. "Блокнот"
2. "MSCTFIME UI"
3. "IME"

Вы получаете ручку второго (все равно), MSCTFIME UI, вот почему вы не можете его показать. Вы должны указать имя класса Блокнот, чтобы получить правильную ручку:

pHandle = FindWindowEx(IntPtr.Zero, pHandle, "Notepad", Nothing) 
+0

Спасибо за ответ. Я буду делиться точками между двумя ответами, которые я получил, потому что ответ @Hans Passant очень показателен, а ваш - очень хорошее решительное резюме. Трудно решить, оба приветствуются как решение. – ElektroStudios

2

Настало время, когда вы начинаете использовать исходный код .NET Framework, так что вы можете обнаружить, почему такой код не работает по сам. Посетите Reference Source web site, чтобы начать.

В поле поиска введите «Process.MainWindowHandle», вы придете к this page. Легко видеть, что именно ProcessManager.GetMainWindowHandle выполняет свою работу. Нажмите «GetMainWindowHandle». Он очень маленький, нажмите «FindMainWindow». Обратите внимание, как он перечисляет окна, прокручивайте немного вправо, чтобы увидеть, что это «EnumWindowsCallback», который выполняет свою работу. Щелкните по нему, легко увидеть, что это «IsMainWindow», который определяет, является ли окно основным. Нажмите на нее:

bool IsMainWindow(IntPtr handle) { 

     if (NativeMethods.GetWindow(new HandleRef(this, handle), NativeMethods.GW_OWNER) != (IntPtr)0 
      || !NativeMethods.IsWindowVisible(new HandleRef(this, handle))) 
      return false; 

     return true; 
    } 

Выражаясь словами, это не основной дескриптор окна, если это принадлежит окно. Или, если не видно.

Последнее предложение, конечно же, ваше заклятие. Вы спрятали окно, теперь код рамки больше не думает, что это главное окно. Таким образом Process.MainWindowHandle возвращает IntPtr.Zero, и ваш код больше не работает.

Одним из очевидных способов решения является просто переписать код .NET Framework и пропустить тест IsWindowVisible(). Это, однако, важный тест, он избегает поиска «окон сообщений», типа, который создает практически любой процесс. Они используются для внутренней сантехники. Другой ответ упоминает их. Вы можете видеть их со Spy ++, Notepad имеет два из них. В противном случае, созданный не в том порядке, в котором вы их найдете, сначала вы найдете главное окно. Это не гарантируется в любом процессе.

Правильный обходной путь является то, что вы должны не забывать, что вы сделали что-то очень недружелюбно к окну. Сам блокнот никогда не скрывает главного окна. Вы в основном превратили его в зомби, пользователь не может ничего сделать, чтобы восстановить окно. Осталось только использовать диспетчер задач, чтобы убить процесс. Поэтому ваша задача снова сделать ее видимой. Задание, которое вы не можете игнорировать, должно восстановить их до выхода вашей программы, например.

Или просто не делайте этого, возиться с окнами пользователя, как это просто враждебно.

+0

Я знаю, что не очень хорошо комментировать слова, чтобы сказать спасибо, но такой ответ заслуживает большой благодарности за то время, которое вы потратили на это, и ссылку на ссылки. – ElektroStudios

Смежные вопросы