UI Elements and DPI

How do I handle DPI scaling for UI elements like buttons that need to stay a specific physical size?

When creating UI elements that need to maintain a consistent physical size across different DPI settings, we need to consider both scaling and positioning. Here's a comprehensive approach to DPI-aware UI elements.

Creating a Basic UI System

Let's create a simple button class that maintains physical size:

// UISystem.h
#include <SDL.h>
#include <string>
#include <functional>

float GetDPIScale(SDL_Window* Window) {/*...*/} class Button { SDL_Rect Bounds; std::string Text; // Width in screen coordinates float PhysicalWidth; // Height in screen coordinates float PhysicalHeight; public: Button( float X, float Y, float Width, float Height, const std::string& ButtonText) : PhysicalWidth{Width} , PhysicalHeight{Height} , Text{ButtonText} { Bounds.x = int(X); Bounds.y = int(Y); // Initial size without scaling UpdateSize(1.0f); } void UpdateSize(float Scale) { Bounds.w = int(PhysicalWidth * Scale); Bounds.h = int(PhysicalHeight * Scale); } void Draw(SDL_Renderer* Renderer) { // Draw button background SDL_SetRenderDrawColor( Renderer, 200, 200, 200, 255); SDL_RenderFillRect(Renderer, &Bounds); // Draw border SDL_SetRenderDrawColor( Renderer, 100, 100, 100, 255); SDL_RenderDrawRect(Renderer, &Bounds); } bool Contains(int X, int Y) { return X >= Bounds.x && X < Bounds.x + Bounds.w && Y >= Bounds.y && Y < Bounds.y + Bounds.h; } }; class UISystem { std::vector<Button> Buttons; float CurrentScale{1.0f}; public: void AddButton( float X, float Y, float Width, float Height, const std::string& Text) { Buttons.emplace_back( X, Y, Width, Height, Text); Buttons.back().UpdateSize(CurrentScale); } void UpdateDPIScale(float NewScale) { if (CurrentScale != NewScale) { CurrentScale = NewScale; for (auto& Button : Buttons) { Button.UpdateSize(NewScale); } } } void Draw(SDL_Renderer* Renderer) { for (auto& Button : Buttons) { Button.Draw(Renderer); } } };

Using the UI System

Here's how to use this system in a real application:

// main.cpp
#include <SDL.h>
#include "UISystem.h"

int main() {
  SDL_SetHint(
    SDL_HINT_WINDOWS_DPI_SCALING, "1");
  SDL_Init(SDL_INIT_VIDEO);

  SDL_Window* Window{
    SDL_CreateWindow(
      "UI Scaling Demo",
      SDL_WINDOWPOS_UNDEFINED,
      SDL_WINDOWPOS_UNDEFINED,
      800, 600,
      SDL_WINDOW_ALLOW_HIGHDPI
    )};

  SDL_Renderer* Renderer{
    SDL_CreateRenderer(
      Window, -1, SDL_RENDERER_ACCELERATED)};

  UISystem UI;
  UI.AddButton(50, 50, 200, 60, "Click Me");
  UI.AddButton(50, 150, 200, 60, "Options");

  float Scale{GetDPIScale(Window)};
  UI.UpdateDPIScale(Scale);

  SDL_Event E;
  bool Running{true};
  while (Running) {
    while (SDL_PollEvent(&E)) {
      if (E.type == SDL_QUIT) Running = false;
      if (E.type == SDL_WINDOWEVENT) {
        if (
           E.window.event == SDL_WINDOWEVENT_RESIZED
        || E.window.event == SDL_WINDOWEVENT_MOVED
        ) {
          Scale = GetDPIScale(Window);
          UI.UpdateDPIScale(Scale);
        }
      }
    }

    SDL_SetRenderDrawColor(
      Renderer, 240, 240, 240, 255);
    SDL_RenderClear(Renderer);

    UI.Draw(Renderer);

    SDL_RenderPresent(Renderer);
  }

  SDL_DestroyRenderer(Renderer);
  SDL_DestroyWindow(Window);
  SDL_Quit();
  return 0;
}

The key points to remember when implementing DPI-aware UI elements are:

  • Store physical sizes separately from rendered sizes
  • Update all UI elements when DPI scale changes
  • Consider input handling relative to scaled coordinates
  • Test with different DPI settings to ensure consistency

Pixel Density and High-DPI Displays

Learn how to create SDL applications that look great on modern displays across different platforms

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Scaling Text in SDL
How can I make text scale properly with different DPI settings?
Why Handle DPI Scaling
Why do we need to handle DPI scaling at all? Can't we just let the operating system handle it?
Image Scaling and DPI
If I'm loading images for my game, do I need different versions for different DPI settings?
DPI Scale Calculation
In GetDPIScale(), why do we only use the width to calculate the scale? What about height?
DPI with SDL_Renderer
The example uses SDL_Surface. Does DPI scaling work differently with SDL_Renderer or SDL_Texture?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant