Warsztat - Programowanie gier

Lipiec 30, 2010, 17:34:05 *
Witamy, Gość. Zaloguj się, lub zarejestruj proszę.

Zaloguj się podając nazwę użytkownika, hasło i długość sesji
Aktualności: Warsztat, Regulamin forum, #warsztat, Wiki, FAQ, NoPaste, Mapa
 
   Strona główna   Pomoc Szukaj Zaloguj się Rejestracja  
Strony: [1]
  Drukuj  
Autor Wątek: [.NET] Problem ze screenshotem  (Przeczytany 543 razy)
counterClockWise
Hero Member
*****

wiadomości: 754



Zobacz profil
« : Październik 26, 2009, 14:50:21 »

Wiem, że trochę mało związane z grami, ale czy jest możliwość w .NET Framework pobrać screenshot ekranu aktualnie zalogowanego użytkownika z poziomu aplikacji typu Windows Service?

W Windows Forms jest banalnie:
Kod:

bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bmp);
graphics.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
           
no ale ta metoda w Windows Service nie ma prawa działać i nie działa.
Zapisane
ConayR
SuperHero Member
******

wiadomości: 1388


Cheers!


Zobacz profil
« Odpowiedz #1 : Październik 26, 2009, 15:00:12 »

W większości przypadków Service nie chodzi uwierzytelniony jako zalogowany użytkownik, więc to nie ma prawa działać tak, jak to sobie obmyśliłeś. Zależnie od licencji na komputerze może być zalogowanych nawet i kilkanaście osób. Skąd serwis ma wiedzieć której zrobić zrzut ekranu? Nie jest to niewykonalne, ale nie do końca przemyślałeś to, co chcesz zrobić. Smiley Więc co próbujesz napisać? (nie jak? - co?)
Zapisane

On the Internet, nobody knows you're a dog
Xion
Member2000
*******

wiadomości: 2507



Zobacz profil WWW
« Odpowiedz #2 : Październik 26, 2009, 15:02:16 »

Możesz spróbować zaimportować GDI i zrobić jak tam, czyli (ostrzeżenie: kod pisany z pamięci):
Kod:
HDC screen = GetDC(0);
HDC hdcBmp = CreateCompatibleDC(screen);
HBITMAP hBmp = CreateCompatibleBitmap(screen);
SelectObject (hdcBmp, hBmp);
BitBlt (screen, /* dużo parametrów */, hdcBmp);
Zapisane

counterClockWise
Hero Member
*****

wiadomości: 754



Zobacz profil
« Odpowiedz #3 : Październik 26, 2009, 15:02:28 »

W większości przypadków Service nie chodzi uwierzytelniony jako zalogowany użytkownik, więc to nie ma prawa działać tak, jak to sobie obmyśliłeś. Zależnie od licencji na komputerze może być zalogowanych nawet i kilkanaście osób. Skąd serwis ma wiedzieć której zrobić zrzut ekranu? Nie jest to niewykonalne, ale nie do końca przemyślałeś to, co chcesz zrobić. Smiley Więc co próbujesz napisać? (nie jak? - co?)

Coś w stylu VNC/Remote Desktop. Pierwsza przymiarka, aby zrobić to samemu, ale ostatecznie pewnie będzie trzeba skorzystać z jakiegoś gotowego mechanizmu.

Możesz spróbować zaimportować GDI i zrobić jak tam, czyli (ostrzeżenie: kod pisany z pamięci):
Kod:
HDC screen = GetDC(0);
HDC hdcBmp = CreateCompatibleDC(screen);
HBITMAP hBmp = CreateCompatibleBitmap(screen);
SelectObject (hdcBmp, hBmp);
BitBlt (screen, /* dużo parametrów */, hdcBmp);

Też o tym pomyślałem, ale czy DC(0) nie zwracał kontekstu samego puplitu bez okienek na nim?
W C# jest Graphics.FromHDC(), więc spróbuję bezpośrednio Smiley

SOLVED - gdyby ktoś miał podobny problem:

Kod:
const int SRCCOPY = 0xcc0020;
        [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
        private static extern int BitBlt(
          IntPtr hdcDest,     
          int nXDest,         
          int nYDest,         
          int nWidth,         
          int nHeight,       
          IntPtr hdcSrc,     
          int nXSrc,         
          int nYSrc,         
          System.Int32 dwRop 
          );

        public static Bitmap GetScreenshot()
        {
            Graphics desktopGraphics = Graphics.FromHwnd(new IntPtr(0));
            int width = (int)desktopGraphics.VisibleClipBounds.Width;
            int height = (int)desktopGraphics.VisibleClipBounds.Height;
            Bitmap bmp = new Bitmap(width, height, desktopGraphics);
           
            Graphics bmpGraphics = Graphics.FromImage(bmp);
            BitBlt(bmpGraphics.GetHdc(), 0, 0, width, height, desktopGraphics.GetHdc(), 0, 0, SRCCOPY);
            bmpGraphics.ReleaseHdc();
            desktopGraphics.ReleaseHdc();
            return bmp;
        }
« Ostatnia zmiana: Październik 26, 2009, 15:50:22 wysłane przez counterClockWise » Zapisane
Xion
Member2000
*******

wiadomości: 2507



Zobacz profil WWW
« Odpowiedz #4 : Październik 26, 2009, 19:36:22 »

No właśnie GetDC(0) zwraca ci cały ekran Smiley Widzę zresztą, że zrobiłeś to mnie więcej tak, jak pisałem, ograniczając jedynie użycie WinAPI do minimum (o ile pamiętam w GDI+ nie ma niestety kopiowania Graphics -> Graphics, więc trzeba użyć BitBlt).
Zapisane

ConayR
SuperHero Member
******

wiadomości: 1388


Cheers!


Zobacz profil
« Odpowiedz #5 : Październik 26, 2009, 21:08:48 »

Jak się zachowa ten kod, kiedy zalogowane będą dwie osoby? Wink
Zapisane

On the Internet, nobody knows you're a dog
counterClockWise
Hero Member
*****

wiadomości: 754



Zobacz profil
« Odpowiedz #6 : Październik 26, 2009, 23:50:01 »

Jak się zachowa ten kod, kiedy zalogowane będą dwie osoby? Wink

Może być zalogowanych wiele osób, ale sam Windows nie pozwala na interaktywne korzystanie kilku, jest tylko jeden InputDesktop.
Niestety tamto rozwiązanie nie było Solved, musiałem przełączyć się na odpowiednią maszynę "winsta0", pobierać odpowiednie uchwyty, dać prawa bieżącemu wątkowi na interakcję z pulpitem.
Powstał długi kod, który mam w pracy, jeżeli ktoś chce, to wkleję jutro Smiley
Zapisane
Strony: [1]
  Drukuj  
 
Skocz do:  

Hosting: Polska Strefa - Ogłoszenia
Powered by SMF 1.1.7 | SMF © 2006, Simple Machines LLC