Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Superfluous events when activating MDI child

Posted on 1997-09-18
12
Medium Priority
?
681 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
ID: 1345439
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
ID: 1345440
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
ID: 1345441
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Expert Comment

by:Dippen
ID: 1345442
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
ID: 1345443
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 600 total points
ID: 1345444
 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
 

Author Comment

by:cadenza
ID: 1345445
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
ID: 1345446
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
ID: 1345447
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
ID: 1345448
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
ID: 1345449
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
ID: 1345450
Thanks, and have fun.

-julio
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Please read the paragraph below before following the instructions in the video — there are important caveats in the paragraph that I did not mention in the video. If your PaperPort 12 or PaperPort 14 is failing to start, or crashing, or hanging, …
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …
Suggested Courses

824 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