Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: BLOB из MFC в базу данных (ODBC)  (Прочитано 28187 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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++ » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 24-04-2005 06:59 » 

это не FAQ , это уже FUCK Ага

vs odbc Улыбаюсь

------------
люди, а если сэрьёзно, мне это всё ещё нужно - будет аааагромная подробная карта (никаких векторов не предвидится) - bmp или jpg и мне надо будет её привязывать к сетке координат. Так - подскажите, как для любых форматов общее нечто сделать?
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 17-04-2006 20:38 » 

Кстати, с выводом битмапов разобрался - сохраняю на диск как файл (тип определяю по сигнатуре в заголовке), затем рендер при помощи IPicture
« Последнее редактирование: 16-05-2006 21:05 от Алексей1153 » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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.   
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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);

делай , что нужно тебе.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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;
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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, заношу рисунок БМП в мое поле (что бы быть уверенным, что он есть там в таблце), пытаюсь его этим кодом вывести на диалоговую форму- ничего. ничего не рисуеться.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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");

а это - ужас )  Отладчиком не проще посмотреть ?
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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);
}
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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);
    //  >>>>>>>>>>>> покажи тут, что вернулось <<<<<<<<<<<<<<<
}

всмысле что там должен быть за код где "покажи тут, что вернулось"? я не очень шарю.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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);
}
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 09-01-2009 10:03 » 

kurlyak, в общем, я не знаю, чем тут помочь - я по базам не спец )) Это работало для ODBC , база- interbase, СУБД - FireBird 1.5

что там в аксессе - я не знаю
Записан

kurlyak
Гость
« Ответ #22 : 11-01-2009 09:02 » 

понятно. ну и на этом спасибо. представление уже есть, что к чему.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines