home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / sql / dblib / c / sqltestn / sqltestn.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-09  |  24.1 KB  |  712 lines

  1. /****************************************************************************
  2.  
  3.     PROGRAM: SqlTestn.c
  4.     Copyright (C) 1995-1997 Microsoft Corp.
  5.  
  6.     PURPOSE: SqlTest sample Windows applications
  7.  
  8.     FUNCTIONS:
  9.  
  10.     WinMain() - calls initialization function, processes message loop
  11.     SqlTestInit() - initializes window data and registers window
  12.     SqlTestWndProc() - processes messages
  13.     AboutSQL() - processes messages for "About" dialog box
  14.     SelectSQL() - processes input of author name
  15.     ConnectSQL() - processes input of server name and connects to server
  16.  
  17.     COMMENTS:
  18.  
  19.     WIN32 can have several copies of your application running at the
  20.     same time.  The variable hInst keeps track of which instance this
  21.     application is so that processing will be to the correct window.
  22.  
  23.     You only need to initialize the application once.  After it is
  24.     initialized, all other copies of the application will use the same
  25.     window class, and do not need to be separately initialized.
  26.  
  27. ****************************************************************************/
  28.  
  29. #include "windows.h"      /* required for all NT Windows applications*/
  30. #include "stdio.h"
  31. #define DBNTWIN32         /* needed to define environment         */
  32. #include "sqlfront.h"     /* standard dblib include file        */
  33. #include "sqldb.h"        /* standard dblib include file        */
  34. #include "sqltestn.h"     /* specific to this program            */
  35.  
  36. PDBPROCESS dbproc = (PDBPROCESS)NULL;
  37.                   /* dbprocess pointer for dblib connection*/
  38. HINSTANCE hInst;    /* current instance                */
  39. HWND ghWnd;      /* global window handle for handlers    */
  40. HWND errhWnd;    /* global window handle for current error*/
  41.  
  42. /****************************************************************************
  43.  
  44.     FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  45.  
  46.     PURPOSE: calls initialization function, processes message loop
  47.  
  48.     COMMENTS:
  49.  
  50.     This will initialize the window class if it is the first time this
  51.     application is run.  It then creates the window, and processes the
  52.     message loop until a PostQuitMessage is received.  It exits the
  53.     application by returning the value passed by the PostQuitMessage.
  54.  
  55. ****************************************************************************/
  56.  
  57. int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  58. HINSTANCE hInstance;                 /* current instance         */
  59. HINSTANCE hPrevInstance;                 /* previous instance         */
  60. LPSTR lpCmdLine;                 /* command line             */
  61. int nCmdShow;                     /* show-window type (open/icon) */
  62. {
  63.     HWND hWnd;                     /* window handle             */
  64.     MSG msg;                     /* message                 */
  65.  
  66.  
  67.     if (!hPrevInstance)            /* Has application been initialized? */
  68.         if (!SqlTestInit(hInstance))
  69.             return (0);        /* Exits if unable to initialize     */
  70.  
  71.     hInst = hInstance;            /* Saves the current instance         */
  72.  
  73.     hWnd = CreateWindow("SQL Test",               /* window class         */
  74.         "SQL Server Sample Windows NT Application", /* window name         */
  75.         WS_OVERLAPPEDWINDOW|WS_VISIBLE,            /* window style         */
  76.         CW_USEDEFAULT,                             /* x position             */
  77.         CW_USEDEFAULT,                             /* y position             */
  78.         CW_USEDEFAULT,                             /* width             */
  79.         CW_USEDEFAULT,                             /* height             */
  80.         NULL,                                      /* parent handle         */
  81.         NULL,                                      /* menu or child ID         */
  82.         hInstance,                                 /* instance             */
  83.         NULL);                                     /* additional info         */
  84.  
  85.     if (!hWnd)                      /* Was the window created? */
  86.         return (0);
  87.  
  88.     ghWnd = hWnd;                  /* set global handle         */
  89.     errhWnd = hWnd;
  90.  
  91.     ShowWindow(hWnd, SW_SHOW); /* Shows the window        */
  92.     UpdateWindow(hWnd);        /* Sends WM_PAINT message  */
  93.  
  94.     while (GetMessage(&msg, /* message structure */
  95.                 NULL,              /* handle of window receiving the message */
  96.                 0,             /* lowest message to examine */
  97.                 0))            /* highest message to examine    */
  98.     {
  99.         TranslateMessage(&msg);       /* Translates virtual key codes         */
  100.         DispatchMessage(&msg);       /* Dispatches message to window         */
  101.     }
  102.     return (msg.wParam);       /* Returns the value from PostQuitMessage */
  103. }
  104.  
  105.  
  106. /****************************************************************************
  107.  
  108.     FUNCTION: SqlTestInit(HANDLE)
  109.  
  110.     PURPOSE: Initializes window data and registers window class
  111.  
  112.     COMMENTS:
  113.  
  114.     Sets up a structure to register the window class.  Structure includes
  115.     such information as what function will process messages, what cursor
  116.     and icon to use, etc.
  117.  
  118. ****************************************************************************/
  119.  
  120. BOOL SqlTestInit(hInstance)
  121. HANDLE hInstance;                   /* current instance         */
  122. {
  123.     HANDLE hMemory;                   /* handle to allocated memory */
  124.     PWNDCLASS pWndClass;               /* structure pointer         */
  125.     BOOL bSuccess;                   /* RegisterClass() result     */
  126.  
  127.     hMemory = LocalAlloc(LPTR, sizeof(WNDCLASS));
  128.     pWndClass = (PWNDCLASS)hMemory;
  129.  
  130.     pWndClass->style = 0; /*CS_HREDRAW | CS_VREDRAW; */
  131.     pWndClass->lpfnWndProc = (WNDPROC)SqlTestWndProc;
  132.     pWndClass->hInstance = hInstance;
  133.     pWndClass->hIcon = LoadIcon(hInstance, "SQLITEST");
  134.     pWndClass->hCursor = LoadCursor(NULL, IDC_ARROW);
  135.     pWndClass->hbrBackground = GetStockObject(WHITE_BRUSH);
  136.     pWndClass->lpszMenuName = (LPSTR)"SQLTest";
  137.     pWndClass->lpszClassName = (LPSTR)"SQL Test";
  138.  
  139.     bSuccess = RegisterClass(pWndClass);
  140.  
  141.     LocalFree(hMemory);                    /* Returns it to NT */
  142.     return (bSuccess);         /* Returns result of registering the window */
  143. }
  144.  
  145. /****************************************************************************
  146.  
  147.     FUNCTION: SqlTestWndProc(HWND, unsigned, WORD, LONG)
  148.  
  149.     PURPOSE:  Processes messages
  150.  
  151.     MESSAGES:
  152.  
  153.     WM_SYSCOMMAND - system menu (About dialog box)
  154.     WM_CREATE     - create window
  155.     WM_DESTROY    - destroy window
  156.     WM_COMMAND    - application menus (Connect and Select dialog boxes
  157.  
  158.     COMMENTS:
  159.  
  160.     To process the ID_ABOUTSQL message. Call Dialog
  161.     box which will create the box according to the information in your
  162.     SqlTest.rc file and turn control over to the About() function.    When
  163.     it returns, free the intance address.
  164.     This same action will take place for the two menu items Connect and
  165.     Select.
  166.  
  167. ****************************************************************************/
  168.  
  169. LONG APIENTRY SqlTestWndProc(hWnd, message, wParam, lParam)
  170. HWND hWnd;                  /* window handle             */
  171. UINT message;                      /* type of message             */
  172. DWORD wParam;                  /* additional information         */
  173. LONG lParam;                  /* additional information         */
  174. {
  175.                       /* functions                  */
  176.     HMENU hMenu;              /* handle to the System menu         */
  177.  
  178.     switch (message)
  179.     {
  180.         case WM_SYSCOMMAND:        /* message: command from system menu */
  181.             if (wParam == ID_ABOUTSQL)
  182.             {
  183.                 DialogBox(hInst,         /* current instance         */
  184.                     (LPTSTR)"ABOUTSQL",         /* resource to use         */
  185.                     hWnd,             /* parent handle         */
  186.                     (DLGPROC) AboutSQL);         /* About() instance address */
  187.  
  188.                 break;
  189.             }
  190.             else                /* Lets NT process it         */
  191.                 return (DefWindowProc(hWnd, message, wParam, lParam));
  192.  
  193.         case WM_CREATE:                /* message: window being created */
  194.  
  195.             /* Get the handle of the System menu */
  196.             hMenu = GetSystemMenu(hWnd, FALSE);
  197.  
  198.             /* Add a separator to the menu */
  199.             AppendMenu(hMenu,                  /* menu handle         */
  200.                 MF_SEPARATOR,                      /* menu item to change */
  201.                 0,                      /* new menu item         */
  202.                 0);                      /* menu identifier     */
  203.  
  204.             /* Add new menu item to the System menu */
  205.           AppendMenu(hMenu,                  /* menu handle         */
  206.                 MF_STRING,                      /* menu item to change */
  207.                 ID_ABOUTSQL,                  /* menu identifier     */
  208.                 "A&bout SQL Test...");              /* new menu item         */
  209.  
  210.             dbinit();                                 /* initialize dblib    */
  211.     
  212.             /* Now make the message and error    */
  213.             /* Install the handler into dblib */    
  214.             dberrhandle((DBERRHANDLE_PROC)dbwinErrorHandler);
  215.             dbmsghandle((DBMSGHANDLE_PROC)dbwinMessageHandler);
  216.             break;
  217.     
  218.         case WM_COMMAND :            /* menu selections generate */
  219.                 
  220.             /* the WM_COMMAND message   */    
  221.             switch(wParam)            /* menu in WORD parameter   */
  222.             {
  223.                 case IDM_CONNECT :        /* connect to server        */
  224.                     DialogBox(hInst,        /* current instance         */
  225.                         "CONNECT",         /* resource to use         */
  226.                         hWnd,            /* parent handle         */
  227.                         (DLGPROC) ConnectSQL);     /* ConnectSQL() instance address */
  228.  
  229.                     break;
  230.     
  231.                 case IDM_SELECT :        /* select an author        */
  232.  
  233.                     DialogBox(hInst,         /* current instance         */
  234.                         "SELECT",         /* resource to use         */
  235.                         hWnd,             /* parent handle         */
  236.                         (DLGPROC) SelectSQL);         /* About() instance address */
  237.  
  238.                     break;
  239.             }
  240.             break;
  241.     
  242.         case WM_DBRESULTS :            /* a select has been issued */
  243.             SqlTestProcessResults(hWnd);    /* process results        */
  244.             break;
  245.  
  246.         case WM_DESTROY:          /* message: window being destroyed */
  247.             dbexit();              /* free any active dbprocesses     */
  248.             PostQuitMessage(0);
  249.             break;
  250.  
  251.         default:              /* Passes it on if unproccessed    */
  252.             return (DefWindowProc(hWnd, message, wParam, lParam));
  253.     }
  254.     
  255.     return (0L);
  256. }
  257.  
  258.  
  259. /****************************************************************************
  260.  
  261.     FUNCTION: AboutSQL(HWND, unsigned, WORD, LONG)
  262.  
  263.     PURPOSE:  Processes messages for "AboutSQL" dialog box
  264.  
  265.     MESSAGES:
  266.  
  267.     WM_INITDIALOG - initialize dialog box
  268.     WM_COMMAND    - Input received
  269.  
  270.     COMMENTS:
  271.  
  272.     No initialization is needed for this particular dialog box, but TRUE
  273.     must be returned to NT.
  274.  
  275.     Wait for user to click on "Ok" button, then close the dialog box.
  276.  
  277. ****************************************************************************/
  278.  
  279. LONG APIENTRY AboutSQL(hDlg, message, wParam, lParam)
  280. HWND hDlg;
  281. UINT message;
  282. DWORD wParam;
  283. LONG lParam;
  284. {
  285.     switch (message)
  286.     {
  287.         case WM_INITDIALOG:           /* message: initialize dialog box */
  288.             return (TRUE);
  289.  
  290.         case WM_COMMAND:              /* message: received a command */
  291.             if (wParam == IDOK)
  292.             {          /* "OK" box selected?         */
  293.                 EndDialog(hDlg, 0);          /* Exits the dialog box         */
  294.                 return (TRUE);
  295.             }
  296.             break;
  297.     }
  298.     return (FALSE);                  /* Didn't process a message    */
  299. }
  300. /****************************************************************************
  301.  
  302.     FUNCTION: SelectSQL(HWND, unsigned, WORD, LONG)
  303.  
  304.     PURPOSE:  Processes messages for "SelectSQL" dialog box
  305.  
  306.     MESSAGES:
  307.  
  308.     WM_INITDIALOG - initialize dialog box
  309.     WM_COMMAND    - Input received
  310.  
  311.     COMMENTS:
  312.  
  313.     No initialization is needed for this particular dialog box, but TRUE
  314.     must be returned to NT.
  315.     
  316.     Let user input into edit control the name of an author (the select
  317.     IS case sensitive).  When user presses OK, format the select statement
  318.     then send it to the server and execute it via dbsqlexec(). If the
  319.     dbsqlexec() SUCCEED's post a WM_DBRESULTS message so the results
  320.     may be retrieved and processed.
  321.  
  322.     Wait for user to click on "Ok" button, then close the dialog box.
  323.  
  324. ****************************************************************************/
  325.  
  326. LONG APIENTRY SelectSQL(hDlg, message, wParam, lParam)
  327. HWND hDlg;
  328. UINT message;
  329. DWORD wParam;
  330. LONG lParam;
  331. {
  332.     char szSelectAuthor[41];          /* string for authors name        */
  333.     char szServerMess[45];          /* string for server response        */
  334.     char szAName[40];              /* format string for author        */
  335.     switch (message)
  336.     {
  337.         case WM_INITDIALOG:           /* message: initialize dialog box */
  338.             SendDlgItemMessage(hDlg,       /* limit input to 40 characters   */
  339.                 AUTHORNAME,EM_LIMITTEXT,40,0L);
  340.             return (TRUE);
  341.  
  342.         case WM_COMMAND:              /* message: received a command */
  343.             errhWnd = hDlg;
  344.             switch(wParam)
  345.             {
  346.                 case IDOK :              /* "OK" box selected?         */
  347.                     *szSelectAuthor = '\0';   /* Null author             */
  348.                     GetDlgItemText(hDlg,AUTHORNAME, (LPSTR)szSelectAuthor, MAX_ANAME);
  349.                     if(dbproc == (PDBPROCESS)NULL) /* if not a valid process*/
  350.                     {
  351.                         /* No server to query        */
  352.                         MessageBox(hDlg,
  353.                             "No SQL Server Connected to Query",
  354.                             "SQL Test",MB_ICONHAND | MB_OK);
  355.                     }
  356.                     else
  357.                         if(*szSelectAuthor != '\0') /* if a name exists */
  358.                         {
  359.                             DBLOCKLIB();        /* lock down the library */
  360.                             /* format the select statement */
  361.                             dbcmd(dbproc,
  362.                                 (LPSTR)"select au_id, au_lname,"
  363.                                 "au_fname, phone, address, city, state, zip");
  364.                             dbcmd(dbproc, (LPSTR)" from authors");
  365.                             dbcmd(dbproc, (LPSTR)" where au_lname = ");
  366.                             sprintf(szAName,"'%s'",szSelectAuthor);
  367.                             dbcmd(dbproc,(LPSTR)szAName);
  368.                             if (dbsqlexec(dbproc) == FAIL)
  369.                             {
  370.                                 sprintf(szServerMess,    /* error, not in db */
  371.                                     "%s not found in database pubs",
  372.                                     szSelectAuthor);
  373.                                 MessageBox(hDlg,
  374.                                     (LPSTR)szServerMess,(LPSTR)"SQL Test",
  375.                                     MB_ICONHAND | MB_OK);
  376.                             }
  377.                             else    /* query SUCCEEDed so             */
  378.                             {    /* post message to process results    */
  379.                                 PostMessage(GetParent(hDlg),WM_DBRESULTS,0,0L);
  380.                             }
  381.                             DBUNLOCKLIB();        /* unlock library    */
  382.                         }
  383.                     EndDialog(hDlg, 0);          /* Exits the dialog box         */
  384.                     return (TRUE);
  385.                     break;
  386.         
  387.                 case IDCANCEL :
  388.                     EndDialog(hDlg, 0);          /* cancelled select */
  389.                     return(TRUE);
  390.                     break;
  391.             }
  392.     break;
  393.     }
  394.     
  395.     return (FALSE); /* Didn't process a message    */
  396. }
  397. /****************************************************************************
  398.  
  399.     FUNCTION: ConnectSQL(HWND, unsigned, WORD, LONG)
  400.  
  401.     PURPOSE:  Processes messages for "Connect" dialog box
  402.  
  403.     MESSAGES:
  404.  
  405.     WM_INITDIALOG - initialize dialog box
  406.     WM_COMMAND    - Input received
  407.  
  408.     COMMENTS:
  409.  
  410.     No initialization is needed for this particular dialog box, but TRUE
  411.     must be returned to NT.
  412.  
  413.     Wait for user to click on "Ok" button, then close the dialog box.
  414.  
  415. ****************************************************************************/
  416.  
  417. LONG APIENTRY ConnectSQL(hDlg, message, wParam, lParam)
  418. HWND hDlg;
  419. UINT message;
  420. DWORD wParam;
  421. LONG lParam;
  422. {
  423.     char szSQLServer[31];
  424.     static PLOGINREC LoginRec;
  425.  
  426.     *szSQLServer = '\0';
  427.     switch (message)
  428.     {
  429.         case WM_INITDIALOG:           /* message: initialize dialog box*/
  430.             SendDlgItemMessage(hDlg,       /* limit input to 30 characters  */
  431.                 SQL_SERVER,EM_LIMITTEXT,30,0L);
  432.             return (TRUE);
  433.  
  434.         case WM_COMMAND:              /* message: received a command*/
  435.             errhWnd = hDlg;
  436.             switch(wParam)
  437.             {
  438.                 case IDOK :              /* "OK" box selected?        */
  439.                     GetDlgItemText(hDlg,SQL_SERVER,
  440.                         (LPSTR)szSQLServer,
  441.                         MAX_SERVERNAME); /* get Server name */
  442.                     if(*szSQLServer != '\0') /* was something input        */
  443.                     {
  444.                         DBLOCKLIB();        /* lock down library        */
  445.                         if (dbproc != (PDBPROCESS)NULL) /* if an active     */
  446.                             /* process close it */
  447.                             dbclose(dbproc);
  448.                         if ((LoginRec = dblogin()) != (PLOGINREC)NULL) /* get loginrec */
  449.                         {
  450.                             DBSETLUSER(LoginRec,(char far *)"sa"); /* set user  */
  451.                             DBSETLVERSION(LoginRec,DBVER60);
  452.  
  453.                             /* now open the connection to server */
  454.                             if((dbproc = dbopen(LoginRec,(LPSTR)szSQLServer))
  455.                                 == (PDBPROCESS)NULL)
  456.                             {
  457.                                 /* if NULL couldn't connect    */
  458.                                 dbfreelogin(LoginRec);
  459.                             }
  460.                             else /* got connect so use the pubs database */
  461.                             {
  462.                                 dbuse(dbproc,(LPSTR)"pubs");
  463.                                 dbfreelogin(LoginRec);
  464.                             }
  465.                         }
  466.                         else /* memory allocation problem */
  467.                             MessageBox(hDlg, "Could not allocate Login Record","System Error", MB_ICONHAND | MB_OK);
  468.                         DBUNLOCKLIB(); /* done unlock library    */
  469.                     }
  470.                     EndDialog(hDlg, 0);          /* Exits the dialog box         */
  471.                     return (TRUE);
  472.                     break;
  473.                 
  474.                 case IDCANCEL :
  475.                     EndDialog(hDlg, 0);
  476.                     return(TRUE);
  477.                     break;
  478.         
  479.             }
  480.     break;
  481.     }
  482.     
  483.     return (FALSE); /* Didn't process a message */
  484. }
  485.  
  486. /****************************************************************************
  487.  
  488.     FUNCTION: CheckForScroll(HWND, int, int, int)
  489.  
  490.     PURPOSE:  Check if next output line will be out of client area
  491.  
  492.     PARAMETERS:
  493.     hWnd - Handle to the window.
  494.     CurrentPosition - Current y coordinate for the line of
  495.         text just written to the client area.
  496.     Spacing - The height of the line (including the space
  497.         separating lines) of the text just written.
  498.     Length - The length of the line just written in device units.
  499.  
  500.     RETURN:    Returns the Y coordinate for the next line of text.
  501.  
  502.     COMMENTS:
  503.  
  504.     Will determine if the next line of text will be out of the client
  505.     area.  If so will scroll the window for the next line.  Also validates
  506.     the current line of text so that a WM_PAINT will not clear it.
  507.  
  508. ****************************************************************************/
  509. int CheckForScroll(hWnd,CurrentPosition,Spacing, Length)
  510. HWND hWnd;
  511. int CurrentPosition;
  512. int Spacing;
  513. int Length;
  514. {
  515.     RECT rect;                /* RECT structure for validation */
  516.     rect.top = CurrentPosition;     /* top of last line of text     */
  517.     rect.bottom = CurrentPosition+Spacing+1; /* bottom of last line     */
  518.     rect.left = 1;            /* left most column of line     */
  519.     rect.right = Length+1;        /* right most column of line     */
  520.     ValidateRect(hWnd,(LPRECT)&rect);   /* validate line so that it is   */
  521.     
  522.     /* not blanked on next paint     */
  523.         
  524.     GetClientRect(hWnd,(LPRECT)&rect);    /* get rect for current client   */
  525.     if(CurrentPosition + (Spacing*2) > rect.bottom) /* will line fit     */
  526.     {
  527.         /* if not scroll window and      */
  528.         /* update client window         */
  529.         ScrollWindow(hWnd,0,-(Spacing+1),NULL,NULL);
  530.         UpdateWindow(hWnd);
  531.         return(CurrentPosition);
  532.     }
  533.     
  534.     return(CurrentPosition+Spacing);
  535. }
  536.  
  537. /****************************************************************************
  538.  
  539.     FUNCTION: SQLTestProcessResults(HWND)
  540.  
  541.     PURPOSE:  If a valid dbprocess is present process all results from pending
  542.         select statement, output each field to client area.  Whenever
  543.         a new line is written to client area it is checked to see if
  544.         the client area needs to be scrolled.
  545.  
  546.     PARAMETERS: hWnd - Handle to the window.
  547.  
  548.     RETURN:    Returns the Y coordinate for the next line of text.
  549.  
  550.     COMMENTS:
  551.     This function will bind the fields in the select statement
  552.     to local variables, format an output string then
  553.     write that string to the client area via TextOut.
  554.     It is called by the main message processing loop
  555.     SQLTestWndProc via the message WM_DBRESULTS.
  556.  
  557. ****************************************************************************/
  558. BOOL SqlTestProcessResults(hWnd)
  559. HWND hWnd;
  560. {
  561.     HDC hDC;                /* display context         */
  562.     TEXTMETRIC tm;            /* text metric structure     */
  563.     char szId[12];            /* Author ID for binding     */
  564.     char szLastName[41];        /* Author last name for binding     */
  565.     char szFirstName[21];        /* Author first name for binding */
  566.     char szPhone[13];            /* Author phone for binding     */
  567.     char szAddress[41];            /* Author address for binding     */
  568.     char szCity[21];            /* Author city for binding     */
  569.     char szState[3];            /* Author state for binding     */
  570.     char szZip[6];            /* Author zipcode for binding     */
  571.     char szOutputString[81];        /* general output string     */
  572.     RETCODE result_code;        /* results code from dbresults     */
  573.     int Y;                /* Y coordinate for text output  */
  574.     int Spacing;            /* Spacing between lines     */
  575.     errhWnd = hWnd;
  576.  
  577.     hDC = GetDC(hWnd);            /* get display context         */
  578.     GetTextMetrics(hDC, (LPTEXTMETRIC)&tm); /* get font info         */
  579.     Spacing = tm.tmExternalLeading + tm.tmHeight; /* set up spacing     */
  580.     Y = 1;                /* start at line 1         */
  581.     
  582.     if(dbproc == (PDBPROCESS)NULL)    /* if process null, no results     */
  583.     {
  584.         ReleaseDC(hWnd,hDC);        /* free resources and return     */
  585.         return(TRUE);
  586.     }
  587.     
  588.     SendMessage(hWnd,WM_ERASEBKGND,(DWORD)hDC,0L); /* always erase background     */
  589.     UpdateWindow(hWnd);            /* force painting of window     */
  590.     DBLOCKLIB();            /* lock down library         */
  591.  
  592.     /* get all results from the query*/
  593.     while(((result_code = dbresults(dbproc)) != NO_MORE_RESULTS) && result_code != FAIL)
  594.     {
  595.         if(result_code == SUCCEED)    /* if results ready         */
  596.         {
  597.             /* Bind all data of interest     */
  598.             dbbind(dbproc,1,NTBSTRINGBIND, 12L, (LPSTR)szId);
  599.             dbbind(dbproc,2,NTBSTRINGBIND, 41L, (LPSTR)szLastName);
  600.             dbbind(dbproc,3,NTBSTRINGBIND, 21L, (LPSTR)szFirstName);
  601.             dbbind(dbproc,4,NTBSTRINGBIND, 13L, (LPSTR)szPhone);
  602.             dbbind(dbproc,5,NTBSTRINGBIND, 41L, (LPSTR)szAddress);
  603.             dbbind(dbproc,6,NTBSTRINGBIND, 21L, (LPSTR)szCity);
  604.             dbbind(dbproc,7,NTBSTRINGBIND, 3L, (LPSTR)szState);
  605.             dbbind(dbproc,8,NTBSTRINGBIND, 6L, (LPSTR)szZip);
  606.             while(dbnextrow(dbproc) != NO_MORE_ROWS) /* get all rows     */
  607.             {
  608.                 /* here we format each field and write it to client */
  609.                 /* area checking to see if the client area needs to */
  610.                 /* be scrolled after each line is written        */
  611.                 sprintf(szOutputString,"Author ID: %s",szId);
  612.                 TextOut(hDC,1,Y,szOutputString,strlen(szOutputString));
  613.                 Y = CheckForScroll(hWnd,Y,Spacing,strlen(szOutputString) * tm.tmMaxCharWidth);
  614.  
  615.                 sprintf(szOutputString,"Last Name: %s",szLastName);
  616.                 TextOut(hDC,1,Y,szOutputString,strlen(szOutputString));
  617.                 Y = CheckForScroll(hWnd,Y,Spacing,strlen(szOutputString) * tm.tmMaxCharWidth);
  618.  
  619.                 sprintf(szOutputString,"Address:   %s",szAddress);
  620.                 TextOut(hDC,1,Y,szOutputString,strlen(szOutputString));
  621.                 Y = CheckForScroll(hWnd,Y,Spacing,strlen(szOutputString) * tm.tmMaxCharWidth);
  622.  
  623.                 sprintf(szOutputString,"City:      %s",szCity);
  624.                 TextOut(hDC,1,Y,szOutputString,strlen(szOutputString));
  625.                 Y = CheckForScroll(hWnd,Y,Spacing,strlen(szOutputString) * tm.tmMaxCharWidth);
  626.  
  627.                 sprintf(szOutputString,"State:     %s",szState);
  628.                 TextOut(hDC,1,Y,szOutputString,strlen(szOutputString));
  629.                 Y = CheckForScroll(hWnd,Y,Spacing,strlen(szOutputString) * tm.tmMaxCharWidth);
  630.  
  631.                 sprintf(szOutputString,"ZipCode:   %s",szZip);
  632.                 TextOut(hDC,1,Y,szOutputString,strlen(szOutputString));
  633.                 Y = CheckForScroll(hWnd,Y,Spacing,strlen(szOutputString) * tm.tmMaxCharWidth);
  634.  
  635.                 sprintf(szOutputString,"Telephone: %s",szPhone);
  636.                 TextOut(hDC,1,Y,szOutputString,strlen(szOutputString));
  637.                 Y = CheckForScroll(hWnd,Y,Spacing,strlen(szOutputString) * tm.tmMaxCharWidth);
  638.  
  639.                 Y = CheckForScroll(hWnd,Y,Spacing,0); /* add extra line     */
  640.                 /* after each results */
  641.             }
  642.         }
  643.     }
  644.  
  645.     DBUNLOCKLIB();                /* unlock library       */
  646.     ReleaseDC(hWnd,hDC);            /* free resource       */
  647.     return(TRUE);
  648. }
  649.  
  650. /****************************************************************************
  651.  
  652.     FUNCTION: dbwinMessageHandler(PDBPROCESS, DBINT, DBSMALLINT, DBSMALLINT,
  653.         LPSTR)
  654.  
  655.     PURPOSE:  When the Data Server returns a message to dblib this function
  656.         will be called to process that message.  This function is
  657.         installed into dblib via MakeProcInstance.  It must be declared
  658.         as a FAR cdecl function, not as a FAR PASCAL function, unlike
  659.         other call back routines, as dblib conducts all of it's calls
  660.         in the cdecl fashion.  You must return 0 to dblib.
  661.  
  662.     RETURN: Return 0
  663.  
  664.     COMMENTS:
  665.  
  666. ****************************************************************************/
  667.  
  668. int API dbwinMessageHandler(dbproc, msgno, msgstate, severity, msgtext)
  669. DBPROCESS        *dbproc;
  670. DBINT            msgno;
  671. INT              msgstate;
  672. INT              severity;
  673. CHAR             *msgtext;
  674. {
  675.     MessageBox(errhWnd,msgtext,(LPSTR)"SQL DataServer Message",MB_OK);
  676.     return(0);
  677. }
  678.  
  679. /****************************************************************************
  680.  
  681.     FUNCTION: dbwinErrorHandler(PDBPROCESS, int, int, int, LPSTR, LPSTR)
  682.  
  683.     PURPOSE: When dblib returns an error message to the application this
  684.         function will be called to process that error.  This function is
  685.         installed into dblib via MakeProcInstance.  It must be declared
  686.         as a FAR cdecl function, not as a FAR PASCAL function, unlike
  687.         other call back routines, as dblib conducts all of it's calls
  688.         in the cdecl fashion.  You must return either INT_CANCEL,
  689.         INT_CONTINUE, or INT_EXIT to dblib.
  690.  
  691.     RETURN: Return continuation code.
  692.  
  693.     COMMENTS:
  694.  
  695. ****************************************************************************/
  696.  
  697. int API dbwinErrorHandler(dbproc, severity, errno, oserr, dberrstr, oserrstr)
  698. PDBPROCESS dbproc;
  699. int severity;
  700. int errno;
  701. int oserr;
  702. LPSTR dberrstr;
  703. LPSTR oserrstr;
  704. {
  705.     MessageBox(errhWnd,dberrstr,(LPSTR)"DB-LIBRARY error",MB_ICONHAND | MB_OK);
  706.  
  707.     if (oserr != DBNOERR)    /* os error    */
  708.         MessageBox(errhWnd,oserrstr,(LPSTR)"Operating-System error",MB_ICONHAND | MB_OK);
  709.  
  710.     return(INT_CANCEL);    /* cancel command */
  711. }
  712.