[EN/PT-BR] Free translator version 24.9.4! Dark mode is beautiful!

image.pngUnsplash

lotus_divisor.png

Hello my friends, how are you?

More updates on the program I created, Free Translator!, to speed up my content creation, focused on quick texts for inLeo threads.

If you want to follow the program's evolution:


The new version is 24.9.4 and to write down what I did, I created a separate class just to write the news.

image.png

namespace TradutorLivre.Class
{
class ChangeLogs
{
/* Next => 24.9.4
*
* * Make it so that only one instance of the program can be opened. * * Correct the screen names to match the menu
* * System Theme => change the program color to match
* whatever is selected from the system
* * creation and coding of the simple threads screen
* * creation of functions of hourglass and hourglass to fix the problem of focus between 2 screens
*
*
* */
}
}

Among the changes is the simple change to block more than one instance of the program, that is, being able to open it only once! I had actually forgotten about this change in the first versions, but now everything is fine!

namespace TradutorLivre
{
static class Program
{
/// <summary>
/// Main entry point for the application. /// </summary>
[STAThread]
static void Main()
{

//24.9.4
string processName = Process.GetCurrentProcess().ProcessName;

if (Process.GetProcessesByName(processName).Length > 1)
{
MsgBox.Warning( "The program is already running!");
return;
}

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FrmMenuPrincipal());
}
}
}

I also changed the title of my two screens to match the name in their respective menu. I like this type of standardization because the screen title is exactly the same as its menu, making it easier to remember which screen it is, even if there are only two.

image.png

I don't think I've shown the "Single Threads" screen yet, so it's It is only intended for generating very simple content, in fact I am using it more for responses, because this way I type what I want in Brazilian Portuguese and translate my response without formatting and just with a TAG.

As we can see in the example below, it's all good... Simple! Eureka!

image.png

Now for some really cool news, this print above and the others are from the program running on a Windows 7 32-bit which is actually a VM (Virtual Machine) that I use for everyday work. In W7 the concept of themes did not yet exist, so let's say that Windows is always "clear". Starting with Windows 10, this function of choosing between themes began to be made available.

So... ta-da!!!

image.png

In Windows 10 and 11 now it follows the standard that is in my system, if I change Windows to light, my program will be light too! Now when I post my threads at night, no light cannon from my program on mine eyes!

The code was as follows: In Form_Load() of each form, I call the AplicarTema() function directly from the TemaSistema() class, passing the current form as a parameter, which in this case is the keyword this, indicating that this instance will be the active form and that it called the function.

private void FrmTradutorThreads_Load(object sender, EventArgs e)
{
try
{
//By calling this function we will apply the theme to the program according to what is in the system
TemaSistema.AplicarTema(this);
}
catch (Exception ex)
{
MsgBox.Critica(this, ex.Message);
}
}

Therefore, the TemaSistema class was set up as follows:

using Microsoft.Win32;
using System; using System.Windows.Forms;

namespace TraduçãoLivre { public class TemaSistema { private static bool IsDarkModeEnabled() { //Path in the Windows registry for theme settings var registryKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");

 if (registryKey != null) { //IF 0 = Dark, 1 = Light var appsUseLightTheme = registryKey.GetValue("AppsUseLightTheme");
 return appsUseLightTheme != null && (int)appsUseLightTheme == 0;
 } return false; // If failed, assume light theme is enabled
}

public static void ApplyTheme(Form form)
{
bool darktheme = SystemTheme.IsDarkModeEnabled();

if (darktheme)
{
// Set dark mode colors
form.BackColor = System.Drawing.Color.FromArgb(45, 45, 48); // Dark background color
form.ForeColor = System.Drawing.Color.White; // Light text

// Set additional controls here
foreach (Control control in form.Controls)
{
ApplyThemeControl(control, darktheme);
}
}
else
{
// Set light mode colors
form.BackColor = System.Drawing.Color.White;
form.ForeColor = System.Drawing.Color.Black;

// Set additional controls here
foreach (Control control in form.Controls)
{
ApplyControlTheme(control, darktheme);
}
}
}

private static void ApplyControlTheme(Control control, bool darktheme)
{
if (darktheme)
{
control.BackColor = System.Drawing.Color.FromArgb(45, 45, 48); // Dark color
control.ForeColor = System.Drawing.Color.White; // Light text
}
else
{
control.BackColor = System.Drawing.Color.White;
control.ForeColor = System.Drawing.Color.Black;
}

// Apply the theme to the child controls
foreach (Control child in control.Controls)
{
ApplyControlTheme(child, darktheme); }
}

}
}

The IsDarkModeEnabled() function checks in the Windows registry whether the applied theme is light or dark. If it fails (which probably happens in Windows 7), it assumes that it will be the light theme. With this, when calling the AplicarTema() function, it will check which theme is being used and then it will change the color of the form:

// Sets the colors of the dark mode
form.BackColor = System.Drawing.Color.FromArgb(45, 45, 48); // Dark background color
form.ForeColor = System.Drawing.Color.White; // Light text

Inside the same function, we will call AplicarTemaControle() which will do the same thing, but for the controls that are on the form. What are the controls? Everything that is on the form, such as textbox, checkbox, combobox, buttons and labels.

control.BackColor = System.Drawing.Color.FromArgb(45, 45, 48); // Dark color
control.ForeColor = System.Drawing.Color.White; // Light text

Anyway, this was really cool, I thought the code would be a bit more complex, but it's actually quite simple. I confess that I searched on ChatGPT how to do this, precisely because I thought it would be very difficult, but it's not.

Finally, I created the functions Hourglass() and EndHourglass() so that during the translation process, the form or its controls could be disabled and then everything could be enabled again. In these same processes, I could control the mouse cursor changing to a "WaitCursor", that is, when the mouse pointer turns into that spinning circle, which usually appears when something heavy or time-consuming is being processed or, for example, when a program is not responding.

Then, in the function that performs the translation, there is a call to the function this.util.Ampulheta(this);, passing the form as a parameter, and so the entire process of locking and setting the mouse pointer to waiting happens.

private void PerformTranslationText()
{
string strTranslationReturn = "";
string inputText = "";
string targetLanguage = "";

if (this.Valida() == false) { return;
 } try { this.util.Hourglass(this);

 ///setting values ​​inputText = this.txtInput.Text.Trim();

 targetLanguage = this.cmbLanguage.SelectedItem.ToString();

 ///performing the translation strRetornoTraducao = this.util.TranslateText(inputText, targetLanguage);

 ///clearing the fields this.txtOutput_inleo.Text = "";
 this.txtOutput_X.Text = "";
 this.txtOutput_threads.Text = "";

 ///formatting the inleo text this.txtOutput_inleo.Text = "*“" + strRetornoTraducao + "”*" + Environment.NewLine + Environment.NewLine;

 this.txtOutput_inleo.Text = this.txtOutput_inleo.Text + "#" + this.txt_primaira_tag.Text.Trim();

 if (this.txt_segunda_tag.Text.Trim() != "") { this.txtOutput_inleo.Text = this.txtOutput_inleo.Text + " #" + this.txt_segunda_tag.Text.Trim();
 } Application.DoEvents();
 ///formatting the raw text ///formatting the text

 this.txtOutput_X.Text = this.txtOutput_X.Text + "#" + this.txt_primeira_tag.Text.Trim();

 if (this.txt_segunda_tag.Text.Trim() != "") { this.txtOutput_X.Text = this.txtOutput_X.Text + " #" + this.txt_segunda_tag.Text.Trim();
 } Application.DoEvents();
 ///formatting text

 Application.DoEvents();

 } catch (Exception ex) { MsgBox.Critica(this, ex.Message);
 } finally { this.util.FimAmpulheta(this);
 }

}

To speed things up, I've already put the two functions here in this block below, showing that I perform a lock on any other form that is open and call the wait cursor, so for the end user the system looks like it has locked and is processing something.

public void Hourglass(Form myScreen)
{

try
{

foreach (Control control in myScreen.Controls)
{
control.Enabled = false; // Disable control
}

foreach (Form form in myScreen.MdiChildren)
{
if (form != myScreen)
{
form.Enabled = false; // Disable other forms
}
}

((Form)myScreen.MdiParent).Cursor = Cursors.WaitCursor; // Also defines in the MDI Parent

Application.DoEvents(); } catch (Exception ex) { throw new Exception(ex.Message);
 } } public void EndHourglass(Form myScreen) { try { foreach (Control control in myScreen.Controls) { control.Enabled = true;
 } foreach (Form form in minhaTela.MdiChildren) { form.Enabled = true;
 } ((Form)myScreen.MdiParent).Cursor = Cursors.Default; // Restores to MDI Parent } catch (Exception ex) { throw new Exception(ex.Message);
 } } 

For the form that called Hourglass(), I don't disable the form itself, but rather its components. This prevents a visual focus bug from happening if there are two screens open. After that, anything else that is open will be disabled.

lotus_divisor.png

Well, friends, these were the changes made for this version. Now the fun will get more serious, because the next steps will be to connect via SQL Server in HiveSQL to make many queries that will help me with my earnings and dividends control that I have been doing.

In addition to other things, such as how many posts did I make in the threads with a certain tag? How many long posts have been made with the "hivebr" tag? Anyway, there are many possibilities and many new things, because I have never integrated C# with SQL Server, I have been working with PostgreSQL my whole life.

So, it may take a while to bring you new things, but they will come! A big hug to you all!

sun_divisor.webp

image.pngUnsplash

lotus_divisor.png

Olá meus amigos, tudo bem com vocês?

Mais atualizações sobre o programa que criei Tradutor Livre! Para agilizar a minha criação de conteúdo, focada em textos rápidos para as threads da inLeo.

Caso queira acompanhar a evolução do programa:


A nova versão é a 24.9.4 e para anotar o que fiz, criei uma classe a parte apenas para escrever as novidades.

image.png

namespace TradutorLivre.Class
{
class ChangeLogs
{
/* Next => 24.9.4
*
* * Make it so that only one instance of the program can be opened. * * Correct the screen names to match the menu
* * System Theme => change the program color to match
* whatever is selected from the system
* * creation and coding of the simple threads screen
* * creation of functions of hourglass and hourglass to fix the problem of focus between 2 screens
*
*
* */
}
}

   

Entre as alterações estão a simples alteração para barrar mais de um instancia do programa, ou seja, poder abri-lo apenas uma vez! Eu realmente havia esquecido dessa alteração nas primeiras versões, mas agora está tudo certo!

namespace TradutorLivre
{
    static class Program
    {
        /// <summary>
        /// Ponto de entrada principal para o aplicativo.
        /// </summary>
        [STAThread]
        static void Main()
        {

            //24.9.4            
            string nomeDoProcesso = Process.GetCurrentProcess().ProcessName;

            if (Process.GetProcessesByName(nomeDoProcesso).Length > 1)
            {
                MsgBox.Advertencia("O programa já está em execução!");
                return;
            }

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new FrmMenuPrincipal());
        }
    }
}

Além disso troquei o titulo das minhas duas telas para ficar de acordo com o nome no menu respectivo delas. Gosto desse tipo de padronização, pois assim o titulo da tela fica exato com o seu menu, facilitando assim conseguir lembrar qual é a tela, mesmo que seja apenas duas.

image.png

Acredito que ainda não mostrei a tela "Threads Simples", então ela é voltada apenas para geração de conteúdo bem simples, na verdade estou usando mais para respostas, pois assim digito o que quero em Português do Brasil e traduzo sem formatações e apenas com uma TAG a minha resposta.

Como podemos ver no exemplo abaixo, é tudo bem... Simples! Eureka!

image.png

Agora uma novidade bem legal, esse print acima e os outros são do programa rodando em um Windows 7 32 bits que na verdade é uma VM (Virtual Machine) que uso para trabalhar no cotidiano. No W7 ainda não existia o conceito de temas, então digamos que o Windows é sempre "claro". A partir do Windows 10 começou a ser disponibilizado essa função de escolha entre os temas.

Portanto... tcharam!!!

image.png

No Windows 10 e 11 agora ele segue o padrão que está em meu sistema, se eu mudar o Windows para claro, o meu programa vai ficar claro também! Agora quando posto minhas threads a noite, nada de canhão de luz do meu programa nos meus olhos!

O código feito ficou assim: No Form_Load() de cada form, chamo a função AplicarTema() diretamente da classe TemaSistema(), passando como parâmetro o form atual, que no caso é a palavra chave this, referenciando que essa instância será o form ativo e que chamou a função.

private void FrmTradutorThreads_Load(object sender, EventArgs e)
        {
            try
            {
                //Chamando essa função vamos aplicar o tema ao programa de acordo com o que está no sistema
                TemaSistema.AplicarTema(this);
            }
            catch (Exception ex)
            {
                MsgBox.Critica(this, ex.Message);
            }
        }

Sendo assim, a classe TemaSistema foi montada da seguinte maneira:

using Microsoft.Win32;
using System;
using System.Windows.Forms;

namespace TradutorLivre
{
    public class TemaSistema
    {
        private static bool IsDarkModeEnabled()
        {
            //Caminho no registro do Windows para as configurações de tema
            var registryKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");

            if (registryKey != null)
            {
                //SE 0 = Escuro, 1 = Claro
                var appsUseLightTheme = registryKey.GetValue("AppsUseLightTheme");
                return appsUseLightTheme != null && (int)appsUseLightTheme == 0;
            }

            return false; // Caso falhe, assume que o tema claro está habilitado
        }

        public static void AplicarTema(Form form)
        {
            bool temaEscuro = TemaSistema.IsDarkModeEnabled();

            if (temaEscuro)
            {
                // Define as cores do modo escuro
                form.BackColor = System.Drawing.Color.FromArgb(45, 45, 48); // Cor de fundo escura
                form.ForeColor = System.Drawing.Color.White; // Texto claro

                // Ajuste os controles adicionais aqui
                foreach (Control control in form.Controls)
                {
                    AplicarTemaControle(control, temaEscuro);
                }
            }
            else
            {
                // Define as cores do modo claro
                form.BackColor = System.Drawing.Color.White;
                form.ForeColor = System.Drawing.Color.Black;

                // Ajuste os controles adicionais aqui
                foreach (Control control in form.Controls)
                {
                    AplicarTemaControle(control, temaEscuro);
                }
            }
        }

        private static void AplicarTemaControle(Control controle, bool temaEscuro)
        {
            if (temaEscuro)
            {
                controle.BackColor = System.Drawing.Color.FromArgb(45, 45, 48); // Cor escura
                controle.ForeColor = System.Drawing.Color.White; // Texto claro
            }
            else
            {
                controle.BackColor = System.Drawing.Color.White;
                controle.ForeColor = System.Drawing.Color.Black;
            }

            // Aplica o tema aos controles filhos
            foreach (Control child in controle.Controls)
            {
                AplicarTemaControle(child, temaEscuro);
            }
        }

    }
}

A função IsDarkModeEnabled() verifica no registro do Windows se o tema aplicado é claro ou escuro, se falhar (o que provavelmente acontece no Windows 7) ele assume que será o tema claro. Com isso, ao chamar a função AplicarTema() ela irá verificar qual tema está sendo usado e assim irá fazer o processo de mudar a cor do form:

 // Define as cores do modo escuro
form.BackColor = System.Drawing.Color.FromArgb(45, 45, 48); // Cor de fundo escura
form.ForeColor = System.Drawing.Color.White; // Texto claro

Dentro da mesma função, iremos chamar a AplicarTemaControle() que irá fazer a mesma coisa, mas para os controles que estão no form. O que são os controles? Tudo o que está no formulário, como textbox, checkbox, combobox, botões e as labels.

controle.BackColor = System.Drawing.Color.FromArgb(45, 45, 48); // Cor escura
controle.ForeColor = System.Drawing.Color.White; // Texto claro

Enfim, esse foi bem legal, eu achei que o código seria algo mais complexo, mas é realmente bem simples. Confesso que pesquisei no ChatGPT como fazer isso, por justamente achar que seria algo muito difícil, mas não é.

Por fim, criei as funções Ampulheta() e FimAmpulheta() para que fosse realizado no processo de tradução, uma desabilitação do formulário ou de seus controles e depois habilitando tudo de novo e nestes mesmos processos, controlar a mudança do cursor do mouse para um "WaitCursor", ou seja, quando o ponteiro do mouse vira aquele circulo que fica girando, geralmente aparece quando algo pesado ou demorado está sendo processado ou por exemplo quando um programa não está respondendo.

Então na função que realiza a tradução, têm a chamada para a função this.util.Ampulheta(this); passando como parâmetro o formulário e assim todo o processo de trava e de colocar o ponteiro do mouse como esperando acontece.

private void RealizarTraducaoTexto()
        {
            string strRetornoTraducao = "";
            string inputText = "";
            string targetLanguage = "";

            if (this.Valida() == false)
            {
                return;
            }

            try
            {

                this.util.Ampulheta(this);

                ///setando valores
                inputText = this.txtInput.Text.Trim();

                targetLanguage = this.cmbLanguage.SelectedItem.ToString();

                ///realizando a tradução
                strRetornoTraducao = this.util.TranslateText(inputText, targetLanguage);

                ///limpando os campos
                this.txtOutput_inleo.Text = "";
                this.txtOutput_X.Text = "";
                this.txtOutput_threads.Text = "";

                ///formatando o texto inleo
                this.txtOutput_inleo.Text = "*“" + strRetornoTraducao + "”*" + Environment.NewLine + Environment.NewLine;

                this.txtOutput_inleo.Text = this.txtOutput_inleo.Text + "#" + this.txt_primeira_tag.Text.Trim();

                if (this.txt_segunda_tag.Text.Trim() != "")
                {
                    this.txtOutput_inleo.Text = this.txtOutput_inleo.Text + " #" + this.txt_segunda_tag.Text.Trim();
                }

                Application.DoEvents();
                ///formatando o texto inleo

                ///formatando o texto X
                this.txtOutput_X.Text = "“" + strRetornoTraducao + "”" + Environment.NewLine + Environment.NewLine;

                this.txtOutput_X.Text = this.txtOutput_X.Text + "#" + this.txt_primeira_tag.Text.Trim();

                if (this.txt_segunda_tag.Text.Trim() != "")
                {
                    this.txtOutput_X.Text = this.txtOutput_X.Text + " #" + this.txt_segunda_tag.Text.Trim();
                }

                Application.DoEvents();
                ///formatando o texto X

                ////formatando para threads
                this.txtOutput_threads.Text = "“" + txtInput.Text.Trim() + "” #" + this.txt_tag_threads.Text.Trim();

                Application.DoEvents();

            }
            catch (Exception ex)
            {
                MsgBox.Critica(this, ex.Message);
            }
            finally
            {
                this.util.FimAmpulheta(this); 
            }

        }

Para agilizar, já coloquei as duas funções aqui nesse bloco abaixo, mostrando que realizo uma trava em qualquer outro form que esteja aberto e chamo o cursor de espera, sendo assim, para o usuário final o sistema parece que travou e que está processando algo.

        public void Ampulheta(Form minhaTela)
        {

            try
            {

                foreach (Control control in minhaTela.Controls)
                {
                    control.Enabled = false; // Desabilitar controle
                }

                foreach (Form form in minhaTela.MdiChildren)
                {
                    if (form != minhaTela)
                    {
                        form.Enabled = false; // Desabilitar outros forms
                    }
                }

                ((Form)minhaTela.MdiParent).Cursor = Cursors.WaitCursor; // Define também no MDI Parent

                Application.DoEvents(); 

            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

        }

        public void FimAmpulheta(Form minhaTela)
        {

            try
            {

                foreach (Control control in minhaTela.Controls)
                {
                    control.Enabled = true; 
                }

                foreach (Form form in minhaTela.MdiChildren)
                {
                    form.Enabled = true; 
                }

                ((Form)minhaTela.MdiParent).Cursor = Cursors.Default; // Restaura no MDI Parent

            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

        }

Para o formulário que chamou a Ampulheta() eu não desabilito propriamente o formulário e sim os seus componentes. Isso impede que um bug visual de focos aconteça caso esteja com duas telas abertas. Depois disso, qualquer outra coisa que estiver aberta será desabilitada.

lotus_divisor.png

Bem amigos, essas foram as modificações realizadas para essa versão. Agora a brincadeira vai ficar mais seria, pois os próximos passos serão conectar via SQL Server no HiveSQL para fazer muitas consultas que irão me ajudar com o meu controle de ganhos e dividendos que tenho feito.

Além de outras coisas, como por exemplo quantas postagens fiz nas threads com uma tag determinada? Quantos posts longos foram feitos com a tag "hivebr"? Enfim, muitas possibilidades e muitas novidades, pois nunca integrei o C# com SQL Server, a minha vida inteira foi mexendo com o PostgreSQL.

Então, talvez demore um pouco para trazer novidades, mas, elas irão vim! Um forte abraço para vocês!

lotus_divisor.png

banner_hiver_br_01.png

🔹Hive Games: Splinterlands | dCrops | Terracore | Holozing🔹

🔹Follow me on X | Get Paid For Unused Internet Honeygain🔹

Posted Using InLeo Alpha



0
0
0.000
20 comments
avatar

!hbits !hiqvote

0
0
0.000
avatar

Bzzt! Congrats @shiftrox! Free Translator looks sleek in dark mode! Hope this new version helps streamline your inLeo threads #hivebr

0
0
0.000
avatar

!PIZZA
!LOL
!INDEED

0
0
0.000
avatar

!LOL
!INDEED

0
0
0.000
avatar

Great work with yout Desktop app Free Translator. Are you uploaded to github? It's an interesting project.

0
0
0.000
avatar

Hello good afternoon, I'm grateful that you liked it, it's something simple but it will help a lot to improve efficiency and control/visualize other things.

I haven't uploaded it to github yet, it's just on my notebook, but in the future I'm thinking of uploading it and maybe even sharing the executable publicly.

0
0
0.000