Блог обо всём на свете
пятница, 21 марта 2025 г.
Access violation at address XXXXYYYY in module 'rtl260.bpl'
вторник, 25 октября 2022 г.
Установка SDK Linux
1) взять соответствующий PAServer (у меня находится в C:\Program Files (x86)\Embarcadero\Studio\20.0\PAServer\LinuxPAServer20.0.tar) 2) перенести LinuxPAServer20.0.tar на машину с линуксом (в моём случае это виртуалка с Ubuntu 21.04), распаковать архив 3) с помощью BASH перейти в папку с распакованным архивом и запустить paserver 4) в IDE выбрать пункт меню Tools -> Options -> Deployment -> Add, заполнить "Profile name" и "Platform", нажать Next 5) заполнить ip-адрес машины с линуксом (в моем случае это 192.168.1.37), проверить соединение, нажав "Test connection" 6) в IDE выбрать пункт меню Tools -> Options -> SDK Manager -> Add, заполнить соответствующие поля Затем начнется установка SDK для компиляции под Linux. Когда она будет закончена, появится соответствующее сообщение. Виртуальная машина с линуксом больше не нужна.
воскресенье, 22 мая 2022 г.
Утечка FastReport
За последний месяц ине пришлось исправить одну ошибку в модулей сериализации, одну в библиотеке EhLib, а теперь вот проблемы с FastReport!
Работая с отчетом, содержимое которого экспортируется в Excel, я заметил, что после закрытия программы FastMM ругается на утечки памяти:
Я решил попробовать поискать в исходниках по строчке "TfrxIEMStyle.Create" и вот что обнаружилось
В конструкторе этого объекта как раз выделялась память, которая очень была похожа по описанию, которое выдал FastMM
Потом я просто стал проверять, все найденные участки кода и в самом последнем обнаружил выделение памяти, которое впоследствии не освобождалось
Вылечилось это элементарным добавлением вызова деструктора
Ну и конечно же надо пересобрать компоненты FastRerpot'а с помощью их утилиты
понедельник, 17 мая 2021 г.
Проблема с IP*Works
Таким образом, демонстрационный пример для скачивания вложений в письме с помощью Ip*Works выглядит так:
program Demo;
{$APPTYPE CONSOLE}
{$R *.res}
uses
ipwCore,
ipwIMAP,
ipwtypes,
System.SysUtils;
var
ImapHandle: TipwIMAP;
procedure InitImap();
begin
ImapHandle.MailServer :=
ImapHandle.MailPort :=
ImapHandle.User :=
ImapHandle.Password :=
ImapHandle.SSLEnabled := False;
ImapHandle.AutoDecodeParts := True;
ImapHandle.Config('UseAttachmentNameParam=false');
end;
begin
ImapHandle := TipwIMAP.Create(nil);
try
try
InitImap();
ImapHandle.Connect();
ImapHandle.Mailbox := 'INBOX';
ImapHandle.SelectMailbox();
for var I := ImapHandle.MessageCount - 1 downto ImapHandle.MessageCount - 1 do
begin
ImapHandle.MessageSet := i.ToString();
ImapHandle.FetchMessageInfo();
WriteLn('Id : ' + ImapHandle.MessageId);
WriteLn('From : ' + ImapHandle.MessageFrom);
WriteLn('Subject : ' + ImapHandle.MessageSubject);
WriteLn('Flags : ' + ImapHandle.MessageFlags);
WriteLn('ContentType: ' + ImapHandle.MessageContentType);
WriteLn('Size : ' + ImapHandle.MessageSize.ToString);
WriteLn('');
for var j := 0 to ImapHandle.MessageParts.Count - 1 do
begin
if ImapHandle.MessageParts[j].Filename <> '' then
begin
WriteLn(' Id : ' + ImapHandle.MessageParts[j].Id);
WriteLn(' ContentId : ' + ImapHandle.MessageParts[j].ContentId);
WriteLn(' Filename : ' + ImapHandle.MessageParts[j].Filename);
WriteLn(' ContentType : ' + ImapHandle.MessageParts[j].ContentType);
WriteLn(' Size : ' + ImapHandle.MessageParts[j].Size.ToString);
WriteLn('');
end
end
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
finally
FreeAndNil(ImapHandle);
end;
Write(#13#10 + 'press any key to continue...');
ReadLn;
end.
среда, 12 мая 2021 г.
Сборка OpenCV
0) Проблема: требуется установить opencv 2.4.13 и настроить для работы в VS 2017
(в дистрибутиве OpenCV собранные бинарники для VC11, VC12 не прилинкуются в новой студии, значит надо собирать из исходников)
1) Качаем последний cmake с сайта https://cmake.org/download/
https://github.com/Kitware/CMake/releases/download/v3.18.0/cmake-3.18.0-win64-x64.msi
2) Устанавливаем cmake в каталог студии (у меня там стоял предыдущий cmake версии 3.12.0, поставленный инсталлятором),
0 просто заменяя папку CMake (если такой папки нет, то можно ставить куда угодно)
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake
3) Качаем opencv-2.4.13.exe и распаковываем в C:/opencv-2-4-13
4) Запускаем "Командная строка для разработчика VS 2017" (если CMake был поставлен в другую папку, то надо в Path прописать до неё путь)
5) Набираем
> cmake --version
Должно выдать
> cmake version 3.18.0
6) Проверяем генераторы, набираем
> cmake -G
Должно выдать полный список генераторов. Поскольку у нас VS 2017 и Win32, то там это должно быть
(за подробностями в документацию https://cmake.org/cmake/help/v3.18/generator/Visual%20Studio%2015%202017.html)
7) Переходим в каталог C:/opencv2/sources, там должен быть файл CMakeLists.txt, набираем (если хотим собрать Win32 для opencv)
> cmake . -G "Visual Studio 15 2017" -A Win32
8) В студии открыть OpenCV.sln, пересобрать проект ALL_BUILD (Win32 Debug)
9) Создать
C:\opencv-2-4-13\build\Debug\Win32\bin
C:\opencv-2-4-13\build\Debug\Win32\lib
C:\opencv-2-4-13\build\include
10) Скопировать в эти каталоги содержимое
C:\opencv-2-4-13\build\Debug\Win32\bin:
C:\opencv-2-4-13\sources\bin\Debug
C:\opencv-2-4-13\build\Debug\Win32\lib:
C:\opencv-2-4-13\sources\lib\Debug
C:\opencv-2-4-13\build\include:
C:\opencv-2-4-13\sources\include
C:\opencv-2-4-13\sources\modules\calib3d\include
C:\opencv-2-4-13\sources\modules\contrib\include
C:\opencv-2-4-13\sources\modules\photo\include
(Если прикомпиляции не будут найдены ещё какие-то файлы .h или .hpp надо их найти и прописать сюда путь до них)
11) Создать пустой проект С++, добавить новый файл main.cpp
12) Внутри файла:
#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
namedWindow("Win");
waitKey(0);
return 0;
}
13) Правой кнопкой мыши по проекту
Проект -> Свойства -> Каталоги VC++
Каталоги исполняемых файлов -> C:\opencv-2-4-13\build\Debug\Win32\bin
Включаемые каталоги -> C:\opencv-2-4-13\build\include
Каталоги библиотек -> C:\opencv-2-4-13\build\Debug\Win32\lib
Компоновщик
Общие -> Дополнительные каталоги библиотек -> C:\opencv-2-4-13\build\Debug\Win32\lib
Ввод -> Дополнительные зависимости -> указываем всё, что есть в /lib, а именно:
opencv_calib3d2413d.lib
opencv_contrib2413d.lib
opencv_core2413d.lib
opencv_features2d2413d.lib
opencv_flann2413d.lib
opencv_gpu2413d.lib
opencv_haartraining_engined.lib
opencv_highgui2413d.lib
opencv_imgproc2413d.lib
opencv_legacy2413d.lib
opencv_ml2413d.lib
opencv_nonfree2413d.lib
opencv_objdetect2413d.lib
opencv_ocl2413d.lib
opencv_photo2413d.lib
opencv_stitching2413d.lib
opencv_superres2413d.lib
opencv_ts2413d.lib
opencv_video2413d.lib
opencv_videostab2413d.lib
События сборки -> События после сборки -> Командная строка -> xcopy /y /d "C:\opencv-2-4-
13\build\Debug\Win32\bin\*.dll" "$(OutDir)"
14) Проверка
#include <opencv2\opencv.hpp>
using namespace cv;
int main()
using namespace cv;
using namespace std;
int main()
{
namedWindow("Win");
waitKey(0);
// задаём высоту и ширину картинки
int height = 620;
int width = 440;
// задаём точку для вывода текста
CvPoint pt = cvPoint(height / 4, width / 2);
// Создаёи 8-битную, 3-канальную картинку
IplImage* hw = cvCreateImage(cvSize(height, width), 8, 3);
// заливаем картинку чёрным цветом
cvSet(hw, cvScalar(0, 0, 0));
// инициализация шрифта
CvFont font;
cvInitFont(&font, CV_FONT_HERSHEY_COMPLEX, 1.0, 1.0, 0, 1, CV_AA);
// используя шрифт выводим на картинку текст
cvPutText(hw, "OpenCV Step By Step", pt, &font, CV_RGB(150, 0, 150));
// создаём окошко
cvNamedWindow("Hello World", 0);
// показываем картинку в созданном окне
cvShowImage("Hello World", hw);
// ждём нажатия клавиши
cvWaitKey(0);
// освобождаем ресурсы
cvReleaseImage(&hw);
cvDestroyWindow("Hello World");
//cout << "\r\npress any key to continue...";
//cin.get();
return 0;
}
вторник, 12 января 2021 г.
Создаем системный хинт
Начиная с Delphi 2009 у компонента TEdit появилось замечательное булевое свойство "NumbersOnly". Его роль понятна из названия - ограничения вводимых символов (только цифры). При попытке ввести иной символ всплывает системный хинт:
Данный хинт является системным, т.е. генерируется самой ОС Windows. Если мы хотим повесить такой хинт на определенные события, придётся создавать его "вручную". Т.е. с помощью API-функций для работы с окнами.
Создадим три процедуры: для создания хинта, для его показа и для сокрытия/удаления:
const
TOOLTIPS_CLASS = 'tooltips_class32';
TTS_ALWAYSTIP = $01;
TTS_NOPREFIX = $02;
TTS_BALLOON = $40;
TTF_SUBCLASS = $0010;
TTF_TRACK = $0020;
TTF_TRANSPARENT = $0100;
TTF_CENTERTIP = $0002;
TTM_ACTIVATE = WM_USER + 1;
TTM_ADDTOOL = WM_USER + 50;
TTM_TRACKACTIVATE = WM_USER + 17;
TTM_TRACKPOSITION = WM_USER + 18;
TTM_SETTITLE = WM_USER + 32;
var
ToolTipHandle: Cardinal;
ToolInfo: TToolInfo;
procedure CreateToolTips();
var
vRect: TRect;
begin
ToolTipHandle := CreateWindowEx(WS_EX_TOPMOST,
TOOLTIPS_CLASS,
nil,
WS_POPUP or TTS_NOPREFIX or TTS_BALLOON or TTS_ALWAYSTIP,
Integer(CW_USEDEFAULT),
Integer(CW_USEDEFAULT),
Integer(CW_USEDEFAULT),
Integer(CW_USEDEFAULT),
Application.Handle,
0,
Application.Handle,
nil);
GetWindowRect(Application.Handle, &vRect);
end;
procedure AddToolTip(Sender: TObject; IconType: Integer; Title: AnsiString; Text: PWideChar);
var
vControl: TWinControl;
vCaretPos: TPoint;
X, Y: Integer;
begin
vControl := Sender as TWinControl;
if ToolTipHandle = 0 then
exit();
SetWindowPos(ToolTipHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
ToolInfo.cbSize := SizeOf(TToolInfo);
ToolInfo.uFlags := {TTF_CENTERTIP or} TTF_TRACK or TTF_TRANSPARENT or TTF_SUBCLASS;
ToolInfo.hwnd := vControl.Handle;
ToolInfo.hInst := Application.Handle;
GetClientRect(ToolInfo.hwnd, ToolInfo.Rect);
ToolInfo.lpszText := Text;
GetCaretPos(vCaretPos);
X := vControl.ClientOrigin.X + vCaretPos.X;
Y := vControl.ClientOrigin.Y + vControl.ClientHeight - vCaretPos.Y;
SendMessage(ToolTipHandle, TTM_ADDTOOL, WPARAM(1), LPARAM(@ToolInfo));
SendMessage(ToolTipHandle, TTM_SETTITLE, IconType, LPARAM(PWideChar(Title)));
SendMessage(ToolTipHandle, TTM_TRACKPOSITION, WPARAM(0), LPARAM(MakeLong(X, Y)));
SendMessage(ToolTipHandle, TTM_TRACKACTIVATE, WPARAM(1), LPARAM(@ToolInfo));
end;
procedure HideToolTip();
begin
SendMessage(ToolTipHandle, TTM_TRACKACTIVATE, WPARAM(0), LPARAM(@ToolInfo));
SendMessage(ToolTipHandle, TTM_DELTOOL, WPARAM(0), LPARAM(@ToolInfo));
end;
При создании формы создаем наш хинт, показывать его будем в событии OnKeyPress у TEdit'а, ну а закрывать по таймеру
procedure TForm1.edtLogKeyPress(Sender: TObject; var Key: Char);
begin
if not charinset(Key,['0'..'9', ',', #8]) then
begin
MessageBeep(MB_ICONWARNING);
AddToolTip(Sender, 3, 'Недопустимый символ', 'Разрешены только цифры и запятая');
Timer.Enabled := True;
Key := #0;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
CreateToolTips();
end;
procedure TForm1.TimerTimer(Sender: TObject);
begin
HideToolTip();
Timer.Enabled := False;
end;
Получаемый результат:
понедельник, 21 декабря 2020 г.
Про частично определенные модули
Не всегда к имени модуля бывает добавлен префикс - имя области действия этого модуля. Я стараюсь писать программы так, чтобы все модули всегда включали такой префикс. Но как быть со сторонними модулями?
Рассмотрим случай, когда требуется использовать библиотеку OExport в консольном проекте (Embarcadero RAD Studio 10.3.3). Для этого в тестовом примере консольного приложения я подключил модули OExport.pas и OExport_VCL.pas (также я добавил модуль MemTableEh.pas библиотеки EhLib).
Код тестового примера:
При компиляции получаю ошибку, связанную с неразрешенностью компилятором частично определенных имен модулей в OExport_VCL: Компилятор не понимает к чему относится модуль Graphics - к Vcl.Graphics или FMX.Graphics (аналогичная ошибка, если закомментировать OExport_VCL в секции uses, будет с модулем Controls в модуле DBGridEh.pas).