Implementing a selection rectangle that works outside the window requires combining mouse capture with proper state tracking. Here's a complete implementation that handles this scenario:
#include <SDL.h>
#include <iostream>
class SelectionRectangle {
public:
SelectionRectangle() : isSelecting{false} {}
void HandleMouseDown(
const SDL_MouseButtonEvent& event) {
if (event.button == SDL_BUTTON_LEFT) {
startX = event.x;
startY = event.y;
currentX = event.x;
currentY = event.y;
isSelecting = true;
// Enable mouse capture for out-of-window
// tracking
SDL_CaptureMouse(SDL_TRUE);
}
}
void HandleMouseUp(
const SDL_MouseButtonEvent& event) {
if (event.button == SDL_BUTTON_LEFT) {
isSelecting = false;
SDL_CaptureMouse(SDL_FALSE);
// Calculate final selection area
int width = std::abs(currentX - startX);
int height = std::abs(currentY - startY);
std::cout << "Final selection: " << width
<< "x" << height << " pixels\n";
}
}
void HandleMouseMotion(
const SDL_MouseMotionEvent& event) {
if (isSelecting) {
currentX = event.x;
currentY = event.y;
}
}
void Render(SDL_Renderer* renderer) {
if (isSelecting) {
// Calculate rectangle dimensions
int x = std::min(startX, currentX);
int y = std::min(startY, currentY);
int w = std::abs(currentX - startX);
int h = std::abs(currentY - startY);
// Draw selection rectangle
SDL_SetRenderDrawColor(
renderer, 0, 120, 255, 255);
SDL_Rect selectionRect{x, y, w, h};
SDL_RenderDrawRect(renderer,
&selectionRect);
// Draw semi-transparent fill
SDL_SetRenderDrawColor(
renderer, 0, 120, 255, 64);
SDL_SetRenderDrawBlendMode(
renderer, SDL_BLENDMODE_BLEND);
SDL_RenderFillRect(renderer,
&selectionRect);
}
}
bool IsSelecting() const {
return isSelecting;
}
private:
bool isSelecting;
int startX, startY;
int currentX, currentY;
};
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window =
SDL_CreateWindow("Selection Rectangle",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800, 600,
SDL_WINDOW_SHOWN);
SDL_Renderer* renderer =
SDL_CreateRenderer(window, -1,
SDL_RENDERER_ACCELERATED);
SelectionRectangle selection;
bool running = true;
while (running) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type ==
SDL_QUIT) { running = false; } else if (
event.type == SDL_MOUSEBUTTONDOWN) {
selection.HandleMouseDown(event.button);
} else if (event.type ==
SDL_MOUSEBUTTONUP) {
selection.HandleMouseUp(event.button);
} else if (event.type ==
SDL_MOUSEMOTION) {
selection.HandleMouseMotion(
event.motion);
}
}
// Clear and render
SDL_SetRenderDrawColor(renderer, 255, 255,
255, 255);
SDL_RenderClear(renderer);
selection.Render(renderer);
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Key features of this implementation:
Mouse Capture Management
Selection State Tracking
Visual Feedback
Error Handling
Answers to questions are automatically generated and may not have been reviewed.
Learn how to track mouse movements and button states across your entire application, even when the mouse leaves your window.