Добро пожаловать, 
                        
                             
                
                       
                   
          
         
       
  
										  
     
      
  
      
 
    
     
    
     
    
      
    
     
    
      
 
  
 
  
  Поиск
	
			
			
				 
				
					
					
					
					Мне нужно записать серию чисел в файл Paradox в blob-поле. Числа получаются из значений компонент, размещенных на форме. Затем мне нужно будет считывать числа из blob-поля и устанавливать согласно им значения компонент. Как мне сделать это?
Вы можете начать свое исследование со следующего модуля: 
Код unit BlobFld; 
  
interface 
  
uses 
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, 
  Forms, Dialogs, StdCtrls, Buttons, DBTables, DB, ExtCtrls, DBCtrls, 
  Grids, DBGrids; 
  
type 
  TFrmBlobFld = class(TForm) 
    BtnWrite: TBitBtn; 
    Table1: TTable; 
    DataSource1: TDataSource; 
    DBNavigator1: TDBNavigator; 
    LbxDisplayBlob: TListBox; 
    Table1pubid: TIntegerField; 
    Table1comments: TMemoField; 
    Table1UpdateTime: TTimeField; 
    Table1Real1: TFloatField; 
    Table1Real2: TFloatField; 
    Table1Real3: TFloatField; 
    Table1Curr1: TCurrencyField; 
    Table1Blobs: TBlobField; 
    Table1Bytes: TBytesField; 
    CbxRead: TCheckBox; 
    procedure BtnWriteClick(Sender: TObject); 
    procedure DataSource1DataChange(Sender: TObject; Field: TField); 
    procedure FormShow(Sender: TObject); 
    procedure FormClose(Sender: TObject; var Action: TCloseAction); 
  private 
    { Private-Deklarationen } 
  public 
    { Public-Deklarationen } 
  end; 
  
var 
  FrmBlobFld: TFrmBlobFld; 
  
implementation 
  
{$R *.DFM} 
  
type 
  ADouble = array[1..12] of double; 
  PADouble = ^ADouble; 
  
procedure TFrmBlobFld.BtnWriteClick(Sender: TObject); 
var 
  i: integer; 
  myBlob: TBlobStream; 
  v: longint; 
begin 
  Table1.Edit; 
  
  myBlob := TBlobStream.Create(Table1Blobs, bmReadWrite); 
  try 
    v := ComponentCount; 
    myBlob.Write(v, sizeof(longint)); 
  
    for i := 0 to ComponentCount - 1 do 
    begin 
      v := Components[i].ComponentIndex; 
      myBlob.Write(v, sizeof(longint)); 
    end; 
  finally 
    Table1.Post; 
    myBlob.Free; 
  end; 
end; 
  
procedure TFrmBlobFld.DataSource1DataChange(Sender: TObject; Field: TField); 
var 
  i: integer; 
  myBlob: TBlobStream; 
  t: longint; 
  v: longint; 
begin 
  if CbxRead.Checked then 
  begin 
    LbxDisplayBlob.Clear; 
  
    myBlob := TBlobStream.Create(Table1Blobs, bmRead); 
    try 
      myBlob.Read(t, sizeof(longint)); 
      LbxDisplayBlob.Items.Add(IntToStr(t)); 
  
      for i := 0 to t - 1 do 
      begin 
        myBlob.Read(v, sizeof(longint)); 
        LbxDisplayBlob.Items.Add(IntToStr(v)); 
      end; 
    finally 
      myBlob.Free; 
    end; 
  end; 
end; 
  
procedure TFrmBlobFld.FormShow(Sender: TObject); 
begin 
  Table1.Open; 
end; 
  
procedure TFrmBlobFld.FormClose(Sender: TObject; 
  var Action: TCloseAction); 
begin 
  Table1.Close; 
end; 
  
end.
 
Как мне в таблице Paradox скопировать массив целочисленных чисел в TBlobField и наоборот? Элементы массива являются точками графика данных, который я хочу выводить, если запись доступна. 
Запишите массив в поток памяти и затем используйте метод TBlob LoadFromStream. Для извлечения данных используйте метод TBlob SaveToStream (сохранение и извлечение массива из потока памяти).
 
					 
					
						Разместил: Вадим 
						 
						 
					 
				 
			 
			
	 
 
	
			
			
				 
				
					
					
					
					Главное о чем стоит упомянуть это, что ваш хранитель экрана будет работать в фоновом режиме и он не должен мешать работе других запущенных программ. Поэтому сам хранитель должен быть как можно меньшего объема. Для уменьшения объема файла в описанной ниже программе не используется визуальные компоненты Delphi, включение хотя бы одного из них приведет к увеличению размера файла свыше 200кб, а так, описанная ниже программа, имеет размер всего 20кб!!!
Технически, хранитель экрана является нормальным EXE файлом (с расширением .SCR), который управляется через командные параметры строки. Например, если пользователь хочет изменить параметры вашего хранителя, Windows выполняет его с параметром "-c" в командной строке. Поэтому начать создание вашего хранителя экрана следует с создания примерно следующей функции:
Код Procedure RunScreenSaver; 
Var S : String; 
Begin 
  S := ParamStr(1); 
  If (Length(S) > 1) Then Begin 
    Delete(S,1,1); { delete first char - usally "/" or "-" } 
    S[1] := UpCase(S[1]); 
  End; 
  LoadSettings; { load settings from registry } 
  If (S = 'C') Then RunSettings 
  Else If (S = 'P') Then RunPreview 
  Else If (S = 'A') Then RunSetPassword 
  Else RunFullScreen; 
End;
 
Поскольку нам нужно создавать небольшое окно предварительного просмотра и полноэкранное окно, их лучше объединить используя единственный класс окна. Следуя правилам хорошего тона, нам также нужно использовать многочисленные нити. Дело в том, что, во-первых, хранитель не должен переставать работать даже если что-то "тяжелое" случилось, и во-вторых, нам не нужно использовать таймер.
Процедура для запуска хранителя на полном экране - приблизительно такова:
Код Procedure RunFullScreen; 
Var 
  R          : TRect; 
  Msg        : TMsg; 
  Dummy      : Integer; 
  Foreground : hWnd; 
Begin 
  IsPreview := False;  MoveCounter := 3;   
  Foreground := GetForegroundWindow; 
  While (ShowCursor(False) > 0) do ; 
  GetWindowRect(GetDesktopWindow,R); 
  CreateScreenSaverWindow(R.Right-R.Left,R.Bottom-R.Top,0); 
  CreateThread(nil,0,@PreviewThreadProc,nil,0,Dummy); 
  SystemParametersInfo(spi_ScreenSaverRunning,1,@Dummy,0); 
  While GetMessage(Msg,0,0,0) do Begin 
    TranslateMessage(Msg); 
    DispatchMessage(Msg); 
  End; 
  SystemParametersInfo(spi_ScreenSaverRunning,0,@Dummy,0); 
  ShowCursor(True); 
  SetForegroundWindow(Foreground); 
End;
 
Во-первых, мы проинициализировали некоторые глобальные переменные (описанные далее), затем прячем курсор мыши и создаем окно хранителя экрана. Имейте в виду, что важно уведомлять Windows, что это - хранителя экрана через SystemParametersInfo (это выводит из строя Ctrl-Alt-Del чтобы нельзя было вернуться в Windows не введя пароль). Создание окна хранителя:
Код Function CreateScreenSaverWindow(Width,Height : Integer;   
  ParentWindow : hWnd) : hWnd; 
Var WC : TWndClass; 
Begin 
  With WC do Begin 
    Style := cs_ParentDC; 
    lpfnWndProc := @PreviewWndProc; 
    cbClsExtra := 0;  cbWndExtra := 0; hIcon := 0; hCursor := 0; 
    hbrBackground := 0; lpszMenuName := nil;  
    lpszClassName := 'MyDelphiScreenSaverClass'; 
    hInstance := System.hInstance; 
  end; 
  RegisterClass(WC); 
  If (ParentWindow  0) Then 
    Result := CreateWindow('MyDelphiScreenSaverClass','MySaver',  
      ws_Child Or ws_Visible or ws_Disabled,0,0,  
      Width,Height,ParentWindow,0,hInstance,nil) 
  Else Begin 
    Result := CreateWindow('MyDelphiScreenSaverClass','MySaver',  
      ws_Visible or ws_Popup,0,0,Width,Height, 0,0,hInstance,nil); 
    SetWindowPos(Result,hwnd_TopMost,0,0,0,0,swp_NoMove or swp_NoSize or swp_NoRedraw); 
  End; 
  PreviewWindow := Result; 
End;
 
Теперь окна созданы используя вызовы API. Я удалил проверку ошибки, но обычно все проходит хорошо, особенно в этом типе приложения.
Теперь Вы можете погадать, как мы получим handle родительского окна предварительного просмотра ? В действительности, это совсем просто: Windows просто передает handle в командной строке, когда это нужно. Таким образом:
Код Procedure RunPreview; 
Var 
  R             : TRect; 
  PreviewWindow : hWnd; 
  Msg           : TMsg; 
  Dummy         : Integer; 
Begin 
  IsPreview := True; 
  PreviewWindow := StrToInt(ParamStr(2)); 
  GetWindowRect(PreviewWindow,R); 
  CreateScreenSaverWindow(R.Right-R.Left,R.Bottom-R.Top,PreviewWindow); 
  CreateThread(nil,0,@PreviewThreadProc,nil,0,Dummy); 
  While GetMessage(Msg,0,0,0) do Begin 
    TranslateMessage(Msg); DispatchMessage(Msg); 
  End; 
End;
 
Как Вы видите, window handle является вторым параметром (после "-p").
Чтобы "выполнять" хранителя экрана - нам нужна нить. Это создается с вышеуказанным CreateThread. Процедура нити выглядит примерно так:
Код Function PreviewThreadProc(Data : Integer) : Integer; StdCall; 
Var R : TRect; 
Begin 
  Result := 0; Randomize; 
  GetWindowRect(PreviewWindow,R); 
  MaxX := R.Right-R.Left;  MaxY := R.Bottom-R.Top; 
  ShowWindow(PreviewWindow,sw_Show); UpdateWindow(PreviewWindow); 
  Repeat 
    InvalidateRect(PreviewWindow,nil,False); 
    Sleep(30); 
  Until QuitSaver; 
  PostMessage(PreviewWindow,wm_Destroy,0,0); 
End;
 
Нить просто заставляет обновляться изображения в нашем окне, спит на некоторое время, и обновляет изображения снова. А Windows будет посылать сообщение WM_PAINT на наше окно (не в нить !). Для того, чтобы оперировать этим сообщением, нам нужна процедура:
Код Function PreviewWndProc(Window : hWnd; Msg,WParam, 
  LParam : Integer): Integer; StdCall; 
Begin 
  Result := 0; 
  Case Msg of 
    wm_NCCreate  : Result := 1; 
    wm_Destroy   : PostQuitMessage(0); 
    wm_Paint     : DrawSingleBox; { paint something } 
    wm_KeyDown   : QuitSaver := AskPassword; 
    wm_LButtonDown, wm_MButtonDown, wm_RButtonDown, wm_MouseMove :  
                   Begin 
                     If (Not IsPreview) Then Begin 
                       Dec(MoveCounter); 
                       If (MoveCounter <= 0) Then QuitSaver := AskPassword; 
                     End; 
                   End; 
     Else Result := DefWindowProc(Window,Msg,WParam,LParam); 
  End; 
End;
 
Если мышь перемещается, кнопка нажала, мы спрашиваем у пользователя пароль:
Код Function AskPassword : Boolean; 
Var 
  Key   : hKey; 
  D1,D2 : Integer; { two dummies } 
  Value : Integer; 
  Lib   : THandle; 
  F     : TVSSPFunc; 
Begin 
  Result := True; 
  If (RegOpenKeyEx(hKey_Current_User,'Control Panel\Desktop',0,  
      Key_Read,Key) = Error_Success) Then  
  Begin 
    D2 := SizeOf(Value); 
    If (RegQueryValueEx(Key,'ScreenSaveUsePassword',nil,@D1,  
        @Value,@D2) = Error_Success) Then  
    Begin 
      If (Value  0) Then Begin 
        Lib := LoadLibrary('PASSWORD.CPL'); 
        If (Lib > 32) Then Begin 
          @F := GetProcAddress(Lib,'VerifyScreenSavePwd'); 
          ShowCursor(True); 
          If (@F  nil) Then Result := F(PreviewWindow); 
          ShowCursor(False); 
          MoveCounter := 3; { reset again if password was wrong } 
          FreeLibrary(Lib); 
        End; 
      End; 
    End; 
    RegCloseKey(Key); 
  End; 
End;
 
Это также демонстрирует использование registry на уровне API. Также имейте в виду как мы динамически загружаем функции пароля, используюя LoadLibrary. Запомните тип функции?
TVSSFunc ОПРЕДЕЛЕН как:
Код Type 
TVSSPFunc = Function(Parent : hWnd) : Bool; StdCall;
 
Теперь почти все готово, кроме диалога конфигурации. Это запросто:
Код Procedure RunSettings; 
Var Result : Integer; 
Begin 
  Result := DialogBox(hInstance,'SaverSettingsDlg',0,@SettingsDlgProc); 
  If (Result = idOK) Then SaveSettings; 
End;
 
Трудная часть -это создать диалоговый сценарий (запомните: мы не используем здесь Delphi формы!). Я сделал это, используя 16-битовую Resource Workshop (остался еще от Turbo Pascal для Windows). Я сохранил файл как сценарий (текст), и скомпилированный это с BRCC32:
Код SaverSettingsDlg DIALOG 70, 130, 166, 75 
STYLE WS_POPUP | WS_DLGFRAME | WS_SYSMENU 
CAPTION "Settings for Boxes" 
FONT 8, "MS Sans Serif" 
BEGIN 
    DEFPUSHBUTTON "OK", 5, 115, 6, 46, 16 
    PUSHBUTTON "Cancel", 6, 115, 28, 46, 16 
	CTEXT "Box &Color:", 3, 2, 30, 39, 9 
    COMBOBOX 4, 4, 40, 104, 50, CBS_DROPDOWNLIST | CBS_HASSTRINGS 
    CTEXT "Box &Type:", 1, 4, 3, 36, 9 
    COMBOBOX 2, 5, 12, 103, 50, CBS_DROPDOWNLIST | CBS_HASSTRINGS 
    LTEXT "Boxes Screen Saver for Win32 Copyright (c) 1996 Jani 
           Jдrvinen.", 7, 4, 57, 103, 16, 
           WS_CHILD | WS_VISIBLE | WS_GROUP 
END
 
Почти также легко сделать диалоговое меню:
Код Function SettingsDlgProc(Window : hWnd; Msg,WParam,LParam : Integer): Integer; StdCall; 
Var S : String; 
Begin 
  Result := 0; 
  Case Msg of 
    wm_InitDialog : Begin 
                      { initialize the dialog box } 
                      Result := 0; 
                    End; 
    wm_Command    : Begin 
                      If (LoWord(WParam) = 5) Then EndDialog(Window,idOK) 
                      Else If (LoWord(WParam) = 6) Then EndDialog(Window,idCancel); 
                    End; 
    wm_Close      : DestroyWindow(Window); 
    wm_Destroy    : PostQuitMessage(0); 
    Else Result := 0; 
  End; 
End;
 
После того, как пользователь выбрал некоторые установочные параметры, нам нужно сохранить их.
Код Procedure SaveSettings; 
Var 
  Key   : hKey; 
  Dummy : Integer; 
Begin 
  If (RegCreateKeyEx(hKey_Current_User, 
                     'Software\SilverStream\SSBoxes', 
                     0,nil,Reg_Option_Non_Volatile, 
                     Key_All_Access,nil,Key, 
                     @Dummy) = Error_Success) Then Begin 
    RegSetValueEx(Key,'RoundedRectangles',0,Reg_Binary,  
     @RoundedRectangles,SizeOf(Boolean)); 
    RegSetValueEx(Key,'SolidColors',0,Reg_Binary, @SolidColors,SizeOf(Boolean)); 
    RegCloseKey(Key); 
  End; 
End;
 
Загружаем параметры так:
Код Procedure LoadSettings; 
Var 
  Key   : hKey; 
  D1,D2 : Integer; { two dummies } 
  Value : Boolean; 
Begin 
  If (RegOpenKeyEx(hKey_Current_User, 
                   'Software\SilverStream\SSBoxes',0, 
                   Key_Read, 
                   Key) = Error_Success) Then Begin 
    D2 := SizeOf(Value); 
    If (RegQueryValueEx(Key,'RoundedRectangles',nil,@D1, 
        @Value, @D2) = Error_Success) Then  
    Begin    
      RoundedRectangles := Value; 
    End; 
    If (RegQueryValueEx(Key,'SolidColors',nil,@D1, 
        @Value,@D2) = Error_Success) Then  
    Begin 
      SolidColors := Value; 
    End; 
    RegCloseKey(Key); 
  End; 
End;
 
Легко? Нам также нужно позволить пользователю, установить пароль. Я честно не знаю почему это оставлено разработчику приложений ! Тем не менее:
Код Procedure RunSetPassword; 
Var 
  Lib : THandle; 
  F   : TPCPAFunc; 
Begin 
  Lib := LoadLibrary('MPR.DLL'); 
  If (Lib > 32) Then Begin 
    @F := GetProcAddress(Lib,'PwdChangePasswordA'); 
    If (@F  nil) Then F('SCRSAVE',StrToInt(ParamStr(2)),0,0); 
    FreeLibrary(Lib); 
  End; 
End;
 
Мы динамически загружаем (недокументированную) библиотеку MPR.DLL, которая имеет функцию, чтобы установить пароль хранителя экрана, так что нам не нужно беспокоиться об этом.
TPCPAFund ОПРЕДЕЛЕН как:
Код Type 
TPCPAFunc = Function(A : PChar; Parent : hWnd; B,C : Integer) : Integer; StdCall;
 
(Не спрашивайте меня что за параметры B и C ! :-)
Теперь единственная вещь, которую нам нужно рассмотреть, - самая странная часть: создание графики. Я не великий ГУРУ графики, так что Вы не увидите затеняющие многоугольники, вращающиеся в реальном времени. Я только сделал некоторые ящики.
Код Procedure DrawSingleBox; 
Var 
  PaintDC  : hDC; 
  Info     : TPaintStruct; 
  OldBrush : hBrush; 
  X,Y      : Integer; 
  Color    : LongInt; 
Begin 
  PaintDC := BeginPaint(PreviewWindow,Info); 
  X := Random(MaxX); Y := Random(MaxY); 
  If SolidColors Then 
    Color := GetNearestColor(PaintDC,RGB(Random(255),Random(255),Random(255))) 
  Else Color := RGB(Random(255),Random(255),Random(255)); 
  OldBrush := SelectObject(PaintDC,CreateSolidBrush(Color)); 
  If RoundedRectangles Then 
    RoundRect(PaintDC,X,Y,X+Random(MaxX-X),Y+Random(MaxY-Y),20,20) 
  Else Rectangle(PaintDC,X,Y,X+Random(MaxX-X),Y+Random(MaxY-Y)); 
  DeleteObject(SelectObject(PaintDC,OldBrush)); 
  EndPaint(PreviewWindow,Info); 
End;
 
И последнее -  глобальные переменные:
Код Var 
  IsPreview         : Boolean; 
  MoveCounter       : Integer; 
  QuitSaver         : Boolean; 
  PreviewWindow     : hWnd; 
  MaxX,MaxY         : Integer; 
  RoundedRectangles : Boolean; 
  SolidColors       : Boolean;
 
Затем исходная программа проекта (.dpr). Красива, а!?
Код program MySaverIsGreat; 
uses 
   windows, messages, Utility; { defines all routines } 
{$R SETTINGS.RES} 
begin 
  RunScreenSaver;  
end.
 
    Ох, чуть не забыл! Если, Вы используете SysUtils в вашем проекте (например фуекцию StrToInt) вы получите EXE-файл больше чем обещанный в 20k. :)  Если Вы хотите все же иметь20k, надо как-то обойтись без SysUtils, например самому написать собственную StrToInt процедуру.
    Если все же очень трудно обойтись без использования Delphi-форм, то можно поступить как в случае с вводом пароля: форму изменения параметров хранителя сохранить в виде DLL и динамически ее загружать при необходимости. Т.о. будет маленький и шустрый файл самого хранителя экрана и довеска DLL для конфигурирования и прочего (там объем и скорость уже не критичны).
 
					 
					
						Разместил: Aleksey Merlin 
						 
						 
					 
				 
			 
			
	 
 
	
			
			
				 
				
					
					
					
					В случае нажатия пользователем клавиши или изменении текущего элемента компонента ComboBox, вы обратите внимание на досадную задержку, возникающую при генерации события On.
 
Так как "работа кипит", я хотел бы отреагировать на изменение 
ItemIndex  несколько позднее, например, 100 миллисекунд спустя. Вот что у меня получилось. На простой форме располагаем компоненты ComboBox и Label. Необходимым дополнением является вызов 
Application.ProcessMessages , позволяющий избежать замедления работы PC, когда очередь сообщений для формы пуста.
Код unit Unit1; 
 
interface 
 
uses 
 
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, 
Dialogs, 
 
StdCtrls; 
 
const 
 
// Просто некоторая константа сообщения 
PM_COMBO = WM_USER + 8001; 
 
// 500 миллисекунд 
CWantedDelay = 500; 
 
type 
 
TForm1 = class(TForm) 
ComboBox1: TComboBox; 
Label1: TLabel; 
procedure ComboBox1(Sender: TObject); 
private 
procedure PMCombo(var message : TMessage); message PM_COMBO; 
public 
end; 
 
var 
 
Form1: TForm1; 
 
implementation 
 
{$R *.DFM} 
 
procedure TForm1.ComboBox1(Sender: TObject); 
begin 
 
PostMessage(Handle, PM_COMBO, 0, 0); 
end; 
 
procedure TForm1.PMCombo(var message : TMessage); 
const 
 
InProc    : BOOLEAN = FALSE; 
StartTick : LONGINT = 0; 
begin 
 
if InProc then begin 
// Обновляем стартовое время задержки 
StartTick := GetTickCount; 
 
end else begin 
// Организация цикла 
InProc := TRUE; 
 
// Инициализация стартового времени 
StartTick := GetTickCount; 
 
// Ожидаем истечения стартового времени. 
// Пока стартовое время не исчерпалось, позволяем операционной системе обрабатывать сообщения 
while GetTickCount - StartTick < CWantedDelay do Application.ProcessMessages; 
 
// Иллюстративное приращение счетчика, задающее некоторую реальную работу обработчику события On 
Label1.Caption := IntToStr ( StrToIntDef ( Label1.Caption, 0 ) + 1); 
 
// Завершение цикла 
InProc := FALSE; 
end; 
end; 
 
end.
 
					 
					
				 
			 
			
	 
 
	
			
			
				 
				
					
					
					
					Очевидно, BDE содержит номер версии структуры, по крайней мере для файлов Paradox. (Я не могу поручиться за dBase и другие форматы.) Всякий раз при изменении структуры (например, в Database Desktop) BDE увеличивает номер версии. Следующий модуль содержит функцию, которая возвращает версию структуры базы данных:
 
Код (***************************************************************************** 
* DbUtils.pas 
* 
* Утилита для работы с базами данных 
*****************************************************************************) 
unit Dbutils; 
 
(****************************************************************************) 
(****************************************************************************) 
 
interface 
(****************************************************************************) 
(****************************************************************************) 
 
uses 
 
DbTables; 
 
function DbGetVersion(table: TTable): LongInt; 
 
 
(****************************************************************************) 
(****************************************************************************) 
 
implementation 
(****************************************************************************) 
(****************************************************************************) 
 
uses 
 
Db, DbiProcs, DbiTypes, {DbiErrs,} 
SysUtils; 
 
 
{-} 
(* 
 
* Цель:                    определение номера версии структуры таблицы 
* Параметры:               table (I) - интересующая нас таблица 
* Возвращаемая величина:   номер версии 
* Исключительная ситуация: EDatabaseError 
*) 
function DbGetVersion(table: TTable): LongInt; 
var 
 
hCursor   : hDBICur; 
tableDesc: TBLFullDesc; 
cName     : array[0..255] of Char; 
begin 
 
{ копируем имя таблицы в строку 'с' } 
StrPCopy(cName, table.TableName); 
 
 
{ просим BDE создать запись, содержащую информацию об определенной таблице } 
Check(DbiOpenTableList(table.DBHandle, True, False, cName, hCursor)); 
 
 
{ получаем запись, содержащую информацию о структуре } 
Check(DbiGetNextRecord(hCursor, dbiNOLOCK, @tableDesc, nil)); 
 
 
{ возвращаем поле записи, содержащее номер версии структуры нашей таблицы } 
Result := tableDesc.tblExt.iRestrVersion; 
 
 
Check(DbiCloseCursor(hCursor)); 
end; 
 
end.  
 
					 
					
				 
			 
			
	 
 
	
			
			
				 
				
					
					
					
					Вот несколько функций для операций с двухмерными массивами. Самый простой путь для создания собственной библиотеки. Процедуры SetV и GetV позволяют читать и сохранять элементы массива VArray (его Вы можете объявить как угодно).
 
Например:
Код type 
 
VArray : Array[1..1] of double; 
var 
 
X : ^VArray; 
NR, NC : Longint; 
 
begin 
 
NR := 10000; 
NC := 100; 
if AllocArray(pointer(X), N*Sizeof(VArray)) then exit; 
SetV(X^, NC, 2000, 5, 3.27);    { X[2000,5] := 3.27 } 
end; 
 
function AllocArray(var V : pointer; const N : longint) : Boolean; 
begin        {распределяем память для массива V размера N} 
 
try 
GetMem(V, N); 
except 
ShowMessage('ОШИБКА выделения памяти. Размер:' + IntToStr(N)); 
Result := True; 
exit; 
end; 
FillChar(V^, N, 0);  {в случае включения длинных строк заполняем их нулями} 
Result := False; 
end; 
 
procedure SetV(var X : Varray;const N,ir,ic : LongInt;const value : 
double); 
begin    {заполняем элементами двухмерный массив X размером ? x N : X[ir,ic] := value} 
 
X[N*(ir-1) + ic] := value; 
end; 
 
function GetV(const X : Varray; const N, ir,ic : Longint) : double; 
begin         {возвращаем величины X[ir,ic] для двухмерного массива шириной N столбцов} 
 
Result := X[N*(ir-1) + ic]; 
end;
 
Самый простой путь - создать массив динамически
Код Myarray := GetMem(rows * cols * sizeof(byte,word,single,double и пр.) 
 
сделайте функцию fetch_num типа
Код function fetch_num(r,c:integer) : single; 
result := pointer + row + col*rows 
 
и затем вместо myarray[2,3] напишите
Код myarray.fetch_num(2,3)
 
Вот способ создания одно- и двухмерных динамических массивов:
Код (* 
 
 
 модуль для создания двух очень простых классов обработки динамических массивов 
     TDynaArray   :  одномерный массив 
     TDynaMatrix  :  двумерный динамический массив 
 
*) 
 
unit DynArray; 
 
INTERFACE 
 
uses 
 
SysUtils; 
 
Type 
 
TDynArrayBaseType = double; 
 
Const 
 
vMaxElements  =  (High(Cardinal) - $f) div sizeof(TDynArrayBaseType); 
{= гарантирует максимально возможный массив =} 
 
 
Type 
 
TDynArrayNDX     =  1..vMaxElements; 
TArrayElements   =  array[TDynArrayNDX] of TDynArrayBaseType; 
{= самый большой массив TDynArrayBaseType, который мы может объявить =} 
PArrayElements   =  ^TArrayElements; 
{= указатель на массив =} 
 
 
EDynArrayRangeError  =  CLASS(ERangeError); 
 
 
TDynArray  =  CLASS 
Private 
fDimension : TDynArrayNDX; 
fMemAllocated : word; 
Function  GetElement(N : TDynArrayNDX) : TDynArrayBaseType; 
Procedure SetElement(N : TDynArrayNDX; const NewValue : TDynArrayBaseType); 
Protected 
Elements : PArrayElements; 
Public 
Constructor Create(NumElements : TDynArrayNDX); 
Destructor Destroy; override; 
Procedure Resize(NewDimension : TDynArrayNDX); virtual; 
Property dimension : TDynArrayNDX 
read fDimension; 
Property Element[N : TDynArrayNDX] : TDynArrayBaseType 
read GetElement 
write SetElement; 
default; 
END; 
 
Const 
 
vMaxMatrixColumns = 65520 div sizeof(TDynArray); 
{= построение матрицы класса с использованием массива объектов TDynArray =} 
 
Type 
 
TMatrixNDX  =  1..vMaxMatrixColumns; 
TMatrixElements  =  array[TMatrixNDX] of TDynArray; 
{= каждая колонка матрицы будет динамическим массивом =} 
PMatrixElements  =  ^TMatrixElements; 
{= указатель на массив указателей... =} 
 
 
TDynaMatrix  =  CLASS 
Private 
fRows          : TDynArrayNDX; 
fColumns       : TMatrixNDX; 
fMemAllocated  : longint; 
Function  GetElement( row : TDynArrayNDX; 
column : TMatrixNDX) : TDynArrayBaseType; 
Procedure SetElement( row : TDynArrayNDX; 
column : TMatrixNDX; 
const NewValue : TDynArrayBaseType); 
Protected 
mtxElements : PMatrixElements; 
Public 
Constructor Create(NumRows : TDynArrayNDX; NumColumns : TMatrixNDX); 
Destructor Destroy; override; 
Property rows : TDynArrayNDX 
read fRows; 
Property columns : TMatrixNDX 
read fColumns; 
Property Element[row : TDynArrayNDX; column : TMatrixNDX] : TDynArrayBaseType 
read GetElement 
write SetElement; 
default; 
END; 
 
IMPLEMENTATION 
 
(* 
 
 
  методы TDynArray 
 
*) 
Constructor TDynArray.Create(NumElements : TDynArrayNDX); 
 
BEGIN   {==TDynArray.Create==} 
inherited Create; 
fDimension := NumElements; 
GetMem( Elements, fDimension*sizeof(TDynArrayBaseType) ); 
fMemAllocated := fDimension*sizeof(TDynArrayBaseType); 
FillChar( Elements^, fMemAllocated, 0 ); 
END;    {==TDynArray.Create==} 
 
Destructor TDynArray.Destroy; 
 
BEGIN   {==TDynArray.Destroy==} 
FreeMem( Elements, fMemAllocated ); 
inherited Destroy; 
END;    {==TDynArray.Destroy==} 
 
Procedure TDynArray.Resize(NewDimension : TDynArrayNDX); 
 
BEGIN   {TDynArray.Resize==} 
if (NewDimension < 1) then 
raise EDynArrayRangeError.CreateFMT('Индекс вышел за границы диапазона : %d', [NewDimension]); 
Elements := ReAllocMem(Elements, fMemAllocated, NewDimension*sizeof(TDynArrayBaseType)); 
fDimension := NewDimension; 
fMemAllocated := fDimension*sizeof(TDynArrayBaseType); 
END;    {TDynArray.Resize==} 
 
Function  TDynArray.GetElement(N : TDynArrayNDX) : TDynArrayBaseType; 
 
BEGIN   {==TDynArray.GetElement==} 
if (N < 1) OR (N > fDimension) then 
raise EDynArrayRangeError.CreateFMT('Индекс вышел за границы диапазона : %d', [N]); 
result := Elements^[N]; 
END;    {==TDynArray.GetElement==} 
 
Procedure TDynArray.SetElement(N : TDynArrayNDX; const NewValue : TDynArrayBaseType); 
 
BEGIN   {==TDynArray.SetElement==} 
if (N < 1) OR (N > fDimension) then 
raise EDynArrayRangeError.CreateFMT('Индекс вышел за границы диапазона : %d', [N]); 
Elements^[N] := NewValue; 
END;    {==TDynArray.SetElement==} 
 
(* 
 
 
  методы TDynaMatrix 
 
*) 
Constructor TDynaMatrix.Create(NumRows : TDynArrayNDX; NumColumns : TMatrixNDX); 
 
Var     col  :  TMatrixNDX; 
BEGIN   {==TDynaMatrix.Create==} 
inherited Create; 
fRows := NumRows; 
fColumns := NumColumns; 
{= выделение памяти для массива указателей (т.е. для массива TDynArrays) =} 
GetMem( mtxElements, fColumns*sizeof(TDynArray) ); 
fMemAllocated := fColumns*sizeof(TDynArray); 
{= теперь выделяем память для каждого столбца матрицы =} 
for col := 1 to fColumns do 
BEGIN 
mtxElements^[col] := TDynArray.Create(fRows); 
inc(fMemAllocated, mtxElements^[col].fMemAllocated); 
END; 
END;    {==TDynaMatrix.Create==} 
 
Destructor  TDynaMatrix.Destroy; 
 
Var     col  :  TMatrixNDX; 
BEGIN   {==TDynaMatrix.Destroy;==} 
for col := fColumns downto 1 do 
BEGIN 
dec(fMemAllocated, mtxElements^[col].fMemAllocated); 
mtxElements^[col].Free; 
END; 
FreeMem( mtxElements, fMemAllocated ); 
inherited Destroy; 
END;    {==TDynaMatrix.Destroy;==} 
 
Function  TDynaMatrix.GetElement( row : TDynArrayNDX; 
 
column : TMatrixNDX) : TDynArrayBaseType; 
BEGIN   {==TDynaMatrix.GetElement==} 
if (row < 1) OR (row > fRows) then 
raise EDynArrayRangeError.CreateFMT('Индекс строки вышел за границы диапазона : %d', [row]); 
if (column < 1) OR (column > fColumns) then 
raise EDynArrayRangeError.CreateFMT('Индекс столбца вышел за границы диапазона : %d', [column]); 
result := mtxElements^[column].Elements^[row]; 
END;    {==TDynaMatrix.GetElement==} 
 
Procedure TDynaMatrix.SetElement( row : TDynArrayNDX; 
 
column : TMatrixNDX; 
const NewValue : TDynArrayBaseType); 
BEGIN   {==TDynaMatrix.SetElement==} 
if (row < 1) OR (row > fRows) then 
raise EDynArrayRangeError.CreateFMT('Индекс строки вышел за границы диапазона : %d', [row]); 
if (column < 1) OR (column > fColumns) then 
raise EDynArrayRangeError.CreateFMT('Индекс столбца вышел за границы диапазона : %d', [column]); 
mtxElements^[column].Elements^[row] := NewValue; 
END;    {==TDynaMatrix.SetElement==} 
 
 
END.  
 
 
Тестовая программа для модуля DynArray 
 
uses DynArray, WinCRT; 
 
Const 
 
NumRows  :  integer = 7; 
NumCols  :  integer = 5; 
 
Var 
 
M : TDynaMatrix; 
row, col : integer; 
BEGIN 
 
M := TDynaMatrix.Create(NumRows, NumCols); 
for row := 1 to M.Rows do 
for col := 1 to M.Columns do 
M[row, col] := row + col/10; 
writeln('Матрица'); 
for row := 1 to M.Rows do 
BEGIN 
for col := 1 to M.Columns do 
write(M[row, col]:5:1); 
writeln; 
END; 
writeln; 
writeln('Перемещение'); 
for col := 1 to M.Columns do 
BEGIN 
for row := 1 to M.Rows do 
write(M[row, col]:5:1); 
writeln; 
END; 
M.Free; 
END.
 
					 
					
				 
			 
			
	 
 
	
			
			
				 
				
					
					
					
					Каким образом запустить процесс завершения работы операционной системы (функция ExitWindows) из кода моей программы? Мне необходимо перезапустить операционную систему без перезапуска компьютера.
 
Ok, приводим обе функции для перезапуска операционной системы:
Код procedure TMainForm.RestartWindowsBtnClick(Sender: TObject); 
begin 
if not ExitWindows(EW_RestartWindows, 0) then 
ShowMessage('Приложение не может завершить работу'); 
end;
 
Код procedure TMainForm.RebootSystemBtnClick(Sender: TObject); 
begin 
if not ExitWindows(EW_RebootSystem, 0) then 
ShowMessage('Приложение не может завершить работу'); 
end;
 
Функция ExitWindows не была правильно задокументирована Microsoft'ом и не содержит описания возвращаемого значения. Более того, информация о этой функции практически не встречается в других источниках. Вот правильное определение этой функции:
Код function ExitWindows (dwReturnCode: Longint; 
Reserved: Word): Bool;
 
					 
					
				 
			 
			
	 
 
	
			
			
				 
				
					
					
					
					У меня есть неотложная задача: в настоящее время я разрабатываю проект, где я должен проверять достоверность введенных дат с применением маски __/__/____, например 12/12/2007.
Некоторое время назад я делал простой шифратор/дешифратор дат, проверяющий достоверность даты.
 
Код приведен ниже. 
Код function CheckDateFormat(SDate:string):string;
var
IDateChar:string;
x,y:integer;
begin
IDateChar:='.,/';
for y:=1 to length(IDateChar) do
begin
x:=pos(IDateChar[y],SDate);
while x>0 do
begin
Delete(SDate,x,1);
('-',SDate,x);
x:=pos(IDateChar[y],SDate);
end;
end;
CheckDateFormat:=SDate;
end;
function DateEncode(SDate:string):longint;
var
year,month,day:longint;
wy,wm,wd:longint;
Dummy:TDateTime;
Check:integer;
begin
DateEncode:=-1;
SDate:=CheckDateFormat(SDate);
Val(Copy(SDate,1,pos('-',SDate)-1),day,check);
Delete(Sdate,1,pos('-',SDate));
Val(Copy(SDate,1,pos('-',SDate)-1),month,check);
Delete(SDate,1,pos('-',SDate));
Val(SDate,year,check);
wy:=year;
wm:=month;
wd:=day;
try
Dummy:=EncodeDate(wy,wm,wd);
except
year:=0;
month:=0;
day:=0;
end;
DateEncode:=(year
000)+(month
0)+day;
end;
 
Примечание:  смайлик - знак умножения
 
					 
					
				 
			 
			
	 
 
	
			
			
				 
				
					
					
					
					Интересно, есть ли технология преобразования Wave-формата в обычный набор звуковых данных? К примеру, мне необходимо удалить заголовок и механизм (метод) сжатия, которые могут компилироваться и сохраняться вместе с Wave-файлами.
 
Код unit LinearSystem; 
 
interface 
 
{============== Тип, описывающий формат WAV ==================} 
type WAVHeader = record 
 
nChannels       : Word; 
nBitsPerSample  : LongInt; 
nSamplesPerSec  : LongInt; 
nAvgBytesPerSec : LongInt; 
RIFFSize        : LongInt; 
fmtSize         : LongInt; 
formatTag       : Word; 
nBlockAlign     : LongInt; 
DataSize        : LongInt; 
end; 
 
{============== Поток данных сэмпла ========================} 
const MaxN = 300;  { максимальное значение величины сэмпла } 
type SampleIndex = 0 .. MaxN+3; 
type DataStream = array[ SampleIndex ] of Real; 
 
var   N     : SampleIndex; 
 
{============== Переменные сопровождения ======================} 
type  Observation = record 
 
Name       : String[40];  {Имя данного сопровождения} 
yyy        : DataStream;  {Массив указателей на данные} 
WAV        : WAVHeader;   {Спецификация WAV для сопровождения} 
Last       : SampleIndex; {Последний доступный индекс yyy} 
MinO, MaxO : Real;        {Диапазон значений yyy} 
end; 
 
var K0R, K1R, K2R, K3R : Observation; 
 
 K0B, K1B, K2B, K3B : Observation; 
 
{================== Переменные имени файла ===================} 
var StandardDatabase : String[ 80 ]; 
 
BaseFileName      : String[ 80 ]; 
StandardOutput    : String[ 80 ]; 
StandardInput     : String[ 80 ]; 
 
{=============== Объявления процедур ==================} 
procedure ReadWAVFile  (var Ki, Kj : Observation); 
procedure WriteWAVFile (var Ki, Kj : Observation); 
procedure ScaleData    (var Kk     : Observation); 
procedure InitAllSignals; 
procedure InitLinearSystem; 
 
 
implementation 
{$R *.DFM} 
uses VarGraph, SysUtils; 
 
{================== Стандартный формат WAV-файла ===================} 
const MaxDataSize : LongInt = (MaxN+1)*2*2; 
const MaxRIFFSize : LongInt = (MaxN+1)*2*2+36; 
const StandardWAV : WAVHeader = ( 
 
nChannels       : Word(2); 
nBitsPerSample  : LongInt(16); 
nSamplesPerSec  : LongInt(8000); 
nAvgBytesPerSec : LongInt(32000); 
RIFFSize        : LongInt((MaxN+1)*2*2+36); 
fmtSize         : LongInt(16); 
formatTag       : Word(1); 
nBlockAlign     : LongInt(4); 
DataSize        : LongInt((MaxN+1)*2*2) 
); 
 
 
{================== Сканирование переменных сопровождения ===================} 
 
 
procedure ScaleData(var Kk : Observation); 
var I : SampleIndex; 
begin 
 
 
{Инициализация переменных сканирования} 
Kk.MaxO := Kk.yyy[0]; 
Kk.MinO := Kk.yyy[0]; 
 
 
{Сканирование для получения максимального и минимального значения} 
for I := 1 to Kk.Last do 
begin 
if Kk.MaxO < Kk.yyy[I] then Kk.MaxO := Kk.yyy[I]; 
if Kk.MinO > Kk.yyy[I] then Kk.MinO := Kk.yyy[I]; 
end; 
end; { ScaleData } 
 
procedure ScaleAllData; 
begin 
 
ScaleData(K0R); 
ScaleData(K0B); 
ScaleData(K1R); 
ScaleData(K1B); 
ScaleData(K2R); 
ScaleData(K2B); 
ScaleData(K3R); 
ScaleData(K3B); 
end; {ScaleAllData} 
 
{================== Считывание/запись WAV-данных ===================} 
 
VAR InFile,  : file of Byte; 
 
type Tag = (F0, T1, M1); 
type FudgeNum = record 
 
case X:Tag of 
F0 : (chrs : array[0..3] of Byte); 
T1 : (lint : LongInt); 
M1 : (up,dn: Integer); 
end; 
var ChunkSize  : FudgeNum; 
 
procedure WriteChunkName(Name:String); 
var i   : Integer; 
 
MM : Byte; 
begin 
 
for i := 1 to 4 do 
begin 
MM := ord(Name[i]); 
write(,MM); 
end; 
end; {WriteChunkName} 
 
procedure WriteChunkSize(LL:Longint); 
var I : integer; 
begin 
 
ChunkSize.x:=T1; 
ChunkSize.lint:=LL; 
ChunkSize.x:=F0; 
for I := 0 to 3 do Write(,ChunkSize.chrs[I]); 
end; 
 
procedure WriteChunkWord(WW:Word); 
var I : integer; 
begin 
 
ChunkSize.x:=T1; 
ChunkSize.up:=WW; 
ChunkSize.x:=M1; 
for I := 0 to 1 do Write(,ChunkSize.chrs[I]); 
end; {WriteChunkWord} 
 
procedure WriteOneDataBlock(var Ki, Kj : Observation); 
var I : Integer; 
begin 
 
ChunkSize.x:=M1; 
with Ki.WAV do 
begin 
case nChannels of 
1:if nBitsPerSample=16 
then begin {1..2 Помещаем в буфер одноканальный 16-битный сэмпл} 
ChunkSize.up := trunc(Ki.yyy[N]+0.5); 
if N<=Ki.Last do WriteOneDataBlock(Ki,Kj); {помещаем 4 байта и увеличиваем счетчик N} 
 
 
{Освобождаем буфер файла} 
CloseFile(  ); 
end; {WriteWAVFile} 
 
procedure InitSpecs; 
begin 
end; { InitSpecs } 
 
procedure InitSignals(var Kk : Observation); 
var J : Integer; 
begin 
 
for J := 0 to MaxN do Kk.yyy[J] := 0.0; 
Kk.MinO := 0.0; 
Kk.MaxO := 0.0; 
Kk.Last := MaxN; 
end; {InitSignals} 
 
procedure InitAllSignals; 
begin  
InitSignals(K0R); 
InitSignals(K0B); 
InitSignals(K1R); 
InitSignals(K1B); 
InitSignals(K2R); 
InitSignals(K2B); 
InitSignals(K3R); 
InitSignals(K3B); 
end; {InitAllSignals}
 
[pagebreak]
Код var ChunkName  : string[4]; 
 
procedure ReadChunkName; 
var I : integer; 
 
MM : Byte; 
begin 
 
ChunkName[0]:=chr(4); 
for I := 1 to 4 do 
begin 
Read(InFile,MM); 
ChunkName[I]:=chr(MM); 
end; 
end; {ReadChunkName} 
 
procedure ReadChunkSize; 
var I : integer; 
 
MM : Byte; 
begin 
 
ChunkSize.x := F0; 
ChunkSize.lint := 0; 
for I := 0 to 3 do 
begin 
Read(InFile,MM); 
ChunkSize.chrs[I]:=MM; 
end; 
ChunkSize.x := T1; 
end; {ReadChunkSize} 
 
procedure ReadOneDataBlock(var Ki,Kj:Observation); 
var I : Integer; 
begin 
 
if N<=MaxN then 
begin 
ReadChunkSize; {получаем 4 байта данных} 
ChunkSize.x:=M1; 
with Ki.WAV do 
case nChannels of 
1:if nBitsPerSample=16 
then begin {1..2 Помещаем в буфер одноканальный 16-битный сэмпл} 
Ki.yyy[N]  :=1.0*ChunkSize.up; 
if N<=MaxN then begin {LastN    := N;} 
Ki.Last := N; 
if Ki.WAV.nChannels=2 then Kj.Last := N; 
end 
else begin {LastN    := MaxN;} 
Ki.Last := MaxN; 
if Ki.WAV.nChannels=2 then Kj.Last := MaxN; 
 
end; 
end; 
end; {ReadOneDataBlock} 
 
procedure ReadWAVFile(var Ki, Kj :Observation); 
var MM        : Byte; 
 
I           : Integer; 
OK          : Boolean; 
NoDataYet   : Boolean; 
DataYet     : Boolean; 
nDataBytes  : LongInt; 
begin 
 
if FileExists(StandardInput) 
then 
with Ki.WAV do 
begin  { Вызов диалога открытия файла } 
OK := True; {если не изменится где-нибудь ниже} 
{Приготовления для чтения файла данных} 
AssignFile(InFile, StandardInput); { Файл, выбранный в диалоговом окне } 
Reset( InFile ); 
 
 
{Считываем ChunkName "RIFF"} 
ReadChunkName; 
if ChunkName<>'RIFF' then OK := False; 
 
 
{Считываем ChunkSize} 
ReadChunkSize; 
RIFFSize    := ChunkSize.lint; {должно быть 18,678} 
 
 
{Считываем ChunkName "WAVE"} 
ReadChunkName; 
if ChunkName<>'WAVE' then OK := False; 
 
 
{Считываем ChunkName "fmt_"} 
ReadChunkName; 
if ChunkName<>'fmt ' then OK := False; 
 
 
{Считываем ChunkSize} 
ReadChunkSize; 
fmtSize     := ChunkSize.lint;  {должно быть 18} 
 
 
{Считываем  formatTag, nChannels} 
ReadChunkSize; 
ChunkSize.x := M1; 
formatTag   := ChunkSize.up; 
nChannels   := ChunkSize.dn; 
 
 
{Считываем  nSamplesPerSec} 
ReadChunkSize; 
nSamplesPerSec  := ChunkSize.lint; 
 
 
{Считываем  nAvgBytesPerSec} 
ReadChunkSize; 
nAvgBytesPerSec := ChunkSize.lint; 
 
 
{Считываем  nBlockAlign} 
ChunkSize.x := F0; 
ChunkSize.lint := 0; 
for I := 0 to 3 do 
begin Read(InFile,MM); 
ChunkSize.chrs[I]:=MM; 
end; 
ChunkSize.x := M1; 
nBlockAlign := ChunkSize.up; 
 
 
{Считываем  nBitsPerSample} 
nBitsPerSample := ChunkSize.dn; 
for I := 17 to fmtSize do Read(InFile,MM); 
 
 
NoDataYet := True; 
while NoDataYet do 
begin 
{Считываем метку блока данных "data"} 
ReadChunkName; 
 
 
{Считываем DataSize} 
ReadChunkSize; 
DataSize := ChunkSize.lint; 
 
 
if ChunkName<>'data' then 
begin 
for I := 1 to DataSize do {пропуск данных, не относящихся к набору звуковых данных} 
Read(InFile,MM); 
end 
else NoDataYet := False; 
end; 
 
 
nDataBytes := DataSize; 
{Наконец, начинаем считывать данные для байтов nDataBytes} 
if nDataBytes>0 then DataYet := True; 
N:=0; {чтение с первой позиции} 
while DataYet do 
begin 
ReadOneDataBlock(Ki,Kj); {получаем 4 байта} 
nDataBytes := nDataBytes-4; 
if nDataBytes<=4 then DataYet := False; 
end; 
 
 
ScaleData(Ki); 
if Ki.WAV.nChannels=2 
then begin Kj.WAV := Ki.WAV; 
ScaleData(Kj); 
end; 
{Освобождаем буфер файла} 
CloseFile( InFile ); 
end 
else begin 
InitSpecs;{файл не существует} 
InitSignals(Ki);{обнуляем массив "Ki"} 
InitSignals(Kj);{обнуляем массив "Kj"} 
end; 
end; { ReadWAVFile } 
 
 
 
{================= Операции с набором данных ====================} 
 
const MaxNumberOfDataBaseItems = 360; 
type  SignalDirectoryIndex = 0 .. MaxNumberOfDataBaseItems; 
 
VAR DataBaseFile   : file of Observation; 
 
LastDataBaseItem : LongInt; {Номер текущего элемента набора данных} 
ItemNameS : array[SignalDirectoryIndex] of String[40]; 
 
procedure GetDatabaseItem( Kk : Observation; N : LongInt ); 
begin 
 
if N<=LastDataBaseItem 
then begin 
Seek(DataBaseFile, N); 
Read(DataBaseFile, Kk); 
end 
else InitSignals(Kk); 
end; {GetDatabaseItem}  
procedure PutDatabaseItem( Kk : Observation; N : LongInt ); 
begin 
 
if N<=LastDataBaseItem 
then begin 
Seek(DataBaseFile,  N); 
Write(DataBaseFile, Kk); 
LastDataBaseItem := LastDataBaseItem+1; 
end 
else while LastDataBaseItem<=N do 
begin 
Seek(DataBaseFile,  LastDataBaseItem); 
Write(DataBaseFile, Kk); 
LastDataBaseItem := LastDataBaseItem+1; 
end 
else ReportError(1); {Попытка чтения MaxNumberOfDataBaseItems} 
end; {PutDatabaseItem} 
 
procedure InitDataBase; 
begin 
 
LastDataBaseItem := 0; 
if FileExists(StandardDataBase) 
then 
begin 
Assign(DataBaseFile,StandardDataBase); 
Reset(DataBaseFile); 
while not EOF(DataBaseFile) do 
begin 
GetDataBaseItem(K0R, LastDataBaseItem); 
ItemNameS[LastDataBaseItem] := K0R.Name; 
LastDataBaseItem := LastDataBaseItem+1; 
end; 
if   EOF(DataBaseFile) 
then if   LastDataBaseItem>0 
then LastDataBaseItem := LastDataBaseItem-1; 
end; 
end; {InitDataBase} 
 
function FindDataBaseName( Nstg : String ):LongInt; 
var ThisOne : LongInt; 
begin 
 
ThisOne          := 0; 
FindDataBaseName := -1; 
while ThisOne
 
					 
					
				 
			 
			
	 
 
Внимание! Если у вас не получилось найти нужную информацию, используйте 
рубрикатор  или воспользуйтесь 
поиском  .      
   
книги  по  программированию  исходники  компоненты  шаблоны  сайтов  C++  PHP  Delphi  скачать