Here's the Tic-Tac game project made for MVD 5.6. If anyone wants to improve it, feel free. If anyone knows how I can set up the Sudoku, they're welcome!
52 2025-09-23 16:07:25
Re: Justify text alignment in memo field (4 replies, posted in General)
Hi Derek, Roberto
Roberto ,
Memo supports left, center and right alignment. Unfortunately, it doesn't support justified text alignment.
Memo displays information as plain text, and the only way to do this is by adding extra spaces between words,
and it's only for viewing. Character widths vary across fonts. We'll need to calculate word widths, etc. Maybe I'll give it a try.
For now, I've tried this:
To view notes, you can try using RichEdit, as in the example below. It uses justified text alignment. You can change the font and its size.
It's just a window similar to Memo. The downside is that RichEdit requires manual output processing
(for example: Form1.RichEdit.Text := SQLExecute (' SELECT text FROM ....' ). Accordingly, saving text from RichEdit also requires
manual processing.
Whether the game is worth the effort is up to you.
Hi Sparrow and Derek! I was familiar with justified alignment in RTF. I saw that in MEMO this is complicated, because RTF aligns by increasing the space size...but thank you both for your intention.
53 2025-09-22 14:13:59
Topic: Justify text alignment in memo field (4 replies, posted in General)
Has anyone created a script to justify text in a memo field?
54 2025-09-14 22:21:22
Re: Trendline on Bar Chart (MVD 5.6) (14 replies, posted in General)
Now the trend line is for line chart.
Var
ChartLine : TChart;
procedure Form1_bLinUpdate_OnClick (Sender: TObject; var Cancel: boolean);
//*** Proc 1334 - LINHA DE TENDÊNCIA GRÁFICO DE LINHA - CHATGPT
var
Results : TDataSet;
DateValue : Double; // valor TDateTime vindo do SQL
sValor : String;
yVal : Double;
// somatórios para regressão (usamos X deslocado = Data - BaseDate)
sumX, sumY, sumXY, sumX2: Double;
n: Integer;
a, b: Double; // coeficientes da reta y = a*Xoffset + b
BaseDate, FirstDate, LastDate: Double;
Xoffset: Double;
Trend: TLineSeries;
begin
// Garante que exista ao menos uma série para os valores
if ChartLine.SeriesCount = 0 then
ChartLine.AddSeries(TLineSeries.Create(ChartLine));
// Limpa série de valores
ChartLine.Series[0].Clear;
// Assegura que exista a série 1 para a tendência e que seja TLineSeries
if ChartLine.SeriesCount < 2 then
ChartLine.AddSeries(TLineSeries.Create(ChartLine))
else if not (ChartLine.Series[1] is TLineSeries) then
begin
ChartLine.Series[1].Free;
ChartLine.AddSeries(TLineSeries.Create(ChartLine));
end;
Trend := TLineSeries(ChartLine.Series[1]);
Trend.Clear;
Trend.SeriesColor := clRed;
Trend.Title := 'Tendência';
// Formatação do eixo X como data (ajuste visual)
ChartLine.Axes.Bottom.LabelStyle := talValue;
ChartLine.Axes.Bottom.DateTimeFormat := 'dd/mm/yyyy';
ChartLine.Axes.Bottom.LabelsAngle := 90;
ChartLine.Legend.Visible := True;
// Inicializa acumuladores
sumX := 0; sumY := 0; sumXY := 0; sumX2 := 0;
n := 0;
BaseDate := 0; FirstDate := 0; LastDate := 0;
// Query (ordem ASC para cronologia)
SQLQuery(
'SELECT Data, valor FROM tbl_medicoes WHERE'+
' id_tbl_parametros = '+IntToStr(Form1.cbo_parametro.dbItemID)+' and id_tbl_usuarios = '+IntToStr(Form1.cbo_user.dbItemID)+
' and Data >= '+Form1.dt_ano_mes_ini.sqlDate+' and Data <= '+Form1.dt_ano_mes_fim.sqlDate+' and'+
' case when length("'+Form1.cbo_sit.Text+'") = 0 then 1=1 else id_tbl_situacao = ' + IntToStr(Form1.cbo_sit.dbItemID)+' end and'+
' case when length("'+Form1.cbo_status.Text+'") = 0 then 1=1 else id_tbl_status = ' + IntToStr(Form1.cbo_status.dbItemID)+' end'+
' ORDER BY Data ASC',
Results
);
// Percorre resultados — plota pontos e acumula para regressão (usando offset de data)
while not Results.Eof do
begin
DateValue := SQLDateTimeToDateTime(Results.FieldByName('Data').AsString);
sValor := Results.FieldByName('valor').AsString;
// tenta converter o valor (aceita "12,5" ou "12.5")
try
yVal := StrToFloatLocale(sValor);
except
// se não for número válido, ignora este registro
Results.Next;
Continue;
end;
// primeira data define base (offset = 0)
if n = 0 then
begin
BaseDate := DateValue;
FirstDate := DateValue;
end;
LastDate := DateValue;
Xoffset := DateValue - BaseDate; // em dias (Double)
// adiciona ponto real no gráfico (eixo X = DateValue)
ChartLine.Series[0].AddXY(DateValue, yVal);
// acumula somatórios usando Xoffset
sumX := sumX + Xoffset;
sumY := sumY + yVal;
sumXY := sumXY + (Xoffset * yVal);
sumX2 := sumX2 + (Xoffset * Xoffset);
Inc(n);
Results.Next;
end;
// calcula regressão (mínimos quadrados) sobre Xoffset
if n > 1 then
begin
// coeficiente angular a e intercepto b (em relação a Xoffset)
a := (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
b := (sumY - a * sumX) / n;
// Desenha a linha de tendência usando as datas reais (primeira e ultima)
// yParaFirst = a*(FirstDate-BaseDate) + b (FirstDate-BaseDate = 0)
Trend.AddXY(FirstDate, a * 0 + b, '', clRed);
Trend.AddXY(LastDate, a * (LastDate - BaseDate) + b, '', clRed);
end;
// Títulos para a legenda
ChartLine.Series[0].Title := 'Valores';
Trend.Title := 'Tendência';
end;
// Função auxiliar que tenta converter string float aceitando pontos ou vírgulas
function StrToFloatLocale(const S: string): Double;
var
s1: string;
begin
// tenta conversão direta (sistema local)
try
Result := StrToFloat(S);
Exit;
except end;
// tenta trocar '.' por ',' (ex.: "2.25" -> "2,25")
s1 := ReplaceStr(S, '.', ',');
try
Result := StrToFloat(s1);
Exit;
except end;
// tenta trocar ',' por '.'
s1 := ReplaceStr(S, ',', '.');
Result := StrToFloat(s1);
end;
procedure Form1_OnShow (Sender: string; Action: string);
begin
// CHARTLINE====================================================================
ChartLine := TChart.Create(Form1);
ChartLine.Parent := Form1.Panel1;
ChartLine.Align := alClient;
ChartLine.AddSeries(TLineSeries.Create(ChartLine));
ChartLine.Series[0].XValues.DateTime := True;
ChartLine.BottomAxis.LabelsAngle := 90;
end;
function ReplaceStrEx(AText, FromText, ToText: string): string;
var //*** Proc 60 - replace por Dmitry
ArStr: array of string;
i, c: integer;
begin
ArStr := SplitString(FromText, ',');
c := Length(ArStr)-1;
for i := 0 to c do
begin
AText := ReplaceStr(AText, ArStr[i], ToText);
end;
result := AText;
end;55 2025-09-14 19:57:03
Re: Trendline on Bar Chart (MVD 5.6) (14 replies, posted in General)
Hi jrga
This proves that what we feared is going to happen.
AI is going to destroy a lot of jobs, first and foremost the entire
world of programmers.
You Give us an example.
JB
Hi JB, AI makes a lot of mistakes! In the case of the trendline, I had to explain what I wanted it to do several times. It made mistakes and repeated some errors. I had to correct parts of the generated script, including the final script. I provided a starting script containing a function created by Dmitry himself (ReplaceStrEx). The AI insisted on giving this function a different name. It takes time to get a result, which often occurs through trial and error. It can help in some cases and speed up problem-solving, but only occasionally. I doubt it will ever fully replace the work of a programmer.
56 2025-09-14 14:35:38
Topic: Trendline on Bar Chart (MVD 5.6) (14 replies, posted in General)
Eureka! I managed to add a trendline to a bar chart (MVD 5.6) with the help of ChatGPT. I searched the forum for a solution, but couldn't find one.
Var
ChartBar: TChart;
procedure Form1_OnShow (Sender: string; Action: string);
begin
// CHARTBAR====================================================================
ChartBar := TChart.Create(Form1);
ChartBar.Parent := Form1.PanelBar;
ChartBar.Align := alClient;
ChartBar.AddSeries(TBarSeries.Create(ChartBar));
TBarSeries(ChartBar.Series[0]).Marks.Visible := False;
ChartBar.Axes.Bottom.LabelsAngle := 90;
ChartBar.View3DOptions.Zoom := 90; // Ajuste o zoom para caber todos os labels
ChartBar.Legend.Visible := true;
Form1.bBarUpdate.Click;
end;
procedure Form1_bBarUpdate_OnClick (Sender: TObject; var Cancel: boolean);
var
Results: TDataSet;
sData: string;
sValue: string;
x: integer;
sumX, sumY, sumXY, sumX2: Double;
n: Integer;
a, b: Double; // Coeficientes da reta Y = aX + b
firstX, lastX: Integer;
begin
ChartBar.Series[0].Clear;
if ChartBar.SeriesCount < 2 then
ChartBar.AddSeries(TLineSeries.Create(ChartBar)); // cria série p/ tendência
ChartBar.Series[1].Clear; // limpa a linha de tendência
TLineSeries(ChartBar.Series[1]).SeriesColor := clRed; // cor da tendência
x := 1;
sumX := 0;
sumY := 0;
sumXY := 0;
sumX2 := 0;
n := 0;
SQLQuery('SELECT strftime("%d/%m/%Y",Data) as DMA, valor FROM tbl_medicoes WHERE'+
' id_tbl_parametros = '+inttostr(form1.cbo_parametro.dbItemID)+' and id_tbl_usuarios = '+inttostr(form1.cbo_user.dbItemID)+
' and Data >= '+form1.dt_ano_mes_ini.sqlDate+' and Data <= '+form1.dt_ano_mes_fim.sqlDate+' and'+
' case when length("'+form1.cbo_sit.text+'") = 0 then 1=1 else id_tbl_situacao = ' + inttostr(form1.cbo_sit.dbItemID)+' end and'+
' case when length("'+form1.cbo_status.text+'") = 0 then 1=1 else id_tbl_status = ' + inttostr(form1.cbo_status.dbItemID)+' end'+
' ORDER BY Data ASC', Results);
while not Results.Eof do
begin
sData := Results.FieldByName('DMA').asString;
sValue := Results.FieldByName('valor').asString;
if sValue <> '' then
begin
ChartBar.Series[0].AddXY(
x,
StrToFloat(ReplaceStr(sValue, '.', ',')),
sData,
RandomColor()
);
// acumula p/ regressão linear
sumX := sumX + x;
sumY := sumY + StrToFloat(ReplaceStrEx(sValue, '.', ','));
sumXY := sumXY + (x * StrToFloat(ReplaceStrEx(sValue, '.', ',')));
sumX2 := sumX2 + (x * x);
Inc(n);
if n = 1 then firstX := x;
lastX := x;
end;
Results.Next;
Inc(x);
end;
// calcula coeficientes da reta
if n > 1 then
begin
a := (n*sumXY - sumX*sumY) / (n*sumX2 - sumX*sumX); // inclinação
b := (sumY - a*sumX) / n; // intercepto
// adiciona 2 pontos extremos p/ desenhar linha de tendência
ChartBar.Series[1].AddXY(firstX, a*firstX + b, 'Tendência', clRed);
ChartBar.Series[1].AddXY(lastX, a*lastX + b, '', clRed);
end;
ChartBar.Series[0].Title := 'Valores';
ChartBar.Series[1].Title := 'Tendência';
end;
function ReplaceStrEx(AText, FromText, ToText: string): string;
var //*** Proc 60 - replace por Dmitry
ArStr: array of string;
i, c: integer;
begin
ArStr := SplitString(FromText, ',');
c := Length(ArStr)-1;
for i := 0 to c do
begin
AText := ReplaceStr(AText, ArStr[i], ToText);
end;
result := AText;
end;
function RandomColor: TColor;
begin // Função para gerar uma cor aleatória em barras dos gráficos
Result := RGB(Random(256), Random(256), Random(256));
end;57 2025-09-09 22:32:34
Re: How to handle a value with decimal places in SQL (2 replies, posted in General)
Hi Roberto
Yes, there is such a problem.
I make a replacement in the script and substitute the value into the query.
It will be something like this:rIndice := ReplaceStr(floattostr(form1.Edit_valor.Value),',','.'); cbo_status := sqlexecute( ' select id_tbl_status from tbl_referencias where '+ ' id_tbl_situacao = 1 and id_tbl_parametros = 1 and '+ ' '+rIndice+' between minimo and maximo');If you do not use a thousand separator, you can simplify it.
rIndice := ReplaceStr(form1.Edit_valor.Text,',','.');
Sparrow, tank you!
58 2025-09-09 19:36:08
Topic: How to handle a value with decimal places in SQL (2 replies, posted in General)
How to handle a value with decimal places, coming from a form field, which uses a comma as a separator, in an SQL statement.
rIndice := form1.Edit_valor.Value;
cbo_status := sqlexecute(
' select id_tbl_status from tbl_referencias where '+
' id_tbl_situacao = 1 and id_tbl_parametros = 1 and '+
' CAST(REPLACE("'+floattostr(rIndice)+'", ",", ".") AS REAL) '+
' between minimo and maximo');59 2025-09-07 22:28:30
Re: Project protection (9 replies, posted in General)
With avast free version it orks fine, with bit defender and Kaspersky paid versions it stop compiling and warn for virus. I um sure that it must be a false alarm. Does anyone has the same problem and how can we solve it to make the compiled file to be us a clean one, because when the antivirus scan it it delete the file
I have to tell Avast that an MVD application is an exception, always the first time I run it... The problem is the end user encountering this, not understanding what is happening and making the wrong decision....
60 2025-09-04 17:33:27
Re: Project protection (9 replies, posted in General)
Enigma Virtual Box
It works! I've tested it.
61 2025-08-28 21:53:24
Re: Track your blood sugar ! (19 replies, posted in General)
Finally, I thought it was important to include the ability to print the table grid's content (filtered or not) using the "print" button. This will make it easier if the user needs to show a report of the measurements they took to their doctor.
62 2025-08-28 15:11:44
Re: Track your blood sugar ! (19 replies, posted in General)
Hi Jean, Roberto
Ok. )
In order for the program to work and not stop by error in version 6.5 (what I checked), some changes need to be made.1. Change in the "Form1_OnShow" procedure. The diagram initialization must occur before accessing them in the checkboxes. Otherwise, an error.
2. When selecting the year filter (cbo_ano), the year value disappears after updating the tables and graphs. That is why a small correction to the query was suggested above.I am posting the corrected version so that users of new versions of MVD can launch and work with the program.
Best regards, sparrow.
Now I understand, thank you!
63 2025-08-28 13:33:53
Re: Track your blood sugar ! (19 replies, posted in General)
Hi Jean, I added a button to delete the contents of the DIABETE table, allowing a new user to start their measurement history. I also added a question at the end, "if a backup is made," if any changes were made to the database. I created the Help.chm with the MyNotesKeeper application.
Dear Sparrow, the SQLite statement you suggested for updating cbo_ano was already contained in the script... thanks anyway!
64 2025-08-27 21:10:46
Re: Track your blood sugar ! (19 replies, posted in General)
jrga wrote:Hi Jean, I found your project interesting! I adapted it to my needs (the most widely used language and metric for diabetes in Brazil). I've included a few modifications...
Hi Roberto
This will fix the display in the year filter (cbo_ano)
procedure Form1_cbo_ano_OnEnter (Sender: TObject); begin form1.cbo_ano.dbSQL := 'select distinct strftime("%Y", Date_Prise) id, strftime("%Y", Date_Prise) from diabete order by date_prise'; form1.cbo_ano.dbUpdate; end;
Thank you Sparrow!
65 2025-08-27 18:45:14
Re: Track your blood sugar ! (19 replies, posted in General)
Hi Jean, I found your project interesting! I adapted it to my needs (the most widely used language and metric for diabetes in Brazil). I've included a few modifications...
66 2025-08-23 20:19:03
Topic: Sharing some information... (0 replies, posted in Script)
The "compilation" of the MVD 5.6 project generates a file called "project_name.exe." I took this file (exe) and placed it in the folder of another MVD project, and when I ran it, the application in the new folder worked normally...
I thought that the EXE of an MVD project could only be run in the project for which it was "compiled." I've since concluded that I was wrong!
The "project_name.exe" is a "runtime" that executes an MVD application, requiring only the files: graphics.dll, sqlite3.dll, forms.xlm, settings.ini, tables.ini, script.pas, and sqlite.db to be contained in the same folder as the EXE?
I also noticed that the EXE file used in this case could have any name.
This doesn't diminish MVD's capabilities in any way. On the contrary, it simply demonstrates its versatility!
I'm not an expert on the subject and just wanted to share the information.
P.S.: This BAT was the only one that worked on Windows 11 and allows you to run any MVD application, having the EXE in another folder (single EXE)
@echo off
setlocal
REM Pega a pasta onde o .bat está
set "BATDIR=%~dp0"
REM Caminho do exe original
set "SRC=C:\run_mvd.exe"
REM Copia o executável para a pasta do bat
copy /Y "%SRC%" "%BATDIR%run_mvd.exe" >nul
REM Vai para a pasta do bat
cd /d "%BATDIR%"
REM Executa o programa e espera terminar
start "" /wait "run_mvd.exe"
REM Apaga o executável sem pedir confirmação
del /f /q "run_mvd.exe"
endlocal67 2025-08-06 15:08:30
Re: Поиск по двум и более полям одновременно в запросе (10 replies, posted in Russian)
I used this statement in a "SQL query" button
SELECT DISTINCT
Items.id AS ID,
CASE WHEN finalizado = 1 THEN '✔' ELSE ' ' END AS Ok,
Items.nome_item AS Item,
ItemsTree.Name AS Tree
FROM Items
INNER JOIN ItemsTree ON Items.id_ItemsTree = ItemsTree.id
LEFT OUTER JOIN tbl_table ON Items.id = tbl_table.id_Items
LEFT OUTER JOIN tbl_campos ON tbl_table.id = tbl_campos.id_tbl_table
LEFT OUTER JOIN tbl_fld_tipos ON tbl_fld_tipos.id = tbl_campos.id_tbl_fld_tipos
WHERE
IFNULL(Items.nome_item, '') ||
IFNULL(ItemsTree.Name, '') ||
IFNULL(Items.notas, '') ||
IFNULL(Items.texto_rtf, '') ||
IFNULL(tbl_table.nome_tabela, '') ||
IFNULL(tbl_table.descricao, '') ||
IFNULL(tbl_table.notas, '') ||
IFNULL(tbl_campos.name, '') ||
IFNULL(tbl_fld_tipos.Name, '') ||
IFNULL(tbl_campos.descricao, '') ||
IFNULL(tbl_campos.notas, '')
LIKE "%{Edit_busca}%"68 2025-08-06 13:45:15
Topic: Problems with displaying accented characters (0 replies, posted in General)
I created a second script in MVD, which is called by the main script through "uses script_name.pas." I placed messages in this second script with accents—for example, "Attention!"—and sometimes these characters aren't displayed correctly. How do I fix this?
COPILOT: (SOLVED!)
This issue with accents in MVD scripts is usually related to the character encoding used in the file and the code page of the terminal where it's executed. Here are some practical solutions to resolve this:
1. Use the correct encoding when saving the script
—UTF-8 without BOM is the most recommended.
—If you're using an editor like Notepad++, go to:
—Encoding → Convert to UTF-8 (without BOM)
—Then save the file again.
2. Avoid copying and pasting from external sources
Sometimes, when copying text from browsers or editors, accents appear in a different encoding. Type directly into the editor or use tools that clean up formatting.
69 2025-07-16 21:06:19
Topic: Freeware Portable application for data and application backup (0 replies, posted in General)
Great app for backing up data and MVD files, in the development phase - batch backup. Various synchronization options. I use the "mirror" option for synchronization. I also use the option to move files from the previous backup, which have undergone new modifications, to a folder "c:\my_mvd\%date%" (see macros option). Backs up to the cloud... numerous options. There are versions for OSX, Windows, and Linux. Link below
70 2025-07-16 15:58:28
Re: Move or hide columns natively in a tablegrid (7 replies, posted in General)
Hi Roberto, Konstantin,
Attached are a couple of suggestions that might help.
1. Hide Columns Persistent.
With this option, the selection of hidden columns is persistent between sessions.
Click on the 'Columns' button and then click on the columns in the 'pop-up' grid that you want to hide / unhide (highlighted with an 'x') and then click on the 'Columns' button again.
2. Re-sort Columns Persistent.
With this option, the order of the columns in the tablegrid is persistent between sessions.
Click on the 'Columns' button and then 'drag and drop' the columns in the 'pop-up' grid in whatever order you want. When they are in the order that you want, click on the 'Columns' button again to re-sort the tablegrid.
Maybe this can give you some ideas.
Regards,
Derek.
Hi Derek, I understand the dynamics of storing information about modified columns in a specific table and restoring this situation in the OnShow procedure. Thank you.
71 2025-07-14 19:43:01
Re: Move or hide columns natively in a tablegrid (7 replies, posted in General)
Hide and Seek and Leapfrog
Custom column settings: built-in capabilities supplemented by scripts.
https://k245.ru/en/mvdb-en/hide-and-see … pfrog.html
Very good, congratulations!
72 2025-07-12 18:27:55
Re: Change Button Text Color Problem (12 replies, posted in Script)
this one is good too
73 2025-07-11 22:52:58
Re: Change Button Text Color Problem (12 replies, posted in Script)
Another possibility...that I learned about here on the forum.
74 2025-07-11 22:18:19
Re: Move or hide columns natively in a tablegrid (7 replies, posted in General)
Is the current user setting for visibility and column position saved the next time the application is launched?
Hi k245! I ran some tests with an application without any scripts, and unfortunately, the information about which columns were hidden or moved isn't saved.
Anyway, my goal was to enable better analysis of monthly values by comparing specific columns and moving and/or hiding one or more of them.
75 2025-07-09 16:17:59
Topic: Move or hide columns natively in a tablegrid (7 replies, posted in General)
Just sharing a little information. I wasn't aware of MVD's native ability to hide and move columns in a tablegrid so easily. The following link shows a short video showing how this is easily done by the end user.
To do this, in the tablegrid properties, options, set the properties to the following status:
- goCanHideColumn = true
- goDisableColumnMoving = false
