{"id":10020998,"date":"2025-09-09T21:14:37","date_gmt":"2025-09-09T13:14:37","guid":{"rendered":"https:\/\/itmax.cn\/?p=10020998"},"modified":"2025-09-09T21:14:37","modified_gmt":"2025-09-09T13:14:37","slug":"%e5%be%ae%e4%bf%a1%e7%94%b5%e8%84%91%e7%89%884-1-x%e6%9c%80%e6%96%b0%e7%89%88%e8%8e%b7%e5%8f%96%e6%9c%aa%e8%af%bb%e6%b6%88%e6%81%af%e5%b9%b6%e5%9c%a8%e5%8f%b3%e4%b8%8b%e8%a7%92%e5%bc%b9%e5%87%ba","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10020998","title":{"rendered":"\u5fae\u4fe1\u7535\u8111\u72484.1.X\u6700\u65b0\u7248\u83b7\u53d6\u672a\u8bfb\u6d88\u606f\u5e76\u5728\u53f3\u4e0b\u89d2\u5f39\u51fa\u63d0\u9192"},"content":{"rendered":"<h2>\u6458\u8981<\/h2>\n<p>\u5fae\u4fe14.1\u7248\u672c\u7684UI\u91c7\u7528\u65b0\u7684\u6846\u67b6\u5f00\u53d1\uff0c\u80fd\u591f\u83b7\u53d6\u5230\u7684\u4fe1\u606f\u6709\u9650\uff0c\u76ee\u524d\u53ea\u80fd\u83b7\u53d6\u5230\u6d88\u606f\u5217\u8868\u7684\u63a7\u4ef6\u5185\u5bb9\u3002<\/p>\n<h2>\u4ee3\u7801<\/h2>\n<pre><code>import time\nimport threading\nimport uiautomation as auto\nfrom win10toast import ToastNotifier\nimport tkinter as tk\nfrom tkinter import ttk\nimport re\n\nshown_msgs = set()\nFILE_NAME = &quot;messages.txt&quot;\n\nimport re\n\ndef parse_chat_name_flexible(raw_name: str):\n    &quot;&quot;&quot;\n    \u7075\u6d3b\u89e3\u6790\u5fae\u4fe1\u672a\u8bfb\u6d88\u606f\uff0c\u5e76\u53bb\u6389\u3010\u6d88\u606f\u514d\u6253\u6270\u3011\u5b57\u6837\u548c\u65b9\u62ec\u53f7\u4e2d\u7684\u672a\u8bfb\u6570\n    &quot;&quot;&quot;\n    if not raw_name:\n        return None\n\n    # \u53bb\u6389\u6d88\u606f\u514d\u6253\u6270\n    raw_name = re.sub(r'[\/[\/(\u3010\uff08]*\u6d88\u606f\u514d\u6253\u6270[\/]\/)\u3011\uff09]*', '', raw_name)\n\n    parts = raw_name.split()\n    if len(parts) &lt; 2:\n        return None\n\n    user = parts[0]\n    unread = &quot;0\u6761\u672a\u8bfb&quot;\n    msg = &quot;&quot;\n    sender = &quot;&quot;\n    time_str = &quot;&quot;\n\n    start_idx = 1\n\n    # \u5df2\u7f6e\u9876\n    if &quot;\u5df2\u7f6e\u9876&quot; in parts:\n        start_idx += 1\n\n    # \u67e5\u627e\u672a\u8bfb\u6761\u6570\n    for i in range(start_idx, min(start_idx + 2, len(parts))):\n        if &quot;\u6761\u672a\u8bfb&quot; in parts[i]:\n            unread = parts[i]\n            start_idx = i + 1\n            break\n\n    # \u67e5\u627e\u65f6\u95f4\n    for i in range(len(parts) - 1, start_idx - 1, -1):\n        if ':' in parts[i] or '\/' in parts[i]:\n            time_str = parts[i]\n            end_idx = i\n            break\n    else:\n        end_idx = len(parts)\n\n    msg_parts = parts[start_idx:end_idx]\n    msg = &quot; &quot;.join(msg_parts)\n\n    # \u62c6\u5206\u53d1\u9001\u4eba\u548c\u6d88\u606f\u5185\u5bb9\n    if &quot;:&quot; in msg:\n        sender, msg_content = msg.split(&quot;:&quot;, 1)\n    elif &quot;\uff1a&quot; in msg:  # \u4e2d\u6587\u5192\u53f7\n        sender, msg_content = msg.split(&quot;\uff1a&quot;, 1)\n    else:\n        sender, msg_content = &quot;&quot;, msg\n\n    # \u6e05\u7406\u53d1\u9001\u4eba\u91cc\u7684 [n\u6761]\n    sender = re.sub(r'\/[\/d+\u6761\/]', '', sender).strip()\n\n    return {\n        &quot;user&quot;: user.strip(),\n        &quot;unread&quot;: unread.strip(),\n        &quot;sender&quot;: sender.strip(),\n        &quot;msg&quot;: msg_content.strip(),\n        &quot;time&quot;: time_str.strip()\n    }\n\n\ndef find_unread_sessions():\n    desktop = auto.GetRootControl()\n    chat_cells = []\n\n    for control, depth in auto.WalkControl(desktop):\n        if control.ClassName == &quot;mmui::ChatSessionCell&quot;:\n            if &quot;\u672a\u8bfb&quot; in (control.Name or &quot;&quot;):\n                parsed = parse_chat_name_flexible(control.Name)\n                if parsed:\n                    chat_cells.append(parsed)\n\n    return chat_cells\n\n\ndef monitor_messages(tree):\n    # \u786e\u4fdd\u5b50\u7ebf\u7a0b\u6b63\u786e\u521d\u59cb\u5316 COM\n    with auto.UIAutomationInitializerInThread():\n        toaster = ToastNotifier()\n        while True:\n            try:\n                sessions = find_unread_sessions()\n\n                for s in sessions:\n                    key = f&quot;{s['user']}_{s['msg']}_{s['time']}&quot;\n                    if key not in shown_msgs:\n                        title = f&quot;{s['user']} ({s['unread']})&quot;\n                        msg = f&quot;{s['msg']}  [{s['time']}]&quot;\n                        print(f&quot;[\u901a\u77e5] {title} -&gt; {msg}&quot;)\n\n                        # \u7cfb\u7edf\u901a\u77e5\n                        toaster.show_toast(title, msg, duration=3, threaded=True)\n\n                        # \u5199\u5165txt\n                        with open(FILE_NAME, &quot;a&quot;, encoding=&quot;utf-8&quot;) as f:\n                            f.write(f&quot;{s['time']}\/t{s['user']}\/t{s['unread']}\/t{s['sender']}\/t{s['msg']}\/n&quot;)\n\n                        # \u66f4\u65b0\u8868\u683c\n                        tree.after(0, lambda s=s: tree.insert(\n                            &quot;&quot;, &quot;end&quot;,\n                            values=(s['time'], s['user'], s['unread'], s['sender'], s['msg'])\n                        ))\n\n                        shown_msgs.add(key)\n\n            except Exception as e:\n                print(f&quot;[\u9519\u8bef] {e}&quot;)\n\n            time.sleep(2)\n\n\ndef start_gui():\n    root = tk.Tk()\n    root.title(&quot;\u5fae\u4fe1\u672a\u8bfb\u6d88\u606f\u76d1\u63a7&quot;)\n    root.geometry(&quot;1200x550&quot;)\n\n    style = ttk.Style(root)\n    style.theme_use(&quot;default&quot;)\n    style.configure(&quot;Treeview&quot;, rowheight=30, font=(&quot;Microsoft YaHei&quot;, 11))\n    style.configure(&quot;Treeview.Heading&quot;, font=(&quot;Microsoft YaHei&quot;, 12, &quot;bold&quot;), anchor=&quot;center&quot;)\n\n    # \u65b0\u589e sender \u5217\n    columns = (&quot;time&quot;, &quot;user&quot;, &quot;unread&quot;, &quot;sender&quot;, &quot;msg&quot;)\n    tree = ttk.Treeview(root, columns=columns, show=&quot;headings&quot;)\n    tree.heading(&quot;time&quot;, text=&quot;\u65f6\u95f4&quot;)\n    tree.heading(&quot;user&quot;, text=&quot;\u7528\u6237&quot;)\n    tree.heading(&quot;unread&quot;, text=&quot;\u672a\u8bfb&quot;)\n    tree.heading(&quot;sender&quot;, text=&quot;\u53d1\u9001\u4eba&quot;)\n    tree.heading(&quot;msg&quot;, text=&quot;\u6d88\u606f\u5185\u5bb9&quot;)\n\n    # \u8bbe\u7f6e\u5217\u5bbd\u548c\u5bf9\u9f50\n    tree.column(&quot;time&quot;, width=100, anchor=&quot;center&quot;)\n    tree.column(&quot;user&quot;, width=120, anchor=&quot;center&quot;)\n    tree.column(&quot;unread&quot;, width=80, anchor=&quot;center&quot;)\n    tree.column(&quot;sender&quot;, width=120, anchor=&quot;center&quot;)\n    tree.column(&quot;msg&quot;, width=500, anchor=&quot;center&quot;)\n\n    # \u6eda\u52a8\u6761\n    scrollbar = ttk.Scrollbar(root, orient=&quot;vertical&quot;, command=tree.yview)\n    tree.configure(yscroll=scrollbar.set)\n    scrollbar.pack(side=&quot;right&quot;, fill=&quot;y&quot;)\n\n    tree.pack(fill=&quot;both&quot;, expand=True)\n\n    # \u542f\u52a8\u540e\u53f0\u7ebf\u7a0b\n    t = threading.Thread(target=monitor_messages, args=(tree,), daemon=True)\n    t.start()\n\n    root.mainloop()\n\nif __name__ == &quot;__main__&quot;:\n    start_gui()<\/code><\/pre>\n<h2>\u4f7f\u7528<\/h2>\n<p>\u9700\u8981\u5c06\u5fae\u4fe1\u6253\u5f00\uff0c\u4e0d\u80fd\u5173\u95ed\uff0c\u53ef\u6700\u5c0f\u5316\uff0c\u4f46\u7edd\u5bf9\u4e0d\u80fd\u53c9\u6389\u3002<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"723\" height=\"176\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVdmqs8\" alt=\"image.png\" title=\"image.png\"><\/p>\n<p>\u7136\u540e\u5141\u8bb8\u8fd9\u4e2aPython\u811a\u672c\u5373\u53ef\u3002<\/p>\n<pre><code>Python wxmsg.py<\/code><\/pre>\n<p>\u76ee\u524d\u652f\u6301\u7684\u529f\u80fd\uff1a<\/p>\n<ol>\n<li>\u8bfb\u53d6\u79c1\u4fe1\u672a\u8bfb\u7684\u6700\u65b0\u7684\u90a3\u6761\u6d88\u606f<\/li>\n<li>\u8bfb\u53d6\u7fa4\u6700\u65b0\u7684\u672a\u8bfb\u7684\u90a3\u6761\u6d88\u606f<\/li>\n<li>\u8bfb\u53d6\u6700\u65b0\u7684\u6536\u6b3e\u8bb0\u5f55<\/li>\n<li>\u4f1a\u5728\u53f3\u4e0b\u89d2\u5f39\u51fa<\/li>\n<li>\u4f1a\u6709ui\u754c\u9762\uff0c\u8bb0\u5f55\u6d88\u606f<\/li>\n<li>\u8bfb\u53d6\u516c\u4f17\u53f7\u6700\u65b0\u53d1\u5e03\u7684\u6d88\u606f<\/li>\n<\/ol>\n<h2>\u754c\u9762<\/h2>\n<p><img decoding=\"async\" width=\"723\" height=\"458\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVdmqtA\" alt=\"image.png\" title=\"image.png\" loading=\"lazy\"><\/p>\n<h2>\u4f5c\u8005<\/h2>\n<p>TANKING<\/p>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000047251654\">https:\/\/segmentfault.com\/a\/1190000047251654<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u6458\u8981 \u5fae\u4fe14.1\u7248\u672c\u7684UI\u91c7\u7528\u65b0\u7684\u6846\u67b6\u5f00\u53d1\uff0c\u80fd\u591f\u83b7\u53d6\u5230\u7684\u4fe1\u606f\u6709\u9650\uff0c\u76ee\u524d\u53ea\u80fd\u83b7\u53d6\u5230\u6d88\u606f\u5217\u8868\u7684\u63a7\u4ef6\u5185\u5bb9\u3002 \u4ee3\u7801 i [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-10020998","post","type-post","status-publish","format-standard","hentry","category-share"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10020998","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10020998"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10020998\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10020998"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10020998"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10020998"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}