Toon posts:

[VB6] Window van externe applicatie capturen

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik probeer in VB6 het window van een tweede applicatie (namelijk Internet Explorer) te capturen naar een picturebox. De volgende code heb ik geprobeerd:

code:
1
2
3
4
5
6
7
8
Dim WithEvents IE As InternetExplorer
Dim hIEDC As Long

Set IE = CreateObject("InternetExplorer.Application.1")
IE.Visible = True
hIEDC = GetDC(IE.hwnd)
BitBlt Picture1.hdc, 0, 0, IE.Width, IE.Height, hIEDC, 0, 0, &HCC0020
ReleaseDC 0&, hIEDC


Nou werkt dit wel aardig, maar de tweede applicatie dient altijd op de voorgrond te staan, anders krijg je namelijk stukken van de overlappende windows te zien.
Vervolgens heb ik (na het lezen van dit artikel) de volgende code geprobeerd:

code:
1
2
3
4
5
6
Private Const WM_PAINT = &HF
Private Const WM_PRINT = &H317
Dim rv As Long

rv = SendMessage(IE.hwnd, WM_PAINT, Picture1.hdc, 0)
rv = SendMessage(IE.hwnd, WM_PRINT, Picture1.hdc, PRF_CHILDREN + PRF_CLIENT + PRF_OWNED)


...maar nu krijg ik een lege picturebox! Weet iemand misschien een andere manier, of wat ik hier fout doe? :?

Verwijderd

Topicstarter
Heeft het er misschien mee te maken dat Internet Explorer niets met de WM_PRINT message kan, of zo?!?

Verwijderd

Topicstarter
(ik blijf 't maar proberen... :|)

Weet iemand wat sowieso het nut is van de (door MSDN voorgestelde) WM_PRINT message? WM_PAINT zou toch in principe voldoende moeten zijn?

Het programma voert trouwens ook nog Picture1.Picture = Picture1.Image en Picture1.Refresh uit, na de SendMessage regels. De AutoRedraw eigenschap van de picturebox staat aan.

  • Sponge
  • Registratie: Januari 2002
  • Laatst online: 28-08 17:06

Sponge

Serious Game Developer

Het is geen optie om het programma als het nodig is, op de voorgrond te zetten, dan te captruen, en dan weer terug te zetten?

Verwijderd

Topicstarter
Dat is inderdaad een mogelijkheid (heb ik nu ook maar tijdelijk geimplementeerd), maar dat ziet er niet uit, vooral omdat de applicatie meerdere malen moet capturen. Het is eigenlijk de bedoeling dat de Internet Explorer totaal niet zichtbaar is...en da's nogal lastig! :)

  • Pooh
  • Registratie: April 2001
  • Niet online

Pooh

Lees eens een boek

Hmmz... wat wil je precies bereiken?

Volgens mij valt er niet zoveel te capturen van een programma in de background (die negeert alle teken-opdrachten gewoon), dus als je 't zo wilt oplossen moet je 'm eerst naar voren halen. Met WM_PRINT kan 't wel: WM_PRINT vraagt 't programma z'n zooi op een specifieke DC te zetten, in plaats van op de standaard DC. (Normaalgesproken op de print-dc natuurlijk, maar ergens anders kan ook best).

edit: Hmm... dat had je al door geloof ik (als ik dat artikel zo lees). Heb je autoredraw uit staan tijdens je print-actie?

Verwijderd

Topicstarter
Ik zal nog eens stap voor stap uitleggen wat nou precies de bedoeling is:
- eerst moet mijn VB programma een instantie van Internet Explorer creëren
- deze instantie moet eigenlijk invisible blijven
- daarna moet IE een internetpagina openen
- als IE daarmee klaar, neemt het programma een screenshot van het hele IE-window (dus mét menus, statusbar, enz.)
- deze screenshot moet in een picturebox worden geplaatst (en dit klinkt dus makkelijker dan het is :))
- de IE-instantie wordt tenslotte om zeep geholpen

Ik zet autoredraw na de WM_PAINT en WM_PRINT message inderdaad weer uit, maar dit werkt helaas ook niet.

Misschien trouwens dat dit artikel het antwoord is...alleen wordt het me al snel abacadabra wat de auteur aan het doen is.

  • Sponge
  • Registratie: Januari 2002
  • Laatst online: 28-08 17:06

Sponge

Serious Game Developer

Je kunt proberen de source te porten naar VB, alle API functies zijn in principe het zelfde, dus dat moet wel lukken?

Verwijderd

Ik zie 'n paar smerige hooks/callbacks/hacks kleine kans dat je die source compleet naar vb krijgt, misschien als je de hooks in C laat en de msg's stuurd vanuit VB kan het msischien werken..

Verwijderd

Topicstarter
Dat porten naar VB lijkt me inderdaad nogal lastig. En om nou een complete 'capture-dll' in C te gaan schrijven...pffff... ;)

Deze tekst staat trouwens in het begin van het artikel:
Sounds good ? There is a catch. Normally only windows implemented by the operating system are knowledgeable to handle these messages. If you send a WM_PRINT message to a window, normally all the non-client area, which includes border, title bar, menu bar, scroll bar, etc., and common controls are drawn properly. Client area of windows implemented by application programs are normally left blank.
Wat ik best raar vind is dat de picturebox in mijn geval helemaal leeg blijft, dus zelfs geen Windows controls of zo.

Verwijderd

Topicstarter
De WM_PRINT message sturen naar een window binnen de eigen applicatie werkt blijkbaar prima:

code:
1
2
3
4
5
6
7
8
9
10
Dim lngProcess As Long
Dim rv As Long

lngProcess = frmTest.hwnd
picCapture.AutoRedraw = True
rv = SendMessage(lngProcess, WM_PAINT, picCapture.hdc, 0)
rv = SendMessage(lngProcess, WM_PRINT, picCapture.hdc, PRF_CLIENT Or PRF_CHILDREN Or PRF_OWNED)
picCapture.Picture = picCapture.Image
picCapture.AutoRedraw = False
Unload frmTest


Als je op frmTest wat test-controls zet, worden deze netjes in picCapture geplakt.

Kan het misschien zo zijn dat ik de verkeerde handle van Internet Explorer gebruik? :? Op dit moment vraag ik 'm zo op:
code:
1
2
3
4
5
Dim WithEvents IE As InternetExplorer
dim lngHWND as long

Set IE = CreateObject("InternetExplorer.Application.1")
lngHWND = IE.HWND

  • Sponge
  • Registratie: Januari 2002
  • Laatst online: 28-08 17:06

Sponge

Serious Game Developer

ah, ja, dat is dus het probleem :)

Zo maak (Create) je een nieuw internet explorer object. Wil je zelf een nieuwe pagina openen met het programma, of bestaande IE vensters bekijken?

Zo ja het laatste, dan moet je zoeken naar het juiste venster (check www.pscode.com voor get windows, get all hwnds, "spy++", "findwindow"oid) en die handle gebruiken.

Als je het handmatig wilt proberen moet je Spy++ gebruiken (weet niet of 'ie bij alle versies van VB(6) zit, bij enterprise wel), en daarmee de handle van het gewenste window selecteren (door middel van een icoon wat je sleept, "find window") .. dan gebruik je die handle in je programma, en als het goed is.. moet het werken.

Edit: eventjes voor je gezocht, niet geprobeerd:

http://www.pscode.com/vb/...p?txtCodeId=4556&lngWId=1
http://www.pscode.com/vb/...?txtCodeId=37447&lngWId=1
http://www.pscode.com/vb/...p?txtCodeId=2157&lngWId=1

Verwijderd

Topicstarter
Ik heb de code van de laatste pagina van PSCode geprobeerd, die inderdaad ook de juiste handle retourneert (gecontroleerd met Spy++), maar...nog steeds helemaal niets! :( Langzamerhand begin ik te denken dat het nogal onmogelijk is om WM_PRINT te gebruiken buiten het eigen proces...
Pagina: 1