Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« : 02-04-2005 12:45 » |
|
юзаю базу типа *.FDB или *.GDB из VC++6 посредством Firebird 1.5 в таблице objects есть поле picture с сами понимаете чем если картинка BMP уже есть в таблице, то я читаю её - НЕКАЯ ПРОЦЕДУРА() { CRecordset rs(&m_base); // m_base - это объект CDataBase подключенный к открытой базе CDBVariant var; CString txt,sql; sql="SELECT picture FROM objects WHERE nomer=3"; DWORD dwdDataLen; BYTE* pbyData; try { //запуск SQL rs.Open(CRecordset::snapshot,sql,CRecordset::readOnly); rs.GetFieldValue((short)0,var); //длина BLOB dwdDataLen=var.m_pbinary->m_dwDataLength; if(dwdDataLen<2000000) { DWORD read=0; //достаюм данные - суть файл формата BMP //(проверил по хексам) var.m_pbinary->m_hData; pbyData =(BYTE*) GlobalLock(var.m_pbinary->m_hData); //pbyData - буфер с файлом BMP в ОЗУ if(pbyData) { BITMAPFILEHEADER* pBmpFileHeader; BITMAPINFOHEADER* pBmpInfoHeader; BITMAPINFO* pBmpInfo; pBmpFileHeader=(BITMAPFILEHEADER*)pbyData; pBmpInfoHeader=(BITMAPINFOHEADER*)(pbyData+sizeof(BITMAPFILEHEADER)); pBmpInfo=(BITMAPINFO*)pbyData; BYTE* pPixels=pbyData+((BITMAPFILEHEADER*)pbyData)->bfOffBits; CBitmap Bmp; BOOL res=Bmp.CreateBitmap(30,30,1,24,pPixels); CDC* pdc; pdc=GetDC(); pdc->FillSolidRect(100,100,30,30,RGB(255,0,0)); res=pdc->DrawState(CPoint(100,100),CSize(30,30),&Bmp,DSS_NORMAL,0); res=Bmp.DeleteObject(); ReleaseDC(pdc); GlobalUnlock(var.m_pbinary->m_hData); } } rs.Close(); } catch(...) { ::AfxMessageBox("ОШИБКА"); } } проблем несколько - во первых BOOL res=Bmp.CreateBitmap(30,30,1,24,pPixels); - тут всё хорошо, возвращает 1 (картинка в базе - 30x30, 24бита/пиксель, без палитры) , но res=pdc->DrawState(CPoint(100,100),CSize(30,30),&Bmp,DSS_NORMAL,0); ничего не рисует, хотя возвращает всё окей... -------- проблемы дальше - как всё-таки считать, изменить и записать BLOB при помощи SQL , который (SQL) я могу запустить by CString sql="INSERT .... "; rs.Open(CRecordset::snapshot, sql ,CRecordset::readOnly); ----------- ещё - слышал я об волшебном препроцессоре gpre.exe, который может по параметру -CXX выцеплять из текстового сишного файла команду EXEC SQL sql; и заменять вызовами API - не расскажите, как это сделать, я не смог... --------------------------------------------------------------------------------- ЗЫ спасибо заранее, надеюсь вернусь скоро, скучаю по всем ) ( ((( )
|
|
« Последнее редактирование: 09-01-2009 08:58 от Алексей1153++ »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #1 : 14-04-2005 14:11 » |
|
с BLOB я разобрался (сейчас расскажу, как) но появились проблемы с картинками (об них - в конце). Спасибище отдельное Альфу - за MSDN!!! И как я раньше без MSDN жил?.. В общем, с блобами я сделал так. Примечание заранее: структура этого кода может несколько странна для примера, но это потому, что взято из проекта, и чтобы мне не перепутать чего, я просто взял процедуры, немного преобразовал их вид и имена переменных. Не из лени а из-за нехватки времени. Просто знаю по опыту - серьёзно менять структуру - это вносить ошибки. Их наверняка там будет, но главное - суть. Постараюсь компенсировать комментариями Название таблицы в БД, которая (таблица) используется в примере - objects, поле nomer - уникальный integer ключ, поле picture - BLOB "глобальные" переменные - CDatabase m_base; //объект, корректно подключенный к базе данных BYTE* m_bufer=0;//буфер для показа картинки //макрос checkRetCode - проверяет на ошибку SQL-процедуры и //в случае ошибки освобождает хендл стейтмента, если он //не равен 0, и генерит ексепшен #define checkRetCode \ if(!(retcode==SQL_SUCCESS||retcode==SQL_SUCCESS_WITH_INFO))\ {if(hstmt)SQLFreeStmt(hstmt,SQL_DROP);hstmt=0;throw 0;}
//Записываем BLOB в базу (пример - читаем файл битмапа с диска и кладём в базу) void CEditObjectDialog::SavePicture() { CString txt,sql; short retcode;//для кода возврата SQL-процедур
//проверка того, что база открыта if(!m_base.IsOpen())return;
//хендл стейтмента SQLHSTMT hstmt=0; //ноль - обязательно !!!
//буфер для чтения файла (aka BLOB) BYTE* bufer=0;// ноль - обязательно !!!
//переменная для длины данных DWORD dwdLen;
//определяем длину данных и загружаем файл в буфер if(LoadBitmapFileToBufer(bufer,dwdLen,0)) { //проверяем - отменил ли пользователь действие // (см описание процедуры LoadBitmapFileToBufer ниже) if(bufer) { //файл загружен. Пишем картинку в поле picture
//очищаем предыдущее значение поля и ставим маркер ввода BLOB "?"
//текст запроса sql="UPDATE objects SET picture=? WHERE nomer=5"; //выделяем память под стейтмент retcode=SQLAllocStmt(m_base.m_hdbc,&hstmt); checkRetCode; //подготовка стейтмента для выполнения запроса retcode=SQLPrepare(hstmt,(BYTE*)sql.GetBuffer(sql.GetLength()),SQL_NTS); checkRetCode; //прикрепляем данные к маркеру retcode=SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,SQL_LONGVARBINARY, 0,0, bufer, 0, (long*)&dwdLen); checkRetCode; //выполнение запроса (и запись BLOB) retcode=SQLExecute(hstmt); checkRetCode; //освобождаем память буфера // (см описание процедуры LoadBitmapFileToBufer ниже) delete[]bufer; bufer=0; } else { //отменили в диалоге выбора файла } } else { //была какая-то ошибка, просто пишем: ::AfxMessageBox("Файл не найден"); //и вся недолга :) } //освобождаем стейтмент if(hstmt)SQLFreeStmt(hstmt,SQL_DROP); hstmt=0; //устанавливаем фокус на окно (если выводился диалог открытия) //файла, то окно потеряло фокус SetFocus();
}
//разопределяем макрос #undef checkRetCode
//Читаем BLOB из базы (пример - читаем файл битмапа и рисуем его) void CEditObjectDialog::ShowPicture() { //проверяем, что база открыта if(!m_base.IsOpen())return;
CRecordset rs(&m_base);//рекордсет для чтения из базы CDBVariant var; CString txt,sql; long read=0; DWORD dwdDataLen=0;//длина BLOB //временный буфер для работы с блокированной памятью BYTE* bufer=0;//ноль - обязательно !!!
//достаём BLOB из записи (nomer=5) try { sql="SELECT picture FROM objects WHERE nomer=5";
//определяем длину BLOB
//делаем запрос в рекордсете rs.Open(CRecordset::snapshot,sql,CRecordset::readOnly); //читаем поле rs.GetFieldValue((short)0,var); //достаём длину и по заодно проверяем всякие ошибки if(var.m_dwType!=DBVT_BINARY || !var.m_pbinary)throw 0; dwdDataLen=(var.m_pbinary->m_dwDataLength); if(!dwdDataLen)throw 0;
//выделяем память для глобального буфера m_bufer=new BYTE[dwdDataLen]; if(!m_bufer)throw 0;
//читаем во временный буфер данные длиной dwdDataLen //(блокируем память для работы с HGLOBAL m_hData)
bufer =(BYTE*) GlobalLock(var.m_pbinary->m_hData); if(!bufer)throw 0; //теперь буфер bufer содержит dwdDataLen байт блоба //копируем массив в глобальный буфер memcpy(m_bufer,bufer,dwdDataLen); //разблокируем память GlobalUnlock(var.m_pbinary->m_hData);
//всё ОК } catch(...) { //в случае ошибки - разблокируем память если нужно if(bufer)GlobalUnlock(var.m_pbinary->m_hData); } }
//загрузка BMP из файла. bufer - ссылка на указатель, которому //при удачном выполнении процедуры будет выделена память //оператором new. Длина буфера - dwdBuflen. При обращении к //процедуре задать bufer==0, иначе будет возвращено false. //В случае победы - true. Если задать имя файла, будет //использовано оно, диалог открытия файла не появится. //Если возвращено true, но bufer==0, значит юзер в //диалоге открытия файла отказался от, и память освобождать //не нужно. При false - освобождать тоже не нужно. В случае //возврата true и bufer!=0 память нужно будет освободить //delete [] bufer bool CFileMinder::LoadBitmapFileToBufer(BYTE*&bufer, DWORD &dwdBuflen,CString* pcsFileName) { if(bufer)return false; dwdBuflen=0;
bool res=false; //возвращаемый результат
//полное имя файла CString csBMPFileName="";
//смотрим - задано ли имя if(!pcsFileName) { //стандартный диалог для открытия файлов CFileDialog dlg(1);
//запрашиваем файл dlg.m_ofn.lpstrFilter="файл BMP (*.bmp)\0*.bmp\0";//список фильтров dlg.m_ofn.lpstrDefExt="bmp";//расширение по умолча dlg.m_ofn.nFilterIndex=1;//номер фильтра dlg.m_ofn.lpstrInitialDir="C:\PICS";//папка по умолчанию dlg.m_ofn.lpstrTitle="Укажите файл BMP-формата" " (24-битный или монохромный)"; BOOL R=dlg.DoModal(); csBMPFileName=dlg.m_ofn.lpstrFile; if(R==IDCANCEL || R==IDCLOSE) { //юзер отменил действие bufer=0; return true; }
if(R!=IDOK)return false; //ошибка } else { csBMPFileName=(*pcsFileName); }
//имя и путь определены -> csBMPFileName
HANDLE hFile=INVALID_HANDLE_VALUE; try { //открываем файл hFile=::CreateFile(csBMPFileName,GENERIC_READ,0,0,OPEN_EXISTING,0,0); if(hFile==INVALID_HANDLE_VALUE)throw 0;
//размер файла dwdBuflen=::GetFileSize(hFile,0);
//память для буфера bufer=new BYTE[dwdBuflen]; if(!bufer)throw 0;
//читаем данные из файла DWORD read=0; if(!::ReadFile(hFile,bufer,dwdBuflen,&read,0))throw 0; if(dwdBuflen!=read)throw 0;
res=true; } catch(...) { res=false;//любая ошибка }
//освобождаем хендл файла if(hFile!=INVALID_HANDLE_VALUE) { ::CloseHandle(hFile); hFile=INVALID_HANDLE_VALUE; }
//в случае ошибки, если память выделялась - освобождаем if(!res && bufer) { delete [] bufer; bufer=0; } return res; }
Вызвав процедуру LoadBitmapFileToBufer я загружаю в буфер m_bufer BLOB - в моём случае это файл формата BMP. Никак не могу понять, как создать из массива байт "с файлом" объект класса CBitmap - чтобы ? Причём желательно учесть любой формат - с палитрой и без, jpg и др. , так чтобы работать с картинкой в общем случае. Я сделал тупое копирование пикселов из 24-битного и монохромного файлов (другие сложные форматы, имхо) - получилось. Но работает медленно и вообще не устраивает душу!!! //вывести битмап byBmpFile на контекст pDC bool DrawBitmapPixels(CDC* pDC, BYTE *byBmpFile, int x0, int y0, int Hmax, int Wmax) { bool result=false; CDC tempDC; CBitmap tempBmp,*oldbmp=0;
try { //разбираем формат BMP-файла BITMAPFILEHEADER* pBmpFileHeader; BITMAPINFOHEADER* pBmpInfoHeader; BITMAPINFO* pBmpInfo;
//указатели на основные структуры pBmpFileHeader=(BITMAPFILEHEADER*)byBmpFile; pBmpInfoHeader=(BITMAPINFOHEADER*)(byBmpFile+sizeof(BITMAPFILEHEADER)); pBmpInfo=(BITMAPINFO*)byBmpFile;
//указатель на начало байтов с пикселами BYTE* pPixels=byBmpFile+((BITMAPFILEHEADER*)byBmpFile)->bfOffBits;
//размер растра int W=pBmpInfoHeader->biWidth; int H=pBmpInfoHeader->biHeight;
//бит/пиксел WORD BitCount=pBmpInfoHeader->biBitCount; //временный контекст в памяти и временный битмап tempDC.CreateCompatibleDC(pDC); tempBmp.CreateCompatibleBitmap(pDC,W,H); oldbmp=tempDC.SelectObject(&tempBmp);
//в зависимости от количества бит/пиксел - распакуем //комментарии на английском - врезки из MSDN switch(BitCount) { case 1: { //The bitmap is monochrome, and the bmiColors member of //BITMAPINFO contains //two entries. Each bit in the bitmap array represents a pixel. If the bit //is clear, the pixel is displayed with the color of the first entry in the //bmiColors table; if the bit is set, the pixel has the color of the second //entry in the table.
BYTE *r,*g,*b; r=pPixels-2; g=pPixels-3; b=pPixels-4;
//второй цвет DWORD dwdcol1=((*b)<<16)|((*g)<<8)|(*r); r-=4; g-=4; b-=4; //первый цвет DWORD dwdcol0=((*b)<<16)|((*g)<<8)|(*r);
//delta -дополнение в байтах к каждой строке байт, кодирующих //одну линию растра (чтобы кратно 4 байтам) int div=4*8;//pix int ost=(W)%div; int delta=(ost?1+(32-ost)/8:0);
int h,w; BYTE *currbyte=pPixels; BYTE currpixmask;
for(h=H-1;h>=0;h--) { currpixmask=0x80; for(w=0;w<W;w++) { if(w<Wmax && h<Hmax) { tempDC.SetPixel(w,h, ((*currbyte)&currpixmask)?dwdcol1:dwdcol0 ); }
if(0==(currpixmask>>=1)) { currpixmask=0x80; currbyte++; } } //дополняем строку байт currbyte+=delta; } //выводим на контекст BitBlt(pDC->GetSafeHdc(), x0,y0,W,H,tempDC.GetSafeHdc(), ,0,SRCCOPY); result=true; } break;
case 24: { //The bitmap has a maximum of 2^24 colors, and the bmiColors member of //BITMAPINFO is NULL. Each 3-byte triplet in the bitmap array represents //the relative intensities of blue, green, and red, respectively, for a //pixel. The bmiColors color table is used for optimizing colors used on //palette-based devices, and must contain the number of entries specified //by the biClrUsed member of the BITMAPINFOHEADER.
//delta дополнение до кратности 4 int div=4; int ost=(W*3)%div; int delta=ost?div-ost:0;
DWORD rgb; BYTE *r=pPixels+2; BYTE *g=pPixels+1; BYTE *b=pPixels+0; int h,w;
for(h=H-1;h>=0;h--) { if(h<Hmax) { for(w=0;w<W;w++) { if(w<Wmax) { rgb=((*b)<<16)| ((*g)<<8)|(*r); tempDC.SetPixel(w,h,rgb); } r+=3;g+=3;b+=3; } } else { r+=3*W;g+=3*W;b+=3*W; } //дополняем строку байт r+=delta; g+=delta; b+=delta; } //выводим на контекст BitBlt(pDC->GetSafeHdc(), x0,y0,W,H,tempDC.GetSafeHdc(), 0,0,SRCCOPY); result=true; } break; } } catch(...){result=false;}
//возвращаем временному контексту старый битмап, если нужно if(oldbmp) { tempDC.SelectObject(oldbmp); tempBmp.DeleteObject(); }
return result; }
пожалуйста, помогите!
|
|
« Последнее редактирование: 08-01-2009 09:42 от Алексей1153++ »
|
Записан
|
|
|
|
fernir
Гость
|
|
« Ответ #2 : 19-04-2005 17:56 » |
|
Алексей1153: Классная информация ... по поводу читать/писать BLOB, мне как раз нужна была подобная инфа для SQL Server a.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #3 : 24-04-2005 06:59 » |
|
это не FAQ , это уже FUCK vs odbc ------------ люди, а если сэрьёзно, мне это всё ещё нужно - будет аааагромная подробная карта (никаких векторов не предвидится) - bmp или jpg и мне надо будет её привязывать к сетке координат. Так - подскажите, как для любых форматов общее нечто сделать?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #4 : 17-04-2006 20:38 » |
|
Кстати, с выводом битмапов разобрался - сохраняю на диск как файл (тип определяю по сигнатуре в заголовке), затем рендер при помощи IPicture
|
|
« Последнее редактирование: 16-05-2006 21:05 от Алексей1153 »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #5 : 19-05-2006 22:02 » |
|
мммм.... в чаво это толкать? Вродо оно и есть ЧАВО, да только бы файлом бы
|
|
|
Записан
|
|
|
|
Alf
Гость
|
|
« Ответ #6 : 19-05-2006 22:12 » |
|
Спасибище отдельное Альфу - за MSDN!!! И как я раньше без MSDN жил?.. Я ведь раньше почему вредный был? Потому что у меня велосипеда не было. А теперь я сразу добреть начну!
|
|
|
Записан
|
|
|
|
mmmmmmm7
Гость
|
|
« Ответ #7 : 12-05-2008 10:21 » |
|
Алексей1153++, Здраствуйте. Не могли бы Вы прислать мне свой проект на адрес magic88@list.ru? Ваша программа очень похожа на проект, над которым я работаю. Это бы мне очень помогло, т.к я пока плохо знаю MFC.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #8 : 12-05-2008 14:18 » |
|
mmmmmmm7, нет, прислать проект не могу - это коммерческая хрень ) дык, а как это связано с писанием блоба в базу ? Абсолютно никак. А пример - вот он, тут, тебе нужно отсюда следующее: запись //макрос checkRetCode - проверяет на ошибку SQL-процедуры и //в случае ошибки освобождает хендл стейтмента, если он //не равен 0, и генерит ексепшен #define checkRetCode \ if(!(retcode==SQL_SUCCESS||retcode==SQL_SUCCESS_WITH_INFO))\ {if(hstmt)SQLFreeStmt(hstmt,SQL_DROP);hstmt=0;throw 0;}
//Записываем BLOB в базу (пример - читаем файл битмапа с диска и кладём в базу) void CEditObjectDialog::SavePicture() { CString txt,sql; short retcode;//для кода возврата SQL-процедур
//проверка того, что база открыта if(!m_base.IsOpen())return;
//хендл стейтмента SQLHSTMT hstmt=0; //ноль - обязательно !!!
//буфер для чтения файла (aka BLOB) BYTE* bufer=0;// ноль - обязательно !!!
//переменная для длины данных DWORD dwdLen;
//определяем длину данных и загружаем файл в буфер if(LoadBitmapFileToBufer(bufer,dwdLen,0)) { //проверяем - отменил ли пользователь действие // (см описание процедуры LoadBitmapFileToBufer ниже) if(bufer) { //файл загружен. Пишем картинку в поле picture
//очищаем предыдущее значение поля и ставим маркер ввода BLOB "?"
//текст запроса sql="UPDATE objects SET picture=? WHERE nomer=5"; //выделяем память под стейтмент retcode=SQLAllocStmt(m_base.m_hdbc,&hstmt); checkRetCode; //подготовка стейтмента для выполнения запроса retcode=SQLPrepare(hstmt,(BYTE*)sql.GetBuffer(sql.GetLength()),SQL_NTS); checkRetCode; //прикрепляем данные к маркеру retcode=SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,SQL_LONGVARBINARY, 0,0, bufer, 0, (long*)&dwdLen); checkRetCode; //выполнение запроса (и запись BLOB) retcode=SQLExecute(hstmt); checkRetCode; //освобождаем память буфера // (см описание процедуры LoadBitmapFileToBufer ниже) delete[]bufer; bufer=0; } else { //отменили в диалоге выбора файла } } else { //была какая-то ошибка, просто пишем: ::AfxMessageBox("Файл не найден"); //и вся недолга :) } //освобождаем стейтмент if(hstmt)SQLFreeStmt(hstmt,SQL_DROP); hstmt=0; //устанавливаем фокус на окно (если выводился диалог открытия) //файла, то окно потеряло фокус SetFocus();
}
//разопределяем макрос #undef checkRetCode
тут заменить только LoadBitmapFileToBufer(bufer,dwdLen,0) - на свою функцию по заполнению буфера чтение //Читаем BLOB из базы (пример - читаем файл битмапа и рисуем его) void CEditObjectDialog::ShowPicture() { //проверяем, что база открыта if(!m_base.IsOpen())return;
CRecordset rs(&m_base);//рекордсет для чтения из базы CDBVariant var; CString txt,sql; long read=0; DWORD dwdDataLen=0;//длина BLOB //временный буфер для работы с блокированной памятью BYTE* bufer=0;//ноль - обязательно !!!
//достаём BLOB из записи (nomer=5) try { sql="SELECT picture FROM objects WHERE nomer=5";
//определяем длину BLOB
//делаем запрос в рекордсете rs.Open(CRecordset::snapshot,sql,CRecordset::readOnly); //читаем поле rs.GetFieldValue((short)0,var); //достаём длину и по заодно проверяем всякие ошибки if(var.m_dwType!=DBVT_BINARY || !var.m_pbinary)throw 0; dwdDataLen=(var.m_pbinary->m_dwDataLength); if(!dwdDataLen)throw 0;
//выделяем память для глобального буфера m_bufer=new BYTE[dwdDataLen]; if(!m_bufer)throw 0;
//читаем во временный буфер данные длиной dwdDataLen //(блокируем память для работы с HGLOBAL m_hData)
bufer =(BYTE*) GlobalLock(var.m_pbinary->m_hData); if(!bufer)throw 0; //теперь буфер bufer содержит dwdDataLen байт блоба //копируем массив в глобальный буфер memcpy(m_bufer,bufer,dwdDataLen); //разблокируем память GlobalUnlock(var.m_pbinary->m_hData);
//всё ОК } catch(...) { //в случае ошибки - разблокируем память если нужно if(bufer)GlobalUnlock(var.m_pbinary->m_hData); } }
тут вместо //копируем массив в глобальный буфер memcpy(m_bufer,bufer,dwdDataLen); делай , что нужно тебе.
|
|
« Последнее редактирование: 08-01-2009 09:43 от Алексей1153++ »
|
Записан
|
|
|
|
kurlyak
Гость
|
|
« Ответ #9 : 07-01-2009 17:31 » |
|
Я прошу прощения, конечно, но что именно надо сделать, что бы этот файл вывести на диалоговую форму скажем. я про то место где говориться:
тут вместо //копируем массив в глобальный буфер memcpy(m_bufer,bufer,dwdDataLen);
делай , что нужно тебе.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #10 : 07-01-2009 17:37 » |
|
kurlyak, вопрос непонятен... Всё зависит от формата твоего файла и от того, как надо его вывести )
|
|
|
Записан
|
|
|
|
kurlyak
Гость
|
|
« Ответ #11 : 08-01-2009 09:35 » |
|
Алексей1153++ извини меня за некомпетентность, но я сравнительно недавно программирую. так вот, я использую следущющий код, который у меня не работает. если тебе не сложно- помоги мне его модифицировать. в базе данных у меня будет bmp. CBitmap bm; bm.SetBitmapBits(dwdDataLen,m_bufer); CDC *pDC; pDC=GetDC(); CDC dcTemp; dcTemp.CreateCompatibleDC(pDC); dcTemp.SelectObject(bm);
pDC->BitBlt(0,0,200,200,&dcTemp,0,0,SRCCOPY);
и объясни пожалуйста что такое в этом коде retcode=SQLAllocStmt(v->m_base.m_hdbc,&hstmt); что такое "v->" в вышеприведенном кусочке кода. (у меня mySQL сервер) я просто пишу без "v->": retcode=SQLAllocStmt(db.m_hdbc,&hstmt); и еще тут вопрос, когда я делаю так: sql="UPDATE Таблица1 SET pic='?' WHERE Код=1;"; то данные записываються не те, и их 2 байта (я проверял), рисунка нету. Когда делаю так sql="UPDATE Таблица1 SET pic=? WHERE Код=1;"; знак ? без кавычек, то именно и выдает ошибку в том месте где retcode=SQLExecute(hstmt); checkRetCode;
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #12 : 08-01-2009 09:52 » |
|
kurlyak, "v->" - это мусор остался изза копи-паста, спасибо, кстати, я его убрал. главное в этом всём "v->m_base.m_hdbc" - это просто передать хендл из переменной, представляющей базу, неважно, где сама переменная находится ----------------------- насчёт битмапа - сначала покажи, как ты его сохранял ------------------------- с вопросиком - если поставишь апострофы, то и запишется символ "?" , без апострофов надо. а какую ошибку выдаёт ? retcode , GetLastError() - чему равны ?
|
|
|
Записан
|
|
|
|
kurlyak
Гость
|
|
« Ответ #13 : 08-01-2009 10:23 » |
|
когда я делаю без апострофов '?', то есть просто sql="UPDATE Таблица1 SET pic= ? WHERE Код=1;"; то у меня retcode=SQLExecute(hstmt); if(retcode==SQL_SUCCESS) AfxMessageBox("OK"); if(retcode==SQL_SUCCESS_WITH_INFO) AfxMessageBox("1"); if(retcode==SQL_NEED_DATA) AfxMessageBox("2"); if(retcode==SQL_STILL_EXECUTING) AfxMessageBox("3"); if(retcode==SQL_ERROR) AfxMessageBox("4"); if(retcode==SQL_NO_DATA) AfxMessageBox("5"); if(retcode==SQL_INVALID_HANDLE) AfxMessageBox("6");
выдает 4, то есть SQL_ERROR. вот полный код: if(LoadBitmapFileToBufer(bufer,dwdLen,0)) { if(bufer) { sql="UPDATE Таблица1 SET pic= ? WHERE Код=1;"; retcode=SQLAllocStmt(db.m_hdbc,&hstmt); checkRetCode; retcode=SQLPrepare(hstmt,(BYTE*)sql.GetBuffer(sql.GetLength()),SQL_NTS); checkRetCode; retcode=SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,SQL_LONGVARBINARY, 0,0, bufer, sizeof(bufer), (long*)&dwdLen); checkRetCode; retcode=SQLExecute(hstmt); if(retcode==SQL_SUCCESS) AfxMessageBox("OK"); if(retcode==SQL_SUCCESS_WITH_INFO) AfxMessageBox("1"); if(retcode==SQL_NEED_DATA) AfxMessageBox("2"); if(retcode==SQL_STILL_EXECUTING) AfxMessageBox("3"); if(retcode==SQL_ERROR) AfxMessageBox("4"); if(retcode==SQL_NO_DATA) AfxMessageBox("5"); if(retcode==SQL_INVALID_HANDLE) AfxMessageBox("6"); вот так вот я и сохранял битмап в базе. выдает как я говорил SQL_ERROR. уже даже поставил MS SQL Server вместо mySQL все равно ошибку эту выдает. а вот насчет этого куска кода: bufer =(BYTE*) GlobalLock(var.m_pbinary->m_hData); if(!bufer)throw 0; memcpy(m_bufer,bufer,dwdDataLen);
CBitmap bm; bm.SetBitmapBits(dwdDataLen,m_bufer);
CDC *pDC; pDC=GetDC(); CDC dcTemp; dcTemp.CreateCompatibleDC(pDC); dcTemp.SelectObject(bm);
pDC->BitBlt(0,0,200,200,&dcTemp,0,0,SRCCOPY); GlobalUnlock(var.m_pbinary->m_hData);
то я даже просто открываю Access, заношу рисунок БМП в мое поле (что бы быть уверенным, что он есть там в таблце), пытаюсь его этим кодом вывести на диалоговую форму- ничего. ничего не рисуеться.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #14 : 08-01-2009 10:37 » |
|
When SQLExecute returns either SQL_ERROR or SQL_SUCCESS_WITH_INFO, an associated SQLSTATE value can be obtained by calling SQLGetDiagRec with a HandleType of SQL_HANDLE_STMT and a Handle of StatementHandle. The following table lists the SQLSTATE values commonly returned by SQLExecute and explains each one in the context of this function; the notation "(DM)" precedes the descriptions of SQLSTATEs returned by the Driver Manager. The return code associated with each SQLSTATE value is SQL_ERROR, unless noted otherwise.
скажи, что вернёт SQLGetDiagRec if(retcode==SQL_SUCCESS) AfxMessageBox("OK"); if(retcode==SQL_SUCCESS_WITH_INFO) AfxMessageBox("1"); if(retcode==SQL_NEED_DATA) AfxMessageBox("2"); if(retcode==SQL_STILL_EXECUTING) AfxMessageBox("3"); if(retcode==SQL_ERROR) AfxMessageBox("4"); if(retcode==SQL_NO_DATA) AfxMessageBox("5"); if(retcode==SQL_INVALID_HANDLE) AfxMessageBox("6");
а это - ужас ) Отладчиком не проще посмотреть ?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #15 : 08-01-2009 10:39 » |
|
такс, а кто про аксесс говорит ? Я понятия не имею, прокатит ли данный код для аксесовской базы
|
|
|
Записан
|
|
|
|
kurlyak
Гость
|
|
« Ответ #16 : 08-01-2009 11:23 » |
|
это типа вот так посмотреть? но выдает этот код всякую чепуху: SQLCHAR SqlState[6], SQLStmt[100], Msg[SQL_MAX_MESSAGE_LENGTH]; SQLINTEGER NativeError; SQLSMALLINT i, MsgLen; SQLRETURN rc1;
if(SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, i, SqlState, &NativeError,Msg, sizeof(Msg), &MsgLen)!=SQL_SUCCESS) { CString str; str.Format("%s",SqlState); AfxMessageBox(str); }
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #17 : 08-01-2009 12:00 » |
|
тогда уж так retcode=SQLExecute(hstmt); if(retcode!=SQL_SUCCESS) { SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, i, SqlState, &NativeError,Msg, sizeof(Msg), &MsgLen); // >>>>>>>>>>>> покажи тут, что вернулось <<<<<<<<<<<<<<< }
собственно, та чепуха и интерисует )
|
|
|
Записан
|
|
|
|
kurlyak
Гость
|
|
« Ответ #18 : 08-01-2009 15:58 » |
|
retcode=SQLExecute(hstmt); if(retcode!=SQL_SUCCESS) { SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, i, SqlState, &NativeError,Msg, sizeof(Msg), &MsgLen); // >>>>>>>>>>>> покажи тут, что вернулось <<<<<<<<<<<<<<< }
всмысле что там должен быть за код где "покажи тут, что вернулось"? я не очень шарю.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #19 : 09-01-2009 09:00 » |
|
значения переменных покажи, вернее содержимое строк SqlState, SQLStmt, Msg
|
|
|
Записан
|
|
|
|
kurlyak
Гость
|
|
« Ответ #20 : 09-01-2009 09:58 » |
|
В таком виде код возвращает для SqlState "MMMMMMMMMMMMMMMMMMMMMMMM8H" и для Msg "MMMMMMMMMMMMMMMMMMM8H". if(retcode!=SQL_SUCCESS) { SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, i, SqlState, &NativeError,Msg, sizeof(Msg), &MsgLen); CString str; str.Format("%s",SqlState); AfxMessageBox(str);
str.Format("%s",Msg); AfxMessageBox(str); }
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #21 : 09-01-2009 10:03 » |
|
kurlyak, в общем, я не знаю, чем тут помочь - я по базам не спец )) Это работало для ODBC , база- interbase, СУБД - FireBird 1.5
что там в аксессе - я не знаю
|
|
|
Записан
|
|
|
|
kurlyak
Гость
|
|
« Ответ #22 : 11-01-2009 09:02 » |
|
понятно. ну и на этом спасибо. представление уже есть, что к чему.
|
|
|
Записан
|
|
|
|
|