home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bde / inventry.pak / INV_MAIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  78.4 KB  |  2,257 lines

  1. // BDE - (C) Copyright 1994 by Borland International
  2.  
  3. #include "inventry.h"
  4.  
  5. #define FILEHANDLESNEEDED 40
  6.  
  7. //=================================================================
  8. //  Function:
  9. //          WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  10. //
  11. //  Input:  hInstance       - The handle that represents the
  12. //                              applications unique instance ID.
  13. //          hPrevInstance   - Indicates if this is the first instance
  14. //                              of the app.
  15. //          lpCmdLine       - Command line parameters (up to the app
  16. //                              to parse).
  17. //          nCmdShow        - TRUE = Show as non-icon application
  18. //
  19. //  Return: ???
  20. //
  21. //  Description:
  22. //          This is the application entry point for the
  23. //          Windows driver. It will set up the app, init
  24. //          the Windows instance, process all event driven
  25. //          messages, and clean up the suite prior to
  26. //          returning to Windows.
  27. //=================================================================
  28. int _pascal
  29. WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
  30.          int nCmdShow)
  31. {
  32.     MSG     msg;
  33.  
  34.     // Used to avoid a warning.
  35.     lpCmdLine = lpCmdLine;
  36.  
  37.     // Register CTL3D
  38.     Ctl3dRegister(hInstance);
  39.     Ctl3dAutoSubclass(hInstance);
  40.     Ctl3dColorChange();
  41.  
  42.     // Make this a single instance program
  43.     if (hPrevInstance)
  44.     {
  45.         MessageBox(GetFocus(), "This application is already running!",
  46.                    "Inventory Program", MB_OK | MB_ICONHAND);
  47.         return FALSE;
  48.     }
  49.  
  50.     // Start the application
  51.     hInst = hInstance;
  52.     if (InitApp(nCmdShow) == FALSE)
  53.     {
  54.         return FALSE;
  55.     }
  56.  
  57.     // Process all event driven messages...
  58.     while (GetMessage(&msg, NULL, NULL, NULL))
  59.     {
  60.         if (hMainWnd == 0 || !IsDialogMessage(hMainWnd, &msg))
  61.         {
  62.             TranslateMessage(&msg);
  63.             DispatchMessage(&msg);
  64.         }
  65.     }
  66.  
  67.     // Unregister CTL3D
  68.     Ctl3dUnregister(hInstance);
  69.     
  70.     return msg.wParam;
  71. }
  72.  
  73. //====================================================================
  74. //  Function:
  75. //          InitApp(int nCmdShow)
  76. //
  77. //  Input:  nCmdShow    - If the Window should be visible
  78. //
  79. //  Return: TRUE - Init worked
  80. //          FALSE - Init failed
  81. //
  82. //  Description:
  83. //          Create the application window & init any default
  84. //          of the main window.
  85. //====================================================================
  86. BOOL
  87. InitApp (int nCmdShow)
  88. {
  89.     WNDCLASS    wc;
  90.     char        szWindowName[] = "Inventory";
  91.     char        szMessage[(DBIMAXMSGLEN * 2) + 1];
  92.     char        szRelativeTblDirectory[DBIMAXPATHLEN+1];
  93.     unsigned    uCount;
  94.  
  95.     // Init the application & create the needed windows
  96.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  97.     wc.lpfnWndProc   = MainDlgProc;
  98.     wc.cbClsExtra    = 0;
  99.     wc.cbWndExtra    = DLGWINDOWEXTRA;
  100.     wc.hInstance     = hInst;
  101.     wc.hIcon         = LoadIcon(hInst, MAKEINTRESOURCE(9999));
  102.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  103.     wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  104.     wc.lpszMenuName  = NULL;
  105.     wc.lpszClassName = szWindowName;
  106.  
  107.     // Register the class
  108.     if(!RegisterClass(&wc))
  109.     {
  110.         MessageBox(NULL, "RegisterClass failed!",  "System Error",
  111.                    MB_OK | MB_ICONHAND);
  112.         return FALSE;
  113.     }
  114.  
  115.     // Increase the number of file handles that are available to the
  116.     // system.  
  117.     uCount = SetHandleCount(FILEHANDLESNEEDED);
  118.     if (uCount < FILEHANDLESNEEDED)
  119.     {
  120.         MessageBox(NULL, "Not enough file handles available. 'Set files=40' in"
  121.                    " CONFIG.SYS.",  "System Error", MB_OK | MB_ICONHAND);
  122.         return FALSE;
  123.     }
  124.  
  125.     // Get the directory which contains the tables. 
  126.     GetPrivateProfileString("INVENTRY", "TblDir",
  127.                             "..\\..\\TABLES",
  128.                             (LPSTR)szRelativeTblDirectory,
  129.                             sizeof(szRelativeTblDirectory),
  130.                             "bde.ini");
  131.  
  132.     // Create a fully qualified pathname for the table directory
  133.     if (MakeFullPath(szTblDirectory, szRelativeTblDirectory))
  134.     {
  135.         sprintf(szMessage,"Table Directory does not exist: %s."
  136.                 "\r\nPlease check BDE.INI in the Windows directory.",
  137.                 szTblDirectory);
  138.         MessageBox(NULL, szMessage,  "System Error", MB_OK | MB_ICONHAND);
  139.  
  140.         return FALSE;
  141.     }
  142.  
  143.     // Get the private directory. 
  144.     GetPrivateProfileString("INVENTRY", "PrivateDir",
  145.                             ".",
  146.                             (LPSTR)szRelativeTblDirectory,
  147.                             sizeof(szRelativeTblDirectory),
  148.                             "bde.ini");
  149.  
  150.     // Create a fully qualified pathname for the table directory
  151.     if (MakeFullPath(szPrivDirectory, szRelativeTblDirectory))
  152.     {
  153.         sprintf(szMessage,"Private Directory does not exist: %s."
  154.                 "\r\nPlease check BDE.INI in the Windows directory.",
  155.                 szPrivDirectory);
  156.         MessageBox(NULL, szMessage,  "System Error", MB_OK | MB_ICONHAND);
  157.  
  158.         return FALSE;
  159.     }
  160.         
  161.     // Create the dialog that serves as the main window
  162.     hMainWnd = CreateDialog(hInst, "MainDlg", 0, NULL);
  163.     if (hMainWnd == NULL)
  164.     {
  165.         MessageBox(NULL, "CreateDialog failed!",  "System Error",
  166.                    MB_OK | MB_ICONHAND);
  167.         return(FALSE);
  168.     }
  169.  
  170.     _wpOrigWndProc = SubClassWindow(GetDlgItem(hMainWnd, IDE_COMMENTS),
  171.                                     EditSubClassProc);
  172.  
  173.     ShowWindow(hMainWnd, nCmdShow);
  174.  
  175.     
  176.     return TRUE;
  177. }
  178.  
  179. // ===============================================================
  180. //  Function:
  181. //          MainDlgProc(hWnd, msg, wParam, lParam);
  182. //
  183. //  Input:  hWnd        - Handle to the Window
  184. //          msg         - Message to Process
  185. //          wParam      - The Word parameter (if any)
  186. //          lParam      - The Double Word parameter (if any)
  187. //
  188. //  Return: Depends on the message
  189. //
  190. //  Description:
  191. //          This routine will process all messaged for the primary
  192. //          application window. Included in this are all menu
  193. //          commands.
  194. // ===============================================================
  195. LRESULT CALLBACK
  196. MainDlgProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  197. {
  198.     DLGPROC lpProc;           // used for createing all the dialog boxes.
  199.     pCHAR   TableInfo = NULL; // used for the full name of the table.
  200.     UINT16  RangeVal = 0;     // Used for the Range dialog box return value.
  201.  
  202.     // The following variables are static so that the original state that
  203.     // is passed into the window proc is kept after we fall through it.
  204.     static  hDBIDb      hDb; // used for the database handle.
  205.     static  hDBICur     hCur; // used for the table handle.
  206.     long    Ret = FALSE;
  207.     HBRUSH  hBrush;
  208.     HWND    hwnd;    
  209.  
  210.     hErrorWnd = hWnd;
  211.     switch (msg)
  212.     {
  213.         case WM_CREATE:
  214.             PostMessage(hWnd, WM_DBIINIT, 0, 0);
  215.             break;
  216.  
  217.         case WM_DBIINIT:
  218.             hwnd = GetWindow(hWnd, GW_CHILD);
  219.             while (hwnd != NULL)
  220.             {
  221.                 Ctl3dSubclassCtl(hwnd);
  222.                 hwnd = GetWindow(hwnd, GW_HWNDNEXT);
  223.             }
  224.             // Check to see if the engine could not initialize.
  225.             if(DbInit()!= DBIERR_NONE)
  226.             {
  227.                 // There was an error so shut down.
  228.                 PostQuitMessage(0);
  229.                 break;
  230.             }
  231.  
  232.             // Get memory to hold the full table name with path.
  233.             TableInfo = (pCHAR)malloc(DBIMAXPATHLEN + 1);
  234.  
  235.             // Check if the table exists or if it is empty.
  236.             if(!TableExist(TableInfo))
  237.             {
  238.                 // Since the table is either empty or does not exist we
  239.                 //   need to recreate it by overwriting the old table or
  240.                 //   creating a new one.
  241.                 if (CreateTable(&hDb, &hCur))
  242.                 {
  243.                     return FALSE;
  244.                 }
  245.  
  246.                 // Fill the table with data from the resource file.
  247.                 FillTable(hCur, &hDb);
  248.             }
  249.  
  250.             // Get the database and cursor handles.
  251.             GetTable(&hDb, &hCur);
  252.             if(hCur==NULL)
  253.             {
  254.                 WinMsg("Error opening tables!", MB_ICONHAND, MB_OK);
  255.                 PostMessage(hWnd, WM_DESTROY, 0, 0L);
  256.             }
  257.             else
  258.             {
  259.                 SetIndex(&hCur, 0);
  260.                 // When we move to the top we are sitting
  261.                 //   the first record. Therefore, we need to move one
  262.                 //   record forward to be sitting on the first record,
  263.                 //   which we need to do to display the record using
  264.                 //   the DisplayRecord function.
  265.                 GoTop(hCur, TRUE);
  266.                 free((void*)TableInfo);
  267.  
  268.                 // Display the current record.
  269.                 PostMessage(hWnd, WM_DISPLAY, 0, 0L);
  270.                 ShowWindow(hWnd, SW_SHOW);
  271.             }
  272.             break;
  273.  
  274.         case WM_CTLCOLOR:
  275.             hBrush = Ctl3dCtlColorEx(msg, wParam, lParam);
  276.             if (hBrush != (HBRUSH)0)
  277.             {
  278.                 return (long)(WORD)hBrush;
  279.             }
  280.             else
  281.             {
  282.                 return DefWindowProc(hWnd, msg, wParam, lParam);
  283.             }
  284.  
  285.         case WM_SYSCOLORCHANGE:
  286.             Ctl3dColorChange();
  287.             return TRUE;
  288.  
  289.         case WM_NCPAINT:
  290.         case WM_NCACTIVATE:
  291.         case WM_SETTEXT:
  292.             return Ctl3dDlgFramePaint(hWnd, msg, wParam, lParam);
  293.  
  294.         case WM_SETFOCUS:
  295.             SetItemFocus();
  296.             break;
  297.  
  298.         case WM_DISPLAY:
  299.             // Check the navigational buttons and disable or enable each of
  300.             //   them based upon the position of the cursor.
  301.             CheckButtons(hCur);
  302.  
  303.             // Display the current record.
  304.             DisplayTable(hCur);
  305.  
  306.             // Setup the edit controls so that the user can only enter the
  307.             //   correct amount of information.
  308.             SetupEdits();
  309.             break;
  310.  
  311.         case WM_COMMAND:
  312.             switch(wParam)
  313.             {
  314.                 // These messages are two buttons that are not visible
  315.                 //   until the user sends an ID_ADD_REC message by
  316.                 //   pressing the add button or choosing the add menu
  317.                 //   option.  Once that is done the OK button will stay
  318.                 //   dimmed until the user has input valid data.  Which
  319.                 //   consists of some first and last name and avalid date.
  320.                 case IDOK:
  321.  
  322.                     // Add the record.
  323.                     SaveRec(hCur, TRUE);
  324.  
  325.                     // Reset the window's normal look.
  326.                     EndNewRec(hCur);
  327.                     SetItemFocus();
  328.                     break;
  329.  
  330.                 case IDCANCEL:
  331.                     // Check if data has been entered and ask if the user
  332.                     // wants  to lose the entered data.
  333.                     if(CanContinue("Data not saved cancel anyway?", IDOK))
  334.                     {
  335.                         // Set the window's normal look and cancel the data.
  336.                         EndNewRec(hCur);
  337.                     }
  338.                     break;
  339.  
  340.                 // Check all the edits at once for any changes.  Then check
  341.                 // if the data is valid.
  342.                 case IDE_ITEM:
  343.                 case IDE_ITEMID:
  344.                 case IDE_NOINSTOCK:
  345.                 case IDE_BUILDING:
  346.                 case IDE_COST:
  347.                 case IDE_ORDERDATE:
  348.                 case IDE_COMMENTS:
  349.                     if (HIWORD(lParam) == EN_UPDATE)
  350.                     {
  351.                         // Checks if the data is valid.
  352.                         if(verified())
  353.                         {
  354.                             // Check what mode we are in.  If we are
  355.                             //   adding a new person to the table then
  356.                             //   enable the OK button.
  357.                             if(NewRecMode)
  358.                             {
  359.                                 EnableWindow(GetDlgItem(hMainWnd, IDOK),
  360.                                              TRUE);
  361.                             }
  362.                             else
  363.                             {
  364.                                 // Otherwise enable the Commit and Undo
  365.                                 //   buttons, that are visible only when
  366.                                 //   we are NOT adding a new person.
  367.                                 SetControl(ID_MOD_REC, TRUE);
  368.                                 SetControl(ID_UNDO_REC, TRUE);
  369.                             }
  370.                         }
  371.                         else
  372.                         {
  373.                             // If the data is not valid and we are adding
  374.                             //   a new person.
  375.                             if(NewRecMode)
  376.                             {
  377.                                 // Disable the OK button, so that the
  378.                                 //   user cannot save the invalid data.
  379.                                 EnableWindow(GetDlgItem(hMainWnd, IDOK),
  380.                                              FALSE);
  381.                             }
  382.                             else
  383.                             {
  384.                                 // The data is not valid and we are NOT
  385.                                 //   adding a new person.  Therefore,
  386.                                 //   disable the Commit button.  BUT, we
  387.                                 //   still enable the Undo button so that
  388.                                 //   the user can undo the changes.
  389.                                 SetControl(ID_MOD_REC, FALSE);
  390.                                 SetControl(ID_UNDO_REC, TRUE);
  391.                             }
  392.                         }
  393.                     }
  394.                     break;
  395.  
  396.                 // Display the About dialog box.
  397.                 case ID_ABOUT:
  398.                     lpProc = (DLGPROC)MakeProcInstance((FARPROC)AboutDlg,
  399.                                                        hInst);
  400.                     DialogBox(hInst, "AboutDlg", hMainWnd, lpProc);
  401.                     FreeProcInstance((FARPROC) lpProc);
  402.                     SetItemFocus();
  403.                     UpdateWindow (hWnd);
  404.                     break;
  405.  
  406.                 // Display the Order dialog box.
  407.                 case ID_ORDER:
  408.                     lpProc = (DLGPROC)MakeProcInstance((FARPROC) OrderDlg,
  409.                                                        hInst);
  410.  
  411.                     // Since we have to change indexes within the Order
  412.                     //   Proc we need to pass the pointer to the cursor
  413.                     //   handle.
  414.                     if(DialogBoxParam(hInst, "OrderDlg", hMainWnd, lpProc,
  415.                                       (LONG)(void far*)&hCur)==IDOK)
  416.                     {
  417.                         // Redisplay the record and check the naviagtional
  418.                         //   buttons as the record may have changed position
  419.                         //   with the new index.
  420.                         DisplayTable(hCur);
  421.                         CheckButtons(hCur);
  422.                     }
  423.                     FreeProcInstance((FARPROC) lpProc);
  424.                     SetItemFocus();
  425.                     UpdateWindow (hWnd);
  426.                     break;
  427.  
  428.                 // Display the Range dialog box.
  429.                 case ID_RANGE:
  430.                     lpProc = (DLGPROC)MakeProcInstance((FARPROC)RangeDlg,
  431.                                                        hInst);
  432.                     // Since we have to change indexes within the Range
  433.                     //   Proc we need to pass the pointer to the cursor
  434.                     //   handle.
  435.                     RangeVal = DialogBoxParam(hInst, "RangeDlg", hMainWnd,
  436.                                               lpProc,
  437.                                               (LONG)(void far*)&hCur);
  438.                     if(RangeVal == IDOK)
  439.                     {
  440.                         // Set the global variable RangeSet to TRUE as we
  441.                         //   did set a range for the present cursor.
  442.                         RangeSet = TRUE;
  443.  
  444.                         // Display the first record of this range and set
  445.                         //   the navigational controls.
  446.                         DisplayTable(hCur);
  447.                         CheckButtons(hCur);
  448.  
  449.                         // Enable the Clear Range menu option.
  450.                         EnableMenuItem(GetMenu(hMainWnd), ID_CLEAR_RANGE,
  451.                                        MF_ENABLED);
  452.                     }
  453.                     else
  454.                     {
  455.                         if(RangeVal == RANGEERROR)                       
  456.                         {
  457.                             // Reset the range as the attempted range was
  458.                             //   invalid.
  459.                             PostMessage(hWnd, WM_COMMAND, ID_CLEAR_RANGE,
  460.                                         0L);
  461.                         }
  462.                         else
  463.                         {
  464.                             // Otherwise, Cancel was pressed so just reset
  465.                             //   focus to the Item edit control.
  466.                             SetItemFocus();
  467.                         }
  468.                     }
  469.                     FreeProcInstance((FARPROC) lpProc);
  470.                     break;
  471.  
  472.                 // This menu option is enabled ONLY after a range has been
  473.                 //   set.
  474.                 case ID_CLEAR_RANGE:
  475.  
  476.                     // Reset the range.
  477.                     ResetRange(hCur);
  478.  
  479.                     // Go to the first record in the table.
  480.                     GoTop(hCur, TRUE);
  481.  
  482.                     // Disable the Reset Range menu option.
  483.                     EnableMenuItem(GetMenu(hMainWnd), ID_CLEAR_RANGE,
  484.                                    MF_GRAYED);
  485.  
  486.                     // Set the global variable to FALSE.
  487.                     RangeSet = FALSE;
  488.  
  489.                     // Redisplay the new range and set the navigational
  490.                     //   controls.
  491.                     DisplayTable(hCur);
  492.                     CheckButtons(hCur);
  493.                     break;
  494.  
  495.                 // Display the Search dialog box.
  496.                 case ID_SEARCH:
  497.                     lpProc = (DLGPROC)MakeProcInstance((FARPROC) SearchDlg,
  498.                                                        hInst);
  499.                     // Since we have to change indexes within the Search
  500.                     //   Proc we need to pass the pointer to the cursor
  501.                     //   handle.
  502.                     DialogBoxParam(hInst, "SearchDlg", hMainWnd, lpProc,
  503.                                    (LONG)(void far*)&hCur);
  504.  
  505.                     // Move one record past the crack that the Search
  506.                     // function leaves you at.
  507.                     GetNextRec(hCur);
  508.  
  509.                     FreeProcInstance((FARPROC) lpProc);
  510.  
  511.                     // Redisplay the new range and set the navigational
  512.                     //   controls.
  513.                     DisplayTable(hCur);
  514.                     CheckButtons(hCur);
  515.                     break;
  516.  
  517.                 case ID_ADD_REC:
  518.                     // Change the "mode" of the main window so as to allow
  519.                     //   for a new name to be entered. This "mode" will
  520.                     //   not be deactivated until the IDOK and IDCANCEL
  521.                     //   messages are processed in this message switch!
  522.                     ChangeEntryMode();
  523.  
  524.                     // Clear the edit controls to allow the user to input
  525.                     //   the new data easily.
  526.                     ClearDlg();
  527.  
  528.                     // Enable the Cancel button.
  529.                     EnableWindow(GetDlgItem(hMainWnd, IDCANCEL), TRUE);
  530.  
  531.                     // Disable the OK button until valid data has been
  532.                     //   input.
  533.                     EnableWindow(GetDlgItem(hMainWnd, IDOK), FALSE);
  534.  
  535.                     // Put the current date into the Date Edit control.
  536.                     SetDefaultDate();
  537.                     SetItemFocus();
  538.                     break;
  539.  
  540.                 case ID_NEXT_REC:
  541.                     // Move one record forward.
  542.                     MoveRec(hCur, NEXT_REC);
  543.                     break;
  544.  
  545.                 case ID_PREV_REC:
  546.                     // Move back one record.
  547.                     MoveRec(hCur, PREV_REC);
  548.                     break;
  549.  
  550.                 case ID_FIRST_REC:
  551.                     // Move to the first record in the table.
  552.                     MoveRec(hCur, TOP);
  553.                     break;
  554.  
  555.                 case ID_LAST_REC:
  556.                     // Move to the last record in the table.
  557.                     MoveRec(hCur, BOTTOM);
  558.                     break;
  559.  
  560.                 case ID_MOD_REC:
  561.                     // This is sent when the Commit button or the Commit
  562.                     //   Changes menu option are chosen.
  563.                     if(CanContinue("Do you want to modify this record?",
  564.                                    ID_UNDO_REC))
  565.                     {
  566.                         // Modify the record.
  567.                         SaveRec(hCur, FALSE);
  568.  
  569.                         // Set the navigational controls and disable the
  570.                         //   Undo and Commit controls.
  571.                         CheckButtons(hCur);
  572.                         SetControl(ID_MOD_REC, FALSE);
  573.                         SetControl(ID_UNDO_REC, FALSE);
  574.                     }
  575.                     break;
  576.  
  577.                 case ID_DEL_REC:
  578.                     // This message is sent upon pressing the Delete
  579.                     //   button, or by choosing the Delete menu option.
  580.                     if(WinMsg("Do you want to delete this record?",
  581.                               MB_ICONHAND, MB_YESNO)== IDYES)
  582.                     {
  583.                         // Delete the record.
  584.                         DeleteRecord(hCur);
  585.                     }
  586.                     break;
  587.  
  588.                 case ID_UNDO_REC:
  589.                     // This message is sent by the Undo button, or by the
  590.                     //   Undo menu option.  First we check the status of
  591.                     //   the Undo button and pass the string to the
  592.                     //   CanContinue function.
  593.                     if(CanContinue("All changes will be lost - Undo"
  594.                                    " anyway?", ID_UNDO_REC))
  595.                     {
  596.                         // Redisplay the original record's data.
  597.                         PostMessage(hWnd, WM_DISPLAY, 0, 0L);
  598.                     }
  599.                     break;
  600.  
  601.                 case ID_EXIT:
  602.                     // Quit the program.
  603.                     PostMessage(hWnd, WM_CLOSE, 0, 0L);
  604.                     break;
  605.  
  606.                 default:
  607.                     Ret = DefWindowProc(hWnd, msg, wParam, lParam);
  608.                     break;
  609.  
  610.             }
  611.             break;
  612.  
  613.         case WM_CLOSE:
  614.             // Check if there is unsaved data by checking if the Undo
  615.             // button is enabled.
  616.             if(CanContinue("Data not saved quit anyway?", ID_UNDO_REC))
  617.             {
  618.                 DestroyWindow(hWnd);
  619.             }
  620.             else
  621.             {
  622.                 // Do not quit the program.
  623.                 SetItemFocus();
  624.             }
  625.             break;
  626.  
  627.         case WM_DESTROY:
  628.             // Clean up - Close the Database and Exit IDAPI
  629.             CloseDb(&hDb);
  630.             DbExit();
  631.             PostQuitMessage(0);
  632.             break;
  633.  
  634.         default:
  635.             // Otherwise default to the DefWindowProc.
  636.             Ret = DefWindowProc(hWnd, msg, wParam, lParam);
  637.             break;
  638.     }
  639.     return(Ret);
  640. }
  641.  
  642. //======================================================================
  643. //  Function:
  644. //          EditSubClassProc(HWND hWnd, WORD msg, WORD wParam,
  645. //                           LONG lParam)
  646. //
  647. //  Input:  hWnd        - Handle to the Windwo
  648. //          msg         - Message to process
  649. //          wParam      - Word Parameter
  650. //          lParam      - Double Word Parameter
  651. //
  652. //  Return: It returns the result of the procedure.  It can return the
  653. //          result of the original edit control if the WM_CHAR is not
  654. //          a tab character.
  655. //
  656. //  Description:
  657. //          This routine will process all I/O for the Comments edit
  658. //          control. It does this by first checking if the tab key was
  659. //          hit inside of the comment edit control.  If it was it moves
  660. //          control to the next control item and then does NOT let the
  661. //          original edit control process the message.  However, if the
  662. //          WM_CHAR is not a tab then it lets the original edit control
  663. //          process the message.
  664. //======================================================================
  665. long FAR _pascal _export
  666. EditSubClassProc (HWND hWnd, WORD msg, WORD wParam, LONG lParam)
  667. {
  668.     LRESULT lResult = 0;
  669.     BOOL    fCallOrigWndProc = TRUE;
  670.  
  671.     switch (msg)
  672.     {
  673.         case WM_CHAR:
  674.             if(wParam == '\t')
  675.             {
  676.                 if(GetKeyState(VK_SHIFT)<0)
  677.                 {
  678.                     SetFocus(GetDlgItem(hMainWnd, IDE_ORDERDATE));
  679.                 }
  680.                 else
  681.                 {
  682.                     if(!NewRecMode)
  683.                     {
  684.                         SetFocus(GetDlgItem(hMainWnd, ID_ORDER));
  685.                         SendMessage(GetDlgItem(hMainWnd, ID_ORDER),
  686.                                     BM_SETSTYLE, (UINT16)BS_DEFPUSHBUTTON,
  687.                                     1L);
  688.                     }
  689.                     else
  690.                     {
  691.                         SetFocus(GetDlgItem(hMainWnd, IDOK));
  692.                         SendMessage(GetDlgItem(hMainWnd, IDOK),
  693.                                     BM_SETSTYLE, (UINT16)BS_DEFPUSHBUTTON,
  694.                                     1L);
  695.                     }
  696.                 }
  697.                 fCallOrigWndProc = FALSE;
  698.             }
  699.             break;
  700.     }
  701.  
  702.     if(fCallOrigWndProc)
  703.     {
  704.         lResult = CallWindowProc(_wpOrigWndProc, hWnd, msg, wParam,
  705.                                  lParam);
  706.     }
  707.     return lResult;
  708. }
  709.  
  710. //======================================================================
  711. //  Function:
  712. //          AboutDlg(HWND hWnd, WORD msg, WORD wParam, LONG lParam)
  713. //
  714. //  Input:  hWnd        - Handle to the Windwo
  715. //          msg         - Message to process
  716. //          wParam      - Word Parameter
  717. //          lParam      - Double Word Parameter
  718. //
  719. //  Return: TRUE -  Dialog Created.
  720. //          FALSE - Dialog Failed to create.
  721. //
  722. //  Description:
  723. //          This routine will process all I/O for the ABOUT dialog.
  724. //======================================================================
  725. BOOL FAR _pascal _export
  726. AboutDlg (HWND hWnd, WORD msg, WORD wParam, LONG lParam)
  727. {
  728.     BOOL    ret = FALSE;
  729.  
  730.     // Done to clear the unused warning.
  731.     lParam = lParam;
  732.  
  733.     switch (msg)
  734.     {
  735.         case WM_COMMAND:
  736.             switch (wParam)
  737.             {
  738.                 case IDOK:
  739.                 case IDCANCEL:
  740.                     ret = TRUE;
  741.                     EndDialog(hWnd, ret);
  742.                     break;
  743.             }
  744.             break;
  745.     }
  746.     return ret;
  747. }
  748.  
  749. //======================================================================
  750. //  Function:
  751. //          OrderDlg(HWND hWnd, WORD msg, WORD wParam, LONG lParam)
  752. //
  753. //  Input:  hWnd        - Handle to the Windwo
  754. //          msg         - Message to process
  755. //          wParam      - Word Parameter
  756. //          lParam      - Double Word Parameter
  757. //                          Also contains the pointer to the cursor during
  758. //                          the WM_INITDIALOG.
  759. //
  760. //  Return: TRUE -  The Index was set.
  761. //          FALSE - Index failed or user canceled the dilaog box.
  762. //
  763. //  Description:
  764. //          This routine will process all I/O for the dialog that will
  765. //          change the order  of the table (i.e. place an index).
  766. //======================================================================
  767. BOOL FAR _pascal _export
  768. OrderDlg (HWND hWnd, WORD msg, WORD wParam, LONG lParam)
  769. {
  770.     BOOL    ret = FALSE;        // Return value from IDAPI functions
  771.     static  phDBICur phCur;     // This is the pointer to the cursor of
  772.                                 //   the table.
  773.     static  UINT16 uStartIndex; // This will hold the original index
  774.                                 //   number.
  775.     UINT32  uIndex;             // Selected Index
  776.     UINT32  uSel;               // Item selected in ListBox
  777.  
  778.     hErrorWnd = hWnd;
  779.     switch (msg)
  780.     {
  781.         case WM_INITDIALOG:
  782.             phCur = (phDBICur)lParam;
  783.  
  784.             // Get the original index before entering this dialog box.
  785.             //   Then we fill the field drop-down list with all the
  786.             //   possible indexed fields.
  787.             uStartIndex=FillDropList(hWnd, *phCur, IDE_ORDER_COMBOBOX);
  788.             return TRUE;
  789.             
  790.         case WM_COMMAND:
  791.             switch (wParam)
  792.             {
  793.                 case IDE_ORDER_COMBOBOX:
  794.                     // Since the combobox is sorted we need to have a way
  795.                     //   to match the user's choice and the original place
  796.                     //   of that choice in the index array.  So we add an
  797.                     //   item data.
  798.                     switch(HIWORD(lParam))
  799.                     {
  800.                         case CBN_SELCHANGE:
  801.                             uSel=SendDlgItemMessage(hWnd,
  802.                                                     IDE_ORDER_COMBOBOX,
  803.                                                     CB_GETCURSEL, 0, 0L);
  804.                             uIndex=SendDlgItemMessage(hWnd,
  805.                                                       IDE_ORDER_COMBOBOX,
  806.                                                       CB_GETITEMDATA,
  807.                                                       (WPARAM)uSel, 0L);
  808.                             // Put the Index description in the static
  809.                             //   text box.
  810.                             SetWindowText(GetDlgItem(hWnd, IDE_ORDER_INFO),
  811.                                           IndexList[(UINT16)uIndex]);
  812.                             break;
  813.                     }
  814.                     break;
  815.                 case IDOK:
  816.                     // Now get the selected item and its item data.
  817.                     uSel=SendDlgItemMessage(hWnd, IDE_ORDER_COMBOBOX,
  818.                                             CB_GETCURSEL, 0, 0L);
  819.                     uIndex=SendDlgItemMessage(hWnd, IDE_ORDER_COMBOBOX,
  820.                                               CB_GETITEMDATA, (WPARAM)uSel,
  821.                                               0L);
  822.  
  823.                     // Check if it is the original index or a new index.
  824.                     if(uStartIndex != uIndex)
  825.                     {
  826.                         if(RangeSet)// If there was a range set - tell the
  827.                                     //   user that they are about to lose
  828.                                     //   it with the new index choice.
  829.                         {
  830.                             if(WinMsg("You will lose the current Range"
  831.                                       " settings do you want to change"
  832.                                       " indexes anyway?",
  833.                                       MB_ICONHAND, MB_YESNO)== IDYES)
  834.                             {
  835.                                 // Switch the index.
  836.                                 SetIndex(phCur, (UINT16)uIndex);
  837.  
  838.                                 // Disable the Reset Range menu option.
  839.                                 EnableMenuItem(GetMenu(hMainWnd),
  840.                                                ID_CLEAR_RANGE, MF_GRAYED);
  841.  
  842.                                 // Reset thge global RangeSet variable to
  843.                                 //   FALSE.
  844.                                 RangeSet = FALSE;
  845.                                 ret = TRUE;
  846.                             }
  847.                             else
  848.                             {
  849.                                 ret = FALSE;
  850.                             }
  851.                         }
  852.                         else
  853.                         {
  854.                             // Switch Index.
  855.                             SetIndex(phCur, (UINT16)uIndex);
  856.                             ret = TRUE;
  857.                         }
  858.                     }
  859.                     else
  860.                     {
  861.                         ret = FALSE;
  862.                     }
  863.                     EndDialog(hWnd, ret);
  864.                     break;
  865.  
  866.                 case IDCANCEL:
  867.                     EndDialog(hWnd, ret);
  868.                     ret = FALSE;
  869.                     break;
  870.             }
  871.             break;
  872.     }
  873.     return ret;
  874. }
  875.  
  876. //======================================================================
  877. //  Function:
  878. //          RangeDlg(HWND hWnd, WORD msg, WORD wParam, LONG lParam)
  879. //
  880. //  Input:  hWnd        - Handle to the Windwo
  881. //          msg         - Message to process
  882. //          wParam      - Word Parameter
  883. //          lParam      - Double Word Parameter
  884. //                          Also contains the pointer to the cursor during
  885. //                          the WM_INITDIALOG.
  886. //
  887. //  Return: TRUE -  The Range was set.
  888. //          FALSE - Range failed or user canceled the dilaog box.
  889. //
  890. //  Description:
  891. //          This routine will process all I/O for the dialog that will
  892. //          change the Range of the present cursor AND Index.
  893. //======================================================================
  894. BOOL FAR _pascal _export
  895. RangeDlg (HWND hWnd, WORD msg, WORD wParam, LONG lParam)
  896. {
  897.     BOOL    ret = FALSE;
  898.  
  899.     static  phDBICur phCur;  // Pointer to the cursor of the table.
  900.  
  901.     // Two Record structure pointers to pass to the SetRange function.
  902.     static  RecordType *pHighRec;
  903.     static  RecordType *pLowRec;
  904.     static  UINT16 uStartIndex; // Used to hold the original index.
  905.     BOOL    bLowInclude;        // Bool to include or not include low
  906.                                 //   value in range.
  907.     BOOL    bHighInclude;       // Bool to include or not include high
  908.                                 //   value in range.
  909.     UINT32  Ret;
  910.     UINT32  uIndex;
  911.     char    szString[220];
  912.  
  913.     // Used to hold the input string from the range edit control.
  914.     CHAR    Temp[FLDLENGTH];
  915.     UINT32  uSel;
  916.  
  917.     // Bools to know whether the low or high ranges were not entered.
  918.     BOOL    bLowEmpty=FALSE;
  919.     BOOL    bHighEmpty=FALSE;
  920.  
  921.     hErrorWnd = hWnd;
  922.     switch (msg)
  923.     {
  924.         case WM_INITDIALOG:
  925.             phCur = (phDBICur)lParam;  // Get the Cursor pointer.
  926.  
  927.             // Fill the combobox with the index names and get the present
  928.             //   index.
  929.             uStartIndex=FillDropList(hWnd, *phCur, IDE_RANGE_COMBO);
  930.  
  931.             // Allocate memory for the High and Low record structures.
  932.             if((pHighRec = (RecordType *) malloc(1 * sizeof(RecordType)))
  933.                == NULL)
  934.             {
  935.                 WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  936.                 return FALSE;
  937.             }
  938.             if((pLowRec = (RecordType *) malloc(1 * sizeof(RecordType)))
  939.                            == NULL)
  940.             {
  941.                 WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  942.                 return FALSE;
  943.             }
  944.  
  945.             // Clear the structures of any unwanted data.
  946.             memset(pLowRec, 0, sizeof(RecordType));
  947.             memset(pHighRec, 0, sizeof(RecordType));
  948.  
  949.             // Finally set the length of the input field to the appropriate
  950.             //   size based upon the present index.
  951.             SetFieldLength(hWnd, uStartIndex, IDE_LOWRANGE, IDE_HIGHRANGE,
  952.                            TRUE);
  953.             LoadString(hInst, IDS_RANGE, szString, 220);
  954.             SetDlgItemText(hWnd, IDS_RANGE_TEXT, (pCHAR)szString);
  955.             ret = TRUE;
  956.             break;
  957.  
  958.         case WM_COMMAND:
  959.             switch (wParam)
  960.             {
  961.                 case IDE_RANGE_COMBO:
  962.                     switch(HIWORD(lParam))
  963.                     {
  964.                         case CBN_SELCHANGE:
  965.                             // Add an item data to track the item in the
  966.                             // sorted listbox.
  967.                             uSel=SendDlgItemMessage(hWnd, IDE_RANGE_COMBO,
  968.                                             CB_GETCURSEL, 0, 0L);
  969.                             uIndex=SendDlgItemMessage(hWnd, IDE_RANGE_COMBO,
  970.                                                       CB_GETITEMDATA,
  971.                                                       (WPARAM)uSel, 0L);
  972.  
  973.                             // Get the text that was entered for that
  974.                             //   index the last time it was chosen.
  975.                             GetField(pLowRec, Temp, (UINT16)uIndex);
  976.                             SetWindowText(GetDlgItem(hWnd, IDE_LOWRANGE),
  977.                                           Temp);
  978.                             GetField(pHighRec, Temp, (UINT16)uIndex);
  979.                             SetWindowText(GetDlgItem(hWnd, IDE_HIGHRANGE),
  980.                                           Temp);
  981.  
  982.                             // Set the field length for the present index.
  983.                             SetFieldLength(hWnd, (UINT16)uIndex,
  984.                                            IDE_LOWRANGE, IDE_HIGHRANGE,
  985.                                            TRUE);
  986.                             ret = TRUE;
  987.                             break;
  988.                     }
  989.                     break;
  990.                 case IDE_LOWRANGE:
  991.                 case IDE_HIGHRANGE:
  992.                     switch(HIWORD(lParam))
  993.                     {
  994.                         case EN_KILLFOCUS:
  995.                             // Get the index and data.
  996.                             uSel=SendDlgItemMessage(hWnd, IDE_RANGE_COMBO,
  997.                                                     CB_GETCURSEL, 0, 0L);
  998.                             uIndex=SendDlgItemMessage(hWnd, IDE_RANGE_COMBO,
  999.                                                       CB_GETITEMDATA,
  1000.                                                       (WPARAM)uSel, 0L);
  1001.  
  1002.                             // Get the inputed range text and save that
  1003.                             //   in the record structure to display again.
  1004.                             GetDlgItemText(hWnd, IDE_LOWRANGE, Temp,
  1005.                                            FLDLENGTH);
  1006.                             PutField(pLowRec, Temp, (UINT16)uIndex);
  1007.                             GetDlgItemText(hWnd, IDE_HIGHRANGE, Temp,
  1008.                                            FLDLENGTH);
  1009.                             PutField(pHighRec, Temp, (UINT16)uIndex);
  1010.                             ret = TRUE;
  1011.                             break;
  1012.                     }
  1013.                     break;
  1014.                 case IDOK:
  1015.                     // Get the present state of the check boxes.
  1016.                     Ret = SendDlgItemMessage(hWnd, IDE_BM_LOW, BM_GETCHECK,
  1017.                                              0, 0L);
  1018.                     if(Ret == 1)
  1019.                     {
  1020.                         bLowInclude = TRUE;
  1021.                     }
  1022.                     else
  1023.                     {
  1024.                         bLowInclude = FALSE;
  1025.                     }
  1026.                     Ret = SendDlgItemMessage(hWnd, IDE_BM_HIGH, BM_GETCHECK,
  1027.                                              0, 0L);
  1028.                     if(Ret == 1)
  1029.                     {
  1030.                         bHighInclude = TRUE;
  1031.                     }
  1032.                     else
  1033.                     {
  1034.                         bHighInclude = FALSE;
  1035.                     }
  1036.  
  1037.                     // Clear the record structures, then fill the
  1038.                     //   appropriate fields in the record structures
  1039.                     //   with the range text.
  1040.                     memset(pLowRec, 0, sizeof(RecordType));
  1041.                     memset(pHighRec, 0, sizeof(RecordType));
  1042.                     uSel=SendDlgItemMessage(hWnd, IDE_RANGE_COMBO,
  1043.                                             CB_GETCURSEL, 0, 0L);
  1044.                     uIndex=SendDlgItemMessage(hWnd, IDE_RANGE_COMBO,
  1045.                                               CB_GETITEMDATA, (WPARAM)uSel,
  1046.                                               0L);
  1047.                     GetDlgItemText(hWnd, IDE_LOWRANGE, Temp, FLDLENGTH);
  1048.  
  1049.                     // If the range was left empty then set the bool to
  1050.                     //   TRUE.
  1051.                     if(strlen(Temp)==0)
  1052.                     {
  1053.                         bLowEmpty = TRUE;
  1054.                     }
  1055.  
  1056.                     // Put the text into the correct field of the
  1057.                     //   record structure, that is to be used by the
  1058.                     //   SetRange function.
  1059.                     PutField(pLowRec, Temp, (UINT16)uIndex);
  1060.                     GetDlgItemText(hWnd, IDE_HIGHRANGE, Temp, FLDLENGTH);
  1061.  
  1062.                     // If the range was left empty then set the bool to
  1063.                     //   TRUE.
  1064.                     if(strlen(Temp)==0)
  1065.                     {
  1066.                         bHighEmpty = TRUE;
  1067.                     }
  1068.  
  1069.                     // Put the text into the correct field of the
  1070.                     //   record structure, that is to be used by the
  1071.                     //   SetRange function.
  1072.                     PutField(pHighRec, Temp, (UINT16)uIndex);
  1073.                     if(uStartIndex != uIndex)
  1074.                     {
  1075.                         SetIndex(phCur, (UINT16)uIndex);
  1076.                     }
  1077.  
  1078.                     // Set the range.  If the function fails return FALSE.
  1079.                     if(SetRange(pHighRec, pLowRec, bHighInclude,
  1080.                                 bLowInclude, *phCur, bHighEmpty,
  1081.                                 bLowEmpty)==DBIERR_NONE)
  1082.                     {
  1083.                         if(AtEOF(*phCur))
  1084.                         {
  1085.                             MessageBox(hWnd, "No Records exist within the"
  1086.                                        " specified range. Resetting to"
  1087.                                        " original range.", "Range Error",
  1088.                                        MB_ICONHAND | MB_OK);
  1089.  
  1090.                             // Reset the range.
  1091.                             ResetRange(*phCur); // Reset the index.
  1092.                             SetIndex(phCur, uStartIndex);
  1093.  
  1094.                             // Set the return value to RANGEERROR, which is
  1095.                             // defined in the header file.
  1096.                             ret = RANGEERROR;
  1097.                         }
  1098.                         else
  1099.                         {
  1100.                             ret = TRUE;
  1101.  
  1102.                             // Since there was no error than move one
  1103.                             //   record forward to move past the crack
  1104.                             //   that SetRange puts  you at.
  1105.                             GetNextRec(*phCur);
  1106.                         }
  1107.                     }
  1108.                     else
  1109.                     {
  1110.                         ret = FALSE;
  1111.                     }
  1112.  
  1113.                     // Close the dialog and free the pointers.
  1114.                     //   Dialog closed first because the pointers are used
  1115.                     //   as part of the killfocus.
  1116.                     if(ret!=RANGEERROR)
  1117.                     {
  1118.                         EndDialog(hWnd, ret);
  1119.                         free(pLowRec);
  1120.                         free(pHighRec);
  1121.                     }
  1122.                     break;
  1123.                 case IDCANCEL:
  1124.                     EndDialog(hWnd, FALSE);
  1125.                     free(pLowRec);
  1126.                     free(pHighRec);
  1127.                     ret = TRUE;
  1128.  
  1129.                     // Set ret = TRUE to return a TRUE value to Windows.
  1130.                     break;
  1131.             }
  1132.             break;
  1133.     }
  1134.     return ret;
  1135. }
  1136.  
  1137. //======================================================================
  1138. //  Function:
  1139. //          SearchDlg(HWND hWnd, WORD msg, WORD wParam, LONG lParam)
  1140. //
  1141. //  Input:  hWnd        - Handle to the Windwo
  1142. //          msg         - Message to process
  1143. //          wParam      - Word Parameter
  1144. //          lParam      - Double Word Parameter
  1145. //                          Also contains the pointer to the cursor during
  1146. //                          the WM_INITDIALOG.
  1147. //
  1148. //  Return: TRUE -  The Search was successful.
  1149. //          FALSE - The search failed or user canceled the dilaog box.
  1150. //
  1151. //  Description:
  1152. //          This routine will process all I/O for the dialog that will
  1153. //          search for a record in the table.
  1154. //======================================================================
  1155. BOOL FAR _pascal _export
  1156. SearchDlg (HWND hWnd, WORD msg, WORD wParam, LONG lParam)
  1157. {
  1158.     BOOL        ret = FALSE;
  1159.     static      BOOL ErrorRet = FALSE;    
  1160.     static      phDBICur phCur;
  1161.     static      UINT16 uStartIndex;
  1162.     CHAR        cKey[FLDLENGTH];
  1163.     UINT16      uSearch;
  1164.     UINT32      uIndex;
  1165.     UINT32      uSel;
  1166.     DBIResult   rslt;
  1167.     char        szString[220];
  1168.  
  1169.     hErrorWnd = hWnd;
  1170.     switch (msg)
  1171.     {
  1172.         case WM_INITDIALOG:
  1173.             phCur = (phDBICur)lParam;
  1174.  
  1175.             // Get original index and fill combobox with index list.
  1176.             uStartIndex=FillDropList(hWnd, *phCur, IDE_SEARCH_COMBO);
  1177.  
  1178.             // Set the field length to the appropriate size.
  1179.             SetFieldLength(hWnd, uStartIndex, IDE_SEARCH, 0, FALSE);
  1180.  
  1181.             // Set the Checkbox to Greater than or equal.
  1182.             SendDlgItemMessage(hWnd, IDC_GREATEREQ, BM_SETCHECK,
  1183.                                (WPARAM)TRUE, 0L);
  1184.             LoadString(hInst, IDS_SEARCH, szString, 220);
  1185.             SetDlgItemText(hWnd, IDS_SEARCH_TEXT, (pCHAR)szString);
  1186.             break;
  1187.  
  1188.         case WM_COMMAND:
  1189.             switch (wParam)
  1190.             {
  1191.                 case IDE_SEARCH_COMBO:
  1192.                     switch(HIWORD(lParam))
  1193.                     {
  1194.                         case CBN_SELCHANGE:
  1195.                             // Get the new index that was chosen and set
  1196.                             //   the edit control's limit to the index's
  1197.                             //   limit.
  1198.                             uSel = SendDlgItemMessage(hWnd,
  1199.                                                       IDE_SEARCH_COMBO,
  1200.                                                       CB_GETCURSEL, 0, 0L);
  1201.                             uIndex = SendDlgItemMessage(hWnd,
  1202.                                                         IDE_SEARCH_COMBO,
  1203.                                                         CB_GETITEMDATA,
  1204.                                                         (WPARAM)uSel, 0L);
  1205.                             SetFieldLength(hWnd, (UINT16)uIndex,
  1206.                                            IDE_SEARCH, 0, FALSE);
  1207.  
  1208.                             // Clear the edit control.
  1209.                             SendDlgItemMessage(hWnd, IDE_SEARCH,
  1210.                                                WM_SETTEXT, 0, NULL);
  1211.                             break;
  1212.                     }
  1213.                     break;
  1214.                 case IDOK:
  1215.                     // Get the new index to search on.
  1216.                     uSel=SendDlgItemMessage(hWnd, IDE_SEARCH_COMBO,
  1217.                                             CB_GETCURSEL, 0, 0L);
  1218.                     uIndex=SendDlgItemMessage(hWnd, IDE_SEARCH_COMBO,
  1219.                                               CB_GETITEMDATA, (WPARAM)uSel,
  1220.                                               0L);
  1221.  
  1222.                     // If it is the same as the original index do NOT
  1223.                     //   reindex.
  1224.                     if(uStartIndex != uIndex)
  1225.                     {
  1226.                         SetIndex(phCur, (UINT16)uIndex);
  1227.                     }
  1228.  
  1229.                     GetDlgItemText(hWnd, IDE_SEARCH, cKey, FLDLENGTH);
  1230.                     uSearch = GetCond(hWnd); // Get the Condition checkbox.
  1231.  
  1232.                     // Search based upon the condition and the search
  1233.                     //   string.
  1234.                     rslt = Search(*phCur, (DBISearchCond)uSearch,
  1235.                                   (pBYTE)cKey);
  1236.                     if(rslt == DBIERR_NONE)
  1237.                     {
  1238.                         ret = TRUE;
  1239.                         ErrorRet = FALSE;
  1240.                     }
  1241.                     else
  1242.                     {
  1243.                         // Check if no match was found.
  1244.                         if (rslt == DBIERR_RECNOTFOUND)
  1245.                         {
  1246.                             MessageBox(hWnd, "Could not find a match",
  1247.                                        "Search Error",
  1248.                                        MB_ICONINFORMATION | MB_OK);
  1249.  
  1250.                             // Go to the first record as the failed search
  1251.                             //   has left us at a the end of the table.
  1252.                             GoTop(*phCur, TRUE);
  1253.                             ErrorRet = TRUE;
  1254.                         }
  1255.                     }
  1256.                     if(!ErrorRet)
  1257.                     {
  1258.                         EndDialog(hWnd, ret);
  1259.                     }    
  1260.                     break;
  1261.  
  1262.                 case IDCANCEL:
  1263.                     EndDialog(hWnd, FALSE);
  1264.                     break;
  1265.             }
  1266.             break;
  1267.     }
  1268.     return ret;
  1269. }
  1270.  
  1271. //======================================================================
  1272. //  Function:
  1273. //          FillStruct(RecordType *pRec, UINT16 OffSet)
  1274. //
  1275. //  Input:  pRec        - Record structure pointer
  1276. //          offSet      - Starting Resource ID
  1277. //
  1278. //  Return: TRUE -  The structure is filled.
  1279. //
  1280. //  Description:
  1281. //          This routine will fill the structure with the strings that
  1282. //          start at Offset and are found in the resource file.
  1283. //======================================================================
  1284. BOOL
  1285. FillStruct (RecordType *pRec, UINT16 OffSet)
  1286. {
  1287.     // used to keep count of the resource ID
  1288.     UINT16      j=IDS_ITEM_1 + (OffSet*uNumFields);
  1289.  
  1290.     memset(pRec, 0, sizeof(RecordType));
  1291.  
  1292.     // Get the string into the structure
  1293.     LoadString(hInst, j++, (pCHAR)pRec->Item, sizeof(pRec->Item));
  1294.     LoadString(hInst, j++, (pCHAR)pRec->ItemId, sizeof(pRec->ItemId));
  1295.     LoadString(hInst, j++, (pCHAR)pRec->In_Stock, sizeof(pRec->In_Stock));
  1296.     LoadString(hInst, j++, (pCHAR)pRec->Building, sizeof(pRec->Building));
  1297.     LoadString(hInst, j++, (pCHAR)pRec->Cost, sizeof(pRec->Cost));
  1298.     LoadString(hInst, j++, (pCHAR)pRec->DateD, sizeof(pRec->DateD));
  1299.     LoadString(hInst, j++, (pCHAR)pRec->Message, sizeof(pRec->Message));
  1300.  
  1301.     return TRUE;
  1302. }
  1303.  
  1304. //======================================================================
  1305. //  Function:
  1306. //          DisplayTable(hDBICur hCur)
  1307. //
  1308. //  Input:  hCur        - Handle to the Cursor
  1309. //
  1310. //  Return: TRUE -  The record is displayed.
  1311. //          FALSE - The record Structure allocation failed.
  1312. //
  1313. //  Description:
  1314. //          This routine will fill a structure with the record pointed
  1315. //          to by the cursor and then display the record in the main
  1316. //          Window.
  1317. //======================================================================
  1318. BOOL
  1319. DisplayTable (hDBICur hCur)
  1320. {
  1321.     RecordType *pRecord=NULL;
  1322.  
  1323.     // Allocate a temporary buffer to read information that is pointed to
  1324.     //   by the cursor.
  1325.     if((pRecord = (RecordType *) malloc(1 * sizeof(RecordType))) == NULL)
  1326.     {
  1327.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1328.         return FALSE;
  1329.     }
  1330.  
  1331.     memset(pRecord, 0, sizeof(RecordType));
  1332.  
  1333.     // Fill the structure with the record.
  1334.     GetData(hCur, pRecord);
  1335.  
  1336.     // Display the record.
  1337.     DispRec(pRecord);
  1338.  
  1339.     // Disable the buttons and menu options for Undo and Commit.
  1340.     SetControl(ID_MOD_REC, FALSE);
  1341.     SetControl(ID_UNDO_REC, FALSE);
  1342.     SetItemFocus();
  1343.  
  1344.     free(pRecord);
  1345.     return TRUE;
  1346. }
  1347.  
  1348. //======================================================================
  1349. //  Function:
  1350. //          TableExist(pCHAR pTableInfo)
  1351. //
  1352. //  Input:  pTableInfo      - Table's FULL name and path
  1353. //
  1354. //  Return: TRUE -  The table exists and IS NOT empty.
  1355. //          FALSE - The table is empty or does not exist.
  1356. //
  1357. //  Description:
  1358. //          This routine takes in a table name and checks if the table
  1359. //          exists. If it exists it checks if the table is empty.
  1360. //======================================================================
  1361. BOOL
  1362. TableExist (pCHAR pTableInfo)
  1363. {
  1364.     BOOL    RetVal;
  1365.     INT16   iExist = 0;
  1366.     hDBIDb  hDb;
  1367.     hDBICur hCur;
  1368.  
  1369.     // Create the full path string of the table.
  1370.     strcpy(pTableInfo, szTblDirectory);
  1371.     strcat(pTableInfo, "\\");
  1372.     strcat(pTableInfo, szTblName);
  1373.     strcat(pTableInfo, ".db");
  1374.     iExist = access(pTableInfo, 00); // Check if the table exists
  1375.     if(iExist == -1)
  1376.     {
  1377.         RetVal = FALSE;
  1378.     }
  1379.     else
  1380.     {
  1381.         // It exists but we need to now if it is empty or not.
  1382.         //   So we get a handle to the cursor and the Database.
  1383.         GetTable(&hDb, &hCur);
  1384.  
  1385.         // Go to the top of the table but, DO NOT move a record forward.
  1386.         //   Rather stay at the crack and check if there is a record in
  1387.         //   the table.
  1388.         GoTop(hCur, FALSE);
  1389.  
  1390.         //  Check if the table is empty.
  1391.         if(AtEOF(hCur))
  1392.         {
  1393.             RetVal = FALSE;
  1394.         }
  1395.         else
  1396.         {
  1397.             RetVal = TRUE;
  1398.         }
  1399.         // Close up and return the bool RetVal.
  1400.         CloseDb(&hDb);
  1401.     }
  1402.  
  1403.     return RetVal;
  1404. }
  1405.  
  1406. //======================================================================
  1407. //  Function:
  1408. //          FillTable(hDBICur hCur, phDBIDb phDb)
  1409. //
  1410. //  Input:  hCur        - Handle to the Cursor
  1411. //          phDb        - Pointer to the Database handle
  1412. //
  1413. //  Return: TRUE -  The record was added to the table.
  1414. //          FALSE - The record Structure allocation failed.
  1415. //
  1416. //  Description:
  1417. //          This function fills the table with all the strings that are
  1418. //          in the resource file.
  1419. //======================================================================
  1420. BOOL
  1421. FillTable (hDBICur hCur, phDBIDb phDb)
  1422. {
  1423.     RecordType  *pRecord = NULL;
  1424.     UINT16      i;
  1425.     DBIResult   rslt;
  1426.  
  1427.     // Allocate a temporary buffer to read information sitting in the
  1428.     //   resource file.
  1429.     if((pRecord = (RecordType *) malloc(1 * sizeof(RecordType))) == NULL)
  1430.     {
  1431.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1432.         return FALSE;
  1433.     }
  1434.  
  1435.     // Loop through the amount of records of data that is sitting in the
  1436.     //   resource file.
  1437.     for(i=0; i<uNumRecs; i++)
  1438.     {
  1439.         memset(pRecord, 0, sizeof(RecordType));
  1440.  
  1441.         // Fill a structure with the data sitting in the resource file.
  1442.         FillStruct(pRecord, i);
  1443.  
  1444.         // Add the record to the table.
  1445.         rslt = AddRecord(hCur, pRecord, TRUE);
  1446.         if(rslt != DBIERR_NONE)
  1447.         {
  1448.             PostMessage(hMainWnd, WM_DISPLAY, 0, 0L);
  1449.         }
  1450.     }
  1451.  
  1452.     free(pRecord);
  1453.     CloseDb(phDb);
  1454.  
  1455.     return TRUE;
  1456. }
  1457.  
  1458. //======================================================================
  1459. //  Function:
  1460. //          DispRec(RecordType *pRecord)
  1461. //
  1462. //  Input:  pRecord     - Record structure pointer
  1463. //
  1464. //  Return: TRUE -  The record was displayed.
  1465. //
  1466. //  Description:
  1467. //          This function displays the data in the record structure
  1468. //          into the main Window.
  1469. //======================================================================
  1470. BOOL
  1471. DispRec (RecordType *pRecord)
  1472. {
  1473.     SetDlgItemText(hMainWnd, IDE_ITEM, pRecord->Item);
  1474.     SetDlgItemText(hMainWnd, IDE_ITEMID, pRecord->ItemId);
  1475.     SetDlgItemText(hMainWnd, IDE_NOINSTOCK, pRecord->In_Stock);
  1476.     SetDlgItemText(hMainWnd, IDE_BUILDING, pRecord->Building);
  1477.     SetDlgItemText(hMainWnd, IDE_COST, pRecord->Cost);
  1478.     SetDlgItemText(hMainWnd, IDE_ORDERDATE, pRecord->DateD);
  1479.     SetDlgItemText(hMainWnd, IDE_COMMENTS, pRecord->Message);
  1480.     return TRUE;
  1481. }
  1482.  
  1483. //======================================================================
  1484. //  Function:
  1485. //          MoveRec(hDBICur hCur, INT16 Movement)
  1486. //
  1487. //  Input:  hCur        - Handle to the Cursor
  1488. //          Movement    - Where to move the record
  1489. //
  1490. //  Return: None.
  1491. //
  1492. //  Description:
  1493. //          This function moves the cursor to the bottom or the top
  1494. //          of the table. Or it moves it a record forward or backwards.
  1495. //======================================================================
  1496. void
  1497. MoveRec (hDBICur hCur, INT16 Movement)
  1498. {
  1499.     // Check if data has been changed by looking at the status of the Undo
  1500.     //   button. Then ask if the user wishes to lose the data by moving.
  1501.     if(CanContinue("Data not saved move to next record anyway?",
  1502.                    ID_UNDO_REC))
  1503.     {
  1504.         switch(Movement)
  1505.         {
  1506.             // These macros are defined in the header file.
  1507.             case TOP:
  1508.                 GoTop(hCur, TRUE);
  1509.                 break;
  1510.             case BOTTOM:
  1511.                 GoBottom(hCur, TRUE);
  1512.                 break;
  1513.             case NEXT_REC:
  1514.                 if(!AtEOF(hCur))
  1515.                 {
  1516.                     GetNextRec(hCur);
  1517.                 }
  1518.                 break;
  1519.             case PREV_REC:
  1520.                 if(!AtBOF(hCur))
  1521.                 {
  1522.                     GetPrevRec(hCur);
  1523.                 }
  1524.                 break;
  1525.             default:
  1526.                 return;
  1527.         }
  1528.  
  1529.         // After moving check the navigational controls and dsiplay the new
  1530.         //   record.
  1531.         CheckButtons(hCur);
  1532.         DisplayTable(hCur);
  1533.     }
  1534.     else
  1535.     {
  1536.         SetItemFocus();
  1537.     }
  1538.  
  1539. }
  1540.  
  1541. //======================================================================
  1542. //  Function:
  1543. //          CheckButtons(hDBICur hCur)
  1544. //
  1545. //  Input:  hCur        - Handle to the cursor
  1546. //
  1547. //  Return: None.
  1548. //
  1549. //  Description:
  1550. //          This function checks the position of the cursor and then
  1551. //          enables or disables the naviagtional buttons AND menu options.
  1552. //======================================================================
  1553. void
  1554. CheckButtons (hDBICur hCur)
  1555. {
  1556.     if(AtEOF(hCur))
  1557.     {
  1558.         // If at EOF disable the Next and Last record buttons and menu
  1559.         //   options.
  1560.         SetControl(ID_NEXT_REC, FALSE);
  1561.         SetControl(ID_LAST_REC, FALSE);
  1562.     }
  1563.     else
  1564.     {
  1565.         // Else enable them.
  1566.         SetControl(ID_NEXT_REC, TRUE);
  1567.         SetControl(ID_LAST_REC, TRUE);
  1568.     }
  1569.  
  1570.     if(AtBOF(hCur))
  1571.     {
  1572.         // If at BOF disable the Prev and First record buttons and menu
  1573.         //   options.
  1574.         SetControl(ID_PREV_REC, FALSE);
  1575.         SetControl(ID_FIRST_REC, FALSE);
  1576.     }
  1577.     else
  1578.     {
  1579.         // Else enable them.
  1580.         SetControl(ID_PREV_REC, TRUE);
  1581.         SetControl(ID_FIRST_REC, TRUE);
  1582.     }
  1583.  
  1584.     // If the table is empty..
  1585.     if(AtBOF(hCur) && AtEOF(hCur))
  1586.     {
  1587.         if(GetPrevRec(hCur)==DBIERR_BOF && GetNextRec(hCur)==DBIERR_EOF)
  1588.         {
  1589.             SetControl(ID_DEL_REC, FALSE);
  1590.             SetControl(ID_ORDER, FALSE);
  1591.             SetControl(ID_RANGE, FALSE);
  1592.             SetControl(ID_SEARCH, FALSE);
  1593.         }
  1594.         else
  1595.         {
  1596.             SetControl(ID_DEL_REC, TRUE);
  1597.             SetControl(ID_ORDER, TRUE);
  1598.             SetControl(ID_RANGE, TRUE);
  1599.             SetControl(ID_SEARCH, TRUE);
  1600.         }
  1601.     }
  1602.     else
  1603.     {
  1604.         SetControl(ID_DEL_REC, TRUE);
  1605.         SetControl(ID_ORDER, TRUE);
  1606.         SetControl(ID_RANGE, TRUE);
  1607.         SetControl(ID_SEARCH, TRUE);
  1608.     }
  1609.  
  1610.     SetItemFocus();
  1611. }
  1612.  
  1613. //======================================================================
  1614. //  Function:
  1615. //          SetupEdits()
  1616. //
  1617. //  Input:  None.
  1618. //
  1619. //  Return: None.
  1620. //
  1621. //  Description:
  1622. //          This function sets the text input limit of each of the edit
  1623. //          controls that are in the main window.
  1624. //======================================================================
  1625. void
  1626. SetupEdits (void)
  1627. {
  1628.     // All the macros are the same macros used to create the table.
  1629.     //   Therefore we need to leave room for the '\0', so we use each
  1630.     //   macro -1.
  1631.     SendDlgItemMessage(hMainWnd, IDE_ITEM, EM_LIMITTEXT,
  1632.                        (WPARAM)FLDLENGTH-1, 0L);
  1633.     SendDlgItemMessage(hMainWnd, IDE_ITEMID, EM_LIMITTEXT,
  1634.                        (WPARAM)IDLENGTH-1, 0L);
  1635.     SendDlgItemMessage(hMainWnd, IDE_NOINSTOCK, EM_LIMITTEXT,
  1636.                        (WPARAM)FLTLENGTH-1, 0L);
  1637.     SendDlgItemMessage(hMainWnd, IDE_BUILDING, EM_LIMITTEXT,
  1638.                        (WPARAM)FLDLENGTH-1, 0L);
  1639.     SendDlgItemMessage(hMainWnd, IDE_COST, EM_LIMITTEXT,
  1640.                        (WPARAM)FLTLENGTH-1, 0L);
  1641.     SendDlgItemMessage(hMainWnd, IDE_ORDERDATE, EM_LIMITTEXT,
  1642.                        (WPARAM)DATELEN-1, 0L);
  1643.     SendDlgItemMessage(hMainWnd, IDE_COMMENTS, EM_LIMITTEXT,
  1644.                        (WPARAM)COMMENTLEN-1, 0L);
  1645.  
  1646.     // Disable the Cancel and OK buttons that are hidden.
  1647.     EnableWindow(GetDlgItem(hMainWnd, IDCANCEL), FALSE);
  1648.     EnableWindow(GetDlgItem(hMainWnd, IDOK), FALSE);
  1649. }
  1650.  
  1651. //======================================================================
  1652. //  Function:
  1653. //          SaveRec(hDBICur hCur, BOOL bAdd)
  1654. //
  1655. //  Input:  hCur        - Handle to the cursor handle
  1656. //          bAdd        - Add or Overwrite bool
  1657. //
  1658. //  Return: TRUE:   If the memory is allocated.
  1659. //          FALSE:  If the memory allocation fails.
  1660. //
  1661. //  Description:
  1662. //          This function takes the data from off the main window and
  1663. //          puts it in a record structure.  Then based upon the bAdd Bool
  1664. //          it inserts the record or overwrites the old record.
  1665. //======================================================================
  1666. BOOL
  1667. SaveRec (hDBICur hCur, BOOL bAdd)
  1668. {
  1669.     RecordType *pRecord=NULL;
  1670.     DBIResult   rslt;
  1671.  
  1672.     // Allocate a temporary buffer to store data that is inside the main
  1673.     //   Window.
  1674.     if((pRecord = (RecordType *) malloc(1 * sizeof(RecordType))) == NULL)
  1675.     {
  1676.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1677.         return FALSE;
  1678.     }
  1679.  
  1680.     // Clear the record structure.
  1681.     memset(pRecord, 0, sizeof(RecordType));
  1682.  
  1683.     // Get the data from the main Window and put it into the record
  1684.     //   structure.
  1685.     GetRec(pRecord);
  1686.  
  1687.     // Add the record or insert the record based upon the bAdd value.
  1688.     rslt = AddRecord(hCur, pRecord, bAdd);
  1689.     if(rslt != DBIERR_NONE)
  1690.     {
  1691.         PostMessage(hMainWnd, WM_DISPLAY, 0, 0L);
  1692.     }
  1693.  
  1694.     // Free pRecord and check the navigational controls.
  1695.     free(pRecord);
  1696.     CheckButtons(hCur);
  1697.     return TRUE;
  1698. }
  1699.  
  1700. //======================================================================
  1701. //  Function:
  1702. //          GetRec(RecordType *pRecord)
  1703. //
  1704. //  Input:  pRecord     - Record structure pointer 
  1705. //
  1706. //  Return: TRUE.
  1707. //
  1708. //  Description:
  1709. //          This function fills the record structure with the data that
  1710. //          is in the main Window.
  1711. //======================================================================
  1712. BOOL
  1713. GetRec (RecordType *pRecord)
  1714. {
  1715.     GetDlgItemText(hMainWnd, IDE_ITEM, pRecord->Item, FLDLENGTH);
  1716.     GetDlgItemText(hMainWnd, IDE_ITEMID, pRecord->ItemId, IDLENGTH);
  1717.     GetDlgItemText(hMainWnd, IDE_NOINSTOCK, pRecord->In_Stock, FLTLENGTH);
  1718.     GetDlgItemText(hMainWnd, IDE_BUILDING, pRecord->Building, FLDLENGTH);
  1719.     GetDlgItemText(hMainWnd, IDE_COST, pRecord->Cost, FLTLENGTH);
  1720.     GetDlgItemText(hMainWnd, IDE_ORDERDATE, pRecord->DateD, DATELEN);
  1721.     GetDlgItemText(hMainWnd, IDE_COMMENTS, pRecord->Message, COMMENTLEN);
  1722.     return TRUE;
  1723. }
  1724.  
  1725. //======================================================================
  1726. //  Function:
  1727. //          FillDropList(HWND hWnd, hDBICur hCur, UINT16 Id)
  1728. //
  1729. //  Input:  hWnd    - Window Handle
  1730. //          hCur    - Handle to the Cursor
  1731. //          Id      - Resource ID
  1732. //
  1733. //  Return: The present index based upon the idxDesc array.
  1734. //
  1735. //  Description:
  1736. //          This function fills the combobox represented by Id with the
  1737. //          list of indexes. Then it gets the current index and returns
  1738. //          it.
  1739. //======================================================================
  1740. UINT16
  1741. FillDropList (HWND hWnd, hDBICur hCur, UINT16 Id)
  1742. {
  1743.     UINT16  i; // used for loop counter
  1744.     UINT32  uOff; //Index offset
  1745.     UINT32  uIndex;
  1746.  
  1747.     // Fill the combobox with all the indexes that are listed in the
  1748.     //   IndexList array. Then send the data item that represents the
  1749.     //   correct position of that index in the original array, so that
  1750.     //   we can sort the list and still retrieve the correct index.
  1751.     for(i=0; i<uNumIndexes; i++)
  1752.     {
  1753.         uOff = SendDlgItemMessage(hWnd, Id, CB_ADDSTRING, 0,
  1754.                                   (LPARAM)idxDesc[i].szName);
  1755.         SendDlgItemMessage(hWnd, Id, CB_SETITEMDATA,
  1756.                            (WPARAM)uOff, (LPARAM)i);
  1757.     }
  1758.  
  1759.     // Get the Present index number.
  1760.     i = GetIndexNum(hCur);
  1761.  
  1762.     // Select that index from the combo box list.
  1763.     uOff=SendDlgItemMessage(hWnd, Id, CB_SELECTSTRING, (WPARAM)-1,
  1764.                             (LPARAM)idxDesc[i].szName);
  1765.     uIndex=SendDlgItemMessage(hWnd, Id, CB_GETITEMDATA,
  1766.                               (WPARAM)uOff, 0L);
  1767.  
  1768.     // Set the description text into the static text box based upon
  1769.     //   the index's item data.
  1770.     if(Id == IDE_ORDER_COMBOBOX)
  1771.     {
  1772.         SetWindowText(GetDlgItem(hWnd, IDE_ORDER_INFO),
  1773.                       IndexList[(UINT16)uIndex]);
  1774.     }
  1775.  
  1776.     // Return the current index.
  1777.     return i;
  1778. }
  1779.  
  1780. //======================================================================
  1781. //  Function:
  1782. //          SetItemFocus()
  1783. //
  1784. //  Input:  None.
  1785. //
  1786. //  Return: None.
  1787. //
  1788. //  Description:
  1789. //          This function sets focus to the 'Item' edit control of
  1790. //          the main Window.
  1791. //======================================================================
  1792. void
  1793. SetItemFocus (void)
  1794. {
  1795.     SetFocus(GetDlgItem(hMainWnd, IDE_ITEM));
  1796. }
  1797.  
  1798. //======================================================================
  1799. //  Function:
  1800. //          DeleteRecord(hDBICur hCur)
  1801. //
  1802. //  Input:  hCur        - Handle to the cursor
  1803. //
  1804. //  Return: TRUE:   If the record is deleted.
  1805. //          FALSE:  If the record is not deleted.
  1806. //
  1807. //  Description:
  1808. //          This function simply deletes the record that the cursor is
  1809. //          pointing to.  It then moves forward one record to get off
  1810. //          the crack that the deleted record created.
  1811. //======================================================================
  1812. BOOL
  1813. DeleteRecord (hDBICur hCur)
  1814. {
  1815.     BOOL Flag = TRUE;
  1816.  
  1817.     DeleteRec(hCur);
  1818.  
  1819.     if(!AtEOF(hCur))
  1820.     {
  1821.         GetNextRec(hCur);
  1822.     }
  1823.     else
  1824.     {
  1825.         if(!AtBOF(hCur))
  1826.         {
  1827.             GetPrevRec(hCur);
  1828.         }
  1829.         else
  1830.         {
  1831.             // The table is now empty and disable the delete controls.
  1832.             Flag = FALSE;
  1833.             SetControl(ID_DEL_REC, FALSE);
  1834.         }
  1835.     }
  1836.  
  1837.     // Redisplay the new record.  If the table is empty, we will put up a
  1838.     // blank screen into the main Window.  Then check the navigational
  1839.     // controls.
  1840.     DisplayTable(hCur);
  1841.     CheckButtons(hCur);
  1842.     return Flag;
  1843. }
  1844.  
  1845. //======================================================================
  1846. //  Function:
  1847. //          SetControl(UINT16 Id, BOOL SetMod)
  1848. //
  1849. //  Input:  Id      - Resource Id
  1850. //          SetMod  - Set bool
  1851. //
  1852. //  Return: None.
  1853. //
  1854. //  Description:
  1855. //          This function sets the button and menu option of the Id to
  1856. //          the bool value.
  1857. //======================================================================
  1858. void
  1859. SetControl (UINT16 Id, BOOL SetMod)
  1860.     EnableWindow(GetDlgItem(hMainWnd, Id), SetMod);
  1861.     if(SetMod)
  1862.     {
  1863.         EnableMenuItem(GetMenu(hMainWnd), Id, MF_ENABLED);
  1864.     }
  1865.     else
  1866.     {
  1867.         EnableMenuItem(GetMenu(hMainWnd), Id, MF_GRAYED);
  1868.     }
  1869. }
  1870.  
  1871. //======================================================================
  1872. //  Function:
  1873. //          ClearDlg()
  1874. //
  1875. //  Input:  None.
  1876. //
  1877. //  Return: TRUE:   If the memory allocation was successful.
  1878. //          FALSE:  If the memory allocation was unsuccessful.
  1879. //
  1880. //  Description:
  1881. //          This function clears all the edit controls in the main Window.
  1882. //======================================================================
  1883. BOOL
  1884. ClearDlg (void)
  1885. {
  1886.     RecordType *pRecord=NULL;
  1887.  
  1888.     // Allocate a temporary record structure to use in clearing the main
  1889.     //   Window.
  1890.     if((pRecord = (RecordType *) malloc(1 * sizeof(RecordType))) == NULL)
  1891.     {
  1892.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1893.         return FALSE;
  1894.     }
  1895.  
  1896.     // Clear the record structure so that we display an empty structure.
  1897.     memset(pRecord, 0, sizeof(RecordType));
  1898.  
  1899.     // Display the empty structure so that we clear the main Window.
  1900.     DispRec(pRecord);
  1901.     SetItemFocus();
  1902.     free(pRecord);
  1903.     return TRUE;
  1904. }
  1905.  
  1906. //======================================================================
  1907. //  Function:
  1908. //          verified()
  1909. //
  1910. //  Input:  None.
  1911. //
  1912. //  Return: TRUE:   If the memory allocation was successful and if the
  1913. //                  data is valid.
  1914. //
  1915. //          FALSE:  If the memory allocation was unsuccessful, or if the
  1916. //                  data is not valid.
  1917. //
  1918. //  Description:
  1919. //          This function varifies if the data in the edit controls are
  1920. //          valid.
  1921. //======================================================================
  1922. BOOL
  1923. verified (void)
  1924. {
  1925.     DBIResult   rslt;           // Return value from IDAPI functions
  1926.     pCHAR       pItem;          // Item data
  1927.     pCHAR       pItemId;        // Item ID data
  1928.     pCHAR       pDate;          // Date data
  1929.     pCHAR       val;            // Temporary used in createing a date
  1930.     BOOL        RetVal;         // Record Valid? True/False
  1931.     UINT16      uItem;          // Item Number
  1932.     UINT16      uItemId;        // Item ID
  1933.     struct      dosdate_t d;    // Date
  1934.     DATE        TempDate;       // Temporary date used in formatting
  1935.  
  1936.     if((pItem = (pCHAR) malloc(IDLENGTH * sizeof(CHAR))) == NULL)
  1937.     {
  1938.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1939.         return FALSE;
  1940.     }
  1941.  
  1942.     if((pItemId = (pCHAR) malloc(FLDLENGTH * sizeof(CHAR))) == NULL)
  1943.     {
  1944.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1945.         return FALSE;
  1946.     }
  1947.  
  1948.     if((pDate = (pCHAR) malloc(DATELEN * sizeof(CHAR))) == NULL)
  1949.     {
  1950.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1951.         return FALSE;
  1952.     }
  1953.  
  1954.     uItem = GetDlgItemText(hMainWnd, IDE_ITEM, pItem, IDLENGTH);
  1955.     uItemId = GetDlgItemText(hMainWnd, IDE_ITEMID, pItemId, FLDLENGTH);
  1956.  
  1957.     // Check if there is data in the First and Last Name edit controls.
  1958.     if((uItem > 0) && (uItemId >0))
  1959.     {
  1960.         // Make certain ItemId contains a valid value
  1961.         if (atof(pItemId) == 0)
  1962.         {
  1963.             RetVal = FALSE;
  1964.         }
  1965.         else
  1966.         {
  1967.             RetVal = TRUE;
  1968.         }
  1969.     }
  1970.     else
  1971.     {
  1972.         RetVal = FALSE;
  1973.     }
  1974.  
  1975.     GetDlgItemText(hMainWnd, IDE_ORDERDATE, pDate, DATELEN);
  1976.  
  1977.     // Validate the Date if items are on order.
  1978.     if (strcmp(pDate, szNoneOnOrder))
  1979.     {
  1980.         val = strtok(pDate, "-"); // Need to convert the string to a Date
  1981.                                   //   structure
  1982.         if(val && RetVal)
  1983.         {
  1984.             d.month = atoi(val); // Date.da_day set to 0 if invalid date.
  1985.             val = strtok(NULL, "-");
  1986.             if(val && RetVal)
  1987.             {
  1988.                 d.day = atoi(val); // Date.da_day set to 0 if invalid date.
  1989.                 val = strtok(NULL, "-");
  1990.                 if(val && RetVal)
  1991.                 {
  1992.                     d.year = atoi(val); // Date.da_year set to 0 if invalid
  1993.                                         //   date.
  1994.                 }
  1995.                 else
  1996.                 {
  1997.                     RetVal = FALSE;
  1998.                 }
  1999.             }
  2000.             else
  2001.             {
  2002.                 RetVal = FALSE;
  2003.             }
  2004.  
  2005.         }
  2006.         else
  2007.         {
  2008.             RetVal = FALSE;
  2009.         }
  2010.  
  2011.         if(RetVal)
  2012.         {
  2013.             // Check if the date is legal.
  2014.             rslt = DateEncode(d.month, d.day, d.year, &TempDate);
  2015.             if(rslt == DBIERR_NONE)
  2016.             {
  2017.                 RetVal = TRUE;
  2018.             }
  2019.             else
  2020.             {
  2021.                 RetVal = FALSE;
  2022.             }
  2023.         }
  2024.     }
  2025.  
  2026.     free((void*)pItem);
  2027.     free((void*)pItemId);
  2028.     free((void*)pDate);
  2029.  
  2030.     return RetVal;
  2031. }
  2032.  
  2033. //======================================================================
  2034. //  Function:
  2035. //          SetDefaultDate()
  2036. //
  2037. //  Input:  None.
  2038. //
  2039. //  Return: None.
  2040. //
  2041. //  Description:
  2042. //          This function puts the current date into the Last Date edit
  2043. //          control so that we have a valid date to start.
  2044. //======================================================================
  2045. void
  2046. SetDefaultDate (void)
  2047. {
  2048.    SetDlgItemText(hMainWnd, IDE_ORDERDATE, szNoneOnOrder);
  2049. }
  2050.  
  2051. //======================================================================
  2052. //  Function:
  2053. //          EndNewRec(hDBICur hCur
  2054. //
  2055. //  Input:  hCur        - Handle to the cursor.
  2056. //
  2057. //  Return: None.
  2058. //
  2059. //  Description:
  2060. //          This function is called during the end of Addind a new record.
  2061. //          It changes the current state of the NewRecMode global
  2062. //          variable.  Then it checks the navigational controls and sets
  2063. //          focus to the first edit control.
  2064. //======================================================================
  2065. void
  2066. EndNewRec (hDBICur hCur)
  2067. {
  2068.     ChangeEntryMode();
  2069.     DisplayTable(hCur);
  2070.     CheckButtons(hCur);
  2071.     SetItemFocus();
  2072. }
  2073.  
  2074. //======================================================================
  2075. //  Function:
  2076. //          PutField(RecordType *pRec, pCHAR Text, UINT16 MemberNum)
  2077. //
  2078. //  Input:  pRec        - Record structure pointer
  2079. //          Text        - Pointer to the input text
  2080. //          MemberNum   - Array element number
  2081. //
  2082. //  Return: None.
  2083. //
  2084. //  Description:
  2085. //          This function puts input text into the correct field of the
  2086. //          record structure pointer based upon MemberNum.
  2087. //======================================================================
  2088. void
  2089. PutField (RecordType *pRec, pCHAR Text, UINT16 MemberNum)
  2090. {
  2091.     switch(MemberNum)
  2092.     {
  2093.         case 0:
  2094.             strcpy(pRec->ItemId, Text);
  2095.             break;
  2096.         case 1:
  2097.             strcpy(pRec->In_Stock, Text);
  2098.             break;
  2099.         case 2:
  2100.             strcpy(pRec->Item, Text);
  2101.             break;
  2102.     }
  2103. }
  2104.  
  2105. //======================================================================
  2106. //  Function:
  2107. //          GetField(RecordType *pRec, pCHAR Text, UINT16 MemberNum)
  2108. //
  2109. //  Input:  pRec        - Record structure pointer
  2110. //          Text        - Pointer to the input text
  2111. //          MemberNum   - Array element number
  2112. //
  2113. //  Return: None.                                      
  2114. //
  2115. //  Description:
  2116. //          This function gets data from the field in the record structure,
  2117. //          based upon the input variable - MemberNum.
  2118. //======================================================================
  2119. void
  2120. GetField (RecordType *pRec, pCHAR Text, UINT16 MemberNum)
  2121. {
  2122.     switch(MemberNum)
  2123.     {
  2124.         case 0:
  2125.             strcpy(Text, pRec->ItemId);
  2126.             break;
  2127.         case 1:
  2128.             strcpy(Text, pRec->In_Stock);
  2129.             break;
  2130.         case 2:
  2131.             strcpy(Text, pRec->Item);
  2132.             break;
  2133.     }
  2134. }
  2135.  
  2136. //======================================================================
  2137. //  Function:
  2138. //          SetFieldLength(HWND hWnd, UINT16 uSel, UINT16 Id1,
  2139. //                         UINT16 Id2, BOOL bTwo)
  2140. //
  2141. //  Input:  hWnd        - Handle to the window
  2142. //          uSel        - Field Number
  2143. //          Id1         - Resource ID1
  2144. //          Id2         - Resource ID2
  2145. //          bTwo        - Bool of if there is a second ID
  2146. //
  2147. //  Return: None.
  2148. //
  2149. //  Description:
  2150. //          This function sets the text input limit of the resource to a
  2151. //          value based upon the Field Number (uSel).
  2152. //======================================================================
  2153. void
  2154. SetFieldLength (HWND hWnd, UINT16 uSel, UINT16 Id1, UINT16 Id2, BOOL bTwo)
  2155. {
  2156.     UINT16 LimitLen;
  2157.  
  2158.     switch(uSel)
  2159.     {
  2160.         case 0:
  2161.             LimitLen = IDLENGTH;
  2162.             break;
  2163.         case 1:
  2164.         case 2:
  2165.             LimitLen = FLDLENGTH;
  2166.             break;
  2167.         case 3:
  2168.         case 4:
  2169.             LimitLen = FLTLENGTH;
  2170.             break;
  2171.     }
  2172.  
  2173.     // Set the limit and if there is a second resource id set that one
  2174.     //   too.
  2175.     SendDlgItemMessage(hWnd, Id1, EM_LIMITTEXT, (WPARAM)LimitLen-1, 0L);
  2176.     if(bTwo)
  2177.     {
  2178.         SendDlgItemMessage(hWnd, Id2, EM_LIMITTEXT, (WPARAM)LimitLen-1,
  2179.                            0L);
  2180.     }
  2181. }
  2182.  
  2183. //======================================================================
  2184. //  Function:
  2185. //          GetCond(HWND hWnd)
  2186. //
  2187. //  Input:  hWnd        - Handle to the window that has the check boxes.
  2188. //
  2189. //  Return: Which check box is checked.
  2190. //
  2191. //  Description:
  2192. //          This function simply returns a number based upon which check
  2193. //          box is checked.
  2194. //======================================================================
  2195. UINT16
  2196. GetCond (HWND hWnd)
  2197. {
  2198.     UINT32  Ret=0;
  2199.     UINT16  i=IDC_GREATEREQ;
  2200.  
  2201.     while(Ret!=1)
  2202.     {
  2203.         Ret = SendDlgItemMessage(hWnd, i, BM_GETCHECK, 0, 0L);
  2204.         i++;
  2205.     }
  2206.  
  2207.     // Subtract 1 to counteract the last i++
  2208.     i--;
  2209.  
  2210.     switch(i)
  2211.     {
  2212.         case IDC_EQUAL:
  2213.             Ret = keySEARCHEQ;
  2214.             break;
  2215.         case IDC_GREATER:
  2216.             Ret = keySEARCHGT;
  2217.             break;
  2218.         case IDC_GREATEREQ:
  2219.             Ret = keySEARCHGEQ;
  2220.             break;
  2221.     }
  2222.  
  2223.     return (UINT16)Ret;
  2224. }
  2225.  
  2226. //======================================================================
  2227. //  Function:
  2228. //          GetCond(pCHAR pString, UINT16 uId)
  2229. //
  2230. //  Input:  pString     - Pointer to the string that is to be displayed
  2231. //          uId         - resource ID 
  2232. //
  2233. //  Return: If the resource is enabled, then it returns the user's
  2234. //          response. Otherwise, it returns a TRUE.
  2235. //
  2236. //  Description:
  2237. //          This function checks if the Id is enabled.  If it is then it
  2238. //          prompts the user with the pString and returns the response.
  2239. //          Otherwise it returns a TRUE.
  2240. //======================================================================
  2241. BOOL
  2242. CanContinue (pCHAR pString, UINT16 uId)
  2243. {
  2244.     BOOL RetVal = TRUE;
  2245.  
  2246.     // Check to see if the button is enabled.
  2247.     if(IsWindowEnabled(GetDlgItem(hMainWnd, uId)))
  2248.     {
  2249.         if(WinMsg(pString, MB_ICONHAND, MB_YESNO) == IDNO)
  2250.         {
  2251.             RetVal = FALSE;
  2252.         }
  2253.     }
  2254.     return RetVal;
  2255. }
  2256.