有没有办法从调用堆栈中获取最后一个表单类



我有一个自定义消息框(基本上是winform),它弹出在调用表单的中心,如下所示:

public partial class Form1 : Form
{
private void button1_Click(object sender, EventArgs e)
{
MsgBox.Show(this, "asdsdfsdf");
}
}

这里我传递this(Form1)作为MsgBox的所有者。现在我知道了MsgBox表单的位置,因为我也在传递父表单(Form1)。

但我需要这个自定义消息框来对齐自己(中心到父窗体),即使是从其他类调用的,例如

public class Computer
{
public void Do(int i)
{
MsgBox.Show(i.ToString());
}
}

这里的问题是我无法将父窗体的引用传递给MsgBox类。所以在这里我无法定位自定义框。我希望MsgBox类能够确定哪个是调用堆栈中的最后一个窗体类?

我试过这个:

public partial class MsgBox : Form
{
private void X()
{
StackTrace df = new StackTrace();
foreach (var item in df.GetFrames())
{
var type = item.GetMethod().DeclaringType;
if (type.BaseType == typeof(Form))
{
IWin32Window w = //how to get the form instance here??
//------------
break;
}
}
}
}

我确实触及了内部if子句;问题是我不知道如何从type变量中获取表单实例或表单的IWin32Window句柄。。我能做些什么来获得类的实例本身,而不是类型吗?

大编辑:很抱歉,我犯了一个很大的错误,说获取父窗体的引用是将子窗体居中。我需要MsqBox实例中父窗体的句柄,因为它还可以做其他事情。简而言之,我需要子窗体中的父窗体,而不需要引用未传递的父窗体。有可能吗?

您可以尝试将MessageBox集中在Form.ActiveForm.上

解决方案:

  • 在每个MsgBox类实例中保留私有Form Parent { get; private set; }属性
  • 创建MsgBox.ActiveForm { get { .. } }静态属性,该属性将拾取Form.ActiveForm,如果其类型为MsgBox,则返回其父级

MsgBox类的静态特性:

public static Form ActiveForm
{
get
{
return Form.ActiveForm == null ? null :
Form.ActiveForm is MsgBox ? ((MsgBox)Form.ActiveForm).Parent :
Form.ActiveForm;
}
}

这是一种方法,谢谢@Joe:

public static Form GetLastForm()
{
if (Form.ActiveForm != null && !(Form.ActiveForm is MsgBox))
return Form.ActiveForm;
var openForms = Application.OpenForms.Cast<Form>().Where(f => !(f is MsgBox));
if (openForms.Count > 0)
return openForms[openForms.Count - 1];
return null;
}

我在通过堆栈跟踪方法获得正确的父窗体时遇到了问题。这里的基本困惑是确定我想要的是当前活动的表单,还是最后打开的表单,或者是导致MsgBox弹出的表单。这三种方法都可能不同,我选择了堆栈跟踪方法,以便获得第三种方法。依赖堆栈跟踪是令人沮丧的。我刚刚得到了活动表单,如果没有,我会检索最后打开的表单。Application.OpenForms按照正确的顺序打开表单。

最新更新