Да, можно без рекурсии, циклом:

procedure ControlScreenPos( Sender:TObject; var X:integer; var Y:integer);
// возвращает экранные координаты компонента
var
  tmpParent: TControl;
begin
  tmpParent := TControl(Sender);
  x := tmpParent.Left;
  y := tmpParent.Top;
  repeat
    tmpParent := TControl( tmpParent.Parent );
    if tmpParent <> nil then
    begin
      x := x + tmpParent.Left;
      y := y + tmpParent.Top;
    end;
  until tmpParent = nil;
end;

Пример использования

procedure Form1_Button2_OnClick (Sender: TObject; var Cancel: boolean);
var
  x,y: integer;
begin
  ControlScreenPos( Sender, X, Y);
  ShowMessage( IntToStr(X)+':'+IntToStr(y)  )
end;

http://myvisualdatabase.com/forum/misc.php?action=pun_attachment&amp;item=8551&amp;download=0

Для этого нужна рекурсивная процедура, которая будет складывать top и left с родительскими. В Дельфи это метод встроен в компоненты, в MVDB придется писать скрипт ))).

803

(4 replies, posted in Russian)

Процедура инициализирует переменную-параметр:

procedure CForm(AObject: TObject; var AForm: TAForm);
// определение формы компонента
begin
  AForm := TAForm(TComponent(AObject).Owner);
end;

Подходит для любых событий, кроме событий формы

procedure frmImage_PreviewImage_OnClick (Sender: TObject);
var
  tmpForm:TAForm;
begin
  CForm(Sender,tmpForm);
  ShowMessage(tmpForm.Name);
end;

Вторая полезная функция находит компонент на форме с проверкой или без:

procedure FindC(AForm: TAForm; AName: string; var AComponent: TComponent; ACheck: boolean = True);
// поиск компонента на форме с контролем
begin
  AComponent := AForm.FindComponent(AName);
  // если включен контроль, а компонент не найден
  if ACheck and (AComponent = nil) then // возбуждаем исключение
    RaiseException('На форме ' + AForm.Name + ' не найден компонент ' + AName);
end;

Это позволяет создавать универсальные обработчики, не привязанные к конкретной форме или компоненту:

procedure frmImage_panPreview_OnResize (Sender: TObject);
// изменение размера
var
  tmpPanel: TdbPanel;
  tmpForm:TAForm;
  tmpScrollBox: TScrollBox;
begin
  CForm(Sender,tmpForm);
  tmpPanel := TdbPanel(Sender);
  FindC(tmpForm,'scbPreview',tmpScrollBox,False);
  ...
end;

Редактор миниатюры

https://blogger.googleusercontent.com/img/a/AVvXsEhF90mN-vwOPub7PqXqpGnLzMOCYvRWKz_EOhA1JvGn6YBgQISTaQ1ZswqB3v1plrtMj-rC8r3WeGnNconuYbXNM6otHz0yYkbH9LjKjmPeJcu5CJ9MRdTA20z8o8VuNBam3aOvPQiUy5nm1hXVQ1CSUP8sFDfgZ6ZH025dnfROwYOxml8SnFpVkJDt=w640-h394


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


Читать: https://createmyvisualdatabaseapp.blogs … -post.html

805

(7 replies, posted in Russian)

Тут несколько принципов нужно применить.


Во-первых, чтобы обработчики этих компонент не содержали в своем коде жесткой привязки к этим компонентам, а работали через FindComponent.


Во-вторых нужно отказаться от хранения этих как я их называю "виртуальных классов"  на форме. Их лучше создавать программно, а на форме для удобства можно размещать "плейсхолдер" - обычный компонент, на месте которого будет "строиться" экземпляр "виртуального класса".


Как раз на эту тему пишу статью )))  Точнее, в статье описываются такие "виртуальные классы". Если интересно, могу эту тему копнуть глубже, дать больше теории и практических примеров.

OK, главное, чтобы вас устаивал результат )))

Используйте подзапрос:

SELECT id_print, t1, t2, (t1 - t2) as t3 from
(
SELECT sch.id_print
   (SELECT max(sch) from sch t1 where (t1.id_print = sch.id_print)),
   (SELECT min(sch) from sch t2 where (t2.id_print = sch.id_print))
from sch 
group BY id_print 
)

Вот только не понятно, что вам даст Group_by...

808

(13 replies, posted in General)

v_pozidis wrote:

In my google account I have a doc file using the google Word and the connection link is public for all. The name of the file is vertest. the file has only a text in it   If you could  "translate" it in pascal . I place the following procedure also in a text file to read it better.


This is the script written in Visual Basic 2008

Private Sub LinkLabel3_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles LinkLabel3.LinkClicked

        On Error GoTo erweb1

        Dim web As New WebClient
        Dim Update As String = web.DownloadString("https://docs.google.com/document/d/1J5czjH1cyhHSGc2ZVhWL8qGNU7j6hrTQhTS6c5ZWlIk/edit?usp=sharing")

        If Update.Contains(Application.ProductVersion) Then
            MsgBox("No new version found.", MsgBoxStyle.Information)
            anavathisi = False

        Else
            MsgBox("New version found.", MsgBoxStyle.Information)
            anavathisi = True
        End If


        Exit Sub
erweb1:
        MsgBox("No connection")
        Exit Sub


    End Sub

Nothing will come of it, since MVDB does not have a WebClient component or its equivalent.

809

(2 replies, posted in General)

https://blu-ray-rezensionen.net/wp-content/uploads/2018/07/Mission-Impossible-4K-UHD-Blu-ray-Review-Szene-1.jpg

Вам нужно пробежать в цикле по таблице с мультиселектом, и для каждой выделенной строки выполнить свою SQL-команду INSERT.

811

(13 replies, posted in General)

v_pozidis wrote:

ok k245 thank's for your help
I have a script which works in Visual Basic (2008 Express). The file that I use is from the Google Word, it;s not an uploaded file.
Can I send you the script and "translate" it in pascal ? I do not have this knowledge

I can try )))

812

(13 replies, posted in General)

v_pozidis wrote:

Hi k245 a question for you. How can I use the google drive for that or the google word. Can you send an example?

About years ago, Google closed the possibility of direct access to its files, so you won’t be able to get a file from a Google drive by simply downloading it. Requires the use of the API. I don't have a solution. Authorization seems especially difficult to me. But perhaps other forum members will be able to share their experience in this direction.

813

(13 replies, posted in General)

StateOne wrote:

hello k245
any new about dmitry??

I'm sorry, but I don't have any news about him. The last time we talked on Skype was in January of this year. He's online, so he's most likely alive smile

814

(13 replies, posted in General)

To implement such functionality, you will need a lot of code, for example, this:

procedure CheckAndUpdate( AShowIfNotFound: boolean );
// проверить обновления и обновить
var
  tmpNewVersion:string;
begin
  case CheckNewVersion(tmpNewVersion) of
  CU_ERROR: ShowMessage( S_.UPD_ERROR.Caption ); // общая ошибка
  CU_NEW_VERSION_AVALIABLE: begin // доступна новая версия, доступно автообновление
    if MessageBox( Format( S_.UPD_NEW_VER.Caption, [tmpNewVersion] ), S_.INFORMATION.Caption, MB_YESNO + MB_ICONINFORMATION ) = IDYES then
      GetNewVersion(tmpNewVersion);
  end;
  CU_NO_UPDATES_FOUND: if AShowIfNotFound then ShowMessage( S_.UPD_NO_UPDATES_FOUND.Caption ); // обновления не найдены
  CU_MANUAL_UPDATE: begin // ручное обновление
    if MessageBox( Format( S_.UPD_MANUAL_UPDATE.Caption, [tmpNewVersion] ), S_.INFORMATION.Caption, MB_YESNO + MB_ICONINFORMATION ) = IDYES then
        OpenURL( S_.ACT_URL_HELP.Caption ); // возможно, понадобится отдельный ресурс, пока используется один и тот, же, что для описания программы
  end;
  CU_CHECK_INTERNET:ShowMessage( S_.UPD_CHECK_CONNECTION.Caption ); // нет соединения с сайтом
  end;
end;

...and this

function CheckNewVersion(var ANewVersion:string ): integer;
// проверка наличия новой версии. извлечение номера новой версии
var
  tmpFile: string; // для загрузки описания обновления
  tmpList: TStringList; // сценарий обновления
  tmpBuld: string; // последний релиз
  tmpCompVer: array of string; // список версий, с которыми совместима последняя версия
  i: integer;
  tmpCurVer: string;
  tmpURL: string;
begin
  Result := CU_ERROR;
  tmpCurVer := APP_VERSION+'.'+APP_BUILD; // текущая версия приложения
  tmpFile := GetTmpFileName('.txt');
  try
    //
    if DebugMode then
      tmpURL := URL_DEBUG_DOWNLOAD + UPDATE_SCENARIO_FILENAME
    else
      tmpURL := URL_DOWNLOAD + UPDATE_SCENARIO_FILENAME;
    // скачать файл с описанием обновления
    try
      HTTPGetFile(tmpURL, tmpFile, True );
    except
      Result := CU_CHECK_INTERNET;
      exit;
    end;
    tmpList := TStringList.Create;
    tmpList.LoadFromFile(tmpFile);
    ANewVersion := tmpList.Values( UT_LAST_VERSION ); // версия в формате <Major>.<Minor>.<Build>
    //
    tmpBuld := ANewVersion;
    delete(tmpBuld,1,pos('.',tmpBuld ));
    delete(tmpBuld,1,pos('.',tmpBuld ));
    // сравниваем билды
    if StrToInt(tmpBuld) > StrToInt(APP_BUILD) then
    begin // найдена новая версия
      Result := CU_MANUAL_UPDATE;
      tmpCompVer := SplitString( tmpList.Values( UT_COMPATIBLE_VERSIONS ), ',' );
      for i := 0 to Length(tmpCompVer) - 1 do
        if tmpCompVer[i] = tmpCurVer then
        begin
          Result := CU_NEW_VERSION_AVALIABLE; // версия может быть загружена автоматически
          break;
        end;
    end
    else
      Result := CU_NO_UPDATES_FOUND; // ничего не найдено
    // зачистка
    tmpList.Free
    //
  finally
    DeleteFile(tmpFile); // удалить временный
  end;
end;

...and more.


You will also need your own website, where you will need to place a text information file. In this file, store scripts for versioning and updating them.

Dear colleagues! I receive applications from you for access to the files of the My Visual Database library ( https://mvdlibrary.blogspot.com ) , but due to the current difficulties in transferring money to Russia, I am ready to provide a year's access in exchange for any 64 GB flash drive. Please fill out the registration form, indicating your email from Google there to provide access.

https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj09kuQkM2fYk4Q-ZGsL-UvOtd_ADqToRxYoqXjvviuxrCDFh7N1exlmN73cVXBFMpbpMndTxM6rZSYLY9Hl63pZUpEanZCEZgs0Djegg-rdC26Tsw6Qasroc_e7WA_djIMxiSmBdAlhIKgZqWB0RIMHQN70ZAs3oKQeIT-xsHscAXDov2UegevDW333Q/w200-h186/%D1%84%D0%BB%D0%B5%D1%88%D0%BA%D0%B0.png

If you want to read library books and articles in English or other languages, please use Google translator. I still won't do a better translation than these cool guys wink


P.S. The flash drive offer is valid for all readers, regardless of language, gender, place of residence and religion big_smile

voron_rvv wrote:

Нууууу до своего приложения на своем Дельфи еще далеко. ))))) Я уж потихоньку Ваше приложение поизучаю.))))
На ваши уроки/статьи скидка не планируется?

А зачем же вам свой FastReport? На какой платформе вы его использовали?


У My Visual Database есть автор - Дмитрий. Я занимаюсь только популяризацией этого проекта, пишу книги и статьи по программированию на данной платформе.


На сегодня (28.03.2022) стоимость годового абонемента составляет всего 999 рублей. Это более 500 страниц для обучения, с примерами и пояснениями. То есть вы получаете доступ к электронным версиям этих документов, включая скачивание в удобных для вас форматах.


Так что стоимость на мой взгляд вполне адекватная и по мере роста библиотечных фондов она будет только увеличиваться ;-)

Галерея изображений


https://blogger.googleusercontent.com/img/a/AVvXsEjVl1MPt85CBNo5TDrp3X2jCWVT34lkPWIJ0LsU5dM9uMV0bvxDiZtqY-IYcEnz-e95rm6RKvHZw4f6DNgdwLK2RgeCDkXbpS_xF2lFnUpxXRAL8Qf5Rpueyb7GYVQMP_O9KvO500AzFsPkB8hX4XV01rw3SUjY7P_OEb2rn8LpjToqqqxJgiALqxns=w640-h402


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


Читать: https://createmyvisualdatabaseapp.blogs … st_27.html

Никак. Либо пишите свое приложение на своем Дельфи со своим Fastreport и вызываете его, передавая нужные параметры в командной строке )))

voron_rvv wrote:

Кулинарная книга


Добрый день, Очень классная идея.
В статье есть ссылки на скачивание, но они не работают.

Благодарю! Ссылки исправил.

Семейный альбом


https://lh4.googleusercontent.com/5cdkzkkXoiuRTnJKb4rxYjTFp-ytHVA_ebY0rHrYx5LIDPK3uz083zqmRnzy6PdFi60aFGRd91X8ETu5ds9yzx2OIS5yhSUC_ms97YCJZsVedQ1s04NdsbVNOLduqvW0Tv4eJPVA=w640-h398


У каждого из нас имеется множество фотографий, хранящих память о наших близких, друзьях, родственниках, памятных событиях и красивых местах, которые мы посетили. Современная техника позволяет получать качественные фотографии с высоким разрешением быстро и легко, к тому же фотокамера теперь всегда под рукой - все современные мобильные телефоны имеют возможность делать снимки. И было бы здорово иметь простую и функциональную систему хранения и просмотра этих фотографий.


Читать:  https://createmyvisualdatabaseapp.blogs … st_23.html

sibprogsistem wrote:

smile
Вы меня опередили, я тоже хотел создать такую программу )))
 
а вообще идея хорошая

Не отказывайтесь от своего желания - программ должно быть много и разных )))

Кулинарная книга


https://lh6.googleusercontent.com/1glM6qK7Xc3b5NdICvFCnS4oWEgQxgx59cGR9DG-mm6r0fZgCbVOfgP4bIZiESY1b2HxCHte_N9InAJePr1s53SgbTiWifUS8ihKgyZAsOoPTWbrXhPUqwhxiPI4qrEhCw9EbTmmUB1b6ed88uw=w640-h426


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


Читать: https://createmyvisualdatabaseapp.blogs … -post.html

823

(2 replies, posted in General)

Doing any image conversions in MVD is possible only for bitmap. Pictures are usually stored in JPG or PNG. That is, the process should look like this: create a bitmap. The source image copied onto its canvas. A transformation is made (rotation, compression, color correction, etc.), and then the canvas is copied back into a JPG image.

http://myvisualdatabase.com/forum/misc.php?action=pun_attachment&amp;item=8503&amp;download=0

824

(2 replies, posted in Russian)

Если я правильно понял, речь идет о проверке, были ли внесены на форме какие-либо изменения в каждом элементе ввода данных. То есть в сравнении с исходными данными, которые были на форме редактирования в момент отображения. Я бы не стал делать именно триггер, так как в процессе изменения пользователь может многократно  менять данные, например, при наборе текста. Лучше иметь возможность в нужный момент узнать, были ли реальные изменения.


Это можно использовать для оптимизации процесса сохранения данных: если пользователь нажал кнопку "Сохранить", но никакие данные не вводил, то и сохранять ничего не нужно. Или наоборот: пользователь что-то поменял, а потом жмет кнопку "Отмена". Тогда можно предупредить его о том, что все изменения будут потеряны.


Готового решения у меня нет, но я бы сделал так.


1. В обработчике onShow пробежать по всем компонентам формы (свойство TForm.components[])   и в свойство TagStr записать текущее значение, при необходимости сконвертировав его в строку. Тут придется использовать проверку на класс (оператор is) и приведение к нужному типу. Это позволит создать один универсальный обработчик и подключить его ко всем формам редактирования.


2. В функции Form_isDataChange опять пробежать по всем компонентам и сравниmь текущее значение и свойство TagStr. Если есть различия, значит были изменения.


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

825

(14 replies, posted in General)

To call Dmitry, it is not enough to repeat his name, sacred ritual actions are required.
http://myvisualdatabase.com/forum/misc.php?action=pun_attachment&amp;item=8502&amp;download=0