Como faço para encontrar a posição / localização de uma janela dado um hWnd sem NativeMethods?

StackOverflow https://stackoverflow.com/questions/1434524

Pergunta

Atualmente estou trabalhando com WatiN, e encontrá-lo para ser uma grande ferramenta de automação de navegação na web. No entanto, a partir do último lançamento, de funcionalidades de captura de tela parece faltar. Eu vim com uma solução viável para a captura de screenshots da tela (independentemente gerar código semelhante ao este StackOverflow pergunta ), além de alguns href="http://www.charlespetzold.com/pwcs/ReadingPixelsFromTheScreen.html" rel="nofollow código por Charles Petzold . Infelizmente, há um componente em falta:? Onde está a janela real

WatiN convenientemente fornece hWnd do navegador para você, então nós podemos (com este exemplo simplificado) prepare-se para copiar uma imagem da tela, assim:

// browser is either an WatiN.Core.IE or a WatiN.Core.FireFox...
IntPtr hWnd = browser.hWnd;
string filename = "my_file.bmp";
using (Graphics browser = Graphics.FromHwnd(browser.hWnd) )
using (Bitmap screenshot = new Bitmap((int)browser.VisibleClipBounds.Width,
                                      (int)browser.VisibleClipBounds.Height,
                                      browser))
using (Graphics screenGraphics = Graphics.FromImage(screenshot))
{
    int hWndX = 0; // Upper left of graphics?  Nope, 
    int hWndY = 0; // this is upper left of the entire desktop!

    screenGraphics.CopyFromScreen(hWndX, hWndY, 0, 0, 
                          new Size((int)browser.VisibileClipBounds.Width,
                                   (int)browser.VisibileClipBounds.Height));
    screenshot.Save(filename, ImageFormat.Bmp);
}

Sucesso! Ficamos com screenshots, mas não há esse problema: hWndX e hWndY sempre apontam para o maior canto superior esquerdo da tela, e não a localização da janela que deseja copiar.

Eu, então, olhou para Control.FromHandle, no entanto, isso parece funcionar apenas com formulários criados; este método retorna um ponteiro nulo se você passar o hWnd para ele.

Em seguida, outras leituras me levar a mudar meus critérios de pesquisa ... Eu estava procurando 'localização da janela' quando a maioria das pessoas realmente querem a 'posição' da janela. Isso levou a outra questão SO , que falou sobre isso, mas a sua resposta era usar métodos nativos.

Assim, Existe um nativo C # forma de encontrar a posição de uma janela, dado somente o hWnd (de preferência com apenas .NET 2.0 bibliotecas EEI)?

Foi útil?

Solução

Eu só passei por isso em um projeto e foi incapaz de encontrar qualquer # caminho C gerenciado.

Para adicionar a resposta da Reed a P / code Invoke é:

 [DllImport("user32.dll", SetLastError = true)]
 [return: MarshalAs(UnmanagedType.Bool)]
 static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
 [StructLayout(LayoutKind.Sequential)]
 private struct RECT
 {
     public int Left;
     public int Top;
     public int Right;
     public int Bottom;
  }

chamá-lo como:

  RECT rct = new RECT();
  GetWindowRect(hWnd, ref rct);

Outras dicas

Não - se você não criar o formulário, você tem que P / Invoke GetWindowRect . Eu não acredito que há um gerenciado equivalente.

A resposta é como os outros, provavelmente, "Não, você não pode tirar um screenshot de uma janela aleatória de um hwnd sem métodos nativos.". Par de advertências antes de mostrá-lo:

AVISO DE:

Para qualquer um que queira usar esse código, nota que o tamanho dada a partir dos VisibleClipBounds só é dentro da janela, e não incluem a barra de borda ou título. É a área drawable. Se você tivesse que, você pode ser capaz de fazer isso sem p / invoke.

(Se você pudesse calcular a fronteira da janela do navegador, você pode usar os VisibleClipBounds. Se você quisesse, você poderia usar o SystemInformation objeto para obter informações importantes, como Border3DSize , ou você poderia tentar calculá-lo através da criação de uma forma de manequim e derivar a borda e título altura da barra de que , mas que todos os sons como a magia negra que os erros são feitos.)

Isto é equivalente a Ctrl + Printscreen da janela. Isso também não faz as sutilezas que a capacidade de captura de tela WatiN faz, como rolagem do navegador e ter uma imagem da página inteira. Isso é adequado para o meu projeto, mas pode não ser para o seu.

Melhorias:

Isto pode ser alterado para ser um método de extensão se você estiver em .NET 3 e up-terra, e uma opção para o tipo de imagem poderia ser acrescentado muito facilmente (eu padrão para ImageFormat.Bmp para este exemplo).

Código:

using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

public class Screenshot
{
    class NativeMethods
    {
        // http://msdn.microsoft.com/en-us/library/ms633519(VS.85).aspx
        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);

        // http://msdn.microsoft.com/en-us/library/a5ch4fda(VS.80).aspx
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
    }
    /// <summary>
    /// Takes a screenshot of the browser.
    /// </summary>
    /// <param name="b">The browser object.</param>
    /// <param name="filename">The path to store the file.</param>
    /// <returns></returns>
    public static bool SaveScreenshot(Browser b, string filename)
    {
        bool success = false;
        IntPtr hWnd = b.hWnd;
        NativeMethods.RECT rect = new NativeMethods.RECT();
        if (NativeMethods.GetWindowRect(hWnd, ref rect))
        {
            Size size = new Size(rect.Right - rect.Left,
                                 rect.Bottom - rect.Top);
            // Get information about the screen
            using (Graphics browserGraphics = Graphics.FromHwnd(hWnd))
            // apply that info to a bitmap...
            using (Bitmap screenshot = new Bitmap(size.Width, size.Height, 
                                                  browserGraphics))
            // and create an Graphics to manipulate that bitmap.
            using (Graphics imageGraphics = Graphics.FromImage(screenshot))
            {
                int hWndX = rect.Left;
                int hWndY = rect.Top;
                imageGraphics.CopyFromScreen(hWndX, hWndY, 0, 0, size);
                screenshot.Save(filename, ImageFormat.Bmp);
                success = true;
            }
        }
        // otherwise, fails.
        return success;
    }   
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top