Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 12.08.2012, 16:59   #11
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Цитата:
Не правы вы! Эти функции можно исползовать не только внутри модуля.
Само собой можно. Только ты сам что написал?

Цитата:
в прикреплённым ниже файле: все функции для копирования/вырезки/вставки через буфер обмена
Вот что написал - то и критикуем.

Если бы ты написал "вот модуль с операциями по работе с оболочкой" - я бы такое не написал. Вместо этого я бы написал:

Цитата:
Не очевидные имена для Shell_Str/Shell_DataOperations. Возможные альтернативы: StringListToShellStr, ShellFileOperation.
И уж тем более, если выносить (т.е. оставлять) Shell_DataOperations публичной, то её интерфейс совершенно не приемлем (почему? Аналогичные причины уже указаны мной для других функций модуля). Должно быть хотя бы так:

Код:
type
  TShellOperation = (soCopy, soMove, soDelete);
  TShellOption = (sopAllowUndo, sopFilesOnly, ...);
  TShellOptions = set of TShellOption;

function ShellFileOperation(const ASourceFiles: TStringList; const ATargetFolder: String; const AOperation: TShellOperation; const AOptions: TShellOptions);
Цитата:
Это сделано специально чтоб этот парметр можно было подсовывать с разных мест, напиример при DragDrop формируется свой список данных которые начали тащить и чтоб его оперделить надо внешний хэндл в функцию пихать.
Аналогично: я писал про то, что ты просил покритиковать, а не то, что ты там у себя в голове держал. Извини, свой миелофон я кому-то одолжил.

Окей, в свете новой информации, внимание, вопрос: а какое описатель внешний код будет передавать в функцию? Буфера обмена? Хм, а сама функция не может его, что-ли получить? Может. А зачем тогда его передавать? Почему это модуль Clipbrd с его объектом Clipboard не просят передавать им никаких описателей, а твой код без них обойтись не может, странно, да?

Цитата:
Аракак иначе сделать? Впринципе работает номально чем плохо то?
Ты следующее сообщение читал? У тебя утечка памяти в коде - именно из-за неудачного дизайна этой функции.

Действительно, чего такого-то... работает же.

И там же (в следующем сообщении) написано "как иначе сделать".

Цитата:
дык ведь попробуйте сами! скопируйте в проводнике файл в буфер и сделайте ShowMessage(inttostr(Clipboard_Send Type)); будет 5...
(Вздох)

Это было домашнее задание и ты с ним не справился. Тебе нужно было почитать и понять, что написано по этой ссылке. А написано там следующее: информация о модификаторе перетаскивания представлена комбинацией констант DROPEFFECT_XYZ. И твой 5 - это, на самом деле, DROPEFFECT_COPY + DROPEFFECT_LINK. Т.е. это вовсе даже не копирование, а создание ярлыка.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 12.08.2012, 17:11   #12
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Цитата:
Не работает! не меняет ваша функиция #13#10 на #0, а надо бы.
А зачем их заменять? Мне из буфера нужно достать тот же текст что я туда положил, а не ту кашу которая получится в результате вырезания CR LF символов перехода.

В любом случае, система сама заботится о хранении строки в буфере при помещени оной туда, системной функцией из поля ввода.

Цитата:
Аракак иначе сделать? Впринципе работает номально чем плохо то?
Вы создаете обьект в пункте А, в результате возвращаете его. В этот момент приходится дублировать обьект. Итого у нас уже 2 обьекта. Притом первый утерян наверки в ОЗУ, а второй возвращается в результат.
Хотя это мое предположение, и я думаю, что реализован автомат на такой случай, чтобы возвращалось то, о чем я скажу ниже.

В общем правильным решением будет вернуть указатель на этот обьект, а не сам обьект.

Код:
Type
  TMyObject=Class(TObject)

  ....
  end;
  PMyObject=^TMyObject;

...

function CreateObject:PMyObject;
var
  Obj:TMyObject;  //Обьявили объект
begin
  Result:=nil;
  Obj:=TMyObject.Create; //Создали объект
  Result:=@Obj; //Передали указатель на этот объект
end;
Для хранения обьектов можно использовать списки(TList, TObjectList и т.д.).

Смысл указателя в том, что созданный объект всегда в одном месте, а указать на него можно откуда угодно.

Цитата:
дык ведь попробуйте сами! скопируйте в проводнике файл в буфер и сделайте ShowMessage(inttostr(Clipboard_Send Type)); будет 5...
Использование Человеко Понятных Констант намного удобнее именно по этому MS рекоммендует...
Цитата:
Вместо волшебных констант 2, 5 и т.п. использовать DROPEFFECT_NONE, DROPEFFECT_COPY, DROPEFFECT_MOVE, DROPEFFECT_LINK.
Вы бы с ума сошли если бы вам пришлось запомнить столько чисел и их значений.

Последний раз редактировалось Человек_Борща; 12.08.2012 в 17:14.
Человек_Борща вне форума Ответить с цитированием
Старый 12.08.2012, 17:16   #13
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
В общем правильным решением будет вернуть указать на этот обьект, а не сам обьект.
и нафиг нам указатель на указатель на обьект?
учитывая что указатель на обьект локальная переменная, и указатель на нее возвращать нельзя.

лучше не возвращать обьект, а если функция должна заполнить обьект, то передать этот обьект как параметр.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 12.08.2012, 17:30   #14
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Цитата:
учитывая что указатель на обьект локальная переменная, и указатель на нее возвращать нельзя.
хм.. как тогда?

Код:
type
  TMyObject=class
    private
      fStr:string;
    public
    property str:string read fStr write fStr;
    constructor Create(aStr:string); overload;
    destructor Destroy; override;
  end;
  PMyObject=^TMyObject;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
 private
    { Private declarations }
  public
    { Public declarations }
    function func1:Pointer;
  end;

var
  Form1: TForm1;
  obj:Pointer;

implementation

{$R *.dfm}

{ TMyObject }

constructor TMyObject.Create(aStr:string);
begin
  inherited Create;
  Str:=aStr;
end;

destructor TMyObject.Destroy;
begin
  inherited;
end;

function TForm1.func1: Pointer;
var
g:TMyObject;
begin
  g:=TMyObject.Create('ghjghj');
  Result:=@g;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  obj:=func1;
  Memo1.Text:=PmyObject(Obj).str;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
    PmyObject(Obj).str:='sdsdggdfgsfgsfgsgfsfdgs';  //Obj = $12F584 , по всеравно AV
    Memo1.Text:=PmyObject(Obj).str;
end;

end.

Последний раз редактировалось Человек_Борща; 12.08.2012 в 17:34.
Человек_Борща вне форума Ответить с цитированием
Старый 12.08.2012, 17:49   #15
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Цитата:
В общем правильным решением будет вернуть указатель на этот обьект, а не сам обьект.
(facepalm)

Объект - это уже указатель. Объекты, строки, динамические массивы, интерфейсы и варианты в Delphi представлены как указатели на данные. Поэтому конструкции вида "указатель на объект", "указатель на строку", "указатель на дин. массив", "указатель на интерфейс", "указатель на вариант" - бессмысленны в 99% случаев и указывают на то, что ты не понимаешь, о чём говоришь.

Ещё раз. Когда есть:
Код:
function DoSomething: TSomeObject;
Это допустимо только тогда, когда функция (а чаще всего - метод) возвращает уже существующий объект. Который вызывающий может использовать, но не удалять.

Если же, у функции нет готового объекта, то тогда этот прототип нужно переделать по двум альтернативным друг к другу вариантам:
1. Функция создаёт объект:
Код:
procedure DoSomething(out AResult: TSomeObject);
В этом случае синтаксис явно говорит нам, что объект создаётся и его нужно удалить после использования. Также он предотвращает неявные утечки памяти (что и случилось у автора вопроса).
2. Функция оперирует с объектом, передаваемым извне:
Код:
procedure DoSomething(AObj: TSomeObject);
В этом случае объект создаёт (и удаляет) вызывающий, а функция только заполняет его данными. Что я и сделал в примерах кода в моих постах выше.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
скопировать файл в буфер обмена Rolls Общие вопросы Delphi 15 17.02.2012 01:03
Как макросом Vba определить содержит ли буфер обмена рисунок? roborrr Microsoft Office Excel 2 27.02.2011 14:24
КАк поместить файл в буфер обмена? Paul Hindenburg Общие вопросы Delphi 1 16.07.2009 10:17
Как очистить буфер обмена? StasSv Microsoft Office Excel 2 11.08.2008 17:38