私はC#で書かれた100のウィンドウフォームを持っていると仮定して、これらのフォームのいずれかのコードを変更することなく、また他のフォームから継承せずにこれらのフォームのロード時に呼び出される関数を定義する方法があります。それは新しいフォームが開いているときに自動的に呼び出される関数ですか?C#ですべてのフォームロードで関数を呼び出す方法は?
ありがとう、
私はC#で書かれた100のウィンドウフォームを持っていると仮定して、これらのフォームのいずれかのコードを変更することなく、また他のフォームから継承せずにこれらのフォームのロード時に呼び出される関数を定義する方法があります。それは新しいフォームが開いているときに自動的に呼び出される関数ですか?C#ですべてのフォームロードで関数を呼び出す方法は?
ありがとう、
このような方法はありません。あなたはあなたの質問で言った解決策の1つを使用するだけです。
MessageFilterを使用して、フォームの読み込みに関するメッセージを傍受することができます。以下は、フォームをインターセプトし、イベントハンドラをイベントに追加するサンプルです。あなたはイベントハンドラで必要なことをすることができます。
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.AddMessageFilter(new TestMessageFilter());
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
私はあなただけのloadイベントの前にはなく、以下のコードでは発生しませんLoad
イベントに加入何らかの理由でコードを実行する必要があります知っています。しかし、あなたがActivated
イベントでそれを行うことができれば、それはうまくいくでしょう。あるいは、別のイベントでそれをやりたければ、以下のコードを修正して、そのイベントがトリガーされるかどうかを確認してください。同じフォームの同じイベントに対して複数のハンドラを追加しないように、コードはすべてのフォームのリストも保持しています。フォームが閉じられると、すべてのハンドラが削除されます。
[SecurityPermission(SecurityAction.LinkDemand, Flags =
SecurityPermissionFlag.UnmanagedCode)]
public class TestMessageFilter : IMessageFilter
{
private Hashtable forms = new Hashtable();
public bool PreFilterMessage(ref Message m)
{
Control c = Control.FromHandle(m.HWnd);
var form = c as Form;
if (form != null &&
!this.forms.ContainsKey(form))
{
form.Load += Form_Load;
form.Activated += Form_Activated;
form.FormClosed += Form_FormClosed;
this.forms.Add(form, form);
}
return false;
}
private void Form_FormClosed(object sender, FormClosedEventArgs e)
{
if (this.forms.ContainsValue(sender))
{
var f = sender as Form;
f.Activated -= Form_Activated;
f.Load -= Form_Load;
this.forms.Remove(sender);
}
}
private void Form_Activated(object sender, EventArgs e)
{
MessageBox.Show("Form_Activated...");
}
private void Form_Load(object sender, EventArgs e)
{
MessageBox.Show("Form_Load...");
}
}
フォームファクトリを使用して、OnLoadメソッドまたはフォームクラス内の他の仮想メソッドをインターセプトするインターセプトを実装できます。
Autofac、Castle.Core、およびAutofac.Extras.DynamicProxyを使用して、各フォームのOnLoadメソッドをインターセプトし、フォームにOnLoadメソッドが呼び出される前と後にコンソールに書き込むという概念証明を作成しました。
フォームファクトリバックオーナーズ。 CreateForm(string formName)は、名前付きAutofacサービスの名前をとります。
public interface IFormFactory
{
Owned<Form> CreateForm(string formName);
}
public class FormFactory : IFormFactory
{
private readonly IContainer _container;
public FormFactory(IContainer container)
{
_container = container;
}
public Owned<Form> CreateForm(string formName)
{
return _container.ResolveNamed<Owned<Form>>(formName);
}
}
以下のインターセプタは、フォーム上の仮想メソッドごとに呼び出されます。 OnLoadのチェックを追加しましたが、他の仮想メソッドも傍受して呼び出すことができます。
public class FormInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
bool isFormOnLoad = invocation.InvocationTarget is Form && invocation.Method.Name.Equals("OnLoad");
if(isFormOnLoad)
{
Console.WriteLine("Before OnLoad");
}
invocation.Proceed();
if(isFormOnLoad)
{
Console.WriteLine("After OnLoad");
}
}
}
インターセプタ、フォーム、および工場で名前付きサービスを使用するように登録してください。名前は、ファクトリメソッドでフォームを作成するために使用されます。以下は
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
var builder = new ContainerBuilder();
builder.RegisterType<FormInterceptor>();
Castle.DynamicProxy.Generators.AttributesToAvoidReplicating.Add<System.Security.Permissions.UIPermissionAttribute>();
// Register your forms
builder.RegisterType<frmMain>()
.Named<Form>("frmMain")
.EnableClassInterceptors()
.InterceptedBy(typeof(FormInterceptor));
builder.RegisterType<frmSubForm>()
.Named<Form>("frmSubForm")
.EnableClassInterceptors()
.InterceptedBy(typeof(FormInterceptor));
FormFactory = new FormFactory(builder.Build());
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(FormFactory.CreateForm("frmMain").Value);
}
public static IFormFactory FormFactory { get; set; }
}
メインフォーム内の試験フォームを作成し、表示の一例です:
private void button1_Click(object sender, EventArgs e)
{
using (var subForm = Program.FormFactory.CreateForm("frmSubForm").Value)
{
subForm.ShowDialog(this);
}
}
どのようにあなたのフォームをインスタンス化していますか?あなたはデコレータを使うことができます。 –
私はこの質問がなぜ下降されているのか分かりません。それは完全に有効な質問です。 – CodingYoshi