Índice:

Gerenciador de janelas embutido: 10 etapas
Gerenciador de janelas embutido: 10 etapas

Vídeo: Gerenciador de janelas embutido: 10 etapas

Vídeo: Gerenciador de janelas embutido: 10 etapas
Vídeo: Windows 10 particionar el disco duro en 2 o 3 partes dentro de windows 2024, Dezembro
Anonim
Gerenciador de janela embutido
Gerenciador de janela embutido
Gerenciador de janela embutido
Gerenciador de janela embutido
Gerenciador de janela embutido
Gerenciador de janela embutido
Gerenciador de janela embutido
Gerenciador de janela embutido

Este projeto mostra como implementar um gerenciador de janelas com janelas móveis sobrepostas em um microcontrolador embutido com um painel LCD e uma tela sensível ao toque. Existem pacotes de software disponíveis comercialmente para fazer isso, mas eles custam dinheiro e são de código fechado. Este, chamado MiniWin, é gratuito e de código aberto. Ele é escrito em C99 totalmente compatível e pode ser usado em um aplicativo C ou C ++. Os objetivos do MiniWin são ser fácil de usar, fácil de modificar, expansível, portátil para uma ampla variedade de hardware e não consumir muitos recursos.

Além de fornecer o código para gerenciar suas janelas, o MiniWin tem uma coleção de controles de interface do usuário - botões, controles deslizantes, barras de progresso, árvores, etc. Você pode ter várias janelas de diferentes tipos ou várias instâncias do mesmo tipo. As janelas podem ser movidas, redimensionadas, maximizadas, minimizadas, fechadas - todas as coisas usuais que você faz com janelas em gerenciadores de janelas maiores. As fontes TrueType com kerning e anti-aliasing (torna o texto mais suave) também são suportadas para uma renderização de texto atraente.

Em cada janela você tem uma área cliente (seu espaço dentro da borda e abaixo da barra superior). Nisto você pode adicionar controles para fazer um diálogo ou você pode usar a biblioteca de gráficos embutida para desenhar o que quiser. Todas as funções da biblioteca gráfica reconhecem a janela. Você não precisa se preocupar com a localização da janela, o que está sobreposta ou se ela está minimizada.

Além de fazer suas próprias janelas, há também alguns diálogos padrão incluídos que são muito fáceis de instanciar - por exemplo, diálogos de confirmação (apenas botões OK ou Sim / Não), configuradores de hora / data, seletores de arquivo, seletores de cores etc.

MiniWin usa um sistema de fila de mensagens de design de gerenciador de janelas padrão. As janelas podem interagir umas com as outras e com o gerenciador de janelas por meio de mensagens. Você não chama funções para fazer as coisas diretamente, você adiciona uma mensagem à fila e o gerenciador de janelas a ativará para você.

MiniWin foi portado para placas de desenvolvimento padrão com telas de toque de fornecedores de microcontroladores ST, NXP e Renesas. Existem drivers de hardware e projetos de exemplo para todos esses dispositivos. Além disso, o MiniWin pode ser desenvolvido para Windows ou Linux para que você possa simular o código da interface do usuário antes de obter o hardware integrado.

MiniWin possui um gerador de código. Você pode especificar suas janelas e controles de forma simples para criar um arquivo JSON legível por humanos e o gerador de código analisa o arquivo e cria o código para você (há muitos exemplos a seguir). Ele cria aplicativos simuladores completos para Windows ou Linux que podem simplesmente ser construídos e tem seu display LCD simulado com suas janelas MiniWin funcionando. Você pode pegar exatamente o mesmo código gerado e soltá-lo em um projeto incorporado e ter o mesmo código mostrando as mesmas janelas e controles momentos depois em seu hardware incorporado.

MiniWin não requer suporte operacional no dispositivo integrado. Tudo é executado em um único segmento. O MiniWin pode ser integrado a um RTOS em execução em um processador embarcado e há exemplos de integração do MiniWin com o FreeRTOS.

Este instrutível mostra como colocar o MiniWin em funcionamento em um processador STM32 M4 usando a placa Discovery STM32F429 barata que vem com uma tela de toque QVGA já instalada. Estes estão facilmente disponíveis no seu fornecedor de componentes eletrônicos.

MiniWin funciona em microcontroladores de gama média e superior.

Suprimentos

Placa de desenvolvimento STM32F429I-DISC1 e um cabo micro USB

Download do STM32CubeIDE que é gratuito.

Etapa 1: Obtendo o Código

Obtendo o Código
Obtendo o Código

Em primeiro lugar, você precisa do STM32CubeIDE instalado. Você consegue isso no site da ST. Você tem que se registrar e demora um pouco para fazer o download e instalá-lo. É tudo grátis.

Durante a instalação, baixe o código-fonte do MiniWin e descompacte-o. É grande, mas você usará apenas uma pequena parte dele. Clique no botão verde 'Clonar ou Baixar' aqui …

github.com/miniwinwm/miniwinwm

em seguida, escolha Baixar Zip. Descompacte o conteúdo.

Etapa 2: Construindo um Projeto de Exemplo

Construindo um Projeto Exemplo
Construindo um Projeto Exemplo
Construindo um Projeto Exemplo
Construindo um Projeto Exemplo

Primeiro, vamos construir um dos projetos de exemplo. Um bom é chamado MiniWinSimple. Inicie o STM32CubeIDE e faça o seguinte:

  1. Escolha Arquivo | Importar …
  2. Abra Geral e escolha Projeto Existente no Espaço de Trabalho. Próximo.
  3. Clique em Navegar e navegue até onde você descompactou o MiniWin. Em seguida, vá para a pasta STM32CubeIDE / MiniWinSimple / STM32F429. Clique em Selecionar pasta.
  4. No projeto: marque MiniWinSimple_STM32F429 e clique em Concluir.
  5. O projeto MiniWinSimple_STM32F429 aparecerá no Project Explorer. Selecione-o e construa-o com Projeto | Construir Projeto.
  6. Agora conecte o cabo USB à placa e ao computador e execute-o usando Run | Debug e quando for baixado, escolha Run | Resume. Você obterá um display de calibração da tela na primeira vez, então toque no centro das 3 cruzes no display LCD. Agora você pode interagir com a janela no visor.

Para mover uma janela, arraste-a pela barra de título. Para redimensionar uma janela, use o ícone de triângulo branco à esquerda da barra de título. As janelas MiniWin não podem ser redimensionadas arrastando as bordas, pois os monitores em que o MiniWin é usado são muito pequenos. Para minimizar, maximizar ou fechar uma janela, use os ícones na extremidade direita da barra de título (fechar pode estar desativado). Quando uma janela é minimizada, você não pode mover os ícones minimizados. Eles aumentam da esquerda para a direita.

Etapa 3: executando o gerador de código

Executando o gerador de código
Executando o gerador de código

Agora vamos alterar o projeto de exemplo, gerando algumas janelas próprias e inserindo o novo código. Para fazer isso, executaremos o gerador de código.

  1. Abra um prompt de comando e vá para a pasta onde você descompactou o MiniWin e depois para a pasta Tools / CodeGen.
  2. O executável para Windows CodeGen.exe já está disponível. Para o Linux, você deve construí-lo digitando make. (Você também pode compilá-lo a partir do código-fonte do Windows se estiver preocupado com a execução de um executável baixado, mas precisa do compilador e do ambiente de desenvolvimento instalados. Consulte a documentação do MiniWin na pasta docs para obter detalhes).
  3. Nesta pasta estão alguns exemplos de arquivos JSON. Usaremos example_empty.json. Você precisa editá-lo primeiro para configurá-lo para Windows ou Linux. Abra-o em um editor e na parte superior, onde você encontrará "TargetType", altere o valor "Linux" ou "Windows" para o qual você está executando o gerador de código.
  4. Agora digite codegen example_empty.json no prompt de comando.
  5. Vá para o seu projeto no STM32CubeIDE e abra a pasta MiniWinSimple_Common. Exclua todos os arquivos lá.
  6. Deixamos o "TargetName" no arquivo JSON como padrão em "MiniWinGen", então esse é o nome da nossa pasta de código gerado. Vá para a pasta onde você descompactou o MiniWin e depois a pasta MiniWinGen_Common. Agora selecione todos esses arquivos e arraste e solte em STM32CubeIDE na pasta MiniWinSimple_Common do seu projeto.
  7. Agora reconstrua e execute novamente o projeto em STM32CubeIDE e sua nova janela de design aparecerá. O botão na janela desapareceu porque example_empty.json não define nenhum.

Etapa 4: Adicionando uma janela

Adicionando uma janela
Adicionando uma janela

Agora adicionaremos uma segunda janela ao arquivo de configuração JSON e regeneraremos o código.

1. Abra example_empty.json em um editor de texto.

2. Na seção "Janelas", há uma série de definições de janelas que atualmente possuem apenas uma janela. Copie tudo isso …

{

"Nome": "W1", "Título": "Janela 1", "X": 10, "Y": 15, "Largura": 200, "Altura": 180, "Borda": verdadeiro, "TitleBar": verdadeiro, "Visível": verdadeiro, "Minimizado": falso}

e cole-o novamente com uma vírgula separando as 2 definições.

3. Altere "W1" para "W2" e "Janela 1" para "Janela 2". Altere "X", "Y", "Largura" e "Altura" para alguns valores diferentes, tendo em mente que a resolução da tela é de 240 de largura por 320 de altura.

4. Salve o arquivo e execute o gerador de código novamente.

5. Copie os arquivos como na etapa anterior, reconstrua e execute novamente. Agora você terá 2 janelas em sua tela.

Etapa 5: Adicionar um controle

Adicionando um controle
Adicionando um controle

Agora vamos adicionar alguns controles à sua nova janela. Edite o mesmo arquivo da etapa anterior.

1. Na especificação da janela W1, adicione uma vírgula após a última configuração ("Minimizado": falso) e adicione este texto

"MenuBar": verdadeiro, "MenuBarEnabled": true, "MenuItems": ["Fred", "Bert", "Pete", "Alf", "Ian"], "Buttons": [{"Name": "B1", "Label": "Button1", "X": 10, "Y": 10, "Ativado": verdadeiro, "Visível": verdadeiro}]

Esta seção adiciona uma barra de menu com 5 itens e a habilita (as barras de menu podem ser desabilitadas globalmente, experimente). Ele também adiciona um botão que está habilitado e visível (eles podem ser criados invisíveis e, em seguida, tornados visíveis no código).

2. Gere novamente o código, copie-o, reconstrua e execute novamente como antes.

Etapa 6: Fazendo com que os controles façam algo

Fazendo os controles fazerem algo
Fazendo os controles fazerem algo

Agora temos a interface de usuário básica de que precisamos para fazer algo. Para este exemplo, abriremos uma caixa de diálogo de seleção de cores quando o botão na janela 1 for pressionado.

Vá para o seu projeto em STM32CubeIDE e abra a pasta MiniWinSimple_Common e depois abra o arquivo W1.c (o nome deste arquivo corresponde ao campo "Nome" da janela no arquivo JSON quando o código foi gerado).

Neste arquivo você encontrará a função window_W1_message_function (). Se parece com isso:

void window_W1_message_function (const mw_message_t * message) {MW_ASSERT (message! = (void *) 0, "Parâmetro de ponteiro nulo"); / * A próxima linha interrompe os avisos do compilador, pois a variável não está sendo usada * / (void) window_W1_data; switch (message-> message_id) {case MW_WINDOW_CREATED_MESSAGE: / * Adicione qualquer código de inicialização de janela aqui * / break; case MW_MENU_BAR_ITEM_PRESSED_MESSAGE: / * Adicionar código de manipulação de menu de janela aqui * / break; case MW_BUTTON_PRESSED_MESSAGE: if (message-> sender_handle == button_B1_handle) {/ * Adicione seu código do manipulador para este controle aqui * /} break; padrão: / * Keep MISRA happy * / break; }}

Isso é chamado pelo gerenciador de janelas para esta janela sempre que o gerenciador de janelas precisa informar a janela que algo aconteceu. Neste caso, estamos interessados em saber que o único botão da janela foi pressionado. Na instrução switch para tipos de mensagem, você verá um caso para MW_BUTTON_PRESSED_MESSAGE. Este código é executado quando o botão é pressionado. Há apenas um botão nesta janela, mas poderia haver mais, portanto, é feita uma verificação de qual botão ele está. Nesse caso, só poderia ser o botão B1 (o nome corresponde novamente ao nome do botão no arquivo JSON).

Portanto, após este rótulo de caso, adicione o código para abrir uma caixa de diálogo de seleção de cores, que é esta:

mw_create_window_dialog_colour_chooser (10, 10, "Cor", MW_HAL_LCD_RED, falso, mensagem-> destinatário_handle);

Os parâmetros são os seguintes:

  • 10, 10 é a localização na tela da caixa de diálogo
  • "Cor" é o título do diálogo
  • MW_HAL_LCD_RED é a cor padrão com a qual a caixa de diálogo iniciará
  • falso significa não mostrar tamanho grande (tente definir como verdadeiro e veja a diferença)
  • mensagem-> identificador de destinatário é quem possui esta caixa de diálogo, neste caso, é esta janela. O identificador de uma janela está no parâmetro de mensagem da função. Esta é a janela para a qual a resposta do diálogo será enviada.

Para descobrir o valor da cor que o usuário escolheu, o gerenciador de janelas enviará à nossa janela uma mensagem com a cor escolhida quando o usuário pressionar o botão OK na caixa de diálogo. Portanto, precisamos interceptar esta mensagem também com outro caso na instrução switch que se parece com isto:

case MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE:

{mw_hal_lcd_colour_t selected_colour = message-> message_data; (vazio) cor escolhida; } pausa;

Não estamos fazendo nada com a cor escolhida ainda, então apenas convertendo-a em vazio para evitar um aviso do compilador. O código final desta função agora se parece com este:

void window_W1_message_function (const mw_message_t * message)

{MW_ASSERT (mensagem! = (Void *) 0, "Parâmetro de ponteiro nulo"); / * A próxima linha interrompe os avisos do compilador, pois a variável não está sendo usada * / (void) window_W1_data; switch (message-> message_id) {case MW_WINDOW_CREATED_MESSAGE: / * Adicione qualquer código de inicialização de janela aqui * / break; case MW_MENU_BAR_ITEM_PRESSED_MESSAGE: / * Adicionar código de manipulação de menu de janela aqui * / break; case MW_BUTTON_PRESSED_MESSAGE: if (mensagem-> sender_handle == button_B1_handle) {/ * Adicione seu código de manipulador para este controle aqui * / mw_create_window_dialog_colour_chooser (10, 10, "Cor", MW_HAL_LCD_RED, falso, mensagem-> destinatário_handle); } pausa; case MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE: {mw_hal_lcd_colour_t selected_colour = message-> message_data; (vazio) cor escolhida; } pausa; padrão: / * Keep MISRA happy * / break; }}

A execução do código é mostrada na imagem acima. Você pode notar que, quando uma caixa de diálogo é exibida, você precisa respondê-la e descartá-la antes de fazer qualquer outra coisa. Isso é chamado de comportamento modal. Diálogos no MiniWin e todos sempre globalmente modais e você só pode ter um sendo exibido por vez. Há mais explicação aqui …

en.wikipedia.org/wiki/Modal_window

Etapa 7: Desenhar na janela

Desenho na janela
Desenho na janela

Até agora, usamos apenas controles e eles se desenham. É hora de fazer algum desenho personalizado em nossa janela. A parte em que você pode desenhar está dentro das bordas (se houver, são opcionais), dentro das barras de rolagem (se definido, também opcional) e abaixo da barra de título (se houver, isso também é opcional). É chamada de área do cliente na terminologia da janela.

Há uma biblioteca de comandos gráficos no MiniWin que você pode usar. Todos estão cientes da janela. Isso significa que você não precisa se preocupar se a janela está visível, parcialmente obscurecida por outras janelas, ligada, parcialmente desligada ou totalmente fora da tela, ou se a coordenada de onde você está desenhando está na área do cliente ou além dela. Está tudo cuidado para você. Você não pode desenhar fora de sua área de cliente.

Desenhar nas áreas do cliente na terminologia do Windows é chamado de pintura e cada janela tem uma função de pintura onde você faz o seu desenho. Você não chama sua função de pintura, o gerenciador de janelas faz isso para você quando necessário. É necessário quando uma janela é movida ou outra janela no topo tem sua posição ou visibilidade alterada. Se você precisa de sua janela repintada porque alguns dos dados dos quais o conteúdo da janela depende mudaram (ou seja, você sabe que uma repintura é necessária em vez de o gerenciador de janelas saber), então você diz ao gerenciador de janelas que uma repintura é necessária e ele chama sua função de pintura. Você não chama isso de si mesmo. (Tudo isso é demonstrado na próxima seção).

Primeiro, você precisa encontrar sua função de pintura. O gerador de código o cria para você e está logo acima da função de manipulador de mensagens modificada na seção anterior. Vá para o seu projeto e abra o arquivo W1.c novamente.

Neste arquivo você encontrará a função window_W1_paint_function (). Se parece com isso:

void window_W1_paint_function (mw_handle_t window_handle, const mw_gl_draw_info_t * draw_info)

{MW_ASSERT (draw_info! = (Void *) 0, "Parâmetro de ponteiro nulo"); / * Preencher a área do cliente da janela com branco sólido * / mw_gl_set_fill (MW_GL_FILL); mw_gl_set_solid_fill_colour (MW_HAL_LCD_WHITE); mw_gl_set_border (MW_GL_BORDER_OFF); mw_gl_clear_pattern (); mw_gl_rectangle (draw_info, 0, 0, mw_get_window_client_rect (window_handle).width, mw_get_window_client_rect (window_handle).height); / * Adicione seu código de pintura de janela aqui * /}

Este é o código conforme gerado e tudo o que ele faz é preencher a área do cliente com branco sólido. Vamos desenhar um círculo amarelo preenchido na área do cliente. Primeiro temos que entender o conceito de contexto gráfico (outra coisa do Windows). Definimos os parâmetros de desenho no contexto gráfico e, em seguida, chamamos uma rotina genérica de desenho de círculo. As coisas que temos que definir neste exemplo são se o círculo tem uma borda, estilo de linha de borda, cor da borda, se o círculo é preenchido, cor de preenchimento e padrão de preenchimento. Você pode ver o código acima que faz algo semelhante para preencher a área do cliente com um retângulo branco preenchido sólido sem borda. Os valores no contexto gráfico não são lembrados entre cada chamada da função pintar, então você deve configurar os valores todas as vezes (eles são lembrados com a função pintar).

No código acima, você pode ver que o preenchimento está ativado e o padrão de preenchimento desativado, portanto, não precisamos defini-los novamente. Precisamos definir a borda ativada, o estilo da linha da borda como sólido, a cor do primeiro plano da borda como preto e a cor de preenchimento como amarelo, assim:

mw_gl_set_fg_colour (MW_HAL_LCD_BLACK);

mw_gl_set_solid_fill_colour (MW_HAL_LCD_YELLOW); mw_gl_set_line (MW_GL_SOLID_LINE); mw_gl_set_border (MW_GL_BORDER_ON); mw_gl_circle (draw_info, window_simple_data.circle_x, window_simple_data.circle_y, 25);

Adicione este código no comentário nesta função onde diz para adicionar seu código. Em seguida, precisamos desenhar um círculo que é feito assim:

mw_gl_circle (draw_info, 30, 30, 15);

Isso desenha um círculo nas coordenadas 30, 30 com raio 15. Reconstrua o código e execute-o novamente e você verá um círculo na janela como mostrado acima. Você notará que o círculo e o botão se sobrepõem, mas o botão está na parte superior. Isso ocorre por design. Os controles estão sempre acima de qualquer coisa que você desenhe na área do cliente.

Etapa 8: janela de dados

Dados da janela
Dados da janela

Até agora, implementamos nosso próprio código na função de mensagem da janela 1 (para lidar com as mensagens recebidas) e sua função pintar (para desenhar na área do cliente da janela). Agora é hora de vincular os dois. Vamos preencher o círculo desenhado na função pintar com a cor que o usuário escolhe pelo seletor de cores quando o botão é pressionado. Lembre-se de que não chamamos a função de pintura, o gerenciador de janelas faz isso, então nossa função de mensagem (que conhece a cor escolhida) não pode chamar a função de pintura diretamente. Em vez disso, precisamos armazenar os dados em cache e informar ao gerenciador de janelas que uma repintura é necessária. O gerenciador de janelas irá então chamar a função de pintura que pode usar os dados em cache.

No topo de W1.c você verá uma estrutura de dados vazia e um objeto deste tipo declarado pelo gerador de código como este:

estrutura de typedef

{/ * Adicione seus membros de dados aqui * / char dummy; / * Alguns compiladores reclamam de estruturas vazias; remova isso ao adicionar seus membros * /} window_W1_data_t; static window_W1_data_t window_W1_data;

É aqui que armazenamos nossos dados em cache para que sejam preservados nas chamadas e sejam conhecidos como dados da janela. Precisamos apenas armazenar a cor escolhida aqui, assim:

estrutura de typedef

{/ * Adicione seus membros de dados aqui * / mw_hal_lcd_colour_t choice_colour; } window_W1_data_t; static window_W1_data_t window_W1_data = {MW_HAL_LCD_YELLOW};

Vamos dar-lhe uma cor inicial amarela. Agora, na função de mensagem, vamos alterar o código ligeiramente para salvar a cor escolhida aqui, assim:

case MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE:

{window_W1_data.chosen_colour = message-> message_data; } pausa;

Em seguida, vamos alterar a função de pintura para usar este valor quando desenha o círculo como este:

mw_gl_set_solid_fill_colour (window_W1_data.chosen_colour);

Agora alteramos os dados dos quais o conteúdo da janela depende, portanto, precisamos informar ao gerenciador de janelas que a janela precisa ser redesenhada. Fazemos isso na função de mensagem quando a mensagem de OK do diálogo é recebida, assim:

mw_paint_window_client (mensagem-> destinatário_handle);

Isso não faz com que a janela seja pintada diretamente. É uma função de utilitário que envia uma mensagem ao gerenciador de janelas de que uma janela precisa ser repintada (se você entrar nela poderá ver como isso acontece). A janela que precisa ser repintada neste caso é ela mesma, e o identificador da janela está no parâmetro de mensagem para a função de manipulador de mensagem.

O arquivo inteiro agora tem a seguinte aparência, se você não tiver certeza de onde vão alguns dos trechos de código acima:

#incluir

#include "miniwin.h" #include "miniwin_user.h" #include "W1.h" typedef struct {/ * Adicione seus membros de dados aqui * / mw_hal_lcd_colour_t choose_colour; } window_W1_data_t; static window_W1_data_t window_W1_data = {MW_HAL_LCD_YELLOW}; void window_W1_paint_function (mw_handle_t window_handle, const mw_gl_draw_info_t * draw_info) {MW_ASSERT (draw_info! = (void *) 0, "Parâmetro de ponteiro nulo"); / * Preencher a área do cliente da janela com branco sólido * / mw_gl_set_fill (MW_GL_FILL); mw_gl_set_solid_fill_colour (MW_HAL_LCD_WHITE); mw_gl_set_border (MW_GL_BORDER_OFF); mw_gl_clear_pattern (); mw_gl_rectangle (draw_info, 0, 0, mw_get_window_client_rect (window_handle).width, mw_get_window_client_rect (window_handle).height); / * Adicione seu código de pintura de janela aqui * / mw_gl_set_fg_colour (MW_HAL_LCD_BLACK); mw_gl_set_solid_fill_colour (window_W1_data.chosen_colour); mw_gl_set_line (MW_GL_SOLID_LINE); mw_gl_set_border (MW_GL_BORDER_ON); mw_gl_circle (draw_info, 30, 30, 15); } void window_W1_message_function (const mw_message_t * message) {MW_ASSERT (message! = (void *) 0, "Parâmetro de ponteiro nulo"); / * A próxima linha interrompe os avisos do compilador, pois a variável não está sendo usada * / (void) window_W1_data; switch (message-> message_id) {case MW_WINDOW_CREATED_MESSAGE: / * Adicione qualquer código de inicialização de janela aqui * / break; case MW_MENU_BAR_ITEM_PRESSED_MESSAGE: / * Adicionar código de manipulação de menu de janela aqui * / break; case MW_BUTTON_PRESSED_MESSAGE: if (mensagem-> sender_handle == button_B1_handle) {/ * Adicione seu código de manipulador para este controle aqui * / mw_create_window_dialog_colour_chooser (10, 10, "Cor", MW_HAL_LCD_RED, falso, mensagem-> destinatário_handle); } pausa; case MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE: {window_W1_data.chosen_colour = message-> message_data; mw_paint_window_client (mensagem-> destinatário_handle); } pausa; padrão: / * Keep MISRA happy * / break; }}

Construa e execute novamente e você deve ser capaz de definir a cor de preenchimento do círculo.

Este exemplo de janela de dados usa dados que são armazenados em uma estrutura de dados estáticos na parte superior do arquivo de origem. Isso é bom se você tiver apenas uma instância da janela, como fazemos neste exemplo, mas se você tiver mais de uma instância, todas elas compartilharão a mesma estrutura de dados. É possível ter dados por instância para que várias instâncias do mesmo tipo de janela tenham seus próprios dados. Isso é explicado na documentação do MiniWin encontrada no diretório docs. O exemplo de arquivo usa-o para mostrar várias imagens no mesmo tipo de janela (como visto na imagem principal no topo deste instrutível).

Etapa 9: alguma diversão final com a fonte

Um pouco de diversão final com a fonte
Um pouco de diversão final com a fonte

MiniWin suporta renderização de fontes TrueType. Se há algo que faz com que sua interface de usuário tenha uma boa aparência, são as fontes atraentes. Esta etapa final mostra como renderizar uma fonte TrueType em uma janela MiniWin.

Existem duas maneiras de renderizar fontes TrueType. Uma é desenhá-los diretamente na área do cliente, como foi feito anteriormente para o círculo, e a outra é adicionar um controle de caixa de texto à sua janela. Estamos fazendo o último porque é mais fácil.

Agora vamos adicionar um controle de caixa de texto em nosso arquivo de configuração JSON. Adicione-o à definição da janela 2 para que tenha a seguinte aparência:

assim:

{

"Nome": "W2", "Título": "Janela 2", "X": 50, "Y": 65, "Largura": 100, "Altura": 80, "Borda": verdadeiro, "TitleBar": true, "Visible": true, "Minimized": false, "TextBoxes": [{"Name": "TB1", "X": 0, "Y": 0, "Width": 115, "Height": 50, "Justificativa": "Center", "BackgroundColour": "MW_HAL_LCD_YELLOW", "ForegroundColour": "MW_HAL_LCD_BLACK", "Font": "mf_rlefont_BLKCHCRY16", "Enabled": true, "Visible": true}]}

Uma palavra rápida sobre as fontes TrueType no MiniWin. As fontes vêm em arquivos.ttf. Em gerenciadores de janela em computadores maiores, eles são renderizados em sua tela quando são necessários. Isso consome muita capacidade de processamento e memória e não é adequado para dispositivos pequenos. No MiniWin, eles são pré-processados em bitmaps e vinculados em tempo de compilação em um tamanho e estilo de fonte fixos (negrito, itálico etc.), ou seja, você deve decidir quais fontes, em que tamanho e estilo, usará em tempo de compilação. Isso foi feito para você para dois exemplos de fontes no arquivo zip MiniWin que você baixou. Se você quiser usar outras fontes em outros tamanhos e estilos, consulte a documentação do MiniWin na pasta docs. Existem ferramentas no MiniWin para Windows e Linux para pré-processamento de arquivos.ttf em arquivos de código-fonte que você pode colocar em seu projeto.

E uma segunda palavra rápida - a maioria das fontes são copyright, incluindo aquelas que você encontrará no Microsoft Windows. Use-as à vontade para uso pessoal, mas qualquer coisa que você publicar, você deve garantir que a licença com a qual as fontes são publicadas o permita, como é o caso das 2 fontes incluídas no MiniWin, mas não as fontes da Microsoft!

De volta ao código! Gere, elimine arquivos, construa e execute novamente como antes e você verá que a janela 2 agora tem algum texto padrão em um fundo amarelo em uma fonte maluca. Vamos mudar o texto editando o arquivo-fonte do Windows 2, W2.c.

Precisamos nos comunicar com a caixa de texto que acabamos de criar e a maneira como você faz isso, como qualquer comunicação no MiniWin, é enviando uma mensagem para ela. Queremos definir o texto no controle quando a janela é criada, mas antes de ser exibida, portanto, adicionamos o código no manipulador de mensagens no caso MW_WINDOW_CREATED_MESSAGE. Isso é recebido pelo código da janela pouco antes de a janela ser exibida e se destina a inicializações como esta. O gerador de código criou um marcador de posição semelhante a este na função de manipulador de mensagens:

case MW_WINDOW_CREATED_MESSAGE:

/ * Adicione qualquer código de inicialização de janela aqui * / break;

Aqui, postaremos uma mensagem para o controle da caixa de texto informando qual texto queremos mostrar usando a função mw_post_message como esta:

case MW_WINDOW_CREATED_MESSAGE:

/ * Adicione qualquer código de inicialização de janela aqui * / mw_post_message (MW_TEXT_BOX_SET_TEXT_MESSAGE, mensagem-> destinatário_handle, text_box_TB1_handle, 0UL, "Foi uma noite escura e tempestuosa…", MW_CONTROL_MESSAGE); pausa;

Estes são os parâmetros:

  • MW_TEXT_BOX_SET_TEXT_MESSAGE - Este é o tipo de mensagem que estamos enviando para o controle. Eles estão listados em miniwin.he documentados na documentação.
  • mensagem-> recipiente_handle - É de quem é a mensagem - esta janela - o identificador que está no parâmetro de mensagem passado para a função de tratamento de mensagem.
  • text_box_TB1_handle - Para quem estamos enviando a mensagem - o identificador do controle de caixa de texto. Eles estão listados no arquivo gerado miniwin_user.h.
  • 0UL - Valor dos dados, nada neste caso.
  • "Era uma noite escura e tempestuosa…" - Valor do ponteiro - o novo texto.
  • MW_CONTROL_MESSAGE - Tipo de destinatário que é um controle.

É isso. Reconstrua e execute novamente como de costume e você obterá a caixa de texto exibida como na imagem acima.

A postagem de mensagens é fundamental para o MiniWin (assim como para todos os gerenciadores de janelas). Para obter mais exemplos, veja os projetos de exemplo no arquivo zip e, para obter uma explicação abrangente, leia a seção sobre mensagens MiniWin na documentação.

Etapa 10: indo além

Image
Image

É isso para esta introdução básica ao MiniWin. O MiniWin pode fazer muito mais do que foi demonstrado aqui. Por exemplo, a tela da placa usada neste instrutível é pequena e os controles são pequenos e precisam ser usados com um dibber. No entanto, outros exemplos e hardware usam controles maiores (há 2 tamanhos) em monitores maiores e podem ser operados com os dedos.

Existem muitos outros tipos de controle além dos demonstrados aqui. Para obter mais controles, dê uma olhada nos vários arquivos JSON de exemplo na pasta do gerador de código. Todos os tipos de controle são abordados nesses exemplos.

O Windows tem muitas opções. A borda, a barra de título e os ícones são todos configuráveis. Você pode ter barras de rolagem e áreas de cliente de janela de rolagem, várias instâncias do mesmo tipo de janela e as janelas podem ser nuas (apenas uma área de cliente, sem borda ou barra de título), o que significa que elas são fixadas em tempo de compilação no lugar no visor (veja a imagem nesta seção com ícones grandes - na verdade, são 6 janelas nuas).

MiniWin não usa memória dinâmica. Isso o torna adequado para pequenos dispositivos restritos e é um requisito para alguns projetos incorporados. MiniWin e o código que ele gera também é totalmente compatível com MISRA 2012 para o nível 'necessário'.

Para obter mais informações, dê uma olhada na pasta docs para a documentação e também os outros aplicativos de exemplo no arquivo zip. Existem exemplos aqui que mostram como usar todos os recursos do MiniWin e como integrar o MiniWin com FatFS e FreeRTOS.

Recomendado: