原理:创建四个窗口平铺在需要添加阴影的窗口上;
vs实现原理:可以使用QQ截图放在vs工具的四周可看出实现原理;
头文件:
#include <QtWidgets/QMainWindow>
#define int32 int
using float64 = double;
typedef unsigned int quint32;
using uint32 = quint32;
using ShiftedMultiplier = uint32;
namespace Main_Window {
enum class ShadowsChange {
Moved = 0x01,
Resized = 0x02,
Shown = 0x04,
Hidden = 0x08,
Activate = 0x10,
};
Q_DECLARE_FLAGS(ShadowsChanges, ShadowsChange);
}
enum {
_PsInitHor = 0x01,
_PsInitVer = 0x02,
};
#define for_const(range_declaration, range_expression) for (range_declaration : std::as_const(range_expression))
#include <QPainter>
#include <Shobjidl.h>
#include <shellapi.h>
#include <WtsApi32.h>
#include <Windowsx.h>
#include <gdiplus.h>
class _PsShadowWindows {
public:
using Change = Main_Window::ShadowsChange;
using Changes = Main_Window::ShadowsChanges;
_PsShadowWindows();
~_PsShadowWindows();
void setColor(QColor c);
bool init(QColor c);
void initCorners(int directions = (_PsInitHor | _PsInitVer));
void verCorners(int h, Gdiplus::Graphics *pgraphics1, Gdiplus::Graphics *pgraphics3);
void horCorners(int w, Gdiplus::Graphics *pgraphics0, Gdiplus::Graphics *pgraphics2);
void update(Changes changes, WINDOWPOS *pos = 0);
void updateWindow(int i, POINT *p, SIZE *s = 0);
void destroy();
//void setApp(myDialog* d);
static void setApp(QWidget* d);
static void setResizeEnable(bool flag);
private:
int _x, _y, _w, _h;
int _metaSize, _fullsize, _size, _shift;
QVector<BYTE> _alphas, _colors;
bool hidden;
HWND hwnds[4];;
static QWidget* m_myApp;
static bool m_bRsizeEnable;
static bool m_bNCactivate;
HDC dcs[4], screenDC;
HBITMAP bitmaps[4];
int max_w, max_h;
BLENDFUNCTION blend;
BYTE r, g, b;
COLORREF noKeyColor;
static LRESULT __stdcall wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
};
extern _PsShadowWindows _psShadowWindows;
实现:
#include "shadow_win.h"
#include <QCoreApplication>
int32 _psSize = 0;
QWidget* _PsShadowWindows::m_myApp = NULL;
bool _PsShadowWindows::m_bRsizeEnable = true;
bool _PsShadowWindows::m_bNCactivate = true;
#pragma comment(lib,"gdiplus.lib")
_PsShadowWindows::_PsShadowWindows() : screenDC(0), max_w(0), max_h(0), _x(0), _y(0), _w(0), _h(0), hidden(true), r(0), g(0), b(0), noKeyColor(RGB(255, 255, 255)) {
for (int i = 0; i < 4; ++i) {
dcs[i] = 0;
bitmaps[i] = 0;
hwnds[i] = 0;
}
}
_PsShadowWindows::~_PsShadowWindows()
{
}
void _PsShadowWindows::setColor(QColor c) {
r = c.red();
g = c.green();
b = c.blue();
if (!hwnds[0]) return;
Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b));
for (int i = 0; i < 4; ++i) {
Gdiplus::Graphics graphics(dcs[i]);
graphics.SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
if ((i % 2) && _h || !(i % 2) && _w) {
graphics.FillRectangle(&brush, 0, 0, (i % 2) ? _size : _w, (i % 2) ? _h : _size);
}
}
initCorners();
_x = _y = _w = _h = 0;
update( (Change)(0x01 | 0x02));
}
bool _PsShadowWindows::init(QColor c) {
_fullsize = 19;
_shift = 1;
auto cornersImage = QImage(_fullsize, _fullsize, QImage::Format_ARGB32_Premultiplied);
QCoreApplication::applicationDirPath();
cornersImage.load(QCoreApplication::applicationDirPath() + "\\Resources\\shadow.png");
_metaSize = _fullsize + 2 * _shift;
_alphas.reserve(_metaSize);
_colors.reserve(_metaSize * _metaSize);
for (int32 j = 0; j < _metaSize; ++j) {
for (int32 i = 0; i < _metaSize; ++i) {
_colors.push_back((i < 2 * _shift || j < 2 * _shift) ? 1 : qMax(BYTE(1), BYTE(cornersImage.pixel(QPoint(i - 2 * _shift, j - 2 * _shift)) >> 24)));
}
}
uchar prev = 0;
for (int32 i = 0; i < _metaSize; ++i) {
uchar a = _colors[(_metaSize - 1) * _metaSize + i];