Saving screenshots of open Windows with graphic files

This forum is for eXpress++ general support.
Message
Author
User avatar
Eugene Lutsenko
Posts: 1649
Joined: Sat Feb 04, 2012 2:23 am
Location: Russia, Southern federal district, city of Krasnodar
Contact:

Re: Saving screenshots of open Windows with graphic files

#41 Post by Eugene Lutsenko »

And I don't know what I want :D Or rather I want the program itself to know the size of the active window. Maybe something like that?

Code: Select all

@ 0,0 DCSTATIC TYPE XBPSTATIC_TYPE_BITMAP ;
      CAPTION L("colors.jpg") ;
      OBJECT oStatic1 ;
      PREEVAL {|o|o:autoSize := .t.} ;
      EVAL {|o|hDC1 := GetWindowDC(o:getHWnd()), ;
               o:motion := {|a,b,o|ShowColor( hDC1, a, oSay, o )}, ;
               aPixel := Array(o:caption:xSize,o:caption:ySize)}

Code: Select all

nXSize := Len(aPixel), nYSize := Len(aPixel[1])
or maybe they calculate from these parameters the window:
nCYCAPTION
nCXBORDER
nCYBORDER
nCXDLGFRAME
nCYDLGFRAME

User avatar
Eugene Lutsenko
Posts: 1649
Joined: Sat Feb 04, 2012 2:23 am
Location: Russia, Southern federal district, city of Krasnodar
Contact:

Re: Saving screenshots of open Windows with graphic files

#42 Post by Eugene Lutsenko »

Jimmy, Tom!

I tried to modify the screenshot saving function so that it would cut out some area from the clipboard. But errors are issued. It's not working. In principle, of course, I can specify which window size to use when it is output. But I would like to see them determined automatically. The fact is that they may differ from the set, if there are buttons. Buttons are are other objects than the window, so simultaneously with the window they are difficult to capture (separately from Windows without problems). In addition, the name of the window contains important information that you would not want to lose in the screenshot. In General, while was so-so, slightly better than nothing.

Code: Select all

FUNCTION SaveScreenAsFile(mXSize,mYSize,cFileName) // hand over filename you want to use
LOCAL oClipBoard, oPicture, nResolution := 30

DC_Scrn2Clipboard()
oClipBoard := XbpClipBoard():new():create()
oClipBoard:open()
oPicture := oClipBoard:GetBuffer(XBPCLPBRD_BITMAP)

*IF ::oClipBoard:open()
*  aFormats := ::oClipBoard:queryFormats()
*  IF ASCAN( aFormats, XBPCLPBRD_BITMAP ) > 0
      oBuffer := ::oClipBoard:getBuffer( XBPCLPBRD_BITMAP )
      // cut out part of bitmap  
      oBMP := CutOutBMP( oBuffer, ::aoChild,mXSize,mYSize )
*  ENDIF
*ENDIF

oClipBoard:Close()
oPicture:SaveFile(cFileName,XBPBMP_FORMAT_JPG,nResolution)

RETURN File(cFileName)
******************************************************************************************

FUNCTION CutOutBMP( oBuffer, aoChild,nOutSizeX,nOutSizeY )                      // Jimmy
LOCAL oOutBMP   := XBPBITMAP() :New() :Create()
LOCAL oMain     := GetApplication()
LOCAL oTargetPS := XBPPRESSPACE() :new() :create()
*LOCAL nOutSizeX := SP_BMPxSize()
*LOCAL nOutSizeY := SP_BMPySize()
LOCAL aPos      := { 0, 0 }
LOCAL aSize     := { 0, 0 }
LOCAL aSize1    := { 0, 0 }

   nCYCAPTION   := GetSystemMetrics( SM_CYCAPTION )
   nCXBORDER    := GetSystemMetrics( SM_CXBORDER )
   nCYBORDER    := GetSystemMetrics( SM_CYBORDER )
   nCXDLGFRAME  := GetSystemMetrics( SM_CXDLGFRAME )
   nCYDLGFRAME  := GetSystemMetrics( SM_CYDLGFRAME )
   nCXPADDEDBORDER := GetSystemMetrics( SM_CXPADDEDBORDER )

   // Pos / Size of Windows 
   aPos := aoChild[ CH_LOGO ] :CurrentPos()
   aSize := aoChild[ CH_ANZEIG ] :CurrentSize()             // parent of WMP

   // need to adjust position "inside" frame
   aPos[ 1 ] += 10                                          // oAnzeig
   aPos[ 2 ] += 10

   // reduce bottom Size with statusbar
   aSize1 := aoChild[ CH_STATBAR ] :CurrentSize()
   aPos[ 2 ] += aSize1[ 2 ]

   // adjust Border wide  
   aPos[ 1 ] += SP_CXBORDER()
   aPos[ 2 ] += SP_CYBORDER()

   // adjust Frame wide  
   aPos[ 1 ] += SP_CXDLGFRAME()
   aPos[ 2 ] += SP_CYDLGFRAME()

   // still 1 Pixel missing
   aPos[ 1 ] += 1
   aPos[ 2 ] += 1

   IF OnOSVersion() > 5                                     // Vista-Win7 DWM Aero
      * aPos[1] += SP_CXPADDEDBORDER()                      // Border Padding ? 
      * aPos[2] += SP_CXPADDEDBORDER()
   ENDIF

   * ------------------------------------------------------ *

   oOutBMP:presSpace( oTargetPS )
   oOutBMP:make( nInSizeX, nInSizeY )

   oBuffer:Draw( oTargetPS, ;                               // oTargetPS
                 { 0, 0, nOutSizeX, nOutSizeY }, ;          // aTargetRect
                 { aPos[1], aPos[2], aPos[1] + aSize[1], aPos[2] + aSize[2] }, ; // aSourceRect
                 GRA_BLT_ROP_SRCCOPY, ;                     // nRasterOP GRA_BLT_ROP_*
                 GRA_BLT_BBO_IGNORE )                       // nCompress GRA_BLT_BBO_*

   Sleep( 0 )
   oTargetPS:destroy()
   Sleep( 0 )
   oTargetPS := NIL

RETURN oOutBMP
******************************************************************************************
FUNCTION SP_CYCAPTION( nValue )                             // Caption height
   IF( PCOUNT() > 0, nCYCAPTION := nValue, NIL )
RETURN nCYCAPTION

FUNCTION SP_CXBORDER( nValue )                              // Border wide
   IF( PCOUNT() > 0, nCXBORDER := nValue, NIL )
RETURN nCXBORDER

FUNCTION SP_CYBORDER( nValue )                              // Border height
   IF( PCOUNT() > 0, nCYBORDER := nValue, NIL )
RETURN nCYBORDER

FUNCTION SP_CXDLGFRAME( nValue )                            // Dialog X-Frame
   IF( PCOUNT() > 0, nCXDLGFRAME := nValue, NIL )
RETURN nCXDLGFRAME

FUNCTION SP_CYDLGFRAME( nValue )                            // Dialog Y-Frame
   IF( PCOUNT() > 0, nCYDLGFRAME := nValue, NIL )
RETURN nCYDLGFRAME

FUNCTION SP_CXPADDEDBORDER( nValue )                        // Border Padding
   IF( PCOUNT() > 0, nCXPADDEDBORDER := nValue, NIL )
RETURN nCXPADDEDBORDER

FUNCTION OnOSVersion()
LOCAL cVersion := OS( OS_VERSION )
LOCAL nVersion := 0
LOCAL nPosi
   nPosi := AT( ".", cVersion )
   IF nPosi > 0
      nVersion := VAL( SUBSTR( cVersion, 1, nPosi - 1 ) )
   ENDIF
RETURN nVersion
[/size]

User avatar
Eugene Lutsenko
Posts: 1649
Joined: Sat Feb 04, 2012 2:23 am
Location: Russia, Southern federal district, city of Krasnodar
Contact:

Re: Saving screenshots of open Windows with graphic files

#43 Post by Eugene Lutsenko »

probably it is necessary to throw this idea and to use the recommendation of Bobby

User avatar
Eugene Lutsenko
Posts: 1649
Joined: Sat Feb 04, 2012 2:23 am
Location: Russia, Southern federal district, city of Krasnodar
Contact:

Re: Saving screenshots of open Windows with graphic files

#44 Post by Eugene Lutsenko »

Jimmy!

Could you show how the function Print_Window() to modify so that it recorded the file with the specified name
Auge_Ohr wrote:hi, Tom
Tom wrote:DC_Scrn2ClipBoard() without any parameter saves the SetAppWindow() to the clipboard.
does DC_Scrn2ClipBoard() without Parameter still work under Windows 10 ?

it use keybd_event()

Code: Select all

DLLFUNCTION keybd_event(mvkey, nscan, flags, xtra) USING STDCALL FROM USER32.DLL
which is IMHO deprecated.
as i know Keyboard and Mouse now use SendInput() API function

Code: Select all

FUNCTION Print_Window( nWindow )
LOCAL oInput := INPUT() :New()                                  // ot4xb Structure
LOCAL nSize  := oInput:_sizeof_()
LOCAL nRet   := 0

   nWindow := IIF( EMPTY( nWindow ), 0, 1 )                 // 0 is entire screen, 1 is active window
   sleep( 10 )

   // deprecated, does not work under Windows 10
   // keybd_Event( VK_SNAPSHOT,nWindow,0,0)

   oInput:type := INPUT_KEYBOARD
   oInput:ki:wVk := VK_SNAPSHOT
   oInput:ki:wScan := nWindow
   oInput:ki:dwFlags := 0
   oInput:ki:dwExtraInfo := 0
   // now use SendInput API Function
   nRet := @user32:SendInput( 1, oInput, nSize )

RETURN nRet

User avatar
Eugene Lutsenko
Posts: 1649
Joined: Sat Feb 04, 2012 2:23 am
Location: Russia, Southern federal district, city of Krasnodar
Contact:

Re: Saving screenshots of open Windows with graphic files

#45 Post by Eugene Lutsenko »

Jimmy!

_AIDOS-X.obj: error ALK2102: unresolved external symbol INPUT

Code: Select all

LOCAL oInput := INPUT():New()                               // ot4xb Structure

Code: Select all

FUNCTION Print_Window( nWindow, cFileName )
*LOCAL oInput := INPUT():New()                               // ot4xb Structure
LOCAL nSize  := oInput:_sizeof_()
LOCAL nRet   := 0

   nWindow := IIF( EMPTY( nWindow ), 0, 1 )                 // 0 is entire screen, 1 is active window
   sleep( 10 )

   // deprecated, does not work under Windows 10
   keybd_Event( VK_SNAPSHOT,nWindow,0,0)

   oInput:type := INPUT_KEYBOARD
   oInput:ki:wVk := VK_SNAPSHOT
   oInput:ki:wScan := nWindow
   oInput:ki:dwFlags := 0
   oInput:ki:dwExtraInfo := 0

   // now use SendInput API Function
*  nRet := @user32:SendInput( 1, oInput, nSize )

   oInput:SaveFile(cFileName,XBPBMP_FORMAT_JPG,600)
   oInput:Close()

RETURN nRet
[/size]

User avatar
Auge_Ohr
Posts: 1405
Joined: Wed Feb 24, 2010 3:44 pm

Re: Saving screenshots of open Windows with graphic files

#46 Post by Auge_Ohr »

as comment say it need ot4xb while it is a Windows Structure
https://msdn.microsoft.com/de-de/librar ... s.85).aspx

neverless your modification is wrong ... there is nothing to o:SaveFile() :naughty:
as i say that Code just to send Keyboard Event "Print-Screen" / "Alt Print-Screen"

Code: Select all

   nRet := @user32:SendInput( 1, oInput, oInput:_sizeof_() )
instead of deprecated Keyboard_Event() / Mouse_Event()
https://msdn.microsoft.com/de-de/librar ... s.85).aspx
https://msdn.microsoft.com/de-de/librar ... s.85).aspx

---

you are working on wrong end ... :naughty:
you have to work on Function CutOutBMP( oBuffer, aoChild )

aoChild is, while 1st Letter is "a", a Array of Child Object so reduce it to single oChild
as you want hole Windows you do not have to care about Frame ( all SP_CX* Function() )

you just have to open Clipboard and figure out how oBuffer:Draw() give that part that you want.
this is what you have

Code: Select all

Function CutOutBMP( oBuffer, oChild )
LOCAL aPos := oChild:CurrentPos() 
LOCAL aSize := oChild:CurrentSize()
LOCAL aDesk := AppDeskTop():CurrentSize()    // hole Desktop with Print-Screen

   oBuffer:draw( [<oTargetPS>]  , ; 
       <aTargetRect>  , ; 
       [<aSourceRect>], ; 
       [<nRasterOP>]  , ; 
       [<nCompress>]  , ; 
       [<nState>] )  --> lSuccess 
greetings by OHR
Jimmy


Post Reply