且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何从另一个类的静态方法(即只有一个对象)调用一个实例方法?

更新时间:2023-02-14 15:07:54

传递按键到其他形式

b

在我看来,你基本上只是将按键传递给你的表单,这意味着一种基本的消息通知/观察者模式。也许你只是需要一个更好的设计模式。请尝试以下操作:

  public class MessageHooks 
{
public static event Action< int> OnHookCallback;
$ b私有静态IntPtr HookCallback(int nCode,IntPtr wParam,IntPtr lParam)
{
if(nCode> = 0&& wParam ==(IntPtr)WM_KEYDOWN)
{
int trueKeyPressed = Marshal.ReadInt32(lParam);
if(OnHookCallBack!= null)
{
OnHookCallback(trueKeyPressed);


返回CallNextHookEx(_hookID,nCode,wParam,lParam);
}
}

猜猜什么?现在你的 HookCallBack 方法甚至不需要知道表单的存在。相反,您的表单将自己注册到事件处理程序中:

  public partial class Form1:Form 
{
public Form1()
{
InitializeComponent();
MessageHooks.OnHookCallBack + = MessageHooks_OnHookCallBack;
this.FormClosed + =(sender,e)=> MessageHooks.OnHookCallBack - = MessageHooks_OnHookCallBack; //< ---总是关闭表单
}

void MessageHooks_OnHookCallBack(int keyPressed)
{
//用keypress $ b $记住,你必须 解开你的窗体事件处理程序在窗体关闭,否则表单将不会被垃圾收集,你会遇到很多奇怪的问题,提高不可见的窗体上的事件。

my form1 class contains a bunch of data that I need to save, so there should only be one instance of it running at a time.

public partial class Form1 : Form
{
    public string form1string = "I really need to save this data";

    public Form1()
    {
        InitializeComponent();


        // Even if I pass my form1 object here I still can't access it from
        // the upcoming static methods.
        InterceptKeys hook = new InterceptKeys();
    }


InterceptKeys, which is not my code, contains a bunch of static methods required for keyboard hooks.

private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
    {
       int trueKeyPressed = Marshal.ReadInt32(lParam);

       if (Form1.mirror)
       {
           Form1.newKeyPress(trueKeyPressed);
           return (IntPtr)1;
       }
    }
    return CallNextHookEx(_hookID, nCode, wParam, lParam);
 }


Because the HookCallBack method is static, Form1.newKeyPress() needs to be static as well.

But if newKeyPress in static, I can't access the data that I need! I wouldn't want to declare a new form1 object here, as that would give me different versions of the data. Correct?

I'm not an Object Oriented Expert. How should I format this, to ensure that all of the InterceptKey's form1 method calls are going to THE form1 object that I want?

Thanks, please let me know if there's any more info that you need!

Passing keypresses to other forms

It occurs to me that you're basically just passing keypresses to your form, which implies a kind of basic message notification / observer pattern. Maybe you just need a better design pattern. Try the following:

public class MessageHooks
{
    public static event Action<int> OnHookCallback;

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
        {
            int trueKeyPressed = Marshal.ReadInt32(lParam);
            if (OnHookCallBack != null)
            {
                OnHookCallback(trueKeyPressed);
            }
        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }
}

Guess what? Now your HookCallBack method doesn't even need to know of the existence of forms. Instead, your forms register themselves to the event handler as such:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        MessageHooks.OnHookCallBack += MessageHooks_OnHookCallBack;
        this.FormClosed += (sender, e) => MessageHooks.OnHookCallBack -= MessageHooks_OnHookCallBack; // <--- ALWAYS UNHOOK ON FORM CLOSE
    }

    void MessageHooks_OnHookCallBack(int keyPressed)
    {
        // do something with the keypress
    }
}

Remember, you must unhook your forms event handler on form close, otherwise the form won't get garbage collected, and you'll run into lots of weird issues raising events on non-visible forms.