WINDOWAPI - Set window properties using the Windows API
There are a lot of functions in the FEX to set the figure properties, e.g. maximized, minimized, always-on-top, level of transparency (using Java).
This submission adds 4 new features:
1. Maximize a window with or without visible taskbar or menu bar.
2. Set transparency level of figure and stencil-color: pixels of a this color are 100% transparent.
3. Placing figures on multi-monitor setups.
4. Clip region: draw only pixles inside a specified rectangle (e.g. splash screen).
5. Lock cursor: Especially for games it can be useful to keep the mouse cursor in a specified rectangle.
FigH: Matlab's figure handle or Windows HWND
TopMost: Window is topmost even if the focus is lost
NoTopMost: Disable the topmost state
Front: Move window on toptemporarily
Minimize: Minimize the window
Restore: Restore to former size
Maximize: Full screen, taskbar and menubar visible
XMax, YMax: Maximize figure horizontally or vertically only
Position: Set inner figure position to 'work' (taskbar visible), 'full' (taskbar hidden),
Monitor index can be specified also
OuterPosition: As Position, but with figure border and titlebar
Flash: Short flashing
Alpha: Set the figure's transparency between 0.0 and 1.0.
4th input [R,G,B]: Pixels with this color are 100% transparent in addition
Opaque: Release memory needed for alpha blending
Clip: Draw only pixels inside a rectangle
ToScreen: Move figure completely to nearest monitor
SetFocus: Gain keyboard focus to figure (figure(FigH) is buggy)
LockCursor: Limit the cursor motion to a rectangle
SetFocus: Activate figure
Enable: Enable or disable all GUI elements
Hide, Show: Hide the window without changing its Os handle
Button: Set visibility of Max, Min, Close buttons in the window border
Reply = WindowAPI(FigureHandle, Command)
GetStatus: Replies 'maximized', 'minimized' or 'restored'.
GetHWnd: Reply the Windows handle of the figure.
Position/OuterPosition: If used with 2 inputs, the position relative to current monitor and the monitor index is replied.
Monitor: Get index and position of monitor.
This function calls Windows-API functions => No Linux, no MacOS - sorry.
The function is written in C and must be compiled before using by the mex command. See WindowAPI.c for instructions.
Depending on the Matlab version, the MEX is compiled for HG1 or HG2 automatically. Both versions can exist
Maximize the current figure:
A semi-transparent figure with through-looking background:
FigH = figure('Color', ones(1,3));
WindowAPI(FigH, 'Alpha', 0.5, [255,255,255]);
Draw a button without surrounding figure ("splash button"):
FigH = figure;
ButtonH = uicontrol('Style', 'PushButton', 'String', 'Bye', ...
'Units', 'pixels', 'Callback', 'delete(gcbf)');
WindowAPI(FigH, 'Clip', get(ButtonH, 'Position'));
Tested: Matlab 6.5, 2008a, 2009a, 2011b/64, 2016b, WinXP/32, Win7/64, MSVC 2008/2010, BCC5.5
Assumed compatibility: Higher Matlab versions.
ShowWindow, Matthew Simoneau:
Window Manipulation, Phil Goddard:
api_showwindow, Mihai Moldovan:
maxfig, Mihai Moldovan:
setFigTransparency, Yair Altman:
Jan (2020). WindowAPI (https://www.mathworks.com/matlabcentral/fileexchange/31437-windowapi), MATLAB Central File Exchange. Retrieved .
It appears this works with the 'figure' function, but not the 'uifigure' function. I am just trying to hide the window borders for an About box in the app designer.
f = uifigure
Executes without error, but the title bar remains on the uifigure.
Exactly what I was looking for! Using setting size code, MATLAB would automatically resize the height to less.
ScreenWorkArea = images.internal.getWorkArea;
set(figHandle, 'Position', [50, -(ImageSizePixels(2) - ScreenWorkArea.top) ,ImageSizePixels(1), ImageSizePixels(2)]);
matlab.ui.internal.PositionUtils.setDevicePixelPosition(figHandle, [50, -(ImageSizePixels(2) - ScreenWorkArea.top) ,ImageSizePixels(1), ImageSizePixels(2)]);
matlab.ui.internal.PositionUtils.setDevicePixelPosition(gca, [0,0, ImageSizePixels(1), ImageSizePixels(2)]);
@Jan Thank you for your reply. If you upload the source code to GitHub I can fork it and add the changes I mentioned. I did discover a workaround that may work in some similar cases (Windows 10, high DPI monitor scaling): Find the path to java.exe used by MATLAB, right-click>"Properties", goto "Compatibility" tab, [x] "Override High DPI Scaling Behavior", choose "Scaling Performed By">"System". After some googling it seems the issue caused by javax.swing
@Peter Cook: Thanks for this valuable suggestion. The scaling problem is severe and I struggle a lot with rounding effects.
It is intended, that WindowAPI replies the real pixel positions, because the unscaled positions are replied by the built-in |get(h, 'Position')| already. A fair solution would be to include both outputs in WindowAPI, for setting and getting the positions.
Jan, a small suggestion for a future update. In Windows 10 (and maybe others?) Microsoft imposes a scaling factor on high DPI monitors (e.g. https://docs.microsoft.com/en-us/windows/win32/api/shtypes/ne-shtypes-device_scale_factor) which distorts some of the values returned by MATLAB w.r.t. figure size/position. e.g. Suppose I create a MATLAB figure with 'Position' property of [64, 64, 512, 1024] on a monitor with a scaling factor of 250% - the actual pixel position on screen is rendered by Windows as [148, 148, 1300, 2684] (which I can only retrieve w/ WindowAPI(h, 'Position') and not get(h,'Position')). I guess that makes it more of a MATLAB problem than a WindowAPI problem, but outputting position coordinates in the same pixel mapping as MATLAB would be useful... It could potentially be rectified with this (https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/nf-shellscalingapi-getscalefactorformonitor) Windows API function.
@Lei: I guess, that you are using the MinGW64 Compiler (C) compiler? There seems like MinGW fails to include the Windows libraries. Please download the pre-compiled files instead, which have been created by the MSVC compilers.
*** Compilation failed:
C:\Users\Lei\AppData\Local\Temp\mex_107417481032953_13660\WindowAPI.obj:WindowAPI.c:(.text+0x83e): undefined reference to `__imp_CreateRectRgn'
C:\Users\Lei\AppData\Local\Temp\mex_107417481032953_13660\WindowAPI.obj:WindowAPI.c:(.text+0x85c): undefined reference to `__imp_DeleteObject'
Thanks to your help, I was able to finish my work perfectly.
I am so sorry on the one hand and really appreciate on the other.
Have a nice day~!
This bug has been fixed. Thank you for your reply and help!
Thanks Youshu Zhou to find this bug. Please test if this is fixed now.
I am very glad to see such birlliant work that is likely to help me a lot. However I encountered a problem when running the demo with Matlab2014b. And the error message is something like this:
Error WindowAPI (line 181)
persistent MexFcn hasHG2
The output parameter "Reply" (possibly other parameters) is not assigned when calling “(...the file path)\WindowAPI_20161126\WindowAPI.m>WindowAPI”
Error demo_WindowAPI (line 21)
MexVersion = WindowAPI();
(The message below is not copied from Matlab exactly because the language of my Matlab is not English so it is translated by me. I hope the interpretation could give you the key point.)
I am wondering whether there is any prerequisite before running the demo.
@SeokHyun Shin: I cannot reproduce the problem on my R2016b. Maybe it is a typo only, but "WindowAPI(hFig,'Alpha',1,[0,0,0])" sets the full opacity. Values < 1.0 make the selected color more transparent. Feel free to contact me by email for a debugging.
I tested according to your advice. but, It still turn back to black background and never turn to transparent until delete patch object.
I wish if you ever solve this problem someday.
@Timothy Plummer: Can you provide more details about the failing compilation? What happens if you use get/set the Position or OuterPosition? Do you get an error message? I had problems with the determination of the size of the window border, if they have non integer values due to the scaling of the operating system. Please use the email address from the code to send me more details. Thanks.
@SeokHyun Shin: The patch command can set the renderer to OpenGL. I did not observe this yet, but maybe this changes the view of the window. What happens for:
hFig = figure('Renderer', OpenGL');
objPath = patch('faces', faces, 'vertices', vertices);
I'm currently using Matlab R2014a and all WindowAPI functions goes well except when I add patch function on my GUI.
This is simplified code that I applied.
hFig = figure;
WindowAPI(hFig,'Alpha',1,[0,0,0]); % transparent background
objPath = patch('faces', faces, 'vertices', vertices); % turn back to opaque black background
Please help me.
Hello, I am glad that this works for the most part with the new figures, even the ones that are part of App Designer, it solves the problem with the main GUI getting shoved to the bottom of the stack when using the uigetfile dialog. The problem that I'm running into is that I was not able to create the mex file, and I seem to only have one of the compilers available for c, the MinGW64 Compiler (C), I wasn't sure if this was one of the ones that caused problems or not.
I then tried one of your precompiled versions, and that seemed to work, but the uTest function failed on get/set position and outer position. ( I changed your errors to Warnings, so I can see what tests failed without it stopping). I wasn't sure if this has something to do with something that happened in Matlab 2017b or not.
Any suggestions would be great.
p.s. If I can get it so that these two problems get solved i would be happy to give this a 5-star glowing rating.
I could not get the mex file to compile. Here is what I tried along with the errors I got. (I'm currently using MATLAB 2015b)
== WindowAPI: Cannot find the compiled mex file
== Start compilation of WindowAPI:
Error using mex
C:\Users\Jonathan\Documents\MATLAB\WindowAPI_04Nov2011\WindowAPI not found; check that you are in the correct current folder, and check the spelling of 'C:\Users\Jonathan\Documents\MATLAB\WindowAPI_04Nov2011\WindowAPI'.
MSVC or Intel compiler is needed - not working with LCC!
Perhaps you must setup the compiler at first:
Error using mex
C:\Users\Jonathan\Documents\MATLAB\WindowAPI_04Nov2011\WindowAPI not found; check that you are in the correct current folder,
and check the spelling of 'C:\Users\Jonathan\Documents\MATLAB\WindowAPI_04Nov2011\WindowAPI'.
Building with 'MinGW64 Compiler (C)'.
Error using mex
Deprecated MEX function mexGet|mexSet was called. Either update the source code to use mxGetProperty|mxSetProperty, OR rerun
MEX with the -DMEX_DOUBLE_HANDLE added to the command line to enter compatibility mode.
Building with 'MinGW64 Compiler (C)'.
Error using mex
C:\Users\Jonathan\AppData\Local\Temp\mex_52468892045512_7732\WindowAPI.obj:WindowAPI.c:(.text+0x829): undefined reference to
C:\Users\Jonathan\AppData\Local\Temp\mex_52468892045512_7732\WindowAPI.obj:WindowAPI.c:(.text+0x847): undefined reference to
collect2.exe: error: ld returned 1 exit status
Thanks, works nicely.
Note that from 2014b, Matlab has changed the format of figure handles:
Therefore, WindowAPI needs to be called with
WindowAPI(figure_handle.Number, 'Position', 'full');
WindowAPI(figure_handle, 'Position', 'full');
Excellent! Saved me hours of coding this myself.
check my way of load library... undocumented
Thanks for the great work
cause it did`nt find file
@Katharina: What about:
nMonitor = size(get(0, 'MonitorPositions'), 1)
Is there a way to find out the number of monitors? Something that returns something like:
1: Monitor A
2: Monitor B
With the change to figure handle objects in R2014b, one needs to get the integer figure handle to pass to WindowAPI for it to work with that version:
h = figure; % object handle
FigH = h.Number; % integer handle
@Jeff: I do not work with GUIDE, therefore I'm not sure what setting the resize behaviour to "proportional" exactly does. I will try some experiments to see, if I can reproduce the behaviour you describe.
This looks perfect for my purposes. I have tried using WindowAPI(fig,'Position','full') to completely maximize a gui I've created with GUIDE. The API has different effects depending on whether the gui's resize behaviour is set to proportional or non-resizable. Taskbar is hidden for non-resizeable, but neither taskbar or title bar are hidden for proportional. I'd like to have them both hidden somehow. The demo works completely fine with WindowAPI(FigH,'Position','full'), hiding both the taskbar and title bar. Using Win 7 x32 here.
Small bug in the test function uTest_WindowAPI: 'Crop' must be changed to 'Clip'.
The function demo_WindowAPI is added to decrease the large help section a little bit.
The update is submitted and will appear soon.
@Gaszton: The new version is comming in the next days with multi-monitor handling. Then this shows your IMSHOW picture on the 2nd monitor:
axes('Position', [0,0,1,1]); imshow(pic); WindowAPI(gcf, 'Position', 'work', 2); WindowAPI(gcf, 'Clip');
Unfortunately I cannot test the code for multiple monitors yet. I will try to expand the submission to support this in the future.
Is it possible to automatically move the figure in fullscreen to the secondary monitor?
I would like to diplay an image with imshow, that is the same size as the resolution of the secondary monitor, so i want the image to cover the full screen.
Hi Jan, I use Windows 7 x64. Unfortunately, I know nothing about these Windows things, sorry. Which is why I really appreciate your work. Cheers.
@Marc: Thanks for the valuable comment. Which OS do you use? Your improved PosCorrect method works well under Win2k and XP also - I'll include it soon.
Do you know a method to set the window in the 'screen' mode on top of the taskbar without setting the TOPMOST flag? To my surprise it works in the 'fullscreen' mode without the TOPMOST flag, but not in the 'screen' mode.
Works well, thanks!
I had to modify the fullscreen numbers, as it was not exactly right, in particular I could still grab the edge of the window at the bottom. With these, it works perfectly:
Rect.left + PosCorrect,
Rect.top - PosCorrect - PosCorrect,
Rect.right + PosCorrect,
Rect.bottom + PosCorrect,
SWP_SHOWWINDOW | SWP_NOSENDCHANGING);
(Note I also removed the topmost property, otherwise I didn't know how to close the figure or switch to another window without calling the task manager...)
Demo did not run due to a bug.
Lock cursor, tested with Win7/64 also.
Bug in uTest_WindowAPI: 'crop' -> 'clip'. No changes in the main function.
Multi-monitor handling, Clip region, ToScreen, XMax, YMax
FullScreen: improved placement and not topmost anymore (thanks Marc!)