2012-01-02 119 views
1

方案 我有我的主要应用程序,它最初是用C#.Net应用程序启动的Borland C++编写的。这个主应用程序偶尔会从一个名为BRWSEXE的进程打开一个模态对话框。弹出模态对话框窗口后,您可能无意中单击主应用程序中的某个位置(而不是对话框),导致焦点短暂变为主应用程序,并以Z顺序发送后面的模式对话框。但是你实际上不能在主应用程序上做任何事情,它会被那个必须先关闭的模式对话框锁定,然后才能继续。SetForegroundWindow在Windows Server 2008上失败

的问题 使用启动一切的.NET应用程序,我可以找出所涉及到的主要应用BRWSEXE的实例,并迫使他们推向前台。这种策略在我到目前为止测试过的任何地方都能正常工作(Windows XP,Windows 7,Windows Server 2003 R2),但它在Windows Server 2008上无法正常工作。所以据我所知,我的代码工作正常。但是那个环境中的东西正在抛弃它。

我的代码

[DllImport("user32.dll")] 
static extern bool SetForegroundWindow(IntPtr hWnd); 

[DllImport("user32.dll")] 
static extern IntPtr AttachThreadInput(IntPtr idAttach, IntPtr idAttachTo, bool fAttach); 


private void PushBRWSEXEToFront() 
{ 
    //Make sure MyApplication is running 
    if (Process.GetProcessesByName("MyApplicationName").Length == 1) 
    { 
     Process[] brwsProc = Process.GetProcessesByName("BRWSEXE"); //Locate any processes for the browse dialog windows 
     for (int x = brwsProc.Length - 1; x > -1; x--) 
     { 
      //Make sure the browse window we are looking at is associated with the active program we are looking at 
      if (brwsProc[x].SessionId == Process.GetCurrentProcess().SessionId 
       || brwsProc[x].SessionId == Process.GetProcessesByName("MyApplicationName")[0].SessionId) 
      { 
       //attach to the main applications thread 
       AttachThreadInput(brwsProc[x].MainWindowHandle, Process.GetProcessesByName("MyApplicationName")[0].MainWindowHandle, true); 

       //Call Set foreground window to push the browse window in front of the rest of the program. 
       SetForegroundWindow(brwsProc[x].MainWindowHandle); 

       //Detach from the main thread 
       AttachThreadInput(brwsProc[x].MainWindowHandle, Process.GetProcessesByName("MyApplicationName")[0].MainWindowHandle, false); 
      } 
     } 
    } 
} 

回答

3

您的AttachThreadInput声明是完全错误的。它返回bool,参数是uint。而你错误地使用它,你应该传递线程ID,而不是窗口句柄。你需要GetWindowThreadProcessId()

而你根本不检查错误,所以你显然无法诊断失败。需要SetLastError属性,用Marshal.GetLastWin32Error()检索错误。使用pinvoke.net更好的pinvoke声明。

+0

原谅我我是一个新手,我必须有一个不好的初始信息来源。用你所说的话,这意味着只有我的SetForegroundWindow调用正在工作,因为它能够成功地将窗口置于前台。但是,这些都不能帮助我找出为什么它可以在Windows Server 2008上的任何地方工作。 感谢您提供有关从这些调用中获取错误的信息。我一定会在使用它的同时继续努力实现这一目标。 – Hagelt18 2012-01-03 14:55:20

+1

AttachThreadInput()调用是有原因的。没有它们,SetForegroundWindow()很有可能不会将窗口实际放到前台。 – 2012-01-03 15:55:20

0

我用SwitchToThisWindow(),虽然MSDN说,它可能会在未来的Windows版本中删除,它仍然为我工作。

+0

它是否适用于最小化窗口? – deadfish 2012-01-02 16:18:40

+0

@MichałMokrzycki是的,它应该显示并把窗口放到前台。 – scottm 2012-01-02 16:23:46

+0

感谢您的建议!我改变了我的代码来使用该函数,但我得到了相同的结果。它使用其他操作系统,但使用Windows Server 2008时失败。 – Hagelt18 2012-01-02 16:26:49