home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / OWLRANGE.PAK / OWLRANGE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  20.8 KB  |  700 lines

  1. // (C) Copyright 1996, Borland International
  2. //
  3. // Owlrange.cpp - VDBT Ttable example show how support search ranges
  4. /*********************************************************************
  5. This example demonstrates how implement a user definable range setting
  6. in VDBT.  The user can navigate through the table using the Main Menu
  7. items or via the keyboard. Only one record will be displayed at a time.
  8. In addition, the user can define a search range to be used while
  9. navigating the table.  This is accomplished through the Range Item on the
  10. Main Menu Bar.  If the entries for the start range or the end range are blank
  11. that indicates that the search range is set to to beginning or end of the
  12. table respectively.
  13.  
  14. The function SetRangeDialog handles displaying the current range settings
  15. via the EditRangeStart and EditRangeEnd TTable methods.  It will then set
  16. the new range settings through the SetRangeStart and SetRangeEnd TTable methods.
  17.  
  18.  
  19.     SETTING UP TO USE AN EVENT HANDLER
  20.  
  21.     Visual Database Tools uses event sources and event sinks (or
  22.     handlers) to encapsulate everything necessary for repsonding
  23.     to event.  The general     steps are:
  24.     1.  Identify the source that will be the source of the events
  25.          you wish to handle, in this particular example, TDataSource.  This is
  26.          done in the MainCreateMsg function.
  27.     2.  Define the event sink to handle the event.  This is done as part of
  28.          the EventHandler class.
  29.     3.  Connect the event sink to the event handler.  This is done as part of
  30.          The EventHandle constructor.
  31.     4.  Connect the event source to the event sink.  This is done in the
  32.          MainCreateMsg function.
  33.  
  34.  
  35. The DIVESTOK table in the diveplan database is used exclusively by this example.
  36. The user cannot specify different databases or tables on the command line.
  37.  
  38. The files needed to build this program are:
  39.  
  40. owlrange.cpp                    Source file for application
  41. print.cpp                          Source file for application
  42. owlrange.rc                        Resource file for application
  43. owlrange.ico                    Icon file for application
  44. ..\..\..\lib\default.def    module definition file 
  45. makefile                            command-line tools build file
  46. owlrange.ide                    BCW 5.0 project file for both 16bit and 32bit target
  47.  
  48. *******************************************************************************/
  49.  
  50. #include <vdbt\bdto.h>
  51. #include <windowsx.h>
  52. #include "resource.h"
  53.  
  54. //******************************************************************************
  55.  
  56. #define NOTUSED( x )        ((void)(long) (x))
  57.  
  58. #define DATABASENAME "DivePlan"
  59. #define TABLENAME "divestok.db"
  60.  
  61. #define MAIN_CLASS_NAME    "Main Class"
  62.  
  63. //******************************************************************************
  64. // function prototypes
  65.  
  66. BOOL RegisterMainClass(VOID);
  67.  
  68. HWND CreateMainWindow(LPSTR lpszCmdLine, int cmdShow );
  69.  
  70. extern "C" LRESULT CALLBACK _export MainWndProc( HWND hwnd, UINT msg,
  71.         WPARAM wParam, LPARAM lParam);
  72.  
  73. void MainCreateMsg( HWND hwnd );
  74.  
  75. void MainPaintMsg( HWND hwnd );
  76.  
  77. void GetAndDrawGraphic( HDC hdc, TGraphicField& graphic, int x, int y,
  78.         int w, int h );
  79.  
  80. void GetAndDisplayMemo( HDC hdc, TMemoField& memo,int top, int width,
  81.                                                                                         int height);
  82.  
  83. void DrawPrettyText(HDC hdc, string PrintString, int left, int top, int width,
  84.                                                                                         int height);
  85.  
  86. BOOL MainCommandMsg( HWND hwnd, WPARAM wParam, LPARAM lParam );
  87.  
  88. void MainKeyDownMsg( HWND hwnd, WPARAM wParam );
  89.  
  90. void MainDestroyMsg( HWND hwnd );
  91.  
  92. extern "C" BOOL CALLBACK _export SetRangeDialog( HWND hDlg, UINT message,
  93.     WPARAM wParam, LPARAM lParam);
  94.  
  95.  
  96. //******************************************************************************
  97. // Global Variable(s)
  98. HINSTANCE hInstance;
  99.  
  100.  
  101. #define EXTRA sizeof(TTable*) + sizeof(TDataSource*) + sizeof(EventHandler*)
  102. #define SWL_TABLE 0
  103. #define SWL_DATASOURCE 4
  104. #define SWL_EVENTHANDLER 8
  105.  
  106.  
  107. /*******************************************************************************
  108. EventHandler
  109.     This is the class that will handle the events that are generated
  110.     by the TDataSource object.  OnDataChangeSink is the sink for the
  111.     OnDataChangeEvent and the OnDataChange method will process all
  112.     events passed to OnDataChangeSink by the TDataSource
  113.     OnDataChangeSource object.
  114. *******************************************************************************/
  115.  
  116. class EventHandler
  117. {
  118. private:
  119.     HWND hwnd;
  120. public:
  121.     EventHandler( HWND h );
  122.  
  123.     // define the event sink to handle the event.  This is step #2 of
  124.     // setting up to use an event handler for a VDBT event.
  125.     TDataChangeSink OnDataChangeSink;
  126.  
  127. protected:
  128.     void OnDataChange(TDataChangeSink& sink, TDataSource& sender, TField* field);
  129. };
  130. // the OnDataChangeSink constructor connects OnDataChangeSink with the
  131. // event handler OnDataChange.  This performs stepd #3 for setting up
  132. // to use an event handler for a VDBT event.
  133. EventHandler::EventHandler( HWND h ):
  134.   OnDataChangeSink( TDataChange_MFUNCTOR( *this, &EventHandler::OnDataChange ) )
  135. {
  136.     hwnd = h;
  137. }
  138.  
  139. /*******************************************************************************
  140. OnDataChange
  141.   When the data changes (the user has navigated to a new record)
  142.   invalidate the right hand side of the window and force a repaint.
  143.   The left hand side of the windows does not need to be repainted
  144.   because it holds data the is static the entire time the app is
  145.   running.
  146. *******************************************************************************/
  147. void EventHandler::OnDataChange( TDataChangeSink&, TDataSource&, TField* )
  148. {
  149.     if (hwnd)
  150.     {
  151.         RECT rc;
  152.         GetClientRect( hwnd, &rc );
  153.         rc.left = rc.right/2;
  154.         InvalidateRect( hwnd, &rc, TRUE );
  155.     }
  156. }
  157.  
  158. //******************************************************************************
  159.  
  160. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpszCmdLine,
  161.                             int cmdShow )
  162. {
  163.     hInstance=hInst;
  164.  
  165.     if (! hPrevInstance)
  166.         if (! RegisterMainClass())
  167.             return 0;
  168.  
  169.     CreateMainWindow(lpszCmdLine, cmdShow);
  170.  
  171.     MSG msg;
  172.     while (GetMessage(&msg, (HWND) 0, 0, 0))
  173.     {
  174.         TranslateMessage(&msg);
  175.         DispatchMessage(&msg);
  176.     }
  177.  
  178.     return 0;
  179. }
  180.  
  181. //******************************************************************************
  182.  
  183. BOOL RegisterMainClass(VOID)
  184. {
  185.     WNDCLASS wndClass;
  186.  
  187.     wndClass.style = CS_HREDRAW | CS_VREDRAW;
  188.     wndClass.lpfnWndProc = MainWndProc;
  189.     wndClass.cbClsExtra = 0;
  190.     // allocate extra memory to hold the table, datasource and event handler
  191.     // pointers.
  192.     wndClass.cbWndExtra = EXTRA;
  193.     wndClass.hInstance = hInstance;
  194.     wndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIN));
  195.     wndClass.hCursor = LoadCursor((HINSTANCE) 0, IDC_ARROW);
  196.     wndClass.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
  197.     wndClass.lpszMenuName = MAKEINTRESOURCE(IDM_MAIN);
  198.     wndClass.lpszClassName = MAIN_CLASS_NAME;
  199.  
  200.     return RegisterClass(&wndClass);
  201. }
  202.  
  203. //******************************************************************************
  204.  
  205. HWND CreateMainWindow(LPSTR lpszCmdLine, int cmdShow )
  206. {
  207.     char    szTitle[30 + 1];
  208.     HWND    hwnd;
  209.  
  210.     LoadString(hInstance, IDS_MAINTITLE, szTitle, 30);
  211.     hwnd = CreateWindow(MAIN_CLASS_NAME, szTitle, WS_TILEDWINDOW,
  212.         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  213.         (HWND) 0, (HMENU) 0, hInstance, lpszCmdLine);
  214.  
  215.     if (hwnd)
  216.     {
  217.         ShowWindow(hwnd, cmdShow);
  218.         UpdateWindow(hwnd);
  219.     }
  220.  
  221.     return hwnd;
  222. }
  223.  
  224. //******************************************************************************
  225.  
  226. extern "C" LRESULT CALLBACK _export MainWndProc(HWND hwnd, UINT msg,
  227.                                                                 WPARAM wParam, LPARAM lParam)
  228. {
  229.  
  230.     switch (msg)
  231.     {
  232.         case WM_CREATE:
  233.             MainCreateMsg( hwnd);
  234.             break;
  235.  
  236.         case WM_PAINT:
  237.             MainPaintMsg(hwnd);
  238.             break;
  239.  
  240.         case WM_COMMAND:
  241.             if (!MainCommandMsg(hwnd, wParam, lParam))
  242.                 return DefWindowProc(hwnd, msg, wParam, lParam);
  243.             break;
  244.  
  245.         case WM_KEYDOWN:
  246.             MainKeyDownMsg(hwnd, wParam);
  247.             break;
  248.  
  249.         case WM_DESTROY:
  250.             MainDestroyMsg(hwnd);
  251.             PostQuitMessage(0);
  252.             break;
  253.  
  254.         default:
  255.             return DefWindowProc(hwnd, msg, wParam, lParam);
  256.     }
  257.  
  258.     return 0L;
  259. }
  260.  
  261.  
  262. /*******************************************************************************
  263.     MainCreateMsg.
  264.         This initializes the main window and the database table.  Things
  265.         to note are the create of the TTable object, the try block that
  266.         opens the database table, the create of the datasource object
  267.         and the attachment to the OnDataChange event.
  268. *******************************************************************************/
  269.  
  270. void MainCreateMsg(HWND hwnd)
  271. {
  272.  
  273.     LPSTR databaseName = DATABASENAME;
  274.     LPSTR tableName = TABLENAME;
  275.  
  276.     // Update the window's title bar with the database and table names.
  277.  
  278.     char    szTitle[30 + 100 + 1];
  279.     int len = GetWindowText( hwnd, szTitle, sizeof(szTitle) );
  280.     wsprintf( szTitle+len, " - :%s:%s", databaseName, tableName );
  281.     SetWindowText( hwnd, szTitle );
  282.  
  283.     // Create the TTable object.  This is the step #1 for setting up to use
  284.     // an event handler for a VDBT event.
  285.  
  286.     TTable* table = new TTable;
  287.     if (table)
  288.     {
  289.         // Put the database and table name properties, open the table.
  290.  
  291.         try
  292.         {
  293.             table->DatabaseName = string( databaseName );
  294.             table->TableName = string( tableName );
  295.             table->Open();
  296.         }
  297.         catch (BDTException e)
  298.         {
  299.             e.Show( "processing WM_CREATE" );
  300.             delete table;
  301.             table = NULL;
  302.         }
  303.         // put the pointer to the table object to the 0 offset (SWL_TABLE=0) of
  304.         // the extra window memory of hwnd.
  305.         SetWindowLong( hwnd, SWL_TABLE, (LONG) table );
  306.  
  307.         if (table)
  308.         {
  309.             // Create a datasource object and attach to the OnDataChange event.
  310.  
  311.             EventHandler* handler = new EventHandler( hwnd );
  312.             if (handler)
  313.             {
  314.                 TDataSource* datasource = new TDataSource;
  315.                 if (datasource)
  316.                 {
  317.                     datasource->DataSet = table;
  318.  
  319.                     // The following line connects the event source,
  320.                     // datasource->OnDataChangeSource to the event sink,
  321.                     // handler->OnDataChangeSink.  The is the fourth and final step
  322.                     // for setting up to use an event handler for a VDBT event.
  323.                     datasource->OnDataChangeSource += handler->OnDataChangeSink;
  324.  
  325.  
  326.                     // put the pointer to the datasource object to the 4 offset
  327.                     // (SWL_DATASOURCE=4) of the extra window memory of hwnd.
  328.                     SetWindowLong( hwnd, SWL_DATASOURCE, (LONG) datasource );
  329.                 }
  330.                 // put the pointer to the event handler object to the 8 offset
  331.                 // (SWL_EVENTHANDLER=8) of the extra window memory of hwnd.
  332.                 SetWindowLong( hwnd, SWL_EVENTHANDLER, (LONG) handler );
  333.             }
  334.         }
  335.     }
  336. }
  337.  
  338.  
  339. /*******************************************************************************
  340. MainPaintMsg
  341.     This function will repaint the window with the (static) table field
  342.     names on the left side and the (dynamic) field entries on the right.
  343.     The table name.
  344. *******************************************************************************/
  345.  
  346. void MainPaintMsg(HWND hwnd)
  347. {
  348.     PAINTSTRUCT ps;
  349.     RECT rc;
  350.  
  351.     BeginPaint( hwnd, &ps );
  352.     GetClientRect( hwnd, &rc );
  353.  
  354.     // Retrieve the pointer to the table from the extra memory in hwnd
  355.     TTable* table = (TTable*) GetWindowLong( hwnd, SWL_TABLE );
  356.  
  357.     
  358.     if (table)
  359.     {
  360.         int count = table->FieldCount;
  361.         if (count)
  362.         {
  363.             int width = rc.right/2;
  364.             int height = rc.bottom/count;
  365.  
  366.             // Paint the field names on the left side of the window, the
  367.             // field values on the right side of the window.
  368.  
  369.             int i;
  370.             for (i = 0; i < count; i++)
  371.             {
  372.                 string s = table->Fields[i]->FieldName;
  373.                 DrawPrettyText( ps.hdc, s, 0, i*height, width, height);
  374.  
  375.                 if (table->Fields[i]->DataType == ftGraphic)
  376.                 {
  377.                     GetAndDrawGraphic( ps.hdc, TGraphicField(table->Fields[i]),
  378.                                            width, i*height, width, height );
  379.                 }
  380.             else if (table->Fields[i]->DataType == ftMemo)
  381.             {
  382.                 
  383.                     GetAndDisplayMemo( ps.hdc, TMemoField(table->Fields[i]),
  384.                                         width, width, height);
  385.             }
  386.                 else
  387.                 {
  388.                     s = table->Fields[i]->Text;
  389.                     DrawPrettyText( ps.hdc, s, width, i*height, width, height);
  390.                 }
  391.             }
  392.         }
  393.     }
  394.  
  395.     EndPaint(hwnd, &ps);
  396. }
  397.  
  398. /*******************************************************************************
  399. GetAndDrawGraphic
  400.     This will function will accurately display a graphic field that is
  401.     in the current record.   Note that the SaveToBitmap method will
  402.     save the bitmap from the graphic field to the hbitmap and hpalette
  403.     handles.
  404. *******************************************************************************/
  405.  
  406. void GetAndDrawGraphic( HDC hdc, TGraphicField& graphic, int x, int y,
  407.                                 int w, int h )
  408. {
  409.     // Use the SaveToBitmap method to get the bitmap and palette handles.
  410.  
  411.     HBITMAP hbm = 0;
  412.     HPALETTE hpal = 0;
  413.     graphic.SaveToBitmap( hbm, hpal );
  414.     if (hbm)
  415.     {
  416.         HDC hdcTemp = CreateCompatibleDC( hdc );
  417.         if (hdcTemp)
  418.         {
  419.             BITMAP bm;
  420.             GetObject( hbm, sizeof(BITMAP), &bm );
  421.             HBITMAP hbmPrev = SelectBitmap( hdcTemp, hbm );
  422.             StretchBlt( hdc, x, y, w, h,
  423.                             hdcTemp, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY );
  424.             SelectBitmap( hdcTemp, hbmPrev );
  425.             DeleteDC( hdcTemp );
  426.         }
  427.         DeleteBitmap( hbm );
  428.     }
  429.     if (hpal)
  430.         DeletePalette( hpal );
  431. }
  432.  
  433. /*******************************************************************************
  434. GetAndDisplayMemo
  435.     This function will accurately display a memo field that is
  436.     in the current record.   Note that the DrawPrettyText function will
  437.    perform word-wrap so that as much of the memo as possible will be
  438.    displayed.
  439. *******************************************************************************/
  440. void GetAndDisplayMemo( HDC hdc, TMemoField& memo, int top, int width,
  441.                                 int height)
  442. {
  443.     TMemoryStream stream;
  444.     memo.SaveToStream( stream );
  445.     stream.Position = 0;
  446.     TStrings strings;
  447.     strings.LoadFromStream( stream );
  448.     string s = strings.Text;
  449.    DrawPrettyText(hdc, s, width, top, width, height);
  450. }
  451.  
  452. /*******************************************************************************
  453. DrawPrettyText
  454. function will use DrawText to perform word-wrap so that as much of 
  455. text to be displayed as possible is actually displayed in the available
  456. rectangle.
  457. *******************************************************************************/
  458. void DrawPrettyText(HDC hdc, string PrintString, int left, int top, int width,
  459.                             int height)
  460. {
  461.     RECT rc;
  462.     rc.left = left;
  463.     rc.top = top;
  464.     rc.right = rc.left + width;
  465.     rc.bottom = rc.top + height;
  466.     DrawText( hdc, PrintString.c_str(), PrintString.length(), &rc,
  467.                 DT_TOP | DT_LEFT | DT_WORDBREAK | DT_NOPREFIX );
  468. }
  469.  
  470.  
  471. /*******************************************************************************
  472. MainCommandMsg
  473.     This handles all of the commands that come for the Main Menu
  474.     to navigate through the table. All other WM_COMMAND messages are
  475.     passed onto Windows.
  476. *******************************************************************************/
  477.  
  478. BOOL MainCommandMsg(HWND hwnd, WPARAM wParam, LPARAM lParam)
  479. {
  480.     NOTUSED( lParam );
  481.     // Process navigation commands from the menu.
  482.  
  483.     TTable* table = (TTable*) GetWindowLong( hwnd, SWL_TABLE );
  484.     if (table)
  485.     {
  486.         switch (GET_WM_COMMAND_ID(wParam, lParam))
  487.         {
  488.             case IDM_NAV_FIRST:
  489.                 table->First();
  490.                 break;
  491.             case IDM_NAV_PRIORSET:
  492.                 table->MoveBy(-5);
  493.                 break;
  494.             case IDM_NAV_PRIOR:
  495.                 table->Prior();
  496.                 break;
  497.             case IDM_NAV_NEXT:
  498.                 table->Next();
  499.                 break;
  500.             case IDM_NAV_NEXTSET:
  501.                 table->MoveBy(5);
  502.                 break;
  503.             case IDM_NAV_LAST:
  504.                 table->Last();
  505.                 break;
  506.             case IDM_TEST_SETRANGE_STARTEND:
  507.             {
  508.                 DialogBox(hInstance, MAKEINTRESOURCE(IDD_START_AND_END), hwnd,
  509.                     (DLGPROC)SetRangeDialog);
  510.  
  511.                 break;
  512.             }
  513.             default:
  514.                 return FALSE;
  515.         }
  516.  
  517.         return TRUE;
  518.     }
  519.  
  520.     return FALSE;
  521. }
  522.  
  523.  
  524. /*******************************************************************************
  525. MainKeyDownMsg
  526.     This handle all of the keyboard messages that will be used to navigate
  527.     the table.  All other WM_KEYDOWN messages are passed onto Windows.
  528. *******************************************************************************/
  529.  
  530. void MainKeyDownMsg(HWND hwnd, WPARAM wParam)
  531. {
  532.     // Process navigation commands from the keyboard.
  533.  
  534.     TTable* table = (TTable*) GetWindowLong( hwnd, SWL_TABLE );
  535.     if (table)
  536.     {
  537.         switch (wParam)
  538.         {
  539.             case VK_HOME:
  540.                 table->First();
  541.                 break;
  542.             case VK_PRIOR:
  543.                 table->MoveBy(-5);
  544.                 break;
  545.             case VK_UP:
  546.                 table->Prior();
  547.                 break;
  548.             case VK_DOWN:
  549.                 table->Next();
  550.                 break;
  551.             case VK_NEXT:
  552.                 table->MoveBy(5);
  553.                 break;
  554.             case VK_END:
  555.                 table->Last();
  556.                 break;
  557.         }
  558.     }
  559. }
  560.  
  561.  
  562. /*******************************************************************************
  563. MainDestroyMsg
  564.     This destroys the datasource object, the handler object and then the
  565.     table object.
  566. *******************************************************************************/
  567.  
  568. void MainDestroyMsg( HWND hwnd )
  569. {
  570.     // Delete the table and the datasource.
  571.  
  572.     // Retrieve the pointer to the table from the extra memory in hwnd
  573.     // and then clear the entry.
  574.     TTable* table = (TTable*) GetWindowLong( hwnd, SWL_TABLE );
  575.     SetWindowLong( hwnd, SWL_TABLE, 0 );
  576.     if (table)
  577.     {
  578.         // Retrieve the pointer to the datasource from the extra memory in hwnd
  579.         // and then clear the entry.
  580.         TDataSource* datasource=(TDataSource*)GetWindowLong(hwnd, SWL_DATASOURCE);
  581.         SetWindowLong( hwnd, SWL_DATASOURCE, 0 );
  582.         if (datasource)
  583.             delete datasource;
  584.  
  585.         // Retrieve the pointer to the event handler from the extra memory
  586.         // in hwnd and then clear the entry.
  587.         EventHandler* handler=(EventHandler*)GetWindowLong(hwnd, SWL_EVENTHANDLER);
  588.         SetWindowLong( hwnd, SWL_EVENTHANDLER, 0 );
  589.         if (handler)
  590.             delete handler;
  591.  
  592.         delete table;
  593.     }
  594. }
  595. /*******************************************************************************
  596. SetRangeDialog
  597.     This handles setting the Start and End Ranges.
  598.    This function is the heart of this example.  It demonstrates how to
  599.    find and display the current range and how to set a new one.
  600. *******************************************************************************/
  601.  
  602. extern "C" BOOL CALLBACK  _export SetRangeDialog (HWND hDlg, UINT message,
  603.                                                                     WPARAM wParam, LPARAM)
  604. {
  605.  
  606.     switch (message)
  607.         {
  608.             case WM_INITDIALOG:
  609.                 {
  610.                 
  611.                 string strTmp;
  612.                 HWND hWnd=GetParent(hDlg);
  613.                 TTable* table = (TTable*) GetWindowLong(hWnd, SWL_TABLE );
  614.  
  615.                 // Use EditRangeStart to get the beginning of the range.  Fields[0]
  616.             // contains the first item in the range.
  617.                 table->EditRangeStart();
  618.                 strTmp = table->Fields[0]->AsString;
  619.                 SetDlgItemText(hDlg, IDC_START_VALUE, strTmp.c_str());
  620.  
  621.                 // Use EditRangeEnd to get the beginning of the range.  Fields[0]
  622.             // contains the last item in the range.
  623.                 table->EditRangeEnd();
  624.                 strTmp = table->Fields[0]->AsString;
  625.                 SetDlgItemText(hDlg, IDC_END_VALUE, strTmp.c_str());
  626.                 table->Cancel();
  627.  
  628.                 return TRUE;
  629.                 }
  630.  
  631.             case WM_COMMAND:
  632.                 {
  633.                 // Retrieve the pointer to the table from the extra memory in hwnd
  634.                 char tmpStr[10];
  635.                 HWND hWnd=GetParent(hDlg);
  636.                 TTable* table = (TTable*) GetWindowLong(hWnd, SWL_TABLE );
  637.         
  638.                 switch (wParam)
  639.                     {
  640.                         case IDOK:
  641.                             {
  642.                             try
  643.                             {
  644.                                 //The SetRangeStart method prepares the table to have
  645.                         //the next assignments to key fields become the starting
  646.                         //values of a range.  In this particular case there is 
  647.                         //only one key field so SetRangeStart will take the
  648.                         //next assignment to table->Fields[0] to be the start
  649.                         //of new range.
  650.                                 table->SetRangeStart();
  651.                                 if (GetWindowTextLength(GetDlgItem(hDlg, IDC_START_VALUE)) != 0)
  652.                                 {
  653.                                     GetDlgItemText( hDlg, IDC_START_VALUE, tmpStr,
  654.                                                 sizeof(tmpStr));
  655.                                     table->Fields[0]->AsString = string(tmpStr);
  656.                                 }
  657.  
  658.                                 //The SetRangeEnd method prepares the table to have
  659.                         //the next assignments to key fields become the ending
  660.                         //values of a range.  In this particular case there is 
  661.                         //only one key field so SetRangeEnd will take the
  662.                         //next assignment to table->Fields[0] to be the end
  663.                         //of new range.
  664.                         table->SetRangeEnd();
  665.                                 if (GetWindowTextLength(GetDlgItem(hDlg, IDC_END_VALUE)) != 0)
  666.                                 {
  667.                                     GetDlgItemText( hDlg, IDC_END_VALUE, tmpStr,
  668.                                                 sizeof(tmpStr));
  669.                                     table->Fields[0]->AsString = string(tmpStr);
  670.                                 }
  671.  
  672.                                 //The ApplyRange method applies the range established
  673.                         //in the lines above with the SetRangeStart and 
  674.                         //SetRangeEnd methods.
  675.                                   table->ApplyRange();
  676.                             }
  677.                             catch (BDTException e)
  678.                             {
  679.                                 e.Show( "Invalid Start Value");
  680.                             }
  681.  
  682.                             EndDialog(hDlg, TRUE);
  683.                             return TRUE;
  684.                             }
  685.  
  686.                         case IDCANCEL:
  687.                             {
  688.                             // don't do anything with the value(s) that the user
  689.                      //entered
  690.                             EndDialog(hDlg, FALSE);
  691.                             return TRUE;
  692.                             }
  693.                     }
  694.                 }
  695.         }
  696.         return FALSE;
  697. }
  698.  
  699.  
  700.