Jump to content

Making Help Manager Useable: Difference between revisions

From EDM2
Created page with "By Samuel Audet ---- Last Modified: May 7, 2001 20:07:02 EDT. ---- First of all, some explanations. When trying to make the usual "help tables" work with notebook dial..."
 
Ak120 (talk | contribs)
mNo edit summary
 
(2 intermediate revisions by 2 users not shown)
Line 1: Line 1:
By [[Samuel Audet]]
''By [[Samuel Audet]]''


----
----
Last Modified: May 7, 2001  20:07:02 EDT.
Last Modified: May 7, 2001  20:07:02 EDT.
----
----
First of all, some explanations. When trying to make the usual "help tables" work with notebook dialogs, it seems they do not accept the notebook dialogs as HELPITEMs. This is very frustrating, as it SHOULD work that way. Oh well, that's how it is... Now, here's how I think is the best (ie.: not perfect) way to implement IPF in Notebook dialogs.


 
First, '''load''' and '''associate''' the usual help tables with the main dialog, but leave out the notebook from it. For example, you have an "OK" and "Save" Button, here's what you'd put in the resource file:
First of all, some explanations. When trying
<pre>
to make the usual "help tables" work with notebook dialogs, it seems they
HELPTABLE MAINTABLE
do not accept the notebook dialogs as HELPITEMs. This is very frustating,
as it SHOULD work that way. Oh well, that's how it is... Now, here's how
I think is the best (ie.: not perfect) way to implement IPF in Notebook
dialogs.
 
 
First, '''load''' and '''associate''' the usual help tables with the
main dialog, but leave out the notebook from it. For example, you have
an "OK" and "Save" Button, here's what you'd put in the resource file:
 
 
<pre>HELPTABLE MAINTABLE
BEGIN
BEGIN
   HELPITEM ID_MAIN, SUBTABLE_MAIN, 1000
   HELPITEM ID_MAIN, SUBTABLE_MAIN, 1000
Line 30: Line 19:
END
END
</pre>
</pre>
Note: as the "extended help" for the MAIN HELPITEM, include a more general help than only the buttons, because if you leave cracks in the following method, the user expects to see something that gives information on the whole notebook.


Note: as the "extended help" for the MAIN HELPITEM, include a more general
Now in the C code, you will need a big structure containing all information needed on the notebook dialog. I always use such a structure when using Notebooks. It permits me, for example to delay loading of dialog windows to when the user requests it, or to easily find a dialog window handle to send a message to it (like we will need here), etc. Thanks Rick Fishman for that great idea everyone should use in Notebooks! Here's what I use:
help than only the buttons, because if you leave cracks in the following
<pre>
method, the user expects to see something that gives information on the
/* notebook page info structure */
whole notebook.
 
 
Now in the C code, you will need a big structure containing all information
needed on the notebook dialog. I always use such a structure when using
Notebooks. It permits me, for example to delay loading of dialog windows
to when the user requests it, or to easily find a dialog window handle
to send a message to it (like we will need here), etc. Thanks Rick Fishman
for that great idea everyone should use in Notebooks! Here's what I use:
 
 
<pre>/* notebook page info structure */


typedef struct _NBPAGE
typedef struct _NBPAGE
Line 61: Line 39:
} NBPAGE, *PNBPAGE;
} NBPAGE, *PNBPAGE;
</pre>
</pre>
 
Then, initialize a global variable of this structure with the values, for example:
Then, initialize a global variable of this structure with the values, for
<pre>
example:
NBPAGE nbpage[] =
 
<pre>NBPAGE nbpage[] =
{
{
   {wpFoo,  "Tab 1 of 4", "~Foo",  ID_FOO,  FALSE, BKA_MAJOR, 0, 0},
   {wpFoo,  "Tab 1 of 4", "~Foo",  ID_FOO,  FALSE, BKA_MAJOR, 0, 0},
Line 82: Line 58:
}
}
</pre>
</pre>
When cooking up your notebook, make AT LEAST the '''window handle''' available.
When cooking up your notebook, make AT LEAST the '''window handle''' available.


 
In the main dialog (or client) window procedure, include the following. You will need to find your Notebook window handle (usually with a window ID).
In the main dialog (or client) window procedure, include the following.
<pre>
You will need to find your Notebook window handle (usually with a window
case WM_HELP:
ID).
 
 
<pre>case WM_HELP:
{
{
   HWND hwndfocus = WinQueryFocus(HWND_DESKTOP);
   HWND hwndfocus = WinQueryFocus(HWND_DESKTOP);
Line 114: Line 85:
       and the focus is on one of the notebook dialog controls */
       and the focus is on one of the notebook dialog controls */


   for(i = 0; i &lt; PAGE_COUNT; i++)
   for(i = 0; i < PAGE_COUNT; i++)
       if(WinIsChild(hwndfocus,nbpage[i].hwnd))
       if(WinIsChild(hwndfocus,nbpage[i].hwnd))
       {
       {
Line 140: Line 111:
}
}
</pre>
</pre>
 
Note: if you try to send a "WM_HELP" to the notebook when "hwndfocus == hwndNB" thinking you are smart because BKN_HELP is sent, and an error occurs, the notebook sends back a WM_HELP to its owner and keeps getting back more and more WM_HELP and BKN_HELP around and around, until you're quick enough to remove the focus from the notebook... don't ask me why. It's a miracle
Note: if you try to send a "WM_HELP" to the notebook when "hwndfocus ==
hwndNB" thinking you are smart because BKN_HELP is sent, and an error occurs,
the notebook sends back a WM_HELP to its owner and keeps getting back more
and more WM_HELP and BKN_HELP around and around, until you're quick enough
to remove the focus from the notebook... don't ask me why. It's a miracle
it even works.
it even works.


 
Then, as you might have imagined where all those WM_HELP are sent to, include the following into all your Notebook dialog window procedures.
Then, as you might have imagined where all those WM_HELP are sent to,
<pre>
include the following into all your Notebook dialog window procedures.
/* this is useful when the user presses F1 in
 
 
<pre>/* this is useful when the user presses F1 in
   any of the dialog controls owned by this window.
   any of the dialog controls owned by this window.
   Also, all the previous kludges send WM_HELP here. */
   Also, all the previous kludges send WM_HELP here. */
Line 163: Line 126:
   return 0; /* grrr, beat off Help Manager */
   return 0; /* grrr, beat off Help Manager */
</pre>
</pre>
 
Next, in your .HLP file, just include the newly defined panel name or reference you have included in all the WM_HELP messages like above. I also recommend a global variable indicating successful '''loading''' of the help file (into a '''help instance''') so that the user won't have to mess around with errors and possible crashes.
Next, in your .HLP file, just include the newly defined panel name or reference
you have included in all the WM_HELP messages like above. I also recommend
a global variable indicating successful '''loading''' of the help file
(into a '''help instance''') so that the user won't have to mess around
with errors and possible crashes.
 


Tada! Great help management in notebooks!
Tada! Great help management in notebooks!
 


[[Category:PM Articles]]
[[Category:PM Articles]]

Latest revision as of 02:51, 25 February 2018

By Samuel Audet


Last Modified: May 7, 2001 20:07:02 EDT.


First of all, some explanations. When trying to make the usual "help tables" work with notebook dialogs, it seems they do not accept the notebook dialogs as HELPITEMs. This is very frustrating, as it SHOULD work that way. Oh well, that's how it is... Now, here's how I think is the best (ie.: not perfect) way to implement IPF in Notebook dialogs.

First, load and associate the usual help tables with the main dialog, but leave out the notebook from it. For example, you have an "OK" and "Save" Button, here's what you'd put in the resource file:

HELPTABLE MAINTABLE
BEGIN
   HELPITEM ID_MAIN, SUBTABLE_MAIN, 1000
END

HELPSUBTABLE SUBTABLE_MAIN
BEGIN
   HELPSUBITEM ID_OKPB, 1100
   HELPSUBITEM ID_SAVEPB, 1100
END

Note: as the "extended help" for the MAIN HELPITEM, include a more general help than only the buttons, because if you leave cracks in the following method, the user expects to see something that gives information on the whole notebook.

Now in the C code, you will need a big structure containing all information needed on the notebook dialog. I always use such a structure when using Notebooks. It permits me, for example to delay loading of dialog windows to when the user requests it, or to easily find a dialog window handle to send a message to it (like we will need here), etc. Thanks Rick Fishman for that great idea everyone should use in Notebooks! Here's what I use:

/* notebook page info structure */

typedef struct _NBPAGE
{
    PFNWP    pfnwpDlg;    /* Window procedure address for the dialog */
    PSZ      szStatusLineText;  /* Text to go on status line */
    PSZ      szTabText;   /* Text to go on major tab */
    ULONG    idDlg;       /* ID of the dialog box for this page */
    BOOL     skip;        /* skip this page (for major pages
                             with minor pages) */
    USHORT   usTabType;   /* BKA_MAJOR or BKA_MINOR */
    ULONG    ulPageId;    /* notebook page ID */
    HWND     hwnd;        /* set only when page frame is loaded */

} NBPAGE, *PNBPAGE;

Then, initialize a global variable of this structure with the values, for example:

NBPAGE nbpage[] =
{
   {wpFoo,  "Tab 1 of 4", "~Foo",  ID_FOO,  FALSE, BKA_MAJOR, 0, 0},
   {wpFoo2, "Tab 2 of 4", "Foo~2", ID_FOO2, FALSE, BKA_MAJOR, 0, 0},
};

/* some constants so that we don't have
   to modify code if we add pages */
#define PAGE_COUNT (sizeof( nbpage ) / sizeof( NBPAGE ))
#define PAGE_FOO  0
#define PAGE_FOO2 1

int main()
{
   ...
}

When cooking up your notebook, make AT LEAST the window handle available.

In the main dialog (or client) window procedure, include the following. You will need to find your Notebook window handle (usually with a window ID).

case WM_HELP:
{
   HWND hwndfocus = WinQueryFocus(HWND_DESKTOP);
   HWND hwndNB = WinWindowFromID(hwnd,ID_NB);
   int i;

   /* this is useful when the user presses Help button
      and the focus is on the notebook tabs themselves */

   if(hwndfocus == hwndNB)
   {
      WinSendMsg(
         LONGFROMMR(WinSendMsg(hwndNB, BKM_QUERYPAGEWINDOWHWND,
            WinSendMsg(hwndNB,BKM_QUERYPAGEID,0,MPFROMSHORT(BKA_TOP))
                                                  , NULL))
                                                     ,WM_HELP,0,0);
      return 0; /* prevents the notebook unfriendly
                   help manager to interfere */
   }

   /* this is useful when the user presses Help button
      and the focus is on one of the notebook dialog controls */

   for(i = 0; i < PAGE_COUNT; i++)
      if(WinIsChild(hwndfocus,nbpage[i].hwnd))
      {
         WinSendMsg(nbpage[i].hwnd,WM_HELP,0,0);
         return 0; /* prevents the notebook unfriendly
                      help manager to interfere */
      }

   break; /* if focus is not on notebook controls or the
             notebook, let the usual help mechanism handle it */

case WM_CONTROL:
{
   switch(SHORT2FROMMP(mp1))
   {

   /* this is useful when the user presses F1 on a notebook tab */
   case BKN_HELP:

      WinSendMsg(LONGFROMMR(WinSendMsg(WinWindowFromID(hwnd,ID_NB),
                 BKM_QUERYPAGEWINDOWHWND, mp2 /* this is ulPageId */, NULL))
                                               ,WM_HELP,0,0);
      return 0; /* bug off Help Manager */
   }
}

Note: if you try to send a "WM_HELP" to the notebook when "hwndfocus == hwndNB" thinking you are smart because BKN_HELP is sent, and an error occurs, the notebook sends back a WM_HELP to its owner and keeps getting back more and more WM_HELP and BKN_HELP around and around, until you're quick enough to remove the focus from the notebook... don't ask me why. It's a miracle it even works.

Then, as you might have imagined where all those WM_HELP are sent to, include the following into all your Notebook dialog window procedures.

/* this is useful when the user presses F1 in
   any of the dialog controls owned by this window.
   Also, all the previous kludges send WM_HELP here. */

case WM_HELP:
   WinSendMsg(WinQueryHelpInstance(hwnd),
              HM_DISPLAY_HELP,MPFROMP("FooPanel"),
              MPFROMSHORT(HM_PANELNAME));
   return 0; /* grrr, beat off Help Manager */

Next, in your .HLP file, just include the newly defined panel name or reference you have included in all the WM_HELP messages like above. I also recommend a global variable indicating successful loading of the help file (into a help instance) so that the user won't have to mess around with errors and possible crashes.

Tada! Great help management in notebooks!