Blog (22)
Komentarze (619)
Recenzje (0)

Tata programista...

@alucosoftwareTata programista...06.06.2012 00:38

Praca na własny rachunek niesie ze sobą wiele korzyści. Jedną z nich jest możliwość częstszego przebywania bliżej rodziny (o ile takową posiadamy). Praca na własny rachunek w charakterze programisty nakłada obowiązek posiadania co najmniej jednego komputera, który współdzielimy (bądź nie) z pozostałymi domownikami. Jeżeli tymi domownikami są małe dzieci - oj, strzeżcie się pliki i foldery, albowiem wasze dni zostały policzone.

Sam mam dwójkę pociech, synka i córeczkę. Och, ach :) Synek, z racji swojego wieku (2,5 roku) i zawodu taty, szybko rozwinął grupę zdolności psychofizycznych umożliwiających sprawne poruszanie się po zakamarkach Internetu. Jeśli przez przypadek pozostawię myszkę "luzem", już po paru chwilach ze zdumieniem obserwuję "kota kota Fimejona" skaczącego po ekranie i Bonifacego wylegującego się na babcinym zapiecku... Pięć kliknięć myszką i YouTube gra pełną parą :) Niech mu będzie.

Swego czasu, na potrzeby świetego spokoju, wskazałem synkowi ikonę do TuxPainta. Wywołało to w nim falę niespotykanej dotąd radości, tym bardziej, że poza samym malowaniem, program oferuje możliwość umieszczania na obrazkach tekstu. Klawiaturę opanował błyskawicznie. Tym większe było moje zdziwienie, kiedy synek, z "chronionego", pełnoekranowego trybu "Dla dzieci", powracał do Pulpitu - bo mu się malowanie znudziło - i rozpoczynał fragmentację moich programistycznych projektów. Ech...

Tylko dla wybranych (klawiszy...)

Ostatnio natrafiłem na stronę www.virtualpiano.net i zaprezentowałem znalezisko małemu psotnikowi. Zabawa niesłychana! Z tym, że gra na wirtualnym pianinie odbywa się za pomocą wybranych - a nie WSZYSTKICH klawiszy :P. Hmm, ale przecież tata zajmuje się tym czym zajmuje. Wziąłem więc synka na kolana i razem zabraliśmy się za pisanie "oprogramowania pomocniczego". Porady malucha były na tyle owocne, że już po kilkunastu minutach klawiatura została okiełznana, a program ukończony (kliknij tutaj, aby pobrać program).

Aplikacja wymaga .NET Framework 2.0 (Systemy Windows Vista i wyżej posiadają środowisko uruchomieniowe .NET w odpowiedniej wersji). Program blokuje przetwarzanie przez system operacyjny tych klawiszy, które nie znajdują się na "białej liście" (w uproszczeniu, ponieważ nie jest to do końca prawda). Jeśli do tego ukryjemy myszkę w sejfie, to możemy pozwolić naszym dzieciom na odrobinę zabawy z wykorzystaniem sprzętu komputerowego, bez konieczności nieustannego zerkania przez ramię.

Efekt końcowy jak na załączonym obrazku :)

Uwaga! Dzieci nie powinny spędzać przy komputerze dłużej niż 20 minut dziennie.

* w ofercie posiadam także inne programistyczne wynalazki dla rodziców małych pociech ;)

Poniżej załączam kod źródłowy (w wersji "wyścig z czasem"). Klasa InterceptKeys to zmodyfikowana implementacja mechanizmu haków w .NET Stephena Toub'a (http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx ).


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace PreventKeys
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new FormKeys());
        }
    }

    public class FormKeys : Form
    {
        Button buttonPreventKeys;

        public FormKeys()
        {
            this.Text = "Klawiatura dla psotnika";
            this.StartPosition = FormStartPosition.CenterScreen;
            this.Size = new System.Drawing.Size(480, 150);

            RichTextBox allowableKeysRichTextBox = new RichTextBox();
            allowableKeysRichTextBox.BorderStyle = BorderStyle.None;
            allowableKeysRichTextBox.BackColor = System.Drawing.Color.White;
            allowableKeysRichTextBox.ReadOnly = true;
            allowableKeysRichTextBox.Dock = DockStyle.Fill;

            InterceptKeys.AllowableKeysRichTextBox = allowableKeysRichTextBox;

            allowableKeysRichTextBox.GotFocus += new EventHandler(allowableKeysRichTextBox_GotFocus);
            allowableKeysRichTextBox.LostFocus += new EventHandler(allowableKeysRichTextBox_LostFocus);

            buttonPreventKeys = new Button();
            buttonPreventKeys.Text = "Zablokuj pozostałe klawisze";
            buttonPreventKeys.Dock = DockStyle.Bottom;
            buttonPreventKeys.Click += new EventHandler(buttonPreventKeys_Click);

            Label label = new Label();
            label.Text = "Kliknij myszką na poniższym polu i naciśnij klawisze, które mają być dostępne dla dziecka";
            label.AutoSize = true;
            label.Padding = new System.Windows.Forms.Padding(4);
            label.Dock = DockStyle.Top;

            this.Controls.Add(allowableKeysRichTextBox);
            this.Controls.Add(label);
            this.Controls.Add(buttonPreventKeys);

            Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
        }

        void allowableKeysRichTextBox_LostFocus(object sender, EventArgs e)
        {
            InterceptKeys.UnHook();
            InterceptKeys.HookMode = InterceptKeys.Mode.PreventOtherKeys;
        }

        void allowableKeysRichTextBox_GotFocus(object sender, EventArgs e)
        {
            buttonPreventKeys.Text = "Zablokuj pozostałe klawisze";
            buttonPreventKeys.Tag = null;
            InterceptKeys.UnHook();

            InterceptKeys.HookMode = InterceptKeys.Mode.PrepareAllowableKeys;
            InterceptKeys.Hook();
        }

        void buttonPreventKeys_Click(object sender, EventArgs e)
        {
            Button button = sender as Button;

            if (button.Tag == null)
            { 
                InterceptKeys.Hook();
                button.Text = "Odblokuj wszystkie klawisze";
                button.Tag = true;
            }
            else
            {
                InterceptKeys.UnHook();
                button.Text = "Zablokuj pozostałe klawisze";
                button.Tag = null;
            }
        }

        void Application_ApplicationExit(object sender, EventArgs e)
        {
            InterceptKeys.UnHook();
        }
    }

    public static class InterceptKeys
    {
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private static LowLevelKeyboardProc _proc = HookCallback;
        private static IntPtr _hookID = IntPtr.Zero;
        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

        public enum Mode
        {
            PrepareAllowableKeys,
            PreventOtherKeys
        }

        public static Mode HookMode { get; set; }
        public static RichTextBox AllowableKeysRichTextBox { get; set; }

        public static void Hook()
        {
            _hookID = SetHook(_proc);
        }

        public static void UnHook()
        {
            UnhookWindowsHookEx(_hookID);
        }

        private static IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
                    GetModuleHandle(curModule.ModuleName), 0);
            }
        }

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

                string keyName = Enum.GetName(typeof(Keys), vkCode);
                bool found = false;

                // Uuuu, ale nieefektywny sposób :)
                // A ile pamięci marnujemy... Dobrze, że GC działa jak należy...
                // Nie ma czasu na zabawę w wyrażenia regularne...
                string[] split = AllowableKeysRichTextBox.Text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                for (int j = 0; j < split.Length; ++j)
                {
                    if (split[j] == keyName)
                    {
                        found = true;
                        break;
                    }
                }

                if (HookMode == Mode.PrepareAllowableKeys)
                {
                    if (!found)
                        AllowableKeysRichTextBox.Text += String.Format("{0} ", keyName);
                    else
                        return new IntPtr(1);
                }
                else
                {
                    if (found)
                        return CallNextHookEx(_hookID, nCode, wParam, lParam);
                    else
                        return new IntPtr(1);
                }
            }
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);
    }
}
Szanowna Użytkowniczko! Szanowny Użytkowniku!
×
Aby dalej móc dostarczać coraz lepsze materiały redakcyjne i udostępniać coraz lepsze usługi, potrzebujemy zgody na dopasowanie treści marketingowych do Twojego zachowania. Twoje dane są u nas bezpieczne, a zgodę możesz wycofać w każdej chwili na podstronie polityka prywatności.

Kliknij "PRZECHODZĘ DO SERWISU" lub na symbol "X" w górnym rogu tej planszy, jeżeli zgadzasz się na przetwarzanie przez Wirtualną Polskę i naszych Zaufanych Partnerów Twoich danych osobowych, zbieranych w ramach korzystania przez Ciebie z usług, portali i serwisów internetowych Wirtualnej Polski (w tym danych zapisywanych w plikach cookies) w celach marketingowych realizowanych na zlecenie naszych Zaufanych Partnerów. Jeśli nie zgadzasz się na przetwarzanie Twoich danych osobowych skorzystaj z ustawień w polityce prywatności. Zgoda jest dobrowolna i możesz ją w dowolnym momencie wycofać zmieniając ustawienia w polityce prywatności (w której znajdziesz odpowiedzi na wszystkie pytania związane z przetwarzaniem Twoich danych osobowych).

Od 25 maja 2018 roku obowiązuje Rozporządzenie Parlamentu Europejskiego i Rady (UE) 2016/679 (określane jako "RODO"). W związku z tym chcielibyśmy poinformować o przetwarzaniu Twoich danych oraz zasadach, na jakich odbywa się to po dniu 25 maja 2018 roku.

Kto będzie administratorem Twoich danych?

Administratorami Twoich danych będzie Wirtualna Polska Media Spółka Akcyjna z siedzibą w Warszawie, oraz pozostałe spółki z grupy Wirtualna Polska, jak również nasi Zaufani Partnerzy, z którymi stale współpracujemy. Szczegółowe informacje dotyczące administratorów znajdują się w polityce prywatności.

O jakich danych mówimy?

Chodzi o dane osobowe, które są zbierane w ramach korzystania przez Ciebie z naszych usług, portali i serwisów internetowych udostępnianych przez Wirtualną Polskę, w tym zapisywanych w plikach cookies, które są instalowane na naszych stronach przez Wirtualną Polskę oraz naszych Zaufanych Partnerów.

Dlaczego chcemy przetwarzać Twoje dane?

Przetwarzamy je dostarczać coraz lepsze materiały redakcyjne, dopasować ich tematykę do Twoich zainteresowań, tworzyć portale i serwisy internetowe, z których będziesz korzystać z przyjemnością, zapewniać większe bezpieczeństwo usług, udoskonalać nasze usługi i maksymalnie dopasować je do Twoich zainteresowań, pokazywać reklamy dopasowane do Twoich potrzeb. Szczegółowe informacje dotyczące celów przetwarzania Twoich danych znajdują się w polityce prywatności.

Komu możemy przekazać dane?

Twoje dane możemy przekazywać podmiotom przetwarzającym je na nasze zlecenie oraz podmiotom uprawnionym do uzyskania danych na podstawie obowiązującego prawa – oczywiście tylko, gdy wystąpią z żądaniem w oparciu o stosowną podstawę prawną.

Jakie masz prawa w stosunku do Twoich danych?

Masz prawo żądania dostępu, sprostowania, usunięcia lub ograniczenia przetwarzania danych. Możesz wycofać zgodę na przetwarzanie, zgłosić sprzeciw oraz skorzystać z innych praw wymienionych szczegółowo w polityce prywatności.

Jakie są podstawy prawne przetwarzania Twoich danych?

Podstawą prawną przetwarzania Twoich danych w celu świadczenia usług jest niezbędność do wykonania umów o ich świadczenie (tymi umowami są zazwyczaj regulaminy). Podstawą prawną przetwarzania danych w celu pomiarów statystycznych i marketingu własnego administratorów jest tzw. uzasadniony interes administratora. Przetwarzanie Twoich danych w celach marketingowych realizowanych przez Wirtualną Polskę na zlecenie Zaufanych Partnerów i bezpośrednio przez Zaufanych Partnerów będzie odbywać się na podstawie Twojej dobrowolnej zgody.