Toon posts:

[Delphi] MDIChildForm en OnShortCut event probleem

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik heb een MDI applicatie waarbij alle MDI children inheriten van een base class.
Bovendien worden alle menu-selecties, keyboard shortcuts, etc. afgehandeld via Actions.
Werkt prachtig, maar ik stuit op 1 probleem:

Wanneer een gebruiker een MDI form opent, en op [Esc] drukt voordat het form zichtbaar is ([Esc] is gekoppeld aan een Action die eigenlijk alleen maar Close doet in dit geval), dan krijgt 'ie een prachtige Access Violation te zien.
De stack trace geeft dan een hele trits StdWndProc(0,0,0,0) calls te zien, Windows messages naar (nog) niet geinitialiseerde controls denk ik.

Ik heb dit geprobeerd af te vangen in het OnShortCut event van de base class (en daar komt 'ie ook als de error optreedt) door de ComponentState te checken (zie code hieronder).
Maar helaas, op het moment dat de fout optreedt, is de ComponentState leeg...

Enig idee wat ik over het hoofd zie?
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
procedure TBaseMDIChild.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
var
  i: Integer;

  function HandleShortcut(AActionList: TCustomActionList): boolean;
  var
    i: integer;
    ShortCut: TShortCut;
    ShiftState: TShiftState;
  begin
    ShiftState := KeyDataToShiftState(Msg.KeyData);
    ShortCut := Menus.ShortCut(Msg.CharCode, ShiftState);
    for i := 0 to AActionList.ActionCount - 1 do
      if (TCustomAction(AActionList.Actions[i]).Enabled) and
         (TCustomAction(AActionList.Actions[i]).Visible) and
         (TCustomAction(AActionList.Actions[i]).ShortCut = ShortCut) then begin
        Result := TCustomAction(AActionList.Actions[i]).Execute;
        Exit;
      end;
    Result := False;
  end;

begin
  // don't process keystrokes if the form isn't ready
  Handled := (ComponentState * [csLoading, csDestroying] <> []);

  if not Handled then begin
    if FActionLists <> nil then begin
      for i := 0 to FActionLists.Count - 1 do begin
        if HandleShortcut(TCustomActionList(FActionLists[i])) then begin
          Handled := True;
          Exit;
        end;
      end;
    end;
  end;
end;

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 13-05 20:49

Tomatoman

Fulltime prutser

Waarom maak je het jezelf niet gemakkelijk en wijs je de shortcut pas toe als het MDI child klaar is? Niet erg netjes, wel effectief.

Een goede grap mag vrienden kosten.


Verwijderd

Topicstarter
Niet erg netjes, wel effectief.
Ga 'k eens even mee spelen. Idd niet echt netjes, maar wanneer je 't generiek doet (in de constructor van 't form de shortcuts parkeren, en die in de FormShow weer terugzetten) zou 't een mogelijkheid zijn. Niet ideaal, en ik weet nog niet wat de impact is als je meerdere MDIChildren hebt die dezelfde ActionLists benaderen, maar 't is de moeite waard.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 13-05 20:49

Tomatoman

Fulltime prutser

Ik heb nog even zitten nadenken over die access violation. Krijg je die zodra de shortcut geactiveerd wordt of pas als Close wordt aangeroepen? Ik gok op het laatste. Je probeert dan een window te vernietigen (eigenlijk de handle), terwijl datzelfde window net wordt gecreëerd. Gooi al die workarounds er eens uit en zet dan in de action event handler voor de shortcut een check of de window handle bestaat. Uit de losse pols:
Delphi:
1
2
3
4
5
procedure TForm1.EscapeActionClick(Sender: TObject);
begin
  if (ComponentState * [csLoading, csDestroying] = []) and HandleAllocated then
    Close;
end;

Een goede grap mag vrienden kosten.


Verwijderd

Topicstarter
Dat was juist het probleem, die AV kwam ergens tussen de shortcut en de Close, in een hele brei van windows messages...

Ik ben nu waarschijnlijk achter de oorzaak:
We gebruiken Multilizer om de boel te localizen (nederlands, engels, US-engels, frans, duits, italiaans), en op 't base MDI form stond een heel mooi TIvTranslator object om die vertaling te regelen. Toen ik die IvTranslator had weggehaald, was m'n hele AV probleem verdwenen...

Blijkbaar probeerde 'ie nog dingen te vertalen die 'ie nog in z'n lijstje had, maar die niet meer bestonden. Nu nog zien een workaround hiervoor te vinden (jammer genoeg geven die Multilizer-jongens niet alle source vrij, alleen "dat wat je nodig hebt").

Ik kwam hier trouwens achter door jouw "niet erg netjes" idee, waarmee ik het shortcut-probleem kon elimineren. Dus alsnog heel erg bedankt! :)

Nu nog een echte oplossing, maar dat vecht ik wel met Multilizer uit. We hebben niet voor niks een arm en een been voor dat pakket betaald...