Getting screen resolution on Windows 11

Are there other functions I can use to get the monitor resolution on Windows 11? I use this code:
set(0, 'units', 'pixels'); % Sets the units of your root object (screen) to pixels
Pix_SS = get(0, 'screensize'); % Obtains the pixel information
And all I get is 1920 x 1080? This Dell U4320Q is 3840 x 2160 as shown in this Settings > Display resolution:

4 Comments

I found this code which works very well, for those who didn't find it :
ScreenPixelsPerInch = java.awt.Toolkit.getDefaultToolkit().getScreenResolution()
ScreenDevices = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
MainScreen = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getScreen()+1;
MainBounds = ScreenDevices(MainScreen).getDefaultConfiguration().getBounds();
MonitorPositions = zeros(numel(ScreenDevices),4);
First of all, I'm susprised to find native support for Java in Matlab, which opens up all kinds of interesting possibilities.
Second of all, even if I get the true physiical screen resolution from Java, it still does not solve my problem? Which is, how I force a figure or an axis to a "real" physical size? If I try to set a figure to be 800x600, for example :
set(FigureH, 'color', 'w', 'MenuBar', 'none', 'Position', [500 200 800 600]);
In actuality, the figure size is "twice" that much or 1600x1200.
May not seem like a problem to you but my algorithms are based on the 'sizes' I have access to from regular Matlab code, such as "MouseMove Fcn" callback :
function mouseMove (source, eventdata)
ax1 = gca; % ancestor(source, 'axes');
% CurrentPoint is relative to ax.InnerPosition
CP = round(get (ax1, 'CurrentPoint'));
x = CP(1,1);
y = CP(1,2);
There is no way I could "trust" the CurrentPoint vector information if the code is ran on a 4K monitor?
Is there a way I can call for all "pixel units" to be on 1920 x 1080 scale?
Even if the interface ends up looking "tiny" on a 4K monitor?
Sorry for these kinds of "mundane" questions which are not very scientific-related...
I just remember tampering with the system "scaling" setting :
I set the scale back to 100% and Matlab's figure size became exactly what I called for, 800x600.
Sadly, straight 4K resolution is unusable for my eyes on this monitor. So I went back to 200% scale.
I guess the question becomes, is there a way, on Windows 11, to find what "scaling" is the going system value?
From what I recall (from discussions when display scaling was new in windows), this parameter is poorly communicated to programs.
But it everything is off by the same factor, is there a problem for your application?
An additional note: Java will be removed from Matlab somewhere in a future release. It is also generally undocumented, meaning it may change release to release without warnings in the release notes.
@Rik: While MATLAB will no longer include Java by default, it will still be usable from within MATLAB, but the user will be responsible for providing their own Java. Using Java within MATLAB is fully documented. For example, this documentation page discusses use of your own Java classes within MATLAB: Call Java from MATLAB

Sign in to comment.

Answers (2)

Note that this is undocumented and not guaranteed to work indefinitely, but there is a property on all figures called ScreenPixelsPerInch that is similar to the property of the same name on groot, but while the value on groot takes into account the display scaling, the value on Figure does not. You can use this to get a conversion factor for the ScreenSize or MonitorPositions properties on groot.
For example:
f = figure;
scaledDPI = groot().ScreenPixelsPerInch % On my machine this is 96
unscaledDPI = f.ScreenPixelsPerInch % On my machine this is 144 because I have 150% scaling.
scaleFactor = unscaledDPI./scaledDPI % On my machine this is 1.5 because I have 150% scaling.
scaledMonitorPositions = groot().MonitorPositions % On my machine this is [1 1 2560 1440; -2559 -5 2560 1440]
% When doing the conversion, the first two values (left and bottom) are
% 1-based, so you need to subtract 1, do the scaling, then add 1.
unscaledMonitorPositions = (scaledMonitorPositions-[1 1 0 0]).*scaleFactor+[1 1 0 0]
On my machine (which runs Windows with 150% display scaling), the Figure's ScreenPixelsPerInch reports 144, while groot reports 96, which reflects the 150% scaling. Using the code above, I get the correct actual resolution of my two monitors (3840 x 2160).
Jacorem
Jacorem about 1 hour ago
Edited: Jacorem about 1 hour ago
First of all, I apologize for the necroposting (last activity on this question was more than 2 years ago...), but I'm facing a similar problem on Matlab R2025b and the solution proposed by @Benjamin Kraus doesn't seems to work any more (sigh).
My solution will:
  1. move a figure to the monitor we are interested in
  2. maximized the figure
  3. read the figure position in the coordinates we like most (the available space for the figures)
  4. (if wanted) calculate the DPI scaling
What I propose is (a) not elegant at all and (b) may rise some concerns about epilettic attack (we are changing the figure size multiple times in a small time frame), but I think that is robust and reliable on the long term.
%% 0a - define handles
selWin = uifigure();
grootObj = groot();
%% 0b - select desired monitor
monitorIdx = 1;
%% 1a - change groot and figure units to normalized
dispUnits = "normalized";
selWin.Units = dispUnits;
grootObj.Units = dispUnits;
%% 1b - move the figure to the monitor we are interested in
% based on my (single) test, the figure should "belong" to
% the monitor containing its center pixel, so let's make
% sure that the figure is small enought and that it will be
% on the desired monitor
monPos_norm = grootObj.MonitorPositions(monitorIdx,:);
selWin.OuterPosition = [(monPos_norm(1)+0.5) (monPos_norm(2)+0.5) 0.1 0.1];
% NOTEs:
% - I put the lower left corner of the figure at the center of the desired
% monitor (monitor origin +0.5 in normalized units)
% - "0.1" meant that the figure should occupy 10% of the
% horizontal/vertical space before scaling. This should work unless the
% user have very high scaling (more than 10x I would say). In such case,
% we should reduce the numbers even more
%% 2 - maximize figure
% We have two options:
% - "maximized" will give us the AVAILABLE space
% (excluding occupied graphical elements,
% like MS Windows start bar or the figure title bar)
% - "fullscreen" will give us the FULL SCREEN space
% (including the graphical elements that are often in
% the foreground, like MS Windows start bar or the
% figure title bar)
%selWin.WindowState = "maximized";
selWin.WindowState = "fullscreen";
pause(0.001); % I often put very short pauses to update graphics
%% 3a - select the units we want to know
dispUnits = "pixels";
selWin.Units = dispUnits;
grootObj.Units = dispUnits;
pause(1);
% waiting 0.1s is NOT enought to correctly change the
% units: on my system I got [ -959 541 192 108]
% instead of (the correct) [-1541 43 1549 824]
% 3b - read the figure position in the coordinates we like most
figPos = selWin.OuterPosition;
monitorX_scaled = figPos(1);
monitorY_scaled = figPos(2);
monitorW_scaled = figPos(3);
monitorH_scaled = figPos(4);
% The available space for the figures will be:
% - between "monitorX_scaled" and "monitorX_scaled" + "monitorW_scaled"
% along the horizontal axis
% - between "monitorY_scaled" and "monitorY_scaled" + "monitorH_scaled"
% along the vertical axis
% Meaning that figure should be at most "monitorW_scaled" x
% "monitorH_scaled" if we want it to occupy the full screen
% 4 - calculate DPI scaling
% This calculation will be approximative in the case we
% choosed "maximized" at step 4
dispPos = grootObj.MonitorPositions(monitorIdx,:);
%monitorX_raw = dispPos(1);
%monitorY_raw = dispPos(2);
monitorW_raw = dispPos(3);
monitorH_raw = dispPos(4);
monitorW_scaling = monitorW_raw/monitorW_scaled;
monitorH_scaling = monitorH_raw/monitorH_scaled;
% on my system:
% option | monitorW_scaling | monitorH_scaling
% "maximized" | 1.2395 | 1.3107
% "fullscreen" | 1.2500 | 1.2500
% | |
% MS windows | |
% settings | 125% | (125%)

3 Comments

@Jacorem I'm not aware of any reason that my old answer from 2 years ago won't continue working on R2025b (or R2026a or R2026b).
I'm not quite sure how your script is calculating the scaling, as both the MonitorPosition property and the OuterPosition property should both be reading in the same (scaled) pixel values. On my system, the monitorW_scaling and monitorH_scaling are both reporting 1, which is what I would expect all the time on any system.
On Windows systems there are three values that can all impact this scaling:
  • In Settings -> System -> Display, the "Scale" is the most common.
  • In Settings -> Accessibility -> Text Size, the "Text size" can also have an impact.
  • In MATLAB, if you have previously used the (undocumented) mechanism for changing the zoom factor of the MATLAB desktop, this can also impact those readings.
What are you seeing when you query the ScreenPixelsPerInch on the Figure?
Note that like the ScreenPixelsPerInch property on the Figure, this is undocumented, comes with no promises that it will work correctly, and is not guaranteed to work indefinitely, but there is also an undocumented devicepixels unit.
r = groot;
px = r.MonitorPositions
r.Units = 'devicepixels';
dpx = r.MonitorPositions
scale_factor = dpx(:,3:4)./px(:,3:4)
Drear @Benjamin Kraus , the problem on my system is that "ScreenPixelsPerInch" does not change when I move my uifigure (may the problem comes from using uifigure [undocked] instead of figure [docked]?) from one screen to another, and is instead always reporting the groot "ScreenPixelsPerInch" ("96" in all the cases on my system).
Concerning my system, I think that I have modified the display scale and (up to my meory), left untouched the text size and Matlab zoom factor (I think that this is the first time that I hear about this feature).
I'm currently running a heavy computation, so I cannot test the value of the 'devicepixels' options.
@Jacorem: Ah, yes. That is an issue. MATLAB only recognizes the display scaling of the "main" monitor. I'm not aware of a workaround to that issue that is better than what your script is doing.

Sign in to comment.

Categories

Products

Release

R2023a

Asked:

on 28 May 2024

Commented:

7 minutes ago

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!