home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C Programming Starter Kit 2.0
/
SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso
/
bde
/
sdkqry.pak
/
QUERY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-07-23
|
54KB
|
1,508 lines
// BDE - (C) Copyright 1994 by Borland International
#include "query.h"
#define FILEHANDLESNEEDED 40
static char szStandard[] = "<STANDARD>";
static DBStructArray dbarray; // Global array of structures containing
// database connections (hDb's) and names.
static int iSelectedDbIndex; // Index to currently selected
// database connection.
void SetSelected(HWND hDlg);
//=================================================================
// Function:
// WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
//
// Input: hInstance - The handle that represents the applications
// unique instance ID
// hPrevInstance - Indicates if this is the first instance
// of the app
// lpCmdLine - Command line parameters (up to the app
// to parse)
// nCmdShow - TRUE = Show as non-icon application
//
// Return: Exit code (wParam value of WM_QUIT message)
//
// Description:
// This is the application entry point for the Query sample
// application. It will set up the app, init the instance,
// process all event driven messages, and clean up the
// application prior to returning to Windows.
//=================================================================
int _pascal
WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
lpCmdLine = lpCmdLine;
nCmdShow = nCmdShow;
// Register CTL3D
Ctl3dRegister(hInstance);
Ctl3dAutoSubclass(hInstance);
// Make this a single instance program
if (hPrevInstance)
{
MessageBox(GetFocus(), "This application is already running!",
"Windows Driver", MB_OK | MB_ICONHAND);
return FALSE;
}
// Start the application, and set the main dialog to not show until
// everything is setup.
hInst = hInstance;
if (InitApp(SW_SHOW) == FALSE)
{
return FALSE;
}
// Process all event driven messages.
while (GetMessage(&msg, NULL, NULL, NULL))
{
if ((hMainWnd == NULL) || (!IsDialogMessage(hMainWnd, &msg)))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// Unregister CTL3D.
Ctl3dUnregister(hInstance);
return msg.wParam;
}
//====================================================================
// Function:
// InitApp(nCmdShow);
//
// Input: nCmdShow - Show the main window
//
// Return: TRUE - Init worked
// FALSE - Init failed
//
// Description:
// Create the application window & init any default
// of the main window.
//====================================================================
BOOL
InitApp (int nCmdShow)
{
WNDCLASS wc;
UINT16 i;
UINT16 uCount;
// Path returned by the GetPrivateProfileString() function
CHAR szRelativeTblDirectory[DBIMAXPATHLEN+1];
CHAR szMessage[(DBIMAXMSGLEN * 2)]; // Allocate enough space to
// contain message
// Init the application & create the needed windows.
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = DLGWINDOWEXTRA;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(9999));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
wc.lpszMenuName = NULL;
wc.lpszClassName = "MainWindowClass";
// Register the class.
if (!RegisterClass(&wc))
{
MessageBox(NULL, "RegisterClass failed!", "System Error",
MB_OK | MB_ICONHAND);
return FALSE;
}
// Increase the number of file handles that are available to the
// system.
uCount = SetHandleCount(FILEHANDLESNEEDED);
if (uCount < FILEHANDLESNEEDED)
{
MessageBox(NULL, "Not enough file handles available. Please set"
" FILES=40 in your CONFIG.SYS.", "System Error",
MB_OK | MB_ICONHAND);
return FALSE;
}
// Get the directory which contains the tables.
GetPrivateProfileString("QUERY",
"TblDir",
"..\\TABLES",
(LPSTR)szRelativeTblDirectory,
sizeof(szRelativeTblDirectory),
"bde.ini");
// Create a fully qualified pathname for the table directory.
if (MakeFullPath(szTblDirectory, szRelativeTblDirectory))
{
sprintf(szMessage, "Table Directory does not exist: %s",
szTblDirectory);
MessageBox(NULL, szMessage, "System Error", MB_OK | MB_ICONHAND);
return FALSE;
}
// Get the private directory.
GetPrivateProfileString("QUERY",
"PrivateDir",
".",
(LPSTR)szRelativeTblDirectory,
sizeof(szRelativeTblDirectory),
"bde.ini");
// Create a fully qualified pathname for the table directory.
if (MakeFullPath(szPrivDirectory, szRelativeTblDirectory))
{
sprintf(szMessage, "Private Directory does not exist: %s."
"\r\nPlease check BDE.INI in your Windows directory.",
szPrivDirectory);
MessageBox(NULL, szMessage, "System Error", MB_OK | MB_ICONHAND);
return FALSE;
}
// Initialize Database Engine.
if (QueryDbiInit() != DBIERR_NONE)
{
MessageBox(NULL, "Application will terminate", "Error", MB_OK);
return FALSE;
}
// Explicitly initialize global array.
for (i = 0; i < MAX_DATABASE_HANDLES; i++)
{
dbarray[i].hdb = 0;
dbarray[i].szDatabaseName[0] = '\0';
}
// Create the dialog that serves as the main window.
hMainWnd = CreateDialog(hInst, "MainDlg", 0, NULL);
if (hMainWnd == NULL)
{
MessageBox(NULL, "CreateDialog failed!", "System Error",
MB_OK | MB_ICONHAND);
return FALSE;
}
_wpOrigWndProc = SubClassWindow(GetDlgItem(hMainWnd, IDC_QUERY_EDIT),
EditSubClassProc);
_wpOrigWndProc1 = SubClassWindow(GetDlgItem(hMainWnd, IDC_RESULT_EDIT),
EditSubClassProc);
ShowWindow(hMainWnd, nCmdShow);
return TRUE;
}
// ===============================================================
// Function:
// MainWndProc(hWnd, msg, wParam, lParam);
//
// Description:
// This routine will process all messages for the primary
// application window. Included in this are all menu
// commands.
// ===============================================================
LRESULT CALLBACK
MainWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static FARPROC lpfnConnectDlgProc;
static DLGPROC lpfnAboutDlgProc;
static DBIQryLang eQryLang;
static CBPROGRESSDesc CbBuf;
char * szQuery = NULL;
static hDBICur hCur = 0;
DBIResult rslt;
LONG lTextLength;
static char szOutputErrorString[(DBIMAXMSGLEN * 6) + 80];
static char szSelectedDatabase[80];
static HFONT hFont;
DWORD lMinMax; // Contains both offset of first and
// last selected characters
WORD iStart; // Offset of first selected character
WORD iEnd; // Offset of last selected character
HWND hwnd;
HBRUSH hBrush;
switch (msg)
{
case WM_CREATE:
eQryLang = qrylangSQL;
// Set up default database.
dbarray[0].hdb = QueryGetStandardConnection();
iSelectedDbIndex = 0;
strcpy(dbarray[iSelectedDbIndex].szDatabaseName, szStandard);
if (dbarray[iSelectedDbIndex].hdb == 0)
{
MessageBox(NULL, "Unable to create STANDARD standard "
"database.", "Application Error",
MB_ICONHAND);
}
PostMessage(hWnd, WM_SETUP, 0, 0);
return FALSE;
case WM_SETUP:
hwnd = GetWindow(hWnd, GW_CHILD);
while (hwnd != NULL)
{
Ctl3dSubclassCtl(hwnd);
hwnd = GetWindow(hwnd, GW_HWNDNEXT);
}
if (! SendDlgItemMessage(hWnd, IDC_RADIO_QBE, BM_GETCHECK, 0, 0))
{
SendDlgItemMessage(hWnd, IDC_RADIO_SQL, BM_SETCHECK, 1, 0);
}
// Set the font of the edit controls to be a fixed pitch font.
hFont = (HFONT) GetStockObject(ANSI_FIXED_FONT);
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, WM_SETFONT,
(WPARAM) hFont, FALSE);
SendDlgItemMessage(hWnd, IDC_RESULT_EDIT, WM_SETFONT,
(WPARAM) hFont, FALSE);
break;
case WM_CTLCOLOR:
hBrush = Ctl3dCtlColorEx(msg, wParam, lParam);
if (hBrush != (HBRUSH)0)
{
return (long)(WORD)hBrush;
}
else
{
return DefWindowProc(hWnd, msg, wParam, lParam);
}
case WM_SYSCOLORCHANGE:
Ctl3dColorChange();
return TRUE;
case WM_NCPAINT:
case WM_NCACTIVATE:
case WM_SETTEXT:
return Ctl3dDlgFramePaint(hWnd, msg, wParam, lParam);
case WM_SETFOCUS:
// Need to set the focus to the first element of the dialog box.
SetFocus(GetDlgItem(hWnd, IDC_QUERY_EDIT));
// Set static control displaying currently selected database.
if (dbarray[iSelectedDbIndex].hdb == NULL)
{
sprintf(szSelectedDatabase, "No connection established");
}
else
{
sprintf(szSelectedDatabase, "Current connection: %s",
dbarray[iSelectedDbIndex].szDatabaseName);
}
SendDlgItemMessage(hWnd, IDS_CURRENT_CONNECTION,
WM_SETTEXT, 0, (LPARAM) szSelectedDatabase);
return FALSE;
case WM_CLOSE:
// Done to get rid of the "Parameter Not used" warning.
// Done in this way in order to work with both BC++ and VC++.
lParam = lParam;
DestroyWindow(hWnd);
return FALSE;
case WM_DESTROY:
CleanUpAnswer(&hCur);
QueryDbiExit();
PostQuitMessage(0);
return FALSE;
case WM_COMMAND:
switch (wParam)
{
case IDC_EXIT:
DestroyWindow(hWnd);
return TRUE;
case IDC_RUN:
// Allow query to be run only if we have a
// valid database handle.
if (dbarray[0].hdb == 0)
{
MessageBox(NULL,
"No database connection established",
"Query SQL/QBE Example", MB_OK);
}
else
{
Cls();
DisplayProgress("");
// Get the length of the query from the Query edit
// control.
lTextLength = SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
WM_GETTEXTLENGTH,
0, 0);
// Allocate space to contain the query.
if ((szQuery = (char*) malloc((int) lTextLength + 1))
== NULL)
{
MessageBox(NULL, "Out of Memory!",
"Fatal Error", MB_ICONHAND);
return TRUE;
}
HourGlassCursor(TRUE);
// Setup the callback.
RegisterCallBack(hCur, cbGENPROGRESS,
(UINT32)"Query Data",
sizeof(CBPROGRESSDesc),
(pVOID)&CbBuf, GenProgCallBack);
// Get the text of the query from the Query edit
// control.
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, WM_GETTEXT,
(int) lTextLength + 1,
(LPARAM) szQuery);
// Close the cursor if it is open.
CleanUpAnswer(&hCur);
// Execute the query.
rslt = QueryQExec(dbarray[iSelectedDbIndex].hdb,
eQryLang, szQuery,
szOutputErrorString, &hCur);
// Remove Callback function.
RegisterCallBack(hCur, cbGENPROGRESS,
(UINT32)"Query Data",
sizeof(CBPROGRESSDesc),
(pVOID)&CbBuf, NULL);
if (szQuery)
{
free(szQuery);
}
// Check if query failed.
if (rslt != DBIERR_NONE)
{
Cls();
Screen(szOutputErrorString);
HourGlassCursor(FALSE);
return TRUE;
}
// Terminate if no cursor was returned.
if (hCur == 0)
{
Cls();
Screen("No information returned from Query.");
HourGlassCursor(FALSE);
return TRUE;
}
Cls();
DisplayTable(hCur, 0);
}
HourGlassCursor(FALSE);
return TRUE;
case IDC_LOADQUERY:
LoadQuery(eQryLang);
return TRUE;
case IDC_SAVEQUERY:
SaveQuery(eQryLang);
return TRUE;
case IDC_SAVERESULT:
if (!hCur || !dbarray[0].hdb)
{
MessageBox(NULL, "No result set to save.",
"Error", MB_ICONHAND);
}
else
{
if (!SaveResultSet (hCur, dbarray[0].hdb))
{
MessageBox(NULL, "Error saving result set",
"Error", MB_ICONHAND);
}
}
return TRUE;
case IDC_CONNECT:
lpfnConnectDlgProc = MakeProcInstance
((FARPROC)ConnectDlgProc, hInst);
DialogBox(hInst, szConnectDialogName,
hWnd, (DLGPROC)lpfnConnectDlgProc);
FreeProcInstance(lpfnConnectDlgProc);
return TRUE;
case IDC_HELP:
MessageBox(NULL, szMainHelpText,
"Query SQL/QBE Example", MB_OK);
return TRUE;
case IDC_ABOUT:
lpfnAboutDlgProc = (DLGPROC)MakeProcInstance((FARPROC)
AboutDlg, hInst);
DialogBox(hInst, "AboutDlg", hWnd, lpfnAboutDlgProc);
FreeProcInstance((FARPROC)lpfnAboutDlgProc);
return TRUE;
case IDC_RADIO_QBE:
eQryLang = qrylangQBE;
return TRUE;
case IDC_RADIO_SQL:
eQryLang = qrylangSQL;
return TRUE;
case IDM_COPY:
// Determine which characters are selected.
lMinMax = SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
EM_GETSEL, 0, 0L);
// Get the first and last selected character.
iStart = LOWORD(lMinMax);
iEnd = HIWORD(lMinMax);
// If nothing is selected, select all.
if (iStart == iEnd)
{
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
EM_SETSEL, 0, 0xfffeL);
}
// Copy the selected text in the QUERY edit box.
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, WM_COPY, 0, 0L);
return TRUE;
case IDM_PASTE:
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
WM_PASTE, 0, 0L);
return TRUE;
case IDM_CLEAR:
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
WM_SETTEXT, 0, (LPARAM)(LPCSTR)"");
return TRUE;
case IDM_CLEARRESULT:
SendDlgItemMessage(hWnd, IDC_RESULT_EDIT,
WM_SETTEXT, 0, (LPARAM)(LPCSTR)"");
return TRUE;
case IDM_DELETE:
PostMessage(hWnd, WM_COMMAND, IDM_CLEAR, 0l);
PostMessage(hWnd, WM_COMMAND, IDM_CLEARRESULT, 0l);
return TRUE;
case IDM_CUT:
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, WM_COPY, 0, 0L);
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, EM_REPLACESEL, 0,
(LPARAM)(LPCSTR)"");
return TRUE;
case IDM_UNDO:
SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, EM_UNDO, 0, 0L);
return TRUE;
}
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
//======================================================================
// Function:
// EditSubClassProc(hWnd, msg, wParam, lParam)
//
// Input: hWnd - Handle of the window
// msg - Message
// wParam - WPARAM
// lParam - LPARAM
//
// Return: It returns the result of the procedure. It can return the
// result of the original edit control if the WM_CHAR is not a
// tab character.
//
// Description:
// This routine will process all I/O for the Comments edit
// control. It does this by first checking if the tab key was
// hit inside of the comment edit control. If it was it moves
// control to the next control item and then does NOT let the
// original edit control process the message. However, if the
// WM_CHAR is not a tab then it lets the original edit control
// process the message.
//======================================================================
long FAR _pascal _export
EditSubClassProc (HWND hWnd, WORD msg, WORD wParam, LONG lParam)
{
LRESULT lResult = 0;
BOOL fCallOrigWndProc = TRUE;
INT16 iId;
UINT32 lType;
WNDPROC WndProc;
iId = GetDlgCtrlID(hWnd);
if (iId == IDC_QUERY_EDIT)
{
WndProc = (WNDPROC)_wpOrigWndProc;
}
else
{
WndProc = (WNDPROC)_wpOrigWndProc1;
}
switch (msg)
{
case WM_GETDLGCODE:
return DLGC_WANTMESSAGE;
case WM_CHAR:
if (wParam == '\t')
{
if (GetKeyState(VK_SHIFT)<0)
{
if (iId == IDC_QUERY_EDIT)
{
iId = IDC_RESULT_EDIT;
}
else
{
iId = IDC_RUN;
}
}
else
{
if (iId == IDC_QUERY_EDIT)
{
lType = SendDlgItemMessage(hMainWnd, IDC_RADIO_SQL,
BM_GETCHECK, 0, 0L);
if (lType == 1)
{
iId = IDC_RADIO_SQL;
}
else
{
iId = IDC_RADIO_QBE;
}
}
else
{
iId = IDC_QUERY_EDIT;
}
}
SetFocus(GetDlgItem(hMainWnd, iId));
fCallOrigWndProc = FALSE;
lResult = TRUE;
}
if (wParam == VK_ESCAPE)
{
MessageBeep(1);
}
break;
}
if (fCallOrigWndProc)
{
lResult = CallWindowProc(WndProc, hWnd, msg, wParam, lParam);
}
return lResult;
}
//======================================================================
// Function:
// AboutDlg(hWnd, msg, wParam, lParam)
//
// Input: hWnd, msg, wParam, lParam
//
// Return: TRUE - Dialog Created.
// FALSE - Dialog Failed to create.
//
// Description:
// This routine will process all I/O for the ABOUT dialog.
//======================================================================
BOOL FAR _pascal _export
AboutDlg (HWND hWnd, WORD msg, WORD wParam, LONG lParam)
{
BOOL ret = FALSE;
// Done to clear the unused warning.
lParam = lParam;
switch (msg)
{
case WM_COMMAND:
switch (wParam)
{
case IDOK:
case IDCANCEL:
ret = TRUE;
EndDialog(hWnd, ret);
break;
}
break;
}
return ret;
}
//======================================================================
// Function:
// ConnectDlgProc(hDlg, message, wParam, lParam)
//
// Input: hDlg, message, wParam, lParam
//
// Return: TRUE if dialog procedure processes a message
// FALSE otherwise.
//
// Description:
// Dialog box procedure for the dialog box that establishes
// and removes connections to databases based on ALIASES
// defined in IDAPI.CFG.
//======================================================================
BOOL CALLBACK _export
ConnectDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
int i;
char szAliasName[81];
WORD ListIndex;
int nIndex;
char szConnectionName[DBIMAXPATHLEN + 1];
static char szDirectory[DBIMAXPATHLEN+1];
char szTemp[DBIMAXPATHLEN + 1];
switch (message)
{
case WM_INITDIALOG:
QueryResetConnectDialog(hDlg, dbarray, iSelectedDbIndex);
if (dbarray[0].hdb != 0)
{
GetWorkingDirectory(dbarray[0].hdb, szDirectory);
}
ShowWindow(hDlg, SW_HIDE);
PostMessage(hDlg, WM_MYSETUP, 0, 0);
return TRUE;
case WM_MYSETUP:
SendDlgItemMessage(hDlg, IDS_SELECTED_CONNECTION,
WM_GETTEXT,
DBIMAXPATHLEN, (LPARAM)szConnectionName);
// Check if this is the standard database.
if (!strcmp(szConnectionName, szStandard))
{
// Show the Directory controls.
ShowWindow(GetDlgItem(hDlg, IDC_DIRECTORY),
SW_SHOW);
ShowWindow(GetDlgItem(hDlg, IDC_EDIT_DIRECTORY),
SW_SHOW);
}
else
{
// Hide the Directory controls.
ShowWindow(GetDlgItem(hDlg, IDC_EDIT_DIRECTORY),
SW_HIDE);
ShowWindow(GetDlgItem(hDlg, IDC_DIRECTORY),
SW_HIDE);
}
// Set the directory.
SendDlgItemMessage(hDlg, IDC_EDIT_DIRECTORY, WM_SETTEXT, 0,
(LPARAM)(LPCSTR)szDirectory);
ShowWindow(hDlg, SW_SHOW);
return TRUE;
case WM_CLOSE:
EndDialog(hDlg, 0);
return TRUE;
case WM_COMMAND:
switch (wParam)
{
case IDC_LB_CONNECTIONS:
if (HIWORD(lParam) == LBN_SELCHANGE)
{
SetSelected(hDlg);
}
return TRUE;
case IDC_BTN_CONNECT:
// First check to see if any alias is selected,
// if not, beep.
ListIndex = (WORD)
SendDlgItemMessage(hDlg, IDC_LB_ALIASES,
LB_GETCURSEL, 0, 0);
if (ListIndex == (WORD) LB_ERR)
{
MessageBeep(MB_ICONEXCLAMATION);
return TRUE;
}
// If an alias is selected, run through
// the array of handles/descriptions to see if we
// have any free one's left.
for (i = 1; i < MAX_DATABASE_HANDLES; i++)
{
if (dbarray[i].hdb == 0)
{
break;
}
}
// If we don't, provide an error message.
if (i == MAX_DATABASE_HANDLES)
{
MessageBox(NULL, "Maximum database handles limit "
"reached.", "Error", MB_OK);
}
else
{
// If we do have room left in our array,
// try to establish connection. If successful,
// add database name to connections list.
HourGlassCursor(TRUE);
if ((dbarray[i].hdb =
QueryConnectToDatabase(hDlg)) != 0)
{
ListIndex = (WORD)
SendDlgItemMessage(hDlg, IDC_LB_ALIASES,
LB_GETCURSEL, 0, 0);
SendDlgItemMessage(hDlg, IDC_LB_ALIASES,
LB_GETTEXT,
(WPARAM)ListIndex,
(LPARAM)szAliasName);
strcpy(dbarray[i].szDatabaseName, szAliasName);
SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS,
LB_ADDSTRING, 0,
(LPARAM)szAliasName);
SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS,
LB_SELECTSTRING,
(WPARAM)-1,
(LPARAM)szAliasName);
SetSelected(hDlg);
}
HourGlassCursor(FALSE);
}
return TRUE;
case IDC_BTN_REMOVE:
// Disconnect from the selected connection.
nIndex = (WORD)
SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS,
LB_GETCURSEL, 0, 0);
RemoveConnection(hDlg, dbarray, nIndex);
return TRUE;
case IDC_BTN_HELP:
// Display information on this application.
MessageBox(NULL, szConnectHelpText, "Help", MB_OK);
return TRUE;
case IDOK:
// find currently selected database based
// on the string in the static control
// displaying this information.
// Get currently selected database.
SendDlgItemMessage(hDlg, IDS_SELECTED_CONNECTION,
WM_GETTEXT, 80,
(LPARAM) szConnectionName);
// Compare currently selected database
// to the strings in the array and
// set iSelectedDbIndex based on that.
// iSelectedDbIndex is in turn used
// as the database handle used to
// execute queries.
for (i = 0; i < MAX_DATABASE_HANDLES,
dbarray[i].hdb != 0; i++)
{
if (strcmpi(dbarray[i].szDatabaseName,
szConnectionName) == 0)
{
iSelectedDbIndex = i;
break;
}
}
if (i == MAX_DATABASE_HANDLES)
{
iSelectedDbIndex = 0;
}
// Check if this is the standard database.
if (!strcmp(szConnectionName, szStandard))
{
// Get currently selected directory.
SendDlgItemMessage(hDlg, IDC_EDIT_DIRECTORY,
WM_GETTEXT, DBIMAXPATHLEN,
(LPARAM)szTemp);
// Only set if changed.
if (strcmp(szTemp, szDirectory))
{
// Check if the directory exists.
if (!access(szTemp, 00))
{
if (SetWorkingDirectory(
dbarray[iSelectedDbIndex].hdb, szTemp))
{
SendDlgItemMessage(hDlg,
IDC_STATIC_STATUS,
WM_SETTEXT, 0,
(LPARAM) "Invalid Directory");
return FALSE;
}
}
else
{
// Display message if directory does not exist.
SendDlgItemMessage(hDlg, IDC_STATIC_STATUS,
WM_SETTEXT, 0,
(LPARAM) "Invalid Directory");
return FALSE;
}
}
}
else
{
}
EndDialog (hDlg, 0);
return TRUE;
case IDCANCEL:
EndDialog (hDlg, 0);
return TRUE;
}
}
return FALSE;
}
//======================================================================
// Function:
// SetSelected (hDlg)
//
// Input: hDlg - Handle of the Dialog
//
// Return: None
//
// Description:
// This routine sets which connection the application uses
// for processing the query.
//======================================================================
void
SetSelected (HWND hDlg)
{
WORD ListIndex;
char szConnectionName[DBIMAXPATHLEN + 1];
// Determine which connection is selected.
ListIndex = (WORD)SendDlgItemMessage(hDlg,
IDC_LB_CONNECTIONS,
LB_GETCURSEL, 0, 0);
// Get the selected connection.
SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS, LB_GETTEXT,
(WPARAM)ListIndex,
(LPARAM)szConnectionName);
// Set the Static control with the selected connection.
SendDlgItemMessage(hDlg, IDS_SELECTED_CONNECTION,
WM_SETTEXT,
0, (LPARAM) szConnectionName);
// Check if this is the standard database.
if (!strcmp(szConnectionName, szStandard))
{
// Show the Directory controls.
ShowWindow(GetDlgItem(hDlg, IDC_DIRECTORY),
SW_SHOW);
ShowWindow(GetDlgItem(hDlg, IDC_EDIT_DIRECTORY),
SW_SHOW);
}
else
{
// Hide the directory controls.
ShowWindow(GetDlgItem(hDlg, IDC_EDIT_DIRECTORY),
SW_HIDE);
ShowWindow(GetDlgItem(hDlg, IDC_DIRECTORY),
SW_HIDE);
}
}
//======================================================================
// Function:
// HourGlassCursor(turnOn)
//
// Input: turnOn - Turn on or off the Hourglass cursor
//
// Return: TRUE
//
// Description:
// Turns the hourglass cursor on or off according to value
// specified in turnOn.
//======================================================================
BOOL CALLBACK
HourGlassCursor (BOOL turnOn)
{
if (turnOn)
{
if (SetCursor(LoadCursor(NULL, IDC_WAIT)))
{
ShowCursor(TRUE);
}
}
else
{
if (SetCursor(LoadCursor(NULL, IDC_ARROW)))
{
ShowCursor(TRUE);
}
}
return TRUE;
}
//======================================================================
// Function:
// LoadQuery(QryType)
//
// Input: Query Type (DBIQryLang).
//
// Return: 1 if succesful,
// 0 if error
//
// Description:
// Using a Windows 3.1 Common Dialog, opens a file open
// dialog box to read a .QBE or .SQL query file into the
// query edit window.
//======================================================================
UINT16
LoadQuery (DBIQryLang QryType)
{
// File types for file open dialog box.
char* SQLFilter = "SQL Script(*.SQL)\0*.SQL\0"
"QBE Script(*.QBE)\0*.QBE\0";
char* QBEFilter = "QBE Script(*.QBE)\0*.QBE\0"
"SQL Script(*.SQL)\0*.SQL\0";
HFILE hFile; // Handle to the returned file
static char pBuf[256]; // filename
LONG flength; // length of file
char ch[1]; // input character
OPENFILENAME ofn; // structure used by File Open
// common dialog
char* szInputBuffer; // pointer to input buffer
char* start; // pointer used as a marker
// Init the structure used by File Open dialog.
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hMainWnd;
ofn.hInstance = hInst;
if (QryType == qrylangQBE)
{
ofn.lpstrFilter = QBEFilter;
}
else
{
ofn.lpstrFilter = SQLFilter;
}
ofn.lpstrCustomFilter = NULL;
ofn.nFilterIndex = 1L;
ofn.lpstrFile = pBuf;
ofn.nMaxFile = 256;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.lpstrDefExt = NULL;
ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR;
// Use the FileOpen common dialog box to get the file name.
if (GetOpenFileName(&ofn))
{
// Open the selected file
hFile = _lopen(ofn.lpstrFile, READ);
if (hFile == HFILE_ERROR)
{
MessageBox(NULL, "Could Not Open File", "File Open",
MB_ICONHAND);
return 0;
}
// Compute length of string needed for file text.
flength = 0;
while (_lread(hFile, ch, 1) != 0)
{
if (ch[0] == '\n')
{
flength += 2; // Need two for newline so
// we can format for edit control.
}
else
{
flength++; // Otherwise length equals one per char.
}
}
// Add one for null.
flength += 1;
// Return to beginning of file.
_llseek(hFile, 0, 0);
// Allocate memory, pointer "start" will remember our place.
start = szInputBuffer = (char *) malloc((int) flength + 1);
memset(szInputBuffer, 0, (int) flength + 1);
if (!szInputBuffer)
{
MessageBox(NULL, "Unable to allocate memory", "Error", MB_ICONHAND);
return FALSE;
}
while ( _lread(hFile, ch, 1) != 0)
{
if (ch[0] == '\n')
{
*szInputBuffer = '\r';
szInputBuffer++;
*szInputBuffer = '\n';
szInputBuffer++;
}
else // Otherwise just read in characters.
{
*szInputBuffer = ch[0];
szInputBuffer++;
}
}
// Reset to beginning of string.
szInputBuffer = start;
// Put the string into the edit control.
SendDlgItemMessage(hMainWnd, IDC_QUERY_EDIT, WM_SETTEXT,
0, (LPARAM) szInputBuffer);
// Cleanup.
free(szInputBuffer);
_lclose(hFile);
return TRUE;
}
return FALSE;
}
//======================================================================
// Function:
// SaveQuery(QryType)
//
// Input: Query Type (DBIQryLang).
//
// Return: 1 if succesful,
// 0 if error
//
// Description:
// Using a Windows 3.1 Common Dialog, opens a file save
// dialog box to save the contents of the query edit
// window to a .QBE or .SQL query file
//======================================================================
UINT16
SaveQuery (DBIQryLang QryType)
{
// File types for File Save dialog box.
char* SQLFilter = "SQL Script(*.SQL)\0*.SQL\0"
"QBE Script(*.QBE)\0*.QBE\0";
char* QBEFilter = "QBE Script(*.QBE)\0*.QBE\0"
"SQL Script(*.SQL)\0*.SQL\0";
static char pBuf[256]; // filename
HFILE hFile; // Handle to the file
OFSTRUCT ofStruct; // OpenFile structure
OPENFILENAME ofn; // structure used by File Open common dialog
char* szQuery; // pointer to text buffer
char* szSeek; // equals szQuery at first
LONG lTextLength; // length of text
// Init the structure used by File Open dialog.
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hMainWnd;
ofn.hInstance = hInst;
if (QryType == qrylangQBE)
{
ofn.lpstrFilter = QBEFilter;
}
else
{
ofn.lpstrFilter = SQLFilter;
}
ofn.lpstrCustomFilter = NULL;
ofn.nFilterIndex = 1L;
ofn.lpstrFile = pBuf;
ofn.nMaxFile = 256;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.lpstrDefExt = NULL;
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY |
OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
if (GetSaveFileName(&ofn))
{
// Determine the length of the text.
lTextLength = SendDlgItemMessage(hMainWnd, IDC_QUERY_EDIT,
WM_GETTEXTLENGTH,
0, 0);
// Allocate memory to contain the query.
if ((szQuery = szSeek = (char*) malloc((int)lTextLength + 1))
== NULL)
{
MessageBox(NULL, "Out of Memory!",
"Fatal Error", MB_ICONHAND);
return FALSE;
}
// Get the query from the edit control.
SendDlgItemMessage(hMainWnd, IDC_QUERY_EDIT, WM_GETTEXT,
(int)lTextLength + 1, (LPARAM)szQuery);
// Open the selected file.
hFile = OpenFile(ofn.lpstrFile, &ofStruct, OF_CREATE);
// Check for errors.
if (hFile == HFILE_ERROR)
{
MessageBox(NULL, "Could Not Open File", "File Open",
MB_ICONHAND);
return FALSE;
}
// Format the query and write to file.
while (*szQuery)
{
if (*szQuery == '\r')
{
szQuery++; // Ignore extra newline.
}
else
{
_lwrite(hFile, (void huge *)(szQuery++), 1);
}
}
// Close the file.
_lclose(hFile);
// Free memory.
free(szSeek);
}
return TRUE;
}
//======================================================================
// Function:
// SaveResultSet(hCur, hDb)
//
// Input: hCur - Handle to the cursor of the in-memory table representing
// the result set of the last query.
// hDb - Handle to a STANDARD database.
//
// Return: 1 on success
// 0 on failure
//
// Description:
// Using a Windows 3.1 Common Dialog, opens a file save
// dialog box to save the contents of the query edit
// window to a .QBE or .SQL query file
//======================================================================
UINT16
SaveResultSet (hDBICur hCur, hDBIDb hDb)
{
static char pBuf[256]; // filename
char pString[300]; // Message String
OPENFILENAME ofn; // structure used by File Open common dialog
char* ScriptFilter = "Paradox Database(*.DB)|*.DB|";
CHAR chWildChar = '|'; // This is the wildcard separator
UINT16 uCtr = 0;
while (ScriptFilter[uCtr])
{
if (ScriptFilter[uCtr]==chWildChar)
{
ScriptFilter[uCtr]=0;
}
uCtr++;
}
// Init the structure used by File Open dialog.
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hMainWnd;
ofn.hInstance = hInst;
ofn.lpstrFilter = ScriptFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nFilterIndex = 1L;
ofn.lpstrFile = pBuf;
ofn.nMaxFile = 256;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.lpstrDefExt = "DB";
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY |
OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
if (GetSaveFileName(&ofn))
{
if (!QuerySaveResultSet(hCur, hDb, pBuf))
{
return FALSE;
}
else
{
wsprintf(pString, "%s was successfully created.", pBuf);
MessageBox(hMainWnd, pString, "Query SQL/QBE Example", MB_OK);
}
}
return TRUE;
}
//======================================================================
// Function:
// RemoveConnection(hDlg, array, nIndex)
//
// Input: hDlg - Handle to the connection dialog box.
// array - A DBStructArray, i.e., an array of structures
// containing valid database names and handles
// nIndex - Index into the connection dialog box of
// the database connection to be removed.
//
// Return: 1 on success
//
// Description:
// Removes a database connection from the connection listbox
// inside the connection dialog box. Also removes the
// corrseponding structure from the array of structures passed
// via the array parameter and resets the currently selected
// selection to the STANDARD database.
//======================================================================
UINT16
RemoveConnection (HWND hDlg, DBStructArray array, int nIndex)
{
int i;
int j;
switch(nIndex)
{
case 0:
MessageBeep(MB_ICONEXCLAMATION);
MessageBox(NULL, "Cannot delete STANDARD database", "Error",
MB_ICONEXCLAMATION);
break;
case LB_ERR:
MessageBeep(MB_ICONEXCLAMATION);
break;
default:
// Reset the static control showing currently selected dialog
// box back to the default.
SendDlgItemMessage(hDlg, IDS_SELECTED_CONNECTION, WM_SETTEXT,
0, (LPARAM) szStandard);
// Remove item from list box.
SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS, LB_DELETESTRING,
nIndex, 0);
// Close database handle.
QueryDbiCloseDatabase(&array[nIndex].hdb);
// Pack array.
for (i = nIndex, j = nIndex + 1; j < MAX_DATABASE_HANDLES;
i++, j++)
{
array[i].hdb = array[j].hdb;
strcpy(array[i].szDatabaseName, array[j].szDatabaseName);
}
// Last member is now blank.
array[j].hdb = 0;
strcpy(array[j].szDatabaseName, "");
}
return TRUE;
}
//======================================================================
// Function:
// GenProgCallBack(ecbType, iClientData, pCbInfo)
//
// Input: ecbType - Callback type (CBType)
// iClientData - Pointer to client information that is passed into
// the callback function (UINT32)
// pCbInfo - The callback structure that holds the information
// about the current state of affairs with
// IDAPI(pVOID)
//
// Return: The action that should be taken (CBRType)
//
// Description:
// This function is called when IDAPI is running an internal
// process and the application setup the callback. The callback
// is sent the current CallBack type (ecbType) so that it can
// react appropriatly. It is sent the pointer to data that was
// passed into the DbiRegisterCallBack function. This data can
// be a Window handle, pointer to a structure etc. In this case
// it is simply a string. It is also sent information about the
// state of this callback in the structure that was passed into
// the DbiRegisterCallBack() function. In our example the
// callback is a progress callback - therefore, we passed a
// progress structure into DbiRegisterCallBack(). We always
// return cbrUSEDEF as we do not want to worry about the callback.
// However, if this was another callback return type you may want
// to return a different callback return type.
//======================================================================
CBRType DBIFN
GenProgCallBack (CBType ecbType, UINT32 iClientData, pVOID pCbInfo)
{
CBPROGRESSDesc *eCBPROGRESSDesc;
CHAR szMessage[DBIMAXMSGLEN + 1 + 30]; // Reserve space for max
// Message plus client
// data
memset(szMessage, 0, DBIMAXMSGLEN + 1);
// Set to stop a Unused variable warning.
iClientData=iClientData;
switch (ecbType)
{
// In case this is a General Progress callback display the progress
// information.
case cbGENPROGRESS:
// First cast the pVOID structure as a General Progress structure.
eCBPROGRESSDesc = (CBPROGRESSDesc far *)pCbInfo;
// Next if the percent done is -1 then the only relevent data is in
// the message string (szMsg).
if (eCBPROGRESSDesc->iPercentDone < 0)
{
wsprintf(szMessage, "%s", eCBPROGRESSDesc->szMsg);
DisplayProgress(szMessage);
}
else
{
// Otherwise you can use the percent done. Here we simply
// display the percent complete. But you can use this number
// to display a moving bar to graphically display the amount
// complete.
wsprintf(szMessage, "%s:%i",
eCBPROGRESSDesc->szMsg, eCBPROGRESSDesc->iPercentDone);
DisplayProgress(szMessage);
}
break;
default:
DisplayProgress(" ### In the Callback function");
}
return cbrUSEDEF;
}
//=====================================================================
// Function:
// MakeFullPath (pszDirectory, pszRelativeDirectory)
//
// Input: pszDirectory - String to contain the path to the tables
// directory
// pszRelativeDirectory - String which contains the relative offset
// from the current directory
//
// Return: int - If the directory exists
//
// Description:
// This function is used to get the fully qualified path to
// the directory which will contain the tables. This function
// will only work when pszRelativeDirectory contains either "."
// an absolute path, or <..\\..\\>TABLES.
//=====================================================================
int
MakeFullPath (pCHAR pszDirectory, pCHAR pszRelativeDirectory)
{
int iExists; // Does the directory exist?
int iLen; // Length of the path
int iLoop; // Loop counter
int iDepth = 0; // How many ..\\ in the directory
// Assume absolute path if second character is a ':'.
if (pszRelativeDirectory[1] == ':')
{
strcpy(pszDirectory, pszRelativeDirectory);
}
else if (!strcmp(pszRelativeDirectory, "."))
{
// Get the current working directory.
getcwd(pszDirectory, DBIMAXPATHLEN);
}
else
{
// Get the current working directory.
getcwd(pszDirectory, DBIMAXPATHLEN);
iLen = strlen(pszDirectory);
// Remove relative parts of the path.
iDepth = 0;
while (!strncmp(&pszRelativeDirectory[iDepth * 3], "..\\", 3))
{
for (iLoop = iLen; iLoop > -1; iLoop = iLoop - 1)
{
if (pszDirectory[iLoop] == '\\')
{
break;
}
}
iLen = iLoop - 1;
iDepth++;
}
// Copy the 'TABLES' directory to form the full path to the tables.
// Need to move szDirectory past the '\\' and szTblDirectory
// past the '..\\'.
strcpy(&pszDirectory[iLoop+1], &pszRelativeDirectory[(3 * iDepth)]);
}
// Check if the directory exists
iExists = access(pszDirectory, 00);
return iExists;
}