Qt有个函数QPixmap QPixmap::grabWidget(QObject *widget, const QRect &rectangle)可以抓取某个窗体的某个区域作为图片。这个功能适合用在屏幕截图。以此函数为核心,写个屏幕截图程序。
开始思路是让一个窗体铺满整个屏幕,窗体半透明,然后让选中的区域透明。这样做功能上可以实现,但是我在win7上运行的,中间选中的透明区域是黑色的。该方法的主要函数是:
void TestWindow::paintEvent( QPaintEvent* )
{
QPainter p(this);
p.setCompositionMode( QPainter::CompositionMode_Clear );
p.fillRect( x, y, width, height, Qt::SolidPattern ); //截取区域的矩形
}
后来换了一种思路,窗体设置成全透明,然后将截取以外的区域遮挡住,只剩截取区域,就可以实现了。具体做法是用四个矩形,挡住非截取部分。控制四个矩形即可。示意图如下。
虽然看上去奇怪了点,但是功能还是好用的。
ScreenMask::ScreenMask(QWidget *parent) :
QWidget(parent),
ui(new Ui::ScreenMask)
{
ui->setupUi(this);
resize(QApplication::desktop()->size());
setWindowOpacity(0.9);
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground, true); //背景设置全透明
x1=-1;
y1=-1;
setCursor(Qt::CrossCursor);
isDrawing=false;
endPoint=lastPoint;
setMouseTracking(true);
}
void ScreenMask::mouseMoveEvent(QMouseEvent *event)
{
x1=event->x();
y1=event->y();
update();
}
void ScreenMask::mousePressEvent(QMouseEvent *event)
{
if(event->button()==Qt::LeftButton)
{
lastPoint=event->pos(); //截屏区域左上角
isDrawing=true;
emit startCut();
}
update();
}
void ScreenMask::mouseReleaseEvent(QMouseEvent *event)
{
if(event->button()==Qt::LeftButton)
{
endPoint=event->pos(); //截屏区域右下角
isDrawing=false;
setCursor(Qt::ArrowCursor);
this->hide();
int x,y,w,h;
x=lastPoint.x();
y=lastPoint.y();
w=endPoint.x()-x;
h=endPoint.y()-y;
QPixmap tmpixmap=QPixmap::grabWindow(QApplication::desktop()->winId(),x,y,w,h);
QClipboard *tmpClipboard=QApplication::clipboard();
tmpClipboard->setPixmap(tmpixmap);
emit endCut();
}
}
void ScreenMask::paintEvent(QPaintEvent *event)
{
int x,y,w,h;
x=lastPoint.x();
y=lastPoint.y();
QPainterPath path;
path.addRect(0, 0, this->width(), this->height());
QPainter painter(this);
if(isDrawing)
{
w=x1-x; //截屏区域宽度
h=y1-y; //截屏区域高度
//设置4个遮挡矩形的大小和位置,空余出截屏位置。
ui->topWidget->setGeometry(0, 0, this->width(), y);
ui->leftWidget->setGeometry(0, y, x, this->height() - y);
ui->rightWidget->setGeometry(x + w, y, this->width() - x - w, this->height() - y);
ui->bottomWidget->setGeometry(x, y + h, w, this->width() - h - y);
}
else
{
ui->topWidget->setGeometry(0,0,this->width(),this->height());
}
update();
}