Использование буфера записей BDEDelphi , Базы данных , BDEИспользование буфера записей BDE
Оформил: DeeCo Автор: Александр Шпихернюк Все идет к тому, что BDE в ближайшее время окончательно сдаст позиции компонентам прямого доступа к данным (IBX, dbExpress).Но все наработанное с использованием BDE сразу не перепишешь и не выбросишь. Компоненты прямого доступа существенно расширяют возможности разработчика. Недавно понадобилось напрямую работать с буфером записей запроса (TQuery), если бы можно было использовать IBQuery проблем бы с этим не возникло, но буфер записей BDE закрыт и просто до него не достучаться. Задача стояла следующая: в БД (Interbase) при работе с достаточно большой таблицей появилась необходимость при навигации в ReadOnly DBGrid и нажатию короткой клавиши отмечать записи для отложенной печати (поле SOST := 1). Данная задача решается несколькими способами:
Второй слишком долгий и ведет к увеличению сетевого трафика. Третий метод возможно реализовать только с использованием IBX или ClientDataSet, что в этом конкретном случае не приемлемо. Поэтому для решения задачи третьим методом пришлось искать где BDE хранит полученные от IB сервера данные, вот что из этого получилось: unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Db, DBTables, Grids, DBGrids, BDE, Menus; type TForm1 = class(TForm) DataSource: TDataSource; Query: TQuery; DBGrid: TDBGrid; Database: TDatabase; SetFldQ: TQuery; PopupMenu: TPopupMenu; Sost1: TMenuItem; Sost0: TMenuItem; procedure FormCreate(Sender: TObject); procedure Sost1Click(Sender: TObject); procedure Sost0Click(Sender: TObject); private { Private declarations } public { Public declarations } procedure SetSost(AValue: Integer); end; var Form1: TForm1; implementation {$R *.DFM} function GetBDERecBuff(ACursor: TQuery): Pointer; {cursor} var P, P1: Pointer; CurNo, RecNo, RecSize: Integer; begin //Вызов этого метода синхронизирует положение курсора //DataSet и BDE ACursor.UpdateCursorPos; P := ACursor.Handle; Inc(PChar(P), $1E); P := Pointer(P^); Inc(PChar(P), $7E); P := Pointer(P^); Inc(PChar(P), $14); P := Pointer(P^); Inc(PChar(P), $36); P := Pointer(P^); // Получаем внутренний BDE-шный номер текущей записи P1 := P; Inc(PChar(P1), $A); Inc(PChar(P1), $2); RecNo := Integer(P1^) - 1; Inc(PChar(P), $4); P := Pointer(P^); // Получаем внутренний BDE-шный номер курсора P1 := P; Inc(PChar(P1), $11F); P1 := Pointer(P1^); CurNo := Word(P1^); // Получаем размер записи P1 := P; Inc(PChar(P1), $113); RecSize := Word(P1^); // Получаем указатель на массив где хранятся указатели на // буфера всех BDE курсоров Inc(PChar(P), $4); P := Pointer(P^); Inc(PChar(P), $68); P := Pointer(P^); // Выбираем из массива нужный нам указатель Inc(PChar(P), 4 * (CurNo - 1)); P := Pointer(P^); // Получаем указатель на текущую запись Inc(PChar(P), RecNo * RecSize); Result := P; end; procedure PutFldToBDEBuf(ACursor: TQuery; AField: TField; pValue: Pointer); var P: Pointer; begin // Получаем указатель на текущую запись P := GetBDERecBuff(ACursor); //складываем нужное значение в буфер BDE Check(DbiPutField(ACursor.Handle, AField.FieldNo, P, pValue)); //Вызов Resync для пересчета Calc-полей и немедленного отображений изменении на экране ACursor.Resync([]); end; procedure TForm1.FormCreate(Sender: TObject); begin Database.Open; Query.DataBaseName := Database.DatabaseName; SetFldQ.DataBaseName := Database.DatabaseName; DBGrid.PopupMenu := PopupMenu; Sost1.ShortCut := TextToShortCut('Ctrl+A'); Sost0.ShortCut := TextToShortCut('Ctrl+S'); Query.SQL.Text := 'SELECT * FROM AKODIF ORDER BY CODE'; Query.Open; SetFldQ.SQL.Text := 'UPDATE AKODIF SET SOST = :SOST WHERE CODE = :CODE'; SetFldQ.Prepare; end; procedure TForm1.SetSost(AValue: Integer); begin SetFldQ.ParamByName('SOST').AsInteger := AValue; SetFldQ.ParamByName('CODE').AsInteger := Query.FieldByName('CODE').AsInteger; SetFldQ.ExecSQL; PutFldToBDEBuf(Query, Query.FieldByName('SOST'), @AValue); end; procedure TForm1.Sost1Click(Sender: TObject); begin SetSost(1); end; procedure TForm1.Sost0Click(Sender: TObject); begin SetSost(0); end; end.Все описанное выше работает в Delphi 3, Delphi 4, Delphi 5. С BDE 5.01, idapi32.dll от 12.11.1999 размер 589 312. С другими версиями BDE скорее всего работать не будет! Все, вышеописанное есть некий частный результат и автор желал бы получить отклик от тех, кого интересует эта тема. Использование буфера записей BDE: разработчик получает доступ к буферу записи запроса TQuery с помощью функции GetBDERecBuff, что позволяет изменять значение поля SOST в таблице AKODIF при навигации по ReadOnly DBGrid и нажатии короткой клавиши. Комментарии и вопросыПолучайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
|
||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |