// COPYRIGHT (C) Tom. ALL RIGHTS RESERVED. // THE AntdUI PROJECT IS AN WINFORM LIBRARY LICENSED UNDER THE Apache-2.0 License. // LICENSED UNDER THE Apache License, VERSION 2.0 (THE "License") // YOU MAY NOT USE THIS FILE EXCEPT IN COMPLIANCE WITH THE License. // YOU MAY OBTAIN A COPY OF THE LICENSE AT // // http://www.apache.org/licenses/LICENSE-2.0 // // UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE // DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND // LIMITATIONS UNDER THE License. // GITEE: https://gitee.com/antdui/AntdUI // GITHUB: https://github.com/AntdUI/AntdUI // CSDN: https://blog.csdn.net/v_132 // QQ: 17379620 using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; namespace AntdUI { internal class LayeredFormPreview : ILayeredFormOpacity { int Radius = 0, Bor = 0; bool HasBor = false; Form form; PreBtns[] btns; Preview.Config config; public LayeredFormPreview(Preview.Config _config) { maxalpha = 255; config = _config; form = _config.Form; Font = form.Font; TopMost = _config.Form.TopMost; if (form.WindowState != FormWindowState.Maximized) { if (form is BorderlessForm borderless) Radius = (int)(borderless.Radius * Config.Dpi); else if (OS.Win11) Radius = (int)(8 * Config.Dpi); //Win11 if (form is Window || form is FormNoBar) { //无边框处理 } else if (form.FormBorderStyle != FormBorderStyle.None) { HasBor = true; Bor = (int)(7 * Config.Dpi); } } if (form is Window window) { SetSize(window.Size); SetLocation(window.Location); Size = window.Size; Location = window.Location; } else { SetSize(form.Size); SetLocation(form.Location); Size = form.Size; Location = form.Location; } PageSize = config.ContentCount; var btnwiths = new PreBtns[] { new PreBtns("@t_flipY",SvgDb.IcoFlip.Insert(28," transform=\"rotate(90),translate(0 -100%)\"")), new PreBtns("@t_flipX",SvgDb.IcoFlip), new PreBtns("@t_rotateL",SvgDb.IcoRotateLeft), new PreBtns("@t_rotateR",SvgDb.IcoRotateRight), new PreBtns("@t_zoomOut",SvgDb.IcoZoomOut), new PreBtns("@t_zoomIn",SvgDb.IcoZoomIn), }; if (config.Btns == null || config.Btns.Length == 0) btns = btnwiths; else { var btntmp = new List(config.Btns.Length + btnwiths.Length); foreach (var it in config.Btns) btntmp.Add(new PreBtns(it.Name, it.IconSvg, it.Tag)); btntmp.AddRange(btnwiths); btns = btntmp.ToArray(); } } int PageSize = 0; protected override void OnLoad(EventArgs e) { if (form is Window window) { SetSize(window.Size); SetLocation(window.Location); Size = window.Size; Location = window.Location; } else { SetSize(form.Size); SetLocation(form.Location); Size = form.Size; Location = form.Location; } form.LocationChanged += Form_LSChanged; form.SizeChanged += Form_LSChanged; LoadImg(); base.OnLoad(e); } private void Form_LSChanged(object? sender, EventArgs e) { if (form is Window window) { SetSize(window.Size); SetLocation(window.Location); Size = window.Size; Location = window.Location; } else { SetSize(form.Size); SetLocation(form.Location); Size = form.Size; Location = form.Location; } Print(); } protected override void Dispose(bool disposing) { form.LocationChanged -= Form_LSChanged; form.SizeChanged -= Form_LSChanged; base.Dispose(disposing); } #region 渲染 #region 渲染图片 bool loading = false; /// /// 加载状态 /// public bool Loading { get => loading; set { if (loading == value) return; loading = value; Print(); } } string? LoadingProgressStr = null; float _value = -1F; /// /// 加载进度 /// public float LoadingProgress { get => _value; set { if (_value == value) return; if (value < 0) value = 0; else if (value > 1) value = 1; _value = value; if (loading) Print(); } } Image? Img = null; int SelectIndex = 0; Size ImgSize = new Size(); void LoadImg() { autoDpi = true; if (config.Content is IList images) { Img = images[SelectIndex]; ImgSize = Img.Size; FillScaleImg(); } else if (config.Content is object[] list && list[0] is IList data) { if (list[1] is Func call) { Img?.Dispose(); Img = call.Invoke(SelectIndex, data[SelectIndex]); if (Img == null) { Print(); return; } ImgSize = Img.Size; FillScaleImg(); } else if (list[1] is Func, Image?> callprog) { LoadingProgressStr = null; _value = -1F; Loading = true; ITask.Run(() => { var img = callprog.Invoke(SelectIndex, data[SelectIndex], (prog, progstr) => { LoadingProgressStr = progstr; LoadingProgress = prog; }); if (img == null) { Img?.Dispose(); Img = null; return; } LoadingProgressStr = null; Img?.Dispose(); Img = img; ImgSize = Img.Size; FillScaleImg(); }, () => { Loading = false; }); } } else { Img = null; Print(); } } #region 缩放 bool autoDpi = true; PointF rect_img_oxy; RectangleF rect_img_dpi; float offsetX = 0, offsetY = 0; float _dpi = 1F; float Dpi { get => _dpi; set { if (value < 0.06) { value = 0.06F; } else if (value > _dpi && _dpi < 1F && value > 1F) value = 1F; _dpi = value; rect_img_dpi = ScaleImg(rect_read, _dpi); } } RectangleF ScaleImg(Rectangle rect, float dpi) { float width = ImgSize.Width * dpi, height = ImgSize.Height * dpi; rect_img_oxy = new PointF((rect.Width - width) / 2, (rect.Height - height) / 2); if (width < rect.Width || height < rect.Height) { if (width < rect.Width && height < rect.Height) { //小 if (offsetX < -rect_img_oxy.X) offsetX = -rect_img_oxy.X; else if (offsetX > rect_img_oxy.X) offsetX = rect_img_oxy.X; if (offsetY < -rect_img_oxy.Y) offsetY = -rect_img_oxy.Y; else if (offsetY > rect_img_oxy.Y) offsetY = rect_img_oxy.Y; } else if (width < rect.Width) { offsetX = 0; if (offsetY > -rect_img_oxy.Y) offsetY = -rect_img_oxy.Y; else if (offsetY < rect_img_oxy.Y) offsetY = rect_img_oxy.Y; } else { offsetY = 0; if (offsetX > -rect_img_oxy.X) offsetX = -rect_img_oxy.X; else if (offsetX < rect_img_oxy.X) offsetX = rect_img_oxy.X; } } else { if (offsetX < rect_img_oxy.X) offsetX = rect_img_oxy.X; else if (offsetX > -rect_img_oxy.X) offsetX = -rect_img_oxy.X; if (offsetY < rect_img_oxy.Y) offsetY = rect_img_oxy.Y; else if (offsetY > -rect_img_oxy.Y) offsetY = -rect_img_oxy.Y; } return new RectangleF(offsetX + rect_img_oxy.X, offsetY + rect_img_oxy.Y, width, height); } void FillScaleImg() { if (autoDpi) { var rect = rect_read; float DpiX = (float)((rect.Width * 1.0) / (ImgSize.Width * 1.0)), DpiY = (float)((rect.Height * 1.0) / (ImgSize.Height * 1.0)); if (DpiX > 1 && DpiY > 0) Dpi = 1F; else if (ImgSize.Width > ImgSize.Height) { if (rect.Width > rect.Height) Dpi = DpiX; else Dpi = DpiY; } else { if (rect.Width > rect.Height) Dpi = DpiY; else Dpi = (float)((rect.Width * 1.0) / (ImgSize.Height * 1.0)); } } } #endregion #endregion readonly StringFormat s_f = Helper.SF_NoWrap(); public override Bitmap PrintBit() { var original_bmp = new Bitmap(TargetRect.Width, TargetRect.Height); using (var g = Graphics.FromImage(original_bmp).High()) { using (var brush = new SolidBrush(Color.FromArgb(115, 0, 0, 0))) { if (Radius > 0) { using (var path = rect_read.RoundPath(Radius)) { g.FillPath(brush, path); } } else g.FillRectangle(brush, rect_read); } if (Img != null) { try { g.DrawImage(Img, rect_img_dpi, new RectangleF(0, 0, ImgSize.Width, ImgSize.Height), GraphicsUnit.Pixel); } catch { } } if (loading) { using (var pen = new Pen(Color.FromArgb(220, Style.Db.PrimaryColor), 6 * Config.Dpi)) using (var penpro = new Pen(Style.Db.Primary, pen.Width)) { int loading_size = (int)(40 * Config.Dpi); var rect_loading = new Rectangle(rect_read.X + (rect_read.Width - loading_size) / 2, rect_read.Y + (rect_read.Height - loading_size) / 2, loading_size, loading_size); g.DrawEllipse(pen, rect_loading); if (_value > -1) { try { g.DrawArc(penpro, rect_loading, -90, 360F * _value); } catch { } if (LoadingProgressStr != null) { rect_loading.Offset(0, loading_size); using (var brush = new SolidBrush(Style.Db.PrimaryColor)) { g.DrawString(LoadingProgressStr, Font, brush, rect_loading, s_f); } } } } } else if (LoadingProgressStr != null) { using (var pen = new Pen(Style.Db.Error, 6 * Config.Dpi)) { int loading_size = (int)(40 * Config.Dpi); var rect_loading = new Rectangle(rect_read.X + (rect_read.Width - loading_size) / 2, rect_read.Y + (rect_read.Height - loading_size) / 2, loading_size, loading_size); g.DrawEllipse(pen, rect_loading); rect_loading.Offset(0, loading_size); using (var brush = new SolidBrush(Style.Db.ErrorColor)) { g.DrawString(LoadingProgressStr, Font, brush, rect_loading, s_f); } } } using (var path = rect_panel.RoundPath(rect_panel.Height)) { using (var brush = new SolidBrush(Color.FromArgb(26, 0, 0, 0))) { g.FillPath(brush, path); PaintBtn(g, brush, rect_close, rect_close_icon, SvgDb.IcoClose, hoverClose, true); if (PageSize > 1) { PaintBtn(g, brush, rect_left, rect_left_icon, SvgDb.IcoLeft, hoverLeft, enabledLeft); PaintBtn(g, brush, rect_right, rect_right_icon, SvgDb.IcoRight, hoverRight, enabledRight); } } } foreach (var it in btns) { using (var bmp = SvgExtend.GetImgExtend(it.svg, it.rect, it.hover ? colorHover : colorDefault)) { if (bmp != null) { if (it.enabled) g.DrawImage(bmp, it.rect); else g.DrawImage(bmp, it.rect, 0.3F); } } } } return original_bmp; } void PaintBtn(Graphics g, SolidBrush brush, Rectangle rect, Rectangle rect_ico, string svg, bool hover, bool enabled) { using (var bmp = SvgExtend.GetImgExtend(svg, rect_ico, Color.White)) { if (bmp != null) { if (hover) { using (var brush_hover = new SolidBrush(Color.FromArgb(51, 0, 0, 0))) { g.FillEllipse(brush_hover, rect); } } else g.FillEllipse(brush, rect); if (enabled) g.DrawImage(bmp, rect_ico); else g.DrawImage(bmp, rect_ico, 0.3F); } } } readonly Color colorDefault = Color.FromArgb(166, 255, 255, 255), colorHover = Color.FromArgb(217, 255, 255, 255); internal class PreBtns { public PreBtns(string _id, string _svg) { id = _id; svg = _svg; } public PreBtns(string _id, string _svg, object? _tag) : this(_id, _svg) { tag = _tag; div = true; } public string id { get; set; } public string svg { get; set; } public bool div { get; set; } public object? tag { get; set; } public Rectangle Rect { get; set; } public Rectangle rect { get; set; } public bool hover { get; set; } public bool enabled { get; set; } = true; public bool mdown { get; set; } } #endregion #region 坐标 Rectangle rect_read, rect_left, rect_left_icon, rect_right, rect_right_icon, rect_close, rect_close_icon, rect_panel; protected override void OnSizeChanged(EventArgs e) { if (btns == null) return; if (HasBor) rect_read = new Rectangle(Bor, 0, TargetRect.Width - Bor * 2, TargetRect.Height - Bor); else rect_read = TargetRectXY; int btn_height = (int)(46 * Config.Dpi), lr_size = (int)(40 * Config.Dpi), btn_width = (int)(42 * Config.Dpi), padding = (int)(24 * Config.Dpi), padding_lr = (int)(12 * Config.Dpi), padding_buttom = (int)(32 * Config.Dpi), icon_size = (int)(18 * Config.Dpi); rect_close = new Rectangle(rect_read.Right - padding_buttom - btn_width, rect_read.Y + padding_buttom, btn_width, btn_width); rect_close_icon = GetCentered(rect_close, icon_size); if (PageSize > 1) { rect_left = new Rectangle(rect_read.X + padding_lr, rect_read.Y + (rect_read.Height - lr_size) / 2, lr_size, lr_size); rect_left_icon = GetCentered(rect_left, icon_size); rect_right = new Rectangle(rect_read.Right - padding_lr - lr_size, rect_read.Y + (rect_read.Height - lr_size) / 2, lr_size, lr_size); rect_right_icon = GetCentered(rect_right, icon_size); } int w = (btn_width * btns.Length - 1) + padding * 2, x = rect_read.X + (rect_read.Width - w) / 2, y = rect_read.Bottom - padding_buttom - btn_height; rect_panel = new Rectangle(x, y, w, btn_height); x += padding; foreach (var it in btns) { it.Rect = new Rectangle(x, y, btn_width, btn_height); it.rect = GetCentered(it.Rect, icon_size); x += btn_width; } base.OnSizeChanged(e); } Rectangle GetCentered(Rectangle rect, int size) { int xy = (rect.Width - size) / 2; return new Rectangle(rect.X + xy, rect.Y + xy, size, size); } #endregion #region 鼠标 bool hoverClose = false, hoverLeft = false, hoverRight = false; bool enabledLeft { get => SelectIndex > 0; } bool enabledRight { get => SelectIndex < PageSize - 1; } protected override void OnMouseWheel(MouseEventArgs e) { if (Img != null) { autoDpi = false; if (e.Delta > 0) { Dpi += 0.1F; SetBtnEnabled("@t_zoomOut", true); } else { Dpi -= 0.1F; SetBtnEnabled("@t_zoomOut", Dpi >= 0.06); } Print(); } base.OnMouseWheel(e); } void SetBtnEnabled(string id, bool enabled) { foreach (var it in btns) { if (it.id == id) it.enabled = enabled; } } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (moveImg) { if ((offsetXOld != e.X && offsetYOld != e.Y) || moveImging) { moveImging = true; offsetX = offsetXOld + e.X - movePos.X; offsetY = offsetYOld + e.Y - movePos.Y; Dpi = _dpi; Print(); return; } } if (btns == null) return; int count = 0, hand = 0; if (rect_close.Contains(e.Location)) { hand++; if (!hoverClose) { hoverClose = true; count++; } } else { if (hoverClose) { hoverClose = false; count++; } } if (PageSize > 1) { if (enabledLeft && rect_left.Contains(e.Location)) { hand++; if (!hoverLeft) { hoverLeft = true; count++; } } else { if (hoverLeft) { hoverLeft = false; count++; } } if (enabledRight && rect_right.Contains(e.Location)) { hand++; if (!hoverRight) { hoverRight = true; count++; } } else { if (hoverRight) { hoverRight = false; count++; } } } foreach (var it in btns) { if (it.enabled && it.Rect.Contains(e.Location)) { hand++; if (!it.hover) { it.hover = true; count++; } } else { if (it.hover) { it.hover = false; count++; } } } SetCursor(hand > 0); if (count > 0) { Print(); } } protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (e.Button == MouseButtons.Left) { foreach (var it in btns) { if (it.enabled && it.Rect.Contains(e.Location)) { it.mdown = true; return; } } if (rect_img_dpi.Contains(e.Location)) { if (rect_img_dpi.Width < Width && rect_img_dpi.Height < Height) { //小 } else { movePos = e.Location; offsetXOld = offsetX; offsetYOld = offsetY; moveImging = false; moveImg = true; } } } } protected override void OnMouseUp(MouseEventArgs e) { if (moveImg) { moveImg = false; if (moveImging) { moveImging = false; base.OnMouseUp(e); return; } } foreach (var it in btns) { if (it.mdown) { if (it.Rect.Contains(e.Location)) { switch (it.id) { case "@t_flipY": if (Img != null) { Img.RotateFlip(RotateFlipType.RotateNoneFlipY); Print(); } break; case "@t_flipX": if (Img != null) { Img.RotateFlip(RotateFlipType.RotateNoneFlipX); Print(); } break; case "@t_rotateL": if (Img != null) { float old = _dpi; bool oldautoDpi = autoDpi; Img.RotateFlip(RotateFlipType.Rotate270FlipNone); ImgSize = Img.Size; autoDpi = true; FillScaleImg(); Dpi = old; autoDpi = oldautoDpi; Print(); } break; case "@t_rotateR": if (Img != null) { float old = _dpi; bool oldautoDpi = autoDpi; Img.RotateFlip(RotateFlipType.Rotate90FlipNone); ImgSize = Img.Size; autoDpi = true; FillScaleImg(); Dpi = old; autoDpi = oldautoDpi; Print(); } break; case "@t_zoomOut": Dpi -= 0.1F; SetBtnEnabled("@t_zoomOut", Dpi >= 0.06); Print(); break; case "@t_zoomIn": Dpi += 0.1F; SetBtnEnabled("@t_zoomOut", true); Print(); break; default: config.OnBtns?.Invoke(it.id, it.tag); break; } } it.mdown = false; return; } } if (rect_close.Contains(e.Location)) { IClose(); return; } if (PageSize > 1) { if (enabledLeft && rect_left.Contains(e.Location)) { SelectIndex--; LoadImg(); Print(); return; } if (enabledRight && rect_right.Contains(e.Location)) { SelectIndex++; LoadImg(); Print(); return; } } if (!rect_img_dpi.Contains(e.Location)) IClose(); base.OnMouseUp(e); } bool moveImg = false, moveImging = false; Point movePos; float offsetXOld = 0, offsetYOld = 0; #endregion } }