Grabowanie okna innej aplikacji

Odpowiedz Nowy wątek
2006-11-16 17:58
Turtles.zolwiu
0

Witam. Od jakiegoś czasu piszę aplikację, która sprawdza procesy użytkownika, wypluwa okienko z jego wyborem. Następnie użytkownik powinien otrzymać screenshota tego wybranego okienka. Kod jest połączeniem WINAPI oraz wxWidget'sów.
Poniżej zamieszczam poszczególne pliki źródłowe i nagłówkowe, zaraz wyjaśnię w czym problem.
//clippingwindow.h
// clippingwindow.h
#ifndef CLIPPINGWINDOW_H
#define CLIPPINGWINDOW_H

#include "wx/wx.h"
#include <vector>

class MyApp: public wxApp {
virtual bool OnInit();
};

class MyFrame: public wxFrame {
wxButton sh_button;
wxPanel
myPanel;
//wxFlexGridSizer ssizer;
wxBitmap
screenshot;

void CaptureWindow( HWND hwnd );

const int showWindowChoiceDlg(const std::vector<wxstring>& pTitles, const std::vector<wxstring>& pClassNames);
public:

MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);

void OnQuit( wxCommandEvent& event );

void OnPaint(wxPaintEvent& event);
void ToDoScreenshot( wxCommandEvent& event );

DECLARE_EVENT_TABLE()

enum
{
ID_Quit = 11000,
ID_Screenshot
};

};

#endif //CLIPPINGWINDOW_H

// clippingwindow.cpp : Defines the entry point for the console application.
#include "clippingwindow.h"
#include <wx/image.h>

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_Quit, MyFrame::OnQuit)
EVT_BUTTON(ID_Screenshot, MyFrame::ToDoScreenshot)
EVT_PAINT(MyFrame::OnPaint)
END_EVENT_TABLE()

IMPLEMENT_APP(MyApp)

#include "stdafx.h"
#include "EnumProc.h"

#define tpf _tprintf

inline bool isswitch(TCHAR c) { return c==L'/' || c==L'-'; }

bool MyApp::OnInit()
{
MyFrame *frame = new MyFrame( wxT("clippingwindow"), wxPoint(50,50), wxSize(450,340) );
frame->Show(TRUE);
SetTopWindow(frame);
return TRUE;
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame((wxFrame )NULL, -1, title, pos, size), screenshot(NULL)
{
wxMenu
menuFile = new wxMenu;
menuFile->Append( ID_Quit, "E&xit" );

wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append( menuFile, "&File" );

SetMenuBar( menuBar );

CreateStatusBar();
SetStatusText( wxT("Welcome to clippingwindow!") );

myPanel = new wxPanel(this);
//ssizer = new wxFlexGridSizer(2);
sh_button = new wxButton(myPanel, ID_Screenshot, _("Screenshot") );
//ssizer->Add(sh_button);

}

void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
Close(TRUE);
}
void MyFrame::ToDoScreenshot( wxCommandEvent& event ) {

std::vector<hwnd> hvec;
std::vector<wxstring> tvec;
std::vector<wxstring> cvec;

int count=0;
BOOL bFirstModule = TRUE;
CProcessIterator itp;
for (DWORD pid=itp.First(); pid; pid=itp.Next()) {
    // Note: first module in CProcessModuleIterator is EXE for this process
    //
    TCHAR modname[_MAX_PATH];
    CProcessModuleIterator itm(pid);
    HMODULE hModule = itm.First(); // .EXE
    if (hModule) {
        GetModuleBaseName(itm.GetProcessHandle(),
            hModule, modname, _MAX_PATH);

        // Iterate over all top-level windows in process
        //
        BOOL bFirstWindow = TRUE;
        CMainWindowIterator itw(pid);
        for (HWND hwnd = itw.First(); hwnd; hwnd=itw.Next()) {
            if (bFirstModule) {
                bFirstModule = FALSE;
            }
            if (bFirstWindow) {
                bFirstWindow = FALSE;
    }
            char classname[256],title[256];
            GetClassName(hwnd,classname,sizeof(classname));
            GetWindowText(hwnd,title,sizeof(title));
    hvec.push_back( hwnd );
    tvec.push_back( wxString( title ) );
    cvec.push_back( wxString( classname ) );

        }
        bFirstWindow || count++;

    }

}

//tu okno wyboru
wxASSERT( hvec.size() == tvec.size() );
wxASSERT( tvec.size() == cvec.size() );
const int index = showWindowChoiceDlg(tvec, cvec);
if( index == -1 ) {
// select cancel in dialog window
return;
}

if( hvec[index] == NULL ) {
wxMessageBox(("Handle to aplication is empty"), ("Warning"), wxICON_WARNING, this);
}

CaptureWindow( hvec[index] );
//--------------------
// Show new modal dialog window with tree or list proces, select one of.., and MyFrame::CaptureWindow( HWND hwnd );

/wxMessageBox( wxT("MyFrame::ToDoScreenshot"),
wxT("Make screenshot"), wxOK | wxICON_INFORMATION, this);
/

}

const int
MyFrame::showWindowChoiceDlg(const std::vector<wxstring>& pTitles, const std::vector<wxstring>& pClassNames) {
wxASSERT(pTitles.size() == pClassNames.size());

// [PL] Tworzymy liste wyboru

wxArrayString lst;
int i=0;
for (std::vector<wxstring>::const_iterator it = pTitles.begin(); it != pTitles.end(); it++) {
const wxString tLabel = *it + wxT(" [") + pClassNames[i] + wxT("]");
++i;
lst.Add(tLabel);
}

if (i==0) {
wxMessageBox(("List is empty"), ("Warning"), wxICON_WARNING, this);
return -1;
}

wxSingleChoiceDialog tDlg(this, ("Select capture window"), ("Select capture window2"), lst);
if (tDlg.ShowModal() == wxID_OK) {
return tDlg.GetSelection();
}

return -1;
}; // showWindowChoiceDlg

void MyFrame::OnPaint(wxPaintEvent& event) {
if (screenshot != NULL) {

    wxPaintDC dc( myPanel );
    //dc.DrawBitmap( *screenshot, 0, 0, true /* use mask */ );

}

event.Skip();

}

void MyFrame::CaptureWindow( HWND hwnd ) {/ wskaniki nie sa puste - ale program poprawnie grabuje tylko siebie/
//------------------

//test
/ SetCapture( hwnd );/

  • ShowWindow(hwnd, SW_HIDE); * hide and show == activate window
    // ShowWindow(hwnd, SW_SHOW);
  • *SetActiveWindow( hwnd );
    //
    ////Create a DC for the whole screen area
    // wxImage::AddHandler(new wxBMPHandler);
    //
    //
  • /wxWindowDC/ wxScreenDC dcWindow;(/ wxWindow aktywny/ );
  • *wxWindowDC dcWindow( );
  • *Get the size of the screen/DC
    // wxCoord screenWidth, screenHeight;
    // dcWindow.GetSize(&screenWidth, &screenHeight);
    //
    // wxBitmap screenshot(screenWidth, screenHeight,-1);
    //
    // wxMemoryDC memDC;
    //
    // memDC.SelectObject(screenshot);
    //
    // memDC.Blit( 0, 0,
    // screenWidth, screenHeight,&dcWindow,
    // 0, 0 );
    //
    // memDC.SelectObject(wxNullBitmap);
    //
    // screenshot.SaveFile("screenshot.bmp",wxBITMAP_TYPE_BMP);
    //

//-----------------
ShowWindow(hwnd, SW_HIDE); // hide and show == activate window
ShowWindow(hwnd, SW_SHOW);
!hwnd = SetActiveWindow( hwnd );it's safe - always window from this instance ?
!hwnd = GetActiveWindow();- always window from this instance ?
!hwnd = GetTopWindow( hwnd ); handle of parent window,

// Ten kod działa dla bierzącej applikacji, inaczej kopiuje czarną bitmapę
//Jak będzie działać ok to przeniosę btmapę do okna w wxwidgetsach
HDC hDCMem = CreateCompatibleDC(NULL); handle to memory device context ! hDC - no effect!

RECT rect;
GetWindowRect(hwnd, & rect);

HBITMAP hBmp = NULL;

{
    HDC hDC = GetDC(hwnd);
    //HDC hDC =GetWindowDC(hwnd);
    hBmp = CreateCompatibleBitmap(hDC, rect.right - rect.left, rect.bottom - rect.top);
    ReleaseDC(hwnd, hDC);
}

// sprobuj zapisac bez schowka
HGDIOBJ hOld = SelectObject(hDCMem, hBmp);
SendMessage(hwnd, WM_PRINT, (WPARAM) hDCMem, PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED);

SelectObject(hDCMem, hOld);
DeleteObject(hDCMem);

OpenClipboard(hwnd);

EmptyClipboard(); 
SetClipboardData(CF_BITMAP, hBmp);
CloseClipboard();

//---------------

// Paste from clipboard to wxBitmap and show
//wxImage::AddHandler(new wxBMPHandler);

  /* wxStaticBitmap aa(myPanel, wxID_ANY, screenshot);
   ssizer->Add(&aa, wxEXPAND );*/

/
//
// screenshot = new wxBitmap(screenWidth, screenHeight,-1);
//
// BITMAP bm;
//GetObject ( hBmp, sizeof(bm), &bm );
// wxBitmap screenshot;
// if(screenshot.Create( (void
) &bm, wxBITMAP_TYPE_BMP, rect.right - rect.left, rect.bottom - rect.top) ) {
// screenshot.SaveFile("screenshot.bmp",wxBITMAP_TYPEBMP);
// wxMessageBox(
("Save picture"), _("Warning"), wxICON_WARNING, this);
// }

*/
}

////////////////////////////////////////////////////////////////
// MSDN Magazine -- July 2002
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual Studio 6.0 and Visual Studio .NET
// Runs in Windows XP and probably Windows 2000 too.
//
#pragma once

//////////////////
// Iterate the top-level windows. Encapsulates ::EnumWindows.
//
class CWindowIterator {
protected:
HWND* m_hwnds; // array of hwnds for this PID
DWORD m_nAlloc; // size of array
DWORD m_count; // number of HWNDs found
DWORD m_current; // current HWND
static BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lp);

// virtual enumerator
virtual BOOL OnEnumProc(HWND hwnd);

// override to filter different kinds of windows
virtual BOOL OnWindow(HWND hwnd) {
    return TRUE;
}

public:
CWindowIterator(DWORD nAlloc=1024);
~CWindowIterator();

DWORD GetCount() { return m_count; }
HWND First();
HWND Next() {
    return m_hwnds && m_current < m_count ? m_hwnds[m_current++] : NULL;
}

};

//////////////////
// Iterate the top-level windows in a process.
//
class CMainWindowIterator : public CWindowIterator {
protected:
DWORD m_pid; // process id
virtual BOOL OnWindow(HWND hwnd);
public:
CMainWindowIterator(DWORD pid, DWORD nAlloc=1024);
~CMainWindowIterator();
};

//////////////////
// Process iterator -- iterator over all system processes
// Always skips the first (IDLE) process with PID=0.
//
class CProcessIterator {
protected:
DWORD* m_pids; // array of procssor IDs
DWORD m_count; // size of array
DWORD m_current; // next array item
public:
CProcessIterator();
~CProcessIterator();

DWORD GetCount() { return m_count; }
DWORD First();
DWORD Next() {
    return m_pids && m_current < m_count ? m_pids[m_current++] : 0;
}

};

//////////////////
// Iterate the modules in a process. Note that the first module is the
// main EXE that started the process.
//
class CProcessModuleIterator {
protected:
HANDLE m_hProcess; // process handle
HMODULE* m_hModules; // array of module handles
DWORD m_count; // size of array
DWORD m_current; // next module handle
public:
CProcessModuleIterator(DWORD pid);
~CProcessModuleIterator();

HANDLE GetProcessHandle()   { return m_hProcess; }
DWORD GetCount()                { return m_count; }
HMODULE First();
HMODULE Next() {
    return m_hProcess && m_current < m_count ? m_hModules[m_current++] : 0;
}

};

////////////////////////////////////////////////////////////////
// MSDN Magazine -- July 2002
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual Studio 6.0 and Visual Studio .NET
// Runs in Windows XP and probably Windows 2000 too.
//
#include "stdafx.h"
#include "EnumProc.h"

CWindowIterator::CWindowIterator(DWORD nAlloc)
{
assert(nAlloc>0);
m_current = m_count = 0;
m_hwnds = new HWND [nAlloc];
m_nAlloc = nAlloc;
}

CWindowIterator::~CWindowIterator()
{
delete [] m_hwnds;
}

//////////////////
// Move to first top-level window.
// Stuff entire array and return the first HWND.
//
HWND CWindowIterator::First()
{
::EnumWindows(EnumProc, (LPARAM)this);
m_current = 0;
return Next();
}

//////////////////
// Static enumerator passes to virtual fn.
//
BOOL CALLBACK CWindowIterator::EnumProc(HWND hwnd, LPARAM lp)
{
return ((CWindowIterator*)lp)->OnEnumProc(hwnd);
}

//////////////////
// Virtual enumerator proc: add HWND to array if OnWindow is TRUE.
//
BOOL CWindowIterator::OnEnumProc(HWND hwnd)
{
if (OnWindow(hwnd)) {
if (m_count < m_nAlloc)
m_hwnds[m_count++] = hwnd;
}
return TRUE; // keep looking
}

//////////////////
// Main window iterator: special case to iterate main windows of a process.
//
CMainWindowIterator::CMainWindowIterator(DWORD pid, DWORD nAlloc)
: CWindowIterator(nAlloc)
{
m_pid = pid;
}

CMainWindowIterator::~CMainWindowIterator()
{
}

//////////////////
// virtual override: is this window a main window of my process?
//
BOOL CMainWindowIterator::OnWindow(HWND hwnd)
{
if (GetWindowLong(hwnd,GWL_STYLE) & WS_VISIBLE) {
DWORD pidwin;
GetWindowThreadProcessId(hwnd, &pidwin);
if (pidwin==m_pid)
return TRUE;
}
return FALSE;
}

CProcessIterator::CProcessIterator()
{
m_pids = NULL;
}

CProcessIterator::~CProcessIterator()
{
delete [] m_pids;
}

//////////////////
// Get first process.
// Call EnumProcesses to initialize entire array, then return first one.
//
DWORD CProcessIterator::First()
{
m_current = (DWORD)-1;
m_count = 0;
DWORD nalloc = 1024;
do {
delete [] m_pids;
m_pids = new DWORD [nalloc];
if (EnumProcesses(m_pids, nalloc*sizeof(DWORD), &m_count)) {
m_count /= sizeof(DWORD);
m_current = 1; // important: skip IDLE process with pid=0.
}
} while (nalloc <= m_count);

return Next();

}

CProcessModuleIterator::CProcessModuleIterator(DWORD pid)
{
// open the process
m_hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, pid);
}

CProcessModuleIterator::~CProcessModuleIterator()
{
CloseHandle(m_hProcess);
delete [] m_hModules;
}

//////////////////
// Get first module in process. Call EnumProcesseModules to
// initialize entire array, then return first module.
//
HMODULE CProcessModuleIterator::First()
{
m_count = 0;
m_current = (DWORD)-1;
m_hModules = NULL;
if (m_hProcess) {
DWORD nalloc = 1024;
do {
delete [] m_hModules;
m_hModules = new HMODULE [nalloc];
if (EnumProcessModules(m_hProcess, m_hModules,
nalloc*sizeof(DWORD), &m_count)) {
m_count /= sizeof(HMODULE);
m_current = 0;
}
} while (nalloc <= m_count);
}
return Next();
}

A tak wygląda sampel dla przeglądania procesóww winapi:
////////////////////////////////////////////////////////////////
// MSDN Magazine -- July 2002
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual Studio 6.0 and Visual Studio .NET
// Runs in Windows XP and probably Windows 2000 too.
//
// lp -- list processes from command line.
// Illustrates how to use the various iterator classes in EnunmProc.h/cpp
//
#include "stdafx.h"
#include "EnumProc.h"

#define tpf _tprintf // to hide ugly underbars

// pre-declare functions
void help();

// global switches
BOOL bClassName=FALSE; // show window classname
BOOL bTitle=FALSE; // show window title
BOOL bBare=FALSE; // no header

// check for switch: / or -
inline BOOL isswitch(TCHAR c) { return c==L'/' || c==L'-'; }

//////////////////
// Main entry point
//
int main(int argc, TCHAR argv[], TCHAR envp[])
{
// Parse command line. Switches can come in any order.
//
for (int i=1; i<argc; i++) {
if (isswitch(argv[i][0])) {
for (UINT j=1; j<_tcslen(argv[i]); j++) {
switch(tolower(argv[i][j])) {
case 'c':
bClassName=TRUE;
break;
case 't':
bTitle=TRUE;
break;
case 'b':
bBare=TRUE;
break;
case '?':
default:
help();
return 0;
}
}
} else {
help();
return 0;
}
}

// Iterate over all processes
//
int count=0;
BOOL bFirstModule = TRUE;
CProcessIterator itp;
for (DWORD pid=itp.First(); pid; pid=itp.Next()) {
    // Note: first module in CProcessModuleIterator is EXE for this process
    //
    TCHAR modname[_MAX_PATH];
    CProcessModuleIterator itm(pid);
    HMODULE hModule = itm.First(); // .EXE
    if (hModule) {
        GetModuleBaseName(itm.GetProcessHandle(),
            hModule, modname, _MAX_PATH);

        // Iterate over all top-level windows in process
        //
        BOOL bFirstWindow = TRUE;
        CMainWindowIterator itw(pid);
        for (HWND hwnd = itw.First(); hwnd; hwnd=itw.Next()) {
            if (bFirstModule) {
                if (!bBare) {
                    tpf(_T("PID  %-13s%-8s %s%s%s\n"),_T("Module"),_T("HWND"),
                        bClassName ? _T("class name") : _T(""),
                        bClassName && bTitle ? _T("/") : _T(""),
                        bTitle ? _T("title") : _T(""));
                    tpf(_T("---- ------------ -------- ----------------\n"));
                }
                bFirstModule = FALSE;
            }
            if (bFirstWindow) {
                tpf(_T("%04x %-13s"), pid, modname);
                bFirstWindow = FALSE;
            } else {
                tpf(_T("%18s"),_T(" "));
            }
            char classname[256],title[256];
            GetClassName(hwnd,classname,sizeof(classname));
            GetWindowText(hwnd,title,sizeof(title));
            tpf(_T("%08x %s %s\n"), hwnd,
                bClassName ? classname : _T(""),
                bTitle ? title : _T(""));
        }
        bFirstWindow || count++;
    }
}
if (!bBare) {
    tpf(_T("----\n"));
    tpf(_T("%d processes found.\n"),count);
}
return 0;

}

void help()
{
tpf(_T("lp: List top-level proceses.\n"));
tpf(_T(" Copyright 2002 Paul DiLascia.\n\n"));
tpf(_T("Format: lp [/bct?]\n\n"));
tpf(_T("Options:\n"));
tpf(_T(" /b(are) no header\n"));
tpf(_T(" /c(lass) show window class names\n"));
tpf(_T(" /t(itle) show window titles\n"));
tpf(_T("\n"));
}

// Jeszcze standardoweplikidodawane do projektów windy:
#define VC_EXTRALEAN // Exclude rarely-used stuff from headers
#include <windows.h>
#include <stdio.h>
#include <conio.h> // getche
#include <tchar.h>
#include <psapi.h> // PSAPI for EnumProcesses
#include <string.h>
#include <assert.h>
#pragma warning(disable:4786) // disable annoying C4786
#include <string> // STL string class
#include <list> // STL list class
using namespace std; // use STL

//oraz

#include "stdafx.h"

//---
Każda metoda która pozwala na zgrabowanie okienka z innego programu jest dla mnie dobra.Walczę ztym odkilkudnia jest to priorytetowe zadanie. Biblioteki mam raczej narzucone, ewentualnie mogę uzywać jakiechś bezpłatnych.

Będę wdzięczny za wszelkie rzeczowe uwagi.

Pozostało 580 znaków

2006-11-16 18:08
0

No chyba przesadziłeś w BCB :


void __fastcall TForm1::Button1Click(TObject *Sender)
{
   HWND BCBHandle = FindWindow("NazwaOkna", NULL);

   if (BCBHandle)
   {
      HDC dc = GetWindowDC(BCBHandle);
      Graphics::TCanvas *ScreenCanvas = new Graphics::TCanvas;
      Graphics::TBitmap *BMP = new Graphics::TBitmap;
      ScreenCanvas->Handle = dc;

      TRect rect = ScreenCanvas->ClipRect;
      rect.Right = rect.Right - rect.Left;
      rect.Bottom = rect.Bottom - rect.Top;
      rect.Top = rect.Left = 0;

      BMP->Width = rect.Right;
      BMP->Height= rect.Bottom;
      BMP->Canvas->CopyRect(rect, ScreenCanvas, ScreenCanvas->ClipRect);

      BMP->SaveToFile("c:\\zrzut.bmp");

      delete ScreenCanvas;
      delete BMP;
      ReleaseDC(BCBHandle, dc);
   }
}

A jak nie pasuje BCB to zrób przekład na API WIN .
Zapewniam że nie jest to wielki problem .


Pozostało 580 znaków

2006-11-17 12:48
0

Na WINAPI będzie to tak: znaleźć kontekst okna (FindWindow, GetWindowDC tak jak dzejo pokazał) i za pomocą BitBlt przenieść jego zawartość na inny kontekst, np kontekst utworzonej przez ciebie bitmapy, którą chcesz zapisać do pliku, albo kontekst okna twojego programu w którym screen ma być pokazany.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0