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.
Comprehensive course covering advanced concepts, and how to use them on large-scale projects.
View Course