Mac Show Application Title, Version, and Company: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: Mac Show Application Title, Version, and Company
| Old | New | Line | |
|---|---|---|---|
| 1 | + | *(macOS only)* | |
| 2 | + | ||
| 3 | + | > **Warning:** This only works **if** the software has an application bundle; otherwise please see [[Show Application Title, Version, and Company]] | |
| 4 | + | ||
| 5 | + | An About window, also called an About Box or About Panel, is an optional window that contains your application’s version and copyright information and may also optionally include credits acknowledging people and code you did not write. Unlike other windows, an About window combines some of the behaviors of panels and windows: Like a panel, an About window is not listed in the application’s Window menu and like a window, it remains visible when the application is inactive. An About window should be modeless so the user can leave it open and perform other tasks in the application. | |
| 6 | + | ||
| 7 | + | Give your macOS application a professional look by using an About window which can be created in one of several different ways: the complex way, the simple way or the overridden simple way. Read on... | |
| 8 | + | ||
| 9 | + | ## The simple way | |
| 10 | + | ||
| 11 | + | Thanks to the wonders of the Apple Cocoa Framework, the easy way to create an About Box for an application comprises just one line of code, one unit added to the *Uses* clause and one HTML file added to your [[Application Bundle]] Resources directory. | |
| 12 | + | ||
| 13 | + | ``` pascal | |
| 14 | + | ... | |
| 15 | + | ||
| 16 | + | Uses | |
| 17 | + | CocoaAll, | |
| 18 | + | ...; | |
| 19 | + | ||
| 20 | + | ... | |
| 21 | + | NSApp.orderFrontStandardAboutPanel(Nil); | |
| 22 | + | ... | |
| 23 | + | ||
| 24 | + | ... | |
| 25 | + | ``` | |
| 26 | + | ||
| 27 | + | Sample output: | |
| 28 | + | ||
| 29 | + | <figure> | |
| 30 | + | <img src="Easy_macOS_About_Box.jpg" title="Easy_macOS_About_Box.jpg" /> | |
| 31 | + | <figcaption>Easy_macOS_About_Box.jpg</figcaption> | |
| 32 | + | </figure> | |
| 33 | + | ||
| 34 | + | Where does this information come from? Your `Info.plist` [[macOS property list files|property list file]] provides the following details: | |
| 35 | + | ||
| 36 | + | - **Application Icon** | |
| 37 | + | ||
| 38 | + | Uses the string value of the `CFBundleIconFile` key. You don't have to include the filename extension in this string value, but you can if you want. If you do not, macOS is smart enough to search for a file of this name that ends with the `.icns` extension. If not available, the generic application icon is used. | |
| 39 | + | ||
| 40 | + | - **Application Name** | |
| 41 | + | ||
| 42 | + | Uses the string value of the `CFBundleName` key which is localisable. If not found, the system uses the `NSProcessInfo.processInfo.processName` (ie the name of your executable). This string is what is displayed in the menu bar when your application is active. | |
| 43 | + | ||
| 44 | + | - **Application Version String** | |
| 45 | + | ||
| 46 | + | Uses the value of the `CFBundleShortVersionString` key. If not found, the build version, if available, is printed alone as "Version x.x.x". This string is useful for actual version identification, but can be thought of as the "marketing" version. As a result, it is typically a more general version number, such as 1.0, and can contain alpha characters with no ill side effects. This value is displayed in the Finder preview too. | |
| 47 | + | ||
| 48 | + | - **Build Version String** | |
| 49 | + | ||
| 50 | + | Uses the value of the `CFBundleVersion` key. Displays the build version number of the application displayed as "(v1.0.0)". If not found, the version area is left blank (the "(v)" is not displayed). | |
| 51 | + | ||
| 52 | + | - **Copyright** | |
| 53 | + | ||
| 54 | + | Uses the string value of the `NSHumanReadableCopyright` key from the Info.plist file. If not found, the copyright area is left blank. | |
| 55 | + | ||
| 56 | + | The **Credits section** comes from a file named `Credits.html` in the Resources directory of your [[Application Bundle|bundle]]. If this file is not found, the system then looks for a file named `Credits.rtf`. If not found, the system looks for a file named `Credits.rtfd`. If not found, the credits area is left blank. Note that the capitalization of the file name is important. By using the HTML format, you can include links if necessary (eg to your web site). | |
| 57 | + | ||
| 58 | + | The `Info.plist` [[macOS property list files|property list file]] used in the sample above was: | |
| 59 | + | ||
| 60 | + | ``` xml | |
| 61 | + | <?xml version="1.0" encoding="UTF-8"?> | |
| 62 | + | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
| 63 | + | <plist version="1.0"> | |
| 64 | + | <dict> | |
| 65 | + | <key>CFBundleDevelopmentRegion</key> | |
| 66 | + | <string>English</string> | |
| 67 | + | <key>CFBundleExecutable</key> | |
| 68 | + | <string>project1</string> | |
| 69 | + | <key>CFBundleName</key> | |
| 70 | + | <string>My Amazing Application</string> | |
| 71 | + | <key>CFBundleIdentifier</key> | |
| 72 | + | <string>com.company.project1</string> | |
| 73 | + | <key>CFBundleInfoDictionaryVersion</key> | |
| 74 | + | <string>6.0</string> | |
| 75 | + | <key>CFBundlePackageType</key> | |
| 76 | + | <string>APPL</string> | |
| 77 | + | <key>CFBundleSignature</key> | |
| 78 | + | <string>proj</string> | |
| 79 | + | <key>CFBundleShortVersionString</key> | |
| 80 | + | <string>1.0</string> | |
| 81 | + | <key>CFBundleVersion</key> | |
| 82 | + | <string>11</string> | |
| 83 | + | <key>CFBundleIconFile</key> | |
| 84 | + | <string>ss4200utility.icns</string> | |
| 85 | + | <key>CSResourcesFileMapped</key> | |
| 86 | + | <true/> | |
| 87 | + | <key>CFBundleDocumentTypes</key> | |
| 88 | + | <array> | |
| 89 | + | <dict> | |
| 90 | + | <key>CFBundleTypeRole</key> | |
| 91 | + | <string>Viewer</string> | |
| 92 | + | <key>CFBundleTypeExtensions</key> | |
| 93 | + | <array> | |
| 94 | + | <string>*</string> | |
| 95 | + | </array> | |
| 96 | + | <key>CFBundleTypeOSTypes</key> | |
| 97 | + | <array> | |
| 98 | + | <string>fold</string> | |
| 99 | + | <string>disk</string> | |
| 100 | + | <string>****</string> | |
| 101 | + | </array> | |
| 102 | + | </dict> | |
| 103 | + | </array> | |
| 104 | + | <key>NSHighResolutionCapable</key> | |
| 105 | + | <true/> | |
| 106 | + | <key>NSHumanReadableCopyright</key> | |
| 107 | + | <string>Copyright 2021, Your Full Name</string> | |
| 108 | + | </dict> | |
| 109 | + | </plist> | |
| 110 | + | ``` | |
| 111 | + | ||
| 112 | + | The HTML file used in the sample above was: | |
| 113 | + | ||
| 114 | + | ``` html | |
| 115 | + | <center> | |
| 116 | + | <p> | |
| 117 | + | <h3>Credits</h3> | |
| 118 | + | <p> | |
| 119 | + | Free Pascal Team | |
| 120 | + | <br/> | |
| 121 | + | Lazarus Team | |
| 122 | + | <br/> | |
| 123 | + | Free Pascal and Lazarus Forums | |
| 124 | + | <br/> | |
| 125 | + | Free Pascal and Lazarus Wiki | |
| 126 | + | <br/> | |
| 127 | + | </center> | |
| 128 | + | ``` | |
| 129 | + | ||
| 130 | + | If the HTML text is short enough, no white scrollbox will appear and the text will appear on the default grey background. | |
| 131 | + | ||
| 132 | + | Full project source code is available from [SourceForge](https://sourceforge.net/p/lazarus-wiki-projects/code/ci/master/tree/laz_about_boxes/). | |
| 133 | + | ||
| 134 | + | ## The overridden simple way | |
| 135 | + | ||
| 136 | + | This is a variation on the simple way described above, but allows us to override some or all of the information which was previously extracted from the `Info.plist` file in the [[Application Bundle]]. | |
| 137 | + | ||
| 138 | + | > **Note:** In versions of macOS before 10.13 (High Sierra) only the Copyright information can be overridden - from macOS 10.13 onwards, all of the information extracted from the `Info.plist` file can be overridden. | |
| 139 | + | ||
| 140 | + | ``` pascal | |
| 141 | + | ... | |
| 142 | + | {$mode objfpc}{$H+} | |
| 143 | + | {$modeswitch objectivec1} | |
| 144 | + | ... | |
| 145 | + | ||
| 146 | + | Uses | |
| 147 | + | CocoaAll, | |
| 148 | + | ...; | |
| 149 | + | ||
| 150 | + | procedure TForm1.MenuItemAboutClick(Sender: TObject); | |
| 151 | + | var | |
| 152 | + | dict: NSDictionary; | |
| 153 | + | val1: NSString; | |
| 154 | + | val2: NSString; | |
| 155 | + | val3: NSString; | |
| 156 | + | val4: NSString; | |
| 157 | + | val5: NSImage; | |
| 158 | + | key1: NSString; | |
| 159 | + | key2: NSString; | |
| 160 | + | key3: NSString; | |
| 161 | + | key4: NSString; | |
| 162 | + | key5: NSString; | |
| 163 | + | begin | |
| 164 | + | key1 := NSStr('Copyright'); | |
| 165 | + | val1 := NSStr('Copyright 2021, An Amazing Author'); | |
| 166 | + | Key2 := NSStr('ApplicationName'); | |
| 167 | + | val2 := NSStr('My Overriden Application'); | |
| 168 | + | key3 := NSStr('Version'); | |
| 169 | + | val3 := NSStr('Beta v1.29c'); | |
| 170 | + | key4 := NSStr('ApplicationVersion'); | |
| 171 | + | val4 := NSStr('Version 1.0.0'); | |
| 172 | + | ||
| 173 | + | key5 := NSStr('ApplicationIcon'); | |
| 174 | + | val5 := NSImage.alloc.init; | |
| 175 | + | val5 := val5.imageNamed(NSStr('PICinfo.icns')); | |
| 176 | + | ||
| 177 | + | dict := NSDictionary.alloc.initWithObjectsAndKeys(Val1, Key1, Val2, Key2, Val3, Key3, Val4, Key4, Val5, Key5, Nil); | |
| 178 | + | ||
| 179 | + | NSApp.orderFrontStandardAboutPanelWithOptions(Dict); | |
| 180 | + | ||
| 181 | + | dict.release; | |
| 182 | + | dict := Nil; | |
| 183 | + | end; | |
| 184 | + | ``` | |
| 185 | + | ||
| 186 | + | The sample output using the same `Credits.html` and `Info.plist` files from The Simple Way example above, plus the new icon file `PICinfo.icns` located in the Resources directory of the application bundle: | |
| 187 | + | ||
| 188 | + | <figure> | |
| 189 | + | <img src="Overidden_Easy_macOS_About_Box.jpg" title="Overidden_Easy_macOS_About_Box.jpg" /> | |
| 190 | + | <figcaption>Overidden_Easy_macOS_About_Box.jpg</figcaption> | |
| 191 | + | </figure> | |
| 192 | + | ||
| 193 | + | Full project source code is available from [SourceForge](https://sourceforge.net/p/lazarus-wiki-projects/code/ci/master/tree/laz_about_boxes2/). | |
| 194 | + | ||
| 195 | + | ## The complex way - now outdated | |
| 196 | + | ||
| 197 | + | **Beware** *CFBundleGetMainBundle* does not really return **nil** if the application has no bundle. Instead it tries to create that handle. See [Apple's documentation](https://developer.apple.com/documentation/corefoundation/1537085-cfbundlegetmainbundle?language=objc). So we should check for the existence of *ValueRef* too. | |
| 198 | + | ||
| 199 | + | ``` pascal | |
| 200 | + | // CODE FOR SHOWING APPLICATION TITLE, VERSION, AND COMPANY | |
| 201 | + | uses MacOSAll, CarbonProc, StrUtils; | |
| 202 | + | ||
| 203 | + | var | |
| 204 | + | BundleID: String; | |
| 205 | + | BundleName: String; | |
| 206 | + | BundleRef: CFBundleRef; | |
| 207 | + | BundleVer: String; | |
| 208 | + | CompanyName: String; | |
| 209 | + | KeyRef: CFStringRef; | |
| 210 | + | ValueRef: CFTypeRef; | |
| 211 | + | ||
| 212 | + | // Retrieve information from the Info.plist file in the application bundle | |
| 213 | + | function GetInfoPlistString(const KeyName : string) : string; | |
| 214 | + | begin | |
| 215 | + | try | |
| 216 | + | Result := ''; | |
| 217 | + | BundleRef := CFBundleGetMainBundle; | |
| 218 | + | if BundleRef = nil then Exit; {Executable not in an app bundle?} | |
| 219 | + | KeyRef := CFStringCreateWithPascalString(nil,KeyName,kCFStringEncodingUTF8); | |
| 220 | + | ValueRef := CFBundleGetValueForInfoDictionaryKey(BundleRef, KeyRef); | |
| 221 | + | if ValueRef = nil then Exit; {Executable not in an app bundle!} | |
| 222 | + | if CFGetTypeID(ValueRef) <> CFStringGetTypeID then Exit; {Value not a string?} | |
| 223 | + | Result := CFStringToStr(ValueRef); | |
| 224 | + | except | |
| 225 | + | on E : Exception do | |
| 226 | + | ShowMessage(E.Message); | |
| 227 | + | end; | |
| 228 | + | FreeCFString(KeyRef); | |
| 229 | + | end; | |
| 230 | + | ||
| 231 | + | // Display the information in an About Box | |
| 232 | + | procedure TForm1.FormCreate(Sender: TObject); | |
| 233 | + | begin | |
| 234 | + | try | |
| 235 | + | Form1.Caption := 'About '+Application.Title; | |
| 236 | + | StaticTextAppTitle.Caption := Application.Title; | |
| 237 | + | BundleID := GetInfoPlistString('CFBundleIdentifier'); | |
| 238 | + | // CompanyName is presumed to be in the form of: com.Company.AppName | |
| 239 | + | CompanyName := AnsiMidStr(BundleID,AnsiPos('.',BundleID)+1,Length(BundleID)); | |
| 240 | + | CompanyName := AnsiMidStr(CompanyName,0,AnsiPos('.',CompanyName)-1); | |
| 241 | + | BundleVer := GetInfoPlistString('CFBundleVersion'); | |
| 242 | + | StaticTextAppVer.Caption := Application.Title+' version '+BundleVer; | |
| 243 | + | StaticTextCompany.Caption := CompanyName; | |
| 244 | + | except | |
| 245 | + | on E : Exception do | |
| 246 | + | ShowMessage(E.Message); | |
| 247 | + | end; | |
| 248 | + | end; | |
| 249 | + | ``` | |
| 250 | + | ||
| 251 | + | Sample output: | |
| 252 | + | ||
| 253 | + | <figure> | |
| 254 | + | <img src="About1.png" title="About1.png" /> | |
| 255 | + | <figcaption>About1.png</figcaption> | |
| 256 | + | </figure> | |
| 257 | + | ||
| 258 | + | Note that Apple-compliant About Boxes should not contain a caption in the title bar. Oops. | |
| 259 | + | ||
| 260 | + | ## See also | |
| 261 | + | ||
| 262 | + | - [[Mac Preferences and About Menu]] | |
| 263 | + | - [[Show Application Title, Version, and Company]]. | |
| 264 | + | - [[Locating the macOS application resources directory]] | |
| 265 | + | ||
| 266 | + | ## External links | |
| 267 | + | ||
| 268 | + | - [Apple: CFBundle Overview](https://developer.apple.com/documentation/corefoundation/cfbundle-s0a). | |
| 269 | + | ||
| 270 | + | - [Apple: orderFrontStandardAboutPanel](https://developer.apple.com/documentation/appkit/nsapplication/1428724-orderfrontstandardaboutpanel). | |
| 271 | + | ||
| 272 | + | - [Apple: orderFrontStandardAboutPanelWithOptions](https://developer.apple.com/documentation/appkit/nsapplication/1428479-orderfrontstandardaboutpanelwith). | |
| 273 | + | ||
| 274 | + | - [Apple: NSAboutPanelOptionKey](https://developer.apple.com/documentation/appkit/nsaboutpaneloptionkey). | |
| 275 | + | ||
| 276 | + | --- | |
| 277 | + | *From the Free Pascal wiki, page "Mac Show Application Title, Version, and Company", as it stood on 2021-12-09 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* | |
| 278 | + | Category: Code Snippets | |
| 279 | + | Category: macOS |
