CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Screenshot z okna
Strona 1 z 4

Screenshot z okna

Nowy postNapisane: środa, 20 lipca 2016, 00:09
przez Arnold_S
Witam!
Mam proste pytanie odnośnie sposobu, który został opisany w temacie "Zrzuty z ekranu" na Waszej stronie. Kod wyglądał następująco:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 TCanvas *pCanvas = new TCanvas();
 Graphics::TBitmap *Bmp = new Graphics::TBitmap;

 HWND okno = FindWindow(NULL, "Form1");
 pCanvas->Handle = GetWindowDC(okno);
 TRect oR;
 GetWindowRect(okno, &oR);
 Bmp->Width = oR.Width();
 Bmp->Height = oR.Height();
 Bmp->Canvas->CopyRect(Rect(0, 0, Bmp->Width, Bmp->Height), pCanvas, Rect(0, 0, Bmp->Width, Bmp->Height));

 Bmp->SaveToFile("c:\\ekran.bmp");
 ReleaseDC(0, pCanvas->Handle);

 delete pCanvas, Bmp;
}
 


Czy funkcja GetWindowRect jest obowiązkowa w tym przypadku? Czy zamiast pobierać rozmiaru okna tą funkcją, mogę wypełnić ręcznie obiekt o nazwie "oR"?
na przykład:
KOD cpp:     UKRYJ  
TRect oR;
oR.Left = 0;
oR.Top = 500;
oR.Right = 100;
oR.Bottom = 400;
Czy to oznacza, że byłby to wycinek okna 100x100 pikseli, umieszczony od lewego, górnego rogu okna?
Czy jeśli wypełnię ręcznie obiekt oR to muszę również ręcznie obliczyć oR.Width i oR.Height?
Pytam dlatego, że próbowałem wypełniać tą strukturę ręcznie bo nie chcę aby mój program robił zrzut całego okna, tylko wycinek, który ja zdefiniuję...i nie bardzo mi to wychodzi.

Re: Screenshot z okna

Nowy postNapisane: środa, 20 lipca 2016, 09:10
przez Mironas
Top powinien być mniejszy niż Bottom.

Re: Screenshot z okna

Nowy postNapisane: środa, 20 lipca 2016, 10:09
przez polymorphism
KOD cpp:     UKRYJ  
delete pCanvas, Bmp;

Ta konstrukcja jest nieprawidłowa, bo usuwa jedynie pCanvas. Nieusunięcie Bmp powoduje wyciek pamięci.

Re: Screenshot z okna

Nowy postNapisane: środa, 20 lipca 2016, 14:50
przez Cyfrowy Baron
To prawda, popełniłem tam błąd. Powinno być:

KOD cpp:     UKRYJ  
delete pCanvas;
delete Bmp;

Re: Screenshot z okna

Nowy postNapisane: środa, 20 lipca 2016, 23:29
przez Arnold_S
Mironas napisał(a):Top powinien być mniejszy niż Bottom.


Dlaczego mniejszy? Czy Top jest współrzędną lewego-górnego rogu prostokąta? To w takim razie ten prostokąt znajduje się pod osią X czy nad osią X?

Re: Screenshot z okna

Nowy postNapisane: czwartek, 21 lipca 2016, 09:28
przez Mironas
Na ekranie punkt 0,0 znajduje się w lewym górnym rogu. Możesz porównać ekran do IV ćwiartki układu współrzędnych.

Top - to odległość od górnej krawędzi ekranu do górnej krawędzi prostokąta.

Re: Screenshot z okna

Nowy postNapisane: wtorek, 26 lipca 2016, 23:38
przez Arnold_S
Jeszcze raz...Mam taki fragment kodu:
Użyłem funkcji GetDC ponieważ nie chcę na screenie mieć górnej "belki" okna, tylko od razu jego zawartość.

KOD cpp:     UKRYJ  
 TCanvas *pCanvas = new TCanvas();
 Graphics::TBitmap *Bmp = new Graphics::TBitmap;
 pCanvas->Handle = GetDC(hWnd);
 TRect prostokat;                                  
 prostokat.Left = 16;                              
 prostokat.Top = 80;                                
 prostokat.Right = 168;                            
 prostokat.Bottom = 90;                            

 Bmp->Width = prostokat.Width();
 Bmp->Height = prostokat.Height();
 Bmp->Canvas->CopyRect(Rect(0, 0, Bmp->Width, Bmp->Height), pCanvas, Rect(0, 0, Bmp->Width, Bmp->Height));

 Bmp->SaveToFile("c:\\screen1.bmp");
 ReleaseDC(0, pCanvas->Handle);
 delete pCanvas;
 delete Bmp;


Problem polega na tym, że jakkolwiek zwiększam (o tę samą wartość) Top i jednocześnie Bottom aby przesuwać tym prostokątem w dół lub w górę otrzymuję screenshot tego samego miejsca na ekranie...jak to możliwe?

Re: Screenshot z okna

Nowy postNapisane: środa, 27 lipca 2016, 10:12
przez Mironas
Bo w CopyRect jako obszar źródłowy podajesz inne parametry niż ten prostokat.
Zrób tak:
KOD cpp:     UKRYJ  
Bmp->Canvas->CopyRect(Rect(0, 0, Bmp->Width, Bmp->Height), pCanvas, prostokat);

PS
Do wstawiania kodu na forum używaj znaczników CPP.

Re: Screenshot z okna

Nowy postNapisane: środa, 27 lipca 2016, 10:16
przez Cyfrowy Baron
KOD cpp:     UKRYJ  
CopyRect(const System::Types::TRect &Dest, TCanvas* Canvas, const System::Types::TRect &Source);


Dest - przeznaczenie - czyli wymiary i położenie obszaru na które kopiujesz obraz
Source - źródło - czyli wymiary i położenie obszaru z którego kopiujesz
Canvbas - płótno na które kopiujesz

Korzystaj z pomocy dołączonej do środowiska. Szybki dostęp - zaznacz funkcję w edytorze i wciśnij na klawiaturze klawisz F1.

Re: Screenshot z okna

Nowy postNapisane: środa, 27 lipca 2016, 19:54
przez Arnold_S
Wielkie dzięki już to rozkminiam. Mam nadzieję, że mnie nie znienawidzicie za taką ilość pytań. Dla mnie przepisanie właściwego rozwiązania nie załatwia sprawy. Więc drążę temat do puki czegoś nie zrozumiem.

/edit
Wydaje mi się. że wiem na czym polegał mój błąd.
Gdy argumenty wyglądały tak:
KOD cpp:     UKRYJ  
CopyRect(Rect(0, 0, Bmp->Width, Bmp->Height), pCanvas, Rect(0, 0, Bmp->Width, Bmp->Height));
 

to obiekt typu TCanvas został jakby "skonfigurowany" poprzez właściwości obiektu typu TRect (który zwraca funkcja Rect)...ale tam nie było współrzędnych tylko długość boków prostokąta, obliczonych na podstawie współrzędnych obiektu "prostokąt". Dlatego za każdym razem screenshot pokazywał wycinek o właściwych wymiarach ale pobrany z niewłaściwych współrzędnych. ehhhh

Temat następny to fakt, że nie bardzo wiem z czego, do czego kopiujemy i w którym obiekcie znajduje się faktycznie ten obraz. Bardzo bym prosił abyście sprostowali mój pogląd na tą sprawę.
Z opisów w pliku pomocy wynika, że pierwszy argument funkcji CopyRect to nic innego jak obiekt, który zawiera rozmiar kwadratu lub prostokąta. Według ustawień, które posiada zostanie przygotowane miejsce (jego wymiar) w którym znajdzie się obraz.
Drugi argument to wskaźnik pokazujący na obiekt TCanvas i to tutaj - do niego ma zostać "wklejony" fragment obrazu.
Trzeci argument to też obiekt TRect ale zawierający współrzędne, wg. których zostanie "wycięty" fragment obrazu źródła.
Zastanawiam się po co obiekt TCanvas musi zawierać kontekst do przechwytywanego okna, skoro w tym obiekcie umieszczamy fragment obrazu? Czy obj. Tcanvas po prostu zawiera rozmiar przechwytywanego okna i po to jest potrzebny funkcji Copyrect?
Inną rzeczą jest fakt, że "*Bmp" to pointer wskazujący na obiekt klasy TBitmap. "Z niego" wywołujemy funkcję CopyRect. Czy to oznacza, że to ten obiekt po wywołaniu tej funkcji będzie przechowywał wycięty kawałek obrazu okna? ...to w takim razie co z obiektem Tcanvas, na który wskazuje pointer pCanvas?
W którym miejscu i kiedy znajduje się kopiowany fragment obrazu przechwyconego okna? Jakoś nie mogę sobie tego wyobrazić, może dlatego, że jestem początkujący. Proszę możliwie ramowe sprostowanie.

Re: Screenshot z okna

Nowy postNapisane: czwartek, 28 lipca 2016, 09:21
przez Mironas
Cyfrowy Baron napisał(a):Canvbas - płótno na które kopiujesz

Nie "na które" tylko "z którego". W funkcji CopyRect parametr Canvas wskazuje płótno źródłowe a nie docelowe.

Arnold_S napisał(a):Drugi argument to wskaźnik pokazujący na obiekt TCanvas i to tutaj - do niego ma zostać "wklejony" fragment obrazu.

Jak wyżej. Nie "do niego" tylko "z niego".

Re: Screenshot z okna

Nowy postNapisane: piątek, 29 lipca 2016, 23:21
przez Arnold_S
Czy tak bardzo ogólnikowo to:
Obiekt na który pokazuje pCanvas, zawiera kontekst do okna. Czy wówczas w tym obiekcie znajduje się obraz z okna?
Czyli CopyRect kopiuje z tego "płótna" do obiektu TBitmap...tak?
Jeśli tak, to czy przed zapisaniem obrazu do pliku, mogę go w jakiś sposób edytować w TBitmap używając wskaźnika Bmp?

Re: Screenshot z okna

Nowy postNapisane: sobota, 30 lipca 2016, 00:33
przez Cyfrowy Baron
TCanvas nie jest obiektem, nie posiada żadnej powierzchni. Canvas będący argumentem funkcji CopyRect jest wskaźnikiem na płótno TCanvas z którego kopiujesz. Nie zawiera jeszcze żadnego kontekstu do okna. Najpierw musisz wskazać z ktrego płótna kopiujesz i robisz to tutaj

KOD cpp:     UKRYJ  
 pCanvas->Handle = GetDC(hWnd);


Po przypisaniu do Canvas uchwytu do okna przechwytujesz okno, a funkcja CopyRect kopiuje go na płótno Canvas innego obiektu.

Obiekt typu TBitmap możesz oczywiście edytować. Przejrzyj te przykłady: http://programowanie.cal.pl/cyfbar/grafika.html

Re: Screenshot z okna

Nowy postNapisane: piątek, 2 września 2016, 23:03
przez Arnold_S
Napotkałem kolejny problem. Niekoniecznie jest to problem związany bezpośrednio z grafiką ale...

Skonstruowałem funkcję i definicję umieściłem w pliku unit1.h. Na samym dole pliku.
W pliku unit1.cpp umieściłem deklarację tej funkcji.
Wszystko było dobrze dopóki nie musiałem przebudować tej funkcji.
Od momentu gdy zaczęła ona przyjmować wskaźnik do obiektu znajdującego się globalnie w pliku cpp. Program zaczął mi strzelać komunikatami AccessViolation, a gdy definicję przeniosłem do pliku cpp na sam koniec i deklarację do pliku unit1.h

KOD cpp:     UKRYJ  
private:        // User declarations
public:         // User declarations
        __fastcall TForm1(TComponent* Owner);
     // tutaj  <-------------------------------
};


....to pojawiają się komunikaty typu: [Linker Error] Unresolved external 'TForm1::compareBars(void *, tagRGBQUAD *, short)' referenced from C:\PROGRAM TESTOWY\UNIT1.OBJ

Proszę podpowiedzcie mi jak to w końcu powinno być.
1. Czy definicje funkcji mogą być w pliku unit1.cpp, a deklaracje muszą być w unit1.h? - jeśli tak to gdzie dokładnie?
2. Czy na odwrót?
3. Czy w 1 przypadku, w pliku unit1.h zaraz pod includami muszę wpisać zmienne globalne z pliku unit1.cpp z dodatkiem extern?

Jaką konwencję należy przyjąć żeby to działało jak trzeba?

Re: Screenshot z okna

Nowy postNapisane: piątek, 2 września 2016, 23:11
przez Cyfrowy Baron
Opisałeś to tak, że nie wiem o co chodzi.