| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    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 на контекст pDCbool 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 »   |  | 
 
 понятно. ну и на этом спасибо. представление уже есть, что к чему. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	|  |