Главная > Программирование > Языки Pascal/Delphi > |
RU.DELPHI FAQ |
Секция 4 из 5 - Предыдущая - Следующая
Все секции
- 1
- 2
- 3
- 4
- 5
Win32MajorVersion, Win32MinorVersion, Win32BuildNumber (в модуле SysUtils). Инициализируются они автоматически, остается только проверить их. Юрий Зотов -+++++++++++++++++++++++++++++ DA> Может комy известен способ отличить Windows 2000 Server от Wks? HKLM\System\CurrentControlSet\Control\ProductOptions ProductType:REG_SZ (WinNT - Prof, ServerNT - Server, LanmanNT - сервер и контроллер домена). Именно по этому ключику сама винда определяет. Это также относится и к NT4 (а может и ко всему остальному) ++++++++++++++++++++++++++++++ DA> Может комy известен способ отличить Windows 2000 Server от Wks? Для определения версии Windows используем API-функцию GetVersionEx(pOSVersionInfo), где pOSVersionInfo - указатель на структуру следующего вида: type TOSVersionInfoEx = record OsVersionInfoSize: DWORD; {Размер структуры типа TOSVersionInfo. Поле обязательно должно быть заполнено перед вызовом GetVersionEx} MajorVersion: DWORD; {основной номер версии ОС} MinorVersion: DWORD; {дополнительный номер версии ОС} BuildNumber: DWORD; {номер сборки ОС} PlatformId: DWORD; {Идентификатор платформы} CSDVersion: array [0..127] of char; {дополнительная текстовая информация об установленной операционной системе} //Далее идут поля, которые появились с выходом Windows 2000 ServicePackMajor: WORD; {основной номер service pack} ServicePackMinor: WORD; {дополнительный номер service pack} SuiteMask: WORD; {доступные программные пакеты; доступные значения: VER_SUITE_SMALLBUSINESS, VER_SUITE_ENTERPRICE, VER_SUITE_BACKOFFICE, VER_SUITE_COMUNICATIONS, VER_SUITE_TERMINAL,VER_SUITE_SMALLBUSINESS_RESTRICTED, VER_SUITE_EMBEDDEDNT,VER_SUITE_DATACENTER} ProductType: Byte; {вариант ОС; принимает значения: VER_NT_WORKSTATION, VER_NT_SERVER, VER_NT_DOMAIN_CONTROLLER} Reserved: Byte; {зарезервировано для будущих версий ОС} end; Значения полей SuiteMask и ProductType смотри в MSDN, поскольку в windows.pas, включая Delphi 7 описан старый вариант TOSVersionInfo (как с этим обстоят дела в Delphi .NET). Отсюда можно сделать вывод: или подправить windows.pas, или описывать самому приведенную выше структуру (обрати внимание, что я специально назвал ее TOSVersionInfoEx, чтобы не конфликтовать с TOSVersionInfo из windows.pas). Может в jvcl поправили данную структуру. Если ты уверен, что твой программный продукт будут использовать только на платформах версий Windows 2000 и старше (включая Windows CE), тогда поле CSDVersion объяви как массив WideChar и используй вызов API-функции GetVersionExW. Oleg Levkin <Oleg.Levkin@p6.f40.n5053.z2.fidonet.org> ------------------------------------------------------------ Q-115: Как помигать Scroll Lock? ------------------------------------------------------------ procedure TForm1.Timer1Timer(Sender: TObject); begin keybd_event(VK_SCROLL, 0, 0, 0); keybd_event(VK_SCROLL, 0, vk_up, 0); end; ++++++++++++++++++++++++++++ procedure TForm1.Timer1Timer(Sender: TObject); begin keybd_event(VK_SCROLL, MapVirtualKey(VK_SCROLL, 0) , 0, 0); keybd_event(VK_SCROLL, MapVirtualKey(VK_SCROLL, 0), vk_up, 0); end; Leonid Troyanovsky <lv.t@eco-pro.ru> ------------------------------------------------------------ Q-116: Как из dll узнать узнать полный путь к этой dll. ------------------------------------------------------------ function GetModuleFileNameStr(Instance: THandle): String; var buffer : array [0..MAX_PATH] of Char; begin GetModuleFileName( Instance, buffer, MAX_PATH); Result := buffer; end; GetModuleFileNameStr(Hinstance); // dll name GetModuleFileNameStr(0); // exe name Leonid Troyanovsky <lv.t@eco-pro.ru> ------------------------------------------------------------ Q-117: Как отобразить каталог? ------------------------------------------------------------ ListBox1.Perform(LB_DIR, 0, LParam(PChar('*.*'))); ------------------------------------------------------------ Q-118: Как узнать кол-во цветов цветовой палитры? ------------------------------------------------------------ function GetColorsCount : DWord; var DC : HDC; begin DC := GetDC( 0 ); Win32Check(DC <> 0); Result :=1 shl (GetDeviceCaps(DC, PLANES) * GetDeviceCaps(DC, BITSPIXEL)); ReleaseDC( 0, DC ); end; Leonid Troyanovsky <lv.t@eco-pro.ru> ------------------------------------------------------------ Q-119: Как ввести текст в "чужой" Edit? ------------------------------------------------------------ SendMessage(EditHandle, WM_SETTEXT, 0, LParam(PChar('MyText'))); ------------------------------------------------------------ Q-120: Как заставить мигать кнопку приложения на AppBar? ------------------------------------------------------------ procedure TForm1.Timer1Timer(Sender: TObject); begin FlashWindow(Application.Handle, True); end; Leonid Troyanovsky <lv.t@eco-pro.ru> ------------------------------------------------------------ Q-121: Как сделать программу без главной формы? ------------------------------------------------------------ program Project1; uses Dialogs; begin ShowMessage('Is there anybody out there ?' ); end. ------------------------------------------------------------ Q-122: Как убрать VerticalScrollBar из TListBox навсегда? ------------------------------------------------------------ procedure TListBoxForEver.CreateParams (var Params: TCreateParams); //override begin inherited CreateParams(Params); Params.Style := Params.Style and not WS_VSCROLL; end; Leonid Troyanovsky <lv.t@eco-pro.ru> ------------------------------------------------------------ Q-123: Как показать диалог выбора директории? ------------------------------------------------------------ из модуля FileCtrl. 1. function SelectDirectory(const Caption: string; const Root: WideString; out Directory: string): Boolean; overload; 2. function SelectDirectory(var Directory: string; Options: TSelectDirOpts; HelpCtx: Longint): Boolean; overload; из RxLib TDirectoryEdit function GetDirectory(nFolder: Longint): String; var Bi : TBrowseInfo; lpName: array [0..MAX_PATH] of Char; ppidl, aItemLst : PItemIDList; begin SHGetSpecialFolderLocation(Application.Handle, nFolder, ppidl); FillChar(Bi, SizeOf(bi), 0); Bi.hwndOwner := Application.Handle; Bi.pidlRoot := ppidl; Bi.pszDisplayName := lpName; Bi.lpszTitle := 'Open directory'; aItemLst := SHBrowseForFolder(Bi); CoTaskMemFree(ppidl); SHGetPathFromIDList(aItemLst, lpName); CoTaskMemFree(aItemLst); Result := lpName; end; Пример использования (иначе не поймут, что такое nFolder) // значения nFolder можно найти в описании // к SHGetSpecialFolderLocation // из Win32 Programmer's Reference (win32.hlp) procedure TForm1.Button1Click(Sender: TObject); begin Caption := GetDirectory(CSIDL_DRIVES); end; ------------------------------------------------------------ Q-124: Как убрать из ListView горизонтальный скролбар навсегда? ------------------------------------------------------------ type TNoHScrollListview = Class( TListview ) private Procedure WMNCCalcSize( Var msg: TMessage ); message WM_NCCALCSIZE; end; procedure TNoHScrollListview.WMNCCalcSize(var msg: TMessage); var style: Integer; begin style := getWindowLong( handle, GWL_STYLE ); If (style and WS_HSCROLL) <> 0 Then SetWindowLong( handle, GWL_STYLE, style and not WS_HSCROLL ); inherited; end; by Peter Below ------------------------------------------------------------ Q-125: Кaк искать oкнo по части eгo нaзвaния? ------------------------------------------------------------ function FindNextWnd(StartHWND: HWND; AString : String): HWND; var Buffer : array [0..255] of char; begin Result := StartHWND; repeat Result := FindWindowEx(0, Result, nil, nil); GetWindowText(Result, Buffer, SizeOf(Buffer)); if StrPos(StrUpper(Buffer), PChar(UpperCase(AString))) <> nil then Break; until (Result = 0); end; ------------------------------------------------------------ Q-126: Как обнаружить активность юзера? ------------------------------------------------------------ Application.OnMessage := DoMessageEvent; procedure TForm1.DoMessageEvent ( var Msg: TMsg; var Handled: Boolean); begin case Msg.message of WM_KEYFIRST..WM_KEYLAST, WM_MOUSEFIRST..WM_MOUSELAST: {Произошли события клавиатуры и мыши}; .. end; end; Leonid Troyanovsky <lv.t@eco-pro.ru> ------------------------------------------------------------ Q-127: Как yзнать текущую Ru/En pаскладкy клавиатypы? ------------------------------------------------------------ GetKeyboardLayoutName(buffer{:array [0..KL_NAMELENGTH] of Char}); case ((StrToInt('$'+ Buffer)) and $03FF) of LANG_ENGLISH: Caption := 'Eng'; LANG_RUSSIAN: Caption := 'Rus'; end; ++++++++++++++++++++++++++++ procedure TForm1.Button1Click(Sender: TObject); var AklName: array [0..2] of Char; begin GetLocaleInfo( LoWord(GetKeyboardLayout(0)), LOCALE_SABBREVLANGNAME, AklName, SizeOf(AklName)); Caption := AklName; end; Leonid Troyanovsky <lv.t@eco-pro.ru> ------------------------------------------------------------ Q-128: Как передать строку другому приложению? ------------------------------------------------------------ получатель: procedure ReceiveMessage (var Msg: TMessage); message WM_COPYDATA; ... procedure TFormReceive.ReceiveMessage; var pcd : PCopyDataStruct; begin pcd := PCopyDataStruct(Msg.LParam); Caption := PChar(pcd.lpData); end; отправитель: procedure TFormXXX.Button1Click(Sender: TObject); var cd : TCopyDataStruct; begin cd.cbData := Length(Edit1.Text)+1; cd.lpData := PChar(Edit1.Text); SendMessage ( FindWindow('TFormReceive', nil), WM_COPYDATA, 0, LParam(@cd)); end; Leonid Troyanovsky <lv.t@eco-pro.ru> ------------------------------------------------------------ Q-129: Как RichEdit сделать скролл на конец текста? ------------------------------------------------------------ with RichEdit do begin SelLength := 0; SelStart := Length(Text); Perform(EM_SCROLLCARET,0,0); end; ------------------------------------------------------------ Q-130: Удаление файлов из временного каталога, безопасно ли? ------------------------------------------------------------ При получении имени папки предназначенной для хранения временных файлов могут возникнуть некоторые проблемы. >> Прекрасно это выглядит, когда в качестве каталога временных файлов >> назначен например C:\Windows > :-) Я и говорю что небезопасно. Особенно пикантно это выглядит, в свете того, что Remarks Windows 95/98/Me: The GetTempPath function gets the temporary file path as follows: The path specified by the TMP environment variable. The path specified by the TEMP environment variable, if TMP is not defined or if TMP specifies a directory that does not exist. The current directory, if both TMP and TEMP are not defined or specify nonexistent directories. Этак переименовываешь C:\TEMP - и программа чистит текущий каталог :-) Windows NT/2000 or later: The GetTempPath function does not verify that the directory specified by the TMP or TEMP environment variables exists. The function gets the temporary file path as follows: The path specified by the TMP environment variable. The path specified by the TEMP environment variable, if TMP is not defined. The Windows directory, if both TMP and TEMP are not defined. Этак удаляешь переменные окружения - и программа "деинсталлирует" Windows Из этого вытекает следующее, удаление файлов из любого каталога, особенно из временного чрезвычайно опасная операция, не ты создал - не трогай. Удалять только ручками, глядя на файлы и принимая решения индивидуально по каждому файлу. При использовании функции GetTempPath проверить если подстрока TEMP в результате и в случае отсутствия вхождения запросить пользователя для принятия решения, с рекомендацией создать каталог TEMP и необходимые переменные среды, лучше посоветоваться обратиться к администратору для принятия решения. Это простое правило позволит избежать серьезных последствий. Тенцер А.Л. <tolik@katren.nsk.ru> Andrew V. Fionik <fionika@chat.ru> Anatoly Podgoretsky <anatoly@podgoretsky.com> ------------------------------------------------------------ Q-131: Как узнать состояние управляющих клавиш - Shift, Ctrl, Alt? ------------------------------------------------------------ function IsKeyDown(vk: Word):Boolean; begin Result := GetKeyState(vk) and $8000 = $8000; end; vk для Ctrl, Shift, Alt соответственно равны: vk_control, vk_shift и vk_menu ------------------------------------------------------------ Q-132: Как сохранить всю форму в файл (как Delphi в *.dfm)? ------------------------------------------------------------ constructor TForm1.Create(AOwner: TComponent); // override; var fname: String; begin { Для динамически создаваемых контролов, может требоваться RegisterClasses(..); } fname := FormFilename; if FileExists( fname ) then begin CreateNew(AOwner); ReadComponentResFile(fname, Self); end else inherited Create( AOwner ); end; procedure TForm1.FormCloseQuery( Sender: TObject; var CanClose: Boolean); begin WriteComponentResFile(FormFileName, Self); end; {Peter Below, Vladimir Titov} ------------------------------------------------------------ Q-133: Как контрол может сам себя разрушить? ------------------------------------------------------------ TMyWinControl = class(TWinControl) private procedure WMuser1(var msg: TMessage); message WM_USER+1; ... public procedure Release; ... end; procedure TMyWinControl.WMuser1; begin Free; end; procedure TMyWinControl.Release; begin PostMessage(Handle, WM_USER+1, 0, 0); end; ------------------------------------------------------------ Q-134: Как отследить переход фокуса в приложении? ------------------------------------------------------------ procedure TForm1.AppControlChange(Sender: TObject); begin if Sender is TScreen then Caption := TScreen(Sender).ActiveForm.ActiveControl.Name; end; procedure TForm1.FormCreate(Sender: TObject); begin Screen.OnActiveControlChange := AppControlChange; end; Leonid Troyanovsky <lv.t@eco-pro.ru> ------------------------------------------------------------ Q-135: Как заставить MediaPlayer крутить один и тот же клип? ------------------------------------------------------------ procedure TForm1.WMUser1(var msg:TMessage);// message WM_USER+1; begin with MediaPlayer1 do begin Previous; Notify := True; Play; end; end; procedure TForm1.MediaPlayer1Notify(Sender: TObject); begin if (Sender as TMediaPlayer).NotifyValue = nvSuccessful then PostMessage(Handle, WM_USER+1, 0, 0); end; ------------------------------------------------------------ Q-136: Как назначить процедуру собственному пункту системного меню? ------------------------------------------------------------ const cm_mycommand = $00A0; procedure TForm1.FormCreate(Sender: TObject); var HSysMenu: HMENU; begin HSysMenu:=GetSystemMenu(Handle,FALSE); InsertMenu( HSysMenu, 0, MF_BYPOSITION or MF_STRING, cm_mycommand, 'MyString'); end; procedure TForm1.WMSysCommand (var Message: TWMSysCommand); // message WM_SYSCOMMAND; begin case Message.CmdType of cm_mycommand: ShowMessage('My Command'); else inherited; end; end; Leonid Troyanovsky <lv.t@eco-pro.ru> ------------------------------------------------------------ Q-137: Какой класс окна у консоли? ------------------------------------------------------------ 'tty' for 9x 'ConsoleWindowClass' for NT ------------------------------------------------------------ Q-138: Какое сообщение надо отлавливать в Application.OnMessage для отслеживания клавиши Alt (vk_menu) ------------------------------------------------------------ WM_SYSKEYDOWN/WM_SYSKEYUP ------------------------------------------------------------ Q-139: Как спрятать контрол, если известен его Handle? ------------------------------------------------------------ ShowWindow(ButtonHandle, SW_HIDE); // SW_SHOW ------------------------------------------------------------ Q-140: Как поменять иконку и стpокy в заголовке консольного окна? ------------------------------------------------------------ procedure TForm1.Button1Click(Sender: TObject); var h : HWND; AIcon : TIcon; begin AllocConsole; SetConsoleTitle(PChar('Console Title')); Sleep(0); h := FindWindow(nil, PChar('Console Title')); AIcon := TIcon.Create; ImageList1.GetIcon(0, AIcon); SendMessage(h, WM_SETICON, 1, AIcon.Handle); AIcon.Free; end; Leonid Troyanovsky <lv.t@eco-pro.ru> ------------------------------------------------------------ Q-141: Как сделать окно без VCL? ------------------------------------------------------------ program Project1; { Copyright (c) 1996 by Charlie Calvert Standard Windows API application written in Object Pascal. No VCL code included. This is all done on the Windows API level. Note that you need to include both Windows and Messages!} uses Windows, Messages; const AppName = 'Window1'; function WindowProc(Window: HWnd; AMessage, WParam, LParam: Longint): Longint; stdcall; begin WindowProc := 0; case AMessage of wm_Destroy: begin PostQuitMessage(0); Exit; end; end; WindowProc := DefWindowProc(Window, AMessage, WParam, LParam); end; { Register the Window Class } function WinRegister: Boolean; var WindowClass: TWndClass; begin WindowClass.Style := cs_hRedraw or cs_vRedraw; WindowClass.lpfnWndProc := @WindowProc; WindowClass.cbClsExtra := 0; WindowClass.cbWndExtra := 0; WindowClass.hInstance := HInstance; WindowClass.hIcon := LoadIcon(0, idi_Application); WindowClass.hCursor := LoadCursor(0, idc_Arrow); WindowClass.hbrBackground := HBrush(Color_Window); WindowClass.lpszMenuName := nil; WindowClass.lpszClassName := AppName; Result := RegisterClass(WindowClass) <> 0; end; { Create the Window Class } function WinCreate: HWnd; var hWindow: HWnd; begin hWindow := CreateWindow(AppName, 'Object Pascal Window', ws_OverlappedWindow, cw_UseDefault, cw_UseDefault, cw_UseDefault, cw_UseDefault, 0, 0, HInstance, nil); if hWindow <> 0 then begin ShowWindow(hWindow, CmdShow); UpdateWindow(hWindow); end; Result := hWindow; end; var AMessage: TMsg; hWindow: HWnd; begin if not WinRegister then begin MessageBox(0, 'Register failed', nil, mb_Ok); Exit; end; hWindow := WinCreate; if hWindow = 0 then begin MessageBox(0, 'WinCreate failed', nil, mb_Ok); Exit; end; while GetMessage(AMessage, 0, 0, 0) do begin TranslateMessage(AMessage); DispatchMessage(AMessage); end; Halt(AMessage.wParam); end. ------------------------------------------------------------ Q-142: Как избежать повторного запуска моего приложения? ------------------------------------------------------------ type TForm1 = class(TForm) Memo1: TMemo; procedure FormCreate(Sender: TObject); private { Private declarations } procedure WMCopyData(var msg: TMessage); message WM_COPYDATA; public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} uses checkinst; procedure TForm1.FormCreate(Sender: TObject); var h : HWND; begin h := SetUniqueUID(Handle, 123456); // назначаем уникальный идентификатор if h <> Handle then begin SendString(h, GetCommandLineStr, Handle, 0); ActivatePrevInstance(h); Halt; end; end; procedure TForm1.WMCopyData; begin Memo1.Lines.CommaText := PChar(PCopyDataStruct(msg.LParam).lpData); end; --------------------------checkinst.pas------------------------- unit checkinst; interface uses Windows, Messages, Sysutils; function SetUniqueUID(ahwnd: HWND; uid: DWord): HWND; procedure ActivatePrevInstance(ahwnd: HWND); procedure SendString(ahwnd:HWND; const s: String; aWParam: WParam; dwData:DWord); function GetCommandLineStr: String; implementation function SetUniqueUID(ahwnd: HWND; uid: DWord): HWND; var ClassName: array [0..255] of Char; begin GetClassName(ahwnd, ClassName, SizeOf(classname)); Result := FindWindowEx(0, 0, ClassName, nil); while (Result <> 0) do if GetProp(Result, 'UID') = uid then Exit else Result := FindWindowEx(0, Result, ClassName, nil); SetProp(ahwnd, 'UID', uid); Result := ahwnd; end; procedure ActivatePrevInstance(ahwnd: HWND); var h : HWND; begin h := GetWindowLong(ahwnd, GWL_HWNDPARENT); if IsIconic(h) then ShowWindow(h, SW_RESTORE); SetForegroundWindow(h); end; procedure SendString(ahwnd:HWND; const s: String; aWParam: WParam; dwData:DWord); var cds: TCopyDataStruct; begin cds.cbData := Length(s)+1; cds.lpData := Pointer(s); cds.dwData := dwData; SendMessage(ahwnd, WM_COPYDATA, aWParam, LParam(@cds)); end; function GetCommandLineStr: String; var i : Integer; begin for i := 0 to ParamCount do Result := Result + ' ' + AnsiQuotedStr(ParamStr(i), '"'); end; -------------------------EOF checkinst.pas--------------------- Leonid Troyanovsky <lv.t@eco-pro.ru> ++++++++++++++++++++++++++++++++++++ === Вариант с Мьютексом === В файле проекта (.dpr) прямо можешь написать нечто вроде: uses windows,... var H: THandle; begin H := CreateMutex(nil, True, 'уникальное_имя_для_твоей_проги'); if GetLastError = ERROR_ALREADY_EXISTS then begin H := FindWindow(nil, 'название заголовка окна программы'); SetForegroundWindow(H); Exit; end; Application.Initialize; Application.Title := 'название заголовка окна программы'; Application.CreateForm(TAppData, AppData); Application.CreateForm(TMain, Main); Application.Run; CloseHandle(H); end; Прочко Денис Владимирович. sysadmin@)farmeko.khv.ru ++++++++++++++++++++++++++++++++++++ Если быстро запустить дважды приложение, то вариант с поиском по классу окна может не сработать, так как окно еще не успеет создаться Анатолий Подгорецкий ------------------------------------------------------------ Q-143: Как записать массив в файл? ------------------------------------------------------------ with TFileStream.Create('array.dat', fmCreate or fmOpenWrite) do begin WriteBuffer(a, SizeOf(a)); Free; end; ------------------------------------------------------------ Q-144: Delphi 6 требует Proxies.pas? ------------------------------------------------------------ {$ifdef D_6_UP} // Это моя константа DesignIntf, DesignEditors, DesignWindows, DsnConst, {$else} DsgnIntf, {$endif} Eugene Mayevski <mayevski@eldos.org> ------------------------------------ Вопрос: Файл designeditors.pas использует 'proxies' в uses. Исходный текст (proxies.pas) или откомпилированный модуль (proxies.dcu) нигде не находится ни на моем жеском диске ни на D6 Pro CD.. Просто реорганизуйте ваш проект на использование runtime пакетов и добавьте "DesignIDE" к вашемк списку runtime пакетов. Proxies находится здесь, и вам не нужен исходный текст вообще. Почему это сделано? Просто доя уверенности, что вы не сможете распространять design time части (property editors, component editors), это запрещено по личензии. DesignIDE.bpl не является свободно распространяемым, вы имеете право использовать его только на машине на которой установлена Delphi, подобно Component libraries. forums.borland.com ------------------------------------------------------------ Q-145: О библиотеке RxLib ------------------------------------------------------------ На сайте delphiplus.org в разделе Бесплатно|RXLibrary (http://delphiplus.spils.lv/RXLibrary.html) лежит RX Library 2.75 с help'ами и четырьмя неофициальными портами RX Library 2.75 под Delphi 6: 1. Версия 1.1 (1.18M) от Oxygen Software 2. Версия 1 (1.36M) от Dennis Ortiz 3. Патч на RxLib версия 1.5 (437K) от Polaris Software 4. Версия от Epsylon Technologies Anatoly Podgoretsky wrote: > > Hi, Delphi Plus! > You wrote to Anatoly Podgoretsky on Tue, 20 Nov 2001 16:00:55 +0000 (UTC): > DP>> 14.11.2001 в раздел "Бесплатно|Компоненты" выложен четвертый DP>> неофициальный порт RX Library 2.75 под Delphi 6 (от Epsylon DP>> Technologies). > DP>> http://www.delphiplus.org - ежедневные новости информационных DP>> технологий http://www.faq.delphiplus.org - коллекция FAQ по Delphi > > Прекрасно, этим я больше доверяю, а как вообще насчет характеристики всех > четырех портов, а то у людей глаза разбегаются :-) Epsylon Technologies ************************* Здравствуйте! Мы были вынуждены сделать свой вариант RxLib потому, что остальные нас немного не устраивали. Сразу скажу, зачем нам вообще нужна библиотека RxLib - она используется в нашем продукте в качестве некоего примера всем известных компонентов. Поэтому к такой библиотеке с нашей стороны предъявлялось требование максимальной стандартности, если можно применить такой термин. Кроме того, наш продукт поддерживает несколько версий Delphi и C++Builder, поэтому от такой библиотеки требуется одновременная поддержка всех нужных нам версий компиляторов. Естественно, мы рассматривали варианты использования уже готовой работы по адаптированию библиотеки под Delphi 6.0. Однако: - вариант от Polaris заточен для использования пакета Polaris Library. Туда что-то добавлено, что-то починено, что-то переделано. Иначе говоря, этот вариант не может быть стандартным; - вариант от Oxygen является версией ТОЛЬКО под Delphi 6.0, содержит ряд мелких неточностей при переводе design-time кода. Также там что-то изменено по сравнению с 2.75. Кроме того, не переименован модуль AppUtils.pas; - вариант от Dennis Ortiz также является версией только под Delphi 6.0. Ничего не могу сказать про нее - мы туда глубоко не заглядывали. Не совсем понятно, зачем выкидывать из библиотеки возможность поддержки предыдущих версий Delphi, когда добавить вариант кода для Delphi 6.0 ничуть не сложнее. Никто также не против исправления каких-либо ошибок в библиотеке, но давайте делать это централизованно, если уж авторы забили на свое детище. Например, через тот же Source Forge. Наш вариант основан на общедоступном коде, и содержит модули из 2.75, включая update от 16.12.1999 и патч для C+Builder 5.0 от 30.05.2000. В эти модули добавлена возможность работы под Delphi 6.0, в том числе добавлен макрос RX_D6 и переименованы модули AppUtils и StrUtils. Все. Ничего больше. Никакая старая функциональность не удалена, никакие баги не чинились. Полдня работы. == Andrey Dementyev, Epsylon Technologies, http://www.epsylontech.com Chief Software Architect Информация от delphiplus ******************************** 1. C 19-ого декабря компания SGB Software совместно с Ником Ходж (Nick Hodges) из Borland support team займется дальнейшим развитием RxLib. Надеются выпустить 3-ю версию к середине марта 2002 года. Все желающие могут принять участие в этой работе, для этого достаточно написать на RxLIb@SGBSoftware.com. 2. На DelphiPlus выложен материал "A где сейчас RXLib?" - заметка написанная по материалам переписки в эхе fido7.ru.delphi. Наконец эта история получила завершение, афера SGB Software лопнула, но RXLib не погибла, а вошла в состав более крупного проекта Jedi Code Library, за эти руки нет опасения, все подробности на сайте delphiplus.org, благодаря которому мы были постянно в курсе событий всех приключений с RXLib, спасибо. ------------------------------------------------------------ Q-146: Как хранить настройки программ. ------------------------------------------------------------ Нижеприведенный текст являет собой вольное изложение отдельных статей февральского выпуска Microsoft Platform SDK. Год 2001 от рождества Христова. При проектировании способов хранения настроек своей программы следует задаться тремя вопросами: Что хранить. Где хранить. Как хранить. Что хранить Поскольку первая часть вопроса нам известна по определению, т.е. хранить мы будем настройки программы, то перейдем ко второй части вопроса. Ваша программа устанавливается на КОМПЬЮТЕР а пользуются ей ПОЛЬЗОВАТЕЛИ. Соответственно все настройки разделяются на две части а то и на все три - настройки которые относятся к компьютеру в целом, настройки которые относятся ко всем локальным пользователям, настройки которые относятся к конкретному пользовател. В зависимости от специфики программы первая и вторая часть могут быть совмещены или разделены. Поэтому важно сделать логическое разделение - какие настройки вашей программы действительно специфичны для самого ПК, какие настройки должны прилагаться ко всем пользователям, какие должны прилагаться к конкретному пользователю. Кроме того Микрософт рекомендует чтобы настройки учитывали возможную мобильность пользователя, т.е. для пользователя находящегося в разных местах, возможно потребуется иметь разные наборы настроек. Где хранить Вообще в голову приходят три вещи. Хранить настройки в системном реестре. Хранить настройки в каталоге куда установлена программа. Хранить настройки в системном каталоге Windows. Хранить настройка в домашнем каталоге пользователя. В Windows имеется три места предназначенных для хранения настроек которыми и следует пользоваться. Системный реестр Домашний каталог пользователя (точнее один из его подкаталогов) Общий каталог для пользователей Прочие мысли о местах хранения настроек должны быть выброшены из голов как вредные и противоестественные, Microsoft уже за вас все придумала и нефиг извращаться. Для тех кто не понимает почему, объясняю. На нормальной ОС (W'NT, W'2K) программа обычно запускается от имени и с правами конкретного пользователя. Обычно, если этот пользователь не является администратором, он имеет право изменять содержимое следующих ресурсов: часть реестра HKEY_CURRENT_USER\* содержимое своего домашнего каталога содержимое временного каталога (который как правило находится внутри домашнего) содержимое некого каталога или каталогов специально выделенного для этого администратором При нормальном (читайте параноидальном) администрировании системы прочие места либо доступны только в режиме чтения, либо вообще недоступны. В том числе и папки \Program Files и Windows. Посему любая попытка программы изменять любые файловые ресурсы окромя вышеуказанных черевата тем что ее (программу) и его (пользователя) пошлют подальше. Причем далеко не в самой вежливой форме. Пример Adobe Photoshop и его разработчики наивно полагают что им должны быть выданы эксклюзивные права мусорить своими scratch-файлами в корневых каталогах дисков, кроме того они полагают что им должна быть выдана в пользование в режиме полный доступ часть системного реестра.. Временных каталогов, специально выделенных для подобоного рода занятий, их не устраивает. Как результат - Photoshop имеет серьезные проблемы с работой под Windows NT/2000. Системный реестр С точки зрения хранения настроек программы системный реестр разделен на две
Секция 4 из 5 - Предыдущая - Следующая
Вернуться в раздел "Языки Pascal/Delphi" - Обсудить эту статью на Форуме |
Главная - Поиск по сайту - О проекте - Форум - Обратная связь |