登录 用户中心() [退出] 后台管理 注册
 

热门搜索:
您的位置:首页 >> 马上代码 >> 马上代码 >> 主题: FreeTDS User Guide
标题 FreeTDS User Guide
clq
浏览(1650) 2009-10-29 12:18:55 发表 编辑

关键字:

http://www.freetds.org/userguide/samplecode.htm

--------------------------------------------------

FreeTDS User Guide: A Guide to Installing, Configuring, and Running FreeTDS
Prev Chapter 11. Programming Next
DB-Library for the Tenderfoot


Few things are harder to put up with than the annoyance of a good example.
Mark Twain

Below is a complete sample working db-lib program, presented as a series of examples.

Features of sample code

*

Processes command-line options to select the server, database, username, and password
*

Remaining arguments on the command line comprise the SQL query to execute
*

Installs error and message handlers
*

Illustrates correct row-processing
*

Illustrates correct error detection and handling

Other sample code may be found in the distribution, in the cleverly named samples directory. A complete program, heavily commented for your perusal, is apps/bsqldb.c.

Important

What's the big deal with errors?

Correct handling of errors is extremely important in database applications because they involve two systems most others don't: the network and the database server. Both can give rise to errors that, if not detected and reported when they occur, let the application proceed blithely on until something truly mysterious happens. In the worst case, in the absence of a properly reported error, the application may seem to have updated the data, when in fact it did not.

Every db-lib application uses the network, making it subject to network failures. Database programs also almost always have very high data integrity requirements. It is necessary to know the row was absolutely, positively committed, once and only once, without error or exception. Without taking great care to trap and handle all error conditions, no statement about the program's reliability can be made with confidence.

How to Get and Build the sample code

1.

Run doc/grep_sample_code to extract the C code from the User Guide SGML source.
2.

Compile
3.

Link

Files Required to Build the Sample Code

*

sybfront.h
*

sybdb.h
*

libsybdb.a or libsybdb.so

Your library's extension may vary according to your operating system.

The source code may be built with commands similar to these. The precise options and paths depend on your particular system. The commands below work with the GNU compiler and linker on an ELF system with dynamic linking, common on Linux and BSD systems.

Example 11-1. Building the Sample Code

$ ../doc/grep_sample_code ../doc/userguide.sgml > sample.c
$ cc -I /usr/local/include -Wl,-L/usr/local/lib -Wl,-R/usr/local/lib sample.c -lsybdb -o sample


where /usr/local/include and /usr/local/lib are respectively the locations of your header files and libraries.

We now proceed to the code proper.
Header files

We need two header files to use db-lib. We need a few others to deal with I/O in C, as you know. Also declare the error and message handler functions, more about which later.

Example 11-2. Sample Code: db-lib header files

#include
#include
#include
#include
#include
#include
#include

#include /* sqlfront.h always comes first */
#include /* sybdb.h is the only other file you need */

int err_handler(DBPROCESS*, int, int, int, char*, char*);
int msg_handler(DBPROCESS*, DBINT, int, int, char*, char*, char*, int);


Prolog

Nothing special here. Collect the command line parameters. We do this with the standard getopts(3) function. Cf. man 3 getopts for details.

Example 11-3. Sample Code: db-lib prolog

extern char *optarg;
extern int optind;

const static char syntax[] =
"syntax: example -S server -D db -U user -P passwd\n";

struct {
char *appname, *servername, *dbname, *username, *password;
} options = {0,0,0,0,0};

int
main(int argc, char *argv[])
{
int i, ch;
LOGINREC *login; (1)
DBPROCESS *dbproc; (2)
RETCODE erc; (3)

options.appname = basename(argv[0]);

while ((ch = getopt(argc, argv, "U:P:S:D:")) != -1) {
switch (ch) {
case 'S':
options.servername = strdup(optarg);
break;
case 'D':
options.dbname = strdup(optarg);
break;
case 'U':
options.username = strdup(optarg);
break;
case 'P':
options.password = strdup(optarg);
break;
case '?':
default:
fprintf(stderr, syntax);
exit(1);
}
}

argc -= optind;
argv += optind;

if (! (options.servername
&& options.username && options.password)) {
fprintf(stderr, syntax);
exit(1);
}


111Prolog Notes

(1)
LOGINREC is a structure that describes the client. It's passed to the server at connect time.
(2)
DBPROCESS is a structure that describes the connection. It is returned by dbopen().
(3)
RETCODE is the most common return code type for db-lib functions.

Initialize

Initialize the library. Create and populate a LOGINREC record.

Example 11-4. Sample Code: db-lib Initialize

(1)
if (dbinit() == FAIL) {
fprintf(stderr, "%s:%d: dbinit() failed\n",
options.appname, __LINE__);
exit(1);
}

(2)
dberrhandle(err_handler);
dbmsghandle(msg_handler);

(3)
if ((login = dblogin()) == NULL) {
fprintf(stderr, "%s:%d: unable to allocate login structure\n",
options.appname, __LINE__);
exit(1);
}

(4)
DBSETLUSER(login, options.username);
DBSETLPWD(login, options.password);





112Initialization Notes

(1)
Always make dbinit() the first db-lib call.
(2)
Install the error- and mesage-handlers right away. They're explained in more detail later.
(3)
dblogin() almost never fails. But check! No point in trying to use a null pointer.
(4)
The LOGIN record isn't directly accessible. It's populated via macros like these. There are other fields, but these two are essential. Look for SETLsomething in the documentation.

Connect to the server

dbopen() forms a connection with the server. We pass our LOGINREC pointer (which describes the client end), and the name of the server. Then, optionally, we change to our favored database. If that step is skipped, the user lands in his default database.

Example 11-5. Sample Code: db-lib Connect to the server

if ((dbproc = dbopen(login, options.servername)) == NULL) {
fprintf(stderr, "%s:%d: unable to connect to %s as %s\n",
options.appname, __LINE__,
options.servername, options.username);
exit(1);
}

if (options.dbname && (erc = dbuse(dbproc, options.dbname)) == FAIL) {
fprintf(stderr, "%s:%d: unable to use to database %s\n",
options.appname, __LINE__, options.dbname);
exit(1);
}




Send a query

db-lib maintains a command buffer to hold the SQL to be sent to the server. Two functions — dbcmd() and dbfcmd() — build up the query from strings of text. The command buffer is reset after the query is sent to the server.

We left the SQL on the command line. We fetch it now and send it to the server.

Example 11-6. Sample Code: db-lib Send a query

for (i=0; i < argc; i++) {
assert(argv[i]);
printf("%s ", argv[i]);
if ((erc = dbfcmd(dbproc, "%s ", argv[i])) == FAIL) {
fprintf(stderr, "%s:%d: dbcmd() failed\n", options.appname, __LINE__);
exit(1); (1)


}
}
printf("\n");

if ((erc = dbsqlexec(dbproc)) == FAIL) {
fprintf(stderr, "%s:%d: dbsqlexec() failed\n", options.appname, __LINE__);
exit(1); (2)

}


113Initialization Notes

(1)
Failure at this juncture is rare. The library is merely allocating memory to hold the SQL.
(2)
dbsqlexec() waits for the server to execute the query. Depending on the complexity of the query, that may take a while.

dbsqlexec() will fail if something is grossly wrong with the query, e.g. incorrect syntax or a reference to nonexistent table. It's only the first of a few places where an error can crop up in processing the query, though. Just because dbsqlexec() succeeded doesn't mean you're in the clear.
Fetch Results

A query may produce zero, one, or more results. Broadly, that entails providing buffers to db-lib to fill, and iterating over the results a row (and column) at a time.

Kinds of Results

Results is a special term: it means more than rows or no rows. To process the results means to gather the data returned by the server into the application's variables.

Table 11-4. Kinds of Results
Type Metadata Regular Rows Compute Rows Return Status Example SQL
None None None None None Any INSERT, UPDATE, or DELETE statement
Empty 1 set None 0 or more None SELECT name FROM systypes WHERE 0 = 1
Simple 1 set 0 or more None None SELECT name FROM sysobjects
Complex 2 or more 0 or more 1 or more None SELECT name FROM sysobjects COMPUTE COUNT(name)
Stored Procedure 0 or more 0 or more 0 or more 1 or more EXEC sp_help sysobjects

As the above table shows, results can comprise ordinary rows and compute rows (resulting from a COMPUTE clause). Stored procedures may of course contain multiple SQL statements, some of which may be SELECT statements and might include COMPUTE clauses. In addition, they generate a return status (with a RETURN statement or else automatically) and perhaps OUTPUT parameters.
Data and Metadata

Observe that a row is set of columns, and each column has attributes such as type and size. The column attributes of a row are collectively known as metadata. The server always returns metadata before any data (even for a a SELECT statement that produced no rows).

Table 11-5. Result-fetching functions
Function Fetches Returns Comment
dbresults() metadata SUCCEED, FAIL or, NO_MORE_RESULTS. SUCCEED indicates just that: the query executed successfully (whew!). There may be metadata (and perhaps data) and/or stored procedure outputs available.
nextrow() data REG_ROW, compute_id, NO_MORE_ROWS, BUF_FULL, or FAIL. Places fetched data into bound columns, if any.
Binding

Each time dbresults() returns SUCCEED, there is something to retrieve. db-lib has different functions to deal with the different kinds of results. The functions are of two kinds: those that convert the data into a form desired by the application, known as binding, and those that return the data in "native" form.

To understand binding, it may be easiest to examine two primitive functions, dbdata() and dbconvert(). dbdata() returns a pointer to the column's data. The data to which it points are in "native" form, 4 bytes for an INT, 8 bytes for a DATETIME and so on. dbconvert() converts between datatypes; you can hand it an integer and get back a character array (or a C double. You might think of dbconvert() as atoi(3) on steroids). dbbind() combines these two functions. The application indicates in what form it would like to use each column, and the library converts them on the fly as each row is read.

To bind a column is to provide a buffer to db-lib to fill and indicate which datatype the buffer is meant to hold. [1]

It may be well to pause here to observe the three ways a datatype is described in a db-lib program.

db-lib Datatype Descriptors

Sever Datatype

Describes the data as an abstract type, not representing any particular kind of storage. SYBREAL, for example, doesn't imply any particular arrangement of bits; it just means "a floating-point datatype corresponding to the T-SQL REAL type on the server." These all begin with SYB, e.g. SYBINT4.
Program Variable Datatype

Defines a C variable in a machine-independent way. Because a C defines its int type according the CPU architecture, it may have 2, 4, 8, or some other number of bytes. A DBINT on the other hand, is guaranteed to be 4 bytes and, as such, assuredly will hold any value returned by the server from a T-SQL INT column. These all begin with DB, e.g. DBREAL.
Bind Type

Prescribes a conversion operation. Indicates to dbbind() the Program Variable Datatype defined by the target buffer. Sybase and Microsoft call this the "vartype". These all end with BIND, e.g. STRINGBIND.

Typically it's more convenient to have db-lib convert the data into the desired form. The function that does that is dbind(). So: after fetching the metadata, and before fetching the data, we usually prepare the bound columns.
Fetching Data

Table 11-6. Data-fetching functions
Type Regular rows Compute rows Return status OUTPUT parameters
Meta dbnumcols() dbnumcompute(), dbnumalts(), dbaltop(), dbbylist() dbhasretstatus() dbnumrets()
Binding dbbind(), dbnullbind() dbaltbind(), dbanullbind() dbretstatus() none
Native dbdatlen(), dbdata() dbadlen(), dbalttype(), dbaltutype(), dbaltlen(), dbadata() none dbretdata(), dbretlen(), dbretname(), dbrettype()

The paradigm may now perhaps be clear: Query, fetch results, bind columns, fetch regular rows, fetch compute rows, fetch stored procedure outputs. Repeat as necessary.

Table 11-7. Putting it all together
Step Function Once Per Many Times Per
Query dbsqlexec() Query Program
Fetch metadata dbresults() SQL statement Query
Prepare variables dbbind() Column Statement
Fetch regular data dbnextrow() Row Statement
Fetch compute data dbnextrow() Compute column Statement
Fetch output parameters dbretdata() output parameter Stored procedure
Fetch return status dbretstatus() Stored procedure Program

Important Fetch All Rows!


db-lib doesn't insist every column — or even any column — be bound or otherwise retrieved into the application's variables. There is, however, one absolutely crucial, inflexible, unalterable requirement: the application must process all rows produced by the query. Before the DBPROCESS can be used for another query, the application must either fetch all rows, or cancel the results and receive an acknowledgement from the server. Cancelling is beyond the scope of this document, so for now fetch all rows.

Now, at last, some sample code that fetches data. In the interest of simplicity, we don't bind anything except regular rows.

Example 11-7. Sample Code: db-lib Fetch Results

while ((erc = dbresults(dbproc)) != NO_MORE_RESULTS) {
struct COL (1)
{
char *name;
char *buffer;
int type, size, status;
} *columns, *pcol;
int ncols;
int row_code;

if (erc == FAIL) {
fprintf(stderr, "%s:%d: dbresults failed\n",
options.appname, __LINE__);
exit(1);
}

ncols = dbnumcols(dbproc);

if ((columns = calloc(ncols, sizeof(struct COL))) == NULL) {
perror(NULL);
exit(1);
}

/*
* Read metadata and bind.
*/
for (pcol = columns; pcol - columns < ncols; pcol++) {
int c = pcol - columns + 1;

pcol->name = dbcolname(dbproc, c); (2)
pcol->type = dbcoltype(dbproc, c);
pcol->size = dbcollen(dbproc, c);

if (SYBCHAR != pcol->type) { (3)
pcol->size = dbwillconvert(pcol->type, SYBCHAR);
}

printf("%*s ", pcol->size, pcol->name);

if ((pcol->buffer = calloc(1, pcol->size + 1)) == NULL){
perror(NULL);
exit(1);
}

erc = dbbind(dbproc, c, NTBSTRINGBIND, (4)
pcol->size+1, (BYTE*)pcol->buffer);
if (erc == FAIL) {
fprintf(stderr, "%s:%d: dbbind(%d) failed\n",
options.appname, __LINE__, c);
exit(1);
}
erc = dbnullbind(dbproc, c, &pcol->status); (5)
if (erc == FAIL) {
fprintf(stderr, "%s:%d: dbnullbind(%d) failed\n",
options.appname, __LINE__, c);
exit(1);
}
}
printf("\n");

/*
* Print the data to stdout.
*/
while ((row_code = dbnextrow(dbproc)) != NO_MORE_ROWS){ (6)
switch (row_code) {
case REG_ROW:
for (pcol=columns; pcol - columns < ncols; pcol++) {
char *buffer = pcol->status == -1?
"NULL" : pcol->buffer;
printf("%*s ", pcol->size, buffer);
}
printf("\n");
break;

case BUF_FULL:
assert(row_code != BUF_FULL);
break;

case FAIL:
fprintf(stderr, "%s:%d: dbresults failed\n",
options.appname, __LINE__);
exit(1);
break;

default: (7)
printf("Data for computeid %d ignored\n", row_code);
}


}

/* free metadata and data buffers */
for (pcol=columns; pcol - columns < ncols; pcol++) {
free(pcol->buffer);
}
free(columns);

/*
* Get row count, if available.
*/
if (DBCOUNT(dbproc) > -1)
fprintf(stderr, "%d rows affected\n", DBCOUNT(dbproc));

/*
* Check return status
*/
if (dbhasretstat(dbproc) == TRUE) {
printf("Procedure returned %d\n", dbretstatus(dbproc));
}
}

dbclose(dbproc);
dbexit();
exit(0);
}


114Data-fetching Notes

(1)
As soon as dbresults() reports SUCCESS, the row's metadata are available.
(2)
db-lib columns start with 1.
(3)
dbcollen() returns the sizeof the native data (e.g. 4 bytes for a T-SQL INT). We'll use dbbind() to convert everything to strings. If the column is [VAR]CHAR, we want the column's defined size, otherwise we want its maximum size when represented as a string, which FreeTDS's dbwillconvert() returns (for fixed-length datatypes). [2]
(4)
NTBSTRINGBIND null-terminates the character array for us. "NTB" might perhaps stand for "null terminating byte".
(5)
A zero-length string is not a NULL! dbnullbind() arranges for the passed buffer to be set to -1 whenever that column is NULL for a particular row.
(6)
Each time dbnextrow() returns REG_ROW, it has filled the bound buffers with the converted values for the row.
(7)
Computed rows are left as an exercise to the reader.

Messages and Errors

Errors may originate on the server or in the library itself. The former are known as messages (because they are: they arrive as messages from the server); the latter are termed errors. Their handling is a little intimidating. It requires writing and installing a callback function (whose parameters are predefined by db-lib), and thinking about how to handle different types of errors.

Kinds of Errors

Messages

Messages arise because the server has something to say. [3]. They usually describe some problem encountered executing the SQL. Perhaps the SQL refers to a nonexistent object or attempted to violate a constraint. But they can also be benign, indicating for instance merely that the default database has changed.
Errors

Errors arise either because the application has misused db-lib in some way — say, passed a NULL DBPROCESS pointer or tried to issue a query while results were pending — or because some trouble cropped up in communicating with the server (couldn't find it, say, or didn't hear back from it).

Why these two require distinct handling is lost in the mists of time. But it does help to keep them distinct in your mind, especially while reading the documentation.

To have db-lib use your handler, pass its name to the appropriate dberrhandle() or dbmsghandle() function immediately after calling dbinit().

Example 11-8. Sample Code: db-lib Error and Message handlers

int
msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity,
char *msgtext, char *srvname, char *procname, int line)
{ (1)
enum {changed_database = 5701, changed_language = 5703 }; (2)

if (msgno == changed_database || msgno == changed_language)
return 0;

if (msgno > 0) {
fprintf(stderr, "Msg %ld, Level %d, State %d\n",
(long) msgno, severity, msgstate);

if (strlen(srvname) > 0)
fprintf(stderr, "Server '%s', ", srvname);
if (strlen(procname) > 0)
fprintf(stderr, "Procedure '%s', ", procname);
if (line > 0)
fprintf(stderr, "Line %d", line);

fprintf(stderr, "\n\t");
}
fprintf(stderr, "%s\n", msgtext);

if (severity > 10) { (3)
fprintf(stderr, "%s: error: severity %d >

clq
2009-10-29 12:20:43 发表 编辑


//VC6的STL警告,要放在之前
#pragma warning(disable : 4786)

//VC的编译控制参数,在MFC程序中应当直接在link的选项中设置

//VC中控制生成程序的是控制台还是窗体系统//其实是就控制是否出现DOS窗口
//#pragma comment(linker,"/SUBSYSTEM:WINDOWS")
#pragma comment(linker,"/SUBSYSTEM:CONSOLE")
//VC中控制主程序的入口点
#pragma comment(linker,"/ENTRY:mainCRTStartup")
//#pragma comment(linker,"/ENTRY:WinMainCRTStartup")


#include
#include
#include

//test
#include "edit.h"
#include "font.h"
#include "button.h"
#include "panel.h"
#include "ListView.h"
#include "tree.h"
#include "Form.h"
//#include "SplitPanel.h"
#include "split_panel.h"
#include "data_table.h"
#include "menu_main.h"
#include "main_form.h"

extern "C"
{
#include /* sqlfront.h always comes first */
#include /* sybdb.h is the only other file you need */
}

//---------------------------------------------------------------------------------------------------
int
msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity,
char *msgtext, char *srvname, char *procname, int line)
{
enum {changed_database = 5701, changed_language = 5703 };

if (msgno == changed_database || msgno == changed_language)
return 0;

if (msgno > 0) {
fprintf(stderr, "Msg %ld, Level %d, State %d\n",
(long) msgno, severity, msgstate);

if (strlen(srvname) > 0)
fprintf(stderr, "Server '%s', ", srvname);
if (strlen(procname) > 0)
fprintf(stderr, "Procedure '%s', ", procname);
if (line > 0)
fprintf(stderr, "Line %d", line);

fprintf(stderr, "\n\t");
}
fprintf(stderr, "%s\n", msgtext);

if (severity > 10) {
fprintf(stderr, "%s: error: severity %d >? exiting\n",
"test", severity);
exit(severity);
}

return 0;
}

int
err_handler(DBPROCESS * dbproc, int severity, int dberr, int oserr,
char *dberrstr, char *oserrstr)
{
if (dberr) {
fprintf(stderr, "%s: Msg %d, Level %d\n",
"test", dberr, severity);
fprintf(stderr, "%s\n\n", dberrstr);
}

else {
fprintf(stderr, "%s: DB-LIBRARY error:\n\t", "test");
fprintf(stderr, "%s\n", dberrstr);
}

return INT_CANCEL;
}

//---------------------------------------------------------------------------------------------------


int main()
{

WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
int err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
WSACleanup();
}


//---------------------------------------------------------------------------------------------------

LOGINREC *login;
DBPROCESS *dbproc;
RETCODE erc;

if (dbinit() == FAIL)
{
//fprintf(stderr, "%s:%d: dbinit() failed\n", options.appname, __LINE__);
fprintf(stderr, "%s:%d: dbinit() failed\n", "test", __LINE__);
exit(1);
}

dberrhandle(err_handler);
dbmsghandle(msg_handler);


if ((login = dblogin()) == NULL)
{
fprintf(stderr, "%s:%d: unable to allocate login structure\n",
"test", __LINE__);
exit(1);
}


//没有这两个后面的 dbopen 会出错
DBSETLUSER(login, "sa");
DBSETLPWD(login, "pass");

//db-lib Connect to the server

if ((dbproc = dbopen(login, "192.168.0.1")) == NULL)
{
//fprintf(stderr, "%s:%d: unable to connect to %s as %s\n",
// options.appname, __LINE__,
// options.servername, options.username);
exit(1);
}

char * dbname = "dbname";

if (dbname && (erc = dbuse(dbproc, dbname)) == FAIL)
{
//fprintf(stderr, "%s:%d: unable to use to database %s\n",
// options.appname, __LINE__, options.dbname);
exit(1);
}

//query
char * appname = "test";

if ((erc = dbfcmd(dbproc, "%s ", " select top 2 * from tLogs ")) == FAIL)
{
fprintf(stderr, "%s:%d: dbcmd() failed\n", appname, __LINE__);
exit(1);
}


printf("\n");

if ((erc = dbsqlexec(dbproc)) == FAIL)
{
fprintf(stderr, "%s:%d: dbsqlexec() failed\n", appname, __LINE__);
exit(1);
}

//结果
while ((erc = dbresults(dbproc)) != NO_MORE_RESULTS)
{
struct COL
{
char *name;
char *buffer;
int type, size, status;
} *columns, *pcol;
int ncols;
int row_code;

if (erc == FAIL)
{
fprintf(stderr, "%s:%d: dbresults failed\n",
appname, __LINE__);
exit(1);
}

ncols = dbnumcols(dbproc);

//if ((columns = calloc(ncols, sizeof(struct COL))) == NULL)
if ((columns = (struct COL *) calloc(ncols, sizeof(struct COL))) == NULL)
{
perror(NULL);
exit(1);
}

/*
* Read metadata and bind.
*/
for (pcol = columns; pcol - columns < ncols; pcol++)
{
int c = pcol - columns + 1;

pcol->name = dbcolname(dbproc, c);
pcol->type = dbcoltype(dbproc, c);
pcol->size = dbcollen(dbproc, c);

if (SYBCHAR != pcol->type)
{
pcol->size = dbwillconvert(pcol->type, SYBCHAR);
}

printf("%*s ", pcol->size, pcol->name);

//if ((pcol->buffer = calloc(1, pcol->size + 1)) == NULL)
if ((pcol->buffer = (char *) calloc(1, pcol->size + 1)) == NULL)
{
perror(NULL);
exit(1);
}

erc = dbbind(dbproc, c, NTBSTRINGBIND,
pcol->size+1, (BYTE*)pcol->buffer);

if (erc == FAIL)
{
fprintf(stderr, "%s:%d: dbbind(%d) failed\n",
appname, __LINE__, c);
exit(1);
}

erc = dbnullbind(dbproc, c, &pcol->status);
if (erc == FAIL)
{
fprintf(stderr, "%s:%d: dbnullbind(%d) failed\n",
appname, __LINE__, c);
exit(1);
}
}
printf("\n");

/*
* Print the data to stdout.
*/
while ((row_code = dbnextrow(dbproc)) != NO_MORE_ROWS)
{
switch (row_code)
{
case REG_ROW:
for (pcol=columns; pcol - columns < ncols; pcol++)
{
char *buffer = pcol->status == -1?
"NULL" : pcol->buffer;
printf("%*s ", pcol->size, buffer);
}
printf("\n");
break;

case BUF_FULL:
//assert(row_code != BUF_FULL);
break;

case FAIL:
fprintf(stderr, "%s:%d: dbresults failed\n",
appname, __LINE__);
exit(1);
break;

default:
printf("Data for computeid %d ignored\n", row_code);
}


}

/* free metadata and data buffers */
for (pcol=columns; pcol - columns < ncols; pcol++)
{
free(pcol->buffer);
}
free(columns);

/*
* Get row count, if available.
*/
if (DBCOUNT(dbproc) > -1)
fprintf(stderr, "%d rows affected\n", DBCOUNT(dbproc));

/*
* Check return status
*/
if (dbhasretstat(dbproc) == TRUE) {
printf("Procedure returned %d\n", dbretstatus(dbproc));
}
}

dbclose(dbproc);
dbexit();





//---------------------------------------------------------------------------------------------------

Font font;
font.Create(90,"宋体");

MyForm form2;
form2.Create(0);
//form2.SetLeft(150);
//form2.SetTop(200);
font.SetFont(form2.button.handle);
font.SetFont(form2.edit.handle);


//////////////////////////////////////////////////////////////////
MSG messages;
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
//---------------------------------------------------------------------------------------------------
//add 2009.10.23
if (messages.message == WM_CLOSE) //关闭窗口,非常关键!没有则线程消息循环无法退出,造成资源泄露!!!
//if (messages.message == WM_DESTROY) //关闭窗口,非常关键!没有则线程消息循环无法退出,造成资源泄露!!!
{//根本没有触发这个消息
PostQuitMessage(0);//使函数GetMessage(&message,NULL,0,0)不成立,退出循环(线程)
return 0;//可以去掉此句。
}

//---------------------------------------------------------------------------------------------------

TranslateMessage(&messages);
DispatchMessage(&messages);
}

/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}


//创建一个tree
HTREEITEM TreeInsertItem(HWND hWnd,const TCHAR* name, HTREEITEM hParent,HTREEITEM hInsertAfter)
{
TV_ITEM item;
TCHAR szName[256];

item.mask = TVIF_TEXT;
strcpy(szName, name);
item.pszText=szName;

TV_INSERTSTRUCT tsInsert;
tsInsert.hParent=hParent;
tsInsert.hInsertAfter=hInsertAfter;
tsInsert.item=item;

return TreeView_InsertItem(hWnd,&tsInsert);
}

/* This function is called by the Windows function DispatchMessage() */
Edit edit;
Button button;
Font font;
Panel panel;
Panel panel2;
ListView listv;
int button_handle;

Form form;

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_CREATE:
//return 0;
//CreateEdit( hwnd, message, wParam, lParam);
form.Create(0);

edit.Create(hwnd);
font.Create(90,"宋体");
edit.SetLeft(100);
edit.SetTop(150);
button.Create(hwnd, &form);
panel.Create(hwnd);

panel2.Create(form.handle);
panel2.pMessageWindow = &form;
panel2.width=200;
panel2.height=200;
panel2.SetLeft(200);

listv.SetReportStyle();
listv.width=180;
listv.Create(panel2.handle, &form);
listv.InsertColumn(0, "aaa");
listv.InsertColumn(1, "中文");


font.SetFont(edit.handle);
font.SetFont(button.handle);

break;
case WM_SHOWWINDOW:
//createdialog();
//MessageBox (NULL, "ok", "", MB_ICONERROR);
//while(true)
//{
// ::Sleep(100);
//}
break;

case WM_COMMAND:
button_handle = lParam;
if (button_handle==(int)button.handle)
MessageBox (NULL, "ok", "", MB_ICONERROR);

return 0;//这句很重要

case WM_DESTROY:
//if (hwnd==main_hwnd) break;
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}

return 0;
}





总数:1 页次:1/1 首页 尾页  


发表评论:
文本/html模式切换 插入图片 文本/html模式切换


附件:




Copyright © 2005-2012 CLQ工作室, All Rights Reserved

CLQ工作室 版权所有