faqs.org.ru

 Главная > Программирование > Языки Pascal/Delphi >

RU.DELPHI FAQ

Секция 5 из 5 - Предыдущая - Следующая
Все секции - 1 - 2 - 3 - 4 - 5

части. Это ветви HKEY_CURRENT_USER для хранения настроек специфичных для
пользователя, и HKEY_LOCAL_MACHINE для хранения настроек специфичных для
всего ПК и соответственно всех пользователей, работающих с этим ПК.
Рекомендуемая структура ветвей для хранения настроек программы -
HKEY_CURRENT_USER\Software\Company Name\Application Name\Version и
соответственно HKEY_LOCAL_MACHINE\Software\Company Name\Application
Name\Version. Параметры Company Name, Application Name, Version желательно
не хранить в виде hard-coded строк в коде программы а устанавливать в опциях
проекта (Project\Options\Version Info) и доставать впоследствии из ресурса с
помощью той же библиотеки RxLib. Альтернативный путь выбирать данные о
версии программы из ресурсов - использование Windows API
(GetFileVersionInfo, GetFileVersionInfoSize, VerQueryValue).
Программе следует расчитывать на то что доступ к подключам
HKEY_LOCAL_MACHINE разрешен в режиме только для чтения, а доступ к подключам
HKEY_CURRENT_USER допускает чтение, изменение и создание новых подключей и
значений.
Программе следует расчитывать на то что нужных ей ключей может не оказаться
в реестре или значения лежащие в реестре имеют неверный формат или
недопустимые значения. В таком случае, вместо несуществующих или неверных
значений настройки, программа должна использовать значения по умолчанию
которые разработчик может "железно забить в код" или получить с помощью
различных системных функций.
Не следует использовать системный реестр для хранения больших кусков данных.
Вместо этого лучше хранить объемные данные в отдельном файле, а в реестре
запомнить имя этого файла.

Домашний каталог пользователя

Для хранения настроек слишком больших для того чтобы их размещать в реестре
существуют специально выделенные каталоги внутри домашнего каталога
пользователя. Эти каталоги обычно называются "специальными каталогами" и
имеют имена Application Data и Local Settings. Полный путь к ним можно
получить с помошью функций SHGetSpecialFolderPath или SHGetFolderPath.

Общий каталог пользователей

Обычно это каталог "Documents and Settings\All users". Внутри него имеются
такие-же подкаталоги для хранения настроек и данных программ но относящихся
ко всем пользователям. Полный путь к ним можно также получить с помошью
функций SHGetSpecialFolderPath или SHGetFolderPath.

Как хранить

Системный реестр
Для работы с системным реестром можно использовать функции Registry API
общим числом около 40 штук, а можно использовать классы из Registry.pas -
TRegistry, TRegistryIniFile, TRegIniFile. Особенно следует обратить внимание
на TRegistryIniFile который предоставляет упрощенную модель доступа к
системному реестру очень схожую с моделью работы с INI-файлами.

INI-файлы
Это старый метод хранения настроек программ, но все еще применяющийся
программистами. Настройки хранятся в текстовом файле в виде:

[Section1]
Field1=Value1
Field2=Value2
....
FieldN=ValueN

[Section2]
Field1=Value1
Field2=Value2
....
FieldN=ValueN
....

[SectionN]
Field1=Value1
Field2=Value2
....
FieldN=ValueN

Для доступа к данным содержащимся в INI-файлах существуют классы из модуля
IniFiles - TIniFile, TMemIniFile.
Преимущество использования INI-файлов состоит в том что их можно легко
подредактировать с помощью текстового редактора. Они обычно легче
воспринимаются для прочтения нежели дерево ключей системного реестра.

Бинарные файлы настроек
Отдельно хочется поговорить о использовании бинарных файлов в качестве
хранилища для настроек программы. Обычные мотивы любителей использовать
бинарные файлы:

  Экономится место
  Настройку можно спрятать от пользователя (сделать нечитабельной)

Первое глупо потому что информация о настройке занимает обычно немного места
и экономия достигается мизерная. Второе глупо потому что невозможность
просмотра и редактирования настроечных данных  простыми средствами
(текстовый редактор) или встроенными (редактор реестра) создает больше
проблем как пользователю так разработчику, нежели пользы (причем весьма
сомнительной) от того что кто-то не сможет прочитать что написано в файле.
Кроме того использование бинарного файла нельзя назвать защитой от
нежелательного просмотра, т.к. любой "продвинутый пользователь" все равно с
помощью редактора бинарных файлов сможет просмотреть и разобраться в
содержимом настройки.

Заключение

Почти вся эта информация была вычерпана из кладезя мудрости под названием
Platform SDK (Software Development Kit), поставляемого в составе сборника
документации MSDN (Microsoft Software Developer Network). Разработчикам
настоятельно рекомендуется приобрести Platform SDK, это снимает огромную
массу вопросов связанную с программированием под Windows.

------------------------------------------------------------
Q-147:  Как вывести ProgresBar на StatusBar?
------------------------------------------------------------
--- Андрей Барташ

Gauge:=TGauge.Create(Form1);
Gauge.Parent:= StatusBar1;
Gauge.Top:=4;
Gauge.Left := 116;
Gauge.Height := 15;
Gauge.Width := 200;

Компонент TGauge находится на закладке Samples

------------------------------------------------------------
I-148:  Список рекомендуемой литературы
------------------------------------------------------------
1. А. Архангельский, В. Ильин, М. Тагин
Русская справка (HELP) по Delphi 5 и Object Pascal (32 стр. с CD-ROM)
Бином, ISBN 5-7989-0168-8

2. А. Архангельский. Программирование в Delphi 5
Бином, ISBN 5-7989-0104-1

3. А. Архангельский. Программирование в Delphi 6
Бином, ISBN 5-7989-0227-7

4. П. Даpахвелидзе, Е. Маpков
Delphi 4 в подлиннике

5. П. Дарахвелидзе, Е. Марков, О. Котенок
Программирование в Delphi 5
BHV-СПб, ISBN 5-8206-0052-5

6) П.В. Шумаков, В.В. Фаронов "Delphi xx. Руководство разработчика баз
данных."

7) М.Кэнту
Delphi 4 для пpофессионалов

8. Ч.Калвеpт
Delphi 4, Энциклопедия пользователя

9. Стив Тейксейра, Ксавье Пачеко
Delphi 5. Руководство разработчика. Том 1.
Основные методы и технологии программирования
Вильямс, ISBN 5-8459-0016-6
2000 Вильямс

10. Стив Тейксейра И Ксавье Пачеко
Delphi 5. Руководство разработчика. Том 2.
Разработка компонентов и работа с базами данных
2000 Вильямс
ISBN 5-8459-0066-2

11. Конопка Рей
Создание оригинальных компонент в среде Delphi: Пер. с англ./Рей Конопка.
К.: НИПФ - "ДиаСофт Лтд.", 1996. - 512 с.
ISBN 5-7707-9551-4

12. Лишнер Рэй
Секреты Delphi 2: Пер. с англ./Рэй Лишнер. -
К.: НИПФ - "ДиаСофт Лтд.", 1996. - 800 с.
ISBN 966-7033-10-4

13. Том Сван "Секреты 32-разрядного программирования в Delphi"
Диалектика, Киев, 1997. 480 стр.,
ISBN 966-506-052-X (рус.)

14. Дэн Оузьер "Дельфи 2. Освой самостоятельно."
Восточная Книжная Компания,
1997. 624 стр. Binom.

15. Михаил Кpаснов. DirectX Гpафика в пpоектах Delphi
BHV
ISBN-5-94157-033-3

В списке отсутствует ряд хороших книг, по причине недостаточнысти данных,
если у кого есть замечания, исправления или дополнения по данной статье, то
просьба посылать их прямо на mailto: anatoly@podgoresky.com

Новые книги можно искать и заказывать через Интернет на сайте
http://books.ru
Там же как правило есть аннотация.

Кроме указанных книг существует большое количество ресурсов в Интернете
посвященных Дельфи - это статьи, электронные библиотеки и прочее. Один из
ресурсов расположен на моем сайте - это несколько проектов электронных
библиотека, в совокупности свыше 200 книг. Доступ ко всем проектам прямо с
главной страницы http://www.podgoretsky.com, существует так же доступ и по
FTP (3 анонимных сессии)

Один из недостатков, это то что сервер сильно перегружен все 24 часа в
сутки, семь дней в неделю, поэтому скорость весьма низкая, поэтому
желательно использовать какой либо менеджер закачек, также не рекомендуется
использовать многопотоковую закачку, это не ускорит сам процесс закачки, а
только уменьшит возможность закачки для других пользователей.
Большинство книг с моего сервера, также доступны и на других серверах и если
есть возможность взять их из другого источника, то это будет более
оптимальным вариантом по скорости.

------------------------------------------------------------
Q-149:  Как нажать клавиши в другом приложении?
------------------------------------------------------------
"Нажимаем" клавиши в Блокноте (уже запущенном):

uses Sendkey; {описан ниже}

procedure TForm1.Button1Click(Sender: TObject);
var
  h: HWND;
begin
  h := FindWindow('Notepad', nil); // ищем окно Блокнота
  SendMessage(h, WM_SYSCOMMAND, SC_HOTKEY, h); // активизируем его
  PlayKeys(StrToKeys('abcdef')); // нажимаем клавиши
  SendMessage(Handle, WM_SYSCOMMAND, SC_HOTKEY, Handle); // возвращаем фокус
end;

Коды vk_ клавиш можно найти в Win32 Programmer's Reference (win32.hlp):
Virtual-Key Codes. {В дельфи не описаны коды клавиш ['A'..'Z'] и ['0'..'9'],
их получают с помощью Ord, например, Ord('A'), Ord('9')}.

Символы из верхнего ряда клавиатуры посылаются с нажатым Shift. Заметим, что
символы в локальной кодировке могут быть посланы после переключения
кодировки в активном приложении, например, если перключатель (switch)
Control-Shift, то это:

  PlayKeys(Chr(vk_control)+#0+Chr(vk_shift)+#0); {downkey = #0};

--- unit Sndkey.pas ---

unit sndkey;

interface

uses
  Windows,
  Messages;

const
  {VK constants missing from windows.pas}
  VK_SEMICOLON    = 186; {;}
  VK_EQUAL        = 187; {=}
  VK_COMMA        = 188; {,}
  VK_MINUS        = 189; {-}
  VK_PERIOD       = 190; {.}
  VK_SLASH        = 191; {/}
  VK_BACKQUOTE    = 192; {`}
  VK_LEFTBRACKET  = 219; {[}
  VK_BACKSLASH    = 220; {\}
  VK_RIGHTBRACKET = 221; {]}
  VK_QUOTE        = 222; {'}

  downkey = #0;
  upkey = Chr(KEYEVENTF_KEYUP); {#2}

procedure PlayKeys(const keys: String);
function StrToKeys(const s: String): String;

{Alt-F4:
PlayKeys(Chr(vk_menu)+#0+Chr(vk_f4)+#0+Chr(vk_f4)+#2+Chr(vk_menu)+#2)}
{"exit"<return>: PlayKeys(StrToKeys('exit'+chr(vk_return)));}
{"EXIT":
PlayKeys(Chr(vk_shift)+downkey+StrToKeys('exit')+Chr(vk_shift)+upkey));}
{or short form: PlayKeys(Chr(vk_shift)+#0+StrToKeys('exit'));}

implementation

function StrToKeys; {keystroke for alone keys}
var
  i: Longint;
  c: Char;
begin
  for i := 1 to Length(s) do
    begin
      c := s[i];
      if c in ['a'..'z'] then {Upper}
        c := Chr(Ord(c) and not $20);
      Result := Result + c + downkey
                       + c + upkey;
    end;
end;

procedure PlayKeys;
const
  ExtendedKeys : set of byte =
    [ vk_up,     vk_down,
      vk_left,   vk_right,
      vk_home,   vk_end,
      vk_prior,  vk_next,
      vk_insert, vk_delete];
var
  i, ips : Longint;
  fb, sb: Byte;
  keysdown: String;

  procedure keybd (vk, kp : Byte);
  begin
    if vk in ExtendedKeys then
      kp := kp + KEYEVENTF_EXTENDEDKEY;
    keybd_event(vk, MapVirtualKey(vk, 0), kp, 0);
  end;

begin
  keysdown := '';
  for i := 1 to Length(keys) div 2 do
    begin
      fb:= Ord(keys[2*i -1]);
      sb:= Ord(keys[2*i]);
      if sb = Ord(downkey) then
        keysdown := keysdown + Chr(fb)
      else
        begin
          ips := pos(Chr(fb), keysdown);
          if ips > 0 then
            Delete(keysdown, ips, 1)
          else
            Continue;
        end;
      keybd(fb, sb);
    end;
    {Autocomplete}
    for i := 1 to Length(keysdown) do
      keybd(Ord(keysdown[i]), Ord(upkey));
end;

end.
--- EOF unit Sndkey.pas ---

Leonid Troyanovsky <lv.t@eco-pro.ru>

------------------------------------------------------------
Q-150:  Как перетащить файлы из проводника в мою программу
------------------------------------------------------------
TMainForm = class(TForm)
  ...
private
  procedure WMDROPFILES(var Message: TWMDROPFILES); message
WM_DROPFILES;
  procedure ProcessFile(Filename: string);
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  DragAcceptFiles(MainForm.Handle, TRUE); // enable drag&drop
end;

procedure TMainForm.ProcessFile(Filename: string);
begin
// any actions
end;

procedure TMainForm.WMDROPFILES(var Message: TWMDROPFILES);
var
  Files  : Longint;
  I      : Longint;
  Buffer : array[0..MAX_PATH] of Char;
begin
  Files := DragQueryFile(Message.Drop,$FFFFFFFF,nil,0); // Get count of
files
  for I := 0 to Files - 1 do begin
    DragQueryFile(Message.Drop,I,@Buffer,SizeOf(Buffer)); // Get N file
    ProcessFile(Buffer); // do something with the file
  end;
  DragFinish(Message.Drop); // end drag loop
end;

"Anatoly Podgoretsky" <anatoly@podgoretsky.com>

------------------------------------------------------------
Q-151:  Как использовать в Дельфи API фyнкции
------------------------------------------------------------
AA> как это ни странно, вызывать их. предварительно заюзав модуль windows.

Правильнее : вызвать, предварительно подключив модуль, в котором данная
функция описана (это может быть windows, activex, shellapi и т.д.).
Найти модуль поможет клавиша F1 на имени функции.

Если функция не нашлась - то попробовать сделать поиск в папке с исходными
текстами Дельфи.

Если функция не нашлась - есть шанс, что в этой версии Дельфи она не
описана. В этом случае надо поискать "заголовочный файл" (API header file) в
интернете. Огромная коллекция их находится на сайте www.delphi-jedi.org.

Если не помогло и это - придется взять описание функции из документации
производителя данного API (обычно оно на С) и самому сделать ее обьявление,
так же, как это сделано в windows.pas, только в своем юните.

Сергей Кабиков

------------------------------------------------------------
Q-152:  Автоматическое определение кодировки текста
------------------------------------------------------------
AG> Существуют ли в сободном для изучения доступе алгоритмы автоматического
AG> определения кодировки текста?
О, еще сколько. Методом таблицы модельных распределений:

type
  TCodePage = (cpWin1251, cp866, cpKOI8R);
  PMap = ^TMap;
  TMap = array [#$80..#$FF] of Char;

function GetMap(CP: TCodePage): PMap;
{ должна возвращать указатель на таблицу перекодировки из CP в Windows1251
  (nil для CP = cpWin1251) }
begin
  GetMap:=nil;
end;

function DetermineRussian(Buf: PChar; Count: Integer): TCodePage;
const
  ModelBigrams: array [0..33, 0..33] of Byte = (
   {АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ_Ё}
{А}(0,20,44,12,22,23,16,60,4,9,63,93,47,110,0,16,35,61,81,1,5,13,24,17,12,4,0,0,0,0,14,31,205,1),
{Б}(19,0,0,0,4,19,0,0,8,0,2,15,1,4,41,0,15,5,0,15,0,2,1,0,0,6,16,37,0,0,0,4,3,0),
{В}(97,0,1,0,2,57,0,5,40,0,4,25,2,23,78,2,8,28,4,12,0,1,0,0,8,1,0,40,1,0,0,5,106,3),
{Г}(13,0,0,0,9,5,0,0,15,0,1,17,1,2,96,0,24,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,8,0),
{Д}(63,0,9,1,2,71,1,0,35,0,3,16,2,22,50,2,19,9,2,25,0,2,1,0,1,0,1,9,4,0,1,5,17,4),
{Е}(4,14,15,34,56,22,13,14,2,34,39,77,73,150,6,9,101,64,81,1,0,15,5,12,10,6,0,0,0,0,3,4,235,1),
{Ж}(13,0,0,0,12,47,0,0,16,0,1,0,0,23,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,2,2),
{З}(76,2,11,3,11,4,1,0,7,0,2,4,11,24,17,0,6,1,0,8,0,0,0,0,0,0,0,16,6,0,1,4,17,0),
{И}(7,9,32,5,18,60,4,42,31,27,28,46,55,49,12,7,26,60,53,0,5,25,14,28,4,1,0,0,0,0,9,56,255,0),
{Й}(0,0,0,0,2,0,0,0,0,0,1,3,0,3,0,0,0,10,3,0,0,0,0,1,1,0,0,0,0,0,0,0,122,0),
{К}(92,0,3,0,0,7,2,1,39,0,0,27,0,14,110,0,18,5,35,18,0,0,11,0,0,0,0,0,0,0,0,0,5,5,0),
{Л}(85,1,0,2,1,70,6,0,85,0,5,3,0,9,67,1,0,9,0,15,0,0,0,2,0,0,0,9,66,0,15,43,57,4),
{М}(44,0,0,0,0,65,0,0,47,0,1,1,10,15,57,7,0,2,0,24,0,0,0,0,0,0,0,28,0,0,0,8,109,3),
{}(139,0,0,1,11,108,0,4,152,0,7,0,1,69,161,0,0,8,25,24,5,1,5,2,0,1,0,83,10,0,1,29,38,5),
{О}(0,72,139,76,74,32,32,19,12,52,21,93,68,72,7,34,93,102,98,1,2,6,6,19,15,2,0,0,0,1,4,9,252,2),
{П}(17,0,0,0,0,43,0,0,14,0,1,9,0,1,125,3,120,1,2,8,0,0,0,0,0,0,0,3,6,0,0,3,2,2),
{Р}(151,1,6,4,3,103,7,0,76,0,4,0,11,10,117,1,0,5,9,39,2,5,0,1,3,0,0,24,7,0,1,10,22,5),
{С}(24,1,21,0,3,39,0,0,33,0,56,41,11,15,58,30,5,30,183,16,0,4,1,4,1,0,0,8,25,0,1,50,41,2),
{Т}(83,0,43,0,3,87,0,0,71,0,9,3,2,26,180,0,55,33,1,23,1,0,1,4,0,0,0,20,78,0,0,5,82,4),
{У}(3,6,7,14,19,8,13,6,0,1,13,15,10,7,0,12,17,16,19,0,1,3,0,12,5,8,0,0,0,0,22,1,65,0),
{Ф}(4,0,0,0,0,4,0,0,11,0,0,1,0,0,9,0,3,0,0,4,1,0,0,0,0,0,0,0,0,0,0,0,2,0),
{Х}(9,0,2,0,0,2,0,0,5,0,0,1,0,5,26,0,4,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,76,0),
{Ц}(5,0,0,0,0,16,0,0,48,0,1,0,0,0,4,0,0,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,3,0),
{Ч}(30,0,0,0,0,52,0,0,23,0,3,1,0,14,1,0,0,0,36,5,0,0,0,0,1,0,0,0,1,0,0,0,2,2),
{Ш}(13,0,0,0,0,28,0,0,17,0,4,4,0,4,3,0,0,0,1,3,0,0,0,0,0,0,0,0,3,0,0,0,1,1),
{Щ}(6,0,0,0,0,23,0,0,16,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1),
{Ъ}(0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0),
{Ы}(0,5,14,1,3,28,0,2,0,22,6,19,21,2,0,5,4,7,10,0,0,37,0,3,4,0,0,0,0,0,0,1,84,0),
{Ь}(0,1,0,0,0,9,0,10,1,0,13,0,2,26,0,0,0,10,3,0,0,0,1,0,6,0,0,0,0,0,6,4,117,0),
{Э}(0,0,0,0,0,0,0,0,0,0,3,3,0,0,0,0,0,0,31,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0),
{Ю}(0,5,0,0,3,0,0,0,0,0,0,1,0,0,0,0,0,1,15,0,0,0,1,4,1,15,0,0,0,0,0,0,38,0),
{Я}(0,0,9,2,7,10,3,19,0,0,1,6,7,8,0,0,2,6,19,0,0,3,5,1,0,3,0,0,0,0,5,2,177,0),
{_}(42,80,193,43,109,41,18,53,159,0,144,27,83,176,187,229,70,231,99,47,15,13,6,58,7,0,0,0,0,38,0,22,0,2),
{Ё}(0,0,0,0,3,0,0,0,0,0,2,4,4,8,0,0,5,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0));
{ "рейтинг" буквы Ё условно принимается равным 1/20 от "рейтинга" буквы E,
  если сочетание с участием Ё корректно, иначе - 0 }
type
  TVariation = array [0..33, 0..33] of Integer;
var
  I, J, iC, iPredC, Max: Integer;
  C: Char;
  CP: TCodePage;
  D, MinD, Factor: Double;
  AMap: PMap;
  PV: ^TVariation;
  Vars: array [TCodePage] of TVariation;
begin
  DetermineRussian:=cpWin1251; { по yмолчанию }
  { вычисление распределений биграмм }
  FillChar(Vars, SizeOf(Vars), 0);
  for CP:=Low(Vars) to High(Vars) do begin
    AMap:=GetMap(CP);
    PV:=@Vars[CP];
    iPredC:=32;
    for I:=0 to Count - 1 do begin
      C:=Buf[I];
      iC:=32;
      if C >= #128 then begin
        if AMap <> nil then C:=AMap^[C];
        if not (C in ['Ё', 'ё']) then begin
          C:=Chr(Ord(C) and not 32); { 'a'..'я' -> 'А'..'Я' }
          if C in ['А'..'Я'] then iC:=Ord(C) - Ord('А');
        end
        else
          iC:=33;
      end;
      Inc(PV^[iPredC, iC]);
      iPredC:=iC;
    end;
  end;
  { вычисление метрики и определение наиболее правдоподобной кодировки }
  MinD:=0;
  for CP:=Low(Vars) to High(Vars) do begin
    PV:=@Vars[CP];
    PV^[32, 32]:=0;
    Max:=1;
    for I:=0 to 33 do
      for J:=0 to 33 do
        if PV^[I, J] > Max then Max:=PV^[I, J];
    Factor:=255 / Max; { ноpмализация }
    D:=0;
    for I:=0 to 33 do
      for J:=0 to 33 do
        D:=D + Abs(PV^[I, J] * Factor - ModelBigrams[I, J]);
    if (MinD = 0) or (D < MinD) then begin
      MinD:=D;
      DetermineRussian:=CP;
    end;
  end;
end;

begin
  { тест: слово 'Пример' в разных кодировках (веpоятность ошибок на таких
    коpотких текстах высока - в данном слyчае пpосто повезло!) }
  writeln(DetermineRussian(#$CF#$F0#$E8#$EC#$E5#$F0, 6) = cpWin1251);
  writeln(DetermineRussian(#$8F#$E0#$A8#$AC#$A5#$E0, 6) = cp866);
  writeln(DetermineRussian(#$F0#$D2#$C9#$CD#$C5#$D2, 6) = cpKOI8R);
  readln;
end.

--
Best regards,
Stas Malinovski.           mailto:stasm@tsl.ru

------------------------------------------------------------
Q-153:  Как помигать лампочками на клавиатуре?
------------------------------------------------------------
var
  KeyState : TKeyboardState;
begin
  GetKeyboardState(KeyState);
  KeyState[VK_NUMLOCK] := KeyState[VK_NUMLOCK] xor 1;
  SetKeyboardState(KeyState);
end;

Изменяет состояние индикаторов на обратное...
См. также VK_NUMLOCK, VK_CAPITAL

WinNT:
    {
    keybd_event( VK_SCROLL, 0x46, KEYEVENTF_EXTENDEDKEY | 0, 0 );
    keybd_event( VK_SCROLL, 0x46, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
0);
    }

Stas Malinovski.  mailto:stasm@tsl.ru

------------------------------------------------------------
Q-154:  Как создать в runtime форму
------------------------------------------------------------
with TxxForm.Create(Self) do Show;

with TxxForm.Create(Self) do
try
  ShowModal;
finally
  Free;
end;

------------------------------------------------------------
Q-155:  Как прочитать порт или записать в него.
------------------------------------------------------------
В мультизадачных ОС как правило доступ к портам запрещен идеологией системы.
И это неспроста - подумайте, что будет, если одновременно с вашей программой
этот же порт попробует использовать другая программа.

Но в Win9x существует частичная возможность обратиться напрямую с помощью
ассемблерных команд. Делать это надо с определенной осторожность. Даже если
вы получите доступ до порта на своей машине, то это не означает, что это
будет и на другой машине, например доступ до LPT порта может быть закрыт
драйвером принтера, такое редко но встречается. Доступ к наиболее важным
портам прикрыты запрещен полностью соответствующими системными драйверами.

В Win NT доступ к оборудованию со стороны пользовательской программы
запрещен полностью. Для доступа на этих ОС требуется использовать kernel
mode драйвера, тоже самое рекомендуется и для Win9x.
Вот несколько полезных ссылок:

  TVicHW32      http://www.entechtaiwan.com/tools.htm
  Tinyport (NT)
http://www.winsite.com/info/pc/winnt/programr/tinypo21.zip.drag
  DriverX       http://www.tetradyne.com
  giveio (NT)
http://www.wideman-one.com/gw/tech/Delphi/iopm/index.htm
  Ports, by Harold Howe, http://www.bcbdev.com/components.htm

Код доступа к портам с помощью ассемблера.

procedure WritePortByte(Port:Word; Value:Byte);
asm
  XCHG  EDX,EAX
  OUT   DX,AL
end;

procedure WritePortWord(Port:Word; Value:Word);
asm
  XCHG  EDX,EAX
  OUT   DX,AX
end;

function ReadPortByte(Port:Word) : Byte;
asm
  MOV   EDX,EAX
  IN    AL,DX
end;

function ReadPortWord(Port:Word) : Word;
asm
  MOV   EDX,EAX
  IN    AX,DX
end;

Примечание:

Существуют устройства с подряд идущими (по адресам) _байтовыми_ портами, к
которым нельзя обращаться со словными командами I/O. На сегодня они почти
вымерли, но :

При выборе типа процедуры (BYTE или WORD) следует ориентироваться на
спецификацию устройства ввода-вывода, к которому идет
обращение. Не следует обращаться к байтовому устройству с
WORD-ориентированными процедурами - экономия времени мизерная, а побочные
эффекты могут быть катастрофическими."
Например, некоторые адаптеры сбрасывают биты ошибок после чтения
статус-регистра. Другие отображают несколько внутренних регистров на один
адрес I/O, и т.п.

На некоторых старых компьютерах Word  процедуры могут не работать из за
специфических особенностей интерфейса, правда такие компьютера практически
уже не встречаются. Есть ISA Bus Specification, где эти вопросы четко
формализованы. Выборка словного порта может быть разбита на два раза, даже
если адрес четный, в зависимости от пожеланий устройства I/O.

------------------------------------------------------------
Q-156:  Как работать с битами?
------------------------------------------------------------
Есть два способа.
Низкоуровневый подход обеспечивается логическими операциями :

var
  I : integer;
  N : integer;                       // Номер бита в диапазоне от
0..SizeOf(TYPE)*8 - 1

  I := I or (1 shl N);               // установка бита
  I := I and not (1 shl N);          // сброс бита
  I := I xor (1 shl N);              // инверсия бита
  if (i and (1 shl N)) <> 0 then...  // проверка установленного бита

Высокоуровневый подход опирается на представление числа в виде множества:

type
  TIntegerSet = set of 0..SizeOf(Integer)*8 - 1;
var
  I : Integer;
  N : Integer;

  Include(TIntegerSet(I), N);     // установили N-ный бит в 1
  Exclude(TIntegerSet(I), N);     // сбросили N-ный бит в 0
  if N in TIntegerSet(I) then...  // проверили N-ный бит

------------------------------------------------------------
Q-157:  Как удалить непустой каталог?
------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
  lpFileOp: TSHFileOpStruct;
begin
   FillChar(lpFileOp,SizeOf(lpFileOp),0);
   lpFileOp.Wnd := Handle;
   lpFileOp.wFunc := FO_DELETE;
   lpFileOp.pFrom := PChar(Edit1.Text);
   lpFileOp.fFlags := FOF_NOCONFIRMATION;
   SHFileOperation(lpFileOp);
end;

Ivan Daniloff <abc12345@eprst.ru>

------------------------------------------------------------
Q-158:  Как получить список файлов со всеми подкаталогами
------------------------------------------------------------
procedure ScanDir(StartDir: string; Mask:string; List:TStrings);
var
  SearchRec : TSearchRec;
begin
  if Mask = '' then Mask := '*.*';
  if StartDir[Length(StartDir)] <> '\' then StartDir := StartDir + '\';
  if FindFirst(StartDir+Mask, faAnyFile, SearchRec) = 0 then
  begin
    repeat
      Application.ProcessMessages;
      if (SearchRec.Attr and faDirectory) <> faDirectory then
        List.Add(StartDir + SearchRec.Name)
      else if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then
begin
        List.Add(StartDir + SearchRec.Name + '\');
        ScanDir(StartDir + SearchRec.Name + '\',Mask,List);
      end;
    until FindNext(SearchRec) <> 0;
    FindClose(SearchRec);
  end;
end;

Пример вызова. параметры
1. имя папки
2. маска, по умолчанию *.*
3. хранилище для резульатат, любой наследник от TString, например
TStringList

procedure TForm1.Button1Click(Sender: TObject);
begin
  ListBox1.Items.Clear;
  ScanDir('c:','',ListBox1.Items);
  Label1.Caption := IntToStr(ListBox1.Items.Count);
end;

Анатолий Подгорецкий
anatoly@podgoretsky.com
-------------------------------------------------------------

В связи с тем, что многие не понимают работу с масками, например пытаются
искать файлы *.txt во всех подкаталогах, вот модифицированная версия для
поиска файлов, которая для поиска подкаталогов использует мвску *.*, а для
файлов указанную маску.
Процедура представлена Юрием Зотовым.

procedure FindAllFiles(List: TStrings; Dir, Mask: string);

  procedure ScanDir(Dir: string);
  var
    SR: TSearchRec;
  begin
    Dir := IncludeTrailingBackSlash(Dir);
    if FindFirst(Dir + '*.*', faAnyFile - faVolumeID, SR) = 0 then
    try
      repeat
        if (SR.Name <> '.') and (SR.Name <> '..') then
          if SR.Attr and faDirectory <> 0 then
            ScanDir(Dir + SR.Name)
          else
            if MatchesMask(SR.Name, Mask) then
              List.Add(Dir + SR.Name)
      until FindNext(SR) <> 0
    finally
      FindClose(SR)
    end
end;

begin
  if (List = nil) or not DirectoryExists(Dir) or (Mask = '') then
    raise Exception.Create('Invalid parameter');
  List.Clear;
  ScanDir(Dir)
end;

Примечания: функция MatchesMask существует только с определенных версий
Дельфи, как минимум в 5 есть.

------------------------------------------------------------
Q-159:  Как преобразовать unix time в TDateTime
------------------------------------------------------------
unix timestamp представляет собой число секунд начиная с 1.01.1970

const
  SecPerDay  = 86400;
  Offset1970 = 25569;

function UnixTimeToDateTime(UnixTime : LongInt): TDate;
begin
  Result := UnixTime / SecPerDay + Offset1970;
end;

function DateTimeToUnixTime(DelphiDate : TDate) : LongInt;
begin
  Result := Trunc((DelphiDate - Offset1970) * SecPerDay);
end;

Если необходима корректировка зимнего/летнего времени, то ее следует сделать
самостоятельно.

------------------------------------------------------------
Q-160:  Как сделать .manifest для Windows XP
------------------------------------------------------------
Для того, чтобы программы запускаемые под Windows XP, имели новый вид,
необходимо вместе с программой поставить файл *.manifest или включить его в
ресурс.
Для это изготовить файл, по ниже приведенной инструкции, назвать его
Project1.exe.manifest, по положить рядышком с Project1.exe, после это
запускаешь под XP и радуешься :-)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
   version="1.0.0.0"
   processorArchitecture="*"
   name="Igor.Schevchenko.XPUtilsTest"
   type="win32"
/>
<description>XP User utils test</description>
<dependency>
   <dependentAssembly>
     <assemblyIdentity
       type="win32"
       name="Microsoft.Windows.Common-Controls"
       version="6.0.0.0"
       processorArchitecture="X86"
       publicKeyToken="6595b64144ccf1df"
       language="*"
     />
   </dependentAssembly>
</dependency>
</assembly>

Строчку name="Igor.Schevchenko.XPUtilsTest" меняешь на
name="Kostya.Ergin.Project1"

С уважением,
Игорь Шевченко
++++++++++++++++++++++++++++++

В Delphi Studio 7 Enterprise и Professional, приложения Borland VCL теперь
включают компоненты, которые разрешают поддержку WindowsR общих контролов
версии 6. Ваше приложение автоматически использует новые контролы Windows на
системе Windows XP, если найдет подходящий манифест файл. Более подробно об
этом в руководстве Developer's Guide тема "Common controls and XP themes"
или в справочной системе.

Анатолий Подгорецкий

------------------------------------------------------------
Q-161:  Как узнать версию программы
------------------------------------------------------------
function GetFileVersion(const FileName: TFileName; var Major, Minor,
Release, Build: Integer): Boolean;
var
  InfoSize, Wnd: DWORD;
  VerBuf: Pointer;
  FI: PVSFixedFileInfo;
VerSize: DWORD;
begin
  Result:= False;
  InfoSize:= GetFileVersionInfoSize(PChar(FileName), Wnd);
  if InfoSize <> 0 then begin
    GetMem(VerBuf, InfoSize);
    try
      if GetFileVersionInfo(PChar(FileName), Wnd, InfoSize, VerBuf) then
        if VerQueryValue(VerBuf, '\', Pointer(FI), VerSize) then begin
          Major:= FI.dwFileVersionMS shr 16;
          Minor:= FI.dwFileVersionMS and $FFFF;
          Release:= FI.dwFileVersionLS shr 16;
          Build:= FI.dwFileVersionLS and $FFFF;
          Result:= True;
        end;
    finally
      FreeMem(VerBuf);
    end;
  end;
end;

Ilya Katargin <Ilya.Katargin@f9.n5029.z2.fidonet.org>
-------------------------------------------------------

function  GetFileVersion(FName: TFileName): String;
var
S: String;
n, Len: Cardinal;
Buf, Value: PChar;
begin
Result:='';
S := FName;
n := GetFileVersionInfoSize(PChar(S), n);
if n = 0 then Exit;
Buf := AllocMem(n);
GetFileVersionInfo(PChar(S), 0, n, Buf);
if VerQueryValue(Buf, PChar('StringFileInfo\041904E3\FileVersion'),
Pointer(Value), Len) then
   Result:=Value;
FreeMem(Buf, n);
end;

шеп <шеп@p256.f1355.n5020.z2.fidonet.org>
-------------------------------------------------

> if VerQueryValue(Buf, PChar('StringFileInfo\041904E3\FileVersion'),

Здесь жестко прописан язык и кодовая страница '041904E3'.
В хелпе к Д6 тоже прописано жестко: '040904E4' (см. Reading version
information в хелпе). Я ,кстати, сам не сразу сообразил, что это значение
в хелпе не работает для русского языка :(
А ведь это значение можно взять там же:
type
  TLangChrSet = array[0..1] of word;
  PLangChrset = ^TLangChrSet;
var
  LangChrSet: PLangChrSet;
....
после получения FileVersionInfo
      VerQueryValue(Buf, PChar('VarFileInfo\Translation'),
pointer(LangChrset), Len);
      S:=Format('%.4x%.4x',[LangChrSet^[0], LangChrSet^[1]]);
теперь в S у нас то, что надо :)

С Уважением, Евгений Переверзев.
Eugene@asv.afn.ru

------------------------------------------------------------
Q-162:  Как выключить или презагрузить компьютер
------------------------------------------------------------
procedure Shutdown(Flags: DWORD);
var
  hToken: THandle;
  Luid: Int64;
  NewPrivileges: TTokenPrivileges;
  OldPrivileges: TTokenPrivileges;
  OldPrivilegesSize: DWORD;
begin
  if Win32Platform = VER_PLATFORM_WIN32_NT
  then // получения привилегий для платформы NT
  begin
      // получения локального уникального ИД
    Win32Check(LookupPrivilegeValue(nil, 'SeShutdownPrivilege', Luid));
      // получения токена процесса
    Win32Check(OpenProcessToken(GetCurrentProcess,
      TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken);
    NewPrivileges.PrivilegeCount := 1;
    NewPrivileges.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
    NewPrivileges.Privileges[0].Luid := Luid;
      // настройка привилегий
    AdjustTokenPrivileges(hToken,
      False,
      NewPrivileges,
      SizeOf(OldPrivileges),
      OldPrivileges,
      OldPrivilegesSize);
    try
      Win32Check(GetLastError = ERROR_SUCCESS);
    finally
      CloseHandle(hToken);
    end
  end;
  Win32Check(ExitWindowsEx(Flags, 0));
end;

Вызов: Shutdown(EWX_SHUTDOWN or EWX_POWEROFF);

Флаги можно комбинировать c помощью оператора OR
  EWX_FORCE    - принудительное выполнение операций, без сохранения данных.4
  EWX_LOGOFF   - выход из сеанса текущего пользователя;
  EWX_POWEROFF - выключение питания;
  EWX_REBOOT   - пеpезагpузка Windows;
  EWX_SHUTDOWN - выключение Windows, точка в которой безопасно выключать
питание.

В разработке темы приняли многие участники конференции, особая благодарность
Andrey Gusev <Andrey.Gusev@p11.f121.n5050.z2.fidonet.org> и Leonid
Troyanovsky <lv.t@eco-pro.ru>
===

Также можно использовать функцию InitiateSystemShutdown. С помощью данной
ф-и можно выключать/перезагружать и удаленные компьютеры в локальной сети.
Только в этом случае дополнительно необходимо иметь привилегию
SeRemoteShutdownPrivilege.
Бакланов Денис <dbacklanov@incon.ru>

------------------------------------------------------------
Q-163:  Куда пропали те или другие компоненты в Д7
------------------------------------------------------------
Последнее время часто задаются вопросы, куда девались те или другие
компоненты в Д7. Большинство из них некуда не девалось, а просто не
инсталлировано. Для инсталляции надо найти соответсвующий bpl файл в папке
BIN и проинсталлировать. По ряду компонент надо поискать readme, которые
могут находиться в других папках, например в DEMOS/

P.S. Если ктото приведет список bpl файлов, то статья будет дополнена данной
информацией.

Client/ServerSocket - delphi7\bin\dclsockets70.bpl
Quick Report - delphi7\bin\dclqrt70.bpl
TeeChart = delphi7\Bin\dcltqr70.bpl

Анатолий Подгорецкий
http://podgoretsky.com

------------------------------------------------------------
Q-164:  Время работы Windows
------------------------------------------------------------
//Возврат времени работы Windoes
// в формате TDateTime
function WindowsUptimeDays: TDateTime;
var
  lpPerformanceCount: Int64;
  lpFrequency: Int64;
begin
  if QueryPerformanceCounter(lpPerformanceCount) then
  begin
    QueryPerformanceFrequency(lpFrequency);
    // в отличие от GetTickCount будет работать более 49 суток
    Result := lpPerformanceCount / lpFrequency / SecsPerDay;
  end
  else
    // на случай, если нет мультимедийного таймера
    Resul t:= GetTickCount/MSecsPerDay;
end;

//Возврат времени работы Windoes
//в формате d, hh:mm:ss
function WindowsUptimeStr: string;
var
  DT: TDateTime;
begin
  DT := WindowsUptimeDays:
  Result := (Trunc(DT)) + ', ' + TimeToStr(DT);
end;

Вызов
S := WindowsUptimeToStr(WindowsUptime):

"Слава Сысолятин" <slava@magicbitsoft.com>

Секция 5 из 5 - Предыдущая - Следующая

Вернуться в раздел "Языки Pascal/Delphi" - Обсудить эту статью на Форуме
Главная - Поиск по сайту - О проекте - Форум - Обратная связь

© faqs.org.ru