Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
As seções anteriores discutiram cliques do mouse e movimento do mouse. Aqui estão algumas outras operações que podem ser executadas com o mouse.
Arrastando elementos da interface do usuário
Se a interface do usuário der suporte ao arrasto de elementos da interface do usuário, há uma outra função que você deve chamar no manipulador de mensagens do mouse para baixo: DragDetect. A função DragDetect retornará VERDADEIRO se o usuário iniciar um gesto de mouse que deve ser interpretado como arrastar. O código a seguir mostra como usar essa função.
case WM_LBUTTONDOWN:
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
if (DragDetect(m_hwnd, pt))
{
// Start dragging.
}
}
return 0;
Esta é a ideia: quando um programa dá suporte a arrastar e soltar, você não quer que cada clique do mouse seja interpretado como um arrastar. Caso contrário, o usuário pode acidentalmente arrastar algo quando ele ou ela simplesmente pretende clicar nele (por exemplo, para selecioná-lo). Mas se um mouse for particularmente sensível, pode ser difícil manter o mouse perfeitamente parado enquanto clica. Portanto, o Windows define um limite de arrastar de alguns pixels. Quando o usuário pressiona o botão do mouse, ele não é considerado um arrastar, a menos que o mouse ultrapasse esse limite. A função DragDetect testa se esse limite é atingido. Se a função retornar TRUE, você poderá interpretar o clique do mouse como um arraste. Caso contrário, não.
Nota
Se DragDetect retornar FALSE, o Windows suprimirá a mensagem de WM_LBUTTONUP quando o usuário liberar o botão do mouse. Portanto, não chame DragDetect, a menos que seu programa esteja atualmente em um modo que dê suporte à arrastar. (Por exemplo, se um elemento de interface do usuário arrastável já estiver selecionado.) No final deste módulo, veremos um exemplo de código mais longo que usa a função DragDetect.
Confinando o cursor
Às vezes, talvez você queira restringir o cursor à área do cliente ou a uma parte da área do cliente. A funçãoClipCursorrestringe o movimento do cursor a um retângulo especificado. Esse retângulo é dado em coordenadas de tela, em vez de coordenadas do cliente, portanto, o ponto (0, 0) significa o canto superior esquerdo da tela. Para converter coordenadas do cliente em coordenadas de tela, chame a função ClientToScreen.
O código a seguir limita o cursor à área do cliente da janela.
// Get the window client area.
RECT rc;
GetClientRect(m_hwnd, &rc);
// Convert the client area to screen coordinates.
POINT pt = { rc.left, rc.top };
POINT pt2 = { rc.right, rc.bottom };
ClientToScreen(m_hwnd, &pt);
ClientToScreen(m_hwnd, &pt2);
SetRect(&rc, pt.x, pt.y, pt2.x, pt2.y);
// Confine the cursor.
ClipCursor(&rc);
ClipCursor usa uma estrutura deRECT, mas ClientToScreen usa uma estruturaPOINT. Um retângulo é definido por seus pontos superior esquerdo e inferior direito. Você pode limitar o cursor a qualquer área retangular, incluindo áreas fora da janela, mas limitar o cursor à área do cliente é uma maneira típica de usar a função. Limitar o cursor a uma região totalmente fora da janela seria incomum, e os usuários provavelmente perceberiam isso como um bug.
Para remover a restrição, chame ClipCursor com o valor NULL.
ClipCursor(NULL);
Eventos de acompanhamento do mouse: focalizar e sair
Duas outras mensagens do mouse são desabilitadas por padrão, mas podem ser úteis para alguns aplicativos:
- WM_MOUSEHOVER: o cursor passou o mouse sobre a área do cliente por um período fixo.
- WM_MOUSELEAVE: o cursor deixou a área do cliente.
Para habilitar essas mensagens, chame a funçãoTrackMouseEvent.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = hwnd;
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.dwHoverTime = HOVER_DEFAULT;
TrackMouseEvent(&tme);
A estruturaTRACKMOUSEEVENTcontém os parâmetros da função. O dwFlags membro da estrutura contém sinalizadores de bits que especificam em quais mensagens de acompanhamento você está interessado. Você pode optar por obter WM_MOUSEHOVER e WM_MOUSELEAVE, conforme mostrado aqui, ou apenas um dos dois. O membro dwHoverTime especifica por quanto tempo o mouse precisa passar o mouse antes que o sistema gere uma mensagem de focalização. Esse valor é fornecido em milissegundos. A constante HOVER_DEFAULT significa usar o padrão do sistema.
Depois de receber uma das mensagens solicitadas, a função TrackMouseEvent será redefinida. Você deve chamá-lo novamente para obter outra mensagem de acompanhamento. No entanto, você deve aguardar até que a próxima mensagem de movimentação do mouse antes de chamar TrackMouseEvent novamente. Caso contrário, sua janela poderá ser inundada com mensagens de rastreamento. Por exemplo, se o mouse estiver pairando, o sistema continuará gerando um fluxo de mensagens WM_MOUSEHOVER enquanto o mouse estiver parado. Na verdade, você não deseja outra mensagem WM_MOUSEHOVER até que o mouse se mova para outro local e passe o mouse novamente.
Aqui está uma classe auxiliar pequena que você pode usar para gerenciar eventos de rastreamento de mouse.
class MouseTrackEvents
{
bool m_bMouseTracking;
public:
MouseTrackEvents() : m_bMouseTracking(false)
{
}
void OnMouseMove(HWND hwnd)
{
if (!m_bMouseTracking)
{
// Enable mouse tracking.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = hwnd;
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.dwHoverTime = HOVER_DEFAULT;
TrackMouseEvent(&tme);
m_bMouseTracking = true;
}
}
void Reset(HWND hwnd)
{
m_bMouseTracking = false;
}
};
O exemplo a seguir mostra como usar essa classe no procedimento de janela.
LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_MOUSEMOVE:
mouseTrack.OnMouseMove(m_hwnd); // Start tracking.
// TODO: Handle the mouse-move message.
return 0;
case WM_MOUSELEAVE:
// TODO: Handle the mouse-leave message.
mouseTrack.Reset(m_hwnd);
return 0;
case WM_MOUSEHOVER:
// TODO: Handle the mouse-hover message.
mouseTrack.Reset(m_hwnd);
return 0;
}
return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
Os eventos de acompanhamento do mouse exigem processamento adicional pelo sistema, portanto, deixe-os desabilitados se você não precisar deles.
Para fins de integridade, aqui está uma função que consulta o sistema quanto ao tempo limite de foco padrão.
UINT GetMouseHoverTime()
{
UINT msec;
if (SystemParametersInfo(SPI_GETMOUSEHOVERTIME, 0, &msec, 0))
{
return msec;
}
else
{
return 0;
}
}
Roda do mouse
A função a seguir verifica se uma roda do mouse está presente.
BOOL IsMouseWheelPresent()
{
return (GetSystemMetrics(SM_MOUSEWHEELPRESENT) != 0);
}
Se o usuário girar a roda do mouse, a janela com foco receberá uma mensagem WM_MOUSEWHEEL. O parâmetro wParam dessa mensagem contém um valor inteiro chamado delta que mede o quão longe a roda foi girada. O delta usa unidades arbitrárias, em que 120 unidades são definidas como a rotação necessária para executar uma "ação". Claro, a definição de uma ação depende do seu programa. Por exemplo, se a roda do mouse for usada para rolar texto, cada 120 unidades de rotação rolará uma linha de texto.
O sinal do delta indica a direção da rotação:
- Positivo: girar para frente, longe do usuário.
- Negativo: gire para trás, em direção ao usuário.
O valor do delta é colocado em wParam juntamente com alguns sinalizadores adicionais. Use a macro GET_WHEEL_DELTA_WPARAM para obter o valor do delta.
int delta = GET_WHEEL_DELTA_WPARAM(wParam);
Se a roda do mouse tiver uma alta resolução, o valor absoluto do delta poderá ser menor que 120. Nesse caso, se fizer sentido que a ação ocorra em incrementos menores, você poderá fazê-lo. Por exemplo, o texto pode rolar por incrementos de menos de uma linha. Caso contrário, acumule o delta total até que a roda gire o suficiente para executar a ação. Armazene o delta não utilizado em uma variável e, quando 120 unidades se acumularem (positivas ou negativas), execute a ação.
Próximo