Hallo,
ich habe seit einiger Zeit ein Problem mit einer
MDI-Anwendung, die ich für einen Kunden geschrieben habe.
Eine Anforderung des Kunden besteht darin, dass während der Login-Phase des Programms innerhalb des
MDI-Clientbereichs eine Bitmap gezeigt wird; eine andere Anforderung besagt, dass in Abhängigkeit von bestimmten Systemzuständen, die sich von Programmstart bis zur Beendigung nicht ändern, die Farbe des Clientbereichs auf rot, blau oder blaugrün gesetzt werden soll. Und nebenbei sollen noch die Scrollbars im Clientbereich entfernt werden.
Dies hab ich nach Suche in diesem Forum folgendermassen realisiert. In der FormCreate-Methode des
MDI-Parent habe ich folgenden Code eingefügt:
Delphi-Quellcode:
FClientInstance := Classes.MakeObjectInstance (ClientWndProc);
FPrevClientProc := Pointer (GetWindowLong (ClientHandle,
GWL_WNDPROC));
if FPrevClientProc = Nil then
Raise EInvalid.Create ('Fensterprozedur bestimmen ' + IntToStr (GetLastError))
else
if SetWindowLong (ClientHandle,
GWL_WNDPROC,
LongInt (FClientInstance)) = 0 then
Raise EInvalid.Create ('Fensterprozedur setzen ' + IntToStr (GetLastError));
Hiermit sollte ja jetzt meine eigene Fensterprozedur für das
MDI-Clientwindow aktiv werden, wenn eine entsprechende Message kommt.
Und so sieht die Fensterprozedur aus:
Delphi-Quellcode:
procedure TFormMDI.ClientWndProc (
var Msg : TMessage);
begin
try
if Msg.Msg = wm_EraseBkgnd
then
begin
{ Hintergrundfarbe des Clientbereichs setzen }
if fSuperVisorMode
then
Canvas.Brush.Color := clRed
else
if LowerCase (System) = '
prozesswerte'
then
{ blau wie Standarddesktop von XP }
Canvas.Brush.Color :=
RGB ( 58,
110,
165)
else
{ grünblau wie Standarddesktop von 95 }
Canvas.Brush.Color :=
RGB ( 0,
128,
128);
{ Hintergrund füllen }
FillRect (TWMEraseBkgnd (Msg).DC,
ClientRect,
Canvas.Brush.Handle);
{ ggf. Hintergrundbild anzeigen }
if fHintergrundBild
then
begin
ImageHintergrund.Left := (Screen.Monitors [1].Width - ImageHintergrund.Picture.Width)
div 2;
ImageHintergrund.Top := (ClientHeight - ImageHintergrund.Picture.Height)
div 2;
ImageHintergrund.Visible := True
end;
Msg.Result := 1
end
else
begin
if Msg.Msg = wm_NCCalcSize
then
{ Scrollbars im MDI-Clientbereich verhindern }
SetWindowLong (ClientHandle,
gwl_Style,
GetWindowLong (ClientHandle,
gwl_Style)
and not (ws_HScroll
or ws_VScroll));
Msg_vb.Result := CallWindowProc (FPrevClientProc,
ClientHandle,
Msg.Msg,
Msg.wParam,
Msg.lParam)
end
except
{ an dieser Stelle dürfen keine Fehlermeldungen ausgegeben werden, da sonst das
Programm komplett abstürzt }
end
end;
Das funktioniert auch alles wunderbar. Nicht nur auf einem, sondern auch auf mehreren Arbeitsplätzen. Aber alle paar Tage kommt es auf einem der Rechner zu einem Fehler: beim Erzeugen eines neuen
MDI-Childwindows bleibt das Programm hängen. Es gibt viele unterschiedliche Typen von
MDI-Children, und der Fehler tritt mal bei dem einen und mal bei dem anderen auf, so dass ich einen Fehler in den Children selbst eigentlich ausschliesse.
Der Fehler äussert sich so:
- Der Rahmen des
MDI-Childs erscheint, der Inhalt bleibt leer.
- wenn keine
Exception-Behandlung in der ClientWndProc-Methode erfolgt, bleibt das Programm komplett hängen und kann nur noch über den Task-Manager abgeschossen werden
- wenn ich in die
Exception-Behandlung folgenden Code einfüge
Delphi-Quellcode:
if Msg_vb.Msg = WM_MDICreate then
try
Msg_vb.Result := CallWindowProc (FPrevClientProc,
ClientHandle,
Msg.Msg,
Msg.wParam,
Msg.lParam)
except
end
läuft das Programm nach einer Wartezeit von ein paar Sekunden in der Regel weiter und erzeugt durch den zweiten Aufruf von CallWindowProc das gewünschte Fenster
- wenn ich versuche, den aufgetretenen Fehler zu ermitteln und auszugeben, z.B. als eMail oder über eine offene Socket-Verbindung zu einem Host, stürzt das Programm gnadenlos ab.
Es hat nun keinen Zweck, dass ich meinen gesamten Quellcode hier anfüge, da damit erstens der Kunde nicht einverstanden sein wird, und zweitens ca. 300000 Zeilen wohl auch ein bißchen viel wären. Es kann natürlich sein, das da noch ein blöder Fehler drin ist, der dann ab und zu dazwischen funkt.
Aber vielleicht hat ja jemand von Euch eine Idee oder auch schon mal Probleme in diesem Umfeld gehat und kann mit Tipps geben, wie ich der Ursache dieses etwas seltsamen Verhaltens auf die Spur kommen kann.
Vielen Dank schon mal
Klaus