- Title bar
- Basic features of the title bar
- Extra features and functions of a title bar
- Строка меню (Справочник по элементам пользовательского интерфейса MSAA)
- Методы IAccessible
- Свойства IAccessible
- Примечания
- Title Bar Replacer
- Installation
- Removing the Native Title Bar
- Keyboard Navigation
- UI Customization
- Changelog
- 2.0.0 — Complete rewrite
- 1.8.0 — Performance Optimization
- License
- I think this package is bad news.
- Customizing the Title bar of an Application Window
- Custom Decorated Desktop App Window With Default Windows Standard Behavior
- Some basics about Desktop Application Windows
- Custom Decorations in Desktop Application Windows
- Custom Decorated Window Using Undecorated JFrame
- Custom Decorated Window Using Java Native Access (JNA)
- Implementation of the Custom Decoration
- Demo App
- Checkout the Demo on GitHub
- What’s Next
Title bar
The title bar is a horizontal bar located at the top of a window in a GUI. It displays the title of the software, name of the current document, or other text identifying the contents of that window. For example, in the picture below, the title bar displays the program name «TextPad» and the document name «Document1» that is currently being edited.
Besides giving a description of the open program or window, the title bar may also contain other useful features that depend on the operating system and program showing the title bar.
If you’re using Microsoft Windows 8 and the title bar is missing, move the mouse pointer to the top of the screen to reveal it.
Basic features of the title bar
As illustrated in the picture above, the standard title bar has a minimize, maximize, and close button, usually on the right side. Also, in the top-left corner of a program’s window, there is an icon that shows these options when clicked.
In Microsoft Windows, pressing Alt + Spacebar shows you the window menu options, as shown in the picture. Using this keyboard shortcut, you can perform any of the title bar options without using a mouse.
Extra features and functions of a title bar
Below is a list of some of the functions of the title bar. Keep in mind that not all of these are available in all operating systems and programs.
- Press and hold the mouse button on the title bar to move the window.
- Double-click the title bar to maximize the window or set the window into window mode.
- Windows 7 introduced side-by-side windows, a feature that «snaps» windows to the side of the screen. To use side-by-side windows, click-and-drag the title bar to any edge of the screen.
- View two windows side-by-side using Smart Window.
Строка меню (Справочник по элементам пользовательского интерфейса MSAA)
В этом разделе описываются объекты строки меню для ссылки на элемент ПОЛЬЗОВАТЕЛЬСКОГО интерфейса MSAA. Создание объектов строки меню в различных ПЛАТФОРМАХ пользовательского интерфейса не описывается здесь. См. справочную документацию по API для платформы пользовательского интерфейса, которую вы используете.
Строка меню — это область окна, расположенная сразу под строкой заголовка, в которой содержатся пункты меню, такие как файл, Правка, окно и Справка. Microsoft Active Accessibility также создает объект строки меню для системного меню, которое представляет собой меню в левом верхнем углу строки заголовка и содержит пункты меню восстановить, переместить, Размер, Minimize и максимизировать.
Поскольку элементы управления «строка меню» не получают фокус, методы аккселект и Get _ аккфокус не поддерживаются для этого элемента управления.
Методы IAccessible
Элементы управления «строка меню» поддерживают следующие методы IAccessible :
Свойства IAccessible
Элементы управления «строка меню» поддерживают следующие свойства IAccessible :
Свойство | Комментарии |
---|---|
получить _ аккчилд | Извлекает IDispatch для указанного элемента меню. Идентификаторы дочерних элементов меню нумеруются последовательно слева направо, начиная с единицы. |
получить _ аккчилдкаунт | Свойство ChildCount — это число пунктов меню в строке меню. Свойство ChildCount для системного меню — это одно из свойств. |
получить _ аккдескриптион | Свойство Description строки меню «содержит команды для управления текущим представлением или документом». Свойство Description для системного меню — содержит команды для управления окном. |
получить _ аккдефаултактион | |
получить _ аккфокус | |
получить _ акчелп | |
получить _ акчелптопик | |
получить _ акккэйбоардшорткут | Свойство кэйбоардшорткут строки меню под заголовком заголовка — «Alt». Свойство кэйбоардшорткут для системного меню — «ALT + пробел». |
получить _ аккнаме | Свойство Name строки меню под заголовком окна «приложение». Свойством » имя » для системного меню является «System». |
получить _ аккпарент | |
получить _ аккроле | Свойство Role — _ _ строка подсистемы роли. |
получить _ аккстате | Свойство State представляет собой сочетание одного или нескольких из следующих значений: Системное состояние _ _ невидимая система состояния, | _ _ сфокусированная на | _ _ системе состояния |
Примечания
Система запускает более одного события системы событий _ _ менустарт , которое не всегда имеет соответствующее событие _ системы событий _ менуенд . Кроме того, система не вызывает согласованность _ системных событий _ менупопупстарт и событий _ System _ менупопупенд . Это известная проблема, которая решена.
Title Bar Replacer
Adds an alternative, theme-aware title bar and application menu that is more inline with Atom’s UI design.
This package is aimed mostly at Windows users, as the native Windows title bar doesn’t really go well with Atom’s UI design. This title bar replacer adds a functional custom title bar, that lets you move, scale, and utilize Aero-snap features. It also adds a custom application menu that is somewhat more intelligent in terms of design. The default behaviour of the title bar and application menu is to choose colors based on the theme you are currently using. However, most of the colors can be customized in the settings, and the menu can also be hidden.
Installation
Install through Atom’s install view or use apm:
Removing the Native Title Bar
As of Atom version 1.53.0 you no longer need to patch Atom in order to hide the native title bar! Go to Settings > Core > Title bar, and set it to hidden . Restart Atom and enjoy the custom title bar.
Keyboard Navigation
The menu bar can be fully utilized from the keyboard. Pressing Alt will allow you to access the various categories through alt key shortcuts, or arrow keys.
- Alt — toggle alt key shortcuts or close menu if it’s open
- ←↑↓→ — navigate the menu
- Enter — Use selected menu item
- Space — Use selected menu item without closing the application menu
- Esc — Close menu
- Alt+Shift+M — Toggle menu bar visibility
- Ctrl+Alt+Shift+M — Toggle title bar visibility
UI Customization
There are provided settings to adjust the title bar layout style as well as a few different window contols presets. If there is some design you are unhappy with, or some design features you miss, the title bar is highly adjustable through CSS (Atom’s stylesheet).
Changelog
2.0.0 — Complete rewrite
- The plugin has been rewritten completely from scratch
- More than 4x faster
- Reworked keyboard navigation
- Efficient menu diff and updates
- Setting for alt focus
- Setting for menu mnemonics
- Title text is hidden when it intersects with the menu bar.
- Dock toggle buttons are now accessible without a window frame.
- Removed the window frame remover in favor of the new ‘Title Bar > hidden’ setting.
- Less terrible code
- Fixed fatal bug occurring when no serialization state exists.
1.8.0 — Performance Optimization
- Unimplemented the transpiler. All TypeScript source files are now compiled pre-distribution.
- Implemented serialization. HTML is now stored and deserialized upon launch.
- Fixed bug that caused the ‘Restore Defaults’ button not to work.
- Handling exiting and disabling properly
- More type definitions.
License
I think this package is bad news.
Good catch. Let us know what about this package looks wrong to you, and we’ll investigate right away.
Customizing the Title bar of an Application Window
Custom Decorated Desktop App Window With Default Windows Standard Behavior
Recently, most modern windows desktop applications have a custom framed window by ditching or modifying the default windows title bar. These arguably enhances the look of the GUI. Such apps include popular IDEs like Intellij IDEA, Visual Studio, VS Code and also Office apps.
If you are like me obsessed with these great looking applications and wondered how to do it, well keep on reading.
The method that we will see below might not be exactly how the above desktop applications did it, but at least it will give you the exact behavior and full control of your desktop application window.
Some basics about Desktop Application Windows
Before we dig in to it, lets have some basic understanding of how Windows renders application window.
An application window has two components: a Non-Client Area and a Client Area. The Non-Client area is composed of the title bar, icon, window border and the caption buttons and the rest is the client area where you add your application user controls (buttons, test boxes ….).
Another important point to note is that an application window has several attributes including a class name, window name, window handle, window style, extended window style … etc..
These attributes help us to determine how the window is displayed and how it will interact with the user, which is very curial to our goal. Additionally, every window has a window procedure, a function that processes all message sent or posted to all the windows of the class.
These messages determine how the application window is displayed and how it interacts with inputs. Hence, by intercepting these messages we can get full control of our window (at least that is the idea).
I highly recommend you to go through the above links to get the full picture.
Custom Decorations in Desktop Application Windows
The techniques that we are going to discuss here work for various programing languages that can load native libraries (of Windows of course).
Implementing this in C++ is relatively easy because we are dealing with native libraries assuming that we have a basic understanding of how applications windows are displayed and how to handle window messages.
But here, we will be doing this using Java, specifically SWING. But I am sure once you get the hang of it you can implement custom decorations for JavaFX and also other programing languages such as C# using the same techniques.
Custom decorated desktop application windows in Java can be achieved in two ways.
- The first is just setting the JFrame to be undecorated (with the setUndecrated function) and then implement everything (resizing, moving and snapping).
- The second method is setting the J Frame to be undecorated and then use the getRootPane function on the JFrame object to get its RootPane and call the setWindowDecorationStyle(JRootPane.FRAME) on the RootPane itself. This will give you the implemention of resizing and dragging, all you need to add is the snap behavior. By default the title bar and border you get is Java’s default look and feel so you will need to change that. Also you will have to deal with adding user controls to the title bar of the JRootPane.
- The other method is using Java Native Access (JNA ). In this method native libraries are loaded and default behaviors for the application window are implemented by the Window itself through integration of custom window procedures. Hence, all the default windows behaviors are reserved plus we will have a custom decorated window.
Custom Decorated Window Using Undecorated JFrame
When we set the JFrame to be undecorated, the Non-Client area will not be rendered and the Client area occupies the whole application window.
The major pitfall of using this method would be it requires a lot of work to get everything working ( I have done this for JavaFX and if you are interested let me know on the comments and I will share it).
Let me go through the basic points on how to do it. Once you make your JFrame undecorated, you will have a blank canvas (or panel) to put everything from title bar to your application controls.
First you can implement the moving by detecting your mouse location and setting your window position accordingly. Then to implement the resizing feature, you need to think of the “hot spots” on the edge of the application window. There are 8 : N, S, E, W, NW, NE, SW & SE.
You can calculate the location of the mouse relative to the application window or you can add thin JPanles at each location and detect whether the mouse is Hovered (to change the curser) or Dragged (to actually resize the window).
Next step is to implement the window snap feature. For these you’ll need to have an additional transparent window to act like the one you see when you move a window close to the edges of the screen and you can show or hide the transparent window accordingly.
Then when the user lets go of the mouse you can change the size and location of the your window to be the same as the transparent window, if the application window is snapping to the edges.
But be reminded that this is just imitation, and snap assist of windows will not detect your application window.
Now the good part; let’s see how to do this so that we don’t have to implement all the default behaviors of application windows.
Custom Decorated Window Using Java Native Access (JNA)
When using this method, we will be entering the realm of windows native libraries. This is made possible by the use of JNA.
The first thing that we need to do is to download jna and jna-platform jar files. You can download the latest files from Java Native Access (JNA) GitHub Repository . Scroll down to the Download Section of the README.md file and you will find the jar files.
I will be using Intellij IDEA Community to create the project, but you can use any IDE you like. Once you have created your project and setup the dependencies (jna and jna-platform) we are good to go.
The first thing that we need to do is to create an interface that extends the User32 interface provided by jna.platform.win32.User32. We are doing this to add few functions that are not provided by jna User32 interface.
The constant GWLP_WNDPROC is an offset value that is used set a new address for the window procedure.
The SetWindowLongPtr function will allow us to set our custom window procedure for our application window, so that we can determine how to handle the selected messages that we will be intercepting.
The CallWindowProc function will allow has to call the default window procedure, this is useful because we are not going to handle all the messages (we will only handle few messages and let the rest of the messages be handled by windows).
Next, we will create a custom window decoration procedure class that extends from WinUser.WindowProc of jna. This class will have a custom callback function and a hit testing function.
The first two constants WM_NCCALCSIZE and WM_NCHITTEST are message values that get sent by windows.
WM_NCCALCSIZE is called by windows before painting the Non-Client area (the border and the title bar) and WM_NCHITTEST is sent by windows to determine which area is currently receiving mouse events there by enabling us to implement resizing and moving.
HWND variable hwnd will be used to store the window handle for the application and the LONG_PTR variable defWndProc will be used to store the pointer to the default window procedure so that we can call it whenever necessary.
The Constructor and the init function will be used to load the native library and also initialize the variables defined above. As you can see below i am loading the native library in the constructor and initializing the rest of the variables on the init function.
I am doing this to make sure the native library is loaded before the window is visible and then initialize the class after the window is visible (because the handle HWND of the window can only be determined after the JFrame is visible in java)
Then, we will define the callback function that actually processes our selected messages: WM_NCCALCSIZE, WM_NCHITTEST and WM_DESTROY.
For the case of WM_NCHITTEST, we have a BorderLessHitTest function that determines which area is used for resize and which area is used for dragging (including windows snap).
The CallWindowProc function is used to pass messages that are not handled by our custom callback function to the default windows procedure.
For the case of WM_DESTROY, we set the default window procedure back to its default. The defWndProc variable is set when we call SetWindowLongPtr to assign our custom window procedure, because this function returns a pointer to the default window procedure.
So as you can realize by now, the most important line here is the line of code that calls the BorderLessHitTest() function. This function is written based on Custom Window Frame Using DWM Appendix C: HitTestNCA .
This function has a return value of the various locations on the application window such as HTTOPLEFT, HTTOP … etc. You can determine the location of the mouse and based on that return these values so that windows can take care of the resizing.
Next you can determine the location of your custom caption and return HTCAPTION and for other areas we return HTNOWHERE.
You can also return HTSYSMENU to display the system menu shown when a desktop application icon (at the top-left corner) is clicked.
By the way these constants are integers you can checkout the documentation about WM_NCHITTEST messages.
The hit testing algorithm depends on what you consider to be a caption area and a resize area. Especially when you place user controls on an area that you consider to be a caption area you must return HTNOWHERE when the mouse is over the area that your controls are so that the default behavior of your controls is kept.
For our case, to help me with this calculation, I have defined a CustomDecorationParameters class to hold by custom values. Which can be modified when the windows gets updated.
For example, the iconWidth will be used to determine how wide the application icon is from the top-left corner and the extraLeftReservedArea variable is used to exclude a specified area from the left of the top-left corner, so that we can place user controls such as a Menu bar.
You can update these AtomicInteger variables according to the behavior of your application window. For instance, if you dynamically add user controls on the caption area, then you need to update these variables.
Implementation of the Custom Decoration
The reset of the code would not require any native interaction. First of all, let’s make a CustomJFrame class that extends JFrame to make it easier to deal with the theme of the JFrame as well as hide the implementation of Custom Decoration on the JFrame.
If you are wondering about the first Theme variable ‘ theme’ it is just a simple interface that defines getter methods so that various themes can be created and applied to the JFrame easily (Please refer the project code base on GitHub).
For our example, I have made a DarkTheme (check out the DarkTheme.java). The rest of the code I think is easier to understand.
Just one reminder is that the handle of the window can only be determined after the JFrame is set visible.
Demo App
I have made a simple demo on the project to demonstrate the usage of the custom decoration. You can find the code on Github.
First, I initialized the CustomJFrame with a theme and a title. Then make I made my own custom Minimize, Maximize / Restore and Close button.
I have made a separate class ControlBoxJButton and overridden paintComponent function to draw the icons. You can also use an icon (PNG, bmp, svg …)
Next, we can place anything anywhere as long as we update the hit-testing algorithm when we place user-controls on the top caption as I have mentioned earlier.
Checkout the Demo on GitHub
What’s Next
Well, that is about it. Of course, there is a bunch of code that I haven’t posted here but you can refer the project code on Github (CustomDecoratedJFrame).
You can apply any customization to the project to suite your GUI design. Keep in mind that, if you are making a cross platform application make sure to check whether the platform is windows before you use the custom decoration, you can do this easily using JNA.
Well I had fun making this project and writing this blog as well. I hope it’s useful for someone out there. You are more than welcome to leave me a comment or any question you might have.
I think I will also be making a YouTube video tutorial, but I will see how it goes.