Форум программистов, компьютерный форум, киберфорум
Delphi
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
61 / 51 / 25
Регистрация: 17.12.2013
Сообщений: 255
RAD XE3+

Компонент на базе TINIFIle - NSSettings

16.03.2019, 16:10. Показов 2177. Ответов 5

Студворк — интернет-сервис помощи студентам
Предлагаю сообществу простенький но удобный компонент.
Все знают что такое TINIFile и все его прелести.
Но также все знают, что в каждом проекте для сохранения и применения шаблонных настроек приложения (например положение окна на экране, его размер и состояние) приходится писать один и тот же код.
Кто-то выносит этот код в отдельные юниты, кто-то копипастит его из проекта в проект, кто-то (упаси бог) пишет все руками каждый раз.
Я решил написать компонент на основе TINIFile, который достаточно кинуть на форму и состояние окна приложения будет сохранено при остановке и восстановлено при запуске.
Так же сохранены все основные методы TINIFile.
Описание свойств в инспекторе объектов
FileName - имя ini файла, в котором сохраняются параметры, если оставить пустым, то компонент создаст файл в папке с исполняемым файлом проекта, таким же именем и расширением ini, по умолчанию пустая строка.
LoadWindowState - флаги, указывающие какие параметры формы восстанавливать при загрузке, [lwsTop, lwsLeft, lwsWidth, lwsHeight, lwsMaximized] - тут я думаю все ясно.
Name - идентификатор объекта.
SaveLastClose - записывать время и дату остановки приложения, по умолчанию включено, параметр в ini LastClose.
SaveLastRun - записывать время и дату запуска приложения, по умолчанию включено, параметр в ini LastRun.
SaveWindowStates - записывать состояние окна приложения, по умолчанию включено, параметры в ini WindowState, Top, Left, Width, Height. Параметры те же, что и соответствующие свойства родительской TForm компонента.
-- Компонент создает раздел [Window] в ini файле и все эти параметры пишет в него.
-- Дабы восстановление состояния окна работало, необходимо, что бы у формы было Position := poDefault
У компонента нет никаких событий.
Перечисление методов RunTime
Все методы идентичны методам TIniFile.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    function SectionExists(const Section: string): Boolean;
    function ReadString(const Section, Ident, Default: string): string;
    procedure WriteString(const Section, Ident, Value: String);
    function ReadInteger(const Section, Ident: string; Default: Integer): Integer;
    procedure WriteInteger(const Section, Ident: string; Value: Integer);
    function ReadBool(const Section, Ident: string; Default: Boolean): Boolean;
    procedure WriteBool(const Section, Ident: string; Value: Boolean);
    function ReadBinaryStream(const Section, Name: string; Value: TStream): Integer;
    function ReadDate(const Section, Name: string; Default: TDateTime): TDateTime;
    function ReadDateTime(const Section, Name: string; Default: TDateTime): TDateTime;
    function ReadFloat(const Section, Name: string; Default: Double): Double;
    function ReadTime(const Section, Name: string; Default: TDateTime): TDateTime;
    procedure WriteBinaryStream(const Section, Name: string; Value: TStream);
    procedure WriteDate(const Section, Name: string; Value: TDateTime);
    procedure WriteDateTime(const Section, Name: string; Value: TDateTime);
    procedure WriteFloat(const Section, Name: string; Value: Double);
    procedure WriteTime(const Section, Name: string; Value: TDateTime);
    procedure ReadSection(const Section: string; Strings: TStrings); virtual;
    procedure ReadSections(const Section: string; Strings: TStrings);
    procedure ReadSubSections(const Section: string; Strings: TStrings; Recurse: Boolean = False);
    procedure ReadSectionValues(const Section: string; Strings: TStrings);
    procedure EraseSection(const Section: string);
    procedure DeleteKey(const Section, Ident: String);
    function ValueExists(const Section, Ident: string): Boolean;
    constructor Create(AOwner: TComponent); override;
Полный код компонента
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
{Создано KMSNasgool}
 
unit NSSettings;
 
interface
 
uses
  System.SysUtils, System.Classes, Vcl.Forms, System.IniFiles;
 
type
  TTL = (lwsTop, lwsLeft, lwsWidth, lwsHeight, lwsMaximized);
  TLoadWindowState = set of TTL;
 
  TNSSettings = class(TComponent)
  private
    { Private declarations }
    FSaveWindowStates: Boolean;
    FSaveLastRun: Boolean;
    FSaveLastClose: Boolean;
    FLoadWindowState: TLoadWindowState;
    FFileName: string;
  protected
    { Protected declarations }
    procedure Loaded; override;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  public
    { Public declarations }
    function SectionExists(const Section: string): Boolean;
    function ReadString(const Section, Ident, Default: string): string;
    procedure WriteString(const Section, Ident, Value: String);
    function ReadInteger(const Section, Ident: string; Default: Integer): Integer;
    procedure WriteInteger(const Section, Ident: string; Value: Integer);
    function ReadBool(const Section, Ident: string; Default: Boolean): Boolean;
    procedure WriteBool(const Section, Ident: string; Value: Boolean);
    function ReadBinaryStream(const Section, Name: string; Value: TStream): Integer;
    function ReadDate(const Section, Name: string; Default: TDateTime): TDateTime;
    function ReadDateTime(const Section, Name: string; Default: TDateTime): TDateTime;
    function ReadFloat(const Section, Name: string; Default: Double): Double;
    function ReadTime(const Section, Name: string; Default: TDateTime): TDateTime;
    procedure WriteBinaryStream(const Section, Name: string; Value: TStream);
    procedure WriteDate(const Section, Name: string; Value: TDateTime);
    procedure WriteDateTime(const Section, Name: string; Value: TDateTime);
    procedure WriteFloat(const Section, Name: string; Value: Double);
    procedure WriteTime(const Section, Name: string; Value: TDateTime);
    procedure ReadSection(const Section: string; Strings: TStrings); virtual;
    procedure ReadSections(const Section: string; Strings: TStrings);
    procedure ReadSubSections(const Section: string; Strings: TStrings; Recurse: Boolean = False);
    procedure ReadSectionValues(const Section: string; Strings: TStrings);
    procedure EraseSection(const Section: string);
    procedure DeleteKey(const Section, Ident: String);
    function ValueExists(const Section, Ident: string): Boolean;
    constructor Create(AOwner: TComponent); override;
  published
    { Published declarations }
    property SaveWindowStates: Boolean read FSaveWindowStates write FSaveWindowStates default True;
    property SaveLastRun: Boolean read FSaveLastRun write FSaveLastRun default True;
    property SaveLastClose: Boolean read FSaveLastClose write FSaveLastClose default True;
    property LoadWindowState: TLoadWindowState read FLoadWindowState write FLoadWindowState default [lwsTop, lwsLeft, lwsWidth, lwsHeight, lwsMaximized];
    property FileName: string read FFileName write FFileName;
  end;
 
procedure Register;
 
implementation
 
procedure Register;
begin
  RegisterComponents('Nasgool Soft', [TNSSettings]);
end;
 
{ TNSSettings }
 
constructor TNSSettings.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FSaveWindowStates := True;
  FSaveLastRun := True;
  FSaveLastClose := True;
  FLoadWindowState := [lwsTop, lwsLeft, lwsWidth, lwsHeight, lwsMaximized];
  if csDesigning in ComponentState then Exit;
  FreeNotification(AOwner);
end;
 
procedure TNSSettings.DeleteKey(const Section, Ident: String);
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  AIniFile.DeleteKey(Section, Ident);
  AIniFile.Free;
end;
 
procedure TNSSettings.EraseSection(const Section: string);
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  AIniFile.EraseSection(Section);
  AIniFile.Free;
end;
 
procedure TNSSettings.Loaded;
var
  AIniFile: TIniFile;
begin
  inherited Loaded;
  if csDesigning in ComponentState then Exit;
  if FFileName = '' then FFileName := ExtractFilePath(Application.ExeName) + Copy(ExtractFileName(Application.ExeName), 1, Length(ExtractFileName(Application.ExeName)) - 4) + '.ini';
  AIniFile := TIniFile.Create(FFileName);
  if FSaveLastRun then AIniFile.WriteDateTime('Window', 'LastRun', Now);
  if lwsTop in FLoadWindowState then (Owner as TForm).Top := AIniFile.ReadInteger('Window', 'Top', (Owner as TForm).Top);
  if lwsLeft in FLoadWindowState then (Owner as TForm).Left := AIniFile.ReadInteger('Window', 'Left', (Owner as TForm).Left);
  if lwsWidth in FLoadWindowState then (Owner as TForm).Width := AIniFile.ReadInteger('Window', 'Width', (Owner as TForm).Width);
  if lwsHeight in FLoadWindowState then (Owner as TForm).Height := AIniFile.ReadInteger('Window', 'Height', (Owner as TForm).Height);
  if (lwsMaximized in FLoadWindowState) and (TWindowState(AIniFile.ReadInteger('Window', 'WindowState', Integer((Owner as TForm).WindowState))) = wsMaximized) then (Owner as TForm).WindowState := wsMaximized;
  AIniFile.Free;
end;
 
procedure TNSSettings.Notification(AComponent: TComponent;
  Operation: TOperation);
var
  AIniFile: TIniFile;
begin
  inherited Notification(AComponent, Operation);
  if (csDesigning in ComponentState) or (AComponent <> Owner) or (Operation <> opRemove) then Exit;
  AIniFile := TIniFile.Create(FFileName);
  if FSaveWindowStates then begin
    AIniFile.WriteInteger('Window', 'WindowState', Integer((Owner as TForm).WindowState));
    (Owner as TForm).WindowState := wsNormal;
    AIniFile.WriteInteger('Window', 'Top', (Owner as TForm).Top);
    AIniFile.WriteInteger('Window', 'Left', (Owner as TForm).Left);
    AIniFile.WriteInteger('Window', 'Width', (Owner as TForm).Width);
    AIniFile.WriteInteger('Window', 'Height', (Owner as TForm).Height);
  end;
  if FSaveLastClose then AIniFile.WriteDateTime('Window', 'LastClose', Now);
  AIniFile.Free;
end;
 
function TNSSettings.ReadBinaryStream(const Section, Name: string;
  Value: TStream): Integer;
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  Result := AIniFile.ReadBinaryStream(Section, Name, Value);
  AIniFile.Free;
end;
 
function TNSSettings.ReadBool(const Section, Ident: string;
  Default: Boolean): Boolean;
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  Result := AIniFile.ReadBool(Section, Ident, Default);
  AIniFile.Free;
end;
 
function TNSSettings.ReadDate(const Section, Name: string;
  Default: TDateTime): TDateTime;
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  Result := AIniFile.ReadDate(Section, Name, Default);
  AIniFile.Free;
end;
 
function TNSSettings.ReadDateTime(const Section, Name: string;
  Default: TDateTime): TDateTime;
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  Result := AIniFile.ReadDateTime(Section, Name, Default);
  AIniFile.Free;
end;
 
function TNSSettings.ReadFloat(const Section, Name: string;
  Default: Double): Double;
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  Result := AIniFile.ReadFloat(Section, Name, Default);
  AIniFile.Free;
end;
 
function TNSSettings.ReadInteger(const Section, Ident: string;
  Default: Integer): Integer;
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  Result := AIniFile.ReadInteger(Section, Ident, Default);
  AIniFile.Free;
end;
 
procedure TNSSettings.ReadSection(const Section: string; Strings: TStrings);
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  AIniFile.ReadSection(Section, Strings);
  AIniFile.Free;
end;
 
procedure TNSSettings.ReadSections(const Section: string; Strings: TStrings);
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  AIniFile.ReadSections(Section, Strings);
  AIniFile.Free;
end;
 
procedure TNSSettings.ReadSectionValues(const Section: string;
  Strings: TStrings);
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  AIniFile.ReadSectionValues(Section, Strings);
  AIniFile.Free;
end;
 
function TNSSettings.ReadString(const Section, Ident, Default: string): string;
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  Result := AIniFile.ReadString(Section, Ident, Default);
  AIniFile.Free;
end;
 
procedure TNSSettings.ReadSubSections(const Section: string; Strings: TStrings;
  Recurse: Boolean);
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  AIniFile.ReadSubSections(Section, Strings, Recurse);
  AIniFile.Free;
end;
 
function TNSSettings.ReadTime(const Section, Name: string;
  Default: TDateTime): TDateTime;
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  Result := AIniFile.ReadTime(Section, Name, Default);
  AIniFile.Free;
end;
 
function TNSSettings.SectionExists(const Section: string): Boolean;
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  Result := AIniFile.SectionExists(Section);
  AIniFile.Free;
end;
 
function TNSSettings.ValueExists(const Section, Ident: string): Boolean;
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  Result := AIniFile.ValueExists(Section, Ident);
  AIniFile.Free;
end;
 
procedure TNSSettings.WriteBinaryStream(const Section, Name: string;
  Value: TStream);
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  AIniFile.WriteBinaryStream(Section, Name, Value);
  AIniFile.Free;
end;
 
procedure TNSSettings.WriteBool(const Section, Ident: string; Value: Boolean);
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  AIniFile.WriteBool(Section, Ident, Value);
  AIniFile.Free;
end;
 
procedure TNSSettings.WriteDate(const Section, Name: string; Value: TDateTime);
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  AIniFile.WriteDate(Section, Name, Value);
  AIniFile.Free;
end;
 
procedure TNSSettings.WriteDateTime(const Section, Name: string;
  Value: TDateTime);
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  AIniFile.WriteDateTime(Section, Name, Value);
  AIniFile.Free;
end;
 
procedure TNSSettings.WriteFloat(const Section, Name: string; Value: Double);
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  AIniFile.WriteFloat(Section, Name, Value);
  AIniFile.Free;
end;
 
procedure TNSSettings.WriteInteger(const Section, Ident: string;
  Value: Integer);
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  AIniFile.WriteInteger(Section, Ident, Value);
  AIniFile.Free;
end;
 
procedure TNSSettings.WriteString(const Section, Ident, Value: String);
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  AIniFile.WriteString(Section, Ident, Value);
  AIniFile.Free;
end;
 
procedure TNSSettings.WriteTime(const Section, Name: string; Value: TDateTime);
var
  AIniFile: TIniFile;
begin
  AIniFile := TIniFile.Create(FFileName);
  AIniFile.WriteTime(Section, Name, Value);
  AIniFile.Free;
end;
 
end.
Написано и протестировано на RAD STUDIO 10.2
Если кто-то из коллег решит доработать компонент, прошу выкладывать код и описание в эту тему.
Надеюсь данная тема будет полезной.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
16.03.2019, 16:10
Ответы с готовыми решениями:

TiniFile пытаюсь создать удаленное подключение к базе, ITable1 false
При компиляции table1 неактивна и никаких записей procedure TForm1.FormClick(Sender: TObject); var FiniFile: TIniFile; begin ...

TIniFile - не смог найти такой компонент
Не смог найти компонент TIniFile. Попробовал создать динамически, но билдер пишет Undeifined symbol 'TIniFile'. В чём может быть проблема? ...

Замена tinifile на бд
На данный момент имеется система авторизации, которая хранит учётные записи пользователей, их логи и персональные настройки в ini файлах....

5
 Аватар для krapotkin
6849 / 4676 / 1464
Регистрация: 14.04.2014
Сообщений: 20,670
Записей в блоге: 21
16.03.2019, 22:12
ini файл очень устарел на текущий момент
де-факто есть стандарт JSON
он делает все что нужно легко и изящно
посмотрите видео JSON new INI file
0
пофигист широкого профиля
4769 / 3204 / 862
Регистрация: 15.07.2013
Сообщений: 18,611
17.03.2019, 03:59
Ещё во времена царя Гороха наши ребята из RxLib уже написали такие компоненты. TFormStorage и TFormPlacement. Они их правда не доделали. Точнее не отладили на все 100.
Но уже тогда их компоненты умели работать и с ини-файлами и с реестром Windows по выбору автора.

Цитата Сообщение от krapotkin Посмотреть сообщение
де-факто есть стандарт JSON
И этот "стандарт" поддерживает Windows по умолчанию?!
0
61 / 51 / 25
Регистрация: 17.12.2013
Сообщений: 255
17.03.2019, 05:20  [ТС]
Цитата Сообщение от northener Посмотреть сообщение
Ещё во времена царя Гороха наши ребята из RxLib уже написали такие компоненты. TFormStorage и TFormPlacement. Они их правда не доделали. Точнее не отладили на все 100.
Но уже тогда их компоненты умели работать и с ини-файлами и с реестром Windows по выбору автора.
Когда у меня возникло ощущение, что мне не хватает подобного компонента, я потратил несколько часов на его поиск. В итоге написал сам.
Цитата Сообщение от krapotkin Посмотреть сообщение
ini файл очень устарел на текущий момент
де-факто есть стандарт JSON
он делает все что нужно легко и изящно
посмотрите видео JSON new INI file
Спасибо, но стандартные средства работы с JSON слишком громосткие для сохранения и чтения небольших конфигов, ини проще и меньше кода.
0
5972 / 4548 / 1094
Регистрация: 29.08.2013
Сообщений: 28,167
Записей в блоге: 3
18.03.2019, 09:09
Цитата Сообщение от KMSNasgool Посмотреть сообщение
с JSON слишком громосткие для сохранения и чтения небольших конфигов
это как раз ини файлы жутко неудобные
код же пишешь ты, как напишешь обертку - так её и используй
0
Эксперт .NET
 Аватар для Rius
13124 / 7685 / 1675
Регистрация: 25.05.2015
Сообщений: 23,454
Записей в блоге: 14
18.03.2019, 11:24
Цитата Сообщение от KMSNasgool Посмотреть сообщение
Все знают что такое TINIFile и все его прелести.
Ага, знают. Поэтому, уже прошли годы, как нормальные люди перешли на XML и JSON...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
18.03.2019, 11:24
Помогаю со студенческими работами здесь

Удаление строки из TIniFile
Написал программу, которая представляет из себя базу данных студентов. ...

Возможно ли подключиться к базе данных не используя компонент ADOConnection?
На просторах интернета нашел решение с подключением заголовочного файла #include &lt;mysql.h&gt; Пример с данного форума: ...

Как наследоваться от класса TIniFile?
class TFile : public TIniFile { void _fastcall SaveToFile(UnicodeString Path, TFL *L); void __fastcall LoadFromFile(UnicodeString...

Максимальная длина строки TMemo/TRichEdit/TIniFile
Ребят, помогите, пожалуйста, понять в чем проблема. На форме: Memo и Button. На клик прописано следующее: #include...

Access violation при использовании экземпляра TIniFile
есть кнопка, в код нажатия на которую я пару дней назад.сегодня добавил ещё вот это AnsiString...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru