C#将表单隐藏,然后再次显示

C#将表单隐藏,然后再次显示,c#,winforms,C#,Winforms,我试图使Windows窗体应用程序能够重复显示然后隐藏自己 其想法是创建一个小应用程序,每次按下修改键(如Num Lock或Caps Lock)时,都会在屏幕上覆盖一幅图像。我可以检测出键盘键的工作状态完美无缺,但是我没有太多的运气来创建一个可以反复显示然后隐藏的表单 在我看来,(如果我错了,请纠正我)有两种可能的方法可以让表单表现出我想要的样子: 在Program.cs中正常启动表单,然后保持隐藏和显示表单以及在Form1.cs中显示图像的逻辑 表单将调用this.Hide()和this.

我试图使Windows窗体应用程序能够重复显示然后隐藏自己

其想法是创建一个小应用程序,每次按下修改键(如Num Lock或Caps Lock)时,都会在屏幕上覆盖一幅图像。我可以检测出键盘键的工作状态完美无缺,但是我没有太多的运气来创建一个可以反复显示然后隐藏的表单

在我看来,(如果我错了,请纠正我)有两种可能的方法可以让表单表现出我想要的样子:

  • Program.cs
    中正常启动表单,然后保持隐藏和显示表单以及在
    Form1.cs中显示图像的逻辑
    
    • 表单将调用
      this.Hide()
      this.Show()
      来隐藏和显示自己,但每当我尝试这样做时,我都无法获得
      this.Hide()
      来隐藏表单;窗体在所有打开的窗口顶部保持可见
  • 按住
    Program.cs中隐藏和显示表单的逻辑,然后按住
    Form1.cs中显示图像的逻辑即可
    
    • 我一直在玩弄如何使用窗体的类包装来显示和隐藏
      程序.cs
      ,但事实证明,
      窗体.Showdialog()
      会阻止任何进一步的代码执行,直到窗体关闭
我自己一直在玩代码,上面的两种方法都不起作用。我是否完全用错误的方式思考这个问题?WFA能以我希望的方式行事吗

这方面的代码有点混乱,我不确定这里哪些部分最相关,但我会尽力将其包括在这里:

程序.cs

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace KeyboardIndicators {
  // ApplicationContext wrapper
  public abstract class TrayIconApplicationContext : ApplicationContext {
    private NotifyIcon lockIcon;
    private ContextMenu lockIconContext;

    protected TrayIconApplicationContext() {
      // Wire up the ApplicationExitHandler to ApplicationExit events
      Application.ApplicationExit += this.ApplicationExitHandler;

      lockIconContext = new ContextMenu {

      };

      // Create lockIcon tray icon and make it visible
      lockIcon = new NotifyIcon {
        ContextMenu = lockIconContext,
        Text = Application.ProductName,
        Icon = new Icon("icon.ico"),
        Visible = true
      };

    }

    protected NotifyIcon LockIcon { get { return lockIcon; } }
    protected ContextMenu LockIconContext { get { return lockIconContext; } }


    // ApplicationExit event handler
    private void ApplicationExitHandler(object sender, EventArgs e) {
      this.OnApplicationExit(e);
    }

    // Performs cleanup to end the application
    protected virtual void OnApplicationExit(EventArgs e) {
      // TODO(Neil): Add meaningful thread cleanup here soon
      if (lockIcon != null) {
        lockIcon.Visible = false;
        lockIcon.Dispose();
      }
      if (lockIconContext != null)
        LockIconContext.Dispose();
    }
  }

  // TrayIconApplicationContext wrapper for Form1 to control the activation of the form window
  class FormApplicationContext : TrayIconApplicationContext {
    public FormApplicationContext() {
      // Add Exit menu item
      MenuItem exit = new MenuItem("E&xit");
      this.LockIconContext.MenuItems.Add(exit);
      exit.Click += this.ExitContextMenuClickHandler;

      //KeyboardIndicators indicators = new KeyboardIndicators();
      //indicators.RunListener();

      {
        using(Form form = new Form1("NumLock", true))
          form.ShowDialog();
      }
    }

    private void ExitContextMenuClickHandler(object sender, EventArgs eventArgs) {
      this.ExitThread();
    }
  }

  public class KeyboardIndicators {
    class LockState {
      // Is the numlock key on?
      public bool Num;
      // Is the capslock key on?
      public bool Caps;
      // Is the scroll lock key on?
      public bool Scroll;
    }

    public void RunListener() {
      try {
        // Store the old keyboard lock state
        LockState prevState = new LockState() {
          Num = Control.IsKeyLocked(Keys.NumLock),
          Caps = Control.IsKeyLocked(Keys.CapsLock),
          Scroll = Control.IsKeyLocked(Keys.Scroll)
        };

        while (true) {
          // Store the new keyboard lock state
          LockState newState = new LockState() {
            Num = Control.IsKeyLocked(Keys.NumLock),
            Caps = Control.IsKeyLocked(Keys.CapsLock),
            Scroll = Control.IsKeyLocked(Keys.Scroll)
          };

          //TODO(Neil): Handle simultaneous presses better, i.e. queue the balloon tips
          if (newState.Num != prevState.Num) {
            Form1 form = new Form1("NumLock", newState.Num);
          } else if (newState.Caps != prevState.Caps) {
            Form1 form = new Form1("CapsLock", newState.Caps);
          } else if (newState.Scroll != prevState.Scroll) {
            Form1 form = new Form1("ScrollLock", newState.Scroll);
          }

          // Set the previous lock state to the new one in prep for the next iteration
          prevState = newState;

          // Sleep for 500ms
          Thread.Sleep(500);
        }
      } catch (ThreadAbortException) { /* No need to do anything, just catch the ThreadAbortException.*/ }
    }
  }

  static class Program {
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main() {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);

      //Application.Run(new Form1("NumLock", true));
      Application.Run(new FormApplicationContext());
    }
  }
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace KeyboardIndicators {
  public partial class Form1 : Form {
    public Form1(String activatedModifier, bool lockState) {
      InitializeComponent();
      ShowForm(activatedModifier);

      //this.Show();
      //this.Hide();
    }

    public void ShowForm(String activatedModifier) {
      PictureBox pictureBox = new PictureBox();

      Image myBitmap = Image.FromFile("cube.png");
      Size bitmapSize = new Size(myBitmap.Width, myBitmap.Height);

      switch (activatedModifier) {
        case "NumLock":
          break;
        case "CapsLock":
          break;
        case "ScrollLock":
          break;
      }

      this.Size = bitmapSize;
      pictureBox.ClientSize = bitmapSize;

      pictureBox.Image = myBitmap;
      pictureBox.Dock = DockStyle.Fill;
      this.Controls.Add(pictureBox);
      this.FormBorderStyle = FormBorderStyle.None;
    }

    protected override CreateParams CreateParams {
      get {
        CreateParams createParams = base.CreateParams;
        createParams.ExStyle |= 0x00000020; // WS_EX_TRANSPARENT

        return createParams;
      }
    }
  }
}

例如,我创建了一个Winforms应用程序,如果按下其中任何一个键,该应用程序将显示“NUM”和/或“CAPS”,否则表单将隐藏。 密钥的检测基于

Program.cs

using System;
using System.Windows.Forms;

namespace WinFormsKeyHook
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WinFormsKeyHook
{
    public class KeyboardHook
    {
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private IntPtr _hookID = IntPtr.Zero;

        public List<Keys> KeysToObserve { get; set; } = new List<Keys>();

        public Action<Keys> KeyDown;

        public void InstallHook()
        {
            _hookID = SetHook(HookCallback);
        }

        ~KeyboardHook()
        {
            UnhookWindowsHookEx(_hookID);
        }

        public IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
            }
        }

        public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

        public IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
             if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                var key = (Keys)vkCode;
                Console.WriteLine(key);
                KeyDown(key);
            }

            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);
    }
}
Form1.cs

using System;
using System.Windows.Forms;

namespace WinFormsKeyHook
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WinFormsKeyHook
{
    public class KeyboardHook
    {
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private IntPtr _hookID = IntPtr.Zero;

        public List<Keys> KeysToObserve { get; set; } = new List<Keys>();

        public Action<Keys> KeyDown;

        public void InstallHook()
        {
            _hookID = SetHook(HookCallback);
        }

        ~KeyboardHook()
        {
            UnhookWindowsHookEx(_hookID);
        }

        public IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
            }
        }

        public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

        public IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
             if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                var key = (Keys)vkCode;
                Console.WriteLine(key);
                KeyDown(key);
            }

            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);
    }
}
注意:在Designer中的Form1中添加名为“label1”的标签

using System.Collections.Generic;
using System.Windows.Forms;

namespace WinFormsKeyHook
{
    public partial class Form1 : Form
    {
        private static bool _caps;
        private static bool _num;

        public Form1()
        {
            InitializeComponent();

            KeyboardHook kh = new KeyboardHook();
            kh.KeysToObserve.AddRange(new List<Keys> { Keys.CapsLock, Keys.NumLock });
            kh.InstallHook();
            kh.KeyDown = key => ProcessKeyDown(key);

            _caps = Control.IsKeyLocked(Keys.CapsLock);
            _num = Control.IsKeyLocked(Keys.NumLock);
        }

        private void ProcessKeyDown(Keys key)
        {

            if (key == Keys.CapsLock)
            {
                _caps = !_caps;
            }
            if (key == Keys.NumLock)
            {
                _num = !_num;
            }

            this.ShowState(_num, _caps);
        }

        internal void ShowState(bool num, bool caps)
        {
            if (!num && !caps)
            {
                this.Hide();
                return;
            }

            this.label1.Text = "";
            this.label1.Text += num ? "NUM " : "";
            this.label1.Text += caps ? "CAPS" : "";

            if (!this.Visible)
            {
                this.Show();
            }
        }
    }
}
使用System.Collections.Generic;
使用System.Windows.Forms;
名称空间WinFormsKeyHook
{
公共部分类Form1:Form
{
专用静态bool_帽;
私有静态布尔数;
公共表格1()
{
初始化组件();
KeyboardHook kh=新的KeyboardHook();
kh.keystobserve.AddRange(新列表{Keys.CapsLock,Keys.NumLock});
kh.InstallHook();
kh.KeyDown=key=>ProcessKeyDown(key);
_caps=控制.IsKeyLocked(Keys.CapsLock);
_num=Control.IsKeyLocked(Keys.NumLock);
}
私有void ProcessKeyDown(密钥)
{
if(key==Keys.CapsLock)
{
_caps=!\u caps;
}
if(key==Keys.NumLock)
{
_num=!\u num;
}
this.ShowState(_num,_caps);
}
内部无效显示状态(bool num,bool caps)
{
如果(!num&&!caps)
{
this.Hide();
返回;
}
this.label1.Text=“”;
this.label1.Text+=num?“num”:“;
this.label1.Text+=大写?“大写”:“;
如果(!this.Visible)
{
this.Show();
}
}
}
}
KeyboardHook.cs

using System;
using System.Windows.Forms;

namespace WinFormsKeyHook
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WinFormsKeyHook
{
    public class KeyboardHook
    {
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private IntPtr _hookID = IntPtr.Zero;

        public List<Keys> KeysToObserve { get; set; } = new List<Keys>();

        public Action<Keys> KeyDown;

        public void InstallHook()
        {
            _hookID = SetHook(HookCallback);
        }

        ~KeyboardHook()
        {
            UnhookWindowsHookEx(_hookID);
        }

        public IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
            }
        }

        public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

        public IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
             if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                var key = (Keys)vkCode;
                Console.WriteLine(key);
                KeyDown(key);
            }

            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);
    }
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用System.Runtime.InteropServices;
使用System.Windows.Forms;
名称空间WinFormsKeyHook
{
公共类键盘钩
{
专用常量int WH_键盘LL=13;
私有常量int WM_KEYDOWN=0x0100;
私有IntPtr_hookID=IntPtr.Zero;
公共列表{get;set;}=new List();
公共行动键控;
公共资源
{
_hookID=SetHook(HookCallback);
}
~KeyboardHook()
{
unhookwindowshookx(_hookID);
}
公共IntPtr设置挂钩(低层键盘程序)
{
使用(Process curProcess=Process.GetCurrentProcess())
使用(ProcessModule curModule=curProcess.MainModule)
{
返回SetWindowsHookEx(WH\u KEYBOARD\u LL,proc,GetModuleHandle(curModule.ModuleName),0);
}
}
公共委托IntPtr低级键盘PROC(int nCode、IntPtr wParam、IntPtr lParam);
公共IntPtr钩子回调(int nCode、IntPtr wParam、IntPtr lParam)
{
如果(nCode>=0&&wParam==(IntPtr)WM\u KEYDOWN)
{
int vkCode=Marshal.ReadInt32(LPRAM);
var key=(key)vkCode;
控制台。写入线(键);
向下键(key);
}
返回CallNextHookEx(_hookID,nCode,wParam,lParam);
}
[DllImport(“user32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
私有静态外部IntPtr SETWINDOWSHOOKX(int idHook、低层键盘PROC lpfn、IntPtr hMod、uint dwThreadId);
[DllImport(“user32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
[返回:Marshallas(UnmanagedType.Bool)]
私有静态外部bool unhookwindowshookx(IntPtr hhk);
[DllImport(“user32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
私有静态外部IntPtr CallNextHookEx(IntPtr hhk、intncode、IntPtr wParam、IntPtr lParam);
[DllImport(“kernel32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
私有静态外部IntPtr GetModuleHandle(字符串lpModuleName);
}
}

我注意到您试图在
表单1
构造函数中调用
this.Hide()
(代码被注释掉)。这是行不通的。如果在显示的
事件中调用
this.hide()
,是否能够隐藏表单