Click-and-Drag Selection
How do I implement a click-and-drag selection rectangle?
Implementing a selection rectangle involves tracking the start and current positions of a drag operation to define the rectangle's bounds. Here's how to create one:
#include <SDL.h>
#include <iostream>
#include "Window.h"
class SelectionBox {
public:
void Tick() {
int MouseX, MouseY;
Uint32 Buttons = SDL_GetMouseState(
&MouseX, &MouseY);
if (Buttons & SDL_BUTTON_LMASK) {
if (!IsSelecting) {
// Start new selection
StartX = MouseX;
StartY = MouseY;
IsSelecting = true;
}
// Calculate rectangle bounds
CurrentX = MouseX;
CurrentY = MouseY;
int Left = std::min(StartX, CurrentX);
int Right = std::max(StartX, CurrentX);
int Top = std::min(StartY, CurrentY);
int Bottom = std::max(StartY, CurrentY);
int Width = Right - Left;
int Height = Bottom - Top;
std::cout << "Selection: Position("
<< Left << ", " << Top << ") "
<< "Size(" << Width << ", "
<< Height << ")\n";
} else if (IsSelecting) {
// Selection complete
IsSelecting = false;
PrintFinalSelection();
}
}
private:
bool IsSelecting{false};
int StartX{0}, StartY{0};
int CurrentX{0}, CurrentY{0};
void PrintFinalSelection() {
int Left = std::min(StartX, CurrentX);
int Right = std::max(StartX, CurrentX);
int Top = std::min(StartY, CurrentY);
int Bottom = std::max(StartY, CurrentY);
std::cout << "Final selection area: ("
<< Left << ", " << Top << ") to ("
<< Right << ", " << Bottom << ")\n";
}
};
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_VIDEO);
Window GameWindow;
SelectionBox Selection;
SDL_Event E;
while (true) {
while (SDL_PollEvent(&E)) {
// Handle other events...
}
Selection.Tick();
GameWindow.Update();
}
SDL_Quit();
return 0;
}
Selection: Position(100, 150) Size(5, 3)
Selection: Position(100, 150) Size(10, 8)
Selection: Position(100, 150) Size(15, 12)
Final selection area: (100, 150) to (115, 162)
How It Works
The selection rectangle system works by:
- Storing the initial click position when the left mouse button is first pressed
- Continuously updating the current mouse position while dragging
- Calculating the rectangle bounds by finding the minimum and maximum X/Y coordinates
- Supporting selections in any direction (up/down/left/right)
Enhanced Version
Here's an enhanced version that includes minimum size and snapping:
#include <SDL.h>
class AdvancedSelectionBox {
public:
void Tick() {
int MouseX, MouseY;
Uint32 Buttons = SDL_GetMouseState(
&MouseX, &MouseY);
if (Buttons & SDL_BUTTON_LMASK) {
if (!IsSelecting) {
StartX = MouseX;
StartY = MouseY;
IsSelecting = true;
}
CurrentX = MouseX;
CurrentY = MouseY;
// Add minimum size requirement
int Width = std::abs(CurrentX - StartX);
int Height = std::abs(CurrentY - StartY);
if (Width < MinimumSize) {
CurrentX = StartX + (CurrentX > StartX
? MinimumSize : -MinimumSize);
}
if (Height < MinimumSize) {
CurrentY = StartY + (CurrentY > StartY
? MinimumSize : -MinimumSize);
}
// Snap to grid
CurrentX = (CurrentX / GridSize) * GridSize;
CurrentY = (CurrentY / GridSize) * GridSize;
PrintSelection();
} else if (IsSelecting) {
IsSelecting = false;
PrintFinalSelection();
}
}
private:
static const int MinimumSize = 10;
static const int GridSize = 8;
bool IsSelecting{false};
int StartX{0}, StartY{0};
int CurrentX{0}, CurrentY{0};
};
This enhanced version includes:
- Minimum selection size requirement
- Grid snapping for more precise selections
- Support for selections in any direction
- Clean separation of selection logic from rendering
The system is flexible enough to be used for many purposes:
- Selecting multiple objects in a game
- Drawing rectangles in an art program
- Defining regions for game mechanics
- Creating UI elements dynamically
Mouse State
Learn how to monitor mouse position and button states in real-time using SDL's state query functions