subject_14760.htm
来自「一些关于vc的问答」· HTM 代码 · 共 36 行 · 第 1/2 页
HTM
36 行
<blockquote><p>
回复者:zm 回复日期:2002-09-11 13:30:05
<br>内容:到vc知识库下在我写的ado连接数据库例子。zhangmin
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:eric 回复日期:2002-09-11 14:00:52
<br>内容:找不到啊!:(
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
<font color=red>答案被接受</font><br>回复者:天花乱追 回复日期:2002-09-13 14:53:34
<br>内容:很老的一个程序,你试试看吧<BR><BR>sample database program using dialog interface <BR><BR>--------------------------------------------------------------------------------<BR><BR>this article was contributed by joel mcalduff. <BR><BR>[this assumes the user has installed the necessary dao files, included on the visual c++ cd, and that you are using vc++ version 5.0 or later] <BR><BR>overview: <BR>occasionally on the discussion board there are requests for examples of how to access database information. one common method is a dialog-based retrieval of data from a record, based on search information provided by the user. <BR><BR>this is a sample program i wrote that allows you to access an employee's record based on their ssn. i created a small test database (db1.mdb) using microsoft access 2.0 that has one table called "employees". social security numbers are used as the primary key. there are 3 records in this database: <BR><BR>123-45-6789 (john doe) <BR>987-65-4321 (jane smith) <BR>456-78-9123 (jack jones) <BR><BR>data fields include: <BR>name [text field] <BR>address [memo field] <BR>title [text field] <BR>hire date [date/time field] <BR>social security number (ssn) [number field (double), primary key]. <BR><BR>the demo program: <BR>the test program is called "database". it will open as a centered, small, single-document view, based on the cformview class. the user opens the desired database (in this case, db1.mdb) using the standard file open dialog. after the database is successfully opened, the user enters the employee ssn in the edit box provided in the formview window (do not include the dashes). click on the "find record" button and a dialog will be displayed with the matching employee's data. changes can be made to the data and will be saved to the database if the user clicks the ok button. clicking the cancel button will not save any changes to the database. <BR><BR>i chose the data access object (dao) architecture to open the database and create the recordset. i've found that dao seems to work better when interfacing exclusively with microsoft access (*.mdb) databases. you should, however, be able to use almost identical code/techniques applying the odbc method. for example, a recordset class using the dao system would be based on the cdaorecordset class. a recordset using odbc would be based on the crecordset class. when you generate a dao class without using the "new project" wizard (as is demonstrated in this tutorial), be sure to include the dao header file "afxdao.h" in your stdafx.h file. <BR><BR>creating the database program: <BR>the next several sections will take you through the method i used to create the sample program. first, create a new workspace using the "mfc appwizard (exe)". i named my program "database". scroll through the wizard, choose single document interface, "none" for database support (that's right, you don't need the wizard to do this!), whatever other features you want, then at step 6, select your view class, press the down arrow of the "base class" combobox, and choose "cformview". then click ok and let developer studio do the rest. go ahead and compile your program to make sure everything is working (so far). <BR><BR>center the main program window: <BR>in the initinstance() function of your app class, add m_pmainwnd->centerwindow(); just before the calls to m_pmainwnd->showwindow(sw_show) and m_pmainwnd->updatewindow(); this will center your main window each time the program is run. if you want the window size maximized each time the program is run, change sw_show to sw_maximized in the showwindow() function. if you want to specify exactly how large your main program window should be, add the following code to your program's cmainframe class, in the precreatewindow() function before the return call: <BR>cs.cy = 300; // main window height <BR>cs.cx = 300; // main window width (substitute whatever values you need). <BR><BR>create the database recordset class: <BR>right click on the classes header in the workspace window of developer studio (the area where your classes are displayed in a tree-control view). this is the top listing in bold font (in the sample program it's called "database classes"). choose "new class" and the new class dialog box appears. class type defaults to "mfc class" which is what we want. under class information, type in the name of your new class in the "name:" field. in the sample program i typed in: cdaorecordsetemployees . now click the down arrow of the "base class:" combobox, scroll down and select "cdaorecordset". check your spelling, then click the ok button to create your new class. a series of dialog boxes will follow, asking you to locate the database. click the " ... " box to the right of the dao datasource field, locate your database file (in the sample program this is the "db1.mdb" file), click the "open" button, accept the defaults of "dynaset", "detect dirty columns" and "bind all columns", and click the ok button. choose your database table (or tables) and click ok. your new recordset should now appear in the workspace window on your program's class tree. later, you will link this recordset with the dialog you create in order to display and edit the database data. <BR><BR>create the dialog-based display: <BR>i won't go into too much detail here. you need to create a new dialog resource using the resource editor. design this dialog box to display the database information in whatever form you need. the sample program is very simplistic: the data are displayed in edit boxes with static text labels. you can certainly display the data using other methods (perhaps fill a listbox, combobox or tree-view). <BR><BR>when we created our program, we set up the base view class as a cformview class. this makes it easy to add dialog components to the main program's view window. in the sample program, i modified the formview the same way you edit your dialog: using the resource editor. i added an edit box for the user to type in the employee's ssn, and a button to perform the "find" function. using class wizard, i associated a member variable called m_ssn with the edit box. finally, i created a windows message member function in the view class based on the "find" button, called onbuttonfind(), that will be used to create the dialog object, link the dialog and database, and find records that match the user supplied ssn's (described in more detail below). <BR><BR>associating database data with dialog controls and variables: <BR>linking the database data to their respective dialog box components can be accomplished in a couple of ways: you can read, buffer, and write the data yourself, using setfieldvalue() functions, or you can use the dialog data exchange mechanism (ddx) provided by mfc. i chose the "easy" approach and used ddx. however, you need to set up a couple of things after creating your dialog class to link it with your database file (just to clarify, we are "linking" our database file and our dialog box using the daorecordset class that we created earlier). <BR><BR>after you create your dialog box using the resource editor and have arranged all of its controls where you want them, leave your dialog box open in the resource editor. <BR><BR>select -- view | class wizard -- from the menu bar. class wizard recognizes the dialog as a new potential class and asks if you want to create a new class based on this dialog. select ok and you will now be in the new class window. give your new class a name -- in the sample program i chose cdialogdata . the base class should have defaulted to cdialog (which is what we want) and the dialog id should have defaulted to your new dialog's id (usually something like idd_dialog1, if you didn't specify an id name yourself in the dialog's "properties" box). click ok to create your new dialog class. <BR><BR>now open the class wizard again (if it closed, select -- view | class wizard -- again) and click on the "class info" tab on the far right side. in the "class name" list box at the top, scroll down and select the name of the new dialog class you just created (again, in the sample program this was named cdialogdata). at the bottom is another listbox named "foreign variable". choose this, scroll down, and select the name of your recordset class that was created earlier (remember, in the sample program this is called cdaorecordsetemployees). type in a variable name in the "foreign variable" box. i usually use the same variable name created by the appwizard: m_pset . (this is actually a pointer variable ; eventually it will point to the address of your recordset class, after that class has been created and initialized with data from the database file). <BR><BR>with class wizard still open, click on the "member variables" tab. you will see all of the control id's listed for your dialog box on the left side of the display window. now when you want to add member variables for these controls, you will be able to select any of the fields available in your recordset (i.e., in your database). these steps are necessary in order to link your dialog's variables with the recordset (database) fields and use ddx to handle transferring and saving the data from the database. when you have finished assigning your dialog control variables, click the ok button to close the class wizard and save your changes. later, you will need to assign the foreign variable pointer (m_pset) to the address of your database recordset. <BR><BR>opening the database file and recordset: <BR>we need to open the database file and pass its address to our recordset class so that we can access its data using our dialog box. this is accomplished within the onopendocument() function of the doc class in the sample program. we will also need a pointer to the recordset object. this is created in the doc header file, so don't forget to include your recordset's header file in the document class's header file. in the sample program, look in the databasedoc.h file under // custom member functions and variables -- you'll see a protected pointer variable cdaorecordsetemployees * m_pset , and a public member function that can be used to retrieve it called getrecset() [trying to be strictly object-oriented here]. we will use this function later in the view class to obtain the address of the recordset and assign it to our dialog's foreign m_pset variable (see the linking the dialog and database: section). here's the onopendocument() function: <BR><BR>bool cdatabasedoc::onopendocument(lpctstr lpszpathname)<BR>{<BR> if (!cdocument::onopendocument(lpszpathname))<BR> return false;<BR><BR> // if user selected a file then try to open it as a database<BR> m_pdb = new cdaodatabase;<BR> assert(m_pdb != null);<BR> try<BR> {<BR> m_pdb->open(lpszpathname);<BR> }<BR> catch (cdaoexception* e)<BR> {<BR> delete m_pdb;<BR> m_pdb = null;<BR><BR> tchar szcause[255];<BR> cstring strformatted = _t("the data file could not be opened because of this error: \n");<BR> e->geterrormessage(szcause, 255);<BR> strformatted += szcause;<BR> afxmessagebox(strformatted, mb_ok | mb_iconexclamation);<BR> e->delete();<BR> m_bfileopen = false;<BR> return false;<BR> }<BR><BR> // if database successfully opened then open employees recordset<BR> m_pset = new cdaorecordsetemployees(m_pdb);<BR> assert(m_pset != null);<BR> try<BR> {<BR> m_pset->open();<BR> }<BR> catch (cdaoexception* e)<BR> {<BR> delete m_pset;<BR> m_pset = null;<BR><BR> tchar szcause[255];<BR> cstring strformatted = _t("the data file could not be opened because of this error: \n");<BR> e->geterrormessage(szcause, 255);<BR> strformatted += szcause;<BR> afxmessagebox(strformatted, mb_ok | mb_iconexclamation);<BR> e->delete();<BR> m_bfileopen = false;<BR> return false;<BR> }<BR><BR> // boolean variable to indicate database is open<BR> m_bfileopen = true;<BR> return true;<BR>}<BR><BR><BR><BR>[note: the catch statements which display dao exceptions were modified from a sample database application included on the visual c++ cd] <BR><BR>the user first sees the common "file open" dialog to locate the correct database file (db1.mdb). if the user has selected a file, we create a new cdaodatabase object and assign our member pointer variable to it. we then try to open this object as a cdaodatabase file. if this is successful, we create a new cdaorecordsetemployees object and assign our member pointer variable to it. we then try to open our recordset, passing it the pointer to the database. if this is successful, we update the boolean "fileopen" variable (used to keep track of the open recordset in the view class, but could be done using the isopen() function as well) and allow the onopendocument() function to return. since we created our database and recordset objects using the "new" function, we need to add appropriate "delete" functions as well. take a look around the databasedoc.cpp file and note where the "delete" functions are used. (this is to prevent those pesky memory leaks!) <BR><BR>linking the dialog and database: <BR>look at the onbuttonfind() function in the cdatabaseview.cpp file. <BR><BR>void cdatabaseview::onbuttonfind()<BR>{<BR> cdatabasedoc* pdoc = getdocument();<BR> assert_valid(pdoc);<BR><BR> // if the database file has been opened view the data<BR> if ( pdoc->isfileopen() )<BR> {<BR> // record ssn user entered<BR> updatedata(true);<BR><BR> // create the data dialog object<BR> cdialogdata dlg;<BR> assert(&dlg != null);<BR><BR> // set the ptr to the open database set<BR> dlg.m_pset = pdoc->getrecset();<BR><BR> // create search string<BR> dlg.m_pset->m_strfilter.format("[ssn] = %9.0f", m_ssn);<BR><BR> // requery the database<BR> dlg.m_pset->requery();<BR><BR> // allow editing of database fields<BR> dlg.m_pset->edit();<BR><BR> // if user edited data, update the database<BR> if (dlg.domodal() == idok)<BR> dlg.m_pset->update();<BR> }<BR> else<BR> afxmessagebox("please open the database file first", mb_ok | mb_iconexclamation);<BR>}<BR><BR><BR><BR>if the user has clicked the find record button, we first make sure that the database file has been opened, otherwise remind the user to do this with a messagebox. if the database file is open, we save the ssn the user entered, create the dialogdata dialog box and set its m_pset variable equal to the recordset's pointer using the following statement: dlg.m_pset = pdoc->getrecset(); since we create our dialog object in the view class, don't forget to include the dialog class's header file at the top of the view class source file (somethingview.cpp). <BR><BR>searching the database: <BR>we then format our search string (a.k.a.: find the record that has the same ssn as that entered by the user), requery the database and display the dialog box, hopefully filled with all the correct data. a call to the edit() function is made so that if the user changes the data displayed in one of the dialog controls and clicks the ok button, the database data can be updated (using the update() function) with the new changes. (you'll get an error message if you try to use update() without calling edit() or new() first). to search through the database and find the employee record that matches the ssn entered by the user, we use the m_strfilter function and requery() the database file. m_strfilter , however, is just as it appears -- a string value. therefore, we have to convert our "double" ssn value into a "string" ssn value using the following function: dlg.m_pset->m_strfilter.format("[ssn] = %9.0f", m_ssn); this sets the value of the m_strfilter variable to a complete string value of "[ssn] = 123456789" when the user enters 123456789 as the employee's ssn. <BR><BR>when i created the test database (db1.mdb), i set up the ssn field as a number field of type "double" (i.e: double precision floating point). it could have just as easily been a text field or long integer. i wanted a number value so that i could designate it as the primary key (see the ms access help if you don't know about primary keys). anyway, when visual c++ interprets the *.mdb file during creation of the daorecordset class, it assigns type "double" to the ssn field. when i created the ssn edit box in the cformview window (the edit box the user enters the employee's ssn number into before pressing the "find record" button), i created a member variable (called m_ssn) using class wizard and assigned it to a type of "double" as well. <BR><BR>by the way, "search" is probably the wrong term to use here. what we are really doing is "filtering" the recordset/database to return only those files that match the m_strfilter variable. since we are basing this filter on a unique database element, the ssn, we know that the requery() function should only return one record. it is possible, therefore, to create a filter that can return more than one record. you would then need to set up your data viewing window so that it contains some method for displaying each matching record. <BR><BR>conclusion: <BR>these are some of the major areas to address when creating your own database application. hopefully this has provided some basic steps to creating at least one type of database application. i hope you find the test program helpful as a template in designing your own custom interface program. it has room for infinite modifications (such as adding new records, deleting old ones, other types of searches/filters, etc.). although i used a simple database with only one table, multiple related tables can be used just as easily. i recommend creating a new recordset for each table in the database, however, then perform your searches/filters using unique keys or on each recordset separately. believe it or not, most of this information can be found using the online help and documentation (that's how i've found most of it, along with trial and error - i am not a professional programmer!). the problem is finding it and, unfortunately, that's not very straightforward. most of the vc++ review books seem to spend very little time on database programming. developer central has a tutorial on database programming that i found helpful. look at the sample database programs as well (under samples | mfc | database) on the visual c++ cd. they provide some good code to dissect and learn from. good luck! <BR><BR>
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?