home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / HELPPRG.ZIP / HELP!.DOC next >
Text File  |  1989-07-10  |  53KB  |  1,313 lines

  1. OUTLINE OF THIS DOCUMENT
  2. ------------------------
  3.  
  4. I. Introduction
  5.         1. Background on HELP!
  6.         2. Archive Contents
  7.         3. What YOU need
  8.         4. The sample program - HELPSAMP
  9.         5. Distributing HELPLIB.DLL & MSHELP.DLL
  10.         6. Acknowledgments
  11.  
  12. II. Using HELPLIB.DLL
  13.         1. The Help File
  14.                 a) Creating the Help file
  15.                         1. Dot commands
  16.                         2. Colors
  17.                         3. Mandatory .contexts
  18.                         4. Tips on creating the help file
  19.                         5. Using HELPMAKE
  20.                 b) Testing the Help File
  21.                         1. Using QuickHelp To test
  22.  
  23.         2. Your Application
  24.                 a) WM_HELP Messages
  25.                 b) HelpBox Function Call
  26.                         1. Prototype
  27.                         2. Explanation of parameters
  28.                 c) The Help Hook
  29.                         1. installing
  30.                         2. Calls To..
  31.                         3. removing
  32.                         4. The HelpHook procedure in detail
  33.                 d) Making the help context sensitive
  34.                         1. STRINGTABLE in RC file
  35.                         2. The F1 key
  36.                         3. Menu Items
  37.                         4. Dialog Boxes
  38.                         5. Message Boxes
  39.                 e) compiling and testing
  40.  
  41. III. Final Words
  42.         1. Distribution (again!!)
  43.         2. I want to see your apps!!!
  44.         3. The future for HELPLIB.DLL
  45.         4. Contacting me
  46.  
  47.  
  48. I. INTRODUCTION
  49. ---------------
  50.  
  51.  
  52. I.1. Background on HELP!
  53.  
  54. The idea of HELP! came to me when I was coding a couple of PM apps at
  55. the same time. I noticed the neat Help boxes Microsoft provided for
  56. Start Programs, Control Panel, Task Manager, etc., and thought it
  57. would be nice to have a facility like that in my programs. Its one
  58. thing to have all those fun HELP buttons in your programs, its
  59. another story doing something useful with them. I hunted around the
  60. zillions of files that OS/2 loaded on to my machine, hoping to find a
  61. .DLL or a sample program with some code I could "borrow". NO LUCK!! I
  62. did however stumble across the file MSHELP.DLL, part of the QuickHelp
  63. files. After EXEHDR'ing this puppy, I knew I was on the right track.
  64. I went back to the documentation, two versions old (SDK v1.03) at the
  65. time, and found some (slim) documentation and the sample program, LQH
  66. (little Quick Help). After v1.03 of the SDK, Microsoft stopped
  67. sending out this documentation, sample program, and even the import
  68. library, MSHELP.LIB. But I had enough to go with, albeit in some
  69. parts crudely, and ended up with the .DLL I was looking for, and
  70. hopefully it will "help" you too!
  71.  
  72. I tried to make implementing Help in your apps as simple as possible.
  73. It is only 1 function call, the addition of a help hook in your
  74. module, and the defining of some strings in your resource file. The
  75. most difficult part of the whole process is the creation of the help
  76. file itself. Only you can decide what topics you want help on, how to
  77. cross reference topics, the verbage you want etc. I've also included
  78. a sample program, HELPSAMP, with its source and help file as a guide
  79. to using HELPLIB.DLL. The sample program shows most of the highlights
  80. of the .DLL, but is by no means inclusive of all you can do. It shows
  81. how to get context sensitive help for menu items, dialog boxes, and
  82. message boxes. The sample help file shows examples of how to set up
  83. cross references ( sometimes referred to as chaining or
  84. backtracking), use of colors, and more. It would behoove you to print
  85. out a copy of HELPSAMP.C, HELPSAMP.H and HELPSAMP.RC as a guide while
  86. you read this text. I will refer to code bits frequently.
  87.  
  88. Some of the features of HELPLIB.DLL include:
  89.  
  90. - Your help files are compatible with QuickHelp!! 
  91.  
  92.   I am still working on reverse compatibility, i.e. bringing QH files
  93.   into HELPLIB. Without documentation on the function calls in
  94.   MSHELP.DLL, this has proved frustrating, but I am getting there.
  95.  
  96. - It looks, works, acts, smells, barks, and sings just like the help
  97.   boxes inherent to OS/2.
  98.  
  99.   things like text reformatting to width of help window, resizeable
  100.   window, window moves independently of client application
  101.   etc.
  102.  
  103. - Easy to implement.
  104.  
  105. - Changing help in your application now involves just changing your
  106.   help file ( in most cases).
  107.  
  108. - liberal use of color to emphasize help text
  109.  
  110. The best way to see what it can do is to play around with the sample
  111. app. More on this later.
  112.  
  113.  
  114. I.2. Archive contents:
  115.  
  116. SAMPLE APP - HELPSAMP
  117. ---------------------
  118. HELPSAMP                - make file
  119. HELPSAMP.C              - SOURCE FILE
  120. HELPSAMP.DEF            - DEFINITION FILE
  121. HELPSAMP.EXE            - EXECUTABLE
  122. HELPSAMP.H              - INCLUDE HEADER FILE
  123. HELPSAMP.HLP            - ENCODED HELP FILE
  124. HELPSAMP.ICO            - ICON FILE 
  125. HELPSAMP.RC             - RESOURCE FILE
  126. HELPSAMP.TXT            - ASCII VERSION OF HELP FILE
  127.  
  128.        
  129. DLL FILES
  130. ---------
  131. HELPLIB.DLL             - HELP DLL
  132. HELPLIB.LIB             - IMPORT LIBRARY FOR HELPLIB.DLL
  133.  
  134.  
  135. HELP!.DOC               - THIS DOCUMENT
  136.  
  137.  
  138.  
  139. I.3. What you need
  140.  
  141. You will need to have certain files and utility programs in order to
  142. utilize HELPLIB.DLL. All of them are included in the PM SDK or
  143. TOOLKIT. Some are also available with MS compilers or with the
  144. QuickHelp disk set that is purchased separately if you didn't buy the
  145. SDK or TOOLKIT.
  146.  
  147. Requirements:
  148.  
  149. 1) OS/2 compatible compiler
  150.  
  151. 2) HELPMAKE.EXE  
  152.  
  153.    This is the utility that allows you to make QuickHelp compatible
  154.    help files. Comes with SDK, TOOLKIT, QuickHelp, and some of the
  155.    compilers. 
  156.  
  157.    I am using version 1.02.014 dated 2/27/89. ( came with commercial
  158.    version of toolkit). I have also used the version that came with
  159.    1.06 of the SDK, and have coded HELPLIB.DLL to work with its
  160.    output, but it doesn't have all the options the newer version
  161.    does. The newer version compresses files a little more. More on
  162.    this later.
  163.  
  164. 3) MSHELP.DLL
  165.  
  166.    This is the "Help engine" used by QuickHelp to find topics,
  167.    decompress them, etc. HELPLIB.DLL makes calls to this DLL to
  168.    access your help file. 
  169.  
  170.    Microsoft keeps changing this DLL. The changes between v1.06 SDK
  171.    and 1.1 (SDK and TOOLKIT) forced me to change code. At present, I
  172.    will only work with the latest version (1.1 SDK and TOOLKIT). The
  173.    file is dated 2/24/89. I am working to make HELPLIB.DLL more 
  174.    backwards compatible.
  175.   
  176. Optional:
  177.  
  178. 4) QuickHelp
  179.  
  180.    QuickHelp isn't really needed, but will REALLY help when you are
  181.    creating your help file. Using QH to test your file before you
  182.    implement HELPLIB in your app will really speed things up and
  183.    solve alot a problems that could arise later.
  184.  
  185.  
  186. I.4) The sample program - HELPSAMP
  187.  
  188. As mentioned earlier, the best way to see what HELPLIB can do is to
  189. play around with the sample application. After playing with it, take
  190. a look at the source. You'll see the guts of implementing HELPLIB are
  191. all in function HelpHook. This function is easily transported into
  192. any application to use as a model.
  193.  
  194.  
  195. ***To install the sample application copy the .EXE file anywhere you
  196. want. The file HELPLIB.DLL must be in a directory your LIBPATH is
  197. pointing to (usually \os2\dll) or in the same directory as
  198. HELPSAMP.EXE. Finally, the file HELPSAMP.HLP MUST be placed in the
  199. directory \os2\system. This is a limitation due only to the fact I
  200. hardcoded the file name into the sample program !!
  201.  
  202.  
  203. I.5) Distributing HELPLIB.DLL & MSHELP.DLL
  204.  
  205. When you finish implementing help in your application and are getting
  206. ready to distribute your app, remember to add HELPLIB.DLL and
  207. MSHELP.DLL in our distribution files!! Also any installation program
  208. you write ( or installation instructions you give) should put these
  209. files in the appropriate place.
  210.  
  211. I have no problem with you distributing HELPLIB.DLL with your app.
  212. MSHELP.DLL is another story though.
  213.  
  214. I have spoken to MANY people at Microsoft about the legalities of
  215. distributing one of their DLL's with an application. In short, the
  216. concensus seems to be as long as you are not writing an app like an
  217. OS/2 toolkit, or a QuickHelp replacement, (basically anything that
  218. would take business away from them selling SDKs, toolkits, QuickHelp
  219. etc) it is OK. I originally was going to include MSHELP.DLL in this
  220. archive, but as of this writing (7/6/89), no one has given me final
  221. absolute approval. PLEASE USE DISCRETION IN DISTRIBUTING MSHELP.DLL!!
  222. If you have any doubt about whether or not Microsoft would approve,
  223. either don't do it, or call Microsoft. BY NO MEANS distribute
  224. MSHELP.DLL with ANY other QuickHelp files (application or HELP). By
  225. itself, the DLL is pretty useless to a user, which is why I think
  226. they have given at least tacit approval.  It would also be REAL nice
  227. (read that MANDATORY) if somewhere in your program or documentation
  228. you gave Microsoft the credit they deserve for MSHELP.DLL. 'Nuff sed!!
  229.  
  230. (P.S. If ANYONE from Microsoft is reading this, PLEASE contact me and
  231. let me know if what I said above is OK!!)
  232.  
  233.  
  234. I.6) Acknowledgments
  235.  
  236. This is my place to say THANKS to lots of people who in some way or
  237. another have helped in creating HELPLIB:
  238.  
  239.         - Microsoft, for MSHELP.DLL, the Help boxes in OS/2 that
  240.           were used as a model for HELPLIB, and for OS/2 in general
  241.           ( It makes coding REAL FUN again !!).
  242.  
  243.         - Noel Bergman, (Compuserve SysOp-MSSYS) for his patience and
  244.           LOTS of suggestions and ideas.
  245.  
  246.         - Charles Petzold, for his book "Programming the OS/2
  247.           Presentation Manager" (a godsend), and miscellaneous
  248.           tips given on CompuServe.
  249.  
  250.         - WHOMEVER coded LQH (Little Quick Help) in v1.03 of the
  251.           OS/2 SDK. This was an invaluable source for accessing QH
  252.           files, and I openly confess to "borrowing" a couple routines!
  253.  
  254.  
  255.  
  256. II. USING HELPLIB.DLL
  257. ---------------------
  258.  
  259. II.1) The Help File
  260.  
  261. As mentioned earlier, the real key to implementing help in your
  262. applications is the work put in up front creating your help file. I
  263. tried to make the creation of the help file as similar to the
  264. creation of QuickHelp files as possible. Although at present
  265. HELPLIB.DLL does not support ALL dot commands, it does support the
  266. REAL important ones. Also, I only know of 1 minor incompatibility in
  267. using your files in QH, and it is optional anyway.  This section
  268. will discuss the creation and testing of the help file, and tips I
  269. found in avoiding problems. For an in depth discussion on the
  270. creation of help files, take a look at the manual "QuickHelp Users
  271. Guide" or the section on using HELPMAKE included with some compilers.
  272.  
  273.  
  274. II.1.a) Creating the Help File
  275.  
  276. I broke down the file creation explanation into the discussion of the
  277. various pieces of the help file. In this section we'll look at dot
  278. commands, addition of colors for emphasis, mandatory contexts, and
  279. the use of the helpmake utility. It would help if you had a printed
  280. copy of the file HELPSAMP.TXT, as I will use it as a reference often.
  281.  
  282.  
  283. II.1.a.1) Dot commands
  284.  
  285. Dot commands will control how help topics are displayed, how topics
  286. are cross referenced, whether of not the help text is a list, and
  287. most importantly, what the search string for a topic will be.
  288. HELPLIB.DLL supports a subset of the QuickHelp dot commands. I plan
  289. to implement the full set in some form or another at some time.
  290.  
  291. The format of the dot commands is the same as for QH. "All dot
  292. commands must be in lowercase letters and must be preceded by a dot
  293. (period). Each dot command is on its own line, and the dot must be
  294. the first character on the line."
  295.  
  296.  
  297. II.1.a.1.a) .context
  298.  
  299. The .context command is used to separate portions of the help
  300. text into topics. The format of the context command is:
  301.  
  302.         .context <topic-name>
  303.  
  304. where <topic-name> is the text that will reference the topic.
  305.  
  306. HELPLIB.DLL always searches for the entire <topic-name> and it is
  307. case sensitive, so topic names Print, print, Printing, and Printing
  308. in the background will all be considered different. All text between
  309. a .context command and the next .context is considered to be the text
  310. for the specified topic. 
  311.  
  312. Optionally, you can specify multiple .context commands before any
  313. help text. This is so you can reference the same help text using a
  314. variety of search strings. A good example of this in HELPSAMP is the
  315. keystroke help text. It has both the context KEYS and the context
  316. Keystroke Help.
  317.  
  318.  
  319. TIP:
  320. Put all your .context commands one after another at the top of any
  321. help topic, before any other dot commands. This makes your file easier
  322. to read, and easier to add text to any topic.
  323.  
  324.  
  325. II.1.a.1.b) .topic
  326.  
  327. The .topic command controls the text that will be displayed at the
  328. top of a help screen ( below the title bar & above the help text !).
  329. In QuickHelp, this is the text that appears in the little box at the
  330. bottom of the screen. 
  331.  
  332. Format of the .topic command is
  333.  
  334.         .topic <topic text>
  335.  
  336. <topic text> is always displayed at the top of the window, centered.
  337.  
  338. HELPLIB.DLL will append the word "Help" after the string specified by
  339. .topic, so don't make the last word Help!! It won't append Help
  340. though for .contexts that are to be treated as lists (.list).
  341.  
  342. TIP:
  343. The .topic command is not mandatory, but HIGHLY recommended. If you
  344. have multiple .context commands pointing to the same help text, the
  345. .topic commands ensure the title above the text is the same.
  346.  
  347.  
  348. II.1.a.1.c) .category
  349.  
  350. The .category command is used to reference help topics back to some
  351. other help context.  Format of the .category command is:
  352.  
  353.         .category <string>
  354.  
  355. where <string> should EXACTLY match a .context topic-name somewhere
  356. in the file.
  357.  
  358. QuickHelp utilizes the .category command by allowing the user to
  359. press the T key to search for the category of any context.
  360. HELPLIB.DLL uses the .category in a similar manner. If a .category
  361. command is associated with a context, a pushbutton in the second
  362. position will appear, labelled "F1=Help". Pressing F1 at this point
  363. will force HELPLIB.DLL to search for  <string> as a context. If it is
  364. found, it is displayed as any other topic. If it is not found, the
  365. default context is displayed. ANY context displayed without an associated
  366. .category command will not offer the user the F1 help button.
  367.  
  368. A good example of the .category command can be followed by starting
  369. at the .context "Message Box 2". This is the help displayed when F1
  370. is pressed when Message box 2 is displayed. Pressing F1 from this
  371. help will display the help text for "Help in Message Boxes". Help in
  372. message boxes in turn has a .category of "Help in Boxes" and "Help In
  373. Boxes" then chains to the context "About HELPSAMP".
  374.  
  375. TIP:
  376. .category commands are not mandatory, but again are HIGHLY
  377. recommended. I usually refer all topics somewhere. If there is no
  378. logical "higher" help context, I usually chain to the default
  379. context. I only make the default topic and list contexts the only
  380. topics without .category commands.
  381.  
  382. PLEASE ONLY 1 .category per topic!!!
  383.  
  384.  
  385. II.1.a.1.d) .list
  386.  
  387. The .list command is used to specify that the topic text that follows
  388. should be displayed in a list box. There are no parameters to the
  389. .list command. The .list command MUST precede any help text in the
  390. topic.
  391.  
  392. You will always have at least 2 .list contexts in your file. (more on
  393. this in the mandatory .contexts section). You can chain list boxes
  394. (.category commands), but this is really not necessary.
  395.  
  396. The list box acts like most PM list boxes. It has a scroll bar to
  397. scroll your list entries, double clicking an entry will force a
  398. search on the text of the entry, any character key will take you to
  399. the first entry starting with that letter, and it has a full keyboard
  400. interface (arrow keys, page up/down, home/end).
  401.  
  402. HELPLIB.DLL does NOT sort the entries in the list. They are put in
  403. the list box in the same order you have them in the file. This is so
  404. you can do things like indenting:
  405.  
  406.         About Help
  407.         Menu Help
  408.            File Menu
  409.            Main Menu
  410.            Sub Menu
  411.         Save Help
  412.  
  413. TIP:
  414.  
  415. Keep your .contexts short, as these are going to be the entries in
  416. your INDEX. The default window width is about 50 characters wide.
  417.  
  418.  
  419. II.1.a.2) Colors
  420.  
  421. Colors help add emphasis to your help text. They are useful to 
  422. distinguish subtopic headers from the text. HELPLIB.DLL allows you to
  423. add color to your text through the use of \ commands. These are the
  424. same \ commands used by QuickHelp.
  425.  
  426. Normal help text is displayed in dark blue. Bold text will display in
  427. cyan, italics text in red and underline text in magenta. You can also
  428. combine the bold and italics attributes to get brown.
  429.  
  430. The slash commands are as follows:
  431. \b - bold
  432. \i - italics
  433. \u - underline
  434. \b\u - bold and underline
  435.  
  436. The \p command turns off all attributes. See the .context "Colors in
  437. Help" in HELPSAMP.TXT for an example of how to use the \ commands, and
  438. to see what the colors look like.
  439.  
  440. Don't use any other combination of the \ attributes or you will end
  441. up with text that is invisible!
  442.  
  443.  
  444.  
  445. II.1.a.3) Mandatory .contexts
  446.  
  447. Although HELPLIB.DLL is fairly flexible in what it will allow you in
  448. our help file, there are a few things it MUST have in order to work
  449. properly. Some of the mandatory .contexts help in assuring
  450. compatibility with QuickHelp, others are for my convenience only.
  451.  
  452. PLEASE make sure you read this section carefully. Most problems I
  453. have seen in implementing HELPLIB.DLL have been because one of the
  454. mandatory .contexts was missing or misspelled. Remember, .context
  455. commands ARE case sensitive, and they MUST appear exactly as
  456. specified here. WEIRD things can occur if one of the .context
  457. commands is missing
  458.  
  459. II.1.a.3.a) .context h.default
  460.  
  461. This context is the topic that will be displayed when a search is
  462. made for a topic and it is not found. It is also the text that will
  463. be displayed when QuickHelp first opens your file. I also make this
  464. the topic that is displayed when F1 is pressed from my application
  465. and no specific help is available. Finally, it is the topic that I
  466. eventually chain all other help topics to.
  467.  
  468. Usually the h.default context is just one of the .contexts associated
  469. with some help text. For example, I also cross reference h.default to
  470. About HELPSAMP in the sample program.
  471.  
  472. The text should probably be general help about your application or
  473. help on how to use help.
  474.  
  475. I have also made my INDEX the default if I always wanted users always
  476. to go back to the help index. Its up to you!
  477.  
  478.  
  479. II.1.a.3.b) .context HELPINDEX
  480.  
  481. The HELPINDEX context is a context of .list type. It contains the
  482. entries of the INDEX OF CONTENTS list, all of the topics you want to
  483. allow your users to reference directly. It will be displayed when F11
  484. is pressed.
  485.  
  486. I usually also reference this context by whatever I have in the List
  487. Categories context (see below). For example, HELPINDEX is also
  488. referenced by HELPSAMP Help in the HELPSAMP application.
  489.  
  490. Remember, list categories do not sort the entries as they insert them
  491. into the list box. Be sure to list them in the order you want them to
  492. appear in the list.
  493.  
  494. Also remember, the entries in the list are used to search the
  495. database for topics of help. This means the entries in HELPINDEX must
  496. match a .context entry in your help file exactly, or you will get the
  497. default help. For example, in the sample application, I have put an
  498. in entry called "Chaining Help" that I never defined. When this entry
  499. is chosen, the default help (h.default of About HELPSAMP) is
  500. displayed. Alot of the problems you may experience are because your
  501. list entries don't match .contexts exactly.
  502.  
  503. II.1.a 3.c) .context KEYS 
  504.  
  505. This is the text displayed for keystroke help. The button F9=Keys
  506. always searches for this context.
  507.  
  508. The text in the sample application is the same as the keys text for
  509. Start Text and the Task Manager. You can use it or make up
  510. application specific keystroke yourself.
  511.  
  512. In the sample application, I have also reference this topic by the
  513. context Keystroke Help. This isn't really necessary but it does show
  514. you a good example of multiple .context's for any topic.
  515.  
  516. II.1.a.3.d) .context List Categories
  517.  
  518. This context is for compatibility with QuickHelp (kind of). This
  519. context under QuickHelp list the names that will display under the
  520. Categories pull down menu for your application. Unlike QuickHelp,
  521. which allows you many items in this list, HELPLIB.DLL only uses the
  522. first entry. Whatever you put in the first entry is what will appear
  523. in the title bar of your help window.
  524.  
  525. I also reference my HELPINDEX context with whatever I put in the
  526. first list entry. This is so when you choose your application help
  527. from the categories menu under QuickHelp, the index of help topics
  528. will appear.
  529.  
  530.  
  531. II.1.a.4) Tips on Creating the Help file
  532.  
  533. Here are some various things I have found about creating help files.
  534. Some of them are useful, some are common sense, and some point out
  535. limitations.
  536.  
  537. 1) The length of any help topic is limited to 64K, same as in
  538. QuickHelp. Remember, we are writing Help screens, not your users
  539. manual. Try to keep your topics of reasonable length. The length of
  540. the enclosed KEYS context is probably as long as you really want to
  541. get.
  542.  
  543. 2) Keep the number of color changes within any specific topic to a
  544. minimum. The way I parse color attributes limits to about 400 color
  545. changes per topic. Remember that changing from normal to bold and back
  546. will use up 3 of the 400. Use color for emphasis, not carnival
  547. effects!
  548.  
  549. 3) Forcing Adjoining Lines
  550. Since HELPLIB.DLL wordwraps all help text, it is hard to force
  551. sub-headers within your text. QuickHelp on the other hand displays
  552. your text exactly as you type it in. This is the one incompatibility
  553. between QH an HELPLIB I mentioned earlier.
  554.  
  555. Sometimes you may want to force two short lines of text one right
  556. after the other:
  557.  
  558. File
  559. Here is text about the file menu
  560.  
  561. I originally had to put a spare blank line in between them in the
  562. text file, but then they appeared as below:
  563.  
  564. File
  565.  
  566. Here is text about the file menu
  567.  
  568.  
  569. I wanted to get rid of the blank line. The way to do this is to put a
  570. \ after a few spaces on the first line. THis will force a spare line
  571. feed to appear in you compressed file. Unfortunately, it doesn't look
  572. real pretty in QuickHelp as they ignore this spare line-feed. One
  573. other problem that appears is the helpmake utility counts the
  574. character as just another character and keeps incrementing the
  575. character count for the line with the next line. The helpmake
  576. utility will holler your line is too long and truncate it. The way
  577. to get around this is to make the second line fairly short and
  578. continue it on the next line. Since HELPLIB.DLL keeps reading until
  579. it finds a blank line, it will word wrap the third line with the
  580. second line. For a good example of how to implement this feature can
  581. be seen in the HELPSAMP.TXT file under the File (pull down) context
  582. and the KEYS context.
  583.  
  584. 4) I found it useful to add an End of file context at the very end of
  585. the file. Sometimes helpmake wouldn't correctly mark end of file, and
  586. I had problems retrieving the last real topic. To solve this I added
  587. the .context EOF after the text for the last topic.
  588.  
  589.  
  590. II.1.a.5) Using helpmake
  591.  
  592. After completing your help file, you must index it and compress it
  593. using the helpmake utility.  I am not going to go into detail about
  594. using the helpmake utility.  The Microsoft documentation is real good
  595. about this. In this section I will discuss the parameters to use when
  596. creating files for use by HELPLIB.DLL.
  597.  
  598.  
  599. The parameters you use will be different depending on the version of
  600. helpmake you are using. The newer version of helpmake support a /t
  601. (terse) parameter that translate your . command to a shorter internal
  602. version. This version was supplied with the 1.1 sdk and the toolkit.
  603. Older version do not support this terse form. HELPLIB.DLL should
  604. support both version of helpmake.
  605.  
  606. Newer versions should invoke helpmake as follows:
  607.  
  608. helpmake /a: /e15 /v9 /t /o<outfile.hlp> <infile.txt>
  609.  
  610.  
  611. Older versions should omit the /t and change the /a: parameter with
  612. /a. 
  613.  
  614. helpmake /a. /e15 /v9 /o<outfile.hlp> <infile.txt>
  615.  
  616. See your helpmake documentation for a complete description of what
  617. all the helpmake parameters are.
  618.  
  619.  
  620.  
  621. II.1.b) Testing your help file
  622.  
  623. The best way to test your help file is to use Quickhelp. If you don't
  624. have QuickHelp, you will have to wait to test your file until you
  625. have modified your application. After compressing your file, you
  626. might want to copy the .HLP file to wherever your QH variable is
  627. pointing to. This way when you start QH, it will automatically open
  628. your file, and you won't have to open it ( providing you have the
  629. latest version of QH).
  630.  
  631. Here is a quick list of things to look for when you test your file
  632. under QH.
  633.  
  634. 1) Open the file.
  635. As mentioned earlier, if you are using the latest version of QH and
  636. the .HLP file is in your help path, QH will open it automatically for
  637. you. If it is not in the path, or you are using an older version of
  638. QH, you will have to open it yourself. Be sure to pass it the entire
  639. drive/path/filename/extension specification. Older versions had
  640. problems unless you do.
  641.  
  642. 2) Check the categories drop down.
  643. You will know your file is open and QH knows it is there by checking
  644. the categories drop down. Whatever you put in the List Categories
  645. context should appear as a new category on the pull down. If it is
  646. not there, try to reopen the file again. If it still doesn't appear,
  647. make sure you have the .context List Categories in your file.
  648.  
  649. 3) Test each item in your help index.
  650. Choose each item in your help index and make sure it retrieves the
  651. correct text. If they don't, CHECK YOUR SPELLING!! Also make sure you
  652. actually have the .context commands that match your entries in the
  653. file.
  654.  
  655. WARNING!!!  Older versions of QH only look at the first word in a
  656. list entry string when it goes to search for another context. If you
  657. keep getting contexts not found or the wrong text, add new .contexts
  658. to your file that are only 1 word long. You can remove them later.
  659.  
  660. 4) Test your help chaining
  661. Test the chaining of your help by pressing 'T' when a topic is
  662. displayed. You should chain to the .categories specified in each
  663. .context. 
  664.  
  665. WARNING!! Once again, older versions of QH only look at the first
  666. word when chaining help. Be sure to check your .context's and your
  667. .category's if you change them.
  668.  
  669.  
  670. II.2) Adding Help to your Application
  671.  
  672. Now to the fun part! If you have taken the time to create your help
  673. file and have tested it thoroughly, you're in the home stretch. If
  674. you didn't, shame on you! Do not pass go, do not collect 200 dollars.
  675.  
  676. Alot of what I will touch on in this section is pretty repetitive
  677. stuff if you have read the sections on Help in the OS/2 Programmers
  678. reference manuals. Refer to these manuals for any questions you may
  679. have. I will also refer to HELPSAMP.C, .RC, and .H frequently, so
  680. have a copy handy.
  681.  
  682. Most of the code you will put in your program you can borrow from the
  683. sample application and tailor to your needs. This should help cut
  684. down development time.
  685.  
  686.  
  687. II.2.A) WM_HELP Messages
  688.  
  689. All requests for help in your PM app in some way or another will end
  690. up generating a WM_HELP message. Unfortunately, not all help messages
  691. will come to your client window procedure (like those generated by
  692. menu help). There are ways around this, though. 
  693.  
  694. WM_HELP messages are generated in many ways. Menu items with style
  695. MIS_HELP, pushbuttons of  BS_HELP, and message boxes of style MB_HELP
  696. will all generate WM_HELP message. The parameters of the help message
  697. will help you determine the source of the message.
  698.  
  699. How you deal with these help messages is up to you. The rest of this
  700. document will show you one way, through the installation of a help
  701. hook.  By installing a hook for all help messages, processing of help
  702. in centralized in one place.
  703.  
  704.  
  705.  
  706. II.2.B) HelpBox Function call
  707.  
  708. Through the use of HELPLIB.DLL, your program can create a help window
  709. with just one function call. The function is HelpBox and its
  710. prototype is as follows:
  711.  
  712. BOOL APIENTRY HelpBox(HWND hwndCallerFrame,
  713.                       HWND hwndActive,
  714.                       HAB  hAB,
  715.                       PSZ  pszHelpFile, 
  716.                       PSZ  pszSearch);
  717.  
  718. Be sure to include this as a forward declaration in your program.
  719. HELPSAMP has it in it .h file
  720.  
  721. The parameters to HelpBox are as follows:
  722.  
  723. hwndCallerFrame: 
  724.  
  725. This is the handle to your frame window. It is returned to in your
  726. WinCreateStdWindow call. Please be sure you pass the correct handle,
  727. as HELPLIB uses this to create a child window of this window. VERY
  728. strange things WILL happen if you pass the wrong handle. For example,
  729. the window may open the first time, but never again.
  730.  
  731.  
  732. hwndActive:
  733.  
  734. This is the handle to the window that is active at the time help is
  735. requested. Most of the time, this will actually be the handle to a
  736. pushbutton window or the menu. HELPSAMP.C calls WinQueryActiveWindow
  737. to retrieve this parameter while calling HelpBox. This parameter is
  738. passed so HELPLIB.DLL knows who to return the focus to.
  739.  
  740.  
  741. hAB:
  742.  
  743. This is the anchor block handle of your program. You got this from
  744. your WinInitialize call somewhere in the beginning of your program.
  745.  
  746.  
  747. pszHelpFile:
  748.  
  749. This is a pointer to a string which contains the name of your help
  750. file.
  751.  
  752. This name MUST include full drive, path, filename and extension
  753. information. How you get this name is up to you. I hardcoded it in
  754. the HELPSAMP program. That probably is NOT how you want to do it. A
  755. much cleaner way would be to retrieve it from the OS2.ini file.
  756. During your program installation, remember to have the user put it in
  757. the directory you want, or if you write an installation program just
  758. go and update the .ini file yourself.
  759.  
  760. If HELPLIB.DLL cannot find your help file, a message box will be
  761. displayed, and you will get a FALSE return code.
  762.  
  763. At this point in time, I only check the file name the first time you
  764. call HelpBox. What this means is you can't change help files on the
  765. fly. I plan to change this in the near future.
  766.  
  767.  
  768. pszSearch:
  769.  
  770. This is the context you want to display help on. The string passed
  771. MUST match a .context in your help file. If it does not, the
  772. h.default context topic will be displayed instead.
  773.  
  774. HELPSAMP.C shows one way to insure the strings passed will match your
  775. contexts. I used strings in my RC file, created from my HELPINDEX,
  776. and load the appropriate string once I have determined what I want
  777. help on. More on this later.
  778.  
  779.  
  780. When you link your program, be sure to link it with HELPLIB.LIB
  781. (which you have already copied to your \lib  directory, right?) to
  782. resolve the external reference to HelpBox.
  783.  
  784.  
  785. II.2.C) The Help Hook
  786.  
  787. As mentioned earlier, the installation of a help hook in your program
  788. will ease the installation of help in your program considerably. In
  789. short, if you ignore ALL WM_HELP messages in your app by passing them
  790. on to the default window procedure, the will end up going to your
  791. help hook procedure. In this way, you can deal with all help requests
  792. in one central location. I have found only 1 place where I have to
  793. intercept the WM_HELP message to get correct context sensitive help.
  794. This is in a dialog box, and only if they access help through the F1
  795. key. I'll describe this situation when I deal with context sensitive
  796. help later on.
  797.  
  798. To use a help hook you must do three things:
  799.         1) install the help hook
  800.         2) call the help hook (this is done  for you!)
  801.         3) remove the help hook before terminating
  802.  
  803. II.2.C.a) Installing the Help hook
  804.  
  805. I usually install the help hook right before I enter my main message
  806. processing loop. You use the function WinSetHook to install the hook.
  807. The HELSAMP program does this in main with the following code:
  808.  
  809.         .
  810.         .
  811.  
  812.         WinSetHook(hab, hmq, HK_HELP, (PFN)HelpHook, NULL);
  813.         .
  814.         .
  815. where HK_HELP is the type of hook to set, and HelpHook is the name of
  816. the function that will act as the hook.
  817.  
  818.  
  819. II.2.C.b) Calls to the Help Hook
  820. Calls to the help hook when help is requested is automatic. DON'T
  821. call this function (HelpHook) yourself!! All you need to do is not
  822. process WM_HELP messages in your application. Pass them on the 
  823. default window procedure, and OS/2 will call the help hook for you.
  824.  
  825. Be sure to include a forward declaration to the help hook function in
  826. your header file. 
  827.  
  828. II.2.C.c) Removing the Help Hook
  829.  
  830. Before you terminate your application, be sure to remove the help
  831. hook you installed. You do this with the WinReleaseHook function.
  832. HELPSAMP does this in main after the message processing loop is
  833. terminated:
  834.  
  835.         .
  836.         .
  837.         WinReleaseHook(hab, hmq, HK_HELP, (PFN)HelpHook, NULL);
  838.         .
  839.         .
  840.  
  841.  
  842. II.2.C.d) The HelpHook Procedure in detail
  843.  
  844. This section will dissect HELPSAMP's help hook procedure, HelpHook,
  845. (catchy name, huh!) in detail. I would help to familiarize yourself
  846. with hooks, by reading the HOOKS section and HELP section in the OS/2
  847. Programmers reference manuals.
  848.  
  849.  
  850. HelpHook is really nothing more than a giant multi-tiered case
  851. statement. The parameters to HelpHook end up telling you where help
  852. was requested from. We will use these parameters to retrieve the
  853. proper search context string, to provide context sensitive HElp.
  854. Finally, HelpHook call HELPLIB.DLL's function HelpBox (described
  855. earlier) to open up the help window.
  856.  
  857. HELPSAMPs HelpHook function only has two local variables,
  858. pszHelpTopic, and usStringNum. pszHelpTopic will end up being the
  859. search string passed to HelpBox as the topic for the requested help.
  860. usStringNum is the number of the string in the programs resource
  861. file. I always prime this to DEFAULT_HELP (0) so I will always load
  862. some kind of string.
  863.  
  864. The first level of the case statement is based on the parameter
  865. usMode. usMode tells us the origin of the help message. It has one
  866. three possible values, HLPM_MENU, HLPM_FRAME, and HLPM_WINDOW. See
  867. your OS/2 Programmers reference or QuickHelp for a detailed description
  868. of what these values mean. In short, HLPM_MENU means the message
  869. originated from a menu, HLPM_FRAME and HLPM_WINDOW means the message
  870. originated in a window.
  871.  
  872. The next level of the case statement is based on the parameter of
  873. idTopic. What idTopic contains depends on the value of usMode. It
  874. will usually contain the identifier of the submenu or of the frame
  875. window when help was called.
  876.  
  877. The last level of the case statement is based on the parameter
  878. idSubTopic. Once again, what idSubTopic contains depends on the value
  879. of usMode. It usually resolves to the selected menu item or the
  880. window that has focus when help is requested.
  881.  
  882. Using these parameters we can identify exactly what state the user
  883. was in when they requested help. Since I give all the help strings in the
  884. resource file the same identifier as the menu item/
  885. pushbutton/message box that they represent, I assign usStringNum the
  886. value of either idTopic or idSubTopic ( more on this in the next
  887. section). 
  888.  
  889. Once I know what string number I want to load,  I load the string
  890. using WinLoadString into pszHelpTopic. Finally, I call HelpBox with
  891. the appropriate parameters.
  892.  
  893. To obtain the active window handle when help was called, the second
  894. parameter of HelpBox is actually a call to WinQueryActiveWindow. This
  895. is so HELPLIB.DLL knows who to restore the focus to when the user
  896. dismisses the help box.
  897.  
  898. Clear as mud, right! Look over this section again, and look through
  899. the HelpHook code. The next section deals with how we made the help
  900. context sensitive.
  901.  
  902.  
  903.  
  904. II.2.D) Making the help context sensitive
  905.  
  906. The help hooks giant case statement is what really made the help
  907. context sensitive. By loading the correct value in usStringNum, we
  908. loaded the appropriate search string that was passed on to HelpBox.
  909. But what do the values of usStringNum really point to?  They all
  910. point to strings in the resource file.
  911.  
  912. II.2.D.1) STRINGTABLE in the RC file
  913.  
  914. Towards the end of the RC file you will find the stringtable defined
  915. for HELPSAMP. The identifiers of the strings in the table are the
  916. same exact identifiers used in defining the resources themselves. For
  917. example, every menu item defined in the main menu has a corresponding
  918. string identified by the menu id. Every help button in every dialog
  919. box has a string, and every message box with a help button has a
  920. string. Additionally, the DEFAULT_HELP identifier is associated with a
  921. string.
  922.  
  923. The strings associated with these identifiers are the .contexts you
  924. created in your help file. EVERY help topic in your file should have
  925. some sort of reference in your stringtable. Most of the entries in
  926. your string table will be the entries in your index. Notice however
  927. you can have search strings for topics NOT in your INDEX. For
  928. example, the entries MSGBOX_ID1 and MSGBOX_ID2 are not in your index.
  929. The ONLY way the user will ever see the text for the .context Message
  930. Box 1 or 2 is to press the Help button while the message box is open.
  931.  
  932. Also notice many identifiers can point to the same topic. For
  933. example, IDM_MESSAGE_1 and IDM_MESSAGE_2 both will display the same
  934. help text, "Help in Message boxes". This make sense though.
  935. IDM_MESSAGE_1 and IDM_MESSAGE_2 are menu items that open message
  936. boxes. If a user highlights one of the menu options, then presses F1,
  937. help text for "help in message boxes" appear!
  938.  
  939. Be sure to include the identifier DEFAULT_HELP with the .context for
  940. your default help somewhere in your stringtable. Remember the
  941. HelpHook primes the sting number variable to default help.
  942.  
  943. One thing to be real careful of. By using your resource identifiers
  944. as the identifiers of string table entries, you MUST be careful every
  945. single resource identifier you create has a unique ID. Sometimes I
  946. will create a menu identifier with an id of 100 and a dialog box with
  947. the identifier 100. This normally works just fine as the identifiers
  948. won't conflict with each other. However, in this case we would try to
  949. load the string with identifier 100 in both cases if help was
  950. requested. This is probably not what you want.
  951.  
  952.  
  953. II.2.D.2) The F1 key
  954.  
  955. The F1 key will, by default, generate a WM_HELP message if you use
  956. the system default keyboard accelerator. PLEASE don't remap this key
  957. to anything else!!
  958.  
  959. You can add the F1=Help menu option to your main menu by adding the
  960. line
  961.  
  962.      MENUITEM "F1=Help", 0x00, MIS_TEXT|MIS_BUTTONSEPARATOR|MIS_HELP
  963.  
  964. to your menu resource in the RC file. Notice the menu item style
  965. MIS_HELP. This tells the system to generate a WM_HELP message when
  966. this menu item is selected. No other menu items in HELPSAMP have this
  967. menu style!!
  968.  
  969. II.2.D.3) Help for Menu Items
  970.  
  971. Menu items are probably the easiest things to get help on. When a
  972. user highlights a menu item (not selects, merely highlights) and
  973. presses the F1 key, a WM_HELP message is generated. Your window
  974. procedure will not get this message. You MUST have a help hook
  975. installed if you want to give help on menu items.
  976.  
  977. The usMode of a help message generated when a menu item is
  978. highlighted will be HLPM_MENU. The second parameter, idTopic, will be
  979. the menu identifier of the submenu containing the selected item.
  980. Finally the third parameter will be the selected menu item id, unless
  981. the submenu itself is selected, in which case it will be -1.
  982.  
  983. Following a quick example using HELPSAMP:
  984.          .
  985.          .
  986.      switch(usMode)
  987.      {
  988.          case HLPM_MENU:
  989.              switch(idTopic)
  990.              {
  991.                  /* List all your High Level menu items here */
  992.                  case IDM_FILE:
  993.                  case IDM_BOXES:
  994.                      switch(idSubTopic)                     
  995.                      {
  996.                          case 0xFFFF:        /* menu bar itself highlighted */
  997.                              usStringNum = idTopic;
  998.                              break;
  999.  
  1000.                          default:
  1001.                              usStringNum = idSubTopic;
  1002.                      }        
  1003.                      break;                    
  1004.  
  1005.                  default:
  1006.                      usStringNum = DEFAULT_HELP;
  1007.                      break;
  1008.              }
  1009.              break;
  1010.  
  1011.  
  1012.          case HLPM_WINDOW:
  1013.              switch(idTopic)
  1014.              {
  1015.          .
  1016.          .
  1017.  
  1018.  
  1019. Say the user highlights the Open menu option under the File submenu,
  1020. then presses F1. HelpHook will be called with usMode = HLPM_MENU.
  1021.  
  1022. The next switch statement will have idTopic equal to IDM_FILE. Since
  1023. it is one of the menu options we will give help on, we fall into the
  1024. next switch statement, checking the subtopic. idSubTopic will contain
  1025. the id IDM_OPEN, so we now know the user want help on the open
  1026. subtopic. Since in HELPSAMP we give help on ALL available submenus,
  1027. we fall into the default case, assigning usStringNum to IDM_OPEN.
  1028.  
  1029. Falling all the way out of the case, we reach the WinLoadString
  1030. function call which will load the string "Open" into pszHelpTopic.
  1031. This is exactly what we want!! Finally HelpBox is called, directing
  1032. it to display help on the .context "Open".
  1033.  
  1034. If the example was just a little different, say they highlighted the
  1035. File submenu instead of an option beneath File, the idSubTopic would
  1036. have been -1. In this case, we know the user wanted help on the File
  1037. menu itself, and usStringNum would be assigned idTopic or IDM_FILE.
  1038. We then would have loaded string IDM_FILE, "File (pull down)", and
  1039. called HelpBox with a different context.
  1040.  
  1041. HELPSAMP is pretty clean in the way it deals with help for menu
  1042. items.  It is clean ONLY because I have identified help for every
  1043. menu option, and just default the subtopic to the chosen menu option
  1044. if the submenu itself is not chosen. You do not have to do this. You 
  1045. can choose to list every single menu option separately, with every
  1046. option of a submenu beneath it. It makes your case statement VERY
  1047. large and tends to be confusing. An example of this can be found in
  1048. the OS/2 Programmers Reference, Vol 1. in the chapter on Help.
  1049.  
  1050.  
  1051. II.2.D.3) Help for Dialog Boxes
  1052.  
  1053. Help for dialog boxes is much the same as help for menu items,
  1054. although there are a few little tricks involved.
  1055.  
  1056. When a user presses a button in a dialog box that has the style
  1057. BS_HELP, a WM_HELP message is generated and is sent to the dialog
  1058. window procedure. Normally you will just pass this message on to the
  1059. WinDefDlgProc as is. There is one small exception to this I will
  1060. discuss in a minute.
  1061.  
  1062. The usMode of the help message generated will usually be HLPM_WINDOW.
  1063. I say usually because the pushbutton in your dialog box USUALLY is a
  1064. child of the dialog box, and your dialog box is NOT the client window
  1065. of the frame window. This is true most of the time unless your client
  1066. window IS the dialog box itself.
  1067.  
  1068. Assuming you do get a help message with usMode HLPM_WINDOW, let's
  1069. trace a simple example from HELPSAMP:
  1070.          .
  1071.          .
  1072.          case HLPM_WINDOW:
  1073.              switch(idTopic)
  1074.              {
  1075.                  /* List identifiers of dialog boxes with help buttons */
  1076.                  case IDD_ABOUT:
  1077.                      switch(idSubTopic)
  1078.                      {
  1079.                         /* list all identifiers for those help buttons here*/
  1080.                          case IDD_ABOUT_HELP:
  1081.                              usStringNum = idSubTopic;
  1082.                              break;
  1083.  
  1084.                          default:
  1085.                              usStringNum = DEFAULT_HELP;
  1086.                      }
  1087.                      break;
  1088.  
  1089.                  /* List all Message Boxes IDs with help Buttons */
  1090.                  case MSGBOX_ID1:
  1091.                  case MSGBOX_ID2:
  1092.  
  1093.          .
  1094.          .
  1095.  
  1096. Say the user has opened the About dialog box, IDD_ABOUT, and presses
  1097. the pushbutton, IDD_ABOUT_HELP, requesting help. HelpHook will be
  1098. called with usMode = HLPM_WINDOW.
  1099.  
  1100. The next switch statement will have idTopic equal to IDD_DIALOG, the
  1101. dialog box itself. Since it is one of the dialog boxes we want to
  1102. give help on, we fall into the next switch statement, checking the
  1103. sub-topic. idSubTopic will contain the value of the pushbutton
  1104. generating the help message, IDD_ABOUT_HELP. This informs us the user
  1105. wants help on the About Box dialog. Since this is one of the
  1106. available help topics (case IDD_ABOUT_HELP), we assign usStringNum
  1107. the id of the pushbutton itself, IDD_ABOUT_HELP.
  1108.  
  1109. Falling all the way out of the case statement, we reach the
  1110. WinLoadString function which will load string IDD_ABOUT_HELP into
  1111. pszHelpTopic. The string associated with id IDD_ABOUT_HELP is "About
  1112. Box". Finally HelpBox is called with this context, resulting in help
  1113. on the About dialog box. Simple!
  1114.  
  1115. Here now is the one little caveat I alluded to earlier. Notice I kept
  1116. mentioning "If the user presses the pushbutton". PRESS is the
  1117. operative word. When a help message is generated, it passes the
  1118. window handle of the window that had the focus when the message is
  1119. generated. In the case of using a mouse, focus will always be on the
  1120. button that was pushed. However, if the user presses the F1
  1121. accelerator key, a WM_HELP message will be generated with a
  1122. idSubTopic of whatever window had the focus. This could be an OK
  1123. button, a list box, or any other control in your dialog box! You can
  1124. resolve this MANY, MANY ways. You can create a local accelerator
  1125. table for your dialog box, you can trap all keyboard input, etc. The
  1126. easiest way I have found is to trap the WM_HELP message that is
  1127. generated, massage its parameters, THEN pass it on to WInDefDlgProc.
  1128. Here is the code bit from HELPSAMPs AboutDlgProc that does the dirty
  1129. work:
  1130.  
  1131.          .
  1132.          .
  1133.          case WM_HELP:    /* process HELP msg only if F1 was pressed */
  1134.             if(SHORT1FROMMP(mp2) == CMDSRC_ACCELERATOR)  /* means F1 was pressed */
  1135.              {
  1136.                  /* Force focus to HELP button */
  1137.                  WinSetFocus(HWND_DESKTOP, WinWindowFromID(hwnd, IDD_ABOUT_HELP));
  1138.  
  1139.                  /* pass on the message modified for button */
  1140.                  return(WinDefDlgProc(hwnd,
  1141.                               WM_HELP,
  1142.                               MPFROMSHORT((SHORT)IDD_ABOUT_HELP),
  1143.                               MPFROM2SHORT((SHORT)CMDSRC_PUSHBUTTON, FALSE)));
  1144.              }
  1145.              break;
  1146.  
  1147. The lowword of mp2 of a WM_HELP message tells you the source of the
  1148. help message. If the value is CMDSRC_ACCELERATOR, this message was
  1149. posted because the user pressed an accelerator key. These are the
  1150. ONLY WM_HELP messages we will process. Otherwise we pass them right
  1151. on.
  1152.  
  1153. Next we reset the focus to the help button itself. Then we pass
  1154. the message on to WinDefDlgProc, after altering mp1 and mp2 to
  1155. make HelpHook think the message was created by the pushbutton and NOT
  1156. the accelerator.
  1157.  
  1158. In reality, there is probably an easier way to do this. I haven't
  1159. taken the time though as this seems to work just fine. If you find a
  1160. cleaner way, let me know!
  1161.  
  1162.  
  1163. II.2.D.3) Help for Message Boxes
  1164.  
  1165. Message boxes follow the same basic pattern as help for dialog boxes.
  1166. When you create a message box with MB_HELP style, PM kindly puts a
  1167. help button in the box for you. Your window procedure never gets the
  1168. resulting WM_HELP message though, if the user presses the button! You
  1169. MUST install a help hook if you want to give help for message boxes.
  1170. The only real good reason I see for help in message boxes is things
  1171. like error messages. Say you determine an error has occurred and you
  1172. flash up a message box. You might want to give the user more help as
  1173. to what the error means and how to resolve it.
  1174.  
  1175. Another important thing to remember about help for messages boxes:
  1176. EVERY message box you create must have a UNIQUE identifier if you
  1177. want to display different help messages. The identifier of the
  1178. message box is the 5th parameter to the WinMessageBox call. In
  1179. HELPSAMP I defined two constants, MSGBOX_ID1 and MSGBOX_ID2, that get
  1180. passed to WinMessageBox.
  1181.  
  1182. Here is one of the calls from HELPSAMP:
  1183.  
  1184.          case IDM_MESSAGE_2:
  1185.              WinMessageBox(HWND_DESKTOP, hwnd,
  1186.                  (PSZ)"Press F1 for help on Message Box 2",
  1187.                  (PSZ)"Message Box 2", (USHORT)MSGBOX_ID2,
  1188.                   MB_OK|MB_HELP);
  1189.              return 0;
  1190.  
  1191. Notice the message box identifier (MSGBOX_ID2) and the message box
  1192. style includes MB_HELP.
  1193.  
  1194. Lets follow this example further. Say the user opens the message box
  1195. and presses the HELP button. Here is the code from HelpHook:
  1196.  
  1197.          .
  1198.          .
  1199.          case HLPM_WINDOW:
  1200.              switch(idTopic)
  1201.              {
  1202.                  /* List identifiers of dialog boxes with help buttons */
  1203.                  case IDD_ABOUT:
  1204.                      switch(idSubTopic)
  1205.                      {   .
  1206.                          .
  1207.                          .
  1208.  
  1209.                  /* List all Message Boxes IDs with help Buttons */
  1210.                  case MSGBOX_ID1:
  1211.                  case MSGBOX_ID2:
  1212.                      usStringNum = idTopic;
  1213.                      break;
  1214.  
  1215.                  default:
  1216.                      usStringNum = DEFAULT_HELP;
  1217.              }
  1218.          .
  1219.          .
  1220.  
  1221. HelpHook will be called with usMode = HLPM_WINDOW. The next switch
  1222. statement will have idTopic equal to the message box identifier. NOTE
  1223. there is no subtopic!! Since idTopic contains the identifier we want,
  1224. MSGBOX_ID2, we assign usStringNum to idTopic.
  1225.  
  1226. Falling out of the case brings us to the WinLoadString call. It will
  1227. load the string identified by MSGBOX_ID2 into pszHelpTopic. The
  1228. string is "Message Box 2" and this gets passed on to HelpBox.
  1229.  
  1230. The only warning I can give is make sure all your message boxes have
  1231. UNIQUE ids.
  1232.  
  1233.  
  1234.  
  1235. II.2.E)  Compiling and Testing
  1236.  
  1237. Now that you have added all this code to your app, go compile it! Be
  1238. sure to link HELPLIB.LIB with our application. You should have copied
  1239. HELPLIB.LIB somewhere your compiler will have found it, and
  1240. HELPLIB.DLL somewhere your LIBPATH points to.
  1241.  
  1242. To test your app, put it through the same paces you tested your file
  1243. under QuickHelp with. Test chaining of help, resizing of windows,
  1244. minimizing your app (the help box should minimize too!), KEYS help,
  1245. all the special keys, etc. REALLY put it through its paces. I haven't
  1246. seen problems until after I really worked it hard.
  1247.  
  1248.  
  1249.  
  1250.  
  1251. III) Final Words !!!
  1252.  
  1253. III.1) Distribution (AGAIN!!)
  1254.  
  1255. Once again, I have no problem with you distributing HELPLIB.DLL with
  1256. your apps. PLEASE reread the section earlier regarding the
  1257. distribution of MSHELP.DLL.
  1258.  
  1259. III.2) I want to see your apps!
  1260.  
  1261. I am real interested in seeing your PM apps, whether you use
  1262. HELPLIB.DLL or not. If you have neat stuff going on, drop me a line
  1263. via CompuServe.
  1264.  
  1265. If you do decide to use HELPLIB.DLL, I REALLY want to see your app. I
  1266. am real interested in seeing how people implement it.
  1267.  
  1268. If you are going to sell your application with HELPLIB.DLL, PLEASE
  1269. let me know. I have no desire for payment, just the gratification in
  1270. knowing someone is using my DLL.
  1271.  
  1272. III.3) The future of HELPLIB.DLL
  1273.  
  1274. Lots of things are planned, if I have the time!!
  1275.  
  1276. First and foremost, all the source for HELPLIB.DLL will be on
  1277. Compuserve next week. I am going on vacation tomorrow and have yet to
  1278. finish the documentation. I DO PROMISE TO UPLOAD IT!!
  1279.  
  1280. I would like to add a bunch of things to HELPLIB, like full QuickHelp
  1281. compatibility, hypertext links, and graphics capabilities. Some of
  1282. these things are planned soon, others as people demand it. The
  1283. QuickHelp compatibility tends to be a problem as I have NO
  1284. documentation on the MSHELP.DLL functions. There are lots of
  1285. functions in there I would love to know how to access. (can anyone
  1286. at Microsoft "help" me out here ????). I also want to add the
  1287. capabilities to access multiple help files on the fly. This shouldn't
  1288. be too hard.
  1289.  
  1290.  
  1291. The way I implemented help in HELPSAMP is just one way to do it. It
  1292. may not be the most efficient, the most elegant, etc. but it works.
  1293. If you come up with a cleaner neater way, let me know. Remember,
  1294. HelpBox just needs a string and a file name. How you get those are up
  1295. to you!!
  1296.  
  1297.  
  1298.  
  1299. III.4) Contacting me
  1300.  
  1301. Any comments you have for HELPLIB.DLL are always appreciated, good or
  1302. bad. Any additional features, bugs, etc. you find can be sent to me
  1303. via Compuserve. I usually can be found somewhere in MSSYS or
  1304. PC_MAGNET. 
  1305.  
  1306. My user id is 75470,716. Mail me your ideas, comments etc.
  1307.  
  1308. Alternatively, I can be reached via U.S. mail at:
  1309.  
  1310. Andy Levine
  1311. 9737 Windy Ridge Rd
  1312. Frisco, Tx 75034
  1313.