Jest kilka sposobów na przechwytywanie komunikatów Windows przekazywanych do Twoich programów. Możesz nadpisać wirtualną funkcję WndProc głównej formy, możesz stworzyć mapę komunikatów, możesz wreszcie stworzyć handler OnMessage dla Twojej aplikacji. private: // User declarations void __fastcall WndProc(Messages::TMessage &Message);Krok 2: Wpisz kod funkcji. Dziedziczona funkcja WndProc powinna wywołać funkcję bazową TForm::WndProc, dla wszystkich komunikatów, które Cię nie interesują. Ta funkcja zapobiega uruchomieniu wygaszacza ekranu. void __fastcall TForm1::WndProc(Messages::TMessage &Message) { if( (Message.Msg == WM_SYSCOMMAND) && (Message.WParam == SC_SCREENSAVE) ) { Application->MessageBox("Nie chcemy wygaszcza!", "SCR No", MB_OK); Message.Result = true; } else TForm::WndProc(Message); } Tworzenie mapy komunikatu (Message Map): Mapy komunikatów pozwalają na pisanie funkcji, które otrzymują jedynie specyficzne komunikaty, a nie wszystkie, tak jak WndProc. Mapy komunikatów używają różnych struktur znajdujących się w \include\messages.hpp. Na przykład, mapa komunikatu WM_GETMINMAXINFO użyłaby struktury TWMGetMinMaxInfo. Te struktury są całkiem przyjemne, ponieważ wartości WPARAM i LPARAM zostały zdekodowane do bardziej zrozumiałych członków struktury. Krok 1: Dodaj deklarację funkcji i mapę komunikatu do nagłówka. private: // User declarations void __fastcall WMSysCommand(TWMSysCommand &Message); public: // User declarations __fastcall TForm1(TComponent* Owner); BEGIN_MESSAGE_MAP MESSAGE_HANDLER(WM_SYSCOMMAND,TWMSysCommand,WMSysCommand) END_MESSAGE_MAP(TForm)Krok 2: Wpisz kod funkcji. Jeżeli chcesz przekazać komunikat do klasy bazowej użyj funkcji Dispatch klasy bazowej. void __fastcall TForm1::WMSysCommand(TWMSysCommand &Message) { if(Message.CmdType == SC_SCREENSAVE) { Application->MessageBox("Nie chcemy wygaszcza!","SCR No",MB_OK); Message.Result = true; } else TForm::Dispatch(&Message); }Uwaga: Upewnij się, że wywołujesz fukcję Dispatch należącą do klasy bazowej, a nie do klasy dziedziczonej. Mapy komunikatów są wyzwalane z funkcji Dispatch dziedziczonej klasy. Wywołanie tejże właśnie funkcji Dispatch spowoduje wykonywanie nieskończonej pętli. Tworzenie handlera OnMessage: Handler ten pozwala na obsługę komunikatu zanim zostanie on przetworzony przez aplikację. Krok 1: Dodaj deklarację funkcji OnMessage. private: // User declarations void __fastcall AppOnMessage(TMsg &Message, bool &Handled);Krok 2: Wpisz kod funkcji. Ustaw flagę Handled dla komunikatów, które obsługujesz. void __fastcall TForm1::AppOnMessage(TMsg &Msg, bool &Handled) { if( (Msg.message == WM_SYSCOMMAND) && (Msg.wParam == SC_SCREENSAVE) ) { Application->MessageBox("Nie chcemy wygaszcza!","SCR No",MB_OK); Handled = true; } else Handled = false; }Krok 3: W konstruktorze głównej formy przypisz funkcję AppOnMessage do zdarzenia OnMessage globalnego obiektu Application. __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { Application->OnMessage = AppOnMessage; } Uwagi: Jak więc zdecydujesz, którego sposobu użyć? Nadpisanie metody WndProc jest dobre w przypadku gdy obsługujesz wiele komunikatów. Mapy komunikatów pozwalają skoncentrować się na pojedynczym komunikacie, a kod jest łatwy do odczytania. Wykorzystując handler OnMessage będziesz mógł przechwycić komunikat zanim przetworzy go program. Minusem jest to, że komunikaty wysłane przez SendMessage albo Perform nie są przekazywane do handlera OnMessage. Na dodatek handler ten może doprowadzić do zawieszenia systemu. Podsumowując, używaj raczej WndProc albo map komunikatów. Zaś handlera OnMessage jedynie w przypadkach, kiedy tylko on jest w stanie przechwycić komunikat. Jeżeli zachodzi konieczność użyj "subclassingu" - poprzez właściwość WindowProc klasy dziedziczonej z TControl. |