Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

screen capture

Status
Not open for further replies.

tokool

Programmer
Nov 6, 2001
40
US
Hi,
I am tryin to capture the screen bitmap of an application(like calc.exe) that i opened in my program using ShellExecute().
I am able to capture the entire screen using, HWND hClientWin = GetDesktopWindow() and then getting the DC from which i bitblt the contents.
How can i do this for only for a single window in the sceen, the window that the application i opened in my program generates.
Is there any other way i can open an application from my program and capture its screen bitmap.
Thanks,
Preetham
 
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#define NAME_OF_PROG &quot;Calculator Mirror.&quot;
#define BLT_TIMER 1
#define WIN_X 260
#define WIN_Y 235
#define WINPOS_X 20
#define WINPOS_Y 90

HWND hMainWin = NULL;
HINSTANCE hInstance= NULL;

LRESULT CALLBACK WindowProc( HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam );

bool Get_Calc_Client( HWND hMain );

int WINAPI WinMain( HINSTANCE hinstance,
HINSTANCE hprevinstance,
LPSTR lpcmdline,
int ncmdshow)
{
HWND hwnd;
MSG msg;
WNDCLASSEX winclass;

winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS | CS_OWNDC |
CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground= (HBRUSH) GetStockObject(WHITE_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName= &quot;WIN_SHELL&quot;;
winclass.hIconSm = NULL;

if( !RegisterClassEx( &winclass ) ) return FALSE;

if(!( hwnd= CreateWindow(&quot;WIN_SHELL&quot;,
NAME_OF_PROG,
WS_VISIBLE | WS_OVERLAPPEDWINDOW,
WINPOS_X,WINPOS_Y,
WIN_X,WIN_Y,
NULL,NULL,
hinstance,NULL)))

return FALSE;

hMainWin= hwnd;

while ( true )
{
if( PeekMessage( &msg,NULL,0,0,PM_REMOVE ) )
{
if( msg.message == WM_QUIT ) break;

TranslateMessage( &msg );
DispatchMessage ( &msg );
}

}

return ( msg.wParam );

}


LRESULT CALLBACK WindowProc( HWND hWnd,
UINT mSg,
WPARAM wParam,
LPARAM lParam )
{
PAINTSTRUCT ps;
HDC hdc;

switch ( mSg )
{
case WM_CREATE:

if ( !Get_Calc_Client( hWnd ) )
MessageBox( hWnd,&quot;Calc. is not opened.&quot;,NAME_OF_PROG,MB_OK );

SetTimer( hWnd,BLT_TIMER,500,NULL );

return 0;

case WM_PAINT:

hdc= BeginPaint( hWnd,&ps);
EndPaint( hWnd,&ps );

return 0;

case WM_DESTROY:

KillTimer( hWnd,BLT_TIMER );
PostQuitMessage( 0 );

return 0;

case WM_KEYDOWN:

Get_Calc_Client( hWnd );

return 0;

case WM_TIMER:

Get_Calc_Client( hWnd );

return 0;

default:
break;

}


return ( DefWindowProc( hWnd, mSg, wParam, lParam ) );
}

bool Get_Calc_Client( HWND hMain )
{
HWND hCalc;
HDC mainDC;
HDC calcDC;
RECT calcRect;

hCalc= FindWindowEx( NULL,NULL,&quot;SciCalc&quot;,&quot;Calculator&quot; );

if ( !hCalc ) return false;

mainDC= GetDC( hMain );
calcDC= GetDC( hCalc );

GetClientRect( hCalc,&calcRect );

if( !BitBlt( mainDC,
calcRect.top,
calcRect.left,
calcRect.right,
calcRect.bottom,
calcDC,0,0,SRCCOPY ) )

MessageBox( hMain,&quot;Calc. Blt failed.&quot;,NAME_OF_PROG,MB_OK );

ReleaseDC( hMain,mainDC );
ReleaseDC( hCalc,calcDC );

return true;
}


The above code uses the raw api to create a simple window. A few more api calls are made to retrieve the HWND of the calc. This HWND is used to capture the image of the calculators client area so that we may bitblt() the contents of it onto our own programs client area. I implemented a timer so that the image would be refreshed every half second.



Mike L.G.
mlg400@blazemail.com
 
thanx mike, but i want to get the class name &quot;SciCalc&quot; for calc thru the program. I dont want it hard coded.
I want my program to open the &quot;calc.exe&quot; executable and pick up the class name, this because i want to make it generic to any application, not just calc...probably even explorer.exe and even mocrosoft word.
Calculator is just an example, i want to open any win executable and pick the screen contents.
 
win32 api call to ->

int GetClassName( HWND hWnd,
LPTSTR lpClassName,
int nMaxCount
);

Mike L.G.
mlg400@blazemail.com
 
Using ShellExecute() to fire up a prog./file is by far the easiest way to accomplish such a task, but by using ShellExecuteEx(), you are not only able to start up a program, but are also able to retrieve it's HWND through the LPSHELLEXECUTEINFO structure. This is the functions only argument. Once you have the programs handle, you can then bitblt() it's client area onto your own programs client area. Because you already have the windows HWND, there is no need to retrieve it's class name. Mike L.G.
mlg400@blazemail.com
 
mike,
i have been using the below program..
void main()
{
//Run the program
SHELLEXECUTEINFO lpExecInfo;
lpExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
lpExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
lpExecInfo.hwnd = NULL;
lpExecInfo.lpVerb = &quot;open&quot;;
lpExecInfo.lpFile = &quot;calc.exe&quot;;
lpExecInfo.lpParameters = NULL;
lpExecInfo.lpDirectory = NULL;
lpExecInfo.nShow = SW_SHOW;
lpExecInfo.lpClass = NULL;
lpExecInfo.hInstApp = NULL;
lpExecInfo.lpIDList = NULL;

BOOL ecPrg = ShellExecuteEx(&lpExecInfo);

cout << lpExecInfo.hwnd << endl;
}

However, after the shellexecuteex fn executes, the value of lpExecInfo.hwnd is still pointing to NULL.
 
the hwnd in the SHELLEXECUTEINFO function points to the window that opend the program, i dont think it points to the window of the opened program.
 
It appears that you are correct on this tokool. I have made an error. You can always retrieve the HWND of the program with FindWindowEx() or FindWindow(). Mike L.G.
mlg400@blazemail.com
 
Mike, i am having a problem sending messages to the application. In the code u sent me, i create a mirror of Calc.exe, and when any key event occurs over the mirror, i send it to the application. But it does not show at the application.
I am using the below function to send a message to the main app. I call this when i receive a WM_KEYUP message from the mirror window.
BOOL sendTheMessage(UINT mSg, WPARAM wParam, LPARAM lParam)
{
HWND hCalc= FindWindowEx( NULL,NULL,&quot;SciCalc&quot;,&quot;Calculator&quot; );
BOOL bm = PostMessage(hCalc, mSg, wParam, lParam);
return bm;
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top