MAIN.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:49k
源码类别:

Windows编程

开发平台:

Visual C++

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