Секция 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 - Предыдущая - Следующая
© faqs.org.ru