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

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

Автор: Grande
Дата сообщения: 13.03.2012 08:14
wasilissk
Абсолютно верно.
Автор: wasilissk
Дата сообщения: 13.03.2012 08:24
Grande
Завети генератор для этих полей и передавать его экземпляр в конструктор наследника TForm.

Код:
TGenerator = class
private
FCurValue: Integer;
public
function GetValue: Integer; // Result := Inc(FCurValue);
end;

TMyForm = class(TForm)
private
FSomeValue: Integer;
public
constructor Create(.., Generator: TGenerator);
end;

........

TMyForm.Create(.., Generator: TGenerator);
begin
...
FSomeValue := Generator.GetValue;
...
end;
Автор: Grande
Дата сообщения: 13.03.2012 08:26
wasilissk
Ага... Сейчас попробую, спасибо.
Автор: ant0ni02004
Дата сообщения: 13.03.2012 17:18
Grande

Через class function + class var проще будет пожалуй
Автор: ArtSnegirev
Дата сообщения: 13.03.2012 20:54
Grande
создать статичный метод (или несколько), генерирующий уникальные данные на момент вызова
class function TForm.GetUniqueValue; static;
и вызывать его при создании формы в TForm.Create, заполняя нужные поля
Автор: wasilissk
Дата сообщения: 14.03.2012 06:10
ArtSnegirev
И текущие значения хранить в глобальных переменных?
ant0ni02004
Как начсет неповторяемости? Или все наследники должны знать друг о друге и проверять неповторяемость в цикле?



Добавлено:
ant0ni02004
Кстати class var будет одна для всех экземпляров.
Автор: ArtSnegirev
Дата сообщения: 14.03.2012 08:57
wasilissk
согласен, где-то придется хранить значения статического генератора, что неудобно
видимо, предложенный вами вариант наиболее удобный
Автор: wasilissk
Дата сообщения: 14.03.2012 12:35
Проблемы с TOpenDialog и TSaveDialog.
Открываем/Сохраняем файл из/в расшаренной папки, этот путь где-то запоминается. Далее если это комп в сети более недоступен (я коннектился по сети к виртуальной машине), при вызове OpenDialog.Execute приложение наглухо виснет. Подобное же поведение наблюдается даже при перезапуске приложения, т.е. где-то в реестре запоминает эту папку, и в этом случае InitialDir = EmptyStr.
В качестве костыля можно указывать явно InitialDir каждый раз, но в таком случае теряем последнюю папку с которой работал пользователь.
Как грамонтно выйти из этой ситуации? Чтобы запоминать последнюю посещенную папку, но либо удалять ее если она указывает на папку в сети, либо указать таймаут для OpenDialog.Execute?
Автор: Grande
Дата сообщения: 14.03.2012 15:50
С этим прошло
Нельзя ли еще вопрос?
Создается несколько экземпляров TSocket, им назначается некая процедура приема (одна на всех).
Сокеты делают запросы на сервер и получают ответ. А как потом выделить информацию для каждого сокета, ведь процедура приема-то одна?
Автор: ant0ni02004
Дата сообщения: 14.03.2012 15:54
wasilissk

кроме InitialDir нужно еще и FileName чистить
Автор: wasilissk
Дата сообщения: 14.03.2012 17:50
ant0ni02004
С этим нет проблем. При установке InitialDir все работает, я же хочу сохранить папку с которой пользователь работал.
При запуске приложения когда InitialDir и FileName пусты, диалог открывает последнюю открытую папку (откуда он ее берет?) и если она в данный момент недоступна, виснет.

Добавлено:
Grande
Процедура это обработчик чтоли? Там наверняка есть Sender, приводите его к вашему типу TSocket и работайте.
Автор: YuraseK
Дата сообщения: 14.03.2012 21:44
[more=Пример кода]
Код: unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type
TTest = class
FValue: Integer;
public
property Value: Integer read FValue;
constructor Create;
end;

TTestThread = class(TThread)
FProc: Pointer;
FProc2: TNotifyEvent;
FType: Boolean;
procedure DoProc;
procedure DoProc2;
public
constructor Create(const Proc: TNotifyEvent); overload;
constructor Create(const P: Pointer); overload;
procedure Execute; override;
end;

TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button2Click(Sender: TObject);
private

public
Test: TTest;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(IntToStr(Test.Value));
end;

{ TTest }

constructor TTest.Create;
begin
FValue:= 8;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Test:= TTest.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
Test.Free;
end;

{ TTestThread }

constructor TTestThread.Create(const Proc: TNotifyEvent);
begin
inherited Create(True);
FType:= False;
FProc2:= Proc;
end;

constructor TTestThread.Create(const P: Pointer);
begin
inherited Create(True);
FType:= True;
FProc:= P;
end;

procedure TTestThread.DoProc;
var
NotifyEvent: TNotifyEvent;
begin
@NotifyEvent:= FProc;
NotifyEvent(nil);
end;

procedure TTestThread.DoProc2;
begin
FProc2(nil);
end;

procedure TTestThread.Execute;
begin
inherited;
if FType then
Synchronize(DoProc)
else
Synchronize(DoProc2);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
TestThread, TestThread2: TTestThread;
NotifyEvent: TNotifyEvent;
begin
NotifyEvent:= Button1Click;

TestThread2:= TTestThread.Create(NotifyEvent);
TestThread2.Resume;
TestThread2.WaitFor;
TestThread2.Free;

TestThread:= TTestThread.Create(@NotifyEvent);
TestThread.Resume;
TestThread.WaitFor;
TestThread.Resume;
end;

end.
Автор: delover
Дата сообщения: 14.03.2012 21:59
YuraseK
Тут я любитель Delphi порекомендую вам СиШапр. Но только из гуманных соображений.
Автор: Frodo_Torbins
Дата сообщения: 14.03.2012 22:28
YuraseK
Ваш Button1Click это не просто процедура, это метод объекта. Указатели на методы объектов имеют длину не 4 байта, как все остальные, а 8. Во втором конструкторе вы теряете половину указателя.
А вообще очень советую взглянуть на более новые версии делфей, там появились анонимные методы. Похоже именно они вам и нужны, если хотите полной универсальности.
Автор: YuraseK
Дата сообщения: 14.03.2012 22:41
Frodo_Torbins
Спасибо за ответ. Требуется решение для 7-й версии. Я посмотрел в отладчике вызов метода идёт через [esp], а указатель на объект берётся из [esp+4], а там пусто.
Я сделал небольшой финт, но работает:

Код: asm
mov eax, Form1;
mov dword ptr [esp + 4], eax;
end;
Автор: Frodo_Torbins
Дата сообщения: 14.03.2012 23:07
YuraseK
А как быть с передачей параметров если они есть? Думаю самое время попробовать готовые библиотеки для организации многопоточности.
Автор: YuraseK
Дата сообщения: 14.03.2012 23:43
Frodo_Torbins
С передачей параметров проблем нет. Проблема в моём случае только в вызове произвольного метода из перечня известных. И это удалось решить переписав вышепредставленный код следующим образом:

Код: type
PMethod = ^TMethod;
TMethod = record
Code, Data: Pointer;
end;


TTestThread = class(TThread)
FObject: TObject;
...
public
...
end;

procedure TForm1.Button2Click(Sender: TObject);
var
TestThread: TTestThread;
NotifyEvent: TNotifyEvent;
begin
NotifyEvent:= Button3Click;
TestThread:= TTestThread.Create(@@NotifyEvent); //указатель на указатель метода
TestThread.Resume;
TestThread.WaitFor;
TestThread.Resume;
end;

constructor TTestThread.Create(const P: Pointer);
begin
inherited Create(True);
FType:= True;
with PMethod(P)^ do
begin
FObject:= Data;
FProc:= Code;
end;

end;

procedure TTestThread.DoProc;
var
NotifyEvent: TNotifyEvent;
begin
with PMethod(@@NotifyEvent)^ do
begin
Code:= FProc;
Data:= FObject;
end;

NotifyEvent(FObject);
end;
Автор: XPerformer
Дата сообщения: 15.03.2012 01:38
Frodo_Torbins

Цитата:
Указатели на методы объектов имеют длину не 4 байта, как все остальные, а 8.

Может, правильнее сказать, состоят из двух 4-х байтовых указателей, а то народ подумает, что речь идет о 64-битной адресации...
Автор: wasilissk
Дата сообщения: 15.03.2012 05:42
YuraseK
Для TNotifyEvent вообще ничего подобного не нужно было городить, он уже объявлен of object. Вам всего лишь надо было завести процедурную переменную of object, вместо Pointer-а, было бы намного нагляднее.
А подобное решение,.. как бы у вас не всплыло через годик трудноуловимым AV или обрушением стека.
Автор: XPerformer
Дата сообщения: 15.03.2012 11:08
wasilissk
А как это может спасти от "трудноуловимого AV"? Процедурные переменные как-то более защищены от обрушения стека, чем обычные поинтеры? по-моему, одно и то же... надо завести привычку проверять переменные на nil перед использованием
Автор: wasilissk
Дата сообщения: 15.03.2012 11:50
XPerformer
При вызове в DoProc, будет переменная того же типа что и в конструкторе. А так как сейчас, можно забыть что там указатель на указатель на метод с непонятно какими параметрами. Плюс работа в потоке, можно потом очень долго искать кто попортил память. Так что AV или обрушение стека еще не самое худшее.
Автор: Frodo_Torbins
Дата сообщения: 15.03.2012 12:35
YuraseK
Кстати да. Если нет надобности в произвольных параметрах или чем то подобном, то нет смысла делать работу компилятора. Просто обьявите переменную TNotifyEvent да и дело с концом.
Автор: Ichigo2
Дата сообщения: 15.03.2012 16:10
Хочу сделать Balloon Tooltips, чтобы выскакивал из статусбара формы. Можно ли так? И реализация этого не зависит от операционной системы? Просто читал, что это пошло с помощников Офиса, и МS вроде забили на это.
Автор: YuriyRR
Дата сообщения: 16.03.2012 02:48
Ichigo2
Уже море готовых.

Цитата:
Можно ли так? И реализация этого не зависит от операционной системы?

Можно, не зависит.
Автор: Grande
Дата сообщения: 20.03.2012 08:53
Уважаемые знатоки, имеется такой код:

Вызывающая программа

Код:
type
TParams = record
Answer1, Answer2, Answer3, Answer4: PChar;
IniString1, IniString2, IniString3, IniString4: PChar;
Frame, IP_Address, BSCPort, MO, FaultNo: PChar;
end;
...

var
Parameters: TParams;
begin
Answer := GetCode(@Parameters);
...
Автор: akaGM
Дата сообщения: 20.03.2012 09:17
Grande

Цитата:
function GetCode(Parameters): PCodes;
var
Parameters: TParams;

ты уверен, что это формат дельфи?

+

как ты вызываешь GetCode()?
Автор: Grande
Дата сообщения: 20.03.2012 09:19
Виноват, в спешке писал, исправил.

Answer := GetCode(@Parameters);
Автор: akaGM
Дата сообщения: 20.03.2012 09:29
Grande
ты не торопись...

Цитата:
function GetCode(Parameters: TParams): PCodes;
...
Answer := GetCode(@Parameters);

опять ведь фигню написал :)

DLL тоже дельфийская или чья?

Автор: Grande
Дата сообщения: 20.03.2012 09:32

Цитата:
DLL тоже дельфийская или чья?


Да, разумеется дельфийская.
Автор: akaGM
Дата сообщения: 20.03.2012 09:56
так как ты там у себя зовёшь getCode()?
+
такой нескромный вопрос:
ты в своих Parameters: TParams; память для разных полей выделил?

Страницы: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374

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


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