home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 5 / 05.iso / a / a025 / 11.ddi / SQLCURSW.C@ / SQLCURSW.bin
Encoding:
Text File  |  1992-09-15  |  29.0 KB  |  902 lines

  1. /****************************************************************************
  2.  
  3.     PROGRAM: SqlCursw.c
  4.          Copyright (C) 1991 Microsoft Corp.
  5.  
  6.     PURPOSE: Sql Server sample Windows applications
  7.  
  8.     COMMENTS:
  9.  
  10.     Windows can have several copies of your application running at the
  11.     same time.  The variable hInst keeps track of which instance this
  12.     application is so that processing will be to the correct window.
  13.  
  14.     You only need to initialize the application once.  After it is
  15.     initialized, all other copies of the application will use the same
  16.     window class, and do not need to be separately initialized.
  17.  
  18. ****************************************************************************/
  19.  
  20. #include "windows.h"            /* required for all Windows applications*/
  21. #define DBMSWIN                /* needed to define environment         */
  22. #include "sqlfront.h"            /* standard dblib include file        */
  23. #include "sqldb.h"            /* standard dblib include file        */
  24. #include "sqlcursw.h"            /* specific to this program         */
  25.  
  26. DBPROCESS *dbproc = (DBPROCESS *)NULL;
  27. DBCURSOR  *hdbcursor = (DBCURSOR *)NULL;
  28.  
  29. char stmt[] = "select au_lname, au_fname, city, state from authors where contract = 1 ";
  30.  
  31. /* Status array, and results set */
  32.  
  33. DBINT        pstat[NROWS];
  34. DBINT        plen[NROWS];
  35. char        au_lname[NROWS][41];
  36. char        au_fname[NROWS][21];
  37. char        au_city[NROWS][21];
  38. char        au_state[NROWS][3];
  39. char        szRowNum[5];
  40. USHORT        rownum = 0;
  41. char        szValues[251];
  42. char        szTable[31];
  43.  
  44. HANDLE hInst;                /* current instance                */
  45. HWND ghWnd;                /* global window handle for handlers    */
  46. HWND errhWnd;                /* global window handle for current error*/
  47. /****************************************************************************
  48.  
  49.     FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  50.  
  51.     PURPOSE: calls initialization function, processes message loop
  52.  
  53.     COMMENTS:
  54.  
  55.     This will initialize the window class if it is the first time this
  56.     application is run.  It then creates the window, and processes the
  57.     message loop until a PostQuitMessage is received.  It exits the
  58.     application by returning the value passed by the PostQuitMessage.
  59.  
  60. ****************************************************************************/
  61.  
  62. int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  63. HANDLE hInstance;                 /* current instance         */
  64. HANDLE hPrevInstance;                 /* previous instance         */
  65. LPSTR lpCmdLine;                 /* command line             */
  66. int nCmdShow;                     /* show-window type (open/icon) */
  67. {
  68.     HWND hWnd;                     /* window handle             */
  69.     MSG msg;                     /* message                 */
  70.  
  71.  
  72.     if (!hPrevInstance)            /* Has application been initialized? */
  73.     if (!SqlTestInit(hInstance))
  74.         return (NULL);        /* Exits if unable to initialize     */
  75.  
  76.     hInst = hInstance;            /* Saves the current instance         */
  77.  
  78.     hWnd = CreateWindow("SQL Test",          /* window class         */
  79.     "SQL Server Sample Windows Application",  /* window name         */
  80.     WS_OVERLAPPEDWINDOW,              /* window style         */
  81.     CW_USEDEFAULT,                  /* x position             */
  82.     CW_USEDEFAULT,                  /* y position             */
  83.     CW_USEDEFAULT,                  /* width             */
  84.     CW_USEDEFAULT,                  /* height             */
  85.     NULL,                      /* parent handle         */
  86.     NULL,                      /* menu or child ID         */
  87.     hInstance,                  /* instance             */
  88.     NULL);                      /* additional info         */
  89.  
  90.     if (!hWnd)                      /* Was the window created? */
  91.     return (NULL);
  92.  
  93.     ghWnd = hWnd;                  /* set global handle         */
  94.     errhWnd = hWnd;
  95.  
  96.     ShowWindow(hWnd, nCmdShow);              /* Shows the window         */
  97.     UpdateWindow(hWnd);                  /* Sends WM_PAINT message  */
  98.  
  99.     while (GetMessage(&msg,       /* message structure                 */
  100.         NULL,           /* handle of window receiving the message */
  101.         NULL,           /* lowest message to examine             */
  102.         NULL))           /* highest message to examine         */
  103.     {
  104.     TranslateMessage(&msg);       /* Translates virtual key codes         */
  105.     DispatchMessage(&msg);       /* Dispatches message to window         */
  106.     }
  107.     return (msg.wParam);       /* Returns the value from PostQuitMessage */
  108. }
  109.  
  110.  
  111. /****************************************************************************
  112.  
  113.     FUNCTION: SqlTestInit(HANDLE)
  114.  
  115.     PURPOSE: Initializes window data and registers window class
  116.  
  117.     COMMENTS:
  118.  
  119.     Sets up a structure to register the window class.  Structure includes
  120.     such information as what function will process messages, what cursor
  121.     and icon to use, etc.
  122.  
  123.  
  124. ****************************************************************************/
  125.  
  126. BOOL SqlTestInit(hInstance)
  127. HANDLE hInstance;                   /* current instance         */
  128. {
  129.     HANDLE hMemory;                   /* handle to allocated memory */
  130.     PWNDCLASS pWndClass;               /* structure pointer         */
  131.     BOOL bSuccess;                   /* RegisterClass() result     */
  132.  
  133.     hMemory = LocalAlloc(LPTR, sizeof(WNDCLASS));
  134.     pWndClass = (PWNDCLASS) LocalLock(hMemory);
  135.  
  136.     pWndClass->style = NULL; /*CS_HREDRAW | CS_VREDRAW; */
  137.     pWndClass->lpfnWndProc = SqlTestWndProc;
  138.     pWndClass->hInstance = hInstance;
  139.     pWndClass->hIcon = LoadIcon(hInstance, "SQLITEST");
  140.     pWndClass->hCursor = LoadCursor(NULL, IDC_ARROW);
  141.     pWndClass->hbrBackground = GetStockObject(WHITE_BRUSH);
  142.     pWndClass->lpszMenuName = (LPSTR)"SQLTest";
  143.     pWndClass->lpszClassName = (LPSTR)"SQL Test";
  144.  
  145.     bSuccess = RegisterClass(pWndClass);
  146.  
  147.  
  148.     LocalUnlock(hMemory);                /* Unlocks the memory    */
  149.     LocalFree(hMemory);                    /* Returns it to Windows */
  150.     return (bSuccess);         /* Returns result of registering the window */
  151. }
  152.  
  153. /****************************************************************************
  154.  
  155.     FUNCTION: SqlTestWndProc(HWND, unsigned, WORD, LONG)
  156.  
  157.     PURPOSE:  Processes messages
  158.  
  159.     MESSAGES:
  160.  
  161.     WM_SYSCOMMAND - system menu (About dialog box)
  162.     WM_CREATE     - create window
  163.     WM_DESTROY    - destroy window
  164.     WM_COMMAND    - application menus (Connect and Select dialog boxes
  165.  
  166.     COMMENTS:
  167.  
  168.     To process the ID_ABOUTSQL message, call MakeProcInstance() to get the
  169.     current instance address of the About() function.  Then call Dialog
  170.     box which will create the box according to the information in your
  171.     SqlTest.rc file and turn control over to the About() function.    When
  172.     it returns, free the intance address.
  173.     This same action will take place for the two menu items Connect and
  174.     Select.
  175.  
  176.  
  177. ****************************************************************************/
  178.  
  179. long FAR PASCAL SqlTestWndProc(hWnd, message, wParam, lParam)
  180. HWND hWnd;                  /* window handle             */
  181. unsigned message;              /* type of message             */
  182. WORD wParam;                  /* additional information         */
  183. LONG lParam;                  /* additional information         */
  184. {
  185.     FARPROC lpProcAbout;          /* pointer to the "About" function */
  186.     FARPROC lpProcRowNum;          /* pointer to the "GetRowNum" function */
  187.     FARPROC lpProcModify;          /* pointer to the "ModifyRow" function */
  188.     FARPROC lpProcSQL;              /* pointer to the "ConnectSQL" function*/
  189.  
  190.     HMENU hMenu;              /* handle to the System menu         */
  191.     static FARPROC lpdbwinMessageHandler; /* pointer to message handler         */
  192.     static FARPROC lpdbwinErrorHandler;   /* pointer to error handler         */
  193.     RETCODE    rc;              /* return code             */
  194.  
  195.     switch (message) {
  196.     case WM_SYSCOMMAND:        /* message: command from system menu */
  197.         if (wParam == ID_ABOUTSQL) {
  198.         lpProcAbout = MakeProcInstance(AboutSQL, hInst);
  199.  
  200.         DialogBox(hInst,         /* current instance         */
  201.             "ABOUTSQL",             /* resource to use         */
  202.             hWnd,             /* parent handle         */
  203.             lpProcAbout);         /* About() instance address */
  204.  
  205.         FreeProcInstance(lpProcAbout);
  206.         break;
  207.         }
  208.  
  209.         else                /* Lets Windows process it         */
  210.         return (DefWindowProc(hWnd, message, wParam, lParam));
  211.  
  212.     case WM_CREATE:                /* message: window being created */
  213.  
  214.         /* Get the handle of the System menu */
  215.  
  216.         hMenu = GetSystemMenu(hWnd, FALSE);
  217.  
  218.         /* Add a separator to the menu */
  219.  
  220.         ChangeMenu(hMenu,                  /* menu handle         */
  221.         NULL,                      /* menu item to change */
  222.         NULL,                      /* new menu item         */
  223.         NULL,                      /* menu identifier     */
  224.         MF_APPEND | MF_SEPARATOR);          /* type of change         */
  225.  
  226.         /* Add new menu item to the System menu */
  227.  
  228.         ChangeMenu(hMenu,                  /* menu handle         */
  229.         NULL,                      /* menu item to change */
  230.         "A&bout SQL Test...",              /* new menu item         */
  231.         ID_ABOUTSQL,                  /* menu identifier     */
  232.         MF_APPEND | MF_STRING);              /* type of change         */
  233.     
  234.                         /* Now make the message and error    */
  235.                     /* handler instances             */
  236.             dbinit();
  237.         lpdbwinMessageHandler =
  238.             MakeProcInstance((FARPROC)dbwinMessageHandler, hInst);
  239.         lpdbwinErrorHandler =
  240.             MakeProcInstance((FARPROC)dbwinErrorHandler, hInst);
  241.                     /* Install the instances into dblib */    
  242.         dbmsghandle(lpdbwinMessageHandler);
  243.         dberrhandle(lpdbwinErrorHandler);
  244.         MessageBox(hWnd,
  245.           (LPSTR)"None of the data modifications will be committed",
  246.           (LPSTR)"SQLCURSW", MB_OK);
  247.         break;
  248.     
  249.     case WM_COMMAND :            /* menu selections generate */
  250.                         /* the WM_COMMAND message   */    
  251.         switch(wParam)            /* menu in WORD parameter   */
  252.         {
  253.         case IDM_CONNECT :        /* connect to server        */
  254.             lpProcSQL = MakeProcInstance(ConnectSQL, hInst);
  255.  
  256.             DialogBox(hInst,        /* current instance         */
  257.             "CONNECT",         /* resource to use         */
  258.             hWnd,            /* parent handle         */
  259.             lpProcSQL);         /* ConnectSQL() instance address */
  260.  
  261.             FreeProcInstance(lpProcSQL);
  262.             break;
  263.         case IDM_RAND :
  264.         case IDM_RELT :
  265.         case IDM_REFRESH :
  266.             /* Obtain the row number */
  267.             lpProcRowNum = MakeProcInstance(GetRowNum, hInst);
  268.             DialogBox(hInst, "ROWNUM", hWnd, lpProcRowNum);
  269.             FreeProcInstance(lpProcRowNum);
  270.  
  271.             /* FALL THROUGH */
  272.  
  273.         case IDM_FIRST :
  274.         case IDM_NEXT :
  275.         case IDM_PREV :
  276.         case IDM_LAST :
  277.             DBLOCKLIB();
  278.             if (wParam == IDM_REFRESH)
  279.             rc = dbcursor(hdbcursor, wParam - UPD_CONST, rownum,
  280.                 NULL, NULL);
  281.             else
  282.             /* Do the fetch and display of rows */
  283.             rc = dbcursorfetch(hdbcursor, wParam - FETCH_CONST,
  284.               rownum);
  285.             if (rc == SUCCEED)
  286.             SQLTestProcessResults(hWnd);
  287.             DBUNLOCKLIB();
  288.             rownum = 0;     /* Reset for next fetch */
  289.             break;
  290.         case IDM_DELETE :
  291.         case IDM_LOCK :
  292.         case IDM_UPDATE :
  293.         case IDM_INSERT :
  294.             szValues[0] = '\0';
  295.             szTable[0] = '\0';
  296.             /* Obtain the row number */
  297.             if (wParam == IDM_DELETE || wParam == IDM_LOCK)
  298.             {
  299.             lpProcModify = MakeProcInstance(DelLockRow, hInst);
  300.             DialogBox(hInst, "DELLOCK", hWnd, lpProcModify);
  301.             }
  302.             else
  303.             {
  304.             lpProcModify = MakeProcInstance(ModifyRow, hInst);
  305.             DialogBox(hInst, "MODIFY", hWnd, lpProcModify);
  306.             }
  307.             FreeProcInstance(lpProcModify);
  308.             DBLOCKLIB();
  309.             /* Do the dbcursor call */
  310.             dbcursor(hdbcursor, wParam - UPD_CONST, rownum,
  311.               szTable, szValues);
  312.             DBUNLOCKLIB();
  313.             rownum = 0;     /* Reset for next command */
  314.             break;
  315.  
  316.         }
  317.         break;
  318.     
  319.     case WM_DESTROY:          /* message: window being destroyed */
  320.         dbexit();              /* free any active dbprocesses     */
  321.         FreeProcInstance(lpdbwinMessageHandler);    /* release handlers  */
  322.         FreeProcInstance(lpdbwinErrorHandler);
  323.             dbwinexit();
  324.         PostQuitMessage(0);
  325.         break;
  326.  
  327.     default:              /* Passes it on if unproccessed    */
  328.         return (DefWindowProc(hWnd, message, wParam, lParam));
  329.     }
  330.     return (NULL);
  331. }
  332.  
  333.  
  334. /****************************************************************************
  335.  
  336.     FUNCTION: AboutSQL(HWND, unsigned, WORD, LONG)
  337.  
  338.     PURPOSE:  Processes messages for "AboutSQL" dialog box
  339.  
  340.     MESSAGES:
  341.  
  342.     WM_INITDIALOG - initialize dialog box
  343.     WM_COMMAND    - Input received
  344.  
  345.     COMMENTS:
  346.  
  347.     No initialization is needed for this particular dialog box, but TRUE
  348.     must be returned to Windows.
  349.  
  350.     Wait for user to click on "Ok" button, then close the dialog box.
  351.  
  352. ****************************************************************************/
  353.  
  354. BOOL FAR PASCAL AboutSQL(hDlg, message, wParam, lParam)
  355. HWND hDlg;
  356. unsigned message;
  357. WORD wParam;
  358. LONG lParam;
  359. {
  360.     switch (message) {
  361.     case WM_INITDIALOG:           /* message: initialize dialog box */
  362.         return (TRUE);
  363.  
  364.     case WM_COMMAND:              /* message: received a command */
  365.         if (wParam == IDOK) {          /* "OK" box selected?         */
  366.         EndDialog(hDlg, NULL);          /* Exits the dialog box         */
  367.         return (TRUE);
  368.         }
  369.         break;
  370.     }
  371.     return (FALSE);                  /* Didn't process a message    */
  372. }
  373. /****************************************************************************
  374.  
  375.     FUNCTION: GetRowNum(HWND, unsigned, WORD, LONG)
  376.  
  377.     PURPOSE:  Processes messages for "ROWNUM" dialog box
  378.  
  379.     MESSAGES:
  380.  
  381.     WM_INITDIALOG - initialize dialog box
  382.     WM_COMMAND    - Input received
  383.  
  384.     COMMENTS:
  385.  
  386.     No initialization is needed for this particular dialog box, but TRUE
  387.     must be returned to Windows.
  388.  
  389.     Wait for user to click on "Ok" button, then close the dialog box.
  390.  
  391. ****************************************************************************/
  392.  
  393. BOOL FAR PASCAL GetRowNum(hDlg, message, wParam, lParam)
  394. HWND hDlg;
  395. unsigned message;
  396. WORD wParam;
  397. LONG lParam;
  398. {
  399.     switch (message) {
  400.     case WM_INITDIALOG:           /* message: initialize dialog box */
  401.         SendDlgItemMessage(hDlg,       /* limit input to 4 characters  */
  402.         ID_ROWNUM,EM_LIMITTEXT,4,0L);
  403.         return (TRUE);
  404.  
  405.     case WM_COMMAND:              /* message: received a command */
  406.         if (wParam == IDOK) {          /* "OK" box selected?         */
  407.         GetDlgItemText(hDlg,ID_ROWNUM,
  408.             (LPSTR)szRowNum,4);       /* Get row number */
  409.         szRowNum[4] = '\0';
  410.         rownum = atoi(szRowNum);
  411.         EndDialog(hDlg, NULL);          /* Exits the dialog box         */
  412.         return (TRUE);
  413.         }
  414.         break;
  415.     }
  416.     return (FALSE);                  /* Didn't process a message    */
  417. }
  418. /****************************************************************************
  419.  
  420.     FUNCTION: DelLockRow(HWND, unsigned, WORD, LONG)
  421.  
  422.     PURPOSE:  Processes messages for "DELLOCK" dialog box
  423.  
  424.     MESSAGES:
  425.  
  426.     WM_INITDIALOG - initialize dialog box
  427.     WM_COMMAND    - Input received
  428.  
  429.     COMMENTS:
  430.  
  431.     No initialization is needed for this particular dialog box, but TRUE
  432.     must be returned to Windows.
  433.  
  434.     Wait for user to click on "Ok" button, then close the dialog box.
  435.  
  436. ****************************************************************************/
  437.  
  438. BOOL FAR PASCAL DelLockRow(hDlg, message, wParam, lParam)
  439. HWND hDlg;
  440. unsigned message;
  441. WORD wParam;
  442. LONG lParam;
  443. {
  444.     switch (message) {
  445.     case WM_INITDIALOG:           /* message: initialize dialog box */
  446.         SendDlgItemMessage(hDlg,       /* limit row# input to 4 characters*/
  447.         ID_DROWNUM,EM_LIMITTEXT,4,0L);
  448.         SendDlgItemMessage(hDlg,       /* limit table input to 30 characters*/
  449.         ID_DTABLE,EM_LIMITTEXT,30,0L);
  450.         return (TRUE);
  451.  
  452.     case WM_COMMAND:              /* message: received a command */
  453.         if (wParam == IDOK) {          /* "OK" box selected?         */
  454.         GetDlgItemText(hDlg,ID_DROWNUM,
  455.             (LPSTR)szRowNum,4);       /* Get row number */
  456.         szRowNum[4] = '\0';
  457.         rownum = atoi(szRowNum);
  458.         GetDlgItemText(hDlg,ID_DTABLE,
  459.             (LPSTR)szTable,30);       /* Get table name */
  460.         EndDialog(hDlg, NULL);          /* Exits the dialog box         */
  461.         return (TRUE);
  462.         }
  463.         else if (wParam == IDCANCEL)
  464.         {
  465.         EndDialog(hDlg, NULL);          /* Exits the dialog box         */
  466.         return (TRUE);
  467.         }
  468.         break;
  469.     }
  470.     return (FALSE);                  /* Didn't process a message    */
  471. }
  472. /****************************************************************************
  473.  
  474.     FUNCTION: ModifyRow(HWND, unsigned, WORD, LONG)
  475.  
  476.     PURPOSE:  Processes messages for "MODIFY" dialog box
  477.  
  478.     MESSAGES:
  479.  
  480.     WM_INITDIALOG - initialize dialog box
  481.     WM_COMMAND    - Input received
  482.  
  483.     COMMENTS:
  484.  
  485.     No initialization is needed for this particular dialog box, but TRUE
  486.     must be returned to Windows.
  487.  
  488.     Wait for user to click on "Ok" button, then close the dialog box.
  489.  
  490. ****************************************************************************/
  491.  
  492. BOOL FAR PASCAL ModifyRow(hDlg, message, wParam, lParam)
  493. HWND hDlg;
  494. unsigned message;
  495. WORD wParam;
  496. LONG lParam;
  497. {
  498.     switch (message) {
  499.     case WM_INITDIALOG:           /* message: initialize dialog box */
  500.         SendDlgItemMessage(hDlg,       /* limit row# input to 4 characters*/
  501.         ID_MROWNUM,EM_LIMITTEXT,4,0L);
  502.         SendDlgItemMessage(hDlg,       /* limit table input to 30 characters*/
  503.         ID_MTABLE,EM_LIMITTEXT,30,0L);
  504.         SendDlgItemMessage(hDlg,       /* limit values input to 250 characters*/
  505.         ID_MVALUES,EM_LIMITTEXT,250,0L);
  506.         return (TRUE);
  507.  
  508.     case WM_COMMAND:              /* message: received a command */
  509.         if (wParam == IDOK) {          /* "OK" box selected?         */
  510.         GetDlgItemText(hDlg,ID_MROWNUM,
  511.             (LPSTR)szRowNum,4);       /* Get row number */
  512.         szRowNum[4] = '\0';
  513.         rownum = atoi(szRowNum);
  514.         GetDlgItemText(hDlg,ID_MTABLE,
  515.             (LPSTR)szTable,30);       /* Get table name */
  516.         GetDlgItemText(hDlg,ID_MVALUES,
  517.             (LPSTR)szValues,250);     /* Get values string */
  518.         EndDialog(hDlg, NULL);          /* Exits the dialog box         */
  519.         return (TRUE);
  520.         }
  521.         else if (wParam == IDCANCEL)
  522.         {
  523.         EndDialog(hDlg, NULL);          /* Exits the dialog box         */
  524.         return (TRUE);
  525.         }
  526.         break;
  527.     }
  528.     return (FALSE);                  /* Didn't process a message    */
  529. }
  530. /****************************************************************************
  531.  
  532.     FUNCTION: ConnectSQL(HWND, unsigned, WORD, LONG)
  533.  
  534.     PURPOSE:  Processes messages for "Connect" dialog box
  535.  
  536.     MESSAGES:
  537.  
  538.     WM_INITDIALOG - initialize dialog box
  539.     WM_COMMAND    - Input received
  540.  
  541.     COMMENTS:
  542.  
  543.     No initialization is needed for this particular dialog box, but TRUE
  544.     must be returned to Windows.
  545.  
  546.     Wait for user to click on "Ok" button, then close the dialog box.
  547.  
  548. ****************************************************************************/
  549.  
  550. BOOL FAR PASCAL ConnectSQL(hDlg, message, wParam, lParam)
  551. HWND hDlg;
  552. unsigned message;
  553. WORD wParam;
  554. LONG lParam;
  555. {
  556.     char szSQLServer[31];
  557.     char szServerMess[81];
  558.     static LOGINREC *LoginRec;
  559.     RETCODE    rc;
  560.  
  561.     *szSQLServer = NULL;
  562.     switch (message) {
  563.     case WM_INITDIALOG:           /* message: initialize dialog box*/
  564.         SendDlgItemMessage(hDlg,       /* limit input to 30 characters  */
  565.         ID_SQLSERVER,EM_LIMITTEXT,30,0L);
  566.         return (TRUE);
  567.  
  568.     case WM_COMMAND:              /* message: received a command*/
  569.         errhWnd = hDlg;
  570.         switch(wParam)
  571.         {
  572.         case IDOK :              /* "OK" box selected?        */
  573.             GetDlgItemText(hDlg,ID_SQLSERVER,
  574.             (LPSTR)szSQLServer,
  575.                 MAX_SERVERNAME); /* get Server name */
  576.             if(*szSQLServer != NULL) /* was something input        */
  577.             {
  578.             DBLOCKLIB();        /* lock down library        */
  579.             if(dbproc != (DBPROCESS *)NULL) /* if an active     */
  580.                                 /* process close it */
  581.             {
  582.                 dbclose(dbproc);
  583.                 dbproc = (DBPROCESS *)NULL;
  584.             }
  585.             if((LoginRec = dblogin()) != (LOGINREC *)NULL) /* get loginrec */
  586.             {
  587.                 DBSETLUSER(LoginRec,(char far *)"sa"); /* set user  */
  588.                     /* now open the connection to server */
  589.                 if((dbproc = dbopen(LoginRec,(LPSTR)szSQLServer))
  590.                      == (DBPROCESS *)NULL)
  591.                 {
  592.                     /* if NULL couldn't connect    */
  593.                 dbfreelogin(LoginRec);
  594.                 }
  595.                 else /* got connect so use the pubs database */
  596.                 {
  597.                 dbuse(dbproc,(LPSTR)"pubs");
  598.                 dbfreelogin(LoginRec);
  599.                 LoginRec = (LOGINREC *)NULL;
  600.                 }
  601.             }
  602.             else /* memory allocation problem */
  603.                 MessageBox(hDlg, "Could not allocate Login Record",
  604.                 "System Error", MB_ICONHAND | MB_OK);
  605.  
  606.             /* Open the cursor, bind variables */
  607.             if (SQLInitCursor() == FALSE)
  608.                 MessageBox(hDlg, "Cursor open failed",
  609.                 "System Error", MB_ICONHAND | MB_OK);
  610.             DBUNLOCKLIB(); /* done unlock library    */
  611.             }
  612.             EndDialog(hDlg, NULL);          /* Exits the dialog box         */
  613.             return (TRUE);
  614.             break;
  615.         case IDCANCEL :
  616.             EndDialog(hDlg, NULL);
  617.             return(TRUE);
  618.             break;
  619.         
  620.         }
  621.         break;
  622.     }
  623.     return (FALSE);                  /* Didn't process a message    */
  624. }
  625.  
  626. /****************************************************************************
  627.  
  628.     FUNCTION: SQLInitCursor(void)
  629.  
  630.     PURPOSE:  Initialize cursor, bind variables
  631.  
  632.     PARAMETERS: NONE
  633.  
  634.     RETURNS: NONE
  635.  
  636.     COMMENTS:
  637.  
  638. ****************************************************************************/
  639. BOOL PASCAL SQLInitCursor()
  640. {
  641.     int     i, j= 0;
  642.     RETCODE  rc;
  643.  
  644.     /* Open the cursor */
  645.     hdbcursor = dbcursoropen(dbproc, stmt,
  646.     KEYSET, CONCUROPT, NROWS, pstat);
  647.     if (hdbcursor == (DBCURSOR *)NULL)
  648.     {
  649.     return FALSE;
  650.     }
  651.  
  652.     /* Start a transaction block. We will exit without
  653.     ** committing, so the pubs database will
  654.     ** not be altered.
  655.     */
  656.     if ((dbcmd(dbproc, "begin tran") != SUCCEED) ||
  657.       (dbsqlexec(dbproc) != SUCCEED))
  658.     {
  659.     /* Error! Close the connection and exit */
  660.     dbclose(dbproc);
  661.     dbproc = (DBPROCESS *)NULL;
  662.     return FALSE;
  663.     }
  664.     while ((rc=dbresults(dbproc)) != NO_MORE_RESULTS)
  665.     {
  666.     if (rc == FAIL)
  667.     {
  668.       /* Error! Close the connection and exit */
  669.       dbclose(dbproc);
  670.       dbproc = (DBPROCESS *)NULL;
  671.       return FALSE;
  672.     }
  673.     }
  674.     /* Bind variables */
  675.     rc = dbcursorbind(hdbcursor, 1, NTBSTRINGBIND, 41, NULL,
  676.     (char far *)au_lname);
  677.     if (rc == FAIL)
  678.     {
  679.     return FALSE;
  680.     }
  681.     rc = dbcursorbind(hdbcursor, 2, NTBSTRINGBIND, 21, NULL,
  682.     (char far *)au_fname);
  683.     if (rc == FAIL)
  684.     {
  685.     return FALSE;
  686.     }
  687.     rc = dbcursorbind(hdbcursor, 3, NTBSTRINGBIND, 21, NULL,
  688.     (char far *)au_city);
  689.     if (rc == FAIL)
  690.     {
  691.     return FALSE;
  692.     }
  693.     rc = dbcursorbind(hdbcursor, 4, NTBSTRINGBIND, 3, NULL,
  694.     (char far *)au_state);
  695.     if (rc == FAIL)
  696.     {
  697.     return FALSE;
  698.     }
  699.     return (TRUE);
  700. }
  701.  
  702.  
  703. /****************************************************************************
  704.  
  705.     FUNCTION: CheckForScroll(HWND, int, int, int)
  706.  
  707.     PURPOSE:  Check if next output line will be out of client area
  708.  
  709.     PARAMETERS: hWnd - Handle to the window.
  710.         CurrentPosition - Current y coordinate for the line of
  711.             text just written to the client area.
  712.         Spacing - The height of the line (including the space
  713.             separating lines) of the text just written.
  714.         Length - The length of the line just written in device
  715.             units.
  716.  
  717.     RETURN:    Returns the Y coordinate for the next line of text.
  718.  
  719.     COMMENTS:
  720.  
  721.     Will determine if the next line of text will be out of the client
  722.     area.  If so will scroll the window for the next line.  Also validates
  723.     the current line of text so that a WM_PAINT will not clear it.
  724.  
  725. ****************************************************************************/
  726. int CheckForScroll(hWnd,CurrentPosition,Spacing, Length)
  727. HWND hWnd;
  728. int CurrentPosition;
  729. int Spacing;
  730. int Length;
  731. {
  732.     RECT rect;                /* RECT structure for validation */
  733.     rect.top = CurrentPosition;     /* top of last line of text     */
  734.     rect.bottom = CurrentPosition+Spacing+1; /* bottom of last line     */
  735.     rect.left = 1;            /* left most column of line     */
  736.     rect.right = Length+1;        /* right most column of line     */
  737.     ValidateRect(hWnd,(LPRECT)&rect);   /* validate line so that it is   */
  738.                     /* not blanked on next paint     */
  739.         
  740.     GetClientRect(hWnd,(LPRECT)&rect);    /* get rect for current client   */
  741.     if(CurrentPosition + (Spacing*2) > rect.bottom) /* will line fit     */
  742.     {
  743.                     /* if not scroll window and      */
  744.                     /* update client window         */
  745.     ScrollWindow(hWnd,0,-(Spacing+1),NULL,NULL);
  746.     UpdateWindow(hWnd);
  747.     return(CurrentPosition);
  748.     }
  749.     return(CurrentPosition+Spacing);
  750. }
  751.  
  752. /****************************************************************************
  753.  
  754.     FUNCTION: SQLTestProcessResults(HWND)
  755.  
  756.     PURPOSE:  If a valid dbprocess is present process all results from pending
  757.           select statement, output each field to client area.  Whenever
  758.           a new line is written to client area it is checked to see if
  759.           the client area needs to be scrolled.
  760.  
  761.     PARAMETERS: hWnd - Handle to the window.
  762.  
  763.     RETURN:    Returns the Y coordinate for the next line of text.
  764.  
  765.     COMMENTS:
  766.         This function will bind the fields in the select statement
  767.             to local variables, format an output string then
  768.             write that string to the client area via TextOut.
  769.  
  770. ****************************************************************************/
  771. BOOL SqlTestProcessResults(hWnd)
  772. HWND hWnd;
  773. {
  774.     HDC hDC;                /* display context         */
  775.     TEXTMETRIC tm;            /* text metric structure     */
  776.     char szOutputString[81];        /* general output string     */
  777.     int Y;                /* Y coordinate for text output  */
  778.     int Spacing;            /* Spacing between lines     */
  779.     unsigned short i;
  780.  
  781.     errhWnd = hWnd;
  782.     hDC = GetDC(hWnd);            /* get display context         */
  783.     GetTextMetrics(hDC, (LPTEXTMETRIC)(&tm)); /* get font info         */
  784.     Spacing = tm.tmExternalLeading + tm.tmHeight; /* set up spacing     */
  785.     Y = 1;                /* start at line 1         */
  786.     if(dbproc == (DBPROCESS *)NULL)    /* if process null, no results     */
  787.     {
  788.     ReleaseDC(hWnd,hDC);        /* free resources and return     */
  789.     return(TRUE);
  790.     }
  791.     SendMessage(hWnd,WM_ERASEBKGND,hDC,0L); /* always erase background     */
  792.     UpdateWindow(hWnd);            /* force painting of window     */
  793.     DBLOCKLIB();            /* lock down library         */
  794.  
  795.      /* Convert from OEM to ansi*/
  796.      for (i=0 ; i < NROWS ; i++)
  797.      {
  798.        if (pstat[i] & FTC_SUCCEED)
  799.        {        /* Print only if fetch succeeded */
  800.      OemToAnsi((LPSTR)(au_lname[i]), (LPSTR)(au_lname[i]));
  801.      OemToAnsi((LPSTR)(au_fname[i]), (LPSTR)(au_fname[i]));
  802.      OemToAnsi((LPSTR)(au_city[i]), (LPSTR)(au_city[i]));
  803.      OemToAnsi((LPSTR)(au_state[i]), (LPSTR)(au_state[i]));
  804.  
  805.      /* here we format each field and write it to client */
  806.      /* area checking to see if the client area needs to */
  807.      /* be scrolled after each line is written         */
  808.      sprintf(szOutputString,"Last Name: %s",au_lname[i]);
  809.      TextOut(hDC,1,Y,szOutputString,strlen(szOutputString));
  810.      Y = CheckForScroll(hWnd,Y,Spacing,strlen(szOutputString) * tm.tmMaxCharWidth);
  811.  
  812.      sprintf(szOutputString,"First Name: %s",au_fname[i]);
  813.      TextOut(hDC,1,Y,szOutputString,strlen(szOutputString));
  814.      Y = CheckForScroll(hWnd,Y,Spacing,strlen(szOutputString) * tm.tmMaxCharWidth);
  815.  
  816.      sprintf(szOutputString,"City:  %s, State:  %s",au_city[i], au_state[i]);
  817.      TextOut(hDC,1,Y,szOutputString,strlen(szOutputString));
  818.      Y = CheckForScroll(hWnd,Y,Spacing,strlen(szOutputString) * tm.tmMaxCharWidth);
  819.  
  820.      Y = CheckForScroll(hWnd,Y,Spacing,0); /* add extra line     */
  821.                               /* after each results */
  822.       }
  823.       else if (pstat[i] & FTC_MISSING)
  824.       {
  825.      sprintf(szOutputString,"Row %d is missing.", i+1);
  826.      TextOut(hDC,1,Y,szOutputString,strlen(szOutputString));
  827.      Y = CheckForScroll(hWnd,Y,Spacing,strlen(szOutputString) * tm.tmMaxCharWidth);
  828.  
  829.      Y = CheckForScroll(hWnd,Y,Spacing,0); /* add extra line     */
  830.       }
  831.     }
  832.  
  833.     DBUNLOCKLIB();                /* unlock library       */
  834.     ReleaseDC(hWnd,hDC);            /* free resource       */
  835.     return(TRUE);
  836. }
  837. /****************************************************************************
  838.  
  839.     FUNCTION: dbwinMessageHandler(DBPROCESS *, DBINT, DBSMALLINT, DBSMALLINT,
  840.             LPSTR)
  841.  
  842.     PURPOSE:  When the Data Server returns a message to dblib this function
  843.           will be called to process that message.  This function is
  844.           installed into dblib via MakeProcInstance.  It must be declared
  845.           as a FAR cdecl function, not as a FAR PASCAL function, unlike
  846.           other call back routines, as dblib conducts all of it's calls
  847.           in the cdecl fashion.  You must return 0 to dblib.
  848.  
  849.     RETURN:    Return 0
  850.  
  851.     COMMENTS:
  852.  
  853. ****************************************************************************/
  854.  
  855. int FAR dbwinMessageHandler(dbproc, msgno, msgstate, severity, msgtext)
  856. DBPROCESS        *dbproc;
  857. DBINT            msgno;
  858. DBSMALLINT       msgstate;
  859. DBSMALLINT       severity;
  860. LPSTR            msgtext;
  861. {
  862.     MessageBox(errhWnd,msgtext,(LPSTR)"SQL DataServer Message",MB_OK);
  863.     return(0);
  864. }
  865.  
  866. /****************************************************************************
  867.  
  868.     FUNCTION: dbwinErrorHandler(DBPROCESS *, int, int, int, LPSTR, LPSTR)
  869.  
  870.     PURPOSE:  When dblib returns an error message to the application this
  871.           function will be called to process that error.  This function is
  872.           installed into dblib via MakeProcInstance.  It must be declared
  873.           as a FAR cdecl function, not as a FAR PASCAL function, unlike
  874.           other call back routines, as dblib conducts all of it's calls
  875.           in the cdecl fashion.  You must return either INT_CANCEL,
  876.           INT_CONTINUE, or INT_EXIT to dblib.
  877.  
  878.     RETURN:    Return continuation code.
  879.  
  880.     COMMENTS:
  881.  
  882. ****************************************************************************/
  883.  
  884. int FAR dbwinErrorHandler(dbproc, severity, errno, oserr, dberrstr, oserrstr)
  885. DBPROCESS *dbproc;
  886. int severity;
  887. int errno;
  888. int oserr;
  889. LPSTR dberrstr;
  890. LPSTR oserrstr;
  891. {
  892.     MessageBox(errhWnd,dberrstr,(LPSTR)"DB-LIBRARY error",MB_ICONHAND | MB_OK);
  893.  
  894.     if (oserr != DBNOERR)    /* os error    */
  895.     {
  896.     MessageBox(errhWnd,oserrstr,(LPSTR)"Operating-System error",MB_ICONHAND | MB_OK);
  897.     }
  898.  
  899.     return(INT_CANCEL);    /* cancel command */
  900. }
  901. 
  902.