MFC - Mensagens e Eventos

Um aplicativo é feito de vários objetos. Na maioria das vezes, mais de um aplicativo está sendo executado no computador e o sistema operacional é constantemente solicitado a realizar algumas atribuições. Como pode haver tantas solicitações apresentadas de maneira imprevisível, o sistema operacional deixa aos objetos a responsabilidade de especificar o que desejam, quando desejam e que comportamento ou resultado esperam.

Visão geral

  • O sistema operacional Microsoft Windows não pode prever quais tipos de solicitações um objeto precisaria ser atendido e que tipo de atribuição outro objeto precisaria.

  • Para gerenciar todas essas atribuições e solicitações, os objetos enviam mensagens.

  • Cada objeto tem a responsabilidade de decidir qual mensagem enviar e quando.

  • Para enviar uma mensagem, um controle deve criar um evento.

  • Para fazer uma distinção entre os dois, o nome de uma mensagem geralmente começa com WM_, que significa Window Message.

  • O nome de um evento geralmente começa com On, que indica uma ação.

  • O evento é a ação de enviar a mensagem.

Mapa de Mensagens

Como o Windows é um sistema operacional orientado a mensagens, uma grande parte da programação do ambiente Windows envolve o tratamento de mensagens. Cada vez que ocorre um evento, como um pressionamento de tecla ou clique do mouse, uma mensagem é enviada ao aplicativo, que deve então tratar o evento.

  • Para que o compilador gerencie as mensagens, elas devem ser incluídas na definição da classe.

  • o DECLARE_MESSAGE_MAP A macro deve ser fornecida no final da definição da classe, conforme mostrado no código a seguir.

class CMainFrame : public CFrameWnd {
   public:
      CMainFrame();
   protected:
      DECLARE_MESSAGE_MAP()
};
  • As mensagens reais devem ser listadas logo acima da linha DECLARE_MESSAGE_MAP.

  • Para implementar as mensagens, você precisa criar uma tabela de mensagens que seu programa está usando.

  • Esta tabela usa duas macros delimitadoras;

  • Isso começa com um BEGIN_MESSAGE_MAP e termina com um END_MESSAGE_MAP macros.

  • A macro BEGIN_MESSAGE_MAP leva dois argumentos, o nome da sua classe e a classe MFC da qual você derivou sua classe, conforme mostrado no código a seguir.

#include <afxwin.h>
class CMainFrame : public CFrameWnd {
   public:
      CMainFrame();
   protected:
      DECLARE_MESSAGE_MAP()
};
CMainFrame::CMainFrame() {

   // Create the window's frame
   Create(NULL, L"MFC Messages Demo", WS_OVERLAPPEDWINDOW,
                                      CRect(120, 100, 700, 480), NULL);
}
class CMessagesApp : public CWinApp {
   public:
      BOOL InitInstance();
};
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
END_MESSAGE_MAP()
BOOL CMessagesApp::InitInstance(){
   m_pMainWnd = new CMainFrame;
   m_pMainWnd->ShowWindow(SW_SHOW);
   m_pMainWnd->UpdateWindow();
   return TRUE;
}
CMessagesApp theApp;

Vejamos um exemplo simples criando um novo projeto Win32.

Step 1 - Para criar um projeto MFC, clique com o botão direito no projeto e selecione Propriedades.

Step 2 - Na seção esquerda, clique em Propriedades de configuração → Geral.

Step 3 - Selecione a opção 'Usar MFC na DLL compartilhada' na seção Padrões do projeto e clique em OK.

Step 4 - Precisamos adicionar um novo arquivo de origem.

Step 5 - Clique com o botão direito em seu Projeto e selecione Adicionar → Novo Item.

Step 6 - Na seção Modelos, clique em Arquivo C ++ (.cpp).

Step 7 - Clique em Adicionar para continuar.

Step 8 - Agora, adicione o seguinte código no arquivo * .cpp.

#include <afxwin.h>
class CMainFrame : public CFrameWnd {
   public:
      CMainFrame();
   protected:
      DECLARE_MESSAGE_MAP()
};

CMainFrame::CMainFrame() {
   // Create the window's frame
   Create(NULL, L"MFC Messages Demo", WS_OVERLAPPEDWINDOW,
      CRect(120, 100, 700, 480), NULL);
}

class CMessagesApp : public CWinApp {
   public:
      BOOL InitInstance();
};

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
END_MESSAGE_MAP()
BOOL CMessagesApp::InitInstance() {
   m_pMainWnd = new CMainFrame;
   m_pMainWnd->ShowWindow(SW_SHOW);
   m_pMainWnd->UpdateWindow();
   return TRUE;
}
CMessagesApp theApp;

Mensagens do Windows

Existem diferentes tipos de mensagens do Windows, como criar uma janela, mostrar uma janela, etc. Aqui estão algumas das mensagens do Windows comumente usadas.

mensagem Entrada do mapa Descrição
WM_ACTIVATE ON_WM_ACTIVATE () A estrutura chama essa função de membro quando um objeto CWnd está sendo ativado ou desativado.
WM_ACTIVATEA PP ON_WM_ACTIVATEAPP () A estrutura chama essa função de membro para todas as janelas de nível superior da tarefa que está sendo ativada e para todas as janelas de nível superior da tarefa que está sendo desativada.
WM_APPCOMM E ON_WM_APPCOMMAND () A estrutura chama essa função de membro quando o usuário gera um evento de comando do aplicativo.
WM_CANCELMODE WM_CANCELMODE () A estrutura chama esta função de membro para informar CWnd para cancelar qualquer modo interno.
WM_CHILDACTIVATE ON_WM_CHILDACTIVATE () Se o objeto CWnd for uma janela filho de interface de documentos múltiplos (MDI), OnChildActivate é chamado pela estrutura quando o usuário clica na barra de título da janela ou quando a janela é ativada, movida ou dimensionada.
WM_CLIPBOAR DUPDATE ON_WM_CLIPBOARDUPDATE () A estrutura chama essa função de membro quando o conteúdo da área de transferência é alterado.
WM_CLOSE ON_WM_CLOSE () A estrutura chama essa função de membro como um sinal de que o CWnd ou um aplicativo deve ser encerrado.
WM_CONTEXTMENU ON_WM_CONTEXTMENU () Chamado pela estrutura quando o usuário clica com o botão direito do mouse (clica com o botão direito) na janela.
WM_COPYDATA ON_WM_COPYDATA () Essa função de membro é chamada pela estrutura para copiar dados de um aplicativo para outro.
WM_CREATE ON_WM_CREATE () A estrutura chama essa função de membro quando um aplicativo solicita que a janela do Windows seja criada chamando a função de membro Create ou CreateEx.
WM_CTLCOLOR ON_WM_CTLCOLOR () A estrutura chama essa função de membro quando um controle filho está prestes a ser desenhado.
WM_DELETEITEM ON_WM_DELETEITEM () A estrutura chama essa função de membro para informar ao proprietário de uma caixa de listagem ou caixa de combinação desenhada pelo proprietário que a caixa de listagem ou caixa de combinação foi destruída ou que os itens foram removidos.
WM_DESTROY ON_WM_DESTROY () A estrutura chama essa função de membro para informar ao objeto CWnd que ele está sendo destruído.
WM_DRAWITEM ON_WM_DRAWITEM () A estrutura chama essa função de membro para o proprietário de um controle de botão de desenho do proprietário, controle de caixa de combinação, controle de caixa de listagem ou menu quando um aspecto visual do controle ou menu é alterado.
WM_DROPFILES ON_WM_DROPFILES () A estrutura chama esta função de membro quando o usuário libera o botão esquerdo do mouse sobre uma janela que se registrou como o destinatário dos arquivos descartados.
WM_ENABLE ON_WM_ENABLE () A estrutura chama essa função de membro quando um aplicativo altera o estado ativado do objeto CWnd. Sintaxe.
WM_HELPINFO ON_WM_HELPINFO () Lida com Ajuda F1 dentro do aplicativo (usando o contexto atual).
WM_HOTKEY ON_WM_HOTKEY () A estrutura chama essa função de membro quando o usuário pressiona uma tecla de atalho de todo o sistema.
WM_HSCROLL ON_WM_HSCROLL () A estrutura chama essa função de membro quando o usuário clica na barra de rolagem horizontal de uma janela.
WM_KEYDOWN ON_WM_KEYDOWN () A estrutura chama essa função de membro quando uma tecla não pertencente ao sistema é pressionada.
WM_KEYUP ON_WM_KEYUP () A estrutura chama essa função de membro quando uma chave não pertencente ao sistema é liberada.
WM_KILLFOCUS ON_WM_KILLFOCUS () A estrutura chama essa função de membro imediatamente antes de perder o foco de entrada.
WM_LBUTTONDBLCLK ON_WM_LBUTTONDBLCLK () A estrutura chama essa função de membro quando o usuário clica duas vezes com o botão esquerdo do mouse.
WM_LBUTTONDOWN ON_WM_LBUTTONDOWN () A estrutura chama essa função de membro quando o usuário pressiona o botão esquerdo do mouse.
WM_LBUTTONUP ON_WM_LBUTTONUP () A estrutura chama essa função de membro quando o usuário libera o botão esquerdo do mouse.
WM_MBUTTONDBLCLK ON_WM_MBUTTONDBLCLK () A estrutura chama essa função de membro quando o usuário clica duas vezes no botão do meio do mouse.
WM_MBUTTONDOWN ON_WM_MBUTTONDOWN () A estrutura chama essa função de membro quando o usuário pressiona o botão do meio do mouse.
WM_MBUTTONUP ON_WM_MBUTTONUP () A estrutura chama essa função de membro quando o usuário libera o botão do meio do mouse.
WM_MENUSELECT ON_WM_MENUSELECT () Se o objeto CWnd estiver associado a um menu, OnMenuSelect será chamado pela estrutura quando o usuário selecionar um item de menu.
WM_MOUSEACTIVATE ON_WM_MOUSEACTIVATE () A estrutura chama esta função de membro quando o cursor está em uma janela inativa e o usuário pressiona um botão do mouse.
WM_MOUSEHOVER ON_WM_MOUSEHOVER () A estrutura chama essa função de membro quando o cursor passa sobre a área do cliente da janela pelo período de tempo especificado em uma chamada anterior para TrackMouseEvent.
WM_MOUSEHWHEEL ON_WM_MOUSEHWHEEL () O framework chama este membro quando a janela atual é composta pelo Desktop Window Manager (DWM), e essa janela é maximizada.
WM_MOUSELEAVE ON_WM_MOUSELEAVE () A estrutura chama essa função de membro quando o cursor deixa a área do cliente da janela especificada em uma chamada anterior para TrackMouseEvent.
WM_MOUSEMOVE ON_WM_MOUSEMOVE () A estrutura chama essa função de membro quando o cursor do mouse se move.
WM_MOVE ON_WM_MOVE () A estrutura chama essa função de membro depois que o objeto CWnd foi movido.
WM_PAINT ON_WM_PAINT () A estrutura chama essa função de membro quando o Windows ou um aplicativo faz uma solicitação para redesenhar uma parte da janela de um aplicativo.
WM_SETFOCUS () ON_WM_SETFOCUS () A estrutura chama essa função de membro depois de obter o foco de entrada.
WM_SIZE () ON_WM_SIZE () A estrutura chama essa função de membro após a alteração do tamanho da janela.
WM_TIMER ON_WM_TIMER () A estrutura chama essa função de membro após cada intervalo especificado na função de membro SetTimer usada para instalar um cronômetro.
WM_VSCROLL ON_WM_VSCROLL () A estrutura chama essa função de membro quando o usuário clica na barra de rolagem vertical da janela.
WM_WINDOWPOSCHANGED ON_WM_WINDOWPOSCHANGED () A estrutura chama essa função de membro quando o tamanho, posição ou ordem Z mudou como resultado de uma chamada para a função de membro SetWindowPos ou outra função de gerenciamento de janela.

Vejamos um exemplo simples de criação de janela.

WM_CREATE - Quando um objeto, chamado de janela, é criado, o quadro que cria os objetos envia uma mensagem identificada como ON_WM_CREATE.

Step 1- Para criar ON_WM_CREATE, adicione afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct); antes de DECLARE_MESSAGE_MAP () conforme mostrado abaixo.

class CMainFrame : public CFrameWnd {
   public:
      CMainFrame();
   protected:
      afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
      DECLARE_MESSAGE_MAP()
};

Step 2 - Adicione o ON_WM_CREATE () após o BEGIN_MESSAGE_MAP (CMainFrame, CFrameWnd) e antes de END_MESSAGE_MAP ()

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
   ON_WM_CREATE()
END_MESSAGE_MAP()

Step 3 - Aqui está a implementação do OnCreate ()

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
   // Call the base class to create the window
   if (CFrameWnd::OnCreate(lpCreateStruct) == 0) {

      // If the window was successfully created, let the user know
      MessageBox(L"The window has been created!!!");
      // Since the window was successfully created, return 0
      return 0;
   }
   // Otherwise, return -1
   return -1;
}

Step 4 - Agora seu arquivo * .cpp será semelhante ao mostrado no código a seguir.

#include <afxwin.h>
class CMainFrame : public CFrameWnd {
   public:
      CMainFrame();
   protected:
      afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
      DECLARE_MESSAGE_MAP()
};
CMainFrame::CMainFrame() {

   // Create the window's frame
   Create(NULL, L"MFC Messages Demo", WS_OVERLAPPEDWINDOW,
      CRect(120, 100, 700, 480), NULL);
}
class CMessagesApp : public CWinApp {
   public:
      BOOL InitInstance();
};
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
   ON_WM_CREATE()
END_MESSAGE_MAP()
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
   // Call the base class to create the window
   if (CFrameWnd::OnCreate(lpCreateStruct) == 0) {
      // If the window was successfully created, let the user know
      MessageBox(L"The window has been created!!!");
      // Since the window was successfully created, return 0
      return 0;
   }
   // Otherwise, return -1
   return -1;
}
BOOL CMessagesApp::InitInstance() { 
   m_pMainWnd = new CMainFrame;
   m_pMainWnd -> ShowWindow(SW_SHOW);
   m_pMainWnd -> UpdateWindow();
   return TRUE;
}
CMessagesApp theApp;

Step 5 - Quando o código acima for compilado e executado, você verá a seguinte saída.

Step 6 - Ao clicar em OK, a janela principal será exibida.

Mensagens de Comando

Uma das principais características de um aplicativo gráfico é apresentar os controles e recursos do Windows que permitem ao usuário interagir com a máquina. Exemplos de controles que aprenderemos são botões, caixas de listagem, caixas de combinação, etc.

Um tipo de recurso que apresentamos na lição anterior é o menu. Esses controles e recursos podem iniciar suas próprias mensagens quando o usuário clica neles. Uma mensagem que emana de um controle ou recurso do Windows é chamada de mensagem de comando.

Vejamos um exemplo simples de mensagens de comando.

Para fornecer ao seu aplicativo a capacidade de criar um novo documento, a classe CWinApp fornece o método OnFileNew ().

afx_msg void OnFileNew();

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
   ON_COMMAND(ID_FILE_NEW, CMainFrame::OnFileNew)
END_MESSAGE_MAP()

Aqui está a definição do método -

void CMainFrame::OnFileNew() {
   // Create New file
}

Mensagens do teclado

UMA keyboardé um objeto de hardware conectado ao computador. Por padrão, é usado para inserir símbolos reconhecíveis, letras e outros caracteres em um controle. Cada tecla do teclado exibe um símbolo, uma letra ou uma combinação deles, para dar uma indicação de para que a tecla pode ser usada. O usuário normalmente pressiona uma tecla, que envia um sinal para um programa.

Cada chave possui um código que o sistema operacional pode reconhecer. Este código é conhecido comovirtual key code.

Sr. Não. Constante / valor e descrição
1

VK_LBUTTON

Botão esquerdo do mouse

2

VK_RBUTTON

Botão direito do mouse

3

VK_CANCEL

Processamento de quebra de controle

4

VK_MBUTTON

Botão do meio do mouse (mouse de três botões)

5

VK_BACK

Tecla BACKSPACE

6

VK_RETURN

Tecla Enter

7

VK_TAB

Tecla de tabulação

8

VK_CLEAR

CLEAR key

9

VK_SHIFT

Tecla Shift

10

VK_CONTROL

Tecla CTRL

11

VK_MENU

Tecla ALT

12

VK_PAUSE

Tecla PAUSA

13

VK_CAPITAL

Tecla CAPS LOCK

14

VK_ESCAPE

Tecla ESC

15

VK_SPACE

BARRA DE ESPAÇO

16

VK_PRIOR

Tecla PAGE UP

17

VK_NEXT

Tecla PAGE DOWN

18

VK_END

Tecla END

19

VK_HOME

Tecla HOME

20

VK_LEFT

Tecla SETA PARA A ESQUERDA

21

VK_UP

Tecla de SETA PARA CIMA

22

VK_RIGHT

Tecla de SETA PARA A DIREITA

23

VK_DOWN

Tecla de SETA PARA BAIXO

24

VK_SELECT

Tecla SELECT

25

VK_PRINT

Tecla PRINT

26

VK_EXECUTE

Tecla EXECUTE

27

VK_SNAPSHOT

Tecla PRINT SCREEN

28

VK_INSERT

Chave INS

29

VK_DELETE

Tecla DEL

30

VK_NUMPAD0

Tecla 0 do teclado numérico

31

VK_NUMPAD1

Teclado numérico 1 tecla

32

VK_NUMPAD2

Tecla 2 do teclado numérico

33

VK_NUMPAD3

Tecla 3 do teclado numérico

34

VK_NUMPAD4

Tecla do teclado numérico 4

35

VK_NUMPAD5

Tecla 5 do teclado numérico

36

VK_NUMPAD6

Tecla 6 do teclado numérico

37

VK_NUMPAD7

Tecla 7 do teclado numérico

38

VK_NUMPAD8

8 teclas do teclado numérico

39

VK_NUMPAD9

Tecla 9 do teclado numérico

40

VK_MULTIPLY

Chave de multiplicação

41

VK_ADD

Adicionar chave

42

VK_SEPARATOR

Chave separadora

43

VK_SUBTRACT

Subtrair chave

44

VK_DECIMAL

Chave decimal

45

VK_DIVIDE

Chave de divisão

46

VK_F1

Tecla F1

47

VK_F2

Tecla F2

48

VK_F3

Tecla F3

49

VK_F4

Tecla F4

50

VK_F5

Tecla F5

52

VK_F6

Tecla F6

53

VK_F7

Tecla F7

54

VK_F8

Tecla F8

55

VK_F9

Tecla F9

56

VK_F10

Tecla F10

57

VK_F11

Tecla F11

58

VK_F12

Tecla F12

59

VK_NUMLOCK

Tecla NUM LOCK

60

VK_SCROLL

Tecla SCROLL LOCK

61

VK_LSHIFT

Tecla SHIFT esquerda

62

VK_RSHIFT

Tecla SHIFT direita

63

VK_LCONTROL

Tecla de controle esquerda

64

VK_RCONTROL

Tecla CONTROL direita

Pressionar uma tecla faz com que uma mensagem WM_KEYDOWN ou WM_SYSKEYDOWN seja colocada na mensagem do thread. Isso pode ser definido da seguinte forma -

afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);

Vejamos um exemplo simples.

Step 1 - Aqui está a mensagem.

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
   ON_WM_CREATE()
   ON_WM_KEYDOWN()
END_MESSAGE_MAP()

Step 2 - Aqui está a implementação de OnKeyDown ().

void CMainFrame::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
   switch (nChar) {

      case VK_RETURN:
         MessageBox(L"You pressed Enter");
         break;
      case VK_F1:
         MessageBox(L"Help is not available at the moment");
         break;
      case VK_DELETE:
         MessageBox(L"Can't Delete This");
         break;
      default:
         MessageBox(L"Whatever");
   }
}

Step 3 - Quando o código acima for compilado e executado, você verá a seguinte saída.

Step 4 - Quando você pressiona Enter, a seguinte mensagem é exibida.

Mensagens do mouse

O mouse é outro objeto anexado ao computador, permitindo ao usuário interagir com a máquina.

  • Se o botão esquerdo do mouse foi pressionado, uma mensagem ON_WM_LBUTTONDOWN é enviada. A sintaxe desta mensagem é -

    • afx_msg void OnLButtonDown (UINT nFlags, ponto CPoint)

  • Se o botão direito do mouse foi pressionado, uma mensagem ON_WM_RBUTTONDOWN é enviada. Sua sintaxe é -

    • afx_msg void OnRButtonDown (UINT nFlags, ponto CPoint)

  • Da mesma forma, se o botão esquerdo do mouse for liberado, a mensagem ON_WM_LBUTTONUP será enviada. Sua sintaxe é -

    • afx_msg void OnLButtonUp (UINT nFlags, ponto CPoint)

  • Se o botão direito do mouse estiver sendo liberado, a mensagem ON_WM_TBUTTONUP será enviada. Sua sintaxe é -

    • afx_msg void OnRButtonUp (UINT nFlags, ponto CPoint)

Vejamos um exemplo simples.

Step 1 - Adicione as duas funções a seguir na definição da classe CMainFrame, conforme mostrado no código a seguir.

class CMainFrame : public CFrameWnd {
   public:
      CMainFrame();
   protected:
      afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
      afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
      afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
      DECLARE_MESSAGE_MAP()
};

Step 2 - Adicione os dois mapas de mensagens a seguir.

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
   ON_WM_KEYDOWN()
   ON_WM_LBUTTONDOWN()
   ON_WM_RBUTTONUP()
END_MESSAGE_MAP()

Step 3 - Aqui está a definição das funções.

void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point) { 
   CString MsgCoord;
   MsgCoord.Format(L"Left Button at P(%d, %d)", point.x, point.y);
   MessageBox(MsgCoord);
}
void CMainFrame::OnRButtonUp(UINT nFlags, CPoint point) { 
   MessageBox(L"Right Mouse Button Up");
}

Step 4 - Ao executar este aplicativo, você verá a seguinte saída.

Step 5 - Ao clicar em OK, você verá a seguinte mensagem.

Step 6- Clique com o botão direito nesta janela. Agora, quando você soltar o botão direito do mouse, a seguinte mensagem será exibida.