MDI uygulamada fare ve klavye olaylarını ana formda yakalama

Başlatan tunayk, 12 Kasım 2015, 21:08:39

tunayk

MDI form ile yapılan bir windows uygulamam var. Bu uygulamada web uygulamalarındaki session timeout benzeri bir mekanizma kullanmak istiyorum. Yani kullanıcı belirli bir süre uygulamanın hiç bir noktasına temas etmemiş ise otomatik olarak log out olsun. Kullanıcının uygulamanın herhangi bir penceresinde veya kontrolde yapmış olduğu klavye veya fare etkileşimlerini merkezi bir noktada yakalyıp o noktada log out timerı resetlemem gerek.

Bir yöntem önerebilecek var mı?

engerex

Şöyle olabilir. Bir timer kurarsın.200 saniye olduğunda timeout devreye girer. Formda her girişin başında timer resetlersin ve aktif oldukça zaman durmaz. Örneğin buton, tıkladın, form tıkladın, edit box tuş tıkladın timer resetlenir.

tunayk

Aslında o konuyu düşündüm ancak 20+ form ve bi çok kontrol olunca, herbirinin olayına yazmak uzun iş.  Merkezi bir sub içinde hepsini yakalaycak bir yol arıyorum.

Ana form da WndProc 'u override ile kullanabiliyorum ancak bunda alt formlara ait olayları tam yakalayamadım sanki

barisertekin

Uygulama ilk açıldığında bir adet threadingTimer başlatıp her mouse veya klavye tuşuna basıldığında sayacı sıfırlayabilirsin.

System.Threading.Timer timer = new System.Threading.Timer(new TimerCallback(DoSomething), null, 0, 1000);

private void DoSomething(object obj)
{
//it executes every second
}

timer.Change(Timeout.Infinite, Timeout.Infinite); //disable
timer.Change(0, 1000); //enable

tunayk

Farklı bir forumda bulup uyguladığım çözümü aşağıda veriyorum belki farklı bir arkadaşın da işine yarar.
Yukarıda bahsettiğim gibi, eskiden ana form da WndProc fonksiyonunu override ederek kullanıyorduk. Buradaki de bunun bir farklı versiyonu ancak daha etkili bir yol olmuş.  Kullandığım altyapı C# + .NET 4.5

ilk olarak uygulamamızda aşağıdaki classı oluşturuyoruz.

[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]

    public class LeaveIdleMessageFilter : System.Windows.Forms.IMessageFilter
    {
        const int WM_NCLBUTTONDOWN = 0x00A1;
        const int WM_NCLBUTTONUP = 0x00A2;
        const int WM_NCRBUTTONDOWN = 0x00A4;
        const int WM_NCRBUTTONUP = 0x00A5;
        const int WM_NCMBUTTONDOWN = 0x00A7;
        const int WM_NCMBUTTONUP = 0x00A8;
        const int WM_NCXBUTTONDOWN = 0x00AB;
        const int WM_NCXBUTTONUP = 0x00AC;
        const int WM_KEYDOWN = 0x0100;
        const int WM_KEYUP = 0x0101;
        const int WM_MOUSEMOVE = 0x0200;
        const int WM_LBUTTONDOWN = 0x0201;
        const int WM_LBUTTONUP = 0x0202;
        const int WM_RBUTTONDOWN = 0x0204;
        const int WM_RBUTTONUP = 0x0205;
        const int WM_MBUTTONDOWN = 0x0207;
        const int WM_MBUTTONUP = 0x0208;
        const int WM_XBUTTONDOWN = 0x020B;
        const int WM_XBUTTONUP = 0x020C;

        // The Messages array must be sorted due to use of Array.BinarySearch
        static int[] Messages = new int[] {WM_NCLBUTTONDOWN,
			WM_NCLBUTTONUP, WM_NCRBUTTONDOWN, WM_NCRBUTTONUP, WM_NCMBUTTONDOWN,
			WM_NCMBUTTONUP, WM_NCXBUTTONDOWN, WM_NCXBUTTONUP, WM_KEYDOWN, WM_KEYUP,
			WM_LBUTTONDOWN, WM_LBUTTONUP, WM_RBUTTONDOWN, WM_RBUTTONUP,
			WM_MBUTTONDOWN, WM_MBUTTONUP, WM_XBUTTONDOWN, WM_XBUTTONUP};

        public bool PreFilterMessage(ref System.Windows.Forms.Message m)
        {
            if (m.Msg == WM_MOUSEMOVE) return false;	// mouse move is high volume
               
            //if (!Program.IdleTimer.Enabled)		// idling?
            //    return false;			// No
            if (Array.BinarySearch(Messages, m.Msg) >= 0) 
            {
               if(frmLogin.Kapali) Program.LoginTimer = 300;
                return false; 
            }
               // Program.IdleTimer.Stop();
            return false;
        }
    }


daha sonra da main fonksiyonu içine alttaki satırları ekliyoruz.

//---------------------
LeaveIdleMessageFilter limf = new LeaveIdleMessageFilter();
Application.AddMessageFilter(limf);
Application.Idle += new EventHandler(Application_Idle);
//---------------------


İşin mekanizması yukarıdan da anlaşılacağı üzere, windows'un uygulamamıza göndermiş olduğu sistem mesajlarının döngüsüne bir kanca atıp bu mesajlardan haberimizin olmasını sağlıyoruz.  Bundan sonra sistemden gelen her mesaj kanca olarak kullandığımız class içindeki fonksiyon tarafından yakalanıyor ve geriye uygun mesaj geldiğinde gerekli işlemleri yapmak kalıyor.

Benim ihtiyacım olan kullanıcı fare veya klavye ile uygulamada bir iş yaptığında session timeout süresini sıfırlamaktı.  İlgili mesajların numaralarını kullanmış oldum.  Ana formda 1sn lik bir timer session timout süresini sıfıra doğru düşürüyor. Eğer hareket varsa , bu süre burada 300'e setlenerek uzatılmış oluyor.

Bu yöntemin avantajı, merkezi bir noktadan yapılmış olması ve her form ve kontrol için ayrı ayrı olay yakalama gereği olmaması.  Bu doğrultuda farklı mesajlar yakalanarak farklı amaçlar için de kullanılabilir. Örneğin sistemin uyku moduna girmesi engellenebilir vb.