"DSN=MYDB"

"Defau">
技术频道

如何在VC++6.O下动态加载ODBC数据源

如何在VC++6.O 下动态加载 ODBC数据源

SQLConfigDataSource()
SQLConfigDataSource(NULL,ODBC_ADD_DSN, "Microsoft FoxPro Driver (*.dbf)",
"DSN=MYDB"

"DefaultDir=c:mydir"

"FIL=FoxPro 2.5"

"DriverId=280"))

在注册DSN时,SQLConfigDataSource函数的第二个参数应该是ODBC_ADD_DSN,第三个参数指定了ODBC驱动程序,它的写法可以参照ODBC管理器的驱动程序页。第四个参数说明了数据源的各种属性,它是由一系列子串构成,每个子串的末尾必须有一个“”。最重要的属性是“DSN=数据源名”,其它属性包括缺省目录以及驱动程序版本信息。在上例中,使用FoxPro 2.5的版本,所以DriverId应该是280,对应地,FoxPro 2.6的DriverId是536,FoxPro 2.0的是24。

如果读者对SQLConfigDataSource函数的第四个参数的设置方法不清楚,那么可以打开Windows的注册表看一看已注册过的DSN的各项属性。运行RegEdit可以打开注册表,然后依次打开HKEY_CURRENT_USER->Software->ODBC->ODBC.INI,就可以看到已注册的DSN,打开各DSN,则可以看到该DSN的各项属性,读者可以仿照DSN属性来设置第四个参数。

的名字必须唯一,因此如果要注册的DSN已被注册过,那么SQLConfigDataSource就修改原来DSN的属性。

一、ODBC
开放数据库连接ODBC(Open Database Connec-tivity)是微软开放服务结构WOSA中关于数据库的一
个重要部分,它允许应用程序通过ODBCAPI访问不同数据资源中的数据,从而为数据库编程提供了
一个标准接口。ODBC是对SQL Access Group的CLI标准的一种实现,它允许应用程序访问范围很广
的数据库(从简单的ASCII文本到复杂的主框架数据库),除了Windows平台外,ODBC还可以在其
他诸如UNIX等的操作平台上使用,因此ODBC获得了世界上大多数领先的数据库和应用程序开发商
的广泛支持。
ODBC主要包括了四层结构:最上层是应用程序,第二层是驱动程序管理器,第三层是不同的驱
动程序,对应不同的数据库,最底层是具体的数据源。每个不同的数据资源类型由一个ODBC驱动程
序支持,这个驱动程序完成了ODBC API程序的核心,而且与数据库通讯。
二、一般加表数据源的方法
通常,开发ODBC应用程序之前必须要手动加入所用的数据源,利用位于控制面板中的ODBC管
理器可以方便地实现数据库加载。双击控制面板中32-bit ODBC的图标就会出现管理器对话框,点击
Add按钮加人数据源,选择使用的驱动程序、数据库名称、服务器地址或其他缺省设置后就把数据源
加载到ODBC管理器中了。ODBC管理器负责安装驱动程序、管理数据源,帮助程序员跟踪ODBC的函
数调用,并能将应用程序的SQL语句及其他消息传递给驱动程序,而驱动程序则负责将结果集传回应
用程序。
利用VC++6.0的AppWizard创建一个基于单文档的工程,选择数据库支持并根据提示加人所需
数据库,这样就可以在应用程序中实现对该数据源的增加、修改和删除等操作了。
毫无疑问,采用上述方法就能方便地对指定数据库进行操作。但是,实际运用中,用户往往要求
在同一个应用程序中能任意访问不同的数据源,开发人员无法确定要加载的数据源,采用一般的加载
方法就有了无法克服的缺陷。显然,这时就要求动态地进行ODBC数据源加载,用户只要选择所需的
数据源,应用程序就会自动地把它装载到ODBC管理器。 "
三、动态加载数据库
创建ODBC数据源可以调用Windows系统子目录下的动态链接库Odbcint.dll中的函数SQLConfigDataSource()
该函数可以动态地增加、修改和删除数据源。
lQLConfigDataSource()函数
SQLConfigDataSource()的原型如下:
BOOLSQLConfigDataSource(HWND hwndParent, UINT
fRequest,LPCSTR IpszDriver, LPCSTR IpszAttributes);
其中四个参数的用法如下:
●参数hwndPwent是父级窗口句柄。如果句柄为NULL,将不会显示一些有关的对话框。
如果参数 IpszAttributes提供的信息不够完善,在创建过程中就会出现对话框要求用户提供相应信息。
●参数fRequest可以设置为下面的数值之一:
ODBC_ADD_DSN: 增加_个新数据源
ODBC_CONHG_DSN: 配置(修改)一个已经存在的数据源
ODBC_REMOVE_DSN: 删除一个已经存在的数据源
ODBC_ADD_SYS_DSN:. 增加一个新的系统数据源
ODBC_CONFIG—SYS—DSN: 更改一个已经存在的系统数据源
ODBC_REMOVE_SYS_DSN:. 删除一个已经存在的系统数据源
●参数lpszDriver是数据库引擎名称,可以参见
ODBC管理器中对ODBC驱动程序的描述。比如要加
载的是Excel数据库,那么数据库引擎名称就为Microsoft Excel Driver(*.xls)

●参数lpszAttributes为一连串的"KeyName=value"
字符串,每两个KeyName值之间用""字符隔开。KeyName主要是新数据源缺省的驱动程序注册说明,其中最主要的关键字是"DSN"----- 新数据源的名称,其余关键字则根据不同的数据源有不同要求。关于lpszAttributes参数的具体设置,详细可以参考Windows系统目录下帮助文件Odbcjtn.hlp主题目录标签中的"ODBC API函数改变|SQLConfigDatasource"条目。
2.SqlConfigDataSource的应用条件
使用SqlConfigDataSource函数之前,必须把
ODBCINST.H文件包含在工程头文件中,将ODBC-
CP32.LIB加人工程,同时保证ODBCCP32.DLL运行时处于系统子目录下。
3.SqlConfigDataSource的应用示例
以下的例子采用SQLConfigDataSource ODBC API函数在VC++6.0下动态加载任意一个Excel数
据源。
由于要求是动态地加载数据源,事先没法手动向ODBC管理器加载数据源,因此无法选择数据库
支持,不能建立基于单文档或多文档的应用程序。启动VC++6.0,利用AppWizard建立一个基于对
话框的应用程序,工程名称为"My"。在对话框模板上放置一个按钮,其ID号为IDC-GETDATA,
Caption为"调数据源"。再派生出一个基于CFile-Doialg类的新类CMyFileDialog,以标准文件对话框
方式选择打开文件,具体做法请参阅有关资料,这里不作说明。
由于应用程序没有对数据库的支持,故必须手工在STDAFX.H文件中加入对数据库的支持,添加有
数据库支持的STDAFX.H文件清单如下所示:

#define VC-EXTRALEAN
/ / Exclude rarely-used stuff from Windows headers
#include <afxwin. h>
//MFC core and standard components
#include <afxext. h> // MFC extensions
#include <afxdb. h //MFC database classes
#include <afxdisp. h> // MFC OLE automation classes
#ifndef _AFX_NO_AFXCMN- SUPPORT
#include <afxcmn. h>
// MFC support for Windows Common Controls
#endif//- AFX-NO_AFXCMN_SUPPORT
//{{AFX_Insert_LOCATION}}
#endif
利用classwizard给按纽添加函数OnGetData,定位到该函数并添加SqlConfigDataSource()以动态调用数据源,值得指出的是,对于要加载的excel数据源的lpszAttributes参数中有个关键字必须要说明,数据源名称:"DSN"
主程序如下
#include"odbcinst.h"
#include"string.h"
#include"stdafx.h"
#include"my.h"
#include"mydlg.h"
IMPLEMENT_DYNAMIC ( CMyFileDialog ,CFileDialog)
CMyFileDialog:: CMyFileDialog ( BOOL bOpenFileDialog,
LPCTSTR lpszDefExt, LPCTSTR lpszFileName,DWORD
dwFlags, LPCTSTR lpszFilter, CWnd * pParentWnd):
CFileDialog (bOpenFileDialog lpszDefExt, lpszFileName,
dwFlags, lpszFilter, pParentWnd)
{}
//CAboutDlg dialog used for App About
class CAboutDlg :public CDialog

public:
CAboutDlg ();
// Dialog Data
/ / { { AFX DATA I CAboutDlg)
enum { IDD = IDDABOUTBOX };
//} }AFX_DATA
/ / ClassWizard generated virtual function overrides
/ / { {AFX VIRTUAL CAboutDlg)
protected:
/ / Implementation
protected:
/ / {AFX_MSG (CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGEMAP()

CAboutDlg: : CAboutDlg() : CDialog(CAboutDlg: : IDD)

//{{AFX_DATA_INIT(CAboutDlg)
//})AFX_DATA_INIT

void CAboutDlg: : DoDataExchange ( CDataExchange * pDX)
{
CDialog:: DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGiN_MESSAGEMAP ( CAboutDlg, CDialog)
// ( {AFX_MSG_MAP(CAboutDlg)
/ / No message handlers
//}}AFX_MSG_MAP
END_MESSAGEMAP()

/ / CMyDlg dialog
CMyDlg: : CMyDlg(CWnd* pParent / * =NULL* /)
CDialog(CMyDlg: : IDD, pParent)
{
//{{AFX_DATA_INIT(CMyDlg)
// NOTE: the ClassWizard will add member
initialization here
//}}AFX_DATA_NIT
m_hlcon =AfxGetApp()->Loadlcon(IDR_MAINFRAME);
}
void CMyDlg: : DoDataExchange ( CDataExchange * pDX)
I
{ CDialog:: DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMyDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//})AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
//{{AFX_MSG_MAP(CMyDIg)
ON WM_SYSCOMMAND()
ON_WMPAINT()
ON WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_GETDATA, OnGetdata)

//}}AFX_MSG_MAP
END_MESSAGEMAP()

/ / CMyDlg message handlers
BOOL CMyDlg: : OnlnitDialog()
{
CDialog: : OnlnitDialog ();
ASSERT( (IDM_ABOUTBOX& OxFFFO) = =IDM_ABOUTBOX);
ASSERT(IDMABOUTBOX < OxF000);
CMenu * pSysMenu = GetSystemMenu ( FALSE);
if(pSysMenu!=NULL)
{CString strAboutMenu;
strAbooutMenu.LoadString(IDS_ABOUTBOX);
if(!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
SetIcon(m.hlcon, TRUE); // Set big icon
SetIcon ( m.hlcon, FALSE); / / Set small icon
/ / TODO: Add extra initialization here
return TRUE; / / return TRUE unless you set the focus to a control
}
void CMyDlg:: OnSysCommand( UINT nlD, LPARAM
lParam)
{ if ((nID & OxFFFO) = = 1DM_ABOUTBOX)
{ CAboutDlg dlgAbout;
dlgAbout. DoModal ();
}
else
{CDialog: : OnSysCommand(nID, lParam);}
}
void CMyDlg: : OnPaint()
{if (lslconic0)
{CPaintDC dc (this); / / device context for painting
SendMessage (WM_ICONERASEBKGND, (WPARAM)
dc.GetSafeHdc0, 0);
/ / Center icon in client rectangle
int cxIcon = GetSystemMetrics ( SMCXICON);
int cyIcon = GetSystemMetrics ( SMCYICON);
CRect rect;
GetClientRect( & rect);
int x = (rect.Width() -cxlcon + 1) / 2;
int y = (rect. Height()-cylcon + 1) / 2;
// Draw the icon
dc.Drawlcon(x, y, m_hlcon);
}


else
{CDiaLog: : OnPaint();}
}
HCURSOR CMyDlg: : OnQueryDraglcon()
{return (HCURSOR) m_hIcon;}

void CMyDlg: OnGetdata ()

/ / TODO: Add your control notification handler code here
CMyFileDialog filedlg (TRUE);
filedlg. DoModal (); / /弹出打开对话框
CString drivername;//数据库引擎名称
CString filetitle = filedlg. GetFileTitle ();
//取得指定文件名(不包含后缀)
CString extention =filedlg. GetFileExt();
/ /取得后缀
if(extention = = "xls")
drivername = "Microsoft Excel Driver (* xis) ";}
char str[50];
strcpy(str, "DSN =");
CString keyname = strcat( str, filetitle);
//keyname 指明了数据源名称
if (FALSE = = SQLConfigDataSource (NULL, ODBC_
ADD_DSN, drivername, keyname)
{MessageBox("加载失败");}
else
{MessageBox("成功将数据源加载到管理器");}
}
进行上述编程之后,用户只要点击"调数据源"按钮,在对话框里任意选择所需Excel数据源,程序就会自动把数据源加载到ODBC管理器而不再需要手动加入,用户可以通过双击"控制面板"中的32位ODBC图据,查看"用户DSN"一栏,即可看见数据源己经自动加载到ODBC管理器了。利用动态加载数据库,用户还可以多次加载所需数据源,操作起来非常方便灵活,应用程序的处理能力也大大增强了。

文章版权归西部工控xbgk所有,未经许可不得转载。