In the lesson, our Rectangle::HandleEvent
function specifically checks if the pressed button was the left mouse button:
// Rectangle.h (Lesson Version Snippet)
// ...
} else if (E.type == SDL_MOUSEBUTTONDOWN) {
if (isPointerHovering &&
E.button.button == SDL_BUTTON_LEFT // Check left
) {
OnLeftClick();
}
}
// ...
The E.button.button
field within the SDL_MouseButtonEvent
structure (which is part of the SDL_Event
union when E.type
is SDL_MOUSEBUTTONDOWN
or SDL_MOUSEBUTTONUP
) tells you which button was pressed.
SDL provides constants for the common mouse buttons:
SDL_BUTTON_LEFT
: The primary mouse button (usually the left one).SDL_BUTTON_RIGHT
: The secondary mouse button (usually the right one).SDL_BUTTON_MIDDLE
: The middle mouse button (often the scroll wheel click).SDL_BUTTON_X1
: Additional mouse button 1 (if present).SDL_BUTTON_X2
: Additional mouse button 2 (if present).To handle right or middle clicks, you simply need to check for these other constants within your SDL_MOUSEBUTTONDOWN
event handling logic.
A good approach is to mirror the OnLeftClick()
pattern by adding corresponding virtual functions to the Rectangle
base class for other clicks you want to support.
// Rectangle.h (Modified)
#pragma once
#include <SDL.h>
class Rectangle {
public:
// ... (Constructor, Render, etc.) ...
virtual void OnMouseEnter() {}
virtual void OnMouseExit() {}
virtual void OnLeftClick() {}
virtual void OnRightClick() {}
virtual void OnMiddleClick() {}
void HandleEvent(SDL_Event& E) {
if (E.type == SDL_MOUSEMOTION) {
// ... (mouse enter/exit logic) ...
bool wasPointerHovering{isPointerHovering};
isPointerHovering = isWithinRect(
E.motion.x, E.motion.y
);
if (!wasPointerHovering && isPointerHovering) {
OnMouseEnter();
} else if (
wasPointerHovering && !isPointerHovering
) {
OnMouseExit();
}
} else if (
E.type == SDL_WINDOWEVENT &&
E.window.event == SDL_WINDOWEVENT_LEAVE
) {
if (isPointerHovering) OnMouseExit();
isPointerHovering = false;
} else if (E.type == SDL_MOUSEBUTTONDOWN) {
if (isPointerHovering) {
if (E.button.button == SDL_BUTTON_LEFT) {
OnLeftClick();
} else if (E.button.button == SDL_BUTTON_RIGHT) {
OnRightClick();
} else if (E.button.button == SDL_BUTTON_MIDDLE) {
OnMiddleClick();
}
}
}
// ... potentially handle SDL_MOUSEBUTTONUP too ...
}
// ... (Rest of the class: SetColor, members) ...
private:
SDL_Rect Rect;
SDL_Color Color{255, 0, 0};
SDL_Color HoverColor{0, 0, 255};
bool isPointerHovering{false};
bool isWithinRect(int x, int y) {
if (x < Rect.x) return false;
if (x > Rect.x + Rect.w) return false;
if (y < Rect.y) return false;
if (y > Rect.y + Rect.h) return false;
return true;
}
};
Now, a derived class like Button
can choose to override these new methods to implement specific behaviors for right or middle clicks:
// Button.h
#pragma once
#include <SDL.h>
#include "Rectangle.h"
#include <iostream> // For std::cout
class UI;
class Button : public Rectangle {
public:
Button(UI& UIManager, const SDL_Rect& Rect)
: UIManager{UIManager},
Rectangle{Rect}
{
SetColor({255, 165, 0, 255});
}
// Override methods as needed
void OnLeftClick() override {
std::cout << "Left Click!\\n";
// Push SDL_QUIT or other actions...
}
void OnRightClick() override {
std::cout << "Right Click! Changing color.\\n";
SetColor({0, 255, 255, 255}); // Cyan
}
// Middle click not overridden, uses base
// class (empty) implementation.
private:
UI& UIManager;
//private: - Typo in original thought, should be private
};
By adding checks for SDL_BUTTON_RIGHT
, SDL_BUTTON_MIDDLE
, etc., in your base event handler and providing corresponding virtual functions, you can create components that respond differently to various mouse button interactions in a clean, extensible way.
Note: Handling mouse events, including button presses, releases, clicks, double-clicks, and mouse wheel scrolling, involves several nuances. We will explore event handling in much greater detail in a subsequent lesson.
Answers to questions are automatically generated and may not have been reviewed.
Learn to create interactive buttons in SDL2 and manage communication between different UI components.