仿照VS工具实现窗口阴影

原理:创建四个窗口平铺在需要添加阴影的窗口上;

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];
		
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二丶九

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值