PDA

View Full Version : Cant get Screenshot of Desktop right as Widget-Background



gerdb
19th February 2015, 00:19
Hi,

i tried to get the desktop as screenshot and then display exactly the part of it which my widget/window overlaps in the widget's background.

i work on a pc with 2 monitors and get different result ( both are broken ) for each

Left Monitor (primary):

- Image gets distorted on Window resize
- Image contains the widget itself, and i dont know how to hide it during screenshoting the desktop

i tried hide, get screenshot, show with setUpdateEnabled false and true again, but some events still are fired -> infinite loop, bad crash

Right Monitor:

- cant copy part of Screenshot, it is always the full screenshot as widget-background

So my most important questions will be:

1. How do i hide and show widget without getting floods of event, signals
2. How do i get the QScreen object from the widget position
3. What are your opinions/suggestions

TransparentPanel.h



#include <QWidget>
#include <QPixmap>

// ================================================== ==========================
/// @class TransparentPanel
// ================================================== ==========================

class TransparentPanel : public QWidget
{
Q_OBJECT
public:
private:
QPixmap mBG;

public:
///@brief Constructor
explicit TransparentPanel( QWidget* parent = 0 );

///@brief Destructor
~TransparentPanel();

void updateBG();

protected:
virtual void paintEvent( QPaintEvent* event ) override;
virtual void resizeEvent(QResizeEvent* event) override;
virtual void moveEvent( QMoveEvent* event) override;
// virtual void enterEvent( QEvent* event ) override;
// virtual void leaveEvent( QEvent* event ) override;
// virtual void mousePressEvent ( QMouseEvent* event );
// virtual void mouseReleaseEvent ( QMouseEvent* event );

};



TransparentPanel.cpp



#include "TransparentPanel.h"

#ifndef VERBOSE
#define VERBOSE 1
#endif

#include <QPainter>
#include <QMouseEvent>
#include <QApplication>
#include <QDesktopWidget>
#include <QScreen>
#include <QDebug>

// ================================================== ==========================
TransparentPanel::TransparentPanel( QWidget* parent )
: QWidget(parent)
// ================================================== ==========================
{
setMinimumSize(10,10);
setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);
setAutoFillBackground( false );
//setAttribute( Qt::WA_OpaquePaintEvent );
setAttribute( Qt::WA_NoSystemBackground );
//setAttribute( Qt::WA_TranslucentBackground );
setUpdatesEnabled( true );

//MMDebug("TransparentPanel::TransparentPanel()\n")
//MMDebug("QApplication::desktop()->winId() = %x\n", (void*)QApplication::desktop()->winId() )
//MMDebug("GetDesktopWindow() = %x\n", (void*)GetDesktopWindow() )
updateBG();
}

// ================================================== ==========================
TransparentPanel::~TransparentPanel()
// ================================================== ==========================
{
//MMDebug("TransparentPanel::~TransparentPanel()\n")
}

// ================================================== ==========================
void TransparentPanel::paintEvent( QPaintEvent* event )
// ================================================== ==========================
{
if (!isVisible())
return;

//MMDebug("TransparentPanel::paintEvent()\n")

QPainter dc(this);
dc.setRenderHint( QPainter::NonCosmeticDefaultPen );

//dc.fillRect( rect(), Qt::white);
if (!mBG.isNull())
{
dc.drawPixmap( rect(), mBG);
}

QWidget::paintEvent(event);
}

// ================================================== ==========================
void TransparentPanel :: resizeEvent(QResizeEvent* event)
// ================================================== ==========================
{
//MMDebug("TransparentPanel::resizeEvent()\n")
updateBG();
//QWidget::resizeEvent(event);
}

// ================================================== ==========================
void TransparentPanel::moveEvent( QMoveEvent* event)
// ================================================== ==========================
{
//MMDebug("TransparentPanel::moveEvent()\n")
updateBG();
//QWidget::moveEvent(event);
}

//// ================================================== ==========================
//void TransparentPanel::enterEvent( QEvent* event )
//// ================================================== ==========================
//{
// QWidget::enterEvent(event);
//}

//// ================================================== ==========================
//void TransparentPanel::leaveEvent( QEvent* event )
//// ================================================== ==========================
//{
// QWidget::leaveEvent(event);
//}

//// ================================================== ==========================
//void TransparentPanel :: mousePressEvent ( QMouseEvent* event )
//// ================================================== ==========================
//{
// QWidget::mousePressEvent( event );
//}

//// ================================================== ==========================
//void TransparentPanel :: mouseReleaseEvent ( QMouseEvent* event )
//// ================================================== ==========================
//{
// QWidget::mouseReleaseEvent( event );
//}


// ================================================== ==========================
void TransparentPanel::updateBG()
// ================================================== ==========================
{
// if (!isVisible())
// return;

//// setVisible(false);
// mBG = QPixmap(); // clear image for low memory situations on weak devices.
// QPoint screenTopLeft = mapToGlobal( geometry().topLeft() );
// int x = screenTopLeft.x();
// int y = screenTopLeft.y();
// int w = width();
// int h = height();
// //mBG = QPixmap::grabWindow(QApplication::desktop()->winId(), x,y, w,h );

// //QScreen* screen = QApplication::screens()->primaryScreen();
// QScreen* screen = QApplication::primaryScreen();
// if (screen)
// //mBG = screen->grabWindow(QApplication::desktop()->window()->winId(), x,y, w,h );
// mBG = screen->grabWindow((WId)GetDesktopWindow(), x,y, w,h );

//// setVisible(true);
// update();

QRect g = geometry();
QPoint p1 = mapToGlobal( g.topLeft() );
QPoint p2 = mapToGlobal( g.bottomRight() );

// setVisible(false);
QPoint screenTopLeft = mapToGlobal( pos() );
int ax = screenTopLeft.x();
int ay = screenTopLeft.y();
int aw = width();
int ah = height();

QRect r( p1, p2 );

// QImage img = pix.toImage();
// for ( int j = 0; j < img.height(); ++j )
// {
// for ( int i = 0; i < img.width(); ++i )
// {
// QColor c = img.pixel(i,j);
// c.setAlpha(255);
// img.setPixel( i,j, c.rgba() );
// }
// }

// //QImage img = pix.toImage();
// dc.drawImage( rect(), img );

// setUpdatesEnabled(false);
// hide();
//QPixmap pix = QDesktopWidget().grab( QRect(x,y,w,h) );
//QPixmap pix = QPixmap::grabWindow(QApplication::desktop()->winId(), x,y, w,h );
//QPixmap screenShot = QApplication::primaryScreen()->grabWindow( (WId)GetDesktopWindow() );
//mBG = screenShot.copy( ax,ay,aw,ah );
//mBG = screenShot.copy( r );

// mBG = QApplication::primaryScreen()->grabWindow( (WId)GetDesktopWindow(), r.left(), r.top(), r.width(), r.height() );

QPixmap scr = QApplication::primaryScreen()->grabWindow( (WId)GetDesktopWindow() );
mBG = scr.copy( r );



#ifdef VERBOSE
std::stringstream s;
s << "pos ( x=" << pos().x() << ",y=" << pos().y() << ")\n";
s << "a ( x=" << ax << ",y=" << ay << ",w=" << aw << ",h=" << ah << ")\n";
s << "g ( x=" << g.left() << ",y=" << g.top() << ",w=" << g.width() << ",h=" << g.height() << ")\n";
s << "r ( x=" << r.left() << ",y=" << r.top() << ",w=" << r.width() << ",h=" << r.height() << ")\n";
s << "scr ( w=" << scr.width() << ",h=" << scr.height() << ")\n";
s << "mBG ( w=" << mBG.width() << ",h=" << mBG.height() << ")\n";
qDebug() << QString::fromStdString(s.str());
//MMPrint("%s", s.str().c_str())
#endif

// show();
// setUpdatesEnabled(true);
update();
}

wysota
19th February 2015, 09:10
1. How do i hide and show widget without getting floods of event, signals
By calling hide() and show() respectively.


2. How do i get the QScreen object from the widget position
No idea what you mean,.

gerdb
19th February 2015, 19:57
Hi,

1.) i did add hide(); command before getting screenshot and right after that i called show();

--> Results in crash ( as i already said )

2.) When i take the screenshot

aka QPixmap scr = QApplication::primaryScreen()->grabWindow( (WId)GetDesktopWindow() );

i get a 1920x1080 pixels, meaning that it is only one of my monitors and not both, thatswhy i assumed the screenshot is taken monitor-wise

and i wanna know how to determine the current monitor where the widgets is one and take the screenshot from that monitor?

Is that more clear?

Thx in advance

wysota
19th February 2015, 21:35
Hi,

1.) i did add hide(); command before getting screenshot and right after that i called show();

--> Results in crash ( as i already said )
You said you called setUpdatesEnabled(false). That's something completely different to calling hide().


2.) When i take the screenshot

aka QPixmap scr = QApplication::primaryScreen()->grabWindow( (WId)GetDesktopWindow() );

i get a 1920x1080 pixels, meaning that it is only one of my monitors and not both, thatswhy i assumed the screenshot is taken monitor-wise

and i wanna know how to determine the current monitor where the widgets is one and take the screenshot from that monitor?


Hmm... QWindow::screen()? :)

PKEv
18th September 2015, 22:58
Can you solve problem?
i use full construction:

QRect systemScreenRect = getSystemScreenRect();
return QApplication::screens().at(1)->grabWindow(0,0,0,
systemScreenRect.width(),
systemScreenRect.height());

but problem not solved full