python 调用C#的dll文件并创建一个托盘图标
使用前需要先安装库
pip install pythonnet
.NET API 浏览器 System.Windows.Forms.NotifyIcon 类
WPF入门之WPF加载和编译xaml
import os
import sys
import clr
import sys
import threading
import pythoncom
from pathlib import Path
def add_WPF_PATH():
sysdll = clr.FindAssembly('System')
if sysdll is not None:
framework_path , name = os.path.split(sysdll)
WPF_path = framework_path+'\\WPF'
if WPF_path not in sys.path:
sys.path.append(str(WPF_path))
add_WPF_PATH()
import time
import threading
import queue
import ctypes
import pprint
ctypes.windll.shcore.SetProcessDpiAwareness(1)
pprint.pprint(sys.path)
# 非常重要,不能省略
import System
__cs_name = [
'System',
# System.Windows.Window 在 PresentationFramework之中
'PresentationFramework',
'System.Windows',
'System.Console',
'System.Drawing',
'System.Windows',
'System.IO',
'System.Windows.Forms',
# 'Python.Runtime'
# 'WindowsBase',
# 'System.Windows.Threading',
# 'System.Windows.Window',
# 'System.Windows.Markup',
]
def func1(_name) -> None:
try:
clr.FindAssembly(_name)
except:
print('FindAssembly异常', _name)
try:
clr.AddReference(_name)
except:
print('AddReference异常', _name)
list(map(func1, __cs_name))
# 正式开始使用dll 中的方法了,这里要重点说一下,在使用C# 中的方法之前呢也需要先实例化一下类,然后方可使用类中的所有方法:
# 也可以
# from System.Windows.Forms import Form,NotifyIcon,ContextMenu,MenuItem,Application,FormWindowState
Form = System.Windows.Forms.Form
NotifyIcon = System.Windows.Forms.NotifyIcon
ContextMenu = System.Windows.Forms.ContextMenu
MenuItem = System.Windows.Forms.MenuItem
Application = System.Windows.Forms.Application
FormWindowState = System.Windows.Forms.FormWindowState
XamlReader = System.Windows.Markup.XamlReader
XamlWriter = System.Windows.Markup.XamlWriter
# FileStream = System.IO.FileStream
FileMode = System.IO.FileMode
Assembly = System.Reflection.Assembly
Dispatcher = System.Windows.Threading.Dispatcher
ApartmentState = System.Threading.ApartmentState
ThreadState = System.Threading.ThreadState
class FileStream(System.IO.FileStream):
'''System.IO.FileStream with Context manager support'''
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
# Context manager support
def __enter__(self):
return self
def __exit__(self, *args):
self.Dispose()
class MemoryStream(System.IO.MemoryStream):
'''System.IO.MemoryStream with Context manager support'''
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
# Context manager support
def __enter__(self):
return self
def __exit__(self, *args):
self.Dispose()
class Form1(Form):
''' '''
def __init__(self) -> None:
''''''
super().__init__()
self.tray_exit = False
# 设置Form的方法
self.FormClosing += System.Windows.Forms.FormClosingEventHandler(self.OnFormClosing)
self.FormClosed += System.EventHandler(self.OnFormClosed)
# // Set up how the form should be displayed.
self.ClientSize = System.Drawing.Size(600, 300)
self.Text = "Notify Icon Example"
# 创建其他内部控件
self.components = System.ComponentModel.Container()
self.contextMenu1 = System.Windows.Forms.ContextMenu()
self.menuItem1 = System.Windows.Forms.MenuItem()
# Initialize contextMenu1
# self.contextMenu1.MenuItems.AddRange([self.menuItem1])
self.contextMenu1.MenuItems.Add(self.menuItem1)
# // Initialize menuItem1
self.menuItem1.Index = 0
self.menuItem1.Text = "退出程序(&Q)"
self.menuItem1.Click += System.EventHandler(self.menuItem1_Click)
# // Create the NotifyIcon.
self.notifyIcon1 = System.Windows.Forms.NotifyIcon(self.components)
# // The Icon property sets the icon that will appear
# // in the systray for self application.
notifyIcon1 = self.notifyIcon1
notifyIcon1.Icon = self.Icon
# // The ContextMenu property sets the menu that will
# // appear when the systray icon is right clicked.
notifyIcon1.ContextMenu = self.contextMenu1
# // The Text property sets the text that will be displayed,
# // in a tooltip, when the mouse hovers over the systray icon.
notifyIcon1.Text = "Form1 (NotifyIcon example)"
notifyIcon1.Visible = True
# // Handle the DoubleClick event to activate the form.
notifyIcon1.DoubleClick += System.EventHandler(self.notifyIcon1_DoubleClick)
# notifyIcon1.DoubleClick += self.notifyIcon1_DoubleClick
def Dispose(self, disposing):
# // Clean up any components being used.
print('清除资源')
if disposing:
if (self.components != None):
self.components.Dispose()
super().Dispose(disposing)
def OnFormClosing(self, sender, e):
'''
object : sender
FormClosingEventArgs : e
'''
# 可以在窗口的FormClosing事件中加上e.Cancel=true这句话,来阻止窗口关闭,从而实现隐藏窗口的效果。这种方法可以通过点击窗口的默认关闭按钮来调用。 blog.csdn.net
self.WindowState = FormWindowState.Minimized
self.Hide()
if not self.tray_exit:
e.Cancel = True
print('窗口已经隐藏')
else:
e.Cancel = False
def OnFormClosed(self, sender, e):
# 在用户或Application类的Close方法或Exit方法关闭窗体后,会发生FormClosed事件。可以使用此事件释放窗体的一些资源
print('程序准备退出')
self.Dispose(True)
def notifyIcon1_DoubleClick(self, Sender, e):
# // Show the form when the user double clicks on the notify icon.
# // Set the WindowState to normal if the form is minimized.
print('双击')
self.Show()
if self.WindowState == FormWindowState.Minimized:
self.WindowState = FormWindowState.Normal
# // Activate the form.
self.Activate()
def menuItem1_Click(self, Sender, e):
# private void menuItem1_Click(object Sender, EventArgs e)
# // Close the form, which closes the application.
print('单击了托盘退出')
self.tray_exit = True
self.Close()
base_window = '''<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />'''
test_xaml = '''<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Label Name="Lb1" Content="Label" HorizontalAlignment="Left" Margin="44,33,0,0" VerticalAlignment="Top"/>
<Button Name="Btn1" Content="Button" HorizontalAlignment="Left" Margin="44,76,0,0" VerticalAlignment="Top"/>
</Grid>'''
class WPF_Window(System.Windows.Window):
''''''
def __init__(self) -> None:
super().__init__()
self.Width = 400
self.Height = 400
self.Left = self.Top = 400
self.Title = "动态创建的元素"
rootElement: System.Windows.DependencyObject
# with FileStream(r'D:\test.xaml', FileMode.Open) as fs:
# rootElement = XamlReader.Load(fs)
buffer = System.Text.Encoding.UTF8.GetBytes(test_xaml)
with MemoryStream(buffer) as fs:
rootElement = XamlReader.Load(fs)
self.Content = rootElement
# rootElement.FindName("Btn1").Click += self.Button_Click
rootElement.FindName("Btn1").Click += System.EventHandler(self.Button_Click)
# self.ShowDialog()
# self.win_xaml = XamlWriter.Save(self)
def Button_Click(self, sender, e):
# def Button_Click(self,object sender, RoutedEventArgs e):
print('单击了按钮')
# WPF1 = WPF_Window()
# WPF1.Show()
class w1(threading.Thread):
'''线程类'''
def __init__(self) -> None:
threading.Thread.__init__(self)
self.daemon = True
def run(self):
# 初始化线程的Apartment状态为STA
pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED)
Application.Run(Form1())
class w2(threading.Thread):
'''线程类'''
def __init__(self) -> None:
threading.Thread.__init__(self)
self.daemon = True
def run(self):
# 初始化线程的Apartment状态为STA
pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED)
self.WPF1 = WPF_Window()
self.WPF1.ShowDialog()
# app = System.Windows.Application()
# app.Run(self.WPF1)
print('窗口结束')
W1 = w1()
W2 = w2()
W1.start()
W2.start()
W1.join()
W2.join()
System.Console.Write('应用程序结束\n')
pass