我的Form1类,包含了一些,我需要保存数据的,所以应该只有它同时运行的一个实例。
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,这不是我的代码,包含了一堆键盘钩子所需的静态方法。
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);
}
因为HookCallBack方法是静态的,Form1.newKeyPress()需要是静态的为好。
但是,如果newKeyPress静态,我无法访问我需要的数据! 我不想在这里宣布一个新的Form1的对象,因为这会给我不同版本的数据。 正确?
我不是一个面向对象的专家。 我应该如何格式化此,以确保所有的InterceptKey的Form1的方法调用的打算,我想在Form1对象?
谢谢,请让我知道如果有任何更多的信息,你需要的!
Answer 1:
按键传递到其他形式
它发生,我认为你基本上只是路过按键到你的形式,这意味着一种基本的消息通知/观察者模式。 也许你只是需要更好的设计模式。 尝试以下方法:
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);
}
}
你猜怎么了? 现在你HookCallBack
方法甚至不需要知道的形式存在。 相反,你的形式注册自己的事件处理程序这样:
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
}
}
记住,你必须解开的形式接近表单事件处理程序,否则表单将不会被回收,你会遇到很多的提高对非视觉形式的活动奇怪的问题。
Answer 2:
你有两个设计问题:
如何从静态方法调用一个实例方法
因为HookCallBack方法是静态的,Form1.newKeyPress()需要是静态的为好。
你可以在你的主要形式,以您的实例通过HookCallBack
方法,你只需要一个额外的参数添加到您的静态方法:
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam, Form1 form)
{
// ...
}
这实际上是首选策略。 无论你的方法和类对其他对象的依赖,你应该通过你的依赖到你的方法,而不是从全局状态拉他们。
除非,你可以通过循环Application.OpenForms收集和发现你正在寻找如下形式:
var form = Application.OpenForms.OfType<Form1>().First();
form.newKeyPress();
如何有一个表单打开的一个实例在同一时间
其他人都建议让您的形式静态 - 这是一种方法,但其糟糕的做法。 静态形式没有得到收集垃圾的处置时,你必须实现自己的init /复位的方法,当你显示/隐藏表单,如果静态形式有那么你的应用程序会慢慢泄漏内存到其他对象的引用, 除其他事项外 。 其实,我建议是这样的:
class FormFactory
{
public Form1 GetForm1()
{
return Application.OpenForms.OfType<Form1>().FirstOrDefault ?? new Form1();
}
}
所以你FormFactory控制窗体的寿命,现在你可以使用get Form1的现有或新的实例new FormFactory.GetForm1()
Answer 3:
从你写的是什么,我想这将工作:
在Form1
,有一个类型的静态成员Form1
,将持有的实例:
private static Form1 instance;
在Form1
构造函数中,设置创建此静态成员的实例:
public Form1()
{
// Existing code
Form1.instance = this;
}
现在,让newKeyPress
静态的,并使用静态成员找到实际的形式,例如:
public static void newKeyPress(int trueKeyPressed)
{
Form1 thisIsTheForm1Instance = Form1.instance;
// Now instance.form1string is the data you want
}
Answer 4:
我觉得就像在Form1类的东西:
private static Form1 instance;
public static Form1 Instance
{
get
{
if (instance == null)
{
instance = new Form1();
}
return instance;
}
}
而在你的班级其中使用它们:
Form1 form1 = Form1.Instance;
将做的工作。 这将首先检查是否有一个,如果是的话,它将返回实例否则它会创建一个和下一次它会返回一个。
文章来源: How do I call an instance method from another classes' static method (i.e. have only one object)?