Tak więc mam rozwiązanie tego problemy, z wykorzystaniem komponentu
TApplicationEvents, który znajdziesz na zakładce
Additional.
Można by się posłużyć mapą komunikatów, ale to tylko skomplikowało by kod, w tym znaczeniu, że byłoby go więcej.
Umieść komponent
ApplicationEvents1 na formularzu okna potomnego (Child), następnie utwórz dla niego zdarzenie
OnMessage.
W pliku nagłówkowym (np. ChildWin.h) w sekcji
public zadeklaruj obiekt typu
TForm, posłuży on do śledzenia położenia i rozmiarów okna głównego (MDIForm).
- Kod: Zaznacz cały
private:
TForm *MyControl;
następnie w pliku źródłowym (np. ChildWin.cpp) w konstruktorze klasy trzeba podłączyć obiekt
MyControl do formularz głównego programu (MDIForm):
- Kod: Zaznacz cały
__fastcall TMDIChild::TMDIChild(TComponent *Owner)
: TForm(Owner)
{
MyControl = Application->MainForm;
}
teraz w utworzonym wcześniej zdarzeniu
OnMessage komponentu
ApplicationEvents1 umieszczamy kod ograniczajÄ…cy obszar przemieszczania siÄ™ okna:
- Kod: Zaznacz cały
void __fastcall TMDIChild::ApplicationEvents1Message(tagMSG &Msg,
bool &Handled)
{
try{
TRect R = Rect(0, 0, MyControl->ClientWidth - this->Width - GetSystemMetrics(SM_CXEDGE)*2,
MyControl->BoundsRect.Bottom);
if(this->Left >= R.Right) this->Left = R.Right;
if(this->Left <= 0) this->Left = 0;
if(this->Top + MyControl->Top + this->Height >= R.Bottom)
this->Top = MyControl->ClientHeight - this->Height - GetSystemMetrics(SM_CYEDGE)*2 - 49;
if(this->Top <= 0) this->Top = 0;
}catch(...){;}
}
Krótkie wyjaśnienie:Funkcja GetSystemMetrics pobiera grubość ramki okna zdefiniowaną w systemie i odejmuje ją od wymiarów formularza głównego.
Struktura MyControl->BoundsRect.Bottom zwraca położenie okna głównego w odniesieniu do dołu ekranu. Jest to potrzebne gdyż występuje problem z obliczeniem obszaru poruszania się okna potomnego po oknie głównych, ze względu na to, że na oknie głównym mogą znajdować się komponenty ToolBar i StatusBar, które nie są uwzględniane przez funkcję ClientHeight, dlatego zrezygnowałem z użycia tej funkcji do obliczania obszaru roboczego okna.
W kodzie występuje jawnie określona wartość
49, jest to suma szerokości komponentów ToolBar (u mnie 30) i StatusBar (u mnie 19). Jeżeli więc u Ciebie występują lub nie jakieś komponenty na formularzu okna głównego (MDIForm) ograniczające obszar przemieszczania się okna potomnego to musisz odpowiednio zmodyfikować tą wartość.
Można by się pokusić o automatyczne określanie szerokości obszaru roboczego okna głównego, ale wymagałoby to stworzenia odrębnego algorytmu, więc jeżeli można określić ten wymiar jawnie, to nie ma sensu komplikować kodu.
Ograniczanie obszaru przemieszczania się formularza potomnego po głównym z wykorzystaniem przechwytywania komunikatów, nie zawsze może działać prawidłowo, gdyż przy większym obciążeniu systemu, do programu mogą nie dotrzeć komunikaty i w efekcie kod nie zadziała.