home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / odbc / qurydemo / main.c next >
Encoding:
C/C++ Source or Header  |  1997-10-06  |  48.6 KB  |  1,501 lines

  1. /*
  2.     PROGRAM: QURYDEMO
  3.     ========
  4.  
  5.     PURPOSE:
  6.     ========
  7.     demonstrates a simple MDI application that allows a user to
  8.     simultaneously connect to multiple hetrogeneous databases
  9.     and perform SQL queries to get results.
  10.  
  11.     FUNCTIONS:
  12.     ==========
  13.     WinMain() - main routine
  14.     MainWndProc() - processes Main Application Window messages
  15.     MDIChildProc() - processes MDI child window messages
  16.     ToolbarProc() - processes tool bar messages
  17.     StatusbarProc() - processes Status bar messages
  18.     ConnectDlgProc() - processes Connection Dialog box messages
  19.     DisconnectDlgProc() - processes Disconnect Dialog box messages
  20.     AboutDlgProc() - processes messages for About dialog box
  21.     MDIChildDlgProc() - processes messages for dummy child dialog box
  22.             in MDI child window
  23.     DrawBitmap() - draws bitmaps for toolbuttons
  24.  
  25.     COMMENTS:
  26.     =========
  27.     Created by Microsoft Corporation.
  28. */
  29.  
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <time.h>
  33.  
  34. #include <windows.h>
  35. #ifdef WIN32
  36. #include <windowsx.h>
  37. #else
  38. #include "w16macro.h"
  39. #endif
  40. #include "qurydemo.h"
  41.  
  42. CONSTSTR(szKeyWord,             "query demo, features");
  43.  
  44.  
  45. /*
  46.     FUNCTION: WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  47.     COMMENTS: Application Entry Routine.
  48.           Register Classes. Create Main Window and MDI Child Window.
  49.           Process Main Message Loop.
  50. */
  51.  
  52. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  53. {
  54.    MSG     msg;            //msg structure
  55.    WNDCLASS    wc;         //class structure
  56.    HICON       hMainIcon;      //App Icon
  57.    HICON       hMDIChildIcon;      //MDI Child Icon
  58.    HWND        hWndMDIChild;       //temp MDI Child Window Handle
  59.    char        szBuffer[MAXBUFLEN+1];  //temp string buffer to check class name
  60.    BOOL        bDialogMessage = FALSE; //temp boolean to check dilogbox msgs
  61.    HACCEL      hAccel;         //accelerator table handle
  62.  
  63.    hAppInstance = hInstance;
  64.  
  65.    // check if application is already running, if
  66.    // so make it active and bring it in focus
  67.  
  68.    if (hWndFrame = FindWindow(ODBCFRAMECLASS, NULL)) {
  69.       hWndFrame = GetLastActivePopup(hWndFrame);
  70.       if (IsIconic(hWndFrame))
  71.          OpenIcon(hWndFrame);
  72.       else
  73.          BringWindowToTop(hWndFrame);
  74.       ACTIVATEWINDOW(hWndFrame);
  75.       return (FALSE);
  76.    }
  77.  
  78.    // initialize ODBC Driver Manager Interface
  79.  
  80.    if (!InitSQLEnvironment()) {
  81.       MessageBox(hWndFrame, INITERROR, EXECERROR, MB_OK|MB_ICONHAND);
  82.       return (FALSE);
  83.    }
  84.  
  85.    // register window classes for the application - Main Window Class
  86.  
  87.    wc.style = 0;
  88.    wc.lpfnWndProc = MainWndProc;
  89.    wc.cbClsExtra = 0;
  90.    wc.cbWndExtra = 0;
  91.    wc.hInstance = hAppInstance;
  92.    wc.hIcon = hMainIcon = LoadIcon(hAppInstance, APPICON);
  93.    wc.hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
  94.    wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1);
  95.    wc.lpszMenuName =  QURYDEMOMENU;
  96.    wc.lpszClassName = ODBCFRAMECLASS;
  97.  
  98.    if (!RegisterClass(&wc)) {
  99.       MessageBox(hWndFrame, CLASSERROR, EXECERROR, MB_OK|MB_ICONHAND|MB_TASKMODAL);
  100.       return (FALSE);
  101.    }
  102.  
  103.    // register Toolbar Class
  104.  
  105.    wc.hIcon = (HICON)NULL;
  106.    wc.lpszMenuName =  NULL;
  107.    wc.lpfnWndProc = ToolbarProc;
  108.    wc.lpszClassName = ODBCTOOLCLASS;
  109.  
  110.    if (!RegisterClass(&wc)) {
  111.       MessageBox(hWndFrame, CLASSERROR, EXECERROR, MB_OK|MB_ICONHAND|MB_TASKMODAL);
  112.       return (FALSE);
  113.    }
  114.  
  115.    // register Statusbar Class
  116.  
  117.    wc.lpfnWndProc = StatusbarProc;
  118.    wc.lpszClassName = ODBCSTATUSCLASS;
  119.  
  120.    if (!RegisterClass(&wc)) {
  121.       MessageBox(hWndFrame, CLASSERROR, EXECERROR, MB_OK|MB_ICONHAND|MB_TASKMODAL);
  122.       return (FALSE);
  123.    }
  124.  
  125.    // register MDI Child Window Class
  126.  
  127.    wc.hIcon = hMDIChildIcon = LoadIcon(hAppInstance, QUERYWINDOWICON);
  128.    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  129.    wc.cbWndExtra = CBWNDEXTRA;
  130.    wc.lpszClassName = ODBCMDICLASS;
  131.    wc.lpfnWndProc = MDIChildProc;
  132.  
  133.    if (!RegisterClass(&wc)) {
  134.       MessageBox(hWndFrame, CLASSERROR, EXECERROR, MB_OK|MB_ICONHAND|MB_TASKMODAL);
  135.       return (FALSE);
  136.    }
  137.  
  138.    // create Main window and the MDI Client window
  139.  
  140.    if (!(hWndFrame = CreateWindow(ODBCFRAMECLASS, APPTITLE, WS_OVERLAPPEDWINDOW,
  141.                                   CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  142.                                   (HWND)NULL, (HMENU)NULL, hAppInstance, NULL))) {
  143.       MessageBox(hWndFrame, CREATEMAINERR, EXECERROR, MB_OK|MB_ICONHAND|MB_TASKMODAL);
  144.       return (FALSE);
  145.    }
  146.  
  147.    ShowWindow(hWndFrame, nCmdShow);
  148.    UpdateWindow(hWndFrame);
  149.  
  150.    // load accelerators
  151.  
  152.    hAccel = LoadAccelerators(hAppInstance, APPACCELERATOR);
  153.  
  154.    // acquire and dispatch messages until a WM_QUIT message is received
  155.  
  156.    while (GetMessage(&msg, (HWND)NULL, 0, 0)) {
  157.  
  158.       // check for App accelerators
  159.  
  160.       if (TranslateAccelerator(hWndFrame, hAccel, &msg))
  161.          continue;
  162.  
  163.       // check for MDI accelerators
  164.  
  165.       if (TranslateMDISysAccel(hWndMDIClient, &msg))
  166.          continue;
  167.  
  168.       // each MDI Child has a modeless dialog in its client area
  169.       // to provide tab controls. Check for Modeless Dialog msgs.
  170.  
  171.       for (hWndMDIChild = GetWindow(hWndMDIClient, GW_CHILD); hWndMDIChild; hWndMDIChild = GetWindow(hWndMDIChild, GW_HWNDNEXT)) {
  172.          GetClassName(hWndMDIChild, szBuffer, MAXBUFLEN);
  173.          if (strcmp(szBuffer, ODBCMDICLASS))
  174.             continue;
  175.          if (IsDialogMessage((HWND)GetWindowLong(hWndMDIChild, GWLAPP_HDLG), &msg)) {
  176.             bDialogMessage = TRUE;
  177.             break;
  178.          }
  179.       }
  180.  
  181.       if (bDialogMessage) {
  182.          bDialogMessage = FALSE;
  183.          continue;
  184.       }
  185.  
  186.       // if the message does not need special processing, dispatch it
  187.  
  188.       TranslateMessage(&msg);
  189.       DispatchMessage(&msg);
  190.    }
  191.  
  192.    // free memory used by ODBC Driver Manager interface
  193.  
  194.    FreeSQLEnvironment();
  195.  
  196.  
  197.    // free Icon resources
  198.  
  199.    if (hMainIcon)
  200.       DestroyIcon(hMainIcon);
  201.  
  202.    if (hMDIChildIcon)
  203.       DestroyIcon(hMDIChildIcon);
  204.  
  205.    return (msg.wParam);
  206. }
  207.  
  208. /*
  209.     FUNCTION: MainWndProc(HWND hWnd, UINT   message, WPARAM wParam, LPARAM lParam)
  210.     COMMENTS: Windows Callback procedure to handle Window messages.
  211.               Menu Commands and System Command messages are handled by
  212.               this main window.
  213. */
  214.  
  215. long CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  216. {
  217.    switch (message) {
  218.       static int  iToolY;         //remember Toolbar height for resize
  219.       static int  iStatusY;       //remember Statusbar height for resize
  220.  
  221.      case WM_CREATE:
  222.       {
  223.          CLIENTCREATESTRUCT  ccs;        //MDIclient window structure
  224.          HDC         hDC;        //Device Context handle
  225.          SIZE            sizeBar;    //Size of a text bar
  226.          RECT            rectCombo;      //Size of combo box
  227.  
  228.          // Create child windows
  229.          //1. combobox to display connections - DSN, SQLHDBC
  230.          //2. combobox to display SQLHSTMT on current SQLHDBC
  231.          //3. Toolbar to put toolbuttons
  232.          //4. Statusbat to display current action, date and time
  233.          //5. MDI Client Window to process MDI children
  234.  
  235.          hWndCrsrList = CreateWindow(COMBOBOXCLASS, NULL,
  236.                                      WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
  237.                                      WS_VSCROLL | CBS_DROPDOWNLIST | CBS_DISABLENOSCROLL,
  238.                                      5, 2, 180, 150, hWnd,
  239.                                      (HMENU)IDW_CRSRLIST, hAppInstance, NULL);
  240.  
  241.          hWndStmtList = CreateWindow(COMBOBOXCLASS, NULL,
  242.                                      WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
  243.                                      WS_VSCROLL | CBS_DROPDOWNLIST | CBS_DISABLENOSCROLL,
  244.                                      190, 2, 150, 150, hWnd,
  245.                                      (HMENU)IDW_STMTLIST, hAppInstance, NULL);
  246.  
  247.          hWndToolbar = CreateWindow(ODBCTOOLCLASS, NULL,
  248.                                     WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
  249.                                     0, 0, 0, 0, hWnd, (HMENU)IDW_TOOLBAR, hAppInstance, NULL);
  250.  
  251.          hWndStatusbar = CreateWindow(ODBCSTATUSCLASS, NULL,
  252.                                       WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
  253.                                       0, 0, 0, 0, hWnd, (HMENU)IDW_STATUSBAR, hAppInstance, NULL);
  254.  
  255.          ccs.hWindowMenu = GetSubMenu(GetMenu(hWnd), WINDOWMENUPLACE);
  256.          ccs.idFirstChild = IDM_MDICHILD;
  257.  
  258.          hWndMDIClient = CreateWindow(MDICLIENTCLASS, NULL,
  259.                                       WS_CHILD | WS_CLIPSIBLINGS |
  260.                                       WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE,
  261.                                       0, 0, 0, 0, hWnd,
  262.                                       (HMENU)IDW_MDICLIENT, hAppInstance, (LPSTR)&ccs);
  263.  
  264.          // check to see if any of the above window creation failed
  265.  
  266.          if (!hWndCrsrList || !hWndStmtList || !hWndToolbar || !hWndStatusbar || !hWndMDIClient) {
  267.             MessageBox(hWnd, CREATEMAINERR, EXECERROR, MB_OK|MB_ICONHAND|MB_TASKMODAL);
  268.             PostMessage(hWnd, WM_CLOSE, 0, 0);
  269.             break;
  270.          }
  271.          // calculate proper text height for tool and status bars
  272.  
  273.          GetWindowRect(hWndStmtList, &rectCombo);
  274.          iToolY = rectCombo.bottom - rectCombo.top + TOOLBARMARGINY;
  275.  
  276.          if (hDC = GetDC(hWndStatusbar)) {
  277.             GetTextExtentPoint(hDC, ALPHABETS, strlen(ALPHABETS), &sizeBar);
  278.             ReleaseDC(hWndStatusbar, hDC);
  279.             iStatusY = sizeBar.cy + STATUSBARMARGINY;
  280.          }
  281.          else {
  282.             iStatusY = 0;
  283.             DestroyWindow(hWndStatusbar);
  284.          }
  285.  
  286.          break;
  287.       }
  288.  
  289.      case WM_GETMINMAXINFO:
  290.  
  291.       // limit minimum size of the main window
  292.  
  293.       ((MINMAXINFO FAR*)lParam)->ptMinTrackSize.x =
  294.          max(MINWIDTH, rectStatusText.right-rectStatusText.left+iTimex+iDatex+14);
  295.       ((MINMAXINFO FAR*)lParam)->ptMinTrackSize.y = MINHEIGHT;
  296.       break;
  297.  
  298.      case WM_SIZE: // resize children
  299.       {
  300.          WORD    wWidth = LOWORD(lParam);    //width of rectangle
  301.          WORD    wHeight = HIWORD(lParam);   //height of rectangle
  302.  
  303.          MoveWindow(hWndToolbar, 0, 0, wWidth, iToolY, TRUE);
  304.          MoveWindow(hWndStatusbar, 0, wHeight-iStatusY, wWidth, iStatusY, TRUE);
  305.          InvalidateRect(hWndStatusbar, NULL, TRUE);
  306.          MoveWindow(hWndMDIClient, 0, iToolY, wWidth, wHeight-iStatusY-iToolY, TRUE);
  307.          break;
  308.       }
  309.  
  310.      case WM_SYSCOLORCHANGE: // inform 3D controls of color change
  311.  
  312.       //      Ctl3dColorChange();
  313.       break;
  314.  
  315.      case WM_SYSCOMMAND: // close comboboxes if dropped down
  316.  
  317.       SendMessage(hWndCrsrList, CB_SHOWDROPDOWN, (WPARAM)FALSE, 0);
  318.       SendMessage(hWndStmtList, CB_SHOWDROPDOWN, (WPARAM)FALSE, 0);
  319.       return (DefFrameProc(hWnd, hWndMDIClient, message, wParam, lParam));
  320.  
  321.      case WM_INITMENUPOPUP: // initialize popup menus
  322.       {
  323.          int iMenuId;    //Menu ID being processed
  324.          int nItems;         //# of menu items
  325.          int nPos;           //Menu Position
  326.  
  327.          //ignore the msg if it is for a system menu
  328.  
  329.          if (HIWORD(lParam))
  330.             break;
  331.  
  332.          // Go through the menu items for current popup menu
  333.          // and enable/disable menu item, if required
  334.  
  335.          nItems = GetMenuItemCount((HMENU)wParam);
  336.          for (nPos = 0; nPos < nItems; nPos++)
  337.             switch (iMenuId = GetMenuItemID((HMENU)wParam, nPos)) {
  338.               case IDM_DISCONNECT:
  339.               case IDM_NEW:
  340.  
  341.                EnableMenuItem((HMENU)wParam, iMenuId, MF_BYCOMMAND|
  342.                               ((SendMessage(hWndCrsrList, CB_GETCOUNT, 0, 0) > 0)
  343.                                ? MF_ENABLED
  344.                                : MF_GRAYED));
  345.                break;
  346.  
  347.               case IDM_QUERY:
  348.               case IDM_TILE:
  349.               case IDM_CASCADE:
  350.               case IDM_ICONS:
  351.               case IDM_CLOSEALL:
  352.  
  353.                EnableMenuItem((HMENU)wParam, iMenuId, MF_BYCOMMAND|
  354.                               (GetWindow(hWndMDIClient, GW_CHILD)
  355.                                ? MF_ENABLED
  356.                                : MF_GRAYED));
  357.                break;
  358.  
  359.               default:
  360.  
  361.                break;
  362.             }
  363.          break;
  364.       }
  365.  
  366.      case WM_MENUSELECT: // update status bar to reflect menu selection
  367.       {
  368.          int iMenuFlag;      //Check menu type
  369.          HMENU   hMenu;              //Menu Handle
  370.          char    szMenuName[MAXBUFLEN+1];//Menu Name
  371.  
  372.          // store Menuitem ID as a state value for text display
  373.  
  374.          wStatusText = GET_WM_MENUSELECT_CMD(wParam, lParam);
  375.  
  376.          // process popup menus ie non menuitem selections
  377.  
  378.          iMenuFlag = GET_WM_MENUSELECT_FLAGS(wParam, lParam);
  379.  
  380.          // if the selected menu is a system popup menu
  381.  
  382.          if (wStatusText && (iMenuFlag & MF_SYSMENU) && (iMenuFlag & MF_POPUP))
  383.             wStatusText = IDM_POPUPAPPSYS;
  384.  
  385.          // else if the selected menu is a popup menu check menu names
  386.          // OR check if it is a control popup menu of maximized MDI Child window
  387.  
  388.          else if (wStatusText && (iMenuFlag & MF_POPUP)) {
  389.             hMenu = (HMENU)wStatusText;
  390.             GetMenuString(hMenu, 0, szMenuName, MAXBUFLEN, MF_BYPOSITION);
  391.             if (!strcmp(szMenuName, MENUITEMCONNECT))
  392.                wStatusText = IDM_POPUPLOGIN;
  393.             else if (!strcmp(szMenuName, MENUITEMQUERY))
  394.                wStatusText = IDM_POPUPQUERY;
  395.             else if (!strcmp(szMenuName, MENUITEMTILE))
  396.                wStatusText = IDM_POPUPWINDOW;
  397.             else if (!strcmp(szMenuName, MENUITEMAPPHELP))
  398.                wStatusText = IDM_POPUPHELP;
  399.             else if (GetMenuString(hMenu, SC_NEXTWINDOW, szMenuName, MAXBUFLEN, MF_BYCOMMAND)>0)
  400.                wStatusText = IDM_POPUPMDISYS;
  401.             else
  402.                wStatusText = 0;
  403.          }
  404.  
  405.          // invalidate status bar for repaint
  406.  
  407.          InvalidateRect(hWndStatusbar, &rectStatusText, TRUE);
  408.          break;
  409.       }
  410.  
  411.      case WM_COMMAND: // process menu commands
  412.  
  413.       switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  414.  
  415.         case IDM_CONNECT: // bring up connect dialog & do connect processing
  416.  
  417.          DialogBox(hAppInstance, CONNECTDIALOG, hWnd,ConnectDlgProc);
  418.          break;
  419.  
  420.         case IDM_DRIVERCONNECT: // let the driver do the dialogs
  421.  
  422.          DriverConnectDatabase(hWnd);
  423.          break;
  424.  
  425.         case IDM_DISCONNECT: // bringup disconnect dlg and do disconnects
  426.  
  427.          DialogBox(hAppInstance, DISCONNECTDIALOG, hWnd,DisconnectDlgProc);
  428.          break;
  429.  
  430.         case IDM_QUERY: // process execute query request
  431.  
  432.          ExecuteQuery();
  433.          break;
  434.  
  435.         case IDM_EXIT: // process exit request
  436.  
  437.          SendMessage(hWndFrame, WM_CLOSE, 0, 0);
  438.          break;
  439.  
  440.         case IDM_NEW: // create a new query window on current connect
  441.  
  442.          NewQueryWindow();
  443.          break;
  444.  
  445.         case IDM_TILE: // let MDI Client tile the MDI children
  446.  
  447.          SendMessage(hWndMDIClient, WM_MDITILE, 0, 0);
  448.          break;
  449.  
  450.         case IDM_CASCADE: // let MDI Client cascade MDI children
  451.  
  452.          SendMessage(hWndMDIClient, WM_MDICASCADE, 0, 0);
  453.          break;
  454.  
  455.         case IDM_ICONS: // let MDI Client arrange iconic MDI children
  456.  
  457.          SendMessage(hWndMDIClient, WM_MDIICONARRANGE, 0, 0);
  458.          break;
  459.  
  460.         case IDM_CLOSEALL: // Close all open windows and free hstmts
  461.          {
  462.             HWND    hWndTemp;   //temp window handle
  463.  
  464.             // hide MDI Client Windows to avoid repaints
  465.  
  466.             ShowWindow(hWndMDIClient,SW_HIDE);
  467.             while (hWndTemp = GetWindow(hWndMDIClient, GW_CHILD))
  468.                SendMessage(hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndTemp, 0);
  469.             ShowWindow(hWndMDIClient, SW_SHOW);
  470.             break;
  471.          }
  472.  
  473.         case IDM_APPHELP: // bring up Samples Help file
  474.  
  475.          WinHelp(hWnd, SAMPLESHELPFILE, HELP_KEY,(DWORD)(LPTSTR)szKeyWord);
  476.             break;
  477.  
  478.         case IDM_ABOUT: // bringup About dialog
  479.  
  480.          DialogBox(hAppInstance, ABOUTDIALOG, hWnd, AboutDlgProc);
  481.          break;
  482.  
  483.         case IDW_CRSRLIST: // change current cursor ?
  484.  
  485.          if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE)
  486.             ChangeCurrentCursor(GET_WM_COMMAND_HWND(wParam, lParam));
  487.          else if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_KILLFOCUS)
  488.             PostMessage(GET_WM_COMMAND_HWND(wParam, lParam), CB_SHOWDROPDOWN,
  489.                         (WPARAM)FALSE, 0);
  490.          else
  491.             DefFrameProc(hWnd, hWndMDIClient, WM_COMMAND, wParam, lParam);
  492.          break;
  493.  
  494.         case IDW_STMTLIST: // change current hstmt?
  495.  
  496.          if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE)
  497.             ChangeCurrentQuery(GET_WM_COMMAND_HWND(wParam, lParam));
  498.          else if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_KILLFOCUS)
  499.             PostMessage(GET_WM_COMMAND_HWND(wParam, lParam), CB_SHOWDROPDOWN,
  500.                         (WPARAM)FALSE, 0);
  501.          else
  502.             DefFrameProc(hWnd, hWndMDIClient, WM_COMMAND, wParam, lParam);
  503.          break;
  504.  
  505.         default:
  506.  
  507.          DefFrameProc(hWnd, hWndMDIClient, WM_COMMAND, wParam, lParam);
  508.          break;
  509.       }
  510.       break;
  511.  
  512.      case WM_CLOSE: //close all MDI windows, hdbcs & hstmts, else fail
  513.  
  514.       return (CloseDatabases()
  515.               ? DefFrameProc(hWnd, hWndMDIClient, message, wParam, lParam)
  516.               : FALSE);
  517.  
  518.      case WM_DESTROY:
  519.  
  520.       // Close Help File if open
  521.  
  522.       WinHelp(hWnd, SAMPLESHELPFILE, HELP_QUIT, 0);
  523.       PostQuitMessage(0);
  524.       break;
  525.  
  526.      default:
  527.  
  528.       return (DefFrameProc(hWnd, hWndMDIClient, message, wParam, lParam));
  529.    }
  530.    return (0);
  531. }
  532.  
  533. /*
  534.     FUNCTION: MDIChildProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  535.     COMMENTS: Window Procedure for MDI Child windows
  536. */
  537.  
  538. long CALLBACK MDIChildProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  539. {
  540.    switch (message) {
  541.       HWND    hWndTemp;   //temporary window handle
  542.       DLGPROC lpDlgProc;  //procedure address for modeless dialog
  543.  
  544.      case WM_CREATE:
  545.  
  546.       // create child windows
  547.       // 1. Modeless Dialog box in the background to process tabs
  548.       // 2. Static Text to display prompt
  549.       // 3. Edit Control to type SQL text
  550.       // 4. List Box to display results
  551.       // store dialog handle for future reference
  552.       // set focus to edit control
  553.  
  554.       // if create failed due to low system resources
  555.  
  556.       if (!hWnd)
  557.          break;
  558.  
  559.       hWndActiveChild = hWnd;
  560.       hWndTemp = CreateDialog(hAppInstance, MDICHILDDIALOG, hWndActiveChild, MDIChildDlgProc);
  561.  
  562.       // check to see if the dialog was created?, if not destroy this window
  563.  
  564.       if (!hWndTemp) {
  565.          return (-1);
  566.       }
  567.  
  568.       SetWindowLong(hWnd, GWLAPP_HDLG, (LONG)hWndTemp);
  569.       SetFocus(GetDlgItem(hWndTemp, IDTEXT_SQL));
  570.       break;
  571.  
  572.      case WM_SIZE: {
  573.         WORD    wWidth;         //New Width of MDI Child
  574.         WORD    wHeight;        //New Height of MDI Child
  575.         HDC     hDC;            //Device Context
  576.         char    szBuffer[MAXBUFLEN+1];  //Static Control Text
  577.         int nStrLen;        //Buffer Length
  578.         SIZE    size;           //Screen size for text display
  579.  
  580.         // call default procedure first, to let MDI position the child & then move its children
  581.  
  582.         DefMDIChildProc(hWnd, message, wParam, lParam);
  583.  
  584.         // move child windows with proper screen size for text display
  585.  
  586.         wWidth = LOWORD(lParam);
  587.         wHeight = HIWORD(lParam);
  588.         hWndTemp = (HWND)GetWindowLong(hWnd, GWLAPP_HDLG);
  589.  
  590.         nStrLen = GetWindowText(GetDlgItem(hWndTemp, IDTEXT_PRMPT), szBuffer, MAXBUFLEN);
  591.         hDC = GetDC(hWnd);
  592.         GetTextExtentPoint(hDC, szBuffer, nStrLen, &size);
  593.         ReleaseDC(hWnd, hDC);
  594.  
  595.         MoveWindow(hWndTemp, 0, 0, wWidth, wHeight, TRUE);
  596.         MoveWindow(GetDlgItem(hWndTemp, IDTEXT_PRMPT), 0, 0, size.cx+2, size.cy+2, TRUE);
  597.         MoveWindow(GetDlgItem(hWndTemp, IDTEXT_SQL), size.cx+3, 0, wWidth - (size.cx+2), size.cy+2, TRUE);
  598.         MoveWindow(GetDlgItem(hWndTemp, IDLIST_RSLT), 0, size.cy+3, wWidth, wHeight - (size.cy+2), TRUE);
  599.         break;
  600.      }
  601.  
  602.      case WM_MENUSELECT: // update status bar to reflect menu selection
  603.       {
  604.          int iMenuFlag;      //Check menu type
  605.  
  606.          // store the Menu Item Id as a state value for text display
  607.  
  608.          wStatusText = GET_WM_MENUSELECT_CMD(wParam, lParam);
  609.  
  610.          // if none of the menuitems was selected, check if
  611.          // the control popup menu is selected.
  612.  
  613.          iMenuFlag = GET_WM_MENUSELECT_FLAGS(wParam, lParam);
  614.  
  615.          // if the selected menu is a system popup menu
  616.  
  617.          if (wStatusText && (iMenuFlag & MF_SYSMENU) && (iMenuFlag & MF_POPUP))
  618.             wStatusText = IDM_POPUPMDISYS;
  619.  
  620.          // invalidate status bar for repaint
  621.  
  622.          InvalidateRect(hWndStatusbar, &rectStatusText, TRUE);
  623.          break;
  624.       }
  625.  
  626.      case WM_MDIACTIVATE:
  627.  
  628.       // check if the display of comboboxes require a change
  629.  
  630.       if (GET_WM_MDIACTIVATE_FACTIVATE(hWnd, wParam, lParam) &&
  631.           (hWndActiveChild) && (hWndActiveChild != hWnd)) {
  632.          hWndActiveChild = hWnd;
  633.          DisplayNewCrsrAndStmt();
  634.       }
  635.       break;
  636.  
  637.      case WM_MOUSEACTIVATE:
  638.  
  639.       // current window has changed, update comboboxes.
  640.  
  641.       hWndActiveChild = hWnd;
  642.       DisplayNewCrsrAndStmt();
  643.       break;
  644.  
  645.      case WM_SETFOCUS:
  646.  
  647.       // pass on the focus to the edit box for user to type in SQL
  648.  
  649.       SetFocus(GetDlgItem((HWND)GetWindowLong(hWnd, GWLAPP_HDLG), IDTEXT_SQL));
  650.       break;
  651.  
  652.      case WM_DESTROY:
  653.  
  654.       // check if the window was being destroyed while creation failed
  655.  
  656.       if (!hWnd)
  657.          break;
  658.  
  659.       // close the window and free instance thunk for modeless dialog
  660.  
  661.       CloseQueryWindow(hWnd);
  662.       lpDlgProc = (DLGPROC)GetWindowLong((HWND)GetWindowLong(hWnd, GWLAPP_HDLG), DWL_DLGPROC);
  663.       DestroyWindow((HWND)GetWindowLong(hWnd, GWLAPP_HDLG));
  664.       FreeProcInstance(lpDlgProc);
  665.       if (hWnd == hWndActiveChild)
  666.          hWndActiveChild = (HWND)NULL;
  667.       break;
  668.  
  669.      default:
  670.  
  671.       return (DefMDIChildProc(hWnd, message, wParam, lParam));
  672.    }
  673.    return (0);
  674. }
  675.  
  676. /*
  677.     FUNCTION: ToolbarProc(HWND hWnd, UINT   message, WPARAM wParam, LPARAM lParam)
  678.     COMMENTS: callback window procedure for toolbar window.
  679.           Handle pain and mouse messages to paint the toolbar and
  680.           provide default button behaviour for toolbar buttons.
  681. */
  682.  
  683. long CALLBACK ToolbarProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  684. {
  685.    switch (message) {
  686.       static HBITMAP  hbmpNewQuery;           //btn1 bitmap handle
  687.       static HBITMAP  hbmpRunQuery;           //btn2 bitmap handle
  688.       static RECT stNewQuery;         //btn1 rectangle
  689.       static RECT stRunQuery;                     //btn2 rectangle
  690.       POINT       stMousePosition;        //current mouse pos
  691.       BOOL        bButtonPosition;        //mouse pos flag
  692.       static BOOL bNewQueryBtnDown = FALSE;   //was btn1 down before?
  693.       static BOOL bRunQueryBtnDown = FALSE;   //was btn2 down before?
  694.       static int  nLastButtonDown = 0;        //Which btn was down before?
  695.  
  696.      case WM_CREATE:
  697.  
  698.       // load bitmaps for buttons
  699.       // initialize static rectangles for button positions on toolbar
  700.       // initialize state variable for status text display
  701.  
  702.       hbmpNewQuery = LoadBitmap(hAppInstance, BMP_NEWQUERY);
  703.       hbmpRunQuery = LoadBitmap(hAppInstance, BMP_RUNQUERY);
  704.  
  705.       stNewQuery.left   = BTTNX;
  706.       stNewQuery.right  = BTTNX+BTTNWIDTH+1;
  707.       stNewQuery.top    = BTTNY;
  708.       stNewQuery.bottom = BTTNY+BTTNHEIGHT+1;
  709.  
  710.       stRunQuery.left   = BTTNX+BTTNWIDTH+BTTNMARGIN;
  711.       stRunQuery.right  = BTTNX+BTTNWIDTH+BTTNMARGIN+BTTNWIDTH+1;
  712.       stRunQuery.top    = BTTNY;
  713.       stRunQuery.bottom = BTTNY+BTTNHEIGHT+1;
  714.  
  715.       wStatusText = 0;
  716.       break;
  717.  
  718.      case WM_DESTROY:
  719.  
  720.       // delete bitmap handles
  721.  
  722.       if (hbmpNewQuery)
  723.          DeleteObject(hbmpNewQuery);
  724.       if (hbmpRunQuery)
  725.          DeleteObject(hbmpRunQuery);
  726.       break;
  727.  
  728.      case WM_LBUTTONDOWN:
  729.  
  730.       // Check if the mouse key lies on any one of the buttons
  731.       // if so, set state variable to reflect that button and
  732.       // invalidate proper regions on tool & status bars for update.
  733.       // set capture on mouse movements till the mouse key is
  734.       // released.
  735.  
  736.       stMousePosition.x = LOWORD(lParam);
  737.       stMousePosition.y = HIWORD(lParam);
  738.  
  739.       if (PtInRect(&stNewQuery, stMousePosition)) {
  740.          bNewQueryBtnDown = TRUE;
  741.          wStatusText = nLastButtonDown = IDM_NEW;
  742.          SetCapture(hWnd);
  743.          InvalidateRect(hWnd, &stNewQuery, TRUE);
  744.          InvalidateRect(hWndStatusbar, &rectStatusText, TRUE);
  745.       }
  746.       else if (PtInRect(&stRunQuery, stMousePosition)) {
  747.          bRunQueryBtnDown = TRUE;
  748.          wStatusText = nLastButtonDown = IDM_QUERY;
  749.          SetCapture(hWnd);
  750.          InvalidateRect(hWnd, &stRunQuery, TRUE);
  751.          InvalidateRect(hWndStatusbar, &rectStatusText, TRUE);
  752.       }
  753.       break;
  754.  
  755.      case WM_LBUTTONUP:
  756.  
  757.       // check if the mouse movements from key down movements
  758.       // were captured, if so process the key release state.
  759.       // if the key was released in the same button where it
  760.       // was pressed, it is equivalent to a button click.
  761.  
  762.       if (hWnd != GetCapture())
  763.          break;
  764.  
  765.       stMousePosition.x = LOWORD(lParam);
  766.       stMousePosition.y = HIWORD(lParam);
  767.  
  768.       if (bNewQueryBtnDown && PtInRect(&stNewQuery, stMousePosition)) {
  769.          bNewQueryBtnDown = FALSE;
  770.          nLastButtonDown = 0;
  771.          InvalidateRect(hWnd, &stNewQuery, TRUE);
  772.          PostMessage(hWndFrame, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_NEW, 0, 0));
  773.          SendMessage(hWndCrsrList, CB_SHOWDROPDOWN, (WPARAM)FALSE, 0);
  774.          SendMessage(hWndStmtList, CB_SHOWDROPDOWN, (WPARAM)FALSE, 0);
  775.       }
  776.       else if (bRunQueryBtnDown && PtInRect(&stRunQuery, stMousePosition)) {
  777.          bRunQueryBtnDown = FALSE;
  778.          nLastButtonDown = 0;
  779.          InvalidateRect(hWnd, &stRunQuery, TRUE);
  780.          PostMessage(hWndFrame, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_QUERY, 0, 0));
  781.          SendMessage(hWndCrsrList, CB_SHOWDROPDOWN, (WPARAM)FALSE, 0);
  782.          SendMessage(hWndStmtList, CB_SHOWDROPDOWN, (WPARAM)FALSE, 0);
  783.       }
  784.  
  785.       ReleaseCapture();
  786.       wStatusText = 0;
  787.       InvalidateRect(hWndStatusbar, &rectStatusText, TRUE);
  788.       break;
  789.  
  790.      case WM_MOUSEMOVE:
  791.  
  792.       // process mouse movement only if the mouse key was pressed
  793.       // down and its movements were being captured. If the mouse
  794.       // moves outside of the currently depressed button, it needs
  795.       // to be drawn again with normal state.
  796.  
  797.       if (hWnd != GetCapture())
  798.          break;
  799.  
  800.       stMousePosition.x = LOWORD(lParam);
  801.       stMousePosition.y = HIWORD(lParam);
  802.  
  803.       if (nLastButtonDown == IDM_NEW) {
  804.          bButtonPosition = PtInRect(&stNewQuery, stMousePosition);
  805.          if (bNewQueryBtnDown != bButtonPosition) {
  806.             bNewQueryBtnDown = bButtonPosition;
  807.             InvalidateRect(hWnd, &stNewQuery, TRUE);
  808.          }
  809.       }
  810.       else if (nLastButtonDown == IDM_QUERY) {
  811.          bButtonPosition = PtInRect(&stRunQuery, stMousePosition);
  812.          if (bRunQueryBtnDown != bButtonPosition) {
  813.             bRunQueryBtnDown = bButtonPosition;
  814.             InvalidateRect(hWnd, &stRunQuery, TRUE);
  815.          }
  816.       }
  817.       break;
  818.  
  819.      case WM_PAINT:
  820.       {
  821.          PAINTSTRUCT ps;     //paint structure
  822.          RECT        rect;       //rectangle for tool bar
  823.          HDC     hDC;        //device context handle
  824.          int     iWidth;     //tool bar width
  825.          int     iHeight;    //tool bar height
  826.          HPEN        hLtGrayPen; //buttonface color pen
  827.          HPEN        hGrayPen;   //buttonshadow color pen
  828.          int     btnx;       //button x coordinate position
  829.  
  830.          if (!(hDC = BeginPaint(hWnd, &ps)))
  831.             break;
  832.  
  833.          GetClientRect(hWnd, &rect);
  834.          iWidth = rect.right;
  835.          iHeight = rect.bottom;
  836.  
  837.          hLtGrayPen = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNFACE));
  838.          hGrayPen = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW));
  839.  
  840.          // draw background and border
  841.  
  842.          SelectObject(hDC, GetStockObject(LTGRAY_BRUSH));
  843.          SelectObject(hDC, hLtGrayPen);
  844.          Rectangle(hDC, 0, 0, iWidth, iHeight);
  845.  
  846.          SelectObject(hDC, GetStockObject(BLACK_PEN));
  847.          MoveToEx(hDC, 0, iHeight-1, NULL);
  848.          LineTo(hDC, iWidth, iHeight-1);
  849.  
  850.          SelectObject(hDC, GetStockObject(WHITE_PEN));
  851.          MoveToEx(hDC, 0, 0, NULL);
  852.          LineTo(hDC, iWidth, 0);
  853.  
  854.          // draw tool bar buttons (new query, run query)
  855.          // check state variables to draw proper button state
  856.  
  857.          btnx = BTTNX;
  858.          SelectObject(hDC, GetStockObject(BLACK_PEN));
  859.          DRAWBTTNRECT(hDC, btnx, BTTNY, BTTNWIDTH, BTTNHEIGHT);
  860.          DrawBitmap(hDC, (bNewQueryBtnDown?btnx+3:btnx+2), (bNewQueryBtnDown?BTTNY+3:BTTNY+2), hbmpNewQuery);
  861.          SelectObject(hDC, (bNewQueryBtnDown ? hGrayPen : GetStockObject(WHITE_PEN)));
  862.          DRAWBTTNLIFT1(hDC, btnx, BTTNY, BTTNWIDTH, BTTNHEIGHT);
  863.          SelectObject(hDC, (bNewQueryBtnDown ? hLtGrayPen : hGrayPen));
  864.          DRAWBTTNLIFT2(hDC, btnx, BTTNY, BTTNWIDTH, BTTNHEIGHT);
  865.  
  866.          btnx += BTTNWIDTH+BTTNMARGIN;
  867.          SelectObject(hDC, GetStockObject(BLACK_PEN));
  868.          DRAWBTTNRECT(hDC, btnx, BTTNY, BTTNWIDTH, BTTNHEIGHT);
  869.          DrawBitmap(hDC, (bRunQueryBtnDown?btnx+3:btnx+2), (bRunQueryBtnDown?BTTNY+3:BTTNY+2), hbmpRunQuery);
  870.          SelectObject(hDC, (bRunQueryBtnDown ? hGrayPen : GetStockObject(WHITE_PEN)));
  871.          DRAWBTTNLIFT1(hDC, btnx, BTTNY, BTTNWIDTH, BTTNHEIGHT);
  872.          SelectObject(hDC, (bRunQueryBtnDown ? hLtGrayPen : hGrayPen));
  873.          DRAWBTTNLIFT2(hDC, btnx, BTTNY, BTTNWIDTH, BTTNHEIGHT);
  874.  
  875.          SelectObject(hDC, GetStockObject(WHITE_PEN));
  876.          EndPaint(hWnd, &ps);
  877.  
  878.          // delete create objects
  879.  
  880.          if (hLtGrayPen)
  881.             DeleteObject(hLtGrayPen);
  882.          if (hGrayPen)
  883.             DeleteObject(hGrayPen);
  884.          break;
  885.       }
  886.  
  887.      default:
  888.  
  889.       return (DefWindowProc(hWnd, message, wParam, lParam));
  890.    }
  891.    return (0);
  892. }
  893.  
  894. /*
  895.     FUNCTION: StatusbarProc(HWND hWnd, UINT   message, WPARAM wParam, LPARAM lParam)
  896.     COMMENTS: callback window procedure for status bar.
  897.           process paint messages and timer messages to update current
  898.           state, date and time
  899. */
  900.  
  901. long CALLBACK StatusbarProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  902. {
  903.    switch (message) {
  904.       static RECT DateTimeRect; // remember for frequent updates
  905.  
  906.      case WM_CREATE:
  907.       {
  908.          HDC hDC;        // device context
  909.          SIZE    sizeText;       // size of status text box
  910.          SIZE    sizeTime;       // size of time display box
  911.          SIZE    sizeDate;       // size of date display box
  912.  
  913.          // start a timer for periodic updates to date and time display
  914.          // find out width of status text, date and time display boxes
  915.  
  916.          SetTimer(hWnd,  (UINT)IDT_STATUSTIMER, (UINT)TIMERDELAY, NULL);
  917.  
  918.          iTimex = iDatex = 0;
  919.          rectStatusText.left = 2;
  920.          rectStatusText.top = 3;
  921.  
  922.          if (hDC = GetDC(hWnd)) {
  923.             GetTextExtentPoint(hDC, STATUSNEW, strlen(STATUSNEW), &sizeText);
  924.             GetTextExtentPoint(hDC, TIMETEXT, strlen(TIMETEXT), &sizeTime);
  925.             GetTextExtentPoint(hDC, DATETEXT, strlen(DATETEXT), &sizeDate);
  926.             ReleaseDC(hWnd, hDC);
  927.             rectStatusText.right = sizeText.cx + rectStatusText.left;
  928.             iTimex = sizeTime.cx;
  929.             iDatex = sizeDate.cx;
  930.          }
  931.          break;
  932.       }
  933.  
  934.      case WM_TIMER:
  935.  
  936.       // invalidate only the date&time area for update
  937.  
  938.       InvalidateRect(hWnd, &DateTimeRect, TRUE);
  939.       break;
  940.  
  941.      case WM_PAINT:
  942.       {
  943.          HDC     hDC;            //device context
  944.          PAINTSTRUCT ps;         //paint structure
  945.          RECT        rect;                   //status bar rect
  946.          int     iWidth;                 //status bar width
  947.          int     iHeight;                //status bar height
  948.          HPEN        hLtGrayPen;             //btnface color pen
  949.          HPEN        hGrayPen;               //btnshadow color pen
  950.          char        szText[MAXBUFLEN];      //text buffer for display
  951.          time_t      tCurrentTime;           //current date&time
  952.          struct tm   stTime;                 //date&time structure
  953.  
  954.          if (!(hDC = BeginPaint(hWnd, &ps)))
  955.             break;
  956.  
  957.          GetClientRect(hWnd, &rect);
  958.          iWidth = rect.right;
  959.          iHeight = rect.bottom;
  960.          rectStatusText.bottom = iHeight-2;
  961.  
  962.          hLtGrayPen = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNFACE));
  963.          hGrayPen = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW));
  964.  
  965.          // paint background and border
  966.  
  967.          SelectObject(hDC, GetStockObject(LTGRAY_BRUSH));
  968.          SelectObject(hDC, hLtGrayPen);
  969.          Rectangle(hDC, 0, 0, iWidth, iHeight);
  970.  
  971.          SelectObject(hDC, GetStockObject(BLACK_PEN));
  972.          MoveToEx(hDC, 0, 0, NULL);
  973.          LineTo(hDC, iWidth, 0);
  974.          SelectObject(hDC, GetStockObject(WHITE_PEN));
  975.          MoveToEx(hDC, 0, 1, NULL);
  976.          LineTo(hDC, iWidth, 1);
  977.  
  978.          // draw text boxes for status, time and date display
  979.  
  980.          SelectObject(hDC, hGrayPen);
  981.          MoveToEx(hDC, rectStatusText.left, rectStatusText.bottom, NULL);
  982.          LineTo(hDC, rectStatusText.left, rectStatusText.top);
  983.          LineTo(hDC, rectStatusText.right, rectStatusText.top);
  984.          SelectObject(hDC, GetStockObject(WHITE_PEN));
  985.          LineTo(hDC, rectStatusText.right, rectStatusText.bottom);
  986.          LineTo(hDC, rectStatusText.left, rectStatusText.bottom);
  987.  
  988.          SelectObject(hDC, hGrayPen);
  989.          MoveToEx(hDC, iWidth-2, 3, NULL);
  990.          LineTo(hDC, iWidth-iDatex-2, 3);
  991.          LineTo(hDC, iWidth-iDatex-2, iHeight-2);
  992.          SelectObject(hDC, GetStockObject(WHITE_PEN));
  993.          LineTo(hDC, iWidth-2, iHeight-2);
  994.          LineTo(hDC, iWidth-2, 3);
  995.  
  996.          SelectObject(hDC, hGrayPen);
  997.          MoveToEx(hDC, iWidth-iDatex-6, 3, NULL);
  998.          LineTo(hDC, iWidth-iTimex-iDatex-6, 3);
  999.          LineTo(hDC, iWidth-iTimex-iDatex-6, iHeight-2);
  1000.          SelectObject(hDC, GetStockObject(WHITE_PEN));
  1001.          LineTo(hDC, iWidth-iDatex-6, iHeight-2);
  1002.          LineTo(hDC, iWidth-iDatex-6, 3);
  1003.  
  1004.          // draw status text in the display box based on current
  1005.          // value of wStatusText global flag
  1006.  
  1007.          SetBkMode(hDC, TRANSPARENT);
  1008.          SetTextColor(hDC, GetSysColor(COLOR_BTNTEXT));
  1009.  
  1010.          switch (wStatusText) {
  1011.            case IDM_POPUPAPPSYS:
  1012.  
  1013.             strcpy(szText, STATUSPOPUPAPPSYS);
  1014.             break;
  1015.  
  1016.            case IDM_POPUPMDISYS:
  1017.  
  1018.             strcpy(szText, STATUSPOPUPMDISYS);
  1019.             break;
  1020.  
  1021.            case SC_RESTORE:
  1022.  
  1023.             strcpy(szText, STATUSRESTORE);
  1024.             break;
  1025.  
  1026.            case SC_MOVE:
  1027.  
  1028.             strcpy(szText, STATUSMOVE);
  1029.             break;
  1030.  
  1031.            case SC_SIZE:
  1032.  
  1033.             strcpy(szText, STATUSSIZE);
  1034.             break;
  1035.  
  1036.            case SC_MINIMIZE:
  1037.  
  1038.             strcpy(szText, STATUSMINIMIZE);
  1039.             break;
  1040.  
  1041.            case SC_MAXIMIZE:
  1042.  
  1043.             strcpy(szText, STATUSMAXIMIZE);
  1044.             break;
  1045.  
  1046.            case SC_CLOSE:
  1047.  
  1048.             strcpy(szText, STATUSCLOSE);
  1049.             break;
  1050.  
  1051.            case SC_NEXTWINDOW:
  1052.  
  1053.             strcpy(szText, STATUSNEXTWINDOW);
  1054.             break;
  1055.  
  1056.            case SC_PREVWINDOW:
  1057.  
  1058.             strcpy(szText, STATUSPREVWINDOW);
  1059.             break;
  1060.  
  1061.            case SC_TASKLIST:
  1062.  
  1063.             strcpy(szText, STATUSTASKLIST);
  1064.             break;
  1065.  
  1066.            case IDM_POPUPLOGIN:
  1067.  
  1068.             strcpy(szText, STATUSPOPUPLOGIN);
  1069.             break;
  1070.  
  1071.            case IDM_CONNECT:
  1072.  
  1073.             strcpy(szText, STATUSCONNECT);
  1074.             break;
  1075.  
  1076.            case IDM_DRIVERCONNECT:
  1077.  
  1078.             strcpy(szText, STATUSDRIVERCONNECT);
  1079.             break;
  1080.  
  1081.            case IDM_DISCONNECT:
  1082.  
  1083.             strcpy(szText, STATUSDISCONNECT);
  1084.             break;
  1085.  
  1086.            case IDM_EXIT:
  1087.  
  1088.             strcpy(szText, STATUSEXIT);
  1089.             break;
  1090.  
  1091.            case IDM_POPUPQUERY:
  1092.  
  1093.             strcpy(szText, STATUSPOPUPQUERY);
  1094.             break;
  1095.  
  1096.            case IDM_QUERY:
  1097.  
  1098.             strcpy(szText, STATUSQUERY);
  1099.             break;
  1100.  
  1101.            case IDM_NEW:
  1102.  
  1103.             strcpy(szText, STATUSNEW);
  1104.             break;
  1105.  
  1106.            case IDM_POPUPWINDOW:
  1107.  
  1108.             strcpy(szText, STATUSPOPUPWINDOW);
  1109.             break;
  1110.  
  1111.            case IDM_TILE:
  1112.  
  1113.             strcpy(szText, STATUSTILE);
  1114.             break;
  1115.  
  1116.            case IDM_CASCADE:
  1117.  
  1118.             strcpy(szText, STATUSCASCADE);
  1119.             break;
  1120.  
  1121.            case IDM_ICONS:
  1122.  
  1123.             strcpy(szText, STATUSICONS);
  1124.             break;
  1125.  
  1126.            case IDM_CLOSEALL:
  1127.  
  1128.             strcpy(szText, STATUSCLOSEALL);
  1129.             break;
  1130.  
  1131.            case IDM_POPUPHELP:
  1132.  
  1133.             strcpy(szText, STATUSPOPUPHELP);
  1134.             break;
  1135.  
  1136.            case IDM_APPHELP:
  1137.  
  1138.             strcpy(szText, STATUSAPPHELP);
  1139.             break;
  1140.  
  1141.            case IDM_ABOUT:
  1142.  
  1143.             strcpy(szText, STATUSABOUT);
  1144.             break;
  1145.  
  1146.            default:
  1147.  
  1148.             if (wStatusText >= IDM_MDICHILD)
  1149.                sprintf(szText, STATUSMDICHILD, wStatusText-IDM_MDICHILD+1);
  1150.             else
  1151.                strcpy(szText, STATUSDEFAULT);
  1152.             break;
  1153.          }
  1154.  
  1155.          DrawText(hDC, szText, strlen(szText), &rectStatusText, DT_LEFT);
  1156.  
  1157.          // get current date and time and display time in time box
  1158.  
  1159.          time(&tCurrentTime);
  1160.          stTime = *localtime(&tCurrentTime);
  1161.          strftime(szText, MAXBUFLEN, TIMEFORMAT, &stTime);
  1162.          rect.top = rectStatusText.top;
  1163.          rect.bottom = rectStatusText.bottom;
  1164.          rect.left  = iWidth-iTimex-iDatex-6;
  1165.          rect.right = iWidth-iDatex-6;
  1166.          DrawText(hDC, szText, strlen(szText), &rect, DT_LEFT);
  1167.  
  1168.          // display date in date box
  1169.  
  1170.          strftime(szText, MAXBUFLEN, DATEFORMAT, &stTime);
  1171.          rect.left  = iWidth-iDatex-2;
  1172.          rect.right = iWidth-2;
  1173.          DrawText(hDC, szText, strlen(szText), &rect, DT_LEFT);
  1174.  
  1175.          // remember the date&time rectangle to minimize painting
  1176.  
  1177.          DateTimeRect.left   = iWidth-iTimex-iDatex-6;
  1178.          DateTimeRect.right  = iWidth-2;
  1179.          DateTimeRect.top    = rect.top;
  1180.          DateTimeRect.bottom = rect.bottom;
  1181.  
  1182.          EndPaint(hWnd, &ps);
  1183.  
  1184.          // delete created objects
  1185.  
  1186.          if (hLtGrayPen)
  1187.             DeleteObject(hLtGrayPen);
  1188.          if (hGrayPen)
  1189.             DeleteObject(hGrayPen);
  1190.          break;
  1191.       }
  1192.  
  1193.      default:
  1194.  
  1195.       return (DefWindowProc(hWnd, message, wParam, lParam));
  1196.       break;
  1197.    }
  1198.    return (0);
  1199. }
  1200.  
  1201. /*
  1202.     FUNCTION: ConnectDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1203.     COMMENTS: Callback dialog box procedure for connect menu command
  1204.           displays a list of available data sources, asks for user
  1205.           name and password to pass default connection parameters
  1206.           for a data source connection
  1207. */
  1208.  
  1209. BOOL CALLBACK ConnectDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1210. {
  1211.    switch (message) {
  1212.       HCURSOR hOldCursor; // Default Cursor Shape
  1213.  
  1214.      case WM_INITDIALOG:
  1215.  
  1216.       // display list of available data sources
  1217.  
  1218.       hOldCursor = SetCursor(LoadCursor((HINSTANCE)NULL, IDC_WAIT));
  1219.       DisplayDatabases(GetDlgItem(hWnd, IDCOMBO_DATASOURCE));
  1220.       SetCursor(hOldCursor);
  1221.       break;
  1222.  
  1223.      case WM_COMMAND:
  1224.  
  1225.       switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  1226.         case IDOK: // make a connection using the supplied values
  1227.  
  1228.          hOldCursor = SetCursor(LoadCursor((HINSTANCE)NULL, IDC_WAIT));
  1229.  
  1230.          // check if a DSN was provided for connection
  1231.  
  1232.          if (SendDlgItemMessage(hWnd, IDCOMBO_DATASOURCE, WM_GETTEXTLENGTH, 0, 0))
  1233.             EndDialog(hWnd, ConnectDatabase(hWnd));
  1234.          else
  1235.             MessageBox(hWnd, NODSNERR, MOREINFO, MB_OK|MB_ICONHAND);
  1236.  
  1237.          SetCursor(hOldCursor);
  1238.          break;
  1239.  
  1240.         case IDCANCEL:
  1241.  
  1242.          EndDialog(hWnd, FALSE);
  1243.          break;
  1244.  
  1245.         default:
  1246.  
  1247.          return (FALSE);
  1248.          break;
  1249.       }
  1250.       break;
  1251.  
  1252.      default:
  1253.  
  1254.       return (FALSE);
  1255.       break;
  1256.    }
  1257.    return (TRUE);
  1258. }
  1259.  
  1260. /*
  1261.     FUNCTION: DisconnectDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1262.     COMMENTS: Callback dialog box procedure for disconnect dialog.
  1263.           provides a list of available SQLHDBCs and a list of SQLHSTMTs
  1264.           for currently selected SQLHDBC. Allows closure of all SQLHDBCs
  1265.           and SQLHSTMTs one by one or in groups.
  1266. */
  1267.  
  1268. BOOL CALLBACK DisconnectDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1269. {
  1270.    switch (message) {
  1271.       static HWND hListhdbc;  //listbox that displays hdbc(s)
  1272.       static HWND hListstmt;      //listbox that displays hstmt(s)
  1273.       static HWND hPushOk;        //pushbutton to free hdbc
  1274.       static HWND hPushClose;     //pushbutton to free hstmt
  1275.       static HWND hPushCancel;    //pushbutton to close dialog
  1276.  
  1277.      case WM_INITDIALOG:
  1278.  
  1279.       // store handles for future reference
  1280.  
  1281.       hListhdbc = GetDlgItem(hWnd, IDLIST_HDBC);
  1282.       hListstmt = GetDlgItem(hWnd, IDLIST_STMT);
  1283.       hPushOk = GetDlgItem(hWnd, IDDISCONNECT);
  1284.       hPushCancel = GetDlgItem(hWnd, IDCANCEL);
  1285.       hPushClose = GetDlgItem(hWnd, IDCLOSE_ACTVTY);
  1286.  
  1287.       // display connected database handles and statements
  1288.  
  1289.       DisplayConnections(hListhdbc);
  1290.       DisplayQueries(hListstmt, hListhdbc, 0);
  1291.  
  1292.       // enable or disable pushbuttons & listboxes to match available hdbc & hstmt
  1293.  
  1294.       if (SendMessage(hListhdbc, LB_GETCOUNT, 0, 0)>0) {
  1295.          EnableWindow(hPushOk, TRUE);
  1296.          if (SendMessage(hListstmt, LB_GETCOUNT, 0, 0)>0) {
  1297.             EnableWindow(hPushClose, TRUE);
  1298.             SetFocus(hPushClose);
  1299.             SendMessage(hPushClose, BM_SETSTYLE, (WPARAM)BS_DEFPUSHBUTTON, TRUE);
  1300.          }
  1301.          else {
  1302.             EnableWindow(hListstmt, FALSE);
  1303.             EnableWindow(hPushClose, FALSE);
  1304.             SetFocus(hPushOk);
  1305.             SendMessage(hPushOk, BM_SETSTYLE, (WPARAM)BS_DEFPUSHBUTTON, TRUE);
  1306.          }
  1307.       }
  1308.       else {
  1309.          EnableWindow(hListhdbc, FALSE);
  1310.          EnableWindow(hListstmt, FALSE);
  1311.          EnableWindow(hPushOk, FALSE);
  1312.          SetFocus(hPushCancel);
  1313.          SendMessage(hPushCancel, BM_SETSTYLE, (WPARAM)BS_DEFPUSHBUTTON, TRUE);
  1314.       }
  1315.  
  1316.       // return FALSE to prevent default focus.
  1317.  
  1318.       return (FALSE);
  1319.  
  1320.      case WM_COMMAND:
  1321.  
  1322.       switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  1323.         case IDDISCONNECT:
  1324.  
  1325.          // Free current hdbc, display available hdbc(s)
  1326.  
  1327.          FreeConnect(hListhdbc);
  1328.          SendMessage(hListstmt, LB_RESETCONTENT, 0, 0);
  1329.          DisplayConnections(hListhdbc);
  1330.  
  1331.          // update displayed hstmt(s) for current hdbc
  1332.          // enable or disable pushbuttons to match available
  1333.          // hdbc(s) and hstmt(s) for closure
  1334.  
  1335.          if (SendMessage(hListhdbc, LB_GETCOUNT, 0, 0) > 0) {
  1336.             SendMessage(hListhdbc, LB_SETCURSEL, 0, 0);
  1337.             EnableWindow(hListstmt, TRUE);
  1338.             DisplayQueries(hListstmt, hListhdbc, 0);
  1339.             if (SendMessage(hListstmt, LB_GETCOUNT, 0, 0)>0) {
  1340.                EnableWindow(hPushClose, TRUE);
  1341.                SetFocus(hPushClose);
  1342.                SendMessage(hPushClose, BM_SETSTYLE, (WPARAM)BS_DEFPUSHBUTTON, TRUE);
  1343.             }
  1344.             else {
  1345.                EnableWindow(hListstmt, FALSE);
  1346.                EnableWindow(hPushClose, FALSE);
  1347.                SetFocus(hPushOk);
  1348.                SendMessage(hPushOk, BM_SETSTYLE, (WPARAM)BS_DEFPUSHBUTTON, TRUE);
  1349.             }
  1350.          }
  1351.          else {
  1352.             EnableWindow(hListhdbc, FALSE);
  1353.             EnableWindow(hPushOk, FALSE);
  1354.             EnableWindow(hPushClose, FALSE);
  1355.             SetFocus(hPushCancel);
  1356.             SendMessage(hPushCancel, BM_SETSTYLE, (WPARAM)BS_DEFPUSHBUTTON, TRUE);
  1357.          }
  1358.          break;
  1359.  
  1360.         case IDCANCEL:
  1361.  
  1362.          // close dialog
  1363.  
  1364.          EndDialog(hWnd, FALSE);
  1365.          break;
  1366.  
  1367.         case IDCLOSE_ACTVTY:
  1368.          {
  1369.             int nIndex; // counter to search for selected hstmt(s)
  1370.  
  1371.             // go through all displayed hstmt(s) and free all highlighted ones
  1372.  
  1373.             for (nIndex = (int)SendMessage(hListstmt, LB_GETCOUNT, 0, 0)-1;
  1374.                  nIndex >= 0; nIndex--)
  1375.                if (SendMessage(hListstmt, LB_GETSEL, nIndex, 0))
  1376.                   FreeQuery(hListstmt, hListhdbc, nIndex);
  1377.  
  1378.             // reset both hdbc(s) and hstmt(s) display
  1379.  
  1380.             nIndex = (int)SendMessage(hListhdbc, LB_GETCURSEL, 0, 0);
  1381.             DisplayConnections(hListhdbc);
  1382.             SendMessage(hListhdbc, LB_SETCURSEL, nIndex, 0);
  1383.             DisplayQueries(hListstmt, hListhdbc, nIndex);
  1384.  
  1385.             // enable or disable pushbuttons to match available
  1386.             // hdbc(s) and hstmt(s) for closure
  1387.  
  1388.             if (SendMessage(hListstmt, LB_GETCOUNT, 0, 0)>0) {
  1389.                EnableWindow(hPushClose, TRUE);
  1390.                SetFocus(hPushClose);
  1391.                SendMessage(hPushClose, BM_SETSTYLE, (WPARAM)BS_DEFPUSHBUTTON, TRUE);
  1392.             }
  1393.             else {
  1394.                EnableWindow(hListstmt, FALSE);
  1395.                EnableWindow(hPushClose, FALSE);
  1396.                SetFocus(hPushOk);
  1397.                SendMessage(hPushOk, BM_SETSTYLE, (WPARAM)BS_DEFPUSHBUTTON, TRUE);
  1398.             }
  1399.             break;
  1400.          }
  1401.  
  1402.         case IDLIST_HDBC:
  1403.  
  1404.          // If the current selection in hdbc(s) has changed
  1405.          // update the list of hstmt(s) to match the new hdbc
  1406.  
  1407.          if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE)
  1408.             DisplayQueries(hListstmt, hListhdbc,
  1409.                            (UINT)SendMessage(GET_WM_COMMAND_HWND(wParam, lParam), LB_GETCURSEL, 0, 0));
  1410.  
  1411.          // Enable or disable hstmt listbox and close pushbutton accordingly
  1412.  
  1413.          EnableWindow(hListstmt, (SendMessage(hListstmt, LB_GETCOUNT, 0, 0)>0));
  1414.          EnableWindow(hPushClose, (SendMessage(hListstmt, LB_GETCOUNT, 0, 0)>0));
  1415.          break;
  1416.  
  1417.         default:
  1418.  
  1419.          return (FALSE);
  1420.       }
  1421.       break;
  1422.  
  1423.      default:
  1424.  
  1425.       return (FALSE);
  1426.    }
  1427.  
  1428.    return (TRUE);
  1429. }
  1430.  
  1431. /*
  1432.     FUNCTION: AboutDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1433.     COMMENTS: Callback dialog box procedure for About dialog box
  1434.           displays the about information and closes upon selection of
  1435.           ok button
  1436. */
  1437.  
  1438. BOOL CALLBACK AboutDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1439. {
  1440.    if (message == WM_COMMAND) {
  1441.       EndDialog(hWnd, TRUE);
  1442.       return (TRUE);
  1443.    }
  1444.    else
  1445.       return (FALSE);
  1446. }
  1447.  
  1448. /*
  1449.     FUNCTION: MDIChildDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1450.     COMMENTS: Callback dialog box procedure for modeless child dialog box
  1451.           in each MDI Child Window. This dialog box simply processes
  1452.           the tab messages (by default) to allow switching from edit
  1453.           control (SQL Text) to list box control (Query results).
  1454. */
  1455.  
  1456. BOOL CALLBACK MDIChildDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1457. {
  1458.    return (FALSE);
  1459. }
  1460.  
  1461. /*
  1462.     FUNCTION: DrawBitmap(HDC hDC, int iLeft, int iTop, HBITMAP hBitmap
  1463.     COMMENTS: Draws a bitmap on given Device context with given bitmap
  1464.           handle at given location
  1465. */
  1466.  
  1467. VOID FAR PASCAL DrawBitmap(HDC hDC, int iLeft, int iTop, HBITMAP hBitmap)
  1468. {
  1469.    HDC hMemDC;     // Device Context in Memory
  1470.    POINT   stPoint;        // point structure for conversion from device to logical units
  1471.    BITMAP  stBitmap;
  1472.    HGDIOBJ hObject;
  1473.  
  1474.    // create a compatible device context in memory and select the bitmap
  1475.    // in to it.
  1476.  
  1477.    if (!(hMemDC = CreateCompatibleDC(hDC))) return;
  1478.  
  1479.    hObject = SelectObject(hMemDC, hBitmap);
  1480.    SetMapMode(hMemDC, GetMapMode(hDC));
  1481.  
  1482.    // Get bitmap size and convert it to logical units from device units.
  1483.  
  1484.    GetObject(hBitmap, sizeof(BITMAP), &stBitmap);
  1485.    stPoint.x = stBitmap.bmWidth;
  1486.    stPoint.y = stBitmap.bmHeight;
  1487.    DPtoLP(hDC, &stPoint, 1);
  1488.  
  1489.    // bit block transfer the bitmap from memory device context to given
  1490.    // device context at specified location
  1491.  
  1492.    BitBlt(hDC, iLeft, iTop, stPoint.x, stPoint.y, hMemDC, 0, 0, SRCCOPY);
  1493.  
  1494.    // select original object in the memory device context and destroy it
  1495.  
  1496.    SelectObject(hMemDC, hObject);
  1497.    DeleteDC(hMemDC);
  1498. }
  1499.  
  1500. /********************************************* END OF FILE **************************************************/
  1501.