# -*- coding: utf-8 -*- """ 事件/逻辑代码迁移:旧项目 主窗口*.cs + 对话框 → 新项目(停靠面板版)。 策略:能复制就复制,只做三类最小改动: 1) namespace MyApp → 成套报价软件;partial class 主窗口 → MainForm 2) 旧构造函数拆到 MainForm.cs(加 CreateDockWindows/Load 接线) 3) 停靠窗口控件在 MainForm 上生成公开别名属性(this.xxx 继续可用) 旧 ui.cs 尾部的 SQLite 加载方法一并带过来。 """ import io import os import re import sys HERE = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, HERE) import migrate_ui as mu SRC_DIR = os.path.dirname(mu.SRC) DST = mu.DST_PROJECT def read(p): return io.open(p, encoding="utf-8-sig").read() def write(p, s): io.open(p, "w", encoding="utf-8-sig", newline="\r\n").write(s) def rename_common(s): s = s.replace("namespace MyApp", "namespace 成套报价软件") s = s.replace("public partial class 主窗口", "public partial class MainForm") return s # ---------------------------------------------------------------- 1) 别名文件 def gen_aliases(): text = read(mu.SRC) decls, begin_inits, blocks, top, edges, ts_edges = mu.parse(text) ctrl_blocks, form_block = mu.classify(blocks) ch = mu.build_children(edges) decl_types = dict(decls) # MainForm 自身已有成员(避免别名冲突) taken = set(["tabControl1", "tabPage1", "tabPage2", "tabPage3", "tabPage4", "tabPage5", "tabPage6", "statusStrip1", "dockSurface1", "components", "InitializeComponent", "CreateDockWindows_dockSurface1", "DockSurface1ActiveContentChanged"]) for n, _t in decls: if n in mu.subtree("tabControl1", ch) or n in mu.subtree("statusStrip1", ch): taken.add(n) wfields = [] props = [] for idx, (cls, tab, title) in enumerate(mu.DOCK_MAP, 1): members = mu.subtree(tab, ch) members.remove(tab) mset = set(members) ordered = [n for n, _t in decls if n in mset] for parent, kids in ts_edges: if parent in mset: ordered += [k for k in kids if k not in ordered] wfields.append("\t\tinternal %s w%d;" % (cls, idx)) for n in ordered: if n in taken: print("!! 别名冲突跳过:", n) continue props.append("\t\tpublic %s %s { get { return w%d.%s; } }" % (decl_types[n], n, idx, n)) taken.add(n) L = [] a = L.append a("// 旧 主窗口 逻辑代码通过 this.<控件名> 访问控件;") a("// 控件已迁入 9 个停靠窗口,这里用别名属性转发,逻辑代码无需改动。") a("// 停靠窗口实例字段由 MainForm.dockSurface1.DockWindows.cs 在创建后赋值。") a("namespace 成套报价软件") a("{") a("\tpublic partial class MainForm") a("\t{") L.extend(wfields) a("") L.extend(props) a("\t}") a("}") write(os.path.join(DST, "MainForm.控件别名.cs"), "\n".join(L)) print("生成 MainForm.控件别名.cs:实例字段 %d 个,别名属性 %d 个" % (len(wfields), len(props))) # ---------------------------------------------------------------- 2) 停靠窗口字段改 public def publify_fields(): pat = re.compile(r"\t\tprivate (?!System\.ComponentModel\.IContainer)([\w.]+) ([\w\u4e00-\u9fff]+);") for cls, _tab, _title in mu.DOCK_MAP: p = os.path.join(DST, "DockWindows", cls, cls + ".Designer.cs") s = read(p) s2, n = pat.subn(r"\t\tpublic \1 \2;", s) write(p, s2) print("%s: %d 个字段改为 public" % (cls, n)) # ---------------------------------------------------------------- 3) 记录停靠窗口实例 def patch_dockwindows_cs(): p = os.path.join(DST, "DockWindows", "MainForm.dockSurface1.DockWindows.cs") s = read(p) n = 0 for idx, (cls, _tab, _title) in enumerate(mu.DOCK_MAP, 1): old = "var w%d = new %s();" % (idx, cls) new = old + "\n\t\t\tthis.w%d = w%d;" % (idx, idx) if old in s and new not in s: s = s.replace(old, new) n += 1 write(p, s) print("MainForm.dockSurface1.DockWindows.cs: 接线 %d 处" % n) # ---------------------------------------------------------------- 4) MainForm.cs + 主窗口.cs def split_main(): src = read(os.path.join(SRC_DIR, "主窗口.cs")) lines = src.split("\n") ctor_start = None for i, l in enumerate(lines): if re.match(r"\s*public 主窗口\(\)", l): ctor_start = i break assert ctor_start is not None, "找不到旧构造函数" # ctor 结束:InitSelectionPage(); 后的第一个 ' }' ctor_end = None for i in range(ctor_start, len(lines)): if "InitSelectionPage();" in lines[i]: for j in range(i, min(i + 5, len(lines))): if lines[j].strip() == "}": ctor_end = j break break assert ctor_end is not None, "找不到构造函数结束" usings = [l for l in lines[:ctor_start] if l.startswith("using ")] ctor_body = lines[ctor_start + 3:ctor_end] # 跳过签名/{/InitializeComponent(); # 新 MainForm.cs L = [] a = L.append a("/*") a(" * 由SharpDevelop创建。") a(" * 用户: 099978") a(" * 日期: 2026-08-25") a(" *") a(" * 主窗体构造函数(由旧项目 主窗口.cs 迁移)。") a(" */") L.extend(usings) a("") a("namespace 成套报价软件") a("{") a("\t/// ") a("\t/// 主窗体:构造函数迁移自旧项目 主窗口.cs(事件挂接全部保留)。") a("\t/// ") a("\tpublic partial class MainForm : Form") a("\t{") a("\t\tpublic MainForm()") a("\t\t{") a("\t\t\tInitializeComponent();") a("\t\t\tCreateDockWindows_dockSurface1();") a("") a("\t\t\t// 旧 ui.cs 设计器注入的 SQLite 数据加载(Load 事件)") a("\t\t\tthis.Load += (s, e) => LoadAllSqliteData();") a("") L.extend(ctor_body) a("") a("\t\tvoid DockSurface1ActiveContentChanged(object sender, EventArgs e)") a("\t\t{") a("") a("\t\t}") a("\t}") a("}") write(os.path.join(DST, "MainForm.cs"), "\n".join(L)) # 主窗口.cs(去掉构造函数的其余逻辑) rest = lines[:ctor_start] + [" // 构造函数已迁至 MainForm.cs", ""] + lines[ctor_end + 1:] write(os.path.join(DST, "主窗口.cs"), rename_common("\n".join(rest))) print("生成 MainForm.cs 与 主窗口.cs(构造函数 %d-%d 行)" % (ctor_start + 1, ctor_end + 1)) # ---------------------------------------------------------------- 5) 其余 partial 与工具类 def copy_partials(): files = ["主窗口.菜单与库.cs", "主窗口.公式重算.cs", "主窗口.母排与备份.cs", "主窗口.项目导入导出.cs", "价格格式化.cs"] for f in files: write(os.path.join(DST, f), rename_common(read(os.path.join(SRC_DIR, f)))) print("复制", f) # ---------------------------------------------------------------- 6) ui.cs 尾部 SQLite 加载 def port_sqlite_tail(): lines = read(mu.SRC).split("\n") start = None for i, l in enumerate(lines): if "加载所有 SQLite 设计数据绑定" in l: start = i break assert start is not None tail = lines[start:] while tail and tail[-1].strip() in ("}", ""): tail.pop() L = ["// 旧 主窗口.ui.cs 尾部的 SQLite 设计数据加载方法(设计器注入,逻辑不变)。"] L.append("namespace 成套报价软件") L.append("{") L.append("\tpublic partial class MainForm") L.append("\t{") L.extend(tail) L.append("\t}") L.append("}") write(os.path.join(DST, "主窗口.SQLite加载.cs"), "\n".join(L)) print("生成 主窗口.SQLite加载.cs(%d 行)" % len(tail)) # ---------------------------------------------------------------- 7) 对话框 DIALOGS = [ ("xiangmu", ["新建项目", "修改项目", "甲方报表", "调系数", "导入报价", "元件排序", "调母排"]), ("shezhi", ["企业信息"]), ("ku", ["用户库元件编辑"]), ("GCS母排计算", ["GCS母排计算窗口", "GCS推荐铜排窗口"]), ] def copy_dialogs(): for sub, names in DIALOGS: for name in names: for ext in (".cs", ".ui.cs"): s = read(os.path.join(SRC_DIR, sub, name + ext)) s = rename_common(s) # 类型引用 主窗口 → MainForm(注释里的中文连写不受影响) s = re.sub(r"主窗口(?=[\s\.\)\[_,;])", "MainForm", s) dst_sub = os.path.join(DST, sub) if not os.path.isdir(dst_sub): os.makedirs(dst_sub) write(os.path.join(dst_sub, name + ext), s) print("复制", sub + "\\" + name + ext) # ---------------------------------------------------------------- 8) csproj CSPROJ_COMPILE = [ "主窗口.cs", "主窗口.菜单与库.cs", "主窗口.公式重算.cs", "主窗口.母排与备份.cs", "主窗口.项目导入导出.cs", "主窗口.SQLite加载.cs", "MainForm.控件别名.cs", "价格格式化.cs", ] for sub, names in DIALOGS: for name in names: CSPROJ_COMPILE.append(sub + "\\" + name + ".cs") CSPROJ_COMPILE.append(sub + "\\" + name + ".ui.cs") LIB_REFS = [ "System.Data.SQLite", "NPOI", "NPOI.OOXML", "NPOI.OpenXml4Net", "NPOI.OpenXmlFormats", "DotNetZip", "ICSharpCode.SharpZipLib", "unvell.ReoGrid", "CJZZ.Controls", ] def patch_csproj(): p = os.path.join(DST, "成套报价软件.csproj") s = read(p) s = s.replace("x86", "x64") # System.Data.SQLite 从 SD bin(x86) 改为 lib\x64 版 s = re.sub( r"\s*.*?\s*", lambda m: '\n lib\\System.Data.SQLite.dll\n True\n ', s, flags=re.S) # 追加 lib 引用(插到 WeifenLuo.ThemeVS2015 引用块之后) ref_xml = "" for name in LIB_REFS: ref_xml += ' \n lib\\%s.dll\n True\n \n' % (name, name) ref_xml += ' \n \n' anchor = "\n " idx = s.rfind(anchor) s = s[:idx + len("\n")] + ref_xml + " " + s[idx + len(anchor):] # 追加 Compile 条目 comp_xml = "" for f in CSPROJ_COMPILE: comp_xml += ' \n' % f anchor2 = ' ' s = s.replace(anchor2, comp_xml + anchor2) write(p, s) print("csproj 已更新(x64 + %d 引用 + %d 编译项)" % (len(LIB_REFS) + 2, len(CSPROJ_COMPILE))) # ---------------------------------------------------------------- 9) verify_build.rsp def gen_rsp(): L = ["# csc 编译验证(UTF-8)", "/target:winexe", "/platform:x64", "/utf8output", "/nologo", "/warn:0", "/out:bin\\Debug\\成套报价软件.exe"] for fw in ["System.dll", "System.Core.dll", "System.Data.dll", "System.Drawing.dll", "System.Windows.Forms.dll", "System.Xml.dll", "System.IO.Compression.dll", "System.IO.Compression.FileSystem.dll"]: L.append("/r:" + fw) for name in ["Smart.CustomComponents", "WeifenLuo.WinFormsUI.Docking", "WeifenLuo.WinFormsUI.Docking.ThemeVS2015"]: L.append('/r:"C:\\Program Files (x86)\\SharpDevelop\\5.2\\bin\\%s.dll"' % name) for name in ["AdvancedDataGridView", "Microsoft.Web.WebView2.Core", "Microsoft.Web.WebView2.WinForms"] + LIB_REFS: L.append('/r:"lib\\%s.dll"' % name) for f in ["MainForm.cs", "MainForm.Designer.cs", "Program.cs", "Properties\\AssemblyInfo.cs"] + CSPROJ_COMPILE: L.append(f) for cls, _t, _ti in mu.DOCK_MAP: L.append("DockWindows\\%s\\%s.cs" % (cls, cls)) L.append("DockWindows\\%s\\%s.Designer.cs" % (cls, cls)) L.append("DockWindows\\MainForm.dockSurface1.DockWindows.cs") write(os.path.join(HERE, "verify_build.rsp"), "\n".join(L) + "\n") print("verify_build.rsp 已重新生成") if __name__ == "__main__": gen_aliases() publify_fields() patch_dockwindows_cs() split_main() copy_partials() port_sqlite_tail() copy_dialogs() patch_csproj() gen_rsp() print("完成")