Solved

Superfluous events when activating MDI child

Posted on 1997-09-18
12
657 Views
Last Modified: 2008-03-10
I need some help to get rid of superfluous events that are generated when the user selects another child window in my MDI app.

When the user selects another child when the child windows are not maximised, the following events are generated:

deactivate old active child
activate new active child
paint new active child

This is what I expected and what my code is designed for.

If the user selects another child (e.g. from the Windows menu) when the child windows are MAXIMISED, the following events are generated:

resize old active child
resize new active child
deactivate old child
activate new child
resize new child
resize new child
paint new child

This is much more than I need and many lines of code (in the OnResize event handler) are executed unnecessarily, taking a lot of time. I want to prevent this by e.g. raising a flag before the resizing starts, but how?? Or, alternatively, how can I make Windows (and Delphi) understand that
resizing is not what I want when activating a child window. (I think the first two resizes are from Windows, the other two from Delphi when merging the menus).
0
Comment
Question by:cadenza
  • 6
  • 5
12 Comments
 
LVL 5

Expert Comment

by:julio011597
Comment Utility
A boolean flag could be a good solution; how to implement it depends on what your handler does and when.

Messing up with events requires a bit of experience 'cause may lead to unpredictable behaviours, such as windows not displaying properly.

Could you tell some more about the task your handler has to accomplish? It may come out that you could cleanly solve your problem by defining a custom event.

-julio
0
 

Author Comment

by:cadenza
Comment Utility
When resizing a child window, my app needs to resize and reposition certain controls on the window + reading and processing some data buffers. This can take a couple of seconds or more. When the user resizes the child e.g. by dragging the resize handle, selecting 'maximize' or pressing the 'previous size' button on the caption bar, this realy needs to be done. On the other hand, when the user switches the active child, the spurious resizes should be ignored by my handler, since I don't want to loose all this time. So BEFORE the first resize I need to know that the user is not resizing the child, but instead switching active childs. When I know this, I could ignore the first resizes and on the last one check if the size realy is different from the previous one (that I have to store myself) and then decide if my handler needs to be executed.

Big commercial apps, like MS Word, seem to know what is happening and don't show any side effects. So my guess is that they trap a message that comes before all these resize messages. But which one??
0
 
LVL 5

Expert Comment

by:julio011597
Comment Utility
Ok, the way i would try and solve the problem is getting rid of the OnResize event, looking for a Windows message closer to your needs (something like WM_RESIZE), and assigning an handler to it in order to perform the needed task.

As soon as i go back home, i'll have a look into documentation.

A bientot, julio
0
 

Expert Comment

by:Dippen
Comment Utility
Hi!

One way of solving the problem with unwanted events resulting in unnecessary code execution is to temporarily shut down the event.

Consider this sample code:

var
  ResizeEvent : TNotifyEvent;

begin
  ResizeEvent := Yourform.OnResize;
  Yourform.OnResize := Nil;
  .
  .    //Resizing code for Yourform
  .
  Yourform.OnResize := ResizeEvent;
  .
  .
  .
  .
end;

I've used the above solution myself with good result.

The usage of the local 'container'-variable ResizeEvent makes the code 100% flexible if you change the event-handlers name afterwards. As far as I know, you can use this code on any event-handler in Delphi.

Hope this solves your problem!

//Dippen
0
 

Author Comment

by:cadenza
Comment Utility
Hi Dippen,

I'm afraid you leave the tricky part unsolved. The key problem in my case is: how do I know if a normal resize is going on (resize of the child directly or resize of the main form causing the maximised child to resize) in which case my handler needs to be executed) or if a switch of active child is done, generating lots of resize events for which I do not want to execute my handler. So the question is not: how to 'disable' my handler, but _when_ to disable my handler.

0
 
LVL 5

Accepted Solution

by:
julio011597 earned 200 total points
Comment Utility
 Hello back,

it seems you can solve the problem by trapping the WM_SIZE message.

You should get rid of the OnResize handler, and put equivalent code into a WM_SIZE handler.

Code would look something like this:

declaration:

--//--
type
  TYourForm = class(TForm)
  ...
  protected
    procedure WMSize(var Msg: TWMSize); message WM_SIZE;
  ...
  end;
--//--

implementation:

--//--
procedure TYourForm.WMSize(var Msg: TWMSize);
begin
  case Msg.SizeType of
   SIZE_RESTORED:  {size changed}
     handle_size_restored;
   SIZE_MINIMIZED: {size changed 'cause the user minimized}
     handle_size_minimized;
   SIZE_MAXIMIZED: {size changed 'cause the user maximized}
     handle_size_maximized;
  end;
  inherited; {don't forget this!}
end;
--//--

This should work, but i couldn't test it.
Just ask more if you have troubles.

Rgds, julio
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:cadenza
Comment Utility
Hi Julio,

I tried your suggestion (thanks!). The key problem remains, however, that you need to find out if the resize is a 'real' resize, or one in the process of changing active child windows. Your method does not solve this, unfortunately. (or am I missing something here??)

I experimented along the lines you set out quite a lot. Specifically trapping the WM_MDIActivate event that is sent to the child windows when the active child window is changed, looked promising. The best I could get it was:
- trap the WM_MDIActivate message
- check if it was sent to the active child
- if so, raise a flag
- the resize event handler checks for the flag and does not execute if the flag is raised
- the paint event handler checks for the flag and if raised calls the resize event handler, resets the flag and does the painting.
- the resize event handler keeps the size of the window in a private variable, to check if it realy needs executing (and if so, updates the size).

This way it worked nearly right. There were some side effects, however, (like hiding the lower side of one of the child windows behind the task bar, hiding the status bar of the child window) which made me decide this still was not good enough. Probably it is possible to correct for this kind of side effect, but that would make the code quite unclear, and so difficult to maintain. Trapping messages, raising flags and checking is OK to me, but that should be it, more or less.

Any suggestions still much appreciated!!

Wim

0
 
LVL 5

Expert Comment

by:julio011597
Comment Utility
Well, i've tryed the WM_SIZE message in an SDI contest, and it does _not_ get raised when changing the active window, which should be what you need.
Maybe the problem is with MDI applications?? I'll have a look at it.

About side effects, did you remeber to put the 'inherited' as last call of your WM_MDIActivate event handler?
Or, the windows may need an Update or Refresh to repaint properly, which, BTW, would again generate some messages, so restarting the whole pain (but, a flag could be raised before the refresh ;)

Cheers, julio
0
 

Author Comment

by:cadenza
Comment Utility
Hi Julio,

thanks for your quick reaction.

1 - yes, I called inherited in the WM_ - event hendlers (OK: I forgot it once, but then indeed nothing happened, so that was easy).

2 - about WM_Size in an SDI app: SDI apps are much different in this respect from MDI apps. In MDI apps the not-active child windows are kept in the 'restored' position, windows style wsNormal. Plus the active child window gets its menu merged with the menu of the parent form. The result of this is 2 resizes in order to restore the old active child and maximise the new active child + 2 resizes to merge the menus (including the system menu). The latter 2 I'm not entirely sure about the cause, but they do occur.

I thought some more about the side effects, and I think the hiding of the child windows status bar behind the tast bar might have to do with the original creation of the window in the wsMaximized style. I'll do another experiment with this. If this side effect can be solved in a clear way, I'll consider the problems solved for the moment.

Cherio,

Wim
0
 
LVL 5

Expert Comment

by:julio011597
Comment Utility
Hello,

topic is 'WM_MDIMAXIMIZE', and here is what Remarks say:

"If an MDI client window receives any message that changes the activation of its child windows while the currently active MDI child window is maximized, Windows restores the active child window and maximizes the newly activated child window".

This seems to mean that your extra two resizes should be a side effect of your code actions.

I still think the solution should be something like putting an WM_SIZE event handler in the child windows; the handler performs some task based on a (per window) flag; the flags should be controlled by the parent window based on events WM_MDIACTIVE and WM_MDIMAXIMIZE.

I'm sorry i can't give you some more help, but i'm very busy this period and have to give up; also think my answer doesn't fit your problem at all, so feel free to reject it.

Good luck, julio
0
 

Author Comment

by:cadenza
Comment Utility
Julio,

I did some reading in the online help and experimented a bit more. It appeared the side effects I mentioned before, also happen in the original code, without trapping the WM_MDIACTIVATE message etc. This seems to me a different subject and I consider the problem solved. Furthermore: the side-effect only happens after first minimising a the child, so I can simply 'solve' this one by making it impossible for the user to minimise the child windows!! :)

I think your contributions were essential for finding the solution and I learned a lot, so I am happy to give you the points.

Cheers,

Wim
0
 
LVL 5

Expert Comment

by:julio011597
Comment Utility
Thanks, and have fun.

-julio
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now