Link to home
Start Free TrialLog in
Avatar of shikari
shikari

asked on

HTASK?

in Microsoft Visual C++ 1.52, in the function "OnActivateApp",  one of the arguments passed into the function is a handle to an HTASK structure.  In the online help provided there is no mention of the HTASK structure.  After doing a small amount of investigative work, we know roughly what HTASK is.  Our question is, with the handle to the HTASK passed into the function, how do we determine CWnd object attached to it.  There is a function "GetWindowTask" which finds the handle of the HTASK structure associated with the passed CWnd, but we want to go the opposite direction.  Got any ideas?
ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of nietod
nietod

A task (application) may have lots of top-level windows.  So there is  not way to use the
""handle to the HTASK passed into the function, ... [to] determine CWnd object attached to it"  There may be many CWnd's associated witht he task.  But you don't need to.  This member procedure is being called for the CWnd that was activated.  See for the task to become active, one of it (potentially many) top-level windows had the be activated.  This procedure is called for the one that was activated.  

Does that help?
Correction:  I seem to have remembered a little wrong.  This is called for every top-level window of the task being activated, not just the one that was activated.  (Similarly, it is called for every top-level window of the task being deactivated.)
Avatar of shikari

ASKER

This function "OnActivateApp", is called both when the application is being activated and de-activated.  There are two arguments passed to the function, "BOOL bActive" which specifies whether the application is being activated or de-activated, and the handle to the HTASK.  When the application is being de-activated, the handle points to the HTASK that being activated, but for some reason, the application that is supposed to be activated doesn't receive a WM_ACTIVATEAPP message, so we just decided to do it manually inside our program, whenever it is being de-activated.  In order to do this, we need to know the application that is being activated.  Does this clairify, at all, what we're trying to do?
I see.

You can use EnumWindows() to enumate all the top-level windows to find the windows of the other task. (That sort of approach is the only way since there may be more than one window for the task.)

However, that sounds like a patch.  It would be better to find out why the application is not getting an ACTIVATEAPP message when activating.  I can help you with that if you are interested.
Avatar of shikari

ASKER

Yeah, if you could help us out with finding out why the other application is not getting an ACTIVATEAPP message it would be great.  
The reason why we started doing all of this was in our application there is a modeless dialog box to display the progress of some procedure (e.g. converting a file), but with the modeless dialog box, the user could select some of the menu items which would interfere with the ongoing procedure and produce an error in the application.  But we didn't want to make the progress dialog modal because we still wanted the user to be able to switch applications since some conversions and such, could take as long as 15 minutes or more.  So we implemented a "PreTranslateMessage" function that would intercept the user's attempts to access functions when the progress dialog box is up.  But once we did that we encountered difficulties switching applications, which led us to implement the "OnActivateApp" function, since we were and are unable to determine the cause of the difficulties in switching applications.
In that case, helping you with the ACTIVATEAPP message problem would still be helping you with a patch.  The heart of the problem is the dialog box.  It sounds like you need a modal, not modeless, dialog.  A modal dialog will prevent the user from accessing other windows in your application, but they can still access other windows in the system.  

If you really want a modeless dialog, but want it to act at least partly like a modal dialog (i.e. prevent access to some of your windows.)  Disable the windows that you don't want the user to access.  This will make the modeless dialog function more like a modal dialog.  

I can still help you track down the message problem, but I think that is a mistake.  Best to solve the problem at its source.
Avatar of shikari

ASKER

Yeah, now I'm thinking we need a modal as well.  I'm not sure how to use a modal with a progress bar though.  Think you could help?
That may be getting out of may area of expertise.  I program in using windows API, not MFC.  Plus I don;t use much of the built in stuff.  Like I implement my own modal dialogs and my own buttons etc.  

But I can try.  What is the problem you are faced with?  Is the progress bar on the dialog or another window?
Avatar of shikari

ASKER

The progress bar is on the dialog.
Okay, but why is this a problem?  Why could you have a progress bar with a modeless dialog and not a modal one?
Avatar of shikari

ASKER

well, we tried to make the dialog box modal by saying
CDialog::CDialog(CProgressStatus::IDD);
CDialog::DoModal();
which made the box modal but the progress bar never showed up!
are we using the right functions to create the modal box? is there any other way to do it?

somethign I wasn't thinking about, if you use a modal dialog when you call DoModal(), the DoModal() procedure doesn't return until the dialog is closed.  Thus you can't use this to display the dialog and then continue execution in the same instruction stream.  Thus you can't do.

Dlg.DoModal()
TranslateFile();

because the TranslateFile(0 procedure is not called until the dialog is closed.  If that is what you were trying, it won't work (I'm probably not telling you anything new there).  To make this work with a modal dialog, you would need to do the TranslateFile in a different thread.  

But if you aren't using multiple threads and don't want to, another option is that you can use a modeless dialog and make it act like a modal dialog.  (Which is what you had tried, so thismight be the best approcach.)  To do this just dissable the other windows of your application, or at least the ones you want to prevent the user from accessing.  I don't use window's modal dialogs in my program.  I use a regular window that has styles that make it look like a dialog and I make the window disable its parent on the WM_NCCREATE message and enable its parent again on the WM_NCDESTROY message.  This works well for my purposes and probably would for you.
Avatar of shikari

ASKER

thank you. that helps a little. The only problem is i'm not sure where to disable the other windows from.
we basically need to restrict the user access to all the functions in the program while this particular update is happening and we don't want to go into the code of every function and disable it one by one b/c that would be very tedious and a problem when new functions are added. so, is there a way to disable every function in one shot while still allowing the user to press cancel to exit the dialog box.
and if i'm supposed to use WM_NCCREATE or WM_NCDESTROY i'm not exactly sure where to use it.
if you could help me out in disabling all the functions in one shot, i'd really appreciate it.
thanks.
I'm not sure what you mean by "functions"  If you mean functions in terms of code.  You don't need to disable those.  Instead you will prevent them from running.

If you mean functions in terms of UI features the user can access (buttons, menus etc) those are disabled by disabling their windows or by disabling on of their ancestor windows.
For example, if you have a MDI interface and you want to put up a "modal" dialog that disables everything in the main MDI window (the menus, toolbar buttons, and all the MDI children).  You just need to disable the MDI main window when you display the "modal" dialog window.  If you want to put up a "modal" dialog that disables on of the document windows, but still allows the user to use the other document windows and menus, etc, you would disable just the document window.

If that doesn't help, can you try describe the user interface to me.  Like what windows there are and what are their relationships.  What windows, if any can be accessed when the "modal" dialog is up.

You don't need to "hook" the create and destroy messages to handle this.  You can handle the disabling "manually".  You will create and display the "modal" dialog.  Then, since its not really modal, the code continues to run, so you can then disable all the windows you would like.  when you destroy the modal dialog, you then manually enable the windows that you had disabled.  

But if you will have lots of "modal"  dialogs and if this fits your design, you can make the dialog window automatically disable its parent when it is created and make it automatically enable its parent again when it is destroyed.  You can do this by placing the appropriate code in the onNCCREATE and onNCDESTROY handlers.  (I don't use MFC so if  can't give you a decent example in MFC, but I can do it in the regular API.)  The code would just get the dialog window's parent's handle and call EnableWindow() on it.  Then the code would call the default window procedure to handle the message as ussual.  It would look a little like this

BOOL SomeClass::OnNcCreate( LPCREATESTRUCT lpCreateStruct )
{
   CWnd *Parent = GetParent();

   Parent->EnableWindow(false);
   // somehow let default window procedure handle.  I don't know how that works in MFC.
}

void SomeClass::OnNcDestroy( )
{
   CWnd *Parent = GetParent();

   Parent->EnableWindow(true);
   // somehow let default window procedure handle.  I don't know how that works in MFC.
}

That should give you the idea.
Avatar of shikari

ASKER

We put in the window enable code, took out some of our code including onactivateapp, and now it seems to be working.  Thanks a lot, you've been a big help.