Files
lserp_cs_6.0/插件库/Lskj.Main/Control/MainPanelControlEx2.Designer.cs
T
2026-08-30 12:00:03 +08:00

771 lines
39 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using DevExpress.XtraTab;
using DevExpress.XtraTreeList;
using Lskj.Business;
using Lskj.Model;
using WinFormsControl = System.Windows.Forms.Control;
namespace Lskj.Main.Control
{
partial class MainPanelControlEx2
{
private static readonly Color HeaderColor = Color.FromArgb(31, 75, 153);
private static readonly Color SidebarColor = Color.FromArgb(39, 45, 81);
private static readonly Color SidebarSelectedColor = Color.FromArgb(52, 142, 216);
private static readonly Color WorkspaceColor = Color.FromArgb(247, 249, 252);
private static readonly Color ShortcutBorderColor = Color.FromArgb(221, 227, 234);
private System.ComponentModel.IContainer components = null;
private MainPanelControlEx _legacyPanel;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null)) components.Dispose();
base.Dispose(disposing);
}
#region 组件设计器生成的代码
private void InitializeComponent()
{
this._legacyPanel = new Lskj.Main.Control.MainPanelControlEx();
this.SuspendLayout();
//
// _legacyPanel
//
this._legacyPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this._legacyPanel.Location = new System.Drawing.Point(0, 0);
this._legacyPanel.Name = "_legacyPanel";
this._legacyPanel.Size = new System.Drawing.Size(1275, 696);
this._legacyPanel.TabIndex = 0;
//
// MainPanelControlEx2
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this._legacyPanel);
this.Name = "MainPanelControlEx2";
this.Size = new System.Drawing.Size(1275, 696);
this.ResumeLayout(false);
}
#endregion
#region 新版主界面外观
private void ApplyWpfShellStyle()
{
Panel header = FindControl<Panel>("plTop");
Panel headerLeft = FindControl<Panel>("pl_top_left");
Panel headerCenter = FindControl<Panel>("pl_top_center");
Panel headerRight = FindControl<Panel>("pl_top_right");
Panel headerSeparator = FindControl<Panel>("panel3");
MenuStrip topMenu = FindControl<MenuStrip>("menuMain");
if (header != null) { header.Height = 50; header.BackColor = HeaderColor; }
if (headerLeft != null)
{
headerLeft.Width = 176;
headerLeft.BackColor = HeaderColor;
headerLeft.BackgroundImage = null;
AddBrandVisual(headerLeft);
}
if (headerCenter != null) { headerCenter.BackColor = HeaderColor; headerCenter.Padding = new Padding(0, 9, 0, 0); }
// 右上角继续使用旧版控件、按钮和位置,仅统一顶部背景色。
if (headerRight != null) { headerRight.BackColor = HeaderColor; headerRight.BackgroundImage = null; }
// 旧版 Logo 与菜单之间有 19px 的装饰分隔面板;WPF 顶部栏是连续布局,
// 保留该控件会在两块蓝色之间形成突兀的深色竖条。
if (headerSeparator != null)
{
headerSeparator.Width = 0;
headerSeparator.BackColor = HeaderColor;
headerSeparator.BackgroundImage = null;
}
StyleSearchControls();
if (topMenu != null) StyleTopNavigation(topMenu);
StyleMainTabs();
StyleSidebar();
StyleWorkspaceAndShortcuts();
RememberStyledNavigation();
}
private void AddBrandVisual(WinFormsControl host)
{
if (host.Controls.Find("wpfBrandVisual", false).Length > 0) return;
PictureBox logo = new PictureBox
{
Name = "wpfBrandVisual", BackColor = Color.Transparent,
Size = new Size(150, 32), Location = new Point(12, 9),
SizeMode = PictureBoxSizeMode.Zoom
};
Image image = LoadWpfHeaderLogo();
if (image != null)
{
logo.Image = image;
host.Controls.Add(logo);
logo.BringToFront();
}
WinFormsControl oldTitle = host.Controls.Find("lblSubTitle", true).FirstOrDefault();
if (oldTitle != null) oldTitle.Visible = false;
}
private static Image LoadWpfHeaderLogo()
{
// 客户部署时只从程序目录下的 Images\Main 查找 Logo
// 文件不存在则不显示图片,不再回退到开发机或 SVG 资源。
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Images", "Main", "logoNew.png");
try
{
if (!File.Exists(path)) return null;
// 克隆后释放文件句柄,避免程序运行期间锁定更新包中的图片。
using (Image source = Image.FromFile(path)) return new Bitmap(source);
}
catch (Exception)
{
return null;
}
}
private void StyleMainTabs()
{
XtraTabControl tabs = FindControl<XtraTabControl>("tabMain");
if (tabs == null) return;
// 旧版 DevExpress 皮肤会把相邻页签绘成深浅不一的灰块,
// 在新版蓝色顶部栏下显得突兀;统一为 WPF 主界面的浅灰页签带,
// 当前页签保持白色,边界与左侧导航自然衔接。
// 与 WPF WorkspaceTabStrip 保持一致:页签栏 #F3F5F8
// 普通页签 #F8FAFC,边框/底部分隔线 #C7D3E4。
Color tabStrip = Color.FromArgb(243, 245, 248);
Color tabNormal = Color.FromArgb(248, 250, 252);
Color tabHover = Color.White;
Color tabBorder = Color.FromArgb(199, 211, 228);
tabs.PaintStyleName = "Flat";
tabs.HeaderLocation = DevExpress.XtraTab.TabHeaderLocation.Top;
tabs.HeaderAutoFill = DevExpress.Utils.DefaultBoolean.False;
tabs.TabPageWidth = 0;
tabs.BackColor = tabStrip;
tabs.Appearance.BackColor = tabStrip;
tabs.Appearance.Options.UseBackColor = true;
ConfigureTabAppearance(tabs.AppearancePage.Header, tabNormal, Color.FromArgb(74, 86, 105), Color.FromArgb(213, 222, 234));
ConfigureTabAppearance(tabs.AppearancePage.HeaderActive, Color.White, Color.FromArgb(31, 119, 201), tabBorder);
ConfigureTabAppearance(tabs.AppearancePage.HeaderHotTracked, tabHover, Color.FromArgb(31, 119, 201), tabBorder);
ConfigureTabAppearance(tabs.AppearancePage.HeaderDisabled, tabStrip, Color.FromArgb(160, 169, 182), tabBorder);
tabs.AppearancePage.Header.Font = new Font("微软雅黑", 9F);
tabs.AppearancePage.HeaderActive.Font = tabs.AppearancePage.Header.Font;
tabs.AppearancePage.HeaderHotTracked.Font = tabs.AppearancePage.Header.Font;
tabs.AppearancePage.HeaderDisabled.Font = tabs.AppearancePage.Header.Font;
tabs.Paint -= MainTabs_Paint;
tabs.Paint += MainTabs_Paint;
// 功能导航页签要与左侧 176px 目录栏严格对齐。DevExpress 旧版
// 页签宽度按文本自适应,因此用不可见的全角空格补足首个页签宽度,
// 其它页签仍保持按内容自适应,并通过边框清晰分隔。
XtraTabPage first = tabs.TabPages.Cast<XtraTabPage>().FirstOrDefault(p => p.Name == "xtpFirst");
if (first != null) first.Text = "功能导航" + new string('\u3000', 10);
}
private void MainTabs_Paint(object sender, PaintEventArgs e)
{
XtraTabControl tabs = sender as XtraTabControl;
DevExpress.XtraTab.IXtraTab tabInterface = tabs as DevExpress.XtraTab.IXtraTab;
DevExpress.XtraTab.ViewInfo.BaseTabControlViewInfo viewInfo =
tabInterface == null ? null : tabInterface.ViewInfo;
if (tabs == null || viewInfo == null || viewInfo.HeaderInfo == null) return;
Rectangle header = viewInfo.HeaderInfo.Bounds;
if (header.Width <= 0 || header.Height <= 0) return;
Color stripColor = Color.FromArgb(243, 245, 248);
Color borderColor = Color.FromArgb(199, 211, 228);
int lastRight = header.Left;
foreach (DevExpress.XtraTab.ViewInfo.BaseTabPageViewInfo page in viewInfo.HeaderInfo.VisiblePages)
{
Rectangle bounds = page.Bounds;
if (bounds.Width <= 0 || bounds.Height <= 0) continue;
lastRight = Math.Max(lastRight, bounds.Right);
using (Pen pen = new Pen(borderColor))
{
// 明确绘制页签左右分隔及顶部边线,避免 DevExpress 不同皮肤
// 忽略 Appearance.BorderColor 后多个白色页签连成一片。
e.Graphics.DrawLine(pen, bounds.Left, bounds.Top, bounds.Left, bounds.Bottom - 1);
e.Graphics.DrawLine(pen, bounds.Right - 1, bounds.Top, bounds.Right - 1, bounds.Bottom - 1);
e.Graphics.DrawLine(pen, bounds.Left, bounds.Top, bounds.Right - 1, bounds.Top);
}
}
// WPF 页签后方是浅灰色页签带,而不是与内容区相同的纯白色。
Rectangle buttons = viewInfo.HeaderInfo.ButtonsBounds;
int emptyRight = buttons.Width > 0 ? buttons.Left : header.Right;
if (lastRight < emptyRight)
{
using (Brush brush = new SolidBrush(stripColor))
e.Graphics.FillRectangle(brush, lastRight, header.Top, emptyRight - lastRight, header.Height);
}
// WPF 在整个 WorkspaceTabStrip 底部单独覆盖一条 1px 的 #C7D3E4
// 分隔线。不能沿用 HeaderInfo.Bounds.Bottom:旧版 DevExpress 中该位置
// 仍可能属于页签头内部,线条会与页签背景混在一起。这里按内容区顶部定位,
// 横跨控件全宽,并增加一条极浅下沿,使 WinForms 在不同 DPI 下仍有边界感。
Rectangle pageClient = tabs.PageClientBounds;
int dividerY = pageClient.Top > 0 ? pageClient.Top - 1 : header.Bottom - 1;
dividerY = Math.Max(0, Math.Min(tabs.ClientSize.Height - 1, dividerY));
using (Pen pen = new Pen(borderColor))
e.Graphics.DrawLine(pen, 0, dividerY, tabs.ClientSize.Width - 1, dividerY);
if (dividerY + 1 < tabs.ClientSize.Height)
{
using (Pen pen = new Pen(Color.FromArgb(237, 242, 247)))
e.Graphics.DrawLine(pen, 0, dividerY + 1, tabs.ClientSize.Width - 1, dividerY + 1);
}
}
private static void ConfigureTabAppearance(DevExpress.Utils.AppearanceObject appearance, Color backColor, Color foreColor, Color borderColor)
{
appearance.BackColor = backColor;
appearance.ForeColor = foreColor;
appearance.BorderColor = borderColor;
appearance.Options.UseBackColor = true;
appearance.Options.UseForeColor = true;
appearance.Options.UseBorderColor = true;
}
private void StyleSearchControls()
{
// 旧版搜索框和按钮原本位于 y=27、高度 25/26,顶部栏改为 50px 后
// 底部会被裁掉约 2~3px。仅上移 2px 并缩短 1~2px,保留足够的
// 输入高度和按钮点击区域,避免控件显得过小。
WinFormsControl searchBox = FindControl<WinFormsControl>("lueUserName");
if (searchBox != null)
{
searchBox.Top = 25;
searchBox.Height = 24;
}
PictureBox searchButton = FindControl<PictureBox>("pic_search");
if (searchButton != null)
{
searchButton.Top = 25;
searchButton.Height = 24;
}
}
private void StyleTopNavigation(MenuStrip menu)
{
menu.Renderer = new WpfMenuRenderer(HeaderColor, () =>
{
// 每次绘制都重新读取当前导航,支持旧版双击或其它入口切换目录。
return FindCurrentTopMenu(menu) ?? _selectedTopMenu;
});
menu.BackColor = HeaderColor;
menu.ForeColor = Color.FromArgb(242, 246, 255);
menu.Font = new Font("微软雅黑", 10F);
menu.Dock = DockStyle.Fill;
menu.Location = Point.Empty;
menu.Padding = new Padding(4, 0, 4, 0);
menu.AutoSize = false;
menu.Height = 32;
foreach (ToolStripMenuItem item in menu.Items.OfType<ToolStripMenuItem>())
{
item.BackColor = Color.Transparent;
item.ForeColor = Color.FromArgb(242, 246, 255);
item.Font = menu.Font;
item.Padding = new Padding(8, 0, 8, 0);
item.Margin = Padding.Empty;
item.AutoSize = true;
item.Click -= TopMenuItem_Click;
item.Click += TopMenuItem_Click;
item.DropDownOpened -= TopMenuDropDownOpened;
item.DropDownOpened += TopMenuDropDownOpened;
item.DropDownClosed -= TopMenuDropDownClosed;
item.DropDownClosed += TopMenuDropDownClosed;
HookDropDownClicks(item);
}
// 当前功能导航是唯一权威状态。旧版在双击切换目录时会更新
// ERPInfo.Instance.SubSysName;这里每次重新套用样式都优先按该值查找,
// 避免上一次点击留下的菜单项一直保持高亮。
ToolStripMenuItem current = FindCurrentTopMenu(menu);
if (current == null)
current = _selectedTopMenu;
if (current == null || !menu.Items.Contains(current))
current = null;
if (current == null)
current = menu.Items.OfType<ToolStripMenuItem>().FirstOrDefault();
SelectTopMenu(current);
}
private void HookDropDownClicks(ToolStripMenuItem root)
{
foreach (ToolStripMenuItem child in root.DropDownItems.OfType<ToolStripMenuItem>())
{
child.Click -= LegacyDropDownItem_Click;
child.Click += LegacyDropDownItem_Click;
HookDropDownClicks(child);
}
}
private void LegacyDropDownItem_Click(object sender, EventArgs e)
{
ToolStripMenuItem item = sender as ToolStripMenuItem;
if (item == null) return;
// 普通二级模块点击不会改变当前功能导航,不要因此重做右侧布局。
if (!IsNavigationChangedSinceLastStyle()) return;
_selectedTopMenu = null;
RequestApplyWpfShellStyle();
}
private void TopMenuDropDownOpened(object sender, EventArgs e)
{
// 下拉菜单展开及二级目录移动期间,旧版会触发父容器重绘;
// 暂停右侧快捷通道的 WM_PAINT,避免看到中间清空状态。
SetShortcutRedraw(false);
}
private void TopMenuDropDownClosed(object sender, EventArgs e)
{
// 若目录切换已经排队,保持暂停到统一样式刷新完成,避免先显示中间状态。
if (_styleUpdatePending) return;
SetShortcutRedraw(true);
}
private void SetShortcutRedraw(bool enabled)
{
_shortcutRedrawSuppressed = !enabled;
Panel right = FindControl<Panel>("pl_center_main_right");
Panel container = FindControl<Panel>("pl_center_main_right_container");
SendRedrawMessage(right, enabled);
if (container != right) SendRedrawMessage(container, enabled);
if (enabled && !_styleUpdatePending)
{
if (right != null) right.Invalidate(true);
if (container != null) container.Invalidate(true);
}
}
private static void SendRedrawMessage(WinFormsControl control, bool enabled)
{
if (control == null || !control.IsHandleCreated) return;
SendMessage(control.Handle, 0x000B, new IntPtr(enabled ? 1 : 0), IntPtr.Zero);
}
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
private static ToolStripMenuItem FindCurrentTopMenu(MenuStrip menu)
{
// 设计器中旧控件尚未加载业务数据,不能触发 ERPInfo 的运行时初始化。
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) return null;
string currentName = (ERPInfo.Instance.SubSysName ?? string.Empty).Trim();
string currentId = (ERPInfo.Instance.SubSysId ?? string.Empty).Trim();
if (string.IsNullOrWhiteSpace(currentName) && string.IsNullOrWhiteSpace(currentId)) return null;
foreach (ToolStripMenuItem item in menu.Items.OfType<ToolStripMenuItem>())
{
if (MenuItemMatchesCurrent(item, currentName, currentId)) return item;
// “更多”中的目录仍属于顶部一级导航,命中子项时返回其顶层父项,
// 这样当前目录无论是否被收进下拉框都能保持顶部高亮。
foreach (ToolStripMenuItem child in item.DropDownItems.OfType<ToolStripMenuItem>())
{
if (MenuItemTreeMatchesCurrent(child, currentName, currentId)) return item;
}
}
return null;
}
private static bool MenuItemTreeMatchesCurrent(ToolStripMenuItem item, string currentName, string currentId)
{
if (MenuItemMatchesCurrent(item, currentName, currentId)) return true;
foreach (ToolStripMenuItem child in item.DropDownItems.OfType<ToolStripMenuItem>())
if (MenuItemTreeMatchesCurrent(child, currentName, currentId)) return true;
return false;
}
private static bool MenuItemMatchesCurrent(ToolStripMenuItem item, string currentName, string currentId)
{
if (!string.IsNullOrWhiteSpace(currentName)
&& string.Equals((item.Text ?? string.Empty).Trim(), currentName, StringComparison.OrdinalIgnoreCase))
return true;
DataRow row = item.Tag as DataRow;
string itemId = row != null && row.Table.Columns.Contains("subsysid")
? row["subsysid"] + ""
: item.Tag + "";
return !string.IsNullOrWhiteSpace(currentId)
&& string.Equals(itemId, currentId, StringComparison.OrdinalIgnoreCase);
}
private void SelectTopMenu(ToolStripMenuItem item)
{
if (item == null) return;
_selectedTopMenu = item;
MenuStrip menu = FindControl<MenuStrip>("menuMain");
if (menu == null) return;
foreach (ToolStripMenuItem top in menu.Items.OfType<ToolStripMenuItem>())
{
top.ForeColor = top == item ? Color.FromArgb(255, 214, 102) : Color.FromArgb(242, 246, 255);
top.Invalidate();
}
}
private void ResetBrandArea()
{
Panel brandArea = FindControl<Panel>("pl_top_left");
if (brandArea != null) brandArea.Width = 176;
WinFormsControl oldTitle = FindControl<WinFormsControl>("lblSubTitle");
if (oldTitle != null) oldTitle.Visible = false;
}
private void StyleSidebar()
{
Panel sidebar = FindControl<Panel>("pl_center_left");
if (sidebar == null) return;
// 新版侧栏对应旧程序的 MainLeftShowMode=1(分组树菜单)配置。
bool useGroupedSidebar = IsGroupedSidebarMode();
sidebar.Width = 176; sidebar.Padding = Padding.Empty; sidebar.BackColor = SidebarColor; sidebar.AutoScroll = true;
if (!useGroupedSidebar) return;
foreach (TreeList tree in FindControls<TreeList>(sidebar))
{
tree.Dock = DockStyle.Fill; tree.RowHeight = 44; tree.BackColor = SidebarColor;
tree.Appearance.Empty.BackColor = SidebarColor; tree.Appearance.Empty.Options.UseBackColor = true;
tree.Appearance.Row.BackColor = SidebarColor; tree.Appearance.Row.ForeColor = Color.FromArgb(235, 255, 255, 255);
tree.Appearance.Row.Font = new Font("微软雅黑", 10F); tree.Appearance.Row.Options.UseBackColor = true;
tree.Appearance.Row.Options.UseForeColor = true; tree.Appearance.Row.Options.UseFont = true;
tree.Appearance.FocusedRow.BackColor = SidebarSelectedColor; tree.Appearance.FocusedRow.ForeColor = Color.White;
tree.Appearance.FocusedRow.Options.UseBackColor = true; tree.Appearance.FocusedRow.Options.UseForeColor = true;
tree.Appearance.HideSelectionRow.BackColor = SidebarSelectedColor; tree.Appearance.HideSelectionRow.ForeColor = Color.White;
tree.Appearance.HideSelectionRow.Options.UseBackColor = true; tree.Appearance.HideSelectionRow.Options.UseForeColor = true;
tree.OptionsView.ShowColumns = false; tree.OptionsView.ShowIndicator = false; tree.OptionsView.ShowHorzLines = false; tree.OptionsView.ShowVertLines = false;
}
foreach (MenuBar menuBar in FindControls<MenuBar>(sidebar))
{
Button button = menuBar.GetButton(); menuBar.BackColor = SidebarColor; menuBar.Height = 44;
button.Dock = DockStyle.Fill; button.BackColor = SidebarColor; button.BackgroundImage = null;
button.FlatStyle = FlatStyle.Flat; button.FlatAppearance.BorderSize = 0;
button.FlatAppearance.MouseOverBackColor = Color.FromArgb(74, 80, 108); button.FlatAppearance.MouseDownBackColor = SidebarSelectedColor;
button.ForeColor = Color.FromArgb(235, 255, 255, 255); button.Font = new Font("微软雅黑", 10F);
button.TextAlign = ContentAlignment.MiddleLeft; button.Padding = new Padding(20, 0, 12, 0);
button.Click -= SidebarButton_Click;
button.Click += SidebarButton_Click;
}
}
private void SidebarButton_Click(object sender, EventArgs e)
{
Button selected = sender as Button;
if (selected == null) return;
Panel sidebar = FindControl<Panel>("pl_center_left");
foreach (Button button in FindControls<Button>(sidebar))
{
button.BackgroundImage = null;
button.BackColor = button == selected ? SidebarSelectedColor : SidebarColor;
}
}
private void StyleWorkspaceAndShortcuts()
{
Panel center = FindControl<Panel>("pl_center_main"); if (center != null) center.BackColor = WorkspaceColor;
Panel middle = FindControl<Panel>("pl_center_main_middle");
if (middle != null)
{
// 工作区外围使用 WPF 的 #F7F9FC,内部模块保持白色。
middle.BackColor = WorkspaceColor;
// 与“我的桌面”页签一致:页签底线下面立即进入内容区,
// 不再保留额外的顶部浅灰留白,只留下 1px 分隔边界。
middle.Padding = new Padding(20, 0, 20, 22);
AddWorkspaceContentDivider(middle);
}
Panel collect = FindControl<Panel>("collectPanel");
Panel all = FindControl<Panel>("allPanel");
Panel allMenu = FindControl<Panel>("allMenuPanel");
if (collect != null) collect.BackColor = Color.White;
if (all != null) all.BackColor = Color.White;
if (allMenu != null) allMenu.BackColor = Color.White;
if (SystemInfo.Instance.HideGallerys)
{
DisableShortcutChannel();
return;
}
Panel right = FindControl<Panel>("pl_center_main_right");
Panel rightContainer = FindControl<Panel>("pl_center_main_right_container");
EnableDoubleBuffer(right);
EnableDoubleBuffer(rightContainer);
if (rightContainer != null) { rightContainer.BackColor = Color.White; rightContainer.Padding = Padding.Empty; }
if (right != null) { right.BackColor = Color.White; right.Padding = new Padding(12); }
SplitContainer split = FindControl<SplitContainer>("splitMainControl");
if (split != null)
{
split.BackColor = WorkspaceColor;
split.SplitterWidth = 1;
if (split.Width > 177) split.SplitterDistance = Math.Max(176, split.Width - 240);
}
StyleShortcutSection("panel6", "lblShortcutset", "其它功能");
StyleShortcutSection("pl_center_main_bottom_right", "lblReportcutset", "最近使用");
foreach (SimpleControl shortcut in FindControls<SimpleControl>(this)) StyleShortcut(shortcut);
foreach (TableLayoutPanel table in FindControls<TableLayoutPanel>(rightContainer)) EnableDoubleBuffer(table);
ResizeShortcutSections();
}
private static void AddWorkspaceContentDivider(Panel middle)
{
Panel divider = middle.Controls.Find("wpfWorkspaceContentDivider", false)
.OfType<Panel>().FirstOrDefault();
if (divider == null)
{
divider = new Panel
{
Name = "wpfWorkspaceContentDivider",
Height = 1,
BackColor = Color.FromArgb(199, 211, 228),
Enabled = false,
TabStop = false,
Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right
};
middle.Controls.Add(divider);
}
// 内容区紧贴页签栏时,分隔线固定在内容区最顶部;独立控件
// 不会被 DevExpress 页签或模块内容的重绘覆盖。
divider.Location = new Point(0, Math.Max(0, middle.Padding.Top - divider.Height));
divider.Width = Math.Max(0, middle.ClientSize.Width);
divider.BringToFront();
}
private void DisableShortcutChannel()
{
SplitContainer split = FindControl<SplitContainer>("splitMainControl");
if (split != null)
{
split.Panel2.VisibleChanged -= ShortcutPanel_VisibleChanged;
split.Panel2.VisibleChanged += ShortcutPanel_VisibleChanged;
split.SizeChanged -= ShortcutHost_SizeChanged;
split.SizeChanged += ShortcutHost_SizeChanged;
}
EnsureShortcutChannelHidden();
// 释放旧控件 OnLoad 中已创建的快捷通道控件;后续因 HideGallerys=true
// 不会再从目录切换逻辑中生成这部分界面。
DisposeChildControls(FindControl<Panel>("pl_center_main_bottom_right_main"));
DisposeChildControls(FindControl<Panel>("pl_center_main_bottom_left_main"));
DisposeChildControls(FindControl<Panel>("workTopPanel"));
DisposeChildControls(FindControl<Panel>("workBottomPanel"));
ClearLegacyCollection("topLayoutPanelDic");
ClearLegacyCollection("botLayoutPanelDic");
ClearLegacyCollection("_quickPageHeaders");
}
private void ShortcutPanel_VisibleChanged(object sender, EventArgs e)
{
if (!_shortcutChannelDisabled || _enforcingShortcutHidden || !IsHandleCreated) return;
BeginInvoke((MethodInvoker)EnsureShortcutChannelHidden);
}
private void ShortcutHost_SizeChanged(object sender, EventArgs e)
{
if (_shortcutChannelDisabled) EnsureShortcutChannelHidden();
}
private void EnsureShortcutChannelHidden()
{
if (!_shortcutChannelDisabled || _enforcingShortcutHidden) return;
_enforcingShortcutHidden = true;
try
{
SplitContainer split = FindControl<SplitContainer>("splitMainControl");
Panel panel = FindControl<Panel>("panel5");
Panel container = FindControl<Panel>("pl_center_main_right_container");
Panel right = FindControl<Panel>("pl_center_main_right");
// 同时隐藏内部旧面板并折叠 SplitContainer,防止旧版页签/布局事件
// 将 Panel2Collapsed 恢复后再次露出“快捷操作通道”。
if (right != null) right.Visible = false;
if (container != null) container.Visible = false;
if (panel != null) panel.Visible = false;
if (split != null && !split.Panel2Collapsed) split.Panel2Collapsed = true;
}
finally
{
_enforcingShortcutHidden = false;
}
}
private static void DisposeChildControls(WinFormsControl parent)
{
if (parent == null || parent.Controls.Count == 0) return;
WinFormsControl[] children = parent.Controls.Cast<WinFormsControl>().ToArray();
parent.Controls.Clear();
foreach (WinFormsControl child in children) child.Dispose();
}
private void ClearLegacyCollection(string fieldName)
{
try
{
FieldInfo field = typeof(MainPanelControlEx).GetField(
fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
IDictionary dictionary = field == null ? null : field.GetValue(_legacyPanel) as IDictionary;
if (dictionary != null) dictionary.Clear();
}
catch (Exception)
{
// 清理缓存失败不影响右侧面板隐藏。
}
}
private static void EnableDoubleBuffer(WinFormsControl control)
{
if (control == null) return;
try
{
PropertyInfo property = typeof(WinFormsControl).GetProperty(
"DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
if (property != null && property.CanWrite) property.SetValue(control, true, null);
}
catch (Exception)
{
// 某些旧版控件不允许修改 DoubleBuffered,不影响正常显示。
}
}
private void ResizeShortcutSections()
{
Panel first = FindControl<Panel>("pl_center_main_bottom_left");
Panel firstContent = FindControl<Panel>("pl_center_main_bottom_right_main");
Panel second = FindControl<Panel>("pl_center_main_bottom_right");
Panel secondContent = FindControl<Panel>("pl_center_main_bottom_left_main");
if (firstContent != null)
{
EnableDoubleBuffer(firstContent);
firstContent.BackColor = Color.White;
firstContent.Padding = new Padding(0, 4, 0, 0);
TableLayoutPanel table = firstContent.Controls.OfType<TableLayoutPanel>().FirstOrDefault();
if (table != null && first != null) first.Height = Math.Max(84, table.Height + 46);
}
if (secondContent != null)
{
EnableDoubleBuffer(secondContent);
secondContent.BackColor = Color.White;
secondContent.Padding = new Padding(0, 4, 0, 0);
TableLayoutPanel table = secondContent.Controls.OfType<TableLayoutPanel>().FirstOrDefault();
if (table != null && second != null) second.Height = Math.Max(84, table.Height + 46);
}
}
private void StyleShortcutSection(string panelName, string titleName, string title)
{
Panel panel = FindControl<Panel>(panelName); Label label = FindControl<Label>(titleName);
if (panel != null) { panel.BackColor = Color.White; panel.Height = 42; panel.Padding = new Padding(4, 0, 0, 0); }
if (label != null) { label.Text = title; label.Tag = title; label.BackColor = Color.White; label.ForeColor = Color.FromArgb(36, 136, 223); label.Font = new Font("微软雅黑", 10F, FontStyle.Bold); label.TextAlign = ContentAlignment.MiddleLeft; label.Padding = new Padding(4, 0, 0, 0); }
}
private void StyleShortcut(SimpleControl shortcut)
{
shortcut.Height = 56; shortcut.Margin = Padding.Empty; shortcut.BackColor = Color.White; shortcut.Padding = new Padding(4, 1, 0, 1); shortcut.Cursor = Cursors.Hand;
shortcut.PicBox.Width = 34; shortcut.PicBox.BackColor = Color.White; shortcut.PicBox.BackgroundImageLayout = ImageLayout.Center;
shortcut.Label.Font = new Font("微软雅黑", 9F); shortcut.Label.ForeColor = Color.FromArgb(55, 68, 84); shortcut.Label.BackColor = Color.White;
shortcut.Label.TextAlign = ContentAlignment.MiddleLeft; shortcut.Label.Padding = new Padding(7, 0, 18, 0); shortcut.Label.AutoEllipsis = true;
DataRow row = shortcut.Label.Tag as DataRow;
if (row != null)
{
string caption = row.Table.Columns.Contains("menucaption") ? row["menucaption"] + "" : shortcut.Label.Text;
string group = row.Table.Columns.Contains("groupcaption") ? row["groupcaption"] + "" : string.Empty;
if (string.IsNullOrWhiteSpace(group)) group = "常用功能";
shortcut.Label.Text = caption + Environment.NewLine + group;
}
TableLayoutPanel table = shortcut.Parent as TableLayoutPanel;
if (table != null)
{
table.AutoSize = true;
table.AutoSizeMode = AutoSizeMode.GrowAndShrink;
table.Dock = DockStyle.Top;
int rowIndex = table.GetRow(shortcut);
if (rowIndex >= 0 && rowIndex < table.RowStyles.Count)
{
table.RowStyles[rowIndex].SizeType = SizeType.Absolute;
table.RowStyles[rowIndex].Height = shortcut.Height;
}
table.BackColor = Color.White;
}
shortcut.Paint -= Shortcut_Paint; shortcut.Paint += Shortcut_Paint;
}
private void Shortcut_Paint(object sender, PaintEventArgs e)
{
SimpleControl shortcut = sender as SimpleControl; if (shortcut == null) return;
using (Pen pen = new Pen(ShortcutBorderColor)) e.Graphics.DrawLine(pen, 0, shortcut.Height - 1, shortcut.Width, shortcut.Height - 1);
using (Pen pen = new Pen(Color.FromArgb(150, 137, 164, 197), 1.5F))
{
int x = Math.Max(0, shortcut.Width - 9), y = shortcut.Height / 2;
e.Graphics.DrawLine(pen, x - 3, y - 4, x + 1, y); e.Graphics.DrawLine(pen, x + 1, y, x - 3, y + 4);
}
}
private T FindControl<T>(string name) where T : WinFormsControl { return Controls.Find(name, true).OfType<T>().FirstOrDefault(); }
private static IEnumerable<T> FindControls<T>(WinFormsControl root) where T : WinFormsControl
{
if (root == null) yield break;
foreach (WinFormsControl child in root.Controls)
{
T typed = child as T; if (typed != null) yield return typed;
foreach (T nested in FindControls<T>(child)) yield return nested;
}
}
private sealed class WpfMenuRenderer : ToolStripProfessionalRenderer
{
private readonly Color _header;
private readonly Func<ToolStripMenuItem> _activeMenuProvider;
public WpfMenuRenderer(Color header, Func<ToolStripMenuItem> activeMenuProvider)
{
_header = header;
_activeMenuProvider = activeMenuProvider;
}
protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
{
// 只改变顶层 MenuStrip 的背景;下拉菜单交回 WinForms 默认渲染。
if (e.ToolStrip is MenuStrip) e.Graphics.Clear(_header);
else base.OnRenderToolStripBackground(e);
}
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
{
ToolStripMenuItem item = e.Item as ToolStripMenuItem; if (item == null) return;
// 下拉框恢复旧版默认效果,不使用 WPF 顶部导航的高亮绘制。
if (!(e.ToolStrip is MenuStrip))
{
base.OnRenderMenuItemBackground(e);
return;
}
// Selected/Pressed 只表示鼠标状态,鼠标移开后会被 WinForms 清除。
// 高亮必须跟随当前功能导航(ERPInfo.SubSysName)持续显示。
string currentName = LicenseManager.UsageMode == LicenseUsageMode.Designtime
? string.Empty
: (ERPInfo.Instance.SubSysName ?? string.Empty).Trim();
bool current = _activeMenuProvider != null && item == _activeMenuProvider();
if (!current)
current = !string.IsNullOrWhiteSpace(currentName)
&& string.Equals((item.Text ?? string.Empty).Trim(), currentName, StringComparison.OrdinalIgnoreCase);
bool hover = (item.Selected || item.Pressed) && !current;
// 当前目录只使用黄色文字和下划线,不再绘制浅色选中背景;
// 其它目录鼠标悬浮时仍保留背景反馈。
item.ForeColor = current
? Color.FromArgb(255, 214, 102)
: Color.FromArgb(242, 246, 255);
Rectangle r = new Rectangle(Point.Empty, item.Size);
if (hover)
{
using (Brush brush = new SolidBrush(Color.FromArgb(42, 88, 164)))
e.Graphics.FillRectangle(brush, r);
}
if (current)
{
using (Brush brush = new SolidBrush(Color.FromArgb(255, 214, 102)))
e.Graphics.FillRectangle(brush, 2, r.Bottom - 3, Math.Max(1, r.Width - 4), 2);
}
}
}
#endregion
}
}