home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / VISUAL_B / FERRAMEN / VXC / VXSAMP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-25  |  38.6 KB  |  1,101 lines

  1. /*
  2. ┌──────────────────────────────────────────────────────────────────────────┐
  3. │ vxBase xbase for Visual Basic library                                    │
  4. │ Copyright 1992 vxBase (512523 Alberta Ltd.)                              │
  5. ├────────────────┬──────┬────────────┬────────┬───────────────┬────────────┤
  6. │ SYSTEM         │ VX   │ PROGRAM ID │ VXSAMP │ CREATION DATE │  02/29/92  │
  7. ├────────────────┼──────┴────────────┴────────┴───────────────┴────────────┤
  8. │ PROGRAM TITLE  │  sample c program using vxbase functions from vxbase.dll│
  9. ├─────┬──────┬───┴┬───────────────────────────┬────────────────────────────┤
  10. │ REV │ DATE │ BY │ DESCRIPTION               │ Written by T. Orletsky     │
  11. ├─────┼──────┼────┼───────────────────────────┴────────────────────────────┤
  12. │     │      │    │                                                        │
  13. └─────┴──────┴────┴────────────────────────────────────────────────────────┘
  14.  
  15. This sample code and all other supplied sample files should be
  16. loaded into \vb\vxc to use the .def and project files
  17. for compilation under Turbo c++ for Windows (ver 3.0).
  18.  
  19. If using a non-Borland compiler, remove the "pragma argsused"
  20. directives.
  21.  
  22. !!! ALWAYS COMPILE UNDER THE LARGE MODEL !!!
  23.  
  24. */
  25.  
  26. #include <windows.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <dos.h>
  30. #include "vxb.h"
  31. #include "vxsamp.h"
  32.  
  33.  
  34. /* ********************************************************* */
  35. /*                global vars defined                        */
  36. /* ********************************************************* */
  37.  
  38. HWND        hgWnd;               //Global Window Handle. 
  39. HANDLE      hgInst;              //Global Instance Handle. 
  40.  
  41. int         DbfArea1;            //vxbase dbf area 1
  42. int         NtxArea1;            //vxbase ntx area 1
  43. int         DbfArea2;            //vxbase dbf area 2
  44. int         NtxArea2;            //vxbase ntx area 2
  45. long        RetVal;              //vxbrowse return value
  46. char        szBuffer[81];        //miscellaneous buffer
  47. char        szBuffer2[81];       //miscellaneous buffer 2
  48.  
  49. /*
  50.  * Array of pointers to strings loaded from the resource file.
  51.  * Pointers can be near since LocalAlloc will be used to get
  52.  * the string space.
  53.  */
  54.  
  55. char NEAR   *rgpsz[CSTRINGS];
  56.  
  57.  
  58. /*
  59.  * WinMain
  60.  *
  61.  * Purpose:
  62.  *  Main entry point of application.   Should register the app class
  63.  *  if a previous instance has not done so and do any other one-time
  64.  *  initializations.
  65.  *
  66.  * Parameters:
  67.  *  See Windows SDK Guide to Programming, page 2-3
  68.  *
  69.  * Return Value:
  70.  *  Value to return to Windows--termination code.
  71.  *
  72.  */
  73.  
  74.  
  75. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  76.                     LPSTR lpszCmdLine, int nCmdShow)
  77.     {
  78.     WNDCLASS    wndClass;
  79.     HANDLE      hStringMem;
  80.     HWND        hWnd;
  81.     MSG         msg;
  82.  
  83.     hgInst = hInstance;
  84.  
  85.     /*
  86.      * InitApp allocates local memory for strings. WinMain must free.
  87.      * If this fails, we should quit BEFORE any classes are registered
  88.      * or do anything else that uses up USER or GDI resources.
  89.      */
  90.     hStringMem = HLoadAppStrings();
  91.  
  92.     if (hStringMem == NULL)
  93.         {
  94.         LocalFree(hStringMem);
  95.         return FALSE;
  96.         }
  97.  
  98.     if (!hPrevInstance)
  99.         {
  100.         wndClass.style          = CS_HREDRAW | CS_VREDRAW;
  101.         wndClass.lpfnWndProc      = vxWndProc;
  102.         wndClass.cbClsExtra     = 0;
  103.         wndClass.cbWndExtra     = 0;
  104.         wndClass.hInstance      = hInstance;
  105.         wndClass.hIcon          = LoadIcon(hInstance, "vxIcon");
  106.         wndClass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  107.         wndClass.hbrBackground  = COLOR_BTNFACE + 1;
  108.         wndClass.lpszMenuName   = "vxMenu";
  109.         wndClass.lpszClassName  = "vxSamp";
  110.  
  111.         if (!RegisterClass(&wndClass))
  112.             return FALSE;
  113.         }
  114.  
  115.     hWnd = CreateWindow("vxSamp",
  116.                        rgpsz[IDS_CAPTION],
  117.                        WS_MINIMIZEBOX | WS_OVERLAPPEDWINDOW,
  118.                        50, 50, 500, 300,
  119.                        NULL,
  120.                        NULL,
  121.                        hInstance,
  122.                        NULL);
  123.  
  124.     hgWnd = hWnd;
  125.     ShowWindow(hWnd, nCmdShow);
  126.     UpdateWindow(hWnd);
  127.  
  128.  
  129.     while (GetMessage(&msg, NULL, 0, 0))
  130.         {
  131.         TranslateMessage(&msg);
  132.         DispatchMessage(&msg);
  133.         }
  134.  
  135.     LocalFree(hStringMem);
  136.     return msg.wParam;
  137.     }
  138.  
  139. /*
  140.  * vxWndProc
  141.  *
  142.  * Purpose:
  143.  *  Window class procedure.  Standard callback.
  144.  *
  145.  * Parameters:
  146.  *  The standard.  See Section 2.4 Windows SDK Guide to Programming,
  147.  *  page 2-4.
  148.  *
  149.  * Return Value:
  150.  *  See Parameters, above.
  151.  *
  152.  */
  153.  
  154. long FAR PASCAL vxWndProc(HWND hWnd, UINT iMessage,
  155.                                WORD wParam, LONG lParam)
  156.    {
  157.    HMENU         hMenu;         // handle to main menu
  158.    int           j;             // work integer
  159.    PAINTSTRUCT   ps;            // paint structure
  160.  
  161.    switch (iMessage)
  162.       {
  163.  
  164.       /* handle vxBase initialization procedures when window */
  165.       /* creation message is received                        */
  166.       /* *************************************************** */
  167.       case WM_CREATE:
  168.          vxInit();                // register in multitask list
  169.          vxCtlGraySet();          // set up gray scale
  170.          vxBrowseCase(VX_UPPER);  // default browse case
  171.          vxSetString(VX_ASCIIZ);  // set string types to c strings
  172.          break;
  173.       
  174.       /* on exit, reset system gray and post quit */
  175.       /* **************************************** */
  176.       case WM_DESTROY:
  177.          vxCtlGrayReset();        // reset system grays
  178.          PostQuitMessage(0);      // kill
  179.          break;
  180.  
  181.       /* on paint, draw frame around window */
  182.       /* ********************************** */
  183.       case WM_PAINT:
  184.          BeginPaint(hWnd, &ps);
  185.          vxFormFrame(hWnd);
  186.          EndPaint(hWnd, &ps);
  187.          break;
  188.  
  189.  
  190.       /* ******************************************* */
  191.       /* If user closes from system menu, ensure     */
  192.       /* that multitask closure sequence is correct. */
  193.       /* The first vxbase task loaded MUST be the    */
  194.       /* last one unloaded because it controls the   */
  195.       /* vxbase shareable memory. If the first task  */
  196.       /* is closed, the memory goes with it and any  */
  197.       /* other tasks using vxbase will terminate     */
  198.       /* with an Unrecoverable Application error.    */
  199.       /* ******************************************* */
  200.       case WM_SYSCOMMAND:
  201.          switch (wParam & 0xFFF0)
  202.             {
  203.             case SC_CLOSE:
  204.                /* vxDeallocate will issue a task closure */
  205.                /* sequence error if this task cannot be  */
  206.                /* shut down                              */
  207.                /* ************************************** */
  208.                if (!vxDeallocate())
  209.                   return(TRUE);
  210.  
  211.             /* we could use this switch set to test for   */
  212.             /* other options selcted from the system menu */
  213.             /* ****************************************** */
  214.             default:
  215.                return(DefWindowProc(hWnd, iMessage, wParam, lParam));
  216.             }
  217.  
  218.  
  219.       /* process menu commands */
  220.       /* ********************* */
  221.       case WM_COMMAND:
  222.          switch (wParam)
  223.                         
  224.             {
  225.             case IDM_BROWSE:
  226.  
  227.                // disable menu items
  228.                hMenu = GetMenu(hWnd);
  229.                EnableMenuItem(hMenu, IDM_BROWSE, MF_GRAYED);
  230.                EnableMenuItem(hMenu, IDM_JOIN, MF_GRAYED);
  231.                EnableMenuItem(hMenu, IDM_PACK, MF_GRAYED);
  232.                RetVal = 0;
  233.  
  234.  
  235.                // set up do loop and keep browsing if edit
  236.                // dialog returns a BROWSE_USER value
  237.                while (TRUE)
  238.                   {
  239.  
  240.                   // if browse went ok, vxTypeBrowse returns nonzero
  241.                   if (vxTypeBrowse())
  242.                      {
  243.                      if (RetVal != BROWSE_USER)
  244.                         {
  245.                         MessageBox(hWnd,
  246.                                    rgpsz[IDS_BROWSE],
  247.                                    rgpsz[IDS_CAPTION],
  248.                                    MB_OK | MB_ICONEXCLAMATION);
  249.                         break;
  250.                         }
  251.                      }
  252.  
  253.                   // otherwise an error occurred
  254.                   else
  255.                      {
  256.                      MessageBox(hWnd,
  257.                                 rgpsz[IDE_BROWSE],
  258.                                 rgpsz[IDS_CAPTION],
  259.                                 MB_OK | MB_ICONEXCLAMATION);
  260.                      break;
  261.                      }
  262.                   }
  263.  
  264.                // re-enable menu items
  265.                hMenu = GetMenu(hWnd);
  266.                EnableMenuItem(hMenu, IDM_BROWSE, MF_ENABLED);
  267.                EnableMenuItem(hMenu, IDM_JOIN, MF_ENABLED);
  268.                EnableMenuItem(hMenu, IDM_PACK, MF_ENABLED);
  269.  
  270.                vxWindowDereg(hWnd);
  271.  
  272.                break;
  273.  
  274.  
  275.             case IDM_JOIN:
  276.  
  277.                // disable menu items
  278.                hMenu = GetMenu(hWnd);
  279.                EnableMenuItem(hMenu, IDM_BROWSE, MF_GRAYED);
  280.                EnableMenuItem(hMenu, IDM_JOIN, MF_GRAYED);
  281.                EnableMenuItem(hMenu, IDM_PACK, MF_GRAYED);
  282.                RetVal = 0;
  283.  
  284.  
  285.                // Demonstration of setting up visual relationships
  286.                // with the vxJoin command. What we have is a file of buyers
  287.                // categorized by type of aircraft they are interested in.
  288.                // What we are going to do is display a browse table of
  289.                // these buyer records and link any buyer record to
  290.                // another browse table of aircraft that match the the
  291.                // buyer aircraft type field.
  292.                // --------------------------------------------------------
  293.    
  294.                // open file that will control the join
  295.                // ------------------------------------
  296.                DbfArea1 = vxUseDbf("\\vb\\vxbtest\\airbuyer.dbf");
  297.                NtxArea1 = vxUseNtx("\\vb\\vxbtest\\airbuy2.ntx");
  298.                // this index is on aircraft type
  299.                // ------------------------------
  300.  
  301.                // define table to show data we are interested in
  302.                // ----------------------------------------------
  303.                vxTableDeclare(VX_BLUE, NULL, NULL, 0, 1, 5);
  304.                vxTableField(1, "Type", "b_cat", VX_FIELD);
  305.                vxTableField(2, "Description", "left(b_desc,20)", VX_EXPR);
  306.                vxTableField(3, "Low", "b_low", VX_FIELD);
  307.                vxTableField(4, "High", "b_high", VX_FIELD);
  308.                vxTableField(5, "Customer", "b_code", VX_FIELD);
  309.  
  310.                // now open secondary file and define its table
  311.                // --------------------------------------------
  312.                DbfArea2 = vxUseDbf("\\vb\\vxbtest\\aircraft.dbf");
  313.                NtxArea2 = vxUseNtx("\\vb\\vxbtest\\aircraf2.ntx");
  314.  
  315.                vxTableDeclare(VX_RED, NULL, NULL, 0, 1, 5);
  316.                vxTableField(1, "Type", "c_cat", VX_FIELD);
  317.                vxTableField(2, "Code", "c_code", VX_FIELD);
  318.                vxTableField(3, "Price", "c_price", VX_FIELD);
  319.                vxTableField(4, "Year", "c_year", VX_FIELD);
  320.                vxTableField(5, "TTSN", "c_ttsn", VX_FIELD);
  321.  
  322.                // reselect the master file and set up the join
  323.                // --------------------------------------------
  324.                vxSelectDbf(DbfArea1);
  325.                vxJoin(DbfArea2, NtxArea2, "b_cat", VX_FIELD, "Possible Sales");
  326.  
  327.                // this joins the Aircraft file using the index selected for
  328.                // it to the buyer file. The "b_cat" param is the field we
  329.                // will use as a key into the aircraft file and the VX_FIELD
  330.                // item tells vxBase that it is a field and not an expression.
  331.                // The last item in the call is a title for the join window.
  332.                // -----------------------------------------------------------
  333.  
  334.                // now set up and execute the browse. The JOIN menu item is
  335.                // automatically enabled.
  336.                // ---------------------------------------------------------
  337.                vxBrowse(hWnd, DbfArea1, NtxArea1, FALSE, TRUE, FALSE, 0, "Buyer Details", &RetVal);
  338.  
  339.                // when we return from the browse we can ignore anything
  340.                // vxBase sent back to us in the RetVal param
  341.                // -----------------------------------------------------
  342.                vxClose();
  343.                vxSelectDbf(DbfArea2);
  344.                vxClose();
  345.                vxWindowDereg(hgWnd);
  346.  
  347.                // re-enable menu items
  348.                hMenu = GetMenu(hWnd);
  349.                EnableMenuItem(hMenu, IDM_BROWSE, MF_ENABLED);
  350.                EnableMenuItem(hMenu, IDM_JOIN, MF_ENABLED);
  351.                EnableMenuItem(hMenu, IDM_PACK, MF_ENABLED);
  352.  
  353.                MessageBox(hgWnd,
  354.                            rgpsz[IDS_JOIN],
  355.                            rgpsz[IDS_CAPTION],
  356.                            MB_OK | MB_ICONEXCLAMATION);
  357.  
  358.                break;
  359.  
  360.  
  361.             case IDM_PACK:
  362.                // disable menu items
  363.                hMenu = GetMenu(hWnd);
  364.                EnableMenuItem(hMenu, IDM_BROWSE, MF_GRAYED);
  365.                EnableMenuItem(hMenu, IDM_JOIN, MF_GRAYED);
  366.                EnableMenuItem(hMenu, IDM_PACK, MF_GRAYED);
  367.  
  368.  
  369.                // only pack if file is not in use
  370.                j = vxAreaDbf("\\vb\vxbtest\\airtypes.dbf");
  371.  
  372.                if (!j)
  373.                   {
  374.                   DbfArea1 = vxUseDbf("\\vb\\vxbtest\\airtypes.dbf");
  375.                   NtxArea1 = vxUseNtx("\\vb\\vxbtest\\airtypes.ntx");
  376.                   vxPack(hWnd);
  377.                   vxClose();
  378.                   MessageBox(hgWnd,
  379.                               rgpsz[IDS_PACK],
  380.                               rgpsz[IDS_CAPTION],
  381.                               MB_OK | MB_ICONEXCLAMATION);
  382.                   }
  383.                else
  384.                   MessageBox(hgWnd,
  385.                               rgpsz[IDE_PACK],
  386.                               rgpsz[IDS_CAPTION],
  387.                               MB_OK | MB_ICONEXCLAMATION);
  388.  
  389.                // re-enable menu items
  390.                hMenu = GetMenu(hWnd);
  391.                EnableMenuItem(hMenu, IDM_BROWSE, MF_ENABLED);
  392.                EnableMenuItem(hMenu, IDM_JOIN, MF_ENABLED);
  393.                EnableMenuItem(hMenu, IDM_PACK, MF_ENABLED);
  394.  
  395.                break;
  396.         
  397.  
  398.             /* see WM_SYSCOMMAND above for explanation of */
  399.             /* why we test vxDeallocate before we allow   */
  400.             /* this task to be closed                     */
  401.             /* ****************************************** */
  402.             case IDM_EXIT:
  403.                if (!vxDeallocate())
  404.                   break;
  405.                PostMessage(hWnd, WM_CLOSE, 0, 0L);
  406.                break;
  407.             }
  408.       default:
  409.           return (DefWindowProc(hWnd, iMessage, wParam, lParam));
  410.       }
  411.  
  412.     return 0L;
  413.     }
  414.  
  415.  
  416. /* ***************** */
  417. /* browse types file */
  418. /* ***************** */
  419. int NEAR PASCAL vxTypeBrowse()
  420.    {
  421.    FARPROC        lpProc;        // discardable proc instance
  422.    
  423.    // open dbf file
  424.    DbfArea1 = vxUseDbf("\\vb\\vxbtest\\airtypes.dbf");
  425.    if (!DbfArea1)
  426.       return (FALSE);
  427.  
  428.    // open index file
  429.    NtxArea1 = vxUseNtx("\\vb\\vxbtest\\airtypes.ntx");
  430.    if (!NtxArea1)
  431.       return (FALSE);
  432.  
  433.    // declare browse table
  434.    vxTableDeclare(VX_RED, NULL, NULL, 0, 1, 2);
  435.    vxTableField(1, "Type", "category", VX_FIELD);
  436.    vxTableField(2, "Description", "catname", VX_FIELD);
  437.  
  438.    // set up initial browse position
  439.    vxBrowsePos(20, 10, 50, 15);
  440.  
  441.    // call the browse
  442.    vxBrowse(hgWnd, DbfArea1, NtxArea1, TRUE, TRUE, TRUE, 0L, "Aircraft Types", &RetVal);
  443.  
  444.    // if user closed, exit TRUE
  445.    if (RetVal == BROWSE_CLOSED)
  446.       return (TRUE);
  447.  
  448.    // if browse had error, exit FALSE
  449.    if (RetVal == BROWSE_ERROR)
  450.       return (FALSE);
  451.  
  452.    // if user picked anything else, do file edit dialog
  453.    // NOTE: RetVal is global so it will be accessible to
  454.    //       the edit dialog
  455.    lpProc = MakeProcInstance(vxTypeEditDlg, hgInst);
  456.    DialogBox (hgInst,
  457.             MAKEINTRESOURCE (IDD_TYPEDIT),
  458.             hgWnd,
  459.             lpProc);
  460.    FreeProcInstance(lpProc);
  461.  
  462.    // if user clicks browse button from dialog, retval
  463.    // is set to BROWSE_USER so calling rtn
  464.    // from wm_command can test if this is to be done again
  465.  
  466.    // close file (first ensure registered)
  467.    vxSelectDbf(DbfArea1);
  468.    vxClose();
  469.  
  470.    return (TRUE);
  471.    }
  472.  
  473.  
  474. /* ********************************************************** */
  475. /*           Edit type file record dialog                     */
  476. /* ********************************************************** */
  477. BOOL FAR PASCAL vxTypeEditDlg(HWND hdlg, WORD wMsg, WORD wParam, LONG lParam)
  478.    {
  479.           HWND  hwndDI;             /* handle to dialog item   */
  480.           int   j;                  /* general integer         */
  481.    static long  RecNum;             /* current record number   */
  482.    static BOOL  IsChanged;          /* set if anything changes */
  483.    static BOOL  IsDeleting;         /* set on if deleting      */
  484.  
  485.    switch (wMsg)
  486.       {
  487.  
  488.       // initialization routine
  489.       // **********************
  490.       case WM_INITDIALOG:
  491.  
  492.          // register database select area with this window
  493.          vxSelectDbf(DbfArea1);
  494.  
  495.          // set control lengths
  496.          SendDlgItemMessage(hdlg, IDD_TYPE,
  497.                             EM_LIMITTEXT, (WORD)vxFieldSize("category"), 0L);
  498.          SendDlgItemMessage(hdlg, IDD_DESC,
  499.                             EM_LIMITTEXT, (WORD)vxFieldSize("catname"), 0L);
  500.          SendDlgItemMessage(hdlg, IDD_STAT,
  501.                             EM_LIMITTEXT, (WORD)64, 0L);
  502.  
  503.          // disable status bar
  504.          hwndDI = GetDlgItem(hdlg, IDD_STAT);
  505.          EnableWindow(hwndDI, FALSE);
  506.  
  507.          // other init stuff
  508.          RecNum = vxRecNo();              // save record number
  509.          szBuffer[0] = '\0';              // clear work buffer
  510.          IsChanged = FALSE;               // default change val
  511.  
  512.          // analyze browse return value and fill controls accordingly
  513.  
  514.          // if user pressed enter key to select record for edit
  515.          if (RetVal > 0)
  516.             RetVal = BROWSE_EDIT;
  517.  
  518.          // if adding, show empty record
  519.          if (RetVal == BROWSE_ADD)
  520.             {
  521.             SetDlgItemText(hdlg, IDD_TYPE, (LPSTR)szBuffer);
  522.             SetDlgItemText(hdlg, IDD_DESC, (LPSTR)szBuffer);
  523.             SetDlgItemText(hdlg, IDD_STAT, (LPSTR)rgpsz[IDS_ADDING]);
  524.  
  525.             // disable add and delete buttons
  526.             hwndDI = GetDlgItem(hdlg, IDD_ADD);
  527.             EnableWindow(hwndDI, FALSE);
  528.             hwndDI = GetDlgItem(hdlg, IDD_DELETE);
  529.             EnableWindow(hwndDI, FALSE);
  530.             }
  531.  
  532.          // if deleting or editing, show record
  533.          else
  534.             {
  535.             // with any vxbase string function, always copy
  536.             // the result to an internal buffer as below
  537.             // ********************************************
  538.             lstrcpy(szBuffer, (LPSTR)vxField("category"));
  539.             vxbTrim(szBuffer, sizeof(szBuffer));
  540.             SetDlgItemText(hdlg, IDD_TYPE, (LPSTR)szBuffer);
  541.  
  542.             lstrcpy(szBuffer, (LPSTR)vxField("catname"));
  543.             vxbTrim(szBuffer, sizeof(szBuffer));
  544.             SetDlgItemText(hdlg, IDD_DESC, (LPSTR)szBuffer);
  545.  
  546.             if (RetVal == BROWSE_DELETE)
  547.                wsprintf(szBuffer, "%s %ld", (LPSTR)rgpsz[IDS_DELE], RecNum);
  548.             else
  549.                {
  550.                wsprintf(szBuffer, "%s %ld", (LPSTR)rgpsz[IDS_EDIT], RecNum);
  551.                vxUnlock();    // unlock if editing for multiusers
  552.                }
  553.             SetDlgItemText(hdlg, IDD_STAT, (LPSTR)szBuffer);
  554.             }
  555.  
  556.          // if deleting, set switch to send delete
  557.          // button click after form has been painted
  558.          if (RetVal == BROWSE_DELETE)
  559.             IsDeleting = TRUE;
  560.  
  561.          // we can't send the WM_COMMAND message here
  562.          // because the dialog box hasn't been
  563.          // painted yet and we want the user to see
  564.          // the record he is deleting
  565.  
  566.  
  567.          // format control
  568.          hwndDI = GetDlgItem(hdlg, IDD_TYPE);
  569.          SetFocus(hwndDI);
  570.          vxCtlFormat(3, 0, 0);     // vx_upper
  571.  
  572.          // after formatting a series of controls (using the
  573.          // three code lines above as a template), remember
  574.          // to reset the focus to the FIRST control and
  575.          // return FALSE because the focus has been set
  576.          // ------------------------------------------------
  577.          return (FALSE);
  578.  
  579.  
  580.       // the wm_ctlcolor, wm_paint, and wm_3dpaint create
  581.       // 3d style controls on a gray background
  582.       // ************************************************
  583.       case WM_CTLCOLOR:
  584.          return (Control3dColor(hdlg,wParam));
  585.  
  586.       case WM_PAINT:
  587.          PostMessage(hdlg,WM_3DPAINT,0,0L);
  588.          return (FALSE);
  589.  
  590.       case WM_3DPAINT:
  591.          // frame
  592.          Draw3dFrame(hdlg,OUTSIDE_FRAME);
  593.  
  594.          // edit controls
  595.          Draw3dBorder(hdlg,IDD_TYPE,RECESSED,2);
  596.          Draw3dBorder(hdlg,IDD_DESC,RECESSED,2);
  597.          Draw3dBorder(hdlg,IDD_STAT,RAISED,2);
  598.  
  599.          // buttons
  600.          Draw3dBorder(hdlg,IDD_SAVE,RECESSED,2);
  601.          Draw3dBorder(hdlg,IDD_CANCEL,RECESSED,2);
  602.          Draw3dBorder(hdlg,IDD_ADD,RECESSED,2);
  603.          Draw3dBorder(hdlg,IDD_DELETE,RECESSED,2);
  604.          Draw3dBorder(hdlg,IDD_NEXT,RECESSED,2);
  605.          Draw3dBorder(hdlg,IDD_PREV,RECESSED,2);
  606.          Draw3dBorder(hdlg,IDD_BROWSE,RECESSED,2);
  607.          Draw3dBorder(hdlg,IDD_EXIT,RECESSED,2);
  608.  
  609.          // if deleting, we send a message as if user punched
  610.          // delete button and we process in wm_command
  611.          if (IsDeleting)
  612.             {
  613.             IsDeleting = FALSE;
  614.             hwndDI = GetDlgItem(hdlg, IDD_DELETE);
  615.             lParam = MAKELONG(hwndDI, BN_CLICKED);
  616.             SendMessage(hdlg, WM_COMMAND, IDD_DELETE, lParam);
  617.             }
  618.  
  619.          return (TRUE);
  620.  
  621.       // user pressed a button
  622.       // *********************
  623.       case WM_COMMAND:
  624.          {
  625.          switch (wParam)
  626.             {
  627.             /* *********** */
  628.             /* save button */
  629.             /* *********** */
  630.             case IDD_SAVE:
  631.  
  632.                // get control item "category"
  633.                GetDlgItemText(hdlg, IDD_TYPE, szBuffer, (vxFieldSize("category") + 1));
  634.  
  635.                // convert to upper case and redisplay
  636.                if (lstrlen(szBuffer))
  637.                   {
  638.                   AnsiUpper(szBuffer);
  639.                   SetDlgItemText(hdlg, IDD_TYPE, (LPSTR)szBuffer);
  640.                   }
  641.                else
  642.                   {
  643.                   MessageBox(hdlg,
  644.                              rgpsz[IDS_BADKEY],
  645.                              rgpsz[IDS_CAPTION],
  646.                              MB_ICONSTOP | MB_OK);
  647.                   hwndDI = GetDlgItem(hdlg, IDD_TYPE);
  648.                   SetFocus(hwndDI);
  649.                   return (FALSE);
  650.                   }
  651.  
  652.                // if new item, test for duplicate key
  653.                if (RetVal == BROWSE_ADD)
  654.                   {
  655.                   if (vxSeek(szBuffer))
  656.                      {
  657.                      vxUnlock();
  658.                      MessageBox(hdlg,
  659.                                 rgpsz[IDS_DUPKEY],
  660.                                 rgpsz[IDS_CAPTION],
  661.                                 MB_ICONSTOP | MB_OK);
  662.                      hwndDI = GetDlgItem(hdlg, IDD_TYPE);
  663.                      SetFocus(hwndDI);
  664.                      return (FALSE);
  665.                      }
  666.  
  667.                   // otherwise add an empty record
  668.                   else
  669.                      vxAppendBlank();
  670.                   }
  671.  
  672.                // if editing position pointer and lock record
  673.                else
  674.                   vxGo(RecNum);
  675.  
  676.                // get catname field data and put fields away
  677.                GetDlgItemText(hdlg, IDD_DESC, szBuffer2, (vxFieldSize("catname") + 1));
  678.                vxReplString("category", szBuffer);
  679.                vxReplString("catname", szBuffer2);
  680.                vxWrite();
  681.  
  682.                // update status box
  683.                RecNum = vxRecNo();
  684.                if (RetVal == BROWSE_ADD)
  685.                   wsprintf(szBuffer, "Record %ld appended", RecNum);
  686.                else
  687.                   wsprintf(szBuffer, "Record %ld saved", RecNum);
  688.                SetDlgItemText(hdlg, IDD_STAT, (LPSTR)szBuffer);
  689.  
  690.                // update buttons
  691.                hwndDI = GetDlgItem(hdlg, IDD_SAVE);
  692.                EnableWindow(hwndDI, TRUE);
  693.                hwndDI = GetDlgItem(hdlg, IDD_CANCEL);
  694.                EnableWindow(hwndDI, TRUE);
  695.                hwndDI = GetDlgItem(hdlg, IDD_ADD);
  696.                EnableWindow(hwndDI, TRUE);
  697.                hwndDI = GetDlgItem(hdlg, IDD_DELETE);
  698.                EnableWindow(hwndDI, TRUE);
  699.  
  700.                // unlock record
  701.                vxUnlock();
  702.  
  703.                // change status to edit mode
  704.                RetVal = BROWSE_EDIT;
  705.  
  706.                return (TRUE);
  707.  
  708.  
  709.             /* ************* */
  710.             /* cancel button */
  711.             /* ************* */
  712.             case IDD_CANCEL:
  713.  
  714.                // clear form data and reset buttons
  715.                szBuffer[0] = '\0';              // clear work buffer
  716.                SetDlgItemText(hdlg, IDD_TYPE, (LPSTR)szBuffer);
  717.                SetDlgItemText(hdlg, IDD_DESC, (LPSTR)szBuffer);
  718.                SetDlgItemText(hdlg, IDD_STAT, (LPSTR)rgpsz[IDS_CANC]);
  719.  
  720.                hwndDI = GetDlgItem(hdlg, IDD_SAVE);
  721.                EnableWindow(hwndDI, FALSE);
  722.                hwndDI = GetDlgItem(hdlg, IDD_CANCEL);
  723.                EnableWindow(hwndDI, FALSE);
  724.                hwndDI = GetDlgItem(hdlg, IDD_ADD);
  725.                EnableWindow(hwndDI, TRUE);
  726.                hwndDI = GetDlgItem(hdlg, IDD_DELETE);
  727.                EnableWindow(hwndDI, FALSE);
  728.  
  729.                // disable data entry
  730.                hwndDI = GetDlgItem(hdlg, IDD_TYPE);
  731.                EnableWindow(hwndDI, TRUE);
  732.                hwndDI = GetDlgItem(hdlg, IDD_DESC);
  733.                EnableWindow(hwndDI, TRUE);
  734.  
  735.                return (TRUE);
  736.  
  737.             /* ********** */
  738.             /* add button */
  739.             /* ********** */
  740.             case IDD_ADD:
  741.                // test if current stuff has changed
  742.                for (j=IDD_TYPE; j<IDD_DESC; j++)
  743.                   if (SendDlgItemMessage(hdlg, j, EM_GETMODIFY, 0, 0L))
  744.                      IsChanged = TRUE;
  745.                if (IsChanged)
  746.                   {
  747.                   IsChanged = FALSE;
  748.                   if (IDNO == (MessageBox(hdlg, "Current record changed. Abandon?",
  749.                                rgpsz[IDS_CAPTION],
  750.                                MB_ICONQUESTION | MB_YESNO)))
  751.                       return (TRUE);
  752.  
  753.                   }
  754.                IsChanged = FALSE;
  755.  
  756.                // clear controls 
  757.                szBuffer[0] = '\0';              // clear work buffer
  758.                SetDlgItemText(hdlg, IDD_TYPE, (LPSTR)szBuffer);
  759.                SetDlgItemText(hdlg, IDD_DESC, (LPSTR)szBuffer);
  760.                SetDlgItemText(hdlg, IDD_STAT, (LPSTR)rgpsz[IDS_ADDING]);
  761.  
  762.                // disable add and delete buttons
  763.                hwndDI = GetDlgItem(hdlg, IDD_ADD);
  764.                EnableWindow(hwndDI, FALSE);
  765.                hwndDI = GetDlgItem(hdlg, IDD_DELETE);
  766.                EnableWindow(hwndDI, FALSE);
  767.  
  768.                // enable data entry
  769.                hwndDI = GetDlgItem(hdlg, IDD_TYPE);
  770.                EnableWindow(hwndDI, TRUE);
  771.                hwndDI = GetDlgItem(hdlg, IDD_DESC);
  772.                EnableWindow(hwndDI, TRUE);
  773.  
  774.  
  775.                // set add mode
  776.                RetVal = BROWSE_ADD;
  777.  
  778.                // set focus to code
  779.                hwndDI = GetDlgItem(hdlg, IDD_TYPE);
  780.                SetFocus(hwndDI);
  781.  
  782.                // when setting focus, always return false
  783.                return (FALSE);
  784.  
  785.  
  786.             /* ************* */
  787.             /* delete button */
  788.             /* ************* */
  789.             case IDD_DELETE:
  790.  
  791.                // confirm deletion
  792.                if (IDNO == (MessageBox(hdlg,
  793.                                        rgpsz[IDS_CDELE],
  794.                                        rgpsz[IDS_CAPTION],
  795.                                        MB_ICONQUESTION | MB_YESNO)))
  796.                   {
  797.                   SetDlgItemText(hdlg, IDD_STAT, "Delete cancelled");
  798.                   RetVal = BROWSE_EDIT;
  799.                   return (TRUE);
  800.                   }
  801.  
  802.                vxLockRecord();
  803.                vxDeleteRec();
  804.                wsprintf(szBuffer, "Record %ld deleted", RecNum);
  805.                SetDlgItemText(hdlg, IDD_STAT, (LPSTR)szBuffer);
  806.  
  807.                // clear data and reset buttons
  808.                szBuffer[0] = '\0';              // clear work buffer
  809.                SetDlgItemText(hdlg, IDD_TYPE, (LPSTR)szBuffer);
  810.                SetDlgItemText(hdlg, IDD_DESC, (LPSTR)szBuffer);
  811.  
  812.                hwndDI = GetDlgItem(hdlg, IDD_SAVE);
  813.                EnableWindow(hwndDI, FALSE);
  814.                hwndDI = GetDlgItem(hdlg, IDD_CANCEL);
  815.                EnableWindow(hwndDI, FALSE);
  816.                hwndDI = GetDlgItem(hdlg, IDD_ADD);
  817.                EnableWindow(hwndDI, TRUE);
  818.                hwndDI = GetDlgItem(hdlg, IDD_DELETE);
  819.                EnableWindow(hwndDI, FALSE);
  820.  
  821.                // disable data entry
  822.                hwndDI = GetDlgItem(hdlg, IDD_TYPE);
  823.                EnableWindow(hwndDI, TRUE);
  824.                hwndDI = GetDlgItem(hdlg, IDD_DESC);
  825.                EnableWindow(hwndDI, TRUE);
  826.  
  827.                RetVal = 0;
  828.                vxUnlock();
  829.                return (TRUE);
  830.  
  831.  
  832.             /* *********** */
  833.             /* next button */
  834.             /* *********** */
  835.             case IDD_NEXT:
  836.                // first test if current rec has changed
  837.                for (j=IDD_TYPE; j<IDD_DESC; j++)
  838.                   if (SendDlgItemMessage(hdlg, j, EM_GETMODIFY, 0, 0L))
  839.                      IsChanged = TRUE;
  840.                if (IsChanged)
  841.                   {
  842.                   IsChanged = FALSE;
  843.                   if (IDNO == (MessageBox(hdlg, "Current record changed. Abandon?",
  844.                                rgpsz[IDS_CAPTION],
  845.                                MB_ICONQUESTION | MB_YESNO)))
  846.                       return (TRUE);
  847.  
  848.                   }
  849.                IsChanged = FALSE;
  850.  
  851.                // skip unless eof; ignore deleted records
  852.                while (TRUE)
  853.                   {
  854.                   vxSkip(1L);
  855.                   if (vxEof())
  856.                      break;
  857.                   if (!vxDeleted())
  858.                      break;
  859.                   }
  860.  
  861.                if (vxEof())
  862.                   {
  863.                   MessageBeep(0);
  864.                   SetDlgItemText(hdlg, IDD_STAT, "End of file");
  865.                   vxBottom();
  866.                   RecNum = vxRecNo();
  867.                   }
  868.                else
  869.                   {
  870.                   RecNum = vxRecNo();
  871.                   wsprintf(szBuffer, "Skipped to record %ld", RecNum);
  872.                   SetDlgItemText(hdlg, IDD_STAT, (LPSTR)szBuffer);
  873.                   }
  874.  
  875.                lstrcpy(szBuffer, (LPSTR)vxField("category"));
  876.                vxbTrim(szBuffer, sizeof(szBuffer));
  877.                SetDlgItemText(hdlg, IDD_TYPE, (LPSTR)szBuffer);
  878.  
  879.                lstrcpy(szBuffer, (LPSTR)vxField("catname"));
  880.                vxbTrim(szBuffer, sizeof(szBuffer));
  881.                SetDlgItemText(hdlg, IDD_DESC, (LPSTR)szBuffer);
  882.  
  883.                RetVal = BROWSE_EDIT;
  884.  
  885.                hwndDI = GetDlgItem(hdlg, IDD_SAVE);
  886.                EnableWindow(hwndDI, TRUE);
  887.                hwndDI = GetDlgItem(hdlg, IDD_CANCEL);
  888.                EnableWindow(hwndDI, TRUE);
  889.                hwndDI = GetDlgItem(hdlg, IDD_ADD);
  890.                EnableWindow(hwndDI, TRUE);
  891.                hwndDI = GetDlgItem(hdlg, IDD_DELETE);
  892.                EnableWindow(hwndDI, TRUE);
  893.  
  894.                // set focus to code
  895.                hwndDI = GetDlgItem(hdlg, IDD_TYPE);
  896.                SetFocus(hwndDI);
  897.                return (FALSE);
  898.  
  899.  
  900.             /* *********** */
  901.             /* prev button */
  902.             /* *********** */
  903.             case IDD_PREV:
  904.                // first test if current rec has changed
  905.                for (j=IDD_TYPE; j<IDD_DESC; j++)
  906.                   if (SendDlgItemMessage(hdlg, j, EM_GETMODIFY, 0, 0L))
  907.                      IsChanged = TRUE;
  908.                if (IsChanged)
  909.                   {
  910.                   IsChanged = FALSE;
  911.                   if (IDNO == (MessageBox(hdlg, "Current record changed. Abandon?",
  912.                                rgpsz[IDS_CAPTION],
  913.                                MB_ICONQUESTION | MB_YESNO)))
  914.                       return (TRUE);
  915.  
  916.                   }
  917.                IsChanged = FALSE;
  918.  
  919.                // skip unless bof; ignore deleted records
  920.                while (TRUE)
  921.                   {
  922.                   vxSkip(-1L);
  923.                   if (vxBof())
  924.                      break;
  925.                   if (!vxDeleted())
  926.                      break;
  927.                   }
  928.  
  929.                if (vxBof())
  930.                   {
  931.                   MessageBeep(0);
  932.                   SetDlgItemText(hdlg, IDD_STAT, "Beginning of file");
  933.                   vxTop();
  934.                   RecNum = vxRecNo();
  935.                   }
  936.                else
  937.                   {
  938.                   RecNum = vxRecNo();
  939.                   wsprintf(szBuffer, "Skipped to record %ld", RecNum);
  940.                   SetDlgItemText(hdlg, IDD_STAT, (LPSTR)szBuffer);
  941.                   }
  942.  
  943.                // load data
  944.                lstrcpy(szBuffer, (LPSTR)vxField("category"));
  945.                vxbTrim(szBuffer, sizeof(szBuffer));
  946.                SetDlgItemText(hdlg, IDD_TYPE, (LPSTR)szBuffer);
  947.  
  948.                lstrcpy(szBuffer, (LPSTR)vxField("catname"));
  949.                vxbTrim(szBuffer, sizeof(szBuffer));
  950.                SetDlgItemText(hdlg, IDD_DESC, (LPSTR)szBuffer);
  951.  
  952.                RetVal = BROWSE_EDIT;
  953.  
  954.                // reset buttons
  955.                hwndDI = GetDlgItem(hdlg, IDD_SAVE);
  956.                EnableWindow(hwndDI, TRUE);
  957.                hwndDI = GetDlgItem(hdlg, IDD_CANCEL);
  958.                EnableWindow(hwndDI, TRUE);
  959.                hwndDI = GetDlgItem(hdlg, IDD_ADD);
  960.                EnableWindow(hwndDI, TRUE);
  961.                hwndDI = GetDlgItem(hdlg, IDD_DELETE);
  962.                EnableWindow(hwndDI, TRUE);
  963.  
  964.                // set focus to code
  965.                hwndDI = GetDlgItem(hdlg, IDD_TYPE);
  966.                SetFocus(hwndDI);
  967.                return (FALSE);
  968.  
  969.  
  970.             /* ************* */
  971.             /* browse button */
  972.             /* ************* */
  973.             case IDD_BROWSE:
  974.                // first test if current rec has changed
  975.                for (j=IDD_TYPE; j<IDD_DESC; j++)
  976.                   if (SendDlgItemMessage(hdlg, j, EM_GETMODIFY, 0, 0L))
  977.                      IsChanged = TRUE;
  978.                if (IsChanged)
  979.                   {
  980.                   IsChanged = FALSE;
  981.                   if (IDNO == (MessageBox(hdlg, "Current record changed. Abandon?",
  982.                                rgpsz[IDS_CAPTION],
  983.                                MB_ICONQUESTION | MB_YESNO)))
  984.                       return (TRUE);
  985.  
  986.                   }
  987.                RetVal = BROWSE_USER;
  988.                EndDialog(hdlg, TRUE);
  989.                return (TRUE);
  990.  
  991.  
  992.             /* *********** */
  993.             /* exit button */
  994.             /* *********** */
  995.             case IDD_EXIT:
  996.                // first test if current rec has changed
  997.                for (j=IDD_TYPE; j<IDD_DESC; j++)
  998.                   if (SendDlgItemMessage(hdlg, j, EM_GETMODIFY, 0, 0L))
  999.                      IsChanged = TRUE;
  1000.                if (IsChanged)
  1001.                   {
  1002.                   IsChanged = FALSE;
  1003.                   if (IDNO == (MessageBox(hdlg, "Current record changed. Abandon?",
  1004.                                rgpsz[IDS_CAPTION],
  1005.                                MB_ICONQUESTION | MB_YESNO)))
  1006.                       return (TRUE);
  1007.  
  1008.                   }
  1009.                RetVal = 0;           // clear RetVal before return
  1010.                vxWindowDereg(hdlg);  // deregister window
  1011.                EndDialog(hdlg, TRUE);
  1012.                return (TRUE);
  1013.             }
  1014.          }
  1015.  
  1016.       default:
  1017.          break;
  1018.       }
  1019.       return (FALSE);
  1020.    }
  1021.  
  1022.  
  1023.  
  1024. /* ************************************************************
  1025.  * HLoadAppStrings
  1026.  *
  1027.  * Purpose:
  1028.  *  Allocates FIXED local memory and reads the applications
  1029.  *  string resources into that memory.  Each string's pointer
  1030.  *  is available with rgpsz[i] where i is the ID value of the
  1031.  *  string.  The strings must have sequential IDs.
  1032.  *
  1033.  * Parameters:
  1034.  *  none
  1035.  *
  1036.  * Return Value:
  1037.  *  HANDLE    Handle to the local memory.  NULL if memory could
  1038.  *            not be allocated.
  1039.  *
  1040.  * ************************************************************ */
  1041.  
  1042. HANDLE NEAR PASCAL HLoadAppStrings(void)
  1043.     {
  1044.     HANDLE      hLocalMem;
  1045.     char NEAR   *pch;
  1046.     WORD        cchUsed = 0;
  1047.     WORD        cch;
  1048.     short       i;
  1049.  
  1050.     /*
  1051.      * Allocate memory and load strings.  NOTE!  The LPTR style
  1052.      * specifies FIXED memory.  This should not be a big deal
  1053.      * since this is an early allocation into the local heap.
  1054.      * But it should be watched if the number of strings becomes
  1055.      * large.
  1056.      */
  1057.     hLocalMem = LocalAlloc(LPTR, CSTRINGS*CCHSTRINGMAX);
  1058.  
  1059.     if (hLocalMem == NULL)
  1060.         return (HANDLE)NULL;
  1061.  
  1062.     /*
  1063.      * This operation is only valid for FIXED memory.  Otherwise use
  1064.      * LocalLock.
  1065.      */
  1066.     pch = (char *)hLocalMem;
  1067.  
  1068.     /*
  1069.      * Load the strings into the memory and retain the specific
  1070.      * pointer to that string.
  1071.      */
  1072.     for (i = 0; i < CSTRINGS; i++)
  1073.         {
  1074.         cch = LoadString(hgInst, i, (LPSTR)(pch + cchUsed), CCHSTRINGMAX - 1);
  1075.         rgpsz[i] = (char *)(pch + cchUsed);
  1076.  
  1077.         /*
  1078.          * One is added to cch to include a NULL.  The memory was ZEROINITed
  1079.          * on allocation so by skipping a byte we get the NULL.
  1080.          */
  1081.         cchUsed += (cch + 1);
  1082.         }
  1083.  
  1084.     /*
  1085.      * It is assumed that no string is over CCHSTRINGMAX, and therefore
  1086.      * not all the allocated memory was used. Therefore LocalReAlloc
  1087.      * will only SHRINK the block, never expand it.  So if it fails, there's
  1088.      * no problem--all the strings are still there, with some wasted
  1089.      * space.
  1090.      */
  1091.     LocalReAlloc(hLocalMem, cchUsed+1, LPTR);
  1092.  
  1093.     return hLocalMem;
  1094.     }
  1095.  
  1096. /*
  1097.  ┌──────────────────────────────────────────────────────────────────────────┐
  1098.  │ END                                                                      │
  1099.  └──────────────────────────────────────────────────────────────────────────┘
  1100. */
  1101.