Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по Delphi (до версии 2009) - часть 6

Автор: Varenik
Дата сообщения: 23.09.2011 15:25
rrromano
Цитата:
А дальше, как я и писал. Правильно?
А дальше надо разобраться, что вы подразумеваете под
Цитата:
копируете один элемент в другой путём копирования области памяти
- как именно это делается и с чем (в сообщении мешанина из структур и экземпляров класса).
Автор: rrromano
Дата сообщения: 23.09.2011 15:44
Varenik

Цитата:
- как именно это делается и с чем (в сообщении мешанина из структур и экземпляров класса).


Загляните на предыдущую страницу. Там автор вопроса делает вот так:


Код: // Структура для хранения данных.

TRouteItem = record
bGateWay : Boolean;
bChecked : Boolean;
pszRouteName: WideString;
dwNetWork : DWORD;
dwNetMask : DWORD;
end;
// Глобальный массив этих структур.

pRouteInfo: Array of TRouteItem;
Автор: Frodo_Torbins
Дата сообщения: 23.09.2011 18:10
Maks150988

Цитата:
Заместо CopyMemory использую цикл.

Код: [no]for i := (idItem + 1) to iCount do
pRouteInfo[i - 1] := pRouteInfo[i];[/no]
Автор: Maks150988
Дата сообщения: 24.09.2011 16:01
rrromano
Нет, без всяких ООП надо.

Frodo_Torbins
А как тогда управлять памятью? Ну вот использую я способ с CopyMemory. Задача - вставить новый элемент в список. Это типа надо выделить память через GetMem, например, для локальной переменной ^TRouteItem размером SizeOf(TRouteItem), выделить в ней подобным способом память под буфер pszRouteName, если тот будет уже LPWSTR и только потом скопировать все под нужный индекс массива, с освобождение памятей этой локальной переменной и буфера от нее?



А вообще интересная задачка выходит. =) Кстати, я тут ранее отписывался насчет контрола. Может кто посмотрит и скажет в чем ошибка. Когда остается один элемент в списке, то при его удалении нарушение доступа возникает. Связано это с освобождением буфера. Хотя я не понял где там косячок, вроде бы все корректно освобождаю, проверив на nil его. Видать FreeMem может что неправильно делает, все-таки там юникод и этот еще нультерминирующий символ присутствовать может, так то если строка пустая, то размер ее 2 байта будет и наверняка пытается как-то не так память освободить. Вобщем кому не сложно, да и тема интересна, гляньте код функции CtrlWndProc_LbDeleteString. =) Может кто даже оптимизирует текущую наработку. Я тут кое-чего добавляю в свободное время. =)

extended_listbox_src.zip


Автор: Frodo_Torbins
Дата сообщения: 24.09.2011 18:53
Maks150988
Память вы должны выделять руками для всего, что является указателем. Если LPWSTR в вашем случае указатель, то под него тоже нужно выделять память. Если же это просто WideString то ничего делать не нужно.
Автор: rrromano
Дата сообщения: 24.09.2011 22:28
Maks150988
Для вас процитирую:

Цитата:
В отличие от ShortString, WideString - указатель, ссылающийся на переменные. Память распределяется для AnsiString только когда необходимо. Например, присваивание значения одного AnsiString другому не распределяет память для копии первой строки. Вместо этого, ссылка считает первую строку увеличенной, и второй AnsiString устанавливает указатель на него.

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

Когда на строку больше не ссылаются (последний указатель WideString установлен на ноль), она уничтожается.

WideStrings может быть присвоен от других строк, от функций, которые возвращают строку, и конкатенациями как в данном примере.


Внимательно прочитав, вы всё поймёте.
Автор: Frodo_Torbins
Дата сообщения: 24.09.2011 23:23
rrromano
А я что то не понял AnsiString - это автоматически управляемая строка со счетчиком ссылок. Тоесть несколько переменных могут ссылаться на одну строку. WideString - автоматически управляемая строка без счетчика ссылок, на нее всегда ссылается только одна переменная. Плюс символы в ней занимают по два байта. В обоих случаях сама переменная имеет длину 4 байта и указывает на строку лежащую где то в другой области памяти. Что касается ShortString то тут я не в курсе. Наверное имеется в виду что переменная этого типа занимает от 0 до 256 байт, и является самой строкой а не указателем на нее.
Автор: my610
Дата сообщения: 25.09.2011 10:39
Frodo_Torbins
Длинные строки и динамические массивы в Delphi все подробно расписано
Автор: GRom V
Дата сообщения: 26.09.2011 06:05
Доброе время суток!!!
Подсабите... есть код: Но есть загвоздка. А именно если oldstring длинее newstring, как в этом случае, тогда получается не 1234 а 1234ty...
Как уброть лишнее?

procedure patch_exe;
begin
oldstring := 'qwerty';
newstring := '1234';
FileName := Form1.Edit1.Text+'.exe';
s := oldstring;
AssignFile(f, FileName);
Reset(f, 1);
for l := 0 to FileSize(f) - Length(oldstring) - 1 do
begin
Application.ProcessMessages;
Seek(f, l);
BlockRead(f, oldstring[1], Length(oldstring));
if oldstring = s then
begin
seek(f, l);
BlockWrite(f, newstring[1], Length(newstring));
end;

Application.ProcessMessages;
end;
CloseFile(f);
showmessage('Done ');
end;
Автор: data man
Дата сообщения: 26.09.2011 07:07
GRom V


Код: ...
uses
Windows, SysUtils;
...
FileHandle := CreateFile(PСhar(Filename), GENERIC_WRITE, fmOpenWrite, Nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
SetFilePointer(FileHandle, нужная длина, Nil, FILE_BEGIN (или FILE_END);
SetEndOfFile(FileHandle);
CloseHandle(FileHandle);
...
Автор: GRom V
Дата сообщения: 26.09.2011 07:58
data man

Цитата:
Код:...
uses
Windows, SysUtils;
...
FileHandle := CreateFile(PСhar(Filename), GENERIC_WRITE, fmOpenWrite, Nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
SetFilePointer(FileHandle, нужная длина, Nil, FILE_BEGIN (или FILE_END);
SetEndOfFile(FileHandle);
CloseHandle(FileHandle);
...


Прошу просчения.... А можно практически - как это с моим кодом подружить???
Автор: YuriyRR
Дата сообщения: 26.09.2011 08:37
GRom V

Цитата:
тогда получается не 1234 а 1234ty...


procedure SetLength(var S; NewLength: Integer);

Description

S is a Delphi string or dynamic-array variable.

NewLength is the new number of characters or elements in S.

For a short-string variable, SetLength simply sets the length-indicator character (the character at S[0]) to the given value. In this case, NewLength must be a value between 0 and 255.

For a long-string or dynamic-array variable, SetLength reallocates the string or array referenced by S to the given length. Existing characters in the string or elements in the array are preserved, but the content of newly allocated space is undefined. The one exception is when increasing the length of a dynamic array in which the elements are types that must be initialized (strings, Variants, Variant arrays, or records that contain such types). When S is a dynamic array of types that must be initialized, newly allocated space is set to 0 or nil.
Автор: ShIvADeSt
Дата сообщения: 26.09.2011 08:46
GRom V

Цитата:
Подсабите... есть код: Но есть загвоздка. А именно если oldstring длинее newstring, как в этом случае, тогда получается не 1234 а 1234ty...

Если уберешь лишнее (уменьшишь размер ехешника на 2 байта) простым обрезанием строки, то получишь битый файл. Заполни пробелами до длины начальной строки и все. А если новая строка длиннее старой, то просто так не заменишь (опять же именно в ехешнике).
Автор: GRom V
Дата сообщения: 26.09.2011 09:18
Всем спасибки...
Автор: my610
Дата сообщения: 26.09.2011 09:51
GRom V, если нужно обрезать строку в бинарнике, просто пропиши в ее конец 0x00:

Код:
71 77 65 72 74 79 qwerty было
31 32 33 34 00 00 1234 надо сделать
31 32 33 34 00 79 1234.y стало
Автор: GRom V
Дата сообщения: 26.09.2011 15:04
my610
Спасибо за наводку (хотя на водку хватает)....глянь личку плизз
Автор: Maks150988
Дата сообщения: 26.09.2011 18:14
Вобщем спасибо всем то дал ценные указания насчет работы с указателями.
У меня вот непонятки с XML. Начал недавно осваивать. Почему-то если вызвать xml.documentElement, то при завершении работы программы появляется ошибка нарушения доступа. Это все, если вызвать CoUninitialize. Но блин получается я же должен закрыть COM и освободить ресурсы. В чем ошибка?


Код: var
hr : HRESULT;
xml : IXMLDOMDocument;
node : IXMLDOMNode;
child : IXMLDOMNodeList;
bRet : Boolean;
iCount : Integer;
IdItem : Integer;
pszData: WideString;
pszText: WideString;
begin
hr := CoInitialize(nil);
if (hr = S_OK) then
try
hr := CoCreateInstance(CLASS_DOMDocument, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IID_IXMLDOMDocument, xml);
if (hr = S_OK) then
try
xml.async := FALSE;
bRet := xml.load('file.xml');
if bRet then
begin
node := xml.documentElement;
{iCount := node.childNodes.length;
for IdItem := 0 to (iCount - 1) do
begin
pszText := pszText + FormatW('Index = %d; ', [IdItem]);
child := node.childNodes.item[IdItem].SelectNodes('type');
pszData := child.item[0].text;
pszText := pszText + FormatW('type = %s; ', [pszData]);
child := node.childNodes.item[IdItem].SelectNodes('name');
pszData := child.item[0].text;
pszText := pszText + FormatW('name = %s; ', [pszData]);
pszText := pszText + sLineBreak;
end;
MessageBoxW(0, LPWSTR(pszText), nil, MB_OK);}
end;
finally
xml := nil;
end;
finally
CoUninitialize;
end;
end.
Автор: data man
Дата сообщения: 26.09.2011 18:43
Maks150988

Цитата:
У меня вот непонятки с XML. Начал недавно осваивать.

Лучше сразу перейти на альтернативные компоненты (OmniXML, NativeXML, etc.), пока не поздно.

Цитата:
чтобы из буфера читать?

В них всё это есть.
Автор: Frodo_Torbins
Дата сообщения: 26.09.2011 18:56
Maks150988
Компилятор делфи пытается сам освободить интерфейсы. Необходимый для этого код он вставляет после всего вашего кода, и перед "end.". В вашем случае это означает что действия с ком-обьектами производятся после вызова CoUninitialize. Попробуйте весь код по работе с интерфейсами вынести в отдельную процедуру, а CoUninitialize дергать после вызова этой процедуры. Если переменные-интерфейсы будут локальными для процедуры, то и код их закрытия компилятор вставит в конец этой процедуры, а не в конец программы.
Автор: druff
Дата сообщения: 27.09.2011 10:27
data man

Цитата:
Лучше сразу перейти на альтернативные компоненты (OmniXML, NativeXML, etc.), пока не поздно.


Почему?
Автор: ShIvADeSt
Дата сообщения: 28.09.2011 02:14
druff

Цитата:
Почему?

Потому что они имеют более человеко-ориентированные методы, чем стандартный от МС. Сам в свое время пытался юзать ДОМ от МС, однако мне не хотелось жрать кактус и я перешел на SimpleXML Там все гораздо проще.
Автор: druff
Дата сообщения: 28.09.2011 09:05
ShIvADeSt
спасибо. Я как раз раздумывал о формате для хранения сопроводительной информации к файлам. Надо сравнить эти альтернативные..
Автор: volser
Дата сообщения: 28.09.2011 22:21
Для не очень больших файлов вполне хватит и ДОМ от МС.
Автор: ShIvADeSt
Дата сообщения: 29.09.2011 03:38
volser

Цитата:
Для не очень больших файлов вполне хватит и ДОМ от МС.

Тут дело такое, что я для того чтобы начать парсить простые и небольшие (для теста) хмл файлы при помощи ДОМ от МС потратил столько времени (правда это было более 5 лет назад, но все же), что плюнул и попробовал SimpleXML (мне его хватало за глаза) - результат - за пол часа я сделал все то же что и раньше, при этом мне хватило встроенной ридмишки. Плюс - если мне надо что то поправить в результатах вывода в хмл - я просто правил код SimpleXML и получал нужное. В случае с ДОМ - такой финт не прокатит.
Автор: GRom V
Дата сообщения: 01.10.2011 10:30
Как в Windows 7 можно заблокировать или убрать кнопку Пуск
Автор: Frodo_Torbins
Дата сообщения: 01.10.2011 10:56
GRom V
Заменить всю оболочку своей. А зачем это вообще нужно?
Автор: Bladerender
Дата сообщения: 01.10.2011 11:11
С своей оболочкой удобнее работать намного. Посмотрите видеообучалки по этому поводу.
Автор: GRom V
Дата сообщения: 01.10.2011 12:55
Frodo_Torbins

Цитата:
А зачем это вообще нужно?

Делаю интегратор на параход чтоб можно было запустить только нужные проги и ничего более. А то у них компы и месяц не живут. Короче остался один гемор с этой кнопкой пуск

Добавлено:

Цитата:
С своей оболочкой удобнее работать намного. Посмотрите видеообучалки по этому поводу.

А где посмотреть можно? ЧЕ за оболочка???
Автор: Frodo_Torbins
Дата сообщения: 01.10.2011 13:51
GRom V
Shell - оболочка, рабочий стол виндовс. Реализуется процессом explorer.exe (попробуйте прибить его диспетчером задач). Стартует вместе с системой и запускает все проги из автозапуска. Существуют уже готовые замены, к примеру Talisman, SharpE, KDE (да-да и для винды тоже), но вы можете написать свой. Главное прописать его в реестр:
Код: [HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Winlogon]
"Shell"="C:\Windows\ehome\ehshell.exe"
Автор: R3Pa4eK
Дата сообщения: 09.10.2011 16:28
Использую компонент ImageEn. Загружаю изображение и посылаю его на хэндл. Это все что делает моя dll, но её размер около 2 Мб, что не приемлемо. Как уменьшить размер dll программно? Всякие UPX'ы не предлагать... [more=Код dll]
library ISLogo;

uses
Windows, Forms, StdCtrls, ImageEnView;

{$R *.res}

var
Logo: TImageEnView;

procedure ISLogo_Draw(Wnd :HWND; FileName: PChar; X, Y, W, H: Integer) stdcall;
begin
try
Logo := TImageEnView.Create(nil);
Logo.ParentWindow := Wnd;
Logo.IO.LoadFromfile(FileName);
DeleteFile(FileName);
Logo.Top := Y;
Logo.Left := X;
Logo.Width := W;
Logo.Height := H;
Logo.BorderStyle := bsNone;
Logo.ScrollBarsAlwaysVisible:= False;
Logo.ScrollBars:= ssNone;
Logo.Update;
except
end
end;

procedure ISLogo_Free; stdcall;
begin
Logo.Clear;
Logo.Destroy;
end;

exports ISLogo_Draw;
exports ISLogo_Free;

begin
end.
[/more]

Страницы: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374

Предыдущая тема: MPO File


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.