【问题标题】:That icon to the top left of most windows [duplicate]大多数窗口左上角的那个图标[重复]
【发布时间】:2012-01-04 17:06:43
【问题描述】:

我用 C# 开发了一个 WinForms 应用程序,它可以通过从下拉列表中选择任何窗口并切换一个复选框来使任何窗口“最顶部”。

但是为此打开一个应用程序似乎有点傻,所以我想知道是否可以在 Windows 的左上角图标中添加一个运行我选择的程序的条目?

我没有任何实验代码,因为我不知道那个图标/点叫什么,因此我无法研究它。

【问题讨论】:

  • screenshot 可能对这个有帮助。
  • 出现的菜单是窗口的系统菜单,也是右键标题栏或任务栏上的窗口触发的。

标签: c# windows winforms winapi


【解决方案1】:

我发现这段代码似乎可以满足您的要求:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WinFormsSystemMenuTest
{
    public partial class Form1 : Form
    {
        #region Win32 API Stuff

        // Define the Win32 API methods we are going to use
        [DllImport("user32.dll")]
        private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

        [DllImport("user32.dll")]
        private static extern bool InsertMenu(IntPtr hMenu, Int32 wPosition, Int32 wFlags, Int32 wIDNewItem, string lpNewItem);

        /// Define our Constants we will use
        public const Int32 WM_SYSCOMMAND = 0x112;
        public const Int32 MF_SEPARATOR = 0x800;
        public const Int32 MF_BYPOSITION = 0x400;
        public const Int32 MF_STRING = 0x0;

        #endregion

        // The constants we'll use to identify our custom system menu items
        public const Int32 _SettingsSysMenuID = 1000;
        public const Int32 _AboutSysMenuID = 1001;

        public Form1()
        {
            InitializeComponent();
        }

        protected override void OnHandleCreated(EventArgs e)
        {
            /// Get the Handle for the Forms System Menu
            IntPtr systemMenuHandle = GetSystemMenu(this.Handle, false);

            /// Create our new System Menu items just before the Close menu item
            InsertMenu(systemMenuHandle, 5, MF_BYPOSITION | MF_SEPARATOR, 0, string.Empty); // <-- Add a menu seperator
            InsertMenu(systemMenuHandle, 6, MF_BYPOSITION, _SettingsSysMenuID, "Settings...");
            InsertMenu(systemMenuHandle, 7, MF_BYPOSITION, _AboutSysMenuID, "About...");

            base.OnHandleCreated(e);
        }

        protected override void WndProc(ref Message m)
        {
            // Check if a System Command has been executed
            if (m.Msg == WM_SYSCOMMAND)
            {
                // Execute the appropriate code for the System Menu item that was clicked
                switch (m.WParam.ToInt32())
                {
                    case _SettingsSysMenuID:
                        MessageBox.Show("\"Settings\" was clicked");
                        break;
                    case _AboutSysMenuID:
                        MessageBox.Show("\"About\" was clicked");
                        break;
                }
            }

            base.WndProc(ref m);
        }
    }
}

我找到了here。这似乎是你想要的,是吗?

【讨论】:

  • Load 事件处理程序中的代码属于 OnHandleCreated() 的覆盖。
  • 哇,看起来比预期的要容易!半小时左右就可以试一试了。从链接看来,这正是我想要的:)
  • 将此行添加到 Load 事件处理程序以查看原因:ShowInTaskbar = false; 有许多属性会导致重新创建本机窗口。发生这种情况时,您的系统菜单自定义将丢失。
  • @HansPassant 谢谢!我已经修改了代码。
【解决方案2】:

winform 的这个区域称为"Non client area"

但我认为最简单的解决方案是,如果您的目标是将您的开关添加到所有外部 Winform,则创建一个流程,该流程将在活动窗口窗体的左上方放置一个带有您的开/关开关的小窗体。可以尝试直接放在外部表单上,但是位置优先级会有问题。

由于您在问题中包含“WinApi”,我想您可以获取当前正在运行的进程的窗口句柄、坐标和最顶层属性。

【讨论】:

    猜你喜欢
    • 2011-10-14
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 2019-06-13
    • 2016-04-03
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    相关资源
    最近更新 更多