Zedna Posted May 19, 2008 Share Posted May 19, 2008 Purpose is to get bitmap screenshot of nonstandard statusbar from another application and later compare it with saved bitmap to see state of application. Now I have working script but only if I capture bitmap (and save it as BMP file) from my own AutoIt's GUI control (StatusBar): expandcollapse popup#include <GUIConstants.au3> #include <GDIPlus.au3> #Include <WinAPI.au3> #include <GUIStatusBar.au3> #include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <StatusBarConstants.au3> #include <WindowsConstants.au3> $Form1_1 = GUICreate("Form1", 593, 453, 193, 115) $StatusBar1 = _GUICtrlStatusBar_Create($Form1_1) _GUICtrlStatusBar_SetSimple($StatusBar1) _GUICtrlStatusBar_SetText($StatusBar1, "Optimizing F:\ks\sybaz7\az-los.pbl ...") $MyButton1 = GUICtrlCreateButton("Get Status as image", 224, 176, 140, 30, 0) GUISetState(@SW_SHOW) While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $MyButton1 GetStatusImage() EndSwitch WEnd Func GetStatusImage() $hWnd = ControlGetHandle("Form1","","msctls_statusbar321") $pos = ControlGetPos("Form1","","msctls_statusbar321") _GDIPlus_StartUp() $Width = $pos[2] $Height = $pos[3] ;~ MsgBox(0,'Image size', $Width & 'x' & $Height) $hDC = _WinAPI_GetDC($hWnd) $memDC = _WinAPI_CreateCompatibleDC($hDC) $memBmp = _WinAPI_CreateCompatibleBitmap($hDC, $Width, $Height) _WinAPI_SelectObject ($memDC, $memBmp) ;~ Func _WinAPI_BitBlt($hDestDC, $iXDest, $iYDest, $iWidth, $iHeight, $hSrcDC, $iXSrc, $iYSrc, $iROP) _WinAPI_BitBlt($memDC, 0, 0, $Width, $Height, $hDC, 0, 0, $SRCCOPY) $hImage = _GDIPlus_BitmapCreateFromHBITMAP ($memBmp) _GDIPlus_ImageSaveToFile($hImage, 'status.bmp') _GDIPlus_ImageDispose ($hImage) _WinAPI_ReleaseDC($hWnd, $hDC) _WinAPI_DeleteDC($memDC) _WinAPI_DeleteObject ($memBmp) _GDIPlus_ShutDown() EndFuncoÝ÷ Û`¦Û«z«µ«¢+Ø¥¹±Õ±ÐíU% ½¹ÍѹÑ̹ÔÌÐì(¥¹±Õ±Ðí%A±Õ̹ÔÌÐì(%¹±Õ±Ðí]¥¹A$¹ÔÌÐì(¥¹±Õ±ÐíU%MÑÑÕÍ È¹ÔÌÐì(¥¹±Õ±Ðí ÕÑѽ¹ ½¹ÍѹÑ̹ÔÌÐì(¥¹±Õ±ÐíU% ½¹ÍѹÑÍà¹ÔÌÐì(¥¹±Õ±ÐíMÑÑÕÍ É ½¹ÍѹÑ̹ÔÌÐì(¥¹±Õ±Ðí]¥¹½ÝÍ ½¹ÍѹÑ̹ÔÌÐì((íøÕ¹ÑMÑÑÕÍ%µ ¤(ÀÌØí¡]¹ô ½¹Ñɽ±Ñ!¹± ÅÕ½Ðí½É´ÄÅÕ½Ðì°ÅÕ½ÐìÅÕ½Ðì°ÅÕ½ÐíµÍѱÍ}ÍÑÑÕÍÈÌÈÄÅÕ½Ðì¤) ½¹Í½±]É¥Ñ ÀÌØí¡]¹¤(ÀÌØíÁ½Ìô ½¹Ñɽ±ÑA½Ì ÅÕ½Ðí½É´ÄÅÕ½Ðì°ÅÕ½ÐìÅÕ½Ðì°ÅÕ½ÐíµÍѱÍ}ÍÑÑÕÍÈÌÈÄÅÕ½Ðì¤()}%A±ÕÍ}MÑÉÑUÀ ¤((ÀÌØí]¥Ñ ôÀÌØíÁ½ÍlÉt(ÀÌØí!¥¡ÐôÀÌØíÁ½ÍlÍt((íø5Í ½à À°Ìäí%µÍ¥éÌäì°ÀÌØí]¥Ñ µÀìÌäíàÌäìµÀìÀÌØí!¥¡Ð¤((ÀÌØí¡ô}]¥¹A%}Ñ ÀÌØí¡]¹¤(ÀÌØíµµô}]¥¹A%} ÉÑ ½µÁÑ¥± ÀÌØí¡¤(ÀÌØíµµ µÀô}]¥¹A%} ÉÑ ½µÁÑ¥± ¥ÑµÀ ÀÌØí¡°ÀÌØí]¥Ñ °ÀÌØí!¥¡Ð¤)}]¥¹A%}M±Ñ=©Ð ÀÌØíµµ°ÀÌØíµµ µÀ¤(íøÕ¹}]¥¹A%} ¥Ñ ±Ð ÀÌØí¡ÍÑ°ÀÌØí¥aÍаÀÌØí¥eÍаÀÌØí¥]¥Ñ °ÀÌØí¥!¥¡Ð°ÀÌØí¡MÉ°ÀÌØí¥aMÉ°ÀÌØí¥eMÉ°ÀÌØí¥I=@¤)}]¥¹A%} ¥Ñ ±Ð ÀÌØíµµ°À°À°ÀÌØí]¥Ñ °ÀÌØí!¥¡Ð°ÀÌØí¡°À°À°ÀÌØíMI =Ad¤((ÀÌØí¡%µô}%A±ÕÍ} ¥ÑµÁ ÉÑɽµ! %Q5@ ÀÌØíµµ µÀ¤)}%A±ÕÍ}%µMÙQ½¥± ÀÌØí¡%µ°ÌäíÍÑÑÕÌȹµÀÌäì¤(%}%A±ÕÍ}%µ¥ÍÁ½Í ÀÌØí¡%µ¤)}]¥¹A%}I±Í ÀÌØí¡]¹°ÀÌØí¡¤)}]¥¹A%}±Ñ ÀÌØíµµ¤)}]¥¹A%}±Ñ=©Ð ÀÌØíµµ µÀ¤()}%A±ÕÍ}M¡Õѽݸ ¤(íø¹Õ¹ Here is screenshot from my first working example: Can somebody help me with this weird behaviour?status.bmp Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
smashly Posted May 19, 2008 Share Posted May 19, 2008 Hi, The window needs to be active or in view from what I can see.. Add WinActivate("Form1") to the top of "2) Capture part" of the code and it works like it should. Cheers Link to comment Share on other sites More sharing options...
Zedna Posted May 19, 2008 Author Share Posted May 19, 2008 Hi, The window needs to be active or in view from what I can see.. Add WinActivate("Form1") to the top of "2) Capture part" of the code and it works like it should. Cheers OK. Thanks for the answer smashly. In my original script I tested MouseGetCursor() = 15 in While loop so it was dependent on active status too. So if somebody switched to another application cursor (hourglass) changed and my logic was gone. I'm rewriting my script to check some inner states inside my target application so it will not be dependent on active status. I thought this will work also on non-active windows/controls. So now new question: How can I do that (bitmap screenshot of control) also with non-active window (it's control)? AutoIt can do such things also with non-active/minimized windows as far as I know. What's the trick? Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
Zedna Posted May 19, 2008 Author Share Posted May 19, 2008 (edited) I discovered the WinActivate("Form1","") WinWaitActive("Form1","") must be called before (not after) BitBlt API call. So problem is in BitBlt API. It needs to have active windows. But on MSDN I see no note about such behaviour/limitation http://msdn.microsoft.com/en-us/library/ms532278(VS.85).aspx The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context. Edited May 19, 2008 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
smashly Posted May 19, 2008 Share Posted May 19, 2008 I'm not sure as of yet how to get an image of a window/control that's not showing. I know it's not what you want to hear or be asked, but can't you use ControlGetText() instead? At least it works on minimized and non focused windows. Link to comment Share on other sites More sharing options...
smashly Posted May 19, 2008 Share Posted May 19, 2008 In regards to the msdn link you posted, it's sorta whack that it states in the dwRop descriptions...CAPTUREBLT Windows 98/Me, Windows 2000/XP: Includes any windows that are layered on top of your window in the resulting image. By default, the image only contains your window. Note that this generally cannot be used for printing device contexts. So the default isn't really working as a default then is it? Link to comment Share on other sites More sharing options...
Zedna Posted May 19, 2008 Author Share Posted May 19, 2008 I know it's not what you want to hear or be asked, but can't you use ControlGetText() instead?At least it works on minimized and non focused windows.Really No.My target application is PowerBuilder and it uses non-standard StatusBar control (ClassName PBHELP801) and I can't see any text from it in Au3Info tool. So I really can't use standard controls' functions. Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
Zedna Posted May 19, 2008 Author Share Posted May 19, 2008 I googled for that problem and here is result:http://www.fengyuan.com/article/wmprint.htmlIn short: Instead of BitBlt use WM_PRINT or WM_PRINTCLIENT API Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
Siao Posted May 19, 2008 Share Posted May 19, 2008 Yea, the subject was discussed before http://www.autoitscript.com/forum/index.php?showtopic=55564 and the same article quoted.All the kiddies around here probably would be overjoyed, as this would be kind of a breakthrough moment in game botting with AutoIt. And therefore I'm not sure if it's really good idea. "be smart, drink your wine" Link to comment Share on other sites More sharing options...
Zedna Posted May 19, 2008 Author Share Posted May 19, 2008 (edited) I have found another nice topic about thathttp://www.xtremevbtalk.com/t238494.htmlhttp://support.microsoft.com/kb/230502/EN-US/I will test it and I will post result later. Edited May 19, 2008 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
Zedna Posted May 21, 2008 Author Share Posted May 21, 2008 (edited) I wasn't successfull I replaced_WinAPI_BitBlt($memDC, 0, 0, $Width, $Height, $hDC, 0, 0, $SRCCOPY)by$ret = _SendMessage($hWnd, $WM_PRINT, $memDC, BitOR($PRF_CHILDREN , $PRF_CLIENT, $PRF_NONCLIENT))I tested all combinations of PRF constants:Const $WM_PRINT = 0x317 Const $PRF_CLIENT = 0x4 ; Draw the window's client area. Const $PRF_NONCLIENT = 0x2 Const $PRF_CHILDREN = 0x10; Draw all visible child windows. Const $PRF_OWNED = 0x20 ; Draw all owned windows.But resulting bitmap was always black. It was black also if I commented WM_PRINT line.I noticed on MSDN at WM_PAINT:http://msdn.microsoft.com/en-us/library/ms534901(VS.85).aspxThe WM_PAINT message is generated by the system and should not be sent by an application. To force a window to draw into a specific device context, use the WM_PRINT or WM_PRINTCLIENT message. Note that this requires the target window to support the WM_PRINTCLIENT message. Most common controls support the WM_PRINTCLIENT message.So if somebody can tell me what else must be done to do the trick I will be glad. Edited May 21, 2008 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
Zedna Posted August 27, 2008 Author Share Posted August 27, 2008 I'm curious why but now it works (also previous code):$ret = _SendMessage($hWnd, $WM_PRINT, $memDC, BitOR($PRF_CHILDREN , $PRF_CLIENT, $PRF_NONCLIENT, $PRF_ERASEBKGND ))thanks ptrex - his post is here:http://www.autoitscript.com/forum/index.ph...st&p=568428 Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
martin Posted August 27, 2008 Share Posted August 27, 2008 (edited) I'm curious why but now it works (also previous code): $ret = _SendMessage($hWnd, $WM_PRINT, $memDC, BitOR($PRF_CHILDREN , $PRF_CLIENT, $PRF_NONCLIENT, $PRF_ERASEBKGND )) thanks ptrex - his post is here: http://www.autoitscript.com/forum/index.ph...st&p=568428I cannot get anything but a black area if I use $PRF_CLIENT. If I add a menu then the menu appears in the jpg but the client area, apart from the menu, is black and no controls are shown. How do you do that? Edited August 27, 2008 by martin Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script. Link to comment Share on other sites More sharing options...
Zedna Posted August 27, 2008 Author Share Posted August 27, 2008 (edited) I cannot get anything but a black area if I use $PRF_CLIENT. If I add a menu then the menu appears in the jpg but the client area, apart from the menu, is black and no controls are shown. How do you do that?It works for me on WIN98.Tomorrow I will test it also on WINXP ...EDIT: On WINXP it really doesn't work (only WIN98). So problem still not solved Edited August 28, 2008 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now