home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / HUGELB.ZIP / HUGELB.C next >
C/C++ Source or Header  |  1992-12-21  |  15KB  |  312 lines

  1. /* ********************************************************************** */
  2. /*                                                                        */
  3. /*   HugeLB   Main Module                                                 */
  4. /*                                                                        */
  5. /*       This sample program demostrates a technique for using owner-     */
  6. /*   drawn list boxes to allow more list entries than would be possible   */
  7. /*   with a normal list box, given the inherent 64k control data heap.    */
  8. /*                                                                        */
  9. /*      Although this sample will show how it is possible to have a large */
  10. /*   number of list items in a list box, having a large number of list    */
  11. /*   items is not necessarily recommended. Very large list boxes may      */
  12. /*   be difficult for users to work with and search thru. It should be    */
  13. /*   carefully considered whether or not there is a better way to display */
  14. /*   the data.                                                            */
  15. /*      Also it should be carefully consider whether to use a container   */
  16. /*   control instead of a large owner-drawn list box. The container       */
  17. /*   control does not have the 64K data heap limit and is extremely       */
  18. /*   flexible and powerful. In most cases of a large amount of data to    */
  19. /*   be displayed, a container would be the preferred control.            */
  20. /*                                                                        */
  21. /*       List boxes, in versions prior to and including 2.0, have a limit */
  22. /*   of 64K of memory availble for maintaining items in the list. Text    */
  23. /*   for the list item, in most cases, uses up the majority of this       */
  24. /*   memory. Owner-drawn list boxes give the ability to maintain the list */
  25. /*   item data in memory *external* to the list box control, thereby      */
  26. /*   allowing more total list items to be inserted into the list.         */
  27. /*       With owner-drawn list boxes, the system sends a WM_DRAWITEM      */
  28. /*   to the owner of the list box (e.g. the dialog proc or the client     */
  29. /*   window proc ) when an item needs to be draw(displayed) in the        */
  30. /*   listbox window on the screen. At this stage, neither the system      */
  31. /*   nor the list box control cares what is drawn or how the item is      */
  32. /*   represented; the owner could draw a bitmap, an icon, a marker,       */
  33. /*   colored text, or combination. This feature can be used to allow      */
  34. /*   the text to be maintained in an external array. The list item itself */
  35. /*   has no text. When the owner receives a WM_DRAWITEM message, it       */
  36. /*   gets the ID (i.e. index) of the item that needs to be drawn. The     */
  37. /*   owner can use the ID to look up the appropriate text string in       */
  38. /*   the external array. It then draws the text onto the screen so that   */
  39. /*   it appears in the list box window. Note that the owner is given      */
  40. /*   all the elements necessary to draw the item (e.g. hps, bounding      */
  41. /*   rect, etc).                                                          */
  42. /*                                                                        */
  43. /*       This technique could also be used in cases where the list        */
  44. /*   box items need to be repeatedly shuffled and sorted to increase      */
  45. /*   performance. To change an items order in a list box, normally        */
  46. /*   involves deleting an re-inserting items into the list box. When      */
  47. /*   this needs to be done a lot, it can be very expensive. However,      */
  48. /*   by maintaining the text externally, only the indexing of the         */
  49. /*   external text needs to be sorted or shuffled. No actual list box     */
  50. /*   items need to be deleted, inserted, or moved. Only the index of      */
  51. /*   the text logically associated with the item needs to be changed.     */
  52. /*                                                                        */
  53. /*     DISCLAIMER OF WARRANTIES.  The following [enclosed] code is        */
  54. /*     sample code created by IBM Corporation. This sample code is not    */
  55. /*     part of any standard or IBM product and is provided to you solely  */
  56. /*     for  the purpose of assisting you in the development of your       */
  57. /*     applications.  The code is provided "AS IS", without               */
  58. /*     warranty of any kind.  IBM shall not be liable for any damages     */
  59. /*     arising out of your use of the sample code, even if they have been */
  60. /*     advised of the possibility of   such damages.                      */
  61. /*                                                                        */
  62. /* ********************************************************************** */
  63.  
  64.  
  65. #define INCL_WIN
  66. #define INCL_GPI
  67. #define INCL_DOS
  68. #define INCL_DOSMISC
  69. #define INCL_DOSERRORS
  70. #include <os2.h>
  71.  
  72. #include <stdio.h>
  73. #include <stdlib.h>
  74. #include "HugeLB.h"
  75.  
  76.  
  77. #define   ENTRY_CNT     2000         // number of list box entries
  78. #define   ENTRY_LENGTH  128          // number of chars in each entry
  79.  
  80.         /* --------------------  Globals  ---------------------- */
  81.  
  82. HAB     hab;
  83. HMQ     hmq;
  84.  
  85. PSZ    szMainTitle  = "Huge ListBox Sample" ;
  86. PSZ    szErrorTitle = "HugeLB Error" ;
  87.  
  88.         
  89.  
  90. CHAR   entries[ENTRY_CNT][ENTRY_LENGTH] ;  // External list text array
  91.              //  Note that this array is being allocated globally purely
  92.              //   for simplicity. In production code, it probably should
  93.              //   be dynamically allocated at runtime. 
  94.  
  95.         /* ----------------  Prototypes  ------------------------ */
  96. MRESULT EXPENTRY DlgWindowProc( HWND, USHORT, MPARAM, MPARAM );
  97.  
  98.  
  99.  
  100. /* ********************************************************************** */
  101. /*                                                                        */
  102. /*   Main                                                                 */
  103. /*                                                                        */
  104. /*      The program uses a dialog window as it's main window for          */
  105. /*   simplicity; it allows the list box to be displayed but otherwise     */
  106. /*   is not very flexible. Note that the dialog window will register      */
  107. /*   with the task manager (i.e. task window). Error checking is weak.    */
  108. /*                                                                        */
  109. /* ********************************************************************** */
  110.  
  111. VOID main()
  112. {
  113.  
  114.   if ( (hab = WinInitialize( 0L )) == (HAB) NULL ){
  115.      printf( "HugeLB Error:  WinInitialize failed \n" );
  116.      return;
  117.   }
  118.   else {
  119.  
  120.      if ( (hmq = WinCreateMsgQueue( hab, 0 )) == (HMQ) NULL ){
  121.         printf( "Shell Error:  WinCreateMsgQueue failed \n" );
  122.         return;
  123.      }
  124.      else {
  125.          WinDlgBox( HWND_DESKTOP,
  126.                     HWND_DESKTOP,
  127.                     (PFNWP)DlgWindowProc,
  128.                     NULLHANDLE,
  129.                     ID_DLG_WIN,
  130.                     (PVOID)NULL );
  131.  
  132.         WinDestroyMsgQueue(hmq);
  133.      }  /* end of else ( ...WinCreateMsgQueue() */
  134.      WinTerminate(hab);
  135.    }  /* end of else (...WinInitialize(NULL) */
  136. }  /*  end of main() */
  137.  
  138. /* ********************************************************************** */
  139. /*                                                                        */
  140. /*   DlgWindowProc                                                        */
  141. /*                                                                        */
  142. /* ********************************************************************** */
  143.  
  144. MRESULT EXPENTRY
  145. DlgWindowProc( HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2 )
  146. {
  147.  
  148.   switch (msg) {
  149.  
  150.        /* --------------------------------------------------------- */
  151.        /*  WM_INITDLG                                               */
  152.        /*                                                           */
  153.        /*     During this message we will register the dialog       */
  154.        /*  window with the task manager. We will also initialize    */
  155.        /*  both the external data array and the list box itself.    */
  156.        /*  We are doing the initialization here for simpilicity;    */
  157.        /*  it would be best to do this in a seperate thread         */
  158.        /*  rather than presenting the wait pointer for an extended  */
  159.        /*  period.                                                  */
  160.        /*                                                           */
  161.        /*     The text string will consist of a number indicating   */
  162.        /*  the index number of the item and a series of '.'s to     */
  163.        /*  fill out the string length                               */
  164.        /*                                                           */
  165.        /*     We will insert items into the list; note that the     */
  166.        /*  text inserted with each item is blank.                   */
  167.        /*                                                           */
  168.        /* --------------------------------------------------------- */
  169.     case WM_INITDLG:
  170.        {
  171.          USHORT    i;
  172.          HPOINTER  hptrOrig, hptrWait;
  173.          PID       pid ;
  174.          SWCNTRL   swCntrl;
  175.  
  176.             /* ---- set Wait pointer for initialization period ---- */
  177.          hptrWait = WinQuerySysPointer( HWND_DESKTOP, SPTR_WAIT, FALSE );
  178.          hptrOrig = WinQueryPointer( HWND_DESKTOP );
  179.          WinSetPointer( HWND_DESKTOP, hptrWait );
  180.  
  181.  
  182.             /* ----------- add program to tasklist  --------------- */
  183.          WinQueryWindowProcess( hwnd, &pid, NULL );
  184.          swCntrl.hwnd = hwnd ;
  185.          swCntrl.hwndIcon = (HWND) NULL ;
  186.          swCntrl.hprog = (HPROGRAM) NULL ;
  187.          swCntrl.idProcess = pid ;
  188.          swCntrl.idSession = (LONG) NULL ;
  189.          swCntrl.uchVisibility = SWL_VISIBLE ;
  190.          swCntrl.fbJump = SWL_JUMPABLE ;
  191.          strncpy( swCntrl.szSwtitle, szMainTitle, MAXNAMEL );
  192.          WinCreateSwitchEntry( hab, (PSWCNTRL)&swCntrl);
  193.  
  194.             /* -- initialize external text array and insert list items -- */
  195.          memset( entries[0], '.', ENTRY_CNT*ENTRY_LENGTH );
  196.          for( i=0; i < ENTRY_CNT; i++ ){
  197.  
  198.             _itoa( i, entries[i], 10 );            // initialize external text
  199.             entries[i][strlen( entries[i])] = '.' ;
  200.             entries[i][ENTRY_LENGTH-1] = '\0' ;
  201.  
  202.             WinSendDlgItemMsg( hwnd,              // insert "no text" item
  203.                                ID_LISTBOX,
  204.                                LM_INSERTITEM,
  205.                                MPFROMSHORT( LIT_END ),
  206.                                MPFROMP( (PVOID)"" ) );  //note: empty string
  207.          }
  208.  
  209.          WinSetPointer( HWND_DESKTOP, hptrOrig );
  210.        }
  211.        break;
  212.  
  213.        /* --------------------------------------------------------- */
  214.        /*                                                           */
  215.        /*  WM_MEASUREITEM                                           */
  216.        /*                                                           */
  217.        /*    With this message the system is asking for the height  */
  218.        /*  and width of a list box item. We are not using a         */
  219.        /*  horizontal scrollbar (i.e. LS_HORZSCROLL) so we will     */
  220.        /*  not have to specify a width, only a height.              */
  221.        /*                                                           */
  222.        /*    The height we need to specify is the height of the     */
  223.        /*  character box of the font that will be used, in our      */
  224.        /*  case the default font. We can get this char box height   */
  225.        /*  from the Max Baseline Extent metric.                     */
  226.        /*                                                           */
  227.        /* --------------------------------------------------------- */
  228.      case WM_MEASUREITEM:           
  229.         {
  230.            HPS           hps ;
  231.            FONTMETRICS   fmMetrics ;
  232.  
  233.  
  234.             hps = WinGetPS (hwnd);
  235.                /* ----------- get metrics of default font  ------------ */
  236.             GpiQueryFontMetrics (hps,
  237.                                  sizeof (FONTMETRICS), 
  238.                                  &fmMetrics);
  239.             WinReleasePS (hps);     
  240.  
  241.             return ((MRESULT)fmMetrics.lMaxBaselineExt);
  242.          }
  243.  
  244.        /* --------------------------------------------------------- */
  245.        /*                                                           */
  246.        /*  WM_DRAWITEM                                              */
  247.        /*                                                           */
  248.        /*     With this message the system requests that we draw    */
  249.        /*  a representation for a given list box item. In our case  */
  250.        /*  we will draw the text from the external text array. We   */
  251.        /*  will use the ID(index) number of the list box item as    */
  252.        /*  an index into the text array.                            */
  253.        /*                                                           */
  254.        /*     Note that we much check the selection state of the    */
  255.        /*  item to determine if it should be drawn with a highlight */
  256.        /*  or not.                                                  */
  257.        /*                                                           */
  258.        /* --------------------------------------------------------- */
  259.         case WM_DRAWITEM:
  260.          {
  261.            POWNERITEM  poiItem;                
  262.            COLOR       clrForeGround;
  263.            COLOR       clrBackGround;
  264.  
  265.             poiItem = (POWNERITEM) PVOIDFROMMP( mp2 );
  266.  
  267.                /* ---- check selection state of the item  ---- */
  268.             if (poiItem->fsState ) {
  269.                 clrForeGround = SYSCLR_HILITEFOREGROUND;
  270.                 clrBackGround = SYSCLR_HILITEBACKGROUND;
  271.                 poiItem->fsState = FALSE;   //clear so PM won't hilite also
  272.             }
  273.             else                       
  274.             {
  275.                 clrForeGround = CLR_NEUTRAL;          // normal colors
  276.                 clrBackGround = SYSCLR_ENTRYFIELD;
  277.             }
  278.  
  279.                 /* ---- draw the text into the given rect ----- */
  280.             WinDrawText (poiItem->hps,    
  281.                          -1,           
  282.                          entries[poiItem->idItem], 
  283.                          &poiItem->rclItem,        
  284.                          clrForeGround,
  285.                          clrBackGround,
  286.                          DT_LEFT | DT_VCENTER | DT_ERASERECT);
  287.  
  288.             poiItem->fsStateOld = FALSE;    //clear so PM won't hilite
  289.             return ((MRESULT)TRUE);
  290.          }
  291.  
  292.  
  293.     case WM_COMMAND :
  294.        switch( SHORT1FROMMP( mp1 ) ){
  295.           case DID_OK :
  296.              WinDismissDlg( hwnd, DID_OK );
  297.            break;
  298.  
  299.           default:
  300.           return WinDefDlgProc(hwnd,msg,mp1,mp2);
  301.         }
  302.     break;
  303.  
  304.     default:
  305.       return WinDefDlgProc(hwnd,msg,mp1,mp2);
  306.  
  307.   } /*  end of switch () */
  308.   return( FALSE );
  309.  
  310. } /*  end of DlgWindowProc */
  311.  
  312.