Главная > Программирование > Языки 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" - Обсудить эту статью на Форуме |
Главная - Поиск по сайту - О проекте - Форум - Обратная связь |