实现无边框可拖动调整大小的阴影窗口

tcStyleToolDialog.cpp


 
 
# include "tcStyleToolDialog.h"
#include "ui_tcStyleToolDialog.h"
#include <QDesktopWidget>
#include <QMouseEvent>
#include <QPainter>
#include <qt_windows.h>
#include <windowsx.h>
#include <QDebug>
void TcStyleToolDialog :: paintShadow ( QWidget * widget , int shadowWidth )
{
QPainterPath path ;
path . setFillRule ( Qt :: WindingFill );
path . addRoundedRect ( shadowWidth , shadowWidth , widget -> width () - shadowWidth * 2 , widget -> height () - shadowWidth * 2 ,
shadowWidth , shadowWidth );
QPainter painter ( widget );
painter . setRenderHint ( QPainter :: Antialiasing , true );
painter . fillPath ( path , QBrush ( Qt :: white ));
QColor color ( 0 , 0 , 0 , 250 );
for ( int i = 0 ; i < shadowWidth ; ++ i )
{
QPainterPath path ;
path . setFillRule ( Qt :: WindingFill );
path . addRoundedRect ( shadowWidth - i ,
shadowWidth - i ,
widget -> width () - ( shadowWidth - i ) * 2 ,
widget -> height () - ( shadowWidth - i ) * 2 ,
shadowWidth , shadowWidth , Qt :: AbsoluteSize );
color . setAlpha (( shadowWidth * 24 ) / ( i + 1 )); //- qSqrt(i)*50);
painter . setPen ( color );
painter . drawPath ( path );
}
}
bool TcStyleToolDialog :: resizeEvent ( const QByteArray & , void * msg , long * result , const QRect & wndRect )
{
bool ret = false ;
MSG * message = ( MSG * ) msg ;
switch ( message -> message )
{
case WM_NCHITTEST :
int xPos = GET_X_LPARAM ( message -> lParam ) - wndRect . x ();
int yPos = GET_Y_LPARAM ( message -> lParam ) - wndRect . y ();
//if ( childAt(xPos, yPos) == ? ) // ? 为桌面控件名,即可实现拖动,但无法双击缩放
//{
// // 移动
// *result = HTCAPTION;
//}else
//{
// return false;
//}
ret = true ;
if ( abs(xPos) <= 5 && abs(yPos) <= 5 )
{
* result = HTTOPLEFT ;
} else
if ( abs ( xPos - wndRect . width ()) <= 5 && abs ( yPos ) <= 5 )
{
* result = HTTOPRIGHT ;
} else
if ( abs ( xPos ) <= 5 && abs ( yPos - wndRect . height ()) <= 5 )
{
* result = HTBOTTOMLEFT ;
} else
if ( abs ( xPos - wndRect . width ()) <= 5 && abs ( yPos - wndRect . height ()) <= 5 )
{
* result = HTBOTTOMRIGHT ;
} else
if ( abs ( xPos ) <= 3 )
{
* result = HTLEFT ;
} else
if ( abs ( xPos - wndRect . width ()) <= 3 )
{
* result = HTRIGHT ;
} else
if ( abs ( yPos ) <= 3 )
{
* result = HTTOP ;
} else
if ( abs ( yPos - wndRect . height ()) <= 3 )
{
* result = HTBOTTOM ;
} else
{
ret = false ;
}
}
return ret ;
}
bool TcStyleToolDialog :: sorptionEvent ( const QByteArray & , void * msg , long * , int shadowWidth )
{
MSG * message = ( MSG * ) msg ;
if ( message -> message == WM_MOVING )
{
LPRECT prc = ( LPRECT ) message -> lParam ;
int wndWidth = prc -> right - prc -> left ;
int wndHeight = prc -> bottom - prc -> top ;
const int distance = 16 ;
static bool sorptionX = false ;
static bool sorptionY = false ;
static int startX ;
static int startY ;
if ( abs ( prc -> left ) <= distance )
{
prc -> left = - shadowWidth ;
prc -> right = wndWidth - shadowWidth ;
if ( ! sorptionX )
{
sorptionX = true ;
startX = QCursor :: pos (). x ();
}
}
if ( abs ( prc -> right - qApp -> desktop () -> availableGeometry (). right ()) <= distance )
{
prc -> left = qApp -> desktop () -> availableGeometry (). right () - wndWidth + shadowWidth ;
prc -> right = qApp -> desktop () -> availableGeometry (). right () + shadowWidth ;
if ( ! sorptionX )
{
sorptionX = true ;
startX = QCursor :: pos (). x ();
}
}
if ( abs ( prc -> top ) <= distance )
{
prc -> top = - shadowWidth ;
prc -> bottom = wndHeight - shadowWidth ;
if ( ! sorptionY )
{
sorptionY = true ;
startY = QCursor :: pos (). y ();
}
}
if ( abs ( prc -> bottom - qApp -> desktop () -> availableGeometry (). bottom ()) <= distance )
{
prc -> top = qApp -> desktop () -> availableGeometry (). bottom () - wndHeight + shadowWidth ;
prc -> bottom = qApp -> desktop () -> availableGeometry (). bottom () + shadowWidth ;
if ( ! sorptionY )
{
sorptionY = true ;
startY = QCursor :: pos (). y ();
}
}
if ( sorptionX )
{
int newX = QCursor :: pos (). x () - startX ;
if ( abs ( newX ) > distance )
{
prc -> left = prc -> left + newX - shadowWidth ;
prc -> right = prc -> left + wndWidth ;
sorptionX = false ;
}
}
if ( sorptionY )
{
int newY = QCursor :: pos (). y () - startY ;
if ( abs ( newY ) > distance )
{
prc -> top = prc -> top + newY - shadowWidth ;
prc -> bottom = prc -> top + wndHeight ;
sorptionY = false ;
}
}
}
return false ;
}
TcStyleToolDialog :: TcStyleToolDialog ( QWidget * parent )
: QDialog ( parent )
, ui ( new Ui :: TcStyleToolDialog )
, m_dialogResize ( false )
{
ui -> setupUi ( this );
setWindowFlags ( windowFlags () | Qt :: FramelessWindowHint );
ui -> DialogWidget -> setAttribute ( Qt :: WA_TranslucentBackground , true );
//QMargins shadowMargins = ui->dialogLayout->contentsMargins();
m_shadowWidth = 0; //(shadowMargins.left()+shadowMargins.top()+shadowMargins.right()+shadowMargins.bottom())/4;
}
TcStyleToolDialog ::~ TcStyleToolDialog ()
{
delete ui ;
}
QLayout * TcStyleToolDialog :: clientLayout ()
{
return ui -> clientLayout ;
}
void TcStyleToolDialog :: setShadowWidth ( int shadowWidth )
{
m_shadowWidth = shadowWidth ;
setContentsMargins ( 0 , 0 , 0 , 0 );
ui -> dialogLayout -> setContentsMargins ( shadowWidth , shadowWidth , shadowWidth , shadowWidth );
setAttribute ( Qt :: WA_TranslucentBackground , shadowWidth > 0 );
}
void TcStyleToolDialog :: initClient ( QWidget * widget )
{
widget -> setParent ( ui -> DialogWidget );
ui -> clientLayout -> addWidget ( widget );
move (( qApp -> desktop () -> availableGeometry (). bottomRight ()
- QPoint ( geometry (). size (). width (), geometry (). size (). height ())) / 2 );
}
void TcStyleToolDialog :: paintEvent ( QPaintEvent * )
{
if ( m_shadowWidth > 0 )
{
paintShadow ( this , m_shadowWidth );
}
}
bool TcStyleToolDialog :: nativeEvent ( const QByteArray & eventType , void * msg , long * result )
{
MSG * message = ( MSG * ) msg ;
switch ( message -> message )
{
case WM_NCHITTEST :
int xPos = GET_X_LPARAM ( message -> lParam ) - geometry (). x ();
int yPos = GET_Y_LPARAM ( message -> lParam ) - geometry (). y ();
if ( isMoveBar ( childAt ( xPos , yPos )) )
{
* result = HTCAPTION ;
return true ;
} else
if ( m_dialogResize )
{
return resizeEvent ( eventType , msg , result , QRect ( geometry (). x () + m_shadowWidth ,
geometry (). y () + m_shadowWidth ,
geometry (). width () - m_shadowWidth - m_shadowWidth ,
geometry (). height () - m_shadowWidth - m_shadowWidth ));
}
}
return QDialog :: nativeEvent ( eventType , msg , result );
}

tcStyleToolDialog.h


 
 
#pragma once
#ifndef TIANCHI_TCSTYLETOOLDIALOG_H
#define TIANCHI_TCSTYLETOOLDIALOG_H
#include <QDialog>
#include <QPixmap>
#include <QVBoxLayout>
#ifndef TIANCHI_API
#define TIANCHI_API
#endif
namespace Ui {
class TcStyleToolDialog ;
}
class TIANCHI _API TcStyleToolDialog : public QDialog
{
typedef QDialog inherited ;
Q_OBJECT
public :
static void paintShadow ( QWidget * widget , int shadowWidth = 3 );
static bool resizeEvent ( const QByteArray & , void * msg , long * result , const QRect & wndRect );
static bool sorptionEvent ( const QByteArray & , void * msg , long * , int shadowWidth = 0 );
explicit TcStyleToolDialog ( QWidget * parent = 0 );
~ TcStyleToolDialog ();
protected :
Ui :: TcStyleToolDialog * ui ;
inline void setDialogResize ( bool value ) { m_dialogResize = value ; }
void setShadowWidth ( int shadowWidth );
QLayout * clientLayout ();
void initClient ( QWidget * widget );
virtual bool isMoveBar ( QWidget * moveBar ) const { Q_UNUSED ( moveBar ); return false ; }
virtual void paintEvent ( QPaintEvent * ) override ;
virtual bool nativeEvent ( const QByteArray & eventType , void * msg , long * result ) override ;
private :
bool m_dialogResize ;
int m_shadowWidth ;
};
#define TC_PAINTSHADOW(w) \
virtual void paintEvent(QPaintEvent*) override \
{ TcStyleToolDialog::paintShadow(this, w); }
#define TC_WINDOWRESIZE(widget) \
virtual bool nativeEvent(const QByteArray& eventType, void* msg, long* result) override \
{ return TcStyleToolDialog::resizeEvent(eventType, msg, result, widget->geometry()); }
#endif // TIANCHI_TCSTYLETOOLDIALOG_H

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值