精华内容
下载资源
问答
  • vc2010 启动后2秒最小化到托盘任务栏没有) 托盘左键双击,任务栏有并显示 托盘右击,出菜单 界面最小到托盘任务栏没有) 界面关闭则退出 感谢lingxiu0613,在原有的基础上增强.
  • outlook2016点击关闭后最小化到任务栏。亲测有效!!!!
  • 这是一个任务栏图标的小程序,用Delphi实现了程序最小化到托盘中的功能,实现托盘闪烁功能。当然你也可以用WINDOW API来实现,但是这个例子的实现实在非常简单,实现了托盘功能的傻瓜式开发。太牛逼了。
  • 教会你怎样把程序最小化到托盘,给你一个最容易实现的方法!!!!!!!!!!!
  • 点击最小化按钮最小化到托盘事件,易语言托盘图标的应用。
  • PB12.5最小化到托盘,powerbuilder12.5最小化到托盘最小化后,会在右下角显示图标,双击右下角图标即可还原窗口
  • winform最小化到任务栏

    2014-06-14 10:22:41
    winform最小化到任务栏,两种方式。可以自行修改
  • 我用的是outlook 2013,(一定要以管理员身份运行) 先点击“文件“-”选项”进入, 再打开的选项窗体中,找到”加载项”, 最下边的CoM加载项右边有一个”转(G)...”,点击一下 点”添加”选择一个相应的dll。
  • 【Qt】程序最小化托盘显示及操作(自己网上学习实践操作整理的资料) 1、QT界面最小化显示右下角托盘 2、点击恢复界面操作 3、右键菜单选择操作
  • 仿QQ方式,通过快捷键方式(我设置的是Ctrl+Alt+E,可以随意修改),将应用程序在正常状态和最小化托盘状态进行切换。
  • 安装这个outlook2016插件后,当点击软件右上角的关闭按钮后,会自动最小化到右下角的任务栏中,而不是直接关闭软件,能省去重复登陆的麻烦。已在64位windows10系统 outlook2016中测试通过。安装说明:运行ReliefJet...
  • 2. 点击右上角x键可以显示提示信息且按钮功能正常(退出程序或者最小化到托盘); 3. 最小化到托盘后实现两个功能(左键单击显示或隐藏主界面,右键显示显示选线可以关闭或者显示主界面,); 1. 首先用...

    这个程序主要完成几个目的:

    1. 主窗口控件最小化等操作后正常可用(点击按钮会在textBrowser中加入一行hello world);

    2. 点击右上角x键可以显示提示信息且按钮功能正常(退出程序或者最小化到托盘);

    3. 最小化到托盘后实现两个功能(左键单击显示或隐藏主界面,右键显示显示选线可以关闭或者显示主界面,);

     

    1. 首先用designer新建了一个demo,这个demo上只有两个控件,一个是textBrowser,一个是pushButton,直接从designer侧边拖就行了。

    有空还可以设置下图标之类的。

    总之整体界面长这样。

    然后将这个界面换成py文件。

    2. 新建一个主函数文件,随笔起个名字就叫demo.py吧

    主要功能就是把这个设计的界面启动起来

    #coding = 'utf-8'
    import sys
    from PyQt5 import QtCore, QtGui, QtWidgets
    import Ui_untitled
    import time
     
    # 函数功能:在textBrowser中添加hello world字段
    # 输入参数:ui对象
    # 输出参数:
    def buttonClicked(girl):
        girl.textBrowser.append("hello world")
     
    if __name__ == '__main__':
        # 创建一个应用对象
        app = QtWidgets.QApplication(sys.argv)
        # 创建QT主窗口对象
        MainWindow = QtWidgets.QMainWindow()
        # 创建UI对象
        ui = Ui_untitled.Ui_MainWindow()
        # 调用setupUi方法,将设计好的界面-->主窗口上
        ui.setupUi(MainWindow)
     
        ui.pushButton.clicked.connect(lambda:buttonClicked(ui))
     
        # 显示一个非模式的对话框,用户可以随便切窗口,.exec()是模式对话框,用户不能随便切
        MainWindow.show()
        # 
        sys.exit(app.exec_())

    然后这个自动生成ui的py文件长这样

    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file 'c:\My_World\gitee_code\qt_toolkit\hello_world\untitled.ui'
    #
    # Created by: PyQt5 UI code generator 5.15.0
    #
    # WARNING: Any manual changes made to this file will be lost when pyuic5 is
    # run again.  Do not edit this file unless you know what you are doing.
    
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.setObjectName("MainWindow")
            MainWindow.resize(800, 600)
            icon = QtGui.QIcon()
            icon.addPixmap(QtGui.QPixmap("c:\\My_World\\gitee_code\\qt_toolkit\\hello_world\\sys-user.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
            MainWindow.setWindowIcon(icon)
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
            self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
            self.textBrowser.setGeometry(QtCore.QRect(160, 110, 256, 192))
            self.textBrowser.setObjectName("textBrowser")
            self.pushButton = QtWidgets.QPushButton(self.centralwidget)
            self.pushButton.setGeometry(QtCore.QRect(570, 190, 75, 23))
            self.pushButton.setObjectName("pushButton")
            MainWindow.setCentralWidget(self.centralwidget)
            self.menubar = QtWidgets.QMenuBar(MainWindow)
            self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
            self.menubar.setObjectName("menubar")
            MainWindow.setMenuBar(self.menubar)
            self.statusbar = QtWidgets.QStatusBar(MainWindow)
            self.statusbar.setObjectName("statusbar")
            MainWindow.setStatusBar(self.statusbar)
    
            self.retranslateUi(MainWindow)
            QtCore.QMetaObject.connectSlotsByName(MainWindow)
    
        def retranslateUi(self, MainWindow):
            _translate = QtCore.QCoreApplication.translate
            MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
            self.pushButton.setText(_translate("MainWindow", "PushButton"))
    

    3. 添加托盘图标功能

    这个具体可以看这个https://blog.csdn.net/marwenx/article/details/107200049

    主要就是我们要新建一个类,专门搞这个托盘功能的。

    class TrayIcon(QtWidgets.QSystemTrayIcon):
        def __init__(self,MainWindow,parent=None):
            super(TrayIcon, self).__init__(parent)
            self.ui = MainWindow
            self.createMenu()
        
        def createMenu(self):
            self.menu = QtWidgets.QMenu()
            self.showAction1 = QtWidgets.QAction("启动", self, triggered=self.show_window)
            self.showAction2 = QtWidgets.QAction("显示通知", self,triggered=self.showMsg)
            self.quitAction = QtWidgets.QAction("退出", self, triggered=self.quit)
    
            self.menu.addAction(self.showAction1)
            self.menu.addAction(self.showAction2)
            self.menu.addAction(self.quitAction)
            self.setContextMenu(self.menu)
    
            #设置图标
            self.setIcon(QtGui.QIcon("c:\\My_World\\gitee_code\\qt_toolkit\\hello_world\\sys-user.png"))
            self.icon = self.MessageIcon()
    
            #把鼠标点击图标的信号和槽连接
            self.activated.connect(self.onIconClicked)
    
        def showMsg(self):
            self.showMessage("Message", "skr at here", self.icon)
    
        def show_window(self):
            #若是最小化,则先正常显示窗口,再变为活动窗口(暂时显示在最前面)
            self.ui.showNormal()
            self.ui.activateWindow()
            
     
        def quit(self):
            QtWidgets.qApp.quit()
    
        #鼠标点击icon传递的信号会带有一个整形的值,1是表示单击右键,2是双击,3是单击左键,4是用鼠标中键点击
        def onIconClicked(self, reason):
            if reason == 2 or reason == 3:
                # self.showMessage("Message", "skr at here", self.icon)
                if self.ui.isMinimized() or not self.ui.isVisible():
                    #若是最小化,则先正常显示窗口,再变为活动窗口(暂时显示在最前面)
                    self.ui.showNormal()
                    self.ui.activateWindow()
                    self.ui.setWindowFlags(QtCore.Qt.Window)
                    self.ui.show()
                else:
                    #若不是最小化,则最小化
                    self.ui.showMinimized()
                    self.ui.setWindowFlags(QtCore.Qt.SplashScreen)
                    self.ui.show()
                    # self.ui.show()

    这个类实现了托盘的几个功能,首先是初始化时创建一个托盘的按钮和图标,并且createMenu方法中创建了三个右键的功能菜单。

    4. 右上角关闭按钮的提示功能和最小化到托盘中的功能。需要重写下closeEvent方法,所以这里创建一个新类。

    class Dialog(QtWidgets.QMainWindow):
        def __init__(self,MainWindow,parent=None):
            super(Dialog, self).__init__(parent)
        def closeEvent(self, event):
            reply = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Question, self.tr("提示"), self.tr("汝妻子我养之,汝勿虑之。\n 汝特么确定要退出吗?"), QtWidgets.QMessageBox.NoButton, self)
            yr_btn = reply.addButton(self.tr("是的我要退出"), QtWidgets.QMessageBox.YesRole)
            reply.addButton(self.tr("最小化到托盘"), QtWidgets.QMessageBox.NoRole)
            reply.exec_()
            if reply.clickedButton() == yr_btn:
                event.accept()
                QtWidgets.qApp.quit()
                # sys.exit(app.exec_())
            else:
                event.ignore()
                # 最小化到托盘
                MainWindow.setWindowFlags(QtCore.Qt.SplashScreen | QtCore.Qt.FramelessWindowHint)
                MainWindow.showMinimized()
    
            # 默认直接调用QMessageBox.question 弹出询问的方法
            # reply = QtWidgets.QMessageBox.question(self,
            #                                        '本程序',
            #                                        "是否要退出程序?",
            #                                        QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No)
            # if reply == QtWidgets.QMessageBox.Yes:
            #     event.accept()
            # elif reply == QtWidgets.QMessageBox.No:
            #     event.ignore()
            #     MainWindow.setWindowFlags(QtCore.Qt.SplashScreen | QtCore.Qt.FramelessWindowHint)
            #     MainWindow.showMinimized()
            # else:
            #     # 最小化到托盘
            #     MainWindow.setWindowFlags(QtCore.Qt.SplashScreen | QtCore.Qt.FramelessWindowHint)
            #     MainWindow.showMinimized()

    类中有两种办法显示这个提示功能,第二种方法被注释了。

    详见:https://mp.csdn.net/console/editor/html/107226531

    这个类完成了两个功能,一个是将关闭按钮加入了提示功能,一个是在提示信息中加入最小化到托盘的功能。

    5. 写一个main。

    if __name__ == '__main__':
        # 创建一个应用对象
        app = QtWidgets.QApplication(sys.argv)
        # 创建QT主窗口对象
        MainWindow = QtWidgets.QMainWindow()
        # 创建UI对象
        ui = Ui_untitled.Ui_MainWindow()
        MainWindow = Dialog(MainWindow)
        # 调用setupUi方法,将设计好的界面-->主窗口上
        ui.setupUi(MainWindow)
    
        MainWindow.setWindowFlags(QtCore.Qt.Window)
        # MainWindow.setWindowFlags(QtCore.Qt.WindowTitleHint)
        
        ui.pushButton.clicked.connect(lambda:buttonClicked(ui))
        # min_tray(ui)
        # 显示一个非模式的对话框,用户可以随便切窗口,.exec()是模式对话框,用户不能随便切
        MainWindow.show()
    
        ti = TrayIcon(MainWindow)
        ti.show()
        
        # 结束程序
        sys.exit(app.exec_())

    这个main函数需要一步一步解释了,大部分的解释我都写成了注释在代码中,不过还是有几行要解释下。

    MainWindow = QtWidgets.QMainWindow()
    MainWindow = Dialog(MainWindow)

    之所以MainWindow会在创建对象时又作为参数传入,是因为想要这个最小化到托盘的功能,所以首先用QtWidgets.QMainWindow()创建一个主窗口对象,将这个对象作为参数再传入到我们重写方法(提示信息和最小化到托盘功能)的类中,这个类又是继承QtWidgets.QMainWindow()这个类的,所以最终的MainWindow对象是重写了方法的QtWidgets.QMainWindow()类对象。

    我不擅长面向对象,一般都是写面向过程解决,这个方法有点笨,大家应该有更好的办法解决。

     

    所以整个代码就是这个样子的

    首先是demo.py文件

    #coding = 'utf-8'
    import sys
    from PyQt5 import QtCore, QtGui, QtWidgets
    import Ui_untitled
    import time
    
    # 函数功能:在textBrowser中添加hello world字段
    # 输入参数:ui对象
    # 输出参数:
    def buttonClicked(girl):
        girl.textBrowser.append("hello world")
    
    class TrayIcon(QtWidgets.QSystemTrayIcon):
        def __init__(self,MainWindow,parent=None):
            super(TrayIcon, self).__init__(parent)
            self.ui = MainWindow
            self.createMenu()
        
        def createMenu(self):
            self.menu = QtWidgets.QMenu()
            self.showAction1 = QtWidgets.QAction("启动", self, triggered=self.show_window)
            self.showAction2 = QtWidgets.QAction("显示通知", self,triggered=self.showMsg)
            self.quitAction = QtWidgets.QAction("退出", self, triggered=self.quit)
    
            self.menu.addAction(self.showAction1)
            self.menu.addAction(self.showAction2)
            self.menu.addAction(self.quitAction)
            self.setContextMenu(self.menu)
    
            #设置图标
            self.setIcon(QtGui.QIcon("c:\\My_World\\gitee_code\\qt_toolkit\\hello_world\\sys-user.png"))
            self.icon = self.MessageIcon()
    
            #把鼠标点击图标的信号和槽连接
            self.activated.connect(self.onIconClicked)
    
        def showMsg(self):
            self.showMessage("Message", "skr at here", self.icon)
    
        def show_window(self):
            #若是最小化,则先正常显示窗口,再变为活动窗口(暂时显示在最前面)
            self.ui.showNormal()
            self.ui.activateWindow()
            
     
        def quit(self):
            QtWidgets.qApp.quit()
    
        #鼠标点击icon传递的信号会带有一个整形的值,1是表示单击右键,2是双击,3是单击左键,4是用鼠标中键点击
        def onIconClicked(self, reason):
            if reason == 2 or reason == 3:
                # self.showMessage("Message", "skr at here", self.icon)
                if self.ui.isMinimized() or not self.ui.isVisible():
                    #若是最小化,则先正常显示窗口,再变为活动窗口(暂时显示在最前面)
                    self.ui.showNormal()
                    self.ui.activateWindow()
                    self.ui.setWindowFlags(QtCore.Qt.Window)
                    self.ui.show()
                else:
                    #若不是最小化,则最小化
                    self.ui.showMinimized()
                    self.ui.setWindowFlags(QtCore.Qt.SplashScreen)
                    self.ui.show()
                    # self.ui.show()
    
    class Dialog(QtWidgets.QMainWindow):
        def __init__(self,MainWindow,parent=None):
            super(Dialog, self).__init__(parent)
        def closeEvent(self, event):
            reply = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Question, self.tr("提示"), self.tr("汝妻子我养之,汝勿虑之。\n 汝特么确定要退出吗?"), QtWidgets.QMessageBox.NoButton, self)
            yr_btn = reply.addButton(self.tr("是的我要退出"), QtWidgets.QMessageBox.YesRole)
            reply.addButton(self.tr("最小化到托盘"), QtWidgets.QMessageBox.NoRole)
            reply.exec_()
            if reply.clickedButton() == yr_btn:
                event.accept()
                QtWidgets.qApp.quit()
                # sys.exit(app.exec_())
            else:
                event.ignore()
                # 最小化到托盘
                MainWindow.setWindowFlags(QtCore.Qt.SplashScreen | QtCore.Qt.FramelessWindowHint)
                MainWindow.showMinimized()
    
            # 默认直接调用QMessageBox.question 弹出询问的方法
            # reply = QtWidgets.QMessageBox.question(self,
            #                                        '本程序',
            #                                        "是否要退出程序?",
            #                                        QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No)
            # if reply == QtWidgets.QMessageBox.Yes:
            #     event.accept()
            # elif reply == QtWidgets.QMessageBox.No:
            #     event.ignore()
            #     MainWindow.setWindowFlags(QtCore.Qt.SplashScreen | QtCore.Qt.FramelessWindowHint)
            #     MainWindow.showMinimized()
            # else:
            #     # 最小化到托盘
            #     MainWindow.setWindowFlags(QtCore.Qt.SplashScreen | QtCore.Qt.FramelessWindowHint)
            #     MainWindow.showMinimized()
                
                
    
    
    
    if __name__ == '__main__':
        # 创建一个应用对象
        app = QtWidgets.QApplication(sys.argv)
        # 创建QT主窗口对象
        MainWindow = QtWidgets.QMainWindow()
        # 创建UI对象
        ui = Ui_untitled.Ui_MainWindow()
        MainWindow = Dialog(MainWindow)
        # 调用setupUi方法,将设计好的界面-->主窗口上
        ui.setupUi(MainWindow)
    
        MainWindow.setWindowFlags(QtCore.Qt.Window)
        # MainWindow.setWindowFlags(QtCore.Qt.WindowTitleHint)
        
        ui.pushButton.clicked.connect(lambda:buttonClicked(ui))
        # min_tray(ui)
        # 显示一个非模式的对话框,用户可以随便切窗口,.exec()是模式对话框,用户不能随便切
        MainWindow.show()
    
        ti = TrayIcon(MainWindow)
        ti.show()
        
        # 结束程序
        sys.exit(app.exec_())

    然后是这个自动生成的ui的py文件

    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file 'c:\My_World\gitee_code\qt_toolkit\hello_world\untitled.ui'
    #
    # Created by: PyQt5 UI code generator 5.15.0
    #
    # WARNING: Any manual changes made to this file will be lost when pyuic5 is
    # run again.  Do not edit this file unless you know what you are doing.
    
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.setObjectName("MainWindow")
            MainWindow.resize(800, 600)
            icon = QtGui.QIcon()
            icon.addPixmap(QtGui.QPixmap("c:\\My_World\\gitee_code\\qt_toolkit\\hello_world\\sys-user.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
            MainWindow.setWindowIcon(icon)
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
            self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
            self.textBrowser.setGeometry(QtCore.QRect(160, 110, 256, 192))
            self.textBrowser.setObjectName("textBrowser")
            self.pushButton = QtWidgets.QPushButton(self.centralwidget)
            self.pushButton.setGeometry(QtCore.QRect(570, 190, 75, 23))
            self.pushButton.setObjectName("pushButton")
            MainWindow.setCentralWidget(self.centralwidget)
            self.menubar = QtWidgets.QMenuBar(MainWindow)
            self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
            self.menubar.setObjectName("menubar")
            MainWindow.setMenuBar(self.menubar)
            self.statusbar = QtWidgets.QStatusBar(MainWindow)
            self.statusbar.setObjectName("statusbar")
            MainWindow.setStatusBar(self.statusbar)
    
            self.retranslateUi(MainWindow)
            QtCore.QMetaObject.connectSlotsByName(MainWindow)
    
        def retranslateUi(self, MainWindow):
            _translate = QtCore.QCoreApplication.translate
            MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
            self.pushButton.setText(_translate("MainWindow", "PushButton"))
    

    运行这个demo.py文件,就可以完成之前设计的功能。

    展开全文
  • C# 系统应用之窗体最小化任务栏,同时在系统托盘区的图标点击左键能显示窗体,右键能关联控件显示3个常用功能最小化任务栏并在系统托盘区留下图标,
  • MFC窗口最小化到托盘,文档中有详细的函数介绍,以及实际例子的代码,及详细步骤
  • 对于GUI程序,如果想要实现当最小化时,程序从任务栏消失,在系统托盘显示一个图标,表示此程序,并能在托盘内通过双击或者菜单使程序界面恢复。
  • outlook 关闭时最小化到任务栏的完美解决方法-附件资源
  • 资源效果及讲解博客地址:http://blog.csdn.net/csnd_ayo/article/details/56004234
  • Unity程序需要监听鼠标点击标题右上角最小化和关闭事件 winform程序需要单例运行(同一时间只允许一个程序允许) Unity程序启动时,同时启动winform程序 2.2 实现 2.2.1 Unity程序监听最小化和关闭事


    更好的实现方式,见这里
    下面这种方式可以废弃了。


    1 基本效果

    基本功能

    • 点击关闭,不直接关闭,缩小到托盘
    • 托盘图标上可打开、隐藏和关闭程序

    效果展示:
    点击最小化和关闭缩小到托盘
    托盘上可最大、最小化以及关闭程序

    2 代码实现

    2.1 思路

    • 两个程序,Unity一个程序,winform一个程序
    • winform程序用来生成托盘图标,并且控制Unity程序的最大、最小化及关闭
    • Unity程序需要监听到鼠标点击标题栏右上角最小化和关闭事件
    • winform程序需要单例运行(同一时间只允许一个程序运行)
    • Unity程序启动时,同时启动winform程序

    2.2 实现

    2.2.1 Unity程序监听最小化和关闭事件

    通过监听windows系统的api来实现的,就废话少说了,具体代码如下。
    用到的Win32 Api引入。
    这里需要注意一下的是,引入FindWindow这个方法时,最好把 CharSet设置为Unicode。如果Untiy打包的程序名是中文,又没设置CharSet为Unicode,调用此函数很可能查找不到窗体。我之前就遇到死活找不到窗体,坑惨了。

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern IntPtr FindWindow(string lpszClass, string lpszTitle);
    

    WinUser32.cs

    /**
    *┌──────────────────────────────────────────────────────────────┐
    *│ 描   述:                                                    
    *│ 作   者:wangying                                                                                           
    *│ 创建时间:2021/2/28 10:33:02   
    *│ 作者blog: http://www.laowangomg.com                       
    *└──────────────────────────────────────────────────────────────┘
    */
    
    
    using System;
    using System.Runtime.InteropServices;
    
    namespace UnityWin
    {
        public delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
    
        class WinUser32
        {
            // Ref:
            // https://docs.microsoft.com/zh-cn/windows/win32/winmsg/about-windows#desktop-window
            // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
            public const int SW_HIDE = 0;
            public const int SW_MAXIMIZE = 3;
            public const int SW_SHOW = 0;
            public const int SW_MINIMIZE = 6;
            public const int SW_RESTORE = 9;
    
            // https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-showwindow?redirectedfrom=MSDN
            public const int WM_SYSCOMMAND = 0x0112;
            public const int SC_CLOSE = 0xF060;
            public const int SC_MAXIMIZE = 0xF030;
            public const int SC_MINIMIZE = 0xF020;
    
            public const int GWL_EXSTYLE = -0x14;
            public const int WS_EX_TOOLWINDOW = 0x0080;
            public const int WS_EX_APPWINDOW = 0x00040000;
    
    
            [DllImport("user32.dll")]
            public static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);
    
            [DllImport("user32.dll", CharSet = CharSet.Unicode)]
            public static extern IntPtr FindWindow(string lpszClass, string lpszTitle);
    
            [DllImport("user32.dll")]
            public static extern IntPtr GetActiveWindow();
            [DllImport("User32.dll")]
            public static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);
    
            [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
            private static extern int SetWindowLong32(HandleRef hWnd, int nIndex, int dwNewLong);
            [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
            private static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, int nIndex, IntPtr dwNewLong);
            [DllImport("user32.dll", EntryPoint = "DefWindowProcA")]
            public static extern IntPtr DefWindowProc(IntPtr hWnd, uint wMsg, IntPtr wParam, IntPtr lParam);
            // 将消息信息传递给指定的窗口过程
            [DllImport("user32.dll")]
            public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
            [DllImport("user32.dll")]
            public static extern bool IsIconic(IntPtr hWnd);
            [DllImport("user32.dll")]
            public static extern bool IsZoomed(IntPtr hWnd);
    
            public static IntPtr GetWindow(string titleOrClassname)
            {
                IntPtr hWnd = FindWindow(null, titleOrClassname); ;
                if (hWnd == IntPtr.Zero)
                {
                    hWnd = FindWindow(titleOrClassname, null); 
                }
    
                return hWnd;
            }
    
            public static IntPtr SetWindowLongPtr(HandleRef hWnd, int nIndex, IntPtr dwNewLong)
            {
                if (IntPtr.Size == 8)
                    return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
                else
                {
                    return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32()));
                }
            }
    
            // 展示任务栏
            public static void ShowTaskWnd()
            {
                ShowWindow(FindWindow("Shell_TrayWnd", null), SW_RESTORE);
            }
    
            // 隐藏任务栏
            public static void HideTaskWnd()
            {
                ShowWindow(FindWindow("Shell_TrayWnd", null), SW_HIDE);
            }
    
            // 展示任务栏上的图标 TODO:有问题
            public static void ShowTaskIcon(string titleOrClassname)
            {
                // https://stackoverflow.com/questions/1462504/how-to-make-window-appear-in-taskbar
                IntPtr mainWindIntPtr = GetWindow(titleOrClassname);
                if (mainWindIntPtr != IntPtr.Zero)
                {
                    HandleRef pMainWindow = new HandleRef(null, mainWindIntPtr);
                    SetWindowLongPtr(pMainWindow, GWL_EXSTYLE, (IntPtr)(GetWindowLong(mainWindIntPtr, GWL_EXSTYLE).ToInt32() | WS_EX_APPWINDOW));
    
                    ShowWindow(mainWindIntPtr, SW_HIDE);
                    ShowWindow(mainWindIntPtr, SW_SHOW);
                }
            }
    
            // 隐藏任务栏上的图标 TODO:有问题
            public static void HideTaskIcon(string titleOrClassname)
            {
                // https://forum.unity.com/threads/can-the-taskbar-icon-of-a-unity-game-be-hidden.888625/?_ga=2.191055082.1747733629.1614429624-1257832814.1586182347#post-5838658
                // https://docs.microsoft.com/en-us/windows/win32/shell/taskbar#managing-taskbar-buttons
                IntPtr mainWindIntPtr = GetWindow(titleOrClassname);
                if (mainWindIntPtr != IntPtr.Zero)
                {
                    HandleRef pMainWindow = new HandleRef(null, mainWindIntPtr);
                    SetWindowLongPtr(pMainWindow, GWL_EXSTYLE, (IntPtr)(GetWindowLong(mainWindIntPtr, GWL_EXSTYLE).ToInt32() | WS_EX_TOOLWINDOW));
    
                    ShowWindow(mainWindIntPtr, SW_HIDE);
                    ShowWindow(mainWindIntPtr, SW_SHOW);
                }
            }
    
        }
    }
    
    

    监听最小化和关闭事件。
    AppStart.cs

    using Lavender.Systems;
    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    using UnityEngine;
    using UnityWin;
    
    public class AppStart : MonoBehaviour
    {
        #region Unity_Method
        private void Start()
        {
            Init();
        }
    
        private void OnDestroy()
        {
            TermWndProc();
        }
    
        private void OnGUI()
        {
            // TODO:有bug
            if (GUI.Button(new Rect(20, 20, 100, 30), "显示任务栏图标"))
            {
                WinUser32.ShowTaskIcon(AppConst.AppName);
            }
            if (GUI.Button(new Rect(20, 60, 100, 30), "隐藏任务栏图标"))
            {
                WinUser32.HideTaskIcon(AppConst.AppName);
            }
        }
    
    
        #endregion
    
        private void Init()
        {
            Screen.SetResolution(AppConst.DefaultWidth, AppConst.DefaultHeight, false);
    
            InitWndProc();
            WinUser32.ShowWindow(WinUser32.GetWindow(AppConst.AppName), WinUser32.SW_HIDE);
    
    #if UNITY_STANDALONE
            // https://github.com/josh4364/IL2cppStartProcess
    
            var processPath = Directory.GetCurrentDirectory() + "\\UnityWinNotify\\UnityWinNotify.exe";
            if (File.Exists(processPath))
            {
                uint ptr = StartExternalProcess.Start(processPath, Directory.GetCurrentDirectory());
            }
    #endif
    
        }
    
        #region 监听窗体事件
    
        private HandleRef hMainWindow;
        private static IntPtr oldWndProcPtr;
        private IntPtr newWndProcPtr;
        private WndProcDelegate newWndProc;
    
        public void InitWndProc()
        {
            hMainWindow = new HandleRef(null, WinUser32.GetWindow(AppConst.AppName));
            newWndProc = new WndProcDelegate(WndProc);
            newWndProcPtr = Marshal.GetFunctionPointerForDelegate(newWndProc);
            oldWndProcPtr = WinUser32.SetWindowLongPtr(hMainWindow, -4, newWndProcPtr);
    
        }
        public void TermWndProc()
        {
            WinUser32.SetWindowLongPtr(hMainWindow, -4, oldWndProcPtr);
            hMainWindow = new HandleRef(null, IntPtr.Zero);
            oldWndProcPtr = IntPtr.Zero;
            newWndProcPtr = IntPtr.Zero;
            newWndProc = null;
        }
    
        [MonoPInvokeCallback]
        private static IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
        {
            if (msg == WinUser32.WM_SYSCOMMAND)
            {
                if ((int)wParam == WinUser32.SC_CLOSE)
                {
                    // 关闭
                    WinUser32.ShowWindow(hWnd, WinUser32.SW_HIDE);
                    return IntPtr.Zero;
                }
                else if ((int)wParam == WinUser32.SC_MAXIMIZE)
                {
                    // 最大化
                }
                else if ((int)wParam == WinUser32.SC_MINIMIZE)
                {
                    // 最小化
                    WinUser32.ShowWindow(hWnd, WinUser32.SW_HIDE);
                    return IntPtr.Zero;
                }
            }
    
            //Debug.Log("WndProc msg:0x" + msg.ToString("x4") + " wParam:0x" + wParam.ToString("x4") + " lParam:0x" + lParam.ToString("x4"));
            return WinUser32.CallWindowProc(oldWndProcPtr, hWnd, msg, wParam, lParam);
        }
    
        #endregion
    
    }
    
    

    2.2.2 方便打包的菜单栏

    方便打包的菜单栏
    BuildTool.cs

    using System.Diagnostics;
    using System.IO;
    using UnityEditor;
    using UnityEditor.Build.Reporting;
    using UnityEngine;
    using UnityWin;
    using Debug = UnityEngine.Debug;
    
    public class BuildTool : Editor
    {
        [MenuItem("Build/Build WindowsStandalone x864")]
        private static void Build()
        {
            PlayerSettings.productName = AppConst.AppName;
            PlayerSettings.runInBackground = true;
            PlayerSettings.fullScreenMode = FullScreenMode.Windowed;
            PlayerSettings.defaultIsNativeResolution = true;
            PlayerSettings.defaultScreenWidth = AppConst.DefaultWidth;
            PlayerSettings.defaultScreenWidth = AppConst.DefaultHeight;
            PlayerSettings.resizableWindow = true;
            PlayerSettings.forceSingleInstance = true;
            PlayerSettings.SetScriptingBackend(BuildTargetGroup.Standalone, ScriptingImplementation.IL2CPP);
            PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Standalone, "");
    
            BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();
            buildPlayerOptions.scenes = new[] { "Assets/Scenes/Start.unity"};
            buildPlayerOptions.locationPathName = $"Build/WindowsStandalone/{AppConst.AppName}.exe";
            buildPlayerOptions.target = BuildTarget.StandaloneWindows;
            buildPlayerOptions.options = BuildOptions.None;
    
            string exePath = System.Environment.CurrentDirectory + "/Build/WindowsStandalone";
            Directory.Delete(exePath, true);
    
            BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);
            BuildSummary summary = report.summary;
    
            if (summary.result == BuildResult.Succeeded)
            {
                FileUtil.CopyFileOrDirectory($"{System.Environment.CurrentDirectory}/UnityWinNotify", $"{exePath}/UnityWinNotify");
    
                Directory.Delete($"{exePath}/UnityWin_BackUpThisFolder_ButDontShipItWithYourGame", true);
                Process.Start(exePath);
                Process.Start($"{exePath}/{AppConst.AppName}.exe");
            }
    
            if (summary.result == BuildResult.Failed)
            {
                Debug.Log("Build failed");
            }
        }
    }
    
    

    2.2.3 IL2CPP启动外部程序

    由于Unity的IL2CPP还未实现c#的Process类,所以不能使用Process.Start启动其他程序。
    具体可见IL2CPP and Process.Start
    github上有其他人写好的工具可解决这个问题
    代码如下:
    StartExternalProcess.cs

    #if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
    using System;
    using System.ComponentModel;
    using System.Runtime.InteropServices;
    // ReSharper disable FieldCanBeMadeReadOnly.Local
    // ReSharper disable InconsistentNaming
    // ReSharper disable UnusedMember.Local
    // ReSharper disable MemberCanBePrivate.Local
    
    namespace Lavender.Systems
    {
        public static class StartExternalProcess
        {
            [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool CreateProcessW(
                string lpApplicationName,
                [In] string lpCommandLine,
                IntPtr procSecAttrs,
                IntPtr threadSecAttrs,
                bool bInheritHandles,
                ProcessCreationFlags dwCreationFlags,
                IntPtr lpEnvironment,
                string lpCurrentDirectory,
                ref STARTUPINFO lpStartupInfo,
                ref PROCESS_INFORMATION lpProcessInformation
            );
    
            [DllImport("kernel32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool CloseHandle(IntPtr hObject);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool TerminateProcess(IntPtr processHandle, uint exitCode);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            private static extern IntPtr OpenProcess(ProcessAccessRights access, bool inherit, uint processId);
    
            [Flags]
            private enum ProcessAccessRights : uint
            {
                PROCESS_CREATE_PROCESS = 0x0080, //  Required to create a process.
                PROCESS_CREATE_THREAD = 0x0002, //  Required to create a thread.
                PROCESS_DUP_HANDLE = 0x0040, // Required to duplicate a handle using DuplicateHandle.
                PROCESS_QUERY_INFORMATION = 0x0400, //  Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken, GetExitCodeProcess, GetPriorityClass, and IsProcessInJob).
                PROCESS_QUERY_LIMITED_INFORMATION = 0x1000, //  Required to retrieve certain information about a process (see QueryFullProcessImageName). A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION. Windows Server 2003 and Windows XP/2000:  This access right is not supported.
                PROCESS_SET_INFORMATION = 0x0200, //    Required to set certain information about a process, such as its priority class (see SetPriorityClass).
                PROCESS_SET_QUOTA = 0x0100, //  Required to set memory limits using SetProcessWorkingSetSize.
                PROCESS_SUSPEND_RESUME = 0x0800, // Required to suspend or resume a process.
                PROCESS_TERMINATE = 0x0001, //  Required to terminate a process using TerminateProcess.
                PROCESS_VM_OPERATION = 0x0008, //   Required to perform an operation on the address space of a process (see VirtualProtectEx and WriteProcessMemory).
                PROCESS_VM_READ = 0x0010, //    Required to read memory in a process using ReadProcessMemory.
                PROCESS_VM_WRITE = 0x0020, //   Required to write to memory in a process using WriteProcessMemory.
                DELETE = 0x00010000, // Required to delete the object.
                READ_CONTROL = 0x00020000, //   Required to read information in the security descriptor for the object, not including the information in the SACL. To read or write the SACL, you must request the ACCESS_SYSTEM_SECURITY access right. For more information, see SACL Access Right.
                SYNCHRONIZE = 0x00100000, //    The right to use the object for synchronization. This enables a thread to wait until the object is in the signaled state.
                WRITE_DAC = 0x00040000, //  Required to modify the DACL in the security descriptor for the object.
                WRITE_OWNER = 0x00080000, //    Required to change the owner in the security descriptor for the object.
                STANDARD_RIGHTS_REQUIRED = 0x000f0000,
                PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF //    All possible access rights for a process object.
            }
    
            [StructLayout(LayoutKind.Sequential)]
            private struct PROCESS_INFORMATION
            {
                internal IntPtr hProcess;
                internal IntPtr hThread;
                internal uint dwProcessId;
                internal uint dwThreadId;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            private struct STARTUPINFO
            {
                internal uint cb;
                internal IntPtr lpReserved;
                internal IntPtr lpDesktop;
                internal IntPtr lpTitle;
                internal uint dwX;
                internal uint dwY;
                internal uint dwXSize;
                internal uint dwYSize;
                internal uint dwXCountChars;
                internal uint dwYCountChars;
                internal uint dwFillAttribute;
                internal uint dwFlags;
                internal ushort wShowWindow;
                internal ushort cbReserved2;
                internal IntPtr lpReserved2;
                internal IntPtr hStdInput;
                internal IntPtr hStdOutput;
                internal IntPtr hStdError;
            }
    
            [Flags]
            private enum ProcessCreationFlags : uint
            {
                NONE = 0,
                CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
                CREATE_DEFAULT_ERROR_MODE = 0x04000000,
                CREATE_NEW_CONSOLE = 0x00000010,
                CREATE_NEW_PROCESS_GROUP = 0x00000200,
                CREATE_NO_WINDOW = 0x08000000,
                CREATE_PROTECTED_PROCESS = 0x00040000,
                CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
                CREATE_SECURE_PROCESS = 0x00400000,
                CREATE_SEPARATE_WOW_VDM = 0x00000800,
                CREATE_SHARED_WOW_VDM = 0x00001000,
                CREATE_SUSPENDED = 0x00000004,
                CREATE_UNICODE_ENVIRONMENT = 0x00000400,
                DEBUG_ONLY_THIS_PROCESS = 0x00000002,
                DEBUG_PROCESS = 0x00000001,
                DETACHED_PROCESS = 0x00000008,
                EXTENDED_STARTUPINFO_PRESENT = 0x00080000,
                INHERIT_PARENT_AFFINITY = 0x00010000
            }
    
            public static uint Start(string path, string dir, bool hidden = false)
            {
                ProcessCreationFlags flags = hidden ? ProcessCreationFlags.CREATE_NO_WINDOW : ProcessCreationFlags.NONE;
                STARTUPINFO startupinfo = new STARTUPINFO
                {
                    cb = (uint)Marshal.SizeOf<STARTUPINFO>()
                };
                PROCESS_INFORMATION processinfo = new PROCESS_INFORMATION();
                if (!CreateProcessW(null, path, IntPtr.Zero, IntPtr.Zero, false, flags, IntPtr.Zero, dir, ref startupinfo, ref processinfo))
                {
                    throw new Win32Exception();
                }
    
                return processinfo.dwProcessId;
            }
    
            public static int KillProcess(uint pid)
            {
                IntPtr handle = OpenProcess(ProcessAccessRights.PROCESS_ALL_ACCESS, false, pid);
    
                if (handle == IntPtr.Zero)
                {
                    return -1;
                }
                if (!TerminateProcess(handle, 0))
                {
                    throw new Win32Exception();
                }
                if (!CloseHandle(handle))
                {
                    throw new Win32Exception();
                }
    
                return 0;
            }
        }
    }
    #endif
    
    

    2.2.4 winform程序的托盘图标

    托盘图标对应的类是NotifyIcon,使用比较简单,相信一看代码就明白了。

    using System;
    using System.Diagnostics;
    using System.Windows.Forms;
    using UnityWin;
    
    namespace UnityWinNotify
    {
        public partial class MainForm : Form
        {
            private const string UnityWinApp = "UnityWin";
            private NotifyIcon notifyIcon;
    
            public MainForm()
            {
                InitializeComponent();
            }
    
            private void MainForm_Load(object sender, EventArgs e)
            {
                InitNotifyIcon();
    
                this.Closed += MainForm_Closed;
    
                // 隐藏窗体
                this.ShowInTaskbar = false;
                this.WindowState = FormWindowState.Minimized;
            }
    
            private void MainForm_Closed(object sender, EventArgs e)
            {
            }
    
            private void InitNotifyIcon()
            {
                notifyIcon = new NotifyIcon();
                
                notifyIcon.BalloonTipText = "Unity程序正在后台运行";            // 首次运行时的提示
                notifyIcon.Text = "控制Unity程序";
                notifyIcon.Icon = Properties.Resources.GithubIco;
                notifyIcon.Visible = true;
                notifyIcon.ShowBalloonTip(2000);                        // 气泡显示的时间 毫秒
                notifyIcon.MouseClick += notifyIcon_MouseClick;
    
                MenuItem maximumMenuItem = new MenuItem("最大化");
                MenuItem minimumMenuItem = new MenuItem("最小化");
                MenuItem spiltLineMenuItem = new MenuItem("-");
                MenuItem exitMenuItem = new MenuItem("退出");
                MenuItem[] childen = new MenuItem[] { maximumMenuItem, minimumMenuItem, spiltLineMenuItem, exitMenuItem };
                notifyIcon.ContextMenu = new ContextMenu(childen);
    
                maximumMenuItem.Click += MaximumMenuItem_Click;
                minimumMenuItem.Click += MinimumMenuItem_Click;
                exitMenuItem.Click += ExitMenuItem_Click;
            }
    
            // 最大化
            private void MaximumMenuItem_Click(object sender, EventArgs e)
            {
                IntPtr hWnd = WinUser32.GetWindow(UnityWinApp);
                if (hWnd != IntPtr.Zero)
                {
                    WinUser32.ShowWindow(hWnd, WinUser32.SW_MAXIMIZE);
                }
            }
    
            // 最小化
            private void MinimumMenuItem_Click(object sender, EventArgs e)
            {
                IntPtr hWnd = WinUser32.GetWindow(UnityWinApp);
                if (hWnd != IntPtr.Zero)
                {
                    //WinUser32.ShowWindow(hWnd, WinUser32.SW_MINIMIZE);
                    // 这里直接隐藏
                    WinUser32.ShowWindow(hWnd, WinUser32.SW_HIDE);
                }
            }
    
            private void ExitMenuItem_Click(object sender, EventArgs e)
            {
                try {
                    Process[] processes = Process.GetProcesses();
                    foreach (Process p in processes)
                    {
                        if (p.ProcessName == UnityWinApp)
                        {
                            p.Kill();
                        }
                    }
                    Environment.Exit(0);
                }
                catch (Exception)
                {
                }
            }
    
            // 点击托盘图标
            private void notifyIcon_MouseClick(object sender, MouseEventArgs e)
            {
                //if (e.Button == MouseButtons.Left)
                //{
                //    if (this.Visible == true)
                //    {
                //        this.Visible = false;
                //    }
                //    else
                //    {
                //        this.Visible = true;
                //        this.Activate();
                //    }
                //}
            }
    
        }
    }
    
    

    2.2.5 winform程序单例运行

    使用了Mutex。

    using System;
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.Windows.Forms;
    
    namespace UnityWinNotify
    {
        [Guid("6e40dbb7-9cc3-440e-9a75-5525dc3b1bfe")]
        static class Program
        {
            // Mutex can be made static so that GC doesn't recycle
            // same effect with GC.KeepAlive(mutex) at the end of main
            static Mutex mutex = new Mutex(false, "6e40dbb7-9cc3-440e-9a75-5525dc3b1bfe");
            // Guid guid = Guid.NewGuid(); // 创建Guid
    
            /// <summary>
            /// 应用程序的主入口点。
            /// </summary>
            [STAThread]
            static void Main()
            {
                if (!mutex.WaitOne(TimeSpan.FromSeconds(2), false))
                {
                    //MessageBox.Show("Application already started!", "", MessageBoxButtons.OK);
                    return;
                }
    
                try
                {
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new MainForm());
                }
                finally
                {
                    mutex.ReleaseMutex();
                }
            }
        }
    }
    

    3 完整项目

    包含Unity及Winform项目。
    链接:https://pan.baidu.com/s/12zyoxck417dtRCobaybseg
    提取码:ho48

    博主个人博客本文链接。

    4 参考文章

    展开全文
  • 实现悬浮窗及最小化到托盘及还原,自己做的,WPF通俗易懂
  • 刚刚上手total commander,使用的时候遇到一些习惯性问题。... 这次遇到的问题很简单,在使用Total Commander的时候有时候会对工具最小化操作,这时候没有一个快速呼出软件的功能,而工具又去了托盘栏,这样重新进...

           刚刚上手total commander,使用的时候遇到一些习惯性问题。但是从交互逻辑来看,我的需求又是对的,因此不妥协。这时候很多软件我就会直接放弃,但是我觉得total commander既然有自己存在的生命活力肯定还是可以做到的,我敢肯定使用这个工具的很多人应该是跟我一样一直在自己使用计算机的操作流程上在不断尝试优化的。

           这次遇到的问题很简单,在使用Total Commander的时候有时候会对工具最小化操作,这时候没有一个快速呼出软件的功能,而工具又去了托盘栏,这样重新进入交互就会麻烦。当然,能够保持TC一直呼出也算是一种方法,但是其他软件的操作也很难避免对此状态有影响。尤其是我们想把多个APP界面切入后台进入桌面的时候。

           改善方法很简单,两个思路:1,快速呼出TC;2,让TC最小化保持在任务栏不去托盘,这样可以鼠标快速切换。

           找了一下,其实还是有修改的地方的。

           通过上面的菜单交互,或者直接F12,可以进入配置。当然,这个F12也是看到这里临时学到的。

           之后,会出现上面的窗口,点击操作方式。

           把图中框出来的部分勾掉,这样最小化的时候就可以不进入托盘了。

           其实,第一种方法可能会是更好的处理方法,但是临时没有找到实现方式。这样的话,快捷键的定制可以借用系统的快捷键定制方式,比如说我自己尝试了win + number的方式来处理。正好上面的配置信息中心有一个主程序只允许运行一个的配置,只要是开启这个,随时使用启动的快捷键也成为可能了。

    展开全文
  • VB托盘演示程序,实现最小化到任务栏,以及任务栏图标设置等。
  • 在做中间层时,中间层往往不需要点击关闭时立刻关闭,而是最小化到托盘。故而特意隐藏关闭按钮功能。  1)隐藏退出功能 用PopMenu退出菜单代替  1.增加popMenu退出菜单,绑定窗体  2.增加变量控制是否真的...

            在做中间层时,中间层往往不需要点击关闭时立刻关闭,而是最小化到托盘。故而特意隐藏关闭按钮功能。

           1)隐藏退出功能 用PopMenu退出菜单代替

                 1.增加popMenu退出菜单,绑定到窗体

                 2.增加变量控制是否真的退出b_isClose;//True 退出 False 不退出

    b_isClose:Boolean; //True 退出 False 不退出

                 3.初始化b_isClose    在FormCreate或者FormShow事件中初始化 设置为False

              

    procedure TForm1.FormShow(Sender: TObject);
    begin
       b_isClose:=False;
    end;

                4.PopMenu增加退出事件

    procedure TForm1.pmExitClick(Sender: TObject);
    begin
       b_isclose := true;//设置为真正退出     
       Close;//调用系统退出事件 响应函数 FormClose
    end;

              5.退出时依据是否真正退出做处理

    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      if b_isclose then
      begin
        action := cafree;//真正退出
      end
      else
      begin
        action := canone;//修改事件类型不退出
      end;
    end;

          2)最小化到托盘

                修改FormClose事件,增加语句:


    Application.Minimize;//最小化应用

            如下:

    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      if  b_isclose then
      begin
        action := cafree;//真正退出
      end
      else
      begin
        action := canone;//修改事件类型不退出
        Application.Minimize;//最小化应用
      end;
    end;

        3) 增加托盘中右键弹出菜单

              1.安装拖放增加第三方控件TRzTrayIcon到界面, 取名:

     RzTrayIcon1: TRzTrayIcon;

               2. 修改FormClose事件,增加语句:

    RzTrayIcon1.PopupMenu := pmFrmMenu;//绑定右下角PopMenu

             最终如下:

    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      if b_isclose then
      begin
        action := cafree;//真正退出
      end
      else
      begin
        action := canone;//修改事件类型不退出
        Application.Minimize;//最小化应用
        RzTrayIcon1.PopupMenu := pmFrmMenu;//绑定右下角PopMenu
      end;
    end;


    展开全文
  • 对应文章地址:https://blog.csdn.net/mazhiyuan1981/article/details/109472818
  • 托盘”,在Windows系统界面中,指的就是下面任务条右侧,有系统时间等等的标志的那一部分。在程序最小化或挂起时,但有不希望占据任务栏的时候,就可以把程序放到托盘区。其实,托盘区的编程很简单
  • 鼠标放在窗体上,右击选择属性,在属性事件中找到Deactivate事件,设置事件点击Enters生成 核心代码部分: ... //当窗体为最小化状态时 if (this.WindowState == FormWindowState.Minimized) { ..
  • 对一个GUI程序,如果在最小化时,程序做任务栏消失或者点击关闭按钮时,应用并不关闭,而是在系统托盘上显示一个图标,来表示该程序仍在运行,在托盘上打开上下文菜单,可以恢复程序正常显示,或者完全退出应用等...
  • 使用Windows任务栏应用程序将雷鸟最小化到任务栏。 在Windows 10上测试。 公告(2021年2月21日) 目前为止,似乎不再需要使用此应用程序来最小化Thunderbird到托盘的距离。 设置菜单中有一个选项,可让您在...
  • pyqt5 窗口最小化到windows托盘

    千次阅读 2020-07-09 12:57:14
    平时我们使用的有些程序也会最小化到任务栏旁边的托盘上,就是在时间日期旁边的小图标,这个需要额外在pyqt5中写点代码设置下了。 首先我们创建一个demo程序,这个程序就是创建一个窗口,窗口中有一个按钮和text...
  • 【C#】窗体最小化到托盘(WinForm和WPF)

    千次阅读 热门讨论 2018-11-25 12:01:46
    下面以WPF为例 ...然后就能实现最小化到托盘的功能。 //引用根据需要添加,可以去除不必要的引用 using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...
  • Winform最小化到托盘

    千次阅读 2017-01-10 19:51:10
    1. 添加控件NotifyIcon (1)属性Icon:托盘图标。该属性必须要设置,否则无法...也可以在程序最小化到托盘时才显示托盘图标,即程序没有最小化到托盘时设为False,最小化到托盘时设为True。 (4)窗口的FormClosing事件

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,443
精华内容 1,377
关键字:

任务栏如何提示最小化到托盘