I have a question on the useage of the PrintWindow API call.
When I call this function, i occasionally get black rectangles im places where an obvious child window lies. For example, at times when i call PrintWindow passing a Explorer window the file explorer child window (SysListView32 i believe) comes up as a black rect, other times it OK. I tried calling UpdateWindow() before the call and it still happens. Called LockWindowUpdate because i hear PrintWindow sends "erase window background" message and pretty much everything came up black. Tried Doevents before and after the call and the same thing happens. Tried Sleep(0) before the call (yes someone did suggest it), same thing.
I read alot of posts about it and could never find a difinitive answer.
Im using Windows XP SP2, could it be the OS?
The code im using is straightforward, and working. Just occasional black rects.
Heres an example of the "Black Rect" i occasionally get. Notice the Explorer window on the left:
Thanx for any replies,
-Xiphias3
Last edited by Xiphias3; Jan 26th, 2009 at 09:10 PM.
I recently added PrintWindow to my app and have not had that problem. Probably because I am only capturing my vb forms. At least not yet, I found this:
Randomly Captured Black Screen By Using PrintWindow API http://social.msdn.microsoft.com/For...-466e5aa91391/
and thought it may help you
Waiting for a full featured smart phone with out marrying a provider
Go Android
Go raiders
I recently added PrintWindow to my app and have not had that problem. Probably because I am only capturing my vb forms. At least not yet, I found this:
Randomly Captured Black Screen By Using PrintWindow API http://social.msdn.microsoft.com/For...-466e5aa91391/
and thought it may help you
Thanks for the reply.
However, i already read the thread that the post you posted linked to. Im just looking for an answer as to why PrintWindow sometimes returns black rects and other times it doesnt when called with the same window (hWnd).
Same Window sometimes different results. Why?
The reason why the "black rectangles" appear is because the window isnt properly refreshed. My question is, how do you know when a Window is "properly"/"completely" refreshed? I have no idea what message or wParam/lParam that could be, or the requirement of subclassing/hacks. Any ideas?
Ill go fool with Spy++ and see if it turns up anything...
The reason why the "black rectangles" appear is because the window isnt properly refreshed. My question is, how do you know when a Window is "properly"/"completely" refreshed? I have no idea what message or wParam/lParam that could be, or the requirement of subclassing/hacks. Any ideas?
Ill go fool with Spy++ and see if it turns up anything...
I posted your question on another site, but have not got a response yet. I was going to suggest doing refresh as i do on the forms i use printwindow on, but how to refresh a window you do not own is unknown. If get a response I will be back.
Waiting for a full featured smart phone with out marrying a provider
Go Android
Go raiders
I posted your question on another site, but have not got a response yet. I was going to suggest doing refresh as i do on the forms i use printwindow on, but how to refresh a window you do not own is unknown. If get a response I will be back.
I have tried everything!
1. RedrawWindow with everypossible combination of RDW_ flags i see, primarily RDW_INVALIDATE
2. UpdateWindow
3. SetWindowPos
Then put DoEvents and/or Sleep before the PrintWindow call.
It still happens
I made a post over at ntwind.com, (the site with TaskSwitchXP) about my problem cuz his app runs good, i only see black rects where expected (vid overlay, etc). Im hoping the author of the app, Alexander (lol, my middle name) will reply instead of thinking im trying to clone his app. http://www.ntwind.com/forum/viewtopic.php?p=2460#2460
I have tried everything!
1. RedrawWindow with everypossible combination of RDW_ flags i see, primarily RDW_INVALIDATE
2. UpdateWindow
3. SetWindowPos
Then put DoEvents and/or Sleep before the PrintWindow call.
It still happens
I made a post over at ntwind.com, (the site with TaskSwitchXP) about my problem cuz his app runs good, i only see black rects where expected (vid overlay, etc). Im hoping the author of the app, Alexander (lol, my middle name) will reply instead of thinking im trying to clone his app. http://www.ntwind.com/forum/viewtopic.php?p=2460#2460
-Xiphias3
I found this might be something else to try: Refresh a window in an external application in vb
Code:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Const WM_SETFOCUS = &H7
----------------------
dim hndl as Long
hndl = FindWindow(vbNullString, "Application Name")
SetForegroundWindow (hndl)
PostMessage hndl, WM_SETFOCUS, 0, 0
Waiting for a full featured smart phone with out marrying a provider
Go Android
Go raiders
If the window is not covered up, you can use some GDI APIs to get the contents...
Code:
Dim tDC As Long
tDC = GetWindowDC(targethWnd)
BitBlt Picture1.hDC, 0, 0, targetWidth, targetHeight, tDC, 0, 0, vbSrcCopy
ReleaseDC targetHwnd, tDC
Get the top level window's dimensions with GetWindowRect API
Edited: Changed GetDC to GetWindowDC API
Im familiar with the *Blt functions and Ive figured out PaintDesktop which seems to be a wierd function, but i just ended up using SPI. The app is working (see my 1st post), but I just cant figure out why the black rects are appearing. I need PrintWindow cuz SendMessage with WM_PRINT isnt working for me, (but ill fool with the flags again i guess). My App-Switcher window is 700px by 400px at the center of the screen with SWP's HWND_TOPMOST, which is gonna obscure other windows.
BTW LaVolpe, i actually have one of ur projects open, CustomWindows. GJ! (Its the 4th to last in the list view on the right in the pic i posted in post #1)
Last edited by Xiphias3; Jan 27th, 2009 at 01:21 PM.
I found this might be something else to try: Refresh a window in an external application in vb
Code:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Const WM_SETFOCUS = &H7
----------------------
dim hndl as Long
hndl = FindWindow(vbNullString, "Application Name")
SetForegroundWindow (hndl)
PostMessage hndl, WM_SETFOCUS, 0, 0
Thx! Will try this now and Edit/Reply. Have to run the app multiple times cuz sometimes i get lucky and all the windows are fine. Come to think of it, im only having probs with Explorer windows, and the usual of course (vid overlay, MS Pic Manager, etc). If i need to settle with the black rects then fine. I can always implement a "refresh" mechanism, but it must be possible since the TaskSwitchXP doesnt seem to have this problem. Maybe i should subclass? Ill fool around a little more before i do that.
EDIT
===
Well, i dont want to set the win as a foreground window since window captures are not gonna happen when I press Alt+Tab. Itll just be a WNDPROC hook that will pass items to an array of WindowInfo (my UDT) and have it fill the picture prop in another thread. Ill fool with it nonetheless. Im trying this out:
Code:
Call RedrawWindow(hwnd, ByVal 0, ByVal 0, RDW_INVALIDATE Or RDW_ALLCHILDREN Or RDW_ERASENOW Or RDW_UPDATENOW)
Call Sleep(75)
lRetPW = PrintWindow(hwnd, hDCMem, 0)
I increased the sleep time to 75 ms then I launched the app 6 times and no black boxes/rects.
Obviously this isnt a solid approach since the sleep time needed most likely will end up being resource dependent.
But, maybe ill live with it since the window cap function will be running in another thread by use of an ActiveX EXE.
Ill do more testing now...
Last edited by Xiphias3; Jan 27th, 2009 at 01:29 PM.
Out of curiosity, does this only happen when the target window is semi-translucent? On your first screenshot, it appears the explorer window is?
More curiosity questions...
Also, can you tell us what you are passing to the PrintWindow api for the hDC parameter? Is it a vb conrol's DC or a memory DC? If a control's DC, is AutoRedraw set to true?
P.S. You are aware that PrintWindow is for XP & above per MSDN? So you won't be able to use it on earlier O/S versions.
Insomnia is just a byproduct of, "It can't be done"
Out of curiosity, does this only happen when the target window is semi-translucent? On your first screenshot, it appears the explorer window is?
Thats just an illusion. Its actually "Form-on-Form" action there. You can laugh. This Task/App-Switcher is for me and my otaku (or anime) friends. Its gonna be apart of a larger project. Applied LWA to the top form, and its owner is the 1 beneath, which is opaque with no LWA.
Originally Posted by LaVolpe
More curiosity questions...
Also, can you tell us what you are passing to the PrintWindow api for the hDC parameter? Is it a vb conrol's DC or a memory DC? If a control's DC, is AutoRedraw set to true?
Im using a mem DC provided by the PhotoTrue object. The only time it ever failed was with PaintDesktop (which cant work with mem DCs because they're not "attached" to a desktop so it was obvious). From testing, the DC type doesnt seem to matter. I used CreateCompatibleDC(), oPO.hdc and pbTmp.hdc (with AutoRedraw = true). The black rects appear occasionally. However, in my last post i said i increased the sleep time and im still using the oPO hdc and it seems to be working fine. Ill do more research and if all fails ill try to "cover all bases" by setting the sleep time to like 200ms and have win capture done in another thread.
Originally Posted by LaVolpe
P.S. You are aware that PrintWindow is for XP & above per MSDN? So you won't be able to use it on earlier O/S versions.
Im good, most of my ppl have XP few Vista. I actually did alot of research on PrintWindow before i made this thread.
If I were to try and replicate the problem, is there some way to guarantee it? You mention that the black rects are intermittent. Any method to the madness? If so, I'd play along, but don't want to waste a bunch of time trying something that may not work (btw, my O/S is XP Pro SP3 which is different than yours).
Insomnia is just a byproduct of, "It can't be done"
If I were to try and replicate the problem, is there some way to guarantee it? You mention that the black rects are intermittent. Any method to the madness? If so, I'd play along, but don't want to waste a bunch of time trying something that may not work (btw, my O/S is XP Pro SP3 which is different than yours).
Im gonna tell ya pretty much all i know. Hopefully it wont be a total refresher course for your 1337ness.
Everything here is what ive learnt through days of research, and im willing to take correction(s). My OS is WinXP Pro, SP2.
There are pretty much 3 types of "Black Rect" artifacts that can end up in the bmp PrintWindow draws to.
1. Improper Response Or No Handling Of WM_PRINT
If you call PrintWindow on certain applications such as Microsoft Office Picture Manager, a black rect WILL occur. The application just doesnt handle the message properly/fully. The areas where the images are will end up being drawn to the desktop itself NOT the DC passed to PrintWindow. Example:
Notice the image on the left on top of the Explorer Bar. From my understanding, you will never be able to get the entire client area, because the app just doesnt hadle the message properly/completely/fully. In cases where you dont know what windows youre capturing, its best to refresh the desktop or maybe prevent painting with LockWindowUpdate.
2. Overlays
Simple. PrintWindow will never work. The bits are stored in the vid card and you cant get them. Example:
Results are pretty much same as #1 and youll possibly need to cleanup the desktop.
3. Invalid/Incomplete/Problematic Window Refresh
This is where i had the Explorer window problems. I have no idea why this is happening. It a refresh problem. I dont know why. It will work at times, other times itll return a black rect for the SysListView (file selection area). Here's my code
Code:
'hwnd is the target window
'd is Dimension (UDT) with width and height as longs
d.Width = (r.Right - r.left)
d.Height = (r.Bottom - r.top)
'Create a PhotoObject the size of the window rect
Call oPT.Create(d.Width, d.Height, vbMagenta)
hDCWnd = GetWindowDC(hwnd)
hDCMem = oPT.hdc 'Or you point it to a CreateCompatibleDC() or a PictureBox.hDC
hBmp = CreateCompatibleBitmap(hDCWnd, oPT.Width, oPT.Height)
Call ReleaseDC(hwnd, hDCWnd) 'Credit to LaVolpe
hBmpOld = SelectObject(hDCMem, hBmp)
hBrush = GetStockObject(DC_BRUSH)
Call SelectObject(hDCMem, hBrush)
Call SetDCBrushColor(hDCMem, vbMagenta)
rgnWnd = CreateRectRgn(0, 0, oPT.Width, oPT.Height)
'Fill with magenta since that's the colour key (LWA)
Call FillRgn(hDCMem, rgnWnd, hBrush)
rgnType = GetWindowRgn(hwnd, rgnWnd)
If (rgnType <> 0) Then rgnOld = SelectObject(hDCMem, rgnWnd)
'Possibly pointless
Call RedrawWindow(hwnd, ByVal 0, ByVal 0, RDW_INVALIDATE Or RDW_ALLCHILDREN Or RDW_ERASENOW Or RDW_UPDATENOW)
'Sleep for a while and hope good things happen :P
Call Sleep(75)
lRetPW = PrintWindow(hwnd, hDCMem, 0)
If (rgnType <> 0) Then Call DeleteObject(SelectObject(hDCMem, rgnOld))
'Resize, Cleanup, etc...
PrintWindow sends the Erase Background message to the window. If you want to see all black call LockWindowUpdate using hwnd before PrintWindow. Some people say they use RedrawWindow and PrintWindow together, but I dont really see the point (or maybe i dont understand). PrintWindow erases the background so whats the point of RedrawWindow? I dont know. Sleep however does seem to be a sensible move. By Sleeping for 75 ms, i was able to run the program Black Rect free 10 time, and pretty much the same thing happened without RedrawWindow.
Theres probably more to it, but this is what ive experienced.
Last edited by Xiphias3; Jan 28th, 2009 at 06:28 PM.
No guarantees I can play with this today. But I did notice something that may help, or it may not.
You are using GetWindowDC, but are never releasing it.
Recommend trying this ...
1. After the hBmp is created, call ReleaseDC hWnd, hDCWnd
2. Rem out the refresh code for now & apply it if the ReleaseDC doesn't work.
3. Rem Sleep for now & apply later if needed
Insomnia is just a byproduct of, "It can't be done"
No guarantees I can play with this today. But I did notice something that may help, or it may not.
You are using GetWindowDC, but are never releasing it.
Recommend trying this ...
1. After the hBmp is created, call ReleaseDC hWnd, hDCWnd
2. Rem out the refresh code for now & apply it if the ReleaseDC doesn't work.
3. Rem Sleep for now & apply later if needed
The commented line,
Code:
'Resize, Cleanup, etc...
is actually,
Code:
Call getConstrainedSizeForWindow(d, d2)
If ((oPT.Width > d.Width) Or (oPT.Height > d.Height)) Then Call oPT.Resize(d.Width, d.Height)
ERA:
On Error Resume Next
If ((oPT.picture Is Nothing) Or (lRetPW = 0)) Then
Set getWindowPicture = frmControl.pbQuesMark.picture
Else
Set getWindowPicture = oPT.picture
End If
Call oPT.Clear
If (hBmp) Then Call DeleteObject(hBmp)
If (hDCWnd) Then Call ReleaseDC(hwnd, hDCWnd)
Calling GetWindowDC and not releasing it before you refresh could prevent the DC from being updated
Originally Posted by msdn
After painting is complete, the ReleaseDC function must be called to release the device context. Not releasing the window device context has serious effects on painting requested by applications
Insomnia is just a byproduct of, "It can't be done"
Calling GetWindowDC and not releasing it before you refresh could prevent the DC from being updated
Here's the entire function, to make life easier:
Code:
'Gets the current Window picture****************************
Public Function getWindowPicture(ByRef WI As WindowInfo) As StdPicture: On Error GoTo ERA
Dim TPPX As Integer, TPPY As Integer, hwnd As Long, r As RECT, sizeSqrd As Long, _
deskRect As RECT, hwndCurrent As Long, szText As String, procID As Long, procIDTmp As Long, _
d As Dimension, hDCMem As Long, hDCWnd As Long, hBmpOld As Long, hBmp As Long, hBrush As Long, _
rgnWnd As Long, rgnOld As Long, rgnType As Long, lRetPW As Long, d2 As Dimension, lStyle As Long, _
bOnScr As Boolean, szTxt As String, oDIBTmp As cDIBSection, oldAI As ANIMATIONINFO, AI As ANIMATIONINFO
hwnd = WI.hwnd
TPPX = Screen.TwipsPerPixelX
TPPY = Screen.TwipsPerPixelY
oldAI.cbSize = Len(oldAI)
AI.cbSize = Len(AI)
AI.iMinAnimate = 0
'For now ignore minimized windows
If (WI.bMinimized) Then
Set getWindowPicture = frmControl.pbQuesMark.picture
Exit Function
End If
If (WI.bMinimized) Then
Call SystemParametersInfo(SPI_GETANIMATION, Len(oldAI), oldAI, 0)
Call SystemParametersInfo(SPI_SETANIMATION, Len(AI), AI, SPIF_SENDWININICHANGE)
lStyle = applyExtendedWindowStyle(hwnd, False, False, , True, 0)
Call ShowWindow(hwnd, SW_RESTORE)
End If
Call GetWindowRect(hwnd, r)
sizeSqrd = (r.Right - r.left) * (r.Bottom - r.top)
Call GetWindowRect(GetDesktopWindow(), deskRect)
bOnScr = (((r.Right < deskRect.left) Or (r.Bottom < deskRect.top) Or _
(r.left > deskRect.Right) Or (r.top > deskRect.Bottom)) = False)
If ((IsRectEmpty(r)) Or (bOnScr = False)) Then
Call GetWindowThreadProcessId(hwnd, procID)
hwndCurrent = GetWindow(hwnd, GW_HWNDFIRST)
szTxt = String(128, Chr(0))
Do While (hwndCurrent <> 0)
Call GetWindowThreadProcessId(hwndCurrent, procIDTmp)
If (procIDTmp = procID) Then
If ((IsWindowVisible(hwndCurrent)) And (GetWindowText(hwndCurrent, szTxt, 128) > 0)) Then
Call GetWindowRect(hwndCurrent, r)
If (IsRectEmpty(r) = False) Then
If ((((r.Right - r.left) * (r.Bottom - r.top)) > sizeSqrd)) Then
sizeSqrd = (r.Right - r.left) * (r.Bottom - r.top)
hwnd = hwndCurrent
End If
End If
End If
End If
hwndCurrent = GetWindow(hwndCurrent, GW_HWNDNEXT)
Loop
End If
Call GetWindowRect(hwnd, r)
If (IsRectEmpty(r)) Then GoTo ERA
'd and d2 are dimension (UDT) with width and height as longs
d.Width = (r.Right - r.left)
d.Height = (r.Bottom - r.top)
'pbWindow is where pic of window will be drawn
d2.Width = frmControl.pbWindow.Width / TPPX
d2.Height = frmControl.pbWindow.Height / TPPY
'Create a PhotoObject the size of the window rect
Call oPT.Create(d.Width, d.Height, vbMagenta)
hDCWnd = GetWindowDC(hwnd)
hDCMem = oPT.hdc 'Or you point it to a CreateCompatibleDC() or a PictureBox.hDC
hBmp = CreateCompatibleBitmap(hDCWnd, oPT.Width, oPT.Height)
Call ReleaseDC(hwnd, hDCWnd) 'Credit to LaVolpe
hBmpOld = SelectObject(hDCMem, hBmp)
hBrush = GetStockObject(DC_BRUSH)
Call SelectObject(hDCMem, hBrush)
Call SetDCBrushColor(hDCMem, vbMagenta)
rgnWnd = CreateRectRgn(0, 0, oPT.Width, oPT.Height)
'Fill with magenta since that's the colour key (LWA)
Call FillRgn(hDCMem, rgnWnd, hBrush)
rgnType = GetWindowRgn(hwnd, rgnWnd)
If (rgnType <> 0) Then rgnOld = SelectObject(hDCMem, rgnWnd)
'Possibly pointless
Call RedrawWindow(hwnd, ByVal 0, ByVal 0, RDW_INVALIDATE Or RDW_ALLCHILDREN Or RDW_ERASENOW Or RDW_UPDATENOW)
'Sleep for a while so good things happen :P
Call Sleep(75)
lRetPW = PrintWindow(hwnd, hDCMem, 0)
If (rgnType <> 0) Then Call DeleteObject(SelectObject(hDCMem, rgnOld))
If (WI.bMinimized) Then
Call SetWindowLong(hwnd, GWL_EXSTYLE, lStyle)
Call ShowWindow(hwnd, SW_MINIMIZE)
Call SystemParametersInfo(SPI_SETANIMATION, Len(oldAI), oldAI, SPIF_SENDWININICHANGE)
End If
If (lRetPW = 0) Then GoTo ERA
Call getConstrainedSizeForWindow(d, d2)
If ((oPT.Width > d.Width) Or (oPT.Height > d.Height)) Then
Call oPT.Resize(d.Width, d.Height)
'Set oDIBTmp = oDIB.Resample(d.Height, d.Width)
'Call DeleteObject(SelectObject(hDCMem, hBmpOld))
'Call oPT.Clear
'Call oPT.Create(d.Width, d.Height, vbMagenta)
'Call oDIBTmp.PaintPicture(oPT.hdc)
'Set oDIBTmp = Nothing
End If
ERA:
On Error Resume Next
If ((oPT.picture Is Nothing) Or (lRetPW = 0)) Then
Set getWindowPicture = frmControl.pbQuesMark.picture
Else
Set getWindowPicture = oPT.picture
End If
Call oPT.Clear
If (hBmp) Then Call DeleteObject(hBmp)
'If (hDCWnd) Then Call ReleaseDC(hwnd, hDCWnd)
If (Not (oDIBTmp Is Nothing)) Then oDIBTmp.ClearUp
End Function
'***********************************************************
Last edited by Xiphias3; Jan 27th, 2009 at 04:37 PM.
I am only quoting what msdn is recommending, release immediately after you are done with it, not at the end of your routine, especially not after you try to get it to refresh.
Code:
hDCWnd = GetWindowDC(hwnd)
hDCMem = oPT.hDC 'Or you point it to a CreateCompatibleDC() or a PictureBox.hDC
hBmp = CreateCompatibleBitmap(hDCWnd, oPT.Width, oPT.Height)
Call ReleaseDC(hwnd, hDCWnd)
hBmpOld = SelectObject(hDCMem, hBmp)
' then rem this line out
If (hDCWnd) Then Call ReleaseDC(hwnd, hDCWnd)
Does no harm in testing it. You might even be experiencing memory leaks. I know that if GetDC is called without ReleaseDC then memory leaks will occur.
Insomnia is just a byproduct of, "It can't be done"
I am only quoting what msdn is recommending, release immediately after you are done with it, not at the end of your routine, especially not after you try to get it to refresh.
Code:
hDCWnd = GetWindowDC(hwnd)
hDCMem = oPT.hDC 'Or you point it to a CreateCompatibleDC() or a PictureBox.hDC
hBmp = CreateCompatibleBitmap(hDCWnd, oPT.Width, oPT.Height)
Call ReleaseDC(hwnd, hDCWnd)
hBmpOld = SelectObject(hDCMem, hBmp)
' then rem this line out
If (hDCWnd) Then Call ReleaseDC(hwnd, hDCWnd)
Does no harm in testing it. You might even be experiencing memory leaks. I know that if GetDC is called without ReleaseDC then memory leaks will occur.
Definately, I see where you're coming from. Thx for your invaluable help.
EDIT:
====
Well the desktop (instead of PrintWindow DC) painting also happens for TaskSwitch XP. Vidz will obviously never work. Printscreen proves it.
Im hoping it was my failure at graphics programming that led to the black rects in explorer.
EDIT2:
=====
In the words of Arnold Schwartenegger(sp), "I'll be back, trust me."
Im gonna write a basic app to test PrintWindow in different ways, after i wake up.
Thx isnoend07 and LaVolpe!
Last edited by Xiphias3; Jan 27th, 2009 at 07:07 PM.
Im carrying out some tests with PrintWindow and Im hoping someone will run the app and help me out by stating which mode/modes cause black rects to appear, if any. My OS is WinXP Pro Sp2.
Code:
Select Case index
Case 0 ' Mode 1
lRet = PrintWindow(hwndTarget, hDCMem, 0)
Case 1 ' Mode 2
Call Sleep(100)
lRet = PrintWindow(hwndTarget, hDCMem, 0)
Case 2 ' Mode 3
Call RedrawWindow(hwndTarget, ByVal 0, ByVal 0, RDW_INVALIDATE Or RDW_ALLCHILDREN Or RDW_UPDATENOW)
lRet = PrintWindow(hwndTarget, hDCMem, 0)
Case 3 ' Mode 4
Call RedrawWindow(hwndTarget, ByVal 0, ByVal 0, RDW_INVALIDATE Or RDW_ALLCHILDREN Or RDW_UPDATENOW)
Call Sleep(100)
lRet = PrintWindow(hwndTarget, hDCMem, 0)
End Select
Thx in advance!
P.S. Project files in the zip attached
Last edited by Xiphias3; Aug 18th, 2009 at 02:49 PM.
Im carrying out some tests with PrintWindow and Im hoping someone will run the app and help me out by stating which mode/modes cause black rects to appear, if any. My OS is WinXP Pro Sp2.
Code:
Select Case index
Case 0 ' Mode 1
lRet = PrintWindow(hwndTarget, hDCMem, 0)
Case 1 ' Mode 2
Call Sleep(100)
lRet = PrintWindow(hwndTarget, hDCMem, 0)
Case 2 ' Mode 3
Call RedrawWindow(hwndTarget, ByVal 0, ByVal 0, RDW_INVALIDATE Or RDW_ALLCHILDREN Or RDW_UPDATENOW)
lRet = PrintWindow(hwndTarget, hDCMem, 0)
Case 3 ' Mode 4
Call RedrawWindow(hwndTarget, ByVal 0, ByVal 0, RDW_INVALIDATE Or RDW_ALLCHILDREN Or RDW_UPDATENOW)
Call Sleep(100)
lRet = PrintWindow(hwndTarget, hDCMem, 0)
End Select
Thx in advance!
P.S. Project files in the zip attached
I am running the same OS as you and the only black screen was M1 image 30, but only one time 5 other test and no black screen m2-m4 None
Waiting for a full featured smart phone with out marrying a provider
Go Android
Go raiders
I am running the same OS as you and the only black screen was M1 image 30, but only one time 5 other test and no black screen m2-m4 None
Thx isnoend07!
Did the black rect occur in an [file] explorer window? In any case, those results are nice to hear. Maybe the black rects are because of my PC. Ill do a test in a VM when i get time. Thx again, isnoend07.
They all produced at least one black filled rect for me eventually, but seems only in explorer type window where it's normally white and shows the files listed, other parts came out fine. Had a Notepad open too and its white area never came out black.
btw, tested on XP Pro (SP3), AMD 2.2GHz dual core, Nvidia 8600GT GPU.
They all produced at least one black filled rect for me eventually, but seems only in explorer type window where it's normally white and shows the files listed, other parts came out fine. Had a Notepad open too and its white area never came out black.
btw, tested on XP Pro (SP3), AMD 2.2GHz dual core, Nvidia 8600GT GPU.
Thx for results Edgemeal!
The black rects do seem to only occasionally appear in the explorer type windows as seen in my first post (aside from the obvious ones in like those in one of my previous posts). For me, M2 and M4 produce better results. It really looks like the Sleep call is helping in my case. With M1 i get multiple black rects appearing, in one case 4 of 9 explorer had black rects. With M2 or M4 i got 1 or none. My Video card is an OLD GeForce 3 TI 200 64 MB. (more powerful laptop is dead because of Toshiba faulty GPUs). I can probably implement a function that does something else with explorer windows like:
1. Module32First -> ME.szExePath to check for ..System32\Explorer.exe
2. FindWindowEx for SysListView32 (i believe)
3. GetWindowRect
4. Check for black pixels
5. Call PrintWindow again if necessary
Ill do some more coding later tonight or tommorrow.
Last edited by Xiphias3; Jan 28th, 2009 at 09:01 PM.
Here's an untested idea. Thinking in reverse logic. What if you try to invalidate the entire window without updating it? Would that provide worse, better or same results? Basically, you will be telling the window that it is needs a 100% refresh, but don't refresh yet. Then the PrintWindow might simultaneously force a refresh while printing to your DC? Just a thought, no gut reaction either way.
Insomnia is just a byproduct of, "It can't be done"
Here's an untested idea. Thinking in reverse logic. What if you try to invalidate the entire window without updating it? Would that provide worse, better or same results? Basically, you will be telling the window that it is needs a 100% refresh, but don't refresh yet. Then the PrintWindow might simultaneously force a refresh while printing to your DC? Just a thought, no gut reaction either way.
Interesting. Thx for the reply. Will try it soon!
EDIT
===
RedrawWindow reuires either RDW_ERASENOW or RDW_UPDATENOW as a flag. RDW_UPDATENOW is the same as RDW_ERASENOW except it sends the window WM_PAINT. I used RDW_ERASENOW instead of RDW_UPDATENOW and it doesnt seem any better.
Last edited by Xiphias3; Jan 28th, 2009 at 09:30 PM.
EDIT
===
RedrawWindow reuires either RDW_ERASENOW or RDW_UPDATENOW as a flag. RDW_UPDATENOW is the same as RDW_ERASENOW except it sends the window WM_PAINT. I used RDW_ERASENOW instead of RDW_UPDATENOW and it doesnt seem any better.
Instead of using RedrawWindow try InvalidateRgn passing 0 for the region
Insomnia is just a byproduct of, "It can't be done"
Yes i tried Windows Explorer, Internet explorer, firefox , vb ide, everthing worked
Thx! Makes me feel good that if i cant sole this problem others probably wont experience it.
LaVolpe, InvalidateRgn seems to be producing same results as M1 for me. 4 of 16 had black rects where file area is. isnoend07 is having good results. Maybe its my PC's problem. Currently working finding the SysListView and them checking pixels on hDCMem. FindWindowEX needs fixing:
Thx! Makes me feel good that if i cant sole this problem others probably wont experience it.
LaVolpe, InvalidateRgn seems to be producing same results as M1 for me. 4 of 16 had black rects where file area is. isnoend07 is having good results. Maybe its my PC's problem. Currently working finding the SysListView and them checking pixels on hDCMem. FindWindowEX needs fixing:
Is there any way you can run code to check for black window and run again if black ?
Indeed, that is what im trying to accomplish. I said it in one of my prev posts that has this:
Originally Posted by Xiphias3
1. Module32First -> ME.szExePath to check for ..System32\Explorer.exe
2. FindWindowEx for SysListView32 (i believe)
3. GetWindowRect
4. Check for black pixels
5. Call PrintWindow again if necessary
Currently im not on the same wavelength with FindWindowEx.
Is there any way you can run code to check for black window and run again if black ?
You'd need to at least check what color the user has their window background color set to in Windows [GetSysColor(5)]. No doubt most people never change it from the default white but there is always that possibility someone actually has it set to black.
You'd need to at least check what color the user has their window background color set to in Windows [GetSysColor(5)]. No doubt most people never change it from the default white but there is always that possibility someone actually has it set to black.
Wonderful! I never thought of that! Ill look up what the constant anme of 5 is, should be easy!
Indeed Private Const COLOR_WINDOW = 5 'Windows background!
Luckily, when PrintWindow fails a window, the result is always is black, at least from everything ive read. Anyway, here's the draft of what im using to detect black rects. It does actually seem to be working. Will attach a proper project soon.
Code:
Case 1 ' Mode 2
'Call Sleep(100)
lRetPW = PrintWindow(hwndTarget, hDCMem, 0)
Call GetWindowThreadProcessId(hwndTarget, procID)
th32SS = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, procID)
Call ZeroMemory(ME32, Len(ME32))
ME32.dwSize = Len(ME32)
lRet = Module32First(th32SS, ME32)
Call CloseHandle(th32SS)
If (InStr(1, ME32.szExeFile, "explorer.exe", vbTextCompare) > 0) Then
lRet = FindWindowEx(hwndTarget, GetWindow(hwndTarget, GW_CHILD), "SHELLDLL_DefView", vbNullString)
lRet = GetWindow(lRet, GW_CHILD) ' DUIViewWndClassName
lRet = GetWindow(lRet, GW_CHILD) ' DirectUIHWND
lRet = GetWindow(lRet, GW_CHILD) ' CtrlNotifySink
lRet = GetWindow(lRet, GW_CHILD) ' SysListView32
szBuff = String(32, Chr(0))
Call GetClassName(lRet, szBuff, 32)
If (InStr(1, szBuff, "SysListView32", vbTextCompare) > 0) Then
Call ZeroMemory(lvRect, Len(lvRect))
Call GetWindowRect(lRet, lvRect)
If (((lvRect.Right - lvRect.Left) > 0) And ((lvRect.Bottom - lvRect.Top) > 0)) Then
Call ZeroMemory(ptWnd, Len(ptWnd))
Call ZeroMemory(ptSysListView, Len(ptSysListView))
Call ClientToScreen(hwndTarget, ptWnd)
Call ClientToScreen(lRet, ptSysListView)
hDCX = (ptSysListView.x - ptWnd.x)
hDCY = (ptSysListView.y - ptWnd.y)
lvWid = (lvRect.Right - lvRect.Left) - 1
lvHei = (lvRect.Bottom - lvRect.Top) - 1
Call Randomize(Timer): pxA = -1: pxB = -1
pxA = GetPixel(hDCMem, hDCX + ((Rnd * lvWid) + 1), hDCY + ((Rnd * lvHei) + 1))
pxB = GetPixel(hDCMem, hDCX + ((Rnd * lvWid) + 1), hDCY + ((Rnd * lvHei) + 1))
wndBGCol = GetSysColor(COLOR_WINDOW)
If ((pxA = vbBlack) And (pxB = vbBlack) And (pxA <> wndBGCol) And (pxB <> wndBGCol)) Then
Call lstBlackRects.AddItem(Format(i, "00") + ".bmp possibly has black rect where SysListView32 is.")
'lRetPW = PrintWindow(hwndTarget, hDCMem, 0)
End If
End If
End If
End If
EDIT:
====
Made a change recommended by Edgemeal!!! wndBGCol = GetSysColor(COLOR_WINDOW)
If ((pxA = vbBlack) And (pxB = vbBlack) And (pxA <> wndBGCol) And (pxB <> wndBGCol)) Then
Last edited by Xiphias3; Jan 29th, 2009 at 12:13 AM.
PrintWindow (using M1 opt.) seems more prone to fail when my PC is busy.
I was updating my usenet app which is multithreaded and eats at least 50% of my dual core when its busy, i set it to capture 33 pics using option M1, worst case was 2 black explorers and 2 black FireFox's. So seems it's not only explorer that can go black, at least for me (3+ year old PC).
btw, compiled with VB6 Pro(SP5) , the exe and captures are on a WD Raptor 10K rpm drive, which is pretty fast I suppose.
PrintWindow (using M1 opt.) seems more prone to fail when my PC is busy.
I was updating my usenet app which is multithreaded and eats at least 50% of my dual core when its busy, i set it to capture 33 pics using option M1, worst case was 2 black explorers and 2 black FireFox's. So seems it's not only explorer that can go black, at least for me (3+ year old PC).
btw, compiled with VB6 Pro(SP5) , the exe and captures are on a WD Raptor 10K rpm drive, which is pretty fast I suppose.
Indeed, thx for the reply Edgemeal!
Ive always had worse results with M1. The call to Sleep seems to help. M2 and M4 are best modes as far as i see. In any case, ill just try to implement black rect detection for windows explorer windows and most likely leave it at that.