commit f6150dafc8ba15162d86594be952794d77d87c27 Author: coddec Date: Mon Dec 4 13:27:18 2017 +1100 Initial commit diff --git a/Binary,Executable/ClassicShellSetup_4_3_1-de.exe b/Binary,Executable/ClassicShellSetup_4_3_1-de.exe new file mode 100644 index 0000000..d9803c5 Binary files /dev/null and b/Binary,Executable/ClassicShellSetup_4_3_1-de.exe differ diff --git a/Binary,Executable/ClassicShellSetup_4_3_1-es.exe b/Binary,Executable/ClassicShellSetup_4_3_1-es.exe new file mode 100644 index 0000000..b088b0f Binary files /dev/null and b/Binary,Executable/ClassicShellSetup_4_3_1-es.exe differ diff --git a/Binary,Executable/ClassicShellSetup_4_3_1-fr.exe b/Binary,Executable/ClassicShellSetup_4_3_1-fr.exe new file mode 100644 index 0000000..146078d Binary files /dev/null and b/Binary,Executable/ClassicShellSetup_4_3_1-fr.exe differ diff --git a/Binary,Executable/ClassicShellSetup_4_3_1-it.exe b/Binary,Executable/ClassicShellSetup_4_3_1-it.exe new file mode 100644 index 0000000..1b4114a Binary files /dev/null and b/Binary,Executable/ClassicShellSetup_4_3_1-it.exe differ diff --git a/Binary,Executable/ClassicShellSetup_4_3_1-pl.exe b/Binary,Executable/ClassicShellSetup_4_3_1-pl.exe new file mode 100644 index 0000000..8da9690 Binary files /dev/null and b/Binary,Executable/ClassicShellSetup_4_3_1-pl.exe differ diff --git a/Binary,Executable/ClassicShellSetup_4_3_1-ru.exe b/Binary,Executable/ClassicShellSetup_4_3_1-ru.exe new file mode 100644 index 0000000..a866bce Binary files /dev/null and b/Binary,Executable/ClassicShellSetup_4_3_1-ru.exe differ diff --git a/Binary,Executable/ClassicShellSetup_4_3_1-zhCN.exe b/Binary,Executable/ClassicShellSetup_4_3_1-zhCN.exe new file mode 100644 index 0000000..5273436 Binary files /dev/null and b/Binary,Executable/ClassicShellSetup_4_3_1-zhCN.exe differ diff --git a/Binary,Executable/ClassicShellSetup_4_3_1-zhTW.exe b/Binary,Executable/ClassicShellSetup_4_3_1-zhTW.exe new file mode 100644 index 0000000..2e82133 Binary files /dev/null and b/Binary,Executable/ClassicShellSetup_4_3_1-zhTW.exe differ diff --git a/Binary,Executable/ClassicShellSetup_4_3_1.exe b/Binary,Executable/ClassicShellSetup_4_3_1.exe new file mode 100644 index 0000000..2a728c6 Binary files /dev/null and b/Binary,Executable/ClassicShellSetup_4_3_1.exe differ diff --git a/Binary,Executable/ClassicShellUtility.exe b/Binary,Executable/ClassicShellUtility.exe new file mode 100644 index 0000000..88630ef Binary files /dev/null and b/Binary,Executable/ClassicShellUtility.exe differ diff --git a/ClassicShellLoc/English/ClassicExplorer.html b/ClassicShellLoc/English/ClassicExplorer.html new file mode 100644 index 0000000..22bf193 --- /dev/null +++ b/ClassicShellLoc/English/ClassicExplorer.html @@ -0,0 +1,437 @@ + + + + + + Classic Explorer + +

Classic Shell website  Classic Explorer


+Classic +Explorer is a plugin for Windows Explorer that: + +
+ + +

New copy UI (Windows 7 only)
+

+ +In Vista when you copy files and there is a conflict you are presented +with this:
+ +
+ +Before
+ +

What’s wrong with it?

+ +

Well, for +starters it is half a screen full of text that you have to read. Also +it is not immediately clear what parts of it are clickable. You have to +move the mouse around to discover the UI like in a Lucas Arts +adventure game. And finally the keyboard usability is awful. To +tell it +“yes, I know what I’m doing, I want to overwrite all files” you have to +press Alt+D, up, up, up, Space! It is harder than performing the Akuma +Kara Demon move in Street Fighter 3. There is a time and a place +for +that stuff and copying files is not it.

+ +

The Classic Explorer plugin brings back the simpler dialog box from Windows XP:
+

+ +

After
+

+ +

It +is immediately clear what is clickable (clue – the buttons at the +bottom), there is easy keyboard navigation (press Y for “Yes”, A to +copy all files) and you can still see which file is newer and which is +larger. And of course just like in Windows XP, holding down Shift while clicking on the No button means "No to All" (or just press Shift+N).
+

+ +

If you click +on More… you will get +the original dialog from Windows. From there you +will see all the details and you’ll get an extra option to “Copy, but +keep both files”.

+

Important Note: Only the UI is replaced. The underlying system that does the actual copying is not affected.
+

+


+

+ + + +

Alt+Enter in the folder panel

+ +Alt+Enter is +universal shortcut across Windows to bring up the properties of the +selection. But newer versions of Windows it doesn’t work in the left +panel that shows the folders. It works fine on the right where the +files are. This is broken compared to Windows XP where Alt+Enter works +in both places. +

To solve the +problem, the Classic Explorer plugin detects when you press Alt+Enter +and shows the properties for the currently selected folder.
+

+


+

+ + +

Toolbar for Windows Explorer

+Windows +Explorer in Vista doesn’t have a toolbar like the one in Windows XP. If +you want to go to the parent folder you have to use the breadcrumbs +bar. If you want to copy or delete a file with the mouse you have to +right-click and look for the Delete command. The right-click menu gets +bigger and bigger the more shell extensions you have installed, and +finding the right command can take a while.
+

To solve the problem, the Classic Explorer plugin adds a new toolbar:
+

+ + Explorer Toolbar
+
+The available button are: Go Up, Cut, Copy, Paste, Delete, Properties, +Email, Settings. More buttons can be added from the Settings dialog.
+
+Hints:
+    - Hold the Control key when clicking the Up button to open the parent folder in a new Explorer window.
+    - Hold the Shift key when clicking the Delete button to permanently delete a file
+ +
+ +The new toolbar doesn’t show up in Explorer automatically after +installation. You have to do a few things before you can use it:
+ +
    + +
  1. Open a new Windows Explorer window (Win key+E)
  2. +
  3. Turn on the menu in Explorer – Go to Tools (Alt+T), Folder +Options, the View tab, and make sure “Always show menus” is checked.
  4. +
  5. Right click on the menu bar and select “Classic Explorer Bar” to +show the toolbar.
  6. +
  7. If that option is not available (you only see “Lock the +Toolbars”) you may have to enable the plugin from Internet Explorer. +Run IE, right click on its toolbar and select “Classic Explorer Bar”. +It will ask you if you want to enable this add-on. Select “Enable”, +then repeat steps 1 through 3 again.
  8. +
  9. If even then you don't see the toolbar, maybe the browser +extensions are disabled on your system. This is usually the default for +servers. Open the "Internet Options", go to the "Advanced" tab, and check +the option "Enable third-party browser extensions".
    +
  10. + +

+

Status bar
+

+Classic Explorer restores the original Explorer status bar that shows the free disk space and the size of the selected files:
+
+File size in status bar
+
+Unlike the built-in status bar, the selection size is shown even if +more than 100 files are selected. When no files are selected the total +size of all files in the folder is shown.
+
Windows 7 note: Classic Explorer enhances the +default status bar instead of replacing it. To see it, you have to turn +it on first from the View menu. +The status bar is different from the blue +Details Pane you see at the bottom of Explorer. You can turn off the +Details Pane from the Organize menu to save space. Also there is a bug +in the Windows 7 Explorer that sometimes doesn't show any text in the +status bar. Press F5 to refresh the view and get the status text.
+
Windows 8 note: Classic Explorer adds its own +status bar. You should hide the default status bar to save space. +Select the View tab in the ribbon, then click on Options. Select the +View tab in the options. Locate the checkbox "Show status bar" and +uncheck it. +
+
+ + +

Settings

You can access the settings of Classic Explorer from the toolbar or from the start menu:
+
+
You can choose from seeing only the basic settings, or all +available settings. Hover over each setting to see a description of +what it's for. Type in the search box to find a setting by name.
+Every setting has a default value. The default value can be constant, +or it may depend on the current system settings. Once you edit a +setting it becomes "modified" and is shown in bold. To revert to the +default value, right-click on the setting.
+
You can save the settings to an XML file, and later load them back. +Press the Backup button to access these functions. From there you can +also reset all settings to their default value.
+ +
+ +Press OK to store your settings. Most of the settings will be applied +the next time you open a new Explorer window. Small number of settings +will require a log off before you can see the change.
+ +
+ +Note: All Settings windows are resizable. Resize them and place them where you want them to be. They will remember the new position.
+ +
+Here's one example of what can be customized:
+ + Title bar tweaks
+
+Click on the Toolbar Buttons tab to customize the toolbar:
+
+
The column on the left shows the current buttons in the toolbar, +and the column on the right lists the buttons you can add to the +toolbar. You can drag and drop buttons from the right column to the +left. You +can rearrange the buttons by dragging them up and down. If you drop one button inside another you will create a sub-menu.
+Hover over each +button to see a short description of what it does. Right-click on each +button to access more functions (like Delete, Rename, etc). From the +right-click menu you can also reset the toolbar to the original state.
+Each item in the left column must have a unique name. This is the +identifier of the item and can only contain English letters, digits and +underscore. Some items (like SEPARATOR) cannot be renamed.
+
+Important Note: Not all available commands have default icons or text. That's because Windows doesn't have icons for things like Undo, Select All, etc. If you want to use such buttons in your toolbar you will have to provide your own icon. See below how to do it.
+
+After you place a button in the toolbar, you can edit it's attributes. Double-click on the button to edit:
+Edit toolbar button
+Here you can select a command for the button, its text and icon. Press the Restore Defaults button to get the default text and icon for the chosen command.
+The command can be:
+ +The link can be a path to a file or a folder. If it is a file, that +file will be executed. If it is a folder, that folder will be opened as +a sub-menu (only for top-level buttons).
+
+The icon can be:
+ +If the label or the tip attribute start with $ (dollar sign), then the +system will treat it as a name of a string in the ExplorerL10N.ini +file. The actual text will depend on the current language setting. This +is useful when creating a toolbar that can be used by multiple languages.
+
+Note to developers: Buttons for custom commands can be checked or disabled. The toolbar checks the registry key HKCU\Software\IvoSoft\ClassicExplorer +for a DWORD value with the name of the button (the name used in left +column). 0 means normal, 1 is disabled and 2 is checked. The toolbar +reads the registry keys on startup. To force the buttons to update +their state after that you need to find all Explorer windows, locate +the child window with class ClassicShell.CBandWindow, and post a message WM_CLEAR. This is useful if you are developing a custom exe to be used by the toolbar.
+ +
+

Examples for Custom Commands

+

0) Use quotes when necessary

In order to support paths that +contain spaces, you should use quotes around the path parameters. The +quotes are not always required, like in examples 1 and 2 below. Make +sure you test your commands with paths containing spaces to avoid +surprises.
+
+

1) Print the current folder

+ +Use this command: cmd.exe /k echo %1. %1 will be replaced by the path of the current folder.
+
+

2) Open the selected file in Notepad

+Use this command: %SystemRoot%\notepad.exe %2. +%2 will be replaced by the full name of the selected file. It doesn't +need to be in quotes because Notepad uses the whole command line as a +file name.
+
+

3) Copy selected files to the parent folder
+

+Create a batch file called C:\CopyParent.bat:
+set list=%1
+set list=%list:"=%
+for /F "delims=" %%i in (%list%) do copy /Y "%%i" ..
+del %1
+
+Use this command: C:\CopyParent.bat "%3". +%3 will be replaced by a text file containing the full names of all +selected files. The batch file will read each line of that text file, +and copy each of the selected files to the parent folder. At the end +the batch file deletes the initial +temp file. The first two set commands remove the quotes from the %1 parameter.
+
+

4) Select all text files

+Create a batch file called C:\SelectText.bat:
+echo select > %1
+dir *.txt /b >> %1
+
+Use this command: C:\SelectText.bat "%5". +%5 will be replaced by a blank text file, where the command must output +the word "select" and a list of files it wants to select. The "dir +*.txt /b" command provides that list.
+
+
+ +

Administrative Settings

The settings are +per user and are stored in the registry. By default every user can edit +all of their settings. An administrator can lock specific settings, so +no user can edit them:
+
+In this example the setting "Show Up button" is locked to always be +"Before Back/Forward" and can't be changed by any user. This is achieved +by adding the setting to the HKEY_LOCAL_MACHINE\SOFTWARE\IvoSoft\ClassicExplorer registry key. Create a string value called "ShowUpButton" and set it to "BeforeBack".
+
In some cases you may not want to lock the value for all users, but +simply modify the initial value of the setting. In such case add +"_Default" to the name of the value. For example if you want the Up +button to be before Back by default but still allow the users to change +it if they wish, create a string value named "ShowUpButton_Default" and +set it to "BeforeBack".
+
+The easiest way to know the registry name of a setting and its value is to modify it, and then look it up in HKEY_CURRENT_USER\Software\IvoSoft\ClassicExplorer\Settings.
+Sometimes you may want to lock a setting to its default value, but you +don't know what the default value is. Then create a DWORD value and set +it to 0xDEFA.
+
+There is also a global setting EnableSettings. Set it to 0 in the +registry to prevent the users from even opening the Settings dialog:
+Disable all settings
+
+You can enable or disable Classic Explorer for individual processes +using the 2 registry settings "ProcessWhiteList" and +"ProcessBlackList". ProcessWhiteList is +a list of processes for which Classic Explorer will load. Use only the +file name of the process (like "notepad.exe"), separate multiple names +with a comma or a semicolon. ProcessBlackList +is a list of processes for which Classic Explorer will not load. You +should only use one of the two lists. If both lists are specified, the +black list will be ignored. The lists are only used when you enable the +features that are supported for processes other than Explorer. At the +moment these features are: the shared overlay icon and the replacements +for the copy dialogs.
+
+Editing the settings through group policies is also supported. Extract the file PolicyDefinitions.zip found in the installation folder and read the document PolicyDefinitions.rtf for more details.
+
+ +
+ +

Dependencies on Windows settings
+

+Some Classic Explorer settings require specific Windows settings to be enabled:
+ + +
+ +

Localization

+ + + + +The user +interface (except the Settings dialog box) is localized in 35 +languages.
+The Settings dialog box is translated in a smaller number of languages. +The default installation contains only English. More languages can be +downloaded from the translations page. Make sure you download the translation package for the exact version of Classic Shell.
+ +
+ + \ No newline at end of file diff --git a/ClassicShellLoc/English/ClassicExplorerADMX.txt b/ClassicShellLoc/English/ClassicExplorerADMX.txt new file mode 100644 index 0000000..6ea1bb5 --- /dev/null +++ b/ClassicShellLoc/English/ClassicExplorerADMX.txt @@ -0,0 +1,62 @@ +; DON'T TRANSLATE ============================================================= + +; disabled +LogLevel.supportedOn = never +ShowFreeSpace2.supportedOn = never +ShowInfoTip2.supportedOn = never + +; os-specific +ReplaceFileUI.supportedOn = win7 +ReplaceFolderUI.supportedOn = win7 +OverwriteAlertLevel.supportedOn = win7 +EnableMore.supportedOn = win7 +MoreProgressDelay.supportedOn = win7 +FileExplorer.supportedOn = win7 +ShowUpButton.supportedOn = win7 +UpIconNormal.supportedOn = win7 +UpIconPressed.supportedOn = win7 +UpIconHot.supportedOn = win7 +UpIconDisabled.supportedOn = win7 +UpIconSize.supportedOn = win7 +FixFolderScroll.supportedOn = win7 +ForceRefreshWin7.supportedOn = win7 +ShowCaption.supportedOn = win7 +ShowIcon.supportedOn = win7 +ShowStatusBar.supportedOn = win881 +ShowZone.supportedOn = win881 + + + +; TRANSLATE =================================================================== + +Title.text = Classic Shell settings +State.text = State: +State1.text = Locked to this value +State2.text = Locked to default +State3.text = Unlocked +State1Help.text = If you set the state to 'Locked to this value', the setting will be locked to the specified value for all users. +State2Help.text = If you set the state to 'Locked to default', the setting will be locked to the default value for all users. The specified value is ignored. +State3Help.text = If you set the state to 'Unlocked', the default value for the setting will be changed to the specified value. Individual users can override the setting. + +ClassicExplorerCat.text = Classic Explorer +ClassicExplorerCatHelp.text = Classic Explorer group policy settings +SUPPORTED_CS404.text = Requires Classic Shell 4.0.4 or later. +SUPPORTED_CS404_WIN7.text = Requires Windows 7. +SUPPORTED_CS404_WIN881.text = Requires Windows 8 or Windows 8.1. + +AddressAltD.nameOverride = Additional shortcut for the address bar +AddressAltD.tipOverride = Enter a letter 'A' to 'Z' to be a shortcut for the address bar in combination with the Alt key +EnableSettings.nameOverride = Enable settings +EnableSettings.tipOverride = Enables the users to edit their own settings +ProcessWhiteList.nameOverride = Process white list +ProcessWhiteList.tipOverride = List of processes that can load Classic Explorer. Use only the file name of the process (like "notepad.exe"), separate multiple names with a comma or semicolon. +ProcessBlackList.nameOverride = Process black list +ProcessBlackList.tipOverride = List of processes that will not load Classic Explorer. Use only the file name of the process (like "notepad.exe"), separate multiple names with a comma or semicolon. +ToolbarItems.nameOverride = Toolbar buttons +ToolbarItems.tipOverride = Select the buttons to be shown in the toolbar.\nThe best way to get the right string is to configure the buttons in the Classic Explorer settings dialog and then look up the value named ToolbarItems in HKCU\Software\IvoSoft\ClassicExplorer\Settings +NoInitialToolbar.nameOverride = No initial showing of the toolbar +NoInitialToolbar.tipOverride = When this is checked, the Explorer toolbar will not be automatically displayed + + +; os-specific +FileExplorer.nameOverride = Enable dialogs only in Explorer (improves performance) diff --git a/ClassicShellLoc/English/ClassicIE.html b/ClassicShellLoc/English/ClassicIE.html new file mode 100644 index 0000000..1ac0788 --- /dev/null +++ b/ClassicShellLoc/English/ClassicIE.html @@ -0,0 +1,100 @@ + + + + + + + + + + + + + Classic IE + +

Classic Shell website  +Classic IE


+Classic IE
+is a +small plugin for Internet Explorer that:
+ +
+See the full page title even when it doesn't fit in the tab:
+
+
See the progress and the security zone:
+
+
+

Installation

+When you run Internet Explorer for the first time after installing +Classic IE it may prompt you that a new add-on called ClassicIEBHO is +installed and if you want to enable it. Click on the Enable button. If +you don't get a prompt, go to Tools -> Manage add-ons and make sure ClassicIEBHO is enabled. After enabling the add-on you have to restart Internet Explorer to activate the plugin.
+
+

Settings

+You can access the settings from Tools -> Classic IE Settings +or from the start menu. The settings control the color and the font of +the caption, and what information to display on the status bar.
+
+
You can choose from seeing only the basic settings, or all +available settings. Hover over each setting to see a description of +what it's for. Type in the search box to find a setting by name.
+Every setting has a default value. The default value can be constant, +or it may depend on the current system settings. Once you edit a +setting it becomes "modified" and is shown in bold. To revert to the +default value, right-click on the setting.
+ +
+You can save the settings to an XML file, and later load them back. +Press the Backup button to access these functions. From there you can +also reset all settings to their default value.
+ + +
+ + +Press OK to store your settings. You need to restart Internet Explorer to apply the new settings.
+ + +
+

Administrative Settings

+The settings are +per user and are stored in the registry. By default every user can edit +all of their settings. An administrator can lock specific settings, so +no user can edit them. This is achieved by adding the setting to the HKEY_LOCAL_MACHINE\SOFTWARE\IvoSoft\ClassicIE registry key.
+
+You may also wish to not lock the setting but only override its initial +value. Then add "_Default" to the name of the registry value.
+
+The easiest way to know the registry name of a setting and its value is to modify it, and then look it up in HKEY_CURRENT_USER\Software\IvoSoft\ClassicIE\Settings.
+ +Sometimes you may want to lock a setting to its default value, but you +don't know what the default value is. Then create a DWORD value and set +it to 0xDEFA.
+ +
+ +There is also a global setting EnableSettings. Set it to 0 in the +registry to prevent the users from even opening the Settings dialog:
+ +
+
+Editing the settings through group policies is also supported. Extract the file PolicyDefinitions.zip found in the installation folder and read the document PolicyDefinitions.rtf for more details.
+
+ \ No newline at end of file diff --git a/ClassicShellLoc/English/ClassicIEADMX.txt b/ClassicShellLoc/English/ClassicIEADMX.txt new file mode 100644 index 0000000..7cc7db7 --- /dev/null +++ b/ClassicShellLoc/English/ClassicIEADMX.txt @@ -0,0 +1,26 @@ +; DON'T TRANSLATE ============================================================= + +LogLevel.supportedOn = never + + + +; TRANSLATE =================================================================== + +Title.text = Classic Shell settings +State.text = State: +State1.text = Locked to this value +State2.text = Locked to default +State3.text = Unlocked +State1Help.text = If you set the state to 'Locked to this value', the setting will be locked to the specified value for all users. +State2Help.text = If you set the state to 'Locked to default', the setting will be locked to the default value for all users. The specified value is ignored. +State3Help.text = If you set the state to 'Unlocked', the default value for the setting will be changed to the specified value. Individual users can override the setting. + +ClassicIECat.text = Classic IE +ClassicIECatHelp.text = Classic IE group policy settings +SUPPORTED_CS404.text = Requires Classic Shell 4.0.4 or later. +SUPPORTED_IE9.text = Requires Internet Explorer 9 or later. + + +EnableSettings.nameOverride = Enable settings +EnableSettings.tipOverride = Enables the users to edit their own settings +CaptionFont.tipAddition = .\n\nThe format is , , . For example "Segoe UI, normal, 9" diff --git a/ClassicShellLoc/English/ClassicShell.chm b/ClassicShellLoc/English/ClassicShell.chm new file mode 100644 index 0000000..292563f Binary files /dev/null and b/ClassicShellLoc/English/ClassicShell.chm differ diff --git a/ClassicShellLoc/English/ClassicShell.hhp b/ClassicShellLoc/English/ClassicShell.hhp new file mode 100644 index 0000000..5d31f67 --- /dev/null +++ b/ClassicShellLoc/English/ClassicShell.hhp @@ -0,0 +1,16 @@ +[OPTIONS] +Compatibility=1.1 or later +Compiled file=ClassicShell.chm +Contents file=ClassicShellTOC.hhc +Default topic=Main.html +Display compile progress=Yes +Language=0x409 English (United States) + + +[FILES] +ClassicExplorer.html +ClassicStartMenu.html +ClassicIE.html + +[INFOTYPES] + diff --git a/ClassicShellLoc/English/ClassicShellADMX.txt b/ClassicShellLoc/English/ClassicShellADMX.txt new file mode 100644 index 0000000..161f991 --- /dev/null +++ b/ClassicShellLoc/English/ClassicShellADMX.txt @@ -0,0 +1,19 @@ +; TRANSLATE =================================================================== + +Title.text = Classic Shell settings +State.text = State: +State1.text = Locked to this value +State2.text = Locked to default +State3.text = Unlocked +State1Help.text = If you set the state to 'Locked to this value', the setting will be locked to the specified value for all users. +State2Help.text = If you set the state to 'Locked to default', the setting will be locked to the default value for all users. The specified value is ignored. +State3Help.text = If you set the state to 'Unlocked', the default value for the setting will be changed to the specified value. Individual users can override the setting. + +ClassicShellCat.text = Classic Shell +ClassicShellCatHelp.text = Classic Shell group policy settings +SUPPORTED_CS404.text = Requires Classic Shell 4.0.4 or later. + +Language.nameOverride = Language for Classic Shell components +Language.tipOverride = Select the language to be used by Classic Shell (for example en-US or de-DE). The language will affect the text in the start menu, toolbars, etc. If the appropriate language DLL is installed, the settings UI may also be translated +Update.nameOverride = Enable automatic checks for new versions +Update.tipOverride = When this is checked, Classic Shell will check for new releases every week. You will be notified if there is a new version of the Classic Shell software or a new update for your current language diff --git a/ClassicShellLoc/English/ClassicShellEULA.rtf b/ClassicShellLoc/English/ClassicShellEULA.rtf new file mode 100644 index 0000000..e630348 --- /dev/null +++ b/ClassicShellLoc/English/ClassicShellEULA.rtf @@ -0,0 +1,272 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;} +{\f36\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} +{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} +{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f379\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f380\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;} +{\f382\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f383\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f386\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f387\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);} +{\f399\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\f400\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\f402\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\f403\fbidi \froman\fcharset162\fprq2 Cambria Tur;} +{\f406\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\f407\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\f409\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f417\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);} +{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;} +{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;} +{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} +{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}} +{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0; +\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\caccentone\ctint255\cshade191\red54\green95\blue145;\caccentone\ctint255\cshade255\red79\green129\blue189; +\caccentone\ctint255\cshade127\red36\green63\blue96;\ctextone\ctint191\cshade255\red64\green64\blue64;\ctexttwo\ctint255\cshade191\red23\green54\blue93;\ctextone\ctint255\cshade255\red0\green0\blue0;\ctextone\ctint127\cshade255\red128\green128\blue128; +\caccenttwo\ctint255\cshade255\red192\green80\blue77;\chyperlink\ctint255\cshade255\red0\green0\blue255;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 \styrsid8675715 Normal;}{\s1\ql \li0\ri0\sb480\sl276\slmult1 +\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs28\alang1025 \ltrch\fcs0 \b\fs28\cf17\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink15 \sqformat \spriority9 \styrsid8675715 heading 1;}{\s2\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs26\alang1025 +\ltrch\fcs0 \b\fs26\cf18\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink16 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid8675715 heading 2;}{\s3\ql \li0\ri0\sb200\sl276\slmult1 +\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel2\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs22\alang1025 \ltrch\fcs0 \b\fs22\cf18\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink17 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid8675715 heading 3;}{\s4\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel3\adjustright\rin0\lin0\itap0 \rtlch\fcs1 +\ab\ai\af0\afs22\alang1025 \ltrch\fcs0 \b\i\fs22\cf18\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink18 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid8675715 heading 4;}{ +\s5\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel4\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\cf19\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink19 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid8675715 heading 5;}{\s6\ql \li0\ri0\sb200\sl276\slmult1 +\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel5\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ai\af0\afs22\alang1025 \ltrch\fcs0 \i\fs22\cf19\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink20 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid8675715 heading 6;}{\s7\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel6\adjustright\rin0\lin0\itap0 \rtlch\fcs1 +\ai\af0\afs22\alang1025 \ltrch\fcs0 \i\fs22\cf20\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink21 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid8675715 heading 7;}{ +\s8\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel7\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs20\alang1025 \ltrch\fcs0 +\fs20\cf18\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink22 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid8675715 heading 8;}{\s9\ql \li0\ri0\sb200\sl276\slmult1 +\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel8\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ai\af0\afs20\alang1025 \ltrch\fcs0 \i\fs20\cf20\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink23 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid8675715 heading 9;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused +Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \ab\af0\afs28 \ltrch\fcs0 \b\fs28\cf17\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink1 \slocked \spriority9 \styrsid8675715 Heading 1 Char;}{\*\cs16 \additive \rtlch\fcs1 \ab\af0\afs26 \ltrch\fcs0 +\b\fs26\cf18\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink2 \slocked \ssemihidden \spriority9 \styrsid8675715 Heading 2 Char;}{\*\cs17 \additive \rtlch\fcs1 \ab\af0 \ltrch\fcs0 \b\cf18\loch\f31502\hich\af31502\dbch\af31501 +\sbasedon10 \slink3 \slocked \spriority9 \styrsid8675715 Heading 3 Char;}{\*\cs18 \additive \rtlch\fcs1 \ab\ai\af0 \ltrch\fcs0 \b\i\cf18\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink4 \slocked \spriority9 \styrsid8675715 Heading 4 Char;}{\* +\cs19 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \cf19\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink5 \slocked \spriority9 \styrsid8675715 Heading 5 Char;}{\*\cs20 \additive \rtlch\fcs1 \ai\af0 \ltrch\fcs0 +\i\cf19\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink6 \slocked \spriority9 \styrsid8675715 Heading 6 Char;}{\*\cs21 \additive \rtlch\fcs1 \ai\af0 \ltrch\fcs0 \i\cf20\loch\f31502\hich\af31502\dbch\af31501 +\sbasedon10 \slink7 \slocked \spriority9 \styrsid8675715 Heading 7 Char;}{\*\cs22 \additive \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\cf18\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink8 \slocked \spriority9 \styrsid8675715 Heading 8 Char;}{\* +\cs23 \additive \rtlch\fcs1 \ai\af0\afs20 \ltrch\fcs0 \i\fs20\cf20\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink9 \slocked \spriority9 \styrsid8675715 Heading 9 Char;}{ +\s24\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext24 \sqformat \spriority1 \styrsid8675715 No Spacing;}{\s25\ql \li0\ri0\sa300\widctlpar\brdrb\brdrs\brdrw20\brsp80\brdrcf18 \wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\contextualspace \rtlch\fcs1 \af0\afs52\alang1025 \ltrch\fcs0 +\fs52\expnd1\expndtw5\cf21\lang1033\langfe1033\kerning28\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink26 \sqformat \spriority10 \styrsid8675715 Title;}{\*\cs26 \additive \rtlch\fcs1 \af0\afs52 \ltrch\fcs0 +\fs52\expnd1\expndtw5\cf21\kerning28\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink25 \slocked \spriority10 \styrsid8675715 Title Char;}{\s27\ql \li0\ri0\sa200\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 +\ab\af0\afs18\alang1025 \ltrch\fcs0 \b\fs18\cf18\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \ssemihidden \sunhideused \sqformat \spriority35 \styrsid8675715 caption;}{ +\s28\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ilvl1\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ai\af0\afs24\alang1025 \ltrch\fcs0 +\i\fs24\expnd3\expndtw15\cf18\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink29 \sqformat \spriority11 \styrsid8675715 Subtitle;}{\*\cs29 \additive \rtlch\fcs1 \ai\af0\afs24 \ltrch\fcs0 +\i\fs24\expnd3\expndtw15\cf18\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink28 \slocked \spriority11 \styrsid8675715 Subtitle Char;}{\*\cs30 \additive \rtlch\fcs1 \ab\af0 \ltrch\fcs0 \b \sbasedon10 \sqformat \spriority22 \styrsid8675715 Strong;} +{\*\cs31 \additive \rtlch\fcs1 \ai\af0 \ltrch\fcs0 \i \sbasedon10 \sqformat \spriority20 \styrsid8675715 Emphasis;}{\s32\ql \li720\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin720\itap0\contextualspace +\rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext32 \sqformat \spriority34 \styrsid8675715 List Paragraph;}{\s33\ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ai\af0\afs22\alang1025 \ltrch\fcs0 \i\fs22\cf22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink34 \sqformat \spriority29 \styrsid8675715 Quote;}{\*\cs34 \additive \rtlch\fcs1 \ai\af0 \ltrch\fcs0 \i\cf22 \sbasedon10 \slink33 \slocked \spriority29 \styrsid8675715 Quote Char;}{\s35\ql \li936\ri936\sb200\sa280\sl276\slmult1 +\widctlpar\brdrb\brdrs\brdrw10\brsp80\brdrcf18 \wrapdefault\aspalpha\aspnum\faauto\adjustright\rin936\lin936\itap0 \rtlch\fcs1 \ab\ai\af0\afs22\alang1025 \ltrch\fcs0 +\b\i\fs22\cf18\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink36 \sqformat \spriority30 \styrsid8675715 Intense Quote;}{\*\cs36 \additive \rtlch\fcs1 \ab\ai\af0 \ltrch\fcs0 \b\i\cf18 +\sbasedon10 \slink35 \slocked \spriority30 \styrsid8675715 Intense Quote Char;}{\*\cs37 \additive \rtlch\fcs1 \ai\af0 \ltrch\fcs0 \i\cf23 \sbasedon10 \sqformat \spriority19 \styrsid8675715 Subtle Emphasis;}{\*\cs38 \additive \rtlch\fcs1 \ab\ai\af0 +\ltrch\fcs0 \b\i\cf18 \sbasedon10 \sqformat \spriority21 \styrsid8675715 Intense Emphasis;}{\*\cs39 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \scaps\ul\cf24 \sbasedon10 \sqformat \spriority31 \styrsid8675715 Subtle Reference;}{\*\cs40 \additive \rtlch\fcs1 +\ab\af0 \ltrch\fcs0 \b\scaps\ul\expnd1\expndtw5\cf24 \sbasedon10 \sqformat \spriority32 \styrsid8675715 Intense Reference;}{\*\cs41 \additive \rtlch\fcs1 \ab\af0 \ltrch\fcs0 \b\scaps\expnd1\expndtw5 \sbasedon10 \sqformat \spriority33 \styrsid8675715 +Book Title;}{\s42\ql \li0\ri0\sb480\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs28\alang1025 \ltrch\fcs0 +\b\fs28\cf17\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon1 \snext0 \ssemihidden \sunhideused \sqformat \spriority39 \styrsid8675715 TOC Heading;}{\*\cs43 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf25 +\sbasedon10 \sunhideused \styrsid15734083 Hyperlink;}}{\*\listtable{\list\listtemplateid1887754378\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace720\levelindent0{\leveltext\leveltemplateid67698703 +\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li360\lin360 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace720\levelindent0{\leveltext\leveltemplateid67698713 +\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li720\lin720 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace720\levelindent0{\leveltext\leveltemplateid67698715 +\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li1440\lin1440 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace720\levelindent0{\leveltext\leveltemplateid67698703 +\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li2160\lin2160 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace720\levelindent0{\leveltext\leveltemplateid67698713 +\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace720\levelindent0{\leveltext\leveltemplateid67698715 +\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li3600\lin3600 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace720\levelindent0{\leveltext\leveltemplateid67698703 +\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li4320\lin4320 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace720\levelindent0{\leveltext\leveltemplateid67698713 +\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace720\levelindent0{\leveltext\leveltemplateid67698715 +\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li5760\lin5760 }{\listname ;}\listid859053399}{\list\listtemplateid-1477962598\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360 +\levelindent0{\leveltext\leveltemplateid67698703\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li1080\lin1080 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0 +{\leveltext\leveltemplateid67698713\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li1800\lin1800 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext +\leveltemplateid67698715\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li2520\lin2520 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext +\leveltemplateid67698703\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li3240\lin3240 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext +\leveltemplateid67698713\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li3960\lin3960 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext +\leveltemplateid67698715\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li4680\lin4680 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext +\leveltemplateid67698703\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5400\lin5400 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext +\leveltemplateid67698713\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li6120\lin6120 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext +\leveltemplateid67698715\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li6840\lin6840 }{\listname ;}\listid1441336739}{\list\listtemplateid-571172774\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67698703\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative +\levelspace0\levelindent0{\leveltext\leveltemplateid67698713\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0 +\levelindent0{\leveltext\leveltemplateid67698715\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0 +{\leveltext\leveltemplateid67698703\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698713\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698715\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698703\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698713\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698715\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li6480\lin6480 }{\listname ;}\listid2044404031}}{\*\listoverridetable{\listoverride\listid2044404031\listoverridecount0\ls1}{\listoverride\listid1441336739 +\listoverridecount0\ls2}{\listoverride\listid859053399\listoverridecount0\ls3}}{\*\rsidtbl \rsid73937\rsid276346\rsid485328\rsid935798\rsid1600407\rsid1642706\rsid1781248\rsid2106295\rsid4477449\rsid5141723\rsid5720124\rsid8598142\rsid8675715\rsid9851428 +\rsid9906829\rsid10302552\rsid12398630\rsid12659872\rsid12679588\rsid13962646\rsid14231072\rsid14297104\rsid14497758\rsid14513824\rsid14615385\rsid14753465\rsid14972022\rsid15356188\rsid15734083\rsid16735381}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0 +\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Ivo}{\creatim\yr2009\mo11\dy21\hr16\min51}{\revtim\yr2016\mo3\dy23\hr19\min48}{\version26}{\edmins60}{\nofpages1}{\nofwords240}{\nofchars1369} +{\nofcharsws1606}{\vern49167}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect +\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701 +\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot8675715 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 +\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 +\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\s25\qc \li0\ri0\sa300\widctlpar\brdrb\brdrs\brdrw20\brsp80\brdrcf18 \wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid1642706\contextualspace \rtlch\fcs1 \af0\afs52\alang1025 \ltrch\fcs0 +\fs52\expnd1\expndtw5\cf21\lang1033\langfe1033\kerning28\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid14753465 \hich\af31502\dbch\af31501\loch\f31502 License}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid8598142 \hich\af31502\dbch\af31501\loch\f31502 Agreement}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid8675715\charrsid8675715 +\par }\pard\plain \ltrpar\s24\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8675715 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid1600407 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Classic Shell \'a9\loch\f31506 2009}{\rtlch\fcs1 \af0 +\ltrch\fcs0 \insrsid14513824 \hich\af31506\dbch\af31505\loch\f31506 -201}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid14497758 \hich\af31506\dbch\af31505\loch\f31506 6}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid14513824 ,}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid1600407 \hich\af31506\dbch\af31505\loch\f31506 Ivo Beltchev +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \cf2\insrsid14231072\charrsid14231072 \hich\af31506\dbch\af31505\loch\f31506 http://}{\rtlch\fcs1 \af0 \ltrch\fcs0 \cf2\insrsid14972022 \hich\af31506\dbch\af31505\loch\f31506 www.}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\cf2\insrsid14231072\charrsid14231072 \hich\af31506\dbch\af31505\loch\f31506 classicshell.net/}{\rtlch\fcs1 \af0 \ltrch\fcs0 \cf2\insrsid12659872\charrsid2106295 +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid1600407\charrsid8675715 +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid14297104\charrsid9851428 \hich\af31506\dbch\af31505\loch\f31506 BY USING THIS SOFTWARE, YOU ACCEPT THESE TERMS. IF YOU DO NOT ACCEPT THEM, DO NOT USE THE SOFTWARE.}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\b\insrsid8675715\charrsid9851428 +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid14297104 +\par \hich\af31506\dbch\af31505\loch\f31506 If you comply with these license terms, you have the rights below. +\par +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \b\f31506\fs22\insrsid14297104\charrsid9851428 \hich\af31506\dbch\af31505\loch\f31506 1.\tab}}\pard\plain \ltrpar\ql \fi-360\li360\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls3\adjustright\rin0\lin360\itap0\pararsid9851428 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 +\ltrch\fcs0 \b\insrsid14297104\charrsid9851428 \hich\af31506\dbch\af31505\loch\f31506 SCOPE OF LICENSE.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid14297104 \hich\af31506\dbch\af31505\loch\f31506 + This agreement only gives you some rights to use the software. The\hich\af31506\dbch\af31505\loch\f31506 author reserves all other rights.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid9851428 +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \b\f31506\fs22\insrsid14297104\charrsid9851428 \hich\af31506\dbch\af31505\loch\f31506 2.\tab}}\pard \ltrpar\ql \fi-360\li360\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls3\adjustright\rin0\lin360\itap0\pararsid12398630 {\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid14297104\charrsid9851428 \hich\af31506\dbch\af31505\loch\f31506 INSTALLATION AND USE RIGHTS.}{\rtlch\fcs1 \af0 +\ltrch\fcs0 \insrsid14297104 \hich\af31506\dbch\af31505\loch\f31506 This software is free}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid12398630\charrsid12398630 \hich\af31506\dbch\af31505\loch\f31506 for both personal and commercial use}{\rtlch\fcs1 \af0 +\ltrch\fcs0 \insrsid14297104 \hich\af31506\dbch\af31505\loch\f31506 . You may install and use it on your }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid9851428 \hich\af31506\dbch\af31505\loch\f31506 computers}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid14297104 +\hich\af31506\dbch\af31505\loch\f31506 free of charge.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid9851428 +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \b\f31506\fs22\insrsid9851428\charrsid9851428 \hich\af31506\dbch\af31505\loch\f31506 3.\tab}}\pard \ltrpar\ql \fi-360\li360\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls3\adjustright\rin0\lin360\itap0\pararsid9851428 {\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid9851428\charrsid9851428 \hich\af31506\dbch\af31505\loch\f31506 REDISTRIBUTION RIGHTS.}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid9851428 \hich\af31506\dbch\af31505\loch\f31506 You may redistribute the software as long \hich\af31506\dbch\af31505\loch\f31506 as you do it free of charge and }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid1600407 \hich\af31506\dbch\af31505\loch\f31506 +you }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid9851428 \hich\af31506\dbch\af31505\loch\f31506 don\hich\f31506 \rquote \loch\f31506 t misrepresent the origin of the software. +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \b\f31506\fs22\insrsid5141723\charrsid73937 \hich\af31506\dbch\af31505\loch\f31506 4.\tab}}\pard \ltrpar\ql \fi-360\li360\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls3\adjustright\rin0\lin360\itap0\pararsid5141723 {\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid5141723\charrsid73937 \hich\af31506\dbch\af31505\loch\f31506 TRADEMARKS.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid5141723 +\hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid5141723\charrsid73937 \hich\af31506\dbch\af31505\loch\f31506 +The Classic Shell name and logo are trademarks of the author. Using them to to identify other products or services is not permitted.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid5141723 +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \b\f31506\fs22\insrsid14297104\charrsid1600407 \hich\af31506\dbch\af31505\loch\f31506 5.\tab}}\pard \ltrpar\ql \fi-360\li360\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls3\adjustright\rin0\lin360\itap0\pararsid1600407 {\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid14297104\charrsid1600407 \hich\af31506\dbch\af31505\loch\f31506 DISCLAIMER OF WARRANTY.}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid14297104 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid1600407 \hich\af31506\dbch\af31505\loch\f31506 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS B +\hich\af31506\dbch\af31505\loch\f31506 E LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \b\f31506\fs22\insrsid1600407 \hich\af31506\dbch\af31505\loch\f31506 6.\tab}}\pard \ltrpar\ql \fi-360\li360\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls3\adjustright\rin0\lin360\itap0\pararsid10302552 {\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid1600407 \hich\af31506\dbch\af31505\loch\f31506 IN }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid935798 +\hich\af31506\dbch\af31505\loch\f31506 OTHER}{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid1600407 \hich\af31506\dbch\af31505\loch\f31506 WORDS}{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid276346 \hich\af31506\dbch\af31505\loch\f31506 :}{\rtlch\fcs1 \af0 +\ltrch\fcs0 \insrsid1600407 \hich\af31506\dbch\af31505\loch\f31506 Basically you can use this software freely for any purpose but don\hich\f31506 \rquote \loch\f31506 t be surprised if it doesn\hich\f31506 \rquote \loch\f31506 t work }{\rtlch\fcs1 \af0 +\ltrch\fcs0 \insrsid4477449 \hich\af31506\dbch\af31505\loch\f31506 as you expect}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid1600407 \hich\af31506\dbch\af31505\loch\f31506 . You can\hich\f31506 \rquote \loch\f31506 +t hold the author responsible for any damages that come to you from using the software. You can\hich\f31506 \rquote \loch\f31506 t profit from selling this software\hich\af31506\dbch\af31505\loch\f31506 . }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid276346 +\hich\af31506\dbch\af31505\loch\f31506 You got it for}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid1600407 \hich\af31506\dbch\af31505\loch\f31506 free after all.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid10302552 +\par }\pard \ltrpar\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid10302552 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid10302552\charrsid8675715 +\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a +9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad +5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 +b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 +0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 +a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f +c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 +0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 +a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 +6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b +4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b +4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210096b5ade296060000501b0000160000007468656d652f7468656d652f +7468656d65312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87 +615b8116d8a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad +79482a9c0498f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b +5d8a314d3c94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab +999fb7b4717509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9 +699640f6719e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd586 +8b37a088d1e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d6 +0cf03ac1a5193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f +9e7ef3f2d117d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be +15c308d3f28acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a9979 +3849c26ae66252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d +32a423279a668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2a +f074481847bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86 +e877f0034e16bafb0e258ebb4faf06b769e888340b103d3311da9750aa9d0a1cd3e4efca31a3508f6d0c5c5c398602f8e2ebc71591f5b616e24dd893aa3261fb +44f95d843b5974bb5c04f4edafb95b7892ec1108f3f98de75dc97d5772bdff7cc95d94cf672db4b3da0a6557f70db629362d72bcb0431e53c6066acac80d699a +6409fb44d08741bdce9c0e4971624a2378cceaba830b05366b90e0ea23aaa241845368b0eb9e2612ca8c742851ca251ceccc70256d8d87265dd96361531f186c +3d9058edf2c00eafe8e1fc5c509031bb4d680e9f39a3154de0accc56ae644441edd76156d7429d995bdd88664a9dc3ad50197c38af1a0c16d684060441db0256 +5e85f3b9660d0713cc48a0ed6ef7dedc2dc60b17e92219e180643ed27acffba86e9c94c78ab90980d8a9f0913ee49d62b512b79626fb06dccee2a432bbc60276 +b9f7dec44b7904cfbca4f3f6443ab2a49c9c2c41476dafd55c6e7ac8c769db1bc399161ee314bc2e75cf8759081743be1236ec4f4d6693e5336fb672c5dc24a8 +c33585b5fb9cc24e1d4885545b58463634cc5416022cd19cacfccb4d30eb45296023fd35a458598360f8d7a4003bbaae25e331f155d9d9a5116d3bfb9a95523e +51440ca2e0088dd844ec6370bf0e55d027a012ae264c45d02f708fa6ad6da6dce29c255df9f6cae0ec38666984b372ab5334cf640b37795cc860de4ae2816e95 +b21be5ceaf8a49f90b52a51cc6ff3355f47e0237052b81f6800fd7b802239daf6d8f0b1571a8426944fdbe80c6c1d40e8816b88b8569082ab84c36ff0539d4ff +6dce591a26ade1c0a7f669880485fd484582903d284b26fa4e2156cff62e4b9265844c4495c495a9157b440e091bea1ab8aaf7760f4510eaa69a6465c0e04ec6 +9ffb9e65d028d44d4e39df9c1a52ecbd3607fee9cec7263328e5d661d3d0e4f62f44acd855ed7ab33cdf7bcb8ae889599bd5c8b3029895b6825696f6af29c239 +b75a5bb1e6345e6ee6c28117e73586c1a2214ae1be07e93fb0ff51e133fb65426fa843be0fb515c187064d0cc206a2fa926d3c902e907670048d931db4c1a449 +59d366ad93b65abe595f70a75bf03d616c2dd959fc7d4e6317cd99cbcec9c58b34766661c7d6766ca1a9c1b327531486c6f941c638c67cd22a7f75e2a37be0e8 +2db8df9f30254d30c1372581a1f51c983c80e4b71ccdd28dbf000000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468 +656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4 +350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d2624 +52282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe5141 +73d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c020000130000000000000000 +0000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000 +000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c0000000000000000000000000019 +0200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d001400060008000000210096b5ade296060000501b00001600000000 +000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b01000027 +00000000000000000000000000a00900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d0100009b0a00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; +\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; +\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; +\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 +4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000d07c +55b07785d101feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/ClassicShellLoc/English/ClassicShellReadme.rtf b/ClassicShellLoc/English/ClassicShellReadme.rtf new file mode 100644 index 0000000..ea68a8a --- /dev/null +++ b/ClassicShellLoc/English/ClassicShellReadme.rtf @@ -0,0 +1,472 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;} +{\f3\fbidi \froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f10\fbidi \fnil\fcharset2\fprq2{\*\panose 05000000000000000000}Wingdings;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;} +{\f36\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} +{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} +{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f59\fbidi \fmodern\fcharset238\fprq1 Courier New CE;}{\f60\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;} +{\f62\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f63\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f64\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f65\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);} +{\f66\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f67\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f379\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f380\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;} +{\f382\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f383\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f386\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f387\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);} +{\f399\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\f400\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\f402\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\f403\fbidi \froman\fcharset162\fprq2 Cambria Tur;} +{\f406\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\f407\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\f409\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f414\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\f415\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);} +{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f417\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;} +{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;} +{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} +{\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} +{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}} +{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0; +\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\caccentone\ctint255\cshade191\red54\green95\blue145;\caccentone\ctint255\cshade255\red79\green129\blue189; +\caccentone\ctint255\cshade127\red36\green63\blue96;\ctextone\ctint191\cshade255\red64\green64\blue64;\chyperlink\ctint255\cshade255\red0\green0\blue255;\cfollowedhyperlink\ctint255\cshade255\red128\green0\blue128; +\ctexttwo\ctint255\cshade191\red23\green54\blue93;\ctextone\ctint255\cshade255\red0\green0\blue0;\ctextone\ctint127\cshade255\red128\green128\blue128;\caccenttwo\ctint255\cshade255\red192\green80\blue77;\red0\green112\blue192;}{\*\defchp +\fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext0 \sqformat \spriority0 \styrsid7830857 Normal;}{\s1\ql \li0\ri0\sb480\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs28\alang1025 \ltrch\fcs0 +\b\fs28\cf17\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink15 \sqformat \spriority9 \styrsid7830857 heading 1;}{\s2\ql \li0\ri0\sb200\sl276\slmult1 +\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs26\alang1025 \ltrch\fcs0 \b\fs26\cf18\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink16 \sunhideused \sqformat \spriority9 \styrsid7830857 heading 2;}{\s3\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel2\adjustright\rin0\lin0\itap0 \rtlch\fcs1 +\ab\af0\afs22\alang1025 \ltrch\fcs0 \b\fs22\cf18\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink17 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid7830857 heading 3;}{ +\s4\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel3\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\ai\af0\afs22\alang1025 \ltrch\fcs0 +\b\i\fs22\cf18\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink18 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid7830857 heading 4;}{\s5\ql \li0\ri0\sb200\sl276\slmult1 +\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel4\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\cf19\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink19 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid7830857 heading 5;}{\s6\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel5\adjustright\rin0\lin0\itap0 \rtlch\fcs1 +\ai\af0\afs22\alang1025 \ltrch\fcs0 \i\fs22\cf19\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink20 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid7830857 heading 6;}{ +\s7\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel6\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ai\af0\afs22\alang1025 \ltrch\fcs0 +\i\fs22\cf20\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink21 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid7830857 heading 7;}{\s8\ql \li0\ri0\sb200\sl276\slmult1 +\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel7\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs20\alang1025 \ltrch\fcs0 \fs20\cf18\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink22 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid7830857 heading 8;}{\s9\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel8\adjustright\rin0\lin0\itap0 \rtlch\fcs1 +\ai\af0\afs20\alang1025 \ltrch\fcs0 \i\fs20\cf20\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink23 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid7830857 heading 9;}{\*\cs10 +\additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused +Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \ab\af0\afs28 \ltrch\fcs0 \b\fs28\cf17\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink1 \slocked \spriority9 \styrsid7830857 Heading 1 Char;}{\*\cs16 \additive \rtlch\fcs1 \ab\af0\afs26 \ltrch\fcs0 +\b\fs26\cf18\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink2 \slocked \spriority9 \styrsid7830857 Heading 2 Char;}{\*\cs17 \additive \rtlch\fcs1 \ab\af0 \ltrch\fcs0 \b\cf18\loch\f31502\hich\af31502\dbch\af31501 +\sbasedon10 \slink3 \slocked \spriority9 \styrsid7830857 Heading 3 Char;}{\*\cs18 \additive \rtlch\fcs1 \ab\ai\af0 \ltrch\fcs0 \b\i\cf18\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink4 \slocked \spriority9 \styrsid7830857 Heading 4 Char;}{\* +\cs19 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \cf19\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink5 \slocked \spriority9 \styrsid7830857 Heading 5 Char;}{\*\cs20 \additive \rtlch\fcs1 \ai\af0 \ltrch\fcs0 +\i\cf19\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink6 \slocked \spriority9 \styrsid7830857 Heading 6 Char;}{\*\cs21 \additive \rtlch\fcs1 \ai\af0 \ltrch\fcs0 \i\cf20\loch\f31502\hich\af31502\dbch\af31501 +\sbasedon10 \slink7 \slocked \spriority9 \styrsid7830857 Heading 7 Char;}{\*\cs22 \additive \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\cf18\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink8 \slocked \spriority9 \styrsid7830857 Heading 8 Char;}{\* +\cs23 \additive \rtlch\fcs1 \ai\af0\afs20 \ltrch\fcs0 \i\fs20\cf20\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink9 \slocked \spriority9 \styrsid7830857 Heading 9 Char;}{\*\cs24 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf21 +\sbasedon10 \sunhideused \styrsid16021474 Hyperlink;}{\*\cs25 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf22 \sbasedon10 \ssemihidden \sunhideused \styrsid16021474 FollowedHyperlink;}{ +\s26\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext26 \slink46 \sqformat \spriority1 \styrsid7830857 No Spacing;}{\s27\ql \li0\ri0\sa200\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs18\alang1025 \ltrch\fcs0 +\b\fs18\cf18\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \ssemihidden \sunhideused \sqformat \spriority35 \styrsid7830857 caption;}{\s28\ql \li0\ri0\sa300\widctlpar\brdrb +\brdrs\brdrw20\brsp80\brdrcf18 \wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\contextualspace \rtlch\fcs1 \af0\afs52\alang1025 \ltrch\fcs0 +\fs52\expnd1\expndtw5\cf23\lang1033\langfe1033\kerning28\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink29 \sqformat \spriority10 \styrsid7830857 Title;}{\*\cs29 \additive \rtlch\fcs1 \af0\afs52 \ltrch\fcs0 +\fs52\expnd1\expndtw5\cf23\kerning28\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink28 \slocked \spriority10 \styrsid7830857 Title Char;}{\s30\ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ilvl1\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ai\af0\afs24\alang1025 \ltrch\fcs0 \i\fs24\expnd3\expndtw15\cf18\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink31 \sqformat \spriority11 \styrsid7830857 Subtitle;}{\*\cs31 \additive \rtlch\fcs1 \ai\af0\afs24 \ltrch\fcs0 \i\fs24\expnd3\expndtw15\cf18\loch\f31502\hich\af31502\dbch\af31501 +\sbasedon10 \slink30 \slocked \spriority11 \styrsid7830857 Subtitle Char;}{\*\cs32 \additive \rtlch\fcs1 \ab\af0 \ltrch\fcs0 \b \sbasedon10 \sqformat \spriority22 \styrsid7830857 Strong;}{\*\cs33 \additive \rtlch\fcs1 \ai\af0 \ltrch\fcs0 \i +\sbasedon10 \sqformat \spriority20 \styrsid7830857 Emphasis;}{\s34\ql \li720\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin720\itap0\contextualspace \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext34 \sqformat \spriority34 \styrsid7830857 List Paragraph;}{\s35\ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ai\af0\afs22\alang1025 \ltrch\fcs0 \i\fs22\cf24\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink36 \sqformat \spriority29 \styrsid7830857 Quote;}{\*\cs36 \additive \rtlch\fcs1 \ai\af0 \ltrch\fcs0 \i\cf24 \sbasedon10 \slink35 \slocked \spriority29 \styrsid7830857 Quote Char;}{\s37\ql \li936\ri936\sb200\sa280\sl276\slmult1 +\widctlpar\brdrb\brdrs\brdrw10\brsp80\brdrcf18 \wrapdefault\aspalpha\aspnum\faauto\adjustright\rin936\lin936\itap0 \rtlch\fcs1 \ab\ai\af0\afs22\alang1025 \ltrch\fcs0 +\b\i\fs22\cf18\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink38 \sqformat \spriority30 \styrsid7830857 Intense Quote;}{\*\cs38 \additive \rtlch\fcs1 \ab\ai\af0 \ltrch\fcs0 \b\i\cf18 +\sbasedon10 \slink37 \slocked \spriority30 \styrsid7830857 Intense Quote Char;}{\*\cs39 \additive \rtlch\fcs1 \ai\af0 \ltrch\fcs0 \i\cf25 \sbasedon10 \sqformat \spriority19 \styrsid7830857 Subtle Emphasis;}{\*\cs40 \additive \rtlch\fcs1 \ab\ai\af0 +\ltrch\fcs0 \b\i\cf18 \sbasedon10 \sqformat \spriority21 \styrsid7830857 Intense Emphasis;}{\*\cs41 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \scaps\ul\cf26 \sbasedon10 \sqformat \spriority31 \styrsid7830857 Subtle Reference;}{\*\cs42 \additive \rtlch\fcs1 +\ab\af0 \ltrch\fcs0 \b\scaps\ul\expnd1\expndtw5\cf26 \sbasedon10 \sqformat \spriority32 \styrsid7830857 Intense Reference;}{\*\cs43 \additive \rtlch\fcs1 \ab\af0 \ltrch\fcs0 \b\scaps\expnd1\expndtw5 \sbasedon10 \sqformat \spriority33 \styrsid7830857 +Book Title;}{\s44\ql \li0\ri0\sb480\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs28\alang1025 \ltrch\fcs0 +\b\fs28\cf17\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon1 \snext0 \ssemihidden \sunhideused \sqformat \spriority39 \styrsid7830857 TOC Heading;}{ +\s45\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs22\alang1025 \ltrch\fcs0 \b\fs22\cf27\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\sbasedon26 \snext45 \slink47 \sqformat \spriority0 \styrsid3570194 Style1;}{\*\cs46 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \sbasedon10 \slink26 \slocked \spriority1 \styrsid3570194 No Spacing Char;}{\*\cs47 \additive \rtlch\fcs1 \ab\af0 \ltrch\fcs0 +\b\cf27 \sbasedon46 \slink45 \slocked \spriority0 \styrsid3570194 Style1 Char;}}{\*\listtable{\list\listtemplateid-2071026886\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext +\leveltemplateid1092763586\'01\u-3913 ?;}{\levelnumbers;}\loch\af3\hich\af3\dbch\af31505\fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693 +\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li2160\lin2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;} +\f3\fbias0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3600\lin3600 } +{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li4320\lin4320 }{\listlevel\levelnfc23\levelnfcn23 +\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0 +\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6480\lin6480 }{\listname ;}\listid314533848}{\list\listtemplateid-1743323628\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid2075014552\'01\u-3913 ?;}{\levelnumbers;}\loch\af3\hich\af3\dbch\af31505\fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 +\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0 +{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li2160\lin2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689 +\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 +\fi-360\li3600\lin3600 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li4320\lin4320 }{\listlevel +\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc23\levelnfcn23\leveljc0 +\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 +\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6480\lin6480 }{\listname ;}\listid467403189}{\list\listtemplateid-342452760\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0 +\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid1092763586\'01\u-3913 ?;}{\levelnumbers;}\loch\af3\hich\af3\dbch\af31505\fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0 +\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative +\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li2160\lin2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0 +{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691 +\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 +\fi-360\li4320\lin4320 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li5040\lin5040 }{\listlevel +\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0 +\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6480\lin6480 }{\listname ;}\listid547912835}{\list\listtemplateid1549811042\listhybrid{\listlevel +\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67698705\'02\'00);}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc4\levelnfcn4 +\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698713\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2 +\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698715\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698703\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1 +\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698713\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative +\levelspace0\levelindent0{\leveltext\leveltemplateid67698715\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0 +\levelindent0{\leveltext\leveltemplateid67698703\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0 +{\leveltext\leveltemplateid67698713\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698715\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li6480\lin6480 }{\listname ;}\listid777985235}{\list\listtemplateid-1690821698\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67698705\'02\'00);}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative +\levelspace0\levelindent0{\leveltext\leveltemplateid67698713\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0 +\levelindent0{\leveltext\leveltemplateid67698715\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0 +{\leveltext\leveltemplateid67698703\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698713\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698715\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698703\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698713\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698715\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li6480\lin6480 }{\listname ;}\listid904804732}{\list\listtemplateid-1390631818\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67698705\'02\'00);}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative +\levelspace0\levelindent0{\leveltext\leveltemplateid67698713\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0 +\levelindent0{\leveltext\leveltemplateid67698715\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0 +{\leveltext\leveltemplateid67698703\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698713\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698715\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698703\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698713\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698715\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li6480\lin6480 }{\listname ;}\listid1127434641}{\list\listtemplateid407811540\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li1080\lin1080 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360 +\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1800\lin1800 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext +\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li2520\lin2520 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698689 +\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li3240\lin3240 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 +\fi-360\li3960\lin3960 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li4680\lin4680 } +{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li5400\lin5400 }{\listlevel\levelnfc23\levelnfcn23 +\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li6120\lin6120 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6840\lin6840 }{\listname ;}\listid1176921641}{\list\listtemplateid854381262\listhybrid{\listlevel\levelnfc23 +\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360 +\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li2160\lin2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext +\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698691 +\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;} +\f10\fbias0 \fi-360\li4320\lin4320 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 +\fi-360\li5040\lin5040 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5760\lin5760 }{\listlevel +\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6480\lin6480 }{\listname ;}\listid1451244311} +{\list\listtemplateid9204898\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\lin720 } +{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc23\levelnfcn23 +\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li2160\lin2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative +\levelspace360\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext +\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li4320\lin4320 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698689 +\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 +\fi-360\li5760\lin5760 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6480\lin6480 } +{\listname ;}\listid1700662769}}{\*\listoverridetable{\listoverride\listid1176921641\listoverridecount0\ls1}{\listoverride\listid467403189\listoverridecount0\ls2}{\listoverride\listid547912835\listoverridecount0\ls3}{\listoverride\listid314533848 +\listoverridecount0\ls4}{\listoverride\listid904804732\listoverridecount0\ls5}{\listoverride\listid777985235\listoverridecount0\ls6}{\listoverride\listid1127434641\listoverridecount0\ls7}{\listoverride\listid1700662769\listoverridecount0\ls8} +{\listoverride\listid1451244311\listoverridecount0\ls9}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid154355\rsid154821\rsid202536\rsid293311\rsid329139\rsid468832\rsid552468\rsid664385\rsid860525\rsid943367\rsid1054415\rsid1071954 +\rsid1128667\rsid1146520\rsid1248335\rsid1329689\rsid1405400\rsid1461965\rsid1462809\rsid1528801\rsid1721007\rsid1770967\rsid1778397\rsid1787318\rsid1863227\rsid1910458\rsid2052359\rsid2114151\rsid2230259\rsid2297266\rsid2631124\rsid2756235\rsid2850720 +\rsid2912007\rsid3164638\rsid3230931\rsid3298972\rsid3424468\rsid3547401\rsid3570194\rsid3687072\rsid3761032\rsid3954017\rsid3997776\rsid4077468\rsid4081496\rsid4219695\rsid4481191\rsid4485749\rsid4674537\rsid4806883\rsid4863662\rsid4869559\rsid4880870 +\rsid4933774\rsid5124543\rsid5256481\rsid5314108\rsid5456447\rsid5651362\rsid5661944\rsid5726365\rsid5773707\rsid5794165\rsid5838933\rsid5857668\rsid6104256\rsid6119665\rsid6297085\rsid6299574\rsid6308193\rsid6436109\rsid6556029\rsid6582832\rsid6645442 +\rsid6646970\rsid6702231\rsid6705495\rsid6763040\rsid6820791\rsid6823287\rsid6832096\rsid6902221\rsid6905770\rsid6950643\rsid7160684\rsid7350701\rsid7675960\rsid7687946\rsid7697173\rsid7830857\rsid7954001\rsid8004164\rsid8063591\rsid8222428\rsid8267417 +\rsid8355555\rsid8471953\rsid8675000\rsid8784967\rsid8803011\rsid8862529\rsid8874896\rsid9113097\rsid9116456\rsid9192247\rsid9245690\rsid9441753\rsid9530647\rsid9585560\rsid9776440\rsid9831548\rsid9836926\rsid9924894\rsid9981332\rsid9986631\rsid10041644 +\rsid10158802\rsid10241328\rsid10355326\rsid10424443\rsid10450127\rsid10556522\rsid10627785\rsid10643016\rsid10688625\rsid10754517\rsid10829429\rsid10842653\rsid10906421\rsid11016316\rsid11146303\rsid11157361\rsid11163947\rsid11170098\rsid11172209 +\rsid11607477\rsid11611672\rsid12003133\rsid12009041\rsid12076428\rsid12079691\rsid12201409\rsid12209379\rsid12546021\rsid12605676\rsid12919976\rsid13000728\rsid13110719\rsid13245866\rsid13269024\rsid13376205\rsid13448550\rsid13461879\rsid13505068 +\rsid13522787\rsid13527300\rsid13586482\rsid13596911\rsid13699501\rsid13959456\rsid13980802\rsid14036376\rsid14159676\rsid14175596\rsid14176797\rsid14226910\rsid14433764\rsid14440559\rsid14568210\rsid14684487\rsid14751137\rsid14829662\rsid14902226 +\rsid15015205\rsid15038196\rsid15225771\rsid15410331\rsid15561804\rsid15884861\rsid15888529\rsid16021474\rsid16142713\rsid16142752\rsid16147999\rsid16215018\rsid16394437\rsid16401272\rsid16404848\rsid16462041\rsid16651668\rsid16728702\rsid16731337} +{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Ivo Beltchev}{\operator Ivo Be}{\creatim\yr2013\mo7\dy13\hr16\min8}{\revtim\yr2017\mo5\dy27\hr15\min49} +{\version34}{\edmins10}{\nofpages3}{\nofwords785}{\nofchars4477}{\nofcharsws5252}{\vern49167}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect +\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701 +\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot4077468 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 +\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 +\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\s28\qc \li0\ri0\sa300\widctlpar\brdrb\brdrs\brdrw20\brsp80\brdrcf18 \wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3570194\contextualspace \rtlch\fcs1 \af0\afs52\alang1025 \ltrch\fcs0 +\fs52\expnd1\expndtw5\cf23\lang1033\langfe1033\kerning28\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31502\dbch\af31501\loch\f31502 Classic Shell +\par }\pard\plain \ltrpar\s30\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ilvl1\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \ai\af0\afs24\alang1025 \ltrch\fcs0 +\i\fs24\expnd3\expndtw15\cf18\lang1033\langfe1033\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid3570194\charrsid9981332 \hich\af31502\dbch\af31501\loch\f31502 Version }{\rtlch\fcs1 \af0 +\ltrch\fcs0 \b\insrsid8675000 \hich\af31502\dbch\af31501\loch\f31502 4.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid15225771 \hich\af31502\dbch\af31501\loch\f31502 3}{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid8675000 .}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\b\insrsid13110719 \hich\af31502\dbch\af31501\loch\f31502 1}{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid3570194 \hich\af31502\dbch\af31501\loch\f31502 \hich\f31502 \endash }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid15225771 +\hich\af31502\dbch\af31501\loch\f31502 general release}{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid3570194\charrsid9981332 +\par }\pard\plain \ltrpar\s26\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par }{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 Thank you for installing }{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \b\cf27\insrsid3570194\charrsid16021474 \hich\af31506\dbch\af31505\loch\f31506 Classic Shell}{\rtlch\fcs1 +\ab\af0 \ltrch\fcs0 \b\cf27\insrsid3570194 \loch\af31506\dbch\af31505\hich\f31506 \'99}{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 . It }{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \insrsid3570194\charrsid13596911 +\hich\af31506\dbch\af31505\loch\f31506 adds some missing features to Windows 7}{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \insrsid9776440 \hich\af31506\dbch\af31505\loch\f31506 , Windows 8, Windows 8.1}{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 +\insrsid3570194\charrsid13596911 \hich\af31506\dbch\af31505\loch\f31506 and }{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 Windows }{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \insrsid16404848 +\hich\af31506\dbch\af31505\loch\f31506 10}{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 - }{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \insrsid3570194\charrsid13596911 \hich\af31506\dbch\af31505\loch\f31506 +like a classic start menu}{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 , start button}{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \insrsid3570194\charrsid13596911 \hich\af31506\dbch\af31505\loch\f31506 , }{\rtlch\fcs1 +\ab\af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 a toolbar for Windows}{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \insrsid3570194\charrsid13596911 \hich\af31506\dbch\af31505\loch\f31506 Explorer and others.}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid3570194 +\par +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid10754517 \hich\af31506\dbch\af31505\loch\f31506 The latest version can be found on }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 the Classic Shell website}{ +\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid10754517 \hich\af31506\dbch\af31505\loch\f31506 : +\par }{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 HYPERLINK "}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid12546021 \hich\af31506\dbch\af31505\loch\f31506 +http://www.classicshell.net/}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 " }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5200000068007400740070003a002f002f007700770077002e0063006c00610073007300690063007300680065006c006c002e006e00650074002f000000795881f43b1d7f48af2c825dc485276300000000a5ab0000 +00740061006c0069006300000000000000006a0000000000000000690000f900000000000000010000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs24\ul\cf21\insrsid3570194\charrsid6104256 \hich\af31506\dbch\af31505\loch\f31506 http://www.classicshell.net/}}}\sectd \ltrsect +\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid10754517 \hich\af31506\dbch\af31505\loch\f31506 For answers to frequently asked questions look here: +\par }{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 HYPERLINK "}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid12546021 \hich\af31506\dbch\af31505\loch\f31506 http://www.classicshell.}{ +\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 net/faq/" }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5a00000068007400740070003a002f002f007700770077002e0063006c00610073007300690063007300680065006c006c002e006e00650074002f006600610071002f000000795881f43b1d7f48af2c825dc4852763 +00000000a5ab000000630069000000640073007200c70000006e00540055006e0074006500000000000000000000000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs24\ul\cf21\insrsid3570194\charrsid6104256 \hich\af31506\dbch\af31505\loch\f31506 +http://www.classicshell.net/faq/}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Or use the discussion forums to get help:}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid10754517 +\par }{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 HYPERLINK "}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid12546021 \hich\af31506\dbch\af31505\loch\f31506 http://www.classicsh}{ +\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 ell.net/forum/viewforum.php?f=6" }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b8000000068007400740070003a002f002f007700770077002e0063006c00610073007300690063007300680065006c006c002e006e00650074002f0066006f00720075006d002f00760069006500770066006f007200 +75006d002e007000680070003f0066003d0036000000795881f43b1d7f48af2c825dc485276300000000a5ab000001000070010000000000009001000000006900610020004d0000000000000000000600000000004300}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 +\cs24\ul\cf21\insrsid3570194\charrsid6104256 \hich\af31506\dbch\af31505\loch\f31506 http://www.classicshell.net/forum/viewforum.php?f=6}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid10754517 \hich\af31506\dbch\af31505\loch\f31506 Report problems in the Classic Shell }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 development forums}{ +\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid10754517 \hich\af31506\dbch\af31505\loch\f31506 :}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par }{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 HYPERLINK "}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid12546021 +\hich\af31506\dbch\af31505\loch\f31506 http://www.classicshell.net/forum/viewforum.php?f=11}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 " }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b8200000068007400740070003a002f002f007700770077002e0063006c00610073007300690063007300680065006c006c002e006e00650074002f0066006f00720075006d002f00760069006500770066006f007200 +75006d002e007000680070003f0066003d00310031000000795881f43b1d7f48af2c825dc485276300000000a5ab0000006d00000090006100c40075006c0061000002000018000000000065006b0000000000007200000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 +\cs24\ul\cf21\insrsid3570194\charrsid6104256 \hich\af31506\dbch\af31505\loch\f31506 http://www.classicshell.net/forum/viewforum.php\hich\af31506\dbch\af31505\loch\f31506 ?f=11}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid3570194 +\par +\par }\pard\plain \ltrpar\s1\ql \li0\ri0\sb480\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \ab\af0\afs28\alang1025 \ltrch\fcs0 +\b\fs28\cf17\lang1033\langfe1033\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31502\dbch\af31501\loch\f31502 Classic Start Menu +\par }\pard\plain \ltrpar\s26\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par }{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \b\cf27\insrsid3570194\charrsid16021474 \hich\af31506\dbch\af31505\loch\f31506 Classic Start Menu}{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \b\insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 is a flexible start menu that can mimic the menu behavior of Windows 2000, XP and Windows 7. It has a variety of advanced features: +\par +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}\pard \ltrpar +\s26\ql \fi-360\li720\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls3\adjustright\rin0\lin720\itap0\pararsid3570194 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Choose between \'93\loch\f31506 +\hich\f31506 Classic\'94\loch\f31506 \hich\f31506 and \'93\loch\f31506 \hich\f31506 Windows 7\'94\loch\f31506 styles +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 Drag and drop to let y\hich\af31506\dbch\af31505\loch\f31506 +ou organize your applications +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 Options to show Favorites, expand Control Panel, etc +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 Shows recently used documents. The number of documents to display is customizable + +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 Translated in 35 languages, including Right-to-left support for Arabic and Hebrew + +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 D\hich\af31506\dbch\af31505\loch\f31506 +oes not disable the original start menu in Windows. You can access it by Shift+Click on the start button +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 Right-click on an item in the menu to delete, rename, sort, or perform other tasks + +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194\charrsid9113097 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid9113097 \hich\af31506\dbch\af31505\loch\f31506 +The search box helps you find your programs }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 and files }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid9113097 \hich\af31506\dbch\af31505\loch\f31506 +without getting in the way of your keyboard shortcuts}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194\charrsid9986631 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid9986631 \hich\af31506\dbch\af31505\loch\f31506 +Supports jumplists for easy access to recent documents and common tasks}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194\charrsid4077468 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid4077468 \hich\af31506\dbch\af31505\loch\f31506 +Available for 32 and 64-bit operating systems}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194\charrsid11163947 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid11163947 \hich\af31506\dbch\af31505\loch\f31506 +Has support for skins, including additional 3rd party skins}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 . Make your own! +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 Fully customizable in both looks and functionality +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 Support for Microsoft\hich\f31506 \rquote \loch\f31506 s Active Accessibility + +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Converts the \'93\loch\f31506 \hich\f31506 All Programs\'94 +\loch\f31506 button in the Windows menu into a cascading menu +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 Implements a customizabl}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16215018 +\hich\af31506\dbch\af31505\loch\f31506 e start button}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194\charrsid9986631 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid9986631 \hich\af31506\dbch\af31505\loch\f31506 +Can show, search and launch Windows \hich\af31506\dbch\af31505\loch\f31506 Store apps (Windows 8)}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid4077468 +\par }\pard\plain \ltrpar\s1\ql \li0\ri0\sb480\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \ab\af0\afs28\alang1025 \ltrch\fcs0 +\b\fs28\cf17\lang1033\langfe1033\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31502\dbch\af31501\loch\f31502 Classic Explorer +\par }\pard\plain \ltrpar\s26\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par }{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \b\cf27\insrsid3570194\charrsid16021474 \hich\af31506\dbch\af31505\loch\f31506 Classic Explorer}{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \b\insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 is a plugin for Windows Explorer that: +\par +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194\charrsid8267417 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}\pard \ltrpar +\s26\ql \fi-360\li720\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls4\adjustright\rin0\lin720\itap0\pararsid3570194 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid8267417 \hich\af31506\dbch\af31505\loch\f31506 +Adds a toolbar to Explorer for some common operations (Go to parent folder, Cut, Copy, Paste, Delete}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 , Properties, Email}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid3570194\charrsid8267417 \hich\af31506\dbch\af31505\loch\f31506 )}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 . }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid7954001 +\hich\af31506\dbch\af31505\loch\f31506 The toolbar is fully customizable}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194\charrsid1787318 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid1787318 \hich\af31506\dbch\af31505\loch\f31506 +Replaces the copy UI in Windows}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid1787318 \hich\af31506\dbch\af31505\loch\f31506 7 with the more user-friendly }{ +\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \loch\af31506\dbch\af31505\hich\f31506 \'93\loch\f31506 \hich\f31506 classic\'94\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid1787318 \hich\af31506\dbch\af31505\loch\f31506 version }{ +\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 similar to}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid1787318 \hich\af31506\dbch\af31505\loch\f31506 Windows XP}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 + +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194\charrsid1787318 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid1787318 \hich\af31506\dbch\af31505\loch\f31506 +Handles Alt+Enter in the folder panel of Windows Explorer and shows the properties of the selected folder}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 Has options for customizing the folder pan\hich\af31506\dbch\af31505\loch\f31506 +el to look more like the Windows XP version}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid11607477 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 +or to not fade the expand buttons +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 +Can show the free disk space and the total size of the selected files in the status bar +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194\charrsid12009041 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid12009041 \hich\af31506\dbch\af31505\loch\f31506 +Can disable the breadcrumbs in the address bar}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 Fixes a long list of features that are broken in Windows 7 \hich\f31506 \endash +\loch\f31506 missing icon overlay for shared folders, the jumping folders in the navigation pane, missing sorting headers in list view, and more +\par }\pard\plain \ltrpar\s1\ql \li0\ri0\sb480\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \ab\af0\afs28\alang1025 \ltrch\fcs0 +\b\fs28\cf17\lang1033\langfe1033\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31502\dbch\af31501\loch\f31502 Classic IE +\par }\pard\plain \ltrpar\s26\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par }\pard\plain \ltrpar\s45\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \ab\af0\afs22\alang1025 \ltrch\fcs0 +\b\fs22\cf27\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid16021474 \hich\af31506\dbch\af31505\loch\f31506 Classic }{\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 IE is a plugin for Internet Explorer 9 and \hich\af31506\dbch\af31505\loch\f31506 later versions that: +\par }\pard\plain \ltrpar\s26\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}\pard \ltrpar +\s26\ql \fi-360\li720\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls9\adjustright\rin0\lin720\itap0\pararsid3570194 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 +Adds a caption to the title bar so you can see the full title of the page +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 Shows the security zone in the status bar +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f3\fs22\insrsid3570194 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af31506\dbch\af31505\loch\f31506 Shows the loading progress in the status bar +\par }\pard\plain \ltrpar\s1\ql \li0\ri0\sb480\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \ab\af0\afs28\alang1025 \ltrch\fcs0 +\b\fs28\cf17\lang1033\langfe1033\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31502\dbch\af31501\loch\f31502 Installation instructions +\par }\pard\plain \ltrpar\s26\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par \hich\af31506\dbch\af31505\loch\f31506 The toolbar for Windows Explorer may not show up automatically after installation. You have to do a few things before you can use it. +\par +\par }{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \cs47\b\cf27\insrsid3570194\charrsid14175596 \hich\af31506\dbch\af31505\loch\f31506 Windows 7:}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 + Press Alt+V to open the View menu. Open the \'93\loch\f31506 \hich\f31506 Toolbars\'94\loch\f31506 \hich\f31506 sub-menu and select \'93\loch\f31506 \hich\f31506 Classic Exlporer Bar\'94\loch\f31506 . Keep in min\hich\af31506\dbch\af31505\loch\f31506 +d that the menu will always be displayed as long as the toolbar is visible. +\par +\par }{\rtlch\fcs1 \ab\af0 \ltrch\fcs0 \cs47\b\cf27\insrsid3570194\charrsid14175596 \hich\af31506\dbch\af31505\loch\f31506 Windows 8:}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 + Press Alt+V to open the View ribbon. Click on the down arrow in the \'93\loch\f31506 \hich\f31506 Options\'94\loch\f31506 \hich\f31506 section. Select \'93\loch\f31506 \hich\f31506 Classic Explorer Bar\'94 +\par +\par \hich\af31506\dbch\af31505\loch\f31506 If these steps don\hich\f31506 \rquote \loch\f31506 t work, it may be possible that\hich\af31506\dbch\af31505\loch\f31506 the Explorer extensions have been disabled. }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16728702 +\hich\af31506\dbch\af31505\loch\f31506 Check the following, then try to show the toolbar again}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 : +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid16728702 \hich\af31506\dbch\af31505\loch\f31506 1)\tab}}\pard \ltrpar +\s26\ql \fi-360\li720\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls5\adjustright\rin0\lin720\itap0\pararsid3570194 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16728702 \hich\af31506\dbch\af31505\loch\f31506 Open Internet Explorer and go }{\rtlch\fcs1 +\af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 to Tools -> Manage add-ons. Locate the add}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16728702 -}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 +\hich\f31506 ons \'93\loch\f31506 \hich\f31506 Classic Explorer Bar\'94\loch\f31506 \hich\f31506 and \'93\loch\f31506 \hich\f31506 ExplorerBHO Class\'94\loch\f31506 and make sure they are enab\hich\af31506\dbch\af31505\loch\f31506 led. +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid16728702 \hich\af31506\dbch\af31505\loch\f31506 2)\tab}}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16728702 \hich\af31506\dbch\af31505\loch\f31506 M}{\rtlch\fcs1 \af0 +\ltrch\fcs0 \insrsid3570194\charrsid10450127 \hich\af31506\dbch\af31505\loch\f31506 aybe the browser extensions are disabled on your system. This is usually the default for }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\hich\af31506\dbch\af31505\loch\f31506 Windows Server}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194\charrsid10450127 \hich\af31506\dbch\af31505\loch\f31506 +. Open the "Internet Options", go to the "Advanced" tab, and check the option "Enable third-party browser extensions".}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par }\pard \ltrpar\s26\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3570194 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2912007 \hich\af31506\dbch\af31505\loch\f31506 On Windows 7 you have to\hich\af31506\dbch\af31505\loch\f31506 turn on the status bar from the View menu if you want to see the file sizes. +\par \hich\af31506\dbch\af31505\loch\f31506 On Windows 8 the Classic Explorer status bar is different from the one in Explorer. You can show/hide the first one from the Classic Explorer settings dialog and show/hide the se +\hich\af31506\dbch\af31505\loch\f31506 cond one from Explorer\hich\f31506 \rquote \loch\f31506 s folder options dialog. +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 The caption in Internet Explorer may not show up automatically after installation. You may get a prompt to enable the ClassicIEBHO plugin. If you get the prompt, select \'93\loch\f31506 \hich\f31506 +Enable\'94\loch\f31506 . If you don\hich\f31506 \rquote \loch\f31506 t get a prompt, g\hich\af31506\dbch\af31505\loch\f31506 o to Tools -> Manage add}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16728702 -}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\hich\af31506\dbch\af31505\loch\f31506 ons and make sure the add}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16728702 -}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 on \'93\loch\f31506 \hich\f31506 +ClassicIEBHO\'94\loch\f31506 is enabled. After that restart Internet Explorer. +\par }\pard\plain \ltrpar\s1\ql \li0\ri0\sb480\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \ab\af0\afs28\alang1025 \ltrch\fcs0 +\b\fs28\cf17\lang1033\langfe1033\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31502\dbch\af31501\loch\f31502 Uninstallation +\par }\pard\plain \ltrpar\s26\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par \hich\af31506\dbch\af31505\loch\f31506 To uninstall }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\cf27\insrsid3570194\charrsid4869559 \hich\af31506\dbch\af31505\loch\f31506 Classic Shell}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\hich\af31506\dbch\af31505\loch\f31506 follow these steps: +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 1)\tab}}\pard \ltrpar +\s26\ql \fi-360\li720\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls7\adjustright\rin0\lin720\itap0\pararsid3570194 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 Open }{\rtlch\fcs1 \af0 \ltrch\fcs0 +\b\insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 Control Panel -> }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid3570194\charrsid4869559 \hich\af31506\dbch\af31505\loch\f31506 Programs and Features}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\hich\af31506\dbch\af31505\loch\f31506 and double-click on }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\insrsid3570194\charrsid4869559 \hich\af31506\dbch\af31505\loch\f31506 Classic\hich\af31506\dbch\af31505\loch\f31506 Shell}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 . Then follow the instructions. You may have to restart Windows to complete the process. +\par {\listtext\pard\plain\ltrpar \s26 \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid3570194 \hich\af31506\dbch\af31505\loch\f31506 2)\tab}\hich\af31506\dbch\af31505\loch\f31506 +If you installed any additional skins for the start menu you will have to delete them manually +\par }\pard \ltrpar\s26\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3570194 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3570194 +\par }\pard\plain \ltrpar\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3570194 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2631124\charrsid3570194 +\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a +9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad +5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 +b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 +0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 +a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f +c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 +0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 +a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 +6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b +4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b +4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210096b5ade296060000501b0000160000007468656d652f7468656d652f +7468656d65312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87 +615b8116d8a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad +79482a9c0498f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b +5d8a314d3c94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab +999fb7b4717509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9 +699640f6719e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd586 +8b37a088d1e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d6 +0cf03ac1a5193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f +9e7ef3f2d117d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be +15c308d3f28acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a9979 +3849c26ae66252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d +32a423279a668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2a +f074481847bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86 +e877f0034e16bafb0e258ebb4faf06b769e888340b103d3311da9750aa9d0a1cd3e4efca31a3508f6d0c5c5c398602f8e2ebc71591f5b616e24dd893aa3261fb +44f95d843b5974bb5c04f4edafb95b7892ec1108f3f98de75dc97d5772bdff7cc95d94cf672db4b3da0a6557f70db629362d72bcb0431e53c6066acac80d699a +6409fb44d08741bdce9c0e4971624a2378cceaba830b05366b90e0ea23aaa241845368b0eb9e2612ca8c742851ca251ceccc70256d8d87265dd96361531f186c +3d9058edf2c00eafe8e1fc5c509031bb4d680e9f39a3154de0accc56ae644441edd76156d7429d995bdd88664a9dc3ad50197c38af1a0c16d684060441db0256 +5e85f3b9660d0713cc48a0ed6ef7dedc2dc60b17e92219e180643ed27acffba86e9c94c78ab90980d8a9f0913ee49d62b512b79626fb06dccee2a432bbc60276 +b9f7dec44b7904cfbca4f3f6443ab2a49c9c2c41476dafd55c6e7ac8c769db1bc399161ee314bc2e75cf8759081743be1236ec4f4d6693e5336fb672c5dc24a8 +c33585b5fb9cc24e1d4885545b58463634cc5416022cd19cacfccb4d30eb45296023fd35a458598360f8d7a4003bbaae25e331f155d9d9a5116d3bfb9a95523e +51440ca2e0088dd844ec6370bf0e55d027a012ae264c45d02f708fa6ad6da6dce29c255df9f6cae0ec38666984b372ab5334cf640b37795cc860de4ae2816e95 +b21be5ceaf8a49f90b52a51cc6ff3355f47e0237052b81f6800fd7b802239daf6d8f0b1571a8426944fdbe80c6c1d40e8816b88b8569082ab84c36ff0539d4ff +6dce591a26ade1c0a7f669880485fd484582903d284b26fa4e2156cff62e4b9265844c4495c495a9157b440e091bea1ab8aaf7760f4510eaa69a6465c0e04ec6 +9ffb9e65d028d44d4e39df9c1a52ecbd3607fee9cec7263328e5d661d3d0e4f62f44acd855ed7ab33cdf7bcb8ae889599bd5c8b3029895b6825696f6af29c239 +b75a5bb1e6345e6ee6c28117e73586c1a2214ae1be07e93fb0ff51e133fb65426fa843be0fb515c187064d0cc206a2fa926d3c902e907670048d931db4c1a449 +59d366ad93b65abe595f70a75bf03d616c2dd959fc7d4e6317cd99cbcec9c58b34766661c7d6766ca1a9c1b327531486c6f941c638c67cd22a7f75e2a37be0e8 +2db8df9f30254d30c1372581a1f51c983c80e4b71ccdd28dbf000000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468 +656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4 +350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d2624 +52282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe5141 +73d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c020000130000000000000000 +0000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000 +000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c0000000000000000000000000019 +0200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d001400060008000000210096b5ade296060000501b00001600000000 +000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b01000027 +00000000000000000000000000a00900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d0100009b0a00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; +\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; +\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; +\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 +4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e50000000000000000000000009015 +6c893bd7d201feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/ClassicShellLoc/English/ClassicShellTOC.hhc b/ClassicShellLoc/English/ClassicShellTOC.hhc new file mode 100644 index 0000000..1727866 --- /dev/null +++ b/ClassicShellLoc/English/ClassicShellTOC.hhc @@ -0,0 +1,138 @@ + + + + + + + + + +
    +
  • + + + + +
  • + + + + +
      +
    • + + + +
    • + + + +
    • + + + + +
    • + + + + +
    • + + + +
    • + + + +
    • + + + +
    • + + + +
    • + + + +
    • + + + +
    +
  • + + + + +
      +
    • + + + +
    • + + + +
    • + + + +
    • + + + +
    • + + + +
    • + + + +
    • + + + +
    • + + + +
    • + + + +
    +
  • + + + + +
      +
    • + + + +
    • + + + +
    • + + + +
    +
  • + + + + +
  • + + + + +
+ diff --git a/ClassicShellLoc/English/ClassicShellText-en-US.wxl b/ClassicShellLoc/English/ClassicShellText-en-US.wxl new file mode 100644 index 0000000..23e1c13 --- /dev/null +++ b/ClassicShellLoc/English/ClassicShellText-en-US.wxl @@ -0,0 +1,33 @@ + + + This installer is only for 32-bit version of Windows. For 64-bit Windows you need to run ClassicShellSetup64. + Classic Shell requires Windows 7 or above. + A newer version of [ProductName] is already installed. The setup will now exit. + Classic Explorer + Classic Explorer adds a toolbar to Windows Explorer, replaces the copy UI and fixes some usability problems + Classic Start Menu + Classic Start Menu is a highly customizable replacement for the Windows start menu + Classic IE + Classic IE lets you customize the title bar and the status bar of Internet Explorer + Classic Shell Update + Classic Shell Update checks periodically for new versions + View the Classic Shell documentation + View the Classic Shell introduction + Edit the settings of Classic Explorer + Edit the settings of the classic start menu + Edit the settings of the Internet Explorer title bar and status bar + Edit the settings for Classic Shell's new version check + Create a start menu folder + Classic Shell website + Donate to Classic Shell + Visit us on Facebook + View Readme file + Classic Shell Help + Classic Shell Readme + Classic Shell Update + Classic Explorer Settings + Classic Start Menu Settings + Classic IE Settings + Open the Start screen + Classic Shell is a collection of usability enhancements for Windows + diff --git a/ClassicShellLoc/English/ClassicStartMenu.html b/ClassicShellLoc/English/ClassicStartMenu.html new file mode 100644 index 0000000..7c1fe39 --- /dev/null +++ b/ClassicShellLoc/English/ClassicStartMenu.html @@ -0,0 +1,349 @@ + + + + + + + + + + + + Classic Start Menu + +

Classic Shell website  +Classic Start Menu


+Classic Start Menu
+is a flexible start menu that can mimic the menu behavior of Windows +2000, XP and Windows 7. It has a variety of advanced features: +
    + +
  • Choose between “Classic” and “Windows 7” styles
    +
  • +
  • Drag and drop to let you organize your applications
  • + +
  • Options to show Favorites, expand Control Panel, etc
  • +
  • Shows recently used documents. The number of documents to display +is customizable
  • +
  • Translated in 35 languages, including Right-to-left support for +Arabic and Hebrew
  • +
  • Does not disable the original start menu in Windows. You can +access it by Shift+Click on the start button
  • +
  • Right-click on an item in the menu to delete, rename, sort, or +perform other tasks
  • +
  • The search box helps you find your programs and files without getting in the way of your keyboard shortcuts
  • +
  • Supports jumplists for easy access to recent documents and common tasks
  • +
  • Available for 32 and 64-bit operating systems
  • +
  • Has support for skins, including additional 3rd party skins. Make your own!
  • +
  • Fully customizable in both looks and functionality
  • +
  • Support for Microsoft’s Active Accessibility
  • +
  • Converts the “All Programs” button in the Windows menu into a cascading menu
  • +
  • Implements a customizable start button
    +
  • +
  • Can show, search and launch Windows Store apps (Windows 8)
  • + + + + +
  • And last but not least – it's FREE!
  • +

+

Styles

+The start menu offers 3 styles to choose from.
+

1) Single-column classic style

+
+This style is similar to the menu found in Windows 2000. It has one +column in the main menu with vertical text on the side. you can +customize the order of items, icons and text.
+ +Programs, jumplists and search results show as cascading sub-menus.
+ +
+

2) Two-column classic style

+
+This style is similar to the Windows XP menu. There are two columns +where you can arrange your menu items. Customize the order, icons and +text.
+Programs, jumplists and search results show as cascading sub-menus.
+
+

3) Windows 7 style
+

+
+This style is similar to the Windows Vista and Windows 7 menu. The +items in the first column are pre-defined to pinned and recent +programs, all programs list and search box. The items in the second +column are fully customizable.
+The jumplists and search results show inside the main menu. The +programs can be inside the main menu or open as a cascading sub-menu.
+This style offers less customizing options than the classic styles, but +has look and feel more familiar to people used to Windows 7.
+
+
+

Operation

+If you have used the start menu in older versions of Windows you’ll +feel right at home:
+ + + +

+Press the Windows key or click on the orb in the corner of the +screen to open the start menu.

+

+Hold down Shift while clicking on the orb to access the operating +system's own +start menu. +

+

+Click on an item to execute it. +

+

+Drag a program to change the order of the programs in a menu, or to +move it to another folder. +

+

+Right-click on an item to rename it, delete it, explore it, sort the +menu, or perform other tasks.

+

+Right-click on the orb to edit the settings for the start menu, to view this help file, or to +stop the start menu.
+

+


+ +

+ +

+Settings

Right-click on the start button to access the settings:
+
+
+You can choose from seeing only the basic settings, or all available +settings. Hover over each setting to see a description of what it's for. Type in the search box to find a setting by name.
+ +Every setting has a default value. The default value can be constant, +or it may depend on the current system settings. Once you edit a +setting it becomes "modified" and is shown in bold. To revert to the +default value, right-click on the setting.
+
+ +You can save the settings to an XML file, and later load them back. +Press the Backup button to access these functions. From there you can +also reset all settings to their default value.
+ + +
+ +Most settings will be changed immediately as you edit them. For example +you can edit the start menu, then while the Settings dialog is open, +access the start menu to see the changes. Small number of settings will +require you to exit the start menu before you can see the change.
+ +
+ + +Note: All Settings windows are resizable. Resize them and place them where you want them to be. They will remember the new position.
+ + +
+Click on the Customize Start Menu tab to customize the menu items. Depending on the style you will see different UI.
+
+For classic styles you can customize both columns of the start menu and +create sub-menus. The left column shows the current items in the menu +and the right column shows the available menu items. Drag from the +right to the left to add items to the menu.
+
+
+For the Windows 7 style you can only edit the items for the second column and there are no sub-menus.
+
+

+Double-click on the icon to edit the item properties:
+
+Here you can select a command for the item, its text, icon and other attributes. Press the Restore Defaults button to get the default text and icon for the chosen command.
+
+The command can be:
+ +
    +
  • one of the predefined commands - from the dropdown
  • custom executable string +- this can be a name of a program and its arguments, or even a URL +(like http://www.google.com). Environment variables like %SystemRoot% are supported
  • left blank - then if the link attribute is used, it will act as a command
    +
  • +
+The link can be a path to a file or a folder. If it is a file, that +file will be executed. If it is a folder, that folder will be opened as +a sub-menu. Some menu items (like Programs and Favorites) have an implicit +link attribute, so for them the Link box will be disabled.
+ +
+ +The icon can be:
+ +
    +
  • left blank - then if the link attribute points to a file or a folder, the icon of that file or folder will be used
    +
  • resource file,icon ID - for example %windir%\notepad.exe,2. Do not leave space between the file name and the comma. Make sure you are using the icon's resource ID, and not the icon's index. For best results use the [...] button next to the icon box
    +
  • ,icon ID - same as above, but the resource file is the ClassicStartMenuDLL.dll itself. This is useful when referring to the start menu's own icons
    +
  • icon file -  for example C:\Program Files\Mozilla Thunderbird\Email.ico
  • none - this will use a blank icon
  • +
+If the label or the tip attribute start with $ (dollar sign), then the system will treat it as a name of a string in the StartMenuL10N.ini +file. The actual text will depend on the current language setting. This +is useful when creating a menu that can be used by multiple languages.
+
+If you check "Insert Sub-items as Buttons", instead of showing the menu +item itself, the start menu will show the sub-items as a row of +buttons. By default the buttons are centered. You can align them to the +left by adding a separator as the last item, or align them to the right +by adding a separator as the first item. One possible use is to replace +the shutdown menu item with +separate buttons for shutdown, restart, log off, etc.
+
+

Administrative Settings

+The settings are +per user and are stored in the registry. By default every user can edit +all of their settings. An administrator can lock specific settings, so +no user can edit them:
+ +
+In this example the setting "Enable right-click menu" is locked to always +be unchecked and can't be changed by any user. This is achieved +by adding the setting to the HKEY_LOCAL_MACHINE\SOFTWARE\IvoSoft\ClassicStartMenu registry key. Create a DWORD value called "EnableContextMenu" and set it to 0.
+
+In some cases you may not want to lock the value for all users, but +simply modify the initial value of the setting. In such case add +"_Default" to the name of the value. For example if you want to context +menu to be disabled by default but still allow the users to enable it +if they wish, create a DWORD value named "EnableContextMenu_Default" +and set it to 0.
+
+The easiest way to know the registry name of a setting and its value is to modify it, and then look it up in HKEY_CURRENT_USER\Software\IvoSoft\ClassicStartMenu\Settings.
+ +Sometimes you may want to lock a setting to its default value, but you +don't know what the default value is. Then create a DWORD value and set +it to 0xDEFA.
+ +
+ +There is also a global setting "EnableSettings". Set it to 0 in the +registry to prevent the users from even opening the Settings dialog:
+ +
+
+The start menu also checks most of the group policies set by the administrator. Run gpedit.msc and go to User Configuration -> Administrative Templates -> Start Menu and Taskbar. From there you can disable Run, Shutdown, Help, and other features. (Not available on Home versions of Windows).
+
+Editing the settings through group policies is also supported. Extract the file PolicyDefinitions.zip found in the installation folder and read the document PolicyDefinitions.rtf for more details.
+
+
+

More About Skins

+You can pick from the many pre-installed skins:
+
+Skins for Classic Start Menu
+
Or you can download and install additional 3rd party skins (from +the main website or from another place). After you download a new skin +you +must copy the .skin file to the Skins directory – usually C:\Program +Files\Classic Shell\Skins. After that it will be available in the settings.
+
+Note: Some skins may be specifically designed for +Classic, Basic, or Aero mode. For example an Aero skin may require +glass support any will look weird if the Classic or Basic theme is +selected. Some Aero skins may also require specific glass color to be +selected.
+
+You can create your own skin. You will need an image editor that +supports alpha channel (like Gimp or Photoshop) and a tool to edit +resource files (like Resource Hacker or Visual Studio). And of course +some talent for graphical design :). Read the Skinning Tutorial before you begin.
+
+

+

Search


+
+ The search box lets you search the contents of the start menu, the +programs in the PATH environment variable and the indexed files. You can have the search box +appear as a normal menu item and then you can get to it using the +up/down arrow keys. You can choose to have the search box selected by +default when you open the start menu. Or you can choose to activate the +search box only with the Tab key, so until you press Tab you can use +the keyboard for navigation as if the search box is not there.
+
+The search results show in the main menu if you are using the Windows 7 style or in a sub-menu for the classic styles.
+Click on each category to expand it and see more results. Click on the icon at the end to view all results in Explorer.
+
+The classic styles allow you to register additional "search providers", which you can use to +search for the text from the search box. You run the search program +either by selecting it from the menu, or by +pressing Alt+key. In this example use Alt+A for Agent Ransack.
+
+
+This is done by adding sub-items of the SearchBoxItem in the Customize Start Menu tab:
+
+
+Open each of the sub-items and enter a command to start the search program. If you use %1 in the command, it will be replaced by the contents of the search box. If you use %2 +it will be replaced by the url-style encoded search text. Enter a +label, tip, and icon to complete your menu entry. In the label text you +can use & to mark the accelerator character (for example &Agent Ransack).
+
+Here are a few possible commands:
+Search with Agent Ransack: "C:\Program Files\Agent Ransack\AgentRansack.exe" -r -f "%1"
+Search with Everything: "C:\Program Files\Everything\Everything.exe" -search "%1"
+Search with Google: http://www.google.com/#q=%2
+Search with Bing: http://www.bing.com/search?q=%2
+
+
+

Custom Start Button
+

Classic Shell can add its own start button to the taskbar. It can +even replace the default start button in Windows 7. You can choose from +an Aero-style orb, a rectangular classic button, or +you can make your own. For a custom start button you need an image that +contain the 3 states of the button - normal, hot and pressed:
+Start button images
+The image must be a 32-bit PNG or BMP. By default the width of the +image determines the size of the button. You can override that by +entering a custom width.
+Read the Button Tutorial for more information about creating custom buttons.
+You can find many custom start button images online. Here are few examples:
+http://www.classicshell.net/forum/viewforum.php?f=18
+http://www.sevenforums.com/themes-styles/34951-custom-start-menu-button-collection.html
+
http://www.sevenforums.com/customization/78291-big-group-custom-start-orbs.html
+http://tutoriales13.deviantart.com/art/Orbs-153450418
+
+
+

Localization

+ +The user interface (except the Settings dialog box) is localized in 35 +languages.
+ +The Settings dialog box is translated in a smaller number of languages. +The default installation contains only English. More languages can be +downloaded from the translations page. Make sure you download the translation package for the exact version of Classic Shell.
+ + +
+

Command Line

+The ClassicStartMenu.exe supports 5 command line parameters: -open, -toggle, -togglenew, -exit and -settings.
+
+The first two do what the name suggests. One opens the classic start menu, the other +toggles it. You can use the parameters to create a shortcut in your +QuickLaunch bar that opens the start menu. Or to set a hotkey in +programs such as WinKey.
+
+The third one "-togglenew" toggles the default Windows start menu (or start screen). It is useful if +you want to create a shortcut or a hotkey to open the default menu and use the Win +key for the classic menu.
+
+Use "-exit" to exit the start menu. This command will only work if the start menu is not currently busy.
+
+Use "-settings" to open the start menu settings. This is useful for creating a shortcut for editing the settings.
+
+
+

Accessibility

The start menu supports screen readers like JAWS, +or Microsoft's Narrator. If the accessibility support causes problems it can be disabled from the General Behavior tab of the Settings.
+ +
+ \ No newline at end of file diff --git a/ClassicShellLoc/English/ClassicStartMenuADMX.txt b/ClassicShellLoc/English/ClassicStartMenuADMX.txt new file mode 100644 index 0000000..0d9d366 --- /dev/null +++ b/ClassicShellLoc/English/ClassicStartMenuADMX.txt @@ -0,0 +1,192 @@ +; DON'T TRANSLATE ============================================================= + +; disabled +CrashDump.supportedOn = never +LogLevel.supportedOn = never +OldProgramsAge.supportedOn = never +DefaultMenuStyle.supportedOn = never +MenuItems.supportedOn = never +Skin1.supportedOn = never +SkinOptions1.supportedOn = never +SkinVariation1.supportedOn = never +Skin2.supportedOn = never +SkinVariation2.supportedOn = never +SkinOptions2.supportedOn = never +SkipMetroCount.supportedOn = never +CompatibilityFixes.supportedOn = never + +; skins +SkinC1.supportedOn = classic1 +SkinVariationC1.supportedOn = classic1 +SkinOptionsC1.supportedOn = classic1 +MenuItems1.supportedOn = classic1 +SkinC2.supportedOn = classic2 +SkinVariationC2.supportedOn = classic2 +SkinOptionsC2.supportedOn = classic2 +MenuItems2.supportedOn = classic2 +SkinW7.supportedOn = win7_style +SkinVariationW7.supportedOn = win7_style +SkinOptionsW7.supportedOn = win7_style +MenuItems7.supportedOn = win7_style + +; style-specific +Computer.supportedOn = classic +Favorites.supportedOn = classic +Documents.supportedOn = classic +UserFiles.supportedOn = classic +UserDocuments.supportedOn = classic +UserPictures.supportedOn = classic +ControlPanel.supportedOn = classic +Network.supportedOn = classic +Printers.supportedOn = classic +Shutdown.supportedOn = classic +LogOff.supportedOn = classic +Undock.supportedOn = classic +Search.supportedOn = classic +Help.supportedOn = classic +Run.supportedOn = classic +SearchFilesCommand.supportedOn = classic +SearchResults.supportedOn = classic +SearchResultsMax.supportedOn = classic +MaxMainMenuWidth.supportedOn = classic +MainMenuAnimation.supportedOn = classic +MainMenuAnimationSpeed.supportedOn = classic +MainMenuScrollSpeed.supportedOn = classic +MenuCaption.supportedOn = classic +MenuUsername.supportedOn = classic +ShutdownCommand.supportedOn = win7_style +MinMainHeight.supportedOn = win7_style +ProgramsStyle.supportedOn = win7_style +FoldersFirst.supportedOn = win7_style +OpenPrograms.supportedOn = win7_style +ProgramsMenuDelay.supportedOn = win7_style +ShutdownW7.supportedOn = win7_style +ProgramsWidth.supportedOn = win7_style +JumplistWidth.supportedOn = win7_style + +; windows 7 +CascadeAll.supportedOn = win7 +AllProgramsDelay.supportedOn = win7 +InitiallySelect.supportedOn = win7 +HideUserPic.supportedOn = win7 +SkinA.supportedOn = win7 +SkinVariationA.supportedOn = win7 +SkinOptionsA.supportedOn = win7 + +; metro settings +AllTaskbars.supportedOn = win881 +AllProgramsMetro.supportedOn = win881 +HideProgramsMetro.supportedOn = win881 +RecentMetroApps.supportedOn = win881 +StartScreenShortcut.supportedOn = win881 +SearchMetroApps.supportedOn = win881 +DisableHotCorner.supportedOn = win881 +OpenMouseMonitor.supportedOn = win881 +SkipMetro.supportedOn = win8 + + + +; TRANSLATE =================================================================== + + +Title.text = Classic Shell settings +State.text = State: +State1.text = Locked to this value +State2.text = Locked to default +State3.text = Unlocked +State1Help.text = If you set the state to 'Locked to this value', the setting will be locked to the specified value for all users. +State2Help.text = If you set the state to 'Locked to default', the setting will be locked to the default value for all users. The specified value is ignored. +State3Help.text = If you set the state to 'Unlocked', the default value for the setting will be changed to the specified value. Individual users can override the setting. + +ClassicStartMenuCat.text = Classic Start Menu +ClassicStartMenuCatHelp.text = Classic Start Menu group policy settings +SUPPORTED_CS404.text = Requires Classic Shell 4.0.4 or later. +SUPPORTED_CS404_WIN7.text = Requires Windows 7. +SUPPORTED_CS404_WIN78.text = Requires Windows 7 or Windows 8. +SUPPORTED_CS404_WIN781.text = Requires Windows 7 or Windows 8.1. +SUPPORTED_CS404_WIN8.text = Requires Windows 8. +SUPPORTED_CS404_WIN881.text = Requires Windows 8 or Windows 8.1. +SUPPORTED_CS404_WIN81.text = Requires Windows 8.1. +SUPPORTED_CS404_CLASSIC1_STYLE.text = Requires Classic menu style with one column. +SUPPORTED_CS404_CLASSIC2_STYLE.text = Requires Classic menu style with two columns. +SUPPORTED_CS404_CLASSIC_STYLE.text = Requires Classic menu style. +SUPPORTED_CS404_WIN7_STYLE.text = Requires Windows 7 menu style. + + +EnableSettings.nameOverride = Enable settings +EnableSettings.tipOverride = Enables the users to edit their own settings + +MenuStyle.nameOverride = Menu style +MenuStyle.tipOverride = Select the style for the start menu.\nThe style determines the overall look and functionality of the menu. +MenuStyle_Classic1.nameOverride = Classic with one column +MenuStyle_Classic2.nameOverride = Classic with two columns +MenuStyle_Win7.nameOverride = Windows 7 + +MouseClick.nameOverride = Left Click opens +ShiftClick.nameOverride = Shift+Click opens +WinKey.nameOverride = Windows Key opens +ShiftWin.nameOverride = Shift+Win opens +MiddleClick.nameOverride = Middle Click opens +Hover.nameOverride = Hover opens + +; skins +SkinC1.nameOverride = Skin for classic menu with one column +SkinC1.tipOverride = Select the skin to be used by the classic style with one column +SkinVariationC1.nameOverride = Skin variation for classic menu with one column +SkinVariationC1.tipOverride = Select the skin variation to be used by the classic style with one column (for skins that support multiple variations) +SkinOptionsC1.nameOverride = Skin options for classic menu with one column +SkinOptionsC1.tipOverride = Select the skin options to be used by the classic style with one column.\nThe options are a list of hex numbers. The best way to get them is to adjust the options in the Classic Start Menu settings dialog and then look up the value named SkinOptionsC1 in HKCU\Software\IvoSoft\ClassicStartMenu\Settings +MenuItems1.nameOverride = Menu items for classic menu with one column +MenuItems1.tipOverride = Select the menu items to be used by the classic style with one column.\nThe best way to get the right string is to configure the items in the Classic Start Menu settings dialog and then look up the value named MenuItems1 in HKCU\Software\IvoSoft\ClassicStartMenu\Settings +SkinC2.nameOverride = Skin for classic menu with two columns +SkinC2.tipOverride = Select the skin to be used by the classic style with two columns +SkinVariationC2.nameOverride = Skin variation for classic menu with two columns +SkinVariationC2.tipOverride = Select the skin variation to be used by the classic style with two columns (for skins that support multiple variations) +SkinOptionsC2.nameOverride = Skin options for classic menu with two columns +SkinOptionsC2.tipOverride = Select the skin options to be used by the classic style with two columns.\nThe options are a list of hex numbers. The best way to get them is to adjust the options in the Classic Start Menu settings dialog and then look up the value named SkinOptionsC2 in HKCU\Software\IvoSoft\ClassicStartMenu\Settings +MenuItems2.nameOverride = Menu items for classic menu with two columns +MenuItems2.tipOverride = Select the menu items to be used by the classic style with two columns.\nThe best way to get the right string is to configure the items in the Classic Start Menu settings dialog and then look up the value named MenuItems2 in HKCU\Software\IvoSoft\ClassicStartMenu\Settings +SkinW7.nameOverride = Skin for the Windows 7 style +SkinW7.tipOverride = Select the skin to be used by the Windows 7 style +SkinVariationW7.nameOverride = Skin variation for the Windows 7 style +SkinVariationW7.tipOverride = Select the skin variation to be used by the Windows 7 style (for skins that support multiple variations) +SkinOptionsW7.nameOverride = Skin options for the Windows 7 style +SkinOptionsW7.tipOverride = Select the skin options to be used by the Windows 7 style.\nThe options are a list of hex numbers. The best way to get them is to adjust the options in the Classic Start Menu settings dialog and then look up the value named SkinOptionsW7 in HKCU\Software\IvoSoft\ClassicStartMenu\Settings +MenuItems7.nameOverride = Menu items for the Windows 7 style +MenuItems7.tipOverride = Select the menu items to be used by the Windows 7 style.\nThe best way to get the right string is to configure the items in the Classic Start Menu settings dialog and then look up the value named MenuItems7 in HKCU\Software\IvoSoft\ClassicStartMenu\Settings + +; windows 7 +SkinA.nameOverride = Skin for the All Programs sub-menu for the Windows 7 start menu +SkinA.tipOverride = Select the skin to be used by the All Programs sub-menu for the Windows 7 start menu +SkinVariationA.nameOverride = Skin variation for the All Programs sub-menu for the Windows 7 start menu +SkinVariationA.tipOverride = Select the skin variation to be used by the All Programs sub-menu for the Windows 7 start menu (for skins that support multiple variations) +SkinOptionsA.nameOverride = Skin options for the All Programs sub-menu for the Windows 7 start menu +SkinOptionsA.tipOverride = Select the skin options to be used by the All Programs sub-menu for the Windows 7 start menu.\nThe options are a list of hex numbers. The best way to get them is to adjust the options in the Classic Start Menu settings dialog and then look up the value named SkinOptionsA in HKCU\Software\IvoSoft\ClassicStartMenu\Settings + +; metro settings +SkipMetro.tipAddition = This setting doesn't work for Windows 8.1. You need to use the built-in Windows setting for booting to Desktop + +; hidden +FolderStartMenu.nameOverride = Start Menu folder +FolderStartMenu.tipOverride = Enter an override for the per-user start menu folder (also overrides the per-user Programs folder).\nThe path can contain environment variables.\nNote: This setting is not editable from the Settings dialog +FolderPrograms.nameOverride = Programs folder +FolderPrograms.tipOverride = Enter an override for the per-user Programs folder.\nThe path can contain environment variables.\nNote: This setting is not editable from the Settings dialog +FolderCommonStartMenu.nameOverride = Common Start Menu folder +FolderCommonStartMenu.tipOverride = Enter an override for the common start menu folder (also overrides the common Programs folder).\nThe path can contain environment variables.\nNote: This setting is not editable from the Settings dialog +FolderCommonPrograms.nameOverride = Common Programs folder +FolderCommonPrograms.tipOverride = Enter an override for the common Programs folder.\nThe path can contain environment variables.\nNote: This setting is not editable from the Settings dialog +AutoStartDelay.nameOverride = Auto-start delay +AutoStartDelay.tipOverride = Enter a delay in ms when launching the start menu automatically during login (does not apply when starting the menu manually by running ClassicStartMenu.exe).\nNote: This setting is not editable from the Settings dialog + +; other +StartButtonIcon.tipAddition = The value can be a path to an ICO file or a path to an EXE/DLL and an the ID of the icon +StartButtonPath.tipAddition = The value is a full path to the BMP or PNG file +SoundMain.tipAddition = The value can be a name of a system event or a path to a WAV file +SoundPopup.tipAddition = The value can be a name of a system event or a path to a WAV file +SoundCommand.tipAddition = The value can be a name of a system event or a path to a WAV file +SoundDrop.tipAddition = The value can be a name of a system event or a path to a WAV file +ExpandFolderLinks.tipAddition = Only works for symbolic links (like junctions) and not for plain shortcuts +StartHoverDelay.nameOverride = Hover delay (for Start button) +AllProgramsDelay.nameOverride = Hover delay (for All Programs in Windows 7) +CSMHotkey.tipAddition = .\n\nThe base value is the main key's virtual code. Add 256 for Shift, 512 for Control and 1024 for Alt.\nThe best way to get the value is to select the hotkey in the Classic Start Menu settings dialog and then look up the value named CSMHotkey in HKCU\Software\IvoSoft\ClassicStartMenu\Settings +WSMHotkey.tipAddition = .\n\nThe base value is the main key's virtual code. Add 256 for Shift, 512 for Control and 1024 for Alt.\nThe best way to get the value is to select the hotkey in the Classic Start Menu settings dialog and then look up the value named WSMHotkey in HKCU\Software\IvoSoft\ClassicStartMenu\Settings diff --git a/ClassicShellLoc/English/License.html b/ClassicShellLoc/English/License.html new file mode 100644 index 0000000..cf831e9 --- /dev/null +++ b/ClassicShellLoc/English/License.html @@ -0,0 +1,60 @@ + + + + + + License Agreement + +

Classic Shell website  License Agreement
+


+Classic Shell 2009-2016, Ivo Beltchev

+http://www.classicshell.net/
+
+BY USING THIS SOFTWARE, YOU ACCEPT THESE TERMS. IF YOU DO NOT ACCEPT THEM, DO NOT USE THE SOFTWARE.
+
+If you comply with these license terms, you have the rights below.
+
+
    +
  1. +

    SCOPE OF LICENSE. This agreement only gives you some rights to use the software. The author reserves all other rights.

    +
  2. +
  3. +

    INSTALLATION AND USE RIGHTS. This software is free for both personal and commercial use. You may install and use it on your computers free of charge.

    +
  4. +
  5. +

    REDISTRIBUTION RIGHTS. You may redistribute the software as long as you do it free of charge and you don’t misrepresent the origin of the software.

    +
  6. +
  7. +

    TRADEMARKS. The Classic Shell name and logo are trademarks of the author. Using them to to identify other products or services is not permitted.

    +
  8. +
  9. +

    DISCLAIMER OF WARRANTY. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    +
  10. +
  11. +

    IN OTHER WORDS: +Basically you can use this software freely for any purpose but don’t be +surprised if it doesn’t work as you expect. You can’t hold the author +responsible for any damages that come to you from using the software. +You can’t profit from selling this software. You got it for free after +all.

    +
  12. +
+ + + \ No newline at end of file diff --git a/ClassicShellLoc/English/Links.html b/ClassicShellLoc/English/Links.html new file mode 100644 index 0000000..61d8729 --- /dev/null +++ b/ClassicShellLoc/English/Links.html @@ -0,0 +1,39 @@ + + + + + + + Classic Shell + +

Classic Shell website  Links


The latest version can be found on the Classic Shell website:
+http://www.classicshell.net/
+
+View the project history here:
+History: http://www.classicshell.net/history/
+
+
+

Get Help

+For answers to frequently asked questions look here:
+FAQ: http://www.classicshell.net/faq/
+ +
+If you don't find your answer in the FAQ, try the discussion forums:
+Discussion Forums: http://www.classicshell.net/forum/viewforum.php?f=6
+ +
+
+

Report Problems

+Report bugs and feature requests in the development forums:
+Development Forums: http://www.classicshell.net/forum/viewforum.php?f=11
+ + \ No newline at end of file diff --git a/ClassicShellLoc/English/Localization.rtf b/ClassicShellLoc/English/Localization.rtf new file mode 100644 index 0000000..b3b8bec --- /dev/null +++ b/ClassicShellLoc/English/Localization.rtf @@ -0,0 +1,345 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} +{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}{\f3\fbidi \froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f10\fbidi \fnil\fcharset2\fprq2{\*\panose 05000000000000000000}Wingdings;} +{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f36\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} +{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} +{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f49\fbidi \fswiss\fcharset238\fprq2 Arial CE;}{\f50\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;} +{\f52\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f53\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f54\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f55\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);} +{\f56\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f57\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\f59\fbidi \fmodern\fcharset238\fprq1 Courier New CE;}{\f60\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;} +{\f62\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f63\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f64\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f65\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);} +{\f66\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f67\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f379\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f380\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;} +{\f382\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f383\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f386\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f387\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);} +{\f399\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\f400\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\f402\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\f403\fbidi \froman\fcharset162\fprq2 Cambria Tur;} +{\f406\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\f407\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;} +{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;} +{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} +{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0; +\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192; +\chyperlink\ctint255\cshade255\red0\green0\blue255;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ +\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext0 \sqformat \spriority0 Normal;}{\s1\ql \li0\ri0\sb240\sa60\sl276\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs32\alang1025 \ltrch\fcs0 +\b\fs32\lang1033\langfe1033\kerning32\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink15 \sqformat \spriority9 \styrsid6947948 heading 1;}{\s2\ql \li0\ri0\sb240\sa60\sl276\slmult1 +\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\ai\af0\afs28\alang1025 \ltrch\fcs0 \b\i\fs28\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink16 \sunhideused \sqformat \spriority9 \styrsid14646721 heading 2;}{\*\cs10 \additive \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused +Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \ab\af0\afs32 \ltrch\fcs0 \b\fs32\kerning32\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink1 \slocked \spriority9 \styrsid6947948 Heading 1 Char;}{\*\cs16 \additive \rtlch\fcs1 \ab\ai\af0\afs28 +\ltrch\fcs0 \b\i\fs28\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink2 \slocked \spriority9 \styrsid14646721 Heading 2 Char;}{\*\cs17 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf17 \sbasedon10 \sunhideused \styrsid6947948 Hyperlink;}{ +\s18\ql \li720\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin720\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext18 \sqformat \spriority34 \styrsid11755305 List Paragraph;}}{\*\listtable{\list\listtemplateid302521304\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext +\leveltemplateid-196446756\'01\u-3913 ?;}{\levelnumbers;}\loch\af3\hich\af3\dbch\af31505\fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext +\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693 +\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li2160\lin2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;} +\f3\fbias0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3600\lin3600 } +{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li4320\lin4320 }{\listlevel\levelnfc23\levelnfcn23 +\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0 +\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6480\lin6480 }{\listname ;}\listid2061244983}}{\*\listoverridetable{\listoverride\listid2061244983\listoverridecount0\ls1}}{\*\rsidtbl \rsid1074044 +\rsid2767162\rsid5637360\rsid6947948\rsid7305812\rsid8198374\rsid8667162\rsid9467422\rsid11602721\rsid11755305\rsid11811362\rsid14490461\rsid14646721\rsid15425079\rsid15878395\rsid16266177\rsid16327957}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0 +\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Ivo}{\creatim\yr2010\mo10\dy24\hr9\min48}{\revtim\yr2014\mo3\dy16\hr12\min16}{\version13}{\edmins88}{\nofpages3}{\nofwords965}{\nofchars5501} +{\nofcharsws6454}{\vern49167}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect +\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701 +\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot6947948 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 +\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 +\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\s1\ql \li0\ri0\sb240\sa60\sl276\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0\pararsid6947948 \rtlch\fcs1 \ab\af0\afs32\alang1025 \ltrch\fcs0 +\b\fs32\lang1033\langfe1033\kerning32\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid7305812 \hich\af31502\dbch\af31501\loch\f31502 Localization of Classic Shell +\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs20 +\ltrch\fcs0 \f1\fs20\insrsid7305812 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid6947948 \hich\af1\dbch\af31505\loch\f1 This file explains the localization system used by Classic Shell and how to translate Classic Shell in new languages. +\par +\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb240\sa60\sl276\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid14646721 \rtlch\fcs1 \ab\ai\af0\afs28\alang1025 \ltrch\fcs0 +\b\i\fs28\lang1033\langfe1033\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16266177 \hich\af31502\dbch\af31501\loch\f31502 1}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid6947948 +\hich\af31502\dbch\af31501\loch\f31502 . What can be localized +\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs20 +\ltrch\fcs0 \f1\fs20\insrsid16266177 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid6947948 \hich\af1\dbch\af31505\loch\f1 Classic Shell has 2 major systems for providing localized text. +\par +\par \hich\af1\dbch\af31505\loch\f1 The first one is the L10N.ini files. There are }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 \hich\af1\dbch\af31505\loch\f1 3 files \hich\f1 \endash \loch\f1 ExplorerL10N.ini, }{\rtlch\fcs1 \af1\afs20 +\ltrch\fcs0 \f1\fs20\insrsid6947948 \hich\af1\dbch\af31505\loch\f1 StartMenuL10N.ini}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 \hich\af1\dbch\af31505\loch\f1 and StartMenuHelperL10N.ini}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid6947948 \hich\af1\dbch\af31505\loch\f1 . They contain translations for the text in Explorer and the start menu\hich\af1\dbch\af31505\loch\f1 + that users will encounter during normal use. These files contain translations for all of the 35 supported languages. Each language is separated in its own section. You will generally not need to edit these files unless you find a typo. If you do, please +\hich\af1\dbch\af31505\loch\f1 s\hich\af1\dbch\af31505\loch\f1 end the correction to }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid6947948 \hich\af1\dbch\af31505\loch\f1 HYPERLINK "mailto:classicshell@ibeltchev.com" }{ +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid9467422 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5c0000006d00610069006c0074006f003a0063006c00610073007300690063007300680065006c006c0040006900620065006c00740063006800650076002e0063006f006d000000795881f43b1d7f48af2c825dc485 +276300000000a5ab0000006b006c}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs17\f1\fs20\ul\cf17\insrsid6947948\charrsid16327957 \hich\af1\dbch\af31505\loch\f1 classicshell@ibeltchev.com}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid6947948 \hich\af1\dbch\af31505\loch\f1 , so I can fix the typo in the next release. +\par +\par \hich\af1\dbch\af31505\loch\f1 The s\hich\af1\dbch\af31505\loch\f1 econd system is for localizing the settings UI and the system messages that Classic Shell displays. The translations are packaged into a resource DLL with the name of the language +\hich\f1 \endash \loch\f1 en-US.dll, ja-JP.dll, etc. The DLL can contain: +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f3\fs20\insrsid6947948 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}\pard \ltrpar\ql \fi-360\li720\ri0\nowidctlpar\wrapdefault\faauto\ls1\rin0\lin720\itap0\pararsid6947948 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid6947948 \hich\af1\dbch\af31505\loch\f1 A string table with repl\hich\af1\dbch\af31505\loch\f1 acement strings +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f3\fs20\insrsid6947948 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af1\dbch\af31505\loch\f1 Dialog resources for the Settings UI +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f3\fs20\insrsid6947948 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}\hich\af1\dbch\af31505\loch\f1 Overrides for te}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14646721 +\hich\af1\dbch\af31505\loch\f1 x}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid6947948 \hich\af1\dbch\af31505\loch\f1 t }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid9467422 \hich\af1\dbch\af31505\loch\f1 lines }{\rtlch\fcs1 \af1\afs20 +\ltrch\fcs0 \f1\fs20\insrsid6947948 \hich\af1\dbch\af31505\loch\f1 in the L10N}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid9467422 \hich\af1\dbch\af31505\loch\f1 .ini}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid6947948 +\hich\af1\dbch\af31505\loch\f1 files +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6947948 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid6947948 \hich\af1\dbch\af31505\loch\f1 The same DLL contains resources for }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 \hich\af1\dbch\af31505\loch\f1 all}{\rtlch\fcs1 \af1\afs20 +\ltrch\fcs0 \f1\fs20\insrsid6947948 \hich\af1\dbch\af31505\loch\f1 of the Classic Shell components \hich\f1 \endash \loch\f1 Classic Explorer}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 ,}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid6947948 \hich\af1\dbch\af31505\loch\f1 Classic Start Menu}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 \hich\af1\dbch\af31505\loch\f1 , etc}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid6947948 .}{\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 \hich\af1\dbch\af31505\loch\f1 Generally resources from 2000 to 3000 belong to Classic Explorer, from 3000 to 4000 belong to Classic Start Menu, }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 +\hich\af1\dbch\af31505\loch\f1 from 5000 to 6000 belong to Classic IE, 6000 to 7000 belong to the updater component }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 \hich\af1\dbch\af31505\loch\f1 and from 4000 to 5000 are shared by }{ +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 \hich\af1\dbch\af31505\loch\f1 all}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 \hich\af1\dbch\af31505\loch\f1 components.}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid6947948 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid6947948 +\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb240\sa60\sl276\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid14646721 \rtlch\fcs1 \ab\ai\af0\afs28\alang1025 \ltrch\fcs0 +\b\i\fs28\lang1033\langfe1033\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16266177 \hich\af31502\dbch\af31501\loch\f31502 2}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid6947948 +\hich\af31502\dbch\af31501\loch\f31502 . \hich\af31502\dbch\af31501\loch\f31502 What }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2767162 \hich\af31502\dbch\af31501\loch\f31502 else }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid6947948 +\hich\af31502\dbch\af31501\loch\f31502 can be localized (if you really want to) +\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs20 +\ltrch\fcs0 \f1\fs20\insrsid16266177 +\par \hich\af1\dbch\af31505\loch\f1 Classic Shell is designed to }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid1074044 \hich\af1\dbch\af31505\loch\f1 mainly }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 \hich\af1\dbch\af31505\loch\f1 +support localizations for the UI. Localizations for other areas, like the installer}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8667162 \hich\af1\dbch\af31505\loch\f1 and}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 +\hich\af1\dbch\af31505\loch\f1 the documentation}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8667162 \hich\af1\dbch\af31505\loch\f1 will }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 \hich\af1\dbch\af31505\loch\f1 +require more work}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 . +\par +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1074044 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 \hich\af1\dbch\af31505\loch\f1 To translate the installer}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid2767162 \hich\af1\dbch\af31505\loch\f1 you need t\hich\af1\dbch\af31505\loch\f1 o translate}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 \hich\af1\dbch\af31505\loch\f1 the }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid2767162\charrsid2767162 \hich\af1\dbch\af31505\loch\f1 ClassicShellText-en-US.wxl}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 \hich\af1\dbch\af31505\loch\f1 }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 +\hich\af1\dbch\af31505\loch\f1 file}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 .}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 \hich\af1\dbch\af31505\loch\f1 }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 +\hich\af1\dbch\af31505\loch\f1 It}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 \hich\af1\dbch\af31505\loch\f1 contain the }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 \hich\af1\dbch\af31505\loch\f1 text for the installe}{ +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8667162 \hich\af1\dbch\af31505\loch\f1 r}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 \hich\af1\dbch\af31505\loch\f1 . }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 +\hich\af1\dbch\af31505\loch\f1 One }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11811362 \hich\af1\dbch\af31505\loch\f1 benefit of translating the installer is that you can localize the names of the shortcuts in the Start menu.}{\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid1074044 \hich\af1\dbch\af31505\loch\f1 You also need to translate the }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid1074044\charrsid2767162 \hich\af1\dbch\af31505\loch\f1 ClassicShellReadme}{\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid1074044 \hich\af1\dbch\af31505\loch\f1 .rtf fi\hich\af1\dbch\af31505\loch\f1 le and ClassicShellEULA.rtf if you want them to display in your language. +\par +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 \hich\af1\dbch\af31505\loch\f1 To translate the help file}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 \hich\af1\dbch\af31505\loch\f1 y}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid16266177 \hich\af1\dbch\af31505\loch\f1 ou will need to }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid1074044 \hich\af1\dbch\af31505\loch\f1 translate the HTML files included in ClassicShellLoc.zip. If you install the tool }{ +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16266177 \hich\af1\dbch\af31505\loch\f1 HTML Help Workshop from Microsoft}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid1074044 \hich\af1\dbch\af31505\loch\f1 +, you will be able to also compile the CHM file and preview it yourself. Use the ClassicShell.hhp help project file for that}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 . +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid5637360 +\par \hich\af1\dbch\af31505\loch\f1 To translate the group policies you will need to translate the files \hich\af1\dbch\af31505\loch\f1 C\hich\af1\dbch\af31505\loch\f1 lassic\hich\af1\dbch\af31505\loch\f1 +ExplorerADMX.txt, ClassicIEADMX.txt, ClassicShellADMX.txt and ClassicStartMenuADMX.txt. You may \hich\af1\dbch\af31505\loch\f1 also translate the PolicyDefinitions.rtf file. +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8667162 \hich\af1\dbch\af31505\loch\f1 When you are done, send all translations to me and I will prepare an installer for }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid1074044 +\hich\af1\dbch\af31505\loch\f1 your}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8667162 \hich\af1\dbch\af31505\loch\f1 language.}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2767162 \hich\af1\dbch\af31505\loch\f1 }{\rtlch\fcs1 \af1\afs20 +\ltrch\fcs0 \f1\fs20\insrsid16266177 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11811362 +\par +\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb240\sa60\sl276\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid14646721 \rtlch\fcs1 \ab\ai\af0\afs28\alang1025 \ltrch\fcs0 +\b\i\fs28\lang1033\langfe1033\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16266177 \hich\af31502\dbch\af31501\loch\f31502 3. }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid14646721 +\hich\af31502\dbch\af31501\loch\f31502 The DLL structure in detail}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16266177 +\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs20 +\ltrch\fcs0 \f1\fs20\insrsid14646721 +\par \hich\af1\dbch\af31505\loch\f1 Look at the provided }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid14646721\charrsid8198374 \hich\af1\dbch\af31505\loch\f1 en-US.dll}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14646721 +\hich\af1\dbch\af31505\loch\f1 file. It contains all English resources that can be translated. +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\i\f1\fs20\insrsid14646721\charrsid14646721 \hich\af1\dbch\af31505\loch\f1 Note:}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \i\f1\fs20\insrsid14646721\charrsid14646721 \hich\af1\dbch\af31505\loch\f1 Classic Shell doesn +\hich\f1 \rquote \loch\f1 t need the en-US.dll file. The English text is already built-in. The purpose of the en-US.dll file is to s\hich\af1\dbch\af31505\loch\f1 erve as an example}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \i\f1\fs20\insrsid8198374 +\hich\af1\dbch\af31505\loch\f1 and starting point}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \i\f1\fs20\insrsid14646721\charrsid14646721 \hich\af1\dbch\af31505\loch\f1 for other languages. +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14646721 +\par \hich\af1\dbch\af31505\loch\f1 The localization DLL contains the following resources: +\par +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f3\fs20\insrsid14646721 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}\pard \ltrpar\ql \fi-360\li720\ri0\nowidctlpar\wrapdefault\faauto\ls1\rin0\lin720\itap0\pararsid14646721 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14646721 \hich\af1\dbch\af31505\loch\f1 A version resource. It must match the version of Classic Shell it is intended to be used with. The reason is that the text often changes b\hich\af1\dbch\af31505\loch\f1 +etween versions, so translations from one version will not work with the next. You may }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8198374 \hich\af1\dbch\af31505\loch\f1 also }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14646721 +\hich\af1\dbch\af31505\loch\f1 use the comments section to list your name as the author. +\par }\pard \ltrpar\ql \li720\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0\pararsid14646721 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14646721 +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f3\fs20\insrsid14646721 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}\pard \ltrpar\ql \fi-360\li720\ri0\nowidctlpar\wrapdefault\faauto\ls1\rin0\lin720\itap0\pararsid8198374 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14646721 \hich\af1\dbch\af31505\loch\f1 A string table. Provide}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8198374 \hich\af1\dbch\af31505\loch\f1 s}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid14646721 \hich\af1\dbch\af31505\loch\f1 translations for the UI text in Classic Shell. Use}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11755305 \hich\af1\dbch\af31505\loch\f1 the text from en-US.dll as +\hich\af1\dbch\af31505\loch\f1 a source. The string table doesn\hich\f1 \rquote \loch\f1 t need to include all strings. If a string is missing, it will stay in English.}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8198374 \line }{\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11755305\charrsid8198374 +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f3\fs20\insrsid11755305 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11755305 \hich\af1\dbch\af31505\loch\f1 +A set of dialog resources. These a\hich\af1\dbch\af31505\loch\f1 +re the dialog boxes that the Settings UI needs. You can replace the text in the dialogs with your own. You can also resize some of the dialog elements to make the text fit. Like with the strings, if a dialog is missing from the DLL, the English version wi +\hich\af1\dbch\af31505\loch\f1 l\hich\af1\dbch\af31505\loch\f1 l be used.}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8198374 \line }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11755305\charrsid8198374 +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f3\fs20\insrsid11755305 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}\pard \ltrpar\ql \fi-360\li720\ri0\nowidctlpar\wrapdefault\faauto\ls1\rin0\lin720\itap0\pararsid15425079 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11755305 \hich\af1\dbch\af31505\loch\f1 \hich\f1 +A L10N resource (its resource ID must be 1). This is a UTF-16 text file that contains replacement strings for the ini files. For example the ini files do not have the text \'93}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11755305\charrsid11755305 +\hich\af1\dbch\af31505\loch\f1 Settings for Classic Start Menu}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11755305 \loch\af1\dbch\af31505\hich\f1 \'94\loch\f1 translated in all languages (since I\hich\af1\dbch\af31505\loch\f1 don\hich\f1 +\rquote \loch\f1 t know how to say it in all 35 languages). So the DLL can provide the translations for the current language. It is possible to replace even text that is already translated \hich\f1 \endash \loch\f1 for example if you want to fix a typo}{ +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8198374 \hich\af1\dbch\af31505\loch\f1 in the ini file}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11755305 \hich\af1\dbch\af31505\loch\f1 , or to provide a better\hich\af1\dbch\af31505\loch\f1 + version of some text line.}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid15425079 \line }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid15425079\charrsid15425079 +\par }\pard\plain \ltrpar\s18\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15425079 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11602721 \hich\af1\dbch\af31505\loch\f1 +You can edit a DLL using a resource editor like Visual Studio, Res Hacker, and many others. +\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb240\sa60\sl276\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid14490461 \rtlch\fcs1 \ab\ai\af0\afs28\alang1025 \ltrch\fcs0 +\b\i\fs28\lang1033\langfe1033\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid11755305 \hich\af31502\dbch\af31501\loch\f31502 4. What if I don\hich\f31502 \rquote \loch\f31502 +t know how to edit DLLs? +\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid11755305 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11755305 +\par \hich\af1\dbch\af31505\loch\f1 Look at the provided }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid11755305\charrsid8198374 \hich\af1\dbch\af31505\loch\f1 en-US.csv}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11755305 +\hich\af1\dbch\af31505\loch\f1 file. It is a tab-separated file in UTF-16 format. You can open it in Excel or any compatible editor. The file contains 4 columns: +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f3\fs20\insrsid11755305\charrsid11602721 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}\pard \ltrpar\ql \fi-360\li720\ri0\nowidctlpar\wrapdefault\faauto\ls1\rin0\lin720\itap0\pararsid11755305 { +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid11755305\charrsid11602721 \hich\af1\dbch\af31505\loch\f1 ID}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11755305 \hich\af1\dbch\af31505\loch\f1 \hich\f1 \endash \loch\f1 + this is the identifier of the text line. There are 3 types of IDs: +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f2\fs20\insrsid11755305 \hich\af2\dbch\af31505\loch\f2 o\tab}}\pard \ltrpar\ql \fi-360\li1440\ri0\nowidctlpar\wrapdefault\faauto\ls1\ilvl1\rin0\lin1440\itap0\pararsid11755305 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11755305 \hich\af1\dbch\af31505\loch\f1 A number, like 2001, 4030, etc. These correspond\hich\af1\dbch\af31505\loch\f1 to the strings in the string table +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f2\fs20\insrsid11755305 \hich\af2\dbch\af31505\loch\f2 o\tab}\hich\af1\dbch\af31505\loch\f1 +A pair of numbers, like 3002/1025. These correspond to strings found in the dialog boxes. The first number is the ID of the dialog, and the second is the ID of the control in that dialog +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f2\fs20\insrsid11755305 \hich\af2\dbch\af31505\loch\f2 o\tab}\hich\af1\dbch\af31505\loch\f1 \hich\f1 Text, like \'93}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid11755305\charrsid11755305 \hich\af1\dbch\af31505\loch\f1 Menu.SettingsTip}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11755305 \loch\af1\dbch\af31505\hich\f1 \'94\hich\af1\dbch\af31505\loch\f1 +. These correspond to the lines of the L10N resource +\par }\pard \ltrpar\ql \li720\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0\pararsid14490461 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid11755305 +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f3\fs20\insrsid14490461\charrsid11602721 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}\pard \ltrpar\ql \fi-360\li720\ri0\nowidctlpar\wrapdefault\faauto\ls1\rin0\lin720\itap0\pararsid14490461 { +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid14490461\charrsid11602721 \hich\af1\dbch\af31505\loch\f1 English}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14490461 \hich\af1\dbch\af31505\loch\f1 \hich\f1 \endash \loch\f1 + this is the original English text +\par }\pard \ltrpar\ql \li720\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0\pararsid14490461 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14490461 +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f3\fs20\insrsid14490461\charrsid11602721 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}\pard \ltrpar\ql \fi-360\li720\ri0\nowidctlpar\wrapdefault\faauto\ls1\rin0\lin720\itap0\pararsid8198374 { +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid14490461\charrsid11602721 \hich\af1\dbch\af31505\loch\f1 Translation}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14490461 \hich\af1\dbch\af31505\loch\f1 \hich\f1 \endash \loch\f1 + this column is empty. That\hich\f1 \rquote \loch\f1 s where you will have to enter the translations for your language}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8198374 \line }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid14490461\charrsid8198374 +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f3\fs20\insrsid14490461\charrsid11602721 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}\pard \ltrpar\ql \fi-360\li720\ri0\nowidctlpar\wrapdefault\faauto\ls1\rin0\lin720\itap0\pararsid14490461 { +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid14490461\charrsid11602721 \hich\af1\dbch\af31505\loch\f1 Comment}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14490461 \hich\af1\dbch\af31505\loch\f1 \hich\f1 \endash +\hich\af1\dbch\af31505\loch\f1 + some lines contain hints for the meaning of the translation, or instructions for providing better translation. If you are still unclear about something, ask me. I will provide more comments in future versions based on which text lines people find confusi +\hich\af1\dbch\af31505\loch\f1 n\hich\af1\dbch\af31505\loch\f1 g +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid14490461 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14490461 +\par +\par \hich\af1\dbch\af31505\loch\f1 Once you are done, send the CSV file to }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14490461 \hich\af1\dbch\af31505\loch\f1 HYPERLINK "mailto:classicshell@ibeltchev.com" }{\rtlch\fcs1 \af1\afs20 +\ltrch\fcs0 \f1\fs20\insrsid9467422 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5c0000006d00610069006c0074006f003a0063006c00610073007300690063007300680065006c006c0040006900620065006c00740063006800650076002e0063006f006d000000795881f43b1d7f48af2c825dc485 +276300000000a5ab00000065006c}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs17\f1\fs20\ul\cf17\insrsid14490461\charrsid16327957 \hich\af1\dbch\af31505\loch\f1 classicshell@ibeltchev.com}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14490461 \hich\af1\dbch\af31505\loch\f1 and I will convert that text\hich\af1\dbch\af31505\loch\f1 into a DLL and upload it to the Classic Shell website. +\par +\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb240\sa60\sl276\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid14490461 \rtlch\fcs1 \ab\ai\af0\afs28\alang1025 \ltrch\fcs0 +\b\i\fs28\lang1033\langfe1033\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid14490461 \hich\af31502\dbch\af31501\loch\f31502 5. Special characters +\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid14490461 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14490461 +\par \hich\af1\dbch\af31505\loch\f1 Some text lines in the DLL or the CSV contain special characters. They are: +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid14490461\charrsid11602721 \\\hich\af1\dbch\af31505\loch\f1 t}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14490461 \hich\af1\dbch\af31505\loch\f1 \hich\f1 \endash \loch\f1 + this is the Tab character. Do not enter an actual tab in the text, because the CSVs don\hich\f1 \rquote \loch\f1 t handl\hich\af1\dbch\af31505\loch\f1 e it well +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid15878395 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid15878395\charrsid11602721 \\\hich\af1\dbch\af31505\loch\f1 r}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid15878395 \hich\af1\dbch\af31505\loch\f1 \hich\f1 \endash \loch\f1 this is a carriage return character +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid14490461 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid14490461\charrsid11602721 \\}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid15878395\charrsid11602721 +\hich\af1\dbch\af31505\loch\f1 n}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14490461 \hich\af1\dbch\af31505\loch\f1 \hich\f1 \endash \loch\f1 this is a new line character +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid14490461\charrsid11602721 \\\\}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14490461 \hich\af1\dbch\af31505\loch\f1 - this is the backslash character. You must use \\\\ instead of \\ +, because a single \\ can be mistaken for a special character +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid14490461\charrsid11602721 \hich\af1\dbch\af31505\loch\f1 %d}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14490461 \hich\af1\dbch\af31505\loch\f1 \hich\f1 \endash +\hich\af1\dbch\af31505\loch\f1 this is a placeholder for a number. The actual number will be provided at run-time +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid14490461\charrsid11602721 \hich\af1\dbch\af31505\loch\f1 %s}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14490461 \hich\af1\dbch\af31505\loch\f1 \hich\f1 \endash \loch\f1 + this is a placeholder for a string. The actual string will be provided at run-time +\par +\par \hich\af1\dbch\af31505\loch\f1 In general, try to keep the special characters as they are}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid15878395 .}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14490461 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid15878395 +\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a +9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad +5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 +b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 +0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 +a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f +c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 +0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 +a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 +6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b +4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b +4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210030dd4329a8060000a41b0000160000007468656d652f7468656d652f +7468656d65312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87 +615b8116d8a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad +79482a9c0498f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b +5d8a314d3c94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab +999fb7b4717509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9 +699640f6719e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd586 +8b37a088d1e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d6 +0cf03ac1a5193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f +9e7ef3f2d117d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be +15c308d3f28acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a9979 +3849c26ae66252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d +32a423279a668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2a +f074481847bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86 +e877f0034e16bafb0e258ebb4faf06b769e888340b103d331115bebc4eb813bf83291b63624a0d1475a756c734f9bbc2cd28546ecbe1e20a3794ca175f3fae90 +fb6d2dd99bb07b55e5ccf68942bd0877b23c77b908e8db5f9db7f024d9239010f35bd4bbe2fcae387bfff9e2bc289f2fbe24cfaa301468dd8bd846dbb4ddf1c2 +ae7b4c191ba8292337a469bc25ec3d411f06f53a73e224c5292c8de0516732307070a1c0660d125c7d44553488700a4d7bddd3444299910e254ab984c3a219ae +a4adf1d0f82b7bd46cea4388ad1c12ab5d1ed8e1153d9c9f350a3246aad01c6873462b9ac05999ad5cc988826eafc3acae853a33b7ba11cd1445875ba1b236b1 +399483c90bd560b0b0263435085a21b0f22a9cf9356b38ec6046026d77eba3dc2dc60b17e92219e180643ed27acffba86e9c94c7ca9c225a0f1b0cfae0788ad5 +4adc5a9aec1b703b8b93caec1a0bd8e5de7b132fe5113cf312503b998e2c2927274bd051db6b35979b1ef271daf6c6704e86c73805af4bdd476216c26593af84 +0dfb5393d964f9cc9bad5c313709ea70f561ed3ea7b053075221d51696910d0d339585004b34272bff7213cc7a510a5454a3b349b1b206c1f0af490176745d4b +c663e2abb2b34b23da76f6352ba57ca2881844c1111ab189d8c7e07e1daaa04f40255c77988aa05fe06e4e5bdb4cb9c5394bbaf28d98c1d971ccd20867e556a7 +689ec9166e0a522183792b8907ba55ca6e943bbf2a26e52f48957218ffcf54d1fb09dc3eac04da033e5c0d0b8c74a6b43d2e54c4a10aa511f5fb021a07533b20 +5ae07e17a621a8e082dafc17e450ffb739676998b48643a4daa7211214f623150942f6a02c99e83b85583ddbbb2c4996113211551257a656ec1139246ca86be0 +aadedb3d1441a89b6a929501833b197fee7b9641a3503739e57c732a59b1f7da1cf8a73b1f9bcca0945b874d4393dbbf10b1680f66bbaa5d6f96e77b6f59113d +316bb31a795600b3d256d0cad2fe354538e7566b2bd69cc6cbcd5c38f0e2bcc63058344429dc2121fd07f63f2a7c66bf76e80d75c8f7a1b622f878a18941d840 +545fb28d07d205d20e8ea071b283369834296bdaac75d256cb37eb0bee740bbe278cad253b8bbfcf69eca23973d939b97891c6ce2cecd8da8e2d343578f6648a +c2d0383fc818c798cf64e52f597c740f1cbd05df0c264c49134cf09d4a60e8a107260f20f92d47b374e32f000000ffff0300504b030414000600080000002100 +0dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f7 +8277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89 +d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd500 +1996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0f +bfff0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6 +a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a +0000001c00000000000000000000000000190200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d00140006000800000021 +0030dd4329a8060000a41b00001600000000000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d001400060008 +00000021000dd1909fb60000001b0100002700000000000000000000000000b20900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000ad0a00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; +\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; +\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; +\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 +4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000f014 +bb3b4c41cf01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/ClassicShellLoc/English/Main.html b/ClassicShellLoc/English/Main.html new file mode 100644 index 0000000..9c1588c --- /dev/null +++ b/ClassicShellLoc/English/Main.html @@ -0,0 +1,49 @@ + + + + + + + + + + + Classic Shell + +

Classic Shell website  Classic Shell

+Version 4.3.1 – general release

+

What is Classic Shell?

+Classic Shell™ is a collection of usability enhancement for Windows. It +has a customizable Start menu and Start button, it adds a +toolbar for Windows Explorer and supports a variety of smaller features.
+
+
+

System Requirements

+Classic Shell works on Windows 7, Windows 8, Windows 8.1, Windows Server 2008 R2, +Windows Server 2012 and Windows Server 2012 R2. Both 32 and 64-bit versions are +supported (the same installer works for both). Some skins for the start menu +require Aero theme to be enabled. Others require at least Basic theme.
+
+
+

Components


+ +Classic Shell has three major components: +
+

Uninstallation

+You can uninstall Classic Shell from Control Panel -> Programs and Features. Another way is  to run the setup again and chose "Remove".
+A logoff may be required to complete the process.
+
+ \ No newline at end of file diff --git a/ClassicShellLoc/English/PolicyDefinitions.rtf b/ClassicShellLoc/English/PolicyDefinitions.rtf new file mode 100644 index 0000000..df3e2e0 --- /dev/null +++ b/ClassicShellLoc/English/PolicyDefinitions.rtf @@ -0,0 +1,270 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;} +{\f36\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} +{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} +{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f379\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f380\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;} +{\f382\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f383\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f386\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f387\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);} +{\f399\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\f400\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\f402\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\f403\fbidi \froman\fcharset162\fprq2 Cambria Tur;} +{\f406\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\f407\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\f409\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f417\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);} +{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;} +{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;} +{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} +{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}} +{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0; +\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red33\green121\blue142;\red45\green162\blue191;\red22\green80\blue94;\red64\green64\blue64;\red52\green52\blue52; +\caccentone\ctint255\cshade255\red79\green129\blue189;\ctextone\ctint127\cshade255\red128\green128\blue128;\caccenttwo\ctint255\cshade255\red192\green80\blue77;\caccentone\ctint255\cshade191\red54\green95\blue145; +\chyperlink\ctint255\cshade255\red0\green0\blue255;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ +\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\snext0 \sqformat \spriority0 \styrsid11172591 Normal;}{\s1\ql \li0\ri0\sb480\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs28\alang1025 \ltrch\fcs0 +\b\fs28\cf17\lang1033\langfe1033\loch\f36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink15 \sqformat \spriority9 \styrsid11172591 heading 1;}{\s2\ql \li0\ri0\sb200\sl276\slmult1 +\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs26\alang1025 \ltrch\fcs0 \b\fs26\cf18\lang1033\langfe1033\loch\f36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink16 \sunhideused \sqformat \spriority9 \styrsid11172591 heading 2;}{\s3\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel2\adjustright\rin0\lin0\itap0 \rtlch\fcs1 +\ab\af0\afs22\alang1025 \ltrch\fcs0 \b\fs22\cf18\lang1033\langfe1033\loch\f36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink17 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid11172591 heading 3;}{ +\s4\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel3\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\ai\af0\afs22\alang1025 \ltrch\fcs0 +\b\i\fs22\cf18\lang1033\langfe1033\loch\f36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink18 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid11172591 heading 4;}{\s5\ql \li0\ri0\sb200\sl276\slmult1 +\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel4\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\cf19\lang1033\langfe1033\loch\f36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink19 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid11172591 heading 5;}{\s6\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel5\adjustright\rin0\lin0\itap0 \rtlch\fcs1 +\ai\af0\afs22\alang1025 \ltrch\fcs0 \i\fs22\cf19\lang1033\langfe1033\loch\f36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink20 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid11172591 heading 6;}{ +\s7\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel6\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ai\af0\afs22\alang1025 \ltrch\fcs0 +\i\fs22\cf20\lang1033\langfe1033\loch\f36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink21 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid11172591 heading 7;}{\s8\ql \li0\ri0\sb200\sl276\slmult1 +\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel7\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs20\alang1025 \ltrch\fcs0 \fs20\cf18\lang1033\langfe1033\loch\f36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink22 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid11172591 heading 8;}{\s9\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel8\adjustright\rin0\lin0\itap0 \rtlch\fcs1 +\ai\af0\afs20\alang1025 \ltrch\fcs0 \i\fs20\cf20\lang1033\langfe1033\loch\f36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink23 \ssemihidden \sunhideused \sqformat \spriority9 \styrsid11172591 heading 9;}{\*\cs10 \additive +\ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused +Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \b\f36\fs28\cf17 \sbasedon10 \slink1 \slocked \spriority9 \styrsid11172591 Heading 1 Char;}{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \b\f36\fs26\cf18 +\sbasedon10 \slink2 \slocked \spriority9 \styrsid11172591 Heading 2 Char;}{\*\cs17 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \b\f36\cf18 \sbasedon10 \slink3 \slocked \ssemihidden \spriority9 \styrsid11172591 Heading 3 Char;}{\*\cs18 \additive \rtlch\fcs1 +\af0 \ltrch\fcs0 \b\i\f36\cf18 \sbasedon10 \slink4 \slocked \ssemihidden \spriority9 \styrsid11172591 Heading 4 Char;}{\*\cs19 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \f36\cf19 \sbasedon10 \slink5 \slocked \ssemihidden \spriority9 \styrsid11172591 +Heading 5 Char;}{\*\cs20 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \i\f36\cf19 \sbasedon10 \slink6 \slocked \ssemihidden \spriority9 \styrsid11172591 Heading 6 Char;}{\*\cs21 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \i\f36\cf20 +\sbasedon10 \slink7 \slocked \ssemihidden \spriority9 \styrsid11172591 Heading 7 Char;}{\*\cs22 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \f36\fs20\cf18 \sbasedon10 \slink8 \slocked \ssemihidden \spriority9 \styrsid11172591 Heading 8 Char;}{\*\cs23 +\additive \rtlch\fcs1 \af0 \ltrch\fcs0 \i\f36\fs20\cf20 \sbasedon10 \slink9 \slocked \ssemihidden \spriority9 \styrsid11172591 Heading 9 Char;}{\s24\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 +\af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext24 \sqformat \spriority1 \styrsid11172591 No Spacing;}{\s25\ql \li0\ri0\sa300\widctlpar\brdrb +\brdrs\brdrw20\brsp80\brdrcf18 \wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\contextualspace \rtlch\fcs1 \af0\afs52\alang1025 \ltrch\fcs0 +\fs52\expnd1\expndtw5\cf21\lang1033\langfe1033\kerning28\loch\f36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink26 \sqformat \spriority10 \styrsid11172591 Title;}{\*\cs26 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 +\f36\fs52\expnd1\expndtw5\cf21\kerning28 \sbasedon10 \slink25 \slocked \spriority10 \styrsid11172591 Title Char;}{\s27\ql \li0\ri0\sa200\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs18\alang1025 +\ltrch\fcs0 \b\fs18\cf22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \ssemihidden \sunhideused \sqformat \spriority35 \styrsid11172591 caption;}{\s28\ql \li0\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ilvl1\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ai\af0\afs24\alang1025 \ltrch\fcs0 \i\fs24\expnd3\expndtw15\cf18\lang1033\langfe1033\loch\f36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink29 \sqformat \spriority11 \styrsid11172591 Subtitle;}{\*\cs29 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \i\f36\fs24\expnd3\expndtw15\cf18 \sbasedon10 \slink28 \slocked \spriority11 \styrsid11172591 Subtitle Char;}{\*\cs30 \additive +\rtlch\fcs1 \af0 \ltrch\fcs0 \b \sbasedon10 \sqformat \spriority22 \styrsid11172591 Strong;}{\*\cs31 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \i \sbasedon10 \sqformat \spriority20 \styrsid11172591 Emphasis;}{\s32\ql \li720\ri0\sa200\sl276\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin720\itap0\contextualspace \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext32 \sqformat \spriority34 \styrsid11172591 List Paragraph;}{\s33\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ai\af0\afs22\alang1025 \ltrch\fcs0 +\i\fs22\cf1\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink34 \sqformat \spriority29 \styrsid11172591 Quote;}{\*\cs34 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \i\cf1 +\sbasedon10 \slink33 \slocked \spriority29 \styrsid11172591 Quote Char;}{\s35\ql \li936\ri936\sb200\sa280\sl276\slmult1\widctlpar\brdrb\brdrs\brdrw10\brsp80\brdrcf18 \wrapdefault\aspalpha\aspnum\faauto\adjustright\rin936\lin936\itap0 \rtlch\fcs1 +\ab\ai\af0\afs22\alang1025 \ltrch\fcs0 \b\i\fs22\cf18\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink36 \sqformat \spriority30 \styrsid11172591 Intense Quote;}{\*\cs36 \additive +\rtlch\fcs1 \af0 \ltrch\fcs0 \b\i\cf18 \sbasedon10 \slink35 \slocked \spriority30 \styrsid11172591 Intense Quote Char;}{\*\cs37 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \i\cf23 \sbasedon10 \sqformat \spriority19 \styrsid11172591 Subtle Emphasis;}{\*\cs38 +\additive \rtlch\fcs1 \af0 \ltrch\fcs0 \b\i\cf22 \sbasedon10 \sqformat \spriority21 \styrsid11172591 Intense Emphasis;}{\*\cs39 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \scaps\ul\cf24 \sbasedon10 \sqformat \spriority31 \styrsid11172591 Subtle Reference;}{\* +\cs40 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \b\scaps\ul\expnd1\expndtw5\cf24 \sbasedon10 \sqformat \spriority32 \styrsid11172591 Intense Reference;}{\*\cs41 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \b\scaps\expnd1\expndtw5 +\sbasedon10 \sqformat \spriority33 \styrsid11172591 Book Title;}{\s42\ql \li0\ri0\sb480\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs28\alang1025 \ltrch\fcs0 +\b\fs28\cf25\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 \sbasedon1 \snext0 \ssemihidden \sunhideused \sqformat \spriority39 \styrsid11172591 TOC Heading;}{\*\cs43 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 +\ul\cf26 \sbasedon10 \sunhideused \styrsid8683100 Hyperlink;}}{\*\rsidtbl \rsid87762\rsid1531249\rsid8026989\rsid8683100\rsid9571533\rsid11172591}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440 +\mintLim0\mnaryLim1}{\info{\operator Ivo}{\creatim\yr2013\mo12\dy8\hr14\min59}{\revtim\yr2014\mo4\dy18\hr7\min11}{\version4}{\edmins29}{\nofpages2}{\nofwords294}{\nofchars1677}{\nofcharsws1968}{\vern49167}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.co +m/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect +\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701 +\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot8026989 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 +\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 +\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\s25\ql \li0\ri0\sa300\widctlpar\brdrb\brdrs\brdrw20\brsp80\brdrcf18 \wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid11172591\contextualspace \rtlch\fcs1 \af0\afs52\alang1025 \ltrch\fcs0 +\fs52\expnd1\expndtw5\cf21\lang1033\langfe1033\kerning28\loch\af36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8026989 \hich\af36\dbch\af31505\loch\f36 +Classic Shell policy definitions}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid87762 +\par }\pard\plain \ltrpar\s24\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8026989 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8026989 +\par \hich\af31506\dbch\af31505\loch\f31506 The provided ADMX files can be used by administrators to adjust the settings for multiple users. +\par +\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid1531249 \rtlch\fcs1 \ab\af0\afs26\alang1025 \ltrch\fcs0 +\b\fs26\cf18\lang1033\langfe1033\loch\af36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid1531249 \hich\af36\dbch\af31505\loch\f36 Installation +\par }\pard\plain \ltrpar\s24\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8026989 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid1531249 +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8026989 \hich\af31506\dbch\af31505\loch\f31506 Copy the contents of}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid11172591 \hich\af31506\dbch\af31505\loch\f31506 the }{ +\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid11172591\charrsid11172591 \hich\af31506\dbch\af31505\loch\f31506 PolicyDefinitions}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid11172591 +\hich\af31506\dbch\af31505\loch\f31506 folder (i}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8026989 \hich\af31506\dbch\af31505\loch\f31506 ncluding the }{\rtlch\fcs1 \af0 \ltrch\fcs0 +\b\lang9\langfe1033\langnp9\insrsid8026989\charrsid11172591 \hich\af31506\dbch\af31505\loch\f31506 en-US}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8026989 \hich\af31506\dbch\af31505\loch\f31506 sub-folder) to }{\rtlch\fcs1 \af0 +\ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid8026989\charrsid11172591 \hich\af31506\dbch\af31505\loch\f31506 C:\\Windows\\PolicyDefinitions}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8026989 . +\par +\par \hich\af31506\dbch\af31505\loch\f31506 After that you will be able to use the }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid8026989\charrsid11172591 \hich\af31506\dbch\af31505\loch\f31506 gpedit.msc}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\lang9\langfe1033\langnp9\insrsid8026989 \hich\af31506\dbch\af31505\loch\f31506 tool edit the settings. They will show up under }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid8026989\charrsid11172591 +\hich\af31506\dbch\af31505\loch\f31506 Administrative Templates -> Classic Shell}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8026989 . +\par +\par }\pard \ltrpar\s24\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9571533 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid9571533 \hich\af31506\dbch\af31505\loch\f31506 To edit a setting, cha +\hich\af31506\dbch\af31505\loch\f31506 nge the policy from }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid9571533\charrsid9571533 \hich\af31506\dbch\af31505\loch\f31506 Not Configured}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\lang9\langfe1033\langnp9\insrsid9571533 \hich\af31506\dbch\af31505\loch\f31506 to }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid9571533\charrsid9571533 \hich\af31506\dbch\af31505\loch\f31506 Enabled}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\lang9\langfe1033\langnp9\insrsid9571533 \hich\af31506\dbch\af31505\loch\f31506 . Setting a policy to }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid9571533\charrsid9571533 \hich\af31506\dbch\af31505\loch\f31506 Disabled}{\rtlch\fcs1 +\af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid9571533 \hich\af31506\dbch\af31505\loch\f31506 is not supported and has no effect. +\par }\pard \ltrpar\s24\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8026989 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid9571533 +\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid1531249 \rtlch\fcs1 \ab\af0\afs26\alang1025 \ltrch\fcs0 +\b\fs26\cf18\lang1033\langfe1033\loch\af36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid1531249 \hich\af36\dbch\af31505\loch\f36 State}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\insrsid1531249\charrsid1531249 +\par }\pard\plain \ltrpar\s24\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8026989 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid1531249 +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8026989 \hich\af31506\dbch\af31505\loch\f31506 Each setting has 2 components \hich\f31506 \endash \loch\f31506 state and value. The state can be: +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid8026989 +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid8026989\charrsid8026989 \hich\af31506\dbch\af31505\loch\f31506 Locked to this value:}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8026989 +\hich\af31506\dbch\af31505\loch\f31506 The value you enter will be used for the setti\hich\af31506\dbch\af31505\loch\f31506 ng. Users will not be able to change the setting using the Settings dialog. +\par +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid8026989\charrsid8026989 \hich\af31506\dbch\af31505\loch\f31506 Locked to default:}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8026989 +\hich\af31506\dbch\af31505\loch\f31506 The setting will be locked to the default value determined by the software. The default value depends on the current OS version and configuration, current style\hich\af31506\dbch\af31505\loch\f31506 +, etc. The value you enter for the policy will be ignored. +\par +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid8026989\charrsid8026989 \hich\af31506\dbch\af31505\loch\f31506 Unlocked:}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8026989 \hich\af31506\dbch\af31505\loch\f31506 + The value you enter will be used to replace the default value of the setting. The users will be able to override the setting from the Settings dialog. +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid9571533 +\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid11172591 \rtlch\fcs1 \ab\af0\afs26\alang1025 \ltrch\fcs0 +\b\fs26\cf18\lang1033\langfe1033\loch\af36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid11172591 \hich\af36\dbch\af31505\loch\f36 Precedence}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\lang9\langfe1033\langnp9\insrsid8026989 +\par }\pard\plain \ltrpar\s24\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8026989 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid11172591 +\par \hich\af31506\dbch\af31505\loch\f31506 There are 4 places whe\hich\af31506\dbch\af31505\loch\f31506 re Classic Shell looks for settings. In order of precedence they are: +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid11172591\charrsid11172591 \hich\af31506\dbch\af31505\loch\f31506 HKLM\\Software\\Policies\\IvoSoft}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid11172591 +\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 \endash \loch\f31506 this is where the Computer Configuration policies are stored +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid11172591\charrsid11172591 \hich\af31506\dbch\af31505\loch\f31506 HKLM\\Software\\IvoSoft}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid11172591 +\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 \endash \loch\f31506 this is where you can manually store settings for all users +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid11172591\charrsid11172591 \hich\af31506\dbch\af31505\loch\f31506 HKCU\\\hich\af31506\dbch\af31505\loch\f31506 Software\\Policies\\IvoSoft}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\lang9\langfe1033\langnp9\insrsid11172591 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 \endash \loch\f31506 this is where the User Configuration policies are stored +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid11172591\charrsid11172591 \hich\af31506\dbch\af31505\loch\f31506 HKCU\\Software\\IvoSoft}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid11172591 +\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 \endash \loch\f31506 this is where the Settings dialog stores the per-user setting +\par +\par \hich\af31506\dbch\af31505\loch\f31506 If a setting is locked in any of the first 3 locations, it will be grayed out in the\hich\af31506\dbch\af31505\loch\f31506 Settings dialog and users can\hich\f31506 \rquote \loch\f31506 t change it. +\par +\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8683100 +\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb200\sl276\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid8683100 \rtlch\fcs1 \ab\af0\afs26\alang1025 \ltrch\fcs0 +\b\fs26\cf18\lang1033\langfe1033\loch\af36\hich\af36\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8683100 \hich\af36\dbch\af31505\loch\f36 Localization +\par }\pard\plain \ltrpar\s24\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8026989 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8683100 +\par }\pard \ltrpar\s24\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8683100 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8683100 \hich\af31506\dbch\af31505\loch\f31506 +You can download translations for the group policy settings\hich\af31506\dbch\af31505\loch\f31506 . }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8683100 \hich\af31506\dbch\af31505\loch\f31506 Look for the file }{\rtlch\fcs1 \af0 +\ltrch\fcs0 \b\lang9\langfe1033\langnp9\insrsid8683100\charrsid8683100 \hich\af31506\dbch\af31505\loch\f31506 PolicyDefinitions.zip}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8683100 +\par }\pard \ltrpar\s24\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8026989 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8683100 \hich\af31506\dbch\af31505\loch\f31506 here: } +{\field{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8683100 \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 HYPERLINK \hich\af31506\dbch\af31505\loch\f31506 "}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\lang9\langfe1033\langnp9\insrsid8683100\charrsid8683100 \hich\af31506\dbch\af31505\loch\f31506 http://www.classicshell.net/translations/}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8683100 \hich\af31506\dbch\af31505\loch\f31506 " +\hich\af31506\dbch\af31505\loch\f31506 }}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs43\ul\cf26\lang9\langfe1033\langnp9\insrsid8683100\charrsid5201726 \hich\af31506\dbch\af31505\loch\f31506 http://www.classicshell.net/translations/}}}\sectd \ltrsect +\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang9\langfe1033\langnp9\insrsid8683100 +\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a +9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad +5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 +b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 +0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 +a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f +c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 +0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 +a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 +6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b +4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b +4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210030dd4329a8060000a41b0000160000007468656d652f7468656d652f +7468656d65312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87 +615b8116d8a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad +79482a9c0498f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b +5d8a314d3c94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab +999fb7b4717509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9 +699640f6719e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd586 +8b37a088d1e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d6 +0cf03ac1a5193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f +9e7ef3f2d117d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be +15c308d3f28acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a9979 +3849c26ae66252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d +32a423279a668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2a +f074481847bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86 +e877f0034e16bafb0e258ebb4faf06b769e888340b103d331115bebc4eb813bf83291b63624a0d1475a756c734f9bbc2cd28546ecbe1e20a3794ca175f3fae90 +fb6d2dd99bb07b55e5ccf68942bd0877b23c77b908e8db5f9db7f024d9239010f35bd4bbe2fcae387bfff9e2bc289f2fbe24cfaa301468dd8bd846dbb4ddf1c2 +ae7b4c191ba8292337a469bc25ec3d411f06f53a73e224c5292c8de0516732307070a1c0660d125c7d44553488700a4d7bddd3444299910e254ab984c3a219ae +a4adf1d0f82b7bd46cea4388ad1c12ab5d1ed8e1153d9c9f350a3246aad01c6873462b9ac05999ad5cc988826eafc3acae853a33b7ba11cd1445875ba1b236b1 +399483c90bd560b0b0263435085a21b0f22a9cf9356b38ec6046026d77eba3dc2dc60b17e92219e180643ed27acffba86e9c94c7ca9c225a0f1b0cfae0788ad5 +4adc5a9aec1b703b8b93caec1a0bd8e5de7b132fe5113cf312503b998e2c2927274bd051db6b35979b1ef271daf6c6704e86c73805af4bdd476216c26593af84 +0dfb5393d964f9cc9bad5c313709ea70f561ed3ea7b053075221d51696910d0d339585004b34272bff7213cc7a510a5454a3b349b1b206c1f0af490176745d4b +c663e2abb2b34b23da76f6352ba57ca2881844c1111ab189d8c7e07e1daaa04f40255c77988aa05fe06e4e5bdb4cb9c5394bbaf28d98c1d971ccd20867e556a7 +689ec9166e0a522183792b8907ba55ca6e943bbf2a26e52f48957218ffcf54d1fb09dc3eac04da033e5c0d0b8c74a6b43d2e54c4a10aa511f5fb021a07533b20 +5ae07e17a621a8e082dafc17e450ffb739676998b48643a4daa7211214f623150942f6a02c99e83b85583ddbbb2c4996113211551257a656ec1139246ca86be0 +aadedb3d1441a89b6a929501833b197fee7b9641a3503739e57c732a59b1f7da1cf8a73b1f9bcca0945b874d4393dbbf10b1680f66bbaa5d6f96e77b6f59113d +316bb31a795600b3d256d0cad2fe354538e7566b2bd69cc6cbcd5c38f0e2bcc63058344429dc2121fd07f63f2a7c66bf76e80d75c8f7a1b622f878a18941d840 +545fb28d07d205d20e8ea071b283369834296bdaac75d256cb37eb0bee740bbe278cad253b8bbfcf69eca23973d939b97891c6ce2cecd8da8e2d343578f6648a +c2d0383fc818c798cf64e52f597c740f1cbd05df0c264c49134cf09d4a60e8a107260f20f92d47b374e32f000000ffff0300504b030414000600080000002100 +0dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f7 +8277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89 +d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd500 +1996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0f +bfff0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6 +a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a +0000001c00000000000000000000000000190200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d00140006000800000021 +0030dd4329a8060000a41b00001600000000000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d001400060008 +00000021000dd1909fb60000001b0100002700000000000000000000000000b20900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000ad0a00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; +\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; +\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; +\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 +4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000d0ca +1027105bcf01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/ClassicShellLoc/English/en-US.csv b/ClassicShellLoc/English/en-US.csv new file mode 100644 index 0000000..a9fbd94 Binary files /dev/null and b/ClassicShellLoc/English/en-US.csv differ diff --git a/ClassicShellLoc/English/en-US.dll b/ClassicShellLoc/English/en-US.dll new file mode 100644 index 0000000..133cc6f Binary files /dev/null and b/ClassicShellLoc/English/en-US.dll differ diff --git a/ClassicShellLoc/English/images/ClassicShell.png b/ClassicShellLoc/English/images/ClassicShell.png new file mode 100644 index 0000000..1c17868 Binary files /dev/null and b/ClassicShellLoc/English/images/ClassicShell.png differ diff --git a/ClassicShellLoc/English/images/acc_locked.png b/ClassicShellLoc/English/images/acc_locked.png new file mode 100644 index 0000000..0dd5dc9 Binary files /dev/null and b/ClassicShellLoc/English/images/acc_locked.png differ diff --git a/ClassicShellLoc/English/images/after.png b/ClassicShellLoc/English/images/after.png new file mode 100644 index 0000000..bdb89f9 Binary files /dev/null and b/ClassicShellLoc/English/images/after.png differ diff --git a/ClassicShellLoc/English/images/before.png b/ClassicShellLoc/English/images/before.png new file mode 100644 index 0000000..62f32e9 Binary files /dev/null and b/ClassicShellLoc/English/images/before.png differ diff --git a/ClassicShellLoc/English/images/button_images.png b/ClassicShellLoc/English/images/button_images.png new file mode 100644 index 0000000..e8bfa32 Binary files /dev/null and b/ClassicShellLoc/English/images/button_images.png differ diff --git a/ClassicShellLoc/English/images/button_settings.png b/ClassicShellLoc/English/images/button_settings.png new file mode 100644 index 0000000..8dcb650 Binary files /dev/null and b/ClassicShellLoc/English/images/button_settings.png differ diff --git a/ClassicShellLoc/English/images/customize_menu.png b/ClassicShellLoc/English/images/customize_menu.png new file mode 100644 index 0000000..ef06aab Binary files /dev/null and b/ClassicShellLoc/English/images/customize_menu.png differ diff --git a/ClassicShellLoc/English/images/explorer_settings.png b/ClassicShellLoc/English/images/explorer_settings.png new file mode 100644 index 0000000..d1d2c15 Binary files /dev/null and b/ClassicShellLoc/English/images/explorer_settings.png differ diff --git a/ClassicShellLoc/English/images/ie9_caption.png b/ClassicShellLoc/English/images/ie9_caption.png new file mode 100644 index 0000000..5d853f7 Binary files /dev/null and b/ClassicShellLoc/English/images/ie9_caption.png differ diff --git a/ClassicShellLoc/English/images/ie9_settings.png b/ClassicShellLoc/English/images/ie9_settings.png new file mode 100644 index 0000000..47342d5 Binary files /dev/null and b/ClassicShellLoc/English/images/ie9_settings.png differ diff --git a/ClassicShellLoc/English/images/ie9_status.png b/ClassicShellLoc/English/images/ie9_status.png new file mode 100644 index 0000000..ebfb297 Binary files /dev/null and b/ClassicShellLoc/English/images/ie9_status.png differ diff --git a/ClassicShellLoc/English/images/item_settings.png b/ClassicShellLoc/English/images/item_settings.png new file mode 100644 index 0000000..d978eb3 Binary files /dev/null and b/ClassicShellLoc/English/images/item_settings.png differ diff --git a/ClassicShellLoc/English/images/menu_settings.png b/ClassicShellLoc/English/images/menu_settings.png new file mode 100644 index 0000000..6d99c16 Binary files /dev/null and b/ClassicShellLoc/English/images/menu_settings.png differ diff --git a/ClassicShellLoc/English/images/search1.png b/ClassicShellLoc/English/images/search1.png new file mode 100644 index 0000000..9c3b512 Binary files /dev/null and b/ClassicShellLoc/English/images/search1.png differ diff --git a/ClassicShellLoc/English/images/search2.png b/ClassicShellLoc/English/images/search2.png new file mode 100644 index 0000000..049f69e Binary files /dev/null and b/ClassicShellLoc/English/images/search2.png differ diff --git a/ClassicShellLoc/English/images/search3.png b/ClassicShellLoc/English/images/search3.png new file mode 100644 index 0000000..9de67eb Binary files /dev/null and b/ClassicShellLoc/English/images/search3.png differ diff --git a/ClassicShellLoc/English/images/settings1.png b/ClassicShellLoc/English/images/settings1.png new file mode 100644 index 0000000..fbbb6ff Binary files /dev/null and b/ClassicShellLoc/English/images/settings1.png differ diff --git a/ClassicShellLoc/English/images/settings2.png b/ClassicShellLoc/English/images/settings2.png new file mode 100644 index 0000000..45c8d55 Binary files /dev/null and b/ClassicShellLoc/English/images/settings2.png differ diff --git a/ClassicShellLoc/English/images/settings3.png b/ClassicShellLoc/English/images/settings3.png new file mode 100644 index 0000000..c72ae67 Binary files /dev/null and b/ClassicShellLoc/English/images/settings3.png differ diff --git a/ClassicShellLoc/English/images/settings4.png b/ClassicShellLoc/English/images/settings4.png new file mode 100644 index 0000000..a2ebb4a Binary files /dev/null and b/ClassicShellLoc/English/images/settings4.png differ diff --git a/ClassicShellLoc/English/images/settings5.png b/ClassicShellLoc/English/images/settings5.png new file mode 100644 index 0000000..f4b0c0c Binary files /dev/null and b/ClassicShellLoc/English/images/settings5.png differ diff --git a/ClassicShellLoc/English/images/settings_disable_ex.png b/ClassicShellLoc/English/images/settings_disable_ex.png new file mode 100644 index 0000000..4bb572d Binary files /dev/null and b/ClassicShellLoc/English/images/settings_disable_ex.png differ diff --git a/ClassicShellLoc/English/images/settings_disable_ie9.png b/ClassicShellLoc/English/images/settings_disable_ie9.png new file mode 100644 index 0000000..352b100 Binary files /dev/null and b/ClassicShellLoc/English/images/settings_disable_ie9.png differ diff --git a/ClassicShellLoc/English/images/settings_disable_sm.png b/ClassicShellLoc/English/images/settings_disable_sm.png new file mode 100644 index 0000000..d65b65a Binary files /dev/null and b/ClassicShellLoc/English/images/settings_disable_sm.png differ diff --git a/ClassicShellLoc/English/images/skins.gif b/ClassicShellLoc/English/images/skins.gif new file mode 100644 index 0000000..c9a26cf Binary files /dev/null and b/ClassicShellLoc/English/images/skins.gif differ diff --git a/ClassicShellLoc/English/images/statusbar.png b/ClassicShellLoc/English/images/statusbar.png new file mode 100644 index 0000000..e9cfc00 Binary files /dev/null and b/ClassicShellLoc/English/images/statusbar.png differ diff --git a/ClassicShellLoc/English/images/style1.png b/ClassicShellLoc/English/images/style1.png new file mode 100644 index 0000000..02cf5be Binary files /dev/null and b/ClassicShellLoc/English/images/style1.png differ diff --git a/ClassicShellLoc/English/images/style2.png b/ClassicShellLoc/English/images/style2.png new file mode 100644 index 0000000..9bbd1d1 Binary files /dev/null and b/ClassicShellLoc/English/images/style2.png differ diff --git a/ClassicShellLoc/English/images/style3.png b/ClassicShellLoc/English/images/style3.png new file mode 100644 index 0000000..67a4f0f Binary files /dev/null and b/ClassicShellLoc/English/images/style3.png differ diff --git a/ClassicShellLoc/English/images/titlebar.png b/ClassicShellLoc/English/images/titlebar.png new file mode 100644 index 0000000..bbad38b Binary files /dev/null and b/ClassicShellLoc/English/images/titlebar.png differ diff --git a/ClassicShellLoc/English/images/toolbar.png b/ClassicShellLoc/English/images/toolbar.png new file mode 100644 index 0000000..7a23fbe Binary files /dev/null and b/ClassicShellLoc/English/images/toolbar.png differ diff --git a/ClassicShellLoc/English/images/toolbar_settings.png b/ClassicShellLoc/English/images/toolbar_settings.png new file mode 100644 index 0000000..93416f2 Binary files /dev/null and b/ClassicShellLoc/English/images/toolbar_settings.png differ diff --git a/ClassicShellLoc/English/images/up_locked.png b/ClassicShellLoc/English/images/up_locked.png new file mode 100644 index 0000000..e1284d8 Binary files /dev/null and b/ClassicShellLoc/English/images/up_locked.png differ diff --git a/ClassicShellLoc/ExplorerL10N.ini b/ClassicShellLoc/ExplorerL10N.ini new file mode 100644 index 0000000..0baeeea --- /dev/null +++ b/ClassicShellLoc/ExplorerL10N.ini @@ -0,0 +1,2599 @@ +; This file contains all localized text for Classic Explorer. There is one section per language. +; Every section contains text lines in the form of = . +; Which section is used depends on the current OS setting. If a key is missing from the language section +; it will be searched in the [default] section. In some cases more than one language can be used. +; For example a Japanese system may use English as a secondary language. In that case the search order +; will be [ja-JP] -> [en-US] -> [default]. +; +; ============================================================================= + + +[default] +Toolbar.Settings = Classic Explorer Settings + + +[ar-SA] - Arabic (Saudi Arabia) +Copy.Cancel = إلغاء الأمر +Copy.More = المزيد... +Copy.CopyHere = ن&سخ إلى هذا الموضع +Copy.MoveHere = ن&قل إلى هذا الموضع +Copy.Title = تأكيد استبدال الملف +Copy.Subtitle = يحتوي هذا المجلد على ملف باسم '%s'. +Copy.SubtitleRO = يحتوي هذا المجلد على ملف للقراءة فقط باسم '‎%s'. +Copy.SubtitleSys = يحتوي هذا المجلد مسبقاً على ملف نظام باسم '‎%s'. +Copy.Prompt1 = ‏‏هل تريد استبدال الملف الموجود +Copy.Prompt2 = بهذا؟ +Copy.Yes = &نعم +Copy.No = &لا +Copy.YesAll = نعم لل&كل +Folder.Title = تأكيد استبدال المجلد +Folder.Prompt = هل ما زلت تريد نقل المجلد أو نسخه؟ +Toolbar.GoUp = مستوى واحد لأعلى +Toolbar.Cut = قص +Toolbar.Copy = نسخ +Toolbar.Paste = لصق +Toolbar.PasteShortcut = لصق الاختصار +Toolbar.Delete = حذف +Toolbar.Email = إرسال العناصر المحددة بالبريد الإلكتروني +Toolbar.Properties = خصائص +Toolbar.NewFolder = مجلد جديد +Toolbar.ZipFolder = مجلد جديد مضغوط +Toolbar.ExtraLarge = رموز كبيرة جداً +Toolbar.Large = رموز كبيرة +Toolbar.Medium = رموز متوسطة +Toolbar.Small = رموز صغيرة +Toolbar.List = قائمة +Toolbar.Details = تفاصيل +Toolbar.Tiles = مربعات +Toolbar.Content = محتوى +Toolbar.Undo = تراجع +Toolbar.Redo = إعادة +Toolbar.Refresh = تحديث +Toolbar.Back = الخلف +Toolbar.Forward = الأمام +Toolbar.Stop = إيقاف +Toolbar.Rename = إعادة تسمية +Toolbar.SelectAll = تحديد الكل +Toolbar.CustomizeFolder = تخصيص هذا المجلد +Toolbar.MapDrive = تعيين محرك أقراص الشبكة +Toolbar.DisconnectDrive = قطع اتصال محرك أقراص الشبكة +Toolbar.NavigationPane = جزء التنقل +Toolbar.DetailsPane = جزء التفاصيل +Toolbar.PreviewPane = جزء المعاينة +Toolbar.CopyTo = نسخ إلى +Toolbar.MoveTo = نقل إلى +Toolbar.Deselect = بلا تحديد +Toolbar.InvertSelection = عكس التحديد +Toolbar.FolderOptions = خيارات المجلد +Toolbar.ShowHiddenFiles = الملفات والمجلدات المخفية +Toolbar.ShowSystemFiles = ملفات النظام +Toolbar.ShowExtensions = ملحقات أسماء الملفات +Status.FreeSpace = ‎%s (مساحة القرص الحرة: ‎%s) +Status.Item = عنصر %s +Status.Items = ‎‎%s عنصر/عناصر +Status.ItemSelected = %s عنصر محدد +Status.ItemsSelected = %s عنصر/عناصر محددة + + +[bg-BG] - Bulgarian (Bulgaria) +Copy.Cancel = Отказ +Copy.More = Още... +Copy.CopyHere = &Копирай тук +Copy.MoveHere = Пр&емести тук +Copy.Title = Потвърждаване на заместването на файл +Copy.Subtitle = Тази папка вече съдържа файл с име '%s'. +Copy.SubtitleRO = Тази папка вече съдържа файл само за четене с име '%s'. +Copy.SubtitleSys = Тази папка вече съдържа системен файл с име '%s'. +Copy.Prompt1 = Желаете ли да заместите съществуващия файл +Copy.Prompt2 = с този? +Copy.Yes = &Да +Copy.No = &Не +Copy.YesAll = "Да" за &всички +Folder.Title = Потвърждаване на заместването на папка +Folder.Prompt = Все още ли искате да преместите или копирате папката? +Toolbar.GoUp = Едно ниво нагоре +Toolbar.Cut = Изрежи +Toolbar.Copy = Копирай +Toolbar.Paste = Постави +Toolbar.PasteShortcut = Постави пряк път +Toolbar.Delete = Изтриване +Toolbar.Email = Изпрати избраните елементи по електронната поща +Toolbar.Properties = Свойства +Toolbar.NewFolder = Нова папка +Toolbar.ZipFolder = Нова компресирана със ZIP папка +Toolbar.ExtraLarge = Много големи икони +Toolbar.Large = Големи икони +Toolbar.Medium = Средни икони +Toolbar.Small = Малки икони +Toolbar.List = Списък +Toolbar.Details = Детайли +Toolbar.Tiles = Мозайка +Toolbar.Content = Съдържание +Toolbar.Undo = Отмени +Toolbar.Redo = Върни +Toolbar.Refresh = Обнови +Toolbar.Back = Назад +Toolbar.Forward = Напред +Toolbar.Stop = Спри +Toolbar.Rename = Преименуване +Toolbar.SelectAll = Избери всички +Toolbar.CustomizeFolder = Персонализиране на тази папка +Toolbar.MapDrive = Назначаване на мрежово устройство +Toolbar.DisconnectDrive = Изключване на мрежово устройство +Toolbar.NavigationPane = Навигационен екран +Toolbar.DetailsPane = Екран за подробни данни +Toolbar.PreviewPane = Прозорец за визуализация +Toolbar.CopyTo = Копирай в +Toolbar.MoveTo = Премести в +Toolbar.Deselect = Не избирай нищо +Toolbar.InvertSelection = Обърни селекцията +Toolbar.FolderOptions = Опции за папката +Toolbar.ShowHiddenFiles = Скрити файлове и папки +Toolbar.ShowSystemFiles = Системни файлове +Toolbar.ShowExtensions = Разширения на имената на файлове +Status.FreeSpace = %s (Свободно място на диска: %s) +Status.Item = %s елемент +Status.Items = %s елемента +Status.ItemSelected = %s избран елемент +Status.ItemsSelected = %s избрани елемента + + +[ca-ES] - Catalan (Catalan) +Copy.Cancel = Cancel·lar +Copy.More = Més... +Copy.CopyHere = &Copiar aquí +Copy.MoveHere = &Moure aquí +Copy.Title = Confirmar la substitució de l'arxiu +Copy.Subtitle = Aquesta carpeta ja conté un arxiu amb el nom "%s". +Copy.SubtitleRO = Aquesta carpeta ja conté un arxiu de sols lectura amb el nom "%s". +Copy.SubtitleSys = Aquesta carpeta ja conté un arxiu de sistema amb el nom "%s". +Copy.Prompt1 = Desitja substituir l'arxiu existent +Copy.Prompt2 = per aquest altre? +Copy.Yes = &Sí +Copy.No = &No +Copy.YesAll = Sí a &tot +Folder.Title = Confirmar la substitució de carpetes +Folder.Prompt = Desitja moure o copiar la carpeta de totes maneres? +Toolbar.GoUp = Pujar un nivell +Toolbar.Cut = Retallar +Toolbar.Copy = Copiar +Toolbar.Paste = Enganxar +Toolbar.PasteShortcut = Enganxar accés directe +Toolbar.Delete = Suprimeix +Toolbar.Email = Enviar per correu electrònic els elements següents +Toolbar.Properties = Propietats +Toolbar.NewFolder = Nova carpeta +Toolbar.ZipFolder = Carpeta comprimida (en zip) nova +Toolbar.ExtraLarge = Icones molt grans +Toolbar.Large = Icones grans +Toolbar.Medium = Icones mitjanes +Toolbar.Small = Icones petites +Toolbar.List = Llista +Toolbar.Details = Detalls +Toolbar.Tiles = Mosaics +Toolbar.Content = Contingut +Toolbar.Undo = Desfer +Toolbar.Redo = Refer +Toolbar.Refresh = Actualitzar +Toolbar.Back = Enrera +Toolbar.Forward = Endavant +Toolbar.Stop = Aturar +Toolbar.Rename = Cambiar nom +Toolbar.SelectAll = Seleccionar tot +Toolbar.CustomizeFolder = Personalitzar aquesta carpeta +Toolbar.MapDrive = Conectar a unitat de xarxa +Toolbar.DisconnectDrive = Desconectar unitat de xarxa +Toolbar.NavigationPane = Panell de navegació +Toolbar.DetailsPane = Panell de detalls +Toolbar.PreviewPane = Panell de vista prèvia +Toolbar.CopyTo = Copia a +Toolbar.MoveTo = Desplaça a +Toolbar.Deselect = No en seleccionis cap +Toolbar.InvertSelection = Inverteix la selecció +Toolbar.FolderOptions = Opcions de carpeta +Toolbar.ShowHiddenFiles = Fitxers i carpetes amagats +Toolbar.ShowSystemFiles = Fitxers del sistema +Toolbar.ShowExtensions = Extensions del nom de fitxer +Toolbar.Settings = Ajustaments del Classic Explorer +Status.FreeSpace = %s (espai disponible en disc: %s) +Status.Item = %s element +Status.Items = %s elements +Status.ItemSelected = %s element seleccionat +Status.ItemsSelected = %s elements seleccionats + + +[cs-CZ] - Czech (Czech Republic) +Copy.Cancel = Storno +Copy.More = Další... +Copy.CopyHere = &Kopírovat sem +Copy.MoveHere = &Přesunout sem +Copy.Title = Potvrdit nahrazení souboru +Copy.Subtitle = Tato složka již obsahuje soubor s názvem %s. +Copy.SubtitleRO = Tato složka již obsahuje soubor jen pro čtení s názvem %s. +Copy.SubtitleSys = Tato složka již obsahuje systémový soubor s názvem %s. +Copy.Prompt1 = Chcete nahradit stávající soubor +Copy.Prompt2 = tímto souborem? +Copy.Yes = &Ano +Copy.No = &Ne +Copy.YesAll = Ano vš&em +Folder.Title = Potvrdit nahrazení složky +Folder.Prompt = Opravdu chcete přesunout nebo zkopírovat tuto složku? +Toolbar.GoUp = O úroveň výš +Toolbar.Cut = Vyjmout +Toolbar.Copy = Kopírovat +Toolbar.Paste = Vložit +Toolbar.PasteShortcut = Vložit zástupce +Toolbar.Delete = Odstranit +Toolbar.Email = Odešle vybrané položky e-mailem +Toolbar.Properties = Vlastnosti +Toolbar.NewFolder = Nová složka +Toolbar.ZipFolder = Nová komprimovaná složka (metoda ZIP) +Toolbar.ExtraLarge = Největší ikony +Toolbar.Large = Velké ikony +Toolbar.Medium = Střední ikony +Toolbar.Small = Malé ikony +Toolbar.List = Seznam +Toolbar.Details = Podrobnosti +Toolbar.Tiles = Dlaždice +Toolbar.Content = Obsah +Toolbar.Undo = Zpět +Toolbar.Redo = Znovu +Toolbar.Refresh = Aktualizovat +Toolbar.Back = Zpět +Toolbar.Forward = Vpřed +Toolbar.Stop = Zastavit +Toolbar.Rename = Přejmenovat +Toolbar.SelectAll = Vybrat vše +Toolbar.CustomizeFolder = Vlastní nastavení této složky +Toolbar.MapDrive = Připojit síťovou jednotku +Toolbar.DisconnectDrive = Odpojit síťovou jednotku +Toolbar.NavigationPane = Navigační podokno +Toolbar.DetailsPane = Podokno podrobností +Toolbar.PreviewPane = Podokno náhledu +Toolbar.CopyTo = Kopírovat do +Toolbar.MoveTo = Přesunout do +Toolbar.Deselect = Zrušit výběr +Toolbar.InvertSelection = Invertovat výběr +Toolbar.FolderOptions = Možnosti složky +Toolbar.ShowHiddenFiles = Skryté soubory a složky +Toolbar.ShowSystemFiles = Systémové soubory +Toolbar.ShowExtensions = Přípony názvů souborů +Status.FreeSpace = %s (volné místo na disku: %s) +Status.Item = %s položka +Status.Items = Počet položek: %s +Status.ItemSelected = %s vybraná položka +Status.ItemsSelected = Vybrané položky: %s + + +[da-DK] - Danish (Denmark) +Copy.Cancel = Annuller +Copy.More = Flere... +Copy.CopyHere = &Kopier hertil +Copy.MoveHere = &Flyt hertil +Copy.Title = Bekræft erstatning af fil +Copy.Subtitle = Denne mappe indeholder allerede en fil med navnet '%s'. +Copy.SubtitleRO = Denne mappe indeholder allerede en skrivebeskyttet fil med navnet '%s'. +Copy.SubtitleSys = Denne mappe indeholder allerede en systemfil med navnet '%s'. +Copy.Prompt1 = Vil du erstatte den eksisterende fil +Copy.Prompt2 = med denne fil? +Copy.Yes = &Ja +Copy.No = &Nej +Copy.YesAll = J&a til alle +Folder.Title = Bekræft erstatning af mappe +Folder.Prompt = Vil du flytte mappen alligevel? +Toolbar.GoUp = Et niveau op +Toolbar.Cut = Klip +Toolbar.Copy = Kopier +Toolbar.Paste = Sæt ind +Toolbar.PasteShortcut = Indsæt genvej +Toolbar.Delete = Slet +Toolbar.Email = Send de markerede elementer med e-mail +Toolbar.Properties = Egenskaber +Toolbar.NewFolder = Ny mappe +Toolbar.ZipFolder = Ny ZIP-komprimeret mappe +Toolbar.ExtraLarge = Ekstra store ikoner +Toolbar.Large = Store ikoner +Toolbar.Medium = Mellemstore ikoner +Toolbar.Small = Små ikoner +Toolbar.List = Oversigt +Toolbar.Details = Detaljer +Toolbar.Tiles = Fliser +Toolbar.Content = Indhold +Toolbar.Undo = Fortryd +Toolbar.Redo = Annuller Fortryd +Toolbar.Refresh = Opdater +Toolbar.Back = Tilbage +Toolbar.Forward = Fremad +Toolbar.Stop = Stop +Toolbar.Rename = Omdøb +Toolbar.SelectAll = Marker alt +Toolbar.CustomizeFolder = Tilpas denne mappe +Toolbar.MapDrive = Tilknyt netværksdrev +Toolbar.DisconnectDrive = Afbryd forbindelsen til et netværksdrev +Toolbar.NavigationPane = Navigationsrude +Toolbar.DetailsPane = Detaljerude +Toolbar.PreviewPane = Indholdsrude +Toolbar.CopyTo = Kopiér til +Toolbar.MoveTo = Flyt til +Toolbar.Deselect = Vælg ingen +Toolbar.InvertSelection = Inverter markeringen +Toolbar.FolderOptions = Mappeindstillinger +Toolbar.ShowHiddenFiles = Skjulte filer og mapper +Toolbar.ShowSystemFiles = Systemfiler +Toolbar.ShowExtensions = Filtypenavne +Status.FreeSpace = %s (ledig diskplads: %s) +Status.Item = %s element +Status.Items = %s elementer +Status.ItemSelected = %s markeret element +Status.ItemsSelected = %s markerede elementer + + +[de-DE] - German (Germany) +Copy.Cancel = Abbrechen +Copy.More = Weitere... +Copy.CopyHere = Hierher &kopieren +Copy.MoveHere = Hierher &verschieben +Copy.Title = Ersetzen von Dateien bestätigen +Copy.Subtitle = Dieser Ordner enthält bereits eine Datei "%s". +Copy.SubtitleRO = Der Ordner enthält bereits eine schreibgeschützte Datei "%s". +Copy.SubtitleSys = Der Ordner enthält bereits eine Systemdatei "%s". +Copy.Prompt1 = Möchten Sie die existierende Datei +Copy.Prompt2 = mit dieser ersetzen? +Copy.Yes = &Ja +Copy.No = &Nein +Copy.YesAll = Ja, &alle +Folder.Title = Ersetzen von Ordnern bestätigen +Folder.Prompt = Soll der Ordner trotzdem verschoben bzw. kopiert werden? +Toolbar.GoUp = Eine Ebene nach oben +Toolbar.Cut = Ausschneiden +Toolbar.Copy = Kopieren +Toolbar.Paste = Einfügen +Toolbar.PasteShortcut = Verknüpfung einfügen +Toolbar.Delete = Löschen +Toolbar.Email = Ausgewählte Elemente in E-Mail senden +Toolbar.Properties = Eigenschaften +Toolbar.NewFolder = Neuer Ordner +Toolbar.ZipFolder = Neuer ZIP-komprimierter Ordner +Toolbar.ExtraLarge = Extra große Symbole +Toolbar.Large = Große Symbole +Toolbar.Medium = Mittelgroße Symbole +Toolbar.Small = Kleine Symbole +Toolbar.List = Liste +Toolbar.Details = Details +Toolbar.Tiles = Kacheln +Toolbar.Content = Inhalt +Toolbar.Undo = Rückgängig +Toolbar.Redo = Wiederholen +Toolbar.Refresh = Aktualisieren +Toolbar.Back = Zurück +Toolbar.Forward = Vorwärts +Toolbar.Stop = Beenden +Toolbar.Rename = Umbenennen +Toolbar.SelectAll = Alles auswählen +Toolbar.CustomizeFolder = Ordner anpassen +Toolbar.MapDrive = Netzlaufwerk verbinden +Toolbar.DisconnectDrive = Netzlaufwerk trennen +Toolbar.NavigationPane = Navigationsbereich +Toolbar.DetailsPane = Detailbereich +Toolbar.PreviewPane = Vorschaufenster +Toolbar.CopyTo = Kopieren nach +Toolbar.MoveTo = Verschieben nach +Toolbar.Deselect = Nichts auswählen +Toolbar.InvertSelection = Auswahl umkehren +Toolbar.FolderOptions = Ordneroptionen +Toolbar.ShowHiddenFiles = Versteckte Dateien und Ordner +Toolbar.ShowSystemFiles = Systemdateien +Toolbar.ShowExtensions = Dateinamenerweiterungen +Status.FreeSpace = %s (Freier Speicherplatz: %s) +Status.Item = %s Element +Status.Items = %s Elemente +Status.ItemSelected = %s Element ausgewählt +Status.ItemsSelected = %s Elemente ausgewählt + + +[el-GR] - Greek (Greece) +Copy.Cancel = Άκυρο +Copy.More = Περισσότερα... +Copy.CopyHere = &Αντιγραφή εδώ +Copy.MoveHere = &Μετακίνηση εδώ +Copy.Title = Επιβεβαίωση αντικατάστασης αρχείου +Copy.Subtitle = Αυτός ο φάκελος περιέχει ήδη ένα αρχείο με όνομα "%s". +Copy.SubtitleRO = Αυτός ο φάκελος περιέχει ήδη ένα αρχείο μόνο για ανάγνωση με όνομα "%s". +Copy.SubtitleSys = Αυτός ο φάκελος περιέχει ήδη ένα αρχείο συστήματος με όνομα "%s". +Copy.Prompt1 = Θέλετε να αντικατασταθεί το υπάρχον αρχείο +Copy.Prompt2 = με αυτό το αρχείο; +Copy.Yes = &Ναι +Copy.No = Ό&χι +Copy.YesAll = Ναι σε ό&λα +Folder.Title = Επιβεβαίωση αντικατάστασης φακέλου +Folder.Prompt = Είστε βέβαιοι ότι θέλετε να μετακινηθεί ή να αντιγραφεί ο φάκελος; +Toolbar.GoUp = Ένα επίπεδο επάνω +Toolbar.Cut = Αποκοπή +Toolbar.Copy = Αντιγραφή +Toolbar.Paste = Επικόλληση +Toolbar.PasteShortcut = Επικόλληση συντόμευσης +Toolbar.Delete = Διαγραφή +Toolbar.Email = Ηλεκτρονική ταχυδρόμηση των επιλεγμένων αντικειμένων +Toolbar.Properties = Ιδιότητες +Toolbar.NewFolder = Νέος φάκελος +Toolbar.ZipFolder = Νέος συμπιεσμένος (μορφή zip) φάκελος +Toolbar.ExtraLarge = Πολύ μεγάλα εικονίδια +Toolbar.Large = Μεγάλα εικονίδια +Toolbar.Medium = Μεσαία εικονίδια +Toolbar.Small = Μικρά εικονίδια +Toolbar.List = Λίστα +Toolbar.Details = Λεπτομέρειες +Toolbar.Tiles = Τίτλοι +Toolbar.Content = Περιεχόμενο +Toolbar.Undo = Αναίρεση +Toolbar.Redo = Επανάληψη +Toolbar.Refresh = Ανανέωση +Toolbar.Back = Πίσω +Toolbar.Forward = Εμπρός +Toolbar.Stop = Τέλος +Toolbar.Rename = Μετονομασία +Toolbar.SelectAll = Επιλογή όλων +Toolbar.CustomizeFolder = Προσαρμογή φακέλου +Toolbar.MapDrive = Αντιστοίχιση δίσκου δικτύου +Toolbar.DisconnectDrive = Αποσύνδεση δίσκου δικτύου +Toolbar.NavigationPane = Παράθυρο περιήγησης +Toolbar.DetailsPane = Παράθυρο λεπτομερειών +Toolbar.PreviewPane = Παράθυρο προεπισκόπησης +Toolbar.CopyTo = Αντιγραφή σε +Toolbar.MoveTo = Μετακίνηση σε +Toolbar.Deselect = Καμία επιλογή +Toolbar.InvertSelection = Αναστροφή επιλογής +Toolbar.FolderOptions = Επιλογές φακέλων +Toolbar.ShowHiddenFiles = Κρυφά αρχεία και φάκελοι +Toolbar.ShowSystemFiles = Αρχεία συστήματος +Toolbar.ShowExtensions = Επεκτάσεις ονόματος αρχείων +Status.FreeSpace = %s (Ελεύθερος χώρος στο δίσκο: %s) +Status.Item = %s στοιχείο +Status.Items = %s στοιχεία +Status.ItemSelected = %s επιλεγμένο στοιχείο +Status.ItemsSelected = %s επιλεγμένα στοιχεία + + +[en-US] - English (United States) +Copy.Cancel = Cancel +Copy.More = More... +Copy.CopyHere = &Copy Here +Copy.MoveHere = &Move Here +Copy.Title = Confirm File Replace +Copy.Subtitle = This folder already contains a file named '%s'. +Copy.SubtitleRO = This folder already contains a read-only file named '%s'. +Copy.SubtitleSys = This folder already contains a system file named '%s'. +Copy.Prompt1 = Would you like to replace the existing file +Copy.Prompt2 = with this one? +Copy.Yes = &Yes +Copy.No = &No +Copy.YesAll = Yes to &All +Folder.Title = Confirm Folder Replace +Folder.Prompt = Do you still want to move or copy the folder? +Toolbar.GoUp = Up One Level +Toolbar.Cut = Cut +Toolbar.Copy = Copy +Toolbar.Paste = Paste +Toolbar.PasteShortcut = Paste Shortcut +Toolbar.Delete = Delete +Toolbar.Email = E-mail the selected items +Toolbar.Properties = Properties +Toolbar.NewFolder = New Folder +Toolbar.ZipFolder = New Compressed (zipped) Folder +Toolbar.ExtraLarge = Extra Large Icons +Toolbar.Large = Large Icons +Toolbar.Medium = Medium Icons +Toolbar.Small = Small Icons +Toolbar.List = List +Toolbar.Details = Details +Toolbar.Tiles = Tiles +Toolbar.Content = Content +Toolbar.Undo = Undo +Toolbar.Redo = Redo +Toolbar.Refresh = Refresh +Toolbar.Back = Back +Toolbar.Forward = Forward +Toolbar.Stop = Stop +Toolbar.Rename = Rename +Toolbar.SelectAll = Select all +Toolbar.CustomizeFolder = Customize this folder +Toolbar.MapDrive = Map network drive +Toolbar.DisconnectDrive = Disconnect network drive +Toolbar.NavigationPane = Navigation pane +Toolbar.DetailsPane = Details pane +Toolbar.PreviewPane = Preview pane +Toolbar.CopyTo = Copy to +Toolbar.MoveTo = Move to +Toolbar.Deselect = Select none +Toolbar.InvertSelection = Invert selection +Toolbar.FolderOptions = Folder options +Toolbar.ShowHiddenFiles = Hidden files and folders +Toolbar.ShowSystemFiles = System files +Toolbar.ShowExtensions = File name extensions +Status.FreeSpace = %s (Disk free space: %s) +Status.Item = %s item +Status.Items = %s items +Status.ItemSelected = %s item selected +Status.ItemsSelected = %s items selected + + +[es-ES] - Spanish (Spain) +Copy.Cancel = Cancelar +Copy.More = Mas... +Copy.CopyHere = &Copiar aquí +Copy.MoveHere = &Mover aquí +Copy.Title = Confirmar el reemplazo de archivo +Copy.Subtitle = Esta carpeta ya contiene un archivo con el nombre "%s". +Copy.SubtitleRO = Esta carpeta ya contiene un archivo de sólo lectura con el nombre "%s". +Copy.SubtitleSys = Esta carpeta ya contiene un archivo de sistema con el nombre "%s". +Copy.Prompt1 = ¿Desea reemplazar el archivo existente +Copy.Prompt2 = por este otro? +Copy.Yes = &Sí +Copy.No = &No +Copy.YesAll = Sí a &todo +Folder.Title = Confirmar el reemplazo de carpetas +Folder.Prompt = ¿Desea mover o copiar la carpeta de todas formas? +Toolbar.GoUp = Subir un nivel +Toolbar.Cut = Cortar +Toolbar.Copy = Copiar +Toolbar.Paste = Pegar +Toolbar.PasteShortcut = Pegar acceso directo +Toolbar.Delete = Eliminar +Toolbar.Email = Enviar por correo electrónico los elementos siguientes +Toolbar.Properties = Propiedades +Toolbar.NewFolder = Nueva carpeta +Toolbar.ZipFolder = Nueva carpeta comprimida (en zip) +Toolbar.ExtraLarge = Iconos muy grandes +Toolbar.Large = Iconos grandes +Toolbar.Medium = Iconos medianos +Toolbar.Small = Iconos pequeños +Toolbar.List = Lista +Toolbar.Details = Detalles +Toolbar.Tiles = Mosaicos +Toolbar.Content = Contenido +Toolbar.Undo = Deshacer +Toolbar.Redo = Rehacer +Toolbar.Refresh = Actualizar +Toolbar.Back = Atrás +Toolbar.Forward = Adelante +Toolbar.Stop = Detener +Toolbar.Rename = Cambiar nombre +Toolbar.SelectAll = Seleccionar todo +Toolbar.CustomizeFolder = Personalizar esta carpeta +Toolbar.MapDrive = Conectar a unidad de red +Toolbar.DisconnectDrive = Desconectar unidad de red +Toolbar.NavigationPane = Panel de navegación +Toolbar.DetailsPane = Panel de detalles +Toolbar.PreviewPane = Panel de vista previa +Toolbar.CopyTo = Copiar a +Toolbar.MoveTo = Mover a +Toolbar.Deselect = No seleccionar ninguno +Toolbar.InvertSelection = Invertir selección +Toolbar.FolderOptions = Opciones de carpeta +Toolbar.ShowHiddenFiles = Archivos y carpetas ocultos +Toolbar.ShowSystemFiles = Archivos de sistema +Toolbar.ShowExtensions = Extensiones de nombre de archivo +Status.FreeSpace = %s (espacio disponible en disco: %s) +Status.Item = %s elemento +Status.Items = %s elementos +Status.ItemSelected = %s elemento seleccionado +Status.ItemsSelected = %s elementos seleccionados + + +[et-EE] - Estonian (Estonia) +Copy.Cancel = Loobu +Copy.More = Veel... +Copy.CopyHere = &Kopeeri siia +Copy.MoveHere = &Teisalda siia +Copy.Title = Kinnitage failiasendus +Copy.Subtitle = See kaust sisaldab juba faili nimega %s. +Copy.SubtitleRO = See kaust sisaldab juba kirjutuskaitstud faili nimega %s. +Copy.SubtitleSys = See kaust sisaldab juba süsteemifaili nimega %s. +Copy.Prompt1 = Kas soovite asendada olemasoleva faili +Copy.Prompt2 = sellega? +Copy.Yes = &Jah +Copy.No = &Ei +Copy.YesAll = &Kõigile jah +Folder.Title = Kinnitage kausta asendamine +Folder.Prompt = Kas soovite kausta ikkagi teisaldada või kopeerida? +Toolbar.GoUp = Taseme võrra üles +Toolbar.Cut = Lõika +Toolbar.Copy = Kopeeri +Toolbar.Paste = Kleebi +Toolbar.PasteShortcut = Kleebi otsetee +Toolbar.Delete = Kustuta +Toolbar.Email = Saada valitud üksused e-postiga +Toolbar.Properties = Atribuudid +Toolbar.NewFolder = Uus kaust +Toolbar.ZipFolder = Uus tihendatud (zip) kaust +Toolbar.ExtraLarge = Eriti suured ikoonid +Toolbar.Large = Suured ikoonid +Toolbar.Medium = Keskmise suurusega ikoonid +Toolbar.Small = Väikesed ikoonid +Toolbar.List = Loend +Toolbar.Details = Üksikasjad +Toolbar.Tiles = Paanid +Toolbar.Content = Sisu +Toolbar.Undo = Võta tagasi +Toolbar.Redo = Tee uuesti +Toolbar.Refresh = Värskenda +Toolbar.Back = Tagasi +Toolbar.Forward = Edasi +Toolbar.Stop = Lõpeta +Toolbar.Rename = Nimeta ümber +Toolbar.SelectAll = Vali kõik +Toolbar.CustomizeFolder = Kohanda seda kausta +Toolbar.MapDrive = Ühenda võrgudraiv +Toolbar.DisconnectDrive = Katkesta võrgudraivi ühendus +Toolbar.NavigationPane = Navigeerimispaan +Toolbar.DetailsPane = Üksikasjapaan +Toolbar.PreviewPane = Eelvaatepaan +Toolbar.CopyTo = Kopeeri asukohta +Toolbar.MoveTo = Teisalda asukohta +Toolbar.Deselect = Ära vali midagi +Toolbar.InvertSelection = Pööra valik +Toolbar.FolderOptions = Kaustasuvandid +Toolbar.ShowHiddenFiles = Peitfailid ja -kaustad +Toolbar.ShowSystemFiles = Süsteemifailid +Toolbar.ShowExtensions = Failinimede laiendid +Status.FreeSpace = %s (vaba kettaruumi: %s) +Status.Item = %s üksus +Status.Items = %s üksust +Status.ItemSelected = Valitud on %s üksus +Status.ItemsSelected = Valitud on %s üksust + + +[fa-IR] - Persian +Copy.Cancel = لغو +Copy.More = بیشتر... +Copy.CopyHere = &کپی به اینجا +Copy.MoveHere = &انتقال به اینجا +Copy.Title = تأیید جایگزینی پرونده +Copy.Subtitle = ‏‏در حال حاضر این پوشه حاوی پرونده‌ای به نام "%s" است. +Copy.SubtitleRO = ‏‏در حال حاضر این پوشه حاوی پرونده‌ای فقط خواندنی به نام "%s" است. +Copy.SubtitleSys = ‏‏در حال حاضر این پوشه حاوی پرونده‌ای سیستمی به نام "%s" است. +Copy.Prompt1 = آیا می‌خواهید پرونده‌ی موجود را جایگزین کنید +Copy.Prompt2 = با این یکی؟ +Copy.Yes = &بله +Copy.No = &خیر +Copy.YesAll = بله برای &همه +Folder.Title = تأیید جایگزینی پوشه +Folder.Prompt = آیا هنوز می‌خواهید پوشه را کپی یا منتقل کنید؟ +Toolbar.GoUp = یک سطح بالاتر +Toolbar.Cut = برش +Toolbar.Copy = کپی +Toolbar.Paste = جایگذاری +Toolbar.PasteShortcut = جایگذاری میانبر +Toolbar.Delete = حذف +Toolbar.Email = مورد انتخابی را با پست الکترونیکی بفرستید +Toolbar.Properties = خصوصیات +Toolbar.NewFolder = پوشه جدید +Toolbar.ZipFolder = پوشه فشرده ‏(زیپ شده)‏ جدید‫ +Toolbar.ExtraLarge = نمادهای خیلی بزرگ +Toolbar.Large = نمادهای بزرگ +Toolbar.Medium = نمادهای متوسط +Toolbar.Small = نمادهای کوچک +Toolbar.List = لیست +Toolbar.Details = جزئیات +Toolbar.Tiles = موزائیک‌ها +Toolbar.Content = محتوا +Toolbar.Undo = لغو عمل +Toolbar.Redo = انجام مجدد +Toolbar.Refresh = تازه‌کردن +Toolbar.Back = عقب +Toolbar.Forward = جلو +Toolbar.Stop = توقف +Toolbar.Rename = تغییر نام +Toolbar.SelectAll = انتخاب همه +Toolbar.CustomizeFolder = سفارشی کردن این پوشه +Toolbar.MapDrive = نگاشت درایو شبکه +Toolbar.DisconnectDrive = قطع اتصال درایو شبکه +Toolbar.NavigationPane = چارچوب پیمایش +Toolbar.DetailsPane = چارچوب جزئیات +Toolbar.PreviewPane = چارچوب پیش‌نمایش +Toolbar.CopyTo = ‏‏کپی در +Toolbar.MoveTo = انتقال به +Toolbar.Deselect = هیچکدام انتخاب نشود +Toolbar.InvertSelection = معکوس کردن انتخاب +Toolbar.FolderOptions = گزینه های پوشه +Toolbar.ShowHiddenFiles = پرونده و پوشه های پنهان +Toolbar.ShowSystemFiles = پرونده های سیستم +Toolbar.ShowExtensions = پسوندهای نام پرونده ها +Toolbar.Settings = تنظیمات کاوشگر کلاسیک +Status.FreeSpace = %s (فضای خالی دیسک: %s) +Status.Item = %s مورد +Status.Items = %s مورد +Status.ItemSelected = %s مورد انتخاب شده +Status.ItemsSelected = %s مورد انتخاب شده + + +[fi-FI] - Finnish (Finland) +Copy.Cancel = Peruuta +Copy.More = Lisää... +Copy.CopyHere = &Kopioi tähän +Copy.MoveHere = &Siirrä tähän +Copy.Title = Vahvista tiedoston korvaus +Copy.Subtitle = Tämä kansio sisältää jo tiedoston %s. +Copy.SubtitleRO = Tämä kansio sisältää jo vain luku -tiedoston %s. +Copy.SubtitleSys = Tämä kansio sisältää jo järjestelmätiedoston %s. +Copy.Prompt1 = Haluatko korvata tiedoston +Copy.Prompt2 = tällä tiedostolla? +Copy.Yes = &Kyllä +Copy.No = &Ei +Copy.YesAll = Kyllä k&aikkiin +Folder.Title = Vahvista kansion korvaus +Folder.Prompt = Haluatko korvata järjestelmässä jo olevan kansion tiedostot siirrettävän tai kopioitavan kansion samannimisillä tiedostoilla? +Toolbar.GoUp = Yksi taso ylöspäin +Toolbar.Cut = Leikkaa +Toolbar.Copy = Kopioi +Toolbar.Paste = Liitä +Toolbar.PasteShortcut = Liitä pikakuvake +Toolbar.Delete = Poista +Toolbar.Email = Lähetä valitut kohteet sähköpostilla +Toolbar.Properties = Ominaisuudet +Toolbar.NewFolder = Uusi kansio +Toolbar.ZipFolder = Uusi pakattu (zip) kansio +Toolbar.ExtraLarge = Suurimmat kuvakkeet +Toolbar.Large = Suuret kuvakkeet +Toolbar.Medium = Keskikokoiset kuvakkeet +Toolbar.Small = Pienet kuvakkeet +Toolbar.List = Luettelo +Toolbar.Details = Tiedot +Toolbar.Tiles = Kuvakkeet ja tiedot +Toolbar.Content = Sisältö +Toolbar.Undo = Kumoa +Toolbar.Redo = Tee uudelleen +Toolbar.Refresh = Päivitä +Toolbar.Back = Edellinen +Toolbar.Forward = Seuraava +Toolbar.Stop = Pysäytä +Toolbar.Rename = Nimeä uudelleen +Toolbar.SelectAll = Valitse kaikki +Toolbar.CustomizeFolder = Mukauta kansiota +Toolbar.MapDrive = Yhdistä verkkoasemaan +Toolbar.DisconnectDrive = Katkaise yhteys verkkoasemaan +Toolbar.NavigationPane = Siirtymisruutu +Toolbar.DetailsPane = Tiedot-ruutu +Toolbar.PreviewPane = Esikatseluruutu +Toolbar.CopyTo = Kopioi kohteeseen +Toolbar.MoveTo = Siirrä kohteeseen +Toolbar.Deselect = Poista valinnat +Toolbar.InvertSelection = Käänteinen valinta +Toolbar.FolderOptions = Kansion asetukset +Toolbar.ShowHiddenFiles = Piilotetut tiedostot ja kansiot +Toolbar.ShowSystemFiles = Järjestelmätiedostot +Toolbar.ShowExtensions = Tiedostotunnisteet +Status.FreeSpace = %s (levyn vapaa tila: %s) +Status.Item = %s kohde +Status.Items = %s kohdetta +Status.ItemSelected = %s kohde valittu +Status.ItemsSelected = %s kohdetta valittu + + +[fr-FR] - French (France) +Copy.Cancel = Annuler +Copy.More = Autres… +Copy.CopyHere = &Copier ici +Copy.MoveHere = &Déplacer ici +Copy.Title = Confirmer le remplacement du fichier +Copy.Subtitle = Ce dossier contient déjà un fichier nommé « %s ». +Copy.SubtitleRO = Ce dossier contient déjà un fichier en lecture seule nommé « %s ». +Copy.SubtitleSys = Ce dossier contient déjà un fichier système nommé « %s ». +Copy.Prompt1 = Faut-il remplacer le fichier existant +Copy.Prompt2 = par celui-ci ? +Copy.Yes = &Oui +Copy.No = &Non +Copy.YesAll = &Tous +Folder.Title = Confirmation du remplacement du dossier +Folder.Prompt = Faut-il vraiment déplacer ou copier le dossier ? +Toolbar.GoUp = Dossier parent +Toolbar.Cut = Couper +Toolbar.Copy = Copier +Toolbar.Paste = Coller +Toolbar.PasteShortcut = Coller le raccourci +Toolbar.Delete = Supprimer +Toolbar.Email = Envoyer les éléments sélectionnés par courrier électronique +Toolbar.Properties = Propriétés +Toolbar.NewFolder = Nouveau dossier +Toolbar.ZipFolder = Nouveau dossier compressé +Toolbar.ExtraLarge = Très grandes icônes +Toolbar.Large = Grandes icônes +Toolbar.Medium = Icônes moyennes +Toolbar.Small = Petites icônes +Toolbar.List = Liste +Toolbar.Details = Détails +Toolbar.Tiles = Mosaïques +Toolbar.Content = Contenu +Toolbar.Undo = Annuler +Toolbar.Redo = Rétablir +Toolbar.Refresh = Actualiser +Toolbar.Back = Précédent +Toolbar.Forward = Suivant +Toolbar.Stop = Arrêter +Toolbar.Rename = Renommer +Toolbar.SelectAll = Sélectionner tout +Toolbar.CustomizeFolder = Personnaliser ce dossier +Toolbar.MapDrive = Connecter un lecteur réseau +Toolbar.DisconnectDrive = Déconnecter un lecteur réseau +Toolbar.NavigationPane = Volet de navigation +Toolbar.DetailsPane = Volet des détails +Toolbar.PreviewPane = Volet de visualisation +Toolbar.CopyTo = Copier vers +Toolbar.MoveTo = Déplacer vers +Toolbar.Deselect = Aucun +Toolbar.InvertSelection = Inverser la sélection +Toolbar.FolderOptions = Options des dossiers +Toolbar.ShowHiddenFiles = Fichiers et dossiers cachés +Toolbar.ShowSystemFiles = Fichiers système +Toolbar.ShowExtensions = Extensions de noms de fichiers +Status.FreeSpace = %s (espace libre : %s) +Status.Item = %s élément +Status.Items = %s éléments +Status.ItemSelected = %s élément sélectionné +Status.ItemsSelected = %s éléments sélectionnés + + +[gd-GB] - Scottish Gaelic (United Kingdom) +Copy.Cancel = Sguir dheth +Copy.More = Barrachd... +Copy.CopyHere = &Cuir an lethbhreac an-seo +Copy.MoveHere = &Gluais an-seo +Copy.Title = Dearbh an cur an àite +Copy.Subtitle = Tha faidhle air a bheil "%s" sa phasgan seo mu thràth. +Copy.SubtitleRO = Tha faidhle air a bheil "%s" sa phasgan seo mu thràth a tha ri leughadh a-mhàin. +Copy.SubtitleSys = Tha faidhle siostaim air a bheil "%s" sa phasgan seo mu thràth. +Copy.Prompt1 = A bheil thu airson am faidhle seo a chur +Copy.Prompt2 = an àite an fhir làithrich? +Copy.Yes = &Tha +Copy.No = &Chan eil +Copy.YesAll = Th&a ris a h-uile +Folder.Title = Dearbh an cur an àite +Folder.Prompt = A bheil thu airson am pasgan a ghluasad fhathast no airson lethbhreac a dhèanamh dheth? +Toolbar.GoUp = Suas aon ìre +Toolbar.Cut = Gearr +Toolbar.Copy = Dàn lethbhreac +Toolbar.Paste = Cuir ann +Toolbar.PasteShortcut = Cuir ann an ath-ghoirid +Toolbar.Delete = Sguab às +Toolbar.Email = Cuir na thagh thu ann am post-d +Toolbar.Properties = Roghainnean +Toolbar.NewFolder = Pasgan ùr +Toolbar.ZipFolder = Pasgan dùmhlaichte (air a shiopadh) ùr +Toolbar.ExtraLarge = Ìomhaigheagan anabarrach mòr +Toolbar.Large = Ìomhaigheagan mòra +Toolbar.Medium = Ìomhaigheagan meadhanach +Toolbar.Small = Ìomhaigheagan beaga +Toolbar.List = Liosta +Toolbar.Details = Mion-fhiosrachadh +Toolbar.Tiles = Leacagan +Toolbar.Content = Susbaint +Toolbar.Undo = Neo-dhèan +Toolbar.Redo = Ath-dhèan +Toolbar.Refresh = Ath-nuadhaich +Toolbar.Back = Air ais +Toolbar.Forward = Air adhart +Toolbar.Stop = Sguir dheth +Toolbar.Rename = Thoir ainm eile air +Toolbar.SelectAll = Tagh na h-uile +Toolbar.CustomizeFolder = Gnàthaich am pasgan seo +Toolbar.MapDrive = Mapaich draibh an lìonraidh +Toolbar.DisconnectDrive = Dì-cheangail draibh an lìonraidh +Toolbar.NavigationPane = Leòsan na seòladaireachd +Toolbar.DetailsPane = Leòsan a' mhion-fhiosrachaidh +Toolbar.PreviewPane = Leòsan an ro-sheallaidh +Toolbar.CopyTo = Cuir lethbhreac gu +Toolbar.MoveTo = Gluais gu +Toolbar.Deselect = Na tagh gin +Toolbar.InvertSelection = Ais-thionndaidh an taghadh +Toolbar.FolderOptions = Roghainnean a' phasgain +Toolbar.ShowHiddenFiles = Faidhlichean is pasgain fhalaichte +Toolbar.ShowSystemFiles = Faidhlichean an t-siostaim +Toolbar.ShowExtensions = Leudachain ainmean nam faidhle +Status.FreeSpace = %s (Àire saor air an diosga: %s) +Status.Item = %s nì +Status.Items = %s nithean +Status.ItemSelected = %s nì air a thaghadh +Status.ItemsSelected = %s nithean air a thaghadh + + +[he-IL] - Hebrew (Israel) +Copy.Cancel = ביטול +Copy.More = עוד... +Copy.CopyHere = הע&תק לכאן +Copy.MoveHere = הע&בר לכאן +Copy.Title = אישור החלפת קובץ +Copy.Subtitle = תיקיה זו מכילה כבר קובץ בשם '‎‎%s‎‏'‏.‏ +Copy.SubtitleRO = תיקיה זו מכילה כבר קובץ המוגדר לקריאה בלבד בשם '‎‎%s‎‏'.‏ +Copy.SubtitleSys = תיקיה זו מכילה כבר קובץ מערכת בשם '‎‎%s‎'‏.‏ +Copy.Prompt1 = ‏‏האם ברצונך להחליף את הקובץ הקיים +Copy.Prompt2 = בקובץ זה? +Copy.Yes = &כן +Copy.No = &לא +Copy.YesAll = כ&ן לכל +Folder.Title = אישור החלפת תיקיה +Folder.Prompt = האם ברצונך להעביר או להעתיק את התיקיה בכל זאת? +Toolbar.GoUp = רמה אחת למעלה +Toolbar.Cut = גזור +Toolbar.Copy = העתק +Toolbar.Paste = הדבק +Toolbar.PasteShortcut = הדבק קיצור דרך +Toolbar.Delete = מחק +Toolbar.Email = שלח את הפריטים הנבחרים בדואר אלקטרוני +Toolbar.Properties = מאפיינים +Toolbar.NewFolder = תיקיה חדשה +Toolbar.ZipFolder = ‫תיקיה ‫דחוסה ‫(מכווצת) ‫חדשה +Toolbar.ExtraLarge = סמלים גדולים מאוד +Toolbar.Large = סמלים גדולים +Toolbar.Medium = סמלים בינוניים +Toolbar.Small = סמלים קטנים +Toolbar.List = רשימה +Toolbar.Details = פרטים +Toolbar.Tiles = משבצות +Toolbar.Content = תוכן +Toolbar.Undo = בטל +Toolbar.Redo = בצע שוב +Toolbar.Refresh = רענן +Toolbar.Back = אחורה +Toolbar.Forward = קדימה +Toolbar.Stop = עצור +Toolbar.Rename = שינוי שם +Toolbar.SelectAll = בחר הכל +Toolbar.CustomizeFolder = התאמה אישית של תיקיה זו +Toolbar.MapDrive = מיפוי כונן רשת +Toolbar.DisconnectDrive = ניתוק כונן רשת +Toolbar.NavigationPane = חלונית ניווט +Toolbar.DetailsPane = חלונית פרטים +Toolbar.PreviewPane = חלונית תצוגה מקדימה +Toolbar.CopyTo = העתק אל +Toolbar.MoveTo = העבר אל +Toolbar.Deselect = אל תבחר +Toolbar.InvertSelection = הפוך בחירה +Toolbar.FolderOptions = אפשרויות תיקיה +Toolbar.ShowHiddenFiles = קבצים ותיקיות מוסתרים +Toolbar.ShowSystemFiles = קבצי מערכת +Toolbar.ShowExtensions = סיומות שמות קבצים +Status.FreeSpace = %s (שטח פנוי בדיסק: %s) +Status.Item = ‏‏%s פריט +Status.Items = %s פריטים +Status.ItemSelected = פריט %s נבחר +Status.ItemsSelected = %s פריטים נבחרו + + +[hr-HR] - Croatian (Croatia) +Copy.DoForAll = Učini to za sljedećih +Copy.Cancel = Odustani +Copy.More = Više... +Copy.CopyHere = &Kopiraj ovdje +Copy.MoveHere = Pr&emjesti ovdje +Copy.Title = Potvrda zamjene datoteke +Copy.Subtitle = Ova mapa već sadrži datoteku naziva '%s'. +Copy.SubtitleRO = Ova mapa već sadrži datoteku samo za čitanje, nazvanu '%s'. +Copy.SubtitleSys = Ova mapa već sadrži sistemsku datoteku, nazvanu '%s'. +Copy.Prompt1 = Želite li zamijeniti postojeću datoteku +Copy.Prompt2 = s ovom? +Copy.Yes = &Da +Copy.No = &Ne +Copy.YesAll = Da za &sve +Folder.Title = Potvrda zamjene mape +Folder.Prompt = Želite li još uvijek premjestiti ili kopirati mapu? +Toolbar.GoUp = Jednu razinu gore +Toolbar.Cut = Izreži +Toolbar.Copy = Kopiraj +Toolbar.Paste = Zalijepi +Toolbar.PasteShortcut = Zalijepi prečac +Toolbar.Delete = Izbriši +Toolbar.Email = Odabrane stavke pošalji e-poštom +Toolbar.Properties = Svojstva +Toolbar.NewFolder = Nova mapa +Toolbar.ZipFolder = Nova komprimirana (zipana) mapa +Toolbar.ExtraLarge = Vrlo velike ikone +Toolbar.Large = Velike ikone +Toolbar.Medium = Srednje ikone +Toolbar.Small = Male ikone +Toolbar.List = Popis +Toolbar.Details = Detalji +Toolbar.Tiles = Pločice +Toolbar.Content = Sadržaj +Toolbar.Undo = Poništi +Toolbar.Redo = Ponovi +Toolbar.Refresh = Osvježi +Toolbar.Back = Natrag +Toolbar.Forward = Naprijed +Toolbar.Stop = Prekini +Toolbar.Rename = Preimenuj +Toolbar.SelectAll = Odaberi sve +Toolbar.CustomizeFolder = Prilagodi ovu mapu +Toolbar.MapDrive = Mapiranje mrežnog pogona +Toolbar.DisconnectDrive = Prekid veze s mrežnim pogonom +Toolbar.NavigationPane = Navigacijsko okno +Toolbar.DetailsPane = Okno s detaljima +Toolbar.PreviewPane = Okno pretpregleda +Toolbar.CopyTo = Kopiraj u +Toolbar.MoveTo = Premjesti u +Toolbar.Deselect = Bez odabira +Toolbar.InvertSelection = Obrni odabir +Toolbar.FolderOptions = Mogućnosti mapa +Toolbar.ShowHiddenFiles = Skrivene datoteke i mape +Toolbar.ShowSystemFiles = Sistemske datoteke +Toolbar.ShowExtensions = Datotečni nastavci +Status.FreeSpace = %s (slobodan prostor na disku: %s) +Status.Item = %s stavka +Status.Items = Broj stavki: %s +Status.ItemSelected = Odabrano stavki: %s +Status.ItemsSelected = Odabrano stavki: %s + + +[hu-HU] - Hungarian (Hungary) +Copy.Cancel = Mégse +Copy.More = Egyebek... +Copy.CopyHere = Más&olás ide +Copy.MoveHere = Át&helyezés ide +Copy.Title = Fájlcsere megerősítése +Copy.Subtitle = A mappa már tartalmaz egy '%s' nevű fájlt. +Copy.SubtitleRO = Ez a mappa már tartalmaz egy '%s' nevű írásvédett fájlt. +Copy.SubtitleSys = Ez a mappa már tartalmaz egy '%s' nevű rendszerfájlt. +Copy.Prompt1 = Kicseréli a létező fájlt +Copy.Prompt2 = ezzel? +Copy.Yes = &Igen +Copy.No = &Nem +Copy.YesAll = Igen, &mindet +Folder.Title = Mappacsere megerősítése +Folder.Prompt = Folytatja a műveletet? +Toolbar.GoUp = Egy szinttel feljebb +Toolbar.Cut = Kivágás +Toolbar.Copy = Másolás +Toolbar.Paste = Beillesztés +Toolbar.PasteShortcut = Parancsikon beillesztése +Toolbar.Delete = Törlés +Toolbar.Email = A kijelölt elemek elküldése e-mailben +Toolbar.Properties = Tulajdonságok +Toolbar.NewFolder = Új mappa +Toolbar.ZipFolder = Új tömörített mappa +Toolbar.ExtraLarge = Extra nagy ikonok +Toolbar.Large = Nagy ikonok +Toolbar.Medium = Közepes ikonok +Toolbar.Small = Kis ikonok +Toolbar.List = Lista +Toolbar.Details = Részletek +Toolbar.Tiles = Mozaik +Toolbar.Content = Tartalom +Toolbar.Undo = Visszavonás +Toolbar.Redo = Mégis +Toolbar.Refresh = Frissítés +Toolbar.Back = Vissza +Toolbar.Forward = Előre +Toolbar.Stop = Leállítás +Toolbar.Rename = Átnevezés +Toolbar.SelectAll = Az összes kijelölése +Toolbar.CustomizeFolder = Mappa testreszabása +Toolbar.MapDrive = Hálózati meghajtó csatlakoztatása +Toolbar.DisconnectDrive = Hálózati meghajtó leválasztása +Toolbar.NavigationPane = Navigációs ablak +Toolbar.DetailsPane = Részletek ablaktábla +Toolbar.PreviewPane = Betekintő ablaktábla +Toolbar.CopyTo = Másolási cél +Toolbar.MoveTo = Áthelyezési cél +Toolbar.Deselect = Kijelölés megszüntetése +Toolbar.InvertSelection = Kijelölés megfordítása +Toolbar.FolderOptions = Mappa beállításai +Toolbar.ShowHiddenFiles = Rejtett fájlok és mappák +Toolbar.ShowSystemFiles = Rendszerfájlok +Toolbar.ShowExtensions = Fájlnévkiterjesztések +Status.FreeSpace = %s (szabad lemezterület: %s) +Status.Item = %s elem +Status.Items = %s elem +Status.ItemSelected = %s kijelölt elem +Status.ItemsSelected = %s kijelölt elem + + +[is-IS] - Icelandic (Iceland) +Toolbar.Settings = Classic Explorer stillingar +Copy.Cancel = Hætta við +Copy.More = Meira... +Copy.CopyHere = &Afrita hingað +Copy.MoveHere = &Færa hingað +Copy.Title = Skipta út skrá +Copy.Subtitle = Endastaðurinn inniheldur þegar skrá með heitinu '%s'. +Copy.SubtitleRO = Endastaðurinn inniheldur þegar skrifvarða skrá með heitinu '%s'. +Copy.SubtitleSys = Endastaðurinn inniheldur þegar stýrikerfisskrá með heitinu '%s'. +Copy.Prompt1 = Viltu skipta út skránni á endastaðnum +Copy.Prompt2 = fyrir þessa skrá? +Copy.Yes = &Já +Copy.No = &Nei +Copy.YesAll = Já við &öllu +Folder.Title = Skipta út möppu +Folder.Prompt = Ertu viss um að þú viljir færa eða afrita möppuna? +Toolbar.GoUp = Upp um eitt þrep +Toolbar.Cut = Klippa +Toolbar.Copy = Afrita +Toolbar.Paste = Líma +Toolbar.PasteShortcut = Líma flýtileið +Toolbar.Delete = Eyða +Toolbar.Email = Senda valin atriði með tölvupósti +Toolbar.Properties = Eiginleikar +Toolbar.NewFolder = Ný mappa +Toolbar.ZipFolder = Ný þjöppuð (zip-þjöppuð) mappa +Toolbar.ExtraLarge = Mjög stór tákn +Toolbar.Large = Stór tákn +Toolbar.Medium = Meðalstór tákn +Toolbar.Small = Lítil tákn +Toolbar.List = Listi +Toolbar.Details = Upplýsingar +Toolbar.Tiles = Reitir +Toolbar.Content = Efni +Toolbar.Undo = Afturkalla +Toolbar.Redo = Endurgera +Toolbar.Refresh = Endurhlaða +Toolbar.Back = Til baka +Toolbar.Forward = Áfram +Toolbar.Stop = Stöðva +Toolbar.Rename = Endurnefna +Toolbar.SelectAll = Velja allt +Toolbar.CustomizeFolder = Sérstilla þessa möppu +Toolbar.MapDrive = Tengja netdrif +Toolbar.DisconnectDrive = Aftengja netdrif +Toolbar.NavigationPane = Yfirlitssvæði +Toolbar.DetailsPane = Upplýsingasvæði +Toolbar.PreviewPane = Forskoðunarsvæði +Toolbar.CopyTo = Afrita til +Toolbar.MoveTo = Færa til +Toolbar.Deselect = Velja ekkert +Toolbar.InvertSelection = Umsnúa vali +Toolbar.FolderOptions = Möppuvalkostir +Toolbar.ShowHiddenFiles = Faldar skrár og möppur +Toolbar.ShowSystemFiles = Kerfisskrár +Toolbar.ShowExtensions = Skráarendingar +Status.FreeSpace = %s (laust pláss: %s) +Status.Item = %s atriði +Status.Items = %s atriði +Status.ItemSelected = %s atriði valin +Status.ItemsSelected = %s atriði valin + + +[it-IT] - Italian (Italy) +Copy.Cancel = Annulla +Copy.More = Altro... +Copy.CopyHere = &Copia qui +Copy.MoveHere = &Sposta qui +Copy.Title = Conferma sostituzione file +Copy.Subtitle = La cartella contiene già un file di nome "%s". +Copy.SubtitleRO = La cartella contiene già un file di sola lettura di nome "%s". +Copy.SubtitleSys = La cartella contiene già un file di sistema di nome "%s". +Copy.Prompt1 = Sostituire il file esistente +Copy.Prompt2 = con questo file? +Copy.Yes = &Sì +Copy.No = &No +Copy.YesAll = Sì t&utti +Folder.Title = Conferma sostituzione cartella +Folder.Prompt = Continuare? +Toolbar.GoUp = Livello superiore +Toolbar.Cut = Taglia +Toolbar.Copy = Copia +Toolbar.Paste = Incolla +Toolbar.PasteShortcut = Incolla collegamento +Toolbar.Delete = Elimina +Toolbar.Email = Invia per posta elettronica gli elementi selezionati +Toolbar.Properties = Proprietà +Toolbar.NewFolder = Nuova cartella +Toolbar.ZipFolder = Nuova cartella compressa +Toolbar.ExtraLarge = Icone molto grandi +Toolbar.Large = Icone grandi +Toolbar.Medium = Icone medie +Toolbar.Small = Icone piccole +Toolbar.List = Elenco +Toolbar.Details = Dettagli +Toolbar.Tiles = Titoli +Toolbar.Content = Contenuto +Toolbar.Undo = Annulla +Toolbar.Redo = Ripeti +Toolbar.Refresh = Aggiorna +Toolbar.Back = Indietro +Toolbar.Forward = Avanti +Toolbar.Stop = Termina +Toolbar.Rename = Rinomina +Toolbar.SelectAll = Seleziona tutto +Toolbar.CustomizeFolder = Personalizza cartella +Toolbar.MapDrive = Connetti unità di rete +Toolbar.DisconnectDrive = Disconnetti unità di rete +Toolbar.NavigationPane = Riquadro di spostamento +Toolbar.DetailsPane = Riquadro dettagli +Toolbar.PreviewPane = Riquadro di anteprima +Toolbar.CopyTo = Copia in +Toolbar.MoveTo = Sposta in +Toolbar.Deselect = Deseleziona tutto +Toolbar.InvertSelection = Inverti selezione +Toolbar.FolderOptions = Opzioni cartella +Toolbar.ShowHiddenFiles = Cartelle e file nascosti +Toolbar.ShowSystemFiles = File di sistema +Toolbar.ShowExtensions = Estensioni nomi file +Status.FreeSpace = %s (Spazio disponibile: %s) +Status.Item = %s elemento +Status.Items = Elementi: %s +Status.ItemSelected = %s elemento selezionato +Status.ItemsSelected = %s elementi selezionati + + +[ja-JP] - Japanese (Japan) +Copy.Cancel = キャンセル +Copy.More = その他... +Copy.CopyHere = ここにコピー(&C) +Copy.MoveHere = ここに移動(&M) +Copy.Title = ファイルの上書きの確認 +Copy.Subtitle = このフォルダには既に '%s' ファイルが存在します。 +Copy.SubtitleRO = このフォルダには既に読み取り専用ファイル '%s' が含まれています。 +Copy.SubtitleSys = このフォルダには既にシステム ファイル '%s' が含まれています。 +Copy.Prompt1 = 現在のファイル +Copy.Prompt2 = を次の新しいファイルで置き換えますか? +Copy.Yes = はい(&Y) +Copy.No = いいえ(&N) +Copy.YesAll = すべて上書き(&A) +Folder.Title = フォルダの上書きの確認 +Folder.Prompt = フォルダを移動またはコピーしますか? +Toolbar.GoUp = 1 つ上のフォルダへ +Toolbar.Cut = 切り取り +Toolbar.Copy = コピー +Toolbar.Paste = 貼り付け +Toolbar.PasteShortcut = ショートカットの貼り付け +Toolbar.Delete = 削除 +Toolbar.Email = 選択した項目を電子メールで送信する +Toolbar.Properties = プロパティ +Toolbar.NewFolder = 新しいフォルダ +Toolbar.ZipFolder = 新しい圧縮された (ZIP) フォルダー +Toolbar.ExtraLarge = 特大アイコン +Toolbar.Large = 大アイコン +Toolbar.Medium = 中アイコン +Toolbar.Small = 小アイコン +Toolbar.List = 一覧 +Toolbar.Details = 詳細 +Toolbar.Tiles = 並べて表示 +Toolbar.Content = コンテンツ +Toolbar.Undo = 元に戻す +Toolbar.Redo = やり直し +Toolbar.Refresh = 最新の情報に更新 +Toolbar.Back = 戻る +Toolbar.Forward = 進む +Toolbar.Stop = 中止 +Toolbar.Rename = 名前の変更 +Toolbar.SelectAll = すべて選択 +Toolbar.CustomizeFolder = このフォルダーのカスタマイズ +Toolbar.MapDrive = ネットワーク ドライブの割り当て +Toolbar.DisconnectDrive = ネットワーク ドライブの切断 +Toolbar.NavigationPane = ナビゲーション ウィンドウ +Toolbar.DetailsPane = 詳細ウィンドウ +Toolbar.PreviewPane = プレビュー ウィンドウ +Toolbar.CopyTo = コピー先​​ +Toolbar.MoveTo = 移動先​​ +Toolbar.Deselect = 選択解除 +Toolbar.InvertSelection = 選択の切り替え +Toolbar.FolderOptions = フォルダー オプション +Toolbar.ShowHiddenFiles = ファイルとフォルダーの表示 +Toolbar.ShowSystemFiles = システム ファイル +Toolbar.ShowExtensions = ファイル名拡張子 +Status.FreeSpace = %s (空きディスク領域: %s) +Status.Item = %s 個 +Status.Items = %s 個の項目 +Status.ItemSelected = %s 個の項目を選択 +Status.ItemsSelected = %s 個の項目を選択 + + +[ko-KR] - Korean (Korea) +Copy.Cancel = 취소 +Copy.More = 자세히... +Copy.CopyHere = 여기에 복사(&C) +Copy.MoveHere = 여기로 이동(&M) +Copy.Title = 파일 바꾸기 확인 +Copy.Subtitle = 이 폴더에 이미 '%s' 파일이 있습니다. +Copy.SubtitleRO = 이 폴더에 이미 '%s' 읽기 전용 파일이 있습니다. +Copy.SubtitleSys = 이 폴더에 이미 '%s' 시스템 파일이 있습니다. +Copy.Prompt1 = 기존 파일을 +Copy.Prompt2 = 이 파일로 바꾸시겠습니까? +Copy.Yes = 예(&Y) +Copy.No = 아니오(&N) +Copy.YesAll = 모두 예(&A) +Folder.Title = 폴더 바꾸기 확인 +Folder.Prompt = 폴더를 이동하거나 복사하시겠습니까? +Toolbar.GoUp = 한 수준 위로 +Toolbar.Cut = 잘라내기 +Toolbar.Copy = 복사 +Toolbar.Paste = 붙여넣기 +Toolbar.PasteShortcut = 바로 가기 붙여넣기 +Toolbar.Delete = 삭제 +Toolbar.Email = 항목을 전자 메일로 보내기 +Toolbar.Properties = 속성 +Toolbar.NewFolder = 새 폴더 +Toolbar.ZipFolder = 새 압축(ZIP) 폴더 +Toolbar.ExtraLarge = 아주 큰 아이콘 +Toolbar.Large = 큰 아이콘 +Toolbar.Medium = 보통 아이콘 +Toolbar.Small = 작은 아이콘 +Toolbar.List = 목록 +Toolbar.Details = 자세히 +Toolbar.Tiles = 나란히 보기 +Toolbar.Content = 내용 +Toolbar.Undo = 실행 취소 +Toolbar.Redo = 다시 실행 +Toolbar.Refresh = 새로 고침 +Toolbar.Back = 뒤로 +Toolbar.Forward = 앞으로 +Toolbar.Stop = 중지 +Toolbar.Rename = 이름 바꾸기 +Toolbar.SelectAll = 모두 선택 +Toolbar.CustomizeFolder = 현재 폴더 사용자 지정 +Toolbar.MapDrive = 네트워크 드라이브 연결 +Toolbar.DisconnectDrive = 네트워크 드라이브 연결 끊기 +Toolbar.NavigationPane = 탐색 창 +Toolbar.DetailsPane = 세부 정보 창 +Toolbar.PreviewPane = 미리 보기 창 +Toolbar.CopyTo = 복사 위치 +Toolbar.MoveTo = 이동 위치 +Toolbar.Deselect = 선택 안 함 +Toolbar.InvertSelection = 선택 영역 반전 +Toolbar.FolderOptions = 폴더 옵션 +Toolbar.ShowHiddenFiles = 숨김 파일 및 폴더 +Toolbar.ShowSystemFiles = 시스템 파일 +Toolbar.ShowExtensions = 파일 확장명 +Status.FreeSpace = %s (빈 디스크 공간: %s) +Status.Item = %s 항목 +Status.Items = %s 항목 +Status.ItemSelected = %s개 항목을 선택했습니다. +Status.ItemsSelected = %s개 항목을 선택했습니다. + + +[lt-LT] - Lithuanian (Lithuania) +Copy.Cancel = Atšaukti +Copy.More = Daugiau... +Copy.CopyHere = &Kopijuoti čia +Copy.MoveHere = &Perkelti čia +Copy.Title = Patvirtinti failo pakeitimą +Copy.Subtitle = Šiame aplanke jau yra failas, pavadintas '%s'. +Copy.SubtitleRO = Aplanke jau yra failas, skirtas tik skaityti, pavadintas '%s'. +Copy.SubtitleSys = Aplanke jau yra sistemos failas, pavadintas '%s'. +Copy.Prompt1 = Ar pakeisti esamą failą +Copy.Prompt2 = šiuo? +Copy.Yes = &Taip +Copy.No = &Ne +Copy.YesAll = Taip &viskam +Folder.Title = Patvirtinti aplanko pakeitimą +Folder.Prompt = Ar vis tiek perkelti, ar kopijuoti aplanką? +Toolbar.GoUp = Vienu lygiu aukščiau +Toolbar.Cut = Iškirpti +Toolbar.Copy = Kopijuoti +Toolbar.Paste = Įklijuoti +Toolbar.PasteShortcut = Įklijuoti nuorodą +Toolbar.Delete = Naikinti +Toolbar.Email = Pažymėtus elementus siųsti el. paštu +Toolbar.Properties = Ypatybės +Toolbar.NewFolder = Naujas aplankas +Toolbar.ZipFolder = Naujas suglaudintas (zip) aplankas +Toolbar.ExtraLarge = Padidintos piktogramos +Toolbar.Large = Didelės piktogramos +Toolbar.Medium = Vidutinės piktogramos +Toolbar.Small = Mažos piktogramos +Toolbar.List = Sąrašas +Toolbar.Details = Išsami informacija +Toolbar.Tiles = Išklotinės +Toolbar.Content = Turinys +Toolbar.Undo = Anuliuoti +Toolbar.Redo = Perdaryti +Toolbar.Refresh = Atnaujinti +Toolbar.Back = Atgal į: +Toolbar.Forward = Pirmyn +Toolbar.Stop = Stabdyti +Toolbar.Rename = Pervardyti +Toolbar.SelectAll = Žymėti viską +Toolbar.CustomizeFolder = Tinkinti šį aplanką +Toolbar.MapDrive = Susieti tinklo diską +Toolbar.DisconnectDrive = Atjungti tinklo diską +Toolbar.NavigationPane = Naršymo sritis +Toolbar.DetailsPane = Išsamios informacijos sritis +Toolbar.PreviewPane = Peržiūros sritis +Toolbar.CopyTo = Kopijuoti į +Toolbar.MoveTo = Perkelti į +Toolbar.Deselect = Nieko nežymėti +Toolbar.InvertSelection = Žymėti priešingai +Toolbar.FolderOptions = Aplanko parinktys +Toolbar.ShowHiddenFiles = Paslėpti failai ir aplankai +Toolbar.ShowSystemFiles = Sistemos failai +Toolbar.ShowExtensions = Failų vardų plėtiniai +Status.FreeSpace = %s (Diske laisvos vietos: %s) +Status.Item = %s elementas +Status.Items = %s elementai +Status.ItemSelected = %s pažymėtas elementas +Status.ItemsSelected = Pažymėta elementų: %s + + +[lv-LV] - Latvian (Latvia) +Copy.Cancel = Atcelt +Copy.More = Vēl... +Copy.CopyHere = &Kopēt šeit +Copy.MoveHere = &Pārvietot šeit +Copy.Title = Failu aizstāšanas apstiprināšana +Copy.Subtitle = Šajā mapē jau ir fails '%s'. +Copy.SubtitleRO = Šajā mapē jau ir tikai lasāms fails '%s'. +Copy.SubtitleSys = Šajā mapē jau ir sistēmas fails '%s'. +Copy.Prompt1 = Vai vēlaties aizstāt esošo failu +Copy.Prompt2 = ar šo? +Copy.Yes = &Jā +Copy.No = &Nē +Copy.YesAll = Jā, &visus +Folder.Title = Mapju aizstāšanas apstiprināšana +Folder.Prompt = Vai tiešām vēlaties pārvietot vai kopēt šo mapi? +Toolbar.GoUp = Vienu līmeni augstāk +Toolbar.Cut = Izgriezt +Toolbar.Copy = Kopēt +Toolbar.Paste = Ielīmēt +Toolbar.PasteShortcut = Ielīmēt saīsni +Toolbar.Delete = Dzēst +Toolbar.Email = Nosūtīt atlasītos vienumus pa e-pastu +Toolbar.Properties = Rekvizīti +Toolbar.NewFolder = Jauna mape +Toolbar.ZipFolder = Jauna saspiestā (tilpsaspiestā) mape +Toolbar.ExtraLarge = Ļoti lielas ikonas +Toolbar.Large = Lielas ikonas +Toolbar.Medium = Vidējas ikonas +Toolbar.Small = Mazas ikonas +Toolbar.List = Saraksts +Toolbar.Details = Detaļas +Toolbar.Tiles = Mozaīka +Toolbar.Content = Saturs +Toolbar.Undo = Atsaukt +Toolbar.Redo = Atcelt atsaukšanu +Toolbar.Refresh = Atsvaidzināt +Toolbar.Back = Atpakaļ +Toolbar.Forward = Uz priekšu +Toolbar.Stop = Apturēt +Toolbar.Rename = Pārdēvēt +Toolbar.SelectAll = Atlasīt visus +Toolbar.CustomizeFolder = Pielāgot šo mapi +Toolbar.MapDrive = Kartēt tīkla disku +Toolbar.DisconnectDrive = Atvienot tīkla disku +Toolbar.NavigationPane = Navigācijas rūts +Toolbar.DetailsPane = Detalizētas informācijas rūts +Toolbar.PreviewPane = Priekšskatījuma rūts +Toolbar.CopyTo = Kopēt uz +Toolbar.MoveTo = Pārvietot uz +Toolbar.Deselect = Neatlasīt neko +Toolbar.InvertSelection = Mainīt atlasi uz pretējo +Toolbar.FolderOptions = Mapes opcijas +Toolbar.ShowHiddenFiles = Slēptie faili un mapes +Toolbar.ShowSystemFiles = Sistēmas faili +Toolbar.ShowExtensions = Failu nosaukumu paplašinājumi +Status.FreeSpace = %s (brīvā vieta diskā: %s) +Status.Item = %s vienums +Status.Items = %s vienumi +Status.ItemSelected = Atlasīts %s vienums +Status.ItemsSelected = Atlasīti %s vienumi + + +[mk-MK] - Macedonian (Macedonia) +Copy.Cancel = Откажи +Copy.More = Повеќе... +Copy.CopyHere = Копирај тука +Copy.MoveHere = Премести тука +Copy.Title = Потврди замена на фајл +Copy.Subtitle = Тој фолдер веќе содржи фајл со име '%s'. +Copy.SubtitleRO = Тој фолдер веќе содржи фајл само за читање со име '%s'. +Copy.SubtitleSys = Тој фолдер веќе содржи системски фајл со име '%s'. +Copy.Prompt1 = Дали сакате да замените постоечкиот фајл +Copy.Prompt2 = а тој? +Copy.Yes = Да +Copy.No = Не +Copy.YesAll = "Да" за сите +Folder.Title = Потврда за промена на фолдерот +Folder.Prompt = Сеуште ли сакате да го преместите или копирате фолдерот? +Toolbar.GoUp = Едно ниво нагоре +Toolbar.Cut = Исечи +Toolbar.Copy = Копирај +Toolbar.Paste = Стави +Toolbar.PasteShortcut = Стави краток пат +Toolbar.Delete = Избриши +Toolbar.Email = Испрати ги селектираните фајлови по електронска пошта +Toolbar.Properties = Својства +Toolbar.NewFolder = Нов фолдер +Toolbar.ZipFolder = Нова компресирана (зипувана) папка +Toolbar.ExtraLarge = Многу големи икони +Toolbar.Large = Големи икони +Toolbar.Medium = Средни икони +Toolbar.Small = Мали икони +Toolbar.List = Список +Toolbar.Details = Детали +Toolbar.Tiles = Мозаик +Toolbar.Content = Содржина +Toolbar.Undo = врати +Toolbar.Redo = повтори +Toolbar.Refresh = Обнови +Toolbar.Back = Назад +Toolbar.Forward = Напред +Toolbar.Stop = Застани +Toolbar.Rename = Преименување +Toolbar.SelectAll = Селектирај ги сите +Toolbar.CustomizeFolder = Персонализирање на тој фолдер +Toolbar.MapDrive = Назначување на мрежен уред +Toolbar.DisconnectDrive = Исклучи го мрежниот уред +Toolbar.NavigationPane = Навигационен екран +Toolbar.DetailsPane = Екран за подетални податоци +Toolbar.PreviewPane = Прозорец за визуализација +Toolbar.CopyTo = Копирај во +Toolbar.MoveTo = Премести во +Toolbar.Deselect = Не избирај ништо +Toolbar.InvertSelection = Преврти го изборот +Toolbar.FolderOptions = Опции за папка +Toolbar.ShowHiddenFiles = Сокриени датотеки и папки +Toolbar.ShowSystemFiles = Системски датотеки +Toolbar.ShowExtensions = Датотечни наставки +Status.FreeSpace = %s (Слободно место на дискот: %s) +Status.Item = %s фајл +Status.Items = %s фајлови +Status.ItemSelected = %s селектиран фајл +Status.ItemsSelected = %s селектирани фајлови + + +[nb-NO] - Norwegian, Bokmål (Norway) +Copy.Cancel = Avbryt +Copy.More = Mer... +Copy.CopyHere = &Kopier hit +Copy.MoveHere = &Flytt hit +Copy.Title = Bekreft erstatting av fil +Copy.Subtitle = Mappen inneholder allerede filen %s. +Copy.SubtitleRO = Mappen inneholder allerede den skrivebeskyttede filen %s. +Copy.SubtitleSys = Mappen inneholder allerede systemfilen %s. +Copy.Prompt1 = Vil du erstatte den eksisterende filen +Copy.Prompt2 = med denne? +Copy.Yes = &Ja +Copy.No = &Nei +Copy.YesAll = J&a til alt +Folder.Title = Bekreft erstatting av mappe +Folder.Prompt = Vil du likevel flytte eller kopiere mappen? +Toolbar.GoUp = Opp ett nivå +Toolbar.Cut = Klipp ut +Toolbar.Copy = Kopier +Toolbar.Paste = Lim inn +Toolbar.PasteShortcut = Lim inn snarvei +Toolbar.Delete = Slett +Toolbar.Email = Send valgte elementer via e-post +Toolbar.Properties = Egenskaper +Toolbar.NewFolder = Ny mappe +Toolbar.ZipFolder = Ny komprimert (zippet) mappe +Toolbar.ExtraLarge = Ekstra store ikoner +Toolbar.Large = Store ikoner +Toolbar.Medium = Middels store ikoner +Toolbar.Small = Små ikoner +Toolbar.List = Liste +Toolbar.Details = Detaljer +Toolbar.Tiles = Side ved side +Toolbar.Content = Innhold +Toolbar.Undo = Angre +Toolbar.Redo = Gjør om +Toolbar.Refresh = Oppdater +Toolbar.Back = Tilbake +Toolbar.Forward = Fremover +Toolbar.Stop = Stopp +Toolbar.Rename = Gi nytt navn +Toolbar.SelectAll = Merk alt +Toolbar.CustomizeFolder = Tilpass denne mappen +Toolbar.MapDrive = Koble til nettverksstasjon +Toolbar.DisconnectDrive = Koble fra nettverksstasjon +Toolbar.NavigationPane = Navigasjonsrute +Toolbar.DetailsPane = Detaljrute +Toolbar.PreviewPane = Forhåndsvisningsrute +Toolbar.CopyTo = Kopier til +Toolbar.MoveTo = Flytt til +Toolbar.Deselect = Merk ingenting +Toolbar.InvertSelection = Inverter utvalg +Toolbar.FolderOptions = Mappealternativer +Toolbar.ShowHiddenFiles = Skjulte filer og mapper +Toolbar.ShowSystemFiles = Systemfiler +Toolbar.ShowExtensions = Filtyper +Status.FreeSpace = %s (Ledig plass på disken: %s) +Status.Item = %s element +Status.Items = %s elementer +Status.ItemSelected = %s element er merket +Status.ItemsSelected = %s elementer er merket + + +[nl-NL] - Dutch (Netherlands) +Copy.Cancel = Annuleren +Copy.More = Meer... +Copy.CopyHere = Hierheen &kopiëren +Copy.MoveHere = Hi&erheen verplaatsen +Copy.Title = Vervangen van bestand bevestigen +Copy.Subtitle = In deze map bevindt zich al een bestand met de naam %s. +Copy.SubtitleRO = In deze map bevindt zich al een bestand met het kenmerk Alleen-lezen en de naam %s. +Copy.SubtitleSys = In deze map bevindt zich al een systeembestand met de naam %s. +Copy.Prompt1 = Wilt u het bestaande bestand: +Copy.Prompt2 = vervangen door het onderstaande bestand? +Copy.Yes = &Ja +Copy.No = &Nee +Copy.YesAll = J&a op alles +Folder.Title = Vervangen van map bevestigen +Folder.Prompt = Wilt u de bestanden in de bestaande map vervangen door de bestanden in de map die u verplaatst of kopieert, als de bestanden dezelfde naam hebben? +Toolbar.GoUp = Bovenliggende map +Toolbar.Cut = Knippen +Toolbar.Copy = Kopiëren +Toolbar.Paste = Plakken +Toolbar.PasteShortcut = Snelkoppeling plakken +Toolbar.Delete = Verwijderen +Toolbar.Email = De geselecteerde items per e-mail verzenden +Toolbar.Properties = Eigenschappen +Toolbar.NewFolder = Nieuwe map +Toolbar.ZipFolder = Nieuwe gecomprimeerde (gezipte) map +Toolbar.ExtraLarge = Extra grote pictogrammen +Toolbar.Large = Grote pictogrammen +Toolbar.Medium = Normale pictogrammen +Toolbar.Small = Kleine pictogrammen +Toolbar.List = Lijst +Toolbar.Details = Details +Toolbar.Tiles = Tegels +Toolbar.Content = Inhoud +Toolbar.Undo = Ongedaan maken +Toolbar.Redo = Opnieuw +Toolbar.Refresh = Vernieuwen +Toolbar.Back = Vorige +Toolbar.Forward = Volgende +Toolbar.Stop = Stoppen +Toolbar.Rename = Naam wijzigen +Toolbar.SelectAll = Alles selecteren +Toolbar.CustomizeFolder = Deze map aanpassen +Toolbar.MapDrive = Netwerkverbinding maken +Toolbar.DisconnectDrive = Netwerkverbinding verbreken +Toolbar.NavigationPane = Navigatievenster +Toolbar.DetailsPane = Detailvenster +Toolbar.PreviewPane = Voorbeeldvenster +Toolbar.CopyTo = Kopiëren naar +Toolbar.MoveTo = Verplaatsen naar +Toolbar.Deselect = Niets selecteren +Toolbar.InvertSelection = Selectie omkeren +Toolbar.FolderOptions = Mapopties +Toolbar.ShowHiddenFiles = Verborgen bestanden en mappen +Toolbar.ShowSystemFiles = Systeembestanden +Toolbar.ShowExtensions = Bestandsnaamextensies +Status.FreeSpace = %s (beschikbare schijfruimte: %s) +Status.Item = %s item +Status.Items = %s items +Status.ItemSelected = %s item geselecteerd +Status.ItemsSelected = %s items geselecteerd + + +[pl-PL] - Polish (Poland) +Copy.Cancel = Anuluj +Copy.More = Więcej... +Copy.CopyHere = &Kopiuj tutaj +Copy.MoveHere = Prze&nieś tutaj +Copy.Title = Potwierdź zamianę pliku +Copy.Subtitle = Ten folder zawiera już plik o nazwie „%s”. +Copy.SubtitleRO = Ten folder zawiera już plik tylko do odczytu o nazwie „%s”. +Copy.SubtitleSys = Ten folder zawiera już plik systemowy o nazwie „%s”. +Copy.Prompt1 = Czy chcesz zamienić istniejący plik +Copy.Prompt2 = na następujący? +Copy.Yes = &Tak +Copy.No = &Nie +Copy.YesAll = Tak na &wszystkie +Folder.Title = Potwierdź zamianę folderu +Folder.Prompt = Czy nadal chcesz przenieść lub skopiować ten folder? +Toolbar.GoUp = Do góry o jeden poziom +Toolbar.Cut = Wytnij +Toolbar.Copy = Kopiuj +Toolbar.Paste = Wklej +Toolbar.PasteShortcut = Wklej skrót +Toolbar.Delete = Usuń +Toolbar.Email = Wyślij zaznaczone elementy pocztą e-mail +Toolbar.Properties = Właściwości +Toolbar.NewFolder = Nowy folder +Toolbar.ZipFolder = Nowy folder skompresowany (zip) +Toolbar.ExtraLarge = Bardzo duże ikony +Toolbar.Large = Duże ikony +Toolbar.Medium = Średnie ikony +Toolbar.Small = Małe ikony +Toolbar.List = Lista +Toolbar.Details = Szczegóły +Toolbar.Tiles = Kafelki +Toolbar.Content = Zawartość +Toolbar.Undo = Cofnij +Toolbar.Redo = Wykonaj ponownie +Toolbar.Refresh = Odśwież +Toolbar.Back = Wstecz +Toolbar.Forward = Dalej +Toolbar.Stop = Zatrzymaj +Toolbar.Rename = Zmień nazwę +Toolbar.SelectAll = Zaznacz wszystko +Toolbar.CustomizeFolder = Dostosuj ten folder +Toolbar.MapDrive = Mapuj dysk sieciowy +Toolbar.DisconnectDrive = Odłącz dysk sieciowy +Toolbar.NavigationPane = Okienko nawigacji +Toolbar.DetailsPane = Okienko szczegółów +Toolbar.PreviewPane = Okienko podglądu +Toolbar.CopyTo = Kopiuj do +Toolbar.MoveTo = Przenieś do +Toolbar.Deselect = Nie zaznaczaj nic +Toolbar.InvertSelection = Odwróć zaznaczenie +Toolbar.FolderOptions = Opcje folderów +Toolbar.ShowHiddenFiles = Ukryte pliki i foldery +Toolbar.ShowSystemFiles = Pliki systemowe +Toolbar.ShowExtensions = Rozszerzenia nazw plików +Status.FreeSpace = %s (Wolne miejsce: %s) +Status.Item = %s element +Status.Items = Elementów: %s +Status.ItemSelected = Wybranych elementów: %s +Status.ItemsSelected = Wybranych elementów: %s + + +[pt-BR] - Portuguese (Brazil) +Copy.Cancel = Cancelar +Copy.More = Mais... +Copy.CopyHere = &Copiar Aqui +Copy.MoveHere = Mov&er para Cá +Copy.Title = Confirmar substituição de arquivo +Copy.Subtitle = Esta pasta já contém um arquivo chamado '%s'. +Copy.SubtitleRO = Esta pasta já contém um arquivo somente leitura chamado '%s'. +Copy.SubtitleSys = Esta pasta já contém um arquivo de sistema chamado '%s'. +Copy.Prompt1 = Deseja substituir o arquivo existente +Copy.Prompt2 = por este? +Copy.Yes = &Sim +Copy.No = &Não +Copy.YesAll = Sim para &todos +Folder.Title = Confirmar substituição de pasta +Folder.Prompt = Deseja mover a pasta mesmo assim? +Toolbar.GoUp = Um Nível Acima +Toolbar.Cut = Recortar +Toolbar.Copy = Copiar +Toolbar.Paste = Colar +Toolbar.PasteShortcut = Colar Atalho +Toolbar.Delete = Excluir +Toolbar.Email = Enviar os itens selecionados por email +Toolbar.Properties = Propriedades +Toolbar.NewFolder = Nova Pasta +Toolbar.ZipFolder = Nova Pasta Compactada +Toolbar.ExtraLarge = Ícones Extra Grandes +Toolbar.Large = Ícones Grandes +Toolbar.Medium = Ícones Médios +Toolbar.Small = Ícones Pequenos +Toolbar.List = Lista +Toolbar.Details = Detalhes +Toolbar.Tiles = Lado a Lado +Toolbar.Content = Conteúdo +Toolbar.Undo = Desfazer +Toolbar.Redo = Refazer +Toolbar.Refresh = Atualizar +Toolbar.Back = Voltar +Toolbar.Forward = Avançar +Toolbar.Stop = Parar +Toolbar.Rename = Renomear +Toolbar.SelectAll = Selecionar tudo +Toolbar.CustomizeFolder = Personalizar esta pasta +Toolbar.MapDrive = Mapear unidade de rede +Toolbar.DisconnectDrive = Desconectar unidade de rede +Toolbar.NavigationPane = Painel de navegação +Toolbar.DetailsPane = Painel de detalhes +Toolbar.PreviewPane = Painel de visualização +Toolbar.CopyTo = Copiar para +Toolbar.MoveTo = Mover para +Toolbar.Deselect = Selecionar nenhum +Toolbar.InvertSelection = Inverter seleção +Toolbar.FolderOptions = Opções de pasta +Toolbar.ShowHiddenFiles = Pastas e arquivos ocultos +Toolbar.ShowSystemFiles = Arquivos do sistema +Toolbar.ShowExtensions = Extensões de nomes de arquivos +Status.FreeSpace = %s (espaço livre em disco: %s) +Status.Item = %s item +Status.Items = %s itens +Status.ItemSelected = %s item selecionado +Status.ItemsSelected = %s itens selecionados + + +[pt-PT] - Portuguese (Portugal) +Copy.Cancel = Cancelar +Copy.More = Mais... +Copy.CopyHere = &Copiar para aqui +Copy.MoveHere = &Mover para aqui +Copy.Title = Confirmar substituição de ficheiro(s) +Copy.Subtitle = Esta pasta já contém um ficheiro com o nome '%s'. +Copy.SubtitleRO = Esta pasta já contém um ficheiro só de leitura com o nome '%s'. +Copy.SubtitleSys = Esta pasta já contém um ficheiro de sistema com o nome '%s'. +Copy.Prompt1 = Pretende substituir o ficheiro existente +Copy.Prompt2 = por este? +Copy.Yes = &Sim +Copy.No = &Não +Copy.YesAll = Sim p&ara todos +Folder.Title = Confirmar substituição de pasta(s) +Folder.Prompt = Pretende continuar a mover ou copiar a pasta? +Toolbar.GoUp = Um nível acima +Toolbar.Cut = Cortar +Toolbar.Copy = Copiar +Toolbar.Paste = Colar +Toolbar.PasteShortcut = Colar atalho +Toolbar.Delete = Eliminar +Toolbar.Email = Enviar os itens seleccionados por correio electrónico +Toolbar.Properties = Propriedades +Toolbar.NewFolder = Nova pasta +Toolbar.ZipFolder = Nova Pasta Comprimida (zipada) +Toolbar.ExtraLarge = Ícones muito grandes +Toolbar.Large = Ícones grandes +Toolbar.Medium = Ícones médios +Toolbar.Small = Ícones pequenos +Toolbar.List = Lista +Toolbar.Details = Detalhes +Toolbar.Tiles = Mosaicos +Toolbar.Content = Conteúdo +Toolbar.Undo = Anular +Toolbar.Redo = Refazer +Toolbar.Refresh = Actualizar +Toolbar.Back = Anterior +Toolbar.Forward = Avançar +Toolbar.Stop = Parar +Toolbar.Rename = Mudar o nome +Toolbar.SelectAll = Seleccionar tudo +Toolbar.CustomizeFolder = Personalizar esta pasta +Toolbar.MapDrive = Mapear unidade de rede +Toolbar.DisconnectDrive = Desligar unidade de rede +Toolbar.NavigationPane = Painel de navegação +Toolbar.DetailsPane = Painel de detalhes +Toolbar.PreviewPane = Painel de pré-visualização +Toolbar.CopyTo = Copiar para +Toolbar.MoveTo = Mover para +Toolbar.Deselect = Desmarcar tudo +Toolbar.InvertSelection = Inverter seleção +Toolbar.FolderOptions = Opções de pastas +Toolbar.ShowHiddenFiles = Ficheiros e pastas ocultos +Toolbar.ShowSystemFiles = Ficheiros de sistema +Toolbar.ShowExtensions = Extensões de nome de ficheiro +Status.FreeSpace = %s (Espaço livre em disco: %s) +Status.Item = %s item +Status.Items = %s itens +Status.ItemSelected = %s item seleccionado +Status.ItemsSelected = %s itens seleccionados + + +[ro-RO] - Romanian (Romania) +Copy.Cancel = Revocare +Copy.More = Mai multe... +Copy.CopyHere = &Copiere în acest loc +Copy.MoveHere = &Mutare în acest loc +Copy.Title = Confirmare înlocuire fişier +Copy.Subtitle = Acest folder conţine deja un fişier cu numele '%s'. +Copy.SubtitleRO = Acest folder conţine deja un fişier doar în citire cu numele '%s'. +Copy.SubtitleSys = Acest folder conţine deja un fişier de sistem cu numele '%s'. +Copy.Prompt1 = Înlocuiţi fişierul existent +Copy.Prompt2 = cu acesta? +Copy.Yes = &Da +Copy.No = &Nu +Copy.YesAll = D&a pentru tot +Folder.Title = Confirmare înlocuire folder +Folder.Prompt = Totuşi, mutaţi sau copiaţi folderul? +Toolbar.GoUp = Mai sus cu un nivel +Toolbar.Cut = Decupare +Toolbar.Copy = Copiere +Toolbar.Paste = Lipire +Toolbar.PasteShortcut = Lipire comandă rapidă +Toolbar.Delete = Ștergere +Toolbar.Email = Se trimit prin poştă electronică elementele selectate +Toolbar.Properties = Proprietăți +Toolbar.NewFolder = Folder nou +Toolbar.ZipFolder = Folder comprimat (ZIP) nou +Toolbar.ExtraLarge = Pictograme foarte mari +Toolbar.Large = Pictograme mari +Toolbar.Medium = Pictograme medii +Toolbar.Small = Pictograme mici +Toolbar.List = Listă +Toolbar.Details = Detalii +Toolbar.Tiles = Cadre +Toolbar.Content = Cuprins +Toolbar.Undo = Anulare +Toolbar.Redo = Refacere +Toolbar.Refresh = Reîmprospătare +Toolbar.Back = Înapoi +Toolbar.Forward = Înainte +Toolbar.Stop = Oprire +Toolbar.Rename = Redenumire +Toolbar.SelectAll = Selectare totală +Toolbar.CustomizeFolder = Particularizare folder +Toolbar.MapDrive = Conectare unitate de rețea +Toolbar.DisconnectDrive = Deconectare unitate de rețea +Toolbar.NavigationPane = Panou de navigare +Toolbar.DetailsPane = Panou detalii +Toolbar.PreviewPane = Panou de examinare +Toolbar.CopyTo = Copiere în +Toolbar.MoveTo = Mutare la +Toolbar.Deselect = Deselectare totală +Toolbar.InvertSelection = Inversare selecție +Toolbar.FolderOptions = Opțiuni folder +Toolbar.ShowHiddenFiles = Fișiere și foldere ascunse +Toolbar.ShowSystemFiles = Fișiere de sistem +Toolbar.ShowExtensions = Extensii nume de fișier +Status.FreeSpace = %s (Spațiu liber pe disc: %s) +Status.Item = Element %s +Status.Items = %s elemente +Status.ItemSelected = %s element selectat +Status.ItemsSelected = %s elemente selectate + + +[ru-RU] - Russian (Russia) +Copy.Cancel = Отмена +Copy.More = Подробнее... +Copy.CopyHere = &Копировать +Copy.MoveHere = П&ереместить +Copy.Title = Подтверждение замены файла +Copy.Subtitle = Папка уже содержит файл "%s". +Copy.SubtitleRO = Папка уже содержит доступный только для чтения файл "%s". +Copy.SubtitleSys = Папка уже содержит системный файл "%s". +Copy.Prompt1 = Заменить имеющийся файл +Copy.Prompt2 = следующим файлом? +Copy.Yes = &Да +Copy.No = &Нет +Copy.YesAll = Да - для &всех +Folder.Title = Подтверждение замены папки +Folder.Prompt = Заменить существующие в ней файлы перемещаемыми при совпадении имен? +Toolbar.GoUp = На один уровень вверх +Toolbar.Cut = Вырезать +Toolbar.Copy = Копировать +Toolbar.Paste = Вставить +Toolbar.PasteShortcut = Вставить ярлык +Toolbar.Delete = Удалить +Toolbar.Email = Отправка выбранных объектов по электронной почте +Toolbar.Properties = Свойства +Toolbar.NewFolder = Новая папка +Toolbar.ZipFolder = Новая сжатая ZIP-папка +Toolbar.ExtraLarge = Огромные значки +Toolbar.Large = Крупные значки +Toolbar.Medium = Обычные значки +Toolbar.Small = Мелкие значки +Toolbar.List = Список +Toolbar.Details = Таблица +Toolbar.Tiles = Плитка +Toolbar.Content = Содержимое +Toolbar.Undo = Отменить +Toolbar.Redo = Вернуть +Toolbar.Refresh = Обновить +Toolbar.Back = Назад +Toolbar.Forward = Вперед +Toolbar.Stop = Остановить +Toolbar.Rename = Переименовать +Toolbar.SelectAll = Выделить все +Toolbar.CustomizeFolder = Настроить папку +Toolbar.MapDrive = Подключить сетевой диск +Toolbar.DisconnectDrive = Отключить сетевой диск +Toolbar.NavigationPane = Область переходов +Toolbar.DetailsPane = Область сведений +Toolbar.PreviewPane = Область предпросмотра +Toolbar.CopyTo = Копировать в +Toolbar.MoveTo = Переместить в +Toolbar.Deselect = Снять выделение +Toolbar.InvertSelection = Обратить выделение +Toolbar.FolderOptions = Параметры папок +Toolbar.ShowHiddenFiles = Скрытые файлы и папки +Toolbar.ShowSystemFiles = Системные файлы +Toolbar.ShowExtensions = Расширения имен файлов +Status.FreeSpace = %s (свободно на диске: %s) +Status.Item = %s элемент +Status.Items = Элементов: %s +Status.ItemSelected = Выбран элемент: %s +Status.ItemsSelected = Выбрано элементов: %s + + +[sk-SK] - Slovak (Slovakia) +Copy.Cancel = Zrušiť +Copy.More = Ďalšie... +Copy.CopyHere = &Kopírovať sem +Copy.MoveHere = &Premiestniť sem +Copy.Title = Potvrdenie nahradenia súboru +Copy.Subtitle = Tento priečinok už obsahuje súbor s názvom %s. +Copy.SubtitleRO = Tento priečinok už obsahuje súbor s názvom %s, ktorý je iba na čítanie. +Copy.SubtitleSys = Tento priečinok už obsahuje systémový súbor s názvom %s. +Copy.Prompt1 = Chcete nahradiť existujúci súbor +Copy.Prompt2 = týmto súborom? +Copy.Yes = Án&o +Copy.No = &Nie +Copy.YesAll = Áno pre &všetky +Folder.Title = Potvrdenie nahradenia priečinka +Folder.Prompt = Naozaj chcete premiestniť alebo skopírovať priečinok? +Toolbar.GoUp = O úroveň vyššie +Toolbar.Cut = Vystrihnúť +Toolbar.Copy = Kopírovať +Toolbar.Paste = Prilepiť +Toolbar.PasteShortcut = Prilepiť odkaz +Toolbar.Delete = Odstrániť +Toolbar.Email = Vybraté položky odoslať e-mailom +Toolbar.Properties = Vlastnosti +Toolbar.NewFolder = Nový priečinok +Toolbar.ZipFolder = Nový komprimovaný priečinok (ZIP) +Toolbar.ExtraLarge = Veľmi veľké ikony +Toolbar.Large = Veľké ikony +Toolbar.Medium = Stredne veľké ikony +Toolbar.Small = Malé ikony +Toolbar.List = Zoznam +Toolbar.Details = Podrobnosti +Toolbar.Tiles = Dlaždice +Toolbar.Content = Obsah +Toolbar.Undo = Späť +Toolbar.Redo = Znova +Toolbar.Refresh = Obnoviť +Toolbar.Back = Dozadu +Toolbar.Forward = Dopredu +Toolbar.Stop = Zastaviť +Toolbar.Rename = Premenovať +Toolbar.SelectAll = Vybrať všetko +Toolbar.CustomizeFolder = Prispôsobiť priečinok +Toolbar.MapDrive = Pripojiť sieťovú jednotku +Toolbar.DisconnectDrive = Odpojiť sieťovú jednotku +Toolbar.NavigationPane = Navigačná tabla +Toolbar.DetailsPane = Tabla podrobností +Toolbar.PreviewPane = Tabla ukážky +Toolbar.CopyTo = Kopírovať do +Toolbar.MoveTo = Premiestniť do +Toolbar.Deselect = Zrušiť výber +Toolbar.InvertSelection = Invertovať výber +Toolbar.FolderOptions = Možnosti priečinka +Toolbar.ShowHiddenFiles = Skryté súbory a priečinky +Toolbar.ShowSystemFiles = Systémové súbory +Toolbar.ShowExtensions = Prípony názvov súborov +Status.FreeSpace = %s (voľné miesto na disku: %s) +Status.Item = %s položka +Status.Items = Počet položiek: %s +Status.ItemSelected = Počet vybratých položiek: %s +Status.ItemsSelected = Počet vybratých položiek: %s + + +[sl-SI] - Slovenian (Slovenia) +Copy.Cancel = Prekliči +Copy.More = Dodatno ... +Copy.CopyHere = &Kopiraj sem +Copy.MoveHere = &Premakni sem +Copy.Title = Potrditev zamenjave datoteke +Copy.Subtitle = Ta mapa že vsebuje datoteko z imenom »%s«. +Copy.SubtitleRO = Ta mapa že vsebuje datoteko samo za branje z imenom »%s«. +Copy.SubtitleSys = Ta mapa že vsebuje sistemsko datoteko z imenom »%s«. +Copy.Prompt1 = Ali želite zamenjati obstoječo datoteko +Copy.Prompt2 = s to datoteko? +Copy.Yes = &Da +Copy.No = &Ne +Copy.YesAll = Da za &vse +Folder.Title = Potrditev zamenjave mape +Folder.Prompt = Ali še vedno želite premakniti ali kopirati mapo? +Toolbar.GoUp = V nadrejeno mapo +Toolbar.Cut = Izreži +Toolbar.Copy = Kopiraj +Toolbar.Paste = Prilepi +Toolbar.PasteShortcut = Prilepi bližnjico +Toolbar.Delete = Izbriši +Toolbar.Email = Pošlji izbrane elemente prek e-pošte +Toolbar.Properties = Lastnosti +Toolbar.NewFolder = Nova mapa +Toolbar.ZipFolder = Nova stisnjena mapa +Toolbar.ExtraLarge = Izredno velike ikone +Toolbar.Large = Velike ikone +Toolbar.Medium = Srednje velike ikone +Toolbar.Small = Male ikone +Toolbar.List = Seznam +Toolbar.Details = Podrobnosti +Toolbar.Tiles = Ploščice +Toolbar.Content = Vsebina +Toolbar.Undo = Razveljavi +Toolbar.Redo = Uveljavi +Toolbar.Refresh = Osveži +Toolbar.Back = Nazaj +Toolbar.Forward = Naprej +Toolbar.Stop = Ustavi +Toolbar.Rename = Preimenuj +Toolbar.SelectAll = Izberi vse +Toolbar.CustomizeFolder = Prilagodi mapo +Toolbar.MapDrive = Preslikaj omrežni pogon +Toolbar.DisconnectDrive = Prekini povezavo z omrežnim pogonom +Toolbar.NavigationPane = Podokno za krmarjenje +Toolbar.DetailsPane = Podokno s podrobnostmi +Toolbar.PreviewPane = Podokno za predogled +Toolbar.CopyTo = Kopiraj v +Toolbar.MoveTo = Premakni v +Toolbar.Deselect = Ne izberi ničesar +Toolbar.InvertSelection = Preobrni izbor +Toolbar.FolderOptions = Možnosti mape +Toolbar.ShowHiddenFiles = Skrite datoteke in mape +Toolbar.ShowSystemFiles = Sistemske datoteke +Toolbar.ShowExtensions = Datotečne pripone +Status.FreeSpace = %s (Nezaseden prostor na disku: %s) +Status.Item = %s predmet +Status.Items = Št. predmetov: %s +Status.ItemSelected = Izbrano je to število elementov: %s +Status.ItemsSelected = Izbrano je to število elementov: %s + + +[sr-Latn-CS] - Serbian (Latin, Serbia) +Copy.Cancel = Otkaži +Copy.More = Više... +Copy.CopyHere = &Kopiraj ovde +Copy.MoveHere = &Premesti ovde +Copy.Title = Potvrdite zamenu datoteke +Copy.Subtitle = Ova fascikla već sadrži datoteku po imenu '%s'. +Copy.SubtitleRO = Ova fascikla već sadrži datoteku samo za čitanje po imenu '%s'. +Copy.SubtitleSys = Ova fascikla već sadrži sistemsku datoteku po imenu '%s'. +Copy.Prompt1 = Želite li da zamenite postojeću datoteku +Copy.Prompt2 = ovom? +Copy.Yes = &Da +Copy.No = &Ne +Copy.YesAll = Da za &sve +Folder.Title = Potvrdite zamenu fascikle +Folder.Prompt = Želite li zaista da premestite ili kopirate ovu fasciklu? +Toolbar.GoUp = Jedan nivo nagore +Toolbar.Cut = Iseci +Toolbar.Copy = Kopiraj +Toolbar.Paste = Nalepi +Toolbar.PasteShortcut = Nalepi prečicu +Toolbar.Delete = Izbriši +Toolbar.Email = Pošalji izabrane stavke e-poštom +Toolbar.Properties = Svojstva +Toolbar.NewFolder = Nova fascikla +Toolbar.ZipFolder = Nova komprimovana (zipovana) fascikla +Toolbar.ExtraLarge = Veoma velike ikone +Toolbar.Large = Velike ikone +Toolbar.Medium = Srednje ikone +Toolbar.Small = Male ikone +Toolbar.List = Lista +Toolbar.Details = Detalji +Toolbar.Tiles = Naporedno slaganje +Toolbar.Content = Sadržaj +Toolbar.Undo = Opozovi radnju +Toolbar.Redo = Ponovi radnju +Toolbar.Refresh = Osveži +Toolbar.Back = Nazad +Toolbar.Forward = Napred +Toolbar.Stop = Zaustavi +Toolbar.Rename = Preimenuj +Toolbar.SelectAll = Izaberi sve +Toolbar.CustomizeFolder = Prilagođavanje fascikle +Toolbar.MapDrive = Mapiraj mrežni disk +Toolbar.DisconnectDrive = Prekini vezu sa mrežnim diskom +Toolbar.NavigationPane = Okno za navigaciju +Toolbar.DetailsPane = Okno sa detaljima +Toolbar.PreviewPane = Okno za pregled +Toolbar.CopyTo = Kopiraj u +Toolbar.MoveTo = Premesti u +Toolbar.Deselect = Nemoj da izabereš nijedno +Toolbar.InvertSelection = Obrni izbor +Toolbar.FolderOptions = Opcije fascikle +Toolbar.ShowHiddenFiles = Skrivene datoteke i fascikle +Toolbar.ShowSystemFiles = Sistemske datoteke +Toolbar.ShowExtensions = Oznake tipa datoteke +Status.FreeSpace = %s (slobodan prostor na disku: %s) +Status.Item = %s stavka +Status.Items = %s stavki +Status.ItemSelected = %s izabrana stavka +Status.ItemsSelected = %s izabranih stavki + + +[sv-SE] - Swedish (Sweden) +Copy.Cancel = Avbryt +Copy.More = Mer... +Copy.CopyHere = K&opiera hit +Copy.MoveHere = &Flytta hit +Copy.Title = Bekräfta ersättning av fil +Copy.Subtitle = Den här mappen innehåller redan en fil med namnet %s. +Copy.SubtitleRO = Den här mappen innehåller redan en skrivskyddad fil med namnet %s. +Copy.SubtitleSys = Den här mappen innehåller redan en systemfil med namnet %s. +Copy.Prompt1 = Vill du ersätta den befintliga filen +Copy.Prompt2 = med följande fil? +Copy.Yes = &Ja +Copy.No = &Nej +Copy.YesAll = Ersätt &alla +Folder.Title = Bekräfta ersättning av mapp +Folder.Prompt = Vill du ersätta filerna i den mappen om de har samma namn som filerna i mappen som flyttas eller kopieras? +Toolbar.GoUp = Upp en nivå +Toolbar.Cut = Klipp ut +Toolbar.Copy = Kopiera +Toolbar.Paste = Klistra in +Toolbar.PasteShortcut = Klistra in genväg +Toolbar.Delete = Ta bort +Toolbar.Email = Skicka de markerade objekten i e-postmeddelanden +Toolbar.Properties = Egenskaper +Toolbar.NewFolder = Ny mapp +Toolbar.ZipFolder = Ny komprimerad mapp +Toolbar.ExtraLarge = Extra stora ikoner +Toolbar.Large = Stora ikoner +Toolbar.Medium = Medelstora ikoner +Toolbar.Small = Små ikoner +Toolbar.List = Lista +Toolbar.Details = Detaljerad lista +Toolbar.Tiles = Sammanfattning +Toolbar.Content = Innehåll +Toolbar.Undo = Ångra +Toolbar.Redo = Gör om +Toolbar.Refresh = Uppdatera +Toolbar.Back = Bakåt +Toolbar.Forward = Framåt +Toolbar.Stop = Stoppa +Toolbar.Rename = Byt namn +Toolbar.SelectAll = Markera alla +Toolbar.CustomizeFolder = Anpassa den här mappen +Toolbar.MapDrive = Anslut nätverksenhet +Toolbar.DisconnectDrive = Koppla från nätverksenhet +Toolbar.NavigationPane = Navigeringsfönstret +Toolbar.DetailsPane = Informationsfönstret +Toolbar.PreviewPane = Förhandsgranskningsfönstret +Toolbar.CopyTo = Kopiera till +Toolbar.MoveTo = Flytta till +Toolbar.Deselect = Avmarkera alla +Toolbar.InvertSelection = Invertera markering +Toolbar.FolderOptions = Mappalternativ +Toolbar.ShowHiddenFiles = Dolda filer och mappar +Toolbar.ShowSystemFiles = Systemfiler +Toolbar.ShowExtensions = Filnamnstillägg +Status.FreeSpace = %s (Ledigt utrymme: %s) +Status.Item = %s objekt +Status.Items = %s objekt +Status.ItemSelected = %s objekt markerat +Status.ItemsSelected = %s objekt markerade + + +[th-TH] - Thai (Thailand) +Copy.Cancel = ยกเลิก +Copy.More = เพิ่มเติม... +Copy.CopyHere = คัด&ลอกมาที่นี่ +Copy.MoveHere = ย้&ายมาที่นี่ +Copy.Title = ยืนยันการแทนที่แฟ้ม +Copy.Subtitle = โฟลเดอร์นี้มีแฟ้มชื่อ '%s' อยู่แล้ว +Copy.SubtitleRO = โฟลเดอร์นี้มีแฟ้มแบบอ่านอย่างเดียวที่ชื่อ '%s' อยู่แล้ว +Copy.SubtitleSys = โฟลเดอร์นี้มีแฟ้มระบบที่ชื่อ '%s' อยู่แล้ว +Copy.Prompt1 = คุณต้องการแทนที่แฟ้มที่มีอยู่ +Copy.Prompt2 = ด้วยแฟ้มนี้หรือไม่ +Copy.Yes = ใ&ช่ +Copy.No = ไ&ม่ใช่ +Copy.YesAll = ใช่&ทั้งหมด +Folder.Title = การยืนยันการแทนที่โฟลเดอร์ +Folder.Prompt = ถ้าแฟ้มในโฟลเดอร์ที่มีอยู่มีชื่อเดียวกันกับแฟ้มในโฟลเดอร์ที่คุณกำลังย้ายหรือคัดลอก แฟ้มเหล่านั้นจะถูกแทนที่ คุณยังต้องการที่จะย้ายหรือคัดลอกโฟลเดอร์หรือไม่ +Toolbar.GoUp = เลื่อนขึ้นหนึ่งระดับ +Toolbar.Cut = ตัด +Toolbar.Copy = คัดลอก +Toolbar.Paste = วาง +Toolbar.PasteShortcut = วางทางลัด +Toolbar.Delete = ลบ +Toolbar.Email = ส่งอีเมลรายการที่เลือก +Toolbar.Properties = คุณสมบัติ +Toolbar.NewFolder = สร้างโฟลเดอร์ +Toolbar.ZipFolder = โฟลเดอร์ที่บีบอัดใหม่ +Toolbar.ExtraLarge = ไอคอนขนาดใหญ่พิเศษ +Toolbar.Large = ไอคอนขนาดใหญ่ +Toolbar.Medium = ไอคอนขนาดกลาง +Toolbar.Small = ไอคอนขนาดเล็ก +Toolbar.List = รายการ +Toolbar.Details = รายละเอียด +Toolbar.Tiles = เรียงต่อกัน +Toolbar.Content = เนื้อหา +Toolbar.Undo = เลิกทำ +Toolbar.Redo = ทำซ้ำ +Toolbar.Refresh = ฟื้นฟู +Toolbar.Back = ย้อนกลับ +Toolbar.Forward = ไปข้างหน้า +Toolbar.Stop = หยุด +Toolbar.Rename = เปลี่ยนชื่อ +Toolbar.SelectAll = เลือกทั้งหมด +Toolbar.CustomizeFolder = กำหนดโฟลเดอร์นี้เอง +Toolbar.MapDrive = แมปไดรฟ์เครือข่าย +Toolbar.DisconnectDrive = ยกเลิกการเชื่อมต่อไดรฟ์เครือข่าย +Toolbar.NavigationPane = บานหน้าต่างนำทาง +Toolbar.DetailsPane = บานหน้าต่างแสดงรายละเอียด +Toolbar.PreviewPane = บานหน้าต่างแสดงตัวอย่าง +Toolbar.CopyTo = คัดลอกไปที่ +Toolbar.MoveTo = ย้ายไปที่ +Toolbar.Deselect = ไม่เลือกเลย +Toolbar.InvertSelection = สลับส่วนที่เลือก +Toolbar.FolderOptions = ตัวเลือกโฟลเดอร์ +Toolbar.ShowHiddenFiles = แฟ้มและโฟลเดอร์ที่ซ่อนไว้ +Toolbar.ShowSystemFiles = แฟ้มระบบ +Toolbar.ShowExtensions = ส่วนขยายของแฟ้ม +Status.FreeSpace = %s (เนื้อที่ว่างดิสก์: %s) +Status.Item = %s รายการ +Status.Items = %s รายการ +Status.ItemSelected = เลือก %s รายการ +Status.ItemsSelected = เลือก %s รายการ + + +[tr-TR] - Turkish (Turkey) +Copy.Cancel = İptal +Copy.More = Tümü... +Copy.CopyHere = Buraya &Kopyala +Copy.MoveHere = Buraya &Taşı +Copy.Title = Dosya Değişimini Onayla +Copy.Subtitle = Bu klasörde zaten '%s' adlı bir dosya var. +Copy.SubtitleRO = Bu klasörde zaten '%s' adlı salt okunur bir dosya var. +Copy.SubtitleSys = Bu klasörde zaten '%s' adlı bir sistem dosyası var. +Copy.Prompt1 = Varolan dosyayı +Copy.Prompt2 = aşağıdaki dosya ile değiştirmek istiyor musunuz? +Copy.Yes = &Evet +Copy.No = &Hayır +Copy.YesAll = &Tümüne Evet +Folder.Title = Klasör Değişimini Onayla +Folder.Prompt = Klasörü taşımak ya da kopyalamak istiyor musunuz? +Toolbar.GoUp = Bir Düzey Yukarı +Toolbar.Cut = Kes +Toolbar.Copy = Kopyala +Toolbar.Paste = Yapıştır +Toolbar.PasteShortcut = Kısayol Yapıştır +Toolbar.Delete = Sil +Toolbar.Email = Seçili öğeleri e-postayla gönder +Toolbar.Properties = Özellikler +Toolbar.NewFolder = Yeni Klasör +Toolbar.ZipFolder = Yeni Sıkıştırılmış Klasör +Toolbar.ExtraLarge = Çok Büyük Simgeler +Toolbar.Large = Büyük Simgeler +Toolbar.Medium = Orta Boy Simgeler +Toolbar.Small = Küçük Simgeler +Toolbar.List = Listele +Toolbar.Details = Ayrıntılar +Toolbar.Tiles = Döşemeler +Toolbar.Content = İçerik +Toolbar.Undo = Geri Al +Toolbar.Redo = Yinele +Toolbar.Refresh = Yenile +Toolbar.Back = Geri +Toolbar.Forward = İleri +Toolbar.Stop = Durdur +Toolbar.Rename = Yeniden Adlandır +Toolbar.SelectAll = Tümünü seç +Toolbar.CustomizeFolder = Bu klasörü özelleştir +Toolbar.MapDrive = Ağ sürücüsüne bağlan +Toolbar.DisconnectDrive = Ağ sürücüsü bağlantısını kes +Toolbar.NavigationPane = Gezinti bölmesi +Toolbar.DetailsPane = Ayrıntılar bölmesi +Toolbar.PreviewPane = Önizleme bölmesi +Toolbar.CopyTo = Kopyalama hedefi +Toolbar.MoveTo = Taşıma hedefi +Toolbar.Deselect = Hiçbirini seçme +Toolbar.InvertSelection = Diğerlerini seç +Toolbar.FolderOptions = Klasör seçenekleri +Toolbar.ShowHiddenFiles = Gizli dosya ve klasörler +Toolbar.ShowSystemFiles = Sistem dosyaları +Toolbar.ShowExtensions = Dosya adı uzantıları +Status.FreeSpace = %s (Boş disk boş alanı: %s) +Status.Item = %s öğe +Status.Items = %s öğe +Status.ItemSelected = %s öğe seçili +Status.ItemsSelected = %s öğe seçili + + +[uk-UA] - Ukrainian (Ukraine) +Copy.Cancel = Скасувати +Copy.More = Додатково... +Copy.CopyHere = &Копіювати сюди +Copy.MoveHere = П&еремістити +Copy.Title = Підтвердження заміни файлу +Copy.Subtitle = Ця папка вже містить файл з ім'ям "%s". +Copy.SubtitleRO = Ця папка вже містить доступний лише для читання файл з ім'ям "%s". +Copy.SubtitleSys = Ця папка вже містить системний файл з ім'ям "%s". +Copy.Prompt1 = Замінити наявний файл +Copy.Prompt2 = на цей файл? +Copy.Yes = &Так +Copy.No = &Ні +Copy.YesAll = Так для &всіх +Folder.Title = Підтвердження заміни папки +Folder.Prompt = Розпочати переміщення або копіювання папки? +Toolbar.GoUp = На один рівень вгору +Toolbar.Cut = Вирізати +Toolbar.Copy = Копіювати +Toolbar.Paste = Вставити +Toolbar.PasteShortcut = Вставити ярлик +Toolbar.Delete = Видалити +Toolbar.Email = Надіслати виділені об'єкти електронною поштою +Toolbar.Properties = Властивості +Toolbar.NewFolder = Створити папку +Toolbar.ZipFolder = Нова стиснута ZIP-папка +Toolbar.ExtraLarge = Величезні піктограми +Toolbar.Large = Великі піктограми +Toolbar.Medium = Середні піктограми +Toolbar.Small = Дрібні піктограми +Toolbar.List = Список +Toolbar.Details = Таблиця +Toolbar.Tiles = Мозаїка +Toolbar.Content = Вміст +Toolbar.Undo = Скасувати +Toolbar.Redo = Повторити +Toolbar.Refresh = Оновити +Toolbar.Back = Назад +Toolbar.Forward = Вперед +Toolbar.Stop = Зупинити +Toolbar.Rename = Перейменувати +Toolbar.SelectAll = Вибрати всі +Toolbar.CustomizeFolder = Настроїти папку +Toolbar.MapDrive = Підключити мережний диск +Toolbar.DisconnectDrive = Відключити мережний диск +Toolbar.NavigationPane = Область переходів +Toolbar.DetailsPane = Область відомостей +Toolbar.PreviewPane = Область перегляду +Toolbar.CopyTo = Копіювати +Toolbar.MoveTo = Перемістити +Toolbar.Deselect = Скасувати виділення +Toolbar.InvertSelection = Обернути виділення +Toolbar.FolderOptions = Параметри папки +Toolbar.ShowHiddenFiles = Приховані файли й папки +Toolbar.ShowSystemFiles = Системні файли +Toolbar.ShowExtensions = Розширення імен файлів +Status.FreeSpace = %s (Доступно на диску: %s) +Status.Item = %s елемент +Status.Items = %s елементів +Status.ItemSelected = Вибрано елемент: %s +Status.ItemsSelected = Вибрано елементів: %s + + +[zh-CN] - Chinese (Simplified) +Copy.Cancel = 取消 +Copy.More = 其他... +Copy.CopyHere = 复制到当前位置(&C) +Copy.MoveHere = 移动到当前位置(&M) +Copy.Title = 确认文件替换 +Copy.Subtitle = 此文件夹已包含一个名为“%s”的文件。 +Copy.SubtitleRO = 此文件夹已包括一个名为“%s”的只读文件。 +Copy.SubtitleSys = 此文件夹已包括一个名为“%s”的系统文件。 +Copy.Prompt1 = 是否将现有文件 +Copy.Prompt2 = 替换为 +Copy.Yes = 是(&Y) +Copy.No = 否(&N) +Copy.YesAll = 全部(&A) +Folder.Title = 确认文件夹替换 +Folder.Prompt = 是否移动或复制文件夹? +Toolbar.GoUp = 向上一级 +Toolbar.Cut = 剪切 +Toolbar.Copy = 复制 +Toolbar.Paste = 粘贴 +Toolbar.PasteShortcut = 粘贴快捷方式 +Toolbar.Delete = 删除 +Toolbar.Email = 以电子邮件形式发送所选项目 +Toolbar.Properties = 属性 +Toolbar.NewFolder = 新文件夹 +Toolbar.ZipFolder = 新建压缩的(zipped)文件夹 +Toolbar.ExtraLarge = 超大图标 +Toolbar.Large = 大图标 +Toolbar.Medium = 中等图标 +Toolbar.Small = 小图标 +Toolbar.List = 列表 +Toolbar.Details = 详细信息 +Toolbar.Tiles = 平铺 +Toolbar.Content = 内容 +Toolbar.Undo = 撤消 +Toolbar.Redo = 恢复 +Toolbar.Refresh = 刷新 +Toolbar.Back = 后退 +Toolbar.Forward = 前进 +Toolbar.Stop = 停止 +Toolbar.Rename = 重命名 +Toolbar.SelectAll = 全选 +Toolbar.CustomizeFolder = 自定义文件夹 +Toolbar.MapDrive = 映射网络驱动器 +Toolbar.DisconnectDrive = 断开网络驱动器 +Toolbar.NavigationPane = 导航窗格 +Toolbar.DetailsPane = 细节窗格 +Toolbar.PreviewPane = 预览窗格 +Toolbar.CopyTo = 复制到​​ +Toolbar.MoveTo = 移动到​​ +Toolbar.Deselect = 全部取消 +Toolbar.InvertSelection = 反向选择 +Toolbar.FolderOptions = 文件夹选项 +Toolbar.ShowHiddenFiles = 隐藏文件和文件夹 +Toolbar.ShowSystemFiles = 系统文件 +Toolbar.ShowExtensions = 文件扩展名 +Status.FreeSpace = %s (磁盘可用空间: %s) +Status.Item = %s 项 +Status.Items = %s 个项目 +Status.ItemSelected = 已选择 %s 项 +Status.ItemsSelected = 已选择 %s 个项 + + +[zh-HK] - Chinese (Traditional) +Copy.Cancel = 取消 +Copy.More = 其他... +Copy.CopyHere = 複製到這裡(&C) +Copy.MoveHere = 移動到這裡(&M) +Copy.Title = 確認取代檔案 +Copy.Subtitle = 這個資料夾已經有一個名稱為 '%s' 的檔案。 +Copy.SubtitleRO = 這個資料夾已經有一個名稱為 '%s' 的唯讀檔。 +Copy.SubtitleSys = 這個資料夾已經有一個名稱為 '%s' 的系統檔。 +Copy.Prompt1 = 您要將目前的檔案 +Copy.Prompt2 = 取代成這個檔案嗎? +Copy.Yes = 是(&Y) +Copy.No = 否(&N) +Copy.YesAll = 全部取代(&A) +Folder.Title = 確認取代資料夾 +Folder.Prompt = 仍然要移動或複製資料夾? +Toolbar.GoUp = 上移一層 +Toolbar.Cut = 剪下 +Toolbar.Copy = 複製 +Toolbar.Paste = 貼上 +Toolbar.PasteShortcut = 貼上捷徑 +Toolbar.Delete = 刪除 +Toolbar.Email = 以電子郵件傳送選取的項目 +Toolbar.Properties = 內容 +Toolbar.NewFolder = 新增資料夾 +Toolbar.ZipFolder = 新壓縮 (zipped) 資料夾 +Toolbar.ExtraLarge = 特大圖示 +Toolbar.Large = 大圖示 +Toolbar.Medium = 中圖示 +Toolbar.Small = 小圖示 +Toolbar.List = 清單 +Toolbar.Details = 詳細資料 +Toolbar.Tiles = 並排 +Toolbar.Content = 內容 +Toolbar.Undo = 復原 +Toolbar.Redo = 重做 +Toolbar.Refresh = 重新整理 +Toolbar.Back = 上一頁 +Toolbar.Forward = 下一頁 +Toolbar.Stop = 停止 +Toolbar.Rename = 重新命名 +Toolbar.SelectAll = 全選 +Toolbar.CustomizeFolder = 自訂此資料夾 +Toolbar.MapDrive = 連線網路磁碟機 +Toolbar.DisconnectDrive = 中斷網路磁碟機 +Toolbar.NavigationPane = 瀏覽窗格 +Toolbar.DetailsPane = 詳細資料窗格 +Toolbar.PreviewPane = 預覽窗格 +Toolbar.CopyTo = 複製到​​ +Toolbar.MoveTo = 移至​​ +Toolbar.Deselect = 全部不選 +Toolbar.InvertSelection = 反向選擇 +Toolbar.FolderOptions = 資料夾選項 +Toolbar.ShowHiddenFiles = 隱藏的檔案和資料夾 +Toolbar.ShowSystemFiles = 系統檔 +Toolbar.ShowExtensions = 副檔名 +Status.FreeSpace = %s (磁碟可用空間: %s) +Status.Item = %s 個項目 +Status.Items = %s 個項目 +Status.ItemSelected = 選取了 %s 個項目 +Status.ItemsSelected = 選取了 %s 個項目 + + +[zh-TW] - Chinese (Traditional) +Copy.Cancel = 取消 +Copy.More = 其他... +Copy.CopyHere = 複製到這裡(&C) +Copy.MoveHere = 移動到這裡(&M) +Copy.Title = 確認取代檔案 +Copy.Subtitle = 這個資料夾已經有一個名稱為 '%s' 的檔案。 +Copy.SubtitleRO = 這個資料夾已經有一個名稱為 '%s' 的唯讀檔。 +Copy.SubtitleSys = 這個資料夾已經有一個名稱為 '%s' 的系統檔。 +Copy.Prompt1 = 您要將目前的檔案 +Copy.Prompt2 = 取代成這個檔案嗎? +Copy.Yes = 是(&Y) +Copy.No = 否(&N) +Copy.YesAll = 全部取代(&A) +Folder.Title = 確認取代資料夾 +Folder.Prompt = 仍然要移動或複製資料夾? +Toolbar.GoUp = 上移一層 +Toolbar.Cut = 剪下 +Toolbar.Copy = 複製 +Toolbar.Paste = 貼上 +Toolbar.PasteShortcut = 貼上捷徑 +Toolbar.Delete = 刪除 +Toolbar.Email = 以電子郵件傳送選取的項目 +Toolbar.Properties = 內容 +Toolbar.NewFolder = 新增資料夾 +Toolbar.ZipFolder = 新壓縮 (zipped) 資料夾 +Toolbar.ExtraLarge = 特大圖示 +Toolbar.Large = 大圖示 +Toolbar.Medium = 中圖示 +Toolbar.Small = 小圖示 +Toolbar.List = 清單 +Toolbar.Details = 詳細資料 +Toolbar.Tiles = 並排 +Toolbar.Content = 內容 +Toolbar.Undo = 復原 +Toolbar.Redo = 重做 +Toolbar.Refresh = 重新整理 +Toolbar.Back = 上一頁 +Toolbar.Forward = 下一頁 +Toolbar.Stop = 停止 +Toolbar.Rename = 重新命名 +Toolbar.SelectAll = 全選 +Toolbar.CustomizeFolder = 自訂此資料夾 +Toolbar.MapDrive = 連線網路磁碟機 +Toolbar.DisconnectDrive = 中斷網路磁碟機 +Toolbar.NavigationPane = 瀏覽窗格 +Toolbar.DetailsPane = 詳細資料窗格 +Toolbar.PreviewPane = 預覽窗格 +Toolbar.CopyTo = 複製到​​ +Toolbar.MoveTo = 移至​​ +Toolbar.Deselect = 全部不選 +Toolbar.InvertSelection = 反向選擇 +Toolbar.FolderOptions = 資料夾選項 +Toolbar.ShowHiddenFiles = 隱藏的檔案和資料夾 +Toolbar.ShowSystemFiles = 系統檔 +Toolbar.ShowExtensions = 副檔名 +Status.FreeSpace = %s (磁碟可用空間: %s) +Status.Item = %s 個項目 +Status.Items = %s 個項目 +Status.ItemSelected = 選取了 %s 個項目 +Status.ItemsSelected = 選取了 %s 個項目 diff --git a/ClassicShellLoc/StartMenuHelperL10N.ini b/ClassicShellLoc/StartMenuHelperL10N.ini new file mode 100644 index 0000000..dcec88f Binary files /dev/null and b/ClassicShellLoc/StartMenuHelperL10N.ini differ diff --git a/ClassicShellLoc/StartMenuL10N.ini b/ClassicShellLoc/StartMenuL10N.ini new file mode 100644 index 0000000..1be09df --- /dev/null +++ b/ClassicShellLoc/StartMenuL10N.ini @@ -0,0 +1,5596 @@ +; This file contains all localized text for Classic Start Menu. There is one section per language. +; Every section contains text lines in the form of = . +; Which section is used depends on the current OS setting. If a key is missing from the language section +; it will be searched in the [default] section. In some cases more than one language can be used. +; For example a Japanese system may use English as a secondary language. In that case the search order +; will be [ja-JP] -> [en-US] -> [default]. +; +; ============================================================================= + + +[default] +Menu.ClassicSettings = Classic Start &Menu +Menu.SettingsTip = Settings for Classic Start Menu + + +[ar-SA] - Arabic (Saudi Arabia) +Menu.Programs = البرا&مج +Menu.Apps = التطبيقات +Menu.AllPrograms = كافة البرامج +Menu.Back = الخلف +Menu.Favorites = المف&ضلة +Menu.Documents = المستن&دات +Menu.Settings = إ&عدادات +Menu.Search = بح&ث +Menu.SearchBox = بحث +Menu.SearchPrograms = البحث في البرامج والملفات +Menu.SearchInternet = بحث في إنترنت +Menu.Searching = يتم الآن البحث... +Menu.NoMatch = لا توجد أية عناصر تطابق البحث. +Menu.MoreResults = الاطلاع على مزيد من النتائج +Menu.Help = التع&ليمات والدعم +Menu.Run = تش&غيل... +Menu.Logoff = ت&سجيل خروج %s‎... +Menu.SwitchUser = تبديل المست&خدم +Menu.Lock = تأ&مين +Menu.LogOffShort = ت&سجيل الخروج +Menu.Undock = إلغاء إرساء ال&كمبيوتر +Menu.Disconnect = &قطع الاتصال +Menu.ShutdownBox = إيقا&ف التشغيل... +Menu.Shutdown = إيقاف الت&شغيل +Menu.Restart = إعادة التش&غيل +Menu.ShutdownUpdate = التحديث وإيقاف التشغيل +Menu.RestartUpdate = تثبيت التحديثات وإعادة التشغيل +Menu.Sleep = &سكون +Menu.Hibernate = إ&سبات +Menu.ControlPanel = لوحة التح&كم +Menu.PCSettings = إعدادات الكمبيوتر +Menu.Security = أمان Windows +Menu.Network = ا&تصالات الشبكة +Menu.Printers = &طابعات +Menu.Taskbar = &شريط المهام والقائمة "ابدأ" +Menu.SearchFiles = عن &ملفات أو مجلدات... +Menu.SearchPrinter = عن &طابعة +Menu.SearchComputers = عن أجهزة &كمبيوتر +Menu.UserFilesTip = يحتوي على مجلدات للمستندات والصور والموسيقى وغير ذلك من الملفات الخاصة بك. +Menu.UserDocumentsTip = يحتوي على خطابات وتقارير ومستندات وملفات أخرى. +Menu.UserPicturesTip = يحتوي على صور فوتوغرافية رقمية وصور وملفات رسومية. +Menu.UserMusicTip = يحتوي على ملفات الموسيقى والصوت الأخرى. +Menu.UserVideosTip = يحتوي على أفلام وملفات فيديو أخرى. +Menu.NetworkTip = ‏‏عرض اتصالات الشبكة الموجودة على هذا الكمبيوتر والمساعدة في إنشاء اتصالات جديدة +Menu.PrintersTip = إضافة الطابعات المحلية وطابعات الشبكة وإزالتها وتكوينها. +Menu.TaskbarTip = ‏‏تخصيص القائمة "ابدأ" وشريط المهام مثل أنواع العناصر التي سيتم عرضها وطريقة عرضها +Menu.ControlPanelTip = ‏‏تغيير الإعدادات وتخصيص وظائف الكمبيوتر. +Menu.DocumentsLibTip = الوصول إلى الخطابات والتقارير والملاحظات وغير ذلك من أنواع المستندات. +Menu.MusicLibTip = تشغيل ملفات الموسيقى وملفات الصوت الأخرى. +Menu.PicturesLibTip = عرض الصور الرقمية وتنظيمها. +Menu.VideosLibTip = مشاهدة الأفلام المنزلية ومقاطع الفيديو الرقمية الأخرى. +Menu.RecordingsLibTip = مشاهدة برامج التلفزيون المسجلة على الكمبيوتر. +Menu.DownloadTip = البحث عن تنزيلات إنترنت والارتباطات بمواقع ويب المفضلة. +Menu.HomegroupTip = الوصول إلى المكتبات والمجلدات المشتركة من قِبل أشخاص آخرين في مجموعة المشاركة المنزلية. +Menu.RunTip = فتح برنامج أو مجلد أو مستند أو موقع على ويب. +Menu.HelpTip = العثور على مواضيع "التعليمات"، والبرامج التعليمية واستكشاف الأخطاء وإصلاحها وخدمات الدعم الأخرى. +Menu.ProgramsTip = فتح قائمة من البرامج. +Menu.SearchFilesTip = البحث عن المستندات والموسيقى والصور والبريد الإلكتروني وغير ذلك. +Menu.GamesTip = تشغيل الألعاب وإدارتها على الكمبيوتر. +Menu.SecurityTip = بدء تشغيل خيارات أمان Windows لتغيير كلمة المرور أو تبديل المستخدم أو بدء إدارة المهام. +Menu.SearchComputersTip = البحث عن أجهزة كمبيوتر على الشبكة +Menu.SearchPrintersTip = البحث عن طابعة +Menu.AdminToolsTip = تكوين الإعدادات الإدارية للكمبيوتر +Menu.ShutdownTip = إغلاق كافة البرامج المفتوحة وإيقاف تشغيل Windows، ثم إيقاف تشغيل الكمبيوتر. +Menu.RestartTip = إغلاق كافة البرامج المفتوحة وإيقاف تشغيل Windows، ثم تشغيله مرة أخرى. +Menu.SleepTip = حفظ جلسة العمل في الذاكرة ووضع الكمبيوتر في حالة الطاقة المنخفضة حتى يمكن استئناف العمل بسرعة. +Menu.HibernateTip = حفظ جلسة العمل وإيقاف تشغيل الكمبيوتر. وعند تشغيل الكمبيوتر يقوم Windows باستعادة الجلسة. +Menu.LogOffTip = ‏‏أغلق البرامج وقم بتسجيل الخروج. +Menu.DisconnectTip = قطع الاتصال بجلسة العمل. يمكنك إعادة الاتصال بجلسة العمل هذه عند تسجيل الدخول مرة أخرى. +Menu.LockTip = تأمين هذا الكمبيوتر. +Menu.UndockTip = إزالة الكمبيوتر المحمول من محطة إرساء. +Menu.SwitchUserTip = تبديل المستخدمين بدون إغلاق البرامج. +Menu.Empty = (فارغ) +Menu.Features = البرامج والميزات +Menu.FeaturesTip = إزالة تثبيت البرامج الموجودة على الكمبيوتر أو تغييرها. +Menu.SearchPeople = عن أ&شخاص... +Menu.SortByName = فرز &حسب الاسم +Menu.Open = ف&تح +Menu.OpenAll = &فتح كافة المستخدمين +Menu.Explore = ا&ستكشاف +Menu.ExploreAll = است&كشاف كافة المستخدمين +Menu.MenuSettings = إعدادات +Menu.MenuHelp = تعليمات +Menu.MenuExit = إنهاء +Menu.LogoffTitle = تسجيل الخروج من Windows +Menu.LogoffPrompt = هل تريد بالتأكيد تسجيل الخروج؟ +Menu.LogoffYes = &تسجيل الخروج +Menu.LogoffNo = &لا +Menu.RenameTitle = إعادة تسمية +Menu.RenamePrompt = الاسم الج&ديد: +Menu.RenameOK = حسنا +Menu.RenameCancel = إلغاء الأمر +Menu.Organize = تنظيم قائمة "ابدأ" +Menu.Expand = تو&سيع +Menu.Collapse = &طي +Menu.NewFolder = مجلد جديد +Menu.NewShortcut = اختصار جديد +Menu.AutoArrange = ترتيب تل&قائي +Menu.ActionOpen = فتح +Menu.ActionClose = إغلاق +Menu.ActionExecute = تنفيذ +Menu.RemoveList = إزالة من هذه ال&قائمة +Menu.RemoveAll = م&سح قائمة العناصر الحديثة +Menu.Explorer = مستكشف Windows +Menu.Start = ابدأ +Menu.StartScreen = شاشة البدء +Menu.StartMenu = القائمة "ابدأ" (Windows) +Menu.PinStart = تثبيت بالقائمة "ابدأ". +Menu.PinStartCs = تثبيت بالقائمة "ابدأ". (Classic Shell) +Menu.UnpinStartCs = إزالة التثبيت من القائمة "ابدأ" (Classic Shell) +Menu.MonitorOff = إيقاف تشغيل شاشة العرض +Menu.RemoveHighlight = إزالة التمييز +Menu.Uninstall = إز&الة التثبيت +Menu.UninstallTitle = إزالة التثبيت +Menu.UninstallPrompt = ‏‏هل تريد بالتأكيد إزالة تثبيت %s؟ +Search.CategorySettings = الإعدادات +Search.CategoryPCSettings = إعدادات الكمبيوتر +Search.CategoryPrograms = البرامج +Search.CategoryDocuments = المستندات +Search.CategoryMusic = الموسيقى +Search.CategoryPictures = الصور +Search.CategoryVideos = ملفات فيديو +Search.CategoryFiles = الملفات +Search.CategoryInternet = إنترنت +JumpList.Recent = حديث +JumpList.Frequent = متكرر +JumpList.Tasks = المهام +JumpList.Pinned = مثبت +JumpList.Pin = ت&ثبيت بهذه القائمة +JumpList.Unpin = إزا&لة التثبيت من هذه القائمة +JumpList.Remove = إزالة من ه&ذه القائمة +JumpList.PinTip = تثبيت بهذه القائمة +JumpList.UnpinTip = إزالة التثبيت من هذه القائمة + + +[bg-BG] - Bulgarian (Bulgaria) +Menu.Programs = &Програми +Menu.Apps = Приложения +Menu.AllPrograms = Всички програми +Menu.Back = Назад +Menu.Favorites = Пре&дпочитани +Menu.Documents = Док&ументи +Menu.Settings = &Настройки +Menu.Search = &Търсене +Menu.SearchBox = Търсене +Menu.SearchPrograms = Търсене на програми и файлове +Menu.SearchInternet = Търсене в интернет +Menu.Searching = Търсене... +Menu.NoMatch = Няма елементи, отговарящи на вашето търсене. +Menu.MoreResults = Показване на повече резултати +Menu.Help = Помо&щ и поддръжка +Menu.Run = &Изпълнение... +Menu.Logoff = Изли&зане на %s... +Menu.SwitchUser = Смяна на потр&ебител +Menu.Lock = З&аключване +Menu.LogOffShort = Из&лизане +Menu.Undock = Откачи компют&ъра +Menu.Disconnect = Пр&екъсване на връзката +Menu.ShutdownBox = Изк&лючване... +Menu.Shutdown = Изк&лючване +Menu.Restart = &Рестартиране +Menu.ShutdownUpdate = Актуализиране и изключване +Menu.RestartUpdate = Актуализиране и рестартиране +Menu.Sleep = &Заспиване +Menu.Hibernate = &Хибернация +Menu.ControlPanel = &Контролен панел +Menu.PCSettings = Настройки на компютъра +Menu.Security = Защита на Windows +Menu.Network = &Мрежови връзки +Menu.Printers = Принт&ери +Menu.Taskbar = &Лента на задачите и меню "Старт" +Menu.SearchFiles = За &файловете или папките... +Menu.SearchPrinter = За &принтер +Menu.SearchComputers = За &компютри +Menu.UserFilesTip = Съдържа папки за документи, изображения, музика и други ваши файлове. +Menu.UserDocumentsTip = Съдържа писма, отчети и други документи и файлове. +Menu.UserPicturesTip = Съдържа цифрови снимки, изображения и графични файлове. +Menu.UserMusicTip = Съдържа музика и други аудио файлове. +Menu.UserVideosTip = Съдържа филми и други видео файлове. +Menu.NetworkTip = Показва съществуващи връзки на мрежата в този компютър и ви помага да създадете нови +Menu.PrintersTip = Добавяне, премахване и конфигуриране на локални и мрежови принтери. +Menu.TaskbarTip = Персонализиране на менюто "Старт" и лентата на задачите, като напр. типовете елементи, които ще бъдат показани, както и начина на тяхната поява. +Menu.ControlPanelTip = Промяна на настройките и персонализиране на функционалността на компютъра. +Menu.DocumentsLibTip = Достъп до писма, отчети, бележки и други видове документи. +Menu.MusicLibTip = Възпроизвеждане на музика и други аудио файлове. +Menu.PicturesLibTip = Преглед и организиране на цифрови картини. +Menu.VideosLibTip = Гледане на домашни филми и други цифрови видеозаписи. +Menu.RecordingsLibTip = Гледане на записани на компютъра ТВ програми. +Menu.DownloadTip = Търсене на изтеглени файлове от интернет и връзки към предпочитани връзки. +Menu.HomegroupTip = Достъп до библиотеки и папки, споделени от други хора в домашната ви мрежа. +Menu.RunTip = Отваря програма, папка, документ или уеб сайт. +Menu.HelpTip = Намерете теми от "Помощ", уроци, отстраняване на неизправности и други поддържащи услуги. +Menu.ProgramsTip = Отваря списък на програмите. +Menu.SearchFilesTip = Търсете документи, музика, картини, електронна поща и др. +Menu.GamesTip = Играйте и управлявайте игрите на своя компютър. +Menu.SecurityTip = Стартирайте опциите за защита на Windows, за да смените парола, да смените потребител или да стартирате диспечера на задачите. +Menu.SearchComputersTip = Търсене на компютри в мрежата +Menu.SearchPrintersTip = Търсене на принтер +Menu.AdminToolsTip = Конфигуриране на административните настройки на компютъра. +Menu.ShutdownTip = Затваря всички отворени програми, изключва Windows и изключва компютъра. +Menu.RestartTip = Затваря всички отворени програми, изключва Windows и после отново стартира Windows. +Menu.SleepTip = Запазва сесията ви в паметта и поставя компютъра в състояние на ниско енергопотребление, така че да можете бързо да възобновите работа. +Menu.HibernateTip = Запазва сесията ви в паметта и изключва компютъра. Когато включите компютъра, Windows възстановява сесията ви. +Menu.LogOffTip = Затваряне на програмите и излизане. +Menu.DisconnectTip = Прекратява връзката с вашата сесия. Можете да се свържете с тази сесия отново, когато влезете отново. +Menu.LockTip = Заключване на този компютър. +Menu.UndockTip = Премахва вашия лаптоп или ноутбук компютър от базова станция. +Menu.SwitchUserTip = Смяна на потребителите потребители без да се затварят програмите. +Menu.Empty = (Празно) +Menu.Features = Програми и компоненти +Menu.FeaturesTip = Деинсталиране или промяна на програми на компютъра. +Menu.SearchPeople = За хо&ра... +Menu.SortByName = &Сортирай по име +Menu.Open = &Отвори +Menu.OpenAll = О&твори "Всички потребители" +Menu.Explore = &Преглед +Menu.ExploreAll = Пре&глед на "Всички потребители" +Menu.MenuSettings = Настройки +Menu.MenuHelp = Помощ +Menu.MenuExit = Изход +Menu.LogoffTitle = Излизане от Windows +Menu.LogoffPrompt = Наистина ли искате да излезете? +Menu.LogoffYes = &Излизане +Menu.LogoffNo = &Не +Menu.RenameTitle = Преименуване +Menu.RenamePrompt = &Ново име: +Menu.RenameOK = OK +Menu.RenameCancel = Отказ +Menu.Organize = Организиране на менюто "Старт" +Menu.Expand = &Разгъни +Menu.Collapse = С&вий +Menu.NewFolder = Нова папка +Menu.NewShortcut = Нов пряк път +Menu.AutoArrange = &Автоматично подреждане +Menu.ActionOpen = Отвори +Menu.ActionClose = Затвори +Menu.ActionExecute = Изпълнение +Menu.RemoveList = Премахни &от този списък +Menu.RemoveAll = И&зчисти списъка с последни програми +Menu.Explorer = Windows Explorer +Menu.Start = Старт +Menu.StartScreen = Стартов екран +Menu.StartMenu = Меню "Старт" (Windows) +Menu.PinStart = Закачи към менюто "Старт" +Menu.PinStartCs = Закачи към менюто "Старт" (Classic Shell) +Menu.UnpinStartCs = Откачи от менюто "Старт" (Classic Shell) +Menu.MonitorOff = Изключване на дисплея +Menu.RemoveHighlight = Премахни осветяването +Menu.Uninstall = &Деинсталирай +Menu.UninstallTitle = Деинсталиране +Menu.UninstallPrompt = Наистина ли искате да деинсталирате %s? +Search.CategorySettings = Настройки +Search.CategoryPCSettings = Настройки на компютъра +Search.CategoryPrograms = Програми +Search.CategoryDocuments = Документи +Search.CategoryMusic = Музика +Search.CategoryPictures = Картини +Search.CategoryVideos = Видеозаписи +Search.CategoryFiles = Файлове +Search.CategoryInternet = Интернет +JumpList.Recent = Последни +JumpList.Frequent = Често Използвани +JumpList.Tasks = Задачи +JumpList.Pinned = Закачени +JumpList.Pin = За&качи към този списък +JumpList.Unpin = &Откачи от този списък +JumpList.Remove = Према&хни от този списък +JumpList.PinTip = Закачи към този списък +JumpList.UnpinTip = Откачи от този списък + + +[ca-ES] - Catalan (Catalan) +Menu.Programs = &Programes +Menu.Apps = Aplicacions +Menu.AllPrograms = Tots els programes +Menu.Back = Enrera +Menu.Favorites = Fa&vorits +Menu.Documents = Docu&ments +Menu.Settings = Con&figuració +Menu.Search = &Cercar +Menu.SearchBox = Cercar +Menu.SearchPrograms = Cercar programes i arxius +Menu.SearchInternet = Cercar a Internet +Menu.Searching = Cercant... +Menu.NoMatch = Ningún element coincideix amb el criteri de cerca. +Menu.MoreResults = Veure més resultats +Menu.Help = &Ajuda i suport técnic +Menu.Run = &Executar... +Menu.Logoff = &Tancar sessió de %s... +Menu.SwitchUser = Canviar d'usuari +Menu.Lock = Bloquejar +Menu.LogOffShort = Tancar sessió +Menu.Undock = De&sacoblar equip +Menu.Disconnect = &Desconectar +Menu.ShutdownBox = Apaga&r... +Menu.Shutdown = &Apagar +Menu.Restart = &Reiniciar +Menu.ShutdownUpdate = Actualitzar i apagar +Menu.RestartUpdate = Actualitzar i reiniciar +Menu.Sleep = &Suspendre +Menu.Hibernate = &Hibernar +Menu.ControlPanel = &Panell de control +Menu.PCSettings = Configuració de l'ordinador +Menu.Security = Seguretat de Windows +Menu.Network = &Conexions de xarxa +Menu.Printers = &Impressores +Menu.Taskbar = &Barra de tasques i Menú Inicia +Menu.SearchFiles = &Arxius o carpetes... +Menu.SearchPrinter = I&mpressores +Menu.SearchComputers = Equip&s +Menu.UserFilesTip = Conté carpetes per a Documents, Imatges, Música i altres arxius que li pertanyen. +Menu.UserDocumentsTip = Conté cartes, informes, i altres documents i arxius. +Menu.UserPicturesTip = Conté fotos digitals, imatges i arxius de gràfics. +Menu.UserMusicTip = Conté música i altres arxius d'àudio. +Menu.UserVideosTip = Conté pel·lícules i altres arxius de vídeo. +Menu.NetworkTip = Mostra les conexions de xarxa existents a aquest equip i ajuda a crear altres noves +Menu.PrintersTip = Agrega, treu i configura impressores locals i de xarxa. +Menu.TaskbarTip = Personalitza el Menú Inicia i la barra de tasques, el tipus d'elements que es mostren i la forma en que tenen que mostrar-se. +Menu.ControlPanelTip = Canviï la configuració i personalitzi la funcionalitat del seu equip. +Menu.DocumentsLibTip = Obtengui accés a cartes, informes, notes i altra classe de documents. +Menu.MusicLibTip = Reprodueixi música i altres arxius d'àudio. +Menu.PicturesLibTip = Vegi i organitzi imatges digitals. +Menu.VideosLibTip = Vegi pel·lícules doméstiques i altres vídeos digitals. +Menu.RecordingsLibTip = Vegi programes de televisió gravats a l'equip. +Menu.DownloadTip = Cerqui descàrregues de Internet i vincles als seus llocs web favorits. +Menu.HomegroupTip = Obtengui accés a les biblioteques i carpetes que comparteixen altres usuaris del seu grup a la llar. +Menu.RunTip = Obre un programa, una carpeta, un document o un lloc web. +Menu.HelpTip = Cerqui temes d'Ajuda, tutorials, resoldre problemes i altres serveis de suport tècnic. +Menu.ProgramsTip = Obre una llista dels seus programes. +Menu.SearchFilesTip = Cercar documents, música, imatges, correu electrònic i més. +Menu.GamesTip = Jugui i administri els jocs a l'equip. +Menu.SecurityTip = Iniciï Opcions de seguretat de Windows per a canviar la contrasenya, canviar d'usuari o iniciar l'Administrador de tasques. +Menu.SearchComputersTip = Cercar equips a la xarxa +Menu.SearchPrintersTip = Cercar una impressora +Menu.AdminToolsTip = Faci configuracions administratives a l'equip +Menu.ShutdownTip = Tanca tots els programes oberts, tanca Windows i, després, apaga l'equip. +Menu.RestartTip = Tanca tots els programes oberts, tanca Windows i després inicia Windows de nou. +Menu.SleepTip = Manté la memoria de la sessió i posa l'equip en un estat de baixa energia per a que pugui continuar treballant ràpidament al reanudar. +Menu.HibernateTip = Guarda la sessió i apaga l'equip. Quan iniciï l'equip, Windows restaurarà la sessió. +Menu.LogOffTip = Tancar els programes i la sessió. +Menu.DisconnectTip = Desconnecta sessió. Pots reconectar-se a aquesta sessió quan torni a iniciar sessió. +Menu.LockTip = Bloquejar aquest equip. +Menu.UndockTip = Treu un equip portàtil o de mà de l'estació de acoblament. +Menu.SwitchUserTip = Canviar d'usuari sense tancar els programes. +Menu.Empty = (Buit) +Menu.Features = Programes i característiques +Menu.FeaturesTip = Desinstal·li o canviï programes a l'equip. +Menu.SearchPeople = &Persones... +Menu.SortByName = Ordenar per &Nom +Menu.Open = &Obrir +Menu.OpenAll = Ob&rir tots els usuaris +Menu.Explore = E&xplorar +Menu.ExploreAll = &Explorar tots els usuaris +Menu.MenuSettings = Configuració +Menu.MenuHelp = Ajuda +Menu.MenuExit = Sortir +Menu.LogoffTitle = Tancar la sessió a Windows +Menu.LogoffPrompt = Està segur de que desitja tancar la sessió? +Menu.LogoffYes = &Tancar sessió +Menu.LogoffNo = &No +Menu.RenameTitle = Canviar nom +Menu.RenamePrompt = &Nou nom: +Menu.RenameOK = Acceptar +Menu.RenameCancel = Cancel·lar +Menu.Organize = Organitzar el Menú Inicia +Menu.Expand = &Expandir +Menu.Collapse = &Contraure +Menu.NewFolder = Nova carpeta +Menu.NewShortcut = Nou accés directe +Menu.AutoArrange = Organi&tzació automàtica +Menu.ActionOpen = Obrir +Menu.ActionClose = Tancar +Menu.ActionExecute = Executar +Menu.RemoveList = &Treure d'aquesta llista +Menu.RemoveAll = &Borrar llista d'elements recents +Menu.Explorer = Explorador de Windows +Menu.Start = Inicia +Menu.StartScreen = Pantalla Inicia +Menu.StartMenu = Menú Inicia (Windows) +Menu.PinStart = Ancorar al Menú Inicia +Menu.PinStartCs = Ancorar al Menú Inicia (Classic Shell) +Menu.UnpinStartCs = Desancorar del Menú Inicia (Classic Shell) +Menu.MonitorOff = Apaga la pantalla +Menu.RemoveHighlight = Suprimeix la marca +Menu.Uninstall = &Desinstal·la +Menu.UninstallTitle = Desinstal·la +Menu.UninstallPrompt = Esteu segur que voleu desinstal·lar el %s? +Menu.ClassicSettings = Classic Start &Menú +Menu.SettingsTip = Ajustaments del Classic Start Menú +Search.CategorySettings = Configuració +Search.CategoryPCSettings = Configuració de l'ordinador +Search.CategoryPrograms = Programes +Search.CategoryDocuments = Documents +Search.CategoryMusic = Música +Search.CategoryPictures = Imatges +Search.CategoryVideos = Vídeos +Search.CategoryFiles = Arxius +Search.CategoryInternet = Internet +JumpList.Recent = Recent +JumpList.Frequent = Freqüent +JumpList.Tasks = Tasques +JumpList.Pinned = Ancorat +JumpList.Pin = &Ancorar a aquesta llista +JumpList.Unpin = &Desancorar d'aquesta llista +JumpList.Remove = &Treure d'aquesta llista +JumpList.PinTip = Ancorar a aquesta llista +JumpList.UnpinTip = Desancorar d'aquesta llista + + +[cs-CZ] - Czech (Czech Republic) +Menu.Programs = &Programy +Menu.Apps = Aplikace +Menu.AllPrograms = Všechny programy +Menu.Back = Zpět +Menu.Favorites = Oblíbené položk&y +Menu.Documents = Doku&menty +Menu.Settings = N&astavení +Menu.Search = &Hledat +Menu.SearchBox = Hledat +Menu.SearchPrograms = Prohledat programy a soubory +Menu.SearchInternet = Vyhledat v Internetu +Menu.Searching = Vyhledávání... +Menu.NoMatch = Hledání neodpovídají žádné položky. +Menu.MoreResults = Zobrazit další výsledky +Menu.Help = &Nápověda a podpora +Menu.Run = Spus&tit... +Menu.Logoff = Odhlásit &uživatele %s... +Menu.SwitchUser = &Přepnout uživatele +Menu.Lock = &Uzamknout +Menu.LogOffShort = Odh&lásit se +Menu.Undock = Vyjmout z dokova&cí stanice +Menu.Disconnect = O&dpojit +Menu.ShutdownBox = &Vypnout... +Menu.Shutdown = &Vypnout +Menu.Restart = &Restartovat +Menu.ShutdownUpdate = Aktualizovat a vypnout +Menu.RestartUpdate = Aktualizovat a restartovat +Menu.Sleep = &Režim spánku +Menu.Hibernate = &Hibernace +Menu.ControlPanel = Ovláda&cí panely +Menu.PCSettings = Nastavení počítače +Menu.Security = Zabezpečení systému Windows +Menu.Network = &Síťová připojení +Menu.Printers = &Tiskárny +Menu.Taskbar = &Hlavní panel a nabídka Start +Menu.SearchFiles = &Soubory či složky... +Menu.SearchPrinter = &Tiskárnu +Menu.SearchComputers = &Počítače +Menu.UserFilesTip = Obsahuje složky pro Dokumenty, Obrázky, Hudbu a další vaše soubory. +Menu.UserDocumentsTip = Obsahuje dopisy, hlášení a další soubory a dokumenty. +Menu.UserPicturesTip = Obsahuje digitální fotografie, obrázky a grafické soubory. +Menu.UserMusicTip = Obsahuje hudební a další zvukové soubory. +Menu.UserVideosTip = Obsahuje filmy a další video soubory. +Menu.NetworkTip = Zobrazí existující síťová připojení a usnadňuje vytvoření nových připojení. +Menu.PrintersTip = Slouží k přidávání, odebírání a konfigurování místních a síťových tiskáren. +Menu.TaskbarTip = Umožňuje upravit nabídku start a hlavní panel (například typy a způsob zobrazení položek). +Menu.ControlPanelTip = Změňte nastavení a přizpůsobte funkčnost svého počítače. +Menu.DocumentsLibTip = Umožňuje přístup k dopisům, zprávám, poznámkám a jiným druhům dokumentů. +Menu.MusicLibTip = Umožňuje přehrávat hudební a jiné zvukové soubory. +Menu.PicturesLibTip = Umožňuje prohlížet a organizovat digitální obrázky. +Menu.VideosLibTip = Umožňuje sledování domácích videí a dalších digitálních videozáznamů. +Menu.RecordingsLibTip = Umožňuje sledování televizních programů nahraných v počítači. +Menu.DownloadTip = Umožňuje hledání položek ke stažení na Internetu a odkazů na oblíbené weby. +Menu.HomegroupTip = Přistupujte ke knihovnám a složkám sdíleným dalšími uživateli v domácí skupině. +Menu.RunTip = Otevře složku, program, dokument nebo webovou stránku. +Menu.HelpTip = Umožní vyhledávat témata nápovědy, kurzy, řešení problémů a další služby podpory. +Menu.ProgramsTip = Zobrazí seznam programů v počítači. +Menu.SearchFilesTip = Umožňuje vyhledávat dokumenty, hudbu, obrázky, e-maily a další. +Menu.GamesTip = Umožňuje hrát a spravovat hry v počítači. +Menu.SecurityTip = Spustí možnosti zabezpečení systému Windows, ve kterých lze změnit heslo, přepnout uživatele nebo spustit Správce úloh. +Menu.SearchComputersTip = Hledat počítače v síti +Menu.SearchPrintersTip = Hledat tiskárnu +Menu.AdminToolsTip = Konfiguruje nastavení počítače pro správu. +Menu.ShutdownTip = Ukončí všechny spuštěné programy, ukončí systém Windows a potom vypne počítač. +Menu.RestartTip = Ukončí všechny spuštěné programy, ukončí systém Windows a potom znovu spustí systém Windows. +Menu.SleepTip = Ponechá relaci v paměti a uvede počítač do režimu nízké spotřeby, takže je možné rychle pokračovat v práci. +Menu.HibernateTip = Uloží relaci a vypne počítač. Po zapnutí počítače systém Windows relaci obnoví. +Menu.LogOffTip = Umožňuje ukončit programy a odhlásit uživatele. +Menu.DisconnectTip = Odpojí vaši relaci. K relaci se můžete opět připojit při dalším přihlášení. +Menu.LockTip = Uzamkne počítač. +Menu.UndockTip = Vyjme přenosný počítač z dokovací stanice. +Menu.SwitchUserTip = Přepne uživatele bez ukončování programů. +Menu.Empty = (prázdné) +Menu.Features = Programy a funkce +Menu.FeaturesTip = Odinstaluje nebo změní programy v počítači. +Menu.SearchPeople = Oso&by... +Menu.SortByName = Seřadit podle &názvu +Menu.Open = &Otevřít +Menu.OpenAll = Ot&evřít položky všech uživatele +Menu.Explore = Proz&koumat +Menu.ExploreAll = P&rocházet položky všech uživatelů +Menu.MenuSettings = Nastavení +Menu.MenuHelp = Nápověda +Menu.MenuExit = Ukončit +Menu.LogoffTitle = Odhlásit se od systému Windows +Menu.LogoffPrompt = Opravdu se chcete odhlásit? +Menu.LogoffYes = &Odhlásit se +Menu.LogoffNo = &Ne +Menu.RenameTitle = Přejmenovat +Menu.RenamePrompt = &Nový název: +Menu.RenameOK = OK +Menu.RenameCancel = Storno +Menu.Organize = Uspořádat nabídku Start +Menu.Expand = Ro&zbalit +Menu.Collapse = S&balit +Menu.NewFolder = Nová složka +Menu.NewShortcut = Nový zástupce +Menu.AutoArrange = &Rovnat automaticky +Menu.ActionOpen = Otevřít +Menu.ActionClose = Zavřít +Menu.ActionExecute = Spouštět +Menu.RemoveList = &Odebrat z tohoto seznamu +Menu.RemoveAll = Smazat seznam pos&ledních položek +Menu.Explorer = Průzkumník Windows +Menu.Start = Start +Menu.StartScreen = Úvodní obrazovka +Menu.StartMenu = Nabídka Start (Windows) +Menu.PinStart = Připnout k nabídce Start +Menu.PinStartCs = Připnout k nabídce Start (Classic Shell) +Menu.UnpinStartCs = Odepnout z nabídky Start (Classic Shell) +Menu.MonitorOff = Vypnout zobrazení +Menu.RemoveHighlight = Odebrat nejzajímavější místo +Menu.Uninstall = &Odinstalovat +Menu.UninstallTitle = Odinstalovat +Menu.UninstallPrompt = Opravdu chcete odinstalovat položku %s? +Search.CategorySettings = Nastavení +Search.CategoryPCSettings = Nastavení počítače +Search.CategoryPrograms = Programy +Search.CategoryDocuments = Dokumenty +Search.CategoryMusic = Hudba +Search.CategoryPictures = Obrázky +Search.CategoryVideos = Videa +Search.CategoryFiles = Soubory +Search.CategoryInternet = Internet +JumpList.Recent = Poslední +JumpList.Frequent = Nejčastěji používané +JumpList.Tasks = Úlohy +JumpList.Pinned = Připnuté +JumpList.Pin = &Připnout do tohoto seznamu +JumpList.Unpin = &Odepnout z tohoto seznamu +JumpList.Remove = O&debrat z tohoto seznamu +JumpList.PinTip = Připnout do tohoto seznamu +JumpList.UnpinTip = Odepnout z tohoto seznamu + + +[da-DK] - Danish (Denmark) +Menu.Programs = &Programmer +Menu.Apps = Apps +Menu.AllPrograms = Alle programmer +Menu.Back = Tilbage +Menu.Favorites = &Favoritter +Menu.Documents = &Dokumenter +Menu.Settings = &Indstillinger +Menu.Search = S&øg +Menu.SearchBox = Søg +Menu.SearchPrograms = Søg i alle programmer og filer +Menu.SearchInternet = Søg på internettet +Menu.Searching = Søger... +Menu.NoMatch = Ingen elementer svarede til dine søgekriterier. +Menu.MoreResults = Se flere resultater +Menu.Help = &Hjælp og support +Menu.Run = &Kør... +Menu.Logoff = L&og %s af... +Menu.SwitchUser = S&kift bruger +Menu.Lock = &Lås +Menu.LogOffShort = Log &af +Menu.Undock = Fradock &computer +Menu.Disconnect = &Afbryd forbindelsen +Menu.ShutdownBox = &Luk computeren... +Menu.Shutdown = &Luk computeren +Menu.Restart = &Genstart +Menu.ShutdownUpdate = Opdater og luk +Menu.RestartUpdate = Opdater og genstart +Menu.Sleep = Sl&umre +Menu.Hibernate = &Dvale +Menu.ControlPanel = &Kontrolpanel +Menu.PCSettings = Pc-indstillinger +Menu.Security = Windows Sikkerhed +Menu.Network = &Netværksforbindelser +Menu.Printers = &Printere +Menu.Taskbar = &Proceslinje og menuen Start +Menu.SearchFiles = efter &Filer eller mapper... +Menu.SearchPrinter = efter &Printer +Menu.SearchComputers = efter &Computere +Menu.UserFilesTip = Indeholder mapper for Dokumenter, Billeder, Musik og andre filer, der tilhører dig. +Menu.UserDocumentsTip = Indeholder breve, rapporter og andre dokumenter og filer +Menu.UserPicturesTip = Indeholder digitale fotos, billeder og grafikfiler +Menu.UserMusicTip = Indeholder musik og andre lydfiler +Menu.UserVideosTip = Indeholder film og andre videofiler +Menu.NetworkTip = Viser eksisterende netværksforbindelser på computeren og hjælper dig med at oprette nye forbindelser +Menu.PrintersTip = Tilføjer, fjerner og konfigurerer printere lokalt og på netværket +Menu.TaskbarTip = Tilpas menuen Start og proceslinjen f.eks. hvilken type elementer, der skal vises, og hvordan de skal vises +Menu.ControlPanelTip = Rediger indstillinger, og tilpas computerens funktioner. +Menu.DocumentsLibTip = Få adgang til breve, rapporter, notater og andre slags dokumenter. +Menu.MusicLibTip = Afspil musik og andre lydfiler. +Menu.PicturesLibTip = Få vist og organiser digitale billeder. +Menu.VideosLibTip = Se film og andre digitale videoer. +Menu.RecordingsLibTip = Se tv-programmer optaget på computeren. +Menu.DownloadTip = Find internetoverførsler og links til yndlingswebsteder. +Menu.HomegroupTip = Få adgang til biblioteker og mapper, der deles af andre i hjemmegruppen. +Menu.RunTip = Åbner et program, en mappe, et dokument eller et websted +Menu.HelpTip = Find emner i Hjælp, selvstudier, fejlfinding og andre supporttjenester +Menu.ProgramsTip = Åbner en liste over dine programmer +Menu.SearchFilesTip = Søg efter dokumenter, musik, billeder, e-mails m.m. +Menu.GamesTip = Spil og administrer spil på computeren +Menu.SecurityTip = Start sikkerhedsindstillingerne i Windows for at skifte adgangskode, ændre bruger eller starte Jobliste. +Menu.SearchComputersTip = Søg efter computere på netværket +Menu.SearchPrintersTip = Søg efter en printer +Menu.AdminToolsTip = Konfigurerer administrative indstillinger for computeren +Menu.ShutdownTip = Lukker alle åbne programmer, lukker Windows og slukker derefter for computeren. +Menu.RestartTip = Lukker alle åbne programmer, lukker Windows og starter derefter Windows igen. +Menu.SleepTip = Bevarer sessionen i hukommelsen og sætter computeren i strømbesparelsestilstand, så du hurtigt kan fortsætte dit arbejde. +Menu.HibernateTip = Gemmer sessionen og slukker for computeren. Når du tænder for computeren, gendanner Windows sessionen. +Menu.LogOffTip = Luk programmer, og log af. +Menu.DisconnectTip = Afbryder sessionen. Du kan genoprette forbindelsen til sessionen, når du logger på igen. +Menu.LockTip = Lås denne computer +Menu.UndockTip = Fjerner din bærbare computer fra en dockingstation. +Menu.SwitchUserTip = Skift brugere uden at lukke programmer. +Menu.Empty = (Tom) +Menu.Features = Installerede programmer og funktioner +Menu.FeaturesTip = Fjern eller rediger programmer på din computer. +Menu.SearchPeople = Efter &personer... +Menu.SortByName = So&rter efter navn +Menu.Open = Å&bn +Menu.OpenAll = &Åbn mappen Alle brugere +Menu.Explore = &Stifinder +Menu.ExploreAll = &Gennemse mappen Alle brugere +Menu.MenuSettings = Indstillinger +Menu.MenuHelp = Hjælp +Menu.MenuExit = Afslut +Menu.LogoffTitle = Log af Windows +Menu.LogoffPrompt = Vil du logge af? +Menu.LogoffYes = &Log af +Menu.LogoffNo = &Nej +Menu.RenameTitle = Omdøb +Menu.RenamePrompt = &Nyt navn: +Menu.RenameOK = OK +Menu.RenameCancel = Annuller +Menu.Organize = Organiser menuen Start +Menu.Expand = &Udvid +Menu.Collapse = S&kjul +Menu.NewFolder = Ny mappe +Menu.NewShortcut = Ny genvej +Menu.AutoArrange = &Arranger automatisk +Menu.ActionOpen = Åbn +Menu.ActionClose = Luk +Menu.ActionExecute = Kør +Menu.RemoveList = Fjern &fra denne liste +Menu.RemoveAll = &Ryd listen over seneste elementer +Menu.Explorer = Windows Stifinder +Menu.Start = Start +Menu.StartScreen = Startskærm +Menu.StartMenu = Menuen Start (Windows) +Menu.PinStart = Fastgør til menuen Start +Menu.PinStartCs = Fastgør til menuen Start (Classic Shell) +Menu.UnpinStartCs = Frigør fra menuen Start (Classic Shell) +Menu.MonitorOff = Sluk skærmen +Menu.RemoveHighlight = Fjern centralt punkt +Menu.Uninstall = &Fjern +Menu.UninstallTitle = Fjern +Menu.UninstallPrompt = Er du sikker på, at du vil fjerne %s? +Search.CategorySettings = Indstillinger +Search.CategoryPCSettings = Pc-indstillinger +Search.CategoryPrograms = Programmer +Search.CategoryDocuments = Dokumenter +Search.CategoryMusic = Musik +Search.CategoryPictures = Billeder +Search.CategoryVideos = Videoer +Search.CategoryFiles = Filer +Search.CategoryInternet = Internet +JumpList.Recent = Seneste +JumpList.Frequent = Ofte +JumpList.Tasks = Opgaver +JumpList.Pinned = Fastgjort +JumpList.Pin = F&astgør til listen +JumpList.Unpin = &Frigør fra listen +JumpList.Remove = Fje&rn fra denne liste +JumpList.PinTip = Fastgør til listen +JumpList.UnpinTip = Frigør fra listen + + +[de-DE] - German (Germany) +Menu.Programs = &Programme +Menu.Apps = Apps +Menu.AllPrograms = Alle Programme +Menu.Back = Zurück +Menu.Favorites = &Favoriten +Menu.Documents = &Dokumente +Menu.Settings = &Einstellungen +Menu.Search = &Suchen +Menu.SearchBox = Suchen +Menu.SearchPrograms = Programme/Dateien durchsuchen +Menu.SearchInternet = Internet durchsuchen +Menu.Searching = Suchvorgang... +Menu.NoMatch = Es wurden keine Suchergebnisse gefunden. +Menu.MoreResults = Weitere Ergebnisse anzeigen +Menu.Help = &Hilfe und Support +Menu.Run = A&usführen... +Menu.Logoff = "%s" ab&melden... +Menu.SwitchUser = &Benutzer wechseln +Menu.Lock = &Sperren +Menu.LogOffShort = &Abmelden +Menu.Undock = Abd&ocken +Menu.Disconnect = &Trennen +Menu.ShutdownBox = He&runterfahren... +Menu.Shutdown = &Herunterfahren +Menu.Restart = &Neu starten +Menu.ShutdownUpdate = Aktualisieren und herunterfahren +Menu.RestartUpdate = Aktualisieren und neu starten +Menu.Sleep = &Energie sparen +Menu.Hibernate = &Ruhezustand +Menu.ControlPanel = S&ystemsteuerung +Menu.PCSettings = PC-Einstellungen +Menu.Security = Windows-Sicherheit +Menu.Network = &Netzwerkverbindungen +Menu.Printers = &Drucker +Menu.Taskbar = &Taskleiste und Startmenü +Menu.SearchFiles = Nach &Dateien oder Ordnern... +Menu.SearchPrinter = Nach &Druckern +Menu.SearchComputers = Nach &Computern +Menu.UserFilesTip = Enthält Ordner für Dokumente, Bilder, Musik und andere Dateien, die Ihnen gehören. +Menu.UserDocumentsTip = Enthält Briefe, Berichte und andere Dokumente und Dateien. +Menu.UserPicturesTip = Enthält digitale Fotos, Bilder und Grafikdateien. +Menu.UserMusicTip = Enthält Musik- und andere Audiodateien. +Menu.UserVideosTip = Enthält Filme und andere Videodateien. +Menu.NetworkTip = Zeigt vorhandene Netzwerkverbindungen an und hilft bei der Erstellung von neuen Verbindungen. +Menu.PrintersTip = Fügt lokale und Netzwerkdrucker hinzu, entfernt und konfiguriert diese. +Menu.TaskbarTip = Passt das Startmenü und die Taskleiste an, z.B. die Auswahl anzuzeigender Elementtypen und deren Darstellung. +Menu.ControlPanelTip = Ändert Einstellungen, und passt die Funktionalität des Computers an. +Menu.DocumentsLibTip = Greift auf Briefe, Berichte, Notizen und andere Dokumente zu. +Menu.MusicLibTip = Gibt Musik und andere Audiodateien wieder. +Menu.PicturesLibTip = Zeigt digitale Bilder an und verwaltet sie. +Menu.VideosLibTip = Sehen Sie sich private Filme und andere digitale Videos an. +Menu.RecordingsLibTip = Sehen Sie sich auf dem Computer aufgezeichnete TV-Programme an. +Menu.DownloadTip = Sucht nach Internetdownloads und Links zu bevorzugten Websites. +Menu.HomegroupTip = Greift auf Bibliotheken und Ordner zu, die von anderen Personen in der Heimnetzgruppe freigegeben werden. +Menu.RunTip = Öffnet ein Programm, einen Ordner, ein Dokument oder eine Website. +Menu.HelpTip = Sucht Hilfethemen, Lernprogramme, Problembehandlung und andere Supportdienste. +Menu.ProgramsTip = Öffnet eine Liste der Programme. +Menu.SearchFilesTip = Sucht nach Dokumenten, Musik, Bildern, E-Mail und mehr. +Menu.GamesTip = Verwaltet Spiele auf dem Computer. +Menu.SecurityTip = Öffnet die Windows-Sicherheitsoptionen, um Kennwörter zu ändern, sich als anderer Benutzer anzumelden oder den Task-Manager zu starten. +Menu.SearchComputersTip = Nach Computern im Netzwerk suchen +Menu.SearchPrintersTip = Nach einem Drucker suchen +Menu.AdminToolsTip = Konfigurieren Sie Verwaltungseinstellungen für den Computer. +Menu.ShutdownTip = Schließt alle offenen Programme, fährt Windows herunter, und schaltet den Computer aus. +Menu.RestartTip = Schließt alle offenen Programme, fährt Windows herunter, und führt einen Neustart durch. +Menu.SleepTip = Speichert die Sitzung im Arbeitsspeicher und versetzt den Computer in einen Energiesparmodus, so dass die Sitzung schnell wiederhergestellt werden kann. +Menu.HibernateTip = Speichert die Sitzung und schaltet den Computer aus. Wenn Sie den Computer einschalten, wird die Sitzung wiederhergestellt. +Menu.LogOffTip = Schließt Programme und führt die Abmeldung aus. +Menu.DisconnectTip = Trennt diese Sitzung. Sie können eine Verbindung mit dieser Sitzung erneut herstellen, wenn Sie sich das nächste Mal anmelden. +Menu.LockTip = Sperrt diesen Computer. +Menu.UndockTip = Entfernt den Laptop- bzw. Notebookcomputer aus der Dockingstation. +Menu.SwitchUserTip = Wechselt Benutzer, ohne Programme zu schließen. +Menu.Empty = (Leer) +Menu.Features = Programme und Funktionen +Menu.FeaturesTip = Deinstalliert oder ändert Programme auf dem Computer. +Menu.SearchPeople = &Nach Personen... +Menu.SortByName = &Nach Namen sortieren +Menu.Open = Ö&ffnen +Menu.OpenAll = Öffnen - &Alle Benutzer +Menu.Explore = &Explorer +Menu.ExploreAll = E&xplorer - Alle Benutzer +Menu.MenuSettings = Einstellungen +Menu.MenuHelp = Hilfe +Menu.MenuExit = Beenden +Menu.LogoffTitle = Windows-Abmeldung +Menu.LogoffPrompt = Möchten Sie sich wirklich abmelden? +Menu.LogoffYes = &Abmelden +Menu.LogoffNo = &Nein +Menu.RenameTitle = Umbenennen +Menu.RenamePrompt = &Neuer Name: +Menu.RenameOK = OK +Menu.RenameCancel = Abbrechen +Menu.Organize = Startmenü organisieren +Menu.Expand = &Erweitern +Menu.Collapse = &Reduzieren +Menu.NewFolder = Neuer Ordner +Menu.NewShortcut = Neue Verknüpfung +Menu.AutoArrange = Automatisch a&nordnen +Menu.ActionOpen = Öffnen +Menu.ActionClose = Schließen +Menu.ActionExecute = Ausführen +Menu.RemoveList = &Aus Liste entfernen +Menu.RemoveAll = &Liste zuletzt verwendeter Elemente löschen +Menu.Explorer = Windows-Explorer +Menu.Start = Start +Menu.StartScreen = Startseite +Menu.StartMenu = Startmenü (Windows) +Menu.PinStart = An Startmenü anheften +Menu.PinStartCs = An Startmenü anheften (Classic Shell) +Menu.UnpinStartCs = Vom Startmenü lösen (Classic Shell) +Menu.MonitorOff = Bildschirm ausschalten +Menu.RemoveHighlight = Haupttreffer entfernen +Menu.Uninstall = &Deinstallieren +Menu.UninstallTitle = Deinstallieren +Menu.UninstallPrompt = Möchten Sie %s wirklich deinstallieren? +Search.CategorySettings = Einstellungen +Search.CategoryPCSettings = PC-Einstellungen +Search.CategoryPrograms = Programme +Search.CategoryDocuments = Dokumente +Search.CategoryMusic = Musik +Search.CategoryPictures = Bilder +Search.CategoryVideos = Videos +Search.CategoryFiles = Dateien +Search.CategoryInternet = Internet +JumpList.Recent = Zuletzt verwendet +JumpList.Frequent = Häufig +JumpList.Tasks = Aufgaben +JumpList.Pinned = Angeheftet +JumpList.Pin = An diese Liste an&heften +JumpList.Unpin = V&on dieser Liste lösen +JumpList.Remove = &Aus Liste entfernen +JumpList.PinTip = An diese Liste anheften +JumpList.UnpinTip = Von dieser Liste lösen + + +[el-GR] - Greek (Greece) +Menu.Programs = &Προγράμματα +Menu.Apps = Εφαρμογές +Menu.AllPrograms = Όλα τα προγράμματα +Menu.Back = Πίσω +Menu.Favorites = Αγαπ&ημένα +Menu.Documents = Έ&γγραφα +Menu.Settings = Ρυ&θμίσεις +Menu.Search = &Αναζήτηση +Menu.SearchBox = Αναζήτηση +Menu.SearchPrograms = Αναζήτηση προγραμμάτων και αρχείων +Menu.SearchInternet = Αναζήτηση στο Internet +Menu.Searching = Αναζήτηση... +Menu.NoMatch = Δεν βρέθηκαν αποτελέσματα για την αναζήτησή σας. +Menu.MoreResults = Περισσότερα αποτελέσματα +Menu.Help = &Βοήθεια και υποστήριξη +Menu.Run = Εκτέ&λεση... +Menu.Logoff = Αποσύν&δεση %s... +Menu.SwitchUser = Α&λλαγή χρήστη +Menu.Lock = &Κλείδωμα +Menu.LogOffShort = &Αποσύνδεση +Menu.Undock = Απαγκύρωση &υπολογιστή +Menu.Disconnect = Απο&σύνδεση +Menu.ShutdownBox = &Τερματισμός... +Menu.Shutdown = &Τερματισμός λειτουργίας +Menu.Restart = &Επανεκκίνηση +Menu.ShutdownUpdate = Ενημέρωση και τερματισμός λειτουργίας +Menu.RestartUpdate = Ενημέρωση και επανεκκίνηση +Menu.Sleep = Αναστολή &λειτουργίας +Menu.Hibernate = &Αδρανοποίηση +Menu.ControlPanel = Πί&νακας Ελέγχου +Menu.PCSettings = Ρυθμίσεις υπολογιστή +Menu.Security = Ασφάλεια των Windows +Menu.Network = &Συνδέσεις Δικτύου +Menu.Printers = Εκτυπ&ωτές +Menu.Taskbar = &Γραμμή εργασιών και μενού "Έναρξη" +Menu.SearchFiles = Για αρ&χεία ή φακέλους... +Menu.SearchPrinter = Για &Εκτυπωτή +Menu.SearchComputers = Για υ&πολογιστές +Menu.UserFilesTip = Περιέχει φακέλους για έγγραφα, εικόνες, μουσική και άλλα αρχεία που σας ανήκουν. +Menu.UserDocumentsTip = Περιέχει επιστολές, αναφορές και άλλα έγγραφα και αρχεία. +Menu.UserPicturesTip = Περιέχει ψηφιακές φωτογραφίες, εικόνες και αρχεία γραφικών. +Menu.UserMusicTip = Περιέχει μουσική και άλλα αρχεία ήχου. +Menu.UserVideosTip = Περιέχει ταινίες και άλλα αρχεία βίντεο. +Menu.NetworkTip = Εμφανίζει τις επίκαιρες συνδέσεις δικτύου σε αυτόν τον υπολογιστή και σας βοηθά στη δημιουργία νέων συνδέσεων +Menu.PrintersTip = Προσθήκη, κατάργηση και ρύθμιση παραμέτρων των τοπικών εκτυπωτών και των εκτυπωτών δικτύου. +Menu.TaskbarTip = Προσαρμογή του μενού "Έναρξη" και της γραμμής εργασιών, όπως των τύπων των προς εμφάνιση στοιχείων και πώς πρέπει να εμφανίζονται. +Menu.ControlPanelTip = Αλλάξτε τις ρυθμίσεις και προσαρμόστε τη λειτουργικότητα του υπολογιστή. +Menu.DocumentsLibTip = Πρόσβαση σε επιστολές, αναφορές, σημειώσεις και άλλους τύπους εγγράφων. +Menu.MusicLibTip = Αναπαραγωγή μουσικής και άλλων αρχείων ήχου. +Menu.PicturesLibTip = Προβολή και οργάνωση ψηφιακών εικόνων. +Menu.VideosLibTip = Παρακολούθηση οικιακών ταινιών και άλλων ψηφιακών βίντεο. +Menu.RecordingsLibTip = Παρακολούθηση τηλεοπτικών προγραμμάτων που έχουν εγγραφεί στον υπολογιστή σας. +Menu.DownloadTip = Εύρεση λήψεων Internet και συνδέσεων προς αγαπημένες τοποθεσίες Web. +Menu.HomegroupTip = Η πρόσβαση σε βιβλιοθήκες και φακέλους είναι κοινή από άλλα άτομα στην οικιακή ομάδα σας. +Menu.RunTip = Ανοίγει ένα πρόγραμμα, φάκελο, έγγραφο ή τοποθεσία Web. +Menu.HelpTip = Βρείτε θέματα Βοήθειας, εγχειρίδια εκμάθησης, λύσεις αντιμετώπισης προβλημάτων και άλλες υπηρεσίες υποστήριξης. +Menu.ProgramsTip = Ανοίγει μια λίστα των προγραμμάτων σας. +Menu.SearchFilesTip = Αναζητήστε έγγραφα, μουσική, εικόνες, αλληλογραφία και πολλά άλλα. +Menu.GamesTip = Χρήση και διαχείριση παιχνιδιών στον υπολογιστή σας. +Menu.SecurityTip = Εκκίνηση Επιλογών ασφαλείας των Windows για αλλαγή κωδικού πρόσβασης, αλλαγή χρήστη ή έναρξη της διαχείρισης εργασιών. +Menu.SearchComputersTip = Αναζήτηση υπολογιστή στο δίκτυο +Menu.SearchPrintersTip = Αναζήτηση ενός εκτυπωτή +Menu.AdminToolsTip = Ρύθμιση των παραμέτρων διαχείρισης του υπολογιστή σας. +Menu.ShutdownTip = Κλείνει όλα τα ανοικτά προγράμματα, τερματίζει τα Windows και, στη συνέχεια, τερματίζει τη λειτουργία του υπολογιστή. +Menu.RestartTip = Κλείνει όλα τα ανοικτά προγράμματα, τερματίζει τα Windows και, στη συνέχεια, πραγματοποιεί επανεκκίνηση των Windows. +Menu.SleepTip = Διατηρεί την περίοδο λειτουργίας στη μνήμη και θέτει τον υπολογιστή σε κατάσταση χαμηλής ενέργειας, ώστε να μπορείτε να συνεχίσετε γρήγορα την εργασία σας. +Menu.HibernateTip = Αποθηκεύει την περίοδο λειτουργίας και απενεργοποιεί τον υπολογιστή. Όταν ενεργοποιήσετε τον υπολογιστή, τα Windows θα επαναφέρουν την περίοδο λειτουργίας σας. +Menu.LogOffTip = Κλείστε τα προγράμματα και αποσυνδεθείτε. +Menu.DisconnectTip = Αποσυνδέει την περίοδο λειτουργίας σας. Μπορείτε να συνδεθείτε ξανά σε αυτήν την περίοδο λειτουργίας την επόμενη φορά που θα εισέλθετε. +Menu.LockTip = Κλείδωμα αυτού του υπολογιστή. +Menu.UndockTip = Αφαιρεί τον φορητό υπολογιστή σας από ένα σταθμό αγκύρωσης. +Menu.SwitchUserTip = Αλλαγή χρηστών χωρίς κλείσιμο των προγραμμάτων. +Menu.Empty = (Κενό) +Menu.Features = Προγράμματα και δυνατότητες +Menu.FeaturesTip = Κατάργηση εγκατάστασης ή αλλαγή των προγραμμάτων του υπολογιστή σας. +Menu.SearchPeople = Για ά&τομα... +Menu.SortByName = Ταξι&νόμηση κατά όνομα +Menu.Open = Άν&οιγμα +Menu.OpenAll = Άνοιγμα ό&λων των χρηστών +Menu.Explore = Ε&ξερεύνηση +Menu.ExploreAll = &Εξερεύνηση όλων των χρηστών +Menu.MenuSettings = Ρυθμίσεις +Menu.MenuHelp = Βοήθεια +Menu.MenuExit = Έξοδος +Menu.LogoffTitle = Αποσύνδεση των Windows +Menu.LogoffPrompt = Είστε βέβαιοι ότι θέλετε να αποσυνδεθείτε; +Menu.LogoffYes = Αποσύ&νδεση +Menu.LogoffNo = Ό&χι +Menu.RenameTitle = Μετονομασία +Menu.RenamePrompt = &Νέο όνομα: +Menu.RenameOK = ΟΚ +Menu.RenameCancel = Άκυρο +Menu.Organize = Οργάνωση μενού "Έναρξη" +Menu.Expand = Ανάπτυ&ξη +Menu.Collapse = Σύμπτ&υξη +Menu.NewFolder = Νέος φάκελος +Menu.NewShortcut = Νέα συντόμευση +Menu.AutoArrange = &Αυτόματη τακτοποίηση +Menu.ActionOpen = Άνοιγμα +Menu.ActionClose = Kλείσιμο +Menu.ActionExecute = Εκτέλεση +Menu.RemoveList = Κατά&ργηση από τη λίστα +Menu.RemoveAll = &Εκκαθάριση λίστας πρόσφατων στοιχείων +Menu.Explorer = Εξερεύνηση των Windows +Menu.Start = Έναρξη +Menu.StartScreen = Οθόνη Έναρξης +Menu.StartMenu = Μενού "Έναρξη" (Windows) +Menu.PinStart = Καρφίτσωμα στο μενού "Έναρξη" +Menu.PinStartCs = Καρφίτσωμα στο μενού "Έναρξη" (Classic Shell) +Menu.UnpinStartCs = Ξεκαρφίτσωμα από το μενού "Έναρξη" (Classic Shell) +Menu.MonitorOff = Απενεργοποίηση της οθόνης +Menu.RemoveHighlight = Κατάργηση επισήμανσης +Menu.Uninstall = &Κατάργηση εγκατάστασης +Menu.UninstallTitle = Κατάργηση εγκατάστασης +Menu.UninstallPrompt = Είστε βέβαιοι ότι θέλετε να καταργήσετε την εγκατάσταση του %s; +Search.CategorySettings = Ρυθμίσεις +Search.CategoryPCSettings = Ρυθμίσεις υπολογιστή +Search.CategoryPrograms = Προγράμματα +Search.CategoryDocuments = Έγγραφα +Search.CategoryMusic = Μουσική +Search.CategoryPictures = Εικόνες +Search.CategoryVideos = Βίντεο +Search.CategoryFiles = Αρχεία +Search.CategoryInternet = Ιnternet +JumpList.Recent = Πρόσφατα +JumpList.Frequent = Στοιχεία που επιλέγονται συχνότερα +JumpList.Tasks = Εργασίες +JumpList.Pinned = Καρφιτσωμένα +JumpList.Pin = &Καρφίτσωμα σε αυτήν τη λίστα +JumpList.Unpin = &Ξεκαρφίτσωμα από αυτήν τη λίστα +JumpList.Remove = Κατά&ργηση από τη λίστα +JumpList.PinTip = Καρφίτσωμα σε αυτήν τη λίστα +JumpList.UnpinTip = Ξεκαρφίτσωμα από αυτήν τη λίστα + + +[en-US] - English (United States) +Menu.Programs = &Programs +Menu.Apps = Apps +Menu.AllPrograms = All Programs +Menu.Back = Back +Menu.Favorites = F&avorites +Menu.Documents = &Documents +Menu.Settings = &Settings +Menu.Search = Sear&ch +Menu.SearchBox = Search +Menu.SearchPrograms = Search programs and files +Menu.SearchInternet = Search the Internet +Menu.Searching = Searching... +Menu.NoMatch = No items match your search. +Menu.MoreResults = See more results +Menu.Help = &Help and Support +Menu.Run = &Run... +Menu.Logoff = &Log Off %s... +Menu.SwitchUser = S&witch user +Menu.Lock = L&ock +Menu.LogOffShort = &Log off +Menu.Undock = Undock Comput&er +Menu.Disconnect = D&isconnect +Menu.ShutdownBox = Sh&ut Down... +Menu.Shutdown = Sh&ut Down +Menu.Restart = &Restart +Menu.ShutdownUpdate = Update and shut down +Menu.RestartUpdate = Update and restart +Menu.Sleep = &Sleep +Menu.Hibernate = &Hibernate +Menu.ControlPanel = &Control Panel +Menu.PCSettings = PC settings +Menu.Security = Windows Security +Menu.Network = &Network Connections +Menu.Printers = &Printers +Menu.Taskbar = &Taskbar and Start Menu +Menu.SearchFiles = For &Files or Folders... +Menu.SearchPrinter = For &Printer +Menu.SearchComputers = For &Computers +Menu.UserFilesTip = Contains folders for Documents, Pictures, Music, and other files that belong to you. +Menu.UserDocumentsTip = Contains letters, reports, and other documents and files. +Menu.UserPicturesTip = Contains digital photos, images, and graphic files. +Menu.UserMusicTip = Contains music and other audio files. +Menu.UserVideosTip = Contains movies and other video files. +Menu.NetworkTip = Displays existing network connections on this computer and helps you create new ones +Menu.PrintersTip = Add, remove, and configure local and network printers. +Menu.TaskbarTip = Customize the Start Menu and the taskbar, such as the types of items to be displayed and how they should appear. +Menu.ControlPanelTip = Change settings and customize the functionality of your computer. +Menu.DocumentsLibTip = Access letters, reports, notes, and other kinds of documents. +Menu.MusicLibTip = Play music and other audio files. +Menu.PicturesLibTip = View and organize digital pictures. +Menu.VideosLibTip = Watch home movies and other digital videos. +Menu.RecordingsLibTip = Watch TV programs recorded on your computer. +Menu.DownloadTip = Find Internet downloads and links to favorite websites. +Menu.HomegroupTip = Access libraries and folders shared by other people in your homegroup. +Menu.RunTip = Opens a program, folder, document, or web site. +Menu.HelpTip = Find Help topics, tutorials, troubleshooting, and other support services. +Menu.ProgramsTip = Opens a list of your programs. +Menu.SearchFilesTip = Search for documents, music, pictures, email and more. +Menu.GamesTip = Play and manage games on your computer. +Menu.SecurityTip = Launch Windows Security Options to Change Password, Switch User, or Start Task Manager. +Menu.SearchComputersTip = Search for computers on the network +Menu.SearchPrintersTip = Search for a printer +Menu.AdminToolsTip = Configure administrative settings for your computer. +Menu.ShutdownTip = Closes all open programs, shuts down Windows, and then turns off your computer. +Menu.RestartTip = Closes all open programs, shuts down Windows, and then starts Windows again. +Menu.SleepTip = Keeps your session in memory and puts the computer in a low-power state so that you can quickly resume working. +Menu.HibernateTip = Saves your session and turns off the computer. When you turn on the computer, Windows restores your session. +Menu.LogOffTip = Close programs and log off. +Menu.DisconnectTip = Disconnects your session. You can reconnect to this session when you log on again. +Menu.LockTip = Lock this computer. +Menu.UndockTip = Removes your laptop or notebook computer from a docking station. +Menu.SwitchUserTip = Switch users without closing programs. +Menu.Empty = (Empty) +Menu.Features = Programs and Features +Menu.FeaturesTip = Uninstall or change programs on your computer. +Menu.SearchPeople = For &People... +Menu.SortByName = Sort &by Name +Menu.Open = &Open +Menu.OpenAll = O&pen All Users +Menu.Explore = &Explore +Menu.ExploreAll = E&xplore All Users +Menu.MenuSettings = Settings +Menu.MenuHelp = Help +Menu.MenuExit = Exit +Menu.LogoffTitle = Log Off Windows +Menu.LogoffPrompt = Are you sure you want to log off? +Menu.LogoffYes = &Log Off +Menu.LogoffNo = &No +Menu.RenameTitle = Rename +Menu.RenamePrompt = &New name: +Menu.RenameOK = OK +Menu.RenameCancel = Cancel +Menu.Organize = Organize Start menu +Menu.Expand = Exp&and +Menu.Collapse = Coll&apse +Menu.NewFolder = New Folder +Menu.NewShortcut = New Shortcut +Menu.AutoArrange = &Auto Arrange +Menu.ActionOpen = Open +Menu.ActionClose = Close +Menu.ActionExecute = Execute +Menu.RemoveList = Remove &from this list +Menu.RemoveAll = C&lear recent items list +Menu.Explorer = Windows Explorer +Menu.Start = Start +Menu.StartScreen = Start Screen +Menu.StartMenu = Start Menu (Windows) +Menu.PinStart = Pin to Start menu +Menu.PinStartCs = Pin to Start menu (Classic Shell) +Menu.UnpinStartCs = Unpin from Start menu (Classic Shell) +Menu.MonitorOff = Turn the display off +Menu.RemoveHighlight = Remove highlight +Menu.Uninstall = &Uninstall +Menu.UninstallTitle = Uninstall +Menu.UninstallPrompt = Are you sure you want to uninstall %s? +Search.CategorySettings = Settings +Search.CategoryPCSettings = PC settings +Search.CategoryPrograms = Programs +Search.CategoryDocuments = Documents +Search.CategoryMusic = Music +Search.CategoryPictures = Pictures +Search.CategoryVideos = Videos +Search.CategoryFiles = Files +Search.CategoryInternet = Internet +JumpList.Recent = Recent +JumpList.Frequent = Frequent +JumpList.Tasks = Tasks +JumpList.Pinned = Pinned +JumpList.Pin = P&in to this list +JumpList.Unpin = &Unpin from this list +JumpList.Remove = Remove &from this list +JumpList.PinTip = Pin to this list +JumpList.UnpinTip = Unpin from this list + + +[es-ES] - Spanish (Spain) +Menu.Programs = &Programas +Menu.Apps = Aplicaciones +Menu.AllPrograms = Todos los programas +Menu.Back = Atrás +Menu.Favorites = Fa&voritos +Menu.Documents = Docu&mentos +Menu.Settings = Con&figuración +Menu.Search = &Buscar +Menu.SearchBox = Buscar +Menu.SearchPrograms = Buscar programas y archivos +Menu.SearchInternet = Buscar en Internet +Menu.Searching = Buscando... +Menu.NoMatch = Ningún elemento coincide con el criterio de búsqueda. +Menu.MoreResults = Ver más resultados +Menu.Help = &Ayuda y soporte técnico +Menu.Run = &Ejecutar... +Menu.Logoff = &Cerrar sesión de %s... +Menu.SwitchUser = Cam&biar de usuario +Menu.Lock = Bl&oquear +Menu.LogOffShort = C&errar sesión +Menu.Undock = De&sacoplar equipo +Menu.Disconnect = &Desconectar +Menu.ShutdownBox = Apaga&r... +Menu.Shutdown = &Apagar +Menu.Restart = &Reiniciar +Menu.ShutdownUpdate = Actualizar y apagar +Menu.RestartUpdate = Actualizar y reiniciar +Menu.Sleep = &Suspender +Menu.Hibernate = &Hibernar +Menu.ControlPanel = &Panel de control +Menu.PCSettings = Configuración de tu PC +Menu.Security = Seguridad de Windows +Menu.Network = &Conexiones de red +Menu.Printers = &Impresoras +Menu.Taskbar = &Barra de tareas y menú Inicio +Menu.SearchFiles = &Archivos o carpetas... +Menu.SearchPrinter = I&mpresoras +Menu.SearchComputers = Equip&os +Menu.UserFilesTip = Contiene carpetas para Documentos, Imágenes, Música y otros archivos que le pertenecen. +Menu.UserDocumentsTip = Contiene cartas, informes, y otros documentos y archivos. +Menu.UserPicturesTip = Contiene fotos digitales, imágenes y archivos de gráficos. +Menu.UserMusicTip = Contiene música y otros archivos de audio. +Menu.UserVideosTip = Contiene películas y otros archivos de vídeo. +Menu.NetworkTip = Muestra las conexiones de red existentes en este equipo y ayuda a crear otras nuevas +Menu.PrintersTip = Agrega, quita y configura impresoras locales y de red. +Menu.TaskbarTip = Personaliza el menú Inicio y la barra de tareas, el tipo de elementos que se muestra y la forma en que deben aparecer. +Menu.ControlPanelTip = Cambie la configuración y personalice la funcionalidad de su equipo. +Menu.DocumentsLibTip = Obtenga acceso a cartas, informes, notas y otra clase de documentos. +Menu.MusicLibTip = Reproduzca música y otros archivos de audio. +Menu.PicturesLibTip = Vea y organice imágenes digitales. +Menu.VideosLibTip = Vea películas domésticas y otros vídeos digitales. +Menu.RecordingsLibTip = Vea programas de televisión grabados en el equipo. +Menu.DownloadTip = Busque descargas de Internet y vínculos a sus sitios web favoritos. +Menu.HomegroupTip = Obtenga acceso a las bibliotecas y carpetas que comparten otros usuarios de su grupo en el hogar. +Menu.RunTip = Abre un programa, una carpeta, un documento o un sitio web. +Menu.HelpTip = Busque temas de Ayuda, tutoriales, solucionar problemas y otros servicios de soporte técnico. +Menu.ProgramsTip = Abre una lista de sus programas. +Menu.SearchFilesTip = Buscar documentos, música, imágenes, correo electrónico y más. +Menu.GamesTip = Juegue y administre los juegos en el equipo. +Menu.SecurityTip = Inicie Opciones de seguridad de Windows para cambiar la contraseña, cambiar de usuario o iniciar el Administrador de tareas. +Menu.SearchComputersTip = Buscar equipos en la red +Menu.SearchPrintersTip = Buscar una impresora +Menu.AdminToolsTip = Haga configuraciones administrativas en el equipo +Menu.ShutdownTip = Cierra todos los programas abiertos, cierra Windows y, después, apaga el equipo. +Menu.RestartTip = Cierra todos los programas abiertos, cierra Windows y después inicia Windows de nuevo. +Menu.SleepTip = Mantiene la memoria de la sesión y pone el equipo en un estado de baja energía para que pueda continuar trabajando rápidamente. +Menu.HibernateTip = Guarda la sesión y apaga el equipo. Cuando inicie el equipo, Windows restaurará la sesión. +Menu.LogOffTip = Cerrar los programas y la sesión. +Menu.DisconnectTip = Desconecta su sesión. Puede reconectarse a esta sesión cuando vuelva a iniciar sesión. +Menu.LockTip = Bloquear este equipo. +Menu.UndockTip = Quita un equipo portátil o de mano de la estación de acoplamiento. +Menu.SwitchUserTip = Cambiar de usuario sin cerrar los programas. +Menu.Empty = (Vacío) +Menu.Features = Programas y características +Menu.FeaturesTip = Desinstale o cambie programas en el equipo. +Menu.SearchPeople = &Personas... +Menu.SortByName = Ordenar por &Nombre +Menu.Open = &Abrir +Menu.OpenAll = Ab&rir todos los usuarios +Menu.Explore = E&xplorar +Menu.ExploreAll = &Explorar todos los usuarios +Menu.MenuSettings = Configuración +Menu.MenuHelp = Ayuda +Menu.MenuExit = Salir +Menu.LogoffTitle = Cerrar la sesión en Windows +Menu.LogoffPrompt = ¿Está seguro de que desea cerrar la sesión? +Menu.LogoffYes = &Cerrar sesión +Menu.LogoffNo = &No +Menu.RenameTitle = Cambiar nombre +Menu.RenamePrompt = &Nuevo nombre: +Menu.RenameOK = Aceptar +Menu.RenameCancel = Cancelar +Menu.Organize = Organizar el menú Inicio +Menu.Expand = &Expandir +Menu.Collapse = &Contraer +Menu.NewFolder = Nueva carpeta +Menu.NewShortcut = Nuevo acceso directo +Menu.AutoArrange = Organi&zación automática +Menu.ActionOpen = Abrir +Menu.ActionClose = Cerrar +Menu.ActionExecute = Ejecutar +Menu.RemoveList = &Quitar de esta lista +Menu.RemoveAll = &Borrar lista de elementos recientes +Menu.Explorer = Explorador de Windows +Menu.Start = Inicio +Menu.StartScreen = Pantalla Inicio +Menu.StartMenu = Menú Inicio (Windows) +Menu.PinStart = Anclar al menú Inicio +Menu.PinStartCs = Anclar al menú Inicio (Classic Shell) +Menu.UnpinStartCs = Desanclar del menú Inicio (Classic Shell) +Menu.MonitorOff = Apagar pantalla +Menu.RemoveHighlight = Quitar como elemento destacado +Menu.Uninstall = &Desinstalar +Menu.UninstallTitle = Desinstalar +Menu.UninstallPrompt = ¿Está seguro de que desea desinstalar %s? +Search.CategorySettings = Configuración +Search.CategoryPCSettings = Configuración de tu PC +Search.CategoryPrograms = Programas +Search.CategoryDocuments = Documentos +Search.CategoryMusic = Música +Search.CategoryPictures = Imágenes +Search.CategoryVideos = Vídeos +Search.CategoryFiles = Archivos +Search.CategoryInternet = Internet +JumpList.Recent = Reciente +JumpList.Frequent = Frecuente +JumpList.Tasks = Tareas +JumpList.Pinned = Anclado +JumpList.Pin = &Anclar a esta lista +JumpList.Unpin = &Desanclar de esta lista +JumpList.Remove = &Quitar de esta lista +JumpList.PinTip = Anclar a esta lista +JumpList.UnpinTip = Desanclar de esta lista + + +[et-EE] - Estonian (Estonia) +Menu.Programs = &Programmid +Menu.Apps = Rakendused +Menu.AllPrograms = Kõik programmid +Menu.Back = Tagasi +Menu.Favorites = &Lemmikud +Menu.Documents = &Dokumendid +Menu.Settings = &Sätted +Menu.Search = O&tsi +Menu.SearchBox = Otsi +Menu.SearchPrograms = Programmide ja failide otsing +Menu.SearchInternet = Otsi Internetist +Menu.Searching = Otsimine... +Menu.NoMatch = Teie otsingule ei vasta ükski üksus. +Menu.MoreResults = Kuva rohkem tulemeid +Menu.Help = Sp&ikker ja tugi +Menu.Run = &Käivita... +Menu.Logoff = L&ogi välja kasutaja %s... +Menu.SwitchUser = V&aheta kasutajat +Menu.Lock = &Lukusta +Menu.LogOffShort = &Logi välja +Menu.Undock = Doki a&rvuti lahti +Menu.Disconnect = K&atkesta ühendus +Menu.ShutdownBox = S&ule arvuti... +Menu.Shutdown = &Sule arvuti +Menu.Restart = &Taaskäivita +Menu.ShutdownUpdate = Värskenda ja sule +Menu.RestartUpdate = Värskenda ja taaskäivita +Menu.Sleep = &Unerežiim +Menu.Hibernate = &Talveunerežiim +Menu.ControlPanel = &Juhtpaneel +Menu.PCSettings = Arvutisätted +Menu.Security = Windowsi turvalisus +Menu.Network = Võrguühe&ndused +Menu.Printers = &Printerid +Menu.Taskbar = &Tegumiriba ja menüü Start +Menu.SearchFiles = &Failid või kaustad... +Menu.SearchPrinter = &Printer +Menu.SearchComputers = &Arvutitele +Menu.UserFilesTip = Sisaldab dokumentide, piltide, muusika ning teiste teile kuuluvate failide kaustu. +Menu.UserDocumentsTip = Sisaldab kirju, aruandeid ja muid dokumente ning faile. +Menu.UserPicturesTip = Sisaldab digitaalfotosid, pilte ja graafikafaile. +Menu.UserMusicTip = Sisaldab muusikat ja muid helifaile. +Menu.UserVideosTip = Sisaldab filme ja muid videofaile. +Menu.NetworkTip = Kuvab selles arvutis olemasolevad võrguühendused ja aitab luua uusi +Menu.PrintersTip = Lisa, eemalda ja konfigureeri kohalikke ning võrguprintereid. +Menu.TaskbarTip = Saate kohandada menüüd Start ja tegumiriba, näiteks seal kuvatavate üksuste tüüpe ja kuvamisviisi. +Menu.ControlPanelTip = Arvuti sätete muutmine ja funktsioonide kohandamine. +Menu.DocumentsLibTip = Juurdepääs kirjadele, aruannetele, märkmetele ja muudele dokumentidele. +Menu.MusicLibTip = Muusika ja muude helifailide esitamine. +Menu.PicturesLibTip = Digipiltide vaatamine ja korraldamine. +Menu.VideosLibTip = Kodu- ja muude digivideote vaatamine. +Menu.RecordingsLibTip = Arvutisse salvestatud telesaadete vaatamine. +Menu.DownloadTip = Internetist allalaaditavate failide ja lemmikveebisaidi linkide otsimine. +Menu.HomegroupTip = Juurdepääs teiste kodurühma inimeste ühiskasutusse antud teekidele ja kaustadele. +Menu.RunTip = Avab programmi, kausta, dokumendi või veebisaidi. +Menu.HelpTip = Otsige spikriteemasid, õpikuid, tõrkeotsinguid ja muid tugiteenuseid. +Menu.ProgramsTip = Kuvab programmide loendi. +Menu.SearchFilesTip = Otsige dokumente, muusikat, pilte, meile ja muud. +Menu.GamesTip = Mängige ja hallake oma arvutis mänge. +Menu.SecurityTip = Parooli muutmiseks, kasutaja vahetamiseks või tegumihalduri käivitamiseks avage Windowsi turbe suvandid. +Menu.SearchComputersTip = Otsi võrgus olevaid arvuteid +Menu.SearchPrintersTip = Otsi printerit +Menu.AdminToolsTip = Arvuti haldussätete konfigureerimine. +Menu.ShutdownTip = Suleb kõik avatud programmid, suleb Windowsi ja lülitab arvuti välja. +Menu.RestartTip = Suleb kõik avatud programmid, sulgeb Windowsi ning seejärel käivitab Windowsi uuesti. +Menu.SleepTip = Säilitab teie seansi mälus ja lülitab arvuti energiasäästurežiimi, et saaksite kiiresti töötamist jätkata. +Menu.HibernateTip = Salvestab teie seansi ning lülitab arvuti välja. Kui lülitate arvuti sisse, taastab Windows teie seansi. +Menu.LogOffTip = Programmide sulgemine ja väljalogimine. +Menu.DisconnectTip = Katkestab teie seansi. Saate selle seansiga ühenduse taastada, kui uuesti sisse logite. +Menu.LockTip = Selle arvuti lukustamine. +Menu.UndockTip = Eemaldab teie sülearvuti dokkimisjaamast. +Menu.SwitchUserTip = Kasutaja vahetamine ilma programme sulgemata. +Menu.Empty = (Tühi) +Menu.Features = Programmid ja funktsioonid +Menu.FeaturesTip = Desinstallige või muutke programme oma arvutis. +Menu.SearchPeople = &Inimesi... +Menu.SortByName = Sor&di nime järgi +Menu.Open = &Ava +Menu.OpenAll = A&va kaust Kõik kasutajad +Menu.Explore = Uu&ri +Menu.ExploreAll = Uur&i kausta Kõik kasutajad +Menu.MenuSettings = Sätted +Menu.MenuHelp = Spikker +Menu.MenuExit = Välju +Menu.LogoffTitle = Windowsist väljalogimine +Menu.LogoffPrompt = Kas soovite kindlasti välja logida? +Menu.LogoffYes = Lo&gi välja +Menu.LogoffNo = &Ei +Menu.RenameTitle = Ümbernimetamine +Menu.RenamePrompt = &Uus nimi: +Menu.RenameOK = OK +Menu.RenameCancel = Loobu +Menu.Organize = Korralda menüü Start +Menu.Expand = &Laienda +Menu.Collapse = A&henda +Menu.NewFolder = Uus kaust +Menu.NewShortcut = Uus otsetee +Menu.AutoArrange = &Korralda automaatselt +Menu.ActionOpen = Ava +Menu.ActionClose = Sule +Menu.ActionExecute = Täida +Menu.RemoveList = Eemal&da sellest loendist +Menu.RemoveAll = Tü&hjenda hiljutiste üksuste loend +Menu.Explorer = Windows Explorer +Menu.Start = Start +Menu.StartScreen = Avakuva +Menu.StartMenu = Menüü Start (Windows) +Menu.PinStart = Kinnita menüüsse Start +Menu.PinStartCs = Kinnita menüüsse Start (Classic Shell) +Menu.UnpinStartCs = Eemalda menüüst Start (Classic Shell) +Menu.MonitorOff = Lülitage kuvar välja +Menu.RemoveHighlight = Eemalda esiletõst +Menu.Uninstall = &Desinstalli +Menu.UninstallTitle = Desinstalli +Menu.UninstallPrompt = Kas soovite kindlasti desinstallida %s? +Search.CategorySettings = Sätted +Search.CategoryPCSettings = Arvutisätted +Search.CategoryPrograms = Programmid +Search.CategoryDocuments = Dokumendid +Search.CategoryMusic = Muusika +Search.CategoryPictures = Pildid +Search.CategoryVideos = Videod +Search.CategoryFiles = Failid +Search.CategoryInternet = Internet +JumpList.Recent = Hiljutised +JumpList.Frequent = Sagedased +JumpList.Tasks = Toimingud +JumpList.Pinned = Kinnitatud +JumpList.Pin = &Kinnita sellesse loendisse +JumpList.Unpin = &Eemalda sellest loendist +JumpList.Remove = Eemal&da sellest loendist +JumpList.PinTip = Kinnita sellesse loendisse +JumpList.UnpinTip = Eemalda sellest loendist + + +[fa-IR] - Persian +Menu.Programs = &برنامه‌ها +Menu.Apps = برنامه‌ها +Menu.AllPrograms = همه برنامه‌ها +Menu.Back = عقب +Menu.Favorites = علا&قه‌مندی‌ها +Menu.Documents = ا&سناد +Menu.Settings = تن&ظیمات +Menu.Search = &جستجو +Menu.SearchBox = جستجو +Menu.SearchPrograms = جستجوی برنامه‌ها و پرونده‌ها +Menu.SearchInternet = جستجوی اینترنت +Menu.Searching = در حال جستجو... +Menu.NoMatch = ‏‏هیچ موردی با جستجوی شما مطابقت ندارد. +Menu.MoreResults = دیدن نتایج بیشتر +Menu.Help = را&هنمایی و پشتیبانی +Menu.Run = &اجرا... +Menu.Logoff = &خروج از سیستم %s... +Menu.SwitchUser = تعویض کاربر +Menu.Lock = قفل کردن +Menu.LogOffShort = خروج از سیستم +Menu.Undock = جداسازی را&یانه از محل استقرار +Menu.Disconnect = ق&طع ارتباط +Menu.ShutdownBox = خامو&ش کردن... +Menu.Shutdown = خامو&ش کردن... +Menu.Restart = &راه‌اندازی مجدد +Menu.ShutdownUpdate = به‌روزرسانی و خاموش کردن +Menu.RestartUpdate = به‌روزرسانی و راه‌اندازی مجدد +Menu.Sleep = خ&واب +Menu.Hibernate = خاموشی &موقت +Menu.ControlPanel = &صفحه کنترل +Menu.PCSettings = تنظیمات رایانه +Menu.Security = امنیت ویندوز +Menu.Network = اتصالات شب&که +Menu.Printers = &چاپگرها +Menu.Taskbar = &نوار وظیفه و منوی شروع +Menu.SearchFiles = برای &پرونده‌ها و پوشه‌ها... +Menu.SearchPrinter = برای &چاپگر +Menu.SearchComputers = برای &رایانه‌ها +Menu.UserFilesTip = شامل پوشه‌های اسناد، تصاویر، موسیقی‌ها و پرونده‌های دیگری است که به شما تعلق دارد. +Menu.UserDocumentsTip = شامل نامه‌ها، اخبار و اسناد و پرونده‌های دیگر است. +Menu.UserPicturesTip = شامل عکس‌های دیجیتالی، تصاویر و پرونده‌های گرافیکی است. +Menu.UserMusicTip = شامل موسیقی‌ها و دیگر پرونده‌های صوتی است. +Menu.UserVideosTip = شامل فیلم‌ها و دیگر پرونده‌های ویدئویی است. +Menu.NetworkTip = ‏‏اتصالات شبکه موجود روی رایانه را نمایش می‌دهد و به شما در ایجاد اتصالات جدید کمک می کند +Menu.PrintersTip = چاپگرهای محلی و شبکه را اضافه، حذف و پیکربندی کنید. +Menu.TaskbarTip = ‏‏منوی "شروع" و نوار وظیفه را سفارشی می کند، مانند انواع موارد و نحوه نمایش آنها. +Menu.ControlPanelTip = تنظیمات را تغییر داده و عملکرد رایانه را سفارشی کنید. +Menu.DocumentsLibTip = دسترسی به نامه‌ها، گزارش‌ها، یادداشت‌ها، و انواع دیگر مدارک. +Menu.MusicLibTip = پخش موسیقی و پرونده‌های صوتی دیگر. +Menu.PicturesLibTip = مشاهده و سازماندهی تصاویر دیجیتالی. +Menu.VideosLibTip = تماشای فیلم‌های خانوادگی و سایر فیلم‌های دیجیتالی. +Menu.RecordingsLibTip = تماشای برنامه‌های تلویزیونی ضبط شده در رایانه شما. +Menu.DownloadTip = یافتن بارگیری‌های اینترنتی و پیوند به وب‌سایت‌های دلخواه. +Menu.HomegroupTip = به کتابخانه‌ها و پوشه‌هایی که دیگران به اشتراک گذاشته‌اند در گروه خانگی خود دسترسی پیدا کنید. +Menu.RunTip = یک برنامه، پوشه، سند یا وب‌سایت را باز می‌کند. +Menu.HelpTip = پیدا کردن عناوین راهنما، آموزش، رفع اشکال، و خدمات پشتیبانی دیگر. +Menu.ProgramsTip = فهرستی از برنامه‌های شما را باز می‌کند. +Menu.SearchFilesTip = جستجو برای سندها، موسیقی‌ها، تصاویر، پست الکترونیکی و موارد دیگر. +Menu.GamesTip = بازی کردن و مدیریت بازی‌های رایانه شما. +Menu.SecurityTip = راه‌اندازی گزینه‌های امنیتی ویندوز برای تغییر رمز ورود، تعویض کاربر یا شروع کنترل‌گر فعالیت‌ها. +Menu.SearchComputersTip = جستجو برای رایانه‌ها در شبکه +Menu.SearchPrintersTip = جستجو برای چاپگر +Menu.AdminToolsTip = پیکربندی تنظیمات مدیریت برای رایانه شما. +Menu.ShutdownTip = همه برنامه‌های باز را می‌بندد، ویندوز را خاموش می‌کند و سپس رایانه شما را خاموش می‌کند. +Menu.RestartTip = همه برنامه‌های باز را می‌بندد، ویندوز را خاموش می‌کند و سپس ویندوز را مجدداً راه‌اندازی می‌کند. +Menu.SleepTip = جلسه شما را در حافظه نگه می‌دارد و رایانه را در حالت مصرف برق کمتر قرار می‌دهد تا شما سریعاً بتوانید به کار خود برگردید. +Menu.HibernateTip = جلسه شما را ذخیره و رایانه را خاموش می‌کند. وقتی که رایانه را روشن می‌کنید، ویندوز جلسه شما را باز می‌گرداند. +Menu.LogOffTip = ‏‏برنامه‌ها را ببندید و از سیستم خارج شوید. +Menu.DisconnectTip = جلسه شما را قطع می‌کند. می‌توانید هنگامی که دوباره به سیستم وارد می‌شوید مجدداً به این جلسه وصل شوید. +Menu.LockTip = این رایانه را قفل کنید. +Menu.UndockTip = رایانه کیفی یا نوت‌بوک خود را از محل استقرار جدا کنید. +Menu.SwitchUserTip = تعویض کاربران بدون بستن برنامه‌ها. +Menu.Empty = (خالی) +Menu.Features = برنامه‌ها و ویژگی‌ها +Menu.FeaturesTip = برنامه‌های رایانه خود را تغییر داده یا پاک کنید. +Menu.SearchPeople = برای ا&فراد... +Menu.SortByName = &ترتیب بر اساس نام +Menu.Open = با&ز کردن +Menu.OpenAll = باز کردن تمام &کاربرها +Menu.Explore = کاو&ش +Menu.ExploreAll = کاوش ت&مام کاربرها +Menu.MenuSettings = تنظیمات +Menu.MenuHelp = راهنما +Menu.MenuExit = خروج +Menu.LogoffTitle = خروج از ویندوز +Menu.LogoffPrompt = آیا برای خروج از سیستم مطمئن هستید؟ +Menu.LogoffYes = خروج از س&یستم +Menu.LogoffNo = &خیر +Menu.RenameTitle = تغییر نام +Menu.RenamePrompt = نام &جدید: +Menu.RenameOK = تایید +Menu.RenameCancel = لغو +Menu.Organize = سازماندهی منوی شروع +Menu.Expand = با&ز شدن +Menu.Collapse = جمع &شدن +Menu.NewFolder = پوشه جدید +Menu.NewShortcut = میانبر جدید +Menu.AutoArrange = ترتیب خو&دکار +Menu.ActionOpen = باز کردن +Menu.ActionClose = بستن +Menu.ActionExecute = اجرا +Menu.RemoveList = حذف از این &لیست +Menu.RemoveAll = &پاک کردن لیست موارد اخیر +Menu.Explorer = کاوشگر ویندوز +Menu.Start = شروع +Menu.StartScreen = صفحه شروع +Menu.StartMenu = منوی آغاز (Windows) +Menu.PinStart = سنجاق کردن به منوی شروع +Menu.PinStartCs = سنجاق کردن به منوی شروع (Classic Shell) +Menu.UnpinStartCs = برداشتن از منوی شروع (Classic Shell) +Menu.MonitorOff = خاموش کردن صفحه نمایش +Menu.RemoveHighlight = حذف هایلایت +Menu.Uninstall = ل&غو نصب +Menu.UninstallTitle = لغو نصب +Menu.UninstallPrompt = ‏‏آیا مطمئنید می خواهید %s را لغو نصب کنید؟ +Menu.ClassicSettings = منوی ش&روع کلاسیک +Menu.SettingsTip = تنظیمات منوی شروع کلاسیک +Search.CategorySettings = تنظیمات +Search.CategoryPCSettings = تنظیمات رایانه +Search.CategoryPrograms = برنامه‌ها +Search.CategoryDocuments = اسناد +Search.CategoryMusic = موسیقی +Search.CategoryPictures = تصاویر +Search.CategoryVideos = فیلم‌ها +Search.CategoryFiles = پرونده‌ها +Search.CategoryInternet = اینترنت +JumpList.Recent = اخیر +JumpList.Frequent = مکرر +JumpList.Tasks = وظایف +JumpList.Pinned = سنجاق شده +JumpList.Pin = سن&جاق کردن به این لیست +JumpList.Unpin = &برداشتن از این لیست +JumpList.Remove = ح&ذف از این لیست +JumpList.PinTip = سننجاق کردن به این لیست +JumpList.UnpinTip = برداشتن از این لیست + + +[fi-FI] - Finnish (Finland) +Menu.Programs = O&hjelmat +Menu.Apps = Sovellukset +Menu.AllPrograms = Kaikki ohjelmat +Menu.Back = Takaisin +Menu.Favorites = &Suosikit +Menu.Documents = &Tiedostot +Menu.Settings = &Asetukset +Menu.Search = &Etsi +Menu.SearchBox = Etsi +Menu.SearchPrograms = Hae ohjelmista ja tiedostoista +Menu.SearchInternet = Etsi Internetistä +Menu.Searching = Etsitään... +Menu.NoMatch = Hakuehtoja täyttäviä kohteita ei löytynyt. +Menu.MoreResults = Näytä lisää tuloksia +Menu.Help = &Ohje ja tuki +Menu.Run = Suo&rita... +Menu.Logoff = Kirjaa &ulos: %s... +Menu.SwitchUser = &Vaihda käyttäjää +Menu.Lock = Luk&itse +Menu.LogOffShort = &Kirjaudu ulos +Menu.Undock = &Poista tietokone +Menu.Disconnect = &Katkaise yhteys +Menu.ShutdownBox = Sa&mmuta... +Menu.Shutdown = &Sammuta +Menu.Restart = Käynnistä &uudelleen +Menu.ShutdownUpdate = Päivitä ja sammuta +Menu.RestartUpdate = Päivitä ja käynnistä uudelleen +Menu.Sleep = L&epotila +Menu.Hibernate = &Horrostila +Menu.ControlPanel = &Ohjauspaneeli +Menu.PCSettings = Tietokoneen asetukset +Menu.Security = Windowsin suojaus +Menu.Network = &Verkkoyhteydet +Menu.Printers = T&ulostimet +Menu.Taskbar = &Tehtäväpalkki ja Käynnistä-valikko +Menu.SearchFiles = &Tiedostoja tai kansioita... +Menu.SearchPrinter = &Tulostimia +Menu.SearchComputers = Tiet&okoneita +Menu.UserFilesTip = Sisältää kansiot asiakirjoille, kuville, musiikille ja muille tiedostoillesi. +Menu.UserDocumentsTip = Sisältää asiakirjoja, tekstitiedostoja ja muita tiedostoja. +Menu.UserPicturesTip = Sisältää digitaalisia kuvia ja grafiikkatiedostoja. +Menu.UserMusicTip = Musiikki- ja äänitiedostojen tallennuspaikka. +Menu.UserVideosTip = Videotiedostojen tallennuspaikka. +Menu.NetworkTip = Näyttää tämän tietokoneen verkkoyhteydet ja auttaa uusien luomisessa +Menu.PrintersTip = Lisää, poistaa ja määrittää paikallisia ja verkossa olevia tulostimia. +Menu.TaskbarTip = Mukauttaa Käynnistä-valikon ja tehtäväpalkin asetuksia, kuten ilmaisinalueen kohteiden näyttötapaa. +Menu.ControlPanelTip = Muuta asetuksia ja muokkaa tietokoneen toimintaa. +Menu.DocumentsLibTip = Käytä kirjeitä, raportteja, muistiinpanoja ja muunlaisia asiakirjoja. +Menu.MusicLibTip = Toista musiikkia ja muita äänitiedostoja. +Menu.PicturesLibTip = Katsele digitaalisia kuvia ja järjestä niitä. +Menu.VideosLibTip = Katsele kotivideoita ja muita digitaalisia videoita. +Menu.RecordingsLibTip = Katsele tietokoneeseen tallennettuja TV-ohjelmia. +Menu.DownloadTip = Löydä ladattavia Internet-tiedostoja ja suosikkisivustojen linkkejä. +Menu.HomegroupTip = Käytä kotiryhmäsi muiden jäsenien jakamia kirjastoja ja kansioita. +Menu.RunTip = Avaa kansion, tiedoston tai WWW-sivun. +Menu.HelpTip = Etsi ohjeaiheita, opetusohjelmia, vianmääritystietoja ja muita tukipalveluja. +Menu.ProgramsTip = Avaa ohjelmaluettelon. +Menu.SearchFilesTip = Etsi asiakirjoja, musiikkia, kuvia, sähköpostiviestejä ja muita tiedostoja. +Menu.GamesTip = Pelaa ja käsittele tietokoneessa olevia pelejä. +Menu.SecurityTip = Avaa Windowsin suojausasetukset, jotta voit vaihtaa salasanan, vaihtaa käyttäjää tai käynnistää Tehtävienhallinnan. +Menu.SearchComputersTip = Etsi tietokoneita verkosta +Menu.SearchPrintersTip = Etsi tulostimia +Menu.AdminToolsTip = Määritä tietokoneen hallinta-asetukset. +Menu.ShutdownTip = Sulkee kaikki ohjelmat ja Windowsin sekä sammuttaa tietokoneen. +Menu.RestartTip = Sulkee kaikki avoimet ohjelmat ja Windowsin ja käynnistää sitten Windowsin uudelleen. +Menu.SleepTip = Säilyttää istunnon muistissa ja siirtää tietokoneen virransäästötilaan, jotta voit nopeasti jatkaa työskentelyä. +Menu.HibernateTip = Tallentaa istunnon ja sammuttaa tietokoneen. Kun käynnistät tietokoneen, Windows jatkaa istuntoa. +Menu.LogOffTip = Sulje ohjelmat ja kirjaudu ulos. +Menu.DisconnectTip = Katkaisee yhteyden istuntoon. Voit muodostaa yhteyden tähän istuntoon uudelleen kirjauduttaessa uudelleen. +Menu.LockTip = Lukitse tämä tietokone. +Menu.UndockTip = Poistaa kannettavan tietokoneen telakointiasemasta. +Menu.SwitchUserTip = Vaihda käyttäjiä sulkematta ohjelmia. +Menu.Empty = (Tyhjä) +Menu.Features = Ohjelmat ja toiminnot +Menu.FeaturesTip = Poista tai muuta tietokoneessa olevia ohjelmia. +Menu.SearchPeople = &Henkilöitä... +Menu.SortByName = &Lajittele nimen mukaan +Menu.Open = &Avaa +Menu.OpenAll = Avaa &kaikki käyttäjät +Menu.Explore = &Resurssienhallinta +Menu.ExploreAll = &Selaa kaikkia käyttäjiä +Menu.MenuSettings = Asetukset +Menu.MenuHelp = Ohje +Menu.MenuExit = Lopeta +Menu.LogoffTitle = Kirjaudu ulos Windowsista +Menu.LogoffPrompt = Haluatko varmasti kirjautua ulos? +Menu.LogoffYes = &Kirjaudu ulos +Menu.LogoffNo = E&i +Menu.RenameTitle = Nimeä uudelleen +Menu.RenamePrompt = &Uusi nimi: +Menu.RenameOK = OK +Menu.RenameCancel = Peruuta +Menu.Organize = Järjestä Käynnistä-valikko +Menu.Expand = &Laajenna +Menu.Collapse = &Kutista +Menu.NewFolder = Uusi kansio +Menu.NewShortcut = Uusi pikakuvake +Menu.AutoArrange = &Järjestä automaattisesti +Menu.ActionOpen = Avaa +Menu.ActionClose = Sulje +Menu.ActionExecute = Suorita +Menu.RemoveList = &Poista luettelosta +Menu.RemoveAll = &Tyhjennä viimeisimpien tiedostojen luettelo +Menu.Explorer = Resurssienhallinta +Menu.Start = Käynnistä +Menu.StartScreen = Aloitusnäyttö +Menu.StartMenu = Käynnistä-valikko (Windows) +Menu.PinStart = Kiinnitä Käynnistä-valikkoon +Menu.PinStartCs = Kiinnitä Käynnistä-valikkoon (Classic Shell) +Menu.UnpinStartCs = Poista kiinnitys Käynnistä-valikosta (Classic Shell) +Menu.MonitorOff = Sammuta näyttö +Menu.RemoveHighlight = Poista tärkeä kohde +Menu.Uninstall = &Poista asennus +Menu.UninstallTitle = Poista asennus +Menu.UninstallPrompt = Haluatko varmasti poistaa kohteen %s asennuksen? +Search.CategorySettings = Asetukset +Search.CategoryPCSettings = Tietokoneen asetukset +Search.CategoryPrograms = Ohjelmat +Search.CategoryDocuments = Tiedostot +Search.CategoryMusic = Musiikki +Search.CategoryPictures = Kuvat +Search.CategoryVideos = Videot +Search.CategoryFiles = Tiedostoja +Search.CategoryInternet = Internet +JumpList.Recent = Viimeksi käytetyt tiedostot +JumpList.Frequent = Usein käytetty +JumpList.Tasks = Tehtävät +JumpList.Pinned = Kiinnitetty +JumpList.Pin = Kiinnitä &tähän luetteloon +JumpList.Unpin = Poista &kiinnitys tästä luettelosta +JumpList.Remove = &Poista luettelosta +JumpList.PinTip = Kiinnitä tähän luetteloon +JumpList.UnpinTip = Poista kiinnitys tästä luettelosta + + +[fr-FR] - French (France) +Menu.Programs = Progra&mmes +Menu.Apps = Applications +Menu.AllPrograms = Tous les programmes +Menu.Back = Précédent +Menu.Favorites = Fa&voris +Menu.Documents = Doc&uments +Menu.Settings = &Paramètres +Menu.Search = Rec&hercher +Menu.SearchBox = Rechercher +Menu.SearchPrograms = Rechercher les programmes et fichiers +Menu.SearchInternet = Rechercher sur Internet +Menu.Searching = Recherche… +Menu.NoMatch = Aucun élément ne correspond à la recherche. +Menu.MoreResults = Voir plus de résultats +Menu.Help = &Aide et support +Menu.Run = E&xécuter… +Menu.Logoff = Fermer la sessi&on %s… +Menu.SwitchUser = &Changer d’utilisateur +Menu.Lock = Verr&ouiller +Menu.LogOffShort = &Fermer la session +Menu.Undock = R&etirer l’ordinateur +Menu.Disconnect = &Déconnecter +Menu.ShutdownBox = Arrê&ter… +Menu.Shutdown = A&rrêter +Menu.Restart = &Redémarrer +Menu.ShutdownUpdate = Mettre à jour et arrêter +Menu.RestartUpdate = Mettre à jour et redémarrer +Menu.Sleep = Mettre en &veille +Menu.Hibernate = &Mettre en veille prolongée +Menu.ControlPanel = &Panneau de configuration +Menu.PCSettings = Paramètres du PC +Menu.Security = Sécurité de Windows +Menu.Network = &Connexions réseau +Menu.Printers = &Imprimantes +Menu.Taskbar = &Barre des tâches et menu Démarrer +Menu.SearchFiles = Des &fichiers ou des dossiers… +Menu.SearchPrinter = Une i&mprimante +Menu.SearchComputers = Des &ordinateurs +Menu.UserFilesTip = Contient des dossiers pour les documents, les images, la musique et d’autres fichiers utilisateur. +Menu.UserDocumentsTip = Ouvrir des lettres, rapports et autres documents et fichiers. +Menu.UserPicturesTip = Contient des photos numériques, des images et des fichiers graphiques. +Menu.UserMusicTip = Contient de la musique et des fichiers audio. +Menu.UserVideosTip = Contient des films et des fichiers vidéo. +Menu.NetworkTip = Affiche les connexions réseau existantes sur cet ordinateur et vous aide à en créer de nouvelles +Menu.PrintersTip = Ajouter, supprimer ou configurer des imprimantes locales ou en réseau. +Menu.TaskbarTip = Personnalise le menu Démarrer et la barre des tâches, notamment les types d’éléments à afficher et l’aspect à leur donner. +Menu.ControlPanelTip = Modifier les paramètres et personnaliser la fonctionnalité de l’ordinateur. +Menu.DocumentsLibTip = Accéder aux lettres, rapports et notes et à d’autres types de documents. +Menu.MusicLibTip = Écouter de la musique et des fichiers audio. +Menu.PicturesLibTip = Afficher et organiser les images. +Menu.VideosLibTip = Regarder des films et d’autres vidéos numériques à la maison. +Menu.RecordingsLibTip = Regarder les programmes TV enregistrés sur cet ordinateur. +Menu.DownloadTip = Rechercher des téléchargements Internet et des liens vers les sites Web favoris. +Menu.HomegroupTip = Accéder aux bibliothèques et aux dossiers partagés par les autres membres du groupe résidentiel. +Menu.RunTip = Ouvrir un programme, un dossier, un document ou un site Web. +Menu.HelpTip = Rechercher des rubriques d’aide, des didacticiels, des informations de dépannage et d’autres services d’assistance. +Menu.ProgramsTip = Afficher tous les programmes présents sur cet ordinateur. +Menu.SearchFilesTip = Rechercher des documents, des morceaux de musique, des images, des messages et bien plus encore. +Menu.GamesTip = Jouer des parties et gérer les jeux de cet ordinateur. +Menu.SecurityTip = Lancer les Options de sécurité Windows pour modifier le mot de passe, changer d’utilisateur ou ouvrir le gestionnaire des tâches. +Menu.SearchComputersTip = Rechercher des ordinateurs sur le réseau +Menu.SearchPrintersTip = Rechercher une imprimante +Menu.AdminToolsTip = Configurer les paramètres d’administration de cet ordinateur. +Menu.ShutdownTip = Fermer tous les programmes ouverts, arrêter Windows et éteindre cet ordinateur. +Menu.RestartTip = Fermer tous les programmes ouverts, arrêter Windows puis redémarrer Windows. +Menu.SleepTip = Conserver cette session en mémoire en plaçant l’ordinateur en mode de consommation réduite, pour permettre de reprendre rapidement le travail. +Menu.HibernateTip = Enregistrer cette session et éteindre l’ordinateur. Lors du redémarrage de l’ordinateur, la session sera restaurée. +Menu.LogOffTip = Fermer les programmes et cette session. +Menu.DisconnectTip = Se déconnecter de cette session. Il sera possible de se reconnecter à cette session à l’ouverture d’une nouvelle session. +Menu.LockTip = Verrouiller cet ordinateur. +Menu.UndockTip = Retirer l’ordinateur portable de sa station d’accueil. +Menu.SwitchUserTip = Changer d’utilisateur sans fermer les programmes. +Menu.Empty = (Vide) +Menu.Features = Programmes et fonctionnalités +Menu.FeaturesTip = Désinstaller ou modifier des programmes sur cet ordinateur. +Menu.SearchPeople = Des &personnes… +Menu.SortByName = Trier par &nom +Menu.Open = &Ouvrir +Menu.OpenAll = Ouvrir &tous les utilisateurs +Menu.Explore = E&xplorer +Menu.ExploreAll = &Explorer Tous les utilisateurs +Menu.MenuSettings = Paramètres +Menu.MenuHelp = Aide +Menu.MenuExit = Quitter +Menu.LogoffTitle = Fermeture de session Windows +Menu.LogoffPrompt = Faut-il vraiment fermer cette session ? +Menu.LogoffYes = &Fermer la session +Menu.LogoffNo = &Non +Menu.RenameTitle = Renommer +Menu.RenamePrompt = &Nouveau nom : +Menu.RenameOK = OK +Menu.RenameCancel = Annuler +Menu.Organize = Organiser le menu Démarrer +Menu.Expand = &Développer +Menu.Collapse = &Réduire +Menu.NewFolder = Nouveau dossier +Menu.NewShortcut = Nouveau raccourci +Menu.AutoArrange = &Réorganisation automatique +Menu.ActionOpen = Ouvrir +Menu.ActionClose = Fermer +Menu.ActionExecute = Exécuter +Menu.RemoveList = &Supprimer de cette liste +Menu.RemoveAll = Effacer les é&léments récents +Menu.Explorer = Explorateur Windows +Menu.Start = Démarrer +Menu.StartScreen = Écran d’accueil +Menu.StartMenu = Menu Démarrer (Windows) +Menu.PinStart = Épingler au menu Démarrer +Menu.PinStartCs = Épingler au menu Démarrer (Classic Shell) +Menu.UnpinStartCs = Détacher du menu Démarrer (Classic Shell) +Menu.MonitorOff = Éteindre l’affichage +Menu.RemoveHighlight = Supprimer la recommandation +Menu.Uninstall = &Désinstaller +Menu.UninstallTitle = Désinstaller +Menu.UninstallPrompt = Faut-il vraiment désinstaller %s ? +Search.CategorySettings = Paramètres +Search.CategoryPCSettings = Paramètres du PC +Search.CategoryPrograms = Programmes +Search.CategoryDocuments = Documents +Search.CategoryMusic = Musique +Search.CategoryPictures = Images +Search.CategoryVideos = Vidéos +Search.CategoryFiles = Fichiers +Search.CategoryInternet = Internet +JumpList.Recent = Récent +JumpList.Frequent = Fréquent +JumpList.Tasks = Tâches +JumpList.Pinned = Épinglé +JumpList.Pin = Ép&ingler à cette liste +JumpList.Unpin = &Détacher de cette liste +JumpList.Remove = Suppri&mer de cette liste +JumpList.PinTip = Épingler à cette liste +JumpList.UnpinTip = Détacher de cette liste + + +[gd-GB] - Scottish Gaelic (United Kingdom) +Menu.Programs = &Prògraman +Menu.Apps = Aplacaidean +Menu.AllPrograms = Na h-uile prògram +Menu.Back = Air ais +Menu.Favorites = &Annsachdan +Menu.Documents = &Sgrìobhainnean +Menu.Settings = R&oghainnean +Menu.Search = &Lorg +Menu.SearchBox = Lorg +Menu.SearchPrograms = Lorg prògraman is faidhlichean +Menu.SearchInternet = Lorg air an eadar-lìon +Menu.Searching = Ga lorg... +Menu.NoMatch = Chan eil dad a' freagairt ris na lorg thu. +Menu.MoreResults = Faic barrachd thoraidhean +Menu.Help = Cob&hair is taic +Menu.Run = &Ruith... +Menu.Logoff = C&làraich %s a-mach... +Menu.SwitchUser = Gearr leum gu cleachdaiche eile +Menu.Lock = Glais +Menu.LogOffShort = Clàraich a-mach +Menu.Undock = N&eo-dhocaich an coimpiutair +Menu.Disconnect = Dì-cheanga&il +Menu.ShutdownBox = &Dùin sìos... +Menu.Shutdown = &Dùin sìos +Menu.Restart = &Ath-thòisich +Menu.ShutdownUpdate = Ùraich is dùin sìos +Menu.RestartUpdate = Ùraich is ath-thòisich +Menu.Sleep = C&uir na chadal +Menu.Hibernate = &Geamhraich +Menu.ControlPanel = A' &phanail-smachd +Menu.PCSettings = Roghainnean a' PC +Menu.Security = Tèarainteachd Windows +Menu.Network = Cea&nglaichean lìonraidh +Menu.Printers = Clò-&bhualadairean +Menu.Taskbar = Bàr nan sao&thair is an clàr-taice tòiseachaidh +Menu.SearchFiles = Airson &faidhlichean no pasganan... +Menu.SearchPrinter = Airson clò-&bhualadair +Menu.SearchComputers = Airson &coimpiutairean +Menu.UserFilesTip = Tha pasgain airson sgrìobhainnean, dealbhan, ceòl is na faidhlichean eile agad ann. +Menu.UserDocumentsTip = Tha litrichean, aithisgean, sgrìobhainnean is faidhlichean eile ann. +Menu.UserPicturesTip = Tha dealbhan digiteach, ìomhaighean is faidhlichean grafaigeach ann. +Menu.UserMusicTip = Tha faidhlichean ciùil is fuaime ann. +Menu.UserVideosTip = Tha filmichean is faidhlichean video eile ann. +Menu.NetworkTip = Seallaidh e ceanglaichean lìonraidh a tha air a' choimpiutair seo 's cuidichidh e a' cruthachadh feadhainn ùra +Menu.PrintersTip = Cuir ris, thoir air falbh is rèitich clò-bhualadairean ionadail is lìonraidh. +Menu.TaskbarTip = Gnàthaich an clàr-taice tòiseachaidh agus bàr nan saothair, can seòrsa nan nithean a chithear agus mar a nochdas iad. +Menu.ControlPanelTip = Atharraich na roghainnean is gnàthaich comas-gnìomh a' choimpiutair agad. +Menu.DocumentsLibTip = Dèan inntrigeadh do litrichean, aithisgean, nòtaichean is sgrìobhainnean eile. +Menu.MusicLibTip = Cluich ceòl is faidhlichean fuaime eile. +Menu.PicturesLibTip = Faic is cuir air dòigh dealbhan digiteach. +Menu.VideosLibTip = Coimhead air filmichean dachaigh is videothan digiteach eile. +Menu.RecordingsLibTip = Coimhead air prògraman TBh a chlàraich thu air a' choimpiutair agad. +Menu.DownloadTip = Lorg rudan ri luchdadh a-nuas on eadar-lìon is ceanglaichean ris na làraichean-lìn as fhearr leat. +Menu.HomegroupTip = Dèan inntrigeadh do leabharlannan is pasgain air an co-roinneadh le daoine eile sa bhuidhinn dachaigh agad. +Menu.RunTip = Fosglaidh seo prògram, pasgan, sgrìobhainn no làrach-lìn. +Menu.HelpTip = Lorg cuspairean na cobharach, treòirean, fuasgladh dhuilgheadasan is seirbheisean taice eile. +Menu.ProgramsTip = Fosglaidh seo liosta nam prògraman agad. +Menu.SearchFilesTip = Lorg sgrìobhainnean, ceòl, dealbhan, puist-d is mòran a bharrachd. +Menu.GamesTip = Cluich is stiùir geamannan air a' choimpiutair agad. +Menu.SecurityTip = Tòisich roghainnean tèarainteachd Windows gus facal-faire atharrachadh, suidseadh eadar cleachdaichean no manaidsear nan saothair a thòiseachadh. +Menu.SearchComputersTip = Lorg coimpiutairean air an lìonra +Menu.SearchPrintersTip = Lorg clò-bhualadair +Menu.AdminToolsTip = Rèitich roghainnean rianaire air a' choimpiutair agad. +Menu.ShutdownTip = Dùinidh seo a h-uile prògram fosgailte, dùinidh e sìos Windows agus cuiridh e dheth an coimpiutair agad. +Menu.RestartTip = Dùinidh seo a h-uile prògram fosgailte, dùinidh e sìos Windows agus tòisichidh e Windows às ùr. +Menu.SleepTip = Cumaidh seo an seisean agad na chuimhne agus cuiridh e an coimpiutair na staid nach cleachd ach beagan cumhachd airson 's gun urrainn dhut tòiseachadh air d' obair a-rithist gu luath. +Menu.HibernateTip = Sàbhailidh seo an seisean agad is cuiridh e dheth an coimpiutair. Nuair a chuireas tu air an coimpiutair a-rithist, aisigidh Windows an seisean dhut. +Menu.LogOffTip = Dùin na prògraman is clàraich a-mach. +Menu.DisconnectTip = Dì-cheanglaidh seo an seisean agad. 'S urrainn dhut ceangal ris an t-seisean seo às ùr nuair a chlàraicheas tu a-steach a-rithist. +Menu.LockTip = Glais an coimpiutair seo. +Menu.UndockTip = Bheir seo an laptop no notebook agad air falbh on stèisean docaidh. +Menu.SwitchUserTip = Gearr leum eadar cleachdaichean gun na prògraman a dhùnadh. +Menu.Empty = (Falamh) +Menu.Features = Prògraman is feartan +Menu.FeaturesTip = Dì-stàlaich no atharraich prògraman air a' choimpiutair agad. +Menu.SearchPeople = Airson &daoine... +Menu.SortByName = Seòrsaich a-rèir ain&m +Menu.Open = F&osgail +Menu.OpenAll = &Fosgail a h-uile cleachdaiche +Menu.Explore = &Rùraich +Menu.ExploreAll = Rùraic&h a h-uile cleachdaiche +Menu.MenuSettings = Roghainnean +Menu.MenuHelp = Cobhair +Menu.MenuExit = Fàg an-seo +Menu.LogoffTitle = Clàraich a-mach à Windows +Menu.LogoffPrompt = A bheil thu cinnteach gu bheil thu airson clàradh a-mach? +Menu.LogoffYes = &Clàraich a-mach +Menu.LogoffNo = Cha&n eil +Menu.RenameTitle = Thoir ainm ùr air +Menu.RenamePrompt = An &t-ainm ùr: +Menu.RenameOK = Ceart ma-thàa +Menu.RenameCancel = Sguir dheth +Menu.Organize = Cuir air dòigh an clàr-taice tòiseachaidh +Menu.Expand = Leud&aich +Menu.Collapse = Co-the&annaich +Menu.NewFolder = Pasgan ùr +Menu.NewShortcut = Ath-ghoirid ùr +Menu.AutoArrange = C&uir air dòigh gu fèin-obrachail +Menu.ActionOpen = Fosgail +Menu.ActionClose = Dùin +Menu.ActionExecute = Cuir an gnìomh +Menu.RemoveList = Thoir air &falbh on liosta seo +Menu.RemoveAll = Fa&lamhaich liosta nan nithean a bha fosgailte o chionn goirid +Menu.Explorer = Windows Explorer +Menu.Start = Tòisich +Menu.StartScreen = An sgrìn-tòiseachaidh +Menu.StartMenu = Start Menu (Windows) +Menu.PinStart = Prìnich ris a' chlàr-taice tòiseachaidh +Menu.PinStartCs = Prìnich ris a' chlàr-taice tòiseachaidh (Classic Shell) +Menu.UnpinStartCs = Dì-phrìnich on chlàr-taice tòiseachaidh (Classic Shell) +Menu.MonitorOff = Cuir an t-uidheam-taisbeanaidh dheth +Menu.RemoveHighlight = Remove highlight +Menu.Uninstall = &Dì-stàlaich +Menu.UninstallTitle = Dì-stàlaich +Menu.UninstallPrompt = A bheil thu cinnteach gu bheil thu airson %s a dhì-stàladh? +Search.CategorySettings = Roghainnean +Search.CategoryPCSettings = Roghainnean a' PC +Search.CategoryPrograms = Prògraman +Search.CategoryDocuments = Sgrìobhainnean +Search.CategoryMusic = Ceòl +Search.CategoryPictures = Dealbhan +Search.CategoryVideos = Videothan +Search.CategoryFiles = Faidhlichean +Search.CategoryInternet = An t-eadar-lìon +JumpList.Recent = O chionn goirid +JumpList.Frequent = Gu tric +JumpList.Tasks = Saothraichean +JumpList.Pinned = Prìnichte +JumpList.Pin = Prìn&ich ris an liosta seo +JumpList.Unpin = Dì-phrìnich &on liosta seo +JumpList.Remove = Thoir air &falbh on liosta seo +JumpList.PinTip = Prìnich ris an liosta seo +JumpList.UnpinTip = Dì-phrìnich on liosta seo + + +[he-IL] - Hebrew (Israel) +Menu.Programs = &תוכניות +Menu.Apps = אפליקציות +Menu.AllPrograms = כל התוכניות +Menu.Back = הקודם +Menu.Favorites = מו&עדפים +Menu.Documents = מסמכ&ים +Menu.Settings = &הגדרות +Menu.Search = &חפש +Menu.SearchBox = חפש +Menu.SearchPrograms = חפש בתוכניות ובקבצים +Menu.SearchInternet = חפש באינטרנט +Menu.Searching = מחפש... +Menu.NoMatch = ‏‏אין פריטים התואמים לחיפוש שלך. +Menu.MoreResults = הצג תוצאות נוספות +Menu.Help = ע&זרה ותמיכה +Menu.Run = הפע&לה... +Menu.Logoff = י&ציאת %s... +Menu.SwitchUser = החלף מש&תמש +Menu.Lock = נ&על +Menu.LogOffShort = &צא +Menu.Undock = &בטל עיגון מחשב +Menu.Disconnect = התנת&קות +Menu.ShutdownBox = &כיבוי... +Menu.Shutdown = &כיבוי +Menu.Restart = &הפעלה מחדש +Menu.ShutdownUpdate = עדכן וכבה +Menu.RestartUpdate = עדכן והפעל מחדש +Menu.Sleep = &שינה +Menu.Hibernate = &מצב שינה +Menu.ControlPanel = &לוח הבקרה +Menu.PCSettings = הגדרות מחשב +Menu.Security = אבטחת Windows +Menu.Network = חיבורי &רשת +Menu.Printers = &מדפסות +Menu.Taskbar = שורת המ&שימות ותפריט התחלה +Menu.SearchFiles = עבור &קבצים או תיקיות... +Menu.SearchPrinter = עבור מ&דפסת +Menu.SearchComputers = עבור &מחשבים +Menu.UserFilesTip = מכיל תיקיות עבור מסמכים, תמונות, מוסיקה וקבצים אחרים השייכים לך. +Menu.UserDocumentsTip = מכיל מכתבים, דוחות ומסמכים וקבצים אחרים. +Menu.UserPicturesTip = תיקיה זו מכילה צילומים דיגיטליים, תמונות וקבצי גרפיקה. +Menu.UserMusicTip = תיקיה זו מכילה קבצי מוסיקה וקבצי שמע אחרים. +Menu.UserVideosTip = תיקיה זו מכילה סרטים וקבצי וידאו אחרים. +Menu.NetworkTip = הצגת חיבורי רשת קיימים במחשב זה ועזרה ביצירת חיבורים חדשים +Menu.PrintersTip = הוסף, הסר והגדר מדפסות מקומיות ומדפסות רשת. +Menu.TaskbarTip = התאם אישית את תפריט התחלה ואת שורת המשימות, כגון סוגי הפריטים שיוצגו ואופן התצוגה שלהם. +Menu.ControlPanelTip = שנה הגדרות והתאם אישית את הפונקציונליות של המחשב שלך. +Menu.DocumentsLibTip = גש למכתבים, דוחות, פתקים וסוגי מסמכים אחרים. +Menu.MusicLibTip = השמע קבצי מוסיקה וקבצי שמע אחרים. +Menu.PicturesLibTip = הצג וארגן תמונות דיגיטליות. +Menu.VideosLibTip = צפה בסרטים ביתיים ובסרטי וידאו דיגיטליים אחרים. +Menu.RecordingsLibTip = צפה בתוכניות טלוויזיה שהוקלטו במחשב שלך. +Menu.DownloadTip = מצא הורדות באינטרנט וקישורים לאתרי אינטרנט מועדפים. +Menu.HomegroupTip = גש לספריות ותיקיות שמשתפים אנשים אחרים בקבוצה הביתית שלך. +Menu.RunTip = פתיחת תוכנית, תיקיה, מסמך או אתר אינטרנט. +Menu.HelpTip = חפש נושאי עזרה, ערכות לימוד, כלי פתרון בעיות ושירותי תמיכה נוספים. +Menu.ProgramsTip = פתיחת רשימה של התוכניות שלך. +Menu.SearchFilesTip = חפש מסמכים, מוסיקה, תמונות, דואר אלקטרוני ועוד. +Menu.GamesTip = שחק ונהל משחקים במחשב. +Menu.SecurityTip = הפעל אפשרויות אבטחה של Windows ל'שנה סיסמה', 'החלף משתמש' או 'הפעל את מנהל המשימות'. +Menu.SearchComputersTip = חפש מחשבים ברשת +Menu.SearchPrintersTip = חפש מדפסת +Menu.AdminToolsTip = קבע תצורה של הגדרות ניהול עבור המחשב. +Menu.ShutdownTip = סגירת כל התוכניות הפתוחות, יציאה מ- Windows ולאחר מכן כיבוי המחשב שלך. +Menu.RestartTip = סגירת כל התוכניות הפתוחות, יציאה מ- Windows ולאחר מכן הפעלה מחדש של Windows. +Menu.SleepTip = שמירת ההפעלה שלך בזיכרון והעברת המחשב למצב צריכת חשמל נמוכה כדי שתוכל לחדש במהירות את העבודה. +Menu.HibernateTip = שמירת ההפעלה שלך וכיבוי המחשב. כאשר תפעיל את המחשב, Windows ישחזר את ההפעלה. +Menu.LogOffTip = סגור תוכניות וצא. +Menu.DisconnectTip = ניתוק ההפעלה שלך. באפשרותך להתחבר מחדש להפעלה זו כשתיכנס שוב. +Menu.LockTip = נעל מחשב זה. +Menu.UndockTip = הסרת המחשב הנישא או מחשב המחברת שלך מתחנת עגינה. +Menu.SwitchUserTip = החלף משתמשים מבלי לסגור תוכניות. +Menu.Empty = (ריק) +Menu.Features = תוכניות ותכונות +Menu.FeaturesTip = הסר התקנה או שנה תוכניות במחשב שלך. +Menu.SearchPeople = עבור &אנשים... +Menu.SortByName = מיין לפי &שם +Menu.Open = &פתח +Menu.OpenAll = פתח את &כל המשתמשים +Menu.Explore = &סייר +Menu.ExploreAll = סיי&ר בכל המשתמשים +Menu.MenuSettings = הגדרות +Menu.MenuHelp = עזרה +Menu.MenuExit = יציאה +Menu.LogoffTitle = יציאה מ- Windows +Menu.LogoffPrompt = האם אתה בטוח שברצונך לצאת? +Menu.LogoffYes = &צא +Menu.LogoffNo = &לא +Menu.RenameTitle = שינוי שם +Menu.RenamePrompt = &שם חדש: +Menu.RenameOK = אישור +Menu.RenameCancel = ביטול +Menu.Organize = ארגן את תפריט התחלה +Menu.Expand = &הרחב +Menu.Collapse = &כווץ +Menu.NewFolder = תיקיה חדשה +Menu.NewShortcut = קיצור דרך חדש +Menu.AutoArrange = סדר &אוטומטית +Menu.ActionOpen = פתח +Menu.ActionClose = סגור +Menu.ActionExecute = בצע +Menu.RemoveList = &הסר מרשימה זו +Menu.RemoveAll = &נקה את רשימת הפריטים האחרונים +Menu.Explorer = סייר Windows +Menu.Start = התחל +Menu.StartScreen = מסך התחל +Menu.StartMenu = תפריט התחלה (Windows) +Menu.PinStart = הצמד לתפריט התחלה +Menu.PinStartCs = הצמד לתפריט התחלה (Classic Shell) +Menu.UnpinStartCs = בטל הצמדה לתפריט התחלה (Classic Shell) +Menu.MonitorOff = כבה את התצוגה +Menu.RemoveHighlight = הסר הבלטה +Menu.Uninstall = ה&סר התקנה +Menu.UninstallTitle = הסר התקנה +Menu.UninstallPrompt = ‏‏האם אתה בטוח שברצונך להסיר את התקנת %s? +Search.CategorySettings = הגדרות +Search.CategoryPCSettings = הגדרות מחשב +Search.CategoryPrograms = תוכניות +Search.CategoryDocuments = מסמכים +Search.CategoryMusic = מוסיקה +Search.CategoryPictures = תמונות +Search.CategoryVideos = סרטי וידאו +Search.CategoryFiles = קבצים +Search.CategoryInternet = אינטרנט +JumpList.Recent = לאחרונה +JumpList.Frequent = תכוף +JumpList.Tasks = משימות +JumpList.Pinned = מוצמד +JumpList.Pin = ה&צמד לרשימה זו +JumpList.Unpin = ב&טל הצמדה לרשימה זו +JumpList.Remove = &הסר מרשימה זו +JumpList.PinTip = הצמד לרשימה זו +JumpList.UnpinTip = בטל הצמדה לרשימה זו + + +[hr-HR] - Croatian (Croatia) +Menu.Programs = Pro&grami +Menu.Apps = Aplikacije +Menu.AllPrograms = Svi programi +Menu.Back = Natrag +Menu.Favorites = &Favoriti +Menu.Documents = &Dokumenti +Menu.Settings = Postav&ke +Menu.Search = T&raži +Menu.SearchBox = Traži +Menu.SearchPrograms = Pretraži programe i datoteke +Menu.SearchInternet = Pretraži internet +Menu.Searching = Pretraživanje... +Menu.NoMatch = Pretraživanje nije dalo rezultata. +Menu.MoreResults = Prikaži još rezultata +Menu.Help = Po&moć i podrška +Menu.Run = &Pokreni... +Menu.Logoff = &Odjava korisnika %s... +Menu.SwitchUser = P&romijeni korisnika +Menu.Lock = &Zaključaj +Menu.LogOffShort = &Odjava +Menu.Undock = Ukloni r&ačunalo iz ležišta +Menu.Disconnect = Prekini &vezu +Menu.ShutdownBox = Isklj&uči računalo... +Menu.Shutdown = I&sključi računalo +Menu.Restart = &Ponovo pokreni +Menu.ShutdownUpdate = Ažuriraj i isključi +Menu.RestartUpdate = Ažuriraj i ponovno pokreni +Menu.Sleep = &Spavaj +Menu.Hibernate = &Hibernacija +Menu.ControlPanel = &Upravljačka ploča +Menu.PCSettings = Postavke PC-ja +Menu.Security = Sigurnost sustava Windows +Menu.Network = &Mrežne veze +Menu.Printers = &Pisači +Menu.Taskbar = Programska traka i izbornik &Start +Menu.SearchFiles = Za &datoteke i mape... +Menu.SearchPrinter = Za &pisač +Menu.SearchComputers = Za &računala +Menu.UserFilesTip = Sadrži mape za dokumente, slike, glazbu i druge datoteke koje vam pripadaju. +Menu.UserDocumentsTip = Sadrži digitalne fotografije, slike i grafičke datoteke. +Menu.UserPicturesTip = Sadrži digitalne fotografije, slike i grafičke datoteke. +Menu.UserMusicTip = Sadrži glazbene i druge audio datoteke. +Menu.UserVideosTip = Sadrži filmove i druge videodatoteke. +Menu.NetworkTip = Prikazuje postojeće mrežne veze u računalu i pomaže vam u stvaranju novih +Menu.PrintersTip = Dodajte, uklonite i konfigurirajte lokalne i mrežne pisače. +Menu.TaskbarTip = Prilagodite izbornik Start i programsku traku (npr. odaberite stavke koje će biti prikazane i njihov izgled). +Menu.ControlPanelTip = Promijenite postavke i prilagodite funkcije svog računala. +Menu.DocumentsLibTip = Pristupajte pismima, izvješćima, bilješkama i drugim vrstama dokumenata. +Menu.MusicLibTip = Reproducirajte glazbu i druge audiodatoteke. +Menu.PicturesLibTip = Pregledavajte i organizirajte digitalne slike. +Menu.VideosLibTip = Gledanje kućnih snimki i drugih digitalnih videozapisa. +Menu.RecordingsLibTip = Gledanje TV programa snimljenog na računalu. +Menu.DownloadTip = Traženje internetskih preuzimanja i veza do omiljenih web-mjesta. +Menu.HomegroupTip = Pristupajte bibliotekama i mapama koje zajednički koriste druge osobe u osnovnoj grupi. +Menu.RunTip = Otvara program, mapu, dokument ili web-mjesto. +Menu.HelpTip = Potražite teme Pomoći, vodiče za korisnike, upute za otklanjanje poteškoća i druge servise podrške. +Menu.ProgramsTip = Otvara popis vaših programa. +Menu.SearchFilesTip = Tražite dokumente, glazbu, slike, poruke e-pošte i štošta drugo. +Menu.GamesTip = Igranje i upravljanje igrama na računalu. +Menu.SecurityTip = Pokretanje mogućnosti sigurnosti sustava Windows radi promjene lozinke ili korisnika, odnosno pokretanja Upravitelja zadataka. +Menu.SearchComputersTip = Traži računala u mreži +Menu.SearchPrintersTip = Traži pisač +Menu.AdminToolsTip = Konfigurirajte administrativne postavke računala. +Menu.ShutdownTip = Zatvara sve otvorene programe i isključuje sustav Windows, a zatim i računalo. +Menu.RestartTip = Zatvara sve otvorene programe i isključuje sustav Windows, a zatim ga ponovno pokreće. +Menu.SleepTip = Čuva sesiju u memoriji, a računalo stavlja u stanje male potrošnje radi mogućnosti što bržeg nastavka s radom. +Menu.HibernateTip = Sprema sesiju i gasi računalo. Kada uključite računalo, Windows vraća vašu sesiju. +Menu.LogOffTip = Zatvaranje programa i odjava korisnika. +Menu.DisconnectTip = Prekida vašu sesiju. Možete nastaviti rad u istoj sesiji kada se ponovno prijavite. +Menu.LockTip = Zaključavanje ovog računala. +Menu.UndockTip = Uklanja prijenosno računalo sa stanice za spajanje. +Menu.SwitchUserTip = Promjena korisnika bez zatvaranja programa. +Menu.Empty = (Prazno) +Menu.Features = Programi i značajke +Menu.FeaturesTip = Deinstaliranje ili uklanjanje programa s računala. +Menu.SearchPeople = Za &osobe... +Menu.SortByName = Poredaj po i&menu +Menu.Open = &Otvori +Menu.OpenAll = Ot&vori sve korisnike +Menu.Explore = Ist&raži +Menu.ExploreAll = Istr&aži sve korisnike +Menu.MenuSettings = Postavke +Menu.MenuHelp = Pomoć +Menu.MenuExit = Izlaz +Menu.LogoffTitle = Odjava iz sustava Windows +Menu.LogoffPrompt = Jeste li sigurni da se želite odjaviti? +Menu.LogoffYes = &Odjava +Menu.LogoffNo = &Ne +Menu.RenameTitle = Preimenovanje +Menu.RenamePrompt = &Novi naziv: +Menu.RenameOK = U redu +Menu.RenameCancel = Odustani +Menu.Organize = Organiziranje izbornika Start +Menu.Expand = &Proširi +Menu.Collapse = Saž&mi +Menu.NewFolder = Nova mapa +Menu.NewShortcut = Novi prečac +Menu.AutoArrange = &Posloži automatski +Menu.ActionOpen = Otvori +Menu.ActionClose = Zatvori +Menu.ActionExecute = Izvrši +Menu.RemoveList = Ukloni s &ovog popisa +Menu.RemoveAll = Oč&isti popis nedavnih stavki +Menu.Explorer = Windows Explorer +Menu.Start = Start +Menu.StartScreen = Početni zaslon +Menu.StartMenu = Izbornik Start (Windows) +Menu.PinStart = Prikvači na izbornik Start +Menu.PinStartCs = Prikvači na izbornik Start (Classic Shell) +Menu.UnpinStartCs = Otkvači s izbornika Start (Classic Shell) +Menu.MonitorOff = Isključi prikaz +Menu.RemoveHighlight = Ukloni isticanje +Menu.Uninstall = &Deinstaliraj +Menu.UninstallTitle = Deinstaliraj +Menu.UninstallPrompt = Jeste li sigurni da želite deinstalirati %s iz računala? +Search.CategorySettings = Postavke +Search.CategoryPCSettings = Postavke PC-ja +Search.CategoryPrograms = Programi +Search.CategoryDocuments = Dokumenti +Search.CategoryMusic = Glazba +Search.CategoryPictures = Slike +Search.CategoryVideos = Videozapisi +Search.CategoryFiles = Datoteke +Search.CategoryInternet = Internet +JumpList.Recent = Nedavni +JumpList.Frequent = Učestali +JumpList.Tasks = Zadaci +JumpList.Pinned = Prikvačeni +JumpList.Pin = &Prikvači na ovaj popis +JumpList.Unpin = &Otkvači s ovog popisa +JumpList.Remove = &Ukloni s ovog popisa +JumpList.PinTip = Prikvači na ovaj popis +JumpList.UnpinTip = Otkvači s ovog popisa + + +[hu-HU] - Hungarian (Hungary) +Menu.Programs = &Programok +Menu.Apps = Alkalmazások +Menu.AllPrograms = Minden program +Menu.Back = Vissza +Menu.Favorites = K&edvencek +Menu.Documents = &Dokumentumok +Menu.Settings = &Beállítások +Menu.Search = &Keresés +Menu.SearchBox = Keresés +Menu.SearchPrograms = Keresés programokban és fájlokban +Menu.SearchInternet = Keresés az interneten +Menu.Searching = Keresés... +Menu.NoMatch = Nincs a keresésnek megfelelő elem. +Menu.MoreResults = További eredmények +Menu.Help = &Súgó és támogatás +Menu.Run = F&uttatás... +Menu.Logoff = Ki&jelentkezés - %s... +Menu.SwitchUser = &Felhasználóváltás +Menu.Lock = &Zárolás +Menu.LogOffShort = &Kijelentkezés +Menu.Undock = &A számítógép dokkolásának megszüntetése +Menu.Disconnect = Kap&csolat bontása +Menu.ShutdownBox = &Leállítás... +Menu.Shutdown = &Leállítás +Menu.Restart = Új&raindítás +Menu.ShutdownUpdate = Frissítés és leállítás +Menu.RestartUpdate = Frissítés és újraindítás +Menu.Sleep = &Alvó állapot +Menu.Hibernate = &Hibernálás +Menu.ControlPanel = &Vezérlőpult +Menu.PCSettings = Gépház +Menu.Security = Windows rendszerbiztonság +Menu.Network = &Hálózati kapcsolatok +Menu.Printers = &Nyomtatók +Menu.Taskbar = &Tálca és Start menü +Menu.SearchFiles = &Fájlok és mappák... +Menu.SearchPrinter = &Nyomtatók +Menu.SearchComputers = &Számítógépek +Menu.UserFilesTip = A Dokumentumok, a Képek és a Zene mappát, illetve egyéb saját fájljait tartalmazó mappák találhatók itt. +Menu.UserDocumentsTip = Levelek, jelentések és egyéb dokumentumok. +Menu.UserPicturesTip = Digitális fényképek, képek és grafikai fájlok. +Menu.UserMusicTip = Zenéket és egyéb audiofájlokat tartalmaz. +Menu.UserVideosTip = Filmeket és egyéb videofájlokat tartalmaz. +Menu.NetworkTip = A számítógépen már létező hálózati kapcsolatok megjelenítése, segítségével új kapcsolatok hozhatók létre +Menu.PrintersTip = Helyi és hálózati nyomtatók hozzáadása, eltávolítása és konfigurálása. +Menu.TaskbarTip = A Start menü és a tálca elemei megjelenésének testreszabása - pl. milyen típusú elemek jelenjenek meg, és hogyan. +Menu.ControlPanelTip = Beállítások módosítása és a számítógép működésének testreszabása. +Menu.DocumentsLibTip = Levelek, jelentések, feljegyzések és egyéb dokumentumok megnyitása. +Menu.MusicLibTip = Zeneszámok és egyéb hangfájlok lejátszása. +Menu.PicturesLibTip = Digitális képek megjelenítése és rendezése. +Menu.VideosLibTip = Saját készítésű filmek és egyéb digitális videók lejátszása. +Menu.RecordingsLibTip = A számítógépre felvett televízióműsorok lejátszása. +Menu.DownloadTip = Internetes letöltések és kedvenc webhelyekre mutató hivatkozások keresése. +Menu.HomegroupTip = Az otthoni csoport más felhasználói által megosztott könyvtárak és mappák elérése. +Menu.RunTip = Program, mappa, dokumentum vagy webhely megnyitása. +Menu.HelpTip = Súgótémakörök, oktatóanyagok, hibaelhárító anyagok és más támogatási szolgáltatások keresése. +Menu.ProgramsTip = A telepített programok listájának megjelenítése. +Menu.SearchFilesTip = Dokumentumok, zenék, képek, levelek és más elemek keresése. +Menu.GamesTip = A számítógépen található játékok elindítása és kezelése. +Menu.SecurityTip = A Windows biztonsági beállításainak megnyitása a jelszó módosítása, felhasználóváltás vagy a Feladatkezelő indítása céljából. +Menu.SearchComputersTip = Számítógépek keresése a hálózaton +Menu.SearchPrintersTip = Nyomtatók keresése +Menu.AdminToolsTip = Felügyeleti beállítások konfigurálása. +Menu.ShutdownTip = Minden futó program bezárása, a Windows leállítása, majd a számítógép kikapcsolása. +Menu.RestartTip = Minden futó program bezárása, a Windows leállítása, majd a Windows rendszer újraindítása. +Menu.SleepTip = Megőrzi a munkamenetet a memóriában, és kis energiafogyasztású állapotba helyezi a számítógépet, hogy gyorsan lehessen folytatni a munkát. +Menu.HibernateTip = A munkamenet mentése és a számítógép kikapcsolása. A számítógép bekapcsolásakor a Windows visszaállítja a munkamenetet. +Menu.LogOffTip = A programok bezárása és kijelentkezés. +Menu.DisconnectTip = A munkamenet leválasztása. Ismét csatlakozhat ehhez a munkamenethez, ha újra bejelentkezik. +Menu.LockTip = A számítógép zárolása. +Menu.UndockTip = A laptop vagy notebook számítógép dokkolásának megszüntetése. +Menu.SwitchUserTip = Felhasználóváltás a programok bezárása nélkül. +Menu.Empty = (Üres) +Menu.Features = Programok és szolgáltatások +Menu.FeaturesTip = A számítógép programjainak eltávolítása vagy módosítása. +Menu.SearchPeople = &Személyek... +Menu.SortByName = &Név szerinti rendezés +Menu.Open = &Megnyitás +Menu.OpenAll = M&egnyitás - All Users +Menu.Explore = T&allózás +Menu.ExploreAll = Ta&llózás - All Users +Menu.MenuSettings = Beállítások +Menu.MenuHelp = Súgó +Menu.MenuExit = Kilépés +Menu.LogoffTitle = Kijelentkezés a Windowsból +Menu.LogoffPrompt = Biztosan kijelentkezik? +Menu.LogoffYes = &Kijelentkezés +Menu.LogoffNo = &Nem +Menu.RenameTitle = Átnevezés +Menu.RenamePrompt = &Új név: +Menu.RenameOK = OK +Menu.RenameCancel = Mégse +Menu.Organize = A Start menü rendezése +Menu.Expand = K&ibontás +Menu.Collapse = Össze&csukás +Menu.NewFolder = Új mappa +Menu.NewShortcut = Új parancsikon +Menu.AutoArrange = Automatikus &elrendezés +Menu.ActionOpen = Megnyitás +Menu.ActionClose = Bezárás +Menu.ActionExecute = Végrehajtás +Menu.RemoveList = Eltá&volítás a listáról +Menu.RemoveAll = &Legutóbbi elemek listájának törlése +Menu.Explorer = Windows Intéző +Menu.Start = Start +Menu.StartScreen = Kezdőképernyő +Menu.StartMenu = Start menü (Windows) +Menu.PinStart = Rögzítés a Start menün +Menu.PinStartCs = Rögzítés a Start menün (Classic Shell) +Menu.UnpinStartCs = Rögzítés feloldása a Start menün (Classic Shell) +Menu.MonitorOff = Kijelző kikapcsolása +Menu.RemoveHighlight = Kiemelés eltávolítása +Menu.Uninstall = Eltá&volítás +Menu.UninstallTitle = Eltávolítás +Menu.UninstallPrompt = Biztosan el kívánja távolítani a következőt: %s? +Search.CategorySettings = Beállítások +Search.CategoryPCSettings = Gépház +Search.CategoryPrograms = Programs +Search.CategoryDocuments = Dokumentumok +Search.CategoryMusic = Zene +Search.CategoryPictures = Képek +Search.CategoryVideos = Videók +Search.CategoryFiles = Fájl +Search.CategoryInternet = Internet +JumpList.Recent = Legutóbbi +JumpList.Frequent = Gyakori +JumpList.Tasks = Feladatok +JumpList.Pinned = Rögzített +JumpList.Pin = &Rögzítés ebbe a listába +JumpList.Unpin = Rögzítés &feloldása ebben a listában +JumpList.Remove = Eltá&volítás a listáról +JumpList.PinTip = Rögzítés ebbe a listába +JumpList.UnpinTip = Rögzítés feloldása ebben a listában + + +[is-IS] - Icelandic (Iceland) +Menu.ClassicSettings = Classic Start &Menu +Menu.SettingsTip = Stillingar fyrir Classic Start Menu +Menu.Programs = &Forrit +Menu.Apps = Snjallforrit +Menu.AllPrograms = Öll forrit +Menu.Back = Til baka +Menu.Favorites = &Eftirlæti +Menu.Documents = &Skjöl +Menu.Settings = S&tillingar +Menu.Search = &Leita +Menu.SearchBox = Leita +Menu.SearchPrograms = Leita í forritum og skrám +Menu.SearchInternet = Leita á vefnum +Menu.Searching = Leita... +Menu.NoMatch = Engin atriði samsvara leitinni. +Menu.MoreResults = Sjá fleiri niðurstöður +Menu.Help = &Hjálp og stuðningur +Menu.Run = &Keyra... +Menu.Logoff = Sk&rá út %s... +Menu.SwitchUser = &Skipta um notanda +Menu.Lock = &Læsa +Menu.LogOffShort = Sk&rá út +Menu.Undock = A&ftengja tölvuna +Menu.Disconnect = Afteng&jast +Menu.ShutdownBox = &Ganga frá... +Menu.Shutdown = &Ganga frá +Menu.Restart = &Endurræsa +Menu.ShutdownUpdate = Uppfæra og ganga frá +Menu.RestartUpdate = Uppfæra og endurræsa +Menu.Sleep = &Hvíldarstaða +Menu.Hibernate = Í &dvala +Menu.ControlPanel = Stjórn&borð +Menu.PCSettings = PC stillingar +Menu.Security = Windows öryggi +Menu.Network = &Nettengingar +Menu.Printers = &Prentarar +Menu.Taskbar = &Verkstika og ræsivalmynd +Menu.SearchFiles = Að &skrám eða möppum... +Menu.SearchPrinter = Að &prentara +Menu.SearchComputers = Að &tölvum +Menu.UserFilesTip = Inniheldur möppur fyrir skjöl, myndir, tónlist, og aðrar skrár sem tilheyra þér. +Menu.UserDocumentsTip = Inniheldur bréf, skýrslur, og önnur skjöl og skrár. +Menu.UserPicturesTip = Inniheldur stafrænar ljósmyndir, myndir, og grafískar skrár. +Menu.UserMusicTip = Inniheldur tónlist og aðrar hljóðskrár. +Menu.UserVideosTip = Inniheldur kvikmyndir og aðrar myndbandaskrár. +Menu.NetworkTip = Sýnir tiltækar nettengingar á þessari tölvu og hjálpar þér að búa til nýjar +Menu.PrintersTip = Bæta við, fjarlægja, og grunnstilla staðbundna og samnýtta prentara. +Menu.TaskbarTip = Sérstilla ræsivalmyndina og verkstikuna, svo sem tegundir atriða til að birta og hvernig þau eiga að birtast. +Menu.ControlPanelTip = Breyta stillingum og sérstilla virkni tölvunnar þinnar. +Menu.DocumentsLibTip = Nálgast bréf, skýrslur, minnispunkta, og annars konar skjöl. +Menu.MusicLibTip = Spila tónlist og aðrar hljóðskrár. +Menu.PicturesLibTip = Skoða og raða stafrænum ljósmyndum. +Menu.VideosLibTip = Horfa á heimatilbúnar kvikmyndir og önnur stafræn myndbönd. +Menu.RecordingsLibTip = Horfa á sjónvarpsþáttaupptökur á tölvunni þinni. +Menu.DownloadTip = Finna vefniðurhöl og vefföng eftirlætis vefsvæða. +Menu.HomegroupTip = Nálgast forritasöfn og möppur samnýttar af öðru fólki í heimahópnum þínum. +Menu.RunTip = Opnar forrit, möppu, skjal, eða vefsvæði. +Menu.HelpTip = Finna hjálparefni, kennslu, bilanagreiningu, og aðrar stuðningsþjónustur. +Menu.ProgramsTip = Opnar lista yfir forritin þín. +Menu.SearchFilesTip = Leita að skjölum, tónlist, myndum, tölvupósti og fleiru. +Menu.GamesTip = Spila og stjórna leikjum á tölvunni þinni. +Menu.SecurityTip = Ræsa Windows öryggi til að breyta lykilorði, skipta um notanda, eða ræsa verkstjórnun. +Menu.SearchComputersTip = Leita að tölvum á netinu +Menu.SearchPrintersTip = Leita að prentara +Menu.AdminToolsTip = Grunnstilla stjórnunarstillingar fyrir tölvuna þína. +Menu.ShutdownTip = Lokar öllum opnum forritum, gengur frá Windows, og slekkur svo á tölvunni þinni. +Menu.RestartTip = Lokar öllum opnum forritum, gengur frá Windows, og ræsir síðan Windows að nýju. +Menu.SleepTip = Geymir innskráningu þína í minni og setur tölvuna í orkusparnaðarstöðu svo þú getir snögglega byrjað aftur að vinna. +Menu.HibernateTip = Vistar innskráningu þína og slekkur á tölvunni. Þegar þú kveikir á tölvunni, sækir Windows innskráninguna þína aftur. +Menu.LogOffTip = Loka forritum og skrá út. +Menu.DisconnectTip = Aftengir innskráningu þína. Þú getur tengst þessari innskráningu aftur með því að skrá inn að nýju. +Menu.LockTip = Læsa þessari tölvu. +Menu.UndockTip = Fjarlægir fartölvuna þína úr tengikví. +Menu.SwitchUserTip = Skipta milli notenda án þess að loka forritum. +Menu.Empty = (Tómt) +Menu.Features = Forrit og eiginleikar +Menu.FeaturesTip = Fjarlægja eða breyta forritum á tölvunni þinni. +Menu.SearchPeople = Að &fólki... +Menu.SortByName = Raða &eftir heiti +Menu.Open = &Opna +Menu.OpenAll = O&pna Allir notendur +Menu.Explore = Opna &möppu +Menu.ExploreAll = Opna m&öppu Allir notendur +Menu.MenuSettings = Stillingar +Menu.MenuHelp = Hjálp +Menu.MenuExit = Hætta +Menu.LogoffTitle = Skrá út úr Windows +Menu.LogoffPrompt = Ertu viss um að þú viljir skrá út? +Menu.LogoffYes = &Skrá út +Menu.LogoffNo = &Nei +Menu.RenameTitle = Endurnefna +Menu.RenamePrompt = &Nýtt heiti: +Menu.RenameOK = Í lagi +Menu.RenameCancel = Hætta við +Menu.Organize = Sérstilla ræsivalmynd +Menu.Expand = Þenj&a út +Menu.Collapse = Dr&aga saman +Menu.NewFolder = Ný mappa +Menu.NewShortcut = Ný flýtileið +Menu.AutoArrange = R&aða sjálfkrafa +Menu.ActionOpen = Opna +Menu.ActionClose = Loka +Menu.ActionExecute = Keyra +Menu.RemoveList = &Fjarlægja &úr þessum lista +Menu.RemoveAll = Hreinsa &lista yfir nýlegt +Menu.Explorer = Skráarvafri +Menu.Start = Ræsa +Menu.StartScreen = Ræsiskjár +Menu.StartMenu = Ræsivalmynd (Windows) +Menu.PinStart = Festa við ræsivalmynd +Menu.PinStartCs = Festa við ræsivalmynd (Classic Shell) +Menu.UnpinStartCs = Losa af ræsivalmynd (Classic Shell) +Menu.MonitorOff = Slökkva á skjánum +Menu.RemoveHighlight = Fjarlægja auðkenningu +Menu.Uninstall = Fjarlægja +Menu.UninstallTitle = Fjarlægja +Menu.UninstallPrompt = Ertu viss um að það eigi að fjarlægja %s? +Search.CategorySettings = Stillingar +Search.CategoryPCSettings = Sérstillingar tölvunnar +Search.CategoryPrograms = Forrit +Search.CategoryDocuments = Skjöl +Search.CategoryMusic = Tónlist +Search.CategoryPictures = Myndir +Search.CategoryVideos = Myndbönd +Search.CategoryFiles = Skrár +Search.CategoryInternet = Vefurinn +JumpList.Recent = Nýlegt +JumpList.Frequent = Algengt +JumpList.Tasks = Verk +JumpList.Pinned = Fest +JumpList.Pin = Festa v&ið þennan lista +JumpList.Unpin = L&osa af þessum lista +JumpList.Remove = &Fjarlægja úr þessum lista +JumpList.PinTip = Festa við þennan lista +JumpList.UnpinTip = Losa af þessum lista + + +[it-IT] - Italian (Italy) +Menu.Programs = &Programmi +Menu.Apps = App +Menu.AllPrograms = Tutti i programmi +Menu.Back = Indietro +Menu.Favorites = Pre&feriti +Menu.Documents = &Dati recenti +Menu.Settings = &Impostazioni +Menu.Search = Ce&rca +Menu.SearchBox = Cerca +Menu.SearchPrograms = Cerca programmi e file +Menu.SearchInternet = Cerca in Internet +Menu.Searching = Ricerca in corso... +Menu.NoMatch = Nessun elemento corrisponde ai criteri di ricerca. +Menu.MoreResults = Ulteriori risultati +Menu.Help = &Guida e supporto tecnico +Menu.Run = &Esegui... +Menu.Logoff = Disc&onnetti %s... +Menu.SwitchUser = &Cambia utente +Menu.Lock = Bl&occa +Menu.LogOffShort = &Disconnetti +Menu.Undock = Disinseri&sci computer +Menu.Disconnect = Disco&nnetti +Menu.ShutdownBox = &Chiudi sessione... +Menu.Shutdown = &Arresta il sistema +Menu.Restart = &Riavvia il sistema +Menu.ShutdownUpdate = Aggiorna e arresta +Menu.RestartUpdate = Aggiorna e riavvia +Menu.Sleep = &Sospendi +Menu.Hibernate = Metti in &ibernazione +Menu.ControlPanel = &Pannello di controllo +Menu.PCSettings = Impostazioni PC +Menu.Security = Protezione di Windows +Menu.Network = Connessioni di &rete +Menu.Printers = &Stampanti +Menu.Taskbar = &Barra delle applicazioni e menu Start +Menu.SearchFiles = &File o cartelle... +Menu.SearchPrinter = &Per stampante +Menu.SearchComputers = Per &Computer +Menu.UserFilesTip = Contiene cartelle per documenti, immagini, musica e altri file dell'utente. +Menu.UserDocumentsTip = Contiene lettere, rapporti e altri documenti e file. +Menu.UserPicturesTip = Contiene foto digitali, immagini e file di grafica. +Menu.UserMusicTip = Contiene file musicali e audio. +Menu.UserVideosTip = Contiene filmati e altri file video. +Menu.NetworkTip = Visualizza le connessioni di rete del computer e consente di crearne nuove +Menu.PrintersTip = Aggiunge, rimuove e configura stampanti locali e di rete. +Menu.TaskbarTip = Personalizza la visualizzazione degli elementi nel menu Start, barra delle applicazioni e area di notifica. +Menu.ControlPanelTip = Modificare le impostazioni e personalizzare la funzionalità del computer. +Menu.DocumentsLibTip = Accedere a lettere, rapporti, note e ad altri tipi di documenti. +Menu.MusicLibTip = Consente di riprodurre musica e altri file audio. +Menu.PicturesLibTip = Consente di visualizzare e organizzare immagini. +Menu.VideosLibTip = Consente di vedere i propri filmati e altri video digitali. +Menu.RecordingsLibTip = Consente di assistere ai programmi TV registrati nel computer. +Menu.DownloadTip = Consente di trovare i collegamenti ai siti Web preferiti per il download. +Menu.HomegroupTip = Consente di accedere a raccolte e cartelle condivise da altri utenti nel gruppo home. +Menu.RunTip = Consente di aprire un programma, una cartella, un documento o un sito. +Menu.HelpTip = Trovare argomenti della Guida, esercitazioni, risoluzione problemi, e altri servizi di supporto tecnico. +Menu.ProgramsTip = Apre l'elenco dei programmi. +Menu.SearchFilesTip = Cercare documenti, musica, immagini, posta elettronica e altro. +Menu.GamesTip = Consente di giocare e gestire i giochi installati nel computer. +Menu.SecurityTip = Avvia le opzioni di Sicurezza di Windows per modificare la password, cambiare utente o avviare Gestione attività. +Menu.SearchComputersTip = Cerca computer sulla rete +Menu.SearchPrintersTip = Cerca stampante +Menu.AdminToolsTip = Configura le impostazioni amministrative del computer. +Menu.ShutdownTip = Chiude tutti i programmi aperti, arresta Windows e spegne il computer. +Menu.RestartTip = Chiude tutti i programmi aperti e riavvia Windows. +Menu.SleepTip = Mantiene la sessione in memoria e imposta la modalità basso consumo che consente di riprendere rapidamente il lavoro. +Menu.HibernateTip = Salva la sessione e spegne il computer. Quando si riaccende il computer, la sessione verrà ripristinata. +Menu.LogOffTip = Chiude i programmi e disconnette l'utente. +Menu.DisconnectTip = Disconnette la sessione. È possibile riconnettersi a questa sessione al prossimo accesso. +Menu.LockTip = Blocca il computer. +Menu.UndockTip = Consente di rimuovere il computer portatile o il notebook dall'alloggiamento di espansione. +Menu.SwitchUserTip = Consente di cambiare utente senza chiudere i programmi. +Menu.Empty = (vuoto) +Menu.Features = Programmi e funzionalità +Menu.FeaturesTip = Disinstalla o modifica i programmi nel computer. +Menu.SearchPeople = &Contatti... +Menu.SortByName = Or&dina per nome +Menu.Open = &Apri +Menu.OpenAll = Apri &cartella Utenti +Menu.Explore = &Esplora +Menu.ExploreAll = Esplora cartella &Utenti +Menu.MenuSettings = Impostazioni +Menu.MenuHelp = Guida +Menu.MenuExit = Esci +Menu.LogoffTitle = Disconnessione da Windows +Menu.LogoffPrompt = Disconnettersi? +Menu.LogoffYes = &Disconnetti +Menu.LogoffNo = &No +Menu.RenameTitle = Rinomina +Menu.RenamePrompt = &Nuovo nome: +Menu.RenameOK = OK +Menu.RenameCancel = Annulla +Menu.Organize = Organizza menu Start +Menu.Expand = &Espandi +Menu.Collapse = Comp&rimi +Menu.NewFolder = Nuova cartella +Menu.NewShortcut = Nuovo collegamento +Menu.AutoArrange = &Disposizione automatica +Menu.ActionOpen = Apri +Menu.ActionClose = Chiudi +Menu.ActionExecute = Esegui +Menu.RemoveList = &Rimuovi da questo elenco +Menu.RemoveAll = Cancella elenco Ogge&tti recenti +Menu.Explorer = Esplora risorse +Menu.Start = Start +Menu.StartScreen = Schermata Start +Menu.StartMenu = Menu Start (Windows) +Menu.PinStart = Aggiungi al menu Start +Menu.PinStartCs = Aggiungi al menu Start (Classic Shell) +Menu.UnpinStartCs = Rimuovi dal menu Start (Classic Shell) +Menu.MonitorOff = Spegne lo schermo +Menu.RemoveHighlight = Rimuovi elemento di rilievo +Menu.Uninstall = &Disinstalla +Menu.UninstallTitle = Disinstalla +Menu.UninstallPrompt = Disinstallare %s? +Search.CategorySettings = Impostazioni +Search.CategoryPCSettings = Impostazioni PC +Search.CategoryPrograms = Programmi +Search.CategoryDocuments = Documenti +Search.CategoryMusic = Musica +Search.CategoryPictures = Immagini +Search.CategoryVideos = Video +Search.CategoryFiles = File +Search.CategoryInternet = Internet +JumpList.Recent = Recenti +JumpList.Frequent = Frequente +JumpList.Tasks = Attività +JumpList.Pinned = Bloccato +JumpList.Pin = Agg&iungi all'elenco +JumpList.Unpin = Rim&uovi dall'elenco +JumpList.Remove = &Rimuovi da questo elenco +JumpList.PinTip = Aggiungi all'elenco +JumpList.UnpinTip = Rimuovi dall'elenco + + +[ja-JP] - Japanese (Japan) +Menu.Programs = プログラム(&P) +Menu.Apps = アプリ +Menu.AllPrograms = すべてのプログラム +Menu.Back = 前に戻る +Menu.Favorites = お気に入り(&A) +Menu.Documents = 最近使ったファイル(&D) +Menu.Settings = 設定(&S) +Menu.Search = 検索(&C) +Menu.SearchBox = 検索 +Menu.SearchPrograms = プログラムとファイルの検索 +Menu.SearchInternet = インターネットの検索 +Menu.Searching = 検索しています... +Menu.NoMatch = 検索条件に一致する項目はありません。 +Menu.MoreResults = 検索結果の続きを表示 +Menu.Help = ヘルプとサポート(&H) +Menu.Run = ファイル名を指定して実行(&R)... +Menu.Logoff = %s のログオフ(&L)... +Menu.SwitchUser = ユーザーの切り替え(&W) +Menu.Lock = ロック(&O) +Menu.LogOffShort = ログオフ(&L) +Menu.Undock = コンピュータの装着解除(&E) +Menu.Disconnect = 切断(&I) +Menu.ShutdownBox = シャットダウン(&U)... +Menu.Shutdown = シャットダウン(&U) +Menu.Restart = 再起動(&R) +Menu.ShutdownUpdate = 更新してシャットダウン +Menu.RestartUpdate = 更新して再起動 +Menu.Sleep = スリープ(&S) +Menu.Hibernate = 休止状態(&H) +Menu.ControlPanel = コントロール パネル(&C) +Menu.PCSettings = PC 設定 +Menu.Security = Windows セキュリティ +Menu.Network = ネットワーク接続(&N) +Menu.Printers = プリンタ(&P) +Menu.Taskbar = タスク バーと [スタート] メニュー(&T) +Menu.SearchFiles = ファイルやフォルダ(&F)... +Menu.SearchPrinter = プリンタの検索(&P) +Menu.SearchComputers = コンピュータの検索(&C) +Menu.UserFilesTip = ユーザーが所有しているドキュメント、画像、音楽などのフォルダが含まれています。 +Menu.UserDocumentsTip = 手紙、レポート、およびそのほかのドキュメントやファイルが含まれます。 +Menu.UserPicturesTip = デジタル写真、イメージ、および画像ファイルが含まれます。 +Menu.UserMusicTip = 音楽およびそのほかのオーディオ ファイルが含まれます。 +Menu.UserVideosTip = ムービーおよびそのほかのビデオ ファイルが含まれます。 +Menu.NetworkTip = このコンピュータにあるネットワーク接続を表示し、新しい接続の作成をお手伝いします +Menu.PrintersTip = ローカルおよびネットワークのプリンタの追加、削除、および構成を行います。 +Menu.TaskbarTip = [スタート] メニューおよびタスク バーに表示される項目の種類や表示方法をカスタマイズします。 +Menu.ControlPanelTip = 設定を変更し、このコンピューターの機能をカスタマイズします。 +Menu.DocumentsLibTip = 手紙、レポート、メモなどのドキュメントにアクセスします。 +Menu.MusicLibTip = 音楽ファイルやオーディオ ファイルを再生します。 +Menu.PicturesLibTip = デジタル画像を表示および整理します。 +Menu.VideosLibTip = ホーム ビデオとその他のデジタル ビデオを視聴します。 +Menu.RecordingsLibTip = コンピューター上に録画されたテレビ番組を視聴します。 +Menu.DownloadTip = インターネット ダウンロードおよびお気に入りの Web サイトへのリンクを検索します。 +Menu.HomegroupTip = ホームグループ内の他のメンバーが共有するライブラリとフォルダーにアクセスします。 +Menu.RunTip = プログラム、フォルダー、ドキュメントまたは Web サイトを開きます。 +Menu.HelpTip = ヘルプのトピック、チュートリアル、トラブルシューティング、サポート サービスなどを検索します。 +Menu.ProgramsTip = プログラムの一覧を表示します。 +Menu.SearchFilesTip = ドキュメント、音楽ファイル、画像、電子メールなどを検索します。 +Menu.GamesTip = コンピューターにあるゲームのプレイと管理を行います。 +Menu.SecurityTip = Windows セキュリティ オプションを起動して [パスワードの変更]、[ユーザーの切り替え]、[タスク マネージャーの起動] を行います。 +Menu.SearchComputersTip = ネットワークのコンピューターを検索します +Menu.SearchPrintersTip = プリンターを検索します +Menu.AdminToolsTip = コンピューターの管理に関する設定を構成します。 +Menu.ShutdownTip = 開いているプログラムをすべて閉じて、Windows をシャットダウンしてからコンピューターの電源を切ります。 +Menu.RestartTip = 開いているプログラムをすべて閉じて、Windows をシャットダウンしてから、Windows を再起動します。 +Menu.SleepTip = すばやく作業を再開できるように、セッションをメモリに保持してコンピューターを低電力の状態にします。 +Menu.HibernateTip = セッションを保存してコンピューターの電源を切ります。コンピューターの電源を入れたときに、セッションは復元されます。 +Menu.LogOffTip = プログラムを閉じて、ログオフします。 +Menu.DisconnectTip = セッションを切断します。ログオンし直すと、このセッションに再接続できます。 +Menu.LockTip = このコンピューターをロックします。 +Menu.UndockTip = ドッキング ステーションからラップトップやノートブック コンピューターを取り外します。 +Menu.SwitchUserTip = プログラムを閉じずに、ユーザーを切り替えます。 +Menu.Empty = (なし) +Menu.Features = プログラムと機能 +Menu.FeaturesTip = コンピュータ上のプログラムをアンインストールまたは変更します。 +Menu.SearchPeople = 人(&P)... +Menu.SortByName = 名前順で並べ替え(&B) +Menu.Open = 開く(&O) +Menu.OpenAll = 開く - All Users(&P) +Menu.Explore = エクスプローラ(&E) +Menu.ExploreAll = エクスプローラ - All Users(&X) +Menu.MenuSettings = 設定 +Menu.MenuHelp = ヘルプ +Menu.MenuExit = 終了 +Menu.LogoffTitle = Windows のログオフ +Menu.LogoffPrompt = ログオフしますか? +Menu.LogoffYes = ログオフ(&L) +Menu.LogoffNo = いいえ(&N) +Menu.RenameTitle = 名前の変更 +Menu.RenamePrompt = 新しい名前(&N): +Menu.RenameOK = OK +Menu.RenameCancel = キャンセル +Menu.Organize = [スタート] メニューの管理 +Menu.Expand = 展開(&A) +Menu.Collapse = 折りたたみ(&A) +Menu.NewFolder = 新しいフォルダ +Menu.NewShortcut = 新しいショートカット +Menu.AutoArrange = 自動整列(&A) +Menu.ActionOpen = 開く +Menu.ActionClose = 閉じる +Menu.ActionExecute = 実行 +Menu.RemoveList = この一覧から削除(&F) +Menu.RemoveAll = 最近使った項目の一覧のクリア(&L) +Menu.Explorer = エクスプローラ +Menu.Start = スタート +Menu.StartScreen = スタート画面 +Menu.StartMenu = スタート メニュー (Windows) +Menu.PinStart = スタート メニューに表示する +Menu.PinStartCs = スタート メニューに表示する (Classic Shell) +Menu.UnpinStartCs = スタート メニューに表示しない (Classic Shell) +Menu.MonitorOff = 画面をオフにする +Menu.RemoveHighlight = ハイライトの削除 +Menu.Uninstall = アンインストール(&U) +Menu.UninstallTitle = アンインストール +Menu.UninstallPrompt = %s をアンインストールしますか? +Search.CategorySettings = 設定 +Search.CategoryPCSettings = PC 設定 +Search.CategoryPrograms = プログラム +Search.CategoryDocuments = ドキュメント +Search.CategoryMusic = ミュージック +Search.CategoryPictures = ピクチャ +Search.CategoryVideos = ビデオ +Search.CategoryFiles = ファイル +Search.CategoryInternet = インターネット +JumpList.Recent = 最近使ったもの +JumpList.Frequent = よく使うもの +JumpList.Tasks = タスク +JumpList.Pinned = いつも表示 +JumpList.Pin = いつも表示する(&I) +JumpList.Unpin = いつも表示するものから外す(&U) +JumpList.Remove = この一覧から削除(&F) +JumpList.PinTip = いつも表示する +JumpList.UnpinTip = いつも表示するものから外す + + +[ko-KR] - Korean (Korea) +Menu.Programs = 프로그램(&P) +Menu.Apps = 앱 +Menu.AllPrograms = 모든 프로그램 +Menu.Back = 뒤로 +Menu.Favorites = 즐겨찾기(&A) +Menu.Documents = 문서(&D) +Menu.Settings = 설정(&S) +Menu.Search = 검색(&C) +Menu.SearchBox = 검색 +Menu.SearchPrograms = 프로그램 및 파일 검색 +Menu.SearchInternet = 인터넷 검색 +Menu.Searching = 검색 중... +Menu.NoMatch = 일치하는 항목이 없습니다. +Menu.MoreResults = 자세한 결과 보기 +Menu.Help = 도움말 및 지원(&H) +Menu.Run = 실행(&R)... +Menu.Logoff = %s 로그오프(&L)... +Menu.SwitchUser = 사용자 전환(&W) +Menu.Lock = 잠금(&O) +Menu.LogOffShort = 로그오프(&L) +Menu.Undock = 컴퓨터 도킹 해제(&E) +Menu.Disconnect = 연결 끊기(&I) +Menu.ShutdownBox = 시스템 종료(&U)... +Menu.Shutdown = 시스템 종료(&U) +Menu.Restart = 다시 시작(&R) +Menu.ShutdownUpdate = 업데이트 및 종료 +Menu.RestartUpdate = 업데이트 및 다시 시작 +Menu.Sleep = 절전(&S) +Menu.Hibernate = 최대 절전 모드(&H) +Menu.ControlPanel = 제어판(&C) +Menu.PCSettings = PC 설정 +Menu.Security = Windows 보안 +Menu.Network = 네트워크 연결(&N) +Menu.Printers = 프린터(&P) +Menu.Taskbar = 작업 표시줄 및 시작 메뉴(&T) +Menu.SearchFiles = 파일 또는 폴더(&F)... +Menu.SearchPrinter = 프린터(&P) +Menu.SearchComputers = 컴퓨터(&C) +Menu.UserFilesTip = 사용자가 소유한 문서, 사진, 음악 및 기타 파일의 폴더가 있습니다. +Menu.UserDocumentsTip = 편지, 보고서, 기타 문서나 파일이 들어 있습니다. +Menu.UserPicturesTip = 디지털 사진, 이미지 및 그래픽 파일이 들어 있습니다. +Menu.UserMusicTip = 음악 및 기타 오디오 파일이 들어 있습니다. +Menu.UserVideosTip = 음악 및 기타 비디오 파일이 들어 있습니다. +Menu.NetworkTip = 이 컴퓨터의 기존 네트워크 연결을 표시하거나 새로 만드는 것을 도와줍니다. +Menu.PrintersTip = 로컬 및 네트워크 프린터를 추가, 제거, 구성합니다. +Menu.TaskbarTip = 표시되는 항목의 유형 및 표시 방법 등과 같은 시작 메뉴 및 작업 표시줄 설정을 사용자 지정합니다. +Menu.ControlPanelTip = 설정을 변경하고 컴퓨터의 기능을 사용자 지정합니다. +Menu.DocumentsLibTip = 편지, 보고서, 메모 및 기타 문서에 액세스합니다. +Menu.MusicLibTip = 음악 및 기타 오디오 파일을 재생합니다. +Menu.PicturesLibTip = 디지털 사진을 보고 정리합니다. +Menu.VideosLibTip = 홈 동영상 및 기타 디지털 비디오를 시청합니다. +Menu.RecordingsLibTip = 컴퓨터에 녹화된 TV 프로그램을 시청합니다. +Menu.DownloadTip = 인터넷 다운로드 및 즐겨 찾는 웹 사이트에 대한 링크를 찾습니다. +Menu.HomegroupTip = 홈 그룹의 다른 사용자가 공유한 라이브러리 및 폴더에 액세스합니다. +Menu.RunTip = 프로그램, 폴더, 문서 또는 웹 사이트를 엽니다. +Menu.HelpTip = 도움말 항목, 자습서, 문제 해결 및 기타 지원 서비스를 찾습니다. +Menu.ProgramsTip = 프로그램의 목록을 표시합니다. +Menu.SearchFilesTip = 문서, 음악, 사진, 전자 메일 등을 검색합니다. +Menu.GamesTip = 컴퓨터에 있는 게임을 실행 및 관리합니다. +Menu.SecurityTip = 암호를 변경하거나, 사용자를 전환하거나, 작업 관리자를 시작하려면 Windows 보안 옵션을 시작합니다. +Menu.SearchComputersTip = 네트워크에서 컴퓨터 찾기 +Menu.SearchPrintersTip = 프린터 찾기 +Menu.AdminToolsTip = 사용자 컴퓨터의 관리 설정을 구성합니다. +Menu.ShutdownTip = 열려 있는 프로그램을 모두 닫고 Windows를 종료한 다음 컴퓨터를 끕니다. +Menu.RestartTip = 열려 있는 프로그램을 모두 닫고 Windows를 종료한 다음 Windows를 다시 시작합니다. +Menu.SleepTip = 작업을 빠르게 다시 시작할 수 있도록 사용자 세션을 메모리에 저장하고 컴퓨터를 절전 상태로 전환합니다. +Menu.HibernateTip = 사용자 세션을 저장하고 컴퓨터를 끕니다. 컴퓨터를 켜면 Windows에 사용자 세션이 복원됩니다. +Menu.LogOffTip = 프로그램을 닫고 로그오프합니다. +Menu.DisconnectTip = 세션 연결을 끊습니다. 다시 로그온할 때 이 세션에 연결할 수 있습니다. +Menu.LockTip = 이 컴퓨터를 잠급니다. +Menu.UndockTip = 도킹 스테이션에서 랩톱 또는 노트북 컴퓨터를 제거합니다. +Menu.SwitchUserTip = 프로그램을 닫지 않고 사용자를 전환합니다. +Menu.Empty = (비어 있음) +Menu.Features = 프로그램 및 기능 +Menu.FeaturesTip = 컴퓨터의 프로그램을 제거하거나 변경합니다. +Menu.SearchPeople = 사람 찾기(&P)... +Menu.SortByName = 이름순 정렬(&B) +Menu.Open = 열기(&O) +Menu.OpenAll = 열기 - All Users(&P) +Menu.Explore = 탐색(&E) +Menu.ExploreAll = 탐색 - All Users(&X) +Menu.MenuSettings = 설정 +Menu.MenuHelp = 도움말 +Menu.MenuExit = 끝내기 +Menu.LogoffTitle = Windows 로그오프 +Menu.LogoffPrompt = 로그오프하시겠습니까? +Menu.LogoffYes = 로그오프(&L) +Menu.LogoffNo = 아니요(&N) +Menu.RenameTitle = 이름 바꾸기 +Menu.RenamePrompt = 새 이름(&N): +Menu.RenameOK = 확인 +Menu.RenameCancel = 취소 +Menu.Organize = 시작 메뉴 구성 +Menu.Expand = 확장(&A) +Menu.Collapse = 축소(&A) +Menu.NewFolder = 새 폴더 +Menu.NewShortcut = 새 바로 가기 +Menu.AutoArrange = 자동 정렬(&A) +Menu.ActionOpen = 열기 +Menu.ActionClose = 닫기 +Menu.ActionExecute = 실행 +Menu.RemoveList = 이 목록에서 제거(&F) +Menu.RemoveAll = 최근 항목 목록 지우기(&L) +Menu.Explorer = Windows 탐색기 +Menu.Start = 시작 +Menu.StartScreen = 시작 화면 +Menu.StartMenu = 시작 메뉴 (Windows) +Menu.PinStart = 시작 메뉴에 고정 +Menu.PinStartCs = 시작 메뉴에 고정 (Classic Shell) +Menu.UnpinStartCs = 시작 메뉴에서 제거 (Classic Shell) +Menu.MonitorOff = 디스플레이 끄기 +Menu.RemoveHighlight = 추천 취소 +Menu.Uninstall = 제거(&U) +Menu.UninstallTitle = 제거 +Menu.UninstallPrompt = %s 설치를 제거하시겠습니까? +Search.CategorySettings = 설정 +Search.CategoryPCSettings = PC 설정 +Search.CategoryPrograms = 프로그램 +Search.CategoryDocuments = 문서 +Search.CategoryMusic = 음악 +Search.CategoryPictures = 사진 +Search.CategoryVideos = 비디오 +Search.CategoryFiles = 파일 +Search.CategoryInternet = 인터넷 +JumpList.Recent = 최근 항목 +JumpList.Frequent = 자주 사용하는 항목 +JumpList.Tasks = 작업 +JumpList.Pinned = 고정됨 +JumpList.Pin = 이 목록에 고정(&I) +JumpList.Unpin = 이 목록에서 제거(&U) +JumpList.Remove = 이 목록에서 제거(&F) +JumpList.PinTip = 이 목록에 고정 +JumpList.UnpinTip = 이 목록에서 제거 + + +[lt-LT] - Lithuanian (Lithuania) +Menu.Programs = &Programos +Menu.Apps = Programėlės +Menu.AllPrograms = Visos programos +Menu.Back = Atgal +Menu.Favorites = P&arankiniai +Menu.Documents = &Dokumentai +Menu.Settings = Para&metrai +Menu.Search = I&eškoti +Menu.SearchBox = Ieškoti +Menu.SearchPrograms = Ieškoti tarp programų ir failų +Menu.SearchInternet = Ieškoti internete +Menu.Searching = Ieškoma... +Menu.NoMatch = Nėra iešką atitinkančių elementų. +Menu.MoreResults = Rodyti daugiau rezultatų +Menu.Help = &Žinynas ir palaikymas +Menu.Run = &Vykdyti... +Menu.Logoff = I&šeiti %s... +Menu.SwitchUser = Perjungti &vartotoją +Menu.Lock = Už&rakinti +Menu.LogOffShort = &Išeiti +Menu.Undock = Kompi&uterį atjungti nuo doko +Menu.Disconnect = A&tsijungti +Menu.ShutdownBox = Išjun>i... +Menu.Shutdown = &Baigti darbą +Menu.Restart = &Paleisti iš naujo +Menu.ShutdownUpdate = Naujinti ir išjungti +Menu.RestartUpdate = Naujinti ir paleisti iš naujo +Menu.Sleep = &Miego būsena +Menu.Hibernate = &Užmigdyti +Menu.ControlPanel = &Valdymo skydas +Menu.PCSettings = PC parametrai +Menu.Security = Windows sauga +Menu.Network = &Tinklo ryšiai +Menu.Printers = &Spausdintuvai +Menu.Taskbar = &Užduočių juosta ir meniu Pradėti +Menu.SearchFiles = Fa&ilams ir aplankams... +Menu.SearchPrinter = S&pausdintuvui +Menu.SearchComputers = &Kompiuteriams +Menu.UserFilesTip = Čia yra aplankai, skirti Dokumentams, Paveikslėliams, Muzikai ir kitoms jums priklausantiems failams. +Menu.UserDocumentsTip = Yra laiškų, ataskaitų ir kitų dokumentų, bei failų. +Menu.UserPicturesTip = Yra skaitmeninių nuotraukų, vaizdų ir grafinių failų. +Menu.UserMusicTip = Yra muzikos ir kitų garso failų. +Menu.UserVideosTip = Yra filmų ir kitų vaizdo failų. +Menu.NetworkTip = Rodomi esantys tinklo ryšiai kompiuteryje ir padedama kurti naujus +Menu.PrintersTip = Įtraukti, šalinti ir konfigūruoti vietinius ir tinklo spausdintuvus. +Menu.TaskbarTip = Tinkinkite meniu Pradėti ir užduočių juostą, pvz., rodyti skirtų elementų tipus ir jų išvaizdą. +Menu.ControlPanelTip = Keiskite parametrus ir tinkinkite savo kompiuterio funkcionalumą. +Menu.DocumentsLibTip = Pasiekite laiškus, ataskaitas, pastabas ir kitų tipų dokumentus. +Menu.MusicLibTip = Leiskite muzikos įrašus ir kitus garso failus. +Menu.PicturesLibTip = Peržiūrėkite ir tvarkykite skaitmeninius paveikslėlius. +Menu.VideosLibTip = Žiūrėkite namų kinus ir kitus skaitmeninius vaizdo įrašus. +Menu.RecordingsLibTip = Žiūrėkite TV programas, įrašytas jūsų kompiuteryje. +Menu.DownloadTip = Ieškokite siūlomų atsisiųsti failų internete ir nuorodų į mėgstamas svetaines. +Menu.HomegroupTip = Pasiekite bibliotekas ir aplankus, kuriuos bendrina kiti jūsų namų grupės nariai. +Menu.RunTip = Atidaro programą, aplanką, dokumentą ar svetainę. +Menu.HelpTip = Ieškokite Žinyno temų, vadovėlių, trikčių šalinimo ir kitų palaikymo paslaugų. +Menu.ProgramsTip = Atidaro programų sąrašą. +Menu.SearchFilesTip = Ieškokite dokumentų, muzikos įrašų, paveikslėlių, el. pašto ir t. t. +Menu.GamesTip = Paleiskite ir valdykite žaidimus kompiuteryje. +Menu.SecurityTip = Paleiskite Windows saugos parinktis, kad pakeistumėte slaptažodį, perjungtumėte vartotoją arba paleistumėte užduočių tvarkytuvą. +Menu.SearchComputersTip = Tinkle ieškoti kompiuterių +Menu.SearchPrintersTip = Ieškoti spausdintuvo +Menu.AdminToolsTip = Konfigūruokite kompiuterio administracinius parametrus. +Menu.ShutdownTip = Uždaro visas atidarytas programas, baigia darbą su Windows ir išjungia kompiuterį. +Menu.RestartTip = Uždaro visas atidarytas programas, Windows ir dar kartą paleidžia Windows. +Menu.SleepTip = Palieka seansą atmintyje ir perjungia kompiuterį veikti eikvojant mažai energijos, kad galėtumėte greitai tęsti darbą. +Menu.HibernateTip = Įrašo seansą ir išjungia kompiuterį. Įjungus kompiuterį, Windows atkuria seansą. +Menu.LogOffTip = Uždaro programas ir išeina. +Menu.DisconnectTip = Atjungiamas seansas. Pakartotinai prisijungti prie šio seanso galėsite dar kartą įėję. +Menu.LockTip = Užrakina šį kompiuterį. +Menu.UndockTip = Iš doko šalinamas nešiojamasis kompiuteris. +Menu.SwitchUserTip = Pakeičia vartotojus neuždarant programų. +Menu.Empty = (Tuščia) +Menu.Features = Programos ir funkcijos +Menu.FeaturesTip = Pašalinkite arba keiskite kompiuterio programas. +Menu.SearchPeople = &Asmenims... +Menu.SortByName = &Rūšiuoti pagal vardus +Menu.Open = &Atidaryti +Menu.OpenAll = A&tidaryti aplanką Visi vartotojai +Menu.Explore = Naršyt&i +Menu.ExploreAll = Na&ršyti visus vartotojus +Menu.MenuSettings = Parametrai +Menu.MenuHelp = Žinynas +Menu.MenuExit = Išeiti +Menu.LogoffTitle = Išeiti iš Windows +Menu.LogoffPrompt = Ar tikrai norite išeiti? +Menu.LogoffYes = I&šeiti +Menu.LogoffNo = &Ne +Menu.RenameTitle = Pervardyti +Menu.RenamePrompt = Naujas &pavadinimas: +Menu.RenameOK = Gerai +Menu.RenameCancel = Atšaukti +Menu.Organize = Tvarkyti pradžios meniu +Menu.Expand = P&lėsti +Menu.Collapse = Su&traukti +Menu.NewFolder = Naujas aplankas +Menu.NewShortcut = Nauja nuoroda +Menu.AutoArrange = Autom&atinis išdėstymas +Menu.ActionOpen = Atidaryti +Menu.ActionClose = Uždaryti +Menu.ActionExecute = Vykdyti +Menu.RemoveList = Šal&inti iš šio sąrašo +Menu.RemoveAll = &Valyti naujausių elementų sąrašą +Menu.Explorer = Windows naršyklė +Menu.Start = Pradėti +Menu.StartScreen = Pradžios ekranas +Menu.StartMenu = Meniu Pradėti (Windows) +Menu.PinStart = Padaryti prieinamą meniu Pradėti +Menu.PinStartCs = Padaryti prieinamą meniu Pradėti (Classic Shell) +Menu.UnpinStartCs = Padaryti neprieinamą meniu Pradėti (Classic Shell) +Menu.MonitorOff = Išjungti ekraną +Menu.RemoveHighlight = Šalinti paryškinimą +Menu.Uninstall = &Pašalinti +Menu.UninstallTitle = Pašalinti +Menu.UninstallPrompt = Ar tikrai norite pašalinti %s? +Search.CategorySettings = Parametrai +Search.CategoryPCSettings = PC parametrai +Search.CategoryPrograms = Programos +Search.CategoryDocuments = Dokumentai +Search.CategoryMusic = Muzika +Search.CategoryPictures = Paveikslėliai +Search.CategoryVideos = Vaizdo įrašai +Search.CategoryFiles = Failai +Search.CategoryInternet = Internetas +JumpList.Recent = Paskutiniai +JumpList.Frequent = Dažniausi +JumpList.Tasks = Užduotys +JumpList.Pinned = Susegta +JumpList.Pin = Į&traukti į šį sąrašą +JumpList.Unpin = P&ašalinti iš šio sąrašo +JumpList.Remove = Pašal&inti iš šio sąrašo +JumpList.PinTip = Įtraukti į šį sąrašą +JumpList.UnpinTip = Pašalinti iš šio sąrašo + + +[lv-LV] - Latvian (Latvia) +Menu.Programs = Pro&grammas +Menu.Apps = Programmas +Menu.AllPrograms = Visas programmas +Menu.Back = Atpakaļ +Menu.Favorites = Mana i&zlase +Menu.Documents = &Dokumenti +Menu.Settings = &Iestatījumi +Menu.Search = &Meklēt +Menu.SearchBox = Meklēt +Menu.SearchPrograms = Meklēt programmas un failus +Menu.SearchInternet = Meklēt internetā +Menu.Searching = Notiek meklēšana... +Menu.NoMatch = Nav vienumu, kas atbilstu meklēšanas kritērijiem. +Menu.MoreResults = Skatīt citus rezultātus +Menu.Help = Pa&līdzība un atbalsts +Menu.Run = Iz&pildīt... +Menu.Logoff = &Atteikties ar vārdu %s... +Menu.SwitchUser = Pār&slēgt lietotāju +Menu.Lock = Ai&zslēgt +Menu.LogOffShort = &Atteikties +Menu.Undock = Atdokot dat&oru +Menu.Disconnect = At&vienoties +Menu.ShutdownBox = &Beidzēt... +Menu.Shutdown = &Beidzēšana +Menu.Restart = &Restartēšana +Menu.ShutdownUpdate = Atjaunināt un izslēgt +Menu.RestartUpdate = Atjaunināt un restartēt +Menu.Sleep = &Miega režīms +Menu.Hibernate = &Hibernācija +Menu.ControlPanel = Vadības &panelis +Menu.PCSettings = Datora iestatījumi +Menu.Security = Windows drošība +Menu.Network = &Tīkla savienojumi +Menu.Printers = P&rinteri +Menu.Taskbar = &Uzdevumjosla un izvēlne Sākt +Menu.SearchFiles = &Failus vai mapes... +Menu.SearchPrinter = &Printeri +Menu.SearchComputers = &Datorus +Menu.UserFilesTip = Ietver sadaļu Mani dokumenti, Mani attēli, Mana mūzika mapes un citus failus, kas jums pieder. +Menu.UserDocumentsTip = Satur vēstules, atskaites un citus dokumentus un failus. +Menu.UserPicturesTip = Satur ciparu fotogrāfijas, attēlus un grafikas failus. +Menu.UserMusicTip = Satur mūziku un citus audio failus. +Menu.UserVideosTip = Satur filmas un citus video failus. +Menu.NetworkTip = Parāda šajā datorā esošos tīkla savienojumus un palīdz izveidot jaunus +Menu.PrintersTip = Pievienojiet, noņemiet un konfigurējiet lokālos un tīkla printerus. +Menu.TaskbarTip = Pielāgot izvēlni Sākt un uzdevumjoslu, piemēram, kāda tipa vienumus rādīt un kā tiem ir jāizskatās. +Menu.ControlPanelTip = Mainīt iestatījumus un pielāgot datora funkcionalitāti. +Menu.DocumentsLibTip = Piekļūt vēstulēm, atskaitēm, piezīmēm un cita veida dokumentiem. +Menu.MusicLibTip = Atskaņot mūzikas un citus audio failus. +Menu.PicturesLibTip = Skatīt un organizēt digitālos attēlus. +Menu.VideosLibTip = Skatiet amatieru filmas un citu ciparvideo. +Menu.RecordingsLibTip = Skatiet datorā ierakstītās TV programmas. +Menu.DownloadTip = Atrodiet interneta lejupielādes un saites uz iecienītajām vietnēm. +Menu.HomegroupTip = Piekļūstiet bibliotēkām un mapēm, ko kopīgojušas citas personas mājas grupā. +Menu.RunTip = Atver programmu, mapi, dokumentu vai tīmekļa vietni. +Menu.HelpTip = Atrast palīdzības tēmas, apmācības, problēmu novēršanu un citus atbalsta pakalpojumus. +Menu.ProgramsTip = Atver programmu sarakstu. +Menu.SearchFilesTip = Meklēt dokumentus, mūziku, attēlus, e-pastu un citu. +Menu.GamesTip = Spēlēt un pārvaldīt spēles datorā. +Menu.SecurityTip = Palaist Windows drošības opcijas, lai mainītu paroli, pārslēgtu lietotāju vai startētu Uzdevumu pārvaldnieku. +Menu.SearchComputersTip = Meklēt datorus tīklā +Menu.SearchPrintersTip = Meklēt printeri +Menu.AdminToolsTip = Konfigurēt datora administratīvos iestatījumus. +Menu.ShutdownTip = Aizver visas atvērtās programmas, izslēdz sistēmu Windows un pēc tam izslēdz datoru. +Menu.RestartTip = Aizver visas atvērtās programmas, izslēdz sistēmu Windows un pēc tam to atkal startē. +Menu.SleepTip = Saglabā sesiju atmiņā un pārslēdz datoru mazas jaudas režīmā, lai pēc tam varētu ātri atsākt darbu. +Menu.HibernateTip = Saglabā sesiju un izslēdz datoru. Ieslēdzot datoru, sistēma Windows atjauno sesiju. +Menu.LogOffTip = Aizvērt programmas un atteikties. +Menu.DisconnectTip = Atvieno sesiju. Atkārtoti izveidot savienojumu ar šo sesiju var, vēlreiz piesakoties sistēmā. +Menu.LockTip = Aizslēgt datoru. +Menu.UndockTip = Noņem klēpjdatoru vai piezīmjdatoru no dokstacijas. +Menu.SwitchUserTip = Pārslēgt lietotājus, neaizverot programmas. +Menu.Empty = (Tukšs) +Menu.Features = Programmas un līdzekļi +Menu.FeaturesTip = Noņemt programmu instalāciju vai mainīt programmas datorā. +Menu.SearchPeople = &Personām... +Menu.SortByName = &Kārtot pēc nosaukuma +Menu.Open = A&tvērt +Menu.OpenAll = &Atvērt visus lietotājus +Menu.Explore = &Pārlūkot +Menu.ExploreAll = Pār&lūkot visus lietotājus +Menu.MenuSettings = Iestatījumi +Menu.MenuHelp = Palīdzība +Menu.MenuExit = Iziet +Menu.LogoffTitle = Atteikšanās sistēmā Windows +Menu.LogoffPrompt = Vai tiešām vēlaties atteikties? +Menu.LogoffYes = &Atteikties +Menu.LogoffNo = &Nē +Menu.RenameTitle = Pārdēvēšana +Menu.RenamePrompt = Jaunais &nosaukums: +Menu.RenameOK = Labi +Menu.RenameCancel = Atcelt +Menu.Organize = Organizēt izvēlni Sākt +Menu.Expand = Izv&ērst +Menu.Collapse = Sakļ&aut +Menu.NewFolder = Jauna mape +Menu.NewShortcut = Jauna saīsne +Menu.AutoArrange = &Automātiski sakārtot +Menu.ActionOpen = Atvērt +Menu.ActionClose = Aizvērt +Menu.ActionExecute = Izpildīt +Menu.RemoveList = &Noņemt no šī saraksta +Menu.RemoveAll = &Notīrīt nesen pievienoto vienumu sarakstu +Menu.Explorer = Windows Explorer +Menu.Start = Sākt +Menu.StartScreen = Sākuma ekrāns +Menu.StartMenu = Izvēlne Sākt (Windows) +Menu.PinStart = Piespraust izvēlnei Sākt +Menu.PinStartCs = Piespraust izvēlnei Sākt (Classic Shell) +Menu.UnpinStartCs = Atspraust no izvēlnes Sākt (Classic Shell) +Menu.MonitorOff = Izslēgt displeju +Menu.RemoveHighlight = Noņemt marķējumu +Menu.Uninstall = &Atinstalēt +Menu.UninstallTitle = Atinstalēt +Menu.UninstallPrompt = Vai esat pārliecināts, ka vēlaties atinstalēt %s? +Search.CategorySettings = Iestatījumi +Search.CategoryPCSettings = Datora iestatījumi +Search.CategoryPrograms = Programmas +Search.CategoryDocuments = Dokumenti +Search.CategoryMusic = Mūzika +Search.CategoryPictures = Attēli +Search.CategoryVideos = Video +Search.CategoryFiles = Faili +Search.CategoryInternet = Internets +JumpList.Recent = Nesen izmantotie +JumpList.Frequent = Biežāk atvērtie +JumpList.Tasks = Uzdevumi +JumpList.Pinned = Piesprausts +JumpList.Pin = Pie&spraust šim sarakstam +JumpList.Unpin = &Atspraust no šī saraksta +JumpList.Remove = &Noņemt no šī saraksta +JumpList.PinTip = Piespraust šim sarakstam +JumpList.UnpinTip = Atspraust no šī saraksta + + +[mk-MK] - Macedonian (Macedonia) +Menu.Programs = Програми +Menu.Apps = Апликации +Menu.AllPrograms = Сите програми +Menu.Back = Назад +Menu.Favorites = Омилени +Menu.Documents = Документи +Menu.Settings = Подесувања +Menu.Search = Пребарување +Menu.SearchBox = Поле за пребарување +Menu.SearchPrograms = Барање на програми и фајлови +Menu.SearchInternet = Пребарување на интернет +Menu.Searching = Пребарување... +Menu.NoMatch = Не е пронајдено ништо. +Menu.MoreResults = Дај повеќе резултати +Menu.Help = Помош и поддршка +Menu.Run = Стартувај... +Menu.Logoff = Излегување од... +Menu.SwitchUser = Смени го корисникот +Menu.Lock = Заклучување +Menu.LogOffShort = Кратко излегување +Menu.Undock = Откачи го компјутерот +Menu.Disconnect = Прекини ја врската +Menu.ShutdownBox = Исклучи... +Menu.Shutdown = Исклучување +Menu.Restart = Рестартирај +Menu.ShutdownUpdate = Надградба и исклучување +Menu.RestartUpdate = Надградба и рестартирање +Menu.Sleep = Заспивање +Menu.Hibernate = Хибернација +Menu.ControlPanel = Контрол панел +Menu.PCSettings = Параметри на компјутерот +Menu.Security = Заштита на Windows +Menu.Network = Компјутерска Мрежа +Menu.Printers = Принтери +Menu.Taskbar = Таскбар и мени “Старт“ +Menu.SearchFiles = За фајлови или фолдери... +Menu.SearchPrinter = За печатар +Menu.SearchComputers = За компјутери +Menu.UserFilesTip = Содржи фолдери за документи, музика и други ваши фајлови. +Menu.UserDocumentsTip = Содржи документи, слики, фајлови и друго. +Menu.UserPicturesTip = Содржи документи, слики и фајлови. +Menu.UserMusicTip = Содржи музика и други аудио фајлови. +Menu.UserVideosTip = Содржи филмови и други видео фајлови. +Menu.NetworkTip = Покажува постоечки врски на мрежата на тој компјутер и ви овозможува да направите нови +Menu.PrintersTip = Додавање, отстранување и конфигурирање на локални мрежини принтери. +Menu.TaskbarTip = Персонализирање на менито "Старт" и таскбарот на задачите, како на прим. типови на елементи коишто ќе бидат покажани. +Menu.ControlPanelTip = Промена на подесување и пресонализирање на функционалноста на компјутерот. +Menu.DocumentsLibTip = Пристап до писма, белешки и други видови на документи. +Menu.MusicLibTip = Репродукција на музика и други аудио фајлови. +Menu.PicturesLibTip = Преглед и организирање на дигитални слики. +Menu.VideosLibTip = Гледање на домашни филмови и други дигитални видеозаписи. +Menu.RecordingsLibTip = Гледање на снимени на компјутер ТВ програми. +Menu.DownloadTip = Барање на даунлоадирани фајлови од интернет и кон напосакуваните врски. +Menu.HomegroupTip = Достап до директориуми и фолдери, споделени од други луѓе во вашата домашна мрежа. +Menu.RunTip = Отвара програма, фолдер, документ или веб сајт. +Menu.HelpTip = Лоцирајте теми од "Помош", туторијали, отстранување на неисправности и други услуги за поддршка. +Menu.ProgramsTip = Го отвора списокот на програмите. +Menu.SearchFilesTip = Барање на документи, музика, слики,и електронска пошта и друго. +Menu.GamesTip = Играјте и управувајте со игрите на својот компјутер. +Menu.SecurityTip = Стартирајте ги опциите за заштита на Windows, за да промените лозинка, да смените корисник или да стартирате таск менаџер. +Menu.SearchComputersTip = Барање на компјутери во мрежата +Menu.SearchPrintersTip = Барање на печатари +Menu.AdminToolsTip = Конфигурирање на административните подесувања на компјутерот. +Menu.ShutdownTip = Ги затвора сите отворени програми, исклучува Windows и исклучува компјутер. +Menu.RestartTip = Ги затвора сите отворени програми, исклучува Windows и после одново се стартува Windows. +Menu.SleepTip = Ја запазува сесијата во меморија и го поставува компјутерот во систем на штедење на енергија, за да можете брзо да продолжите со работа. +Menu.HibernateTip = Ја запазува сесијата во меморија и исклучува компјутерот. Кога ќе го вклучите компјутерот, Windows ја продолжува вашата сесија. +Menu.LogOffTip = Затварање на програмите и излегување. +Menu.DisconnectTip = Ја прекинува врската со вашата сесија. Можете да се поврзете со таа сесија повторно, кога ќе влезете повторно. +Menu.LockTip = Заклупување на компјутерот. +Menu.UndockTip = Го отстранува вашиот лаптоп или ноутбук комјутер од базната станица. +Menu.SwitchUserTip = Смена на корисниците без да се затвораат програмите. +Menu.Empty = (Празно) +Menu.Features = Програми и компоненти +Menu.FeaturesTip = Деинсталација или промена на програми на компјутерот. +Menu.SearchPeople = За луѓе... +Menu.SortByName = Сортирај по име +Menu.Open = Отвори +Menu.OpenAll = Отвори "Сите корисници" +Menu.Explore = Преглед +Menu.ExploreAll = Преглед на "Сите корисници" +Menu.MenuSettings = Подесувања +Menu.MenuHelp = Помош +Menu.MenuExit = Излез +Menu.LogoffTitle = Излегување од Windows +Menu.LogoffPrompt = Навистина сакате да излезете? +Menu.LogoffYes = Излегување +Menu.LogoffNo = Не +Menu.RenameTitle = Преименување +Menu.RenamePrompt = Ново име: +Menu.RenameOK = OK +Menu.RenameCancel = Откажи +Menu.Organize = Организирање на менито "Старт" +Menu.Expand = Прошири +Menu.Collapse = Собери +Menu.NewFolder = Нов фолдер +Menu.NewShortcut = Нов краток пат +Menu.AutoArrange = Автоматско подредување +Menu.ActionOpen = Отвори +Menu.ActionClose = Затвори +Menu.ActionExecute = Изврши +Menu.RemoveList = Отстрани од тој список +Menu.RemoveAll = Исчисти го списокот од последните програми +Menu.Explorer = Windows Explorer +Menu.Start = Старт +Menu.StartScreen = Почетен екран +Menu.StartMenu = Мени "Старт" (Windows) +Menu.PinStart = Закачи кон менито "Старт" +Menu.PinStartCs = Закачи го кон менито "Старт" (Classic Shell) +Menu.UnpinStartCs = Откачи го од менито "Старт" (Classic Shell) +Menu.MonitorOff = Исклучување на дисплејот +Menu.RemoveHighlight = Remove highlight +Menu.Uninstall = &Деинсталирај +Menu.UninstallTitle = Деинсталирај +Menu.UninstallPrompt = Дали сте сигурни дека сакате да го деинсталирате %s? +Search.CategorySettings = Подесувања +Search.CategoryPCSettings = Параметри на компјутерот +Search.CategoryPrograms = Програми +Search.CategoryDocuments = Документи +Search.CategoryMusic = Музика +Search.CategoryPictures = Слики +Search.CategoryVideos = Видеозаписи +Search.CategoryFiles = Фајлови +Search.CategoryInternet = Интернет +JumpList.Recent = Последни +JumpList.Frequent = Често Користени +JumpList.Tasks = Задачи +JumpList.Pinned = Закачени +JumpList.Pin = Закачи кон тој список +JumpList.Unpin = Откачи од тој список +JumpList.Remove = Отстрани од тој список +JumpList.PinTip = Закачи кон тој список +JumpList.UnpinTip = Откачи од тој список + + +[nb-NO] - Norwegian, Bokmål (Norway) +Menu.Programs = &Programmer +Menu.Apps = Apper +Menu.AllPrograms = Alle programmer +Menu.Back = Tilbake +Menu.Favorites = &Favoritter +Menu.Documents = &Dokumenter +Menu.Settings = &Innstillinger +Menu.Search = &Søk +Menu.SearchBox = Søk +Menu.SearchPrograms = Søk i programmer og filer +Menu.SearchInternet = Søk på Internett +Menu.Searching = Søker... +Menu.NoMatch = Ingen elementer stemmer med søket. +Menu.MoreResults = Se flere resultater +Menu.Help = &Hjelp og støtte +Menu.Run = &Kjør... +Menu.Logoff = &Logg av %s... +Menu.SwitchUser = &Bytt bruker +Menu.Lock = L&ås +Menu.LogOffShort = &Logg av +Menu.Undock = Koble fra P&C +Menu.Disconnect = K&oble fra +Menu.ShutdownBox = &Avslutt... +Menu.Shutdown = &Avslutt +Menu.Restart = &Start på nytt +Menu.ShutdownUpdate = Oppdater og slå av +Menu.RestartUpdate = Oppdater og start på nytt +Menu.Sleep = &Hvilemodus +Menu.Hibernate = &Dvalemodus +Menu.ControlPanel = &Kontrollpanel +Menu.PCSettings = PC-innstillinger +Menu.Security = Windows-sikkerhet +Menu.Network = &Nettverkstilkoblinger +Menu.Printers = &Skrivere +Menu.Taskbar = &Oppgavelinje og Start-meny +Menu.SearchFiles = Etter &filer eller mapper... +Menu.SearchPrinter = Etter &skriver +Menu.SearchComputers = Etter &datamaskiner +Menu.UserFilesTip = Inneholder mapper for dokumenter, bilder, musikk og andre filer som tilhører deg. +Menu.UserDocumentsTip = Inneholder brev, rapporter og andre dokumenter og filer. +Menu.UserPicturesTip = Inneholder digitale fotografier, bilder og grafikkfiler. +Menu.UserMusicTip = Inneholder musikk- og andre lydfiler. +Menu.UserVideosTip = Inneholder filmer og andre videofiler. +Menu.NetworkTip = Viser eksisterende tilkoblinger på denne datamaskinen, og hjelper deg med å opprette nye +Menu.PrintersTip = Legg til, fjern og konfigurer lokale skrivere. +Menu.TaskbarTip = Tilpass Start-menyen og oppgavelinjen, for eksempel typen elementer som skal vises, og hvordan de skal vises. +Menu.ControlPanelTip = Endre innstillinger og tilpass funksjonaliteten på datamaskinen. +Menu.DocumentsLibTip = Lagre brev, rapporter, notater og andre typer dokumenter. +Menu.MusicLibTip = Spill av musikk og andre lydfiler. +Menu.PicturesLibTip = Vis og ordne digitale bilder. +Menu.VideosLibTip = Se hjemmefilmer og andre digitale videoer. +Menu.RecordingsLibTip = Se TV-programmer lagret på datamaskinen. +Menu.DownloadTip = Finn Internett-nedlastinger og koblinger til favorittsteder på nettet. +Menu.HomegroupTip = Få tilgang til biblioteker og mapper delt med andre i hjemmegruppen. +Menu.RunTip = Åpner et program, en mappe, et dokument eller et webområde. +Menu.HelpTip = Finn hjelpeemner, opplæring, feilsøking og andre støttetjenester. +Menu.ProgramsTip = Åpner en liste over programmer. +Menu.SearchFilesTip = Søk etter dokumenter, musikk, bilder, e-post og mer. +Menu.GamesTip = Spill og administrer spill på datamaskinen. +Menu.SecurityTip = Start Windows sikkerhetsalternativer for å endre Passord, Bytte bruker eller starte Oppgavebehandling. +Menu.SearchComputersTip = Søk etter datamaskiner på nettverket +Menu.SearchPrintersTip = Søk etter en skriver +Menu.AdminToolsTip = Konfigurer administrative innstillinger for datamaskinen. +Menu.ShutdownTip = Lukker alle åpne programmer, avslutter Windows og slår deretter av datamaskinen. +Menu.RestartTip = Lukker alle åpne programmer, avslutter Windows, og starter deretter Windows på nytt. +Menu.SleepTip = Beholder økten i minnet, og setter datamaskinen i en status med lavt strømforbruk så du raskt kan gjenoppta arbeidet. +Menu.HibernateTip = Lagrer økten, og slår av datamaskinen. Windows gjenoppretter økten når du slår på datamaskinen. +Menu.LogOffTip = Lukk programmer og logg av. +Menu.DisconnectTip = Kobler fra økten. Du kan koble til denne økten når du logger på igjen. +Menu.LockTip = Lås denne datamaskinen. +Menu.UndockTip = Fjerner den bærbare datamaskinen fra en forankringsstasjon. +Menu.SwitchUserTip = Bytt brukere uten å lukke programmer. +Menu.Empty = (Tom) +Menu.Features = Programmer og funksjoner +Menu.FeaturesTip = Avinstaller eller endre programmer på datamaskinen. +Menu.SearchPeople = Etter &personer... +Menu.SortByName = Sorter etter &navn +Menu.Open = Å&pne +Menu.OpenAll = &Åpne mappen All users +Menu.Explore = &Utforsk +Menu.ExploreAll = Utforsk &mappen All users +Menu.MenuSettings = Innstillinger +Menu.MenuHelp = Hjelp +Menu.MenuExit = Avslutt +Menu.LogoffTitle = Logg av Windows +Menu.LogoffPrompt = Er du sikker på at du vil logge av? +Menu.LogoffYes = &Logg av +Menu.LogoffNo = &Nei +Menu.RenameTitle = Gi nytt navn +Menu.RenamePrompt = &Nytt navn: +Menu.RenameOK = OK +Menu.RenameCancel = Avbryt +Menu.Organize = Organiser Start-meny +Menu.Expand = &Utvid +Menu.Collapse = &Minimer +Menu.NewFolder = Ny mappe +Menu.NewShortcut = Ny snarvei +Menu.AutoArrange = O&rdne automatisk +Menu.ActionOpen = Åpne +Menu.ActionClose = Lukk +Menu.ActionExecute = Utføre +Menu.RemoveList = &Fjern fra denne listen +Menu.RemoveAll = &Tøm listen over nylig brukte elementer +Menu.Explorer = Windows Utforsker +Menu.Start = Start +Menu.StartScreen = Startskjerm +Menu.StartMenu = Start-meny (Windows) +Menu.PinStart = Fest til Start-menyen +Menu.PinStartCs = Fest til Start-menyen (Classic Shell) +Menu.UnpinStartCs = Løsne fra Start-menyen (Classic Shell) +Menu.MonitorOff = Slå av skjermen +Menu.RemoveHighlight = Fjern høydepunkt +Menu.Uninstall = &Avinstaller +Menu.UninstallTitle = Avinstaller +Menu.UninstallPrompt = Er du sikker på at du vil avinstallere %s? +Search.CategorySettings = Innstillinger +Search.CategoryPCSettings = PC-innstillinger +Search.CategoryPrograms = Programmer +Search.CategoryDocuments = Dokumenter +Search.CategoryMusic = Musikk +Search.CategoryPictures = Bilder +Search.CategoryVideos = Videoer +Search.CategoryFiles = Filer +Search.CategoryInternet = Internett +JumpList.Recent = Siste +JumpList.Frequent = Ofte +JumpList.Tasks = Oppgaver +JumpList.Pinned = Låst +JumpList.Pin = &Fest til denne listen +JumpList.Unpin = &Løsne fra denne listen +JumpList.Remove = Fjer&n fra denne listen +JumpList.PinTip = Fest til denne listen +JumpList.UnpinTip = Løsne fra denne listen + + +[nl-NL] - Dutch (Netherlands) +Menu.Programs = &Programma's +Menu.Apps = Apps +Menu.AllPrograms = Alle programma's +Menu.Back = Vorige weergave +Menu.Favorites = &Favorieten +Menu.Documents = &Documenten +Menu.Settings = &Instellingen +Menu.Search = &Zoeken +Menu.SearchBox = Zoeken +Menu.SearchPrograms = Programma's en bestanden zoeken +Menu.SearchInternet = Op internet zoeken +Menu.Searching = Zoeken... +Menu.NoMatch = Geen zoekresultaten. +Menu.MoreResults = Meer resultaten weergeven +Menu.Help = &Help en ondersteuning +Menu.Run = &Uitvoeren... +Menu.Logoff = %s af&melden... +Menu.SwitchUser = An&dere gebruiker +Menu.Lock = &Vergrendelen +Menu.LogOffShort = Afmel&den +Menu.Undock = &Laptop loskoppelen +Menu.Disconnect = Ver&binding verbreken +Menu.ShutdownBox = &Afsluiten... +Menu.Shutdown = A&fsluiten +Menu.Restart = &Opnieuw opstarten +Menu.ShutdownUpdate = Bijwerken en afsluiten +Menu.RestartUpdate = Bijwerken en opnieuw opstarten +Menu.Sleep = &Slaapstand +Menu.Hibernate = Slui&merstand +Menu.ControlPanel = &Configuratiescherm +Menu.PCSettings = Pc-instellingen +Menu.Security = Windows-beveiliging +Menu.Network = &Netwerkverbindingen +Menu.Printers = &Printers +Menu.Taskbar = &Taakbalk en menu Start +Menu.SearchFiles = Naar &bestanden of mappen... +Menu.SearchPrinter = &Naar printer +Menu.SearchComputers = Naar &computers +Menu.UserFilesTip = Bevat mappen voor documenten, afbeeldingen, muziek en andere bestanden die van u zijn. +Menu.UserDocumentsTip = Dit is de locatie waar u brieven, rapporten, documenten en andere bestanden kunt opslaan +Menu.UserPicturesTip = Dit is de locatie waar u digitale foto's, afbeeldingen en andere grafische bestanden kunt opslaan +Menu.UserMusicTip = Dit is de locatie waar u muziek en andere audiobestanden kunt opslaan +Menu.UserVideosTip = Dit is de locatie waar u filmfragmenten en andere videobestanden kunt opslaan +Menu.NetworkTip = Hiermee worden netwerkverbindingen op deze computer weergegeven en krijgt u hulp bij het maken van nieuwe verbindingen +Menu.PrintersTip = Hiermee kunt u lokale en netwerkprinters toevoegen, verwijderen en configureren +Menu.TaskbarTip = Hiermee kunt u de weergave wijzigen van onderdelen die in het menu Start of op de taakbalk staan +Menu.ControlPanelTip = De instellingen en functionaliteit van uw computer wijzigen +Menu.DocumentsLibTip = Brieven, rapporten, notities en andere soorten documenten openen +Menu.MusicLibTip = Muziek en andere audiobestanden afspelen +Menu.PicturesLibTip = Digitale foto's weergeven en rangschikken +Menu.VideosLibTip = Bekijk zelfgemaakte films en andere digitale video's. +Menu.RecordingsLibTip = Bekijk televisieprogramma's die op de computer zijn opgenomen. +Menu.DownloadTip = Zoek internetdownloads en koppelingen naar favoriete websites. +Menu.HomegroupTip = Toegang krijgen tot bibliotheken en maken die gedeeld worden door andere gebruikers in uw thuisgroep. +Menu.RunTip = Hiermee kunt u een programma starten, map openen of een website bezoeken +Menu.HelpTip = Help-onderwerpen, zelfstudies, probleemoplossingen en andere ondersteuningsdiensten zoeken +Menu.ProgramsTip = Hiermee kunt u een lijst met beschikbare programma's weergeven +Menu.SearchFilesTip = Documenten, muziek, afbeeldingen, e-mailberichten en meer zoeken +Menu.GamesTip = Spellen op uw computer spelen en beheren +Menu.SecurityTip = Start Windows-beveiligingsopties om het wachtwoord te wijzigen, van gebruiker te veranderen of Taakbeheer te starten. +Menu.SearchComputersTip = Computers in het netwerk zoeken +Menu.SearchPrintersTip = Een printer zoeken +Menu.AdminToolsTip = Hiermee kunt u beheerinstellingen voor deze computer configureren +Menu.ShutdownTip = Alle geopende programma's sluiten, Windows afsluiten en vervolgens de computer uitschakelen +Menu.RestartTip = Alle geopende programma's sluiten en vervolgens Windows opnieuw starten +Menu.SleepTip = Uw sessie wordt in het geheugen bewaard en de computer wordt in een toestand van laag energieverbruik gezet, zodat u uw werk snel kunt hervatten. +Menu.HibernateTip = Uw sessie wordt opgeslagen en de computer wordt uitgeschakeld. Als u de computer inschakelt, wordt uw sessie hersteld. +Menu.LogOffTip = Alle programma's sluiten en u afmelden +Menu.DisconnectTip = De sessie beëindigen. U kunt de sessie hervatten door u opnieuw aan te melden. +Menu.LockTip = Deze computer vergrendelen +Menu.UndockTip = Uw draagbare computer loskoppelen van het basisstation +Menu.SwitchUserTip = Een andere gebruiker in staat stellen zich aan te melden zonder programma's te sluiten +Menu.Empty = (leeg) +Menu.Features = Programma's en onderdelen +Menu.FeaturesTip = Programma's op uw computer wijzigen of van uw computer verwijderen +Menu.SearchPeople = &Personen... +Menu.SortByName = S&orteren op naam +Menu.Open = &Openen +Menu.OpenAll = &Alle gebruikers weergeven +Menu.Explore = Ve&rkennen +Menu.ExploreAll = Alle &gebruikers verkennen +Menu.MenuSettings = Instellingen +Menu.MenuHelp = Help +Menu.MenuExit = Afsluiten +Menu.LogoffTitle = Afmelden bij Windows +Menu.LogoffPrompt = Weet u zeker dat u zich wilt afmelden? +Menu.LogoffYes = A&fmelden +Menu.LogoffNo = &Nee +Menu.RenameTitle = Naam wijzigen +Menu.RenamePrompt = &Nieuwe naam: +Menu.RenameOK = OK +Menu.RenameCancel = Annuleren +Menu.Organize = Menu Start organiseren +Menu.Expand = &Uitvouwen +Menu.Collapse = Samen&vouwen +Menu.NewFolder = Nieuwe map +Menu.NewShortcut = Nieuwe snelkoppeling +Menu.AutoArrange = Automatisch sc&hikken +Menu.ActionOpen = Openen +Menu.ActionClose = Sluiten +Menu.ActionExecute = Uitvoeren +Menu.RemoveList = Uit deze lijst &verwijderen +Menu.RemoveAll = Lijst met recente items &wissen +Menu.Explorer = Windows Verkenner +Menu.Start = Start +Menu.StartScreen = Startscherm +Menu.StartMenu = Menu Start (Windows) +Menu.PinStart = Vastmaken aan menu Start +Menu.PinStartCs = Vastmaken aan menu Start (Classic Shell) +Menu.UnpinStartCs = Losmaken van menu Start (Classic Shell) +Menu.MonitorOff = Het beeldscherm uitschakelen +Menu.RemoveHighlight = Aandachtspunt verwijderen +Menu.Uninstall = V&erwijderen +Menu.UninstallTitle = Verwijderen +Menu.UninstallPrompt = Weet u zeker dat u %s wilt verwijderen? +Search.CategorySettings = Instellingen +Search.CategoryPCSettings = Pc-instellingen +Search.CategoryPrograms = Programma's +Search.CategoryDocuments = Documenten +Search.CategoryMusic = Muziek +Search.CategoryPictures = Afbeeldingen +Search.CategoryVideos = Video's +Search.CategoryFiles = Bestanden +Search.CategoryInternet = Internet +JumpList.Recent = Recent +JumpList.Frequent = Vaak gebruikte items +JumpList.Tasks = Taken +JumpList.Pinned = Gepind +JumpList.Pin = &Aan deze lijst vastmaken +JumpList.Unpin = &Van deze lijst losmaken +JumpList.Remove = Uit deze lijst &verwijderen +JumpList.PinTip = Aan deze lijst vastmaken +JumpList.UnpinTip = Van deze lijst losmaken + + +[pl-PL] - Polish (Poland) +Menu.Programs = &Programy +Menu.Apps = Aplikacje +Menu.AllPrograms = Wszystkie programy +Menu.Back = Wstecz +Menu.Favorites = Ulu&bione +Menu.Documents = &Dokumenty +Menu.Settings = &Ustawienia +Menu.Search = &Wyszukaj +Menu.SearchBox = Wyszukaj +Menu.SearchPrograms = Wyszukaj programy i pliki +Menu.SearchInternet = Przeszukaj Internet +Menu.Searching = Trwa wyszukiwanie... +Menu.NoMatch = Żadne elementy nie pasują do kryteriów wyszukiwania. +Menu.MoreResults = Wyświetl więcej wyników +Menu.Help = Pomo&c i obsługa techniczna +Menu.Run = Urucho&m... +Menu.Logoff = Wy&loguj: %s... +Menu.SwitchUser = &Przełącz użytkownika +Menu.Lock = &Zablokuj +Menu.LogOffShort = Wy&loguj +Menu.Undock = Oddokuj kompu&ter +Menu.Disconnect = &Rozłącz +Menu.ShutdownBox = Zam&knij... +Menu.Shutdown = &Zamknij +Menu.Restart = &Uruchom ponownie +Menu.ShutdownUpdate = Zaktualizuj i zamknij +Menu.RestartUpdate = Zaktualizuj i uruchom ponownie +Menu.Sleep = &Wstrzymaj +Menu.Hibernate = &Hibernacja +Menu.ControlPanel = Panel &sterowania +Menu.PCSettings = Ustawienia komputera +Menu.Security = Zabezpieczenia systemu Windows +Menu.Network = &Połączenia sieciowe +Menu.Printers = &Drukarki +Menu.Taskbar = Pasek zadań i &menu Start +Menu.SearchFiles = &Pliki lub foldery... +Menu.SearchPrinter = &Drukarki +Menu.SearchComputers = &Komputery +Menu.UserFilesTip = Zawiera foldery na dokumenty, obrazy, muzykę i inne Twoje pliki. +Menu.UserDocumentsTip = Zawiera listy, raporty i inne dokumenty i pliki. +Menu.UserPicturesTip = Zawiera fotografie cyfrowe, obrazy i pliki graficzne. +Menu.UserMusicTip = Zawiera muzykę i inne pliki audio. +Menu.UserVideosTip = Zawiera filmy i inne pliki wideo. +Menu.NetworkTip = Wyświetla istniejące połączenia sieciowe na tym komputerze, oraz ułatwia tworzenie nowych. +Menu.PrintersTip = Dodawaj, usuwaj i konfiguruj drukarki lokalne i sieciowe. +Menu.TaskbarTip = Dostosuj menu Start i pasek zadań, na przykład typy wyświetlanych elementów i sposób ich wyświetlania. +Menu.ControlPanelTip = Zmień ustawienia i dostosuj funkcjonalność tego komputera. +Menu.DocumentsLibTip = Przechowuj listy, raporty, notatki i inne rodzaje dokumentów. +Menu.MusicLibTip = Odtwarzaj muzykę i inne pliki audio. +Menu.PicturesLibTip = Wyświetlaj i organizuj obrazy cyfrowe. +Menu.VideosLibTip = Oglądaj filmy i inne cyfrowe materiały wideo. +Menu.RecordingsLibTip = Oglądaj programy telewizyjne nagrane na komputerze. +Menu.DownloadTip = Znajdź pliki pobrane z Internetu i łącza do ulubionych witryn sieci Web. +Menu.HomegroupTip = Uzyskaj dostęp do bibliotek i folderów udostępnionych w grupie domowej przez inne osoby. +Menu.RunTip = Otwiera program, folder, dokument lub witrynę sieci web. +Menu.HelpTip = Znajdź tematy Pomocy, samouczki, narzędzia do rozwiązywania problemów i inne usługi pomocnicze. +Menu.ProgramsTip = Otwiera listę programów. +Menu.SearchFilesTip = Wyszukuj dokumenty, muzykę, obrazy, wiadomości e-mail i inne elementy. +Menu.GamesTip = Graj i zarządzaj grami na komputerze. +Menu.SecurityTip = Otwórz opcje zabezpieczeń systemu Windows, aby zmienić hasło, przełączyć użytkownika lub uruchomić Menedżera zadań. +Menu.SearchComputersTip = Wyszukiwanie komputerów w sieci +Menu.SearchPrintersTip = Wyszukiwanie drukarki +Menu.AdminToolsTip = Konfiguruje ustawienia administracyjne dla tego komputera. +Menu.ShutdownTip = Zamyka wszystkie otwarte programy, zamyka system Windows, a następnie wyłącza komputer. +Menu.RestartTip = Zamyka wszystkie otwarte programy, zamyka system Windows, a następnie ponownie go uruchamia. +Menu.SleepTip = Zachowuje sesję w pamięci i przełącza komputer w stan niskiego poboru energii, umożliwiając szybkie wznowienie pracy. +Menu.HibernateTip = Zapisuje sesję i wyłącza komputer. Gdy włączysz komputer, system Windows przywróci sesję. +Menu.LogOffTip = Zamknij programy i wyloguj się. +Menu.DisconnectTip = Rozłącza sesję. Po ponownym zalogowaniu można ponownie połączyć się z tą samą sesją. +Menu.LockTip = Zablokuj ten komputer. +Menu.UndockTip = Odłącza komputer przenośny od stacji dokowania. +Menu.SwitchUserTip = Przełącz użytkowników bez zamykania programów. +Menu.Empty = (Puste) +Menu.Features = Programy i funkcje +Menu.FeaturesTip = Odinstaluj lub zmień programy na komputerze. +Menu.SearchPeople = &Do osób... +Menu.SortByName = Sortuj w&edług nazw +Menu.Open = &Otwórz +Menu.OpenAll = Otwórz &wszystkich użytkowników +Menu.Explore = &Eksploruj +Menu.ExploreAll = E&ksploruj wszystkich użytkowników +Menu.MenuSettings = Ustawienia +Menu.MenuHelp = Pomoc +Menu.MenuExit = Zakończ +Menu.LogoffTitle = Wylogowywanie z systemu Windows +Menu.LogoffPrompt = Czy na pewno chcesz się wylogować? +Menu.LogoffYes = &Wyloguj +Menu.LogoffNo = &Nie +Menu.RenameTitle = Zmienianie nazwy +Menu.RenamePrompt = &Nowa nazwa: +Menu.RenameOK = OK +Menu.RenameCancel = Anuluj +Menu.Organize = Organizuj menu Start +Menu.Expand = &Rozwiń +Menu.Collapse = &Zwiń +Menu.NewFolder = Nowy folder +Menu.NewShortcut = Nowy skrót +Menu.AutoArrange = &Autorozmieszczanie +Menu.ActionOpen = Otwórz +Menu.ActionClose = Zamknij +Menu.ActionExecute = Wykonaj +Menu.RemoveList = &Usuń z tej listy +Menu.RemoveAll = &Wyczyść listę niedawno używanych elementów +Menu.Explorer = Eksplorator Windows +Menu.Start = Start +Menu.StartScreen = Ekran startowy +Menu.StartMenu = Menu Start (Windows) +Menu.PinStart = Przypnij do menu Start +Menu.PinStartCs = Przypnij do menu Start (Classic Shell) +Menu.UnpinStartCs = Odepnij od menu Start (Classic Shell) +Menu.MonitorOff = Wyłącz ekran +Menu.RemoveHighlight = Usuń wyróżnienie +Menu.Uninstall = &Odinstaluj +Menu.UninstallTitle = Odinstaluj +Menu.UninstallPrompt = Czy na pewno chcesz odinstalować program %s? +Search.CategorySettings = Ustawienia +Search.CategoryPCSettings = Ustawienia komputera +Search.CategoryPrograms = Programy +Search.CategoryDocuments = Dokumenty +Search.CategoryMusic = Muzyka +Search.CategoryPictures = Obrazy +Search.CategoryVideos = Wideo +Search.CategoryFiles = Pliki +Search.CategoryInternet = Internet +JumpList.Recent = Najnowsze +JumpList.Frequent = Częste +JumpList.Tasks = Zadania +JumpList.Pinned = Zakotwiczony +JumpList.Pin = &Przypnij do tej listy +JumpList.Unpin = &Odepnij od tej listy +JumpList.Remove = U&suń z tej listy +JumpList.PinTip = Przypnij do tej listy +JumpList.UnpinTip = Odepnij od tej listy + + +[pt-BR] - Portuguese (Brazil) +Menu.Programs = &Programas +Menu.Apps = Aplicativos +Menu.AllPrograms = Todos os Programas +Menu.Back = Voltar +Menu.Favorites = &Favoritos +Menu.Documents = Docu&mentos +Menu.Settings = &Configurações +Menu.Search = Pe&squisar +Menu.SearchBox = Pesquisar +Menu.SearchPrograms = Pesquisar programas e arquivos +Menu.SearchInternet = Pesquisar na Internet +Menu.Searching = Pesquisando... +Menu.NoMatch = Nenhum item corresponde à pesquisa. +Menu.MoreResults = Ver mais resultados +Menu.Help = &Ajuda e Suporte +Menu.Run = Execu&tar... +Menu.Logoff = Fa&zer Logoff de %s... +Menu.SwitchUser = &Trocar usuário +Menu.Lock = Bl&oquear +Menu.LogOffShort = Faz&er logoff +Menu.Undock = Desencai&xar +Menu.Disconnect = &Desconectar +Menu.ShutdownBox = Desliga&r... +Menu.Shutdown = &Desligar +Menu.Restart = &Reiniciar +Menu.ShutdownUpdate = Atualizar e desligar +Menu.RestartUpdate = Atualizar e reiniciar +Menu.Sleep = &Dormir +Menu.Hibernate = &Hibernar +Menu.ControlPanel = &Painel de controle +Menu.PCSettings = Configurações do computador +Menu.Security = Segurança do Windows +Menu.Network = Co&nexões de Rede +Menu.Printers = &Impressoras +Menu.Taskbar = &Barra de Tarefas e menu Iniciar +Menu.SearchFiles = &Arquivos ou Pastas... +Menu.SearchPrinter = Imp&ressora +Menu.SearchComputers = &Computadores +Menu.UserFilesTip = Contém pastas de Documentos, Imagens, Músicas e outros arquivos pertencentes a você. +Menu.UserDocumentsTip = Contém cartas, relatórios e outros documentos e arquivos. +Menu.UserPicturesTip = Contém fotos digitais, imagens e arquivos gráficos. +Menu.UserMusicTip = Contém música e outros arquivos de áudio. +Menu.UserVideosTip = Contém filmes e outros arquivos de vídeo. +Menu.NetworkTip = Exibe as conexões de rede existentes neste computador e ajuda a criar novas conexões +Menu.PrintersTip = Adicione, remova e configure impressoras e locais e de rede. +Menu.TaskbarTip = Personaliza o menu Iniciar e a barra de ferramentas: tipos de itens a exibir e a maneira como aparecem. +Menu.ControlPanelTip = Altere as configurações e personalize a funcionalidade do seu computador. +Menu.DocumentsLibTip = Acesse cartas, relatórios, anotações e outros tipos de documentos. +Menu.MusicLibTip = Toque música e outros arquivos de áudio. +Menu.PicturesLibTip = Veja e organize imagens digitais. +Menu.VideosLibTip = Assistir a filmes caseiros e outros vídeos digitais. +Menu.RecordingsLibTip = Assistir programas de TV gravados no seu computador. +Menu.DownloadTip = Localizar downloads da Internet e links para sites favoritos. +Menu.HomegroupTip = Acesse bibliotecas e pastas compartilhadas por outras pessoas em seu grupo doméstico. +Menu.RunTip = Abre um programa, uma pasta, um documento ou um site. +Menu.HelpTip = Localizar tópicos da Ajuda, tutoriais, soluções de problemas e outros serviços de suporte. +Menu.ProgramsTip = Abre uma lista dos programas. +Menu.SearchFilesTip = Pesquisar documentos, músicas, imagens, emails e muito mais. +Menu.GamesTip = Jogar e gerenciar jogos no computador. +Menu.SecurityTip = Iniciar Opções de Segurança do Windows para Alterar Senha, Alternar Usuário ou Iniciar o Gerenciador de Tarefas. +Menu.SearchComputersTip = Procurar computadores na rede +Menu.SearchPrintersTip = Procurar uma impressora +Menu.AdminToolsTip = Definir configurações administrativas para o computador. +Menu.ShutdownTip = Fecha todos os programas, desliga o Windows e desliga o computador. +Menu.RestartTip = Fecha todos os programas, desliga o Windows e o reinicia. +Menu.SleepTip = Mantém a sua sessão na memória e coloca o computador em um estado de baixa energia para que você possa reiniciar rapidamente o trabalho. +Menu.HibernateTip = Salva sua sessão e desliga o computador. Quando você liga o computador novamente, o Windows restaura a sessão. +Menu.LogOffTip = Fechar todos os programas e fazer logoff. +Menu.DisconnectTip = Desconecta a sessão. Você pode reconectá-la quando fizer logon novamente. +Menu.LockTip = Bloquear este computador. +Menu.UndockTip = Remove o laptop ou notebook de uma base de encaixe. +Menu.SwitchUserTip = Alternar os usuários sem fechar os programas. +Menu.Empty = (Vazio) +Menu.Features = Programas e Recursos +Menu.FeaturesTip = Desinstalar ou alterar programas do computador. +Menu.SearchPeople = Para &Pessoas... +Menu.SortByName = C&lassificar por nome +Menu.Open = &Abrir +Menu.OpenAll = A&brir a pasta All Users +Menu.Explore = E&xplorar +Menu.ExploreAll = Expl&orar a pasta All Users +Menu.MenuSettings = Configurações +Menu.MenuHelp = Ajuda +Menu.MenuExit = Sair +Menu.LogoffTitle = Fazer Logoff do Windows +Menu.LogoffPrompt = Tem certeza de que deseja fazer logoff? +Menu.LogoffYes = Faz&er Logoff +Menu.LogoffNo = &Não +Menu.RenameTitle = Renomear +Menu.RenamePrompt = &Novo nome: +Menu.RenameOK = OK +Menu.RenameCancel = Cancelar +Menu.Organize = Organizar o menu Iniciar +Menu.Expand = E&xpandir +Menu.Collapse = &Recolher +Menu.NewFolder = Nova Pasta +Menu.NewShortcut = Novo Atalho +Menu.AutoArrange = Organi&zar Automaticamente +Menu.ActionOpen = Abrir +Menu.ActionClose = Fechar +Menu.ActionExecute = Executar +Menu.RemoveList = Remover desta &lista +Menu.RemoveAll = &Limpar lista de itens recentes +Menu.Explorer = Windows Explorer +Menu.Start = Iniciar +Menu.StartScreen = Tela Inicial +Menu.StartMenu = Menu Iniciar (Windows) +Menu.PinStart = Fixar no Menu Iniciar +Menu.PinStartCs = Fixar no Menu Iniciar (Classic Shell) +Menu.UnpinStartCs = Desafixar do Menu Iniciar (Classic Shell) +Menu.MonitorOff = Desativar o vídeo +Menu.RemoveHighlight = Remover Destaque +Menu.Uninstall = &Desinstalar +Menu.UninstallTitle = Desinstalar +Menu.UninstallPrompt = Tem certeza de que deseja desinstalar %s? +Search.CategorySettings = Configurações +Search.CategoryPCSettings = Configurações do computador +Search.CategoryPrograms = Programas +Search.CategoryDocuments = Documentos +Search.CategoryMusic = Músicas +Search.CategoryPictures = Imagens +Search.CategoryVideos = Vídeos +Search.CategoryFiles = Arquivos +Search.CategoryInternet = Internet +JumpList.Recent = Recentes +JumpList.Frequent = Frequente +JumpList.Tasks = Tarefas +JumpList.Pinned = Fixo +JumpList.Pin = In&cluir nesta lista +JumpList.Unpin = &Tirar desta lista +JumpList.Remove = Remover desta &lista +JumpList.PinTip = Incluir nesta lista +JumpList.UnpinTip = Tirar desta lista + + +[pt-PT] - Portuguese (Portugal) +Menu.Programs = &Programas +Menu.Apps = Aplicações +Menu.AllPrograms = Todos os Programas +Menu.Back = Anterior +Menu.Favorites = &Favoritos +Menu.Documents = &Documentos +Menu.Settings = Defi&nições +Menu.Search = Pro&curar +Menu.SearchBox = Procurar +Menu.SearchPrograms = Procurar programas e ficheiros +Menu.SearchInternet = Procurar na Internet +Menu.Searching = A procurar... +Menu.NoMatch = Nenhum item corresponde à pesquisa. +Menu.MoreResults = Ver mais resultados +Menu.Help = &Ajuda e suporte +Menu.Run = E&xecutar... +Menu.Logoff = &Terminar sessão de %s... +Menu.SwitchUser = M&udar de utilizador +Menu.Lock = &Bloquear +Menu.LogOffShort = &Terminar sessão +Menu.Undock = D&esancorar +Menu.Disconnect = Des&ligar +Menu.ShutdownBox = Ence&rrar... +Menu.Shutdown = &Encerrar +Menu.Restart = &Reiniciar +Menu.ShutdownUpdate = Atualizar e encerrar +Menu.RestartUpdate = Atualizar e reiniciar +Menu.Sleep = &Suspender +Menu.Hibernate = &Hibernar +Menu.ControlPanel = &Painel de controlo +Menu.PCSettings = Definições do PC +Menu.Security = Segurança do Windows +Menu.Network = &Ligações de rede +Menu.Printers = &Impressoras +Menu.Taskbar = &Barra de tarefas e menu Iniciar +Menu.SearchFiles = &Ficheiros ou Pastas... +Menu.SearchPrinter = &Impressora +Menu.SearchComputers = &Computadores +Menu.UserFilesTip = Contém pastas de Documentos, Imagens, Música e outros ficheiros que lhe pertençam. +Menu.UserDocumentsTip = Contém cartas, relatórios e outros documentos e ficheiros. +Menu.UserPicturesTip = Contém fotografias digitais, imagens e ficheiros gráficos. +Menu.UserMusicTip = Contém música e outros ficheiros de áudio. +Menu.UserVideosTip = Contém filmes e outros ficheiros de vídeo. +Menu.NetworkTip = Mostra as ligações de rede existentes neste computador e ajuda a criar novas ligações +Menu.PrintersTip = Adiciona, remove e configura impressoras locais e de rede. +Menu.TaskbarTip = Personalize o menu Iniciar e a barra de tarefas, por exemplo, o tipo de itens a apresentar e o modo como devem ser apresentados. +Menu.ControlPanelTip = Alterar as definições e personalizar a funcionalidade do computador. +Menu.DocumentsLibTip = Aceder a cartas, relatórios, notas e outros tipos de documentos. +Menu.MusicLibTip = Reproduzir música e outros ficheiros de áudio. +Menu.PicturesLibTip = Ver e organizar imagens digitais. +Menu.VideosLibTip = Assistir a filmes domésticos e a outros vídeos digitais. +Menu.RecordingsLibTip = Assistir a programas de TV gravados no computador. +Menu.DownloadTip = Localizar transferências e hiperligações para Web sites favoritos. +Menu.HomegroupTip = Aceda a bibliotecas e pastas partilhadas por outras pessoas no grupo doméstico. +Menu.RunTip = Abre um programa, pasta, documento ou Web site. +Menu.HelpTip = Localizar tópicos de Ajuda, iniciações, resolução de problemas e outros serviços de suporte. +Menu.ProgramsTip = Abre uma lista dos seus programas. +Menu.SearchFilesTip = Procurar documentos, música, imagens, correio electrónico e muito mais. +Menu.GamesTip = Jogar e gerir os jogos existentes no computador. +Menu.SecurityTip = Iniciar Opções de Segurança do Windows para Alterar Palavra-passe, Mudar de Utilizador ou Iniciar o Gestor de Tarefas. +Menu.SearchComputersTip = Procurar computadores na rede +Menu.SearchPrintersTip = Procurar impressora +Menu.AdminToolsTip = Configura definições administrativas para o computador. +Menu.ShutdownTip = Fecha todos os programas abertos, encerra o Windows e, em seguida, desliga o computador. +Menu.RestartTip = Fecha todos os programas abertos, encerra o Windows e, em seguida, inicia novamente o Windows. +Menu.SleepTip = Mantém a sessão em memória e coloca o computador num estado de baixo consumo para poder retomar o trabalho rapidamente. +Menu.HibernateTip = Guarda a sessão e desliga o computador. Quando ligar o computador, o Windows vai restaurar a sessão. +Menu.LogOffTip = Fecha programas e termina sessão. +Menu.DisconnectTip = Desliga a sua sessão. Pode religar a esta sessão quando iniciar sessão novamente. +Menu.LockTip = Bloqueia este computador. +Menu.UndockTip = Remove o computador portátil de uma estação de ancoragem. +Menu.SwitchUserTip = Muda de utilizadores sem fechar os programas. +Menu.Empty = (Vazio) +Menu.Features = Programas e Funcionalidades +Menu.FeaturesTip = Desinstale ou altere programas no computador. +Menu.SearchPeople = &Pessoas... +Menu.SortByName = Ordenar pelo &nome +Menu.Open = &Abrir +Menu.OpenAll = A&brir All Users +Menu.Explore = E&xplorar +Menu.ExploreAll = Explorar All &Users +Menu.MenuSettings = Definições +Menu.MenuHelp = Ajuda +Menu.MenuExit = Sair +Menu.LogoffTitle = Terminar sessão no Windows +Menu.LogoffPrompt = Tem a certeza de que pretende terminar a sessão? +Menu.LogoffYes = &Terminar sessão +Menu.LogoffNo = &Não +Menu.RenameTitle = Mudar o nome +Menu.RenamePrompt = &Novo nome: +Menu.RenameOK = OK +Menu.RenameCancel = Cancelar +Menu.Organize = Organizar o menu Iniciar +Menu.Expand = E&xpandir +Menu.Collapse = &Fechar +Menu.NewFolder = Nova pasta +Menu.NewShortcut = Novo atalho +Menu.AutoArrange = Dispor au&tomaticamente +Menu.ActionOpen = Abrir +Menu.ActionClose = Fechar +Menu.ActionExecute = Executar +Menu.RemoveList = Remover &desta lista +Menu.RemoveAll = &Limpar lista de itens recentes +Menu.Explorer = Explorador do Windows +Menu.Start = Iniciar +Menu.StartScreen = Ecrã Iniciar +Menu.StartMenu = Menu Iniciar (Windows) +Menu.PinStart = Afixar no menu Iniciar +Menu.PinStartCs = Afixar no menu Iniciar (Classic Shell) +Menu.UnpinStartCs = Remover do menu Iniciar (Classic Shell) +Menu.MonitorOff = Desligar a visualização +Menu.RemoveHighlight = Remover destaque +Menu.Uninstall = D&esinstalar +Menu.UninstallTitle = Desinstalar +Menu.UninstallPrompt = Tem a certeza de que pretende desinstalar %s? +Search.CategorySettings = Definições +Search.CategoryPCSettings = Definições do PC +Search.CategoryPrograms = Programas +Search.CategoryDocuments = Documentos +Search.CategoryMusic = Música +Search.CategoryPictures = Imagens +Search.CategoryVideos = Vídeos +Search.CategoryFiles = Ficheiros +Search.CategoryInternet = Internet +JumpList.Recent = Recente +JumpList.Frequent = Frequente +JumpList.Tasks = Tarefas +JumpList.Pinned = Fixado +JumpList.Pin = Afi&xar nesta lista +JumpList.Unpin = &Remover desta lista +JumpList.Remove = Remover &desta lista +JumpList.PinTip = Afixar nesta lista +JumpList.UnpinTip = Remover desta lista + + +[ro-RO] - Romanian (Romania) +Menu.Programs = &Programe +Menu.Apps = Aplicații +Menu.AllPrograms = Toate programele +Menu.Back = Înapoi +Menu.Favorites = Pre&ferințe +Menu.Documents = D&ocumente +Menu.Settings = &Setări +Menu.Search = &Căutare +Menu.SearchBox = Căutare +Menu.SearchPrograms = Căutare programe și fișiere +Menu.SearchInternet = Căutare pe Internet +Menu.Searching = Se caută... +Menu.NoMatch = Niciun element nu corespunde căutării. +Menu.MoreResults = Mai multe rezultate +Menu.Help = &Ajutor și asistență +Menu.Run = E&xecutare... +Menu.Logoff = &Log off %s... +Menu.SwitchUser = &Comutare utilizatori +Menu.Lock = &Blocare +Menu.LogOffShort = &Log off +Menu.Undock = De&tașare computer +Menu.Disconnect = D&econectare +Menu.ShutdownBox = Î&nchidere... +Menu.Shutdown = Î&nchidere +Menu.Restart = &Repornire +Menu.ShutdownUpdate = Actualizare și închidere +Menu.RestartUpdate = Actualizare și repornire +Menu.Sleep = &Repaus +Menu.Hibernate = &Hibernare +Menu.ControlPanel = Pano&u de control +Menu.PCSettings = Setări PC +Menu.Security = Securitate Windows +Menu.Network = &Conexiuni în rețea +Menu.Printers = &Imprimante +Menu.Taskbar = Ba&ra de activități și meniu Start +Menu.SearchFiles = &Fișiere sau foldere... +Menu.SearchPrinter = I&mprimantă +Menu.SearchComputers = &Computere +Menu.UserFilesTip = Conține foldere pentru Documente, Imagini, Muzică și alte fișiere care vă aparțin. +Menu.UserDocumentsTip = Conține scrisori, rapoarte și alte documente și fișiere. +Menu.UserPicturesTip = Conține fotografii digitale, imagini și fișiere grafice. +Menu.UserMusicTip = Conține muzică și alte fișiere audio. +Menu.UserVideosTip = Conține filme și alte fișiere video. +Menu.NetworkTip = Afișează conexiunile existente în rețea și ajută la crearea unora noi +Menu.PrintersTip = Adăugare, eliminare și configurare imprimante locale și în rețea. +Menu.TaskbarTip = Se particularizează meniul Start și bara de stare, cum ar fi tipurile de elemente și modul lor de afișare. +Menu.ControlPanelTip = Modificați setările și particularizați funcționalitățile computerului. +Menu.DocumentsLibTip = Accesați scrisori, rapoarte, note și alte tipuri de documente. +Menu.MusicLibTip = Redați muzică și alte fișiere audio. +Menu.PicturesLibTip = Vizualizați și organizați imaginile digitale. +Menu.VideosLibTip = Vizionați filme făcute în casă și alte materiale video digitale. +Menu.RecordingsLibTip = Vizionați programe TV înregistrate pe computer. +Menu.DownloadTip = Găsiți descărcări Internet și linkuri la site-urile Web preferate. +Menu.HomegroupTip = Accesați bibliotecile și folderele partajate de alte persoane din grupul de domiciliu. +Menu.RunTip = Se deschide un program, un folder, un document sau un site Web. +Menu.HelpTip = Găsiți subiecte de ajutor, asistenți de instruire, depanare și alte servicii de asistență. +Menu.ProgramsTip = Se deschide o listă de programe. +Menu.SearchFilesTip = Se caută documente, muzică, imagini, mesaje de poștă electronică și altele. +Menu.GamesTip = Jucați și gestionați jocuri pe computer. +Menu.SecurityTip = Lansați Opțiuni de securitate Windows pentru a modifica parola, pentru a comuta la alt utilizator sau pentru a porni Manager activități. +Menu.SearchComputersTip = Căutare computere în rețea +Menu.SearchPrintersTip = Căutare imprimantă +Menu.AdminToolsTip = Configurare setări de administrare pe acest computer. +Menu.ShutdownTip = Închide toate programele deschise, închide Windows, apoi oprește computerul. +Menu.RestartTip = Închide toate programele deschise, închide Windows, apoi pornește din nou Windows. +Menu.SleepTip = Păstrează sesiunea în memorie și pune computerul într-o stare cu alimentare redusă, astfel încât aveți posibilitatea să reluați rapid lucrul. +Menu.HibernateTip = Salvează sesiunea și închide computerul. Când deschideți computerul, Windows restaurează sesiunea. +Menu.LogOffTip = Închide programele și face logoff. +Menu.DisconnectTip = Sesiunea se deconectează. Aveți posibilitatea să vă reconectați la această sesiune atunci când faceți din nou Log on. +Menu.LockTip = Blochează acest computer. +Menu.UndockTip = Deconectează laptopul sau computerul portabil dintr-o stație de andocare. +Menu.SwitchUserTip = Comută între utilizatori fără a închide programele. +Menu.Empty = (Gol) +Menu.Features = Programe și caracteristici +Menu.FeaturesTip = Dezinstalează sau modifică programe de pe computer. +Menu.SearchPeople = &Persoane... +Menu.SortByName = &Sortare după nume +Menu.Open = &Deschidere +Menu.OpenAll = Desc&hidere Toți utilizatorii +Menu.Explore = &Explorare +Menu.ExploreAll = E&xplorare Toți utilizatorii +Menu.MenuSettings = Setări +Menu.MenuHelp = Ajutor +Menu.MenuExit = Ieșire +Menu.LogoffTitle = Log off din Windows +Menu.LogoffPrompt = Sigur faceți logoff? +Menu.LogoffYes = &Log off +Menu.LogoffNo = &Nu +Menu.RenameTitle = Redenumire +Menu.RenamePrompt = &Nume nou: +Menu.RenameOK = OK +Menu.RenameCancel = Revocare +Menu.Organize = Organizare meniu Start +Menu.Expand = E&xtindere +Menu.Collapse = &Restrângere +Menu.NewFolder = Folder nou +Menu.NewShortcut = Comandă rapidă nouă +Menu.AutoArrange = Aran&jare automată +Menu.ActionOpen = Deschidere +Menu.ActionClose = Închidere +Menu.ActionExecute = Executare +Menu.RemoveList = Eliminare &din această listă +Menu.RemoveAll = &Golire Listă elemente recente +Menu.Explorer = Windows Explorer +Menu.Start = Start +Menu.StartScreen = Ecranul de Start +Menu.StartMenu = Meniu Start (Windows) +Menu.PinStart = Fixare la meniul Start +Menu.PinStartCs = Fixare la meniul Start (Classic Shell) +Menu.UnpinStartCs = Anulare fixare la meniul Start (Classic Shell) +Menu.MonitorOff = Dezactivare ecranului +Menu.RemoveHighlight = Eliminare evidențiere +Menu.Uninstall = &Dezinstalare +Menu.UninstallTitle = Dezinstalare +Menu.UninstallPrompt = Sigur dezinstalați %s? +Search.CategorySettings = Setări +Search.CategoryPCSettings = Setări PC +Search.CategoryPrograms = Programe +Search.CategoryDocuments = Documente +Search.CategoryMusic = Muzică +Search.CategoryPictures = Imagini +Search.CategoryVideos = Video +Search.CategoryFiles = Fișiere +Search.CategoryInternet = Internet +JumpList.Recent = Recent +JumpList.Frequent = Frecvent +JumpList.Tasks = Activități +JumpList.Pinned = Fixat +JumpList.Pin = F&ixare la această listă +JumpList.Unpin = An&ulare fixare la această listă +JumpList.Remove = Eliminare &din această listă +JumpList.PinTip = Fixare la această listă +JumpList.UnpinTip = Anulare fixare la această listă + + +[ru-RU] - Russian (Russia) +Menu.Programs = &Программы +Menu.Apps = Приложения +Menu.AllPrograms = Все программы +Menu.Back = Назад +Menu.Favorites = &Избранное +Menu.Documents = &Документы +Menu.Settings = Н&астройка +Menu.Search = &Найти +Menu.SearchBox = Найти +Menu.SearchPrograms = Найти программы и файлы +Menu.SearchInternet = Поиск в Интернете +Menu.Searching = Идет поиск... +Menu.NoMatch = Нет элементов, удовлетворяющих условиям поиска. +Menu.MoreResults = Ознакомиться с другими результатами +Menu.Help = &Справка и поддержка +Menu.Run = &Выполнить... +Menu.Logoff = Завер&шение сеанса %s... +Menu.SwitchUser = См&енить пользователя +Menu.Lock = &Блокировать +Menu.LogOffShort = Завер&шение сеанса +Menu.Undock = Отстыковать &компьютер +Menu.Disconnect = Отклю&чить +Menu.ShutdownBox = &Завершение работы... +Menu.Shutdown = &Завершение работы +Menu.Restart = &Перезагрузка +Menu.ShutdownUpdate = Обновить и завершить работу +Menu.RestartUpdate = Обновить и перезагрузить +Menu.Sleep = &Сон +Menu.Hibernate = &Гибернация +Menu.ControlPanel = П&анель управления +Menu.PCSettings = Параметры ПК +Menu.Security = Безопасность Windows +Menu.Network = С&етевые подключения +Menu.Printers = &Принтеры +Menu.Taskbar = Панель &задач и меню "Пуск" +Menu.SearchFiles = &Файлы и папки... +Menu.SearchPrinter = &Принтер +Menu.SearchComputers = &Компьютеры +Menu.UserFilesTip = Содержит папки для документов, фотографий и изображений, музыки и других принадлежащих вам файлов. +Menu.UserDocumentsTip = Содержит письма, отчеты и другие документы и файлы. +Menu.UserPicturesTip = Содержит цифровые фотографии, рисунки, графические файлы. +Menu.UserMusicTip = Содержит музыкальные и звуковые файлы. +Menu.UserVideosTip = Содержит фильмы и видеофайлы. +Menu.NetworkTip = Отображение сетевых подключений для этого компьютера и создание новых подключений +Menu.PrintersTip = Добавление, удаление и настройка локальных и сетевых принтеров +Menu.TaskbarTip = Настройка меню ''Пуск'' и панели задач, например, изменение списка отображаемых элементов и внешнего вида. +Menu.ControlPanelTip = Изменение параметров и настройка функциональных возможностей компьютера. +Menu.DocumentsLibTip = Доступ к письмам, отчетам, заметкам и другим видам документов. +Menu.MusicLibTip = Проигрывание музыки и других аудиофайлов. +Menu.PicturesLibTip = Просмотр и упорядочение цифровых изображений. +Menu.VideosLibTip = Просмотр фильмов и другого цифрового видео. +Menu.RecordingsLibTip = Просмотр записанных на компьютере телевизионных передач. +Menu.DownloadTip = Поиск ссылок на избранные веб-узлы и загрузка файлов из Интернета. +Menu.HomegroupTip = Доступ к библиотекам и папкам, общий доступ к которым предоставлен другими участниками домашней группы. +Menu.RunTip = Открытие программы, папки, документа или веб-сайта. +Menu.HelpTip = Поиск разделов справки, учебников, средств устранения неисправностей и других служб поддержки. +Menu.ProgramsTip = Отображение списка программ, установленных на этом компьютере. +Menu.SearchFilesTip = Поиск документов, музыки, изображений, писем и многое другое. +Menu.GamesTip = Играть в игры и управлять ими на этом компьютере. +Menu.SecurityTip = Открыть параметры безопасности Windows для смены пароля или пользователя, а также запуска диспетчера задач. +Menu.SearchComputersTip = Поиск компьютеров в сети +Menu.SearchPrintersTip = Поиск принтера +Menu.AdminToolsTip = Настройка параметров управления этого компьютера +Menu.ShutdownTip = Закрытие всех открытых программ, завершение работы Windows и выключение компьютера. +Menu.RestartTip = Закрытие всех открытых программ, завершение работы Windows и повторный запуск Windows. +Menu.SleepTip = Перевод компьютера в состояние пониженного энергопотребления и сохранение текущего сеанса в памяти, что позволяет быстро возобновить работу. +Menu.HibernateTip = Сохранение сеанса на диске и выключение компьютера. При включении компьютера Windows восстанавливает текущий сеанс. +Menu.LogOffTip = Закрытие программ и выход из системы. +Menu.DisconnectTip = Отключение текущего сеанса. Можно вновь подключиться к этому сеансу при выполнении входа. +Menu.LockTip = Блокировка этого компьютера. +Menu.UndockTip = Извлечение ноутбука из стыковочного узла. +Menu.SwitchUserTip = Смена пользователей без закрытия программ. +Menu.Empty = (пусто) +Menu.Features = Программы и компоненты +Menu.FeaturesTip = Удаление или изменение программ на этом компьютере. +Menu.SearchPeople = &Людей... +Menu.SortByName = &Сортировать по имени +Menu.Open = &Открыть +Menu.OpenAll = Открыть о&бщее для всех меню +Menu.Explore = &Проводник +Menu.ExploreAll = Проводни&к в общее для всех меню +Menu.MenuSettings = Настройка +Menu.MenuHelp = Справка +Menu.MenuExit = Выход +Menu.LogoffTitle = Выход из Windows +Menu.LogoffPrompt = Вы действительно хотите выйти из системы? +Menu.LogoffYes = В&ыход +Menu.LogoffNo = Н&ет +Menu.RenameTitle = Переименование +Menu.RenamePrompt = &Новое имя: +Menu.RenameOK = ОК +Menu.RenameCancel = Отмена +Menu.Organize = Упорядочение меню "Пуск" +Menu.Expand = &Развернуть +Menu.Collapse = &Свернуть +Menu.NewFolder = Новая папка +Menu.NewShortcut = Новый ярлык +Menu.AutoArrange = Выравнивать &автоматически +Menu.ActionOpen = Открыть +Menu.ActionClose = Закрыть +Menu.ActionExecute = Выполнить +Menu.RemoveList = Удалить &из этого списка +Menu.RemoveAll = &Очистить список последних элементов +Menu.Explorer = Проводник +Menu.Start = Пуск +Menu.StartScreen = Начальный экран +Menu.StartMenu = Меню "Пуск" (Windows) +Menu.PinStart = Закрепить в меню "Пуск" +Menu.PinStartCs = Закрепить в меню "Пуск" (Classic Shell) +Menu.UnpinStartCs = Изъять из меню "Пуск" (Classic Shell) +Menu.MonitorOff = Выключение экрана +Menu.RemoveHighlight = Выключить пометку +Menu.Uninstall = &Удалить +Menu.UninstallTitle = Удалить +Menu.UninstallPrompt = Вы действительно хотите удалить "%s"? +Search.CategorySettings = Параметры +Search.CategoryPCSettings = Параметры ПК +Search.CategoryPrograms = Программы +Search.CategoryDocuments = Документы +Search.CategoryMusic = Музыка +Search.CategoryPictures = Изображения +Search.CategoryVideos = Видео +Search.CategoryFiles = Файлы +Search.CategoryInternet = Интернет +JumpList.Recent = Последние +JumpList.Frequent = Часто используемые +JumpList.Tasks = Задачи +JumpList.Pinned = Закреплено +JumpList.Pin = &Закрепить в списке +JumpList.Unpin = &Изъять из списка +JumpList.Remove = Удалить &из этого списка +JumpList.PinTip = Закрепить в списке +JumpList.UnpinTip = Изъять из списка + + +[sk-SK] - Slovak (Slovakia) +Menu.Programs = Progra&my +Menu.Apps = Aplikácie +Menu.AllPrograms = Všetky programy +Menu.Back = Naspäť +Menu.Favorites = O&bľúbené položky +Menu.Documents = Do&kumenty +Menu.Settings = Nastav&enie +Menu.Search = &Hľadať +Menu.SearchBox = Hľadať +Menu.SearchPrograms = Prehľadať programy a súbory +Menu.SearchInternet = Hľadať na Internete +Menu.Searching = Hľadá sa... +Menu.NoMatch = Kritériám vyhľadávania nevyhovujú žiadne položky. +Menu.MoreResults = Zobraziť ďalšie výsledky +Menu.Help = &Pomoc a technická podpora +Menu.Run = Sp&ustiť... +Menu.Logoff = O&dhlásiť používateľa %s... +Menu.SwitchUser = &Prepnúť používateľa +Menu.Lock = &Zamknúť +Menu.LogOffShort = Odh&lásiť +Menu.Undock = Vybr&ať počítač z doku +Menu.Disconnect = &Odpojiť +Menu.ShutdownBox = &Vypnúť... +Menu.Shutdown = &Vypnúť +Menu.Restart = &Reštartovať +Menu.ShutdownUpdate = Aktualizovať a vypnúť +Menu.RestartUpdate = Aktualizovať a reštartovať +Menu.Sleep = &Uspať +Menu.Hibernate = &Prepnúť do režimu dlhodobého spánku +Menu.ControlPanel = &Ovládací panel +Menu.PCSettings = Nastavenie PC +Menu.Security = Zabezpečenie systému Windows +Menu.Network = Sieťové pripoje&nia +Menu.Printers = &Tlačiarne +Menu.Taskbar = P&anel úloh a ponuka Štart +Menu.SearchFiles = &Súbory alebo priečinky... +Menu.SearchPrinter = &Tlačiarne +Menu.SearchComputers = &Počítače +Menu.UserFilesTip = Obsahuje priečinky pre dokumenty, obrázky, hudbu a ďalšie vaše súbory. +Menu.UserDocumentsTip = Obsahuje priečinok s listami, zostavami a inými dokumentmi a súbormi. +Menu.UserPicturesTip = Obsahuje digitálne fotografie, obrázky a grafické súbory. +Menu.UserMusicTip = Obsahuje hudbu a iné zvukové súbory. +Menu.UserVideosTip = Obsahuje filmy a iné videosúbory. +Menu.NetworkTip = Zobrazí existujúce sieťové pripojenia na tomto počítači a pomôže vytvoriť nové pripojenia. +Menu.PrintersTip = Pridá, odstráni a nakonfiguruje lokálne alebo sieťové tlačiarne. +Menu.TaskbarTip = Prispôsobí ponuku Štart a panel úloh, ako napríklad typy zobrazených položiek a spôsob ich zobrazenia. +Menu.ControlPanelTip = Umožňuje zmeniť nastavenia a prispôsobiť funkcie počítača. +Menu.DocumentsLibTip = Umožňuje získať prístup k listom, zostavám, poznámkam a ďalším typom dokumentov. +Menu.MusicLibTip = Umožňuje prehrávať hudbu a ďalšie zvukové súbory. +Menu.PicturesLibTip = Umožňuje zobraziť a usporiadať digitálne obrázky. +Menu.VideosLibTip = Umožňuje sledovať domáce filmy a ďalšie digitálne videá. +Menu.RecordingsLibTip = Umožňuje sledovať nahrané televízne programy v počítači. +Menu.DownloadTip = Umožňuje vyhľadať položky na prevzatie na Internete a prepojenia na obľúbené webové lokality. +Menu.HomegroupTip = Získajte prístup ku knižniciam a priečinkom, ktoré zdieľanú ostatné osoby v domácej skupine. +Menu.RunTip = Spustí program alebo otvorí priečinok, dokument alebo webovú lokalitu. +Menu.HelpTip = Umožňuje vyhľadať témy Pomocníka, kurzy, informácie pre riešenie problémov a ďalšie služby technickej podpory. +Menu.ProgramsTip = Zobrazí zoznam programov. +Menu.SearchFilesTip = Umožňuje vyhľadať dokumenty, hudbu, obrázky, e-maily a ďalšie položky. +Menu.GamesTip = Umožňuje hrať a spravovať hry v počítači. +Menu.SecurityTip = Ak chcete zmeniť heslo, prepnúť používateľa alebo spustiť Správcu úloh, otvorte okno Možnosti zabezpečenia systému Windows. +Menu.SearchComputersTip = Hľadať počítače v sieti +Menu.SearchPrintersTip = Hľadať tlačiareň +Menu.AdminToolsTip = Umožní konfigurovať nastavenia na správu počítača. +Menu.ShutdownTip = Zatvorí všetky otvorené programy, vypne systém Windows a vypne počítač. +Menu.RestartTip = Zatvorí všetky otvorené programy, vypne systém Windows a znovu ho spustí. +Menu.SleepTip = Uloží reláciu do pamäte a prepne počítač do režimu nízkej spotreby energie, z ktorého možno počítač kedykoľvek rýchlo zapnúť do pôvodného stavu. +Menu.HibernateTip = Uloží reláciu a vypne počítač. Keď ho zapnete, systém Windows obnoví reláciu. +Menu.LogOffTip = Zavrie programy a odhlási používateľa. +Menu.DisconnectTip = Odpojí reláciu. K relácii sa môžete opäť pripojiť pri ďalšom prihlásení. +Menu.LockTip = Zamkne tento počítač. +Menu.UndockTip = Odstráni prenosný počítač z doku. +Menu.SwitchUserTip = Prepne používateľov bez zatvorenia programov. +Menu.Empty = (Prázdne) +Menu.Features = Programy a súčasti +Menu.FeaturesTip = Odinštaluje alebo zmení programy v počítači. +Menu.SearchPeople = Ľu&dia... +Menu.SortByName = &Usporiadať podľa názvov +Menu.Open = &Otvoriť +Menu.OpenAll = Ot&voriť profil All Users +Menu.Explore = &Preskúmať +Menu.ExploreAll = P&reskúmať profil All Users +Menu.MenuSettings = Nastavenie +Menu.MenuHelp = Pomocník +Menu.MenuExit = Skončiť +Menu.LogoffTitle = Odhlásenie zo systému Windows +Menu.LogoffPrompt = Naozaj sa chcete odhlásiť? +Menu.LogoffYes = &Odhlásiť +Menu.LogoffNo = &Nie +Menu.RenameTitle = Premenovanie +Menu.RenamePrompt = &Nový názov: +Menu.RenameOK = OK +Menu.RenameCancel = Zrušiť +Menu.Organize = Usporiadanie ponuky Štart +Menu.Expand = &Rozbaliť +Menu.Collapse = Zb&aliť +Menu.NewFolder = Nový priečinok +Menu.NewShortcut = Nový odkaz +Menu.AutoArrange = Usporiadať &automaticky +Menu.ActionOpen = Otvoriť +Menu.ActionClose = Zavrieť +Menu.ActionExecute = Vykonať +Menu.RemoveList = Odstrániť &z tohto zoznamu +Menu.RemoveAll = &Vymazať zoznam naposledy použitých položiek +Menu.Explorer = Windows Prieskumník +Menu.Start = Štart +Menu.StartScreen = Domovská obrazovka +Menu.StartMenu = Ponuka Štart (Windows) +Menu.PinStart = Pripnúť položku do ponuky Štart +Menu.PinStartCs = Pripnúť položku do ponuky Štart (Classic Shell) +Menu.UnpinStartCs = Zrušiť pripnutie položky v ponuke Štart (Classic Shell) +Menu.MonitorOff = Vypnúť displej +Menu.RemoveHighlight = Odstrániť zvýraznenie +Menu.Uninstall = &Odinštalovať +Menu.UninstallTitle = Odinštalovať +Menu.UninstallPrompt = Naozaj chcete odinštalovať program %s? +Search.CategorySettings = Nastavenia +Search.CategoryPCSettings = Nastavenie PC +Search.CategoryPrograms = Programy +Search.CategoryDocuments = Dokumenty +Search.CategoryMusic = Hudba +Search.CategoryPictures = Obrázky +Search.CategoryVideos = Videá +Search.CategoryFiles = Súbory +Search.CategoryInternet = Internet +JumpList.Recent = Naposledy použité +JumpList.Frequent = Najčastejšie používané +JumpList.Tasks = Úlohy +JumpList.Pinned = Pripnuté +JumpList.Pin = Pr&ipnúť do tohto zoznamu +JumpList.Unpin = Zr&ušiť pripnutie v tomto zozname +JumpList.Remove = Odstrániť &z tohto zoznamu +JumpList.PinTip = Pripnúť do tohto zoznamu +JumpList.UnpinTip = Zrušiť pripnutie v tomto zozname + + +[sl-SI] - Slovenian (Slovenia) +Menu.Programs = Progr&ami +Menu.Apps = Programi +Menu.AllPrograms = Vsi programi +Menu.Back = Nazaj +Menu.Favorites = P&riljubljene +Menu.Documents = &Dokumenti +Menu.Settings = Nas&tavitve +Menu.Search = Is&kanje +Menu.SearchBox = Iskanje +Menu.SearchPrograms = Iskanje programov in datotek +Menu.SearchInternet = Preišči internet +Menu.Searching = Iskanje ... +Menu.NoMatch = Vašemu iskanju ne ustreza noben element. +Menu.MoreResults = Pokaži več rezultatov +Menu.Help = &Pomoč in podpora +Menu.Run = &Zaženi ... +Menu.Logoff = &Odjavi %s ... +Menu.SwitchUser = P&reklopi med uporabniki +Menu.Lock = Z&akleni +Menu.LogOffShort = &Odjava +Menu.Undock = Razdr&uži računalnik +Menu.Disconnect = Pr&ekini povezavo +Menu.ShutdownBox = Zaustavitev &sistema ... +Menu.Shutdown = &Zaustavitev sistema +Menu.Restart = &Vnovični zagon +Menu.ShutdownUpdate = Posodobi in zaustavi +Menu.RestartUpdate = Posodobi in zaženi znova +Menu.Sleep = &Mirovanje +Menu.Hibernate = &Hibernacija +Menu.ControlPanel = &Nadzorna plošča +Menu.PCSettings = Nastavitve računalnika +Menu.Security = Varnost sistema Windows +Menu.Network = &Omrežne povezave +Menu.Printers = &Tiskalniki +Menu.Taskbar = Op&ravilna vrstica in meni »Start« +Menu.SearchFiles = &Datotek ali map ... +Menu.SearchPrinter = &Tiskalnika +Menu.SearchComputers = &Računalnikov +Menu.UserFilesTip = Vsebuje mape za dokumente, slike, glasbo in druge datoteke v vaši lasti. +Menu.UserDocumentsTip = Vsebuje pisma, poročila in druge dokumente ter datoteke. +Menu.UserPicturesTip = Vsebuje digitalne fotografije, slike in grafične datoteke. +Menu.UserMusicTip = Vsebuje glasbo in druge zvočne datoteke. +Menu.UserVideosTip = Vsebuje filme in druge videodatoteke. +Menu.NetworkTip = Prikaže obstoječe omrežne povezave v tem računalniku in vam pomaga ustvarjati nove +Menu.PrintersTip = Doda, odstrani in konfigurira lokalne ter omrežne tiskalnike. +Menu.TaskbarTip = Prilagodi meni »Start« in opravilno vrstico, kot so vrste elementov, ki naj se prikažejo, ter način njihovega prikaza. +Menu.ControlPanelTip = Spremenite nastavitve in prilagodite način delovanja računalnika. +Menu.DocumentsLibTip = Dostopajte do pisem, poročil, obvestil in drugih vrst dokumentov. +Menu.MusicLibTip = Predvajajte glasbene in druge zvočne datoteke. +Menu.PicturesLibTip = Oglejte si digitalne slike in jih razvrstite. +Menu.VideosLibTip = Glejte domače filme in druge digitalne videe. +Menu.RecordingsLibTip = Glejte TV-programe, posnete v računalniku. +Menu.DownloadTip = Poiščite prenose iz interneta in povezave do priljubljenih spletnih mest. +Menu.HomegroupTip = Dostop do knjižnic in map, za katere skupno rabo omogočijo druge osebe v domači skupini. +Menu.RunTip = Odpre program, mapo, dokument ali spletno mesto. +Menu.HelpTip = Poiščite teme pomoči, vadnice, odpravljanje težav in druge storitve za podporo. +Menu.ProgramsTip = Prikaže seznam vaših programov. +Menu.SearchFilesTip = Poiščite dokumente, glasbo, slike, e-pošto in še kaj. +Menu.GamesTip = Igranje in upravljanje nameščenih iger v računalniku. +Menu.SecurityTip = Zaženite možnosti varnosti sistema Windows, če želite spremeniti geslo, preklopiti med uporabniki ali zagnati upravitelja opravil. +Menu.SearchComputersTip = Iskanje računalnikov v omrežju +Menu.SearchPrintersTip = Iskanje tiskalnika +Menu.AdminToolsTip = Konfigurira računalnikove skrbniške nastavitve. +Menu.ShutdownTip = Zapre vse odprte programe, zaustavi sistem Windows in nato izklopi računalnik. +Menu.RestartTip = Zapre vse odprte programe, zaustavi sistem Windows in ga nato znova zažene. +Menu.SleepTip = Ohrani vašo sejo v pomnilniku in postavi računalnik v stanje nizke porabe, tako da lahko hitro nadaljujete delo. +Menu.HibernateTip = Shrani vašo sejo in izklopi računalnik. Ko računalnik vklopite, sistem Windows obnovi vašo sejo. +Menu.LogOffTip = Zapri programe in se odjavi. +Menu.DisconnectTip = Prekine povezavo s sejo. Znova jo lahko vzpostavite po prijavi. +Menu.LockTip = Zakleni ta računalnik. +Menu.UndockTip = Odstrani prenosni računalnik iz združitvene postaje. +Menu.SwitchUserTip = Preklop med uporabniki, ne da bi se programi zaprli. +Menu.Empty = (Prazno) +Menu.Features = Programi in funkcije +Menu.FeaturesTip = Odstranitev ali spreminjanje programov v računalniku. +Menu.SearchPeople = &Za osebe ... +Menu.SortByName = &Razvrsti po imenih +Menu.Open = &Odpri +Menu.OpenAll = O&dpri mapo »All users« +Menu.Explore = R&azišči +Menu.ExploreAll = &Razišči mapo »All users« +Menu.MenuSettings = Nastavitve +Menu.MenuHelp = Pomoč +Menu.MenuExit = Izhod +Menu.LogoffTitle = Odjava iz sistema Windows +Menu.LogoffPrompt = Ali ste prepričani, da se želite odjaviti? +Menu.LogoffYes = &Odjavi se +Menu.LogoffNo = &Ne +Menu.RenameTitle = Preimenuj +Menu.RenamePrompt = &Novo ime: +Menu.RenameOK = V redu +Menu.RenameCancel = Prekliči +Menu.Organize = Organiziraj meni Start +Menu.Expand = R&azširi +Menu.Collapse = &Strni +Menu.NewFolder = Nova mapa +Menu.NewShortcut = Nova bližnjica +Menu.AutoArrange = Samod&ejno razporedi +Menu.ActionOpen = Odpri +Menu.ActionClose = Zapri +Menu.ActionExecute = Izvedi +Menu.RemoveList = Od&strani s tega seznama +Menu.RemoveAll = &Izbriši seznam nedavnih elementov +Menu.Explorer = Raziskovalec +Menu.Start = Start +Menu.StartScreen = Začetni zaslon +Menu.StartMenu = Meni »Start« (Windows) +Menu.PinStart = Pripni v meni »Start« +Menu.PinStartCs = Pripni v meni »Start«. (Classic Shell) +Menu.UnpinStartCs = Odpni iz menija »Start«. (Classic Shell) +Menu.MonitorOff = Izklopi prikaz +Menu.RemoveHighlight = Odstrani označitev +Menu.Uninstall = &Odstrani +Menu.UninstallTitle = Odstrani +Menu.UninstallPrompt = Ali ste prepričani, da želite odstraniti %s? +Search.CategorySettings = Nastavitve +Search.CategoryPCSettings = Nastavitve računalnika +Search.CategoryPrograms = Programi +Search.CategoryDocuments = Dokumenti +Search.CategoryMusic = Glasba +Search.CategoryPictures = Slike +Search.CategoryVideos = Videi +Search.CategoryFiles = Datoteke +Search.CategoryInternet = Internet +JumpList.Recent = Nedavno +JumpList.Frequent = Pogosto +JumpList.Tasks = Opravila +JumpList.Pinned = Pripeto +JumpList.Pin = &Pripni na ta seznam +JumpList.Unpin = &Odpni s tega seznama +JumpList.Remove = Od&strani s tega seznama +JumpList.PinTip = Pripni na ta seznam +JumpList.UnpinTip = Odpni s tega seznama + + +[sr-Latn-CS] - Serbian (Latin, Serbia) +Menu.Programs = &Programi +Menu.Apps = Aplikacije +Menu.AllPrograms = Svi programi +Menu.Back = Nazad +Menu.Favorites = Omiljene& lokacije +Menu.Documents = &Dokumenti +Menu.Settings = Postavk&e +Menu.Search = Pre&traži +Menu.SearchBox = Pretraži +Menu.SearchPrograms = Pretraži programe i datoteke +Menu.SearchInternet = Pretraži Internet +Menu.Searching = Pretraživanje... +Menu.NoMatch = Nijedna stavka se ne podudara sa pretragom. +Menu.MoreResults = Pogledajte više rezultata +Menu.Help = Po&moć i podrška +Menu.Run = Po&kreni... +Menu.Logoff = &Odjavi se sa %s... +Menu.SwitchUser = P&romeni korisnika +Menu.Lock = Z&aključaj +Menu.LogOffShort = &Odjavi se +Menu.Undock = Odvoji računar od &bazne stanice +Menu.Disconnect = Prekini &vezu +Menu.ShutdownBox = &Isključi... +Menu.Shutdown = &Isključi +Menu.Restart = &Ponovo pokreni +Menu.ShutdownUpdate = Ažuriraj i isključi +Menu.RestartUpdate = Ažuriraj i ponovo pokreni +Menu.Sleep = &Stanje spavanja +Menu.Hibernate = &U stanju hibernacije +Menu.ControlPanel = &Kontrolna tabla +Menu.PCSettings = Postavke računara +Menu.Security = Windows bezbednost +Menu.Network = &Mrežne veze +Menu.Printers = Št&ači +Menu.Taskbar = &Traka zadataka i „Start“ meni +Menu.SearchFiles = &Za datoteke i fascikle... +Menu.SearchPrinter = &Za štampač +Menu.SearchComputers = &Za računare +Menu.UserFilesTip = Sadrži fascikle za dokumente, slike, muziku i druge datoteke koje vam pripadaju. +Menu.UserDocumentsTip = Sadrži pisma, izveštaje i druge dokumente i datoteke. +Menu.UserPicturesTip = Sadrži digitalne fotografije, slike i grafičke datoteke. +Menu.UserMusicTip = Sadrži muziku i druge audio datoteke. +Menu.UserVideosTip = Sadrži filmove i druge video datoteke. +Menu.NetworkTip = Prikazuje postojeće mrežne veze ovog računara i pomaže pri kreiranju novih +Menu.PrintersTip = Dodajte, uklonite i konfigurišite lokalne i mrežne štampače. +Menu.TaskbarTip = Prilagodite „Start“ meni i traku zadataka, npr. tipove stavki koje će biti prikazane i način njihovog pojavljivanja. +Menu.ControlPanelTip = Promenite postavke i prilagodite funkcionalnost računara. +Menu.DocumentsLibTip = Pristupajte pismima, izveštajima, beleškama i drugim vrstama dokumenata. +Menu.MusicLibTip = Reprodukujte muziku i druge zvučne datoteke. +Menu.PicturesLibTip = Prikazujte i organizujte digitalne slike. +Menu.VideosLibTip = Gledajte kućne filmove i druge digitalne video zapise. +Menu.RecordingsLibTip = Gledajte TV programe snimljene na računaru. +Menu.DownloadTip = Pronađite Internet preuzimanja i veze ka omiljenim Veb lokacijama. +Menu.HomegroupTip = Pristupite bibliotekama i fasciklama koje dele druge osobe u matičnoj grupi. +Menu.RunTip = Otvara program, fasciklu, dokument ili Veb lokaciju. +Menu.HelpTip = Pronađite teme pomoći, podučavanja, rešavanje problema i druge usluge podrške. +Menu.ProgramsTip = Otvara listu programa. +Menu.SearchFilesTip = Tražite dokumente, muziku, slike, e-poštu i još mnogo toga. +Menu.GamesTip = Igrajte i upravljajte igrama na računaru. +Menu.SecurityTip = Pokrenite Windows opcije bezbednosti da biste promenili lozinku, promenili korisnika ili pokrenuli upravljač zadacima. +Menu.SearchComputersTip = Pronađi računare u mreži +Menu.SearchPrintersTip = Pronađi štampač +Menu.AdminToolsTip = Konfigurišite administrativne postavke na svom računaru. +Menu.ShutdownTip = Zatvara sve otvorene programe, isključuje Windows i zatim isključuje računar. +Menu.RestartTip = Zatvara sve otvorene programe, isključuje Windows i zatim ponovo pokreće Windows. +Menu.SleepTip = Čuva sesiju u memoriji i stavlja računar u stanje niske potrošnje tako da možete brzo da nastavite sa radom. +Menu.HibernateTip = Čuva sesiju i isključuje računar. Kada uključite računar, Windows vraća sesiju u prethodno stanje. +Menu.LogOffTip = Zatvori programe i odjavi se. +Menu.DisconnectTip = Prekida vezu sesije. Možete se ponovo povezati sa sesijom kad se ponovo prijavite. +Menu.LockTip = Zaključaj ovaj računar. +Menu.UndockTip = Uklanja laptop ili notebook računar sa bazne stanice. +Menu.SwitchUserTip = Promeni korisnike bez zatvaranja programa. +Menu.Empty = (Prazno) +Menu.Features = Programi i funkcije +Menu.FeaturesTip = Deinstalirajte ili promenite programe na računaru. +Menu.SearchPeople = &Za osobe... +Menu.SortByName = &Sortiraj po imenu +Menu.Open = &Otvori +Menu.OpenAll = O&tvori sve korisnike +Menu.Explore = &Istraži +Menu.ExploreAll = Istraži sve &korisnike +Menu.MenuSettings = Postavke +Menu.MenuHelp = Pomoć +Menu.MenuExit = Izađi +Menu.LogoffTitle = Odjava iz Windowsa +Menu.LogoffPrompt = Želite li zaista da se odjavite? +Menu.LogoffYes = &Odjavi se +Menu.LogoffNo = &Ne +Menu.RenameTitle = Preimenovanje +Menu.RenamePrompt = &Novo ime: +Menu.RenameOK = U redu +Menu.RenameCancel = Otkaži +Menu.Organize = Organizovanje menija „Start“ +Menu.Expand = R&azvij +Menu.Collapse = Sk&upi +Menu.NewFolder = Nova fascikla +Menu.NewShortcut = Nova prečica +Menu.AutoArrange = Rasporedi &automatski +Menu.ActionOpen = Otvori +Menu.ActionClose = Zatvori +Menu.ActionExecute = Izvrši +Menu.RemoveList = &Ukloni sa ovog spiska +Menu.RemoveAll = O&briši listu nedavno korišćenih stavki +Menu.Explorer = Windows Explorer +Menu.Start = Pokreni +Menu.StartScreen = Početni ekran +Menu.StartMenu = „Start“ meni (Windows) +Menu.PinStart = Dodaj u „Start“ meni +Menu.PinStartCs = Dodaj u „Start“ meni (Classic Shell) +Menu.UnpinStartCs = Ukloni iz „Start“ menija (Classic Shell) +Menu.MonitorOff = Isključi displej +Menu.RemoveHighlight = Ukloni istaknuti sadržaj +Menu.Uninstall = &Deinstaliraj +Menu.UninstallTitle = Deinstaliraj +Menu.UninstallPrompt = Želite li zaista da deinstalirate %s? +Search.CategorySettings = Postavke +Search.CategoryPCSettings = Postavke računara +Search.CategoryPrograms = Programs +Search.CategoryDocuments = Dokumenti +Search.CategoryMusic = Muzika +Search.CategoryPictures = Slike +Search.CategoryVideos = Video zapisi +Search.CategoryFiles = Datoteke +Search.CategoryInternet = Internet +JumpList.Recent = Nedavno +JumpList.Frequent = Često +JumpList.Tasks = Zadaci +JumpList.Pinned = Dodato +JumpList.Pin = Zakač&i na ovu listu +JumpList.Unpin = &Otkači sa ove liste +JumpList.Remove = U&kloni sa ovog spiska +JumpList.PinTip = Zakači na ovu listu +JumpList.UnpinTip = Otkači sa ove liste + + +[sv-SE] - Swedish (Sweden) +Menu.Programs = &Program +Menu.Apps = Appar +Menu.AllPrograms = Alla program +Menu.Back = Föregående +Menu.Favorites = &Favoriter +Menu.Documents = &Dokument +Menu.Settings = &Inställningar +Menu.Search = &Sök +Menu.SearchBox = Sök +Menu.SearchPrograms = Sök bland program och filer +Menu.SearchInternet = Sök på Internet +Menu.Searching = Söker... +Menu.NoMatch = Inga objekt matchade sökningen. +Menu.MoreResults = Visa fler resultat +Menu.Help = &Hjälp och support +Menu.Run = K&ör... +Menu.Logoff = &Logga ut %s... +Menu.SwitchUser = &Växla användare +Menu.Lock = L&ås +Menu.LogOffShort = &Logga ut +Menu.Undock = K&oppla från datorn +Menu.Disconnect = Koppla fr&ån +Menu.ShutdownBox = &Avsluta... +Menu.Shutdown = Stäng &av +Menu.Restart = &Starta om +Menu.ShutdownUpdate = Uppdatera och stäng av +Menu.RestartUpdate = Uppdatera och starta om +Menu.Sleep = &Vila +Menu.Hibernate = &Viloläge +Menu.ControlPanel = &Kontrollpanelen +Menu.PCSettings = Datorinställningar +Menu.Security = Windows-säkerhet +Menu.Network = &Nätverksanslutningar +Menu.Printers = &Skrivare +Menu.Taskbar = &Aktivitetsfältet och Start-menyn +Menu.SearchFiles = E&fter filer eller mappar... +Menu.SearchPrinter = Efter &skrivare +Menu.SearchComputers = &Efter datorer +Menu.UserFilesTip = Innehåller mappar för dokument, bilder, musik och andra filer som tillhör dig. +Menu.UserDocumentsTip = Innehåller brev, rapporter och andra dokument och filer. +Menu.UserPicturesTip = Innehåller digitala foton, bilder och grafikfiler. +Menu.UserMusicTip = Innehåller musik och andra ljudfiler. +Menu.UserVideosTip = Innehåller filmer och andra videofiler. +Menu.NetworkTip = Visar befintliga nätverks- och fjärranslutningar på den här datorn samt hjälper dig att skapa nya +Menu.PrintersTip = Lägg till, ta bort och konfigurera lokala och nätverksskrivare. +Menu.TaskbarTip = Anpassa Start-menyn och Aktivitetsfältet, som exempelvis vilka objekt som ska synas och hur de ska visas. +Menu.ControlPanelTip = Ändra inställningar och anpassa datorns funktioner. +Menu.DocumentsLibTip = Använd brev, rapporter, anteckningar och andra dokument. +Menu.MusicLibTip = Spela musik och andra ljudfiler. +Menu.PicturesLibTip = Visa och ordna digitala bilder. +Menu.VideosLibTip = Titta på egna filmer och andra digitala videofilmer. +Menu.RecordingsLibTip = Titta på TV-program som har spelats in på datorn. +Menu.DownloadTip = Sök efter filer som du har hämtat från Internet och länkar till favoritwebbplatser. +Menu.HomegroupTip = Få åtkomst till bibliotek och mappar som delas ut av andra personer i hemgruppen. +Menu.RunTip = Öppnar ett program, en mapp, ett dokument eller en webbplats. +Menu.HelpTip = Hitta hjälpavsnitt, självstudier, felsökning och andra supporttjänster. +Menu.ProgramsTip = Öppnar en lista över program på datorn. +Menu.SearchFilesTip = Sök efter dokument, musik, bilder, e-post och mycket mer. +Menu.GamesTip = Spela och hantera spel på datorn. +Menu.SecurityTip = Visa Windows-säkerhetsalternativ om du vill ändra lösenord, växla användare eller starta Aktivitetshanteraren. +Menu.SearchComputersTip = Sök efter datorer på nätverket +Menu.SearchPrintersTip = Sök efter en skrivare +Menu.AdminToolsTip = Konfigurera administrationsinställningar för datorn. +Menu.ShutdownTip = Stänger alla öppna program, avslutar Windows och stänger sedan av datorn. +Menu.RestartTip = Stänger alla öppna program, avslutar Windows och startar sedan Windows igen. +Menu.SleepTip = Behåller sessionen i minnet och försätter datorn i energisparläge så att du snabbt kan återgå till arbetet. +Menu.HibernateTip = Sparar sessionen och stänger av datorn. Sessionen återställs när du startar datorn. +Menu.LogOffTip = Stänger alla program och loggar ut. +Menu.DisconnectTip = Kopplar från sessionen. Du kan ansluta till den här sessionen på nytt när du loggar in igen. +Menu.LockTip = Låser den här datorn. +Menu.UndockTip = Kopplar från din bärbara dator från dockningsstationen. +Menu.SwitchUserTip = Växlar användare utan att stänga program. +Menu.Empty = (Tom) +Menu.Features = Program och funktioner +Menu.FeaturesTip = Avinstallera eller ändra program på datorn. +Menu.SearchPeople = Efter &personer... +Menu.SortByName = Sortera efter &namn +Menu.Open = &Öppna +Menu.OpenAll = Öppna &delade Start-menyn +Menu.Explore = &Utforska +Menu.ExploreAll = Utf&orska delade Start-menyn +Menu.MenuSettings = Inställningar +Menu.MenuHelp = Hjälp +Menu.MenuExit = Avsluta +Menu.LogoffTitle = Logga ut +Menu.LogoffPrompt = Vill du logga ut? +Menu.LogoffYes = &Logga ut +Menu.LogoffNo = N&ej +Menu.RenameTitle = Byt namn +Menu.RenamePrompt = &Nytt namn: +Menu.RenameOK = OK +Menu.RenameCancel = Avbryt +Menu.Organize = Organisera Start-menyn +Menu.Expand = Exp&andera +Menu.Collapse = &Dölj +Menu.NewFolder = Ny mapp +Menu.NewShortcut = Ny genväg +Menu.AutoArrange = &Ordna automatiskt +Menu.ActionOpen = Öppna +Menu.ActionClose = Stäng +Menu.ActionExecute = Kör +Menu.RemoveList = &Ta bort från den här listan +Menu.RemoveAll = &Rensa listan Tidigare +Menu.Explorer = Utforskaren +Menu.Start = Start +Menu.StartScreen = Startskärmen +Menu.StartMenu = Startmenyn (Windows) +Menu.PinStart = Fäst på Start-menyn +Menu.PinStartCs = Fäst på Start-menyn (Classic Shell) +Menu.UnpinStartCs = Ta bort från Start-menyn (Classic Shell) +Menu.MonitorOff = Stänga av bildskärmen +Menu.RemoveHighlight = Ta bort fokus +Menu.Uninstall = &Avinstallera +Menu.UninstallTitle = Avinstallera +Menu.UninstallPrompt = Vill du avinstallera %s? +Search.CategorySettings = Inställningar +Search.CategoryPCSettings = Datorinställningar +Search.CategoryPrograms = Program +Search.CategoryDocuments = Dokument +Search.CategoryMusic = Musik +Search.CategoryPictures = Bilder +Search.CategoryVideos = Filmer +Search.CategoryFiles = Filer +Search.CategoryInternet = Internet +JumpList.Recent = Senast använda +JumpList.Frequent = Ofta använda +JumpList.Tasks = Aktiviteter +JumpList.Pinned = Fastnålat +JumpList.Pin = &Fäst i den här listan +JumpList.Unpin = &Ta bort från den här listan +JumpList.Remove = &Ta bort från den här listan +JumpList.PinTip = Fäst i den här listan +JumpList.UnpinTip = Ta bort från den här listan + + +[th-TH] - Thai (Thailand) +Menu.Programs = โ&ปรแกรม +Menu.Apps = โปรแกรม +Menu.AllPrograms = โปรแกรมทั้งหมด +Menu.Back = ย้อนกลับ +Menu.Favorites = ร&ายการโปรด +Menu.Documents = เอก&สาร +Menu.Settings = &การตั้งค่า +Menu.Search = &ค้นหา +Menu.SearchBox = ค้นหา +Menu.SearchPrograms = ค้นหาโปรแกรมและแฟ้ม +Menu.SearchInternet = ค้นหาอินเทอร์เน็ต +Menu.Searching = กำลังค้นหา... +Menu.NoMatch = ไม่มีรายการที่ตรงกับการค้นหาของคุณ +Menu.MoreResults = ดูผลลัพธ์เพิ่มเติม +Menu.Help = &บริการช่วยเหลือและวิธีใช้ +Menu.Run = เรียก&ใช้... +Menu.Logoff = ออก&จากระบบ %s... +Menu.SwitchUser = สลับ&ผู้ใช้ +Menu.Lock = &ล็อก +Menu.LogOffShort = &ออกจากระบบ +Menu.Undock = ปล&ดชุดต่ออุปกรณ์ +Menu.Disconnect = &ยกเลิกการเชื่อมต่อ +Menu.ShutdownBox = ปิดเครื่&อง... +Menu.Shutdown = ปิ&ดเครื่อง +Menu.Restart = เริ่มการทำงานใ&หม่ +Menu.ShutdownUpdate = ปรับปรุงและปิดเครื่อง +Menu.RestartUpdate = ปรับปรุงและเริ่มระบบของคอมพิวเตอร์ใหม่ +Menu.Sleep = &สลีป +Menu.Hibernate = ไฮเบอร์เ&นต +Menu.ControlPanel = แ&ผงควบคุม +Menu.PCSettings = การตั้งค่าพีซี +Menu.Security = การรักษาความปลอดภัยของ Windows +Menu.Network = การเชื่อมต่อเค&รือข่าย +Menu.Printers = เ&ครื่องพิมพ์ +Menu.Taskbar = แ&ถบงานและเมนู 'เริ่ม' +Menu.SearchFiles = แ&ฟ้มหรือโฟลเดอร์... +Menu.SearchPrinter = เ&ครื่องพิมพ์ +Menu.SearchComputers = &คอมพิวเตอร์ +Menu.UserFilesTip = ประกอบด้วยโฟลเดอร์สำหรับเอกสาร รูปภาพ เพลง และแฟ้มอื่นๆ ที่เป็นของคุณ +Menu.UserDocumentsTip = เก็บจดหมาย รายงาน รวมทั้งเอกสารและแฟ้มอื่นๆ +Menu.UserPicturesTip = เก็บรูปถ่ายดิจิทัล รูป และแฟ้มกราฟิกต่างๆ +Menu.UserMusicTip = มีเพลงและแฟ้มเสียงอื่นๆ +Menu.UserVideosTip = มีภาพยนตร์และแฟ้มวิดีโออื่นๆ +Menu.NetworkTip = แสดงการเชื่อมต่อเครือข่ายที่มีอยู่บนคอมพิวเตอร์นี้ และช่วยคุณสร้างการเชื่อมต่อเครือข่ายใหม่ +Menu.PrintersTip = เพิ่ม เอาออก และกำหนดค่าเครื่องพิมพ์เฉพาะที่และเครื่องพิมพ์เครือข่าย +Menu.TaskbarTip = กำหนดเมนู 'เริ่ม' และแถบเครื่องมือเอง เช่น ชนิดของรายการที่จะแสดงและลักษณะที่จะปรากฏของเมนู 'เริ่ม' และแถบเครื่องมือ +Menu.ControlPanelTip = เปลี่ยนแปลงการตั้งค่าและกำหนดฟังก์ชันของคอมพิวเตอร์ของคุณ +Menu.DocumentsLibTip = เข้าถึงจดหมาย รายงาน บันทึกย่อ และเอกสารประเภทอื่นๆ +Menu.MusicLibTip = เล่นดนตรีและแฟ้มเสียงอื่นๆ +Menu.PicturesLibTip = ดูและจัดระเบียบรูปภาพดิจิทัล +Menu.VideosLibTip = ดูภาพยนตร์ถ่ายทำเองและวิดีโอดิจิทัลอื่นๆ +Menu.RecordingsLibTip = ดูรายการทีวีที่บันทึกบนคอมพิวเตอร์ +Menu.DownloadTip = ค้นหารายการดาวน์โหลดบนอินเทอร์เน็ตและการเชื่อมโยงไปยังเว็บไซต์โปรด +Menu.HomegroupTip = เข้าถึงไลบรารีและโฟลเดอร์ต่างๆ ที่ผู้อื่นเปิดให้ใช้ร่วมกันในโฮมกรุ๊ปของคุณ +Menu.RunTip = เปิดโปรแกรม โฟลเดอร์ เอกสาร หรือเว็บไซต์ +Menu.HelpTip = ค้นหาแหล่งข้อมูลสำหรับหัวข้อวิธีใช้ บทช่วยสอน การแก้ไขปัญหา และบริการช่วยเหลืออื่นๆ +Menu.ProgramsTip = เปิดรายชื่อของโปรแกรมของคุณ +Menu.SearchFilesTip = ค้นหาเอกสาร ดนตรี รูปภาพ อีเมล และอื่นๆอีกมาก +Menu.GamesTip = เล่นและจัดการกับเกมบนเครื่องคอมพิวเตอร์ของคุณ +Menu.SecurityTip = เปิดใช้ตัวเลือก 'การรักษาความปลอดภัยของ Windows' เพื่อเปลี่ยนรหัสผ่าน สลับผู้ใช้ หรือเริ่ม 'ตัวจัดการงาน' +Menu.SearchComputersTip = ค้นหาคอมพิวเตอร์บนเครือข่าย +Menu.SearchPrintersTip = ค้นหาเครื่องพิมพ์ +Menu.AdminToolsTip = กำหนดค่าการตั้งค่าเกี่ยวกับการจัดการ +สำหรับคอมพิวเตอร์ของคุณ +Menu.ShutdownTip = ปิดโปรแกรมที่เปิดอยู่ทั้งหมด ปิดระบบ Windows แล้วปิดคอมพิวเตอร์ของคุณ +Menu.RestartTip = ปิดโปรแกรมที่เปิดอยู่ทั้งหมด ปิดระบบ Windows แล้วเริ่มการทำงานของ Windows อีกครั้ง +Menu.SleepTip = รักษาเซสชันของคุณในหน่วยความจำ และทำให้คอมพิวเตอร์อยู่ในสถานะที่ใช้พลังงานต่ำ เพื่อให้คุณสามารถกลับมาดำเนินการต่อได้อย่างรวดเร็ว +Menu.HibernateTip = บันทึกเซสชันของคุณ และปิดเครื่องคอมพิวเตอร์ เมื่อคุณเปิดคอมพิวเตอร์ Windows จะคืนค่าเซสชันของคุณ +Menu.LogOffTip = ปิดโปรแกรมและออกจากระบบ +Menu.DisconnectTip = ยกเลิกการเชื่อมต่อเซสชันของคุณ คุณสามารถเชื่อมต่อใหม่ไปยังเซสชันนี้ได้เมื่อคุณเข้าสู่ระบบอีกครั้ง +Menu.LockTip = ล็อกคอมพิวเตอร์นี้ +Menu.UndockTip = เอาคอมพิวเตอร์แล็ปท็อปหรือโน้ตบุ๊กของคุณออกจากที่วางเทียบ +Menu.SwitchUserTip = สลับผู้ใช้โดยไม่ปิดโปรแกรม +Menu.Empty = (ว่าง) +Menu.Features = โปรแกรมและคุณลักษณะ +Menu.FeaturesTip = ถอนการติดตั้งหรือเปลี่ยนแปลงโปรแกรมบนคอมพิวเตอร์ของคุณ +Menu.SearchPeople = สำหรับ&บุคคล... +Menu.SortByName = เรียงลำดั&บตามชื่อ +Menu.Open = เ&ปิด +Menu.OpenAll = &เปิดโฟลเดอร์ All Users +Menu.Explore = สำรว&จ +Menu.ExploreAll = &สำรวจโฟลเดอร์ All Users +Menu.MenuSettings = การตั้งค่า +Menu.MenuHelp = วิธีใช้ +Menu.MenuExit = ออก +Menu.LogoffTitle = ออกจากระบบ Windows +Menu.LogoffPrompt = คุณแน่ใจหรือไม่ว่าคุณต้องการออกจากระบบ +Menu.LogoffYes = &ออกจากระบบ +Menu.LogoffNo = ไ&ม่ใช่ +Menu.RenameTitle = เปลี่ยนชื่อ +Menu.RenamePrompt = &ชื่อใหม่: +Menu.RenameOK = ตกลง +Menu.RenameCancel = ยกเลิก +Menu.Organize = จัดระเบียบเมนู 'เริ่ม' +Menu.Expand = &ขยาย +Menu.Collapse = &ยุบ +Menu.NewFolder = สร้างโฟลเดอร์ +Menu.NewShortcut = ทางลัดใหม่ +Menu.AutoArrange = จัดเรียงอัต&โนมัติ +Menu.ActionOpen = เปิด +Menu.ActionClose = ปิด +Menu.ActionExecute = ปฏิบัติการ +Menu.RemoveList = เอาออก&จากรายชื่อนี้ +Menu.RemoveAll = &ล้างรายการล่าสุด +Menu.Explorer = Windows Explorer +Menu.Start = เริ่ม +Menu.StartScreen = หน้าจอเริ่ม +Menu.StartMenu = เมนูเริ่ม (Windows) +Menu.PinStart = ตรึงกับเมนูเริ่ม +Menu.PinStartCs = ตรึงกับเมนูเริ่ม (Classic Shell) +Menu.UnpinStartCs = ถอนการตรึงออกจากเมนูเริ่ม (Classic Shell) +Menu.MonitorOff = ปิดจอแสดงผล +Menu.RemoveHighlight = เอาไฮไลท์ออก +Menu.Uninstall = &ถอนการติดตั้ง +Menu.UninstallTitle = ถอนการติดตั้ง +Menu.UninstallPrompt = คุณแน่ใจหรือไม่ว่าคุณต้องการถอนการติดตั้ง %s +Search.CategorySettings = การตั้งค่า +Search.CategoryPCSettings = การตั้งค่าพีซี +Search.CategoryPrograms = โปรแกรม +Search.CategoryDocuments = เอกสาร +Search.CategoryMusic = เพลง +Search.CategoryPictures = รูปภาพ +Search.CategoryVideos = วิดีโอ +Search.CategoryFiles = แฟ้ม +Search.CategoryInternet = อินเทอร์เน็ต +JumpList.Recent = ล่าสุด +JumpList.Frequent = ที่ใช้บ่อย +JumpList.Tasks = งาน +JumpList.Pinned = ตรึงไว้ +JumpList.Pin = &ตรึงเข้ากับรายการนี้ +JumpList.Unpin = &ถอนการตรึงออกจากรายการนี้ +JumpList.Remove = เอาออก&จากรายการนี้ +JumpList.PinTip = ตรึงเข้ากับรายการนี้ +JumpList.UnpinTip = ถอนการตรึงออกจากรายการนี้ + + +[tr-TR] - Turkish (Turkey) +Menu.Programs = Progra&mlar +Menu.Apps = Uygulamalar +Menu.AllPrograms = Tüm Programlar +Menu.Back = Geri +Menu.Favorites = &Sık Kullanılanlar +Menu.Documents = &Belgeler +Menu.Settings = Ayar&lar +Menu.Search = &Ara +Menu.SearchBox = Ara +Menu.SearchPrograms = Programları ve dosyaları ara +Menu.SearchInternet = Internet'te ara +Menu.Searching = Arıyor... +Menu.NoMatch = Aramanızla eşleşen öğe yok. +Menu.MoreResults = Diğer sonuçlar +Menu.Help = &Yardım ve Destek +Menu.Run = Çal&ıştır... +Menu.Logoff = %s Oturumunu &Kapat... +Menu.SwitchUser = &Kullanıcı değiştir +Menu.Lock = Kili&tle +Menu.LogOffShort = &Oturumu Kapat +Menu.Undock = Bilgisaya&rı Çıkar +Menu.Disconnect = Ba&ğlantıyı Kes +Menu.ShutdownBox = B&ilgisayarı Kapat... +Menu.Shutdown = &Bilgisayarı Kapat +Menu.Restart = &Yeniden Başlat +Menu.ShutdownUpdate = Güncelleştir ve kapat +Menu.RestartUpdate = Güncelleştir ve yeniden başlat +Menu.Sleep = &Uyku +Menu.Hibernate = &Hazırda Beklet +Menu.ControlPanel = &Denetim Masası +Menu.PCSettings = Bilgisayar ayarları +Menu.Security = Windows Güvenliği +Menu.Network = &Ağ Bağlantıları +Menu.Printers = &Yazıcılar +Menu.Taskbar = &Görev Çubuğu ve Başlat Menüsü +Menu.SearchFiles = &Dosya ya da Klasör... +Menu.SearchPrinter = &Yazıcı için +Menu.SearchComputers = &Bilgisayar için +Menu.UserFilesTip = Size ait Belge, Resim, Müzik dosyalarının ve diğer dosyaların klasörlerini içerir. +Menu.UserDocumentsTip = Mektup, rapor ve benzeri belge ve dosyaları içerir. +Menu.UserPicturesTip = Dijital foto, resim ve grafik dosyaları içerir. +Menu.UserMusicTip = Müzik ve diğer ses dosyalarını içerir. +Menu.UserVideosTip = Film ve diğer video dosyalarını içerir. +Menu.NetworkTip = Bu bilgisayar üzerindeki ağ bağlantılarını görüntüleyip yenilerini oluşturmanıza yardımcı olur +Menu.PrintersTip = Yerel yazıcıları ve ağ yazıcılarını ekler, kaldırır ve yapılandırır. +Menu.TaskbarTip = Görüntülenecek öğeler ve ve nasıl görünmeleri gerektiği gibi konularda Başlat Menüsünü ve görev çubuğunu özelleştir. +Menu.ControlPanelTip = Bilgisayarınızın ayarlarını değiştirin ve işlevlerini özelleştirin. +Menu.DocumentsLibTip = Mektuplara, raporlara, notlara ve diğer belge türlerine erişin. +Menu.MusicLibTip = Müzik ve diğer ses dosyalarını çalın. +Menu.PicturesLibTip = Dijital resimleri görüntüleyin ve düzenleyin. +Menu.VideosLibTip = Ev filmlerini ve diğer dijital videoları izleyin. +Menu.RecordingsLibTip = Bilgisayarınızda kayıtlı TV programlarını izleyin. +Menu.DownloadTip = Internet yüklemelerini ve sık kullanılan web siteleri bağlantılarını bulun. +Menu.HomegroupTip = Ev grubunuzdaki diğer kişiler tarafından paylaşılan kitaplıklara ve klasörlere erişin. +Menu.RunTip = Bir program, klasör, belge veya Web sitesi açar. +Menu.HelpTip = Yardım konularını, bilgilendirici rehberleri ve diğer destek hizmetlerini bulun. +Menu.ProgramsTip = Programlarınızın listesini açar. +Menu.SearchFilesTip = Belge, müzik, resim, e-posta ve pek çok başka öğeyi arayın. +Menu.GamesTip = Bilgisayarınızda oyun oynayın ve oyunları yönetin. +Menu.SecurityTip = Parola Değiştirmek, Kullanıcı Değiştirmek veya Görev Yöneticisini Başlatmak için Windows Güvenlik Seçenekleri'ni başlatın. +Menu.SearchComputersTip = Ağda bilgisayarlar ara +Menu.SearchPrintersTip = Yazıcı arayın +Menu.AdminToolsTip = Bilgisayarınızın yönetimle ilgili ayarlarını yapılandırır. +Menu.ShutdownTip = Tüm açık programları kapatır, Windows'u kapatır ve sonra bilgisayarınızı kapatır. +Menu.RestartTip = Tüm açık programları kapatır, Windows'u kapatır ve sonra Windows'u yeniden başlatır. +Menu.SleepTip = Çalışmanızı kolayca devam ettirebilmeniz için oturumunuzu bellekte tutar ve bilgisayarı düşük güçte çalışma durumuna geçirir. +Menu.HibernateTip = Oturumunuzu kaydeder ve bilgisayarı kapatır. Bilgisayarı açtığınızda, Windows oturumunuzu geri yükler. +Menu.LogOffTip = Programları kapatın ve oturumdan çıkın. +Menu.DisconnectTip = Oturum bağlantınız kesilir. Oturum açtığınızda yeniden bağlanabilirsiniz. +Menu.LockTip = Bu bilgisayarı kilitleyin. +Menu.UndockTip = Dizüstü veya notebook bilgisayarınızı takma biriminden çıkartır. +Menu.SwitchUserTip = Kullanıcıları, programları kapatmadan değiştirin. +Menu.Empty = (Boş) +Menu.Features = Programlar ve Özellikler +Menu.FeaturesTip = Bilgisayarınızdaki programları kaldırın veya değiştirin. +Menu.SearchPeople = &Kişiler... +Menu.SortByName = A&da Göre Sırala +Menu.Open = &Aç +Menu.OpenAll = Tü&m Kullanıcıları Aç +Menu.Explore = A&raştır +Menu.ExploreAll = &Tüm Kullanıcıları Araştır +Menu.MenuSettings = Ayarlar +Menu.MenuHelp = Yardım +Menu.MenuExit = Çıkış +Menu.LogoffTitle = Windows Oturumunu Kapat +Menu.LogoffPrompt = Oturumu kapatmayı gerçekten istiyor musunuz? +Menu.LogoffYes = Oturumu &Kapat +Menu.LogoffNo = &Hayır +Menu.RenameTitle = Yeniden Adlandır +Menu.RenamePrompt = &Yeni ad: +Menu.RenameOK = Tamam +Menu.RenameCancel = İptal +Menu.Organize = Başlat menüsünü düzenle +Menu.Expand = &Genişlet +Menu.Collapse = &Daralt +Menu.NewFolder = Yeni Klasör +Menu.NewShortcut = Yeni Kısayol +Menu.AutoArrange = &Otomatik Düzenle +Menu.ActionOpen = Aç +Menu.ActionClose = Kapat +Menu.ActionExecute = Çalıştır +Menu.RemoveList = &Bu listeden kaldır +Menu.RemoveAll = &Son kullanılan öğeler listesini temizle +Menu.Explorer = Windows Gezgini +Menu.Start = Başlat +Menu.StartScreen = Başlangıç Ekranı +Menu.StartMenu = Başlat menüsü (Windows) +Menu.PinStart = Başlat menüsüne sabitle +Menu.PinStartCs = Başlat menüsüne sabitle (Classic Shell) +Menu.UnpinStartCs = Başlat menüsünden ayır (Classic Shell) +Menu.MonitorOff = Ekranı kapat +Menu.RemoveHighlight = Önemli Noktayı Kaldır +Menu.Uninstall = &Kaldır +Menu.UninstallTitle = Kaldır +Menu.UninstallPrompt = %s programını kaldırmak istediğinizden emin misiniz? +Search.CategorySettings = Ayarlar +Search.CategoryPCSettings = Bilgisayar ayarları +Search.CategoryPrograms = Programlar +Search.CategoryDocuments = Belgeler +Search.CategoryMusic = Müzik +Search.CategoryPictures = Resimler +Search.CategoryVideos = Videolar +Search.CategoryFiles = Dosyalar +Search.CategoryInternet = Internet +JumpList.Recent = En Son +JumpList.Frequent = Sık Kullanılanlar +JumpList.Tasks = Görevler +JumpList.Pinned = Sabitlendi +JumpList.Pin = Bu listeye &sabitle +JumpList.Unpin = Bu listeden çı&kar +JumpList.Remove = &Bu listeden kaldır +JumpList.PinTip = Bu listeye sabitle +JumpList.UnpinTip = Bu listeden çıkar + + +[uk-UA] - Ukrainian (Ukraine) +Menu.Programs = &Програми +Menu.Apps = Застосунки +Menu.AllPrograms = Усі програми +Menu.Back = Назад +Menu.Favorites = &Уподобання +Menu.Documents = До&кументи +Menu.Settings = Н&астройки +Menu.Search = З&найти +Menu.SearchBox = Знайти +Menu.SearchPrograms = Пошук програм та файлів +Menu.SearchInternet = Пошук в Інтернеті +Menu.Searching = Триває пошук... +Menu.NoMatch = Пошук не дав результатів. +Menu.MoreResults = Інші результати +Menu.Help = &Довідка та підтримка +Menu.Run = Запуск про&грами... +Menu.Logoff = Завер&шення сеансу %s... +Menu.SwitchUser = З&мінити користувача +Menu.Lock = Б&локувати +Menu.LogOffShort = &Вийти з системи +Menu.Undock = Відстикувати комп'&ютер +Menu.Disconnect = В&ідключити +Menu.ShutdownBox = &Завершення роботи... +Menu.Shutdown = &Завершення роботи +Menu.Restart = &Перезавантаження +Menu.ShutdownUpdate = Інсталювати оновлення та завершити роботу +Menu.RestartUpdate = Інсталювати оновлення та перезавантажити +Menu.Sleep = &Сон +Menu.Hibernate = &Режим глибокого сну +Menu.ControlPanel = П&анель керування +Menu.PCSettings = Параметри ПК +Menu.Security = Безпека Windows +Menu.Network = &Мережні підключення +Menu.Printers = Пр&интери +Menu.Taskbar = Панель &завдань і меню "Пуск" +Menu.SearchFiles = &Файли й папки... +Menu.SearchPrinter = &Принтер +Menu.SearchComputers = &Комп'ютери +Menu.UserFilesTip = Містить папки для документів, зображень, музики та інших ваших файлів. +Menu.UserDocumentsTip = Містить листи, звіти та інші документи й файли. +Menu.UserPicturesTip = Містить цифрові фотографії, малюнки, графічні файли. +Menu.UserMusicTip = Містить музичні та інші звукові файли. +Menu.UserVideosTip = Містить фільми та відеофайли. +Menu.NetworkTip = Показ наявних мережних підключень для цього комп’ютера та створення нових підключень +Menu.PrintersTip = Додати, видалити або настроїти локальні чи мережні принтери. +Menu.TaskbarTip = Настройка меню "Пуск" і панелі завдань, наприклад, установка типів і зовнішнього вигляду елементів, які буде показано. +Menu.ControlPanelTip = Змінити параметри та настроїти функціональність системи. +Menu.DocumentsLibTip = Отримайте доступ до листів, звітів, приміток та документів інших видів. +Menu.MusicLibTip = Відтворюйте музику та інші звукові файли. +Menu.PicturesLibTip = Переглядайте та організовуйте цифрові зображення. +Menu.VideosLibTip = Переглядати домашнє та інше цифрове відео. +Menu.RecordingsLibTip = Переглядати ТВ-програми, записані на комп'ютер. +Menu.DownloadTip = Знайти завантаження Інтернету і посилання на улюблені веб-сайти. +Menu.HomegroupTip = Спільний доступ до бібліотек і папок інших користувачів із домашньої групи. +Menu.RunTip = Відкриття програми, папки, документа або веб-сайту. +Menu.HelpTip = Пошук довідкових матеріалів, навчальних програм, засобів виправлення неполадок та інших служб технічної підтримки. +Menu.ProgramsTip = Відкрити список програм. +Menu.SearchFilesTip = Пошук документів, музики, зображень, адрес електронної пошти та іншого. +Menu.GamesTip = Гра та керування іграми, інстальованими на цьому комп’ютері. +Menu.SecurityTip = Запустити Параметри безпеки Windows для зміни пароля, переключення користувача або запуску диспетчера завдань. +Menu.SearchComputersTip = Пошук комп’ютерів у мережі +Menu.SearchPrintersTip = Пошук принтера +Menu.AdminToolsTip = Настройка параметрів адміністрування для цього комп'ютера. +Menu.ShutdownTip = Закриває всі відкриті програми, завершує роботу системи та вимикає комп’ютер. +Menu.RestartTip = Закриває всі відкриті програми, завершує роботу системи та запускає систему знову. +Menu.SleepTip = Зберігає сеанс роботи в пам’яті та переводить комп’ютер до режиму зниженого енергоспоживання, що надає змогу швидко відновити роботу. +Menu.HibernateTip = Зберігає дані сеансу та вимикає комп’ютер. Після увімкнення комп’ютера система відновлює сеанс. +Menu.LogOffTip = Закрити програми та вийти з системи. +Menu.DisconnectTip = Відключає ваш сеанс. Можна знову підключитися до сеансу, повторно увійшовши до системи. +Menu.LockTip = Заблокувати комп'ютер. +Menu.UndockTip = Видалення ноутбука із пристрою стаціонарного підключення. +Menu.SwitchUserTip = Переключення користувачів без закриття програм. +Menu.Empty = (пусто) +Menu.Features = Програми та засоби +Menu.FeaturesTip = Змінити або видалити програми на комп’ютері. +Menu.SearchPeople = Л&юдей... +Menu.SortByName = Сортувати за &іменем +Menu.Open = &Відкрити +Menu.OpenAll = В&ідкрити спільне для всіх меню +Menu.Explore = &Провідник +Menu.ExploreAll = Пр&овідник до спільного для всіх меню +Menu.MenuSettings = Настройки +Menu.MenuHelp = Довідка +Menu.MenuExit = Вихід +Menu.LogoffTitle = Вихід із Windows +Menu.LogoffPrompt = Ви дійсно бажаєте вийти із системи? +Menu.LogoffYes = В&ихід +Menu.LogoffNo = &Ні +Menu.RenameTitle = Перейменування +Menu.RenamePrompt = &Нове ім'я: +Menu.RenameOK = ОК +Menu.RenameCancel = Скасувати +Menu.Organize = Упорядкування меню "Пуск" +Menu.Expand = &Розгорнути +Menu.Collapse = &Згорнути +Menu.NewFolder = Створити папку +Menu.NewShortcut = Новий ярлик +Menu.AutoArrange = &Автоматично +Menu.ActionOpen = Відкрити +Menu.ActionClose = Закрити +Menu.ActionExecute = Виконати +Menu.RemoveList = Видалити &з цього списку +Menu.RemoveAll = О&чистити список останніх елементів +Menu.Explorer = Провідник +Menu.Start = Запустити +Menu.StartScreen = Початковий екран +Menu.StartMenu = Меню "Пуск" (Windows) +Menu.PinStart = Прикріпити до меню "Пуск" +Menu.PinStartCs = Прикріпити до меню "Пуск" (Classic Shell) +Menu.UnpinStartCs = Відкріпити від меню "Пуск" (Classic Shell) +Menu.MonitorOff = Вимкнути дисплей +Menu.RemoveHighlight = Видалити виділення +Menu.Uninstall = &Видалити +Menu.UninstallTitle = Видалити +Menu.UninstallPrompt = Дійсно видалити %s? +Search.CategorySettings = Настройки +Search.CategoryPCSettings = Параметри ПК +Search.CategoryPrograms = Програми +Search.CategoryDocuments = Документи +Search.CategoryMusic = Музика +Search.CategoryPictures = Зображення +Search.CategoryVideos = Відео +Search.CategoryFiles = Файли +Search.CategoryInternet = Інтернет +JumpList.Recent = Недавні +JumpList.Frequent = Часто використовувані +JumpList.Tasks = Завдання +JumpList.Pinned = Зафіксовано +JumpList.Pin = &Прикріпити до списку +JumpList.Unpin = &Відкріпити від списку +JumpList.Remove = Видали&ти з цього списку +JumpList.PinTip = Прикріпити до списку +JumpList.UnpinTip = Відкріпити від списку + + +[zh-CN] - Chinese (Simplified) +Menu.Programs = 程序(&P) +Menu.Apps = 应用 +Menu.AllPrograms = 所有程序 +Menu.Back = 返回 +Menu.Favorites = 收藏夹(&A) +Menu.Documents = 文档(&D) +Menu.Settings = 设置(&S) +Menu.Search = 搜索(&C) +Menu.SearchBox = 搜索 +Menu.SearchPrograms = 搜索程序和文件 +Menu.SearchInternet = 搜索 Internet +Menu.Searching = 正在搜索... +Menu.NoMatch = 没有与搜索条件匹配的项。 +Menu.MoreResults = 查看更多结果 +Menu.Help = 帮助和支持(&H) +Menu.Run = 运行(&R)... +Menu.Logoff = 注销 %s(&L)... +Menu.SwitchUser = 切换用户(&W) +Menu.Lock = 锁定(&O) +Menu.LogOffShort = 注销(&L) +Menu.Undock = 弹出 PC(&E) +Menu.Disconnect = 断开(&I) +Menu.ShutdownBox = 关机(&U)... +Menu.Shutdown = 关机(&U) +Menu.Restart = 重新启动(&R) +Menu.ShutdownUpdate = 更新并关机 +Menu.RestartUpdate = 更新并重启 +Menu.Sleep = 睡眠(&S) +Menu.Hibernate = 休眠(&H) +Menu.ControlPanel = 控制面板(&C) +Menu.PCSettings = 电脑设置 +Menu.Security = Windows 安全 +Menu.Network = 网络连接(&N) +Menu.Printers = 打印机(&P) +Menu.Taskbar = 任务栏和「开始」菜单(&T) +Menu.SearchFiles = 文件或文件夹(&F)... +Menu.SearchPrinter = 打印机(&P) +Menu.SearchComputers = 计算机(&C) +Menu.UserFilesTip = 包含文档文件、图片文件、音乐文件及您拥有的其他文件的文件夹。 +Menu.UserDocumentsTip = 包含信件,报告和其它文档以及文件。 +Menu.UserPicturesTip = 包含数字照片,图片和图形文件。 +Menu.UserMusicTip = 包含音乐和其他音频文件。 +Menu.UserVideosTip = 包含音乐和其他视频文件。 +Menu.NetworkTip = 显示此计算机上现有的网络连接并帮助您创建新的 +Menu.PrintersTip = 添加、删除和配置本地及网络打印机。 +Menu.TaskbarTip = 自定义「开始」菜单和任务栏,例如要显示项目的类型及如何显示。 +Menu.ControlPanelTip = 更改您的计算机设置并自定义其功能。 +Menu.DocumentsLibTip = 访问信件、报告、便笺以及其他类型的文档。 +Menu.MusicLibTip = 播放音乐和其他音频文件。 +Menu.PicturesLibTip = 查看和组织数字图片。 +Menu.VideosLibTip = 观看家庭电影和其他数字视频。 +Menu.RecordingsLibTip = 在计算机上观看录制的电视节目。 +Menu.DownloadTip = 查找 Internet 下载以及最喜欢的网站链接。 +Menu.HomegroupTip = 访问家庭组中其他人员共享的库和文件夹。 +Menu.RunTip = 打开一个程序、文件夹、文档或网站。 +Menu.HelpTip = 查找帮助主题、教程、疑难解答和其他支持服务。 +Menu.ProgramsTip = 打开您的程序列表。 +Menu.SearchFilesTip = 搜索文档、音乐、图片、电子邮件等等。 +Menu.GamesTip = 在计算机上运行和管理游戏。 +Menu.SecurityTip = 启动 Windows 安全选项以更改密码、切换用户或启动任务管理器。 +Menu.SearchComputersTip = 搜索网络计算机 +Menu.SearchPrintersTip = 搜索打印机 +Menu.AdminToolsTip = 配置您计算机的管理设置。 +Menu.ShutdownTip = 关闭所有打开的程序,关闭 Windows,然后关闭计算机。 +Menu.RestartTip = 关闭所有打开的程序,关闭 Windows,然后重新启动 Windows。 +Menu.SleepTip = 将会话保存在内存中并将计算机置于低功耗状态,这样即可快速恢复工作状态。 +Menu.HibernateTip = 保存会话并关闭计算机。打开计算机时,Windows 会还原会话。 +Menu.LogOffTip = 关闭程序并注销。 +Menu.DisconnectTip = 断开会话。再次登录时可以重新连接到该会话。 +Menu.LockTip = 锁定该计算机。 +Menu.UndockTip = 将您的便携式和笔记本计算机从扩展坞中移除。 +Menu.SwitchUserTip = 不关闭程序切换用户。 +Menu.Empty = (空) +Menu.Features = 程序和功能 +Menu.FeaturesTip = 卸载或更改计算机上的程序。 +Menu.SearchPeople = 个人(&P)... +Menu.SortByName = 按名称排序(&B) +Menu.Open = 打开(&O) +Menu.OpenAll = 打开所有用户(&P) +Menu.Explore = 浏览(&E) +Menu.ExploreAll = 浏览所有用户(&X) +Menu.MenuSettings = 设置 +Menu.MenuHelp = 帮助 +Menu.MenuExit = 退出 +Menu.LogoffTitle = 注销 Windows +Menu.LogoffPrompt = 确实要注销吗? +Menu.LogoffYes = 注销(&L) +Menu.LogoffNo = 否(&N) +Menu.RenameTitle = 重命名 +Menu.RenamePrompt = 新名称(&N): +Menu.RenameOK = 确定 +Menu.RenameCancel = 取消 +Menu.Organize = 组织「开始」菜单 +Menu.Expand = 展开(&A) +Menu.Collapse = 折叠(&A) +Menu.NewFolder = 新文件夹 +Menu.NewShortcut = 新快捷方式 +Menu.AutoArrange = 自动排列(&A) +Menu.ActionOpen = 打开 +Menu.ActionClose = 关闭 +Menu.ActionExecute = 执行 +Menu.RemoveList = 从列表中删除(&F) +Menu.RemoveAll = 清除最近的项目列表(&L) +Menu.Explorer = Windows 资源管理器 +Menu.Start = 开始 +Menu.StartScreen = “开始”屏幕 +Menu.StartMenu = 「开始」菜单 (Windows) +Menu.PinStart = 锁定到「开始」菜单 +Menu.PinStartCs = 锁定到「开始」菜单 (Classic Shell) +Menu.UnpinStartCs = 从「开始」菜单解锁 (Classic Shell) +Menu.MonitorOff = 关闭显示器 +Menu.RemoveHighlight = 删除突出显示 +Menu.Uninstall = 卸载(&U) +Menu.UninstallTitle = 卸载 +Menu.UninstallPrompt = 确实要卸载 %s 吗? +Search.CategorySettings = 设置 +Search.CategoryPCSettings = 电脑设置 +Search.CategoryPrograms = 程序 +Search.CategoryDocuments = 文档 +Search.CategoryMusic = 音乐 +Search.CategoryPictures = 图片 +Search.CategoryVideos = 视频 +Search.CategoryFiles = 文件 +Search.CategoryInternet = Internet +JumpList.Recent = 最近 +JumpList.Frequent = 常用 +JumpList.Tasks = 任务 +JumpList.Pinned = 已固定 +JumpList.Pin = 锁定到此列表(&I) +JumpList.Unpin = 从此列表解锁(&U) +JumpList.Remove = 从列表中删除(&F) +JumpList.PinTip = 锁定到此列表 +JumpList.UnpinTip = 从此列表解锁 + + +[zh-HK] - Chinese (Traditional) +Menu.Programs = 程式集(&P) +Menu.Apps = 應用程式 +Menu.AllPrograms = 所有程式 +Menu.Back = 上一頁 +Menu.Favorites = 我的最愛(&A) +Menu.Documents = 文件(&D) +Menu.Settings = 設定(&S) +Menu.Search = 搜尋(&C) +Menu.SearchBox = 搜尋 +Menu.SearchPrograms = 搜尋程式及檔案 +Menu.SearchInternet = 搜尋網際網路 +Menu.Searching = 正在搜尋... +Menu.NoMatch = 沒有符合搜尋的項目。 +Menu.MoreResults = 查看更多結果 +Menu.Help = 說明及支援(&H) +Menu.Run = 執行(&R)... +Menu.Logoff = 登出 %s(&L)... +Menu.SwitchUser = 切換使用者(&W) +Menu.Lock = 鎖定(&O) +Menu.LogOffShort = 登出(&L) +Menu.Undock = 卸除 PC(&E) +Menu.Disconnect = 中斷連線(&I) +Menu.ShutdownBox = 關機(&U)... +Menu.Shutdown = 關機(&U) +Menu.Restart = 重新啟動(&R) +Menu.ShutdownUpdate = 更新並關機 +Menu.RestartUpdate = 更新並重新啟動 +Menu.Sleep = 睡眠(&S) +Menu.Hibernate = 休眠(&H) +Menu.ControlPanel = 控制台(&C) +Menu.PCSettings = 電腦設定 +Menu.Security = Windows 安全性 +Menu.Network = 網路連線(&N) +Menu.Printers = 印表機(&P) +Menu.Taskbar = 工作列及 [開始] 功能表(&T) +Menu.SearchFiles = 檔案或資料夾(&F)... +Menu.SearchPrinter = 印表機(&P) +Menu.SearchComputers = 電腦(&C) +Menu.UserFilesTip = 包含 [文件]、[圖片]、[音樂] 資料夾,以及其他屬於您的檔案。 +Menu.UserDocumentsTip = 包含信件、報告、其他文件和檔案。 +Menu.UserPicturesTip = 包含數位相片、影像和圖形檔案。 +Menu.UserMusicTip = 包含音樂和其他音訊檔案。 +Menu.UserVideosTip = 包含影片和其他視訊檔案。 +Menu.NetworkTip = 顯示這台電腦目前的網路連線,並協助您建立新連線。 +Menu.PrintersTip = 新增、移除和設定本機及網路印表機。 +Menu.TaskbarTip = 自訂開始功能表和工作列,例如要顯示的項目類型和顯示的方式。 +Menu.ControlPanelTip = 變更設定和自訂電腦的功能。 +Menu.DocumentsLibTip = 存取信件、報告、筆記及其他類型的文件。 +Menu.MusicLibTip = 播放音樂及其他音訊檔案。 +Menu.PicturesLibTip = 檢視及管理數位圖片。 +Menu.VideosLibTip = 觀看家庭影片及其他數位視訊。 +Menu.RecordingsLibTip = 觀看電腦上錄製的電視節目。 +Menu.DownloadTip = 尋找網際網路下載與我的最愛網站的連結。 +Menu.HomegroupTip = 存取家用群組中其他人共用的媒體櫃與資料夾。 +Menu.RunTip = 開啟程式、資料夾、文件或網站。 +Menu.HelpTip = 尋找說明主題、教學課程、疑難排解和其他支援服務。 +Menu.ProgramsTip = 開啟程式清單。 +Menu.SearchFilesTip = 搜尋文件、音樂、圖片及電子郵件等等。 +Menu.GamesTip = 玩和管理您電腦上的遊戲。 +Menu.SecurityTip = 啟動 [Windows 安全性選項] 以變更密碼、切換使用者或啟動工作管理員。 +Menu.SearchComputersTip = 搜尋網路上的電腦 +Menu.SearchPrintersTip = 搜尋印表機 +Menu.AdminToolsTip = 設定電腦的系統管理設定。 +Menu.ShutdownTip = 關閉所有開啟的程式、關閉 Windows,然後關閉您的電腦。 +Menu.RestartTip = 關閉所有開啟的程式、關閉 Windows,然後重新啟動 Windows。 +Menu.SleepTip = 將您的工作階段保留在記憶體中,並且讓電腦處於低電源狀態,如此您就能夠快速地恢復工作。 +Menu.HibernateTip = 儲存您的工作階段,並且關閉電腦。當您開啟電腦時,Windows 會還原您的工作階段。 +Menu.LogOffTip = 關閉程式並登出。 +Menu.DisconnectTip = 中斷您的工作階段連線。下次重新登入時,可以重新連線。 +Menu.LockTip = 鎖定此電腦。 +Menu.UndockTip = 將筆記型電腦從船塢中卸除。 +Menu.SwitchUserTip = 切換使用者 (不關閉程式)。 +Menu.Empty = (空白) +Menu.Features = 程式和功能 +Menu.FeaturesTip = 解除安裝或變更您電腦上的程式。 +Menu.SearchPeople = 人員(&P)... +Menu.SortByName = 依名稱排序(&B) +Menu.Open = 開啟(&O) +Menu.OpenAll = 開啟所有使用者(&P) +Menu.Explore = 檔案總管(&E) +Menu.ExploreAll = 瀏覽所有使用者(&X) +Menu.MenuSettings = 設定 +Menu.MenuHelp = 說明 +Menu.MenuExit = 結束 +Menu.LogoffTitle = 登出 Windows +Menu.LogoffPrompt = 您確定要登出? +Menu.LogoffYes = 登出(&L) +Menu.LogoffNo = 否(&N) +Menu.RenameTitle = 重新命名 +Menu.RenamePrompt = 新名稱(&N): +Menu.RenameOK = 確定 +Menu.RenameCancel = 取消 +Menu.Organize = 組織 [開始] 功能表 +Menu.Expand = 展開(&A) +Menu.Collapse = 摺疊(&A) +Menu.NewFolder = 新增資料夾 +Menu.NewShortcut = 新增捷徑 +Menu.AutoArrange = 自動排列(&A) +Menu.ActionOpen = 開啟 +Menu.ActionClose = 關閉 +Menu.ActionExecute = 執行 +Menu.RemoveList = 從清單中移除(&F) +Menu.RemoveAll = 清除最近使用的項目清單(&L) +Menu.Explorer = Windows 檔案總管 +Menu.Start = 開始 +Menu.StartScreen = [開始] 畫面 +Menu.StartMenu = [開始] 功能表 (Windows) +Menu.PinStart = 釘選到 [開始] 功能表 +Menu.PinStartCs = 釘選到 [開始] 功能表 (Classic Shell) +Menu.UnpinStartCs = 從 [開始] 功能表取消釘選 (Classic Shell) +Menu.MonitorOff = 關閉顯示 +Menu.RemoveHighlight = 移除醒目提示 +Menu.Uninstall = 解除安裝(&U) +Menu.UninstallTitle = 解除安裝 +Menu.UninstallPrompt = 您確定要從電腦解除安裝 %s 嗎? +Search.CategorySettings = 設定 +Search.CategoryPCSettings = 電腦設定 +Search.CategoryPrograms = 程式 +Search.CategoryDocuments = 文件 +Search.CategoryMusic = 音樂 +Search.CategoryPictures = 圖片 +Search.CategoryVideos = 影片 +Search.CategoryFiles = 檔案 +Search.CategoryInternet = 網際網路 +JumpList.Recent = 最近 +JumpList.Frequent = 常用 +JumpList.Tasks = 工作 +JumpList.Pinned = 已釘選 +JumpList.Pin = 釘選到這個清單(&I) +JumpList.Unpin = 從這個清單取消釘選(&U) +JumpList.Remove = 從清單中移除(&F) +JumpList.PinTip = 釘選到這個清單 +JumpList.UnpinTip = 從這個清單取消釘選 + + +[zh-TW] - Chinese (Traditional) +Menu.Programs = 程式集(&P) +Menu.Apps = 應用程式 +Menu.AllPrograms = 所有程式 +Menu.Back = 上一頁 +Menu.Favorites = 我的最愛(&A) +Menu.Documents = 文件(&D) +Menu.Settings = 設定(&S) +Menu.Search = 搜尋(&C) +Menu.SearchBox = 搜尋 +Menu.SearchPrograms = 搜尋程式及檔案 +Menu.SearchInternet = 搜尋網際網路 +Menu.Searching = 正在搜尋... +Menu.NoMatch = 沒有符合搜尋的項目。 +Menu.MoreResults = 查看更多結果 +Menu.Help = 說明及支援(&H) +Menu.Run = 執行(&R)... +Menu.Logoff = 登出 %s(&L)... +Menu.SwitchUser = 切換使用者(&W) +Menu.Lock = 鎖定(&O) +Menu.LogOffShort = 登出(&L) +Menu.Undock = 卸除 PC(&E) +Menu.Disconnect = 中斷連線(&I) +Menu.ShutdownBox = 關機(&U)... +Menu.Shutdown = 關機(&U) +Menu.Restart = 重新啟動(&R) +Menu.ShutdownUpdate = 更新並關機 +Menu.RestartUpdate = 更新並重新啟動 +Menu.Sleep = 睡眠(&S) +Menu.Hibernate = 休眠(&H) +Menu.ControlPanel = 控制台(&C) +Menu.PCSettings = 電腦設定 +Menu.Security = Windows 安全性 +Menu.Network = 網路連線(&N) +Menu.Printers = 印表機(&P) +Menu.Taskbar = 工作列及 [開始] 功能表(&T) +Menu.SearchFiles = 檔案或資料夾(&F)... +Menu.SearchPrinter = 印表機(&P) +Menu.SearchComputers = 電腦(&C) +Menu.UserFilesTip = 包含 [文件]、[圖片]、[音樂] 資料夾,以及其他屬於您的檔案。 +Menu.UserDocumentsTip = 包含信件、報告、其他文件和檔案。 +Menu.UserPicturesTip = 包含數位相片、影像和圖形檔案。 +Menu.UserMusicTip = 包含音樂和其他音訊檔案。 +Menu.UserVideosTip = 包含影片和其他視訊檔案。 +Menu.NetworkTip = 顯示這台電腦目前的網路連線,並協助您建立新連線。 +Menu.PrintersTip = 新增、移除和設定本機及網路印表機。 +Menu.TaskbarTip = 自訂開始功能表和工作列,例如要顯示的項目類型和顯示的方式。 +Menu.ControlPanelTip = 變更設定和自訂電腦的功能。 +Menu.DocumentsLibTip = 存取信件、報告、筆記及其他類型的文件。 +Menu.MusicLibTip = 播放音樂及其他音訊檔案。 +Menu.PicturesLibTip = 檢視及管理數位圖片。 +Menu.VideosLibTip = 觀看家庭影片及其他數位視訊。 +Menu.RecordingsLibTip = 觀看電腦上錄製的電視節目。 +Menu.DownloadTip = 尋找網際網路下載與我的最愛網站的連結。 +Menu.HomegroupTip = 存取家用群組中其他人共用的媒體櫃與資料夾。 +Menu.RunTip = 開啟程式、資料夾、文件或網站。 +Menu.HelpTip = 尋找說明主題、教學課程、疑難排解和其他支援服務。 +Menu.ProgramsTip = 開啟程式清單。 +Menu.SearchFilesTip = 搜尋文件、音樂、圖片及電子郵件等等。 +Menu.GamesTip = 玩和管理您電腦上的遊戲。 +Menu.SecurityTip = 啟動 [Windows 安全性選項] 以變更密碼、切換使用者或啟動工作管理員。 +Menu.SearchComputersTip = 搜尋網路上的電腦 +Menu.SearchPrintersTip = 搜尋印表機 +Menu.AdminToolsTip = 設定電腦的系統管理設定。 +Menu.ShutdownTip = 關閉所有開啟的程式、關閉 Windows,然後關閉您的電腦。 +Menu.RestartTip = 關閉所有開啟的程式、關閉 Windows,然後重新啟動 Windows。 +Menu.SleepTip = 將您的工作階段保留在記憶體中,並且讓電腦處於低電源狀態,如此您就能夠快速地恢復工作。 +Menu.HibernateTip = 儲存您的工作階段,並且關閉電腦。當您開啟電腦時,Windows 會還原您的工作階段。 +Menu.LogOffTip = 關閉程式並登出。 +Menu.DisconnectTip = 中斷您的工作階段連線。下次重新登入時,可以重新連線。 +Menu.LockTip = 鎖定此電腦。 +Menu.UndockTip = 將筆記型電腦從船塢中卸除。 +Menu.SwitchUserTip = 切換使用者 (不關閉程式)。 +Menu.Empty = (空白) +Menu.Features = 程式和功能 +Menu.FeaturesTip = 解除安裝或變更您電腦上的程式。 +Menu.SearchPeople = 人員(&P)... +Menu.SortByName = 依名稱排序(&B) +Menu.Open = 開啟(&O) +Menu.OpenAll = 開啟所有使用者(&P) +Menu.Explore = 檔案總管(&E) +Menu.ExploreAll = 瀏覽所有使用者(&X) +Menu.MenuSettings = 設定 +Menu.MenuHelp = 說明 +Menu.MenuExit = 結束 +Menu.LogoffTitle = 登出 Windows +Menu.LogoffPrompt = 您確定要登出? +Menu.LogoffYes = 登出(&L) +Menu.LogoffNo = 否(&N) +Menu.RenameTitle = 重新命名 +Menu.RenamePrompt = 新名稱(&N): +Menu.RenameOK = 確定 +Menu.RenameCancel = 取消 +Menu.Organize = 組織 [開始] 功能表 +Menu.Expand = 展開(&A) +Menu.Collapse = 摺疊(&A) +Menu.NewFolder = 新增資料夾 +Menu.NewShortcut = 新增捷徑 +Menu.AutoArrange = 自動排列(&A) +Menu.ActionOpen = 開啟 +Menu.ActionClose = 關閉 +Menu.ActionExecute = 執行 +Menu.RemoveList = 從清單中移除(&F) +Menu.RemoveAll = 清除最近使用的項目清單(&L) +Menu.Explorer = Windows 檔案總管 +Menu.Start = 開始 +Menu.StartScreen = [開始] 畫面 +Menu.StartMenu = [開始] 功能表 (Windows) +Menu.PinStart = 釘選到 [開始] 功能表 +Menu.PinStartCs = 釘選到 [開始] 功能表 (Classic Shell) +Menu.UnpinStartCs = 從 [開始] 功能表取消釘選 (Classic Shell) +Menu.MonitorOff = 關閉顯示 +Menu.RemoveHighlight = 移除醒目提示 +Menu.Uninstall = 解除安裝(&U) +Menu.UninstallTitle = 解除安裝 +Menu.UninstallPrompt = 您確定要從電腦解除安裝 %s 嗎? +Search.CategorySettings = 設定 +Search.CategoryPCSettings = 電腦設定 +Search.CategoryPrograms = 程式 +Search.CategoryDocuments = 文件 +Search.CategoryMusic = 音樂 +Search.CategoryPictures = 圖片 +Search.CategoryVideos = 影片 +Search.CategoryFiles = 檔案 +Search.CategoryInternet = 網際網路 +JumpList.Recent = 最近 +JumpList.Frequent = 常用 +JumpList.Tasks = 工作 +JumpList.Pinned = 已釘選 +JumpList.Pin = 釘選到這個清單(&I) +JumpList.Unpin = 從這個清單取消釘選(&U) +JumpList.Remove = 從清單中移除(&F) +JumpList.PinTip = 釘選到這個清單 +JumpList.UnpinTip = 從這個清單取消釘選 diff --git a/ClassicShellPDB/PDB32/ClassicExplorer32.dll b/ClassicShellPDB/PDB32/ClassicExplorer32.dll new file mode 100644 index 0000000..a0b1147 Binary files /dev/null and b/ClassicShellPDB/PDB32/ClassicExplorer32.dll differ diff --git a/ClassicShellPDB/PDB32/ClassicExplorer32.pdb b/ClassicShellPDB/PDB32/ClassicExplorer32.pdb new file mode 100644 index 0000000..3575820 Binary files /dev/null and b/ClassicShellPDB/PDB32/ClassicExplorer32.pdb differ diff --git a/ClassicShellPDB/PDB32/ClassicExplorerSettings.exe b/ClassicShellPDB/PDB32/ClassicExplorerSettings.exe new file mode 100644 index 0000000..5acba37 Binary files /dev/null and b/ClassicShellPDB/PDB32/ClassicExplorerSettings.exe differ diff --git a/ClassicShellPDB/PDB32/ClassicExplorerSettings.pdb b/ClassicShellPDB/PDB32/ClassicExplorerSettings.pdb new file mode 100644 index 0000000..56e4520 Binary files /dev/null and b/ClassicShellPDB/PDB32/ClassicExplorerSettings.pdb differ diff --git a/ClassicShellPDB/PDB32/ClassicIEDLL_32.dll b/ClassicShellPDB/PDB32/ClassicIEDLL_32.dll new file mode 100644 index 0000000..cf7eea5 Binary files /dev/null and b/ClassicShellPDB/PDB32/ClassicIEDLL_32.dll differ diff --git a/ClassicShellPDB/PDB32/ClassicIEDLL_32.pdb b/ClassicShellPDB/PDB32/ClassicIEDLL_32.pdb new file mode 100644 index 0000000..c8b950c Binary files /dev/null and b/ClassicShellPDB/PDB32/ClassicIEDLL_32.pdb differ diff --git a/ClassicShellPDB/PDB32/ClassicIE_32.exe b/ClassicShellPDB/PDB32/ClassicIE_32.exe new file mode 100644 index 0000000..233a64d Binary files /dev/null and b/ClassicShellPDB/PDB32/ClassicIE_32.exe differ diff --git a/ClassicShellPDB/PDB32/ClassicShellUpdate.exe b/ClassicShellPDB/PDB32/ClassicShellUpdate.exe new file mode 100644 index 0000000..c331e86 Binary files /dev/null and b/ClassicShellPDB/PDB32/ClassicShellUpdate.exe differ diff --git a/ClassicShellPDB/PDB32/ClassicShellUpdate.pdb b/ClassicShellPDB/PDB32/ClassicShellUpdate.pdb new file mode 100644 index 0000000..d67dfa2 Binary files /dev/null and b/ClassicShellPDB/PDB32/ClassicShellUpdate.pdb differ diff --git a/ClassicShellPDB/PDB32/ClassicStartMenu.exe b/ClassicShellPDB/PDB32/ClassicStartMenu.exe new file mode 100644 index 0000000..98ead03 Binary files /dev/null and b/ClassicShellPDB/PDB32/ClassicStartMenu.exe differ diff --git a/ClassicShellPDB/PDB32/ClassicStartMenu.pdb b/ClassicShellPDB/PDB32/ClassicStartMenu.pdb new file mode 100644 index 0000000..442d569 Binary files /dev/null and b/ClassicShellPDB/PDB32/ClassicStartMenu.pdb differ diff --git a/ClassicShellPDB/PDB32/ClassicStartMenuDLL.dll b/ClassicShellPDB/PDB32/ClassicStartMenuDLL.dll new file mode 100644 index 0000000..49cf996 Binary files /dev/null and b/ClassicShellPDB/PDB32/ClassicStartMenuDLL.dll differ diff --git a/ClassicShellPDB/PDB32/ClassicStartMenuDLL.pdb b/ClassicShellPDB/PDB32/ClassicStartMenuDLL.pdb new file mode 100644 index 0000000..adf567f Binary files /dev/null and b/ClassicShellPDB/PDB32/ClassicStartMenuDLL.pdb differ diff --git a/ClassicShellPDB/PDB32/StartMenuHelper32.dll b/ClassicShellPDB/PDB32/StartMenuHelper32.dll new file mode 100644 index 0000000..41773b5 Binary files /dev/null and b/ClassicShellPDB/PDB32/StartMenuHelper32.dll differ diff --git a/ClassicShellPDB/PDB32/StartMenuHelper32.pdb b/ClassicShellPDB/PDB32/StartMenuHelper32.pdb new file mode 100644 index 0000000..8669de2 Binary files /dev/null and b/ClassicShellPDB/PDB32/StartMenuHelper32.pdb differ diff --git a/ClassicShellPDB/PDB64/ClassicExplorer64.dll b/ClassicShellPDB/PDB64/ClassicExplorer64.dll new file mode 100644 index 0000000..b16fb8b Binary files /dev/null and b/ClassicShellPDB/PDB64/ClassicExplorer64.dll differ diff --git a/ClassicShellPDB/PDB64/ClassicExplorer64.pdb b/ClassicShellPDB/PDB64/ClassicExplorer64.pdb new file mode 100644 index 0000000..894bb2d Binary files /dev/null and b/ClassicShellPDB/PDB64/ClassicExplorer64.pdb differ diff --git a/ClassicShellPDB/PDB64/ClassicIEDLL_64.dll b/ClassicShellPDB/PDB64/ClassicIEDLL_64.dll new file mode 100644 index 0000000..f72e07c Binary files /dev/null and b/ClassicShellPDB/PDB64/ClassicIEDLL_64.dll differ diff --git a/ClassicShellPDB/PDB64/ClassicIEDLL_64.pdb b/ClassicShellPDB/PDB64/ClassicIEDLL_64.pdb new file mode 100644 index 0000000..82db19c Binary files /dev/null and b/ClassicShellPDB/PDB64/ClassicIEDLL_64.pdb differ diff --git a/ClassicShellPDB/PDB64/ClassicIE_64.exe b/ClassicShellPDB/PDB64/ClassicIE_64.exe new file mode 100644 index 0000000..3a97f5d Binary files /dev/null and b/ClassicShellPDB/PDB64/ClassicIE_64.exe differ diff --git a/ClassicShellPDB/PDB64/ClassicStartMenu.exe b/ClassicShellPDB/PDB64/ClassicStartMenu.exe new file mode 100644 index 0000000..17e3ea1 Binary files /dev/null and b/ClassicShellPDB/PDB64/ClassicStartMenu.exe differ diff --git a/ClassicShellPDB/PDB64/ClassicStartMenu.pdb b/ClassicShellPDB/PDB64/ClassicStartMenu.pdb new file mode 100644 index 0000000..e0fedba Binary files /dev/null and b/ClassicShellPDB/PDB64/ClassicStartMenu.pdb differ diff --git a/ClassicShellPDB/PDB64/ClassicStartMenuDLL.dll b/ClassicShellPDB/PDB64/ClassicStartMenuDLL.dll new file mode 100644 index 0000000..4708b60 Binary files /dev/null and b/ClassicShellPDB/PDB64/ClassicStartMenuDLL.dll differ diff --git a/ClassicShellPDB/PDB64/ClassicStartMenuDLL.pdb b/ClassicShellPDB/PDB64/ClassicStartMenuDLL.pdb new file mode 100644 index 0000000..4859327 Binary files /dev/null and b/ClassicShellPDB/PDB64/ClassicStartMenuDLL.pdb differ diff --git a/ClassicShellPDB/PDB64/StartMenuHelper64.dll b/ClassicShellPDB/PDB64/StartMenuHelper64.dll new file mode 100644 index 0000000..2653a32 Binary files /dev/null and b/ClassicShellPDB/PDB64/StartMenuHelper64.dll differ diff --git a/ClassicShellPDB/PDB64/StartMenuHelper64.pdb b/ClassicShellPDB/PDB64/StartMenuHelper64.pdb new file mode 100644 index 0000000..2851881 Binary files /dev/null and b/ClassicShellPDB/PDB64/StartMenuHelper64.pdb differ diff --git a/ClassicShellSrc/BUILDME.txt b/ClassicShellSrc/BUILDME.txt new file mode 100644 index 0000000..850d0c8 --- /dev/null +++ b/ClassicShellSrc/BUILDME.txt @@ -0,0 +1,16 @@ +To build Classic Shell, navigate to the ClassicShellSetup folder and run __MakeFinal.bat. +It will compile the binaries, produce installer for English, and create the final archives. +Then you can run the individual language files like _BuildFrench.bat to create the installers +for other languages. +The final files (installers, archives) are saved to the ClassicShellSetup\Final folder. + +You need the following tools: +Visual Studio 2008 +Windows SDK 7.1 +HTML Help Workshop +WiX 3.7 +It is possible to convert the projects to newer versions of Visual Studio and newer SDKs. +Newer versions of WiX will probably work fine. + +Note: Unlike the official release, the source code does not contain digital certificate and +produces unsigned binaries. \ No newline at end of file diff --git a/ClassicShellSrc/ClassicExplorer/ClassicCopy.cpp b/ClassicShellSrc/ClassicExplorer/ClassicCopy.cpp new file mode 100644 index 0000000..92c90df --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicCopy.cpp @@ -0,0 +1,774 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include +#include +#include +#include +#include +#include "Translations.h" +#include "Settings.h" +#include "ResourceHelper.h" +#include "ComHelper.h" +#include "dllmain.h" + +static wchar_t g_TitleMove[256]; +static wchar_t g_TitleCopy[256]; +static wchar_t g_TitleFolder[256]; +static wchar_t g_ButtonMove[256]; +static wchar_t g_ButtonDontMove[256]; +static wchar_t g_ButtonCopy[256]; +static wchar_t g_ButtonDontCopy[256]; +static wchar_t g_ButtonCancel[256]; +static wchar_t g_ButtonMore[256]; +static HMODULE g_hShell32; + +static void LogPrint( CString *pLog, const wchar_t *format, ... ) +{ + wchar_t buf[256]; + va_list args; + va_start(args,format); + int len=Vsprintf(buf,_countof(buf),format,args); + va_end(args); + *pLog+=buf; +} + +// CClassicCopyFile - this is the implementation of the Copy UI dialog box for files + +class CClassicCopyFile +{ +public: + CClassicCopyFile( void ); + ~CClassicCopyFile( void ); + + bool Run( HWND hWnd, IAccessible *pAcc, CString *pLog ); + +private: + void EnumAccChildren( IAccessible *pAcc, CString *pLog ); + void AddAccChild( IAccessible *pAcc, const VARIANT &id, CString *pLog ); + void GetFileInfo( IAccessible *pAcc, bool bSrc ); + + CString m_FileName; + bool m_bSystem; + bool m_bReadOnly; + HICON m_Icon; + + CString m_SrcSize; + CString m_SrcTime; + HICON m_SrcIcon; + + CString m_DstSize; + CString m_DstTime; + HICON m_DstIcon; + + typedef std::pair,int> CControl; + CControl m_YesButton; + CControl m_NoButton; + CControl m_CheckBox; + CControl m_Cancel; + bool m_bCopyMultiLast; // the last of a series of multi-file boxes + + static INT_PTR CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); + + static void PumpMessages( void ); +}; + +CClassicCopyFile::CClassicCopyFile( void ) +{ + m_Icon=m_SrcIcon=m_DstIcon=NULL; + m_bCopyMultiLast=false; + m_bSystem=m_bReadOnly=false; +} + +CClassicCopyFile::~CClassicCopyFile( void ) +{ + if (m_Icon) DestroyIcon(m_Icon); + if (m_SrcIcon) DestroyIcon(m_SrcIcon); + if (m_DstIcon) DestroyIcon(m_DstIcon); +} + +// Show the dialog box. Returns true to suppress the original task dialog box +bool CClassicCopyFile::Run( HWND hWnd, IAccessible *pAcc, CString *pLog ) +{ + // find all interesting controls + EnumAccChildren(pAcc,pLog); + + if (!m_YesButton.first || m_YesButton.second!=CHILDID_SELF || !m_NoButton.first || m_NoButton.second!=CHILDID_SELF || !m_Cancel.first) + return false; // something is wrong, do nothing + + if (pLog) pLog->Empty(); // success - no need to log anything + + // get the info for the source and the destination file (file name, icon, properties) + m_bReadOnly=false; + m_bSystem=false; + GetFileInfo(m_YesButton.first,true); + GetFileInfo(m_NoButton.first,false); + + TlsData *pTlsData=GetTlsData(); + if (m_CheckBox.first) + pTlsData->bCopyMultiFile=true; + else if (pTlsData->bCopyMultiFile) + m_bCopyMultiLast=true; + + // pick the correct dialog template (for single and multiple files, for LTR and RTL) + int dlg=pTlsData->bCopyMultiFile?(IsLanguageRTL()?IDD_FILEMULTIR:IDD_FILEMULTI):(IsLanguageRTL()?IDD_FILER:IDD_FILE); + + HWND parent=GetWindow(GetAncestor(hWnd,GA_ROOT),GW_OWNER); + + int res=(int)DialogBoxParam(g_Instance,MAKEINTRESOURCE(dlg),parent,DialogProc,(LPARAM)this); + + if (res==IDOK || (res==IDYES && m_bCopyMultiLast)) + { + // Yes was pressed, proceed with the operation + m_YesButton.first->accDoDefaultAction(CComVariant(CHILDID_SELF)); + } + else if (res==IDNO) + { + // No + if (m_CheckBox.first && GetKeyState(VK_SHIFT)<0) + m_CheckBox.first->accDoDefaultAction(CComVariant(CHILDID_SELF)); // Shift+No = No to All + PumpMessages(); // messages need to be pumped after every accessibility action. otherwise the next action doesn't work + m_NoButton.first->accDoDefaultAction(CComVariant(CHILDID_SELF)); + } + else if (res==IDYES) + { + // Yes to All + m_CheckBox.first->accDoDefaultAction(CComVariant(CHILDID_SELF)); + PumpMessages(); // messages need to be pumped after every accessibility action. otherwise the next action doesn't work + m_YesButton.first->accDoDefaultAction(CComVariant(CHILDID_SELF)); + } + if (res==IDCANCEL) + { + // Cancel + if (GetKeyState(VK_SHIFT)<0 || GetKeyState(VK_CONTROL)<0) + return false; // // Shift+Cancel or Ctrl+Cancel was clicked - show the original dialog box + m_Cancel.first->accDoDefaultAction(CComVariant(CHILDID_SELF)); + } + if (res==IDC_LINKMORE) + { + // More... was clicked - show the original dialog box + return false; + } + return true; +} + +void CClassicCopyFile::PumpMessages( void ) +{ + MSG msg; + while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +void CClassicCopyFile::AddAccChild( IAccessible *pAcc, const VARIANT &id, CString *pLog ) +{ + CComVariant state; + pAcc->get_accState(id,&state); + if (state.intVal&(STATE_SYSTEM_UNAVAILABLE|STATE_SYSTEM_INVISIBLE)) return; + CComVariant role; + pAcc->get_accRole(id,&role); + if (role.intVal==ROLE_SYSTEM_PUSHBUTTON) + { + CComBSTR name; + if (SUCCEEDED(pAcc->get_accName(id,&name)) && name) + { + if (pLog) + LogPrint(pLog,L"button found: '%s', %d\r\n",name,id.intVal); + if (_wcsicmp(name,g_ButtonCopy)==0 || _wcsicmp(name,g_ButtonMove)==0) + { + m_YesButton.first=pAcc; + m_YesButton.second=id.intVal; + if (pLog) + LogPrint(pLog,L"YES button: %x, %d\r\n",(DWORD)pAcc,id.intVal); + } + else if (_wcsicmp(name,g_ButtonDontCopy)==0 || _wcsicmp(name,g_ButtonDontMove)==0) + { + m_NoButton.first=pAcc; + m_NoButton.second=id.intVal; + if (pLog) + LogPrint(pLog,L"NO button: %x, %d\r\n",(DWORD)pAcc,id.intVal); + } + else if (_wcsicmp(name,g_ButtonCancel)==0) + { + m_Cancel.first=pAcc; + m_Cancel.second=id.intVal; + if (pLog) + LogPrint(pLog,L"CANCEL button: %x, %d\r\n",(DWORD)pAcc,id.intVal); + } + } + } + if (role.intVal==ROLE_SYSTEM_CHECKBUTTON) + { + // hopefully there is only one checkbox + m_CheckBox.first=pAcc; + m_CheckBox.second=id.intVal; + } +} + +void CClassicCopyFile::EnumAccChildren( IAccessible *pAcc, CString *pLog ) +{ + AddAccChild(pAcc,CComVariant(CHILDID_SELF),pLog); + long count; + pAcc->get_accChildCount(&count); + CComVariant children[20]; + AccessibleChildren(pAcc,0,count,children,&count); + for (int i=0;i pChild=children[i].pdispVal; + if (pChild) + EnumAccChildren(pChild,pLog); + } + else + AddAccChild(pAcc,children[i],pLog); + } +} + +void CClassicCopyFile::GetFileInfo( IAccessible *pAcc, bool bSrc ) +{ + long count; + pAcc->get_accChildCount(&count); + CComVariant children[20]; + AccessibleChildren(pAcc,0,count,children,&count); + + wchar_t fname[_MAX_PATH]=L""; + wchar_t dir[_MAX_PATH]=L""; + CString size; + CString date; + + // get the file name, directory, size and date + for (int i=0;i pChild=children[i].pdispVal; + if (pChild) + pChild->get_accName(CComVariant(CHILDID_SELF),&name); + } + else + { + pAcc->get_accName(children[i],&name); + } + switch (i) + { + case 2: if (wcslen(name)<_countof(fname)) wcscpy_s(fname,name); break; + case 3: if (wcslen(name)<_countof(dir)) wcscpy_s(dir,name); break; + case 4: size=name; break; + case 5: date=name; break; + } + } + + if (bSrc) + { + m_FileName=fname; + m_SrcSize=size; + m_SrcTime=date; + } + else + { + m_DstSize=size; + m_DstTime=date; + } + + if (!fname[0] || !dir[0]) return; + + wchar_t fname2[_MAX_PATH]; + memcpy(fname2,fname,sizeof(fname2)); + *PathFindExtension(fname2)=0; + + int len1=Strlen(fname2); + // the directory text is something like "filename (directory)". we need to parse out the real directory name + int len2=Strlen(dir); + if (dir[0]==0x202A) len1++; // for Arabic the first character is some RTL marker. needs to be skipped + if (dir[len1]==0x1E) len1++; // for Hebrew there is an extra control character after the file name + if (len1+1>=len2 || dir[len1]!=L' ' || dir[len1+1]!=L'(' || dir[len2-1]!=L')') return; + if (dir[len1+2]==0x202A) len1++; // for Hebrew the first character is some RTL marker. needs to be skipped + if (dir[len2-2]==0x202C) len2--; // for Hebrew the last character is some RTL marker. needs to be skipped + dir[len2-1]=0; + + // construct the full file name + wchar_t path[_MAX_PATH]; + _wmakepath_s(path,NULL,dir+len1+2,fname,NULL); + + if (!bSrc) + { + DWORD attrib=GetFileAttributes(path); + if (attrib!=INVALID_FILE_ATTRIBUTES) + { + if (attrib&FILE_ATTRIBUTE_READONLY) m_bReadOnly=true; + if (attrib&FILE_ATTRIBUTE_SYSTEM) m_bSystem=true; + } + } + + // get file icon + HICON hIcon=NULL; + CAbsolutePidl pidl; + if (SUCCEEDED(SHParseDisplayName(path,NULL,&pidl,0,NULL)) && pidl) + { + int iconSize=GetSystemMetrics(SM_CXICON); + HBITMAP hBitmap=NULL; + CComPtr pFactory; + if (SUCCEEDED(SHCreateItemFromIDList(pidl,IID_IShellItemImageFactory,(void**)&pFactory)) && pFactory) + { + SIZE size={iconSize,iconSize}; + if (FAILED(pFactory->GetImage(size,SIIGBF_ICONONLY,&hBitmap))) + hBitmap=NULL; + } + + if (hBitmap) + { + HBITMAP hMonoBitmap=CreateBitmap(iconSize,iconSize,1,1,NULL); + ICONINFO info={TRUE,0,0,hMonoBitmap,hBitmap}; + hIcon=CreateIconIndirect(&info); + DeleteObject(hMonoBitmap); + DeleteObject(hBitmap); + } + } + if (!hIcon) return; + + if (bSrc) + m_SrcIcon=hIcon; + else + m_DstIcon=hIcon; +} + +const int WM_BRINGFOREGROUND=WM_USER+11; + +INT_PTR CALLBACK CClassicCopyFile::DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if (uMsg==WM_INITDIALOG) + { + SetWindowText(hwndDlg,FindTranslation(L"Copy.Title",L"Confirm File Replace")); + CClassicCopyFile *pThis=(CClassicCopyFile*)lParam; + wchar_t text[_MAX_PATH*2]; + if (pThis->m_bSystem) + { + Sprintf(text,_countof(text),FindTranslation(L"Copy.SubtitleSys",L"This folder already contains a system file named '%s'."),pThis->m_FileName); + if (GetSettingInt(L"OverwriteAlertLevel")>=1) + PlaySound(L".Default",NULL,SND_APPLICATION|SND_ALIAS|SND_ASYNC|SND_NODEFAULT|SND_SYSTEM); + } + else if (pThis->m_bReadOnly) + { + Sprintf(text,_countof(text),FindTranslation(L"Copy.SubtitleRO",L"This folder already contains a read-only file named '%s'."),pThis->m_FileName); + if (GetSettingInt(L"OverwriteAlertLevel")>=2) + PlaySound(L".Default",NULL,SND_APPLICATION|SND_ALIAS|SND_ASYNC|SND_NODEFAULT|SND_SYSTEM); + } + else + Sprintf(text,_countof(text),FindTranslation(L"Copy.Subtitle",L"This folder already contains a file named '%s'."),pThis->m_FileName); + SetDlgItemText(hwndDlg,IDC_STATICFNAME,text); + + // load icon for file conflict (146) from Shell32.dll + HMODULE hShell32=GetModuleHandle(L"Shell32.dll"); + pThis->m_Icon=LoadIcon(hShell32,MAKEINTRESOURCE(146)); + if (pThis->m_Icon) + SendDlgItemMessage(hwndDlg,IDC_STATICICON1,STM_SETICON,(LPARAM)pThis->m_Icon,0); + + // set the localized text + SetDlgItemText(hwndDlg,IDC_STATICPROMPT1,FindTranslation(L"Copy.Prompt1",L"Do you want to replace the existing file:")); + SetDlgItemText(hwndDlg,IDC_STATICDSTSIZE,pThis->m_DstSize); + SetDlgItemText(hwndDlg,IDC_STATICDSTTIME,pThis->m_DstTime); + SetDlgItemText(hwndDlg,IDC_STATICPROMPT2,FindTranslation(L"Copy.Prompt2",L"with this one?")); + SendDlgItemMessage(hwndDlg,IDC_STATICDSTICON,STM_SETICON,(LPARAM)pThis->m_DstIcon,0); + SetDlgItemText(hwndDlg,IDC_STATICSRCSIZE,pThis->m_SrcSize); + SetDlgItemText(hwndDlg,IDC_STATICSRCTIME,pThis->m_SrcTime); + SendDlgItemMessage(hwndDlg,IDC_STATICSRCICON,STM_SETICON,(LPARAM)pThis->m_SrcIcon,0); + SetDlgItemText(hwndDlg,IDOK,FindTranslation(L"Copy.Yes",L"&Yes")); + SetDlgItemText(hwndDlg,IDNO,FindTranslation(L"Copy.No",L"&No")); + if (GetDlgItem(hwndDlg,IDYES)) + SetDlgItemText(hwndDlg,IDYES,FindTranslation(L"Copy.YesAll",L"Yes to &All")); + if (GetDlgItem(hwndDlg,IDCANCEL)) + SetDlgItemText(hwndDlg,IDCANCEL,FindTranslation(L"Copy.Cancel",L"Cancel")); + Sprintf(text,_countof(text),L"%s",FindTranslation(L"Copy.More",L"&More...")); + SetDlgItemText(hwndDlg,IDC_LINKMORE,text); + PostMessage(hwndDlg,WM_BRINGFOREGROUND,0,0); + return TRUE; + } + if (uMsg==WM_BRINGFOREGROUND) + { + // bring window to front (sometimes on Windows7 it shows up behind Explorer) + SetForegroundWindow(hwndDlg); + return TRUE; + } + if (uMsg==WM_COMMAND && (wParam==IDOK || wParam==IDYES || wParam==IDNO || wParam==IDCANCEL)) + { + EndDialog(hwndDlg,wParam); + return TRUE; + } + if (uMsg==WM_NOTIFY) + { + NMHDR *pHdr=(NMHDR*)lParam; + if (pHdr->idFrom==IDC_LINKMORE && (pHdr->code==NM_CLICK || pHdr->code==NM_RETURN)) + { + EndDialog(hwndDlg,IDC_LINKMORE); + return TRUE; + } + } + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////// + +// CClassicCopyFolder - this is the implementation of the Copy UI dialog box for folders + +class CClassicCopyFolder +{ +public: + CClassicCopyFolder( void ) { m_Icon=NULL; m_Original=NULL; } + ~CClassicCopyFolder( void ); + + bool Run( HWND hWnd ); + +private: + HICON m_Icon; + HWND m_Original; + + static INT_PTR CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); +}; + +CClassicCopyFolder::~CClassicCopyFolder( void ) +{ + if (m_Icon) DestroyIcon(m_Icon); +} + +// Show the dialog box. Returns true to suppress the original task dialog box +bool CClassicCopyFolder::Run( HWND hWnd ) +{ + m_Original=hWnd; + const int ID_ALLCHECK=16663; + HWND check=GetDlgItem(hWnd,ID_ALLCHECK); + bool bMulti=(check && (GetWindowLong(check,GWL_STYLE)&WS_VISIBLE)); + // pick the correct dialog template (for single and multiple files, for LTR and RTL) + int dlg=bMulti?(IsLanguageRTL()?IDD_FOLDERMULTIR:IDD_FOLDERMULTI):(IsLanguageRTL()?IDD_FOLDERR:IDD_FOLDER); + + HWND parent=GetWindow(GetAncestor(hWnd,GA_ROOT),GW_OWNER); + + int res=(int)DialogBoxParam(g_Instance,MAKEINTRESOURCE(dlg),parent,DialogProc,(LPARAM)this); + + if (res==IDOK) // Yes button for single folder + { + // Yes was pressed, proceed with the operation + PostMessage(hWnd,WM_COMMAND,IDYES,(LPARAM)GetDlgItem(hWnd,IDYES)); + } + else if (res==IDNO) + { + // No + if (bMulti) + { + if (GetKeyState(VK_SHIFT)<0) + { + CheckDlgButton(hWnd,ID_ALLCHECK,BST_CHECKED); + SendMessage(hWnd,WM_COMMAND,ID_ALLCHECK,(LPARAM)check); + } + PostMessage(hWnd,WM_COMMAND,IDNO,(LPARAM)GetDlgItem(hWnd,IDNO)); // Skip + } + else + PostMessage(hWnd,WM_COMMAND,IDCANCEL,(LPARAM)GetDlgItem(hWnd,IDCANCEL)); // No + } + else if (res==IDYES) + { + // Yes to All + CheckDlgButton(hWnd,ID_ALLCHECK,BST_CHECKED); + SendMessage(hWnd,WM_COMMAND,ID_ALLCHECK,(LPARAM)check); + PostMessage(hWnd,WM_COMMAND,IDYES,(LPARAM)GetDlgItem(hWnd,IDYES)); + } + if (res==IDCANCEL) + { + // Cancel + if (GetKeyState(VK_SHIFT)<0 || GetKeyState(VK_CONTROL)<0) + return false; // // Shift+Cancel or Ctrl+Cancel was clicked - show the original dialog box + PostMessage(hWnd,WM_COMMAND,IDCANCEL,(LPARAM)GetDlgItem(hWnd,IDCANCEL)); // No + } + if (res==IDC_LINKMORE) + { + // More... was clicked - show the original dialog box + return false; + } + return true; +} + +INT_PTR CALLBACK CClassicCopyFolder::DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if (uMsg==WM_INITDIALOG) + { + SetWindowText(hwndDlg,FindTranslation(L"Folder.Title",L"Confirm Folder Replace")); + CClassicCopyFolder *pThis=(CClassicCopyFolder*)lParam; + wchar_t text[2048]; + // find the link control and get its text + HWND link=FindWindowEx(pThis->m_Original,NULL,WC_LINK,NULL); + if (link) + GetWindowText(link,text,_countof(text)); + else + text[0]=0; + Strcat(text,_countof(text),L"\r\n\r\n"); + Strcat(text,_countof(text),FindTranslation(L"Folder.Prompt",L"Do you still want to move or copy the folder?")); + SetDlgItemText(hwndDlg,IDC_STATICFNAME,text); + + // load icon for file conflict (146) from Shell32.dll + HMODULE hShell32=GetModuleHandle(L"Shell32.dll"); + pThis->m_Icon=LoadIcon(hShell32,MAKEINTRESOURCE(146)); + if (pThis->m_Icon) + SendDlgItemMessage(hwndDlg,IDC_STATICICON1,STM_SETICON,(LPARAM)pThis->m_Icon,0); + + // set the localized text + SetDlgItemText(hwndDlg,IDOK,FindTranslation(L"Copy.Yes",L"&Yes")); + SetDlgItemText(hwndDlg,IDNO,FindTranslation(L"Copy.No",L"&No")); + if (GetDlgItem(hwndDlg,IDYES)) + SetDlgItemText(hwndDlg,IDYES,FindTranslation(L"Copy.YesAll",L"Yes to &All")); + if (GetDlgItem(hwndDlg,IDCANCEL)) + SetDlgItemText(hwndDlg,IDCANCEL,FindTranslation(L"Copy.Cancel",L"Cancel")); + Sprintf(text,_countof(text),L"%s",FindTranslation(L"Copy.More",L"&More...")); + SetDlgItemText(hwndDlg,IDC_LINKMORE,text); + PostMessage(hwndDlg,WM_BRINGFOREGROUND,0,0); + return TRUE; + } + if (uMsg==WM_BRINGFOREGROUND) + { + // bring window to front (sometimes on Windows7 it shows up behind Explorer) + SetForegroundWindow(hwndDlg); + return TRUE; + } + if (uMsg==WM_COMMAND && (wParam==IDOK || wParam==IDYES || wParam==IDNO || wParam==IDCANCEL)) + { + EndDialog(hwndDlg,wParam); + return TRUE; + } + if (uMsg==WM_NOTIFY) + { + NMHDR *pHdr=(NMHDR*)lParam; + if (pHdr->idFrom==IDC_LINKMORE && (pHdr->code==NM_CLICK || pHdr->code==NM_RETURN)) + { + EndDialog(hwndDlg,IDC_LINKMORE); + return TRUE; + } + } + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////// + +static CComPtr FindMoreButton( IAccessible *pAcc ) +{ + CComVariant state; + CComVariant self(CHILDID_SELF); + pAcc->get_accState(self,&state); + if (!(state.intVal&(STATE_SYSTEM_UNAVAILABLE|STATE_SYSTEM_INVISIBLE))) + { + CComVariant role; + pAcc->get_accRole(self,&role); + if (role.intVal==ROLE_SYSTEM_PUSHBUTTON) + { + CComBSTR name; + if (SUCCEEDED(pAcc->get_accName(self,&name)) && name && _wcsicmp(name,g_ButtonMore)==0) + return pAcc; + } + } + + CComVariant children[30]; + long count; + AccessibleChildren(pAcc,0,_countof(children),children,&count); + for (int i=0;i pChild=children[i].pdispVal; + if (pChild) + { + CComPtr pRes=FindMoreButton(pChild); + if (pRes) return pRes; + } + } + } + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +static LRESULT CALLBACK WindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_WINDOWPOSCHANGING) + { + WINDOWPOS *pos=(WINDOWPOS*)lParam; + if (pos->flags&SWP_SHOWWINDOW) + { + wchar_t title[256]; + GetWindowText(hWnd,title,_countof(title)); + + if (_wcsicmp(title,g_TitleMove)==0 || _wcsicmp(title,g_TitleCopy)==0) + { + // file UI + if (GetSettingBool(L"ReplaceFileUI")) + { + CString log; + CComPtr pAcc; + HRESULT h=AccessibleObjectFromWindow(hWnd,OBJID_WINDOW,IID_IAccessible,(void**)&pAcc); + if (SUCCEEDED(h) && pAcc) + { + CClassicCopyFile copy; + if (copy.Run(hWnd,pAcc,g_bLogLevel?&log:NULL)) + { + pos->x=pos->y=-20000; + pos->flags&=~(SWP_SHOWWINDOW|SWP_NOMOVE); + } + } + else if (g_bLogLevel) + LogPrint(&log,L"AccessibleObjectFromWindow: error=0x%X, hWnd=0x%X",h,(DWORD)hWnd); + + if (g_bLogLevel) + { + wchar_t fname[_MAX_PATH]=L"%LOCALAPPDATA%\\ClassicShell"; + DoEnvironmentSubst(fname,_MAX_PATH); + SHCreateDirectory(NULL,fname); + Strcat(fname,_countof(fname),L"\\ExplorerLog.txt"); + if (!log.IsEmpty()) + { + FILE *f; + if (_wfopen_s(&f,fname,L"wb")==0) + { + fwprintf(f,L"\xFEFF"); + + OSVERSIONINFOEX ver={sizeof(ver)}; + GetVersionEx((OSVERSIONINFO*)&ver); + fwprintf(f,L"version = %d.%d.%d - %d.%d\r\n\r\n",ver.dwMajorVersion,ver.dwMinorVersion,ver.dwBuildNumber,ver.wServicePackMajor,ver.wServicePackMinor); + + wchar_t languages[100]={0}; + ULONG size=4; // up to 4 languages + ULONG len=_countof(languages); + GetUserPreferredUILanguages(MUI_LANGUAGE_NAME,&size,languages,&len); + for (const wchar_t *lang=languages;*lang;lang+=wcslen(lang)+1) + fwprintf(f,L"language = %s\r\n",lang); + + fwprintf(f,L"\r\n"); + fwprintf(f,L"g_ButtonMove = '%s'\r\n",g_ButtonMove); + fwprintf(f,L"g_ButtonDontMove = '%s'\r\n",g_ButtonDontMove); + fwprintf(f,L"g_ButtonCopy = '%s'\r\n",g_ButtonCopy); + fwprintf(f,L"g_ButtonDontCopy = '%s'\r\n",g_ButtonDontCopy); + fwprintf(f,L"g_ButtonCancel = '%s'\r\n",g_ButtonCancel); + fwprintf(f,L"\r\n"); + + fwrite((const wchar_t*)log,log.GetLength(),2,f); + fclose(f); + } + } + else + DeleteFile(fname); + } + } + } + else if (_wcsicmp(title,g_TitleFolder)==0) + { + // folder UI + if (GetSettingBool(L"ReplaceFolderUI")) + { + CClassicCopyFolder copy; + if (copy.Run(hWnd)) + { + pos->x=pos->y=-20000; + pos->flags&=~(SWP_SHOWWINDOW|SWP_NOMOVE); + } + } + } + else + { + // look for progress bar + if (GetSettingBool(L"EnableMore")) + { + HWND progress=FindChildWindow(hWnd,PROGRESS_CLASS); + if (progress) + { + bool bDef; + int delay=GetSettingInt(L"MoreProgressDelay",bDef); + if (bDef) + { + delay=0; + if (GetWinVersion()>=WIN_VER_WIN7) + { + BOOL comp; + if (SUCCEEDED(DwmIsCompositionEnabled(&comp)) && comp) + delay=500; + } + } + SetTimer(hWnd,'CLEX',delay,NULL); + return DefSubclassProc(hWnd,uMsg,wParam,lParam); + } + } + } + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + RemoveWindowSubclass(hWnd,WindowProc,uIdSubclass); + return res; + } + } + if (uMsg==WM_TIMER && wParam=='CLEX') + { + KillTimer(hWnd,wParam); + + CComPtr pAcc; + HRESULT h=AccessibleObjectFromWindow(hWnd,OBJID_WINDOW,IID_IAccessible,(void**)&pAcc); + if (SUCCEEDED(h) && pAcc) + { + CComPtr pMore=FindMoreButton(pAcc); + if (pMore) pMore->accDoDefaultAction(CComVariant(CHILDID_SELF)); + } + + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + RemoveWindowSubclass(hWnd,WindowProc,uIdSubclass); + return res; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +LRESULT CALLBACK ClassicCopyHook( int nCode, WPARAM wParam, LPARAM lParam ) +{ + if (nCode==HCBT_CREATEWND) + { + HWND hWnd=(HWND)wParam; + CBT_CREATEWND *create=(CBT_CREATEWND*)lParam; + HINSTANCE hInst=(HINSTANCE)GetWindowLongPtr(hWnd,GWLP_HINSTANCE); + if (create->lpcs->lpszName && (int)create->lpcs->lpszClass==32770 && hInst==g_hShell32) + { + WaitDllInitThread(); + static LONG id; + int i=InterlockedIncrement(&id); + SetWindowSubclass(hWnd,WindowProc,i,0); + } + } + TlsData *pTlsData=GetTlsData(); + return CallNextHookEx(pTlsData->copyHook,nCode,wParam,lParam); +} + +void InitClassicCopyProcess( void ) +{ + // load UI text from shell32.dll + // the text is used to locate controls in the copy dialog by name + g_hShell32=GetModuleHandle(L"shell32.dll"); + LoadString(g_hShell32,17027,g_TitleMove,256); + LoadString(g_hShell32,17024,g_TitleCopy,256); + LoadString(g_hShell32,16705,g_TitleFolder,256); + LoadString(g_hShell32,13610,g_ButtonMove,256); + LoadString(g_hShell32,13623,g_ButtonDontMove,256); + LoadString(g_hShell32,13604,g_ButtonCopy,256); + LoadString(g_hShell32,13606,g_ButtonDontCopy,256); + LoadString(g_hShell32,13588,g_ButtonCancel,256); + LoadString(g_hShell32,32992,g_ButtonMore,256); +} + +void InitClassicCopyThread( void ) +{ + TlsData *pTlsData=GetTlsData(); + if (!pTlsData->copyHook) + pTlsData->copyHook=SetWindowsHookEx(WH_CBT,ClassicCopyHook,g_Instance,GetCurrentThreadId()); +} + +void FreeClassicCopyThread( void ) +{ + TlsData *pTlsData=GetTlsData(); + if (pTlsData->copyHook) + { + UnhookWindowsHookEx(pTlsData->copyHook); + pTlsData->copyHook=NULL; + } +} diff --git a/ClassicShellSrc/ClassicExplorer/ClassicCopyExt.cpp b/ClassicShellSrc/ClassicExplorer/ClassicCopyExt.cpp new file mode 100644 index 0000000..90a8e0f --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicCopyExt.cpp @@ -0,0 +1,43 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// ClassicCopyExt.cpp : Implementation of CClassicCopyExt + +#include "stdafx.h" +#include "ClassicCopyExt.h" +#include "ResourceHelper.h" +#include "dllmain.h" + + +// CClassicCopyExt - this is a dummy drag and drop handler. Its purpose is to get Explorer to load the DLL when +// a file is being copied or moved. + +void InitClassicCopyThread( void ); + +STDMETHODIMP CClassicCopyExt::Initialize( PCIDLIST_ABSOLUTE pidlFolder, LPDATAOBJECT pDataObj, HKEY hProgID ) +{ + InitClassicCopyThread(); + return S_OK; +} + +STDMETHODIMP CClassicCopyExt::QueryContextMenu( HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags ) +{ + return MAKE_HRESULT(SEVERITY_SUCCESS,FACILITY_NULL,0); +} + +STDMETHODIMP CClassicCopyExt::GetCommandString( UINT_PTR idCmd, UINT uFlags, UINT* pwReserved, LPSTR pszName, UINT cchMax ) +{ + return E_INVALIDARG; +} + +STDMETHODIMP CClassicCopyExt::InvokeCommand( LPCMINVOKECOMMANDINFO pCmdInfo ) +{ + return E_INVALIDARG; +} + +HRESULT WINAPI CClassicCopyExt::UpdateRegistry( BOOL bRegister ) +{ + if (GetWinVersion()>=WIN_VER_WIN8) + return S_OK; + return _AtlModule.UpdateRegistryFromResource(IDR_CLASSICCOPYEXT,bRegister); +} diff --git a/ClassicShellSrc/ClassicExplorer/ClassicCopyExt.h b/ClassicShellSrc/ClassicExplorer/ClassicCopyExt.h new file mode 100644 index 0000000..e28b35a --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicCopyExt.h @@ -0,0 +1,58 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// ClassicCopyExt.h : Declaration of the CClassicCopyExt + +#pragma once +#include "resource.h" // main symbols + +#include "ClassicExplorer_i.h" +#include + +// CClassicCopyExt + +class ATL_NO_VTABLE CClassicCopyExt : + public CComObjectRootEx, + public CComCoClass, + public IShellExtInit, + public IContextMenu + +{ +public: + CClassicCopyExt() + { + } + + static HRESULT WINAPI UpdateRegistry( BOOL bRegister ); + +DECLARE_NOT_AGGREGATABLE(CClassicCopyExt) + +BEGIN_COM_MAP(CClassicCopyExt) + COM_INTERFACE_ENTRY(IShellExtInit) + COM_INTERFACE_ENTRY(IContextMenu) +END_COM_MAP() + + + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + HRESULT FinalConstruct() + { + return S_OK; + } + + void FinalRelease() + { + } + +public: + // IShellExtInit + STDMETHODIMP Initialize(PCIDLIST_ABSOLUTE, LPDATAOBJECT, HKEY); + + // IContextMenu + STDMETHODIMP GetCommandString(UINT_PTR, UINT, UINT*, LPSTR, UINT); + STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO); + STDMETHODIMP QueryContextMenu(HMENU, UINT, UINT, UINT, UINT); +}; + +OBJECT_ENTRY_AUTO(__uuidof(ClassicCopyExt), CClassicCopyExt) diff --git a/ClassicShellSrc/ClassicExplorer/ClassicCopyExt.rgs b/ClassicShellSrc/ClassicExplorer/ClassicCopyExt.rgs new file mode 100644 index 0000000..4a09c1c --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicCopyExt.rgs @@ -0,0 +1,58 @@ +HKCR +{ + ClassicExplorer.ClassicCopyExt.1 = s 'ClassicCopyExt Class' + { + CLSID = s '{8C83ACB1-75C3-45D2-882C-EFA32333491C}' + } + ClassicExplorer.ClassicCopyExt = s 'ClassicCopyExt Class' + { + CLSID = s '{8C83ACB1-75C3-45D2-882C-EFA32333491C}' + CurVer = s 'ClassicExplorer.ClassicCopyExt.1' + } + NoRemove CLSID + { + ForceRemove {8C83ACB1-75C3-45D2-882C-EFA32333491C} = s 'ClassicCopyExt Class' + { + ProgID = s 'ClassicExplorer.ClassicCopyExt.1' + VersionIndependentProgID = s 'ClassicExplorer.ClassicCopyExt' + ForceRemove 'Programmable' + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Apartment' + } + 'TypeLib' = s '{BF8D124A-A4E0-402F-8152-4EF377E62586}' + } + } + + NoRemove Directory + { + NoRemove shellex + { + NoRemove DragDropHandlers + { + ForceRemove ClassicCopyExt = s '{8C83ACB1-75C3-45D2-882C-EFA32333491C}' + } + } + } + NoRemove Drive + { + NoRemove shellex + { + NoRemove DragDropHandlers + { + ForceRemove ClassicCopyExt = s '{8C83ACB1-75C3-45D2-882C-EFA32333491C}' + } + } + } + + NoRemove Folder + { + NoRemove shellex + { + NoRemove DragDropHandlers + { + ForceRemove ClassicCopyExt = s '{8C83ACB1-75C3-45D2-882C-EFA32333491C}' + } + } + } +} diff --git a/ClassicShellSrc/ClassicExplorer/ClassicExplorer.cpp b/ClassicShellSrc/ClassicExplorer/ClassicExplorer.cpp new file mode 100644 index 0000000..66b55f4 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicExplorer.cpp @@ -0,0 +1,90 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// ClassicExplorer.cpp : Implementation of DLL Exports. + +#include "stdafx.h" +#include "resource.h" +#include "ClassicExplorer_i.h" +#include "dllmain.h" + +// Used to determine whether the DLL can be unloaded by OLE +STDAPI DllCanUnloadNow(void) +{ + return _AtlModule.DllCanUnloadNow(); +} + +extern bool g_bExplorerExe; + +// Returns a class factory to create an object of the requested type +STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) +{ + WaitDllInitThread(); + if (!g_bExplorerExe && rclsid!=CLSID_ShareOverlay) + return CLASS_E_CLASSNOTAVAILABLE; + return _AtlModule.DllGetClassObject(rclsid, riid, ppv); +} + + +// DllRegisterServer - Adds entries to the system registry +STDAPI DllRegisterServer(void) +{ + WaitDllInitThread(); + // registers object, typelib and all interfaces in typelib + HRESULT res=_AtlModule.DllRegisterServer(); + if (SUCCEEDED(res)) + { + // mark the extensions as compatible with the enhanced protected mode of IE10 + // they are not technically IE extensions, but it complains about them as + // being incompatible + CComPtr catRegister; + catRegister.CoCreateInstance(CLSID_StdComponentCategoriesMgr); + if (catRegister) + { + CATID CATID_AppContainerCompatible={0x59fb2056,0xd625,0x48d0,{0xa9,0x44,0x1a,0x85,0xb5,0xab,0x26,0x40}}; + catRegister->RegisterClassImplCategories(CLSID_ExplorerBHO,1,&CATID_AppContainerCompatible); + catRegister->RegisterClassImplCategories(CLSID_ExplorerBand,1,&CATID_AppContainerCompatible); + } + } + return res; +} + + +// DllUnregisterServer - Removes entries from the system registry +STDAPI DllUnregisterServer(void) +{ + WaitDllInitThread(); + return _AtlModule.DllUnregisterServer(); +} + +// DllInstall - Adds/Removes entries to the system registry per user +// per machine. +STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine) +{ + WaitDllInitThread(); + HRESULT hr = E_FAIL; + static const wchar_t szUserSwitch[] = L"user"; + + if (pszCmdLine != NULL) + { + if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0) + { + AtlSetPerUserRegistration(true); + } + } + + if (bInstall) + { + hr = DllRegisterServer(); + if (FAILED(hr)) + { + DllUnregisterServer(); + } + } + else + { + hr = DllUnregisterServer(); + } + + return hr; +} diff --git a/ClassicShellSrc/ClassicExplorer/ClassicExplorer.idl b/ClassicShellSrc/ClassicExplorer/ClassicExplorer.idl new file mode 100644 index 0000000..a457dc4 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicExplorer.idl @@ -0,0 +1,90 @@ +// ClassicExplorer.idl : IDL source for ClassicExplorer +// + +// This file will be processed by the MIDL tool to +// produce the type library (ClassicExplorer.tlb) and marshalling code. + +import "oaidl.idl"; +import "ocidl.idl"; + +[ + object, + uuid(BC4C1B8F-0BDE-4E42-9583-E072B2A28E0D), + dual, + nonextensible, + helpstring("IExplorerBand Interface"), + pointer_default(unique) +] +interface IExplorerBand : IDispatch{ +}; +[ + object, + uuid(6E00B97F-A4D4-4062-98E4-4F66FC96F32F), + dual, + nonextensible, + helpstring("IClassicCopyExt Interface"), + pointer_default(unique) +] +interface IClassicCopyExt : IDispatch{ +}; +[ + object, + uuid(A1678625-A011-4B7C-A1FA-D691E4CDDB79), + dual, + nonextensible, + helpstring("IExplorerBHO Interface"), + pointer_default(unique) +] +interface IExplorerBHO : IDispatch{ +}; +[ + object, + uuid(2576496C-B58A-4995-8878-8B68F9E8D1FC), + dual, + nonextensible, + helpstring("IShareOverlay Interface"), + pointer_default(unique) +] +interface IShareOverlay : IDispatch{ +}; +[ + uuid(BF8D124A-A4E0-402F-8152-4EF377E62586), + version(1.0), + helpstring("ClassicExplorer 1.0 Type Library") +] +library ClassicExplorerLib +{ + importlib("stdole2.tlb"); + [ + uuid(553891B7-A0D5-4526-BE18-D3CE461D6310), + helpstring("ExplorerBand Class") + ] + coclass ExplorerBand + { + [default] interface IExplorerBand; + }; + [ + uuid(8C83ACB1-75C3-45D2-882C-EFA32333491C), + helpstring("ClassicCopyExt Class") + ] + coclass ClassicCopyExt + { + [default] interface IClassicCopyExt; + }; + [ + uuid(449D0D6E-2412-4E61-B68F-1CB625CD9E52), + helpstring("ExplorerBHO Class") + ] + coclass ExplorerBHO + { + [default] interface IExplorerBHO; + }; + [ + uuid(594D4122-1F87-41E2-96C7-825FB4796516), + helpstring("ShareOverlay Class") + ] + coclass ShareOverlay + { + [default] interface IShareOverlay; + }; +}; diff --git a/ClassicShellSrc/ClassicExplorer/ClassicExplorer.rc b/ClassicShellSrc/ClassicExplorer/ClassicExplorer.rc new file mode 100644 index 0000000..59dfcd2 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicExplorer.rc @@ -0,0 +1,674 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" +#include "..\ClassicShellLib\resource.h" +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "#include ""..\\ClassicShellLib\\resource.h""\0" +END + +3 TEXTINCLUDE +BEGIN + "#include ""..\\ClassicShellLib\\resource.h""\r\n" + "#include ""..\\ClassicShellLib\\ClassicShellLib.rc""\r\n" + "1 TYPELIB ""ClassicExplorer.tlb""\r\0" +END + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "#include ""..\\ClassicShellLib\\resource.h""\r\n" + "#include ""..\\ClassicShellLib\\ClassicShellLib.rc""\r\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\0" +END + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#ifndef APSTUDIO_INVOKED\r\n" + "#include ""targetver.h""\r\n" + "#endif\r\n" + "#include ""winres.h""\r\n" + "#include ""..\\ClassicShellLib\\resource.h""\r\n" + "#include ""..\\ClassicShellLib\\ClassicShellLib.rc""\r\0" +END + +3 TEXTINCLUDE +BEGIN + "1 TYPELIB ""ClassicExplorer.tlb""\r\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_FILE DIALOGEX 0, 0, 266, 136 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Confirm File Replace" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "&Yes",IDOK,149,115,53,14 + PUSHBUTTON "&No",IDNO,206,115,53,14 + ICON "",IDC_STATICICON1,7,7,20,20 + LTEXT "This folder already contains a file called 'blah.txt'.",IDC_STATICFNAME,35,7,224,23,SS_NOPREFIX + LTEXT "Do you want to replace the existing file:",IDC_STATICPROMPT1,35,34,224,8,SS_NOPREFIX + ICON "",IDC_STATICDSTICON,43,46,20,20 + LTEXT "Static",IDC_STATICDSTSIZE,69,47,190,8,SS_NOPREFIX + LTEXT "Static",IDC_STATICDSTTIME,69,57,190,8,SS_NOPREFIX + LTEXT "with this one?",IDC_STATICPROMPT2,35,74,224,8,SS_NOPREFIX + ICON "",IDC_STATICSRCICON,43,86,20,20 + LTEXT "Static",IDC_STATICSRCSIZE,69,87,190,8,SS_NOPREFIX + LTEXT "Static",IDC_STATICSRCTIME,69,97,190,8,SS_NOPREFIX + CONTROL "&More...",IDC_LINKMORE,"SysLink",WS_TABSTOP,7,120,57,10 +END + +IDD_FILEMULTI DIALOGEX 0, 0, 285, 136 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Confirm File Replace" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "&Yes",IDOK,55,115,53,14 + PUSHBUTTON "Yes to &All",IDYES,112,115,53,14 + PUSHBUTTON "&No",IDNO,169,115,53,14 + PUSHBUTTON "Cancel",IDCANCEL,226,115,53,14 + ICON "",IDC_STATICICON1,7,7,20,20 + LTEXT "This folder already contains a file called 'blah.txt'.",IDC_STATICFNAME,35,7,243,23,SS_NOPREFIX + LTEXT "Do you want to replace the existing file:",IDC_STATICPROMPT1,35,34,243,8,SS_NOPREFIX + ICON "",IDC_STATICDSTICON,43,46,20,20 + LTEXT "Static",IDC_STATICDSTSIZE,69,47,209,8,SS_NOPREFIX + LTEXT "Static",IDC_STATICDSTTIME,69,57,209,8,SS_NOPREFIX + LTEXT "with this one?",IDC_STATICPROMPT2,35,74,243,8,SS_NOPREFIX + ICON "",IDC_STATICSRCICON,43,86,20,20 + LTEXT "Static",IDC_STATICSRCSIZE,69,87,209,8,SS_NOPREFIX + LTEXT "Static",IDC_STATICSRCTIME,69,97,209,8,SS_NOPREFIX + CONTROL "&More...",IDC_LINKMORE,"SysLink",WS_TABSTOP,7,120,45,10 +END + +IDD_FILEMULTIR DIALOGEX 0, 0, 285, 136 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_LAYOUTRTL +CAPTION "Confirm File Replace" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "&Yes",IDOK,55,115,53,14 + PUSHBUTTON "Yes to &All",IDYES,112,115,53,14 + PUSHBUTTON "&No",IDNO,169,115,53,14 + PUSHBUTTON "Cancel",IDCANCEL,226,115,53,14 + ICON "",IDC_STATICICON1,7,7,20,20 + LTEXT "This folder already contains a file called 'blah.txt'.",IDC_STATICFNAME,35,7,243,23,SS_NOPREFIX + LTEXT "Do you want to replace the existing file:",IDC_STATICPROMPT1,35,34,243,8,SS_NOPREFIX + ICON "",IDC_STATICDSTICON,43,46,20,20 + LTEXT "Static",IDC_STATICDSTSIZE,69,47,209,8,SS_NOPREFIX + LTEXT "Static",IDC_STATICDSTTIME,69,57,209,8,SS_NOPREFIX + LTEXT "with this one?",IDC_STATICPROMPT2,35,74,243,8,SS_NOPREFIX + ICON "",IDC_STATICSRCICON,43,86,20,20 + LTEXT "Static",IDC_STATICSRCSIZE,69,87,209,8,SS_NOPREFIX + LTEXT "Static",IDC_STATICSRCTIME,69,97,209,8,SS_NOPREFIX + CONTROL "&More...",IDC_LINKMORE,"SysLink",WS_TABSTOP,7,120,45,10 +END + +IDD_FILER DIALOGEX 0, 0, 266, 136 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_LAYOUTRTL +CAPTION "Confirm File Replace" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "&Yes",IDOK,149,115,53,14 + PUSHBUTTON "&No",IDNO,206,115,53,14 + ICON "",IDC_STATICICON1,7,7,20,20 + LTEXT "This folder already contains a file called 'blah.txt'.",IDC_STATICFNAME,35,7,224,23,SS_NOPREFIX + LTEXT "Do you want to replace the existing file:",IDC_STATICPROMPT1,35,34,224,8,SS_NOPREFIX + ICON "",IDC_STATICDSTICON,43,46,20,20 + LTEXT "Static",IDC_STATICDSTSIZE,69,47,190,8,SS_NOPREFIX + LTEXT "Static",IDC_STATICDSTTIME,69,57,190,8,SS_NOPREFIX + LTEXT "with this one?",IDC_STATICPROMPT2,35,74,224,8,SS_NOPREFIX + ICON "",IDC_STATICSRCICON,43,86,20,20 + LTEXT "Static",IDC_STATICSRCSIZE,69,87,190,8,SS_NOPREFIX + LTEXT "Static",IDC_STATICSRCTIME,69,97,190,8,SS_NOPREFIX + CONTROL "&More...",IDC_LINKMORE,"SysLink",WS_TABSTOP,7,120,57,10 +END + +IDD_FOLDERMULTI DIALOGEX 0, 0, 285, 100 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Confirm Folder Replace" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "&Yes",IDOK,55,79,53,14 + PUSHBUTTON "Yes to &All",IDYES,112,79,53,14 + PUSHBUTTON "&No",IDNO,169,79,53,14 + PUSHBUTTON "Cancel",IDCANCEL,226,79,53,14 + ICON "",IDC_STATICICON1,7,7,20,20 + LTEXT "This folder already contains a folder called 'blah'.",IDC_STATICFNAME,35,7,243,65,SS_NOPREFIX + CONTROL "&More...",IDC_LINKMORE,"SysLink",WS_TABSTOP,7,84,45,10 +END + +IDD_FOLDER DIALOGEX 0, 0, 266, 100 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Confirm Folder Replace" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "&Yes",IDOK,149,79,53,14 + PUSHBUTTON "&No",IDNO,206,79,53,14 + ICON "",IDC_STATICICON1,7,7,20,20 + LTEXT "This folder already contains a folder called 'blah'.",IDC_STATICFNAME,35,7,224,65,SS_NOPREFIX + CONTROL "&More...",IDC_LINKMORE,"SysLink",WS_TABSTOP,7,84,57,10 +END + +IDD_FOLDERR DIALOGEX 0, 0, 266, 99 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_LAYOUTRTL +CAPTION "Confirm Folder Replace" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "&Yes",IDOK,149,78,53,14 + PUSHBUTTON "&No",IDNO,206,78,53,14 + ICON "",IDC_STATICICON1,7,7,20,20 + LTEXT "This folder already contains a folder called 'blah'.",IDC_STATICFNAME,35,7,224,65,SS_NOPREFIX + CONTROL "&More...",IDC_LINKMORE,"SysLink",WS_TABSTOP,7,83,57,10 +END + +IDD_FOLDERMULTIR DIALOGEX 0, 0, 285, 100 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_LAYOUTRTL +CAPTION "Confirm Folder Replace" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "&Yes",IDOK,55,79,53,14 + PUSHBUTTON "Yes to &All",IDYES,112,79,53,14 + PUSHBUTTON "&No",IDNO,169,79,53,14 + PUSHBUTTON "Cancel",IDCANCEL,226,79,53,14 + ICON "",IDC_STATICICON1,7,7,20,20 + LTEXT "This folder already contains a folder called 'blah'.",IDC_STATICFNAME,35,7,243,65,SS_NOPREFIX + CONTROL "&More...",IDC_LINKMORE,"SysLink",WS_TABSTOP,7,84,45,10 +END + +IDD_CUSTOMTOOLBAR DIALOGEX 0, 0, 249, 183 +STYLE DS_SETFONT | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +CAPTION "Edit Toolbar Button (%s)" +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + LTEXT "Command:",IDC_STATICCOMMAND,7,7,35,12,SS_CENTERIMAGE + COMBOBOX IDC_COMBOCOMMAND,47,7,180,30,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "...",IDC_BUTTONCOMMAND,228,7,14,12 + LTEXT "Link:",IDC_STATICLINK,7,23,16,12,SS_CENTERIMAGE + COMBOBOX IDC_COMBOLINK,47,23,180,30,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "...",IDC_BUTTONLINK,228,23,14,12 + LTEXT "Label:",IDC_STATICTEXT,7,41,22,12,SS_CENTERIMAGE + EDITTEXT IDC_EDITLABEL,47,41,195,12,ES_AUTOHSCROLL + LTEXT "Tip:",IDC_STATICINFOTIP,7,58,13,12,SS_CENTERIMAGE + EDITTEXT IDC_EDITTIP,47,58,195,12,ES_AUTOHSCROLL + LTEXT "Icon:",IDC_STATICICON,7,74,18,12,SS_CENTERIMAGE + EDITTEXT IDC_EDITICON,47,74,180,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BUTTONICON,228,74,14,12 + ICON "",IDC_ICONN,9,89,20,20 + LTEXT "Disabled:",IDC_STATICICOND,7,113,35,12,SS_CENTERIMAGE + EDITTEXT IDC_EDITICOND,47,113,180,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BUTTONICOND,228,113,14,12 + ICON "",IDC_ICOND,9,127,20,20 + PUSHBUTTON "Restore defaults",IDC_BUTTONRESET,7,162,90,14 + DEFPUSHBUTTON "OK",IDOK,135,162,50,14 + PUSHBUTTON "Cancel",IDCANCEL,192,162,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 4,3,1,0 + PRODUCTVERSION 4,3,1,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "IvoSoft" + VALUE "FileDescription", "Adds classic Windows Explorer features" + VALUE "FileVersion", "4, 3, 1, 0" + VALUE "InternalName", "ClassicExplorer.dll" + VALUE "LegalCopyright", "Copyright (C) 2009-2016, Ivo Beltchev" + VALUE "OriginalFilename", "ClassicExplorer.dll" + VALUE "ProductName", "Classic Shell" + VALUE "ProductVersion", "4, 3, 1, 0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// REGISTRY +// + +IDR_CLASSICEXPLORER REGISTRY "ClassicExplorer.rgs" +IDR_EXPLORERBAND REGISTRY "ExplorerBand.rgs" +IDR_EXPLORERBHO REGISTRY "ExplorerBHO.rgs" +IDR_CLASSICCOPYEXT REGISTRY "ClassicCopyExt.rgs" +IDR_SHAREOVERLAY REGISTRY "ShareOverlay.rgs" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APPICON ICON "..\\ClassicShellSetup\\ClassicShell.ico" +IDI_UP2DISABLED ICON "up2Disabled.ico" +IDI_UP2HOT ICON "up2Hot.ico" +IDI_UP2NORMAL ICON "up2Normal.ico" +IDI_UP2PRESSED ICON "up2Pressed.ico" +IDI_UP ICON "up.ico" +IDI_UPDISABLED ICON "upDisabled.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CUSTOMTOOLBAR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 242 + TOPMARGIN, 7 + BOTTOMMARGIN, 176 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_APP_TITLE "Classic Explorer" + IDS_NEW_SETTINGS1 "The new settings will take effect the next time you open an Explorer window." + IDS_NEW_SETTINGS2 "You need to log off and back on for the new settings to take effect." + IDS_SETTINGS_TITLE "Settings for Classic Explorer" + IDS_SETTINGS_TITLE_VER "Settings for Classic Explorer %d.%d.%d" + IDS_LANGUAGE_SETTINGS "Language" + IDS_TOOLBAR_SETTINGS "Toolbar Settings" + IDS_BIG_BUTTONS "Big buttons" + IDS_BIG_BUTTONS_TIP "Use big buttons in the toolbar" + IDS_SMALL_SIZE "Small icon size" + IDS_SMALL_SIZE_TIP "Set the icon size when 'Big buttons' is unchecked. By default it is 16 for DPI<120 and 24 for DPI>=120" +END + +STRINGTABLE +BEGIN + IDS_LARGE_SIZE "Large icon size" + IDS_LARGE_SIZE_TIP "Set the icon size when 'Big buttons' is checked. By default it is 24 for DPI<120 and 32 for DPI>=120" + IDS_MENU_SIZE "Menu icon size" + IDS_MENU_SIZE_TIP "Set the size of the icons in the dropdown menus" + IDS_SAME_SIZE "Same size buttons" + IDS_SAME_SIZE_TIP "When this is checked, all toolbar buttons are the same size, determined by the widest button. Cannot be combined with 'Text is on the side'" + IDS_LIST_MODE "Text is on the side" + IDS_LIST_MODE_TIP "When this is checked, the toolbar is in list mode. The button text shows next to the icon instead of under the icon" + IDS_RESIZEABLE "Resizeable toolbar" + IDS_RESIZEABLE_TIP "When this is checked, the toolbar can be resized to be smaller than its full size. The buttons that don't fit on screen can be accessed by clicking on the small chevron button" + IDS_BUTTONS_SETTINGS "Toolbar Buttons" + IDS_NAVIGATION_SETTINGS "Navigation Pane" + IDS_TREE_STYLE "Navigation pane style" + IDS_TREE_STYLE_TIP "Pick the style for the folder tree in the navigation pane" + IDS_XPCLASSIC "Windows XP Classic" + IDS_XPCLASSIC_TIP "The navigation pane has lines connecting the folders" +END + +STRINGTABLE +BEGIN + IDS_XPSIMPLE "Windows XP Simple" + IDS_XPSIMPLE_TIP "The navigation pane has no lines" + IDS_VISTA "Windows Vista" + IDS_VISTA_TIP "The navigation pane shows little triangles to expand the folders" + IDS_TREE_SPACING "Tree item spacing" + IDS_TREE_SPACING_TIP "This is a number for controlling the spacing between the items in the folder tree. Use positive numbers to increase the spacing, and negative numbers to reduce the spacing" + IDS_NO_FADE "Don't fade buttons" + IDS_NO_FADE_TIP "When this is checked, the small triangle buttons for expanding the folder will not fade out when the mouse moves away" + IDS_FULL_INDENT "Full-size offset for sub-folders" + IDS_FULL_INDENT_TIP "When this is checked, the sub-folders will be offset by the full size of the icon, instead of the half of the size" + IDS_NAVIGATE "Auto-navigate to the selected folder" + IDS_NAVIGATE_TIP "Select if the files on the right should update to show the current folder on the left" + IDS_NAV_DELAY "Auto-navigation delay" + IDS_NAV_DELAY_TIP "Enter the delay (in ms) for updating the files after selecting a new folder" + IDS_ALT_ENTER "Enable Alt+Enter in the navigation pane" + IDS_ALT_ENTER_TIP "When this is checked, pressing Alt+Enter will show the properties of the selected folder" +END + +STRINGTABLE +BEGIN + IDS_VIEWCONTENT_TIP "Shows the Content view" + IDS_VIEWICONS1_TIP "Shows the Small Icons view" + IDS_VIEWICONS2_TIP "Shows the Medium Icons view" + IDS_VIEWICONS3_TIP "Shows the Large Icons view" + IDS_VIEWICONS4_TIP "Shows the Extra Large Icons view" + IDS_OPEN_TIP "Opens a given folder in the current window" + IDS_CUSTOM_TIP "This is a custom button. Use the command property to launch a program, or the link property to show a folder as a drop-down menu" + IDS_NEWFOLDER_TIP "Creates a new folder" + IDS_SCROLLTIP "Hide scroll tooltips" + IDS_SCROLLTIP_TIP "When this is checked, there won't be a tooltip when you are dragging the vertical scrollbar" + IDS_NAV_DEFAULT "Default behavior" + IDS_NAV_DEFAULT_TIP "Don't change the default behavior of Explorer" + IDS_NAV_KBD "When using the keyboard" + IDS_NAV_KBD_TIP "The files will update only if you select a new folder with the keyboard" + IDS_NAV_ALWAYS "Always" + IDS_NAV_ALWAYS_TIP "The files will update every time the selected folder changes for any reason" +END + +STRINGTABLE +BEGIN + IDS_FIX_SCROLL "Fix folder scrolling" + IDS_FIX_SCROLL_TIP "This option fixes a bug in Windows 7 that moves a folder to the bottom of the screen after it is expanded" + IDS_TITLE_SETTINGS "Title Bar" + IDS_SHOW_CAPTION "Show caption in the title bar" + IDS_SHOW_CAPTION_TIP "Show the caption (the current path) in the title bar" + IDS_SHOW_ICON "Show icon in the title bar" + IDS_SHOW_ICON_TIP "Show the icon of the current folder in the title bar" + IDS_NO_BREADCRUMBS "Disable breadcrumbs" + IDS_NO_BREADCRUMBS_TIP "Disable breadcrumbs and show the full path in the address bar" + IDS_ADDRESS_HISTORY "Address bar history" + IDS_ADDRESS_HISTORY_TIP "Control the contents of the history dropdown" + IDS_NORMAL_HISTORY "Normal history" + IDS_NORMAL_HISTORY_TIP "Show the default contents as provided by Explorer (recently visited folders and websites)" + IDS_SIMPLE_PATH "Simple path" + IDS_SIMPLE_PATH_TIP "Show the parents of the current folder all the way to the Desktop" + IDS_EXTENDED_PATH "Extended path" +END + +STRINGTABLE +BEGIN + IDS_EXTENDED_PATH_TIP "Besides the parents, shows all immediate folders of the Desktop and Computer. This is how it works in Windows XP" + IDS_HIDE_SEARCH "Hide Search box" + IDS_HIDE_SEARCH_TIP "Hide the search box from the address bar" + IDS_UP_SETTINGS "Up Button" + IDS_SHOW_UP "Show Up button" + IDS_SHOW_UP_TIP "Controls how the Up button is displayed" + IDS_DONT_SHOW "Don't show" + IDS_DONT_SHOW_TIP "The Up button is not shown" + IDS_BEFORE_BACK "Before Back/Forward" + IDS_BEFORE_BACK_TIP "The Up button appears before the Back/Forward buttons" + IDS_AFTER_BACK "After Back/Forward" + IDS_AFTER_BACK_TIP "The Up button appears after the Back/Forward buttons" + IDS_UP_NORMAL "Normal Up button icon" + IDS_UP_NORMAL_TIP "Pick the icon to use for the normal Up button" + IDS_UP_HOT "Hot Up button icon" + IDS_UP_HOT_TIP "Pick the icon to use for the hot Up button (when the mouse is over the button)" +END + +STRINGTABLE +BEGIN + IDS_UP_PRESSED "Pressed Up button icon" + IDS_UP_PRESSED_TIP "Pick the icon to use for the pressed Up button" + IDS_UP_DISABLED "Disabled Up button icon" + IDS_UP_DISABLED_TIP "Pick the icon to use for the disabled Up button" + IDS_UP_SIZE "Up button size" + IDS_UP_SIZE_TIP "Set the size for the Up button. By default it is 30 for DPI<120 and 36 for DPI>=120" + IDS_STATUS_SETTINGS "Status Bar" + IDS_FREE_SPACE "Show free space and file size" + IDS_FREE_SPACE_TIP "The status bar will show the free space on the current drive and the total size of all selected files. If no files are selected, the total size of all files will be shown" + IDS_INFO_TIP "Show detailed info for single selection" + IDS_INFO_TIP_TIP "When a single file is selected, the status bar will show the detailed information for that file" + IDS_FORCE_REFRESH "Force status refresh" + IDS_FORCE_REFRESH_TIP "This is a workaround for a bug in Explorer for Windows 7. Sometimes when a new Explorer window is opened the status bar is blank. Check this option to enable the workaround" + IDS_FILE_SETTINGS "File Operation" + IDS_FILE_UI "Replace file conflict dialog" + IDS_FILE_UI_TIP "When this is checked, the dialog showing file conflicts during a copy or move operation will be replaced with the old-style dialog from Windows XP" +END + +STRINGTABLE +BEGIN + IDS_FOLDER_UI "Replace folder conflict dialog" + IDS_FOLDER_UI_TIP "When this is checked, the dialog showing folder conflicts during a copy or move operation will be replaced with the old-style dialog from Windows XP" + IDS_ALERT_LEVEL "Sound alert for file conflicts" + IDS_ALERT_LEVEL_TIP "This setting adds a sound alert to the copy confirmation dialog when a system or read-only file is about to be overwritten" + IDS_NO_ALERT "No alert" + IDS_NO_ALERT_TIP "No sound is played" + IDS_SYS_FILES "For system files" + IDS_SYS_FILES_TIP "A sound is played when a system file is about to be overwritten" + IDS_RO_FILES "For system and read-only files" + IDS_RO_FILES_TIP "A sound is played when a system or a read-only file is about to be overwritten" + IDS_MORE "Always show more details" + IDS_MORE_TIP "When this is checked, Explorer dialogs like Copy, Move or Delete will expand to show all details by default" + IDS_MORE_DELAY "Delay for more details" + IDS_MORE_DELAY_TIP "Delay (in ms) for showing more details in the progress dialog. On Windows 7 with Aero if the details are shown too soon the progress dialog flickers badly. Use a delay of at least 250 ms to avoid the flicker. The delay is also useful if you want to see the details only for longer operations" + IDS_FILE_EXPLORER "Enable only in Explorer (improves performance)" + IDS_FILE_EXPLORER_TIP "When this is checked, the file and folder conflict dialogs will be replaced only in Explorer. Otherwise they will be replaced for all processes" +END + +STRINGTABLE +BEGIN + IDS_FILEPANE_SETTINGS "File Pane" + IDS_SHARE "Add icon overlay for shared folders" + IDS_SHARE_TIP "When this is checked, the shared folders will get a small overlay icon" + IDS_SHARE_ICON "Share overlay icon" + IDS_SHARE_ICON_TIP "Set the icon to be used for the overlay" + IDS_SHARE_EXPLORER "Show overlay only in Explorer (improves performance)" + IDS_SHARE_EXPLORER_TIP "When this is checked, the overlay icon will be shown only in Explorer. Otherwise they will be shown in all processes" + IDS_HEADERS "Show sort headers in all views" + IDS_HEADERS_TIP "When this is checked, the sort headers will show in all views, not just Details" + IDS_SCROLLBAR "Show horizontal scrollbar" + IDS_SCROLLBAR_TIP "Select if the horizontal scrollbar will be enabled" + IDS_SCROLLBAR_DEFAULT "Default" + IDS_SCROLLBAR_DEFAULT_TIP + "The scrollbar will be disabled for the 'Windows Vista' navigation pane style, and enabled for the others" + IDS_SCROLLBAR_ON "Enabled" + IDS_SCROLLBAR_ON_TIP "The scrollbar will show up when it is needed" + IDS_SCROLLBAR_OFF "Disabled" +END + +STRINGTABLE +BEGIN + IDS_SCROLLBAR_OFF_TIP "The scrollbar will be hidden at all times" + IDS_COMMAND_TIP "Pick a command for the button. The command determines what the button does when clicked" + IDS_LINK_TIP "Type a full path of a file or a folder. The folder will open like a dropdown menu. The file will be executed when the button is clicked" + IDS_TEXT_TIP "Enter the text for the button. If the text starts with $ (like $Toolbar.Settings) it will be looked up in the file ExplorerL10N.ini" + IDS_TIP_TIP "Enter the tooltip for the button. If the text starts with $ (like $Toolbar.Settings) it will be looked up in the file ExplorerL10N.ini" + IDS_ICON_TIP "Enter the icon for the button. If the icon is blank, the default icon of the link will be used instead. Use either a path to a .ico file, or a combination of a .dll file and a icon ID. Use 'none' to get no icon at all" + IDS_ICOND_TIP "Enter the disabled icon for the button. If the setting is blank, the disabled icon will be generated from the normal icon" + IDS_RESTORE_TIP "Restores all properties (text, icon and more) to the defaults for the selected command" + IDS_SEPARATOR_TIP "This item separates buttons in the toolbar" + IDS_UP_TIP "Goes up to the parent folder" + IDS_CUT_TIP "Cuts the selected files" + IDS_COPY_TIP "Copies the selected files" + IDS_PASTE_TIP "Pastes files from the clipboard" + IDS_DELETE_TIP "Deletes the selected files" + IDS_PROPERTIES_TIP "Shows properties for the selection" + IDS_EMAIL_TIP "Emails the selected files" +END + +STRINGTABLE +BEGIN + IDS_SETTINGS_TIP "Shows the Classic Explorer settings" + IDS_REFRESH_TIP "Refreshes the Explorer view" + IDS_STOP_TIP "Stops the current operation" + IDS_RENAME_TIP "Renames the selected file" + IDS_MOVETO_TIP "Moves the selection to a new place" + IDS_COPYTO_TIP "Copies the selection to a new place" + IDS_UNDO_TIP "Undoes the last operation" + IDS_REDO_TIP "Redoes the last undo" + IDS_SELECTALL_TIP "Selects all files in the folder" + IDS_DESELECT_TIP "Deselects all" + IDS_INVERT_TIP "Inverts the selection" + IDS_BACK_TIP "Goes back to the previous location" + IDS_FORWARD_TIP "Goes to the next location" + IDS_VIEWTILES_TIP "Shows the Tiles view" + IDS_VIEWDEATAILS_TIP "Shows the Details view" + IDS_VIEWLIST_TIP "Shows the List view" +END + +STRINGTABLE +BEGIN + IDS_ALT_D "Additional shortcut for the address bar: Alt +" + IDS_ALT_D_TIP "Enter a letter 'A' to 'Z' to be a shortcut for the address bar. In some languages the default shortcut conflicts with a menu item" + IDS_SORT_TIP "Sorts the folder by the given property (name, type, size or date). Use '-' before the property to sort in descending order. Read the help for more options." + IDS_GROUP_TIP "Groups the folder by the given property (name, type, size or date). Use '-' before the property to group in descending order. Read the help for more options." + IDS_PASTE_SHORTCUT_TIP "Creates shortcuts for the files in the clipboard" + IDS_UP_HOTKEY "Additional shortcut for the Up button" + IDS_UP_HOTKEY_TIP "Select a shortcut for navigating to the parent folder" + IDS_MAP_DRIVE_TIP "Connects to a network drive" + IDS_DISCONNECT_DRIVE_TIP "Disconnects from a network drive" + IDS_CUSTOMIZEFOLDER_TIP "Customize this folder" + IDS_SEPARATOR_ITEM "SEPARATOR" + IDS_UP_ITEM "Up" + IDS_CUT_ITEM "Cut" + IDS_COPY_ITEM "Copy" + IDS_PASTE_ITEM "Paste" + IDS_PASTE_LNK_ITEM "Paste shortcut" +END + +STRINGTABLE +BEGIN + IDS_DELETE_ITEM "Delete" + IDS_PROPERTIES_ITEM "Properties" + IDS_EMAIL_ITEM "Email" + IDS_SETTINGS_ITEM "Settings" + IDS_REFRESH_ITEM "Refresh" + IDS_STOP_ITEM "Stop" + IDS_RENAME_ITEM "Rename" + IDS_NEWFOLDER_ITEM "New folder" + IDS_MOVETO_ITEM "Move to" + IDS_COPYTO_ITEM "Copy to" + IDS_UNDO_ITEM "Undo" + IDS_REDO_ITEM "Redo" + IDS_SELECTALL_ITEM "Select all" + IDS_DESELECT_ITEM "Deselect" + IDS_INVERT_ITEM "Invert selection" + IDS_BACK_ITEM "Back" +END + +STRINGTABLE +BEGIN + IDS_FORWARD_ITEM "Forward" + IDS_MAP_DRIVE_ITEM "Map network drive" + IDS_DISCONNECT_ITEM "Disconnect network drive" + IDS_CUSTOMIZE_ITEM "Customize folder" + IDS_VIEWTILES_ITEM "View Tiles" + IDS_VIEWDETAILS_ITEM "View Details" + IDS_VIEWLIST_ITEM "View List" + IDS_VIEWCONTENT_ITEM "View Content" + IDS_VIEWICONS1_ITEM "View Small icons" + IDS_VIEWICONS2_ITEM "View Medium icons" + IDS_VIEWICONS3_ITEM "View Large icons" + IDS_VIEWICONS4_ITEM "View Extra large icons" + IDS_OPEN_ITEM "Open" + IDS_SORYBY_ITEM "Sort by" + IDS_GROUPBY_ITEM "Group by" + IDS_CUSTOM_ITEM "Custom" +END + +STRINGTABLE +BEGIN + IDS_SHOWSTATUSBAR "Show status bar" + IDS_SHOWSTATUSBAR_TIP "When this is checked, Explorer will have a status bar that shows information about the total selection size, free disk space, and more" + IDS_SHOW_ZONE "Show zone" + IDS_SHOW_ZONE_TIP "When this is checked, the status bar will display the current security zone" + IDS_SHARE_HIDDEN "Show hidden shares" + IDS_SHARE_HIDDEN_TIP "When this is checked, the overlay will appear also for hidden shares ending with $" + IDS_NAVPANE_ITEM "Navigation pane" + IDS_NAVPANE_TIP "Toggles the navigation pane" + IDS_DETAILSPANE_ITEM "Details pane" + IDS_DETAILSPANE_TIP "Toggles the details pane" + IDS_PREVIEWPANE_ITEM "Preview pane" + IDS_PREVIEWPANE_TIP "Toggles the preview pane" + IDS_SHOW_EXTENSIONS "Show extensions" + IDS_SHOW_EXTENSIONS_TIP "Toggles the visibility of the file extensions" + IDS_HIDDEN_FILES "Hidden files" + IDS_HIDDEN_FILES_TIP "Toggles the visibility of the hidden files" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_FILES "System files" + IDS_SYSTEM_FILES_TIP "Toggles the visibility of the system files" + IDS_ZIP_ITEM "Create zip file" + IDS_ZIP_TIP "Creates a zip file from the selected items" + IDS_STATUS_FONT "Status bar font" + IDS_STATUS_FONT_TIP "Select the font to use for the status bar" + IDS_FOLDEROPTIONS "Folder options" + IDS_FOLDEROPTIONS_TIP "Opens the folder options dialog" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "..\ClassicShellLib\resource.h" +#include "..\ClassicShellLib\ClassicShellLib.rc" +1 TYPELIB "ClassicExplorer.tlb" +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/ClassicShellSrc/ClassicExplorer/ClassicExplorer.rgs b/ClassicShellSrc/ClassicExplorer/ClassicExplorer.rgs new file mode 100644 index 0000000..0fc7e1b --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicExplorer.rgs @@ -0,0 +1,11 @@ +HKCR +{ + NoRemove AppID + { + '%APPID%' = s 'ClassicExplorer' + 'ClassicExplorer.DLL' + { + val AppID = s '%APPID%' + } + } +} diff --git a/ClassicShellSrc/ClassicExplorer/ClassicExplorer.vcproj b/ClassicShellSrc/ClassicExplorer/ClassicExplorer.vcproj new file mode 100644 index 0000000..da8513a --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicExplorer.vcproj @@ -0,0 +1,928 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicExplorer/ClassicExplorer32.def b/ClassicShellSrc/ClassicExplorer/ClassicExplorer32.def new file mode 100644 index 0000000..9c00d51 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicExplorer32.def @@ -0,0 +1,14 @@ +; ClassicExplorer.def : Declares the module parameters. + +LIBRARY "ClassicExplorer32.DLL" + +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE + DllInstall PRIVATE + ShowExplorerSettings + DllImportSettingsXml + DllExportSettingsXml + DllSaveAdmx diff --git a/ClassicShellSrc/ClassicExplorer/ClassicExplorer64.def b/ClassicShellSrc/ClassicExplorer/ClassicExplorer64.def new file mode 100644 index 0000000..5aaae4c --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicExplorer64.def @@ -0,0 +1,13 @@ +; ClassicExplorer.def : Declares the module parameters. + +LIBRARY "ClassicExplorer64.DLL" + +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE + DllInstall PRIVATE + ShowExplorerSettings + DllImportSettingsXml + DllExportSettingsXml diff --git a/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/ClassicExplorerSettings.cpp b/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/ClassicExplorerSettings.cpp new file mode 100644 index 0000000..0345e63 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/ClassicExplorerSettings.cpp @@ -0,0 +1,139 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include +#include +#include +#include +#include "StringUtils.h" + +// Find and activate the Settings window +static BOOL CALLBACK FindSettingsEnum( HWND hwnd, LPARAM lParam ) +{ + wchar_t className[256]; + if (!GetClassName(hwnd,className,_countof(className)) || _wcsicmp(className,L"#32770")!=0) + return TRUE; + DWORD process=0; + GetWindowThreadProcessId(hwnd,&process); + HANDLE hProcess=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,process); + bool bFound=false; + if (hProcess!=INVALID_HANDLE_VALUE) + { + wchar_t path[_MAX_PATH]; + if (GetModuleFileNameEx(hProcess,NULL,path,_countof(path))) + { + if (_wcsicmp(PathFindFileName(path),L"ClassicExplorerSettings.exe")==0) + { + SetForegroundWindow(hwnd); + bFound=true; + } + } + CloseHandle(hProcess); + } + return !bFound; +} + +HMODULE LoadClassicExplorerDll( void ) +{ + wchar_t path[_MAX_PATH]; + GetModuleFileName(NULL,path,_countof(path)); + *PathFindFileName(path)=0; + PathAppend(path,L"ClassicExplorer32.dll"); + return LoadLibrary(path); +} + +// A simple program that loads ClassicExplorer32.dll and calls the ShowExplorerSettings function +// Why not use rundll32 instead? Because it doesn't include the correct manifest for comctl32.dll +int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstrCmdLine, int nCmdShow ) +{ + INITCOMMONCONTROLSEX init={sizeof(init),ICC_STANDARD_CLASSES}; + InitCommonControlsEx(&init); + + { + const wchar_t *pXml=wcsstr(lpstrCmdLine,L"-xml "); + if (pXml) + { + wchar_t xml[_MAX_PATH]; + GetToken(pXml+5,xml,_countof(xml),L" "); + HMODULE dll=LoadClassicExplorerDll(); + if (!dll) return 1; + typedef bool (*tImportSettingsXml)( const wchar_t *fname ); + tImportSettingsXml DllImportSettingsXml=(tImportSettingsXml)GetProcAddress(dll,"DllImportSettingsXml"); + if (!DllImportSettingsXml) + return 1; + CoInitialize(NULL); + bool res=DllImportSettingsXml(xml); + CoUninitialize(); + return res?0:1; + } + } + + { + const wchar_t *pBackup=wcsstr(lpstrCmdLine,L"-backup "); + if (pBackup) + { + wchar_t xml[_MAX_PATH]; + GetToken(pBackup+8,xml,_countof(xml),L" "); + + HMODULE dll=LoadClassicExplorerDll(); + if (!dll) return 1; + typedef bool (*tExportSettingsXml)( const wchar_t *fname ); + tExportSettingsXml DllExportSettingsXml=(tExportSettingsXml)GetProcAddress(dll,"DllExportSettingsXml"); + if (!DllExportSettingsXml) + return 1; + + CoInitialize(NULL); + bool res=DllExportSettingsXml(xml); + CoUninitialize(); + return res?0:1; + } + } + +#ifndef _WIN64 + const wchar_t *pSaveAdmx=wcsstr(lpstrCmdLine,L"-saveadmx "); + if (pSaveAdmx) + { + wchar_t language[100]; + GetToken(pSaveAdmx+10,language,_countof(language),L" "); + + HMODULE dll=LoadClassicExplorerDll(); + if (!dll) return 1; + typedef bool (*tSaveAdmx)( const char *admxFile, const char *admlFile, const char *docFile, const wchar_t *language ); + tSaveAdmx SaveAdmx=(tSaveAdmx)GetProcAddress(dll,"DllSaveAdmx"); + if (!SaveAdmx || !SaveAdmx("ClassicExplorer.admx","ClassicExplorer.adml","ClassicExplorerADMX.txt",language)) + return 1; + return 0; + } +#endif + + // prevent multiple instances from running on the same desktop + // the assumption is that multiple desktops for the same user will have different name (but may repeat across users) + wchar_t userName[256]; + DWORD len=_countof(userName); + GetUserName(userName,&len); + len=0; + HANDLE desktop=GetThreadDesktop(GetCurrentThreadId()); + GetUserObjectInformation(desktop,UOI_NAME,NULL,0,&len); + wchar_t *deskName=(wchar_t*)malloc(len); + GetUserObjectInformation(desktop,UOI_NAME,deskName,len,&len); + + wchar_t mutexName[1024]; + Sprintf(mutexName,_countof(mutexName),L"ClassicExplorerSettings.Mutex.%s.%s",userName,deskName); + free(deskName); + + HANDLE hMutex=CreateMutex(NULL,TRUE,mutexName); + if (GetLastError()==ERROR_ALREADY_EXISTS || GetLastError()==ERROR_ACCESS_DENIED) + { + EnumWindows(FindSettingsEnum,0); + return 0; + } + + HMODULE dll=LoadClassicExplorerDll(); + if (!dll) return 1; + + FARPROC proc=GetProcAddress(dll,"ShowExplorerSettings"); + if (!proc) return 2; + + proc(); + return 0; +} diff --git a/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/ClassicExplorerSettings.manifest b/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/ClassicExplorerSettings.manifest new file mode 100644 index 0000000..7e51f65 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/ClassicExplorerSettings.manifest @@ -0,0 +1,41 @@ + + + +Classic Explorer Settings + + + + + + + + true + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/ClassicExplorerSettings.rc b/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/ClassicExplorerSettings.rc new file mode 100644 index 0000000..b669394 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/ClassicExplorerSettings.rc @@ -0,0 +1,111 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APPICON ICON "..\\..\\ClassicShellSetup\\ClassicShell.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 4,3,1,0 + PRODUCTVERSION 4,3,1,0 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "IvoSoft" + VALUE "FileDescription", "Classic Explorer Settings" + VALUE "FileVersion", "4, 3, 1, 0" + VALUE "InternalName", "ClassicExplorerSettings" + VALUE "LegalCopyright", "Copyright (C) 2009-2016, Ivo Beltchev" + VALUE "OriginalFilename", "ClassicExplorerSettings.exe" + VALUE "ProductName", "Classic Shell" + VALUE "ProductVersion", "4, 3, 1, 0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/ClassicExplorerSettings.vcproj b/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/ClassicExplorerSettings.vcproj new file mode 100644 index 0000000..5d4a172 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/ClassicExplorerSettings.vcproj @@ -0,0 +1,286 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/resource.h b/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/resource.h new file mode 100644 index 0000000..82575d8 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ClassicExplorerSettings/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ClassicExplorerSettings.rc +// +#define IDI_APPICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/ClassicShellSrc/ClassicExplorer/ExplorerBHO.cpp b/ClassicShellSrc/ClassicExplorer/ExplorerBHO.cpp new file mode 100644 index 0000000..83dcd12 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ExplorerBHO.cpp @@ -0,0 +1,1572 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// ExplorerBHO.cpp : Implementation of CExplorerBHO + +#include "stdafx.h" +#include "ExplorerBHO.h" +#include "Settings.h" +#include "ResourceHelper.h" +#include "resource.h" +#include "SettingsUI.h" +#include "Translations.h" +#include "SettingsUIHelper.h" +#include "DownloadHelper.h" +#include "FNVHash.h" +#include "dllmain.h" +#include +#include +#include +#include + +// CExplorerBHO - a browser helper object that implements Alt+Enter for the folder tree + +const UINT_PTR TIMER_NAVIGATE='CLSH'; + +int CExplorerBHO::s_AutoNavDelay; + +static void GetTreeItemPidl( HTREEITEM hItem, HWND hwndTree, PIDLIST_ABSOLUTE *result ) +{ + // find the PIDL of the tree item (combine all child PIDLs from the current item and its parents) + CAbsolutePidl pidl; + while (hItem) + { + TVITEMEX info={TVIF_PARAM,hItem}; + TreeView_GetItem(hwndTree,&info); + PIDLIST_RELATIVE **pidl1=(PIDLIST_RELATIVE**)info.lParam; + if (!pidl1 || !*pidl1 || !**pidl1) + { + pidl.Clear(); + break; + } + pidl.Attach(pidl?ILCombine((PIDLIST_ABSOLUTE)**pidl1,pidl):(PIDLIST_ABSOLUTE)ILClone(**pidl1)); + hItem=TreeView_GetParent(hwndTree,hItem); + } + *result=pidl.Detach(); +} + +LRESULT CALLBACK CExplorerBHO::SubclassTreeParentProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + // when the tree selection changes start a timer to navigate to the new folder in 100ms + if (uMsg==WM_NOTIFY && ((NMHDR*)lParam)->code==TVN_SELCHANGED) + { + if (GetSettingInt(L"AutoNavigate")==2 || ((NMTREEVIEW*)lParam)->action==TVC_BYKEYBOARD) + SetTimer(((NMHDR*)lParam)->hwndFrom,TIMER_NAVIGATE,s_AutoNavDelay,NULL); + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +// Subclass the tree control to: +// - support Alt+Enter +// - navigate to the new folder when you go up/down with the keyboard +// - fix the random scrolling of the tree when a folder is expanded +// - change the tree styles to achieve different looks +LRESULT CALLBACK CExplorerBHO::SubclassTreeProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==TVM_ENSUREVISIBLE && (dwRefData&1)) + { + // HACK! there is a bug in Win7 Explorer and when the selected folder is expanded for the first time it sends TVM_ENSUREVISIBLE for + // the root tree item. This causes the navigation pane to scroll up. To work around the bug we ignore TVM_ENSUREVISIBLE if it tries + // to show the root item and it is not selected + HTREEITEM hItem=(HTREEITEM)lParam; + if (!TreeView_GetParent(hWnd,hItem) && !(TreeView_GetItemState(hWnd,hItem,TVIS_SELECTED)&TVIS_SELECTED)) + return 0; + } + if (uMsg==WM_TIMER && wParam==TIMER_NAVIGATE) + { + // time to navigate to the selected folder (only if different from the current folder) + KillTimer(hWnd,TIMER_NAVIGATE); + if (GetFocus()!=hWnd) + return 0; + CAbsolutePidl pidl; + GetTreeItemPidl(TreeView_GetSelection(hWnd),hWnd,&pidl); + if (pidl) + { + bool bSameFolder=false; + CExplorerBHO *pThis=GetTlsData()->bho; + CComPtr pView; + if (pThis->m_pBrowser && SUCCEEDED(pThis->m_pBrowser->QueryActiveShellView(&pView))) + { + CComQIPtr pView2=pView; + + CComPtr pFolder; + CAbsolutePidl pidl2; + if (pView2 && SUCCEEDED(pView2->GetFolder(IID_IPersistFolder2,(void**)&pFolder)) && SUCCEEDED(pFolder->GetCurFolder(&pidl2)) && pidl2) + { + if (ILIsEqual(pidl,pidl2)) + bSameFolder=true; + } + } + if (!bSameFolder) + SendMessage(hWnd,WM_KEYDOWN,VK_SPACE,0); + } + return 0; + } + + // ignore the Alt+Enter syscharacter (to stop the tree view from beeping) + if (uMsg==WM_SYSCHAR && wParam==VK_RETURN) + return 0; + + if (uMsg==WM_SYSKEYDOWN && wParam==VK_RETURN) + { + // Alt+Enter is pressed + // if this message was for the folder tree, show the properties of the selected item + if (GetSettingBool(L"AltEnter") && ShowTreeProperties(hWnd)) + return 0; + } + + if ((uMsg==WM_LBUTTONDOWN || uMsg==WM_LBUTTONDBLCLK) && (wParam&MK_CONTROL)) + { + TVHITTESTINFO test; + test.pt.x=(short)LOWORD(lParam); + test.pt.y=(short)HIWORD(lParam); + HTREEITEM hItem=TreeView_HitTest(hWnd,&test); + if (test.flags&TVHT_ONITEM) + { + CAbsolutePidl pidl; + GetTreeItemPidl(hItem,hWnd,&pidl); + if (pidl) + { + CExplorerBHO *pThis=GetTlsData()->bho; + if (pThis->m_pBrowser) + { + pThis->m_pBrowser->BrowseObject(pidl,SBSP_NEWBROWSER|SBSP_ABSOLUTE); + } + } + } + return 0; + } + + if (uMsg==TVM_SETEXTENDEDSTYLE && wParam==(TVS_EX_FADEINOUTEXPANDOS|TVS_EX_AUTOHSCROLL|0x80000000) && lParam==0) + { + wParam&=0x7FFFFFFF; + + if (GetSettingInt(L"AutoNavigate")>0) + SetWindowSubclass(GetParent(hWnd),SubclassTreeParentProc,'CLSH',0); + + if (!GetSettingBool(L"NoFadeButtons")) + wParam&=~TVS_EX_FADEINOUTEXPANDOS; + + int indent=-1; + if (GetSettingBool(L"FullIndent")) + indent=0; + + int treeStyle=GetSettingInt(L"TreeStyle"); + if (treeStyle==STYLE_CLASSIC && GetWinVersion()>=WIN_VER_WIN10) + treeStyle=STYLE_VISTA; + DWORD style=GetWindowLong(hWnd,GWL_STYLE); + if (treeStyle!=STYLE_VISTA) + { + SetWindowTheme(hWnd,NULL,NULL); + if (treeStyle==STYLE_SIMPLE) + { + style|=TVS_SINGLEEXPAND|TVS_TRACKSELECT; + style&=~TVS_HASLINES; + } + else + { + style|=TVS_HASLINES; + style&=~(TVS_SINGLEEXPAND|TVS_TRACKSELECT); + wParam|=TVS_EX_FADEINOUTEXPANDOS; + HIMAGELIST images=TreeView_GetImageList(hWnd,TVSIL_NORMAL); + int cx, cy; + ImageList_GetIconSize(images,&cx,&cy); + indent=cx+3; + } + } + int scroll=GetSettingInt(L"HScrollbar"); + + if ((scroll==0 && treeStyle==STYLE_VISTA) || scroll==1) + wParam&=~TVS_EX_AUTOHSCROLL; + if ((scroll==0 && treeStyle!=STYLE_VISTA) || scroll==2) + style&=~TVS_NOHSCROLL; + + SetWindowLong(hWnd,GWL_STYLE,style); + + if (indent>=0) + TreeView_SetIndent(hWnd,indent); + + int d=GetSettingInt(L"TreeItemSpacing"); + if (d) + { + CExplorerBHO *pThis=GetTlsData()->bho; + pThis->m_TreeItemHeight=TreeView_GetItemHeight(hWnd)+d; + TreeView_SetItemHeight(hWnd,pThis->m_TreeItemHeight); + } + + if (wParam==0) + return 0; + } + + if (uMsg==WM_SETTINGCHANGE) + { + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + int indent=-1; + if (GetSettingBool(L"FullIndent")) + indent=0; + + if (GetSettingInt(L"TreeStyle")==STYLE_CLASSIC && GetWinVersion()=0) + TreeView_SetIndent(hWnd,indent); + return res; + } + if (uMsg==TVM_SETITEMHEIGHT) + { + CExplorerBHO *pThis=GetTlsData()->bho; + if (pThis->m_TreeItemHeight>0) + wParam=pThis->m_TreeItemHeight; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +LRESULT CALLBACK CExplorerBHO::HookExplorer( int nCode, WPARAM wParam, LPARAM lParam ) +{ + // wait for the tree control to be created and subclass it + if (nCode==HCBT_CREATEWND) + { + HWND hWnd=(HWND)wParam; + CBT_CREATEWND *pCreate=(CBT_CREATEWND*)lParam; + if (pCreate->lpcs->lpszClass>(LPTSTR)0xFFFF && _wcsicmp(pCreate->lpcs->lpszClass,WC_TREEVIEW)==0) + { + HWND parent=GetAncestor(pCreate->lpcs->hwndParent,GA_ROOT); + wchar_t name[256]; + if (GetClassName(parent,name,_countof(name)) && _wcsicmp(name,L"CabinetWClass")==0) + { + DWORD_PTR settings=0; + if (GetWinVersion()==WIN_VER_WIN7 && GetSettingBool(L"FixFolderScroll")) + settings|=1; + SetWindowSubclass(hWnd,SubclassTreeProc,'CLSH',settings); + PostMessage(hWnd,TVM_SETEXTENDEDSTYLE,TVS_EX_FADEINOUTEXPANDOS|TVS_EX_AUTOHSCROLL|0x80000000,0); + } + } + else if (pCreate->lpcs->lpszClass>(LPTSTR)0xFFFF && _wcsicmp(pCreate->lpcs->lpszClass,L"DUIViewWndClassName")==0) + { + TlsData *pTlsData=GetTlsData(); + if (!pTlsData->bho->m_DUIView) + { + pTlsData->bho->m_DUIView=hWnd; + SetWindowSubclass(pTlsData->bho->m_DUIView,SubclassDUIViewProc,(UINT_PTR)pTlsData->bho,'CLSH'); + } + } + } + return CallNextHookEx(NULL,nCode,wParam,lParam); +} + +LRESULT CALLBACK CExplorerBHO::HookKeyboard( int nCode, WPARAM wParam, LPARAM lParam ) +{ + // wait for the tree control to be created and subclass it + if (nCode==HC_ACTION) + { + TlsData *pTlsData=GetTlsData(); + if (wParam==pTlsData->bho->m_AltD && (lParam&0x20000000)) + { + if (lParam&0x80000000) + { + return 0; + } + else + { + if (IsWindow(pTlsData->bho->m_Breadcrumbs) && IsWindowVisible(pTlsData->bho->m_Breadcrumbs)) + { + SetFocus(pTlsData->bho->m_Breadcrumbs); + SendMessage(pTlsData->bho->m_Breadcrumbs,WM_KEYDOWN,VK_SPACE,0); + SendMessage(pTlsData->bho->m_Breadcrumbs,WM_KEYUP,VK_SPACE,0); + return 0; + } + } + } + if (wParam==(pTlsData->bho->m_UpHotkey&255) && !(lParam&0x80000000)) + { + // Backspace goes to the parent folder, but only if no window has the caret + GUITHREADINFO info={sizeof(info)}; + if (GetGUIThreadInfo(GetCurrentThreadId(),&info) && !info.hwndCaret) + { + bool bShift1=(pTlsData->bho->m_UpHotkey&(HOTKEYF_SHIFT<<8))!=0; + bool bCtrl1=(pTlsData->bho->m_UpHotkey&(HOTKEYF_CONTROL<<8))!=0; + bool bAlt1=(pTlsData->bho->m_UpHotkey&(HOTKEYF_ALT<<8))!=0; + bool bShift2=GetKeyState(VK_SHIFT)<0; + bool bCtrl2=GetKeyState(VK_CONTROL)<0; + bool bAlt2=GetKeyState(VK_MENU)<0; + if (bShift1==bShift2 && bAlt1==bAlt2) + { + if (bCtrl1==bCtrl2) + { + pTlsData->bho->m_pBrowser->BrowseObject(NULL,SBSP_SAMEBROWSER|SBSP_PARENT); + return 1; + } + else if (bCtrl2) + { + pTlsData->bho->m_pBrowser->BrowseObject(NULL,SBSP_NEWBROWSER|SBSP_PARENT); + return 1; + } + } + } + } + } + return CallNextHookEx(NULL,nCode,wParam,lParam); +} + +bool CExplorerBHO::GetStatusText( wchar_t *buf, int size, const wchar_t *oldText, bool bShowTip, bool bShowSpace ) +{ + bool res=false; + CComPtr pView; + if (m_pBrowser && SUCCEEDED(m_pBrowser->QueryActiveShellView(&pView))) + { + CComQIPtr pView2=pView; + + CComPtr pFolder; + if (pView2 && SUCCEEDED(pView2->GetFolder(IID_IPersistFolder2,(void**)&pFolder))) + { + int count; + if (bShowTip && SUCCEEDED(pView2->ItemCount(SVGIO_SELECTION,&count)) && count==1) + { + // if only one item is selected, show its info in the status bar + CComPtr pEnum; + PITEMID_CHILD child; + if (SUCCEEDED(pView2->Items(SVGIO_SELECTION,IID_IEnumIDList,(void**)&pEnum)) && pEnum && pEnum->Next(1,&child,NULL)==S_OK) + { + CComQIPtr pFolder2=pFolder; + if (pFolder2) + { + CComPtr pQueryInfo; + if (SUCCEEDED(pFolder2->GetUIObjectOf(NULL,1,(PCUITEMID_CHILD*)&child,IID_IQueryInfo,NULL,(void**)&pQueryInfo))) + { + CComString pTip; + if (SUCCEEDED(pQueryInfo->GetInfoTip(QITIPF_DEFAULT|QITIPF_SINGLELINE,&pTip)) && pTip) + { + Strcpy(buf,size,pTip); + for (wchar_t *p=buf;*p;p++) + if (*p=='\t') + *p=' '; + res=true; + } + } + } + } + } + + if (!res) + { + wchar_t buf2[256]; + if (!oldText) + { + int count=-1; + const wchar_t *fmt=NULL; + if (SUCCEEDED(pView2->ItemCount(SVGIO_SELECTION,&count)) && count>0) + { + fmt=(count==1?FindTranslation(L"Status.ItemSelected",L"%s item selected"):FindTranslation(L"Status.ItemsSelected",L"%s items selected")); + } + else if (SUCCEEDED(pView2->ItemCount(SVGIO_ALLVIEW,&count)) && count>=0) + { + fmt=(count==1?FindTranslation(L"Status.Item",L"%s item"):FindTranslation(L"Status.Items",L"%s items")); + } + else + buf2[0]=0; + if (fmt) + { + wchar_t str1[100]; + wchar_t str2[100]; + Sprintf(str1,_countof(str1),L"%d",count); + NUMBERFMT numFmt; + wchar_t sep1[10], sep2[10]; + numFmt.NumDigits=0; + GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_ILZERO,sep1,10); + numFmt.LeadingZero=_wtol(buf); + GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_INEGNUMBER,sep1,10); + numFmt.NegativeOrder=_wtol(buf); + GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SGROUPING,sep1,10); + numFmt.Grouping=0; + for (const wchar_t *p=sep1;*p;p++) + if (*p>='1' && *p<='9') + numFmt.Grouping=numFmt.Grouping*10+(*p-'0'); + GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SDECIMAL,sep1,10); + numFmt.lpDecimalSep=sep1; + GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_STHOUSAND,sep2,10); + numFmt.lpThousandSep=sep2; + + if (GetNumberFormat(LOCALE_USER_DEFAULT,0,str1,&numFmt,str2,_countof(str2))) + Sprintf(buf2,_countof(buf2),fmt,str2); + else + Sprintf(buf2,_countof(buf2),fmt,str1); + } + res=true; + } + if (bShowSpace) + { + // show the free space of the drive containing the current folder + // also works for network locations + CAbsolutePidl pidl; + wchar_t path[_MAX_PATH]; + ULARGE_INTEGER diskSize; + if (SUCCEEDED(pFolder->GetCurFolder(&pidl)) && SHGetPathFromIDList(pidl,path) && GetDiskFreeSpaceEx(path,NULL,NULL,&diskSize)) + { + wchar_t str[100]; + StrFormatByteSize64(diskSize.QuadPart,str,_countof(str)); + Sprintf(buf,size,FindTranslation(L"Status.FreeSpace",L"%s (Disk free space: %s)"),oldText?oldText:buf2,str); + res=true; + } + else if (!oldText) + Strcpy(buf,size,buf2); + } + else if (!oldText) + Strcpy(buf,size,buf2); + } + } + } + return res; +} + +void CExplorerBHO::GetFileSize( wchar_t *buf, int size ) +{ + __int64 fileSize=-1; + CComPtr pView; + bool bMore=false; + int time0=GetTickCount(); + if (m_pBrowser && SUCCEEDED(m_pBrowser->QueryActiveShellView(&pView))) + { + CComQIPtr pView2=pView; + CComPtr pFolder; + CAbsolutePidl pidl; + if (pView2 && SUCCEEDED(pView2->GetFolder(IID_IPersistFolder2,(void**)&pFolder)) && SUCCEEDED(pFolder->GetCurFolder(&pidl))) + { + CComQIPtr pFolder2=pFolder; + UINT type=SVGIO_SELECTION; + int count, selCount; + if (SUCCEEDED(pView2->ItemCount(SVGIO_ALLVIEW,&count))) + { + if ((FAILED(pView2->ItemCount(SVGIO_SELECTION,&selCount)) || selCount==0)) + type=SVGIO_ALLVIEW; + CComPtr pEnum; + if ((count<10000 || selCount<1000) && SUCCEEDED(pView2->Items(type,IID_IEnumIDList,(void**)&pEnum)) && pEnum) + { + PITEMID_CHILD child; + SHCOLUMNID column={PSGUID_STORAGE,PID_STG_SIZE}; + int index=0; + while (pEnum->Next(1,&child,NULL)==S_OK) + { + index++; + if ((index%100)==0 && (GetTickCount()-time0)>500) + { + ILFree(child); + bMore=true; + break; + } + CComVariant var; + if (SUCCEEDED(pFolder2->GetDetailsEx(child,&column,&var)) && var.vt==VT_UI8) + { + if (fileSize<0) + fileSize=var.ullVal; + else + fileSize+=var.ullVal; + } + ILFree(child); + } + } + } + } + } + if (fileSize>=0) + { + // format the file size as KB, MB, etc + StrFormatByteSize64(fileSize,buf,size); + if (bMore) + Strcat(buf,size,L"+"); + } + else + buf[0]=0; +} + +// Subclass the statusbar to: +// - show free disk space +// - show the total size of the selected files +LRESULT CALLBACK CExplorerBHO::SubclassStatusProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + wchar_t buf[1024]; + if (uMsg==WM_CLEAR) + { + // recalculate the selection size on a timer. this way if the status text is changed frequently + // the recalculation will not happen every time + SetTimer(hWnd,uIdSubclass,10,NULL); + } + if (uMsg==WM_PAINT && ((CExplorerBHO*)uIdSubclass)->m_bForceRefresh) + { + // sometimes Explorer doesn't fully initialize the status bar on Windows 7 and leaves it with 1 part + // in such case force the view to refresh after the status bar is fully visible + ((CExplorerBHO*)uIdSubclass)->m_bForceRefresh=false; + if (SendMessage(hWnd,SB_GETPARTS,0,0)<=1) + PostMessage(GetParent(hWnd),WM_COMMAND,41504,0); // Refresh command + } + if (uMsg==SB_SETTEXT && LOWORD(wParam)==0) + { + // when the text of the first part is changing + if (dwRefData&SHOW_FREE_SPACE) + { + if (((CExplorerBHO*)uIdSubclass)->m_bResetStatus && SendMessage(hWnd,SB_GETPARTS,0,0)<=1) + { + // HACK! there is a bug in Win7 and when the Explorer window is created it doesn't correctly + // initialize the status bar to have 3 parts. as soon as the user resizes the window the + // 3 parts appear. so here we resize the parent of the status bar to create the 3 parts. + HWND parent=GetParent(hWnd); + RECT rc; + GetWindowRect(parent,&rc); + SetWindowPos(parent,NULL,0,0,rc.right-rc.left+1,rc.bottom-rc.top,SWP_NOZORDER|SWP_NOMOVE); + SetWindowPos(parent,NULL,0,0,rc.right-rc.left,rc.bottom-rc.top,SWP_NOZORDER|SWP_NOMOVE); + // the first time the status text is set it is too early. so we do this until we get at lest 2 parts + if (SendMessage(hWnd,SB_GETPARTS,0,0)>1) + ((CExplorerBHO*)uIdSubclass)->m_bResetStatus=false; + } + } + if (((CExplorerBHO*)uIdSubclass)->GetStatusText(buf,_countof(buf),(wchar_t*)lParam,(dwRefData&SHOW_INFOTIP)!=0,(dwRefData&SHOW_FREE_SPACE)!=0)) + lParam=(LPARAM)buf; + } + if (uMsg==SB_SETTEXT && LOWORD(wParam)==1) + { + return 0; + } + + if (uMsg==WM_TIMER && wParam==uIdSubclass) + { + // recalculate the total size of the selected files and show it in part 2 of the status bar + KillTimer(hWnd,wParam); + ((CExplorerBHO*)uIdSubclass)->GetFileSize(buf,_countof(buf)); + DefSubclassProc(hWnd,SB_SETTEXT,1,(LPARAM)buf); + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +LRESULT CALLBACK CExplorerBHO::SubclassStatusProc8( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + wchar_t buf[1024]; + if (uMsg==WM_CLEAR) + { + // recalculate the selection size on a timer. this way if the status text is changed frequently + // the recalculation will not happen every time + SetTimer(hWnd,uIdSubclass,10,NULL); + + if (!((CExplorerBHO*)uIdSubclass)->GetStatusText(buf,_countof(buf),NULL,(dwRefData&SHOW_INFOTIP)!=0,(dwRefData&SHOW_FREE_SPACE)!=0)) + buf[0]=0; + SendMessage(hWnd,SB_SETTEXT,PART_TEXT,(LPARAM)buf); + return 0; + } + if (uMsg==WM_TIMER && wParam==uIdSubclass) + { + // recalculate the total size of the selected files and show it in part 2 of the status bar + KillTimer(hWnd,wParam); + ((CExplorerBHO*)uIdSubclass)->GetFileSize(buf,_countof(buf)); + SendMessage(hWnd,SB_SETTEXT,PART_SIZE,(LPARAM)buf); + return 0; + } + if (uMsg==WM_LBUTTONDBLCLK) + { + POINT pt={(short)LOWORD(lParam),(short)HIWORD(lParam)}; + RECT rc; + DefSubclassProc(hWnd,SB_GETRECT,PART_ZONE,(LPARAM)&rc); + if (PtInRect(&rc,pt)) + { + CExplorerBHO *pThis=(CExplorerBHO*)uIdSubclass; + CComBSTR url; + if (pThis->m_pWebBrowser && SUCCEEDED(pThis->m_pWebBrowser->get_LocationURL(&url))) + { + // use undocumented function 383 from shlwapi + typedef void (WINAPI* FZoneConfigureW)(HWND,LPCWSTR); + FZoneConfigureW ZoneConfigureW; + + HMODULE hShlwapi=LoadLibrary(L"shlwapi.dll"); + if(hShlwapi) + { + ZoneConfigureW=(FZoneConfigureW)GetProcAddress(hShlwapi,MAKEINTRESOURCEA(383)); + if(ZoneConfigureW) + ZoneConfigureW(GetAncestor(hWnd,GA_ROOT),url); + FreeLibrary(hShlwapi); + } + } + return 0; + } + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +// Subclass the DUIView to reduce its size and reposition the taskbar +LRESULT CALLBACK CExplorerBHO::SubclassDUIViewProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + CExplorerBHO *pThis=(CExplorerBHO*)uIdSubclass; + if (uMsg==WM_WINDOWPOSCHANGING && pThis->m_Status8) + { + WINDOWPOS *pPos=(WINDOWPOS*)lParam; + if (!(pPos->flags&SWP_NOSIZE)) + { + RECT rc; + GetWindowRect(pThis->m_Status8,&rc); + int height=rc.bottom-rc.top; + pPos->cy-=height; + SetWindowPos(pThis->m_Status8,NULL,pPos->x,pPos->y+pPos->cy,pPos->cx,rc.bottom-rc.top,SWP_NOZORDER); + int parts[]={pPos->cx-height-pThis->m_FileSizeWidth-pThis->m_ZoneWidth,pPos->cx-height-pThis->m_ZoneWidth,-1}; + SendMessage(pThis->m_Status8,SB_SETPARTS,pThis->m_ZoneWidth?3:2,(LPARAM)parts); + } + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +// Subclass the rebar in the title bar to handle the title bar Up button +LRESULT CALLBACK CExplorerBHO::SubclassRebarProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_NOTIFY && ((NMHDR*)lParam)->hwndFrom==(HWND)dwRefData && ((NMHDR*)lParam)->code==NM_CUSTOMDRAW) + { + // custom-draw the toolbar. just draw the correct icon and nothing else + NMTBCUSTOMDRAW *pDraw=(NMTBCUSTOMDRAW*)lParam; + if (pDraw->nmcd.dwDrawStage==CDDS_PREPAINT) + return CDRF_NOTIFYITEMDRAW; + if (pDraw->nmcd.dwDrawStage==CDDS_ITEMPREPAINT) + { + CExplorerBHO *pThis=(CExplorerBHO*)uIdSubclass; + BOOL comp; + if (SUCCEEDED(DwmIsCompositionEnabled(&comp)) && comp) + FillRect(pDraw->nmcd.hdc,&pDraw->nmcd.rc,(HBRUSH)GetStockObject(BLACK_BRUSH)); + if (pDraw->nmcd.uItemState&CDIS_DISABLED) + { + if (pThis->m_IconDisabled) + DrawIconEx(pDraw->nmcd.hdc,0,0,pThis->m_IconDisabled,0,0,0,NULL,DI_NORMAL|DI_NOMIRROR); + else + DrawIconEx(pDraw->nmcd.hdc,0,0,pThis->m_IconNormal,0,0,0,NULL,DI_NORMAL|DI_NOMIRROR); + } + else if (pDraw->nmcd.uItemState&CDIS_SELECTED) + { + if (pThis->m_IconPressed) + DrawIconEx(pDraw->nmcd.hdc,0,0,pThis->m_IconPressed,0,0,0,NULL,DI_NORMAL|DI_NOMIRROR); + else + DrawIconEx(pDraw->nmcd.hdc,1,1,pThis->m_IconNormal,0,0,0,NULL,DI_NORMAL|DI_NOMIRROR); + } + else if (pDraw->nmcd.uItemState&CDIS_HOT) + { + if (pThis->m_IconHot) + DrawIconEx(pDraw->nmcd.hdc,0,0,pThis->m_IconHot,0,0,0,NULL,DI_NORMAL|DI_NOMIRROR); + else + DrawIconEx(pDraw->nmcd.hdc,0,0,pThis->m_IconNormal,0,0,0,NULL,DI_NORMAL|DI_NOMIRROR); + } + else + DrawIconEx(pDraw->nmcd.hdc,0,0,pThis->m_IconNormal,0,0,0,NULL,DI_NORMAL|DI_NOMIRROR); + return CDRF_SKIPDEFAULT; + } + } + + if (uMsg==WM_THEMECHANGED) + { + // the button size is reset when the theme changes. force the correct size again + HWND toolbar=(HWND)dwRefData; + RECT rc; + GetClientRect(toolbar,&rc); + PostMessage(toolbar,TB_SETBUTTONSIZE,0,MAKELONG(rc.right,rc.bottom)); + } + + if (uMsg==WM_NOTIFY && ((NMHDR*)lParam)->hwndFrom==(HWND)dwRefData && ((NMHDR*)lParam)->code==TBN_GETINFOTIP) + { + // show the tip for the up button + NMTBGETINFOTIP *pTip=(NMTBGETINFOTIP*)lParam; + Strcpy(pTip->pszText,pTip->cchTextMax,FindTranslation(L"Toolbar.GoUp",L"Up One Level")); + return 0; + } + + if (uMsg==WM_NOTIFY && ((NMHDR*)lParam)->hwndFrom==(HWND)dwRefData && ((NMHDR*)lParam)->code==NM_RCLICK) + { + NMMOUSE *pInfo=(NMMOUSE*)lParam; + POINT pt=pInfo->pt; + ClientToScreen(pInfo->hdr.hwndFrom,&pt); + ShowSettingsMenu(hWnd,pt.x,pt.y); + return TRUE; + } + + if (uMsg==WM_COMMAND && wParam==1) + { + UINT flags=(GetKeyState(VK_CONTROL)<0?SBSP_NEWBROWSER:SBSP_SAMEBROWSER); + ((CExplorerBHO*)uIdSubclass)->m_pBrowser->BrowseObject(NULL,flags|SBSP_PARENT); + } + + CExplorerBHO *pThis=(CExplorerBHO*)uIdSubclass; + if (pThis->m_bRemapBands) + { + // HACK! Explorer doesn't use RB_IDTOINDEX every time it needs to access a particular band. Since we insert the Up button in the second + // position, the rest of the bands get offset and comedy ensues (the search box is not sized properly). + // To fix the issue, we renumber the bands so that from the outside ours appears to be last. + static int remapNewOld[2][4]={{3,0,1,2},{0,3,1,2}}; + static int remapOldNew[2][4]={{1,2,3,0},{0,2,3,1}}; + + if (uMsg==RB_IDTOINDEX || uMsg==RB_HITTEST) + { + // remap the result from RB_IDTOINDEX and RB_HITTEST + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + if (res<0 || res>3) return res; + res=remapNewOld[pThis->m_UpButtonIndex-1][res]; + if (lParam && uMsg==RB_HITTEST) ((RBHITTESTINFO*)lParam)->iBand=(int)res; + return res; + } + if (uMsg==RB_GETBANDBORDERS || uMsg==RB_GETBANDINFO || uMsg==RB_GETRECT || uMsg==RB_SETBANDINFO || uMsg==RB_SETBANDWIDTH) + { + // remap wParam for all GET/SET messages + if (wParam>=0 && wParam<=3) + wParam=remapOldNew[pThis->m_UpButtonIndex-1][wParam]; + } + } + + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +// Subclass the breadcrumbs to make them show the full path +LRESULT CALLBACK CExplorerBHO::SubclassBreadcrumbProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + CExplorerBHO *pThis=(CExplorerBHO*)uIdSubclass; + if (*pThis->m_CurPath) + { + if (uMsg==WM_SETFOCUS) + { + if (wParam) + { + // see if the focus comes from the combo box. if so, most likely Escape was pressed, so just focus the main frame + HWND from=(HWND)wParam; + HWND combo=FindChildWindow(GetParent(GetParent(hWnd)),WC_COMBOBOXEX); + if (combo && (combo==from || IsChild(combo,from))) + { + SetFocus(GetAncestor(hWnd,GA_ROOT)); + return 0; + } + } + // when the breadcrumbs are focused, switch to the combobox by simulating a mouse click + RECT rc; + GetClientRect(hWnd,&rc); + LPARAM pos=MAKELONG(rc.right-1,rc.bottom/2); + DefSubclassProc(hWnd,WM_LBUTTONDOWN,MK_LBUTTON,pos); + DefSubclassProc(hWnd,WM_LBUTTONUP,0,pos); + return 0; + } + if (uMsg==WM_LBUTTONDOWN || uMsg==WM_LBUTTONDBLCLK || uMsg==WM_LBUTTONUP) + { + // unless the mouse is clicked on the icon, replace the mouse position with a point on the far right. + // this will cause Explorer to switch to the combobox even when a breadcrumb is clicked + int iconSize=GetSystemMetrics(SM_CXSMICON); + if (!pThis->m_CurIcon || (short)LOWORD(lParam)>iconSize+3) + { + RECT rc; + GetClientRect(hWnd,&rc); + lParam=MAKELONG(rc.right-1,rc.bottom/2); + } + } + + if (uMsg==WM_PAINT) + { + // make the breadcrumbs control draw the full path like the XP address bar + RECT rc; + GetClientRect(hWnd,&rc); + + PAINTSTRUCT ps; + HDC hdc=BeginPaint(hWnd,&ps); + + // we need to use buffered painting because DrawThemeTextEx with DTT_COMPOSITED requires it + // on Vista DTT_COMPOSITED is required so that the black text doesn't get transparent. On Windows 7 regular DrawText seems to work fine + BP_PAINTPARAMS paintParams={sizeof(paintParams)}; + paintParams.dwFlags=BPPF_ERASE; + HDC hdcPaint=NULL; + HPAINTBUFFER hBufferedPaint=BeginBufferedPaint(hdc,&rc,BPBF_TOPDOWNDIB,&paintParams,&hdcPaint); + if (hdcPaint) + { + rc.top++; + SendMessage(GetParent(GetParent(hWnd)),WM_PRINTCLIENT,(WPARAM)hdcPaint,PRF_CLIENT); + + // draw icon + int iconSize=GetSystemMetrics(SM_CXSMICON); + if (pThis->m_CurIcon) + DrawIconEx(hdcPaint,rc.left+3,(rc.top+rc.bottom-iconSize)/2,pThis->m_CurIcon,iconSize,iconSize,0,NULL,DI_NORMAL); + rc.left+=iconSize+8; // Not a good idea to hard-code number of pixels, but seems to work fine for different DPI settings + + // draw path + HFONT font=(HFONT)SendMessage(hWnd,WM_GETFONT,0,0); + HGDIOBJ font0=SelectObject(hdcPaint,font); + SetBkMode(hdcPaint,TRANSPARENT); + SetTextColor(hdcPaint,GetSysColor(COLOR_WINDOWTEXT)); + HTHEME theme=GetWindowTheme(hWnd); + BOOL dwm; + if (theme && SUCCEEDED(DwmIsCompositionEnabled(&dwm)) && dwm) + { + DTTOPTS opts={sizeof(opts),DTT_COMPOSITED|DTT_TEXTCOLOR}; + opts.crText=GetSysColor(COLOR_WINDOWTEXT); + DrawThemeTextEx(theme,hdcPaint,0,0,pThis->m_CurPath,-1,DT_NOPREFIX|DT_VCENTER|DT_SINGLELINE,&rc,&opts); + } + else + { + DrawText(hdcPaint,pThis->m_CurPath,-1,&rc,DT_NOPREFIX|DT_VCENTER|DT_SINGLELINE); + } + SelectObject(hdcPaint,font0); + EndBufferedPaint(hBufferedPaint,TRUE); + } + EndPaint(hWnd,&ps); + return 0; + } + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +// Subclass the progress bar behind the address bar to remove the history and replace it with a list of parent folders +LRESULT CALLBACK CExplorerBHO::SubclassProgressProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + CExplorerBHO *pThis=(CExplorerBHO*)uIdSubclass; + + if (uMsg==WM_PARENTNOTIFY && LOWORD(wParam)==WM_CREATE && !pThis->m_ComboBox.m_hWnd) + { + // on Windows 7 the combobox is not created at startup. so listen for child windows being created and update pThis->m_ComboBox + HWND combo=(HWND)lParam; + wchar_t className[256]; + GetClassName(combo,className,_countof(className)); + if (_wcsicmp(className,WC_COMBOBOXEX)==0) + pThis->m_ComboBox=combo; + } + + if (uMsg==WM_COMMAND && (HWND)lParam==pThis->m_ComboBox.m_hWnd) + { + if (HIWORD(wParam)==CBN_DROPDOWN) + { + // on drop down refresh the list + pThis->ClearComboItems(); + + CComPtr pDesktop; + SHGetDesktopFolder(&pDesktop); + + { + // add desktop + ITEMIDLIST shEmpty={{0}}; + CComString pName; + if (SUCCEEDED(SHGetNameFromIDList((PIDLIST_ABSOLUTE)&shEmpty,SIGDN_DESKTOPABSOLUTEEDITING,&pName))) + { + ComboItem item={ILCloneFull((PIDLIST_ABSOLUTE)&shEmpty),0,CString(pName)}; + pThis->m_ComboItems.push_back(item); + } + } + + if (dwRefData==2) + { + // enumerate all desktop items + CComPtr pEnum; + if (SUCCEEDED(pDesktop->EnumObjects(NULL,SHCONTF_FOLDERS,&pEnum)) && pEnum) + { + PITEMID_CHILD child; + while (pEnum->Next(1,&child,NULL)==S_OK) + { + STRRET str; + if (SUCCEEDED(pDesktop->GetDisplayNameOf(child,SHGDN_INFOLDER|SHGDN_NORMAL,&str))) + { + CComString pName; + StrRetToStr(&str,child,&pName); + ComboItem item={(PIDLIST_ABSOLUTE)child,1,CString(pName)}; + item.sortName=item.name; + pThis->m_ComboItems.push_back(item); + } + else + ILFree(child); + } + } + + // sort desktop items + std::sort(pThis->m_ComboItems.begin()+1,pThis->m_ComboItems.end()); + } + + if (dwRefData==2) + { + // enumerate all computer items + CAbsolutePidl pidlComp; + SHGetKnownFolderIDList(FOLDERID_ComputerFolder,0,NULL,&pidlComp); + int index=1; + for (int i=1;i<(int)pThis->m_ComboItems.size();i++) + if (ILIsEqual(pidlComp,pThis->m_ComboItems[i].pidl)) + { + index=i+1; + break; + } + int index0=index; + CComPtr pComputer; + pDesktop->BindToObject(pidlComp,NULL,IID_IShellFolder,(void**)&pComputer); + + CComPtr pEnum; + if (pComputer && SUCCEEDED(pComputer->EnumObjects(NULL,SHCONTF_FOLDERS,&pEnum)) && pEnum) + { + PITEMID_CHILD child; + while (pEnum->Next(1,&child,NULL)==S_OK) + { + STRRET str; + if (SUCCEEDED(pComputer->GetDisplayNameOf(child,SHGDN_INFOLDER|SHGDN_NORMAL,&str))) + { + CComString pName; + StrRetToStr(&str,child,&pName); + ComboItem item={ILCombine(pidlComp,child),2,CString(pName)}; + pThis->m_ComboItems.insert(pThis->m_ComboItems.begin()+index,1,item); + index++; + } + ILFree(child); + } + } + + //sort computer items + std::sort(pThis->m_ComboItems.begin()+index0,pThis->m_ComboItems.begin()+index); + } + + if (pThis->m_CurPidl) + { + // enumerate all parent items + CAbsolutePidl pidl(pThis->m_CurPidl); + PIDLIST_ABSOLUTE pidlStart=pidl; + int index=0; + for (int i=0;i<(int)pThis->m_ComboItems.size();i++) + { + PIDLIST_ABSOLUTE p=(PIDLIST_ABSOLUTE)ILFindChild(pThis->m_ComboItems[i].pidl,pidl); + if (p) + { + index=i; + pidlStart=p; + } + } + int n=0; + for (PUIDLIST_RELATIVE child=pidl;!ILIsEmpty(child);child=ILGetNext(child)) + n++; + + int start=n; + for (PUIDLIST_RELATIVE child=pidlStart;!ILIsEmpty(child);child=ILGetNext(child)) + start--; + + for (int i=start;i pFolder; + PCITEMID_CHILD child; + if (SUCCEEDED(SHBindToParent(pidl,IID_IShellFolder,(void**)&pFolder,&child))) + { + STRRET str; + if (SUCCEEDED(pFolder->GetDisplayNameOf(child,SHGDN_INFOLDER|SHGDN_NORMAL,&str))) + { + CComString pName; + StrRetToStr(&str,child,&pName); + ComboItem item={ILCloneFull(pidl),n-(i-start),CString(pName)}; + pThis->m_ComboItems.insert(pThis->m_ComboItems.begin()+index+1,1,item); + } + } + ILRemoveLastID(pidl); + } + } + + // add all sorted items to the combobox + COMBOBOXEXITEM item={CBEIF_TEXT|CBEIF_IMAGE|CBEIF_SELECTEDIMAGE|CBEIF_INDENT|CBEIF_LPARAM}; + item.iItem=-1; + for (std::vector::const_iterator it=pThis->m_ComboItems.begin();it!=pThis->m_ComboItems.end();++it) + { + item.iImage=item.iSelectedImage=-1; + item.pszText=(LPWSTR)(LPCWSTR)it->name; + item.iIndent=it->indent; + item.lParam=(LPARAM)it->pidl; + SHFILEINFO info; + if (SHGetFileInfo((LPCTSTR)it->pidl,0,&info,sizeof(info),SHGFI_PIDL|SHGFI_SYSICONINDEX|SHGFI_SMALLICON)) + item.iImage=item.iSelectedImage=info.iIcon; + int idx=(int)pThis->m_ComboBox.SendMessage(CBEM_INSERTITEM,'CLSH',(LPARAM)&item); + if (pThis->m_CurPidl && ILIsEqual(it->pidl,pThis->m_CurPidl)) + pThis->m_ComboBox.SendMessage(CB_SETCURSEL,idx); + } + + return 0; + } + if (HIWORD(wParam)==CBN_CLOSEUP || HIWORD(wParam)==CBN_SELENDCANCEL) + { + // on close clear the list + if (!pThis->m_ComboItems.empty()) + { + pThis->m_ComboBox.SetWindowText(pThis->m_CurPath); + pThis->ClearComboItems(); + } + if (HIWORD(wParam)==CBN_SELENDCANCEL) + PostMessage(hWnd,pThis->m_NavigateMsg,1,0); + return 0; + } + if (HIWORD(wParam)==CBN_SELENDOK) + { + // when an item is selected, go to it and clear the list (selection with mouse) + int index=(int)pThis->m_ComboBox.SendMessage(CB_GETCURSEL); + if (index>=0) + { + COMBOBOXEXITEM item={CBEIF_LPARAM,index}; + pThis->m_ComboBox.SendMessage(CBEM_GETITEM,0,(LPARAM)&item); + pThis->m_NavigatePidl.Clone((PIDLIST_ABSOLUTE)item.lParam); + PostMessage(hWnd,pThis->m_NavigateMsg,0,0); + } + pThis->ClearComboItems(); + return 0; + } + } + + if (uMsg==WM_NOTIFY && ((NMHDR*)lParam)->code==CBEN_BEGINEDIT) + { + // ignore this, so Explorer doesn't add its history to the list + return 0; + } + + if (uMsg==WM_NOTIFY && ((NMHDR*)lParam)->code==CBEN_ENDEDIT) + { + if (pThis->m_ComboBox.SendMessage(CB_GETDROPPEDSTATE)) + { + // when an item is selected, go to it and clear the list (selection with keyboard) + NMCBEENDEDIT *pEdit=(NMCBEENDEDIT*)lParam; + int index=pEdit->iNewSelection; + if (index>=0) + { + COMBOBOXEXITEM item={CBEIF_LPARAM,index}; + pThis->m_ComboBox.SendMessage(CBEM_GETITEM,0,(LPARAM)&item); + pThis->m_NavigatePidl.Clone((PIDLIST_ABSOLUTE)item.lParam); + pThis->ClearComboItems(); + PostMessage(hWnd,pThis->m_NavigateMsg,0,0); + pThis->m_ComboBox.SendMessage(CB_SHOWDROPDOWN,FALSE); + } + return 0; + } + } + + if (uMsg==pThis->m_NavigateMsg) + { + // navigate to the selected item + if (wParam==0 && pThis->m_NavigatePidl && !(pThis->m_CurPidl && ILIsEqual(pThis->m_NavigatePidl,pThis->m_CurPidl))) + pThis->m_pBrowser->BrowseObject(pThis->m_NavigatePidl,SBSP_SAMEBROWSER|SBSP_ABSOLUTE); + else + SetFocus(hWnd); + pThis->m_NavigatePidl.Clear(); + } + + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +static void NewVersionCallback( VersionData &data ) +{ + wchar_t path[_MAX_PATH]; + GetModuleFileName(g_Instance,path,_countof(path)); + PathRemoveFileSpec(path); + PathAppend(path,L"ClassicShellUpdate.exe"); + wchar_t cmdLine[1024]; + Sprintf(cmdLine,_countof(cmdLine),L"\"%s\" -popup",path); + STARTUPINFO startupInfo={sizeof(startupInfo)}; + PROCESS_INFORMATION processInfo; + memset(&processInfo,0,sizeof(processInfo)); + if (CreateProcess(path,cmdLine,NULL,NULL,TRUE,0,NULL,NULL,&startupInfo,&processInfo)) + { + CloseHandle(processInfo.hThread); + CloseHandle(processInfo.hProcess); + } +} + +HRESULT STDMETHODCALLTYPE CExplorerBHO::SetSite( IUnknown *pUnkSite ) +{ + IObjectWithSiteImpl::SetSite(pUnkSite); + + if (pUnkSite) + { + // hook + GetTlsData()->bho=this; + if (!m_Hook) + { + m_Hook=SetWindowsHookEx(WH_CBT,HookExplorer,NULL,GetCurrentThreadId()); + } + CComQIPtr pProvider=pUnkSite; + + if (pProvider) + { + pProvider->QueryService(SID_SShellBrowser,IID_IShellBrowser,(void**)&m_pBrowser); + + // listen for web browser notifications. we only care about DISPID_NAVIGATECOMPLETE2 and DISPID_ONQUIT + pProvider->QueryService(SID_SWebBrowserApp,IID_IWebBrowser2,(void**)&m_pWebBrowser); + if (m_pWebBrowser) + { + if (DispEvent1::m_dwEventCookie==0xFEFEFEFE) // ATL's event cookie is 0xFEFEFEFE when the sink is not advised + DispEvent1::DispEventAdvise(m_pWebBrowser,&DIID_DWebBrowserEvents2); + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,GetSettingsRegPath())!=ERROR_SUCCESS) + regKey.Create(HKEY_CURRENT_USER,GetSettingsRegPath()); + + DWORD val; + if (regKey.QueryDWORDValue(L"ShowedToolbar",val)!=ERROR_SUCCESS || !val) + { + CComVariant name(L"{553891B7-A0D5-4526-BE18-D3CE461D6310}"); + CComVariant show(true); + if (GetSettingBool(L"NoInitialToolbar") || SUCCEEDED(m_pWebBrowser->ShowBrowserBar(&name,&show,NULL))) + regKey.SetDWORDValue(L"ShowedToolbar",1); + } + } + + HWND status; + if (m_pBrowser && SUCCEEDED(m_pBrowser->GetControlWindow(FCW_STATUS,&status))) + { + m_TopWindow=GetAncestor(status,GA_ROOT); + if (!GetProp(m_TopWindow,g_LoadedSettingsAtom)) + { + SetProp(m_TopWindow,g_LoadedSettingsAtom,(HANDLE)1); + LoadSettings(); + } + bool bWin8=(GetWinVersion()>=WIN_VER_WIN8); + + m_UpButtonIndex=bWin8?0:GetSettingInt(L"ShowUpButton"); + bool bShowCaption=!bWin8 && GetSettingBool(L"ShowCaption"); + bool bShowIcon=!bWin8 && GetSettingBool(L"ShowIcon"); + + if (m_TopWindow && (bShowCaption || bShowIcon)) + { + // show the title and the icon for the main Explorer window + DWORD flags=WTNCA_NODRAWCAPTION|WTNCA_NODRAWICON; + if (bShowCaption) flags&=~WTNCA_NODRAWCAPTION; + if (bShowIcon) flags&=~WTNCA_NODRAWICON; + SetWindowThemeNonClientAttributes(m_TopWindow,WTNCA_NODRAWCAPTION|WTNCA_NODRAWICON,flags); + } + + // find the TravelBand and the rebar + HWND band=NULL, rebar=NULL; + if (m_TopWindow) + band=FindChildWindow(m_TopWindow,L"TravelBand"); + if (band) + rebar=GetParent(band); + + bool bRedrawRebar=false; + + m_Rebar=rebar; + m_AltD=0; + if (rebar && GetSettingBool(L"HideSearch")) + { + // to remove the Search box, first find the band with ID=2 (or 4 for Win8). Then disable the child control and hide the band + int idx=(int)SendMessage(rebar,RB_IDTOINDEX,bWin8?4:2,0); + if (idx>=0) + { + REBARBANDINFO info={sizeof(info),RBBIM_CHILD}; + SendMessage(rebar,RB_GETBANDINFO,idx,(LPARAM)&info); + if (info.hwndChild) + EnableWindow(info.hwndChild,FALSE); + SendMessage(rebar,RB_SHOWBAND,idx,FALSE); + bRedrawRebar=true; + } + } + + if (rebar && m_UpButtonIndex) + { + // find the toolbar + HWND toolbar=FindWindowEx(band,NULL,TOOLBARCLASSNAME,NULL); + RECT rc; + GetClientRect(toolbar,&rc); + bool bDef; + int size=GetSettingInt(L"UpIconSize",bDef); + if (bDef) + size=rc.bottom; + m_Toolbar.Create(rebar,NULL,NULL,WS_CHILD|TBSTYLE_TOOLTIPS|TBSTYLE_FLAT|TBSTYLE_CUSTOMERASE|CCS_NODIVIDER|CCS_NOPARENTALIGN|CCS_NORESIZE); + m_Toolbar.SendMessage(TB_SETEXTENDEDSTYLE,0,TBSTYLE_EX_MIXEDBUTTONS); + m_Toolbar.SendMessage(TB_BUTTONSTRUCTSIZE,sizeof(TBBUTTON)); + m_Toolbar.SendMessage(TB_SETMAXTEXTROWS,1); + + std::vector modules; + CString str=GetSettingString(L"UpIconNormal"); + m_IconNormal=str?LoadIcon(size,str,modules):NULL; + if (m_IconNormal) + { + str=GetSettingString(L"UpIconHot"); + m_IconHot=LoadIcon(size,str,modules); + str=GetSettingString(L"UpIconPressed"); + m_IconPressed=LoadIcon(size,str,modules); + str=GetSettingString(L"UpIconDisabled"); + m_IconDisabled=LoadIcon(size,str,modules); + if (!m_IconDisabled) + m_IconDisabled=CreateDisabledIcon(m_IconNormal,size); + } + else + { + m_IconNormal=(HICON)LoadImage(g_Instance,MAKEINTRESOURCE(IDI_UP2NORMAL),IMAGE_ICON,size,size,LR_DEFAULTCOLOR); + m_IconHot=(HICON)LoadImage(g_Instance,MAKEINTRESOURCE(IDI_UP2HOT),IMAGE_ICON,size,size,LR_DEFAULTCOLOR); + m_IconPressed=(HICON)LoadImage(g_Instance,MAKEINTRESOURCE(IDI_UP2PRESSED),IMAGE_ICON,size,size,LR_DEFAULTCOLOR); + m_IconDisabled=(HICON)LoadImage(g_Instance,MAKEINTRESOURCE(IDI_UP2DISABLED),IMAGE_ICON,size,size,LR_DEFAULTCOLOR); + } + + for (std::vector::const_iterator it=modules.begin();it!=modules.end();++it) + FreeLibrary(*it); + + TBBUTTON button={I_IMAGENONE,1,TBSTATE_ENABLED}; + m_Toolbar.SendMessage(TB_ADDBUTTONS,1,(LPARAM)&button); + m_Toolbar.SendMessage(TB_SETBUTTONSIZE,0,MAKELONG(size,size)); + + m_bRemapBands=true; + SetWindowSubclass(rebar,SubclassRebarProc,(UINT_PTR)this,(DWORD_PTR)m_Toolbar.m_hWnd); + REBARBANDINFO info={sizeof(info),RBBIM_CHILD|RBBIM_ID|RBBIM_CHILDSIZE|RBBIM_IDEALSIZE|RBBIM_SIZE|RBBIM_STYLE}; + info.fStyle=RBBS_HIDETITLE|RBBS_NOGRIPPER|RBBS_FIXEDSIZE; + info.hwndChild=m_Toolbar.m_hWnd; + info.cxIdeal=info.cx=info.cxMinChild=size; + info.cyMinChild=size; + info.wID='UBTN'; + SendMessage(rebar,RB_INSERTBAND,m_UpButtonIndex-1,(LPARAM)&info); + bRedrawRebar=true; + } + + if (rebar) + { + int AddressBarHistory=GetSettingInt(L"AddressBarHistory"); + HWND progress=NULL; + HWND breadcrumbs=FindChildWindow(rebar,L"Breadcrumb Parent"); + if (breadcrumbs) + { + progress=GetParent(breadcrumbs); + breadcrumbs=FindWindowEx(breadcrumbs,NULL,TOOLBARCLASSNAME,NULL); + m_AltD=(char)GetSettingString(L"AddressAltD")[0]; + if (m_AltD>='a' && m_AltD<='z') + m_AltD+='A'-'a'; + if (m_AltD<'A' || m_AltD>'Z') + m_AltD=0; + } + m_Breadcrumbs=breadcrumbs; + if (GetSettingBool(L"DisableBreadcrumbs")) + { + // "hide" the breadcrumbs. no, not really. instead of hiding the breadcrumbs we just make them show the full path as text + if (breadcrumbs) + { + m_bNoBreadcrumbs=true; + SetWindowSubclass(breadcrumbs,SubclassBreadcrumbProc,(UINT_PTR)this,0); + } + } + if (progress && AddressBarHistory) + { + m_Progress=progress; + m_ComboBox=FindWindowEx(progress,NULL,WC_COMBOBOXEX,NULL); + SetWindowSubclass(progress,SubclassProgressProc,(UINT_PTR)this,AddressBarHistory); + m_NavigateMsg=RegisterWindowMessage(L"ClassicShell.Navigate"); + } + } + + if (bRedrawRebar) + RedrawWindow(rebar,NULL,NULL,RDW_UPDATENOW|RDW_ALLCHILDREN); + + m_UpHotkey=GetSettingInt(L"UpHotkey"); + if ((m_AltD || m_UpHotkey) && !m_HookKbd) + { + m_HookKbd=SetWindowsHookEx(WH_KEYBOARD,HookKeyboard,NULL,GetCurrentThreadId()); + } + + if ((bWin8 && GetSettingBool(L"ShowStatusBar")) || (!bWin8 && GetSettingBool(L"ShowFreeSpace"))) + { + DWORD flags=(GetSettingBool(L"ShowInfoTip")?SHOW_INFOTIP:0)|(GetSettingBool(L"ShowFreeSpace")?SHOW_FREE_SPACE:0); + if (bWin8) + { + RECT rc; + GetWindowRect(status,&rc); + m_Status8=CreateWindow(STATUSCLASSNAME,NULL,WS_CHILD|WS_VISIBLE|SBARS_SIZEGRIP|SBARS_TOOLTIPS,0,0,rc.right-rc.left,rc.bottom-rc.top,GetParent(status),NULL,g_Instance,NULL); + HDC hdc=CreateCompatibleDC(NULL); + HGDIOBJ font0=SelectObject(hdc,(HFONT)SendMessage(m_Status8,WM_GETFONT,0,0)); + + HFONT font=CreateFontSetting(GetSettingString(L"StatusBarFont"),GetDeviceCaps(hdc,LOGPIXELSY)); + if (font) + { + SendMessage(m_Status8,WM_SETFONT,(WPARAM)font,0); + SelectObject(hdc,font); + TEXTMETRIC met; + GetTextMetrics(hdc,&met); + int height=GetSystemMetrics(SM_CXSMICON); + if (heightGetZoneAttributes(zone,&attributes))) + { + if (GetTextExtentPoint32(hdc,attributes.szDisplayName,Strlen(attributes.szDisplayName),&size) && m_ZoneWidthbho=NULL; + if (m_Hook) + UnhookWindowsHookEx(m_Hook); + m_Hook=NULL; + if (m_HookKbd) + UnhookWindowsHookEx(m_HookKbd); + m_HookKbd=NULL; + if (m_Status) + RemoveWindowSubclass(m_Status,SubclassStatusProc,(UINT_PTR)this); + m_Status=NULL; + if (m_Status8) + RemoveWindowSubclass(m_Status8,SubclassStatusProc8,(UINT_PTR)this); + m_Status8=NULL; + if (m_DUIView) + RemoveWindowSubclass(m_DUIView,SubclassDUIViewProc,(UINT_PTR)this); + m_DUIView=NULL; + if (m_Progress) + RemoveWindowSubclass(m_Progress,SubclassProgressProc,(UINT_PTR)this); + m_Progress=NULL; + if (m_bNoBreadcrumbs) + RemoveWindowSubclass(m_Breadcrumbs,SubclassBreadcrumbProc,(UINT_PTR)this); + m_Breadcrumbs=NULL; + m_bNoBreadcrumbs=false; + if (m_Rebar) + RemoveWindowSubclass(m_Rebar,SubclassRebarProc,(UINT_PTR)this); + m_pBrowser=NULL; + if (m_pWebBrowser && DispEvent1::m_dwEventCookie!=0xFEFEFEFE) + DispEvent1::DispEventUnadvise(m_pWebBrowser,&DIID_DWebBrowserEvents2); + m_pWebBrowser=NULL; + if (m_pWebDoc && DispEvent2::m_dwEventCookie!=0xFEFEFEFE) + DispEvent2::DispEventUnadvise(m_pWebDoc,&DIID_DShellFolderViewEvents); + m_pWebDoc=NULL; + if (m_Toolbar.m_hWnd) + m_Toolbar.DestroyWindow(); + if (m_IconNormal) DestroyIcon(m_IconNormal); m_IconNormal=NULL; + if (m_IconHot) DestroyIcon(m_IconHot); m_IconHot=NULL; + if (m_IconPressed) DestroyIcon(m_IconPressed); m_IconPressed=NULL; + if (m_IconDisabled) DestroyIcon(m_IconDisabled); m_IconDisabled=NULL; + if (m_CurIcon) DestroyIcon(m_CurIcon); m_CurIcon=NULL; + m_CurPidl.Clear(); + m_NavigatePidl.Clear(); + if (m_TopWindow) RemoveProp(m_TopWindow,g_LoadedSettingsAtom); + m_TopWindow=NULL; + if (m_Balloon) + { + DestroyWindow(m_Balloon); + m_Balloon=NULL; + } + for (std::map::iterator it=m_ZoneIconCache.begin();it!=m_ZoneIconCache.end();++it) + DestroyIcon(it->second); + } + ClearComboItems(); + return S_OK; +} + +void CExplorerBHO::ClearComboItems( void ) +{ + for (std::vector::iterator it=m_ComboItems.begin();it!=m_ComboItems.end();++it) + ILFree(it->pidl); + m_ComboItems.clear(); + if (m_ComboBox.m_hWnd) + { + for (int i=(int)m_ComboBox.SendMessage(CB_GETCOUNT)-1;i>=0;i--) + m_ComboBox.SendMessage(CBEM_DELETEITEM,i); + } +} + +STDMETHODIMP CExplorerBHO::OnDocumentComplete( IDispatch *pDisp, VARIANT *URL ) +{ + // this is called when the current folder changes. disable the Up button if this is the desktop folder + bool bDesktop=false; + m_CurPath[0]=0; + if (m_CurIcon) DestroyIcon(m_CurIcon); + m_CurIcon=NULL; + m_CurPidl.Clear(); + if (m_pWebBrowser && (m_Status || m_Status8)) + { + if (m_pWebDoc && DispEvent2::m_dwEventCookie!=0xFEFEFEFE) + DispEvent2::DispEventUnadvise(m_pWebDoc,&DIID_DShellFolderViewEvents); + m_pWebDoc=NULL; + m_pWebBrowser->get_Document(&m_pWebDoc); + if (m_pWebDoc && DispEvent2::m_dwEventCookie==0xFEFEFEFE) // ATL's event cookie is 0xFEFEFEFE when the sink is not advised + DispEvent2::DispEventAdvise(m_pWebDoc,&DIID_DShellFolderViewEvents); + if (DispEvent2::m_dwEventCookie!=0xFEFEFEFE) + { + if (m_Status) + SendMessage(m_Status,WM_CLEAR,0,0); + if (m_Status8) + SendMessage(m_Status8,WM_CLEAR,0,0); + } + } + if (m_pBrowser) + { + CComPtr pView; + m_pBrowser->QueryActiveShellView(&pView); + if (pView) + { + CComQIPtr pFolderView=pView; + if (pFolderView) + { + if (GetSettingBool(L"ShowHeaders")) + { + + // *********************************************************************** + + // The code to turn on the headers is borrowed from the Explorer7Fixes project under the terms of the MIT license: + // http://github.com/ijprest/Explorer7Fixes - Copyright (c) 2010 Ian Prest + + CComQIPtr pView2=pFolderView; + if (pView2) + { + // Turn on the sort header! + pView2->SetCurrentFolderFlags(FWF_NOHEADERINALLVIEWS,0); + // It seems the ItemsView doesn't respect the FWF_NOHEADERINALLVIEWS flag + // until the view has been refreshed. Rather than call Refresh, we just + // briefly change the view mode and change it back. + FOLDERVIEWMODE viewMode; + int itemSize=0; + pView2->GetViewModeAndIconSize(&viewMode,&itemSize); + if (viewMode!=FVM_DETAILS) + { + pView2->SetViewModeAndIconSize(viewMode==FVM_LIST?FVM_SMALLICON:FVM_LIST,itemSize); + pView2->SetViewModeAndIconSize(viewMode,itemSize); + } + } + // *********************************************************************** + + } + + CComPtr pFolder; + pFolderView->GetFolder(IID_IPersistFolder2,(void**)&pFolder); + if (pFolder && SUCCEEDED(pFolder->GetCurFolder(&m_CurPidl)) && m_CurPidl) + { + if (ILIsEmpty(m_CurPidl)) + bDesktop=true; // only the top level has empty PIDL + + // find path and icon + // it is possible to get the path and icon from the caption of the main window, but there are 2 problems: + // 1) on Vista the icon is wrong. after you navigate to a new folder the icon switches to some default image and doesn't change any more + // 2) if the user has not checked "display full path in title bar", the caption of the main window is just the current folder name and not the full path + // so do it the hard way and grab it from SHGetNameFromIDList and SHGetFileInfo + if (m_bNoBreadcrumbs) + { + CComString pPath; + if (SUCCEEDED(SHGetNameFromIDList(m_CurPidl,SIGDN_DESKTOPABSOLUTEEDITING,&pPath))) + Strcpy(m_CurPath,_countof(m_CurPath),pPath); + else if (SUCCEEDED(SHGetNameFromIDList(m_CurPidl,SIGDN_FILESYSPATH,&pPath))) + Strcpy(m_CurPath,_countof(m_CurPath),pPath); // just in case DESKTOPABSOLUTE fails let's try the FILESYSPATH. probably not needed + SHFILEINFO info; + if (SUCCEEDED(SHGetFileInfo((LPCTSTR)(PIDLIST_ABSOLUTE)m_CurPidl,0,&info,sizeof(info),SHGFI_ICON|SHGFI_SMALLICON|SHGFI_PIDL))) + m_CurIcon=info.hIcon; + } + } + } + } + if (GetSettingBool(L"HideScrollTip")) + { + CComQIPtr pOptions=m_pBrowser; + if (pOptions) + pOptions->SetFolderViewOptions(FVO_NOSCROLLTIPS,FVO_NOSCROLLTIPS); + } + } + if (m_Toolbar.m_hWnd) + m_Toolbar.SendMessage(TB_ENABLEBUTTON,1,bDesktop?0:1); + + if (m_pZoneManager && m_pSecurityManager) + { + wchar_t text[256]; + text[0]=0; + HICON hIcon=NULL; + if (URL && URL->vt==VT_BSTR) + { + DWORD zone; + if (FAILED(m_pSecurityManager->MapUrlToZone(URL->bstrVal,&zone,0))) + zone=URLZONE_LOCAL_MACHINE; + ZONEATTRIBUTES attributes={sizeof(attributes)}; + if (SUCCEEDED(m_pZoneManager->GetZoneAttributes(zone,&attributes))) + { + Strcpy(text,_countof(text),attributes.szDisplayName); + unsigned int key=CalcFNVHash(attributes.szIconPath); + std::map::const_iterator it=m_ZoneIconCache.find(key); + if (it!=m_ZoneIconCache.end()) + hIcon=it->second; + else + { + wchar_t path[_MAX_PATH]; + wchar_t *str=wcschr(attributes.szIconPath,'#'); + if (!str) str=wcschr(attributes.szIconPath,','); + int index=0; + if (str) + { + index=_wtol(str+1); + *str=0; + } + int iconSize=GetSystemMetrics(SM_CXSMICON); + Strcpy(path,_countof(path),attributes.szIconPath); + if (PathIsRelative(path)) + PathFindOnPath(path,NULL); + if (index==0) + hIcon=(HICON)LoadImage(NULL,path,IMAGE_ICON,iconSize,iconSize,LR_LOADFROMFILE); + else + { + HMODULE hModule=LoadLibraryEx(path,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (hModule) + { + hIcon=(HICON)LoadImage(hModule,MAKEINTRESOURCE(index),IMAGE_ICON,iconSize,iconSize,0); + FreeLibrary(hModule); + } + } + m_ZoneIconCache[key]=hIcon; + } + } + } + + SendMessage(m_Status8,SB_SETTEXT,PART_ZONE,(LPARAM)text); + SendMessage(m_Status8,SB_SETICON,PART_ZONE,(LPARAM)hIcon); + + } + return S_OK; +} + +STDMETHODIMP CExplorerBHO::OnQuit( void ) +{ + if (m_pWebBrowser && DispEvent1::m_dwEventCookie!=0xFEFEFEFE) // ATL's event cookie is 0xFEFEFEFE, when the sink is not advised + DispEvent1::DispEventUnadvise(m_pWebBrowser,&DIID_DWebBrowserEvents2); + if (m_pWebDoc && DispEvent2::m_dwEventCookie!=0xFEFEFEFE) + DispEvent2::DispEventUnadvise(m_pWebDoc,&DIID_DShellFolderViewEvents); + return S_OK; +} + +STDMETHODIMP CExplorerBHO::OnSelChanged( void ) +{ + if (m_Status) + SendMessage(m_Status,WM_CLEAR,0,0); + if (m_Status8) + SendMessage(m_Status8,WM_CLEAR,0,0); + return S_OK; +} + +bool ShowTreeProperties( HWND hwndTree ) +{ + CAbsolutePidl pidl; + GetTreeItemPidl(TreeView_GetSelection(hwndTree),hwndTree,&pidl); + if (pidl) + { + // show properties + SHELLEXECUTEINFO execute={sizeof(execute),SEE_MASK_IDLIST|SEE_MASK_INVOKEIDLIST,NULL,L"properties"}; + execute.lpIDList=pidl; + execute.nShow=SW_SHOWNORMAL; + ShellExecuteEx(&execute); + return true; + } + return false; +} diff --git a/ClassicShellSrc/ClassicExplorer/ExplorerBHO.h b/ClassicShellSrc/ClassicExplorer/ExplorerBHO.h new file mode 100644 index 0000000..9dd6ffa --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ExplorerBHO.h @@ -0,0 +1,190 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// ExplorerBHO.h : Declaration of the CExplorerBHO + +#pragma once +#include "resource.h" // main symbols +#include +#include + +#include "ClassicExplorer_i.h" +#include "ComHelper.h" +#include + + +// CExplorerBHO + +class ATL_NO_VTABLE CExplorerBHO : + public CComObjectRootEx, + public CComCoClass, + public IObjectWithSiteImpl, + public IDispatchImpl, + public IDispEventImpl<1,CExplorerBHO,&DIID_DWebBrowserEvents2,&LIBID_SHDocVw,1,1>, + public IDispEventImpl<2,CExplorerBHO,&DIID_DShellFolderViewEvents,&LIBID_Shell32,1,0> +{ +public: + typedef IDispEventImpl<1,CExplorerBHO,&DIID_DWebBrowserEvents2,&LIBID_SHDocVw,1,1> DispEvent1; + typedef IDispEventImpl<2,CExplorerBHO,&DIID_DShellFolderViewEvents,&LIBID_Shell32,1,0> DispEvent2; + CExplorerBHO() + { + m_bResetStatus=true; + m_bForceRefresh=false; + m_bRemapBands=false; + m_bNoBreadcrumbs=false; + m_TreeItemHeight=0; + m_CurIcon=NULL; + m_CurPath[0]=0; + m_Rebar=NULL; + m_TopWindow=NULL; + m_Breadcrumbs=NULL; + m_Progress=NULL; + m_Status=m_Status8=NULL; + m_DUIView=NULL; + m_Hook=m_HookKbd=NULL; + m_Balloon=NULL; + m_UpButtonIndex=0; + m_UpHotkey=0; + m_IconNormal=m_IconHot=m_IconPressed=m_IconDisabled=NULL; + m_NavigateMsg=0; + m_AltD=0; + m_FileSizeWidth=0; + m_ZoneWidth=0; + } + + DECLARE_REGISTRY_RESOURCEID(IDR_EXPLORERBHO) + + BEGIN_SINK_MAP( CExplorerBHO ) + SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete) + SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_ONQUIT, OnQuit) + SINK_ENTRY_EX(2, DIID_DShellFolderViewEvents, DISPID_SELECTIONCHANGED, OnSelChanged) + END_SINK_MAP() + + BEGIN_COM_MAP(CExplorerBHO) + COM_INTERFACE_ENTRY(IExplorerBHO) + COM_INTERFACE_ENTRY(IObjectWithSite) + COM_INTERFACE_ENTRY(IDispatch) + END_COM_MAP() + + + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + HRESULT FinalConstruct() + { + return S_OK; + } + + void FinalRelease() + { + } + + // Navigation pane styles + enum + { + STYLE_CLASSIC=0, // use classic XP style + STYLE_SIMPLE=1, // use simple XP style + STYLE_VISTA=2, // no change + }; + + enum + { + SHOW_INFOTIP=1, + SHOW_FREE_SPACE=2, + SHOW_ZONE=4, + }; + + enum + { + PART_TEXT, + PART_SIZE, + PART_ZONE, + }; +public: + // IObjectWithSite + STDMETHOD(SetSite)(IUnknown *pUnkSite); + + // DWebBrowserEvents2 + STDMETHOD(OnDocumentComplete)( IDispatch *pDisp, VARIANT *URL ); + STDMETHOD(OnQuit)( void ); + + // DShellFolderViewEvents + STDMETHOD(OnSelChanged)( void ); + +private: + // Super-class the toolbar, so it has a different class name. A program called Folder Menu 3 looks for specific controls in Explorer, + // and our extra toolbar throws it off + class CToolbar: public CWindowImpl + { + public: + DECLARE_WND_SUPERCLASS(L"ClassicShell.UpButton",TOOLBARCLASSNAME); + + BEGIN_MSG_MAP( CToolbar ) + END_MSG_MAP() + }; + + CComPtr m_pBrowser; + CComPtr m_pWebBrowser; + CComPtr m_pWebDoc; + CComPtr m_pZoneManager; + CComPtr m_pSecurityManager; + std::map m_ZoneIconCache; + bool m_bResetStatus; + bool m_bForceRefresh; + bool m_bNoBreadcrumbs; + bool m_bRemapBands; + int m_TreeItemHeight; + int m_UpButtonIndex; + int m_UpHotkey; + CToolbar m_Toolbar; + HWND m_TopWindow; + HWND m_Rebar; + HWND m_Balloon; + HICON m_IconNormal, m_IconHot, m_IconPressed, m_IconDisabled; + HICON m_CurIcon; + CAbsolutePidl m_CurPidl; + wchar_t m_CurPath[1024]; // the current path + CWindow m_ComboBox; + CAbsolutePidl m_NavigatePidl; + UINT m_NavigateMsg; // private message that is posted to the progress bar to navigate to m_NavigatePidl + HHOOK m_Hook; + HHOOK m_HookKbd; + HWND m_Breadcrumbs; + HWND m_Progress; + HWND m_Status, m_Status8; + HWND m_DUIView; + int m_FileSizeWidth; + int m_ZoneWidth; + char m_AltD; + + struct ComboItem + { + PIDLIST_ABSOLUTE pidl; + int indent; + CString name; + CString sortName; + + bool operator<( const ComboItem &item ) { return _wcsicmp(sortName,item.sortName)<0; } + }; + std::vector m_ComboItems; + void ClearComboItems( void ); + bool GetStatusText( wchar_t *buf, int size, const wchar_t *oldText, bool bShowTip, bool bShowSpace ); + void GetFileSize( wchar_t *buf, int size ); + + static int s_AutoNavDelay; + + static LRESULT CALLBACK HookExplorer( int code, WPARAM wParam, LPARAM lParam ); + static LRESULT CALLBACK HookKeyboard( int code, WPARAM wParam, LPARAM lParam ); + static LRESULT CALLBACK SubclassTreeParentProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + static LRESULT CALLBACK SubclassTreeProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + static LRESULT CALLBACK SubclassStatusProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + static LRESULT CALLBACK SubclassStatusProc8( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + static LRESULT CALLBACK SubclassDUIViewProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + static LRESULT CALLBACK SubclassRebarProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + static LRESULT CALLBACK SubclassBreadcrumbProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + static LRESULT CALLBACK SubclassProgressProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); +}; + +OBJECT_ENTRY_AUTO(__uuidof(ExplorerBHO), CExplorerBHO) + +bool ShowTreeProperties( HWND hwndTree ); diff --git a/ClassicShellSrc/ClassicExplorer/ExplorerBHO.rgs b/ClassicShellSrc/ClassicExplorer/ExplorerBHO.rgs new file mode 100644 index 0000000..c98fc25 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ExplorerBHO.rgs @@ -0,0 +1,59 @@ +HKCR +{ + ClassicExplorer.ExplorerBHO.1 = s 'ExplorerBHO Class' + { + CLSID = s '{449D0D6E-2412-4E61-B68F-1CB625CD9E52}' + } + ClassicExplorer.ExplorerBHO = s 'ExplorerBHO Class' + { + CLSID = s '{449D0D6E-2412-4E61-B68F-1CB625CD9E52}' + CurVer = s 'ClassicExplorer.ExplorerBHO.1' + } + NoRemove CLSID + { + ForceRemove {449D0D6E-2412-4E61-B68F-1CB625CD9E52} = s 'ExplorerBHO Class' + { + ProgID = s 'ClassicExplorer.ExplorerBHO.1' + VersionIndependentProgID = s 'ClassicExplorer.ExplorerBHO' + ForceRemove 'Programmable' + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Apartment' + } + 'TypeLib' = s '{BF8D124A-A4E0-402F-8152-4EF377E62586}' + } + } +} + +HKLM +{ + NoRemove SOFTWARE + { + NoRemove Microsoft + { + NoRemove Windows + { + NoRemove CurrentVersion + { + NoRemove Explorer + { + NoRemove 'Browser Helper Objects' + { + ForceRemove '{449D0D6E-2412-4E61-B68F-1CB625CD9E52}' + } + } + NoRemove Policies + { + NoRemove Ext + { + NoRemove CLSID + { + ForceRemove val {449D0D6E-2412-4E61-B68F-1CB625CD9E52} = s '2' + } + } + } + } + } + } + } +} diff --git a/ClassicShellSrc/ClassicExplorer/ExplorerBand.cpp b/ClassicShellSrc/ClassicExplorer/ExplorerBand.cpp new file mode 100644 index 0000000..2e03f30 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ExplorerBand.cpp @@ -0,0 +1,2284 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// ExplorerBand.cpp : Implementation of CExplorerBand + +#include "stdafx.h" +#include "ExplorerBand.h" +#include "resource.h" +#include "ExplorerBHO.h" +#include "ResourceHelper.h" +#include "SettingsUI.h" +#include "Settings.h" +#include "SettingsParser.h" +#include "Translations.h" +#include "dllmain.h" +#include "SettingsUIHelper.h" +#include "FNVHash.h" +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////// + +// CBandWindow - the parent window of the toolbar + +static struct +{ + const wchar_t *name; + int id; +} g_StdCommands[]={ + {L"up",CBandWindow::ID_GOUP}, + {L"cut",CBandWindow::ID_CUT}, + {L"copy",CBandWindow::ID_COPY}, + {L"paste",CBandWindow::ID_PASTE}, + {L"paste_shortcut",CBandWindow::ID_PASTE_SHORTCUT}, + {L"delete",CBandWindow::ID_DELETE}, + {L"properties",CBandWindow::ID_PROPERTIES}, + {L"email",CBandWindow::ID_EMAIL}, + {L"settings",CBandWindow::ID_SETTINGS}, + {L"moveto",CBandWindow::ID_MOVETO}, + {L"copyto",CBandWindow::ID_COPYTO}, + {L"undo",CBandWindow::ID_UNDO}, + {L"redo",CBandWindow::ID_REDO}, + {L"selectall",CBandWindow::ID_SELECTALL}, + {L"deselect",CBandWindow::ID_DESELECT}, + {L"invertselection",CBandWindow::ID_INVERT}, + {L"back",CBandWindow::ID_GOBACK}, + {L"forward",CBandWindow::ID_GOFORWARD}, + {L"refresh",CBandWindow::ID_REFRESH}, + {L"stop",CBandWindow::ID_STOP}, + {L"rename",CBandWindow::ID_RENAME}, + {L"newfolder",CBandWindow::ID_NEWFOLDER}, + {L"zipfolder",CBandWindow::ID_ZIPFOLDER}, + {L"nav_pane",CBandWindow::ID_NAVPANE}, + {L"details_pane",CBandWindow::ID_DETAILSPANE}, + {L"preview_pane",CBandWindow::ID_PREVIEWPANE}, + {L"mapdrive",CBandWindow::ID_MAP_DRIVE}, + {L"disconnect",CBandWindow::ID_DISCONNECT}, + {L"customizefolder",CBandWindow::ID_CUSTOMIZEFOLDER}, + {L"folderoptions",CBandWindow::ID_FOLDEROPTIONS}, + {L"viewtiles",CBandWindow::ID_VIEW_TILES}, + {L"viewdetails",CBandWindow::ID_VIEW_DETAILS}, + {L"viewlist",CBandWindow::ID_VIEW_LIST}, + {L"viewcontent",CBandWindow::ID_VIEW_CONTENT}, + {L"viewicons_small",CBandWindow::ID_VIEW_ICONS1}, + {L"viewicons_medium",CBandWindow::ID_VIEW_ICONS2}, + {L"viewicons_large",CBandWindow::ID_VIEW_ICONS3}, + {L"viewicons_extralarge",CBandWindow::ID_VIEW_ICONS4}, + {L"show_extensions",CBandWindow::ID_SHOW_EXTENSIONS}, + {L"hidden_files",CBandWindow::ID_HIDDEN_FILES}, + {L"system_files",CBandWindow::ID_SYSTEM_FILES}, +}; + +static GUID SID_FrameManager={0x31e4fa78,0x02b4,0x419f,{0x94,0x30,0x7b,0x75,0x85,0x23,0x7c,0x77}}; +static GUID SID_PerBrowserPropertyBag={0xa3b24a0a,0x7b68,0x448d,{0x99,0x79,0xc7,0x00,0x05,0x9c,0x3a,0xd1}}; +const wchar_t *g_NavPaneVisible=L"PageSpaceControlSizer_Visible"; +const wchar_t *g_DetailsPaneVisible=L"PreviewPaneSizer_Visible"; +const wchar_t *g_DetailsPaneEnabled=L"PreviewPaneSizer_Loaded"; +const wchar_t *g_PreviewPaneVisible=L"ReadingPaneSizer_Visible"; +const wchar_t *g_PreviewPaneEnabled=L"ReadingPaneSizer_Loaded"; +const wchar_t *g_ComboPaneEnabled=L"DetailsContainerSizer_Loaded"; + +typedef HRESULT (__stdcall *tBagWrite)( IPropertyBag *pThis, LPCOLESTR pszPropName, VARIANT *pVar ); +static volatile tBagWrite g_OldBagWrite; + +void CBandWindow::ParseToolbarItem( const wchar_t *name, StdToolbarItem &item ) +{ + wchar_t text[256]; + Sprintf(text,_countof(text),L"%s.Command",name); + const wchar_t *str=m_Parser.FindSetting(text); + + item.id=ID_CUSTOM; + if (str) + { + for (int i=0;i<_countof(g_StdCommands);i++) + if (_wcsicmp(str,g_StdCommands[i].name)==0) + { + item.id=g_StdCommands[i].id; + break; + } + } + + if (item.id==ID_CUSTOM) + { + item.command=str; + item.regName=name; + } + + Sprintf(text,_countof(text),L"%s.Link",name); + item.link=m_Parser.FindSetting(text); + if (item.link) + { + const wchar_t *c=wcschr(item.link,'|'); + if (c) + { + for (c++;*c==' ';) + c++; + item.link=c; + } + } + + Sprintf(text,_countof(text),L"%s.Icon",name); + item.iconPath=m_Parser.FindSetting(text); + + Sprintf(text,_countof(text),L"%s.IconDisabled",name); + item.iconPathD=m_Parser.FindSetting(text); + + Sprintf(text,_countof(text),L"%s.Label",name); + str=m_Parser.FindSetting(text); + if (str) + { + if (str[0]=='$') + item.label=FindTranslation(str+1,NULL); + else + item.label=str; + } + + Sprintf(text,_countof(text),L"%s.Tip",name); + str=m_Parser.FindSetting(text); + if (str) + { + if (str[0]=='$') + item.tip=FindTranslation(str+1,NULL); + else + item.tip=str; + } + +} + +void CBandWindow::ParseToolbar( void ) +{ + m_Items.clear(); + CString setting=GetSettingString(L"ToolbarItems"); + m_Parser.LoadText(setting,setting.GetLength()); + m_Parser.ParseText(); + std::vector items; + m_Parser.ParseTree(L"Items",items); + m_Items.resize(items.size()); + for (int i=0;i<(int)items.size();i++) + { + const wchar_t *name=items[i].name; + StdToolbarItem &item=m_Items[i]; + { + // can't use memset here because item is not a POD (there is a CString inside) + item.id=0; + item.tip=NULL; + item.label=NULL; + item.command=NULL; + item.link=NULL; + item.iconPath=NULL; + item.iconPathD=NULL; + item.submenu=NULL; + item.menuIcon=NULL; + item.menuIconD=NULL; + item.bIconLoaded=false; + item.bDisabled=false; + item.bChecked=false; + } + + // handle special names + if (!*name) + { + item.id=ID_LAST; + continue; + } + if (_wcsicmp(name,L"SEPARATOR")==0) + { + item.id=ID_SEPARATOR; + continue; + } + + ParseToolbarItem(name,item); + int idx=items[i].children; + if (idx>=0) + item.submenu=&m_Items[idx]; + } + if (m_Items.size()==1) + { + m_Items.resize(2); + m_Items[1]=m_Items[0]; + m_Items[0].id=ID_SETTINGS; + m_Items[0].tip=FindTranslation(L"$Toolbar.Settings",NULL); + m_Items[0].command=L"settings"; + m_Items[0].iconPath=L",1"; + } +} + +LRESULT CALLBACK CBandWindow::ToolbarSubclassProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_SETTINGCHANGE) + { + // HACK: Looks like WM_SETTINGCHANGE breaks the toolbar if it contains a split dropdown button (most likely something to do with metrics or themes) + // So we delete all buttons and post a message recreate them + int count=(int)SendMessage(hWnd,TB_BUTTONCOUNT,0,0); + CBandWindow *pThis=(CBandWindow*)uIdSubclass; + if (count>0) + { + for (int i=count-1;i>=0;i--) + { + TBBUTTON button; + SendMessage(hWnd,TB_GETBUTTON,i,(LPARAM)&button); + pThis->m_Buttons[i].fsState=button.fsState; + SendMessage(hWnd,TB_DELETEBUTTON,i,0); + } + ::PostMessage((HWND)dwRefData,CBandWindow::BWM_UPDATEBUTTONS,0,0); + } + + // Also refresh the buttons when the folder settings change + if (pThis->HasFolderSettings()) + ::PostMessage((HWND)dwRefData,CBandWindow::BWM_UPDATETOOLBAR,0,0); + } + if (uMsg==WM_PAINT) + { + CBandWindow *pThis=(CBandWindow*)uIdSubclass; + if (!pThis->m_pBrowserBag && pThis->HasPanes()) + pThis->UpdateBag(); + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +LRESULT CBandWindow::OnCreate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + ParseToolbar(); + + bool bLabels=false; + bool bList=GetSettingBool(L"ToolbarListMode"); + int mainCount=0; // number of the main items + for (std::vector::const_iterator it=m_Items.begin();it->id!=ID_LAST;++it,mainCount++) + if (it->label) + bLabels=true; + + // create the toolbar + if (bLabels && !bList) + m_Toolbar=CreateWindow(TOOLBARCLASSNAME,L"",WS_CHILD|TBSTYLE_TOOLTIPS|TBSTYLE_FLAT|CCS_NODIVIDER|CCS_NOPARENTALIGN|CCS_NORESIZE,0,0,10,10,m_hWnd,(HMENU)101,g_Instance,NULL); + else + m_Toolbar=CreateWindow(TOOLBARCLASSNAME,L"",WS_CHILD|TBSTYLE_TOOLTIPS|TBSTYLE_FLAT|TBSTYLE_LIST|CCS_NODIVIDER|CCS_NOPARENTALIGN|CCS_NORESIZE,0,0,10,10,m_hWnd,(HMENU)101,g_Instance,NULL); + + m_Toolbar.SendMessage(TB_SETEXTENDEDSTYLE,0,TBSTYLE_EX_MIXEDBUTTONS|TBSTYLE_EX_DRAWDDARROWS|TBSTYLE_EX_HIDECLIPPEDBUTTONS); + m_Toolbar.SendMessage(TB_BUTTONSTRUCTSIZE,sizeof(TBBUTTON)); + m_Toolbar.SendMessage(TB_SETMAXTEXTROWS,1); + SetWindowSubclass(m_Toolbar,ToolbarSubclassProc,(UINT_PTR)this,(DWORD_PTR)m_hWnd); + + int iconSize=GetSettingInt(GetSettingBool(L"UseBigButtons")?L"LargeIconSize":L"SmallIconSize"); + if (iconSize<8) iconSize=8; + else if (iconSize>128) iconSize=128; + + m_MenuIconSize=GetSettingInt(L"MenuIconSize"); + if (m_MenuIconSize<=0) m_MenuIconSize=0; + else if (m_MenuIconSize<8) m_MenuIconSize=8; + if (m_MenuIconSize>32) m_MenuIconSize=32; + + m_ImgEnabled=ImageList_Create(iconSize,iconSize,ILC_COLOR32|ILC_MASK|(IsLanguageRTL()?ILC_MIRROR:0),0,mainCount); + m_ImgDisabled=ImageList_Create(iconSize,iconSize,ILC_COLOR32|ILC_MASK|(IsLanguageRTL()?ILC_MIRROR:0),0,mainCount); + + HMODULE hShell32=GetModuleHandle(L"Shell32.dll"); + std::vector modules; + + bool bSame=GetSettingBool(L"SameSizeButtons"); + + // create buttons + m_Buttons.resize(mainCount); + for (int i=0;i pFactory; + if (SUCCEEDED(SHCreateItemFromIDList(pidl,IID_IShellItemImageFactory,(void**)&pFactory)) && pFactory) + { + SIZE size={iconSize,iconSize}; + if (FAILED(pFactory->GetImage(size,SIIGBF_ICONONLY,&hBitmap))) + hBitmap=NULL; + } + + } + } + + if (!hIcon && !hBitmap && !bNoIcon) + hIcon=(HICON)LoadImage(hShell32,MAKEINTRESOURCE(1),IMAGE_ICON,iconSize,iconSize,LR_DEFAULTCOLOR); + if (hIcon) + { + button.iBitmap=ImageList_AddIcon(m_ImgEnabled,hIcon); + HICON hIcon2=item.iconPathD?LoadIcon(iconSize,item.iconPathD,modules):NULL; + if (!hIcon2) + hIcon2=CreateDisabledIcon(hIcon,iconSize); + int idx=ImageList_AddIcon(m_ImgDisabled,hIcon2); + Assert(button.iBitmap==idx); + DestroyIcon(hIcon); + DestroyIcon(hIcon2); + } + else if (hBitmap) + { + button.iBitmap=ImageList_AddMasked(m_ImgEnabled,hBitmap,CLR_NONE); + int idx=ImageList_AddMasked(m_ImgDisabled,hBitmap,CLR_NONE); + Assert(button.iBitmap==idx); + DeleteObject(hBitmap); + } + + button.fsState=(item.id!=ID_SETTINGS || GetSettingBool(L"EnableSettings"))?TBSTATE_ENABLED:0; + button.fsStyle=BTNS_BUTTON|BTNS_NOPREFIX; + if (!bSame) + button.fsStyle|=BTNS_AUTOSIZE; + if (item.label) + { + button.fsStyle|=BTNS_SHOWTEXT; + button.iString=(INT_PTR)item.label; + } + + bool bFolder=false; + if (item.link) + { + wchar_t path[_MAX_PATH]; + Strcpy(path,_countof(path),item.link); + DoEnvironmentSubst(path,_countof(path)); + CAbsolutePidl pidl; + SFGAOF flags=0; + if (SUCCEEDED(ShParseDisplayName(path,&pidl,SFGAO_FOLDER,&flags))) + { + if (flags&SFGAO_FOLDER) + bFolder=true; + } + } + + if (item.submenu || bFolder) + button.fsStyle|=(item.id::const_iterator it=modules.begin();it!=modules.end();++it) + FreeLibrary(*it); + + // add buttons + HIMAGELIST old=(HIMAGELIST)m_Toolbar.SendMessage(TB_SETIMAGELIST,0,(LPARAM)m_ImgEnabled); + if (old) ImageList_Destroy(old); + old=(HIMAGELIST)m_Toolbar.SendMessage(TB_SETDISABLEDIMAGELIST,0,(LPARAM)m_ImgDisabled); + if (old) ImageList_Destroy(old); + if (!m_Buttons.empty()) + m_Toolbar.SendMessage(TB_ADDBUTTONS,(WPARAM)m_Buttons.size(),(LPARAM)&m_Buttons[0]); + SendMessage(WM_CLEAR); + return 0; +} + +LRESULT CBandWindow::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_ImgEnabled) ImageList_Destroy(m_ImgEnabled); m_ImgEnabled=NULL; + if (m_ImgDisabled) ImageList_Destroy(m_ImgDisabled); m_ImgDisabled=NULL; + for (std::vector::iterator it=m_Items.begin();it!=m_Items.end();++it) + { + if (it->menuIcon) DeleteObject(it->menuIcon); + if (it->menuIconD) DeleteObject(it->menuIconD); + } + m_Items.clear(); + bHandled=FALSE; + return 0; +} + +LRESULT CBandWindow::OnUpdateUI( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + // update the state of the custom buttons based on the registry settings + CRegKey regSettings; + if (regSettings.Open(HKEY_CURRENT_USER,GetSettingsRegPath())==ERROR_SUCCESS) + { + bool bMain=true; + for (int idx=0;idx<(int)m_Items.size();idx++) + { + if (m_Items[idx].id==ID_LAST) + bMain=false; + if (!m_Items[idx].regName.IsEmpty()) + { + DWORD val; + if (regSettings.QueryDWORDValue(m_Items[idx].regName,val)!=ERROR_SUCCESS) + val=0; + bool bDisabled=(val&1)!=0; + bool bChecked=(val&2)!=0; + if (bMain) + { + if (bDisabled!=m_Items[idx].bDisabled) m_Toolbar.SendMessage(TB_ENABLEBUTTON,idx+1,bDisabled?0:1); + if (bChecked!=m_Items[idx].bChecked) m_Toolbar.SendMessage(TB_CHECKBUTTON,idx+1,bChecked?1:0); + } + m_Items[idx].bDisabled=bDisabled; + m_Items[idx].bChecked=bChecked; + } + } + } + return 0; +} + +void CBandWindow::SendEmail( void ) +{ + const IID CLSID_SendMail={0x9E56BE60,0xC50F,0x11CF,{0x9A,0x2C,0x00,0xA0,0xC9,0x0A,0x90,0xCE}}; + + CComPtr pView; + if (FAILED(m_pBrowser->QueryActiveShellView(&pView))) return; + + // check if there is anything selected + CComQIPtr pView2=pView; + int count; + if (pView2 && SUCCEEDED(pView2->ItemCount(SVGIO_SELECTION,&count)) && count==0) + return; + + // get the data object + CComPtr pDataObj; + if (FAILED(pView->GetItemObject(SVGIO_SELECTION,IID_IDataObject,(void**)&pDataObj))) + return; + CComQIPtr pAsync=pDataObj; + if (pAsync) + pAsync->SetAsyncMode(FALSE); + + // drop into the SendMail handler + CComPtr pDropTarget; + if (SUCCEEDED(CoCreateInstance(CLSID_SendMail,NULL,CLSCTX_ALL,IID_IDropTarget,(void **)&pDropTarget))) + { + POINTL pt={0,0}; + DWORD dwEffect=DROPEFFECT_COPY; + pDropTarget->DragEnter(pDataObj,MK_LBUTTON,pt,&dwEffect); + pDropTarget->Drop(pDataObj,0,pt,&dwEffect); + } +} + +class CSendToZipHelper: public CComObjectRootEx, public IServiceProvider +{ +public: + BEGIN_COM_MAP(CSendToZipHelper) + COM_INTERFACE_ENTRY_IID( IID_IServiceProvider, IServiceProvider ) + END_COM_MAP() + + // from IServiceProvider + virtual HRESULT STDMETHODCALLTYPE QueryService( REFGUID guidService, REFIID riid, void **ppvObject ); + + CComPtr m_pFolderView; +}; + +HRESULT CSendToZipHelper::QueryService( REFGUID guidService, REFIID riid, void **ppvObject ) +{ + if (guidService==SID_SNewMenuClient) + { + return m_pFolderView->QueryInterface(riid,ppvObject); + } + return E_NOINTERFACE; +} + +void CBandWindow::SendToZip( void ) +{ + const IID CLSID_SendToZip={0x888DCA60, 0xFC0A, 0x11CF, {0x8F, 0x0F, 0x00, 0xC0, 0x4F, 0xD7, 0xD0, 0x62}}; + + CComPtr pView; + if (FAILED(m_pBrowser->QueryActiveShellView(&pView))) return; + + // check if there is anything selected + CComQIPtr pView2=pView; + + CComPtr pFolder; + if (FAILED(pView2->GetFolder(IID_IShellFolder,(void**)&pFolder)) || !pFolder) return; + + int count; + if (pView2 && SUCCEEDED(pView2->ItemCount(SVGIO_SELECTION,&count)) && count==0) + return; + + // get the data object + CComPtr pDataObj; + if (FAILED(pView->GetItemObject(SVGIO_SELECTION,IID_IDataObject,(void**)&pDataObj))) + return; + CComQIPtr pAsync=pDataObj; + if (pAsync) + pAsync->SetAsyncMode(FALSE); + + // drop into the SendMail handler + CComPtr pDropTarget; + if (SUCCEEDED(CoCreateInstance(CLSID_SendToZip,NULL,CLSCTX_ALL,IID_IDropTarget,(void **)&pDropTarget))) + { + CComQIPtr pDropWithSite=pDropTarget; + if (pDropWithSite) + { + CComObject *pHelper; + if (SUCCEEDED(CComObject::CreateInstance(&pHelper))) + { + pHelper->m_pFolderView=pView2; + pDropWithSite->SetSite(pHelper); + } + else + delete pHelper; + } + POINTL pt={0,0}; + DWORD dwEffect=DROPEFFECT_COPY; + pDropTarget->DragEnter(pDataObj,MK_LBUTTON,pt,&dwEffect); + pDropTarget->Drop(pDataObj,0,pt,&dwEffect); + } +} + +static bool GetPidlPath( PIDLIST_ABSOLUTE pidl, wchar_t *path ) +{ + path[0]=0; + if (SHGetPathFromIDList(pidl,path) && *path) + return true; + if (GetWinVersion()>=WIN_VER_WIN7) + { + // maybe it is a library - try the default save folder + CComPtr pShellItem; + if (SUCCEEDED(SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pShellItem))) + { + CComPtr pLibrary; + if (SUCCEEDED(pLibrary.CoCreateInstance(CLSID_ShellLibrary)) && SUCCEEDED(pLibrary->LoadLibraryFromItem(pShellItem,STGM_READ))) + { + pShellItem=NULL; + if (SUCCEEDED(pLibrary->GetDefaultSaveFolder(DSFT_DETECT,IID_IShellItem,(void**)&pShellItem)) && pShellItem) + { + CComString pPath; + if (SUCCEEDED(pShellItem->GetDisplayName(SIGDN_FILESYSPATH,&pPath))) + { + Strcpy(path,_MAX_PATH,pPath); + return true; + } + } + } + } + } + return false; +} + +void CBandWindow::NewFolder( void ) +{ + CComPtr pView; + if (FAILED(m_pBrowser->QueryActiveShellView(&pView))) return; + CComQIPtr pView2=pView; + if (!pView2) return; + + { + // check if this is a filesystem folder (InvokeCommand may crash for non-folders) + CComPtr pFolder; + CAbsolutePidl pidl; + if (FAILED(pView2->GetFolder(IID_IPersistFolder2,(void**)&pFolder)) || FAILED(pFolder->GetCurFolder(&pidl))) + return; + wchar_t path[_MAX_PATH]; + bool bFolder=GetPidlPath(pidl,path); // it is a folder if it has a path + if (!bFolder) + return; + } + + CComPtr pFolder; + if (FAILED(pView2->GetFolder(IID_IShellFolder,(void**)&pFolder)) || !pFolder) return; + + std::vector items; + { + // remember the old folders + CComPtr pEnum; + if (pFolder->EnumObjects(NULL,SHCONTF_FOLDERS,&pEnum)!=S_OK) pEnum=NULL; + + PITEMID_CHILD child; + while (pEnum && pEnum->Next(1,&child,NULL)==S_OK) + { + STRRET str; + if (SUCCEEDED(pFolder->GetDisplayNameOf(child,SHGDN_INFOLDER|SHGDN_FORPARSING,&str))) + { + CComString pName; + StrRetToStr(&str,child,&pName); + items.push_back(CalcFNVHash(pName)); + } + ILFree(child); + } + } + + CComPtr pMenu; + HMENU menu=CreatePopupMenu(); + bool bRename=false; + if (SUCCEEDED(pFolder->CreateViewObject(m_hWnd,IID_IContextMenu,(void**)&pMenu))) + { + if (SUCCEEDED(pMenu->QueryContextMenu(menu,0,1,32767,CMF_NORMAL))) + { + CMINVOKECOMMANDINFOEX info={sizeof(info),CMIC_MASK_UNICODE}; + info.lpVerb="NewFolder"; + info.lpVerbW=L"NewFolder"; + info.nShow=SW_SHOWNORMAL; + info.fMask|=CMIC_MASK_NOASYNC; + info.hwnd=GetAncestor(m_hWnd,GA_ROOT); + // Note: InvokeCommand crashes if the item is "Computer". I don't know if this is a bug in Explorer + // or I am not supposed to give unsupported verbs to InvokeCommand. Unfortunately there is no way to + // check if "NewFolder" is a supported verb. It is not present in the menu no matter what I give to + // QueryContextMenu. So we verify if this is a filesystem folder, cross fingers and hope for the best + if (SUCCEEDED(pMenu->InvokeCommand((CMINVOKECOMMANDINFO*)&info))) + bRename=true; + } + } + DestroyMenu(menu); + + if (bRename) + { + // look for a new folder and rename it + CComPtr pEnum; + if (pFolder->EnumObjects(NULL,SHCONTF_FOLDERS,&pEnum)!=S_OK) pEnum=NULL; + + PITEMID_CHILD child; + while (pEnum && pEnum->Next(1,&child,NULL)==S_OK) + { + STRRET str; + if (SUCCEEDED(pFolder->GetDisplayNameOf(child,SHGDN_INFOLDER|SHGDN_FORPARSING,&str))) + { + CComString pName; + StrRetToStr(&str,child,&pName); + unsigned int hash=CalcFNVHash(pName); + if (std::find(items.begin(),items.end(),hash)==items.end()) + { + // found the new folder + pView->SelectItem(child,SVSI_SELECT|SVSI_EDIT|SVSI_DESELECTOTHERS|SVSI_ENSUREVISIBLE|SVSI_FOCUSED); + break; + } + } + ILFree(child); + } + } +} + +void CBandWindow::ExecuteCommandFile( const wchar_t *pText ) +{ + wchar_t command[256]; + pText=GetToken(pText,command,_countof(command),L" \t\r\n"); + if (_wcsicmp(command,L"open")==0) + { + // navigate to the given folder + wchar_t path[_MAX_PATH]; + GetToken(pText,path,_countof(path),L" \t\r\n"); + CAbsolutePidl pidl; + if (m_pBrowser && SUCCEEDED(ShParseDisplayName(path,&pidl,0,NULL))) + { + UINT flags=(GetKeyState(VK_CONTROL)<0?SBSP_NEWBROWSER:SBSP_SAMEBROWSER); + m_pBrowser->BrowseObject(pidl,flags|SBSP_ABSOLUTE); + } + } + else if (_wcsicmp(command,L"refresh")==0) + { + // refresh Explorer + SendShellTabCommand(41504); + } + else if (_wcsicmp(command,L"select")==0) + { + // select the given files, deselect all others + + std::vector selected; + wchar_t path[_MAX_PATH]; + while (*pText) + { + pText=GetToken(pText,path,_countof(path),L"\t\r\n"); + wchar_t *fname=PathFindFileName(path); + CharUpper(fname); + + // trim leading spaces + while (*fname==' ') + fname++; + // trim trailing spaces + wchar_t *end=fname+Strlen(fname); + while (end>fname && end[-1]==' ') + end--; + *end=0; + + if (*fname) + selected.push_back(CalcFNVHash(fname)); + } + + CComPtr pView; + if (SUCCEEDED(m_pBrowser->QueryActiveShellView(&pView))) + { + CComQIPtr pView2=pView; + if (!pView2) return; + CComPtr pFolder; + if (FAILED(pView2->GetFolder(IID_IShellFolder,(void**)&pFolder)) || !pFolder) return; + CComPtr pEnum; + if (SUCCEEDED(pView2->Items(SVGIO_ALLVIEW,IID_IEnumIDList,(void**)&pEnum)) && pEnum) + { + PITEMID_CHILD child; + bool bFirst=true; + while (pEnum->Next(1,&child,NULL)==S_OK) + { + STRRET str; + if (SUCCEEDED(pFolder->GetDisplayNameOf(child,SHGDN_FORPARSING|SHGDN_INFOLDER,&str))) + { + CComString pName; + StrRetToStr(&str,child,&pName); + + pName.MakeUpper(); + unsigned int hash=CalcFNVHash(pName); + + UINT flags=SVSI_DESELECT; + if (std::find(selected.begin(),selected.end(),hash)!=selected.end()) + { + // the file is in the list + flags=SVSI_SELECT; + if (bFirst) + { + flags|=SVSI_ENSUREVISIBLE|SVSI_FOCUSED; + bFirst=false; + } + } + pView->SelectItem(child,flags); + } + ILFree(child); + } + } + } + } +} + +void CBandWindow::SendShellTabCommand( int command ) +{ + // sends a command to the ShellTabWindowClass window + for (CWindow parent=GetParent();parent.m_hWnd;parent=parent.GetParent()) + { + // find a parent window with class ShellTabWindowClass + wchar_t name[256]; + GetClassName(parent.m_hWnd,name,_countof(name)); + if (_wcsicmp(name,L"ShellTabWindowClass")==0) + { + parent.SendMessage(WM_COMMAND,command); + break; + } + } +} + +void CBandWindow::ExecuteCustomCommand( const wchar_t *pCommand ) +{ + wchar_t buf[2048]; + Strcpy(buf,_countof(buf),pCommand); + // expand environment variables + DoEnvironmentSubst(buf,_countof(buf)); + wchar_t *pBuf=buf; + bool bArg1=wcsstr(buf,L"%1")!=NULL; + bool bArg2=wcsstr(buf,L"%2")!=NULL; + bool bArg3=wcsstr(buf,L"%3")!=NULL; + bool bArg4=wcsstr(buf,L"%4")!=NULL; + bool bArg5=wcsstr(buf,L"%5")!=NULL; + wchar_t path[_MAX_PATH]; + wchar_t file[_MAX_PATH]; + wchar_t input[_MAX_PATH]; + wchar_t output[_MAX_PATH]; + wchar_t temp[_MAX_PATH]; + path[0]=file[0]=input[0]=output[0]=temp[0]=0; + + CComPtr pView; + if (SUCCEEDED(m_pBrowser->QueryActiveShellView(&pView))) + { + CComPtr pFolder; + CAbsolutePidl pidl; + CComQIPtr pView2=pView; + if (pView2 && SUCCEEDED(pView2->GetFolder(IID_IPersistFolder2,(void**)&pFolder)) && SUCCEEDED(pFolder->GetCurFolder(&pidl))) + { + // get current path + GetPidlPath(pidl,path); + if (bArg2) + { + CComPtr pEnum; + int count; + // if only one file is selected get the file name (%2) + if (SUCCEEDED(pView2->ItemCount(SVGIO_SELECTION,&count)) && count==1 && SUCCEEDED(pView2->Items(SVGIO_SELECTION,IID_IEnumIDList,(void**)&pEnum)) && pEnum) + { + PITEMID_CHILD child; + if (pEnum->Next(1,&child,NULL)==S_OK) + { + CAbsolutePidl full; + full.Attach(ILCombine(pidl,child)); + SHGetPathFromIDList(full,file); + ILFree(child); + } + } + } + + if (bArg3 || bArg4) + { + GetTempPath(_countof(temp),temp); + if (GetTempFileName(temp,L"cei",0,input)) + { + // create a text file with the selected files + FILE *f; + if (_wfopen_s(&f,input,L"wb")==0 && f) + { + CComPtr pEnum; + if (SUCCEEDED(pView2->Items(SVGIO_SELECTION,IID_IEnumIDList,(void**)&pEnum)) && pEnum) + { + PITEMID_CHILD child; + while (pEnum->Next(1,&child,NULL)==S_OK) + { + wchar_t fname[_MAX_PATH]; + CAbsolutePidl full; + full.Attach(ILCombine(pidl,child)); + SHGetPathFromIDList(full,fname); + ILFree(child); + if (bArg3) + { + char fnameA[_MAX_PATH]; + WcsToMbs(fnameA,_countof(fnameA),fname); + fprintf_s(f,"%s\r\n",fnameA); + } + else + { + fwprintf_s(f,L"%s\r\n",fname); + } + } + } + fclose(f); + } + else + { + input[0]=0; + bArg3=false; + bArg4=false; + } + } + else + { + input[0]=0; + bArg3=false; + bArg4=false; + } + } + } + + if (bArg5) + { + if (!temp[0]) GetTempPath(_countof(temp),temp); + if (GetTempFileName(temp,L"ceo",0,output)) + { + FILE *f; + if (_wfopen_s(&f,output,L"wb")==0 && f) + { + fclose(f); + } + else + { + output[0]=0; + bArg5=false; + } + } + else + { + output[0]=0; + bArg5=false; + } + } + if (bArg1 || bArg2 || bArg3 || bArg4 || bArg5) + { + // expand %1, %2, %3, %4, %5 + DWORD_PTR args[100]={(DWORD_PTR)path,(DWORD_PTR)file,(DWORD_PTR)input,(DWORD_PTR)input,(DWORD_PTR)output}; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_ARGUMENT_ARRAY|FORMAT_MESSAGE_FROM_STRING,buf,0,0,(LPWSTR)&pBuf,0,(va_list*)args); + } + + wchar_t exe[_MAX_PATH]; + const wchar_t *params=SeparateArguments(pBuf,exe); + if (_wcsicmp(exe,L"open")==0) + { + CAbsolutePidl pidl; + if (m_pBrowser && SUCCEEDED(ShParseDisplayName((LPWSTR)params,&pidl,0,NULL))) + { + UINT flags=(GetKeyState(VK_CONTROL)<0?SBSP_NEWBROWSER:SBSP_SAMEBROWSER); + m_pBrowser->BrowseObject(pidl,flags|SBSP_ABSOLUTE); + } + } + else if (_wcsicmp(exe,L"sortby")==0) + { + CComQIPtr pView2=pView; + if (pView2) + ViewByProperty(pView2,params,false); + } + else if (_wcsicmp(exe,L"groupby")==0) + { + CComQIPtr pView2=pView; + if (pView2) + ViewByProperty(pView2,params,true); + } + else if (bArg3 || bArg4 || bArg5) + { + // create a process instead of using ShellExecute + STARTUPINFO startupInfo={sizeof(startupInfo)}; + PROCESS_INFORMATION processInfo; + memset(&processInfo,0,sizeof(processInfo)); + DWORD flags=CREATE_NO_WINDOW; + if (CreateProcess(exe,pBuf,NULL,NULL,TRUE,flags,NULL,*path?path:NULL,&startupInfo,&processInfo)) + { + CloseHandle(processInfo.hThread); + if (bArg5) + { + // wait for the process to finish so we can parse the output file + WaitForSingleObject(processInfo.hProcess,INFINITE); + } + CloseHandle(processInfo.hProcess); + } + if (bArg5) + { + // process output + FILE *f; + if (_wfopen_s(&f,output,L"rb")==0 && f) + { + // load output file + fseek(f,0,SEEK_END); + int size=ftell(f); + fseek(f,0,SEEK_SET); + std::vector text(size+2); + if (fread(&text[0],1,size,f)!=size) + text.clear(); + fclose(f); + if (!text.empty()) + { + text[size]=0; + text[size+1]=0; + std::vector textW; + if (size>=2 && text[0]==0xFF && text[1]==0xFE) + ExecuteCommandFile((wchar_t*)&text[2]); + else + { + int len=MbsToWcs(NULL,0,(char*)&text[0]); + textW.resize(len+1); + MbsToWcs(&textW[0],len+1,(char*)&text[0]); + ExecuteCommandFile(&textW[0]); + } + } + } + DeleteFile(output); + } + } + else + { + // simply execute + ShellExecute(NULL,NULL,exe,params,path,SW_SHOWNORMAL); + } + if (pBuf!=buf) + LocalFree(pBuf); + } +} + +void CBandWindow::ViewByProperty( IFolderView2 *pView, const wchar_t *pProperty, bool bGroup ) +{ + SORTCOLUMN column={0}; + column.direction=SORT_ASCENDING; + if (pProperty) + { + if (pProperty[0]=='-') + { + column.direction=SORT_DESCENDING; + pProperty++; + } + if (_wcsicmp(pProperty,L"name")==0) + column.propkey=PKEY_ItemNameDisplay; + else if (_wcsicmp(pProperty,L"type")==0) + column.propkey=PKEY_ItemTypeText; + else if (_wcsicmp(pProperty,L"size")==0) + column.propkey=PKEY_Size; + else if (_wcsicmp(pProperty,L"date")==0) + column.propkey=PKEY_DateModified; + else + { + wchar_t token[256]; + pProperty=GetToken(pProperty,token,_countof(token),L" ,"); + if (IIDFromString(token,&column.propkey.fmtid)!=S_OK) + return; + pProperty=GetToken(pProperty,token,_countof(token),L" ,"); + column.propkey.pid=_wtol(token); + } + } + + if (bGroup) + { + PROPERTYKEY prop; + BOOL ascending; + if (pProperty && SUCCEEDED(pView->GetGroupBy(&prop,&ascending))) + { + if (prop==column.propkey && ascending) + column.direction=SORT_DESCENDING; + } + pView->SetGroupBy(column.propkey,column.direction==SORT_ASCENDING); + } + else + { + int count; + if (pProperty && SUCCEEDED(pView->GetSortColumnCount(&count)) && count>0) + { + std::vector columns(count); + if (SUCCEEDED(pView->GetSortColumns(&columns[0],count))) + { + if (columns[0].propkey==column.propkey) + column.direction=-columns[0].direction; + } + } + pView->SetSortColumns(&column,1); + } +} + +LRESULT CBandWindow::OnUpdateButtons( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (!m_Buttons.empty() && m_Toolbar.SendMessage(TB_BUTTONCOUNT)==0) + m_Toolbar.SendMessage(TB_ADDBUTTONS,(WPARAM)m_Buttons.size(),(LPARAM)&m_Buttons[0]); + return 0; +} + +LRESULT CBandWindow::OnUpdateToolbar( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + UpdateToolbar(); + return 0; +} + +static BOOL CALLBACK RefreshExplorerWindows( HWND hwnd, LPARAM lParam ) +{ + wchar_t className[256]; + if (GetClassName(hwnd,className,_countof(className))) + { + if (_wcsicmp(className,L"CabinetWClass")==0 || _wcsicmp(className,L"Progman")==0) + PostMessage(hwnd,WM_COMMAND,41504,0); // post refresh command + } + return TRUE; +} + +static bool ToggleExplorerSetting( const wchar_t *setting, DWORD off, DWORD on ) +{ + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",KEY_READ|KEY_WRITE|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + DWORD val=off; + if (regKey.QueryDWORDValue(setting,val)!=ERROR_SUCCESS) + val=off; + regKey.SetDWORDValue(setting,val==on?off:on); + + EnumWindows(RefreshExplorerWindows,0); + return val==off; + } + return false; +} + +// Executes a cut/copy/paste/delete command +LRESULT CBandWindow::OnCommand( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + int idx=LOWORD(wParam)-1; + int id=m_Items[idx].id; + if (id>=ID_CUSTOM) + { + if (m_Items[idx].command) + { + ExecuteCustomCommand(m_Items[idx].command); + } + else if (m_Items[idx].link) + { + wchar_t path[_MAX_PATH]; + Strcpy(path,_countof(path),m_Items[idx].link); + DoEnvironmentSubst(path,_countof(path)); + CAbsolutePidl pidl; + if (m_pBrowser && SUCCEEDED(ShParseDisplayName(path,&pidl,0,NULL))) + { + UINT flags=(GetKeyState(VK_CONTROL)<0?SBSP_NEWBROWSER:SBSP_SAMEBROWSER); + m_pBrowser->BrowseObject(pidl,flags|SBSP_ABSOLUTE); + } + } + + return TRUE; + } + + if (id==ID_SETTINGS) + { +#ifndef BUILD_SETUP + if (GetKeyState(VK_SHIFT)<0) + *(int*)0=0; // force a crash if Shift is pressed. Makes it easy to restart explorer.exe +#endif + EditSettings(); + return TRUE; + } + + if (id==ID_GOUP || id==ID_GOBACK || id==ID_GOFORWARD) + { + if (m_pBrowser) + { + UINT flags=(GetKeyState(VK_CONTROL)<0?SBSP_NEWBROWSER:SBSP_SAMEBROWSER); + if (id==ID_GOUP) + m_pBrowser->BrowseObject(NULL,flags|SBSP_PARENT); + if (id==ID_GOBACK) + m_pBrowser->BrowseObject(NULL,flags|SBSP_NAVIGATEBACK); + if (id==ID_GOFORWARD) + m_pBrowser->BrowseObject(NULL,flags|SBSP_NAVIGATEFORWARD); + } + return TRUE; + } + if (id==ID_EMAIL) + { + SendEmail(); + return TRUE; + } + if (id==ID_RENAME) + { + CComPtr pView; + if (SUCCEEDED(m_pBrowser->QueryActiveShellView(&pView))) + { + CComQIPtr pView2=pView; + if (pView2) pView2->DoRename(); + } + return TRUE; + } + if (id==ID_NEWFOLDER) + { + NewFolder(); + return TRUE; + } + if (id==ID_ZIPFOLDER) + { + SendToZip(); + return TRUE; + } + if (id==ID_NAVPANE) + { + if (m_pBrowserBag) + { + VARIANT val={VT_EMPTY}; + bool bNavPane=SUCCEEDED(m_pBrowserBag->Read(g_NavPaneVisible,&val,NULL)) && val.vt==VT_BOOL && val.boolVal; + VariantClear(&val); + val.vt=VT_BOOL; + val.boolVal=bNavPane?VARIANT_FALSE:VARIANT_TRUE; + m_pBrowserBag->Write(g_NavPaneVisible,&val); + } + return TRUE; + } + if (id==ID_DETAILSPANE) + { + if (m_pBrowserBag) + { + VARIANT val={VT_EMPTY}; + bool bNavPane=SUCCEEDED(m_pBrowserBag->Read(g_DetailsPaneVisible,&val,NULL)) && val.vt==VT_BOOL && val.boolVal; + VariantClear(&val); + val.vt=VT_BOOL; + val.boolVal=bNavPane?VARIANT_FALSE:VARIANT_TRUE; + m_pBrowserBag->Write(g_DetailsPaneVisible,&val); + } + return TRUE; + } + if (id==ID_PREVIEWPANE) + { + if (m_pBrowserBag) + { + VARIANT val={VT_EMPTY}; + bool bNavPane=SUCCEEDED(m_pBrowserBag->Read(g_PreviewPaneVisible,&val,NULL)) && val.vt==VT_BOOL && val.boolVal; + VariantClear(&val); + val.vt=VT_BOOL; + val.boolVal=bNavPane?VARIANT_FALSE:VARIANT_TRUE; + m_pBrowserBag->Write(g_PreviewPaneVisible,&val); + } + return TRUE; + } + if (id==ID_SHOW_EXTENSIONS) + { + CheckButton(ID_SHOW_EXTENSIONS,ToggleExplorerSetting(L"HideFileExt",1,0)); + return TRUE; + } + if (id==ID_HIDDEN_FILES) + { + CheckButton(ID_HIDDEN_FILES,ToggleExplorerSetting(L"Hidden",2,1)); + return TRUE; + } + if (id==ID_SYSTEM_FILES) + { + CheckButton(ID_SYSTEM_FILES,ToggleExplorerSetting(L"ShowSuperHidden",0,1)); + return TRUE; + } + + // check if the focus is on the tree side or on the list side + CWindow focus=GetFocus(); + wchar_t name[256]; + GetClassName(focus,name,_countof(name)); + CWindow parent=focus.GetParent(); + if (_wcsicmp(name,WC_TREEVIEW)==0) + { + // send these commands to the parent of the tree view + if (id==ID_CUT) + parent.SendMessage(WM_COMMAND,41025); + if (id==ID_COPY) + parent.SendMessage(WM_COMMAND,41026); + if (id==ID_PASTE) + parent.SendMessage(WM_COMMAND,41027); + if (id==ID_DELETE) + parent.SendMessage(WM_COMMAND,40995); + if (id==ID_PROPERTIES) + ShowTreeProperties(focus.m_hWnd); + } + else + { + GetClassName(parent,name,_countof(name)); + if (_wcsicmp(name,L"SHELLDLL_DefView")==0) + { + // send these commands to the SHELLDLL_DefView window + if (id==ID_CUT) + { + parent.SendMessage(WM_COMMAND,28696); + focus.InvalidateRect(NULL); + } + if (id==ID_COPY) + parent.SendMessage(WM_COMMAND,28697); + if (id==ID_PASTE) + parent.SendMessage(WM_COMMAND,28698); + if (id==ID_DELETE) + parent.SendMessage(WM_COMMAND,28689); + if (id==ID_PROPERTIES) + parent.SendMessage(WM_COMMAND,28691); + if (id==ID_COPYTO) + parent.SendMessage(WM_COMMAND,28702); + if (id==ID_MOVETO) + parent.SendMessage(WM_COMMAND,28703); + } + } + + if (id==ID_UNDO) + SendShellTabCommand(28699); + if (id==ID_REDO) + SendShellTabCommand(28704); + if (id==ID_PASTE_SHORTCUT) + parent.SendMessage(WM_COMMAND,28700); + if (id==ID_MAP_DRIVE) + SendShellTabCommand(41089); + if (id==ID_DISCONNECT) + SendShellTabCommand(41090); + if (id==ID_CUSTOMIZEFOLDER) + SendShellTabCommand(28722); + if (id==ID_FOLDEROPTIONS) + SendShellTabCommand(41251); + + if (id==ID_VIEW_TILES) + SendShellTabCommand(28748); + if (id==ID_VIEW_DETAILS) + SendShellTabCommand(28747); + if (id==ID_VIEW_LIST) + SendShellTabCommand(28753); + if (id==ID_VIEW_CONTENT) + SendShellTabCommand(28754); + if (id==ID_VIEW_ICONS1) + SendShellTabCommand(28752); + if (id==ID_VIEW_ICONS2) + SendShellTabCommand(28750); + if (id==ID_VIEW_ICONS3) + SendShellTabCommand(28751); + if (id==ID_VIEW_ICONS4) + SendShellTabCommand(28749); + + if (id==ID_SELECTALL || id==ID_INVERT || id==ID_DESELECT) + { + // handle selection commands the hard way (instead of sending commands with SendShellTabCommand). + // some folders don't support selection and they crash if they get selection commands + CComPtr pView; + if (FAILED(m_pBrowser->QueryActiveShellView(&pView))) + return TRUE; + + CComQIPtr pView2=pView; + if (!pView2) return TRUE; + + // ID_DESELECT + if (id==ID_DESELECT) + { + pView2->SelectItem(-1,SVSI_DESELECTOTHERS); + return TRUE; + } + + int count; + if (FAILED(pView2->ItemCount(SVGIO_ALLVIEW,&count))) + return TRUE; + + // ID_SELECTALL + if (id==ID_SELECTALL) + { + for (int i=0;iSelectItem(i,SVSI_SELECT); + return TRUE; + } + + // ID_INVERT + // we can't use IFolderView2::GetSelectedItem to enumerate the selected items. there is a bug in it on Windows 7. when called + // with 0 or 1 it returns 0 for the next item, causing an infinite loop. we have to use Item + GetSelectionState instead. + // it allocates a PIDLs, so it is not ideal, but what can you do. stupid bugs + for (int i=0;iItem(i,&child)) && child) + { + DWORD state; + if (SUCCEEDED(pView2->GetSelectionState(child,&state))) + pView2->SelectItem(i,(state&SVSI_SELECT)?SVSI_DESELECT:SVSI_SELECT); + ILFree(child); + } + } + return TRUE; + } + if (id==ID_REFRESH) + SendShellTabCommand(41504); + if (id==ID_STOP && m_pWebBrowser) + m_pWebBrowser->Stop(); + + return TRUE; +} + +LRESULT CBandWindow::OnRClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMMOUSE *pInfo=(NMMOUSE*)pnmh; + POINT pt=pInfo->pt; + { + RECT rc; + int count=(int)m_Toolbar.SendMessage(TB_BUTTONCOUNT); + m_Toolbar.SendMessage(TB_GETITEMRECT,count-1,(LPARAM)&rc); + if (pt.x>rc.right) + return 0; + } + m_Toolbar.ClientToScreen(&pt); + ShowSettingsMenu(m_hWnd,pt.x,pt.y); + return 1; +} + +LRESULT CBandWindow::OnGetInfoTip( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMTBGETINFOTIP *pTip=(NMTBGETINFOTIP*)pnmh; + const StdToolbarItem &item=m_Items[pTip->lParam]; + if (item.tip && _wcsicmp(item.tip,L"none")!=0) + { + // show the tip for the standard item + Strcpy(pTip->pszText,pTip->cchTextMax,item.tip); + } + return 0; +} + +// Callback for IShellMenu. Executes the selected command +class CMenuCallback: public IShellMenuCallback +{ +public: + CMenuCallback( IShellBrowser *pBrowser ) { m_bExecuted=false; m_pBrowser=pBrowser; } + + virtual HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void **ppvObject ); + virtual ULONG STDMETHODCALLTYPE AddRef( void ) { return 1; } + virtual ULONG STDMETHODCALLTYPE Release( void ) { return 1; } + STDMETHOD(CallbackSM)( LPSMDATA psmd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + +private: + bool m_bExecuted; + IShellBrowser *m_pBrowser; +}; + +HRESULT STDMETHODCALLTYPE CMenuCallback::QueryInterface( REFIID riid, void **ppvObject ) +{ + if (riid==IID_IUnknown || riid==IID_IShellMenuCallback) + { + *ppvObject=this; + return S_OK; + } + else + { + *ppvObject=NULL; + return E_NOINTERFACE; + } +} + +HRESULT STDMETHODCALLTYPE CMenuCallback::CallbackSM( LPSMDATA psmd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + switch(uMsg) + { + case SMC_GETINFO: + { + SMINFO *pSmInfo=(SMINFO*)lParam; + + if (pSmInfo->dwMask&SMIM_FLAGS) + pSmInfo->dwFlags|=SMIF_DROPCASCADE|SMIF_TRACKPOPUP; + + if (pSmInfo->dwMask&SMIM_ICON) + pSmInfo->iIcon=-1; + } + return S_OK; + + case SMC_SFEXEC: + { + if (m_bExecuted) + return S_OK; + m_bExecuted=true; + SFGAOF flags=SFGAO_FOLDER|SFGAO_LINK; + + if (SUCCEEDED(psmd->psf->GetAttributesOf(1,&psmd->pidlItem,&flags))) + { + CAbsolutePidl pidl; + if (flags&SFGAO_LINK) + { + flags=0; + // resolve link + CComPtr pLink; + if (SUCCEEDED(psmd->psf->GetUIObjectOf(NULL,1,&psmd->pidlItem,IID_IShellLink,NULL,(void**)&pLink)) && pLink) + pLink->GetIDList(&pidl); + if (pidl) + { + CComPtr pFolder; + PCUITEMID_CHILD child; + SHBindToParent(pidl,IID_IShellFolder,(void**)&pFolder,&child); + SFGAOF flags2=SFGAO_FOLDER; + if (pFolder && SUCCEEDED(pFolder->GetAttributesOf(1,&child,&flags2)) && (flags2&SFGAO_FOLDER)) + flags=SFGAO_FOLDER; + else + pidl.Clear(); + } + } + + if (!pidl) + pidl.Attach(ILCombine(psmd->pidlFolder,psmd->pidlItem)); + + if (flags&SFGAO_FOLDER) + { + // navigate to folder + if (m_pBrowser) + { + UINT flags=(GetKeyState(VK_CONTROL)<0?SBSP_NEWBROWSER:SBSP_SAMEBROWSER); + m_pBrowser->BrowseObject(pidl,flags); + } + } + else + { + // execute file + SHELLEXECUTEINFO execute={sizeof(execute),SEE_MASK_IDLIST|SEE_MASK_FLAG_LOG_USAGE}; + execute.lpIDList=pidl; + execute.nShow=SW_SHOWNORMAL; + ShellExecuteEx(&execute); + } + } + return S_OK; + } + + case SMC_PROMOTE: + case SMC_EXITMENU: + case SMC_GETSFINFO: + case SMC_SFSELECTITEM: + case SMC_REFRESH: + case SMC_DEMOTE: + case SMC_DEFAULTICON: + case SMC_NEWITEM: + case SMC_CHEVRONEXPAND: + case SMC_DISPLAYCHEVRONTIP: + case SMC_SETSFOBJECT: + case SMC_SHCHANGENOTIFY: + case SMC_CHEVRONGETTIP: + case SMC_SFDDRESTRICTED: + return S_OK; + + default: + return S_FALSE; + } +} + +LRESULT CBandWindow::OnDropDown( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMTOOLBAR *pButton=(NMTOOLBAR*)pnmh; + int idx=0; + const StdToolbarItem *pItem=NULL; + for (std::vector::const_iterator it=m_Items.begin();it->id!=ID_LAST;++it,idx++) + { + RECT rc; + if (m_Toolbar.SendMessage(TB_GETITEMRECT,idx,(LPARAM)&rc) && memcmp(&rc,&pButton->rcButton,sizeof(RECT))==0) + { + pItem=&*it; + break; + } + } + if (pItem && (pItem->submenu || pItem->link)) + { + if (pItem->submenu) + { + TPMPARAMS params={sizeof(params),pButton->rcButton}; + m_Toolbar.ClientToScreen(¶ms.rcExclude); // must not use MapWindowPoints because it produces wrong results in RTL cases + HMENU menu=CreateDropMenu(pItem->submenu); + int res=TrackPopupMenuEx(menu,TPM_RETURNCMD|TPM_VERTICAL,params.rcExclude.left,params.rcExclude.bottom,m_hWnd,¶ms); + DestroyMenu(menu); + if (res>0) + PostMessage(WM_COMMAND,res); + } + else if (pItem->link) + { + TPMPARAMS params={sizeof(params),pButton->rcButton}; + m_Toolbar.MapWindowPoints(NULL,¶ms.rcExclude); // must use MapWindowPoints to handle RTL correctly + + CAbsolutePidl pidl; + CComPtr pFolder; + wchar_t buf[1024]; + Strcpy(buf,_countof(buf),pItem->link); + DoEnvironmentSubst(buf,_countof(buf)); + if (SUCCEEDED(ShParseDisplayName(buf,&pidl,0,NULL))) + SHBindToObject(NULL,pidl,NULL,IID_IShellFolder,(void **)&pFolder); + if (pFolder) + { + HRESULT hr; + CComPtr pMenu; + + CoCreateInstance(CLSID_TrackShellMenu,NULL,CLSCTX_INPROC_SERVER,IID_ITrackShellMenu,(void**)&pMenu); + + if (pMenu) + { + CMenuCallback callback(m_pBrowser); + hr=pMenu->Initialize(&callback,-1,ANCESTORDEFAULT,SMINIT_TOPLEVEL|SMINIT_VERTICAL|SMINIT_RESTRICT_DRAGDROP); + if (SUCCEEDED(hr)) + { + CRegKey cRegOrder; + + CComString pFavs; + SHGetKnownFolderPath(FOLDERID_Favorites,0,NULL,&pFavs); + if (pFavs && SUCCEEDED(SHGetPathFromIDList(pidl,buf))) + { + // must compare strings and not pidls. sometimes pidls can be different but point to the same folder + pFavs.MakeUpper(); + CharUpper(buf); + if (wcscmp(pFavs,buf)==0) + cRegOrder.Open(HKEY_CURRENT_USER,_T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MenuOrder\\Favorites")); + } + + hr=pMenu->SetShellFolder(pFolder,pidl,cRegOrder.m_hKey,SMSET_BOTTOM|0x00000008); // SMSET_USEBKICONEXTRACTION=0x00000008 + if (SUCCEEDED(hr)) + { + cRegOrder.Detach(); + POINTL ptl={params.rcExclude.left,params.rcExclude.bottom}; + RECTL rcl={params.rcExclude.left,params.rcExclude.top,params.rcExclude.right,params.rcExclude.bottom}; + pMenu->Popup(GetAncestor(m_hWnd,GA_ROOT),&ptl,&rcl,MPPF_SETFOCUS|MPPF_BOTTOM); + } + } + } + } + } + + // remove the next mouse click if it is on the same button + MSG msg; + RECT rc=pButton->rcButton; + m_Toolbar.ClientToScreen(&rc); + if (PeekMessage(&msg,NULL,WM_LBUTTONDOWN,WM_LBUTTONDBLCLK,PM_NOREMOVE) && PtInRect(&rc,msg.pt)) + PeekMessage(&msg,NULL,WM_LBUTTONDOWN,WM_LBUTTONDBLCLK,PM_REMOVE); + } + return TBDDRET_DEFAULT; +} + +LRESULT CBandWindow::OnChevron( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMREBARCHEVRON *pChevron=(NMREBARCHEVRON*)pnmh; + REBARBANDINFO info={sizeof(info),RBBIM_CHILD}; + if (::SendMessage(pnmh->hwndFrom,RB_GETBANDINFO,pChevron->uBand,(LPARAM)&info) && info.hwndChild==m_Toolbar.m_hWnd) + { + RECT clientRect; + m_Toolbar.GetClientRect(&clientRect); + int idx=0; + for (std::vector::const_iterator it=m_Items.begin();it->id!=ID_LAST;++it,idx++) + { + RECT rc; + m_Toolbar.SendMessage(TB_GETITEMRECT,idx,(LPARAM)&rc); + if (rc.right>clientRect.right) + break; + } + while (m_Items[idx].id==ID_SEPARATOR) + idx++; + if (m_Items[idx].id==ID_LAST) return 1; + HMENU menu=CreateDropMenu(&m_Items[idx]); + TPMPARAMS params={sizeof(params),pChevron->rc}; + // use ClientToScreen instead of MapWindowPoints because it works better in RTL mode + ::ClientToScreen(pnmh->hwndFrom,(POINT*)¶ms.rcExclude); + ::ClientToScreen(pnmh->hwndFrom,((POINT*)¶ms.rcExclude)+1); + int res=TrackPopupMenuEx(menu,TPM_RETURNCMD|TPM_VERTICAL,params.rcExclude.left,params.rcExclude.bottom,m_hWnd,¶ms); + DestroyMenu(menu); + + if (res>0) + PostMessage(WM_COMMAND,res); + + // remove the next mouse click if it is on the chevron + MSG msg; + if (PeekMessage(&msg,NULL,WM_LBUTTONDOWN,WM_LBUTTONDBLCLK,PM_NOREMOVE) && PtInRect(¶ms.rcExclude,msg.pt)) + PeekMessage(&msg,NULL,WM_LBUTTONDOWN,WM_LBUTTONDBLCLK,PM_REMOVE); + + return 1; + } + return 0; +} + +HMENU CBandWindow::CreateDropMenu( const StdToolbarItem *pItem ) +{ + HMODULE hShell32=GetModuleHandle(L"Shell32.dll"); + std::vector modules; + HMENU menu=CreateDropMenuRec(pItem,modules,hShell32); + for (std::vector::const_iterator it=modules.begin();it!=modules.end();++it) + FreeLibrary(*it); + MENUINFO info={sizeof(info),MIM_STYLE,MNS_CHECKORBMP}; + SetMenuInfo(menu,&info); + return menu; +} + +HMENU CBandWindow::CreateDropMenuRec( const StdToolbarItem *pItem, std::vector &modules, HMODULE hShell32 ) +{ + HMENU menu=CreatePopupMenu(); + for (int idx=0;pItem->id!=ID_LAST;pItem++,idx++) + { + if (pItem->id==ID_SEPARATOR) + { + AppendMenu(menu,MF_SEPARATOR,0,0); + continue; + } + const wchar_t *name=pItem->label; + if (!name && pItem->tip && _wcsicmp(pItem->tip,L"none")!=0) + name=pItem->tip; + + if (!pItem->bIconLoaded) + { + pItem->bIconLoaded=true; + if (m_MenuIconSize>0) + { + if (pItem->iconPath) + { + if (_wcsicmp(pItem->iconPath,L"NONE")!=0) + { + HICON hIcon=LoadIcon(m_MenuIconSize,pItem->iconPath,modules); + if (!hIcon) + hIcon=(HICON)LoadImage(hShell32,MAKEINTRESOURCE(1),IMAGE_ICON,m_MenuIconSize,m_MenuIconSize,LR_DEFAULTCOLOR); + if (hIcon) + { + HICON hIcon2=pItem->iconPathD?LoadIcon(m_MenuIconSize,pItem->iconPathD,modules):NULL; + if (!hIcon2) + hIcon2=CreateDisabledIcon(hIcon,m_MenuIconSize); + pItem->menuIcon=BitmapFromIcon(hIcon,m_MenuIconSize,NULL,true); + pItem->menuIconD=BitmapFromIcon(hIcon2,m_MenuIconSize,NULL,true); + } + } + } + else if (pItem->link) + { + HICON hIcon=NULL; + CAbsolutePidl pidl; + wchar_t path[_MAX_PATH]; + Strcpy(path,_countof(path),pItem->link); + DoEnvironmentSubst(path,_countof(path)); + if (SUCCEEDED(ShParseDisplayName(path,&pidl,0,NULL))) + { + if (!name) + { + CComString pName; + if (SUCCEEDED(SHGetNameFromIDList(pidl,SIGDN_PARENTRELATIVEEDITING,&pName)) && pName) + { + pItem->menuText=pName; + } + } + hIcon=LoadIcon(m_MenuIconSize,pidl); + } + if (hIcon) + { + HICON hIcon2=pItem->iconPathD?LoadIcon(m_MenuIconSize,pItem->iconPathD,modules):NULL; + if (!hIcon2) + hIcon2=CreateDisabledIcon(hIcon,m_MenuIconSize); + pItem->menuIcon=BitmapFromIcon(hIcon,m_MenuIconSize,NULL,true); + pItem->menuIconD=BitmapFromIcon(hIcon2,m_MenuIconSize,NULL,true); + } + } + } + } + + if (!name) name=pItem->menuText; + + if (pItem->submenu) + { + HMENU menu2=CreateDropMenu(pItem->submenu); + AppendMenu(menu,MF_POPUP,(UINT_PTR)menu2,name); + } + else + { + int cmd=(int)(pItem-&m_Items[0]+1); + AppendMenu(menu,MF_STRING,cmd,name); + } + + if (pItem->menuIcon) + { + MENUITEMINFO mii={sizeof(mii)}; + mii.fMask=MIIM_BITMAP; + mii.hbmpItem=pItem->bDisabled?pItem->menuIconD:pItem->menuIcon; + SetMenuItemInfo(menu,idx,TRUE,&mii); + } + + if (pItem->bDisabled) + EnableMenuItem(menu,idx,MF_BYPOSITION|MF_GRAYED); + if (pItem->bChecked) + CheckMenuItem(menu,idx,MF_BYPOSITION|MF_CHECKED); + } + return menu; +} + +void CBandWindow::UpdateToolbar( void ) +{ + // disable the Up button if we are at the top level + bool bDesktop=false; + bool bNavPane=true; + bool bDisableNavPane=false; + bool bDetailsPane=true; + bool bDisableDetailsPane=false; + bool bPreviewPane=true; + bool bDisablePreviewPane=false; + if (m_pBrowser) + { + CComPtr pView; + m_pBrowser->QueryActiveShellView(&pView); + if (pView) + { + CComQIPtr pView2=pView; + if (pView2) + { + CComPtr pFolder; + pView2->GetFolder(IID_IPersistFolder2,(void**)&pFolder); + if (pFolder) + { + CAbsolutePidl pidl; + if (SUCCEEDED(pFolder->GetCurFolder(&pidl)) && pidl) + { + if (ILIsEmpty(pidl)) + bDesktop=true; // only the top level has empty PIDL + } + } + + if (m_pBrowserBag) + { + if (GetWinVersion()>=WIN_VER_WIN8) + { + VARIANT val={VT_EMPTY}; + if (SUCCEEDED(m_pBrowserBag->Read(g_ComboPaneEnabled,&val,NULL)) && val.vt==VT_BOOL && !val.boolVal) + { + bDisableDetailsPane=true; + bDetailsPane=false; + bDisablePreviewPane=true; + bPreviewPane=false; + } + VariantClear(&val); + } + else + { + VARIANT val={VT_EMPTY}; + if (SUCCEEDED(m_pBrowserBag->Read(g_DetailsPaneEnabled,&val,NULL)) && val.vt==VT_BOOL && !val.boolVal) + { + bDisableDetailsPane=true; + bDetailsPane=false; + } + VariantClear(&val); + if (SUCCEEDED(m_pBrowserBag->Read(g_PreviewPaneEnabled,&val,NULL)) && val.vt==VT_BOOL && !val.boolVal) + { + bDisablePreviewPane=true; + bPreviewPane=false; + } + VariantClear(&val); + } + CComPtr pVisibility; + if (SUCCEEDED(pView2->GetFolder(IID_IExplorerPaneVisibility,(void**)&pVisibility)) && pVisibility) + { + EXPLORERPANESTATE state=0; + if (SUCCEEDED(pVisibility->GetPaneState(EP_NavPane,&state))) + { + bDisableNavPane=(state&EPS_FORCE)!=0; + if (bDisableNavPane) + bNavPane=!(state&EPS_DEFAULT_OFF); + } + if (!bDisableDetailsPane) + { + state=0; + if (SUCCEEDED(pVisibility->GetPaneState(EP_DetailsPane,&state))) + { + bDisableDetailsPane=(state&EPS_FORCE)!=0; + if (bDisableDetailsPane) + bDetailsPane=!(state&EPS_DEFAULT_OFF); + } + } + if (!bDisablePreviewPane) + { + state=0; + if (SUCCEEDED(pVisibility->GetPaneState(EP_PreviewPane,&state))) + { + bDisablePreviewPane=(state&EPS_FORCE)!=0; + if (bDisablePreviewPane) + bPreviewPane=!(state&EPS_DEFAULT_OFF); + } + } + } + } + } + } + + if (m_pBrowserBag) + { + if (!bDisableNavPane) + { + VARIANT val={VT_EMPTY}; + bNavPane=SUCCEEDED(m_pBrowserBag->Read(g_NavPaneVisible,&val,NULL)) && val.vt==VT_BOOL && val.boolVal; + VariantClear(&val); + } + if (!bDisableDetailsPane) + { + VARIANT val={VT_EMPTY}; + bDetailsPane=SUCCEEDED(m_pBrowserBag->Read(g_DetailsPaneVisible,&val,NULL)) && val.vt==VT_BOOL && val.boolVal; + VariantClear(&val); + } + if (!bDisablePreviewPane) + { + VARIANT val={VT_EMPTY}; + bPreviewPane=SUCCEEDED(m_pBrowserBag->Read(g_PreviewPaneVisible,&val,NULL)) && val.vt==VT_BOOL && val.boolVal; + VariantClear(&val); + } + } + } + EnableButton(ID_GOUP,!bDesktop); + if (m_pBrowserBag) + { + EnableButton(ID_NAVPANE,!bDisableNavPane); + CheckButton(ID_NAVPANE,bNavPane); + EnableButton(ID_DETAILSPANE,!bDisableDetailsPane); + CheckButton(ID_DETAILSPANE,bDetailsPane); + EnableButton(ID_PREVIEWPANE,!bDisablePreviewPane); + CheckButton(ID_PREVIEWPANE,bPreviewPane); + } + + if (HasFolderSettings()) + UpdateFolderSettings(); +} + +void CBandWindow::UpdateFolderSettings( void ) +{ + bool bExtensions=false, bHidden=false, bSystem=false; + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + DWORD val; + if (regKey.QueryDWORDValue(L"HideFileExt",val)==ERROR_SUCCESS) + bExtensions=(val!=1); + if (regKey.QueryDWORDValue(L"Hidden",val)==ERROR_SUCCESS) + bHidden=(val==1); + if (regKey.QueryDWORDValue(L"ShowSuperHidden",val)==ERROR_SUCCESS) + bSystem=(val==1); + } + CheckButton(ID_SHOW_EXTENSIONS,bExtensions); + CheckButton(ID_HIDDEN_FILES,bHidden); + CheckButton(ID_SYSTEM_FILES,bSystem); +} + +void CBandWindow::EnableButton( int cmd, bool bEnable ) +{ + bool bMain=true; + bool bDisabled=!bEnable; + for (int idx=0;idx<(int)m_Items.size();idx++) + { + if (m_Items[idx].id==ID_LAST) + bMain=false; + if (m_Items[idx].id==cmd && m_Items[idx].bDisabled!=bDisabled) + { + m_Items[idx].bDisabled=bDisabled; + if (bMain) + m_Toolbar.SendMessage(TB_ENABLEBUTTON,idx+1,bDisabled?0:1); + } + } +} + +void CBandWindow::CheckButton( int cmd, bool bCheck ) +{ + bool bMain=true; + for (int idx=0;idx<(int)m_Items.size();idx++) + { + if (m_Items[idx].id==ID_LAST) + bMain=false; + if (m_Items[idx].id==cmd && m_Items[idx].bChecked!=bCheck) + { + m_Items[idx].bChecked=bCheck; + if (bMain) + m_Toolbar.SendMessage(TB_CHECKBUTTON,idx+1,bCheck?1:0); + } + } +} + +bool CBandWindow::HasPanes( void ) const +{ + for (int idx=0;idx<(int)m_Items.size();idx++) + { + if (m_Items[idx].id==ID_NAVPANE || m_Items[idx].id==ID_DETAILSPANE || m_Items[idx].id==ID_PREVIEWPANE) + return true; + } + return false; +} + +bool CBandWindow::HasFolderSettings( void ) const +{ + for (int idx=0;idx<(int)m_Items.size();idx++) + { + if (m_Items[idx].id==ID_SHOW_EXTENSIONS || m_Items[idx].id==ID_HIDDEN_FILES || m_Items[idx].id==ID_SYSTEM_FILES) + return true; + } + return false; +} + +void CBandWindow::UpdateBag( void ) +{ + if (!m_pBrowserBag) + { + CComPtr pFrame; + IUnknown_QueryService(m_pBrowser,SID_FrameManager,IID_IUnknown,(void**)&pFrame); + IUnknown_QueryService(pFrame,SID_PerBrowserPropertyBag,IID_IPropertyBag,(void**)&m_pBrowserBag); + if (m_pBrowserBag) + { + void **vtbl=*(void***)m_pBrowserBag.p+4; + if (InterlockedCompareExchangePointer((void**)&g_OldBagWrite,*vtbl,0)==0) + { + DWORD oldProtect; + VirtualProtect(vtbl,sizeof(void*),PAGE_READWRITE,&oldProtect); + *vtbl=BagWriteHook; + VirtualProtect(vtbl,sizeof(void*),oldProtect,&oldProtect); + + // prevent the DLL from being unloaded after we mess with the vtable, otherwise bad things happen + HMODULE q; + GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,(const wchar_t*)g_Instance,&q); + } + } + } + PostMessage(BWM_UPDATETOOLBAR); +} + +HRESULT __stdcall CBandWindow::BagWriteHook( IPropertyBag *pThis, LPCOLESTR pszPropName, VARIANT *pVar ) +{ + if (_wcsicmp(pszPropName,g_NavPaneVisible)==0 || + _wcsicmp(pszPropName,g_DetailsPaneVisible)==0 || + _wcsicmp(pszPropName,g_PreviewPaneVisible)==0 || + _wcsicmp(pszPropName,g_DetailsPaneEnabled)==0 || + _wcsicmp(pszPropName,g_PreviewPaneEnabled)==0 || + _wcsicmp(pszPropName,g_ComboPaneEnabled)==0 + ) + { + TlsData *pData=GetTlsData(); + if (pData && pData->band) + pData->band->m_BandWindow.PostMessage(BWM_UPDATETOOLBAR); + } + return g_OldBagWrite(pThis,pszPropName,pVar); +} + +void CBandWindow::Clear( void ) +{ + m_TreeParent=NULL; + m_pBrowser=NULL; + m_pWebBrowser=NULL; + m_pBrowserBag=NULL; +} + +void CBandWindow::SetBrowsers( IShellBrowser *pBrowser, IWebBrowser2 *pWebBrowser ) +{ + m_pBrowser=pBrowser; + m_pWebBrowser=pWebBrowser; + m_pBrowserBag=NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +// CExplorerBand - adds a toolbar band to Windows Explorer with 2 buttons - "Up" and "Settings" + +CExplorerBand::CExplorerBand( void ) +{ + m_bSubclassRebar=GetWinVersion()>=WIN_VER_WIN7; + m_bSubclassedRebar=false; + m_TopWindow=NULL; +} + +// Subclasses the rebar control on Windows 7. Makes sure the RBBS_BREAK style is properly set. Windows 7 has a bug +// that forces RBBS_BREAK for every rebar band +LRESULT CALLBACK CExplorerBand::RebarSubclassProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==RB_SETBANDINFO && ((CExplorerBand*)uIdSubclass)->m_bHandleSetInfo) + { + REBARBANDINFO *pInfo=(REBARBANDINFO*)lParam; + if ((pInfo->hwndChild==(HWND)dwRefData) && (pInfo->fMask&RBBIM_STYLE)) + { + if (((CExplorerBand*)uIdSubclass)->m_bBandNewLine) + pInfo->fStyle|=RBBS_BREAK; + else + pInfo->fStyle&=~RBBS_BREAK; + } + } + + if (uMsg==WM_CLEAR) + ((CExplorerBand*)uIdSubclass)->m_bHandleSetInfo=false; + + if (uMsg==RB_DELETEBAND) + { + int n=(int)SendMessage(hWnd,RB_GETBANDCOUNT,0,0); + CExplorerBand *pThis=(CExplorerBand*)uIdSubclass; + for (int i=0;im_bHandleSetInfo; + pThis->m_bHandleSetInfo=false; + SendMessage(hWnd,RB_SETBANDINFO,i,(LPARAM)&info); + pThis->m_bHandleSetInfo=old; + } + return res; + } + } + } + + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +// Subclasses the rebar's parent to catch RBN_CHEVRONPUSHED +LRESULT CALLBACK CExplorerBand::ParentSubclassProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_NOTIFY && ((NMHDR*)lParam)->code==RBN_CHEVRONPUSHED) + { + if (SendMessage((HWND)dwRefData,uMsg,wParam,lParam)) + return 0; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +// IDeskBand +STDMETHODIMP CExplorerBand::GetBandInfo( DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi ) +{ + // initializes the band + if (!m_bSubclassedRebar) + { + HWND rebar=GetParent(m_BandWindow.GetToolbar()); + wchar_t className[256]; + GetClassName(rebar,className,_countof(className)); + if (_wcsicmp(className,REBARCLASSNAME)==0) + { + if (m_bSubclassRebar) + { + CRegKey regSettings; + m_bBandNewLine=false; + if (regSettings.Open(HKEY_CURRENT_USER,GetSettingsRegPath())==ERROR_SUCCESS) + { + DWORD NewLine; + if (regSettings.QueryDWORDValue(L"NewLine",NewLine)==ERROR_SUCCESS) + m_bBandNewLine=NewLine!=0; + } + + SetWindowSubclass(rebar,RebarSubclassProc,(UINT_PTR)this,(DWORD_PTR)m_BandWindow.GetToolbar()); + } + SetWindowSubclass(GetParent(rebar),ParentSubclassProc,(UINT_PTR)this,(DWORD_PTR)m_BandWindow.m_hWnd); + m_bSubclassedRebar=true; + } + } + RECT rc; + SendMessage(m_BandWindow.GetToolbar(),TB_GETITEMRECT,0,(LPARAM)&rc); + int minSize=rc.right; + int count=(int)SendMessage(m_BandWindow.GetToolbar(),TB_BUTTONCOUNT,0,0); + SendMessage(m_BandWindow.GetToolbar(),TB_GETITEMRECT,count-1,(LPARAM)&rc); + bool bChevron=GetSettingBool(L"ResizeableToolbar"); + + if (pdbi) + { + if (pdbi->dwMask&DBIM_MINSIZE) + { + pdbi->ptMinSize.x=bChevron?minSize:rc.right; + pdbi->ptMinSize.y=rc.bottom; + } + if (pdbi->dwMask&DBIM_MAXSIZE) + { + pdbi->ptMaxSize.x=0; // ignored + pdbi->ptMaxSize.y=-1; // unlimited + } + if (pdbi->dwMask&DBIM_INTEGRAL) + { + pdbi->ptIntegral.x=0; // not sizeable + pdbi->ptIntegral.y=0; // not sizeable + } + if (pdbi->dwMask&DBIM_ACTUAL) + { + pdbi->ptActual.x=rc.right; + pdbi->ptActual.y=rc.bottom; + } + if (pdbi->dwMask&DBIM_TITLE) + { + *pdbi->wszTitle=0; // no title + } + if (pdbi->dwMask&DBIM_BKCOLOR) + { + //Use the default background color by removing this flag. + pdbi->dwMask&=~DBIM_BKCOLOR; + } + if (pdbi->dwMask&DBIM_MODEFLAGS) + { + if (bChevron) + pdbi->dwModeFlags|=DBIMF_USECHEVRON; + } + } + return S_OK; +} + +// IOleWindow +STDMETHODIMP CExplorerBand::GetWindow( HWND* phwnd ) +{ + if (!phwnd) + return E_INVALIDARG; + *phwnd=m_BandWindow.GetToolbar(); + return S_OK; +} + +STDMETHODIMP CExplorerBand::ContextSensitiveHelp( BOOL fEnterMode ) +{ + return S_OK; +} + +// IDockingWindow +STDMETHODIMP CExplorerBand::CloseDW( unsigned long dwReserved ) +{ + ShowDW(FALSE); + return S_OK; +} + +STDMETHODIMP CExplorerBand::ResizeBorderDW( const RECT* prcBorder, IUnknown* punkToolbarSite, BOOL fReserved ) +{ + // Not used by any band object. + return E_NOTIMPL; +} + +STDMETHODIMP CExplorerBand::ShowDW( BOOL fShow ) +{ + if (m_bSubclassRebar && m_bSubclassedRebar) + { + // on Windows 7 get the current RBBS_BREAK state and save it in the registry to be restored later + HWND rebar=GetParent(m_BandWindow.GetToolbar()); + m_bHandleSetInfo=true; + if (!fShow) + { + int n=(int)SendMessage(rebar,RB_GETBANDCOUNT,0,0); + for (int i=0;i::SetSite(pUnkSite); + + if (m_BandWindow.IsWindow()) + m_BandWindow.DestroyWindow(); + m_BandWindow.Clear(); + if (m_bSubclassedRebar) + { + HWND hwnd=GetParent(m_BandWindow.GetToolbar()); + if (m_bSubclassRebar) + RemoveWindowSubclass(hwnd,RebarSubclassProc,(UINT_PTR)this); + RemoveWindowSubclass(GetParent(hwnd),ParentSubclassProc,(UINT_PTR)this); + } + m_bSubclassedRebar=false; + m_bHandleSetInfo=true; + + if (m_pWebBrowser && m_dwEventCookie!=0xFEFEFEFE) + DispEventUnadvise(m_pWebBrowser,&DIID_DWebBrowserEvents2); + m_pWebBrowser=NULL; + + //If punkSite is not NULL, a new site is being set. + if (pUnkSite) + { + // hook + GetTlsData()->band=this; + + //Get the parent window. + HWND hWndParent=NULL; + + CComQIPtr pOleWindow=pUnkSite; + if (pOleWindow) + pOleWindow->GetWindow(&hWndParent); + + if (!IsWindow(hWndParent)) + return E_FAIL; + + m_TopWindow=GetAncestor(hWndParent,GA_ROOT); + if (!GetProp(m_TopWindow,g_LoadedSettingsAtom)) + { + SetProp(m_TopWindow,g_LoadedSettingsAtom,(HANDLE)1); + LoadSettings(); + } + + m_BandWindow.Create(hWndParent,NULL,NULL,WS_CHILD); + if (!m_BandWindow.IsWindow()) + return E_FAIL; + + CComQIPtr pProvider=pUnkSite; + + if (pProvider) + { + CComPtr pBrowser; + pProvider->QueryService(SID_SShellBrowser,IID_IShellBrowser,(void**)&pBrowser); + + // listen for web browser notifications. we only care about DISPID_NAVIGATECOMPLETE2 and DISPID_ONQUIT + pProvider->QueryService(SID_SWebBrowserApp,IID_IWebBrowser2,(void**)&m_pWebBrowser); + if (m_pWebBrowser) + { + if (m_dwEventCookie==0xFEFEFEFE) // ATL's event cookie is 0xFEFEFEFE when the sink is not advised + DispEventAdvise(m_pWebBrowser,&DIID_DWebBrowserEvents2); + } + m_BandWindow.SetBrowsers(pBrowser,m_pWebBrowser); + } + } + else + { + // unhook + GetTlsData()->band=NULL; + if (m_TopWindow) RemoveProp(m_TopWindow,g_LoadedSettingsAtom); + m_TopWindow=NULL; + } + return S_OK; +} + +STDMETHODIMP CExplorerBand::OnNavigateComplete( IDispatch *pDisp, VARIANT *URL ) +{ + // this is called when the current folder changes. disable the Up button if this is the desktop folder + m_BandWindow.UpdateToolbar(); + return S_OK; +} + +STDMETHODIMP CExplorerBand::OnCommandStateChange( long Command, VARIANT_BOOL Enable ) +{ + if (Command==CSC_NAVIGATEFORWARD) + { + m_BandWindow.EnableButton(CBandWindow::ID_GOFORWARD,Enable?true:false); + } + if (Command==CSC_NAVIGATEBACK) + { + m_BandWindow.EnableButton(CBandWindow::ID_GOBACK,Enable?true:false); + } + return S_OK; +} + +STDMETHODIMP CExplorerBand::OnQuit( void ) +{ + if (m_pWebBrowser && m_dwEventCookie!=0xFEFEFEFE) // ATL's event cookie is 0xFEFEFEFE, when the sink is not advised + return DispEventUnadvise(m_pWebBrowser,&DIID_DWebBrowserEvents2); + return S_OK; +} diff --git a/ClassicShellSrc/ClassicExplorer/ExplorerBand.h b/ClassicShellSrc/ClassicExplorer/ExplorerBand.h new file mode 100644 index 0000000..ae59405 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ExplorerBand.h @@ -0,0 +1,245 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// ExplorerBand.h : Declaration of the CExplorerBand + +#pragma once +#include "resource.h" +#include "ClassicExplorer_i.h" +#include "SettingsParser.h" +#include + +class CBandWindow: public CWindowImpl +{ +public: + + enum + { + ID_LAST=-1, + ID_SEPARATOR=0, + + // standard toolbar commands + ID_SETTINGS=1, + ID_GOUP, + ID_CUT, + ID_COPY, + ID_PASTE, + ID_PASTE_SHORTCUT, + ID_DELETE, + ID_PROPERTIES, + ID_EMAIL, + + ID_MOVETO, + ID_COPYTO, + ID_UNDO, + ID_REDO, + ID_SELECTALL, + ID_DESELECT, + ID_INVERT, + ID_GOBACK, + ID_GOFORWARD, + ID_REFRESH, + ID_STOP, + ID_RENAME, + ID_NEWFOLDER, + ID_ZIPFOLDER, + ID_NAVPANE, + ID_DETAILSPANE, + ID_PREVIEWPANE, + ID_MAP_DRIVE, + ID_DISCONNECT, + ID_CUSTOMIZEFOLDER, + ID_FOLDEROPTIONS, + ID_VIEW_TILES, + ID_VIEW_DETAILS, + ID_VIEW_LIST, + ID_VIEW_CONTENT, + ID_VIEW_ICONS1, + ID_VIEW_ICONS2, + ID_VIEW_ICONS3, + ID_VIEW_ICONS4, + ID_SHOW_EXTENSIONS, + ID_HIDDEN_FILES, + ID_SYSTEM_FILES, + + ID_CUSTOM=100, + }; + + DECLARE_WND_CLASS(L"ClassicShell.CBandWindow") + + enum { + BWM_UPDATEBUTTONS=WM_USER, + BWM_UPDATETOOLBAR, + }; + + BEGIN_MSG_MAP( CBandWindow ) + MESSAGE_HANDLER( WM_CREATE, OnCreate ) + MESSAGE_HANDLER( WM_DESTROY, OnDestroy ) + MESSAGE_HANDLER( WM_CLEAR, OnUpdateUI ) + MESSAGE_HANDLER( WM_COMMAND, OnCommand ) + MESSAGE_HANDLER( BWM_UPDATEBUTTONS, OnUpdateButtons ) + MESSAGE_HANDLER( BWM_UPDATETOOLBAR, OnUpdateToolbar ) + NOTIFY_CODE_HANDLER( NM_RCLICK, OnRClick ) + NOTIFY_CODE_HANDLER( TBN_GETINFOTIP, OnGetInfoTip ) + NOTIFY_CODE_HANDLER( TBN_DROPDOWN, OnDropDown ) + NOTIFY_CODE_HANDLER( RBN_CHEVRONPUSHED, OnChevron ) + END_MSG_MAP() + + CBandWindow( void ) { m_ImgEnabled=m_ImgDisabled=NULL; m_MenuIconSize=0; } + + HWND GetToolbar( void ) { return m_Toolbar.m_hWnd; } + void SetBrowsers( IShellBrowser *pBrowser, IWebBrowser2 *pWebBrowser ); + void Clear( void ); + void UpdateToolbar( void ); + void EnableButton( int cmd, bool bEnable ); + void CheckButton( int cmd, bool bCheck ); + bool HasPanes( void ) const; + bool HasFolderSettings( void ) const; + +protected: + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnCreate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnUpdateUI( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnCommand( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnUpdateButtons( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnUpdateToolbar( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnRClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnGetInfoTip( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnDropDown( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnChevron( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + +private: + CWindow m_Toolbar; + CWindow m_TreeParent; + CComPtr m_pBrowser; + CComPtr m_pWebBrowser; + CComPtr m_pBrowserBag; + HIMAGELIST m_ImgEnabled; + HIMAGELIST m_ImgDisabled; + int m_MenuIconSize; + + struct StdToolbarItem + { + int id; + const wchar_t *command; + const wchar_t *link; + const wchar_t *label; // text on the button + const wchar_t *tip; // default tooltip + const wchar_t *iconPath; + const wchar_t *iconPathD; + CString regName; // name of the registry value to check for enabled/checked state + CString labelString, tipString; // additional storage for the strings + const StdToolbarItem *submenu; + mutable HBITMAP menuIcon; + mutable HBITMAP menuIconD; + mutable CString menuText; + mutable bool bIconLoaded; // the menu icon is loaded + bool bDisabled; + bool bChecked; + }; + + std::vector m_Items; + std::vector m_Buttons; + CSettingsParser m_Parser; + + void ParseToolbar( void ); + void ParseToolbarItem( const wchar_t *name, StdToolbarItem &item ); + void SendShellTabCommand( int command ); + HMENU CreateDropMenu( const StdToolbarItem *pItem ); + HMENU CreateDropMenuRec( const StdToolbarItem *pItem, std::vector &modules, HMODULE hShell32 ); + void SendEmail( void ); + void SendToZip( void ); + void NewFolder( void ); + void ExecuteCommandFile( const wchar_t *pText ); + void ExecuteCustomCommand( const wchar_t *pCommand ); + void ViewByProperty( IFolderView2 *pView, const wchar_t *pProperty, bool bGroup ); + void UpdateBag( void ); + void UpdateFolderSettings( void ); + + static LRESULT CALLBACK ToolbarSubclassProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + static HRESULT __stdcall BagWriteHook( IPropertyBag *pThis, LPCOLESTR pszPropName, VARIANT *pVar ); +}; + + +// CExplorerBand + +class ATL_NO_VTABLE CExplorerBand : + public CComObjectRootEx, + public CComCoClass, + public IObjectWithSiteImpl, + public IDeskBand, + public IDispEventImpl<1,CExplorerBand,&DIID_DWebBrowserEvents2,&LIBID_SHDocVw,1,1> +{ +public: + CExplorerBand( void ); + + DECLARE_REGISTRY_RESOURCEID(IDR_EXPLORERBAND) + + BEGIN_SINK_MAP( CExplorerBand ) + SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_NAVIGATECOMPLETE2, OnNavigateComplete) + SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_COMMANDSTATECHANGE, OnCommandStateChange) + SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_ONQUIT, OnQuit) + END_SINK_MAP() + + BEGIN_COM_MAP(CExplorerBand) + COM_INTERFACE_ENTRY( IOleWindow ) + COM_INTERFACE_ENTRY( IObjectWithSite ) + COM_INTERFACE_ENTRY_IID( IID_IDockingWindow, IDockingWindow ) + COM_INTERFACE_ENTRY_IID( IID_IDeskBand, IDeskBand ) + END_COM_MAP() + + + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + HRESULT FinalConstruct() + { + return S_OK; + } + + void FinalRelease() + { + } + +public: + + // IDeskBand + STDMETHOD(GetBandInfo)( DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi ); + + // IObjectWithSite + STDMETHOD(SetSite)( IUnknown* pUnkSite ); + + // IOleWindow + STDMETHOD(GetWindow)( HWND* phwnd ); + STDMETHOD(ContextSensitiveHelp)( BOOL fEnterMode ); + + // IDockingWindow + STDMETHOD(CloseDW)( unsigned long dwReserved ); + STDMETHOD(ResizeBorderDW)( const RECT* prcBorder, IUnknown* punkToolbarSite, BOOL fReserved ); + STDMETHOD(ShowDW)( BOOL fShow ); + + // DWebBrowserEvents2 + STDMETHOD(OnNavigateComplete)( IDispatch *pDisp, VARIANT *URL ); + STDMETHOD(OnCommandStateChange)( long Command, VARIANT_BOOL Enable ); + STDMETHOD(OnQuit)( void ); + +protected: + bool m_bSubclassRebar; // the rebar needs subclassing + bool m_bSubclassedRebar; // the rebar is subclassed + bool m_bBandNewLine; // our band is on a new line (has RBBS_BREAK style) + bool m_bHandleSetInfo; // mess with the RB_SETBANDINFO message + CBandWindow m_BandWindow; + CComPtr m_pWebBrowser; + HWND m_TopWindow; + + static LRESULT CALLBACK RebarSubclassProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + static LRESULT CALLBACK ParentSubclassProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + + friend class CBandWindow; +}; + +OBJECT_ENTRY_AUTO(__uuidof(ExplorerBand), CExplorerBand) diff --git a/ClassicShellSrc/ClassicExplorer/ExplorerBand.rgs b/ClassicShellSrc/ClassicExplorer/ExplorerBand.rgs new file mode 100644 index 0000000..6cb18a3 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ExplorerBand.rgs @@ -0,0 +1,59 @@ +HKCR +{ + ClassicExplorer.ExplorerBand.1 = s 'ExplorerBand Class' + { + CLSID = s '{553891B7-A0D5-4526-BE18-D3CE461D6310}' + } + ClassicExplorer.ExplorerBand = s 'ExplorerBand Class' + { + CLSID = s '{553891B7-A0D5-4526-BE18-D3CE461D6310}' + CurVer = s 'ClassicExplorer.ExplorerBand.1' + } + NoRemove CLSID + { + ForceRemove {553891B7-A0D5-4526-BE18-D3CE461D6310} = s 'Classic Explorer Bar' + { + ProgID = s 'ClassicExplorer.ExplorerBand.1' + VersionIndependentProgID = s 'ClassicExplorer.ExplorerBand' + ForceRemove 'Programmable' + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Apartment' + } + 'TypeLib' = s '{BF8D124A-A4E0-402F-8152-4EF377E62586}' + } + } +} + +HKLM +{ + NoRemove Software + { + NoRemove Microsoft + { + NoRemove 'Internet Explorer' + { + NoRemove Toolbar + { + ForceRemove val {553891B7-A0D5-4526-BE18-D3CE461D6310} = b '' + } + } + NoRemove Windows + { + NoRemove CurrentVersion + { + NoRemove Policies + { + NoRemove Ext + { + NoRemove CLSID + { + ForceRemove val {553891B7-A0D5-4526-BE18-D3CE461D6310} = s '2' + } + } + } + } + } + } + } +} diff --git a/ClassicShellSrc/ClassicExplorer/ExplorerL10N.ini b/ClassicShellSrc/ClassicExplorer/ExplorerL10N.ini new file mode 100644 index 0000000..0baeeea --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ExplorerL10N.ini @@ -0,0 +1,2599 @@ +; This file contains all localized text for Classic Explorer. There is one section per language. +; Every section contains text lines in the form of = . +; Which section is used depends on the current OS setting. If a key is missing from the language section +; it will be searched in the [default] section. In some cases more than one language can be used. +; For example a Japanese system may use English as a secondary language. In that case the search order +; will be [ja-JP] -> [en-US] -> [default]. +; +; ============================================================================= + + +[default] +Toolbar.Settings = Classic Explorer Settings + + +[ar-SA] - Arabic (Saudi Arabia) +Copy.Cancel = إلغاء الأمر +Copy.More = المزيد... +Copy.CopyHere = ن&سخ إلى هذا الموضع +Copy.MoveHere = ن&قل إلى هذا الموضع +Copy.Title = تأكيد استبدال الملف +Copy.Subtitle = يحتوي هذا المجلد على ملف باسم '%s'. +Copy.SubtitleRO = يحتوي هذا المجلد على ملف للقراءة فقط باسم '‎%s'. +Copy.SubtitleSys = يحتوي هذا المجلد مسبقاً على ملف نظام باسم '‎%s'. +Copy.Prompt1 = ‏‏هل تريد استبدال الملف الموجود +Copy.Prompt2 = بهذا؟ +Copy.Yes = &نعم +Copy.No = &لا +Copy.YesAll = نعم لل&كل +Folder.Title = تأكيد استبدال المجلد +Folder.Prompt = هل ما زلت تريد نقل المجلد أو نسخه؟ +Toolbar.GoUp = مستوى واحد لأعلى +Toolbar.Cut = قص +Toolbar.Copy = نسخ +Toolbar.Paste = لصق +Toolbar.PasteShortcut = لصق الاختصار +Toolbar.Delete = حذف +Toolbar.Email = إرسال العناصر المحددة بالبريد الإلكتروني +Toolbar.Properties = خصائص +Toolbar.NewFolder = مجلد جديد +Toolbar.ZipFolder = مجلد جديد مضغوط +Toolbar.ExtraLarge = رموز كبيرة جداً +Toolbar.Large = رموز كبيرة +Toolbar.Medium = رموز متوسطة +Toolbar.Small = رموز صغيرة +Toolbar.List = قائمة +Toolbar.Details = تفاصيل +Toolbar.Tiles = مربعات +Toolbar.Content = محتوى +Toolbar.Undo = تراجع +Toolbar.Redo = إعادة +Toolbar.Refresh = تحديث +Toolbar.Back = الخلف +Toolbar.Forward = الأمام +Toolbar.Stop = إيقاف +Toolbar.Rename = إعادة تسمية +Toolbar.SelectAll = تحديد الكل +Toolbar.CustomizeFolder = تخصيص هذا المجلد +Toolbar.MapDrive = تعيين محرك أقراص الشبكة +Toolbar.DisconnectDrive = قطع اتصال محرك أقراص الشبكة +Toolbar.NavigationPane = جزء التنقل +Toolbar.DetailsPane = جزء التفاصيل +Toolbar.PreviewPane = جزء المعاينة +Toolbar.CopyTo = نسخ إلى +Toolbar.MoveTo = نقل إلى +Toolbar.Deselect = بلا تحديد +Toolbar.InvertSelection = عكس التحديد +Toolbar.FolderOptions = خيارات المجلد +Toolbar.ShowHiddenFiles = الملفات والمجلدات المخفية +Toolbar.ShowSystemFiles = ملفات النظام +Toolbar.ShowExtensions = ملحقات أسماء الملفات +Status.FreeSpace = ‎%s (مساحة القرص الحرة: ‎%s) +Status.Item = عنصر %s +Status.Items = ‎‎%s عنصر/عناصر +Status.ItemSelected = %s عنصر محدد +Status.ItemsSelected = %s عنصر/عناصر محددة + + +[bg-BG] - Bulgarian (Bulgaria) +Copy.Cancel = Отказ +Copy.More = Още... +Copy.CopyHere = &Копирай тук +Copy.MoveHere = Пр&емести тук +Copy.Title = Потвърждаване на заместването на файл +Copy.Subtitle = Тази папка вече съдържа файл с име '%s'. +Copy.SubtitleRO = Тази папка вече съдържа файл само за четене с име '%s'. +Copy.SubtitleSys = Тази папка вече съдържа системен файл с име '%s'. +Copy.Prompt1 = Желаете ли да заместите съществуващия файл +Copy.Prompt2 = с този? +Copy.Yes = &Да +Copy.No = &Не +Copy.YesAll = "Да" за &всички +Folder.Title = Потвърждаване на заместването на папка +Folder.Prompt = Все още ли искате да преместите или копирате папката? +Toolbar.GoUp = Едно ниво нагоре +Toolbar.Cut = Изрежи +Toolbar.Copy = Копирай +Toolbar.Paste = Постави +Toolbar.PasteShortcut = Постави пряк път +Toolbar.Delete = Изтриване +Toolbar.Email = Изпрати избраните елементи по електронната поща +Toolbar.Properties = Свойства +Toolbar.NewFolder = Нова папка +Toolbar.ZipFolder = Нова компресирана със ZIP папка +Toolbar.ExtraLarge = Много големи икони +Toolbar.Large = Големи икони +Toolbar.Medium = Средни икони +Toolbar.Small = Малки икони +Toolbar.List = Списък +Toolbar.Details = Детайли +Toolbar.Tiles = Мозайка +Toolbar.Content = Съдържание +Toolbar.Undo = Отмени +Toolbar.Redo = Върни +Toolbar.Refresh = Обнови +Toolbar.Back = Назад +Toolbar.Forward = Напред +Toolbar.Stop = Спри +Toolbar.Rename = Преименуване +Toolbar.SelectAll = Избери всички +Toolbar.CustomizeFolder = Персонализиране на тази папка +Toolbar.MapDrive = Назначаване на мрежово устройство +Toolbar.DisconnectDrive = Изключване на мрежово устройство +Toolbar.NavigationPane = Навигационен екран +Toolbar.DetailsPane = Екран за подробни данни +Toolbar.PreviewPane = Прозорец за визуализация +Toolbar.CopyTo = Копирай в +Toolbar.MoveTo = Премести в +Toolbar.Deselect = Не избирай нищо +Toolbar.InvertSelection = Обърни селекцията +Toolbar.FolderOptions = Опции за папката +Toolbar.ShowHiddenFiles = Скрити файлове и папки +Toolbar.ShowSystemFiles = Системни файлове +Toolbar.ShowExtensions = Разширения на имената на файлове +Status.FreeSpace = %s (Свободно място на диска: %s) +Status.Item = %s елемент +Status.Items = %s елемента +Status.ItemSelected = %s избран елемент +Status.ItemsSelected = %s избрани елемента + + +[ca-ES] - Catalan (Catalan) +Copy.Cancel = Cancel·lar +Copy.More = Més... +Copy.CopyHere = &Copiar aquí +Copy.MoveHere = &Moure aquí +Copy.Title = Confirmar la substitució de l'arxiu +Copy.Subtitle = Aquesta carpeta ja conté un arxiu amb el nom "%s". +Copy.SubtitleRO = Aquesta carpeta ja conté un arxiu de sols lectura amb el nom "%s". +Copy.SubtitleSys = Aquesta carpeta ja conté un arxiu de sistema amb el nom "%s". +Copy.Prompt1 = Desitja substituir l'arxiu existent +Copy.Prompt2 = per aquest altre? +Copy.Yes = &Sí +Copy.No = &No +Copy.YesAll = Sí a &tot +Folder.Title = Confirmar la substitució de carpetes +Folder.Prompt = Desitja moure o copiar la carpeta de totes maneres? +Toolbar.GoUp = Pujar un nivell +Toolbar.Cut = Retallar +Toolbar.Copy = Copiar +Toolbar.Paste = Enganxar +Toolbar.PasteShortcut = Enganxar accés directe +Toolbar.Delete = Suprimeix +Toolbar.Email = Enviar per correu electrònic els elements següents +Toolbar.Properties = Propietats +Toolbar.NewFolder = Nova carpeta +Toolbar.ZipFolder = Carpeta comprimida (en zip) nova +Toolbar.ExtraLarge = Icones molt grans +Toolbar.Large = Icones grans +Toolbar.Medium = Icones mitjanes +Toolbar.Small = Icones petites +Toolbar.List = Llista +Toolbar.Details = Detalls +Toolbar.Tiles = Mosaics +Toolbar.Content = Contingut +Toolbar.Undo = Desfer +Toolbar.Redo = Refer +Toolbar.Refresh = Actualitzar +Toolbar.Back = Enrera +Toolbar.Forward = Endavant +Toolbar.Stop = Aturar +Toolbar.Rename = Cambiar nom +Toolbar.SelectAll = Seleccionar tot +Toolbar.CustomizeFolder = Personalitzar aquesta carpeta +Toolbar.MapDrive = Conectar a unitat de xarxa +Toolbar.DisconnectDrive = Desconectar unitat de xarxa +Toolbar.NavigationPane = Panell de navegació +Toolbar.DetailsPane = Panell de detalls +Toolbar.PreviewPane = Panell de vista prèvia +Toolbar.CopyTo = Copia a +Toolbar.MoveTo = Desplaça a +Toolbar.Deselect = No en seleccionis cap +Toolbar.InvertSelection = Inverteix la selecció +Toolbar.FolderOptions = Opcions de carpeta +Toolbar.ShowHiddenFiles = Fitxers i carpetes amagats +Toolbar.ShowSystemFiles = Fitxers del sistema +Toolbar.ShowExtensions = Extensions del nom de fitxer +Toolbar.Settings = Ajustaments del Classic Explorer +Status.FreeSpace = %s (espai disponible en disc: %s) +Status.Item = %s element +Status.Items = %s elements +Status.ItemSelected = %s element seleccionat +Status.ItemsSelected = %s elements seleccionats + + +[cs-CZ] - Czech (Czech Republic) +Copy.Cancel = Storno +Copy.More = Další... +Copy.CopyHere = &Kopírovat sem +Copy.MoveHere = &Přesunout sem +Copy.Title = Potvrdit nahrazení souboru +Copy.Subtitle = Tato složka již obsahuje soubor s názvem %s. +Copy.SubtitleRO = Tato složka již obsahuje soubor jen pro čtení s názvem %s. +Copy.SubtitleSys = Tato složka již obsahuje systémový soubor s názvem %s. +Copy.Prompt1 = Chcete nahradit stávající soubor +Copy.Prompt2 = tímto souborem? +Copy.Yes = &Ano +Copy.No = &Ne +Copy.YesAll = Ano vš&em +Folder.Title = Potvrdit nahrazení složky +Folder.Prompt = Opravdu chcete přesunout nebo zkopírovat tuto složku? +Toolbar.GoUp = O úroveň výš +Toolbar.Cut = Vyjmout +Toolbar.Copy = Kopírovat +Toolbar.Paste = Vložit +Toolbar.PasteShortcut = Vložit zástupce +Toolbar.Delete = Odstranit +Toolbar.Email = Odešle vybrané položky e-mailem +Toolbar.Properties = Vlastnosti +Toolbar.NewFolder = Nová složka +Toolbar.ZipFolder = Nová komprimovaná složka (metoda ZIP) +Toolbar.ExtraLarge = Největší ikony +Toolbar.Large = Velké ikony +Toolbar.Medium = Střední ikony +Toolbar.Small = Malé ikony +Toolbar.List = Seznam +Toolbar.Details = Podrobnosti +Toolbar.Tiles = Dlaždice +Toolbar.Content = Obsah +Toolbar.Undo = Zpět +Toolbar.Redo = Znovu +Toolbar.Refresh = Aktualizovat +Toolbar.Back = Zpět +Toolbar.Forward = Vpřed +Toolbar.Stop = Zastavit +Toolbar.Rename = Přejmenovat +Toolbar.SelectAll = Vybrat vše +Toolbar.CustomizeFolder = Vlastní nastavení této složky +Toolbar.MapDrive = Připojit síťovou jednotku +Toolbar.DisconnectDrive = Odpojit síťovou jednotku +Toolbar.NavigationPane = Navigační podokno +Toolbar.DetailsPane = Podokno podrobností +Toolbar.PreviewPane = Podokno náhledu +Toolbar.CopyTo = Kopírovat do +Toolbar.MoveTo = Přesunout do +Toolbar.Deselect = Zrušit výběr +Toolbar.InvertSelection = Invertovat výběr +Toolbar.FolderOptions = Možnosti složky +Toolbar.ShowHiddenFiles = Skryté soubory a složky +Toolbar.ShowSystemFiles = Systémové soubory +Toolbar.ShowExtensions = Přípony názvů souborů +Status.FreeSpace = %s (volné místo na disku: %s) +Status.Item = %s položka +Status.Items = Počet položek: %s +Status.ItemSelected = %s vybraná položka +Status.ItemsSelected = Vybrané položky: %s + + +[da-DK] - Danish (Denmark) +Copy.Cancel = Annuller +Copy.More = Flere... +Copy.CopyHere = &Kopier hertil +Copy.MoveHere = &Flyt hertil +Copy.Title = Bekræft erstatning af fil +Copy.Subtitle = Denne mappe indeholder allerede en fil med navnet '%s'. +Copy.SubtitleRO = Denne mappe indeholder allerede en skrivebeskyttet fil med navnet '%s'. +Copy.SubtitleSys = Denne mappe indeholder allerede en systemfil med navnet '%s'. +Copy.Prompt1 = Vil du erstatte den eksisterende fil +Copy.Prompt2 = med denne fil? +Copy.Yes = &Ja +Copy.No = &Nej +Copy.YesAll = J&a til alle +Folder.Title = Bekræft erstatning af mappe +Folder.Prompt = Vil du flytte mappen alligevel? +Toolbar.GoUp = Et niveau op +Toolbar.Cut = Klip +Toolbar.Copy = Kopier +Toolbar.Paste = Sæt ind +Toolbar.PasteShortcut = Indsæt genvej +Toolbar.Delete = Slet +Toolbar.Email = Send de markerede elementer med e-mail +Toolbar.Properties = Egenskaber +Toolbar.NewFolder = Ny mappe +Toolbar.ZipFolder = Ny ZIP-komprimeret mappe +Toolbar.ExtraLarge = Ekstra store ikoner +Toolbar.Large = Store ikoner +Toolbar.Medium = Mellemstore ikoner +Toolbar.Small = Små ikoner +Toolbar.List = Oversigt +Toolbar.Details = Detaljer +Toolbar.Tiles = Fliser +Toolbar.Content = Indhold +Toolbar.Undo = Fortryd +Toolbar.Redo = Annuller Fortryd +Toolbar.Refresh = Opdater +Toolbar.Back = Tilbage +Toolbar.Forward = Fremad +Toolbar.Stop = Stop +Toolbar.Rename = Omdøb +Toolbar.SelectAll = Marker alt +Toolbar.CustomizeFolder = Tilpas denne mappe +Toolbar.MapDrive = Tilknyt netværksdrev +Toolbar.DisconnectDrive = Afbryd forbindelsen til et netværksdrev +Toolbar.NavigationPane = Navigationsrude +Toolbar.DetailsPane = Detaljerude +Toolbar.PreviewPane = Indholdsrude +Toolbar.CopyTo = Kopiér til +Toolbar.MoveTo = Flyt til +Toolbar.Deselect = Vælg ingen +Toolbar.InvertSelection = Inverter markeringen +Toolbar.FolderOptions = Mappeindstillinger +Toolbar.ShowHiddenFiles = Skjulte filer og mapper +Toolbar.ShowSystemFiles = Systemfiler +Toolbar.ShowExtensions = Filtypenavne +Status.FreeSpace = %s (ledig diskplads: %s) +Status.Item = %s element +Status.Items = %s elementer +Status.ItemSelected = %s markeret element +Status.ItemsSelected = %s markerede elementer + + +[de-DE] - German (Germany) +Copy.Cancel = Abbrechen +Copy.More = Weitere... +Copy.CopyHere = Hierher &kopieren +Copy.MoveHere = Hierher &verschieben +Copy.Title = Ersetzen von Dateien bestätigen +Copy.Subtitle = Dieser Ordner enthält bereits eine Datei "%s". +Copy.SubtitleRO = Der Ordner enthält bereits eine schreibgeschützte Datei "%s". +Copy.SubtitleSys = Der Ordner enthält bereits eine Systemdatei "%s". +Copy.Prompt1 = Möchten Sie die existierende Datei +Copy.Prompt2 = mit dieser ersetzen? +Copy.Yes = &Ja +Copy.No = &Nein +Copy.YesAll = Ja, &alle +Folder.Title = Ersetzen von Ordnern bestätigen +Folder.Prompt = Soll der Ordner trotzdem verschoben bzw. kopiert werden? +Toolbar.GoUp = Eine Ebene nach oben +Toolbar.Cut = Ausschneiden +Toolbar.Copy = Kopieren +Toolbar.Paste = Einfügen +Toolbar.PasteShortcut = Verknüpfung einfügen +Toolbar.Delete = Löschen +Toolbar.Email = Ausgewählte Elemente in E-Mail senden +Toolbar.Properties = Eigenschaften +Toolbar.NewFolder = Neuer Ordner +Toolbar.ZipFolder = Neuer ZIP-komprimierter Ordner +Toolbar.ExtraLarge = Extra große Symbole +Toolbar.Large = Große Symbole +Toolbar.Medium = Mittelgroße Symbole +Toolbar.Small = Kleine Symbole +Toolbar.List = Liste +Toolbar.Details = Details +Toolbar.Tiles = Kacheln +Toolbar.Content = Inhalt +Toolbar.Undo = Rückgängig +Toolbar.Redo = Wiederholen +Toolbar.Refresh = Aktualisieren +Toolbar.Back = Zurück +Toolbar.Forward = Vorwärts +Toolbar.Stop = Beenden +Toolbar.Rename = Umbenennen +Toolbar.SelectAll = Alles auswählen +Toolbar.CustomizeFolder = Ordner anpassen +Toolbar.MapDrive = Netzlaufwerk verbinden +Toolbar.DisconnectDrive = Netzlaufwerk trennen +Toolbar.NavigationPane = Navigationsbereich +Toolbar.DetailsPane = Detailbereich +Toolbar.PreviewPane = Vorschaufenster +Toolbar.CopyTo = Kopieren nach +Toolbar.MoveTo = Verschieben nach +Toolbar.Deselect = Nichts auswählen +Toolbar.InvertSelection = Auswahl umkehren +Toolbar.FolderOptions = Ordneroptionen +Toolbar.ShowHiddenFiles = Versteckte Dateien und Ordner +Toolbar.ShowSystemFiles = Systemdateien +Toolbar.ShowExtensions = Dateinamenerweiterungen +Status.FreeSpace = %s (Freier Speicherplatz: %s) +Status.Item = %s Element +Status.Items = %s Elemente +Status.ItemSelected = %s Element ausgewählt +Status.ItemsSelected = %s Elemente ausgewählt + + +[el-GR] - Greek (Greece) +Copy.Cancel = Άκυρο +Copy.More = Περισσότερα... +Copy.CopyHere = &Αντιγραφή εδώ +Copy.MoveHere = &Μετακίνηση εδώ +Copy.Title = Επιβεβαίωση αντικατάστασης αρχείου +Copy.Subtitle = Αυτός ο φάκελος περιέχει ήδη ένα αρχείο με όνομα "%s". +Copy.SubtitleRO = Αυτός ο φάκελος περιέχει ήδη ένα αρχείο μόνο για ανάγνωση με όνομα "%s". +Copy.SubtitleSys = Αυτός ο φάκελος περιέχει ήδη ένα αρχείο συστήματος με όνομα "%s". +Copy.Prompt1 = Θέλετε να αντικατασταθεί το υπάρχον αρχείο +Copy.Prompt2 = με αυτό το αρχείο; +Copy.Yes = &Ναι +Copy.No = Ό&χι +Copy.YesAll = Ναι σε ό&λα +Folder.Title = Επιβεβαίωση αντικατάστασης φακέλου +Folder.Prompt = Είστε βέβαιοι ότι θέλετε να μετακινηθεί ή να αντιγραφεί ο φάκελος; +Toolbar.GoUp = Ένα επίπεδο επάνω +Toolbar.Cut = Αποκοπή +Toolbar.Copy = Αντιγραφή +Toolbar.Paste = Επικόλληση +Toolbar.PasteShortcut = Επικόλληση συντόμευσης +Toolbar.Delete = Διαγραφή +Toolbar.Email = Ηλεκτρονική ταχυδρόμηση των επιλεγμένων αντικειμένων +Toolbar.Properties = Ιδιότητες +Toolbar.NewFolder = Νέος φάκελος +Toolbar.ZipFolder = Νέος συμπιεσμένος (μορφή zip) φάκελος +Toolbar.ExtraLarge = Πολύ μεγάλα εικονίδια +Toolbar.Large = Μεγάλα εικονίδια +Toolbar.Medium = Μεσαία εικονίδια +Toolbar.Small = Μικρά εικονίδια +Toolbar.List = Λίστα +Toolbar.Details = Λεπτομέρειες +Toolbar.Tiles = Τίτλοι +Toolbar.Content = Περιεχόμενο +Toolbar.Undo = Αναίρεση +Toolbar.Redo = Επανάληψη +Toolbar.Refresh = Ανανέωση +Toolbar.Back = Πίσω +Toolbar.Forward = Εμπρός +Toolbar.Stop = Τέλος +Toolbar.Rename = Μετονομασία +Toolbar.SelectAll = Επιλογή όλων +Toolbar.CustomizeFolder = Προσαρμογή φακέλου +Toolbar.MapDrive = Αντιστοίχιση δίσκου δικτύου +Toolbar.DisconnectDrive = Αποσύνδεση δίσκου δικτύου +Toolbar.NavigationPane = Παράθυρο περιήγησης +Toolbar.DetailsPane = Παράθυρο λεπτομερειών +Toolbar.PreviewPane = Παράθυρο προεπισκόπησης +Toolbar.CopyTo = Αντιγραφή σε +Toolbar.MoveTo = Μετακίνηση σε +Toolbar.Deselect = Καμία επιλογή +Toolbar.InvertSelection = Αναστροφή επιλογής +Toolbar.FolderOptions = Επιλογές φακέλων +Toolbar.ShowHiddenFiles = Κρυφά αρχεία και φάκελοι +Toolbar.ShowSystemFiles = Αρχεία συστήματος +Toolbar.ShowExtensions = Επεκτάσεις ονόματος αρχείων +Status.FreeSpace = %s (Ελεύθερος χώρος στο δίσκο: %s) +Status.Item = %s στοιχείο +Status.Items = %s στοιχεία +Status.ItemSelected = %s επιλεγμένο στοιχείο +Status.ItemsSelected = %s επιλεγμένα στοιχεία + + +[en-US] - English (United States) +Copy.Cancel = Cancel +Copy.More = More... +Copy.CopyHere = &Copy Here +Copy.MoveHere = &Move Here +Copy.Title = Confirm File Replace +Copy.Subtitle = This folder already contains a file named '%s'. +Copy.SubtitleRO = This folder already contains a read-only file named '%s'. +Copy.SubtitleSys = This folder already contains a system file named '%s'. +Copy.Prompt1 = Would you like to replace the existing file +Copy.Prompt2 = with this one? +Copy.Yes = &Yes +Copy.No = &No +Copy.YesAll = Yes to &All +Folder.Title = Confirm Folder Replace +Folder.Prompt = Do you still want to move or copy the folder? +Toolbar.GoUp = Up One Level +Toolbar.Cut = Cut +Toolbar.Copy = Copy +Toolbar.Paste = Paste +Toolbar.PasteShortcut = Paste Shortcut +Toolbar.Delete = Delete +Toolbar.Email = E-mail the selected items +Toolbar.Properties = Properties +Toolbar.NewFolder = New Folder +Toolbar.ZipFolder = New Compressed (zipped) Folder +Toolbar.ExtraLarge = Extra Large Icons +Toolbar.Large = Large Icons +Toolbar.Medium = Medium Icons +Toolbar.Small = Small Icons +Toolbar.List = List +Toolbar.Details = Details +Toolbar.Tiles = Tiles +Toolbar.Content = Content +Toolbar.Undo = Undo +Toolbar.Redo = Redo +Toolbar.Refresh = Refresh +Toolbar.Back = Back +Toolbar.Forward = Forward +Toolbar.Stop = Stop +Toolbar.Rename = Rename +Toolbar.SelectAll = Select all +Toolbar.CustomizeFolder = Customize this folder +Toolbar.MapDrive = Map network drive +Toolbar.DisconnectDrive = Disconnect network drive +Toolbar.NavigationPane = Navigation pane +Toolbar.DetailsPane = Details pane +Toolbar.PreviewPane = Preview pane +Toolbar.CopyTo = Copy to +Toolbar.MoveTo = Move to +Toolbar.Deselect = Select none +Toolbar.InvertSelection = Invert selection +Toolbar.FolderOptions = Folder options +Toolbar.ShowHiddenFiles = Hidden files and folders +Toolbar.ShowSystemFiles = System files +Toolbar.ShowExtensions = File name extensions +Status.FreeSpace = %s (Disk free space: %s) +Status.Item = %s item +Status.Items = %s items +Status.ItemSelected = %s item selected +Status.ItemsSelected = %s items selected + + +[es-ES] - Spanish (Spain) +Copy.Cancel = Cancelar +Copy.More = Mas... +Copy.CopyHere = &Copiar aquí +Copy.MoveHere = &Mover aquí +Copy.Title = Confirmar el reemplazo de archivo +Copy.Subtitle = Esta carpeta ya contiene un archivo con el nombre "%s". +Copy.SubtitleRO = Esta carpeta ya contiene un archivo de sólo lectura con el nombre "%s". +Copy.SubtitleSys = Esta carpeta ya contiene un archivo de sistema con el nombre "%s". +Copy.Prompt1 = ¿Desea reemplazar el archivo existente +Copy.Prompt2 = por este otro? +Copy.Yes = &Sí +Copy.No = &No +Copy.YesAll = Sí a &todo +Folder.Title = Confirmar el reemplazo de carpetas +Folder.Prompt = ¿Desea mover o copiar la carpeta de todas formas? +Toolbar.GoUp = Subir un nivel +Toolbar.Cut = Cortar +Toolbar.Copy = Copiar +Toolbar.Paste = Pegar +Toolbar.PasteShortcut = Pegar acceso directo +Toolbar.Delete = Eliminar +Toolbar.Email = Enviar por correo electrónico los elementos siguientes +Toolbar.Properties = Propiedades +Toolbar.NewFolder = Nueva carpeta +Toolbar.ZipFolder = Nueva carpeta comprimida (en zip) +Toolbar.ExtraLarge = Iconos muy grandes +Toolbar.Large = Iconos grandes +Toolbar.Medium = Iconos medianos +Toolbar.Small = Iconos pequeños +Toolbar.List = Lista +Toolbar.Details = Detalles +Toolbar.Tiles = Mosaicos +Toolbar.Content = Contenido +Toolbar.Undo = Deshacer +Toolbar.Redo = Rehacer +Toolbar.Refresh = Actualizar +Toolbar.Back = Atrás +Toolbar.Forward = Adelante +Toolbar.Stop = Detener +Toolbar.Rename = Cambiar nombre +Toolbar.SelectAll = Seleccionar todo +Toolbar.CustomizeFolder = Personalizar esta carpeta +Toolbar.MapDrive = Conectar a unidad de red +Toolbar.DisconnectDrive = Desconectar unidad de red +Toolbar.NavigationPane = Panel de navegación +Toolbar.DetailsPane = Panel de detalles +Toolbar.PreviewPane = Panel de vista previa +Toolbar.CopyTo = Copiar a +Toolbar.MoveTo = Mover a +Toolbar.Deselect = No seleccionar ninguno +Toolbar.InvertSelection = Invertir selección +Toolbar.FolderOptions = Opciones de carpeta +Toolbar.ShowHiddenFiles = Archivos y carpetas ocultos +Toolbar.ShowSystemFiles = Archivos de sistema +Toolbar.ShowExtensions = Extensiones de nombre de archivo +Status.FreeSpace = %s (espacio disponible en disco: %s) +Status.Item = %s elemento +Status.Items = %s elementos +Status.ItemSelected = %s elemento seleccionado +Status.ItemsSelected = %s elementos seleccionados + + +[et-EE] - Estonian (Estonia) +Copy.Cancel = Loobu +Copy.More = Veel... +Copy.CopyHere = &Kopeeri siia +Copy.MoveHere = &Teisalda siia +Copy.Title = Kinnitage failiasendus +Copy.Subtitle = See kaust sisaldab juba faili nimega %s. +Copy.SubtitleRO = See kaust sisaldab juba kirjutuskaitstud faili nimega %s. +Copy.SubtitleSys = See kaust sisaldab juba süsteemifaili nimega %s. +Copy.Prompt1 = Kas soovite asendada olemasoleva faili +Copy.Prompt2 = sellega? +Copy.Yes = &Jah +Copy.No = &Ei +Copy.YesAll = &Kõigile jah +Folder.Title = Kinnitage kausta asendamine +Folder.Prompt = Kas soovite kausta ikkagi teisaldada või kopeerida? +Toolbar.GoUp = Taseme võrra üles +Toolbar.Cut = Lõika +Toolbar.Copy = Kopeeri +Toolbar.Paste = Kleebi +Toolbar.PasteShortcut = Kleebi otsetee +Toolbar.Delete = Kustuta +Toolbar.Email = Saada valitud üksused e-postiga +Toolbar.Properties = Atribuudid +Toolbar.NewFolder = Uus kaust +Toolbar.ZipFolder = Uus tihendatud (zip) kaust +Toolbar.ExtraLarge = Eriti suured ikoonid +Toolbar.Large = Suured ikoonid +Toolbar.Medium = Keskmise suurusega ikoonid +Toolbar.Small = Väikesed ikoonid +Toolbar.List = Loend +Toolbar.Details = Üksikasjad +Toolbar.Tiles = Paanid +Toolbar.Content = Sisu +Toolbar.Undo = Võta tagasi +Toolbar.Redo = Tee uuesti +Toolbar.Refresh = Värskenda +Toolbar.Back = Tagasi +Toolbar.Forward = Edasi +Toolbar.Stop = Lõpeta +Toolbar.Rename = Nimeta ümber +Toolbar.SelectAll = Vali kõik +Toolbar.CustomizeFolder = Kohanda seda kausta +Toolbar.MapDrive = Ühenda võrgudraiv +Toolbar.DisconnectDrive = Katkesta võrgudraivi ühendus +Toolbar.NavigationPane = Navigeerimispaan +Toolbar.DetailsPane = Üksikasjapaan +Toolbar.PreviewPane = Eelvaatepaan +Toolbar.CopyTo = Kopeeri asukohta +Toolbar.MoveTo = Teisalda asukohta +Toolbar.Deselect = Ära vali midagi +Toolbar.InvertSelection = Pööra valik +Toolbar.FolderOptions = Kaustasuvandid +Toolbar.ShowHiddenFiles = Peitfailid ja -kaustad +Toolbar.ShowSystemFiles = Süsteemifailid +Toolbar.ShowExtensions = Failinimede laiendid +Status.FreeSpace = %s (vaba kettaruumi: %s) +Status.Item = %s üksus +Status.Items = %s üksust +Status.ItemSelected = Valitud on %s üksus +Status.ItemsSelected = Valitud on %s üksust + + +[fa-IR] - Persian +Copy.Cancel = لغو +Copy.More = بیشتر... +Copy.CopyHere = &کپی به اینجا +Copy.MoveHere = &انتقال به اینجا +Copy.Title = تأیید جایگزینی پرونده +Copy.Subtitle = ‏‏در حال حاضر این پوشه حاوی پرونده‌ای به نام "%s" است. +Copy.SubtitleRO = ‏‏در حال حاضر این پوشه حاوی پرونده‌ای فقط خواندنی به نام "%s" است. +Copy.SubtitleSys = ‏‏در حال حاضر این پوشه حاوی پرونده‌ای سیستمی به نام "%s" است. +Copy.Prompt1 = آیا می‌خواهید پرونده‌ی موجود را جایگزین کنید +Copy.Prompt2 = با این یکی؟ +Copy.Yes = &بله +Copy.No = &خیر +Copy.YesAll = بله برای &همه +Folder.Title = تأیید جایگزینی پوشه +Folder.Prompt = آیا هنوز می‌خواهید پوشه را کپی یا منتقل کنید؟ +Toolbar.GoUp = یک سطح بالاتر +Toolbar.Cut = برش +Toolbar.Copy = کپی +Toolbar.Paste = جایگذاری +Toolbar.PasteShortcut = جایگذاری میانبر +Toolbar.Delete = حذف +Toolbar.Email = مورد انتخابی را با پست الکترونیکی بفرستید +Toolbar.Properties = خصوصیات +Toolbar.NewFolder = پوشه جدید +Toolbar.ZipFolder = پوشه فشرده ‏(زیپ شده)‏ جدید‫ +Toolbar.ExtraLarge = نمادهای خیلی بزرگ +Toolbar.Large = نمادهای بزرگ +Toolbar.Medium = نمادهای متوسط +Toolbar.Small = نمادهای کوچک +Toolbar.List = لیست +Toolbar.Details = جزئیات +Toolbar.Tiles = موزائیک‌ها +Toolbar.Content = محتوا +Toolbar.Undo = لغو عمل +Toolbar.Redo = انجام مجدد +Toolbar.Refresh = تازه‌کردن +Toolbar.Back = عقب +Toolbar.Forward = جلو +Toolbar.Stop = توقف +Toolbar.Rename = تغییر نام +Toolbar.SelectAll = انتخاب همه +Toolbar.CustomizeFolder = سفارشی کردن این پوشه +Toolbar.MapDrive = نگاشت درایو شبکه +Toolbar.DisconnectDrive = قطع اتصال درایو شبکه +Toolbar.NavigationPane = چارچوب پیمایش +Toolbar.DetailsPane = چارچوب جزئیات +Toolbar.PreviewPane = چارچوب پیش‌نمایش +Toolbar.CopyTo = ‏‏کپی در +Toolbar.MoveTo = انتقال به +Toolbar.Deselect = هیچکدام انتخاب نشود +Toolbar.InvertSelection = معکوس کردن انتخاب +Toolbar.FolderOptions = گزینه های پوشه +Toolbar.ShowHiddenFiles = پرونده و پوشه های پنهان +Toolbar.ShowSystemFiles = پرونده های سیستم +Toolbar.ShowExtensions = پسوندهای نام پرونده ها +Toolbar.Settings = تنظیمات کاوشگر کلاسیک +Status.FreeSpace = %s (فضای خالی دیسک: %s) +Status.Item = %s مورد +Status.Items = %s مورد +Status.ItemSelected = %s مورد انتخاب شده +Status.ItemsSelected = %s مورد انتخاب شده + + +[fi-FI] - Finnish (Finland) +Copy.Cancel = Peruuta +Copy.More = Lisää... +Copy.CopyHere = &Kopioi tähän +Copy.MoveHere = &Siirrä tähän +Copy.Title = Vahvista tiedoston korvaus +Copy.Subtitle = Tämä kansio sisältää jo tiedoston %s. +Copy.SubtitleRO = Tämä kansio sisältää jo vain luku -tiedoston %s. +Copy.SubtitleSys = Tämä kansio sisältää jo järjestelmätiedoston %s. +Copy.Prompt1 = Haluatko korvata tiedoston +Copy.Prompt2 = tällä tiedostolla? +Copy.Yes = &Kyllä +Copy.No = &Ei +Copy.YesAll = Kyllä k&aikkiin +Folder.Title = Vahvista kansion korvaus +Folder.Prompt = Haluatko korvata järjestelmässä jo olevan kansion tiedostot siirrettävän tai kopioitavan kansion samannimisillä tiedostoilla? +Toolbar.GoUp = Yksi taso ylöspäin +Toolbar.Cut = Leikkaa +Toolbar.Copy = Kopioi +Toolbar.Paste = Liitä +Toolbar.PasteShortcut = Liitä pikakuvake +Toolbar.Delete = Poista +Toolbar.Email = Lähetä valitut kohteet sähköpostilla +Toolbar.Properties = Ominaisuudet +Toolbar.NewFolder = Uusi kansio +Toolbar.ZipFolder = Uusi pakattu (zip) kansio +Toolbar.ExtraLarge = Suurimmat kuvakkeet +Toolbar.Large = Suuret kuvakkeet +Toolbar.Medium = Keskikokoiset kuvakkeet +Toolbar.Small = Pienet kuvakkeet +Toolbar.List = Luettelo +Toolbar.Details = Tiedot +Toolbar.Tiles = Kuvakkeet ja tiedot +Toolbar.Content = Sisältö +Toolbar.Undo = Kumoa +Toolbar.Redo = Tee uudelleen +Toolbar.Refresh = Päivitä +Toolbar.Back = Edellinen +Toolbar.Forward = Seuraava +Toolbar.Stop = Pysäytä +Toolbar.Rename = Nimeä uudelleen +Toolbar.SelectAll = Valitse kaikki +Toolbar.CustomizeFolder = Mukauta kansiota +Toolbar.MapDrive = Yhdistä verkkoasemaan +Toolbar.DisconnectDrive = Katkaise yhteys verkkoasemaan +Toolbar.NavigationPane = Siirtymisruutu +Toolbar.DetailsPane = Tiedot-ruutu +Toolbar.PreviewPane = Esikatseluruutu +Toolbar.CopyTo = Kopioi kohteeseen +Toolbar.MoveTo = Siirrä kohteeseen +Toolbar.Deselect = Poista valinnat +Toolbar.InvertSelection = Käänteinen valinta +Toolbar.FolderOptions = Kansion asetukset +Toolbar.ShowHiddenFiles = Piilotetut tiedostot ja kansiot +Toolbar.ShowSystemFiles = Järjestelmätiedostot +Toolbar.ShowExtensions = Tiedostotunnisteet +Status.FreeSpace = %s (levyn vapaa tila: %s) +Status.Item = %s kohde +Status.Items = %s kohdetta +Status.ItemSelected = %s kohde valittu +Status.ItemsSelected = %s kohdetta valittu + + +[fr-FR] - French (France) +Copy.Cancel = Annuler +Copy.More = Autres… +Copy.CopyHere = &Copier ici +Copy.MoveHere = &Déplacer ici +Copy.Title = Confirmer le remplacement du fichier +Copy.Subtitle = Ce dossier contient déjà un fichier nommé « %s ». +Copy.SubtitleRO = Ce dossier contient déjà un fichier en lecture seule nommé « %s ». +Copy.SubtitleSys = Ce dossier contient déjà un fichier système nommé « %s ». +Copy.Prompt1 = Faut-il remplacer le fichier existant +Copy.Prompt2 = par celui-ci ? +Copy.Yes = &Oui +Copy.No = &Non +Copy.YesAll = &Tous +Folder.Title = Confirmation du remplacement du dossier +Folder.Prompt = Faut-il vraiment déplacer ou copier le dossier ? +Toolbar.GoUp = Dossier parent +Toolbar.Cut = Couper +Toolbar.Copy = Copier +Toolbar.Paste = Coller +Toolbar.PasteShortcut = Coller le raccourci +Toolbar.Delete = Supprimer +Toolbar.Email = Envoyer les éléments sélectionnés par courrier électronique +Toolbar.Properties = Propriétés +Toolbar.NewFolder = Nouveau dossier +Toolbar.ZipFolder = Nouveau dossier compressé +Toolbar.ExtraLarge = Très grandes icônes +Toolbar.Large = Grandes icônes +Toolbar.Medium = Icônes moyennes +Toolbar.Small = Petites icônes +Toolbar.List = Liste +Toolbar.Details = Détails +Toolbar.Tiles = Mosaïques +Toolbar.Content = Contenu +Toolbar.Undo = Annuler +Toolbar.Redo = Rétablir +Toolbar.Refresh = Actualiser +Toolbar.Back = Précédent +Toolbar.Forward = Suivant +Toolbar.Stop = Arrêter +Toolbar.Rename = Renommer +Toolbar.SelectAll = Sélectionner tout +Toolbar.CustomizeFolder = Personnaliser ce dossier +Toolbar.MapDrive = Connecter un lecteur réseau +Toolbar.DisconnectDrive = Déconnecter un lecteur réseau +Toolbar.NavigationPane = Volet de navigation +Toolbar.DetailsPane = Volet des détails +Toolbar.PreviewPane = Volet de visualisation +Toolbar.CopyTo = Copier vers +Toolbar.MoveTo = Déplacer vers +Toolbar.Deselect = Aucun +Toolbar.InvertSelection = Inverser la sélection +Toolbar.FolderOptions = Options des dossiers +Toolbar.ShowHiddenFiles = Fichiers et dossiers cachés +Toolbar.ShowSystemFiles = Fichiers système +Toolbar.ShowExtensions = Extensions de noms de fichiers +Status.FreeSpace = %s (espace libre : %s) +Status.Item = %s élément +Status.Items = %s éléments +Status.ItemSelected = %s élément sélectionné +Status.ItemsSelected = %s éléments sélectionnés + + +[gd-GB] - Scottish Gaelic (United Kingdom) +Copy.Cancel = Sguir dheth +Copy.More = Barrachd... +Copy.CopyHere = &Cuir an lethbhreac an-seo +Copy.MoveHere = &Gluais an-seo +Copy.Title = Dearbh an cur an àite +Copy.Subtitle = Tha faidhle air a bheil "%s" sa phasgan seo mu thràth. +Copy.SubtitleRO = Tha faidhle air a bheil "%s" sa phasgan seo mu thràth a tha ri leughadh a-mhàin. +Copy.SubtitleSys = Tha faidhle siostaim air a bheil "%s" sa phasgan seo mu thràth. +Copy.Prompt1 = A bheil thu airson am faidhle seo a chur +Copy.Prompt2 = an àite an fhir làithrich? +Copy.Yes = &Tha +Copy.No = &Chan eil +Copy.YesAll = Th&a ris a h-uile +Folder.Title = Dearbh an cur an àite +Folder.Prompt = A bheil thu airson am pasgan a ghluasad fhathast no airson lethbhreac a dhèanamh dheth? +Toolbar.GoUp = Suas aon ìre +Toolbar.Cut = Gearr +Toolbar.Copy = Dàn lethbhreac +Toolbar.Paste = Cuir ann +Toolbar.PasteShortcut = Cuir ann an ath-ghoirid +Toolbar.Delete = Sguab às +Toolbar.Email = Cuir na thagh thu ann am post-d +Toolbar.Properties = Roghainnean +Toolbar.NewFolder = Pasgan ùr +Toolbar.ZipFolder = Pasgan dùmhlaichte (air a shiopadh) ùr +Toolbar.ExtraLarge = Ìomhaigheagan anabarrach mòr +Toolbar.Large = Ìomhaigheagan mòra +Toolbar.Medium = Ìomhaigheagan meadhanach +Toolbar.Small = Ìomhaigheagan beaga +Toolbar.List = Liosta +Toolbar.Details = Mion-fhiosrachadh +Toolbar.Tiles = Leacagan +Toolbar.Content = Susbaint +Toolbar.Undo = Neo-dhèan +Toolbar.Redo = Ath-dhèan +Toolbar.Refresh = Ath-nuadhaich +Toolbar.Back = Air ais +Toolbar.Forward = Air adhart +Toolbar.Stop = Sguir dheth +Toolbar.Rename = Thoir ainm eile air +Toolbar.SelectAll = Tagh na h-uile +Toolbar.CustomizeFolder = Gnàthaich am pasgan seo +Toolbar.MapDrive = Mapaich draibh an lìonraidh +Toolbar.DisconnectDrive = Dì-cheangail draibh an lìonraidh +Toolbar.NavigationPane = Leòsan na seòladaireachd +Toolbar.DetailsPane = Leòsan a' mhion-fhiosrachaidh +Toolbar.PreviewPane = Leòsan an ro-sheallaidh +Toolbar.CopyTo = Cuir lethbhreac gu +Toolbar.MoveTo = Gluais gu +Toolbar.Deselect = Na tagh gin +Toolbar.InvertSelection = Ais-thionndaidh an taghadh +Toolbar.FolderOptions = Roghainnean a' phasgain +Toolbar.ShowHiddenFiles = Faidhlichean is pasgain fhalaichte +Toolbar.ShowSystemFiles = Faidhlichean an t-siostaim +Toolbar.ShowExtensions = Leudachain ainmean nam faidhle +Status.FreeSpace = %s (Àire saor air an diosga: %s) +Status.Item = %s nì +Status.Items = %s nithean +Status.ItemSelected = %s nì air a thaghadh +Status.ItemsSelected = %s nithean air a thaghadh + + +[he-IL] - Hebrew (Israel) +Copy.Cancel = ביטול +Copy.More = עוד... +Copy.CopyHere = הע&תק לכאן +Copy.MoveHere = הע&בר לכאן +Copy.Title = אישור החלפת קובץ +Copy.Subtitle = תיקיה זו מכילה כבר קובץ בשם '‎‎%s‎‏'‏.‏ +Copy.SubtitleRO = תיקיה זו מכילה כבר קובץ המוגדר לקריאה בלבד בשם '‎‎%s‎‏'.‏ +Copy.SubtitleSys = תיקיה זו מכילה כבר קובץ מערכת בשם '‎‎%s‎'‏.‏ +Copy.Prompt1 = ‏‏האם ברצונך להחליף את הקובץ הקיים +Copy.Prompt2 = בקובץ זה? +Copy.Yes = &כן +Copy.No = &לא +Copy.YesAll = כ&ן לכל +Folder.Title = אישור החלפת תיקיה +Folder.Prompt = האם ברצונך להעביר או להעתיק את התיקיה בכל זאת? +Toolbar.GoUp = רמה אחת למעלה +Toolbar.Cut = גזור +Toolbar.Copy = העתק +Toolbar.Paste = הדבק +Toolbar.PasteShortcut = הדבק קיצור דרך +Toolbar.Delete = מחק +Toolbar.Email = שלח את הפריטים הנבחרים בדואר אלקטרוני +Toolbar.Properties = מאפיינים +Toolbar.NewFolder = תיקיה חדשה +Toolbar.ZipFolder = ‫תיקיה ‫דחוסה ‫(מכווצת) ‫חדשה +Toolbar.ExtraLarge = סמלים גדולים מאוד +Toolbar.Large = סמלים גדולים +Toolbar.Medium = סמלים בינוניים +Toolbar.Small = סמלים קטנים +Toolbar.List = רשימה +Toolbar.Details = פרטים +Toolbar.Tiles = משבצות +Toolbar.Content = תוכן +Toolbar.Undo = בטל +Toolbar.Redo = בצע שוב +Toolbar.Refresh = רענן +Toolbar.Back = אחורה +Toolbar.Forward = קדימה +Toolbar.Stop = עצור +Toolbar.Rename = שינוי שם +Toolbar.SelectAll = בחר הכל +Toolbar.CustomizeFolder = התאמה אישית של תיקיה זו +Toolbar.MapDrive = מיפוי כונן רשת +Toolbar.DisconnectDrive = ניתוק כונן רשת +Toolbar.NavigationPane = חלונית ניווט +Toolbar.DetailsPane = חלונית פרטים +Toolbar.PreviewPane = חלונית תצוגה מקדימה +Toolbar.CopyTo = העתק אל +Toolbar.MoveTo = העבר אל +Toolbar.Deselect = אל תבחר +Toolbar.InvertSelection = הפוך בחירה +Toolbar.FolderOptions = אפשרויות תיקיה +Toolbar.ShowHiddenFiles = קבצים ותיקיות מוסתרים +Toolbar.ShowSystemFiles = קבצי מערכת +Toolbar.ShowExtensions = סיומות שמות קבצים +Status.FreeSpace = %s (שטח פנוי בדיסק: %s) +Status.Item = ‏‏%s פריט +Status.Items = %s פריטים +Status.ItemSelected = פריט %s נבחר +Status.ItemsSelected = %s פריטים נבחרו + + +[hr-HR] - Croatian (Croatia) +Copy.DoForAll = Učini to za sljedećih +Copy.Cancel = Odustani +Copy.More = Više... +Copy.CopyHere = &Kopiraj ovdje +Copy.MoveHere = Pr&emjesti ovdje +Copy.Title = Potvrda zamjene datoteke +Copy.Subtitle = Ova mapa već sadrži datoteku naziva '%s'. +Copy.SubtitleRO = Ova mapa već sadrži datoteku samo za čitanje, nazvanu '%s'. +Copy.SubtitleSys = Ova mapa već sadrži sistemsku datoteku, nazvanu '%s'. +Copy.Prompt1 = Želite li zamijeniti postojeću datoteku +Copy.Prompt2 = s ovom? +Copy.Yes = &Da +Copy.No = &Ne +Copy.YesAll = Da za &sve +Folder.Title = Potvrda zamjene mape +Folder.Prompt = Želite li još uvijek premjestiti ili kopirati mapu? +Toolbar.GoUp = Jednu razinu gore +Toolbar.Cut = Izreži +Toolbar.Copy = Kopiraj +Toolbar.Paste = Zalijepi +Toolbar.PasteShortcut = Zalijepi prečac +Toolbar.Delete = Izbriši +Toolbar.Email = Odabrane stavke pošalji e-poštom +Toolbar.Properties = Svojstva +Toolbar.NewFolder = Nova mapa +Toolbar.ZipFolder = Nova komprimirana (zipana) mapa +Toolbar.ExtraLarge = Vrlo velike ikone +Toolbar.Large = Velike ikone +Toolbar.Medium = Srednje ikone +Toolbar.Small = Male ikone +Toolbar.List = Popis +Toolbar.Details = Detalji +Toolbar.Tiles = Pločice +Toolbar.Content = Sadržaj +Toolbar.Undo = Poništi +Toolbar.Redo = Ponovi +Toolbar.Refresh = Osvježi +Toolbar.Back = Natrag +Toolbar.Forward = Naprijed +Toolbar.Stop = Prekini +Toolbar.Rename = Preimenuj +Toolbar.SelectAll = Odaberi sve +Toolbar.CustomizeFolder = Prilagodi ovu mapu +Toolbar.MapDrive = Mapiranje mrežnog pogona +Toolbar.DisconnectDrive = Prekid veze s mrežnim pogonom +Toolbar.NavigationPane = Navigacijsko okno +Toolbar.DetailsPane = Okno s detaljima +Toolbar.PreviewPane = Okno pretpregleda +Toolbar.CopyTo = Kopiraj u +Toolbar.MoveTo = Premjesti u +Toolbar.Deselect = Bez odabira +Toolbar.InvertSelection = Obrni odabir +Toolbar.FolderOptions = Mogućnosti mapa +Toolbar.ShowHiddenFiles = Skrivene datoteke i mape +Toolbar.ShowSystemFiles = Sistemske datoteke +Toolbar.ShowExtensions = Datotečni nastavci +Status.FreeSpace = %s (slobodan prostor na disku: %s) +Status.Item = %s stavka +Status.Items = Broj stavki: %s +Status.ItemSelected = Odabrano stavki: %s +Status.ItemsSelected = Odabrano stavki: %s + + +[hu-HU] - Hungarian (Hungary) +Copy.Cancel = Mégse +Copy.More = Egyebek... +Copy.CopyHere = Más&olás ide +Copy.MoveHere = Át&helyezés ide +Copy.Title = Fájlcsere megerősítése +Copy.Subtitle = A mappa már tartalmaz egy '%s' nevű fájlt. +Copy.SubtitleRO = Ez a mappa már tartalmaz egy '%s' nevű írásvédett fájlt. +Copy.SubtitleSys = Ez a mappa már tartalmaz egy '%s' nevű rendszerfájlt. +Copy.Prompt1 = Kicseréli a létező fájlt +Copy.Prompt2 = ezzel? +Copy.Yes = &Igen +Copy.No = &Nem +Copy.YesAll = Igen, &mindet +Folder.Title = Mappacsere megerősítése +Folder.Prompt = Folytatja a műveletet? +Toolbar.GoUp = Egy szinttel feljebb +Toolbar.Cut = Kivágás +Toolbar.Copy = Másolás +Toolbar.Paste = Beillesztés +Toolbar.PasteShortcut = Parancsikon beillesztése +Toolbar.Delete = Törlés +Toolbar.Email = A kijelölt elemek elküldése e-mailben +Toolbar.Properties = Tulajdonságok +Toolbar.NewFolder = Új mappa +Toolbar.ZipFolder = Új tömörített mappa +Toolbar.ExtraLarge = Extra nagy ikonok +Toolbar.Large = Nagy ikonok +Toolbar.Medium = Közepes ikonok +Toolbar.Small = Kis ikonok +Toolbar.List = Lista +Toolbar.Details = Részletek +Toolbar.Tiles = Mozaik +Toolbar.Content = Tartalom +Toolbar.Undo = Visszavonás +Toolbar.Redo = Mégis +Toolbar.Refresh = Frissítés +Toolbar.Back = Vissza +Toolbar.Forward = Előre +Toolbar.Stop = Leállítás +Toolbar.Rename = Átnevezés +Toolbar.SelectAll = Az összes kijelölése +Toolbar.CustomizeFolder = Mappa testreszabása +Toolbar.MapDrive = Hálózati meghajtó csatlakoztatása +Toolbar.DisconnectDrive = Hálózati meghajtó leválasztása +Toolbar.NavigationPane = Navigációs ablak +Toolbar.DetailsPane = Részletek ablaktábla +Toolbar.PreviewPane = Betekintő ablaktábla +Toolbar.CopyTo = Másolási cél +Toolbar.MoveTo = Áthelyezési cél +Toolbar.Deselect = Kijelölés megszüntetése +Toolbar.InvertSelection = Kijelölés megfordítása +Toolbar.FolderOptions = Mappa beállításai +Toolbar.ShowHiddenFiles = Rejtett fájlok és mappák +Toolbar.ShowSystemFiles = Rendszerfájlok +Toolbar.ShowExtensions = Fájlnévkiterjesztések +Status.FreeSpace = %s (szabad lemezterület: %s) +Status.Item = %s elem +Status.Items = %s elem +Status.ItemSelected = %s kijelölt elem +Status.ItemsSelected = %s kijelölt elem + + +[is-IS] - Icelandic (Iceland) +Toolbar.Settings = Classic Explorer stillingar +Copy.Cancel = Hætta við +Copy.More = Meira... +Copy.CopyHere = &Afrita hingað +Copy.MoveHere = &Færa hingað +Copy.Title = Skipta út skrá +Copy.Subtitle = Endastaðurinn inniheldur þegar skrá með heitinu '%s'. +Copy.SubtitleRO = Endastaðurinn inniheldur þegar skrifvarða skrá með heitinu '%s'. +Copy.SubtitleSys = Endastaðurinn inniheldur þegar stýrikerfisskrá með heitinu '%s'. +Copy.Prompt1 = Viltu skipta út skránni á endastaðnum +Copy.Prompt2 = fyrir þessa skrá? +Copy.Yes = &Já +Copy.No = &Nei +Copy.YesAll = Já við &öllu +Folder.Title = Skipta út möppu +Folder.Prompt = Ertu viss um að þú viljir færa eða afrita möppuna? +Toolbar.GoUp = Upp um eitt þrep +Toolbar.Cut = Klippa +Toolbar.Copy = Afrita +Toolbar.Paste = Líma +Toolbar.PasteShortcut = Líma flýtileið +Toolbar.Delete = Eyða +Toolbar.Email = Senda valin atriði með tölvupósti +Toolbar.Properties = Eiginleikar +Toolbar.NewFolder = Ný mappa +Toolbar.ZipFolder = Ný þjöppuð (zip-þjöppuð) mappa +Toolbar.ExtraLarge = Mjög stór tákn +Toolbar.Large = Stór tákn +Toolbar.Medium = Meðalstór tákn +Toolbar.Small = Lítil tákn +Toolbar.List = Listi +Toolbar.Details = Upplýsingar +Toolbar.Tiles = Reitir +Toolbar.Content = Efni +Toolbar.Undo = Afturkalla +Toolbar.Redo = Endurgera +Toolbar.Refresh = Endurhlaða +Toolbar.Back = Til baka +Toolbar.Forward = Áfram +Toolbar.Stop = Stöðva +Toolbar.Rename = Endurnefna +Toolbar.SelectAll = Velja allt +Toolbar.CustomizeFolder = Sérstilla þessa möppu +Toolbar.MapDrive = Tengja netdrif +Toolbar.DisconnectDrive = Aftengja netdrif +Toolbar.NavigationPane = Yfirlitssvæði +Toolbar.DetailsPane = Upplýsingasvæði +Toolbar.PreviewPane = Forskoðunarsvæði +Toolbar.CopyTo = Afrita til +Toolbar.MoveTo = Færa til +Toolbar.Deselect = Velja ekkert +Toolbar.InvertSelection = Umsnúa vali +Toolbar.FolderOptions = Möppuvalkostir +Toolbar.ShowHiddenFiles = Faldar skrár og möppur +Toolbar.ShowSystemFiles = Kerfisskrár +Toolbar.ShowExtensions = Skráarendingar +Status.FreeSpace = %s (laust pláss: %s) +Status.Item = %s atriði +Status.Items = %s atriði +Status.ItemSelected = %s atriði valin +Status.ItemsSelected = %s atriði valin + + +[it-IT] - Italian (Italy) +Copy.Cancel = Annulla +Copy.More = Altro... +Copy.CopyHere = &Copia qui +Copy.MoveHere = &Sposta qui +Copy.Title = Conferma sostituzione file +Copy.Subtitle = La cartella contiene già un file di nome "%s". +Copy.SubtitleRO = La cartella contiene già un file di sola lettura di nome "%s". +Copy.SubtitleSys = La cartella contiene già un file di sistema di nome "%s". +Copy.Prompt1 = Sostituire il file esistente +Copy.Prompt2 = con questo file? +Copy.Yes = &Sì +Copy.No = &No +Copy.YesAll = Sì t&utti +Folder.Title = Conferma sostituzione cartella +Folder.Prompt = Continuare? +Toolbar.GoUp = Livello superiore +Toolbar.Cut = Taglia +Toolbar.Copy = Copia +Toolbar.Paste = Incolla +Toolbar.PasteShortcut = Incolla collegamento +Toolbar.Delete = Elimina +Toolbar.Email = Invia per posta elettronica gli elementi selezionati +Toolbar.Properties = Proprietà +Toolbar.NewFolder = Nuova cartella +Toolbar.ZipFolder = Nuova cartella compressa +Toolbar.ExtraLarge = Icone molto grandi +Toolbar.Large = Icone grandi +Toolbar.Medium = Icone medie +Toolbar.Small = Icone piccole +Toolbar.List = Elenco +Toolbar.Details = Dettagli +Toolbar.Tiles = Titoli +Toolbar.Content = Contenuto +Toolbar.Undo = Annulla +Toolbar.Redo = Ripeti +Toolbar.Refresh = Aggiorna +Toolbar.Back = Indietro +Toolbar.Forward = Avanti +Toolbar.Stop = Termina +Toolbar.Rename = Rinomina +Toolbar.SelectAll = Seleziona tutto +Toolbar.CustomizeFolder = Personalizza cartella +Toolbar.MapDrive = Connetti unità di rete +Toolbar.DisconnectDrive = Disconnetti unità di rete +Toolbar.NavigationPane = Riquadro di spostamento +Toolbar.DetailsPane = Riquadro dettagli +Toolbar.PreviewPane = Riquadro di anteprima +Toolbar.CopyTo = Copia in +Toolbar.MoveTo = Sposta in +Toolbar.Deselect = Deseleziona tutto +Toolbar.InvertSelection = Inverti selezione +Toolbar.FolderOptions = Opzioni cartella +Toolbar.ShowHiddenFiles = Cartelle e file nascosti +Toolbar.ShowSystemFiles = File di sistema +Toolbar.ShowExtensions = Estensioni nomi file +Status.FreeSpace = %s (Spazio disponibile: %s) +Status.Item = %s elemento +Status.Items = Elementi: %s +Status.ItemSelected = %s elemento selezionato +Status.ItemsSelected = %s elementi selezionati + + +[ja-JP] - Japanese (Japan) +Copy.Cancel = キャンセル +Copy.More = その他... +Copy.CopyHere = ここにコピー(&C) +Copy.MoveHere = ここに移動(&M) +Copy.Title = ファイルの上書きの確認 +Copy.Subtitle = このフォルダには既に '%s' ファイルが存在します。 +Copy.SubtitleRO = このフォルダには既に読み取り専用ファイル '%s' が含まれています。 +Copy.SubtitleSys = このフォルダには既にシステム ファイル '%s' が含まれています。 +Copy.Prompt1 = 現在のファイル +Copy.Prompt2 = を次の新しいファイルで置き換えますか? +Copy.Yes = はい(&Y) +Copy.No = いいえ(&N) +Copy.YesAll = すべて上書き(&A) +Folder.Title = フォルダの上書きの確認 +Folder.Prompt = フォルダを移動またはコピーしますか? +Toolbar.GoUp = 1 つ上のフォルダへ +Toolbar.Cut = 切り取り +Toolbar.Copy = コピー +Toolbar.Paste = 貼り付け +Toolbar.PasteShortcut = ショートカットの貼り付け +Toolbar.Delete = 削除 +Toolbar.Email = 選択した項目を電子メールで送信する +Toolbar.Properties = プロパティ +Toolbar.NewFolder = 新しいフォルダ +Toolbar.ZipFolder = 新しい圧縮された (ZIP) フォルダー +Toolbar.ExtraLarge = 特大アイコン +Toolbar.Large = 大アイコン +Toolbar.Medium = 中アイコン +Toolbar.Small = 小アイコン +Toolbar.List = 一覧 +Toolbar.Details = 詳細 +Toolbar.Tiles = 並べて表示 +Toolbar.Content = コンテンツ +Toolbar.Undo = 元に戻す +Toolbar.Redo = やり直し +Toolbar.Refresh = 最新の情報に更新 +Toolbar.Back = 戻る +Toolbar.Forward = 進む +Toolbar.Stop = 中止 +Toolbar.Rename = 名前の変更 +Toolbar.SelectAll = すべて選択 +Toolbar.CustomizeFolder = このフォルダーのカスタマイズ +Toolbar.MapDrive = ネットワーク ドライブの割り当て +Toolbar.DisconnectDrive = ネットワーク ドライブの切断 +Toolbar.NavigationPane = ナビゲーション ウィンドウ +Toolbar.DetailsPane = 詳細ウィンドウ +Toolbar.PreviewPane = プレビュー ウィンドウ +Toolbar.CopyTo = コピー先​​ +Toolbar.MoveTo = 移動先​​ +Toolbar.Deselect = 選択解除 +Toolbar.InvertSelection = 選択の切り替え +Toolbar.FolderOptions = フォルダー オプション +Toolbar.ShowHiddenFiles = ファイルとフォルダーの表示 +Toolbar.ShowSystemFiles = システム ファイル +Toolbar.ShowExtensions = ファイル名拡張子 +Status.FreeSpace = %s (空きディスク領域: %s) +Status.Item = %s 個 +Status.Items = %s 個の項目 +Status.ItemSelected = %s 個の項目を選択 +Status.ItemsSelected = %s 個の項目を選択 + + +[ko-KR] - Korean (Korea) +Copy.Cancel = 취소 +Copy.More = 자세히... +Copy.CopyHere = 여기에 복사(&C) +Copy.MoveHere = 여기로 이동(&M) +Copy.Title = 파일 바꾸기 확인 +Copy.Subtitle = 이 폴더에 이미 '%s' 파일이 있습니다. +Copy.SubtitleRO = 이 폴더에 이미 '%s' 읽기 전용 파일이 있습니다. +Copy.SubtitleSys = 이 폴더에 이미 '%s' 시스템 파일이 있습니다. +Copy.Prompt1 = 기존 파일을 +Copy.Prompt2 = 이 파일로 바꾸시겠습니까? +Copy.Yes = 예(&Y) +Copy.No = 아니오(&N) +Copy.YesAll = 모두 예(&A) +Folder.Title = 폴더 바꾸기 확인 +Folder.Prompt = 폴더를 이동하거나 복사하시겠습니까? +Toolbar.GoUp = 한 수준 위로 +Toolbar.Cut = 잘라내기 +Toolbar.Copy = 복사 +Toolbar.Paste = 붙여넣기 +Toolbar.PasteShortcut = 바로 가기 붙여넣기 +Toolbar.Delete = 삭제 +Toolbar.Email = 항목을 전자 메일로 보내기 +Toolbar.Properties = 속성 +Toolbar.NewFolder = 새 폴더 +Toolbar.ZipFolder = 새 압축(ZIP) 폴더 +Toolbar.ExtraLarge = 아주 큰 아이콘 +Toolbar.Large = 큰 아이콘 +Toolbar.Medium = 보통 아이콘 +Toolbar.Small = 작은 아이콘 +Toolbar.List = 목록 +Toolbar.Details = 자세히 +Toolbar.Tiles = 나란히 보기 +Toolbar.Content = 내용 +Toolbar.Undo = 실행 취소 +Toolbar.Redo = 다시 실행 +Toolbar.Refresh = 새로 고침 +Toolbar.Back = 뒤로 +Toolbar.Forward = 앞으로 +Toolbar.Stop = 중지 +Toolbar.Rename = 이름 바꾸기 +Toolbar.SelectAll = 모두 선택 +Toolbar.CustomizeFolder = 현재 폴더 사용자 지정 +Toolbar.MapDrive = 네트워크 드라이브 연결 +Toolbar.DisconnectDrive = 네트워크 드라이브 연결 끊기 +Toolbar.NavigationPane = 탐색 창 +Toolbar.DetailsPane = 세부 정보 창 +Toolbar.PreviewPane = 미리 보기 창 +Toolbar.CopyTo = 복사 위치 +Toolbar.MoveTo = 이동 위치 +Toolbar.Deselect = 선택 안 함 +Toolbar.InvertSelection = 선택 영역 반전 +Toolbar.FolderOptions = 폴더 옵션 +Toolbar.ShowHiddenFiles = 숨김 파일 및 폴더 +Toolbar.ShowSystemFiles = 시스템 파일 +Toolbar.ShowExtensions = 파일 확장명 +Status.FreeSpace = %s (빈 디스크 공간: %s) +Status.Item = %s 항목 +Status.Items = %s 항목 +Status.ItemSelected = %s개 항목을 선택했습니다. +Status.ItemsSelected = %s개 항목을 선택했습니다. + + +[lt-LT] - Lithuanian (Lithuania) +Copy.Cancel = Atšaukti +Copy.More = Daugiau... +Copy.CopyHere = &Kopijuoti čia +Copy.MoveHere = &Perkelti čia +Copy.Title = Patvirtinti failo pakeitimą +Copy.Subtitle = Šiame aplanke jau yra failas, pavadintas '%s'. +Copy.SubtitleRO = Aplanke jau yra failas, skirtas tik skaityti, pavadintas '%s'. +Copy.SubtitleSys = Aplanke jau yra sistemos failas, pavadintas '%s'. +Copy.Prompt1 = Ar pakeisti esamą failą +Copy.Prompt2 = šiuo? +Copy.Yes = &Taip +Copy.No = &Ne +Copy.YesAll = Taip &viskam +Folder.Title = Patvirtinti aplanko pakeitimą +Folder.Prompt = Ar vis tiek perkelti, ar kopijuoti aplanką? +Toolbar.GoUp = Vienu lygiu aukščiau +Toolbar.Cut = Iškirpti +Toolbar.Copy = Kopijuoti +Toolbar.Paste = Įklijuoti +Toolbar.PasteShortcut = Įklijuoti nuorodą +Toolbar.Delete = Naikinti +Toolbar.Email = Pažymėtus elementus siųsti el. paštu +Toolbar.Properties = Ypatybės +Toolbar.NewFolder = Naujas aplankas +Toolbar.ZipFolder = Naujas suglaudintas (zip) aplankas +Toolbar.ExtraLarge = Padidintos piktogramos +Toolbar.Large = Didelės piktogramos +Toolbar.Medium = Vidutinės piktogramos +Toolbar.Small = Mažos piktogramos +Toolbar.List = Sąrašas +Toolbar.Details = Išsami informacija +Toolbar.Tiles = Išklotinės +Toolbar.Content = Turinys +Toolbar.Undo = Anuliuoti +Toolbar.Redo = Perdaryti +Toolbar.Refresh = Atnaujinti +Toolbar.Back = Atgal į: +Toolbar.Forward = Pirmyn +Toolbar.Stop = Stabdyti +Toolbar.Rename = Pervardyti +Toolbar.SelectAll = Žymėti viską +Toolbar.CustomizeFolder = Tinkinti šį aplanką +Toolbar.MapDrive = Susieti tinklo diską +Toolbar.DisconnectDrive = Atjungti tinklo diską +Toolbar.NavigationPane = Naršymo sritis +Toolbar.DetailsPane = Išsamios informacijos sritis +Toolbar.PreviewPane = Peržiūros sritis +Toolbar.CopyTo = Kopijuoti į +Toolbar.MoveTo = Perkelti į +Toolbar.Deselect = Nieko nežymėti +Toolbar.InvertSelection = Žymėti priešingai +Toolbar.FolderOptions = Aplanko parinktys +Toolbar.ShowHiddenFiles = Paslėpti failai ir aplankai +Toolbar.ShowSystemFiles = Sistemos failai +Toolbar.ShowExtensions = Failų vardų plėtiniai +Status.FreeSpace = %s (Diske laisvos vietos: %s) +Status.Item = %s elementas +Status.Items = %s elementai +Status.ItemSelected = %s pažymėtas elementas +Status.ItemsSelected = Pažymėta elementų: %s + + +[lv-LV] - Latvian (Latvia) +Copy.Cancel = Atcelt +Copy.More = Vēl... +Copy.CopyHere = &Kopēt šeit +Copy.MoveHere = &Pārvietot šeit +Copy.Title = Failu aizstāšanas apstiprināšana +Copy.Subtitle = Šajā mapē jau ir fails '%s'. +Copy.SubtitleRO = Šajā mapē jau ir tikai lasāms fails '%s'. +Copy.SubtitleSys = Šajā mapē jau ir sistēmas fails '%s'. +Copy.Prompt1 = Vai vēlaties aizstāt esošo failu +Copy.Prompt2 = ar šo? +Copy.Yes = &Jā +Copy.No = &Nē +Copy.YesAll = Jā, &visus +Folder.Title = Mapju aizstāšanas apstiprināšana +Folder.Prompt = Vai tiešām vēlaties pārvietot vai kopēt šo mapi? +Toolbar.GoUp = Vienu līmeni augstāk +Toolbar.Cut = Izgriezt +Toolbar.Copy = Kopēt +Toolbar.Paste = Ielīmēt +Toolbar.PasteShortcut = Ielīmēt saīsni +Toolbar.Delete = Dzēst +Toolbar.Email = Nosūtīt atlasītos vienumus pa e-pastu +Toolbar.Properties = Rekvizīti +Toolbar.NewFolder = Jauna mape +Toolbar.ZipFolder = Jauna saspiestā (tilpsaspiestā) mape +Toolbar.ExtraLarge = Ļoti lielas ikonas +Toolbar.Large = Lielas ikonas +Toolbar.Medium = Vidējas ikonas +Toolbar.Small = Mazas ikonas +Toolbar.List = Saraksts +Toolbar.Details = Detaļas +Toolbar.Tiles = Mozaīka +Toolbar.Content = Saturs +Toolbar.Undo = Atsaukt +Toolbar.Redo = Atcelt atsaukšanu +Toolbar.Refresh = Atsvaidzināt +Toolbar.Back = Atpakaļ +Toolbar.Forward = Uz priekšu +Toolbar.Stop = Apturēt +Toolbar.Rename = Pārdēvēt +Toolbar.SelectAll = Atlasīt visus +Toolbar.CustomizeFolder = Pielāgot šo mapi +Toolbar.MapDrive = Kartēt tīkla disku +Toolbar.DisconnectDrive = Atvienot tīkla disku +Toolbar.NavigationPane = Navigācijas rūts +Toolbar.DetailsPane = Detalizētas informācijas rūts +Toolbar.PreviewPane = Priekšskatījuma rūts +Toolbar.CopyTo = Kopēt uz +Toolbar.MoveTo = Pārvietot uz +Toolbar.Deselect = Neatlasīt neko +Toolbar.InvertSelection = Mainīt atlasi uz pretējo +Toolbar.FolderOptions = Mapes opcijas +Toolbar.ShowHiddenFiles = Slēptie faili un mapes +Toolbar.ShowSystemFiles = Sistēmas faili +Toolbar.ShowExtensions = Failu nosaukumu paplašinājumi +Status.FreeSpace = %s (brīvā vieta diskā: %s) +Status.Item = %s vienums +Status.Items = %s vienumi +Status.ItemSelected = Atlasīts %s vienums +Status.ItemsSelected = Atlasīti %s vienumi + + +[mk-MK] - Macedonian (Macedonia) +Copy.Cancel = Откажи +Copy.More = Повеќе... +Copy.CopyHere = Копирај тука +Copy.MoveHere = Премести тука +Copy.Title = Потврди замена на фајл +Copy.Subtitle = Тој фолдер веќе содржи фајл со име '%s'. +Copy.SubtitleRO = Тој фолдер веќе содржи фајл само за читање со име '%s'. +Copy.SubtitleSys = Тој фолдер веќе содржи системски фајл со име '%s'. +Copy.Prompt1 = Дали сакате да замените постоечкиот фајл +Copy.Prompt2 = а тој? +Copy.Yes = Да +Copy.No = Не +Copy.YesAll = "Да" за сите +Folder.Title = Потврда за промена на фолдерот +Folder.Prompt = Сеуште ли сакате да го преместите или копирате фолдерот? +Toolbar.GoUp = Едно ниво нагоре +Toolbar.Cut = Исечи +Toolbar.Copy = Копирај +Toolbar.Paste = Стави +Toolbar.PasteShortcut = Стави краток пат +Toolbar.Delete = Избриши +Toolbar.Email = Испрати ги селектираните фајлови по електронска пошта +Toolbar.Properties = Својства +Toolbar.NewFolder = Нов фолдер +Toolbar.ZipFolder = Нова компресирана (зипувана) папка +Toolbar.ExtraLarge = Многу големи икони +Toolbar.Large = Големи икони +Toolbar.Medium = Средни икони +Toolbar.Small = Мали икони +Toolbar.List = Список +Toolbar.Details = Детали +Toolbar.Tiles = Мозаик +Toolbar.Content = Содржина +Toolbar.Undo = врати +Toolbar.Redo = повтори +Toolbar.Refresh = Обнови +Toolbar.Back = Назад +Toolbar.Forward = Напред +Toolbar.Stop = Застани +Toolbar.Rename = Преименување +Toolbar.SelectAll = Селектирај ги сите +Toolbar.CustomizeFolder = Персонализирање на тој фолдер +Toolbar.MapDrive = Назначување на мрежен уред +Toolbar.DisconnectDrive = Исклучи го мрежниот уред +Toolbar.NavigationPane = Навигационен екран +Toolbar.DetailsPane = Екран за подетални податоци +Toolbar.PreviewPane = Прозорец за визуализација +Toolbar.CopyTo = Копирај во +Toolbar.MoveTo = Премести во +Toolbar.Deselect = Не избирај ништо +Toolbar.InvertSelection = Преврти го изборот +Toolbar.FolderOptions = Опции за папка +Toolbar.ShowHiddenFiles = Сокриени датотеки и папки +Toolbar.ShowSystemFiles = Системски датотеки +Toolbar.ShowExtensions = Датотечни наставки +Status.FreeSpace = %s (Слободно место на дискот: %s) +Status.Item = %s фајл +Status.Items = %s фајлови +Status.ItemSelected = %s селектиран фајл +Status.ItemsSelected = %s селектирани фајлови + + +[nb-NO] - Norwegian, Bokmål (Norway) +Copy.Cancel = Avbryt +Copy.More = Mer... +Copy.CopyHere = &Kopier hit +Copy.MoveHere = &Flytt hit +Copy.Title = Bekreft erstatting av fil +Copy.Subtitle = Mappen inneholder allerede filen %s. +Copy.SubtitleRO = Mappen inneholder allerede den skrivebeskyttede filen %s. +Copy.SubtitleSys = Mappen inneholder allerede systemfilen %s. +Copy.Prompt1 = Vil du erstatte den eksisterende filen +Copy.Prompt2 = med denne? +Copy.Yes = &Ja +Copy.No = &Nei +Copy.YesAll = J&a til alt +Folder.Title = Bekreft erstatting av mappe +Folder.Prompt = Vil du likevel flytte eller kopiere mappen? +Toolbar.GoUp = Opp ett nivå +Toolbar.Cut = Klipp ut +Toolbar.Copy = Kopier +Toolbar.Paste = Lim inn +Toolbar.PasteShortcut = Lim inn snarvei +Toolbar.Delete = Slett +Toolbar.Email = Send valgte elementer via e-post +Toolbar.Properties = Egenskaper +Toolbar.NewFolder = Ny mappe +Toolbar.ZipFolder = Ny komprimert (zippet) mappe +Toolbar.ExtraLarge = Ekstra store ikoner +Toolbar.Large = Store ikoner +Toolbar.Medium = Middels store ikoner +Toolbar.Small = Små ikoner +Toolbar.List = Liste +Toolbar.Details = Detaljer +Toolbar.Tiles = Side ved side +Toolbar.Content = Innhold +Toolbar.Undo = Angre +Toolbar.Redo = Gjør om +Toolbar.Refresh = Oppdater +Toolbar.Back = Tilbake +Toolbar.Forward = Fremover +Toolbar.Stop = Stopp +Toolbar.Rename = Gi nytt navn +Toolbar.SelectAll = Merk alt +Toolbar.CustomizeFolder = Tilpass denne mappen +Toolbar.MapDrive = Koble til nettverksstasjon +Toolbar.DisconnectDrive = Koble fra nettverksstasjon +Toolbar.NavigationPane = Navigasjonsrute +Toolbar.DetailsPane = Detaljrute +Toolbar.PreviewPane = Forhåndsvisningsrute +Toolbar.CopyTo = Kopier til +Toolbar.MoveTo = Flytt til +Toolbar.Deselect = Merk ingenting +Toolbar.InvertSelection = Inverter utvalg +Toolbar.FolderOptions = Mappealternativer +Toolbar.ShowHiddenFiles = Skjulte filer og mapper +Toolbar.ShowSystemFiles = Systemfiler +Toolbar.ShowExtensions = Filtyper +Status.FreeSpace = %s (Ledig plass på disken: %s) +Status.Item = %s element +Status.Items = %s elementer +Status.ItemSelected = %s element er merket +Status.ItemsSelected = %s elementer er merket + + +[nl-NL] - Dutch (Netherlands) +Copy.Cancel = Annuleren +Copy.More = Meer... +Copy.CopyHere = Hierheen &kopiëren +Copy.MoveHere = Hi&erheen verplaatsen +Copy.Title = Vervangen van bestand bevestigen +Copy.Subtitle = In deze map bevindt zich al een bestand met de naam %s. +Copy.SubtitleRO = In deze map bevindt zich al een bestand met het kenmerk Alleen-lezen en de naam %s. +Copy.SubtitleSys = In deze map bevindt zich al een systeembestand met de naam %s. +Copy.Prompt1 = Wilt u het bestaande bestand: +Copy.Prompt2 = vervangen door het onderstaande bestand? +Copy.Yes = &Ja +Copy.No = &Nee +Copy.YesAll = J&a op alles +Folder.Title = Vervangen van map bevestigen +Folder.Prompt = Wilt u de bestanden in de bestaande map vervangen door de bestanden in de map die u verplaatst of kopieert, als de bestanden dezelfde naam hebben? +Toolbar.GoUp = Bovenliggende map +Toolbar.Cut = Knippen +Toolbar.Copy = Kopiëren +Toolbar.Paste = Plakken +Toolbar.PasteShortcut = Snelkoppeling plakken +Toolbar.Delete = Verwijderen +Toolbar.Email = De geselecteerde items per e-mail verzenden +Toolbar.Properties = Eigenschappen +Toolbar.NewFolder = Nieuwe map +Toolbar.ZipFolder = Nieuwe gecomprimeerde (gezipte) map +Toolbar.ExtraLarge = Extra grote pictogrammen +Toolbar.Large = Grote pictogrammen +Toolbar.Medium = Normale pictogrammen +Toolbar.Small = Kleine pictogrammen +Toolbar.List = Lijst +Toolbar.Details = Details +Toolbar.Tiles = Tegels +Toolbar.Content = Inhoud +Toolbar.Undo = Ongedaan maken +Toolbar.Redo = Opnieuw +Toolbar.Refresh = Vernieuwen +Toolbar.Back = Vorige +Toolbar.Forward = Volgende +Toolbar.Stop = Stoppen +Toolbar.Rename = Naam wijzigen +Toolbar.SelectAll = Alles selecteren +Toolbar.CustomizeFolder = Deze map aanpassen +Toolbar.MapDrive = Netwerkverbinding maken +Toolbar.DisconnectDrive = Netwerkverbinding verbreken +Toolbar.NavigationPane = Navigatievenster +Toolbar.DetailsPane = Detailvenster +Toolbar.PreviewPane = Voorbeeldvenster +Toolbar.CopyTo = Kopiëren naar +Toolbar.MoveTo = Verplaatsen naar +Toolbar.Deselect = Niets selecteren +Toolbar.InvertSelection = Selectie omkeren +Toolbar.FolderOptions = Mapopties +Toolbar.ShowHiddenFiles = Verborgen bestanden en mappen +Toolbar.ShowSystemFiles = Systeembestanden +Toolbar.ShowExtensions = Bestandsnaamextensies +Status.FreeSpace = %s (beschikbare schijfruimte: %s) +Status.Item = %s item +Status.Items = %s items +Status.ItemSelected = %s item geselecteerd +Status.ItemsSelected = %s items geselecteerd + + +[pl-PL] - Polish (Poland) +Copy.Cancel = Anuluj +Copy.More = Więcej... +Copy.CopyHere = &Kopiuj tutaj +Copy.MoveHere = Prze&nieś tutaj +Copy.Title = Potwierdź zamianę pliku +Copy.Subtitle = Ten folder zawiera już plik o nazwie „%s”. +Copy.SubtitleRO = Ten folder zawiera już plik tylko do odczytu o nazwie „%s”. +Copy.SubtitleSys = Ten folder zawiera już plik systemowy o nazwie „%s”. +Copy.Prompt1 = Czy chcesz zamienić istniejący plik +Copy.Prompt2 = na następujący? +Copy.Yes = &Tak +Copy.No = &Nie +Copy.YesAll = Tak na &wszystkie +Folder.Title = Potwierdź zamianę folderu +Folder.Prompt = Czy nadal chcesz przenieść lub skopiować ten folder? +Toolbar.GoUp = Do góry o jeden poziom +Toolbar.Cut = Wytnij +Toolbar.Copy = Kopiuj +Toolbar.Paste = Wklej +Toolbar.PasteShortcut = Wklej skrót +Toolbar.Delete = Usuń +Toolbar.Email = Wyślij zaznaczone elementy pocztą e-mail +Toolbar.Properties = Właściwości +Toolbar.NewFolder = Nowy folder +Toolbar.ZipFolder = Nowy folder skompresowany (zip) +Toolbar.ExtraLarge = Bardzo duże ikony +Toolbar.Large = Duże ikony +Toolbar.Medium = Średnie ikony +Toolbar.Small = Małe ikony +Toolbar.List = Lista +Toolbar.Details = Szczegóły +Toolbar.Tiles = Kafelki +Toolbar.Content = Zawartość +Toolbar.Undo = Cofnij +Toolbar.Redo = Wykonaj ponownie +Toolbar.Refresh = Odśwież +Toolbar.Back = Wstecz +Toolbar.Forward = Dalej +Toolbar.Stop = Zatrzymaj +Toolbar.Rename = Zmień nazwę +Toolbar.SelectAll = Zaznacz wszystko +Toolbar.CustomizeFolder = Dostosuj ten folder +Toolbar.MapDrive = Mapuj dysk sieciowy +Toolbar.DisconnectDrive = Odłącz dysk sieciowy +Toolbar.NavigationPane = Okienko nawigacji +Toolbar.DetailsPane = Okienko szczegółów +Toolbar.PreviewPane = Okienko podglądu +Toolbar.CopyTo = Kopiuj do +Toolbar.MoveTo = Przenieś do +Toolbar.Deselect = Nie zaznaczaj nic +Toolbar.InvertSelection = Odwróć zaznaczenie +Toolbar.FolderOptions = Opcje folderów +Toolbar.ShowHiddenFiles = Ukryte pliki i foldery +Toolbar.ShowSystemFiles = Pliki systemowe +Toolbar.ShowExtensions = Rozszerzenia nazw plików +Status.FreeSpace = %s (Wolne miejsce: %s) +Status.Item = %s element +Status.Items = Elementów: %s +Status.ItemSelected = Wybranych elementów: %s +Status.ItemsSelected = Wybranych elementów: %s + + +[pt-BR] - Portuguese (Brazil) +Copy.Cancel = Cancelar +Copy.More = Mais... +Copy.CopyHere = &Copiar Aqui +Copy.MoveHere = Mov&er para Cá +Copy.Title = Confirmar substituição de arquivo +Copy.Subtitle = Esta pasta já contém um arquivo chamado '%s'. +Copy.SubtitleRO = Esta pasta já contém um arquivo somente leitura chamado '%s'. +Copy.SubtitleSys = Esta pasta já contém um arquivo de sistema chamado '%s'. +Copy.Prompt1 = Deseja substituir o arquivo existente +Copy.Prompt2 = por este? +Copy.Yes = &Sim +Copy.No = &Não +Copy.YesAll = Sim para &todos +Folder.Title = Confirmar substituição de pasta +Folder.Prompt = Deseja mover a pasta mesmo assim? +Toolbar.GoUp = Um Nível Acima +Toolbar.Cut = Recortar +Toolbar.Copy = Copiar +Toolbar.Paste = Colar +Toolbar.PasteShortcut = Colar Atalho +Toolbar.Delete = Excluir +Toolbar.Email = Enviar os itens selecionados por email +Toolbar.Properties = Propriedades +Toolbar.NewFolder = Nova Pasta +Toolbar.ZipFolder = Nova Pasta Compactada +Toolbar.ExtraLarge = Ícones Extra Grandes +Toolbar.Large = Ícones Grandes +Toolbar.Medium = Ícones Médios +Toolbar.Small = Ícones Pequenos +Toolbar.List = Lista +Toolbar.Details = Detalhes +Toolbar.Tiles = Lado a Lado +Toolbar.Content = Conteúdo +Toolbar.Undo = Desfazer +Toolbar.Redo = Refazer +Toolbar.Refresh = Atualizar +Toolbar.Back = Voltar +Toolbar.Forward = Avançar +Toolbar.Stop = Parar +Toolbar.Rename = Renomear +Toolbar.SelectAll = Selecionar tudo +Toolbar.CustomizeFolder = Personalizar esta pasta +Toolbar.MapDrive = Mapear unidade de rede +Toolbar.DisconnectDrive = Desconectar unidade de rede +Toolbar.NavigationPane = Painel de navegação +Toolbar.DetailsPane = Painel de detalhes +Toolbar.PreviewPane = Painel de visualização +Toolbar.CopyTo = Copiar para +Toolbar.MoveTo = Mover para +Toolbar.Deselect = Selecionar nenhum +Toolbar.InvertSelection = Inverter seleção +Toolbar.FolderOptions = Opções de pasta +Toolbar.ShowHiddenFiles = Pastas e arquivos ocultos +Toolbar.ShowSystemFiles = Arquivos do sistema +Toolbar.ShowExtensions = Extensões de nomes de arquivos +Status.FreeSpace = %s (espaço livre em disco: %s) +Status.Item = %s item +Status.Items = %s itens +Status.ItemSelected = %s item selecionado +Status.ItemsSelected = %s itens selecionados + + +[pt-PT] - Portuguese (Portugal) +Copy.Cancel = Cancelar +Copy.More = Mais... +Copy.CopyHere = &Copiar para aqui +Copy.MoveHere = &Mover para aqui +Copy.Title = Confirmar substituição de ficheiro(s) +Copy.Subtitle = Esta pasta já contém um ficheiro com o nome '%s'. +Copy.SubtitleRO = Esta pasta já contém um ficheiro só de leitura com o nome '%s'. +Copy.SubtitleSys = Esta pasta já contém um ficheiro de sistema com o nome '%s'. +Copy.Prompt1 = Pretende substituir o ficheiro existente +Copy.Prompt2 = por este? +Copy.Yes = &Sim +Copy.No = &Não +Copy.YesAll = Sim p&ara todos +Folder.Title = Confirmar substituição de pasta(s) +Folder.Prompt = Pretende continuar a mover ou copiar a pasta? +Toolbar.GoUp = Um nível acima +Toolbar.Cut = Cortar +Toolbar.Copy = Copiar +Toolbar.Paste = Colar +Toolbar.PasteShortcut = Colar atalho +Toolbar.Delete = Eliminar +Toolbar.Email = Enviar os itens seleccionados por correio electrónico +Toolbar.Properties = Propriedades +Toolbar.NewFolder = Nova pasta +Toolbar.ZipFolder = Nova Pasta Comprimida (zipada) +Toolbar.ExtraLarge = Ícones muito grandes +Toolbar.Large = Ícones grandes +Toolbar.Medium = Ícones médios +Toolbar.Small = Ícones pequenos +Toolbar.List = Lista +Toolbar.Details = Detalhes +Toolbar.Tiles = Mosaicos +Toolbar.Content = Conteúdo +Toolbar.Undo = Anular +Toolbar.Redo = Refazer +Toolbar.Refresh = Actualizar +Toolbar.Back = Anterior +Toolbar.Forward = Avançar +Toolbar.Stop = Parar +Toolbar.Rename = Mudar o nome +Toolbar.SelectAll = Seleccionar tudo +Toolbar.CustomizeFolder = Personalizar esta pasta +Toolbar.MapDrive = Mapear unidade de rede +Toolbar.DisconnectDrive = Desligar unidade de rede +Toolbar.NavigationPane = Painel de navegação +Toolbar.DetailsPane = Painel de detalhes +Toolbar.PreviewPane = Painel de pré-visualização +Toolbar.CopyTo = Copiar para +Toolbar.MoveTo = Mover para +Toolbar.Deselect = Desmarcar tudo +Toolbar.InvertSelection = Inverter seleção +Toolbar.FolderOptions = Opções de pastas +Toolbar.ShowHiddenFiles = Ficheiros e pastas ocultos +Toolbar.ShowSystemFiles = Ficheiros de sistema +Toolbar.ShowExtensions = Extensões de nome de ficheiro +Status.FreeSpace = %s (Espaço livre em disco: %s) +Status.Item = %s item +Status.Items = %s itens +Status.ItemSelected = %s item seleccionado +Status.ItemsSelected = %s itens seleccionados + + +[ro-RO] - Romanian (Romania) +Copy.Cancel = Revocare +Copy.More = Mai multe... +Copy.CopyHere = &Copiere în acest loc +Copy.MoveHere = &Mutare în acest loc +Copy.Title = Confirmare înlocuire fişier +Copy.Subtitle = Acest folder conţine deja un fişier cu numele '%s'. +Copy.SubtitleRO = Acest folder conţine deja un fişier doar în citire cu numele '%s'. +Copy.SubtitleSys = Acest folder conţine deja un fişier de sistem cu numele '%s'. +Copy.Prompt1 = Înlocuiţi fişierul existent +Copy.Prompt2 = cu acesta? +Copy.Yes = &Da +Copy.No = &Nu +Copy.YesAll = D&a pentru tot +Folder.Title = Confirmare înlocuire folder +Folder.Prompt = Totuşi, mutaţi sau copiaţi folderul? +Toolbar.GoUp = Mai sus cu un nivel +Toolbar.Cut = Decupare +Toolbar.Copy = Copiere +Toolbar.Paste = Lipire +Toolbar.PasteShortcut = Lipire comandă rapidă +Toolbar.Delete = Ștergere +Toolbar.Email = Se trimit prin poştă electronică elementele selectate +Toolbar.Properties = Proprietăți +Toolbar.NewFolder = Folder nou +Toolbar.ZipFolder = Folder comprimat (ZIP) nou +Toolbar.ExtraLarge = Pictograme foarte mari +Toolbar.Large = Pictograme mari +Toolbar.Medium = Pictograme medii +Toolbar.Small = Pictograme mici +Toolbar.List = Listă +Toolbar.Details = Detalii +Toolbar.Tiles = Cadre +Toolbar.Content = Cuprins +Toolbar.Undo = Anulare +Toolbar.Redo = Refacere +Toolbar.Refresh = Reîmprospătare +Toolbar.Back = Înapoi +Toolbar.Forward = Înainte +Toolbar.Stop = Oprire +Toolbar.Rename = Redenumire +Toolbar.SelectAll = Selectare totală +Toolbar.CustomizeFolder = Particularizare folder +Toolbar.MapDrive = Conectare unitate de rețea +Toolbar.DisconnectDrive = Deconectare unitate de rețea +Toolbar.NavigationPane = Panou de navigare +Toolbar.DetailsPane = Panou detalii +Toolbar.PreviewPane = Panou de examinare +Toolbar.CopyTo = Copiere în +Toolbar.MoveTo = Mutare la +Toolbar.Deselect = Deselectare totală +Toolbar.InvertSelection = Inversare selecție +Toolbar.FolderOptions = Opțiuni folder +Toolbar.ShowHiddenFiles = Fișiere și foldere ascunse +Toolbar.ShowSystemFiles = Fișiere de sistem +Toolbar.ShowExtensions = Extensii nume de fișier +Status.FreeSpace = %s (Spațiu liber pe disc: %s) +Status.Item = Element %s +Status.Items = %s elemente +Status.ItemSelected = %s element selectat +Status.ItemsSelected = %s elemente selectate + + +[ru-RU] - Russian (Russia) +Copy.Cancel = Отмена +Copy.More = Подробнее... +Copy.CopyHere = &Копировать +Copy.MoveHere = П&ереместить +Copy.Title = Подтверждение замены файла +Copy.Subtitle = Папка уже содержит файл "%s". +Copy.SubtitleRO = Папка уже содержит доступный только для чтения файл "%s". +Copy.SubtitleSys = Папка уже содержит системный файл "%s". +Copy.Prompt1 = Заменить имеющийся файл +Copy.Prompt2 = следующим файлом? +Copy.Yes = &Да +Copy.No = &Нет +Copy.YesAll = Да - для &всех +Folder.Title = Подтверждение замены папки +Folder.Prompt = Заменить существующие в ней файлы перемещаемыми при совпадении имен? +Toolbar.GoUp = На один уровень вверх +Toolbar.Cut = Вырезать +Toolbar.Copy = Копировать +Toolbar.Paste = Вставить +Toolbar.PasteShortcut = Вставить ярлык +Toolbar.Delete = Удалить +Toolbar.Email = Отправка выбранных объектов по электронной почте +Toolbar.Properties = Свойства +Toolbar.NewFolder = Новая папка +Toolbar.ZipFolder = Новая сжатая ZIP-папка +Toolbar.ExtraLarge = Огромные значки +Toolbar.Large = Крупные значки +Toolbar.Medium = Обычные значки +Toolbar.Small = Мелкие значки +Toolbar.List = Список +Toolbar.Details = Таблица +Toolbar.Tiles = Плитка +Toolbar.Content = Содержимое +Toolbar.Undo = Отменить +Toolbar.Redo = Вернуть +Toolbar.Refresh = Обновить +Toolbar.Back = Назад +Toolbar.Forward = Вперед +Toolbar.Stop = Остановить +Toolbar.Rename = Переименовать +Toolbar.SelectAll = Выделить все +Toolbar.CustomizeFolder = Настроить папку +Toolbar.MapDrive = Подключить сетевой диск +Toolbar.DisconnectDrive = Отключить сетевой диск +Toolbar.NavigationPane = Область переходов +Toolbar.DetailsPane = Область сведений +Toolbar.PreviewPane = Область предпросмотра +Toolbar.CopyTo = Копировать в +Toolbar.MoveTo = Переместить в +Toolbar.Deselect = Снять выделение +Toolbar.InvertSelection = Обратить выделение +Toolbar.FolderOptions = Параметры папок +Toolbar.ShowHiddenFiles = Скрытые файлы и папки +Toolbar.ShowSystemFiles = Системные файлы +Toolbar.ShowExtensions = Расширения имен файлов +Status.FreeSpace = %s (свободно на диске: %s) +Status.Item = %s элемент +Status.Items = Элементов: %s +Status.ItemSelected = Выбран элемент: %s +Status.ItemsSelected = Выбрано элементов: %s + + +[sk-SK] - Slovak (Slovakia) +Copy.Cancel = Zrušiť +Copy.More = Ďalšie... +Copy.CopyHere = &Kopírovať sem +Copy.MoveHere = &Premiestniť sem +Copy.Title = Potvrdenie nahradenia súboru +Copy.Subtitle = Tento priečinok už obsahuje súbor s názvom %s. +Copy.SubtitleRO = Tento priečinok už obsahuje súbor s názvom %s, ktorý je iba na čítanie. +Copy.SubtitleSys = Tento priečinok už obsahuje systémový súbor s názvom %s. +Copy.Prompt1 = Chcete nahradiť existujúci súbor +Copy.Prompt2 = týmto súborom? +Copy.Yes = Án&o +Copy.No = &Nie +Copy.YesAll = Áno pre &všetky +Folder.Title = Potvrdenie nahradenia priečinka +Folder.Prompt = Naozaj chcete premiestniť alebo skopírovať priečinok? +Toolbar.GoUp = O úroveň vyššie +Toolbar.Cut = Vystrihnúť +Toolbar.Copy = Kopírovať +Toolbar.Paste = Prilepiť +Toolbar.PasteShortcut = Prilepiť odkaz +Toolbar.Delete = Odstrániť +Toolbar.Email = Vybraté položky odoslať e-mailom +Toolbar.Properties = Vlastnosti +Toolbar.NewFolder = Nový priečinok +Toolbar.ZipFolder = Nový komprimovaný priečinok (ZIP) +Toolbar.ExtraLarge = Veľmi veľké ikony +Toolbar.Large = Veľké ikony +Toolbar.Medium = Stredne veľké ikony +Toolbar.Small = Malé ikony +Toolbar.List = Zoznam +Toolbar.Details = Podrobnosti +Toolbar.Tiles = Dlaždice +Toolbar.Content = Obsah +Toolbar.Undo = Späť +Toolbar.Redo = Znova +Toolbar.Refresh = Obnoviť +Toolbar.Back = Dozadu +Toolbar.Forward = Dopredu +Toolbar.Stop = Zastaviť +Toolbar.Rename = Premenovať +Toolbar.SelectAll = Vybrať všetko +Toolbar.CustomizeFolder = Prispôsobiť priečinok +Toolbar.MapDrive = Pripojiť sieťovú jednotku +Toolbar.DisconnectDrive = Odpojiť sieťovú jednotku +Toolbar.NavigationPane = Navigačná tabla +Toolbar.DetailsPane = Tabla podrobností +Toolbar.PreviewPane = Tabla ukážky +Toolbar.CopyTo = Kopírovať do +Toolbar.MoveTo = Premiestniť do +Toolbar.Deselect = Zrušiť výber +Toolbar.InvertSelection = Invertovať výber +Toolbar.FolderOptions = Možnosti priečinka +Toolbar.ShowHiddenFiles = Skryté súbory a priečinky +Toolbar.ShowSystemFiles = Systémové súbory +Toolbar.ShowExtensions = Prípony názvov súborov +Status.FreeSpace = %s (voľné miesto na disku: %s) +Status.Item = %s položka +Status.Items = Počet položiek: %s +Status.ItemSelected = Počet vybratých položiek: %s +Status.ItemsSelected = Počet vybratých položiek: %s + + +[sl-SI] - Slovenian (Slovenia) +Copy.Cancel = Prekliči +Copy.More = Dodatno ... +Copy.CopyHere = &Kopiraj sem +Copy.MoveHere = &Premakni sem +Copy.Title = Potrditev zamenjave datoteke +Copy.Subtitle = Ta mapa že vsebuje datoteko z imenom »%s«. +Copy.SubtitleRO = Ta mapa že vsebuje datoteko samo za branje z imenom »%s«. +Copy.SubtitleSys = Ta mapa že vsebuje sistemsko datoteko z imenom »%s«. +Copy.Prompt1 = Ali želite zamenjati obstoječo datoteko +Copy.Prompt2 = s to datoteko? +Copy.Yes = &Da +Copy.No = &Ne +Copy.YesAll = Da za &vse +Folder.Title = Potrditev zamenjave mape +Folder.Prompt = Ali še vedno želite premakniti ali kopirati mapo? +Toolbar.GoUp = V nadrejeno mapo +Toolbar.Cut = Izreži +Toolbar.Copy = Kopiraj +Toolbar.Paste = Prilepi +Toolbar.PasteShortcut = Prilepi bližnjico +Toolbar.Delete = Izbriši +Toolbar.Email = Pošlji izbrane elemente prek e-pošte +Toolbar.Properties = Lastnosti +Toolbar.NewFolder = Nova mapa +Toolbar.ZipFolder = Nova stisnjena mapa +Toolbar.ExtraLarge = Izredno velike ikone +Toolbar.Large = Velike ikone +Toolbar.Medium = Srednje velike ikone +Toolbar.Small = Male ikone +Toolbar.List = Seznam +Toolbar.Details = Podrobnosti +Toolbar.Tiles = Ploščice +Toolbar.Content = Vsebina +Toolbar.Undo = Razveljavi +Toolbar.Redo = Uveljavi +Toolbar.Refresh = Osveži +Toolbar.Back = Nazaj +Toolbar.Forward = Naprej +Toolbar.Stop = Ustavi +Toolbar.Rename = Preimenuj +Toolbar.SelectAll = Izberi vse +Toolbar.CustomizeFolder = Prilagodi mapo +Toolbar.MapDrive = Preslikaj omrežni pogon +Toolbar.DisconnectDrive = Prekini povezavo z omrežnim pogonom +Toolbar.NavigationPane = Podokno za krmarjenje +Toolbar.DetailsPane = Podokno s podrobnostmi +Toolbar.PreviewPane = Podokno za predogled +Toolbar.CopyTo = Kopiraj v +Toolbar.MoveTo = Premakni v +Toolbar.Deselect = Ne izberi ničesar +Toolbar.InvertSelection = Preobrni izbor +Toolbar.FolderOptions = Možnosti mape +Toolbar.ShowHiddenFiles = Skrite datoteke in mape +Toolbar.ShowSystemFiles = Sistemske datoteke +Toolbar.ShowExtensions = Datotečne pripone +Status.FreeSpace = %s (Nezaseden prostor na disku: %s) +Status.Item = %s predmet +Status.Items = Št. predmetov: %s +Status.ItemSelected = Izbrano je to število elementov: %s +Status.ItemsSelected = Izbrano je to število elementov: %s + + +[sr-Latn-CS] - Serbian (Latin, Serbia) +Copy.Cancel = Otkaži +Copy.More = Više... +Copy.CopyHere = &Kopiraj ovde +Copy.MoveHere = &Premesti ovde +Copy.Title = Potvrdite zamenu datoteke +Copy.Subtitle = Ova fascikla već sadrži datoteku po imenu '%s'. +Copy.SubtitleRO = Ova fascikla već sadrži datoteku samo za čitanje po imenu '%s'. +Copy.SubtitleSys = Ova fascikla već sadrži sistemsku datoteku po imenu '%s'. +Copy.Prompt1 = Želite li da zamenite postojeću datoteku +Copy.Prompt2 = ovom? +Copy.Yes = &Da +Copy.No = &Ne +Copy.YesAll = Da za &sve +Folder.Title = Potvrdite zamenu fascikle +Folder.Prompt = Želite li zaista da premestite ili kopirate ovu fasciklu? +Toolbar.GoUp = Jedan nivo nagore +Toolbar.Cut = Iseci +Toolbar.Copy = Kopiraj +Toolbar.Paste = Nalepi +Toolbar.PasteShortcut = Nalepi prečicu +Toolbar.Delete = Izbriši +Toolbar.Email = Pošalji izabrane stavke e-poštom +Toolbar.Properties = Svojstva +Toolbar.NewFolder = Nova fascikla +Toolbar.ZipFolder = Nova komprimovana (zipovana) fascikla +Toolbar.ExtraLarge = Veoma velike ikone +Toolbar.Large = Velike ikone +Toolbar.Medium = Srednje ikone +Toolbar.Small = Male ikone +Toolbar.List = Lista +Toolbar.Details = Detalji +Toolbar.Tiles = Naporedno slaganje +Toolbar.Content = Sadržaj +Toolbar.Undo = Opozovi radnju +Toolbar.Redo = Ponovi radnju +Toolbar.Refresh = Osveži +Toolbar.Back = Nazad +Toolbar.Forward = Napred +Toolbar.Stop = Zaustavi +Toolbar.Rename = Preimenuj +Toolbar.SelectAll = Izaberi sve +Toolbar.CustomizeFolder = Prilagođavanje fascikle +Toolbar.MapDrive = Mapiraj mrežni disk +Toolbar.DisconnectDrive = Prekini vezu sa mrežnim diskom +Toolbar.NavigationPane = Okno za navigaciju +Toolbar.DetailsPane = Okno sa detaljima +Toolbar.PreviewPane = Okno za pregled +Toolbar.CopyTo = Kopiraj u +Toolbar.MoveTo = Premesti u +Toolbar.Deselect = Nemoj da izabereš nijedno +Toolbar.InvertSelection = Obrni izbor +Toolbar.FolderOptions = Opcije fascikle +Toolbar.ShowHiddenFiles = Skrivene datoteke i fascikle +Toolbar.ShowSystemFiles = Sistemske datoteke +Toolbar.ShowExtensions = Oznake tipa datoteke +Status.FreeSpace = %s (slobodan prostor na disku: %s) +Status.Item = %s stavka +Status.Items = %s stavki +Status.ItemSelected = %s izabrana stavka +Status.ItemsSelected = %s izabranih stavki + + +[sv-SE] - Swedish (Sweden) +Copy.Cancel = Avbryt +Copy.More = Mer... +Copy.CopyHere = K&opiera hit +Copy.MoveHere = &Flytta hit +Copy.Title = Bekräfta ersättning av fil +Copy.Subtitle = Den här mappen innehåller redan en fil med namnet %s. +Copy.SubtitleRO = Den här mappen innehåller redan en skrivskyddad fil med namnet %s. +Copy.SubtitleSys = Den här mappen innehåller redan en systemfil med namnet %s. +Copy.Prompt1 = Vill du ersätta den befintliga filen +Copy.Prompt2 = med följande fil? +Copy.Yes = &Ja +Copy.No = &Nej +Copy.YesAll = Ersätt &alla +Folder.Title = Bekräfta ersättning av mapp +Folder.Prompt = Vill du ersätta filerna i den mappen om de har samma namn som filerna i mappen som flyttas eller kopieras? +Toolbar.GoUp = Upp en nivå +Toolbar.Cut = Klipp ut +Toolbar.Copy = Kopiera +Toolbar.Paste = Klistra in +Toolbar.PasteShortcut = Klistra in genväg +Toolbar.Delete = Ta bort +Toolbar.Email = Skicka de markerade objekten i e-postmeddelanden +Toolbar.Properties = Egenskaper +Toolbar.NewFolder = Ny mapp +Toolbar.ZipFolder = Ny komprimerad mapp +Toolbar.ExtraLarge = Extra stora ikoner +Toolbar.Large = Stora ikoner +Toolbar.Medium = Medelstora ikoner +Toolbar.Small = Små ikoner +Toolbar.List = Lista +Toolbar.Details = Detaljerad lista +Toolbar.Tiles = Sammanfattning +Toolbar.Content = Innehåll +Toolbar.Undo = Ångra +Toolbar.Redo = Gör om +Toolbar.Refresh = Uppdatera +Toolbar.Back = Bakåt +Toolbar.Forward = Framåt +Toolbar.Stop = Stoppa +Toolbar.Rename = Byt namn +Toolbar.SelectAll = Markera alla +Toolbar.CustomizeFolder = Anpassa den här mappen +Toolbar.MapDrive = Anslut nätverksenhet +Toolbar.DisconnectDrive = Koppla från nätverksenhet +Toolbar.NavigationPane = Navigeringsfönstret +Toolbar.DetailsPane = Informationsfönstret +Toolbar.PreviewPane = Förhandsgranskningsfönstret +Toolbar.CopyTo = Kopiera till +Toolbar.MoveTo = Flytta till +Toolbar.Deselect = Avmarkera alla +Toolbar.InvertSelection = Invertera markering +Toolbar.FolderOptions = Mappalternativ +Toolbar.ShowHiddenFiles = Dolda filer och mappar +Toolbar.ShowSystemFiles = Systemfiler +Toolbar.ShowExtensions = Filnamnstillägg +Status.FreeSpace = %s (Ledigt utrymme: %s) +Status.Item = %s objekt +Status.Items = %s objekt +Status.ItemSelected = %s objekt markerat +Status.ItemsSelected = %s objekt markerade + + +[th-TH] - Thai (Thailand) +Copy.Cancel = ยกเลิก +Copy.More = เพิ่มเติม... +Copy.CopyHere = คัด&ลอกมาที่นี่ +Copy.MoveHere = ย้&ายมาที่นี่ +Copy.Title = ยืนยันการแทนที่แฟ้ม +Copy.Subtitle = โฟลเดอร์นี้มีแฟ้มชื่อ '%s' อยู่แล้ว +Copy.SubtitleRO = โฟลเดอร์นี้มีแฟ้มแบบอ่านอย่างเดียวที่ชื่อ '%s' อยู่แล้ว +Copy.SubtitleSys = โฟลเดอร์นี้มีแฟ้มระบบที่ชื่อ '%s' อยู่แล้ว +Copy.Prompt1 = คุณต้องการแทนที่แฟ้มที่มีอยู่ +Copy.Prompt2 = ด้วยแฟ้มนี้หรือไม่ +Copy.Yes = ใ&ช่ +Copy.No = ไ&ม่ใช่ +Copy.YesAll = ใช่&ทั้งหมด +Folder.Title = การยืนยันการแทนที่โฟลเดอร์ +Folder.Prompt = ถ้าแฟ้มในโฟลเดอร์ที่มีอยู่มีชื่อเดียวกันกับแฟ้มในโฟลเดอร์ที่คุณกำลังย้ายหรือคัดลอก แฟ้มเหล่านั้นจะถูกแทนที่ คุณยังต้องการที่จะย้ายหรือคัดลอกโฟลเดอร์หรือไม่ +Toolbar.GoUp = เลื่อนขึ้นหนึ่งระดับ +Toolbar.Cut = ตัด +Toolbar.Copy = คัดลอก +Toolbar.Paste = วาง +Toolbar.PasteShortcut = วางทางลัด +Toolbar.Delete = ลบ +Toolbar.Email = ส่งอีเมลรายการที่เลือก +Toolbar.Properties = คุณสมบัติ +Toolbar.NewFolder = สร้างโฟลเดอร์ +Toolbar.ZipFolder = โฟลเดอร์ที่บีบอัดใหม่ +Toolbar.ExtraLarge = ไอคอนขนาดใหญ่พิเศษ +Toolbar.Large = ไอคอนขนาดใหญ่ +Toolbar.Medium = ไอคอนขนาดกลาง +Toolbar.Small = ไอคอนขนาดเล็ก +Toolbar.List = รายการ +Toolbar.Details = รายละเอียด +Toolbar.Tiles = เรียงต่อกัน +Toolbar.Content = เนื้อหา +Toolbar.Undo = เลิกทำ +Toolbar.Redo = ทำซ้ำ +Toolbar.Refresh = ฟื้นฟู +Toolbar.Back = ย้อนกลับ +Toolbar.Forward = ไปข้างหน้า +Toolbar.Stop = หยุด +Toolbar.Rename = เปลี่ยนชื่อ +Toolbar.SelectAll = เลือกทั้งหมด +Toolbar.CustomizeFolder = กำหนดโฟลเดอร์นี้เอง +Toolbar.MapDrive = แมปไดรฟ์เครือข่าย +Toolbar.DisconnectDrive = ยกเลิกการเชื่อมต่อไดรฟ์เครือข่าย +Toolbar.NavigationPane = บานหน้าต่างนำทาง +Toolbar.DetailsPane = บานหน้าต่างแสดงรายละเอียด +Toolbar.PreviewPane = บานหน้าต่างแสดงตัวอย่าง +Toolbar.CopyTo = คัดลอกไปที่ +Toolbar.MoveTo = ย้ายไปที่ +Toolbar.Deselect = ไม่เลือกเลย +Toolbar.InvertSelection = สลับส่วนที่เลือก +Toolbar.FolderOptions = ตัวเลือกโฟลเดอร์ +Toolbar.ShowHiddenFiles = แฟ้มและโฟลเดอร์ที่ซ่อนไว้ +Toolbar.ShowSystemFiles = แฟ้มระบบ +Toolbar.ShowExtensions = ส่วนขยายของแฟ้ม +Status.FreeSpace = %s (เนื้อที่ว่างดิสก์: %s) +Status.Item = %s รายการ +Status.Items = %s รายการ +Status.ItemSelected = เลือก %s รายการ +Status.ItemsSelected = เลือก %s รายการ + + +[tr-TR] - Turkish (Turkey) +Copy.Cancel = İptal +Copy.More = Tümü... +Copy.CopyHere = Buraya &Kopyala +Copy.MoveHere = Buraya &Taşı +Copy.Title = Dosya Değişimini Onayla +Copy.Subtitle = Bu klasörde zaten '%s' adlı bir dosya var. +Copy.SubtitleRO = Bu klasörde zaten '%s' adlı salt okunur bir dosya var. +Copy.SubtitleSys = Bu klasörde zaten '%s' adlı bir sistem dosyası var. +Copy.Prompt1 = Varolan dosyayı +Copy.Prompt2 = aşağıdaki dosya ile değiştirmek istiyor musunuz? +Copy.Yes = &Evet +Copy.No = &Hayır +Copy.YesAll = &Tümüne Evet +Folder.Title = Klasör Değişimini Onayla +Folder.Prompt = Klasörü taşımak ya da kopyalamak istiyor musunuz? +Toolbar.GoUp = Bir Düzey Yukarı +Toolbar.Cut = Kes +Toolbar.Copy = Kopyala +Toolbar.Paste = Yapıştır +Toolbar.PasteShortcut = Kısayol Yapıştır +Toolbar.Delete = Sil +Toolbar.Email = Seçili öğeleri e-postayla gönder +Toolbar.Properties = Özellikler +Toolbar.NewFolder = Yeni Klasör +Toolbar.ZipFolder = Yeni Sıkıştırılmış Klasör +Toolbar.ExtraLarge = Çok Büyük Simgeler +Toolbar.Large = Büyük Simgeler +Toolbar.Medium = Orta Boy Simgeler +Toolbar.Small = Küçük Simgeler +Toolbar.List = Listele +Toolbar.Details = Ayrıntılar +Toolbar.Tiles = Döşemeler +Toolbar.Content = İçerik +Toolbar.Undo = Geri Al +Toolbar.Redo = Yinele +Toolbar.Refresh = Yenile +Toolbar.Back = Geri +Toolbar.Forward = İleri +Toolbar.Stop = Durdur +Toolbar.Rename = Yeniden Adlandır +Toolbar.SelectAll = Tümünü seç +Toolbar.CustomizeFolder = Bu klasörü özelleştir +Toolbar.MapDrive = Ağ sürücüsüne bağlan +Toolbar.DisconnectDrive = Ağ sürücüsü bağlantısını kes +Toolbar.NavigationPane = Gezinti bölmesi +Toolbar.DetailsPane = Ayrıntılar bölmesi +Toolbar.PreviewPane = Önizleme bölmesi +Toolbar.CopyTo = Kopyalama hedefi +Toolbar.MoveTo = Taşıma hedefi +Toolbar.Deselect = Hiçbirini seçme +Toolbar.InvertSelection = Diğerlerini seç +Toolbar.FolderOptions = Klasör seçenekleri +Toolbar.ShowHiddenFiles = Gizli dosya ve klasörler +Toolbar.ShowSystemFiles = Sistem dosyaları +Toolbar.ShowExtensions = Dosya adı uzantıları +Status.FreeSpace = %s (Boş disk boş alanı: %s) +Status.Item = %s öğe +Status.Items = %s öğe +Status.ItemSelected = %s öğe seçili +Status.ItemsSelected = %s öğe seçili + + +[uk-UA] - Ukrainian (Ukraine) +Copy.Cancel = Скасувати +Copy.More = Додатково... +Copy.CopyHere = &Копіювати сюди +Copy.MoveHere = П&еремістити +Copy.Title = Підтвердження заміни файлу +Copy.Subtitle = Ця папка вже містить файл з ім'ям "%s". +Copy.SubtitleRO = Ця папка вже містить доступний лише для читання файл з ім'ям "%s". +Copy.SubtitleSys = Ця папка вже містить системний файл з ім'ям "%s". +Copy.Prompt1 = Замінити наявний файл +Copy.Prompt2 = на цей файл? +Copy.Yes = &Так +Copy.No = &Ні +Copy.YesAll = Так для &всіх +Folder.Title = Підтвердження заміни папки +Folder.Prompt = Розпочати переміщення або копіювання папки? +Toolbar.GoUp = На один рівень вгору +Toolbar.Cut = Вирізати +Toolbar.Copy = Копіювати +Toolbar.Paste = Вставити +Toolbar.PasteShortcut = Вставити ярлик +Toolbar.Delete = Видалити +Toolbar.Email = Надіслати виділені об'єкти електронною поштою +Toolbar.Properties = Властивості +Toolbar.NewFolder = Створити папку +Toolbar.ZipFolder = Нова стиснута ZIP-папка +Toolbar.ExtraLarge = Величезні піктограми +Toolbar.Large = Великі піктограми +Toolbar.Medium = Середні піктограми +Toolbar.Small = Дрібні піктограми +Toolbar.List = Список +Toolbar.Details = Таблиця +Toolbar.Tiles = Мозаїка +Toolbar.Content = Вміст +Toolbar.Undo = Скасувати +Toolbar.Redo = Повторити +Toolbar.Refresh = Оновити +Toolbar.Back = Назад +Toolbar.Forward = Вперед +Toolbar.Stop = Зупинити +Toolbar.Rename = Перейменувати +Toolbar.SelectAll = Вибрати всі +Toolbar.CustomizeFolder = Настроїти папку +Toolbar.MapDrive = Підключити мережний диск +Toolbar.DisconnectDrive = Відключити мережний диск +Toolbar.NavigationPane = Область переходів +Toolbar.DetailsPane = Область відомостей +Toolbar.PreviewPane = Область перегляду +Toolbar.CopyTo = Копіювати +Toolbar.MoveTo = Перемістити +Toolbar.Deselect = Скасувати виділення +Toolbar.InvertSelection = Обернути виділення +Toolbar.FolderOptions = Параметри папки +Toolbar.ShowHiddenFiles = Приховані файли й папки +Toolbar.ShowSystemFiles = Системні файли +Toolbar.ShowExtensions = Розширення імен файлів +Status.FreeSpace = %s (Доступно на диску: %s) +Status.Item = %s елемент +Status.Items = %s елементів +Status.ItemSelected = Вибрано елемент: %s +Status.ItemsSelected = Вибрано елементів: %s + + +[zh-CN] - Chinese (Simplified) +Copy.Cancel = 取消 +Copy.More = 其他... +Copy.CopyHere = 复制到当前位置(&C) +Copy.MoveHere = 移动到当前位置(&M) +Copy.Title = 确认文件替换 +Copy.Subtitle = 此文件夹已包含一个名为“%s”的文件。 +Copy.SubtitleRO = 此文件夹已包括一个名为“%s”的只读文件。 +Copy.SubtitleSys = 此文件夹已包括一个名为“%s”的系统文件。 +Copy.Prompt1 = 是否将现有文件 +Copy.Prompt2 = 替换为 +Copy.Yes = 是(&Y) +Copy.No = 否(&N) +Copy.YesAll = 全部(&A) +Folder.Title = 确认文件夹替换 +Folder.Prompt = 是否移动或复制文件夹? +Toolbar.GoUp = 向上一级 +Toolbar.Cut = 剪切 +Toolbar.Copy = 复制 +Toolbar.Paste = 粘贴 +Toolbar.PasteShortcut = 粘贴快捷方式 +Toolbar.Delete = 删除 +Toolbar.Email = 以电子邮件形式发送所选项目 +Toolbar.Properties = 属性 +Toolbar.NewFolder = 新文件夹 +Toolbar.ZipFolder = 新建压缩的(zipped)文件夹 +Toolbar.ExtraLarge = 超大图标 +Toolbar.Large = 大图标 +Toolbar.Medium = 中等图标 +Toolbar.Small = 小图标 +Toolbar.List = 列表 +Toolbar.Details = 详细信息 +Toolbar.Tiles = 平铺 +Toolbar.Content = 内容 +Toolbar.Undo = 撤消 +Toolbar.Redo = 恢复 +Toolbar.Refresh = 刷新 +Toolbar.Back = 后退 +Toolbar.Forward = 前进 +Toolbar.Stop = 停止 +Toolbar.Rename = 重命名 +Toolbar.SelectAll = 全选 +Toolbar.CustomizeFolder = 自定义文件夹 +Toolbar.MapDrive = 映射网络驱动器 +Toolbar.DisconnectDrive = 断开网络驱动器 +Toolbar.NavigationPane = 导航窗格 +Toolbar.DetailsPane = 细节窗格 +Toolbar.PreviewPane = 预览窗格 +Toolbar.CopyTo = 复制到​​ +Toolbar.MoveTo = 移动到​​ +Toolbar.Deselect = 全部取消 +Toolbar.InvertSelection = 反向选择 +Toolbar.FolderOptions = 文件夹选项 +Toolbar.ShowHiddenFiles = 隐藏文件和文件夹 +Toolbar.ShowSystemFiles = 系统文件 +Toolbar.ShowExtensions = 文件扩展名 +Status.FreeSpace = %s (磁盘可用空间: %s) +Status.Item = %s 项 +Status.Items = %s 个项目 +Status.ItemSelected = 已选择 %s 项 +Status.ItemsSelected = 已选择 %s 个项 + + +[zh-HK] - Chinese (Traditional) +Copy.Cancel = 取消 +Copy.More = 其他... +Copy.CopyHere = 複製到這裡(&C) +Copy.MoveHere = 移動到這裡(&M) +Copy.Title = 確認取代檔案 +Copy.Subtitle = 這個資料夾已經有一個名稱為 '%s' 的檔案。 +Copy.SubtitleRO = 這個資料夾已經有一個名稱為 '%s' 的唯讀檔。 +Copy.SubtitleSys = 這個資料夾已經有一個名稱為 '%s' 的系統檔。 +Copy.Prompt1 = 您要將目前的檔案 +Copy.Prompt2 = 取代成這個檔案嗎? +Copy.Yes = 是(&Y) +Copy.No = 否(&N) +Copy.YesAll = 全部取代(&A) +Folder.Title = 確認取代資料夾 +Folder.Prompt = 仍然要移動或複製資料夾? +Toolbar.GoUp = 上移一層 +Toolbar.Cut = 剪下 +Toolbar.Copy = 複製 +Toolbar.Paste = 貼上 +Toolbar.PasteShortcut = 貼上捷徑 +Toolbar.Delete = 刪除 +Toolbar.Email = 以電子郵件傳送選取的項目 +Toolbar.Properties = 內容 +Toolbar.NewFolder = 新增資料夾 +Toolbar.ZipFolder = 新壓縮 (zipped) 資料夾 +Toolbar.ExtraLarge = 特大圖示 +Toolbar.Large = 大圖示 +Toolbar.Medium = 中圖示 +Toolbar.Small = 小圖示 +Toolbar.List = 清單 +Toolbar.Details = 詳細資料 +Toolbar.Tiles = 並排 +Toolbar.Content = 內容 +Toolbar.Undo = 復原 +Toolbar.Redo = 重做 +Toolbar.Refresh = 重新整理 +Toolbar.Back = 上一頁 +Toolbar.Forward = 下一頁 +Toolbar.Stop = 停止 +Toolbar.Rename = 重新命名 +Toolbar.SelectAll = 全選 +Toolbar.CustomizeFolder = 自訂此資料夾 +Toolbar.MapDrive = 連線網路磁碟機 +Toolbar.DisconnectDrive = 中斷網路磁碟機 +Toolbar.NavigationPane = 瀏覽窗格 +Toolbar.DetailsPane = 詳細資料窗格 +Toolbar.PreviewPane = 預覽窗格 +Toolbar.CopyTo = 複製到​​ +Toolbar.MoveTo = 移至​​ +Toolbar.Deselect = 全部不選 +Toolbar.InvertSelection = 反向選擇 +Toolbar.FolderOptions = 資料夾選項 +Toolbar.ShowHiddenFiles = 隱藏的檔案和資料夾 +Toolbar.ShowSystemFiles = 系統檔 +Toolbar.ShowExtensions = 副檔名 +Status.FreeSpace = %s (磁碟可用空間: %s) +Status.Item = %s 個項目 +Status.Items = %s 個項目 +Status.ItemSelected = 選取了 %s 個項目 +Status.ItemsSelected = 選取了 %s 個項目 + + +[zh-TW] - Chinese (Traditional) +Copy.Cancel = 取消 +Copy.More = 其他... +Copy.CopyHere = 複製到這裡(&C) +Copy.MoveHere = 移動到這裡(&M) +Copy.Title = 確認取代檔案 +Copy.Subtitle = 這個資料夾已經有一個名稱為 '%s' 的檔案。 +Copy.SubtitleRO = 這個資料夾已經有一個名稱為 '%s' 的唯讀檔。 +Copy.SubtitleSys = 這個資料夾已經有一個名稱為 '%s' 的系統檔。 +Copy.Prompt1 = 您要將目前的檔案 +Copy.Prompt2 = 取代成這個檔案嗎? +Copy.Yes = 是(&Y) +Copy.No = 否(&N) +Copy.YesAll = 全部取代(&A) +Folder.Title = 確認取代資料夾 +Folder.Prompt = 仍然要移動或複製資料夾? +Toolbar.GoUp = 上移一層 +Toolbar.Cut = 剪下 +Toolbar.Copy = 複製 +Toolbar.Paste = 貼上 +Toolbar.PasteShortcut = 貼上捷徑 +Toolbar.Delete = 刪除 +Toolbar.Email = 以電子郵件傳送選取的項目 +Toolbar.Properties = 內容 +Toolbar.NewFolder = 新增資料夾 +Toolbar.ZipFolder = 新壓縮 (zipped) 資料夾 +Toolbar.ExtraLarge = 特大圖示 +Toolbar.Large = 大圖示 +Toolbar.Medium = 中圖示 +Toolbar.Small = 小圖示 +Toolbar.List = 清單 +Toolbar.Details = 詳細資料 +Toolbar.Tiles = 並排 +Toolbar.Content = 內容 +Toolbar.Undo = 復原 +Toolbar.Redo = 重做 +Toolbar.Refresh = 重新整理 +Toolbar.Back = 上一頁 +Toolbar.Forward = 下一頁 +Toolbar.Stop = 停止 +Toolbar.Rename = 重新命名 +Toolbar.SelectAll = 全選 +Toolbar.CustomizeFolder = 自訂此資料夾 +Toolbar.MapDrive = 連線網路磁碟機 +Toolbar.DisconnectDrive = 中斷網路磁碟機 +Toolbar.NavigationPane = 瀏覽窗格 +Toolbar.DetailsPane = 詳細資料窗格 +Toolbar.PreviewPane = 預覽窗格 +Toolbar.CopyTo = 複製到​​ +Toolbar.MoveTo = 移至​​ +Toolbar.Deselect = 全部不選 +Toolbar.InvertSelection = 反向選擇 +Toolbar.FolderOptions = 資料夾選項 +Toolbar.ShowHiddenFiles = 隱藏的檔案和資料夾 +Toolbar.ShowSystemFiles = 系統檔 +Toolbar.ShowExtensions = 副檔名 +Status.FreeSpace = %s (磁碟可用空間: %s) +Status.Item = %s 個項目 +Status.Items = %s 個項目 +Status.ItemSelected = 選取了 %s 個項目 +Status.ItemsSelected = 選取了 %s 個項目 diff --git a/ClassicShellSrc/ClassicExplorer/SettingsUI.cpp b/ClassicShellSrc/ClassicExplorer/SettingsUI.cpp new file mode 100644 index 0000000..a809e69 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/SettingsUI.cpp @@ -0,0 +1,764 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "ExplorerBand.h" +#include "ExplorerBHO.h" +#include "SettingsUI.h" +#include "Settings.h" +#include "SettingsUIHelper.h" +#include "LanguageSettingsHelper.h" +#include "ResourceHelper.h" +#include "Translations.h" +#include "resource.h" +#include "dllmain.h" +#include + +enum +{ + SETTINGS_STYLE_WIN7=1, + SETTINGS_STYLE_WIN8=2, + SETTINGS_STYLE_MASK=SETTINGS_STYLE_WIN7|SETTINGS_STYLE_WIN8, +}; + +static const CStdCommand g_StdCommands[]={ + {L"SEPARATOR",IDS_SEPARATOR_ITEM,IDS_SEPARATOR_TIP}, + {L"up",IDS_UP_ITEM,IDS_UP_TIP,L"UpItem",NULL,L"$Toolbar.GoUp",L",2",NULL,0,L",3"}, + {L"cut",IDS_CUT_ITEM,IDS_CUT_TIP,L"CutItem",NULL,L"$Toolbar.Cut",L"shell32.dll,16762"}, + {L"copy",IDS_COPY_ITEM,IDS_COPY_TIP,L"CopyItem",NULL,L"$Toolbar.Copy",L"shell32.dll,243"}, + {L"paste",IDS_PASTE_ITEM,IDS_PASTE_TIP,L"PasteItem",NULL,L"$Toolbar.Paste",L"shell32.dll,16763"}, + {L"paste_shortcut",IDS_PASTE_LNK_ITEM,IDS_PASTE_SHORTCUT_TIP,L"PasteShortcutItem",NULL,L"$Toolbar.PasteShortcut",L"shell32.dll,16763",NULL,SETTINGS_STYLE_WIN7}, + {L"paste_shortcut",IDS_PASTE_LNK_ITEM,IDS_PASTE_SHORTCUT_TIP,L"PasteShortcutItem",NULL,L"$Toolbar.PasteShortcut",L"imageres.dll,5301",NULL,SETTINGS_STYLE_WIN8}, + {L"delete",IDS_DELETE_ITEM,IDS_DELETE_TIP,L"DeleteItem",NULL,L"$Toolbar.Delete",L"shell32.dll,240"}, + {L"properties",IDS_PROPERTIES_ITEM,IDS_PROPERTIES_TIP,L"PropertiesItem",NULL,L"$Toolbar.Properties",L"shell32.dll,253"}, + {L"email",IDS_EMAIL_ITEM,IDS_EMAIL_TIP,L"EmailItem",NULL,L"$Toolbar.Email",L"shell32.dll,265"}, + {L"settings",IDS_SETTINGS_ITEM,IDS_SETTINGS_TIP,L"SettingsItem",NULL,L"$Toolbar.Settings",L",1"}, + {L"refresh",IDS_REFRESH_ITEM,IDS_REFRESH_TIP,L"RefreshItem",NULL,L"$Toolbar.Refresh",L"shell32.dll,16739"}, + {L"stop",IDS_STOP_ITEM,IDS_STOP_TIP,L"StopItem",NULL,L"$Toolbar.Stop",L"imageres.dll,98"}, + {L"rename",IDS_RENAME_ITEM,IDS_RENAME_TIP,L"RenameItem",NULL,L"$Toolbar.Rename",L"shell32.dll,242"}, + {L"customizefolder",IDS_CUSTOMIZE_ITEM,IDS_CUSTOMIZEFOLDER_TIP,L"CustomizeFolderItem",NULL,L"$Toolbar.CustomizeFolder",L"shell32.dll,274"}, + {L"folderoptions",IDS_FOLDEROPTIONS,IDS_FOLDEROPTIONS_TIP,L"FolderOptionsItem",NULL,L"$Toolbar.FolderOptions",L"imageres.dll,166"}, + {L"newfolder",IDS_NEWFOLDER_ITEM,IDS_NEWFOLDER_TIP,L"NewFolderItem",NULL,L"$Toolbar.NewFolder",L"shell32.dll,319"}, + {L"zipfolder",IDS_ZIP_ITEM,IDS_ZIP_TIP,L"ZipItem",NULL,L"$Toolbar.ZipFolder",L"imageres.dll,174"}, + {L"nav_pane",IDS_NAVPANE_ITEM,IDS_NAVPANE_TIP,L"NavPaneItem",NULL,L"$Toolbar.NavigationPane",L"shell32.dll,16755"}, + {L"details_pane",IDS_DETAILSPANE_ITEM,IDS_DETAILSPANE_TIP,L"DetailsPaneItem",NULL,L"$Toolbar.DetailsPane",L"shell32.dll,16759",NULL,SETTINGS_STYLE_WIN7}, + {L"details_pane",IDS_DETAILSPANE_ITEM,IDS_DETAILSPANE_TIP,L"DetailsPaneItem",NULL,L"$Toolbar.DetailsPane",L"shell32.dll,16814",NULL,SETTINGS_STYLE_WIN8}, + {L"preview_pane",IDS_PREVIEWPANE_ITEM,IDS_PREVIEWPANE_TIP,L"PreviewPaneItem",NULL,L"$Toolbar.PreviewPane",L"shell32.dll,16757"}, + {L"mapdrive",IDS_MAP_DRIVE_ITEM,IDS_MAP_DRIVE_TIP,L"MapDriveItem",NULL,L"$Toolbar.MapDrive",L"shell32.dll,16779"}, + {L"disconnect",IDS_DISCONNECT_ITEM,IDS_DISCONNECT_DRIVE_TIP,L"DisconnectItem",NULL,L"$Toolbar.DisconnectDrive",L"shell32.dll,11"}, + {L"viewtiles",IDS_VIEWTILES_ITEM,IDS_VIEWTILES_TIP,L"TilesItem",NULL,L"$Toolbar.Tiles",L"shell32.dll,62999"}, + {L"viewdetails",IDS_VIEWDETAILS_ITEM,IDS_VIEWDEATAILS_TIP,L"DetailsItem",NULL,L"$Toolbar.Details",L"shell32.dll,62998"}, + {L"viewlist",IDS_VIEWLIST_ITEM,IDS_VIEWLIST_TIP,L"ListItem",NULL,L"$Toolbar.List",L"shell32.dll,63000"}, + {L"viewcontent",IDS_VIEWCONTENT_ITEM,IDS_VIEWCONTENT_TIP,L"ContentItem",NULL,L"$Toolbar.Content",L"shell32.dll,63011"}, + {L"viewicons_small",IDS_VIEWICONS1_ITEM,IDS_VIEWICONS1_TIP,L"Icons1Item",NULL,L"$Toolbar.Small",L"shell32.dll,63010"}, + {L"viewicons_medium",IDS_VIEWICONS2_ITEM,IDS_VIEWICONS2_TIP,L"Icons2Item",NULL,L"$Toolbar.Medium",L"shell32.dll,63009"}, + {L"viewicons_large",IDS_VIEWICONS3_ITEM,IDS_VIEWICONS3_TIP,L"Icons3Item",NULL,L"$Toolbar.Large",L"shell32.dll,63008"}, + {L"viewicons_extralarge",IDS_VIEWICONS4_ITEM,IDS_VIEWICONS4_TIP,L"Icons4Item",NULL,L"$Toolbar.ExtraLarge",L"shell32.dll,63001"}, + {L"moveto",IDS_MOVETO_ITEM,IDS_MOVETO_TIP,L"MoveToItem",NULL,L"$Toolbar.MoveTo",L"",NULL,SETTINGS_STYLE_WIN7}, + {L"moveto",IDS_MOVETO_ITEM,IDS_MOVETO_TIP,L"MoveToItem",NULL,L"$Toolbar.MoveTo",L"imageres.dll,5303",NULL,SETTINGS_STYLE_WIN8}, + {L"copyto",IDS_COPYTO_ITEM,IDS_COPYTO_TIP,L"CopyToItem",NULL,L"$Toolbar.CopyTo",L"",NULL,SETTINGS_STYLE_WIN7}, + {L"copyto",IDS_COPYTO_ITEM,IDS_COPYTO_TIP,L"CopyToItem",NULL,L"$Toolbar.CopyTo",L"imageres.dll,5304",NULL,SETTINGS_STYLE_WIN8}, + {L"undo",IDS_UNDO_ITEM,IDS_UNDO_TIP,L"UndoItem",NULL,L"$Toolbar.Undo",L"",NULL,SETTINGS_STYLE_WIN7}, + {L"undo",IDS_UNDO_ITEM,IDS_UNDO_TIP,L"UndoItem",NULL,L"$Toolbar.Undo",L"imageres.dll,5315",NULL,SETTINGS_STYLE_WIN8}, + {L"redo",IDS_REDO_ITEM,IDS_REDO_TIP,L"RedoItem",NULL,L"$Toolbar.Redo",L"",NULL,SETTINGS_STYLE_WIN7}, + {L"redo",IDS_REDO_ITEM,IDS_REDO_TIP,L"RedoItem",NULL,L"$Toolbar.Redo",L"imageres.dll,5311",NULL,SETTINGS_STYLE_WIN8}, + {L"selectall",IDS_SELECTALL_ITEM,IDS_SELECTALL_TIP,L"SelectAllItem",NULL,L"$Toolbar.SelectAll",L"",NULL,SETTINGS_STYLE_WIN7}, + {L"selectall",IDS_SELECTALL_ITEM,IDS_SELECTALL_TIP,L"SelectAllItem",NULL,L"$Toolbar.SelectAll",L"imageres.dll,5308",NULL,SETTINGS_STYLE_WIN8}, + {L"deselect",IDS_DESELECT_ITEM,IDS_DESELECT_TIP,L"DeselectItem",NULL,L"$Toolbar.Deselect",L"",NULL,SETTINGS_STYLE_WIN7}, + {L"deselect",IDS_DESELECT_ITEM,IDS_DESELECT_TIP,L"DeselectItem",NULL,L"$Toolbar.Deselect",L"imageres.dll,5309",NULL,SETTINGS_STYLE_WIN8}, + {L"invertselection",IDS_INVERT_ITEM,IDS_INVERT_TIP,L"InvertItem",NULL,L"$Toolbar.InvertSelection",L"",NULL,SETTINGS_STYLE_WIN7}, + {L"invertselection",IDS_INVERT_ITEM,IDS_INVERT_TIP,L"InvertItem",NULL,L"$Toolbar.InvertSelection",L"imageres.dll,5310",NULL,SETTINGS_STYLE_WIN8}, + {L"back",IDS_BACK_ITEM,IDS_BACK_TIP,L"BackItem",NULL,L"$Toolbar.Back",L""}, + {L"forward",IDS_FORWARD_ITEM,IDS_FORWARD_TIP,L"ForwardItem",NULL,L"$Toolbar.Forward",L""}, + {L"show_extensions",IDS_SHOW_EXTENSIONS,IDS_SHOW_EXTENSIONS_TIP,L"ShowExtensionsItem",NULL,L"$Toolbar.ShowExtensions"}, + {L"hidden_files",IDS_HIDDEN_FILES,IDS_HIDDEN_FILES_TIP,L"HiddenFilesItem",NULL,L"$Toolbar.ShowHiddenFiles"}, + {L"system_files",IDS_SYSTEM_FILES,IDS_SYSTEM_FILES_TIP,L"SystemFilesItem",NULL,L"$Toolbar.ShowSystemFiles"}, + {L"open ",IDS_OPEN_ITEM,IDS_OPEN_TIP,L"OpenFolderItem",NULL,NULL,L""}, + {L"sortby ",IDS_SORYBY_ITEM,IDS_SORT_TIP,L"SortFolderItem",NULL,NULL,L""}, + {L"groupby ",IDS_GROUPBY_ITEM,IDS_GROUP_TIP,L"GroupFolderItem",NULL,NULL,L""}, + {L"",IDS_CUSTOM_ITEM,IDS_CUSTOM_TIP,L"CustomItem",NULL,NULL,L""}, + {NULL}, +}; + +static const KNOWNFOLDERID *g_CommonLinks[]= +{ + &FOLDERID_ComputerFolder, + &FOLDERID_DesktopRoot, + &FOLDERID_Desktop, + &FOLDERID_Documents, + &FOLDERID_Downloads, + &FOLDERID_Favorites, + &FOLDERID_Games, + &FOLDERID_Links, + &FOLDERID_Music, + &FOLDERID_Pictures, + &FOLDERID_Videos, + &FOLDERID_Profile, + &FOLDERID_HomeGroup, + &FOLDERID_Libraries, + &FOLDERID_DocumentsLibrary, + &FOLDERID_MusicLibrary, + &FOLDERID_PicturesLibrary, + &FOLDERID_VideosLibrary, + &FOLDERID_NetworkFolder, + NULL, +}; + +const wchar_t *g_DefaultToolbar= + L"Items=UpItem, NavPaneItem, FolderOptionsItem, CutItem, CopyItem, PasteItem, DeleteItem, PropertiesItem, EmailItem, SEPARATOR, SettingsItem\n" + L"UpItem.Command=up\n" + L"UpItem.Tip=$Toolbar.GoUp\n" + L"UpItem.Icon=,2\n" + L"UpItem.IconDisabled=,3\n" + L"NavPaneItem.Command=nav_pane\n" + L"NavPaneItem.Tip=$Toolbar.NavigationPane\n" + L"NavPaneItem.Icon=shell32.dll,16755\n" + L"FolderOptionsItem.Command=folderoptions\n" + L"FolderOptionsItem.Tip=$Toolbar.FolderOptions\n" + L"FolderOptionsItem.Icon=imageres.dll,166\n" + L"FolderOptionsItem.Items=ShowExtensionsItem, HiddenFilesItem, SystemFilesItem\n" + L"ShowExtensionsItem.Command=show_extensions\n" + L"ShowExtensionsItem.Label=$Toolbar.ShowExtensions\n" + L"ShowExtensionsItem.Icon=none\n" + L"HiddenFilesItem.Command=hidden_files\n" + L"HiddenFilesItem.Label=$Toolbar.ShowHiddenFiles\n" + L"HiddenFilesItem.Icon=none\n" + L"SystemFilesItem.Command=system_files\n" + L"SystemFilesItem.Label=$Toolbar.ShowSystemFiles\n" + L"SystemFilesItem.Icon=none\n" + L"CutItem.Command=cut\n" + L"CutItem.Tip=$Toolbar.Cut\n" + L"CutItem.Icon=shell32.dll,16762\n" + L"CopyItem.Command=copy\n" + L"CopyItem.Tip=$Toolbar.Copy\n" + L"CopyItem.Icon=shell32.dll,243\n" + L"PasteItem.Command=paste\n" + L"PasteItem.Tip=$Toolbar.Paste\n" + L"PasteItem.Icon=shell32.dll,16763\n" + L"DeleteItem.Command=delete\n" + L"DeleteItem.Tip=$Toolbar.Delete\n" + L"DeleteItem.Icon=shell32.dll,240\n" + L"PropertiesItem.Command=properties\n" + L"PropertiesItem.Tip=$Toolbar.Properties\n" + L"PropertiesItem.Icon=shell32.dll,253\n" + L"EmailItem.Command=email\n" + L"EmailItem.Tip=$Toolbar.Email\n" + L"EmailItem.Icon=shell32.dll,265\n" + L"SettingsItem.Command=settings\n" + L"SettingsItem.Tip=$Toolbar.Settings\n" + L"SettingsItem.Icon=,1\n"; + +const wchar_t *g_DefaultToolbar2= + L"Items=NavPaneItem, FolderOptionsItem, CutItem, CopyItem, PasteItem, DeleteItem, PropertiesItem, EmailItem, SEPARATOR, SettingsItem\n" + L"NavPaneItem.Command=nav_pane\n" + L"NavPaneItem.Tip=$Toolbar.NavigationPane\n" + L"NavPaneItem.Icon=shell32.dll,16755\n" + L"FolderOptionsItem.Command=folderoptions\n" + L"FolderOptionsItem.Tip=$Toolbar.FolderOptions\n" + L"FolderOptionsItem.Icon=imageres.dll,166\n" + L"FolderOptionsItem.Items=ShowExtensionsItem, HiddenFilesItem, SystemFilesItem\n" + L"ShowExtensionsItem.Command=show_extensions\n" + L"ShowExtensionsItem.Label=$Toolbar.ShowExtensions\n" + L"ShowExtensionsItem.Icon=none\n" + L"HiddenFilesItem.Command=hidden_files\n" + L"HiddenFilesItem.Label=$Toolbar.ShowHiddenFiles\n" + L"HiddenFilesItem.Icon=none\n" + L"SystemFilesItem.Command=system_files\n" + L"SystemFilesItem.Label=$Toolbar.ShowSystemFiles\n" + L"SystemFilesItem.Icon=none\n" + L"CutItem.Command=cut\n" + L"CutItem.Tip=$Toolbar.Cut\n" + L"CutItem.Icon=shell32.dll,16762\n" + L"CopyItem.Command=copy\n" + L"CopyItem.Tip=$Toolbar.Copy\n" + L"CopyItem.Icon=shell32.dll,243\n" + L"PasteItem.Command=paste\n" + L"PasteItem.Tip=$Toolbar.Paste\n" + L"PasteItem.Icon=shell32.dll,16763\n" + L"DeleteItem.Command=delete\n" + L"DeleteItem.Tip=$Toolbar.Delete\n" + L"DeleteItem.Icon=shell32.dll,240\n" + L"PropertiesItem.Command=properties\n" + L"PropertiesItem.Tip=$Toolbar.Properties\n" + L"PropertiesItem.Icon=shell32.dll,253\n" + L"EmailItem.Command=email\n" + L"EmailItem.Tip=$Toolbar.Email\n" + L"EmailItem.Icon=shell32.dll,265\n" + L"SettingsItem.Command=settings\n" + L"SettingsItem.Tip=$Toolbar.Settings\n" + L"SettingsItem.Icon=,1\n"; + +/////////////////////////////////////////////////////////////////////////////// + +class CEditToolbarDlg: public CEditCustomItemDlg +{ +public: + CEditToolbarDlg( CTreeItem *pItem, bool bNoLinks, std::vector &modules ): CEditCustomItemDlg(pItem,modules) { m_bNoLinks=bNoLinks; } + + BEGIN_MSG_MAP( CEditToolbarDlg ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + COMMAND_ID_HANDLER( IDOK, OnOK ) + COMMAND_ID_HANDLER( IDCANCEL, OnCancel ) + COMMAND_HANDLER( IDC_COMBOCOMMAND, CBN_KILLFOCUS, OnCommandChanged ) + COMMAND_HANDLER( IDC_COMBOCOMMAND, CBN_SELENDOK, OnCommandChanged ) + COMMAND_HANDLER( IDC_BUTTONCOMMAND, BN_CLICKED, OnBrowseCommand ) + COMMAND_HANDLER( IDC_BUTTONLINK, BN_CLICKED, OnBrowseLink ) + COMMAND_HANDLER( IDC_BUTTONICON, BN_CLICKED, OnBrowseIcon ) + COMMAND_HANDLER( IDC_BUTTONICOND, BN_CLICKED, OnBrowseIcon ) + COMMAND_HANDLER( IDC_COMBOLINK, CBN_KILLFOCUS, OnLinkChanged ) + COMMAND_HANDLER( IDC_COMBOLINK, CBN_SELENDOK, OnLinkChanged ) + COMMAND_HANDLER( IDC_EDITICON, EN_KILLFOCUS, OnIconChanged ) + COMMAND_HANDLER( IDC_EDITICOND, EN_KILLFOCUS, OnIconDChanged ) + COMMAND_HANDLER( IDC_BUTTONRESET, BN_CLICKED, OnReset ) + CHAIN_MSG_MAP( CEditCustomItemDlg ) + END_MSG_MAP() + + virtual BEGIN_RESIZE_MAP + RESIZE_CONTROL(IDC_COMBOCOMMAND,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_COMBOLINK,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_BUTTONCOMMAND,MOVE_MOVE_X) + RESIZE_CONTROL(IDC_BUTTONLINK,MOVE_MOVE_X) + RESIZE_CONTROL(IDC_EDITLABEL,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_EDITTIP,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_EDITICON,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_BUTTONICON,MOVE_MOVE_X) + RESIZE_CONTROL(IDC_EDITICOND,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_BUTTONICOND,MOVE_MOVE_X) + RESIZE_CONTROL(IDOK,MOVE_MOVE_X) + RESIZE_CONTROL(IDCANCEL,MOVE_MOVE_X) + END_RESIZE_MAP + +protected: + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCommandChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnLinkChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnIconChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnIconDChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnBrowseCommand( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnBrowseLink( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnBrowseIcon( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnReset( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + +private: + bool m_bNoLinks; + int m_Style; +}; + +LRESULT CEditToolbarDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + m_Style=GetWinVersion()>=WIN_VER_WIN8?SETTINGS_STYLE_WIN8:SETTINGS_STYLE_WIN7; + CWindow commands=GetDlgItem(IDC_COMBOCOMMAND); + CWindow links=GetDlgItem(IDC_COMBOLINK); + InitDialog(commands,g_StdCommands,m_Style,SETTINGS_STYLE_MASK,links,g_CommonLinks); + SetDlgItemText(IDC_EDITLABEL,m_pItem->label); + SetDlgItemText(IDC_EDITTIP,m_pItem->tip); + SetDlgItemText(IDC_EDITICON,m_pItem->icon); + SetDlgItemText(IDC_EDITICOND,m_pItem->iconD); + + GetDlgItem(IDC_BUTTONRESET).EnableWindow(m_pItem->pStdCommand && *m_pItem->pStdCommand->name); + + UpdateIcons(IDC_ICONN,IDC_ICOND); + + CWindow tooltip=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_TRANSPARENT,TOOLTIPS_CLASS,NULL,WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP,0,0,0,0,m_hWnd,NULL,g_Instance,NULL); + tooltip.SendMessage(TTM_SETMAXTIPWIDTH,0,GetSystemMetrics(SM_CXSCREEN)/2); + + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS|TTF_IDISHWND,m_hWnd,(UINT_PTR)(HWND)commands}; + CString str=LoadStringEx(IDS_COMMAND_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + tool.uId=(UINT_PTR)(HWND)commands.GetWindow(GW_CHILD); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_LINK_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)links; + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + tool.uId=(UINT_PTR)(HWND)links.GetWindow(GW_CHILD); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_TEXT_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_EDITLABEL); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_TIP_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_EDITTIP); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_ICON_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_EDITICON); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_ICOND_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_EDITICOND); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_RESTORE_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_BUTTONRESET); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + return TRUE; +} + +LRESULT CEditToolbarDlg::OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + GetDlgItemText(IDC_EDITLABEL,m_pItem->label); + m_pItem->label.TrimLeft(); + m_pItem->label.TrimRight(); + GetDlgItemText(IDC_EDITTIP,m_pItem->tip); + m_pItem->tip.TrimLeft(); + m_pItem->tip.TrimRight(); + + return CEditCustomItemDlg::OnOK(wNotifyCode,wID,hWndCtl,bHandled); +} + +LRESULT CEditToolbarDlg::OnCommandChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CString text=GetComboText(wNotifyCode,wID); + if (text==m_pItem->command) return 0; + m_pItem->SetCommand(text,g_StdCommands,m_Style,SETTINGS_STYLE_MASK); + GetDlgItem(IDC_BUTTONRESET).EnableWindow(m_pItem->pStdCommand && *m_pItem->pStdCommand->name); + UpdateIcons(IDC_ICONN,IDC_ICOND); + return 0; +} + +LRESULT CEditToolbarDlg::OnLinkChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CString text=GetComboText(wNotifyCode,wID); + if (text==m_pItem->link) return 0; + m_pItem->link=text; + UpdateIcons(IDC_ICONN,IDC_ICOND); + return 0; +} + +LRESULT CEditToolbarDlg::OnIconChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CString text; + GetDlgItemText(IDC_EDITICON,text); + text.TrimLeft(); + text.TrimRight(); + if (text==m_pItem->icon) return 0; + m_pItem->icon=text; + UpdateIcons(IDC_ICONN,IDC_ICOND); + return 0; +} + +LRESULT CEditToolbarDlg::OnIconDChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CString text; + GetDlgItemText(IDC_EDITICOND,text); + text.TrimLeft(); + text.TrimRight(); + if (text==m_pItem->iconD) return 0; + m_pItem->iconD=text; + UpdateIcons(IDC_ICONN,IDC_ICOND); + return 0; +} + +LRESULT CEditToolbarDlg::OnBrowseCommand( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + wchar_t text[_MAX_PATH]; + GetDlgItemText(IDC_COMBOCOMMAND,text,_countof(text)); + if (BrowseCommandHelper(m_hWnd,text)) + { + SetDlgItemText(IDC_COMBOCOMMAND,text); + SendMessage(WM_COMMAND,MAKEWPARAM(IDC_COMBOCOMMAND,CBN_KILLFOCUS)); + } + return 0; +} + +LRESULT CEditToolbarDlg::OnBrowseLink( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + wchar_t text[_MAX_PATH]; + GetDlgItemText(IDC_COMBOLINK,text,_countof(text)); + if (BrowseLinkHelper(m_hWnd,text)) + { + SetDlgItemText(IDC_COMBOLINK,text); + SendMessage(WM_COMMAND,MAKEWPARAM(IDC_COMBOLINK,CBN_KILLFOCUS)); + } + return 0; +} + +LRESULT CEditToolbarDlg::OnBrowseIcon( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + wchar_t text[_MAX_PATH]; + if (wID==IDC_BUTTONICON) wID=IDC_EDITICON; + if (wID==IDC_BUTTONICOND) wID=IDC_EDITICOND; + GetDlgItemText(wID,text,_countof(text)); + if (wID==IDC_EDITICOND && !*text) + GetDlgItemText(IDC_EDITICON,text,_countof(text)); + if (BrowseIconHelper(m_hWnd,text)) + { + SetDlgItemText(wID,text); + SendMessage(WM_COMMAND,MAKEWPARAM(wID,EN_KILLFOCUS)); + } + return 0; +} + +LRESULT CEditToolbarDlg::OnReset( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (!m_pItem->pStdCommand || !*m_pItem->pStdCommand->name) + return 0; + m_pItem->link.Empty(); + m_pItem->label=m_pItem->pStdCommand->label; + m_pItem->tip=m_pItem->pStdCommand->tip; + m_pItem->icon=m_pItem->pStdCommand->icon; + m_pItem->iconD=m_pItem->pStdCommand->iconD; + SendDlgItemMessage(IDC_COMBOLINK,CB_SETCURSEL,-1); + SetDlgItemText(IDC_EDITLABEL,m_pItem->label); + SetDlgItemText(IDC_EDITTIP,m_pItem->tip); + SetDlgItemText(IDC_EDITICON,m_pItem->icon); + SetDlgItemText(IDC_EDITICOND,m_pItem->iconD); + + UpdateIcons(IDC_ICONN,IDC_ICOND); + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +class CCustomToolbarDlg: public CCustomTreeDlg +{ +public: + CCustomToolbarDlg( void ): CCustomTreeDlg(false,g_StdCommands,GetWinVersion()>=WIN_VER_WIN8?SETTINGS_STYLE_WIN8:SETTINGS_STYLE_WIN7,SETTINGS_STYLE_MASK) {} + +protected: + virtual void ParseTreeItemExtra( CTreeItem *pItem, CSettingsParser &parser ); + virtual void SerializeItemExtra( CTreeItem *pItem, std::vector &stringBuilder ); + virtual bool EditItem( CTreeItem *pItem, HWND tree, HTREEITEM hItem, std::vector &modules ); +}; + +void CCustomToolbarDlg::ParseTreeItemExtra( CTreeItem *pItem, CSettingsParser &parser ) +{ + wchar_t text[256]; + Sprintf(text,_countof(text),L"%s.IconDisabled",pItem->name); + pItem->iconD=parser.FindSetting(text,L""); +} + +void CCustomToolbarDlg::SerializeItemExtra( CTreeItem *pItem, std::vector &stringBuilder ) +{ + if (!pItem->iconD.IsEmpty()) + { + wchar_t text[2048]; + Sprintf(text,_countof(text),L"%s.IconDisabled=%s\n",pItem->name,pItem->iconD); + AppendString(stringBuilder,text); + } +} + +bool CCustomToolbarDlg::EditItem( CTreeItem *pItem, HWND tree, HTREEITEM hItem, std::vector &modules ) +{ + bool bNoLinks=(TreeView_GetParent(tree,hItem) || TreeView_GetChild(tree,hItem)); + return CEditToolbarDlg(pItem,bNoLinks,modules).Run(m_hWnd,IDD_CUSTOMTOOLBAR); +} + +class CCustomToolbarPanel: public ISettingsPanel +{ +public: + virtual HWND Create( HWND parent ); + virtual HWND Activate( CSetting *pGroup, const RECT &rect, bool bReset ); + virtual bool Validate( HWND parent ) { return true; } + +private: + static CCustomToolbarDlg s_Dialog; +}; + +CCustomToolbarDlg CCustomToolbarPanel::s_Dialog; + +HWND CCustomToolbarPanel::Create( HWND parent ) +{ + if (!s_Dialog.m_hWnd) + s_Dialog.Create(parent,LoadDialogEx(IDD_CUSTOMTREE)); + return s_Dialog.m_hWnd; +} + +HWND CCustomToolbarPanel::Activate( CSetting *pGroup, const RECT &rect, bool bReset ) +{ + s_Dialog.SetGroup(pGroup,bReset); + s_Dialog.SetWindowPos(HWND_TOP,&rect,SWP_SHOWWINDOW); + return s_Dialog.m_hWnd; +} + +static CCustomToolbarPanel g_CustomToolbarPanel; + +/////////////////////////////////////////////////////////////////////////////// + +static CSetting g_Settings[]={ +{L"Basic",CSetting::TYPE_GROUP,IDS_BASIC_SETTINGS}, + {L"EnableSettings",CSetting::TYPE_BOOL,0,0,1,CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"ProcessWhiteList",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"ProcessBlackList",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"NoInitialToolbar",CSetting::TYPE_BOOL,0,0,0,CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + +{L"NavigationPane",CSetting::TYPE_GROUP,IDS_NAVIGATION_SETTINGS}, + {L"TreeStyle",CSetting::TYPE_INT,IDS_TREE_STYLE,IDS_TREE_STYLE_TIP,2,CSetting::FLAG_WARM|CSetting::FLAG_BASIC}, + {L"XPClassic",CSetting::TYPE_RADIO,IDS_XPCLASSIC,IDS_XPCLASSIC_TIP}, + {L"XPSimple",CSetting::TYPE_RADIO,IDS_XPSIMPLE,IDS_XPSIMPLE_TIP}, + {L"Vista",CSetting::TYPE_RADIO,IDS_VISTA,IDS_VISTA_TIP}, + {L"HScrollbar",CSetting::TYPE_INT,IDS_SCROLLBAR,IDS_SCROLLBAR_TIP,0,CSetting::FLAG_WARM}, + {L"Default",CSetting::TYPE_RADIO,IDS_SCROLLBAR_DEFAULT,IDS_SCROLLBAR_DEFAULT_TIP}, + {L"Off",CSetting::TYPE_RADIO,IDS_SCROLLBAR_OFF,IDS_SCROLLBAR_OFF_TIP}, + {L"On",CSetting::TYPE_RADIO,IDS_SCROLLBAR_ON,IDS_SCROLLBAR_ON_TIP}, + {L"NoFadeButtons",CSetting::TYPE_BOOL,IDS_NO_FADE,IDS_NO_FADE_TIP,0,CSetting::FLAG_WARM,L"TreeStyle"}, + {L"TreeItemSpacing",CSetting::TYPE_INT,IDS_TREE_SPACING,IDS_TREE_SPACING_TIP,0,CSetting::FLAG_WARM}, + {L"FullIndent",CSetting::TYPE_BOOL,IDS_FULL_INDENT,IDS_FULL_INDENT_TIP,0,CSetting::FLAG_WARM,L"TreeStyle"}, + {L"AutoNavigate",CSetting::TYPE_INT,IDS_NAVIGATE,IDS_NAVIGATE_TIP,0,CSetting::FLAG_WARM|CSetting::FLAG_BASIC}, + {L"Default",CSetting::TYPE_RADIO,IDS_NAV_DEFAULT,IDS_NAV_DEFAULT_TIP}, + {L"KeyboardOnly",CSetting::TYPE_RADIO,IDS_NAV_KBD,IDS_NAV_KBD_TIP}, + {L"Always",CSetting::TYPE_RADIO,IDS_NAV_ALWAYS,IDS_NAV_ALWAYS_TIP}, + {L"AutoNavDelay",CSetting::TYPE_INT,IDS_NAV_DELAY,IDS_NAV_DELAY_TIP,100,CSetting::FLAG_WARM,L"AutoNavigate"}, + {L"AltEnter",CSetting::TYPE_BOOL,IDS_ALT_ENTER,IDS_ALT_ENTER_TIP,1,CSetting::FLAG_WARM|CSetting::FLAG_BASIC}, + {L"FixFolderScroll",CSetting::TYPE_BOOL,IDS_FIX_SCROLL,IDS_FIX_SCROLL_TIP,1,CSetting::FLAG_WARM}, + +{L"TitleBar",CSetting::TYPE_GROUP,IDS_TITLE_SETTINGS}, + {L"ShowCaption",CSetting::TYPE_BOOL,IDS_SHOW_CAPTION,IDS_SHOW_CAPTION_TIP,0,CSetting::FLAG_WARM}, + {L"ShowIcon",CSetting::TYPE_BOOL,IDS_SHOW_ICON,IDS_SHOW_ICON_TIP,0,CSetting::FLAG_WARM}, + {L"DisableBreadcrumbs",CSetting::TYPE_BOOL,IDS_NO_BREADCRUMBS,IDS_NO_BREADCRUMBS_TIP,0,CSetting::FLAG_WARM|CSetting::FLAG_BASIC}, + {L"AddressBarHistory",CSetting::TYPE_INT,IDS_ADDRESS_HISTORY,IDS_ADDRESS_HISTORY_TIP,0,CSetting::FLAG_WARM}, + {L"NormalHistory",CSetting::TYPE_RADIO,IDS_NORMAL_HISTORY,IDS_NORMAL_HISTORY_TIP}, + {L"SimplePath",CSetting::TYPE_RADIO,IDS_SIMPLE_PATH,IDS_SIMPLE_PATH_TIP}, + {L"ExtendedPath",CSetting::TYPE_RADIO,IDS_EXTENDED_PATH,IDS_EXTENDED_PATH_TIP}, + {L"HideSearch",CSetting::TYPE_BOOL,IDS_HIDE_SEARCH,IDS_HIDE_SEARCH_TIP,0,CSetting::FLAG_WARM}, + {L"AddressAltD",CSetting::TYPE_STRING,IDS_ALT_D,IDS_ALT_D_TIP,L"",CSetting::FLAG_WARM}, + {L"UpHotkey2",CSetting::TYPE_HOTKEY_ANY,IDS_UP_HOTKEY,IDS_UP_HOTKEY_TIP,0,CSetting::FLAG_WARM}, + +{L"UpButton",CSetting::TYPE_GROUP,IDS_UP_SETTINGS}, + {L"ShowUpButton",CSetting::TYPE_INT,IDS_SHOW_UP,IDS_SHOW_UP_TIP,2,CSetting::FLAG_WARM|CSetting::FLAG_BASIC}, + {L"DontShow",CSetting::TYPE_RADIO,IDS_DONT_SHOW,IDS_DONT_SHOW_TIP}, + {L"BeforeBack",CSetting::TYPE_RADIO,IDS_BEFORE_BACK,IDS_BEFORE_BACK_TIP}, + {L"AfterBack",CSetting::TYPE_RADIO,IDS_AFTER_BACK,IDS_AFTER_BACK_TIP}, + {L"UpIconNormal",CSetting::TYPE_ICON,IDS_UP_NORMAL,IDS_UP_NORMAL_TIP,L",4",CSetting::FLAG_WARM,L"ShowUpButton"}, + {L"UpIconPressed",CSetting::TYPE_ICON,IDS_UP_PRESSED,IDS_UP_PRESSED_TIP,L",5",CSetting::FLAG_WARM,L"ShowUpButton"}, + {L"UpIconHot",CSetting::TYPE_ICON,IDS_UP_HOT,IDS_UP_HOT_TIP,L",6",CSetting::FLAG_WARM,L"ShowUpButton"}, + {L"UpIconDisabled",CSetting::TYPE_ICON,IDS_UP_DISABLED,IDS_UP_DISABLED_TIP,L",7",CSetting::FLAG_WARM,L"ShowUpButton"}, + {L"UpIconSize",CSetting::TYPE_INT,IDS_UP_SIZE,IDS_UP_SIZE_TIP,0,CSetting::FLAG_WARM,L"ShowUpButton"}, // 30 for DPI<120 and 36 for DPI>=120 + {L"UpHotkey",CSetting::TYPE_HOTKEY_ANY,IDS_UP_HOTKEY,IDS_UP_HOTKEY_TIP,0,CSetting::FLAG_WARM}, + +{L"Toolbar",CSetting::TYPE_GROUP,IDS_TOOLBAR_SETTINGS}, + {L"UseBigButtons",CSetting::TYPE_BOOL,IDS_BIG_BUTTONS,IDS_BIG_BUTTONS_TIP,1,CSetting::FLAG_WARM}, + {L"SmallIconSize",CSetting::TYPE_INT,IDS_SMALL_SIZE,IDS_SMALL_SIZE_TIP,-1,CSetting::FLAG_WARM}, // 16 for DPI<120 and 24 for DPI>=120 + {L"LargeIconSize",CSetting::TYPE_INT,IDS_LARGE_SIZE,IDS_LARGE_SIZE_TIP,-1,CSetting::FLAG_WARM}, // 24 for DPI<120 and 32 for DPI>=120 + {L"MenuIconSize",CSetting::TYPE_INT,IDS_MENU_SIZE,IDS_MENU_SIZE_TIP,16,CSetting::FLAG_WARM}, + {L"ToolbarListMode",CSetting::TYPE_BOOL,IDS_LIST_MODE,IDS_LIST_MODE_TIP,0,CSetting::FLAG_WARM}, + {L"SameSizeButtons",CSetting::TYPE_BOOL,IDS_SAME_SIZE,IDS_SAME_SIZE_TIP,0,CSetting::FLAG_WARM,L"ToolbarListMode=0"}, + {L"ResizeableToolbar",CSetting::TYPE_BOOL,IDS_RESIZEABLE,IDS_RESIZEABLE_TIP,0,CSetting::FLAG_WARM}, + +{L"CustomToolbar",CSetting::TYPE_GROUP,IDS_BUTTONS_SETTINGS,0,0,0,NULL,NULL,&g_CustomToolbarPanel}, + {L"ToolbarItems",CSetting::TYPE_MULTISTRING,0,0,g_DefaultToolbar,CSetting::FLAG_WARM}, + +{L"StatusBar",CSetting::TYPE_GROUP,IDS_STATUS_SETTINGS}, + {L"ShowFreeSpace",CSetting::TYPE_BOOL,IDS_FREE_SPACE,IDS_FREE_SPACE_TIP,1,CSetting::FLAG_WARM|CSetting::FLAG_BASIC}, + {L"ShowInfoTip",CSetting::TYPE_BOOL,IDS_INFO_TIP,IDS_INFO_TIP_TIP,1,CSetting::FLAG_WARM,L"ShowFreeSpace"}, + {L"ForceRefreshWin7",CSetting::TYPE_BOOL,IDS_FORCE_REFRESH,IDS_FORCE_REFRESH_TIP,1,CSetting::FLAG_WARM,L"ShowFreeSpace"}, + +{L"StatusBar8",CSetting::TYPE_GROUP,IDS_STATUS_SETTINGS}, + {L"ShowStatusBar",CSetting::TYPE_BOOL,IDS_SHOWSTATUSBAR,IDS_SHOWSTATUSBAR_TIP,1,CSetting::FLAG_WARM|CSetting::FLAG_BASIC}, + {L"ShowFreeSpace2",CSetting::TYPE_BOOL,IDS_FREE_SPACE,IDS_FREE_SPACE_TIP,1,CSetting::FLAG_WARM,L"ShowStatusBar",L"ShowStatusBar"}, + {L"ShowZone",CSetting::TYPE_BOOL,IDS_SHOW_ZONE,IDS_SHOW_ZONE_TIP,1,CSetting::FLAG_WARM,L"ShowStatusBar",L"ShowStatusBar"}, + {L"ShowInfoTip2",CSetting::TYPE_BOOL,IDS_INFO_TIP,IDS_INFO_TIP_TIP,1,CSetting::FLAG_WARM,L"ShowStatusBar",L"ShowStatusBar"}, + {L"StatusBarFont",CSetting::TYPE_FONT,IDS_STATUS_FONT,IDS_STATUS_FONT_TIP,L"Segoe UI, normal, 9",CSetting::FLAG_WARM,L"ShowStatusBar",L"ShowStatusBar"}, + +{L"FilePane",CSetting::TYPE_GROUP,IDS_FILEPANE_SETTINGS}, + {L"ShareOverlay",CSetting::TYPE_BOOL,IDS_SHARE,IDS_SHARE_TIP,0,CSetting::FLAG_COLD|CSetting::FLAG_BASIC}, + {L"ShareOverlayIcon",CSetting::TYPE_ICON,IDS_SHARE_ICON,IDS_SHARE_ICON_TIP,L"%windir%\\system32\\imageres.dll,164",CSetting::FLAG_COLD,L"ShareOverlay",L"ShareOverlay"}, + {L"ShareOverlayHidden",CSetting::TYPE_BOOL,IDS_SHARE_HIDDEN,IDS_SHARE_HIDDEN_TIP,0,CSetting::FLAG_COLD,L"ShareOverlay",L"ShareOverlay"}, + {L"ShareExplorer",CSetting::TYPE_BOOL,IDS_SHARE_EXPLORER,IDS_SHARE_EXPLORER_TIP,1,CSetting::FLAG_COLD,L"ShareOverlay",L"ShareOverlay"}, + {L"ShowHeaders",CSetting::TYPE_BOOL,IDS_HEADERS,IDS_HEADERS_TIP,0,CSetting::FLAG_WARM}, + {L"HideScrollTip",CSetting::TYPE_BOOL,IDS_SCROLLTIP,IDS_SCROLLTIP_TIP,0,CSetting::FLAG_WARM}, + +{L"FileOperation",CSetting::TYPE_GROUP,IDS_FILE_SETTINGS}, + {L"ReplaceFileUI",CSetting::TYPE_BOOL,IDS_FILE_UI,IDS_FILE_UI_TIP,1,CSetting::FLAG_WARM|CSetting::FLAG_BASIC}, + {L"ReplaceFolderUI",CSetting::TYPE_BOOL,IDS_FOLDER_UI,IDS_FOLDER_UI_TIP,1,CSetting::FLAG_WARM|CSetting::FLAG_BASIC}, + {L"OverwriteAlertLevel",CSetting::TYPE_INT,IDS_ALERT_LEVEL,IDS_ALERT_LEVEL_TIP,0,CSetting::FLAG_WARM,L"ReplaceFileUI",L"ReplaceFileUI"}, + {L"NoAlert",CSetting::TYPE_RADIO,IDS_NO_ALERT,IDS_NO_ALERT_TIP}, + {L"SystemFiles",CSetting::TYPE_RADIO,IDS_SYS_FILES,IDS_SYS_FILES_TIP}, + {L"ReadOnlyFiles",CSetting::TYPE_RADIO,IDS_RO_FILES,IDS_RO_FILES_TIP}, + {L"EnableMore",CSetting::TYPE_BOOL,IDS_MORE,IDS_MORE_TIP,0,CSetting::FLAG_WARM}, + {L"MoreProgressDelay",CSetting::TYPE_INT,IDS_MORE_DELAY,IDS_MORE_DELAY_TIP,-1,CSetting::FLAG_WARM,L"EnableMore",L"EnableMore"}, // 500 for Windows 7 Aero, and 0 otherwise + {L"FileExplorer",CSetting::TYPE_BOOL,IDS_FILE_EXPLORER,IDS_FILE_EXPLORER_TIP,1,CSetting::FLAG_COLD}, + +{L"Language",CSetting::TYPE_GROUP,IDS_LANGUAGE_SETTINGS,0,0,0,NULL,NULL,GetLanguageSettings(COMPONENT_EXPLORER)}, + {L"Language",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_COLD|CSetting::FLAG_SHARED}, + +{NULL} +}; + +void UpgradeSettings( bool bShared ) +{ +} + +void UpdateSettings( void ) +{ + HDC hdc=GetDC(NULL); + int dpi=GetDeviceCaps(hdc,LOGPIXELSY); + ReleaseDC(NULL,hdc); + UpdateSetting(L"SmallIconSize",CComVariant((dpi>=120)?24:16),false); + UpdateSetting(L"LargeIconSize",CComVariant((dpi>=120)?32:24),false); + UpdateSetting(L"UpIconSize",CComVariant((dpi>=120)?36:30),false); + FindSetting(L"UpHotkey2")->pLinkTo=FindSetting(L"UpHotkey"); + + if (GetWinVersion()>=WIN_VER_WIN8) + { + // Windows 8 + HideSettingGroup(L"StatusBar",true); + HideSetting(L"ShowFreeSpace",true); + FindSetting(L"ShowFreeSpace2")->pLinkTo=FindSetting(L"ShowFreeSpace"); + FindSetting(L"ShowInfoTip2")->pLinkTo=FindSetting(L"ShowInfoTip"); + + HideSettingGroup(L"UpButton",true); + UpdateSetting(L"ShowUpButton",CComVariant(0),false); HideSetting(L"ShowUpButton",true); + + HideSettingGroup(L"FileOperation",true); + UpdateSetting(L"ReplaceFileUI",CComVariant(0),false); HideSetting(L"ReplaceFileUI",true); + UpdateSetting(L"ReplaceFolderUI",CComVariant(0),false); HideSetting(L"ReplaceFolderUI",true); + + UpdateSetting(L"ShowCaption",CComVariant(0),false); HideSetting(L"ShowCaption",true); + UpdateSetting(L"ShowIcon",CComVariant(0),false); HideSetting(L"ShowIcon",true); + UpdateSetting(L"FixFolderScroll",CComVariant(0),false); HideSetting(L"FixFolderScroll",true); + UpdateSetting(L"ToolbarItems",CComVariant(g_DefaultToolbar2),false); + + if (GetWinVersion()>=WIN_VER_WIN10) + { + FindSetting(L"TreeStyle")[1].flags|=CSetting::FLAG_HIDDEN; + } + } + else + { + // Windows 7 + int delay=0; + BOOL comp; + if (SUCCEEDED(DwmIsCompositionEnabled(&comp)) && comp) + delay=500; + UpdateSetting(L"MoreProgressDelay",CComVariant(delay),false); + HideSetting(L"UpHotkey2",true); + HideSettingGroup(L"StatusBar8",true); + } + + CRegKey regKey; + wchar_t language[100]=L""; + if (regKey.Open(HKEY_LOCAL_MACHINE,L"Software\\IvoSoft\\ClassicShell",KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + ULONG size=_countof(language); + if (regKey.QueryStringValue(L"DefaultLanguage",language,&size)!=ERROR_SUCCESS) + language[0]=0; + } + UpdateSetting(L"Language",language,false); +} + +static bool g_bCopyHook0; // initial state of the copy hook before the settings are edited + +void InitSettings( void ) +{ + InitSettings(g_Settings,COMPONENT_EXPLORER,NULL); + g_bCopyHook0=GetWinVersion()>24,(ver>>16)&0xFF,ver&0xFFFF); + else + Sprintf(title,_countof(title),LoadStringEx(IDS_SETTINGS_TITLE)); + EditSettings(title,true,0); +} + +bool DllImportSettingsXml( const wchar_t *fname ) +{ + return ImportSettingsXml(fname); +} + +bool DllExportSettingsXml( const wchar_t *fname ) +{ + return ExportSettingsXml(fname); +} + +#ifndef _WIN64 +bool DllSaveAdmx( const char *admxFile, const char *admlFile, const char *docFile, const wchar_t *language ) +{ + WaitDllInitThread(); + HMODULE dll=NULL; + if (language[0]) + { + wchar_t path[_MAX_PATH]; + GetCurrentDirectory(_countof(path),path); + PathAppend(path,language); + PathAddExtension(path,L".dll"); + dll=LoadLibraryEx(path,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + } + LoadTranslationResources(dll,NULL); + return SaveAdmx(COMPONENT_EXPLORER,admxFile,admlFile,docFile); +} +#endif diff --git a/ClassicShellSrc/ClassicExplorer/SettingsUI.h b/ClassicShellSrc/ClassicExplorer/SettingsUI.h new file mode 100644 index 0000000..e44f170 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/SettingsUI.h @@ -0,0 +1,8 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +void InitSettings( void ); +void EditSettings( void ); +void ShowSettingsMenu( HWND parent, int x, int y ); diff --git a/ClassicShellSrc/ClassicExplorer/ShareOverlay.cpp b/ClassicShellSrc/ClassicExplorer/ShareOverlay.cpp new file mode 100644 index 0000000..f8540e7 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ShareOverlay.cpp @@ -0,0 +1,133 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// ShareOverlay.cpp : Implementation of CShareOverlay + +#include "stdafx.h" +#include "ShareOverlay.h" + +// CShareOverlay - adds an overlay icon to the shared folders + +bool CShareOverlay::s_bEnabled=false; +bool CShareOverlay::s_bShowHidden=false; +int CShareOverlay::s_Index; +wchar_t CShareOverlay::s_IconPath[_MAX_PATH]; + +CShareOverlay::CShareOverlay( void ) +{ + SHGetDesktopFolder(&m_pDesktop); + m_pShareInfo=NULL; + m_ShareCount=0; + m_UpdateTime=0; + InitializeCriticalSection(&m_Section); +} + +void CShareOverlay::FinalRelease( void ) +{ + DeleteCriticalSection(&m_Section); + if (m_pShareInfo) + NetApiBufferFree(m_pShareInfo); + m_pShareInfo=NULL; +} + +void CShareOverlay::InitOverlay( const wchar_t *icon, bool showHidden ) +{ + s_bEnabled=true; + if (icon) + { + Strcpy(s_IconPath,_countof(s_IconPath),icon); + wchar_t *c=wcsrchr(s_IconPath,','); + if (c) + { + *c=0; + s_Index=-_wtol(c+1); + } + else + s_Index=0; + } + else + { + Strcpy(s_IconPath,_countof(s_IconPath),L"%windir%\\system32\\imageres.dll"); + s_Index=-164; + } + DoEnvironmentSubst(s_IconPath,_countof(s_IconPath)); + s_bShowHidden=showHidden; +} + +HRESULT CShareOverlay::_InternalQueryInterface( REFIID iid, void** ppvObject ) +{ + if (iid==IID_IUnknown) + { + AddRef(); + *ppvObject=static_cast(this); + return S_OK; + } + if (iid==IID_IShellIconOverlayIdentifier && s_bEnabled) + { + // only support IShellIconOverlayIdentifier if s_bEnabled is true + AddRef(); + *ppvObject=static_cast(this); + return S_OK; + } + *ppvObject=NULL; + return E_NOINTERFACE; +} + +STDMETHODIMP CShareOverlay::IsMemberOf( LPCWSTR pwszPath, DWORD dwAttrib ) +{ + EnterCriticalSection(&m_Section); + UpdateShareInfo(); + HRESULT res=S_FALSE; + if (m_pShareInfo) + { + for (DWORD i=0;i + +#include "ClassicExplorer_i.h" + +// CShareOverlay + +class ATL_NO_VTABLE CShareOverlay : + public CComObjectRootEx, + public CComCoClass, + public IShellIconOverlayIdentifier +{ +public: + CShareOverlay( void ); + + DECLARE_REGISTRY_RESOURCEID(IDR_SHAREOVERLAY) + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + HRESULT FinalConstruct( void ) + { + return S_OK; + } + + void FinalRelease( void ); + +public: + + HRESULT _InternalQueryInterface( REFIID iid, void** ppvObject ); + + // IShellIconOverlayIdentifier + STDMETHOD (IsMemberOf)( LPCWSTR pwszPath, DWORD dwAttrib ); + STDMETHOD (GetOverlayInfo)( LPWSTR pwszIconFile, int cchMax, int * pIndex, DWORD * pdwFlags ); + STDMETHOD (GetPriority)( int * pIPriority ); + + static void InitOverlay( const wchar_t *icon, bool showHidden ); + +private: + CComPtr m_pDesktop; + CRITICAL_SECTION m_Section; + SHARE_INFO_502 *m_pShareInfo; + DWORD m_ShareCount; + int m_UpdateTime; + + void UpdateShareInfo( void ); + + static bool s_bEnabled; + static bool s_bShowHidden; + static int s_Index; + static wchar_t s_IconPath[_MAX_PATH]; +}; + +OBJECT_ENTRY_AUTO(__uuidof(ShareOverlay), CShareOverlay) diff --git a/ClassicShellSrc/ClassicExplorer/ShareOverlay.rgs b/ClassicShellSrc/ClassicExplorer/ShareOverlay.rgs new file mode 100644 index 0000000..4ec4d9e --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/ShareOverlay.rgs @@ -0,0 +1,49 @@ +HKCR +{ + ClassicExplorer.ShareOverlay.1 = s 'ShareOverlay Class' + { + CLSID = s '{594D4122-1F87-41E2-96C7-825FB4796516}' + } + ClassicExplorer.ShareOverlay = s 'ShareOverlay Class' + { + CLSID = s '{594D4122-1F87-41E2-96C7-825FB4796516}' + CurVer = s 'ClassicExplorer.ShareOverlay.1' + } + NoRemove CLSID + { + ForceRemove {594D4122-1F87-41E2-96C7-825FB4796516} = s 'ShareOverlay Class' + { + ProgID = s 'ClassicExplorer.ShareOverlay.1' + VersionIndependentProgID = s 'ClassicExplorer.ShareOverlay' + ForceRemove 'Programmable' + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Apartment' + } + 'TypeLib' = s '{BF8D124A-A4E0-402F-8152-4EF377E62586}' + } + } +} + +HKLM +{ + NoRemove SOFTWARE + { + NoRemove Microsoft + { + NoRemove Windows + { + NoRemove CurrentVersion + { + NoRemove Explorer + { + NoRemove ShellIconOverlayIdentifiers + { + ForceRemove ShareOverlay = s '{594D4122-1F87-41E2-96C7-825FB4796516}' + } + } + } + } + } + } +} diff --git a/ClassicShellSrc/ClassicExplorer/dllmain.cpp b/ClassicShellSrc/ClassicExplorer/dllmain.cpp new file mode 100644 index 0000000..6b1c042 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/dllmain.cpp @@ -0,0 +1,282 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// dllmain.cpp : Implementation of DllMain. + +#include "stdafx.h" +#include "resource.h" +#include "..\ClassicShellLib\resource.h" +#include "dllmain.h" +#include "ShareOverlay.h" +#include "SettingsUI.h" +#include "Settings.h" +#include "Translations.h" +#include "ResourceHelper.h" +#include "FNVHash.h" +#include +#include + +#pragma comment(linker, \ + "\"/manifestdependency:type='Win32' "\ + "name='Microsoft.Windows.Common-Controls' "\ + "version='6.0.0.0' "\ + "processorArchitecture='*' "\ + "publicKeyToken='6595b64144ccf1df' "\ + "language='*'\"") + +CClassicExplorerModule _AtlModule; +bool g_bLogLevel; + +void InitClassicCopyProcess( void ); +void InitClassicCopyThread( void ); +void FreeClassicCopyThread( void ); + +bool g_bHookCopyThreads; +bool g_bExplorerExe; +LPCWSTR g_LoadedSettingsAtom; + +static int g_LoadDialogs[]= +{ + IDD_SETTINGS,0x04000000, + IDD_SETTINGSTREE,0x04000000, + IDD_BROWSEFORICON,0x04000000, + IDD_LANGUAGE,0x04000000, + IDD_CUSTOMTOOLBAR,0x04000000, + IDD_CUSTOMTREE,0x04000000, + IDD_PROGRESS,0x04000004, + 0 +}; + +const wchar_t *GetDocRelativePath( void ) +{ + return DOC_PATH; +} + +struct FindChild +{ + const wchar_t *className; + HWND hWnd; +}; + +static BOOL CALLBACK EnumChildProc( HWND hwnd, LPARAM lParam ) +{ + FindChild &find=*(FindChild*)lParam; + wchar_t name[256]; + GetClassName(hwnd,name,_countof(name)); + if (_wcsicmp(name,find.className)!=0) return TRUE; + find.hWnd=hwnd; + return FALSE; +} + +HWND FindChildWindow( HWND hwnd, const wchar_t *className ) +{ + FindChild find={className}; + EnumChildWindows(hwnd,EnumChildProc,(LPARAM)&find); + return find.hWnd; +} + +static DWORD g_TlsIndex; + +TlsData *GetTlsData( void ) +{ + void *pData=TlsGetValue(g_TlsIndex); + if (!pData) + { + pData=(void*)LocalAlloc(LPTR,sizeof(TlsData)); + memset(pData,0,sizeof(TlsData)); + TlsSetValue(g_TlsIndex,pData); + } + return (TlsData*)pData; +} + +static HANDLE g_DllInitThread; + +static DWORD CALLBACK DllInitThread( void* ) +{ + { + g_bLogLevel=false; + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicExplorer\\Settings",KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + DWORD log; + if (regKey.QueryDWORDValue(L"LogLevel",log)==ERROR_SUCCESS) + g_bLogLevel=log!=0; + } + } + InitSettings(); + + wchar_t path[_MAX_PATH]; + GetModuleFileName(g_Instance,path,_countof(path)); + *PathFindFileName(path)=0; + wchar_t fname[_MAX_PATH]; + Sprintf(fname,_countof(fname),L"%s" INI_PATH L"ExplorerL10N.ini",path); + CString language=GetSettingString(L"Language"); + ParseTranslations(fname,language); + + HINSTANCE resInstance=LoadTranslationDll(language); + + LoadTranslationResources(resInstance,g_LoadDialogs); + + if (resInstance) + FreeLibrary(resInstance); + + if (GetSettingBool(L"ShareOverlay") && (g_bExplorerExe || !GetSettingBool(L"ShareExplorer"))) + CShareOverlay::InitOverlay(GetSettingString(L"ShareOverlayIcon"),GetSettingBool(L"ShareOverlayHidden")); + return 0; +} + +void WaitDllInitThread( void ) +{ + ATLASSERT(g_DllInitThread); + WaitForSingleObject(g_DllInitThread,INFINITE); +} + +// DLL Entry Point +extern "C" BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved ) +{ + if (dwReason==DLL_PROCESS_ATTACH) + { + g_Instance=hInstance; + g_TlsIndex=TlsAlloc(); + if (g_TlsIndex==TLS_OUT_OF_INDEXES) + return FALSE; // TLS failure + + CRegKey regSettings, regSettingsUser, regPolicy, regPolicyUser; + bool bUpgrade=OpenSettingsKeys(COMPONENT_EXPLORER,regSettings,regSettingsUser,regPolicy,regPolicyUser); + + enum + { + SETTING_SHARE_OVERLAY, + SETTING_SHARE_EXPLORER, + SETTING_FILE_EXPLORER, + SETTING_REPLACE_FILE, + SETTING_REPLACE_FOLDER, + SETTING_MORE, + SETTING_WHITE_LIST, + SETTING_BLACK_LIST, + }; + + CSetting settings[]={ + {L"ShareOverlay",CSetting::TYPE_BOOL,0,0,0}, + {L"ShareExplorer",CSetting::TYPE_BOOL,0,0,1}, + {L"FileExplorer",CSetting::TYPE_BOOL,0,0,1}, + {L"ReplaceFileUI",CSetting::TYPE_BOOL,0,0,1}, + {L"ReplaceFolderUI",CSetting::TYPE_BOOL,0,0,1}, + {L"EnableMore",CSetting::TYPE_BOOL,0,0,0}, + {L"ProcessWhiteList",CSetting::TYPE_STRING,0,0,L""}, + {L"ProcessBlackList",CSetting::TYPE_STRING,0,0,L""}, + {NULL} + }; + + wchar_t path[_MAX_PATH]; + GetModuleFileName(NULL,path,_countof(path)); + const wchar_t *exe=PathFindFileName(path); + g_bExplorerExe=(_wcsicmp(exe,L"explorer.exe")==0 || _wcsicmp(exe,L"verclsid.exe")==0); + bool bReplaceUI=false; + if (GetWinVersion()<=WIN_VER_WIN7) + { + settings[SETTING_REPLACE_FILE].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser); + settings[SETTING_REPLACE_FOLDER].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser); + settings[SETTING_MORE].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser); + bReplaceUI=(GetSettingBool(settings[SETTING_REPLACE_FILE]) || GetSettingBool(settings[SETTING_REPLACE_FOLDER]) || GetSettingBool(settings[SETTING_MORE])); + } + + settings[SETTING_FILE_EXPLORER].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser); + if (_wcsicmp(exe,L"regsvr32.exe")!=0 && _wcsicmp(exe,L"msiexec.exe")!=0 && _wcsicmp(exe,L"ClassicExplorerSettings.exe")!=0 && !g_bExplorerExe) + { + // some arbitrary app + settings[SETTING_SHARE_OVERLAY].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser); + settings[SETTING_SHARE_EXPLORER].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser); + if ((!GetSettingBool(settings[SETTING_SHARE_OVERLAY]) || GetSettingBool(settings[SETTING_SHARE_EXPLORER])) && (!bReplaceUI || GetSettingBool(settings[SETTING_FILE_EXPLORER]))) + return FALSE; + + settings[SETTING_WHITE_LIST].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser); + CString whiteList=GetSettingString(settings[SETTING_WHITE_LIST]); + if (!whiteList.IsEmpty()) + { + // check for whitelisted process names + const wchar_t *str=whiteList; + bool bFound=false; + while (*str) + { + wchar_t token[_MAX_PATH]; + str=GetToken(str,token,_countof(token),L",;"); + wchar_t *start=token; + while (*start==' ') + start++; + wchar_t *end=start+Strlen(start); + while (end>start && end[-1]==' ') + end--; + *end=0; + if (_wcsicmp(exe,start)==0) + { + bFound=true; + break; + } + } + if (!bFound) + return FALSE; + } + else + { + settings[SETTING_BLACK_LIST].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser); + // check for blacklisted process names + CString blackList=GetSettingString(settings[SETTING_BLACK_LIST]); + const wchar_t *str=blackList; + while (*str) + { + wchar_t token[_MAX_PATH]; + str=GetToken(str,token,_countof(token),L",;"); + wchar_t *start=token; + while (*start==' ') + start++; + wchar_t *end=start+Strlen(start); + while (end>start && end[-1]==' ') + end--; + *end=0; + if (_wcsicmp(exe,start)==0) + return FALSE; + } + } + } + + g_LoadedSettingsAtom=(LPCWSTR)GlobalAddAtom(L"ClassicExplorer.LoadedSettings"); + + g_bHookCopyThreads=(bReplaceUI && (g_bExplorerExe || !GetSettingBool(settings[SETTING_FILE_EXPLORER]))); + if (g_bHookCopyThreads) + { + InitClassicCopyProcess(); + InitClassicCopyThread(); + } + + g_DllInitThread=CreateThread(NULL,0,DllInitThread,NULL,0,NULL); + } + + if (dwReason==DLL_THREAD_ATTACH) + { + if (g_bHookCopyThreads) + InitClassicCopyThread(); + } + + if (dwReason==DLL_THREAD_DETACH) + { + void *pData=TlsGetValue(g_TlsIndex); + if (pData) + LocalFree((HLOCAL)pData); + TlsSetValue(g_TlsIndex,NULL); + if (g_bHookCopyThreads) + FreeClassicCopyThread(); + } + + if (dwReason==DLL_PROCESS_DETACH) + { + void *pData=TlsGetValue(g_TlsIndex); + if (pData) + LocalFree((HLOCAL)pData); + TlsSetValue(g_TlsIndex,NULL); + TlsFree(g_TlsIndex); + GlobalDeleteAtom((ATOM)g_LoadedSettingsAtom); + } + + return _AtlModule.DllMain(dwReason, lpReserved); +} diff --git a/ClassicShellSrc/ClassicExplorer/dllmain.h b/ClassicShellSrc/ClassicExplorer/dllmain.h new file mode 100644 index 0000000..3a7d524 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/dllmain.h @@ -0,0 +1,43 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// dllmain.h : Declaration of module class. +#pragma once + +#include "ClassicExplorer_i.h" +#include + +class CClassicExplorerModule : public CAtlDllModuleT< CClassicExplorerModule > +{ +public : + DECLARE_LIBID(LIBID_ClassicExplorerLib) + DECLARE_REGISTRY_APPID_RESOURCEID(IDR_CLASSICEXPLORER, "{65843E27-A491-429F-84A0-30A947E20F92}") +}; + +extern class CClassicExplorerModule _AtlModule; + +// Some utility functions used by various modules +HWND FindChildWindow( HWND hwnd, const wchar_t *className ); +INT_PTR RunSettingsDialog( HWND hWndParent, DLGPROC lpDialogFunc ); + +struct TlsData +{ + // the bho instance that runs on this thread + class CExplorerBHO *bho; + + // the band instance that runs on this thread + class CExplorerBand *band; + + // one hook for each copy thread + HHOOK copyHook; + + // bCopyMultiFile is true if the first dialog in this thread is multi-file (IDD_FILEMULTI) + // if so, all the rest are multi-file. this makes the UI consistent (like the position of the Yes button doesn't change) + bool bCopyMultiFile; +}; + +TlsData *GetTlsData( void ); +extern LPCWSTR g_LoadedSettingsAtom; +extern bool g_bLogLevel; + +void WaitDllInitThread( void ); diff --git a/ClassicShellSrc/ClassicExplorer/resource.h b/ClassicShellSrc/ClassicExplorer/resource.h new file mode 100644 index 0000000..f2577bc --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/resource.h @@ -0,0 +1,336 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ClassicExplorer.rc +// +#define IDI_APPICON 1 +#define IDI_UP 2 +#define IDI_UPDISABLED 3 +#define IDI_UP2NORMAL 4 +#define IDI_UP2PRESSED 5 +#define IDI_UP2HOT 6 +#define IDI_UP2DISABLED 7 +#define IDR_CLASSICEXPLORER 101 +#define IDR_EXPLORERBAND 102 +#define IDR_EXPLORERBHO 104 +#define IDR_SHAREOVERLAY 105 +#define IDD_FILEMULTI 129 +#define IDD_FILE 130 +#define IDC_LINKMORE 204 +#define IDC_CHECKBHO 205 +#define IDC_CHECKCOPY 206 +#define IDC_STATICPROMPT1 207 +#define IDC_CHECKBIG 207 +#define IDC_STATICPROMPT2 208 +#define IDD_FILEMULTIR 208 +#define IDD_FILER 209 +#define IDC_STATICICON 209 +#define IDC_CHECK1 210 +#define IDD_FOLDERMULTI 210 +#define IDC_CHECK2 211 +#define IDD_FOLDER 211 +#define IDC_CHECK3 212 +#define IDD_FOLDERR 212 +#define IDC_CHECK4 213 +#define IDD_FOLDERMULTIR 213 +#define IDC_CHECK5 214 +#define IDC_CHECK6 215 +#define IDR_CLASSICCOPYEXT 216 +#define IDC_CHECKNOFADE 218 +#define IDC_CHECKSIZE 219 +#define IDC_CHECKAUTO 220 +#define IDC_CHECKCOPYFOLDER 221 +#define IDC_CHECK7 222 +#define IDC_CHECK8 223 +#define IDC_COMBOSTYLE 224 +#define IDC_CHECKOFFSET 225 +#define IDC_CHECKUP 226 +#define IDC_CHECKTITLE 227 +#define IDC_CHECKICON 228 +#define IDC_CHECKCRUMBS 229 +#define IDC_CHECKSHARED 230 +#define IDC_CHECKSHAREDEXP 231 +#define IDC_CHECKCOPYEXP 233 +#define IDC_CHECKMORE 234 +#define IDC_CHECKINFO 235 +#define IDC_COMBOCOMMAND 239 +#define IDC_EDITLABEL 240 +#define IDC_EDITTIP 241 +#define IDC_BUTTONLINK 242 +#define IDC_BUTTONCOMMAND 243 +#define IDC_EDITICON 245 +#define IDC_BUTTONICON 246 +#define IDC_EDITICOND 247 +#define IDC_BUTTONICOND 248 +#define IDC_STATICCOMMAND 251 +#define IDC_STATICLINK 252 +#define IDC_STATICTEXT 253 +#define IDC_STATICINFOTIP 254 +#define IDC_STATICICOND 255 +#define IDC_ICONN 256 +#define IDC_ICOND 257 +#define IDC_COMBOLINK 258 +#define IDC_STATICICON1 260 +#define IDC_BUTTONRESET 261 +#define IDC_STATICFNAME 1003 +#define IDC_STATICSRCSIZE 1004 +#define IDC_STATICSRCTIME 1005 +#define IDC_STATICDSTSIZE 1006 +#define IDC_STATICDSTTIME 1007 +#define IDC_STATICSRCICON 1008 +#define IDC_STATICDSTICON 1009 +#define IDD_CUSTOMTOOLBAR 2001 +#define IDS_APP_TITLE 2001 +#define IDS_SETTINGS_BTN 2002 +#define IDS_NEW_SETTINGS1 2003 +#define IDS_NEW_SETTINGS2 2004 +#define IDS_SETTINGS_TITLE 2005 +#define IDS_SETTINGS_TITLE_VER 2006 +#define IDS_LANGUAGE_SETTINGS 2010 +#define IDS_TOOLBAR_SETTINGS 2011 +#define IDS_BIG_BUTTONS 2012 +#define IDS_BIG_BUTTONS_TIP 2013 +#define IDS_SMALL_SIZE 2014 +#define IDS_SMALL_SIZE_TIP 2015 +#define IDS_LARGE_SIZE 2016 +#define IDS_LARGE_SIZE_TIP 2017 +#define IDS_MENU_SIZE 2018 +#define IDS_MENU_SIZE_TIP 2019 +#define IDS_SAME_SIZE 2020 +#define IDS_SAME_SIZE_TIP 2021 +#define IDS_LIST_MODE 2022 +#define IDS_LIST_MODE_TIP 2023 +#define IDS_RESIZEABLE 2024 +#define IDS_RESIZEABLE_TIP 2025 +#define IDS_BUTTONS_SETTINGS 2026 +#define IDS_NAVIGATION_SETTINGS 2027 +#define IDS_TREE_STYLE 2028 +#define IDS_TREE_STYLE_TIP 2029 +#define IDS_XPCLASSIC 2030 +#define IDS_XPCLASSIC_TIP 2031 +#define IDS_XPSIMPLE 2032 +#define IDS_XPSIMPLE_TIP 2033 +#define IDS_VISTA 2034 +#define IDS_VISTA_TIP 2035 +#define IDS_TREE_SPACING 2036 +#define IDS_TREE_SPACING_TIP 2037 +#define IDS_NO_FADE 2038 +#define IDS_NO_FADE_TIP 2039 +#define IDS_FULL_INDENT 2040 +#define IDS_FULL_INDENT_TIP 2041 +#define IDS_NAVIGATE 2042 +#define IDS_NAVIGATE_TIP 2043 +#define IDS_NAV_DELAY 2044 +#define IDS_NAV_DELAY_TIP 2045 +#define IDS_ALT_ENTER 2046 +#define IDS_ALT_ENTER_TIP 2047 +#define IDS_FIX_SCROLL 2048 +#define IDS_FIX_SCROLL_TIP 2049 +#define IDS_TITLE_SETTINGS 2050 +#define IDS_SHOW_CAPTION 2051 +#define IDS_SHOW_CAPTION_TIP 2052 +#define IDS_SHOW_ICON 2053 +#define IDS_SHOW_ICON_TIP 2054 +#define IDS_NO_BREADCRUMBS 2055 +#define IDS_NO_BREADCRUMBS_TIP 2056 +#define IDS_ADDRESS_HISTORY 2057 +#define IDS_ADDRESS_HISTORY_TIP 2058 +#define IDS_NORMAL_HISTORY 2059 +#define IDS_NORMAL_HISTORY_TIP 2060 +#define IDS_SIMPLE_PATH 2061 +#define IDS_SIMPLE_PATH_TIP 2062 +#define IDS_EXTENDED_PATH 2063 +#define IDS_EXTENDED_PATH_TIP 2064 +#define IDS_HIDE_SEARCH 2065 +#define IDS_HIDE_SEARCH_TIP 2066 +#define IDS_UP_SETTINGS 2067 +#define IDS_SHOW_UP 2068 +#define IDS_SHOW_UP_TIP 2069 +#define IDS_DONT_SHOW 2070 +#define IDS_DONT_SHOW_TIP 2071 +#define IDS_BEFORE_BACK 2072 +#define IDS_BEFORE_BACK_TIP 2073 +#define IDS_AFTER_BACK 2074 +#define IDS_AFTER_BACK_TIP 2075 +#define IDS_UP_NORMAL 2076 +#define IDS_UP_NORMAL_TIP 2077 +#define IDS_UP_HOT 2078 +#define IDS_UP_HOT_TIP 2079 +#define IDS_UP_PRESSED 2080 +#define IDS_UP_PRESSED_TIP 2081 +#define IDS_UP_DISABLED 2082 +#define IDS_UP_DISABLED_TIP 2083 +#define IDS_UP_SIZE 2084 +#define IDS_UP_SIZE_TIP 2085 +#define IDS_STATUS_SETTINGS 2086 +#define IDS_FREE_SPACE 2087 +#define IDS_FREE_SPACE_TIP 2088 +#define IDS_INFO_TIP 2089 +#define IDS_INFO_TIP_TIP 2090 +#define IDS_FORCE_REFRESH 2091 +#define IDS_FORCE_REFRESH_TIP 2092 +#define IDS_FILE_SETTINGS 2093 +#define IDS_FILE_UI 2094 +#define IDS_FILE_UI_TIP 2095 +#define IDS_FOLDER_UI 2096 +#define IDS_FOLDER_UI_TIP 2097 +#define IDS_ALERT_LEVEL 2098 +#define IDS_ALERT_LEVEL_TIP 2099 +#define IDS_NO_ALERT 2100 +#define IDS_NO_ALERT_TIP 2101 +#define IDS_SYS_FILES 2102 +#define IDS_SYS_FILES_TIP 2103 +#define IDS_RO_FILES 2104 +#define IDS_RO_FILES_TIP 2105 +#define IDS_MORE 2106 +#define IDS_MORE_TIP 2107 +#define IDS_MORE_DELAY 2108 +#define IDS_MORE_DELAY_TIP 2109 +#define IDS_FILE_EXPLORER 2110 +#define IDS_FILE_EXPLORER_TIP 2111 +#define IDS_FILEPANE_SETTINGS 2112 +#define IDS_SHARE 2113 +#define IDS_SHARE_TIP 2114 +#define IDS_SHARE_ICON 2115 +#define IDS_SHARE_ICON_TIP 2116 +#define IDS_SHARE_EXPLORER 2117 +#define IDS_SHARE_EXPLORER_TIP 2118 +#define IDS_HEADERS 2119 +#define IDS_HEADERS_TIP 2120 +#define IDS_SCROLLBAR 2121 +#define IDS_SCROLLBAR_TIP 2122 +#define IDS_SCROLLBAR_DEFAULT 2123 +#define IDS_SCROLLBAR_DEFAULT_TIP 2124 +#define IDS_SCROLLBAR_ON 2125 +#define IDS_SCROLLBAR_ON_TIP 2126 +#define IDS_SCROLLBAR_OFF 2127 +#define IDS_SCROLLBAR_OFF_TIP 2128 +#define IDS_COMMAND_TIP 2129 +#define IDS_LINK_TIP 2130 +#define IDS_TEXT_TIP 2131 +#define IDS_TIP_TIP 2132 +#define IDS_ICON_TIP 2133 +#define IDS_ICOND_TIP 2134 +#define IDS_RESTORE_TIP 2135 +#define IDS_SEPARATOR_TIP 2136 +#define IDS_UP_TIP 2137 +#define IDS_CUT_TIP 2138 +#define IDS_COPY_TIP 2139 +#define IDS_PASTE_TIP 2140 +#define IDS_DELETE_TIP 2141 +#define IDS_PROPERTIES_TIP 2142 +#define IDS_EMAIL_TIP 2143 +#define IDS_SETTINGS_TIP 2144 +#define IDS_REFRESH_TIP 2145 +#define IDS_STOP_TIP 2146 +#define IDS_RENAME_TIP 2147 +#define IDS_MOVETO_TIP 2148 +#define IDS_COPYTO_TIP 2149 +#define IDS_UNDO_TIP 2150 +#define IDS_REDO_TIP 2151 +#define IDS_SELECTALL_TIP 2152 +#define IDS_DESELECT_TIP 2153 +#define IDS_INVERT_TIP 2154 +#define IDS_BACK_TIP 2155 +#define IDS_FORWARD_TIP 2156 +#define IDS_VIEWTILES_TIP 2157 +#define IDS_VIEWDEATAILS_TIP 2158 +#define IDS_VIEWLIST_TIP 2159 +#define IDS_VIEWCONTENT_TIP 2160 +#define IDS_VIEWICONS1_TIP 2161 +#define IDS_VIEWICONS2_TIP 2162 +#define IDS_VIEWICONS3_TIP 2163 +#define IDS_VIEWICONS4_TIP 2164 +#define IDS_OPEN_TIP 2165 +#define IDS_CUSTOM_TIP 2166 +#define IDS_NEWFOLDER_TIP 2167 +#define IDS_SCROLLTIP 2168 +#define IDS_SCROLLTIP_TIP 2169 +#define IDS_NAV_DEFAULT 2170 +#define IDS_NAV_DEFAULT_TIP 2171 +#define IDS_NAV_KBD 2172 +#define IDS_NAV_KBD_TIP 2173 +#define IDS_NAV_ALWAYS 2174 +#define IDS_NAV_ALWAYS_TIP 2175 +#define IDS_ALT_D 2176 +#define IDS_ALT_D_TIP 2177 +#define IDS_SORT_TIP 2178 +#define IDS_GROUP_TIP 2179 +#define IDS_PASTE_SHORTCUT_TIP 2180 +#define IDS_UP_HOTKEY 2181 +#define IDS_UP_HOTKEY_TIP 2182 +#define IDS_MAP_DRIVE_TIP 2183 +#define IDS_DISCONNECT_DRIVE_TIP 2184 +#define IDS_CUSTOMIZEFOLDER_TIP 2185 +#define IDS_SEPARATOR_ITEM 2186 +#define IDS_UP_ITEM 2187 +#define IDS_CUT_ITEM 2188 +#define IDS_COPY_ITEM 2189 +#define IDS_PASTE_ITEM 2190 +#define IDS_PASTE_LNK_ITEM 2191 +#define IDS_DELETE_ITEM 2192 +#define IDS_PROPERTIES_ITEM 2193 +#define IDS_EMAIL_ITEM 2194 +#define IDS_SETTINGS_ITEM 2195 +#define IDS_REFRESH_ITEM 2196 +#define IDS_STOP_ITEM 2197 +#define IDS_RENAME_ITEM 2198 +#define IDS_NEWFOLDER_ITEM 2199 +#define IDS_MOVETO_ITEM 2200 +#define IDS_COPYTO_ITEM 2201 +#define IDS_UNDO_ITEM 2202 +#define IDS_REDO_ITEM 2203 +#define IDS_SELECTALL_ITEM 2204 +#define IDS_DESELECT_ITEM 2205 +#define IDS_INVERT_ITEM 2206 +#define IDS_BACK_ITEM 2207 +#define IDS_FORWARD_ITEM 2208 +#define IDS_MAP_DRIVE_ITEM 2209 +#define IDS_DISCONNECT_ITEM 2210 +#define IDS_CUSTOMIZE_ITEM 2211 +#define IDS_VIEWTILES_ITEM 2212 +#define IDS_VIEWDETAILS_ITEM 2213 +#define IDS_VIEWLIST_ITEM 2214 +#define IDS_VIEWCONTENT_ITEM 2215 +#define IDS_VIEWICONS1_ITEM 2216 +#define IDS_VIEWICONS2_ITEM 2217 +#define IDS_VIEWICONS3_ITEM 2218 +#define IDS_VIEWICONS4_ITEM 2219 +#define IDS_OPEN_ITEM 2220 +#define IDS_SORYBY_ITEM 2221 +#define IDS_GROUPBY_ITEM 2222 +#define IDS_CUSTOM_ITEM 2223 +#define IDS_SHOWSTATUSBAR 2224 +#define IDS_SHOWSTATUSBAR_TIP 2225 +#define IDS_SHOW_ZONE 2226 +#define IDS_SHOW_ZONE_TIP 2227 +#define IDS_SHARE_HIDDEN 2228 +#define IDS_SHARE_HIDDEN_TIP 2229 +#define IDS_NAVPANE_ITEM 2230 +#define IDS_NAVPANE_TIP 2231 +#define IDS_DETAILSPANE_ITEM 2232 +#define IDS_DETAILSPANE_TIP 2233 +#define IDS_PREVIEWPANE_ITEM 2234 +#define IDS_PREVIEWPANE_TIP 2235 +#define IDS_SHOW_EXTENSIONS 2236 +#define IDS_SHOW_EXTENSIONS_TIP 2237 +#define IDS_HIDDEN_FILES 2238 +#define IDS_HIDDEN_FILES_TIP 2239 +#define IDS_SYSTEM_FILES 2240 +#define IDS_SYSTEM_FILES_TIP 2241 +#define IDS_ZIP_ITEM 2242 +#define IDS_ZIP_TIP 2243 +#define IDS_STATUS_FONT 2244 +#define IDS_STATUS_FONT_TIP 2245 +#define IDS_FOLDEROPTIONS 2246 +#define IDS_FOLDEROPTIONS_TIP 2247 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 227 +#define _APS_NEXT_COMMAND_VALUE 32769 +#define _APS_NEXT_CONTROL_VALUE 262 +#define _APS_NEXT_SYMED_VALUE 106 +#endif +#endif diff --git a/ClassicShellSrc/ClassicExplorer/stdafx.cpp b/ClassicShellSrc/ClassicExplorer/stdafx.cpp new file mode 100644 index 0000000..2cde651 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/stdafx.cpp @@ -0,0 +1,6 @@ +// stdafx.cpp : source file that includes just the standard includes +// ClassicExplorer.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + diff --git a/ClassicShellSrc/ClassicExplorer/stdafx.h b/ClassicShellSrc/ClassicExplorer/stdafx.h new file mode 100644 index 0000000..76735f2 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/stdafx.h @@ -0,0 +1,37 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently + +#pragma once + +#include "targetver.h" + +#define STRICT_TYPED_ITEMIDS + +#define _ATL_APARTMENT_THREADED +#define _ATL_NO_AUTOMATIC_NAMESPACE + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +#include "resource.h" +#include +#include +#include +#include + +using namespace ATL; + +#include +#include +#include +#include + +#ifdef BUILD_SETUP +#define INI_PATH L"" +#define DOC_PATH L"" +#else +#define INI_PATH L"..\\" +#define DOC_PATH L"..\\..\\Docs\\Help\\" +#endif + +#include "StringUtils.h" diff --git a/ClassicShellSrc/ClassicExplorer/targetver.h b/ClassicShellSrc/ClassicExplorer/targetver.h new file mode 100644 index 0000000..d4feea8 --- /dev/null +++ b/ClassicShellSrc/ClassicExplorer/targetver.h @@ -0,0 +1,24 @@ +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Specifies that the minimum required platform is Windows 7. +#define WINVER 0x0602 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows 7. +#define _WIN32_WINNT 0x0602 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. +#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. +#endif diff --git a/ClassicShellSrc/ClassicExplorer/up.ico b/ClassicShellSrc/ClassicExplorer/up.ico new file mode 100644 index 0000000..bf70f04 Binary files /dev/null and b/ClassicShellSrc/ClassicExplorer/up.ico differ diff --git a/ClassicShellSrc/ClassicExplorer/up2Disabled.ico b/ClassicShellSrc/ClassicExplorer/up2Disabled.ico new file mode 100644 index 0000000..82e88ff Binary files /dev/null and b/ClassicShellSrc/ClassicExplorer/up2Disabled.ico differ diff --git a/ClassicShellSrc/ClassicExplorer/up2Hot.ico b/ClassicShellSrc/ClassicExplorer/up2Hot.ico new file mode 100644 index 0000000..4131c94 Binary files /dev/null and b/ClassicShellSrc/ClassicExplorer/up2Hot.ico differ diff --git a/ClassicShellSrc/ClassicExplorer/up2Normal.ico b/ClassicShellSrc/ClassicExplorer/up2Normal.ico new file mode 100644 index 0000000..1557a67 Binary files /dev/null and b/ClassicShellSrc/ClassicExplorer/up2Normal.ico differ diff --git a/ClassicShellSrc/ClassicExplorer/up2Pressed.ico b/ClassicShellSrc/ClassicExplorer/up2Pressed.ico new file mode 100644 index 0000000..a706603 Binary files /dev/null and b/ClassicShellSrc/ClassicExplorer/up2Pressed.ico differ diff --git a/ClassicShellSrc/ClassicExplorer/upDisabled.ico b/ClassicShellSrc/ClassicExplorer/upDisabled.ico new file mode 100644 index 0000000..0897dde Binary files /dev/null and b/ClassicShellSrc/ClassicExplorer/upDisabled.ico differ diff --git a/ClassicShellSrc/ClassicIE/ClassicIE.cpp b/ClassicShellSrc/ClassicIE/ClassicIE.cpp new file mode 100644 index 0000000..3ecbf4e --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIE.cpp @@ -0,0 +1,256 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#define STRICT_TYPED_ITEMIDS +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit +#include +#include +#include +#include +#include +#include "StringUtils.h" +#include "ResourceHelper.h" +#include "ClassicIEDLL\ClassicIEDLL.h" + +// Manifest to enable the 6.0 common controls +#pragma comment(linker, \ + "\"/manifestdependency:type='Win32' "\ + "name='Microsoft.Windows.Common-Controls' "\ + "version='6.0.0.0' "\ + "processorArchitecture='*' "\ + "publicKeyToken='6595b64144ccf1df' "\ + "language='*'\"") + +// Find and activate the Settings window +static BOOL CALLBACK FindSettingsEnum( HWND hwnd, LPARAM lParam ) +{ + wchar_t className[256]; + if (!GetClassName(hwnd,className,_countof(className)) || _wcsicmp(className,L"#32770")!=0) + return TRUE; + DWORD process=0; + GetWindowThreadProcessId(hwnd,&process); + HANDLE hProcess=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,process); + bool bFound=false; + if (hProcess!=INVALID_HANDLE_VALUE) + { + wchar_t path[_MAX_PATH]; + if (GetModuleFileNameEx(hProcess,NULL,path,_countof(path))) + { + if (_wcsicmp(PathFindFileName(path),L"ClassicIE_32.exe")==0) + { + SetForegroundWindow(hwnd); + bFound=true; + } + } + CloseHandle(hProcess); + } + return !bFound; +} + +void ZoneConfigure( HWND hWnd, const wchar_t *url ) +{ + // use undocumented function 383 from shlwapi + typedef void (WINAPI* FZoneConfigureW)(HWND,LPCWSTR); + FZoneConfigureW ZoneConfigureW; + + HMODULE hShlwapi=LoadLibrary(L"shlwapi.dll"); + if(hShlwapi) + { + ZoneConfigureW=(FZoneConfigureW)GetProcAddress(hShlwapi,MAKEINTRESOURCEA(383)); + if(ZoneConfigureW) + ZoneConfigureW(hWnd,url); + FreeLibrary(hShlwapi); + } +} + +int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow ) +{ + if (wcsncmp(lpCmdLine,L"zone ",5)==0) + { + wchar_t token[100]; + const wchar_t *url=GetToken(lpCmdLine+5,token,_countof(token),L" "); + ZoneConfigure((HWND)_wtol(token),url); + return 0; + } + + { + const wchar_t *pXml=wcsstr(lpCmdLine,L"-xml "); + if (pXml) + { + wchar_t xml[_MAX_PATH]; + GetToken(pXml+5,xml,_countof(xml),L" "); + CoInitialize(NULL); + bool res=DllImportSettingsXml(xml); + CoUninitialize(); + return res?0:1; + } + } + + { + const wchar_t *pBackup=wcsstr(lpCmdLine,L"-backup "); + if (pBackup) + { + wchar_t xml[_MAX_PATH]; + GetToken(pBackup+8,xml,_countof(xml),L" "); + CoInitialize(NULL); + bool res=DllExportSettingsXml(xml); + CoUninitialize(); + return res?0:1; + } + } + +#ifndef _WIN64 + const wchar_t *pSaveAdmx=wcsstr(lpCmdLine,L"-saveadmx "); + if (pSaveAdmx) + { + wchar_t language[100]; + GetToken(pSaveAdmx+10,language,_countof(language),L" "); + if (!DllSaveAdmx("ClassicIE.admx","ClassicIE.adml","ClassicIEADMX.txt",language)) + return 1; + return 0; + } +#endif + + WaitDllInitThread(); + + DWORD settings=GetIESettings(); + + HWND topWindow=(HWND)_wtol(lpCmdLine); + if (topWindow) + { + DWORD processId; + DWORD threadId=GetWindowThreadProcessId(topWindow,&processId); + bool bWrongBitness=false; + + { + HANDLE hProcess=OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,processId); + + if (hProcess) + { + BOOL bWow64; +#ifdef _WIN64 + bWrongBitness=(IsWow64Process(hProcess,&bWow64) && bWow64); // the current process is 64-bit, but the target is wow64 (32-bit) +#else + if (IsWow64Process(GetCurrentProcess(),&bWow64) && bWow64) + { + bWrongBitness=(!IsWow64Process(hProcess,&bWow64) || !bWow64); // the current process is 32-bit, but the target is 64-bit + } +#endif + CloseHandle(hProcess); + } + } + + if (bWrongBitness) + { + wchar_t path[_MAX_PATH]; + GetModuleFileName(hInstance,path,_countof(path)); + PathRemoveFileSpec(path); +#ifdef _WIN64 + PathAppend(path,L"ClassicIE_32.exe"); +#else + PathAppend(path,L"ClassicIE_64.exe"); +#endif + wchar_t cmdLine[1024]; + Sprintf(cmdLine,_countof(cmdLine),L"%s %s",path,lpCmdLine); + STARTUPINFO startupInfo={sizeof(startupInfo)}; + PROCESS_INFORMATION processInfo; + memset(&processInfo,0,sizeof(processInfo)); + if (CreateProcess(path,cmdLine,NULL,NULL,TRUE,0,NULL,NULL,&startupInfo,&processInfo)) + { + CloseHandle(processInfo.hThread); + CloseHandle(processInfo.hProcess); + } + return settings; + } + + CheckForNewVersionIE(); + + if (!(settings&IE_SETTING_CAPTION)) + return settings; + + HWND caption=FindWindowEx(topWindow,NULL,L"Client Caption",NULL); + DllLogToFile(CIE_LOG,L"exe: topWindow=%X, caption=%X",(DWORD)topWindow,(DWORD)caption); + UINT message=RegisterWindowMessage(L"ClassicIE.Injected"); + if (caption) + { + if (SendMessage(caption,message,0,0)!=0) + return settings; + + { + HANDLE hToken; + if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken)) + { + TOKEN_PRIVILEGES tp={1}; + if (LookupPrivilegeValue(NULL,L"SeDebugPrivilege",&tp.Privileges[0].Luid)) + tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; + AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL); + CloseHandle(hToken); + } + } + +#ifdef _WIN64 + HMODULE hHookModule=GetModuleHandle(L"ClassicIEDLL_64.dll"); +#else + HMODULE hHookModule=GetModuleHandle(L"ClassicIEDLL_32.dll"); +#endif + + HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,processId); + if (hProcess) + { + wchar_t path[_MAX_PATH]; + GetModuleFileName(hHookModule,path,_countof(path)); + void *remotePath=VirtualAllocEx(hProcess,NULL,sizeof(path),MEM_COMMIT,PAGE_READWRITE); + if (remotePath) + { + if (WriteProcessMemory(hProcess,remotePath,path,sizeof(path),NULL)) + { + HANDLE hThread=CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"LoadLibraryW"),remotePath,0,NULL); + if (hThread) + { + WaitForSingleObject(hThread,INFINITE); + CloseHandle(hThread); + } + } + VirtualFreeEx(hProcess,remotePath,sizeof(path),MEM_RELEASE); + } + CloseHandle(hProcess); + } + } + return settings; + } + +#ifndef _WIN64 + if (*lpCmdLine) +#endif + return settings; + + // if 32-bit exe is called with no arguments, show the settings + + INITCOMMONCONTROLSEX init={sizeof(init),ICC_STANDARD_CLASSES}; + InitCommonControlsEx(&init); + + // prevent multiple instances from running on the same desktop + // the assumption is that multiple desktops for the same user will have different name (but may repeat across users) + wchar_t userName[256]; + DWORD len=_countof(userName); + GetUserName(userName,&len); + len=0; + HANDLE desktop=GetThreadDesktop(GetCurrentThreadId()); + GetUserObjectInformation(desktop,UOI_NAME,NULL,0,&len); + wchar_t *deskName=(wchar_t*)malloc(len); + GetUserObjectInformation(desktop,UOI_NAME,deskName,len,&len); + + wchar_t mutexName[1024]; + Sprintf(mutexName,_countof(mutexName),L"ClassicIESettings.Mutex.%s.%s",userName,deskName); + free(deskName); + + HANDLE hMutex=CreateMutex(NULL,TRUE,mutexName); + if (GetLastError()==ERROR_ALREADY_EXISTS || GetLastError()==ERROR_ACCESS_DENIED) + { + EnumWindows(FindSettingsEnum,0); + return 0; + } + + ShowIESettings(); + return 0; +} diff --git a/ClassicShellSrc/ClassicIE/ClassicIE.manifest b/ClassicShellSrc/ClassicIE/ClassicIE.manifest new file mode 100644 index 0000000..1aa9b12 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIE.manifest @@ -0,0 +1,22 @@ + + + + + true + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicIE/ClassicIE.rc b/ClassicShellSrc/ClassicIE/ClassicIE.rc new file mode 100644 index 0000000..3b7f903 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIE.rc @@ -0,0 +1,101 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\0" +END + +3 TEXTINCLUDE +BEGIN + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 4,3,1,0 + PRODUCTVERSION 4,3,1,0 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "IvoSoft" + VALUE "FileDescription", "Classic IE" + VALUE "FileVersion", "4, 3, 1, 0" + VALUE "InternalName", "ClassicIE" + VALUE "LegalCopyright", "Copyright (C) 2009-2016, Ivo Beltchev" + VALUE "OriginalFilename", "ClassicIE.exe" + VALUE "ProductName", "Classic Shell" + VALUE "ProductVersion", "4, 3, 1, 0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON "..\\ClassicShellSetup\\ClassicShell.ico" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + diff --git a/ClassicShellSrc/ClassicIE/ClassicIE.vcproj b/ClassicShellSrc/ClassicIE/ClassicIE.vcproj new file mode 100644 index 0000000..466d528 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIE.vcproj @@ -0,0 +1,527 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEBHO.cpp b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEBHO.cpp new file mode 100644 index 0000000..3fbd7a8 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEBHO.cpp @@ -0,0 +1,405 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "ClassicIEDLL_i.h" +#include "ClassicIEBHO.h" +#include "ClassicIEDLL.h" +#include "Settings.h" +#include "SettingsUIHelper.h" +#include "ResourceHelper.h" +#include "Translations.h" +#include "FNVHash.h" +#include "dllmain.h" +#include + +static bool IsLowIntegrity( void ) +{ + bool bLow=false; + HANDLE hToken; + if (OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY|TOKEN_QUERY_SOURCE,&hToken)) + { + DWORD dwLengthNeeded; + if (!GetTokenInformation(hToken,TokenIntegrityLevel,NULL,0,&dwLengthNeeded)) + { + TOKEN_MANDATORY_LABEL *pTIL=(TOKEN_MANDATORY_LABEL*)malloc(dwLengthNeeded); + if (pTIL) + { + if (GetTokenInformation(hToken,TokenIntegrityLevel,pTIL,dwLengthNeeded,&dwLengthNeeded)) + { + DWORD dwIntegrityLevel=*GetSidSubAuthority(pTIL->Label.Sid,(DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTIL->Label.Sid)-1)); + bLow=(dwIntegrityLevel>24)<10) + PathAppend(path,L"ClassicIE_32.exe"); + else +#endif + PathAppend(path,L"ClassicIE_64.exe"); + + wchar_t cmdLine[1024]; + Sprintf(cmdLine,_countof(cmdLine),L"\"%s\" %s",path,param); + STARTUPINFO startupInfo={sizeof(startupInfo)}; + PROCESS_INFORMATION processInfo; + memset(&processInfo,0,sizeof(processInfo)); + DWORD res=GetIESettings(); + if (CreateProcess(path,cmdLine,NULL,NULL,TRUE,0,NULL,NULL,&startupInfo,&processInfo)) + { + CloseHandle(processInfo.hThread); + if (bWait) + { + if (WaitForSingleObject(processInfo.hProcess,2000)==WAIT_OBJECT_0) + GetExitCodeProcess(processInfo.hProcess,&res); + } + CloseHandle(processInfo.hProcess); + } + return res; +} + +HRESULT STDMETHODCALLTYPE CClassicIEBHO::SetSite( IUnknown *pUnkSite ) +{ + if (m_pWebBrowser && m_dwEventCookie!=0xFEFEFEFE) + DispEventUnadvise(m_pWebBrowser,&DIID_DWebBrowserEvents2); + m_pWebBrowser=NULL; + + IObjectWithSiteImpl::SetSite(pUnkSite); + if (pUnkSite) + { + HMODULE hFrame=GetModuleHandle(L"ieframe.dll"); + bool bLowIntegrity=IsLowIntegrity(); + m_ProtectedMode.LoadString(hFrame,bLowIntegrity?12939:12940); + m_ProtectedMode=L" | "+m_ProtectedMode; + // find the top window and run another process to subclass it (the top window can be in a higher-level process, so we can't subclass from here) + LogToFile(CIE_LOG,L"SetSite"); + CComQIPtr pProvider=pUnkSite; + + m_Settings=0; + + if (pProvider) + { + + pProvider->QueryService(SID_SShellBrowser,IID_IShellBrowser,(void**)&m_pBrowser); + + HWND hwnd; + HWND topWindow=NULL; + if (m_pBrowser && SUCCEEDED(m_pBrowser->GetWindow(&hwnd))) + { + HWND topWindow=GetAncestor(hwnd,GA_ROOT); + if (topWindow) + { + wchar_t param[100]; + Sprintf(param,_countof(param),L"%u",(DWORD)topWindow); + m_Settings=StartBroker(bLowIntegrity,param); + + if (m_Settings&(IE_SETTING_PROGRESS|IE_SETTING_ZONE)) + { + m_pZoneManager.CoCreateInstance(CLSID_InternetZoneManager,NULL,CLSCTX_INPROC_SERVER); + m_pSecurityManager.CoCreateInstance(CLSID_InternetSecurityManager,NULL,CLSCTX_INPROC_SERVER); + + pProvider->QueryService(SID_SWebBrowserApp,IID_IWebBrowser2,(void**)&m_pWebBrowser); + if (m_pWebBrowser) + { + if (m_dwEventCookie==0xFEFEFEFE) // ATL's event cookie is 0xFEFEFEFE when the sink is not advised + DispEventAdvise(m_pWebBrowser,&DIID_DWebBrowserEvents2); + } + } + } + } + } + } + else + { + m_pBrowser=NULL; + m_pWebBrowser=NULL; + m_pZoneManager=NULL; + m_pSecurityManager=NULL; + } + return S_OK; +} + +HRESULT WINAPI CClassicIEBHO::UpdateRegistry( BOOL bRegister ) +{ + wchar_t path[_MAX_PATH]; + GetModuleFileName(g_Instance,path,_countof(path)); + PathRemoveFileSpec(path); + + CString menu; + menu.LoadString(IDS_SETTINGS_TITLE); + + _ATL_REGMAP_ENTRY mapEntries[]={ + {L"MODULEPATH",path}, + {L"MENUTEXT",menu}, + {NULL,NULL} + }; + + return _AtlModule.UpdateRegistryFromResource(IDR_CLASSICIEBHO,bRegister,mapEntries); +} + +LRESULT CALLBACK CClassicIEBHO::SubclassStatusProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==SB_SETPARTS && wParam>0) + { + CClassicIEBHO *pThis=(CClassicIEBHO*)uIdSubclass; + int w0=*(int*)lParam; // total width + int w1=pThis->m_Progress<0?0:PROGRESS_WIDTH; // progress part + int w2=pThis->m_TextWidth; // zone part + int w=w1+w2; + int parts[PART_COUNT]; + parts[PART_TEXT]=w0; + if (parts[PART_TEXT]>=w+MIN_TEXT_WIDTH) + parts[PART_TEXT]-=w; + else if (parts[PART_TEXT]>=MIN_TEXT_WIDTH) + parts[PART_TEXT]=MIN_TEXT_WIDTH; + if (parts[PART_TEXT]>w0) + parts[PART_TEXT]=w0; + + if (parts[PART_TEXT]+w1>w0) + w1=0; + parts[PART_PROGRESS]=parts[PART_TEXT]+w1; + parts[PART_ZONE]=w0; + parts[PART_ZOOM]=-1; + + DefSubclassProc(hWnd,SB_SETPARTS,_countof(parts),(LPARAM)parts); + + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS,hWnd}; + tool.uId=1; + DefSubclassProc(hWnd,SB_GETRECT,PART_ZONE,(LPARAM)&tool.rect); + SendMessage(pThis->m_Tooltip,TTM_NEWTOOLRECT,0,(LPARAM)&tool); + + if (w1==0) + ShowWindow(pThis->m_ProgressBar,SW_HIDE); + else + { + RECT rc; + DefSubclassProc(hWnd,SB_GETRECT,PART_PROGRESS,(LPARAM)&rc); + rc.left+=2; + rc.right-=2; + rc.top+=1; + rc.bottom-=1; + SetWindowPos(pThis->m_ProgressBar,NULL,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,SWP_NOZORDER|SWP_SHOWWINDOW); + } + return TRUE; + } + + if (uMsg==SB_GETPARTS) + { + int parts[10]; + int n=(int)DefSubclassProc(hWnd,SB_GETPARTS,_countof(parts),(LPARAM)parts); + const int *p=parts; + if (n>2) + { + p+=n-2; + n=2; + } + if (lParam) + memcpy((int*)lParam,p,4*((n<(int)wParam)?n:wParam)); + return n; + } + + if (uMsg==SB_GETRECT) + { + if (wParam==1) wParam=PART_ZOOM; + else if (wParam>PART_OFFSET) wParam-=PART_OFFSET; + } + + if (uMsg==SB_SETTEXT) + { + if (!SendMessage(hWnd,SB_ISSIMPLE,0,0)) + { + if ((wParam&255)==1) wParam=PART_ZOOM; + else if ((wParam&255)>PART_OFFSET) wParam-=PART_OFFSET; + } + } + + if (uMsg==WM_LBUTTONDBLCLK) + { + POINT pt={(short)LOWORD(lParam),(short)HIWORD(lParam)}; + RECT rc; + DefSubclassProc(hWnd,SB_GETRECT,PART_ZONE,(LPARAM)&rc); + if (PtInRect(&rc,pt)) + { + CClassicIEBHO *pThis=(CClassicIEBHO*)uIdSubclass; + CComBSTR url; + if (pThis->m_pWebBrowser && SUCCEEDED(pThis->m_pWebBrowser->get_LocationURL(&url))) + { + wchar_t buf[1024]; + Sprintf(buf,_countof(buf),L"zone %u %s",(unsigned)GetAncestor(hWnd,GA_ROOT),(const wchar_t*)url); + StartBroker(false,buf); + } + + return 0; + } + } + + if (uMsg==SB_SIMPLE) + { + CClassicIEBHO *pThis=(CClassicIEBHO*)uIdSubclass; + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + if (wParam) + { + ShowWindow(pThis->m_ProgressBar,SW_HIDE); + } + else + { + pThis->ResetParts(); + } + return res; + } + + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +void CClassicIEBHO::ResetParts( void ) +{ + int parts[256]; + int n=(int)SendMessage(m_StatusBar,SB_GETPARTS,_countof(parts),(LPARAM)parts); + SendMessage(m_StatusBar,SB_SETPARTS,n,(LPARAM)parts); +} + +STDMETHODIMP CClassicIEBHO::OnNavigateComplete( IDispatch *pDisp, VARIANT *URL ) +{ + HWND status; + if (!m_pBrowser || FAILED(m_pBrowser->GetControlWindow(FCW_STATUS,&status))) + return S_OK; + + if (m_StatusBar!=status) + { + if (m_StatusBar) RemoveWindowSubclass(m_StatusBar,SubclassStatusProc,(UINT_PTR)this); + m_StatusBar=status; + if (m_StatusBar) + { + m_TextWidth=0; + SetWindowSubclass(m_StatusBar,SubclassStatusProc,(UINT_PTR)this,0); + ResetParts(); + } + } + + if (!m_StatusBar) return S_OK; + + if (!m_Tooltip) + { + m_Tooltip=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_TRANSPARENT,TOOLTIPS_CLASS,NULL,WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP,0,0,0,0,m_StatusBar,NULL,g_Instance,NULL); + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS,m_StatusBar}; + tool.uId=1; + tool.hinst=GetModuleHandle(L"ieframe.dll"); + tool.lpszText=MAKEINTRESOURCE(12941); + SendMessage(m_Tooltip,TTM_ADDTOOL,0,(LPARAM)&tool); + } + + if (!m_ProgressBar) + { + m_ProgressBar=CreateWindowEx(0,PROGRESS_CLASS,NULL,WS_CHILD|PBS_SMOOTH,0,0,0,0,m_StatusBar,NULL,g_Instance,NULL); + SendMessage(m_ProgressBar,PBM_SETRANGE,0,MAKELPARAM(0,100)); + } + + m_TextWidth=0; + if (!(m_Settings&IE_SETTING_ZONE)) + return S_OK; + wchar_t text[256]; + text[0]=0; + HICON hIcon=NULL; + if (m_pZoneManager && m_pSecurityManager && URL && URL->vt==VT_BSTR) + { + DWORD zone; + ZONEATTRIBUTES attributes={sizeof(attributes)}; + if (SUCCEEDED(m_pSecurityManager->MapUrlToZone(URL->bstrVal,&zone,0)) && SUCCEEDED(m_pZoneManager->GetZoneAttributes(zone,&attributes))) + { + Strcpy(text,_countof(text),attributes.szDisplayName); + if (m_Settings&IE_SETTING_PROTECTED) + Strcat(text,_countof(text),m_ProtectedMode); + unsigned int key=CalcFNVHash(attributes.szIconPath); + std::map::const_iterator it=m_IconCache.find(key); + if (it!=m_IconCache.end()) + hIcon=it->second; + else + { + wchar_t path[_MAX_PATH]; + wchar_t *str=wcschr(attributes.szIconPath,'#'); + if (!str) str=wcschr(attributes.szIconPath,','); + int index=0; + if (str) + { + index=_wtol(str+1); + *str=0; + } + Strcpy(path,_countof(path),attributes.szIconPath); + if (PathIsRelative(path)) + PathFindOnPath(path,NULL); + if (index==0) + hIcon=(HICON)LoadImage(NULL,path,IMAGE_ICON,16,16,LR_LOADFROMFILE); + else + { + HMODULE hModule=LoadLibraryEx(path,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (hModule) + { + hIcon=(HICON)LoadImage(hModule,MAKEINTRESOURCE(index),IMAGE_ICON,16,16,0); + FreeLibrary(hModule); + } + } + m_IconCache[key]=hIcon; + } + } + } + if (text[0]) + { + HDC hdc=GetDC(m_StatusBar); + HGDIOBJ font0=SelectObject(hdc,(HFONT)SendMessage(m_StatusBar,WM_GETFONT,0,0)); + SIZE size; + GetTextExtentPoint32(hdc,text,Strlen(text),&size); + m_TextWidth=size.cx; + SelectObject(hdc,font0); + ReleaseDC(m_StatusBar,hdc); + } + + // reset the parts to apply the new text width + m_TextWidth+=32; + ResetParts(); + + // set text and icon + SendMessage(m_StatusBar,SB_SETTEXT,PART_ZONE+PART_OFFSET,(LPARAM)text); + SendMessage(m_StatusBar,SB_SETICON,PART_ZONE,(LPARAM)hIcon); + + return S_OK; +} + +STDMETHODIMP CClassicIEBHO::OnProgressChange( long progress, long progressMax ) +{ + if (!(m_Settings&IE_SETTING_PROGRESS)) + return S_OK; + bool bVisible=(IsWindowVisible(m_ProgressBar)!=0); + if (progress<0 || progressMax==0) + { + m_Progress=-1; + if (!bVisible) return S_OK; + } + else + { + m_Progress=progress*100/progressMax; + SendMessage(m_ProgressBar,PBM_SETPOS,m_Progress,0); + if (bVisible) return S_OK; + } + ResetParts(); + RedrawWindow(m_StatusBar,NULL,NULL,RDW_UPDATENOW|RDW_ALLCHILDREN); + return S_OK; +} + +STDMETHODIMP CClassicIEBHO::OnQuit( void ) +{ + if (m_pWebBrowser && m_dwEventCookie!=0xFEFEFEFE) // ATL's event cookie is 0xFEFEFEFE, when the sink is not advised + return DispEventUnadvise(m_pWebBrowser,&DIID_DWebBrowserEvents2); + return S_OK; +} diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEBHO.h b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEBHO.h new file mode 100644 index 0000000..145bd88 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEBHO.h @@ -0,0 +1,92 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#include +#include +#include + +// CClassicIEBHO + +class ATL_NO_VTABLE CClassicIEBHO : + public CComObjectRootEx, + public CComCoClass, + public IObjectWithSiteImpl, + public IDispEventImpl<1,CClassicIEBHO,&DIID_DWebBrowserEvents2,&LIBID_SHDocVw,1,1> +{ +public: + CClassicIEBHO() + { + m_Settings=0; + m_StatusBar=NULL; + m_Tooltip=NULL; + m_ProgressBar=NULL; + m_TextWidth=0; + m_Progress=-1; + } + + static HRESULT WINAPI UpdateRegistry( BOOL bRegister ); + + BEGIN_SINK_MAP( CClassicIEBHO ) + SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_NAVIGATECOMPLETE2, OnNavigateComplete) + SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_PROGRESSCHANGE, OnProgressChange) + SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_ONQUIT, OnQuit) + END_SINK_MAP() + + BEGIN_COM_MAP(CClassicIEBHO) + COM_INTERFACE_ENTRY(IObjectWithSite) + END_COM_MAP() + + + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + HRESULT FinalConstruct() + { + return S_OK; + } + + // IObjectWithSite + STDMETHOD(SetSite)(IUnknown *pUnkSite); + + // DWebBrowserEvents2 + STDMETHOD(OnNavigateComplete)( IDispatch *pDisp, VARIANT *URL ); + STDMETHOD(OnProgressChange)( long progress, long progressMax ); + STDMETHOD(OnQuit)( void ); + +private: + enum + { + PART_TEXT, + PART_PROGRESS, + PART_ZONE, + PART_ZOOM, + + PART_COUNT, + PART_OFFSET=100, + + PROGRESS_WIDTH=110, + MIN_TEXT_WIDTH=100, + }; + + CComPtrm_pBrowser; + CComPtr m_pWebBrowser; + CComPtr m_pZoneManager; + CComPtr m_pSecurityManager; + + DWORD m_Settings; + HWND m_StatusBar; + HWND m_Tooltip; + HWND m_ProgressBar; + CString m_ProtectedMode; + int m_TextWidth; + int m_Progress; + std::map m_IconCache; + + static LRESULT CALLBACK SubclassStatusProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + + void ResetParts( void ); +}; + +OBJECT_ENTRY_AUTO(__uuidof(ClassicIEBHO), CClassicIEBHO) diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEBHO.rgs b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEBHO.rgs new file mode 100644 index 0000000..1407be5 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEBHO.rgs @@ -0,0 +1,108 @@ +HKCR +{ + ClassicIE.ClassicIEBHO.1 = s 'ClassicIEBHO Class' + { + CLSID = s '{EA801577-E6AD-4BD5-8F71-4BE0154331A4}' + } + ClassicIE.ClassicIEBHO = s 'ClassicIEBHO Class' + { + CLSID = s '{EA801577-E6AD-4BD5-8F71-4BE0154331A4}' + CurVer = s 'ClassicIE.ClassicIEBHO.1' + } + NoRemove CLSID + { + ForceRemove {EA801577-E6AD-4BD5-8F71-4BE0154331A4} = s 'ClassicIEBHO Class' + { + ProgID = s 'ClassicIE.ClassicIEBHO.1' + VersionIndependentProgID = s 'ClassicIE.ClassicIEBHO' + ForceRemove 'Programmable' + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Apartment' + } + 'TypeLib' = s '{FDA50A1E-B8CE-49DE-8D17-B034A84AA280}' + } + } +} + +HKLM +{ + NoRemove SOFTWARE + { + NoRemove Microsoft + { + NoRemove Windows + { + NoRemove CurrentVersion + { + NoRemove Explorer + { + NoRemove 'Browser Helper Objects' + { + ForceRemove '{EA801577-E6AD-4BD5-8F71-4BE0154331A4}' + { + val NoExplorer = d '1' + } + } + } + NoRemove Policies + { + NoRemove Ext + { + NoRemove CLSID + { + ForceRemove val {EA801577-E6AD-4BD5-8F71-4BE0154331A4} = s '2' + } + } + } + } + } + } + } +} + +HKLM +{ + NoRemove SOFTWARE + { + NoRemove Microsoft + { + NoRemove 'Internet Explorer' + { + NoRemove 'Low Rights' + { + NoRemove ElevationPolicy + { + ForceRemove '{56753E59-AF1D-4FBA-9E15-31557124ADA2}' + { + val AppPath = s '%MODULEPATH%' + val AppName = s 'ClassicIE_32.exe' + val Policy = d '3' + } + ForceRemove '{C0393554-9B48-458A-B91B-3F684D003B2F}' + { + val AppPath = s '%MODULEPATH%' + val AppName = s 'ClassicIE_64.exe' + val Policy = d '3' + } + ForceRemove '{02E6771D-8375-42B9-9F83-B4730F697900}' + { + val AppPath = s '%MODULEPATH%' + val AppName = s 'ClassicShellUpdate.exe' + val Policy = d '3' + } + } + } + NoRemove Extensions + { + ForceRemove '{56753E59-AF1D-4FBA-9E15-31557124ADA2}' + { + val CLSID = s '{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}' + val MenuText = s '%MENUTEXT%' + val Exec = s '%MODULEPATH%\ClassicIE_32.exe' + } + } + } + } + } +} diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.cpp b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.cpp new file mode 100644 index 0000000..6aa8e06 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.cpp @@ -0,0 +1,84 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "resource.h" +#include "ClassicIEDLL_i.h" +#include "ClassicIEDLL.h" +#include "Settings.h" +#include "dllmain.h" + +// Used to determine whether the DLL can be unloaded by OLE +STDAPI DllCanUnloadNow(void) +{ + return _AtlModule.DllCanUnloadNow(); +} + + +// Returns a class factory to create an object of the requested type +STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) +{ + WaitDllInitThread(); + return _AtlModule.DllGetClassObject(rclsid, riid, ppv); +} + + +// DllRegisterServer - Adds entries to the system registry +STDAPI DllRegisterServer(void) +{ + WaitDllInitThread(); + // registers object, typelib and all interfaces in typelib + HRESULT res=_AtlModule.DllRegisterServer(); + if (SUCCEEDED(res)) + { + // mark the extension as compatible with the enhanced protected mode of IE10 + CComPtr catRegister; + catRegister.CoCreateInstance(CLSID_StdComponentCategoriesMgr); + if (catRegister) + { + CATID CATID_AppContainerCompatible={0x59fb2056,0xd625,0x48d0,{0xa9,0x44,0x1a,0x85,0xb5,0xab,0x26,0x40}}; + catRegister->RegisterClassImplCategories(CLSID_ClassicIEBHO,1,&CATID_AppContainerCompatible); + } + } + return res; +} + + +// DllUnregisterServer - Removes entries from the system registry +STDAPI DllUnregisterServer(void) +{ + WaitDllInitThread(); + return _AtlModule.DllUnregisterServer(); +} + +// DllInstall - Adds/Removes entries to the system registry per user +// per machine. +STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine) +{ + WaitDllInitThread(); + HRESULT hr = E_FAIL; + static const wchar_t szUserSwitch[] = L"user"; + + if (pszCmdLine != NULL) + { + if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0) + { + AtlSetPerUserRegistration(true); + } + } + + if (bInstall) + { + hr = DllRegisterServer(); + if (FAILED(hr)) + { + DllUnregisterServer(); + } + } + else + { + hr = DllUnregisterServer(); + } + + return hr; +} diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.h b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.h new file mode 100644 index 0000000..7f974cd --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.h @@ -0,0 +1,33 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#ifdef CLASSICIEDLL_EXPORTS +#define CSIEAPI __declspec(dllexport) +#else +#define CSIEAPI __declspec(dllimport) +#endif + +void InitClassicIE( HMODULE hModule ); +CSIEAPI void ShowIESettings( void ); +CSIEAPI DWORD GetIESettings( void ); +CSIEAPI void CheckForNewVersionIE( void ); +CSIEAPI void WaitDllInitThread( void ); +CSIEAPI void DllLogToFile( const wchar_t *location, const wchar_t *message, ... ); + +#ifndef _WIN64 +CSIEAPI bool DllSaveAdmx( const char *admxFile, const char *admlFile, const char *docFile, const wchar_t *language ); +#endif +CSIEAPI bool DllImportSettingsXml( const wchar_t *fname ); +CSIEAPI bool DllExportSettingsXml( const wchar_t *fname ); + +enum +{ + IE_SETTING_CAPTION=1, + IE_SETTING_PROGRESS=2, + IE_SETTING_ZONE=4, + IE_SETTING_PROTECTED=8, +}; + +#define CIE_LOG L"Software\\IvoSoft\\ClassicIE\\Settings|LogLevel|%LOCALAPPDATA%\\ClassicShell\\ClassicIELog.txt" diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.idl b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.idl new file mode 100644 index 0000000..1620ff1 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.idl @@ -0,0 +1,36 @@ +// ClassicIEDLL.idl : IDL source for ClassicIEDLL +// + +// This file will be processed by the MIDL tool to +// produce the type library (ClassicIEDLL.tlb) and marshalling code. + +import "oaidl.idl"; +import "ocidl.idl"; + +[ + object, + uuid(C698A81E-5D02-42B1-9801-5381CA8BBC2F), + dual, + nonextensible, + helpstring("IClassicIEBHO Interface"), + pointer_default(unique) +] +interface IClassicIEBHO : IDispatch{ +}; +[ + uuid(FDA50A1E-B8CE-49DE-8D17-B034A84AA280), + version(1.0), + helpstring("ClassicIE 1.0 Type Library") +] +library ClassicIEDLLLib +{ + importlib("stdole2.tlb"); + [ + uuid(EA801577-E6AD-4BD5-8F71-4BE0154331A4), + helpstring("ClassicIEBHO Class") + ] + coclass ClassicIEBHO + { + [default] interface IClassicIEBHO; + }; +}; diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.rc b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.rc new file mode 100644 index 0000000..f40c3ba --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.rc @@ -0,0 +1,183 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" +#include "..\..\ClassicShellLib\resource.h" +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "#include ""..\\..\\ClassicShellLib\\resource.h""\r\0" +END + +3 TEXTINCLUDE +BEGIN + "#include ""..\\..\\ClassicShellLib\\resource.h""\r\n" + "#include ""..\\..\\ClassicShellLib\\ClassicShellLib.rc""\r\r\n" + "1 TYPELIB ""ClassicIEDLL.tlb""\r\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 4,3,1,0 + PRODUCTVERSION 4,3,1,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "IvoSoft" + VALUE "FileDescription", "Customizations for the title bar and status bar of IE" + VALUE "FileVersion", "4, 3, 1, 0" + VALUE "InternalName", "ClassicIEDLL.dll" + VALUE "LegalCopyright", "Copyright (C) 2009-2016, Ivo Beltchev" + VALUE "OriginalFilename", "ClassicIEDLL.dll" + VALUE "ProductName", "Classic Shell" + VALUE "ProductVersion", "4, 3, 1, 0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// REGISTRY +// + +IDR_CLASSICIEDLL REGISTRY "ClassicIEDLL.rgs" +IDR_CLASSICIEBHO REGISTRY "ClassicIEBHO.rgs" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APPICON ICON "..\\..\\ClassicShellSetup\\ClassicShell.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_GLOW BITMAP "glow.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_APP_TITLE "Classic IE" + IDS_SETTINGS_TITLE "Classic IE Settings" + IDS_SETTINGS_TITLE_VER "Classic IE Settings %d.%d.%d" + IDS_NEW_SETTINGS "The new settings will take effect after you restart Internet Explorer." + IDS_TITLE_SETTINGS "Title Bar" + IDS_SHOW_CAPTION "Show caption in the title bar" + IDS_SHOW_CAPTION_TIP "When this is checked, Internet Explorer will show the page title in the title bar" + IDS_CENTER_CAPTION "Center caption" +END + +STRINGTABLE +BEGIN + IDS_CENTER_CAPTION_TIP "When this is checked, the caption will be centered in the title bar" + IDS_LANGUAGE_SETTINGS "Language" + IDS_CAPTION_FONT "Caption font" + IDS_CAPTION_FONT_TIP "Select the font and text size to use for the caption" + IDS_TEXT_COLOR "Text color" + IDS_TEXT_COLOR_TIP "Select the color for the caption text" + IDS_MAXTEXT_COLOR "Text color (maximized)" + IDS_MAXTEXT_COLOR_TIP "Select the color for the caption text when the window is maximized" + IDS_INTEXT_COLOR "Text color (inactive)" + IDS_INTEXT_COLOR_TIP "Select the color for the caption text when the window is inactive" + IDS_MAXINTEXT_COLOR "Text color (maximized, inactive)" + IDS_MAXINTEXT_COLOR_TIP "Select the color for the caption text when the window is maximized and inactive" + IDS_GLOW "Text glow" + IDS_GLOW_TIP "When this is checked, the text will have a glow around it" + IDS_GLOW_COLOR "Glow color" + IDS_GLOW_COLOR_TIP "Select the color for the caption glow" +END + +STRINGTABLE +BEGIN + IDS_MAXGLOW "Text glow (maximized)" + IDS_MAXGLOW_TIP "When this is checked, the text in the maximized window will have a glow around it" + IDS_MAXGLOW_COLOR "Glow color (maximized)" + IDS_MAXGLOW_COLOR_TIP "Select the color for the caption glow when the window is maximized" + IDS_STATUS_SETTINGS "Status Bar" + IDS_SHOW_PROGRESS "Show progress" + IDS_SHOW_PROGRESS_TIP "When this is checked, the status bar will show the progress of the current page" + IDS_SHOW_ZONE "Show zone" + IDS_SHOW_ZONE_TIP "When this is checked, the status bar will show the current security zone" + IDS_SHOW_PROTECTED "Show protected mode" + IDS_SHOW_PROTECTED_TIP "When this is checked, the status bar will show if the browser is running in protected mode" + IDS_SHOW_ICON "Show icon in the title bar" + IDS_SHOW_ICON_TIP "When this is checked, Internet Explorer will show the page icon in the title bar" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "..\..\ClassicShellLib\resource.h" +#include "..\..\ClassicShellLib\ClassicShellLib.rc" +1 TYPELIB "ClassicIEDLL.tlb" +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.rgs b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.rgs new file mode 100644 index 0000000..839c785 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.rgs @@ -0,0 +1,11 @@ +HKCR +{ + NoRemove AppID + { + '%APPID%' = s 'ClassicIE' + 'ClassicIE.DLL' + { + val AppID = s '%APPID%' + } + } +} diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.vcproj b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.vcproj new file mode 100644 index 0000000..388d035 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL.vcproj @@ -0,0 +1,845 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL_32.def b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL_32.def new file mode 100644 index 0000000..8bdb715 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL_32.def @@ -0,0 +1,11 @@ +; ClassicIEDLL_32.def : Declares the module parameters. + +LIBRARY "ClassicIEDLL_32.DLL" + +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE + DllInstall PRIVATE + DllSaveAdmx \ No newline at end of file diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL_64.def b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL_64.def new file mode 100644 index 0000000..85f86b5 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/ClassicIEDLL_64.def @@ -0,0 +1,10 @@ +; ClassicIEDLL.def : Declares the module parameters. + +LIBRARY "ClassicIEDLL_64.DLL" + +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE + DllInstall PRIVATE diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/DrawCaption.cpp b/ClassicShellSrc/ClassicIE/ClassicIEDLL/DrawCaption.cpp new file mode 100644 index 0000000..565b858 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/DrawCaption.cpp @@ -0,0 +1,345 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "ClassicIEDLL.h" +#include "Settings.h" +#include "ResourceHelper.h" +#include "SettingsUIHelper.h" +#include +#include + +static _declspec(thread) SIZE g_SysButtonSize; // the size of the system buttons (close, minimize) for this thread's window +static WNDPROC g_OldClassCaptionProc; +static HBITMAP g_GlowBmp; +static HBITMAP g_GlowBmpMax; +static LONG g_bInjected; // the process is injected +static int g_DPI; +static UINT g_Message; // private message to detect if the caption is subclassed +static ATOM g_SubclassAtom; + +struct CustomCaption +{ + int leftPadding; + int topPadding; + int iconPadding; +}; + +static CustomCaption g_CustomCaption[3]={ + {2,3,10}, // Aero + {4,2,10}, // Aero maximized + {4,2,10}, // Basic +}; + +void GetSysButtonSize( HWND hWnd ) +{ + TITLEBARINFOEX titleInfo={sizeof(titleInfo)}; + SendMessage(hWnd,WM_GETTITLEBARINFOEX,0,(LPARAM)&titleInfo); + int buttonLeft=titleInfo.rgrect[2].left; + if (buttonLeft>titleInfo.rgrect[5].left) buttonLeft=titleInfo.rgrect[5].left; + int buttonRight=titleInfo.rgrect[2].right; + if (buttonRightrc.bottom-iconSize) y=rc.bottom-iconSize; + if (bIcon) + { + DrawIconEx(hdcPaint,rc.left,y,hIcon,iconSize,iconSize,0,NULL,DI_NORMAL|DI_NOMIRROR); + rc.left+=iconSize; + } + rc.left+=g_CustomCaption[0].iconPadding; + rc.bottom++; + } + else + { + // when the window is maximized, the caption bar is partially off-screen, so align the icon to the bottom + rc.left+=g_CustomCaption[1].leftPadding; + if (bIcon) + { + DrawIconEx(hdcPaint,rc.left,rc.bottom-iconSize-g_CustomCaption[1].topPadding,hIcon,iconSize,iconSize,0,NULL,DI_NORMAL|DI_NOMIRROR); + rc.left+=iconSize; + } + rc.left+=g_CustomCaption[1].iconPadding; + if (GetWinVersion()>=WIN_VER_WIN10) + rc.bottom++; + } + if (GetWinVersion()rc.right-rc.left) + textWidth=rc.right-rc.left; + opts.dwFlags&=~DTT_CALCRECT; + + if (bGlow) + { + HDC hSrc=CreateCompatibleDC(hdcPaint); + HGDIOBJ bmp0=SelectObject(hSrc,bMaximized?g_GlowBmpMax:g_GlowBmp); + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + AlphaBlend(hdcPaint,rc.left-11,rc.top,11,rc.bottom-rc.top,hSrc,0,0,11,24,func); + AlphaBlend(hdcPaint,rc.left,rc.top,textWidth,rc.bottom-rc.top,hSrc,11,0,2,24,func); + AlphaBlend(hdcPaint,rc.left+textWidth,rc.top,11,rc.bottom-rc.top,hSrc,13,0,11,24,func); + SelectObject(hSrc,bmp0); + DeleteDC(hSrc); + } + DrawThemeTextEx(theme,hdcPaint,0,0,caption,-1,DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS,&rc,&opts); + SelectObject(hdcPaint,font0); + + EndBufferedPaint(hBufferedPaint,TRUE); + } + EndPaint(hWnd,&ps); + } + else + { + // Basic Theme + + // first draw the caption bar + DefCaptionProc(hWnd,uMsg,wParam,lParam); + + // then draw the caption directly in the window DC + HDC hdc=GetWindowDC(hWnd); + + // exclude the caption buttons + rc.right-=g_SysButtonSize.cx+5; + rc.top=rc.bottom-g_SysButtonSize.cy; + + rc.left+=g_CustomCaption[2].leftPadding; + if (bIcon) + { + DrawIconEx(hdc,rc.left,rc.bottom-iconSize-g_CustomCaption[2].topPadding,hIcon,iconSize,iconSize,0,NULL,DI_NORMAL|DI_NOMIRROR); + rc.left+=iconSize; + } + rc.left+=g_CustomCaption[2].iconPadding; + + HFONT font0=(HFONT)SelectObject(hdc,font); + RECT rcText={0,0,0,0}; + opts.dwFlags|=DTT_CALCRECT; + DrawThemeTextEx(theme,hdc,0,0,caption,-1,DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE|DT_CALCRECT,&rcText,&opts); + int textWidth=rcText.right-rcText.left; + if (bCenter && textWidthrc.right-rc.left) + textWidth=rc.right-rc.left; + opts.dwFlags&=~DTT_CALCRECT; + + if (bGlow) + { + HDC hSrc=CreateCompatibleDC(hdc); + HGDIOBJ bmp0=SelectObject(hSrc,bMaximized?g_GlowBmpMax:g_GlowBmp); + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + AlphaBlend(hdc,rc.left-11,rc.top,11,rc.bottom-rc.top,hSrc,0,0,11,24,func); + AlphaBlend(hdc,rc.left,rc.top,textWidth,rc.bottom-rc.top,hSrc,11,0,2,24,func); + AlphaBlend(hdc,rc.left+textWidth,rc.top,11,rc.bottom-rc.top,hSrc,13,0,11,24,func); + SelectObject(hSrc,bmp0); + DeleteDC(hSrc); + } + DrawThemeTextEx(theme,hdc,0,0,caption,-1,DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS,&rc,&opts); + SelectObject(hdc,font0); + + ReleaseDC(hWnd,hdc); + } + + DeleteObject(font); + CloseThemeData(theme); + return 0; + } + return DefCaptionProc(hWnd,uMsg,wParam,lParam); +} + +// Replacement proc for the "Client Caption" class that hooks the main frame and the caption windows +static LRESULT CALLBACK ClassCaptionProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if (uMsg==WM_CREATE) + { + WNDPROC proc=(WNDPROC)SetWindowLongPtr(hWnd,GWLP_WNDPROC,(LONG_PTR)SubclassCaptionProc); + SetProp(hWnd,MAKEINTATOM(g_SubclassAtom),(HANDLE)proc); + HWND frame=GetParent(hWnd); + proc=(WNDPROC)SetWindowLongPtr(frame,GWLP_WNDPROC,(LONG_PTR)SubclassFrameProc); + SetProp(frame,MAKEINTATOM(g_SubclassAtom),(HANDLE)proc); + PostMessage(frame,g_Message,0,0); + } + return CallWindowProc(g_OldClassCaptionProc,hWnd,uMsg,wParam,lParam); +} + +static BOOL CALLBACK EnumTopWindows( HWND hwnd, LPARAM lParam ) +{ + DWORD processId; + DWORD threadId=GetWindowThreadProcessId(hwnd,&processId); + if (processId==GetCurrentProcessId()) + { + HWND caption=FindWindowEx(hwnd,NULL,L"Client Caption",NULL); + if (caption) + { + LogToFile(CIE_LOG,L"InitClassicIE: caption=%X",(DWORD)caption); + if (!g_OldClassCaptionProc) + g_OldClassCaptionProc=(WNDPROC)SetClassLongPtr(caption,GCLP_WNDPROC,(LONG_PTR)ClassCaptionProc); + WNDPROC proc=(WNDPROC)SetWindowLongPtr(caption,GWLP_WNDPROC,(LONG_PTR)SubclassCaptionProc); + SetProp(caption,MAKEINTATOM(g_SubclassAtom),(HANDLE)proc); + proc=(WNDPROC)SetWindowLongPtr(hwnd,GWLP_WNDPROC,(LONG_PTR)SubclassFrameProc); + SetProp(hwnd,MAKEINTATOM(g_SubclassAtom),(HANDLE)proc); + PostMessage(hwnd,g_Message,0,0); + } + } + return TRUE; +} + +void InitClassicIE( HMODULE hModule ) +{ + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,GetSettingsRegPath())==ERROR_SUCCESS) + { + DWORD val; + if (regKey.QueryDWORDValue(L"CustomAero",val)==ERROR_SUCCESS) + { + g_CustomCaption[0].leftPadding=(val&255); + g_CustomCaption[0].topPadding=((val>>8)&255); + g_CustomCaption[0].iconPadding=((val>>16)&255); + } + if (regKey.QueryDWORDValue(L"CustomAeroMax",val)==ERROR_SUCCESS) + { + g_CustomCaption[1].leftPadding=(val&255); + g_CustomCaption[1].topPadding=((val>>8)&255); + g_CustomCaption[1].iconPadding=((val>>16)&255); + } + if (regKey.QueryDWORDValue(L"CustomBasic",val)==ERROR_SUCCESS) + { + g_CustomCaption[2].leftPadding=(val&255); + g_CustomCaption[2].topPadding=((val>>8)&255); + g_CustomCaption[2].iconPadding=((val>>16)&255); + } + } + + g_Message=RegisterWindowMessage(L"ClassicIE.Injected"); + g_SubclassAtom=GlobalAddAtom(L"ClassicIE.Subclass"); + ChangeWindowMessageFilter(g_Message,MSGFLT_ADD); + g_GlowBmp=(HBITMAP)LoadImage(g_Instance,MAKEINTRESOURCE(IDB_GLOW),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION); + PremultiplyBitmap(g_GlowBmp,GetSettingInt(L"GlowColor")); + g_GlowBmpMax=(HBITMAP)LoadImage(g_Instance,MAKEINTRESOURCE(IDB_GLOW),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION); + PremultiplyBitmap(g_GlowBmpMax,GetSettingInt(L"MaxGlowColor")); + + EnumWindows(EnumTopWindows,0); +} diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/SettingsUI.cpp b/ClassicShellSrc/ClassicIE/ClassicIEDLL/SettingsUI.cpp new file mode 100644 index 0000000..5e4c53c --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/SettingsUI.cpp @@ -0,0 +1,171 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "Settings.h" +#include "SettingsUIHelper.h" +#include "LanguageSettingsHelper.h" +#include "ResourceHelper.h" +#include "Translations.h" +#include "resource.h" +#include "dllmain.h" +#include "ClassicIEDLL.h" +#include +#include + +/////////////////////////////////////////////////////////////////////////////// + +static CSetting g_Settings[]={ +{L"Basic",CSetting::TYPE_GROUP,IDS_BASIC_SETTINGS}, + {L"EnableSettings",CSetting::TYPE_BOOL,0,0,1,CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + +{L"TitleBar",CSetting::TYPE_GROUP,IDS_TITLE_SETTINGS}, + {L"ShowCaption",CSetting::TYPE_BOOL,IDS_SHOW_CAPTION,IDS_SHOW_CAPTION_TIP,1,CSetting::FLAG_WARM|CSetting::FLAG_BASIC}, + {L"ShowIcon",CSetting::TYPE_BOOL,IDS_SHOW_ICON,IDS_SHOW_ICON_TIP,1,CSetting::FLAG_WARM|CSetting::FLAG_BASIC,L"ShowCaption"}, + {L"CenterCaption",CSetting::TYPE_BOOL,IDS_CENTER_CAPTION,IDS_CENTER_CAPTION_TIP,0,CSetting::FLAG_WARM|CSetting::FLAG_BASIC,L"ShowCaption"}, + {L"CaptionFont",CSetting::TYPE_FONT,IDS_CAPTION_FONT,IDS_CAPTION_FONT_TIP,L"Segoe UI, normal, 9",CSetting::FLAG_WARM,L"ShowCaption"}, + {L"TextColor",CSetting::TYPE_COLOR,IDS_TEXT_COLOR,IDS_TEXT_COLOR_TIP,0,CSetting::FLAG_WARM,L"ShowCaption"}, + {L"MaxColor",CSetting::TYPE_COLOR,IDS_MAXTEXT_COLOR,IDS_MAXTEXT_COLOR_TIP,0,CSetting::FLAG_WARM|(1<<24),L"ShowCaption"}, + {L"InactiveColor",CSetting::TYPE_COLOR,IDS_INTEXT_COLOR,IDS_INTEXT_COLOR_TIP,0,CSetting::FLAG_WARM|(2<<24),L"ShowCaption"}, + {L"InactiveMaxColor",CSetting::TYPE_COLOR,IDS_MAXINTEXT_COLOR,IDS_MAXINTEXT_COLOR_TIP,0,CSetting::FLAG_WARM|(3<<24),L"ShowCaption"}, + {L"Glow",CSetting::TYPE_BOOL,IDS_GLOW,IDS_GLOW_TIP,0,CSetting::FLAG_WARM,L"ShowCaption"}, + {L"GlowColor",CSetting::TYPE_COLOR,IDS_GLOW_COLOR,IDS_GLOW_COLOR_TIP,0xFFFFFF,CSetting::FLAG_WARM|(4<<24),L"#Glow",L"Glow"}, + {L"MaxGlow",CSetting::TYPE_BOOL,IDS_MAXGLOW,IDS_MAXGLOW_TIP,0,CSetting::FLAG_WARM,L"ShowCaption"}, + {L"MaxGlowColor",CSetting::TYPE_COLOR,IDS_MAXGLOW_COLOR,IDS_MAXGLOW_COLOR_TIP,0xFFFFFF,CSetting::FLAG_WARM|(5<<24),L"#MaxGlow",L"MaxGlow"}, + +{L"StatusBar",CSetting::TYPE_GROUP,IDS_STATUS_SETTINGS}, + {L"ShowProgress",CSetting::TYPE_BOOL,IDS_SHOW_PROGRESS,IDS_SHOW_PROGRESS_TIP,1,CSetting::FLAG_WARM|CSetting::FLAG_BASIC}, + {L"ShowZone",CSetting::TYPE_BOOL,IDS_SHOW_ZONE,IDS_SHOW_ZONE_TIP,1,CSetting::FLAG_WARM|CSetting::FLAG_BASIC}, + {L"ShowProtected",CSetting::TYPE_BOOL,IDS_SHOW_PROTECTED,IDS_SHOW_PROTECTED_TIP,1,CSetting::FLAG_WARM,L"ShowZone",L"ShowZone"}, + +{L"Language",CSetting::TYPE_GROUP,IDS_LANGUAGE_SETTINGS,0,0,0,NULL,NULL,GetLanguageSettings(COMPONENT_IE)}, + {L"Language",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_SHARED}, + +{NULL} +}; + +void UpgradeSettings( bool bShared ) +{ +} + +void UpdateSettings( void ) +{ + bool bWin8=(GetWinVersion()>=WIN_VER_WIN8); + + BOOL bComposition=0; + if (FAILED(DwmIsCompositionEnabled(&bComposition))) + bComposition=FALSE; + + if (bComposition && bWin8) + { + // check for High Contrast theme on Win8 + HIGHCONTRAST contrast={sizeof(contrast)}; + if (SystemParametersInfo(SPI_GETHIGHCONTRAST,sizeof(contrast),&contrast,0) && (contrast.dwFlags&HCF_HIGHCONTRASTON)) + bComposition=FALSE; + else + { + // check for Basic theme + DWORD color; + BOOL opaque; + if (SUCCEEDED(DwmGetColorizationColor(&color,&opaque)) && opaque) + bComposition=FALSE; + } + } + + UpdateSetting(L"Glow",CComVariant(bComposition?1:0),false); + UpdateSetting(L"MaxGlow",CComVariant(bComposition?1:0),false); + UpdateSetting(L"CenterCaption",CComVariant((bWin8 && GetWinVersion()=FW_BOLD) + type=font.lfItalic?L"bold_italic":L"bold"; + Sprintf(text,_countof(text),L"%s, %s, %d",font.lfFaceName,type,(-font.lfHeight*72+dpi/2)/dpi); + UpdateSetting(L"CaptionFont",CComVariant(text),false); + + int color=GetThemeSysColor(theme,COLOR_CAPTIONTEXT); + UpdateSetting(L"TextColor",CComVariant(color),false); + UpdateSetting(L"MaxColor",CComVariant(color),false); + if (bWin8) + color=GetThemeSysColor(theme,COLOR_INACTIVECAPTIONTEXT); + UpdateSetting(L"InactiveColor",CComVariant(color),false); + UpdateSetting(L"InactiveMaxColor",CComVariant(color),false); + + CloseThemeData(theme); + } + else + { + int color=GetSysColor(COLOR_CAPTIONTEXT); + UpdateSetting(L"TextColor",CComVariant(color),false); + UpdateSetting(L"MaxColor",CComVariant(color),false); + color=GetSysColor(COLOR_INACTIVECAPTIONTEXT); + UpdateSetting(L"InactiveColor",CComVariant(color),false); + UpdateSetting(L"InactiveMaxColor",CComVariant(color),false); + } + DestroyWindow(hwnd); + + CRegKey regKey; + wchar_t language[100]=L""; + if (regKey.Open(HKEY_LOCAL_MACHINE,L"Software\\IvoSoft\\ClassicShell",KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + ULONG size=_countof(language); + if (regKey.QueryStringValue(L"DefaultLanguage",language,&size)!=ERROR_SUCCESS) + language[0]=0; + } + UpdateSetting(L"Language",language,false); +} + +void InitSettings( void ) +{ + InitSettings(g_Settings,COMPONENT_IE,NULL); +} + +void ClosingSettings( HWND hWnd, int flags, int command ) +{ + if (command==IDOK) + { + if (flags&CSetting::FLAG_WARM) + { + if (FindWindow(L"IEFrame",NULL)) + MessageBox(hWnd,LoadStringEx(IDS_NEW_SETTINGS),LoadStringEx(IDS_APP_TITLE),MB_OK|MB_ICONINFORMATION); + } + } +} + +void SettingChangedCallback( const CSetting *pSetting ) +{ +} + +CSIEAPI void ShowIESettings( void ) +{ + if (!GetSettingBool(L"EnableSettings")) + return; + wchar_t title[100]; + DWORD ver=GetVersionEx(g_Instance); + if (ver) + Sprintf(title,_countof(title),LoadStringEx(IDS_SETTINGS_TITLE_VER),ver>>24,(ver>>16)&0xFF,ver&0xFFFF); + else + Sprintf(title,_countof(title),LoadStringEx(IDS_SETTINGS_TITLE)); + EditSettings(title,true,0); +} + +CSIEAPI DWORD GetIESettings( void ) +{ + DWORD res=0; + if (GetSettingBool(L"ShowCaption")) res|=IE_SETTING_CAPTION; + if (GetSettingBool(L"ShowProgress")) res|=IE_SETTING_PROGRESS; + if (GetSettingBool(L"ShowZone")) res|=IE_SETTING_ZONE; + if (GetSettingBool(L"ShowProtected")) res|=IE_SETTING_PROTECTED; + return res; +} diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/SettingsUI.h b/ClassicShellSrc/ClassicIE/ClassicIEDLL/SettingsUI.h new file mode 100644 index 0000000..3787470 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/SettingsUI.h @@ -0,0 +1,6 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +void InitSettings( void ); diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/dllmain.cpp b/ClassicShellSrc/ClassicIE/ClassicIEDLL/dllmain.cpp new file mode 100644 index 0000000..3e6aa27 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/dllmain.cpp @@ -0,0 +1,160 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "resource.h" +#include "..\..\ClassicShellLib\resource.h" +#include "Settings.h" +#include "SettingsUI.h" +#include "SettingsUIHelper.h" +#include "DownloadHelper.h" +#include "Translations.h" +#include "ResourceHelper.h" +#include "dllmain.h" +#include "ClassicIEDLL.h" + +#pragma comment(linker, \ + "\"/manifestdependency:type='Win32' "\ + "name='Microsoft.Windows.Common-Controls' "\ + "version='6.0.0.0' "\ + "processorArchitecture='*' "\ + "publicKeyToken='6595b64144ccf1df' "\ + "language='*'\"") + +CClassicIEDLLModule _AtlModule; + +static int g_LoadDialogs[]= +{ + IDD_SETTINGS,0x04000000, + IDD_SETTINGSTREE,0x04000000, + IDD_LANGUAGE,0x04000000, + IDD_PROGRESS,0x04000004, + 0 +}; + +const wchar_t *GetDocRelativePath( void ) +{ + return DOC_PATH; +} + +static void NewVersionCallback( VersionData &data ) +{ + wchar_t path[_MAX_PATH]; + GetModuleFileName(g_Instance,path,_countof(path)); + PathRemoveFileSpec(path); + PathAppend(path,L"ClassicShellUpdate.exe"); + wchar_t cmdLine[1024]; + Sprintf(cmdLine,_countof(cmdLine),L"\"%s\" -popup",path); + STARTUPINFO startupInfo={sizeof(startupInfo)}; + PROCESS_INFORMATION processInfo; + memset(&processInfo,0,sizeof(processInfo)); + if (CreateProcess(path,cmdLine,NULL,NULL,TRUE,0,NULL,NULL,&startupInfo,&processInfo)) + { + CloseHandle(processInfo.hThread); + CloseHandle(processInfo.hProcess); + } +} + +CSIEAPI void CheckForNewVersionIE( void ) +{ + CheckForNewVersion(NULL,COMPONENT_IE,CHECK_AUTO_WAIT,NewVersionCallback); +} + +static HANDLE g_DllInitThread; + +static DWORD CALLBACK DllInitThread( void* ) +{ + InitSettings(); + CString language=GetSettingString(L"Language"); + ParseTranslations(NULL,language); + + HINSTANCE resInstance=LoadTranslationDll(language); + + LoadTranslationResources(resInstance,g_LoadDialogs); + + if (resInstance) + FreeLibrary(resInstance); + InitClassicIE(g_Instance); + return 0; +} + +CSIEAPI void WaitDllInitThread( void ) +{ + ATLASSERT(g_DllInitThread); + WaitForSingleObject(g_DllInitThread,INFINITE); +} + +CSIEAPI void DllLogToFile( const wchar_t *location, const wchar_t *message, ... ) +{ + va_list args; + va_start(args,message); + VLogToFile(location,message,args); + va_end(args); +} + +#ifndef _WIN64 +CSIEAPI bool DllSaveAdmx( const char *admxFile, const char *admlFile, const char *docFile, const wchar_t *language ) +{ + WaitDllInitThread(); + HMODULE dll=NULL; + if (language[0]) + { + wchar_t path[_MAX_PATH]; + GetCurrentDirectory(_countof(path),path); + PathAppend(path,language); + PathAddExtension(path,L".dll"); + dll=LoadLibraryEx(path,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + } + LoadTranslationResources(dll,NULL); + return SaveAdmx(COMPONENT_IE,admxFile,admlFile,docFile); +} +#endif + +CSIEAPI bool DllImportSettingsXml( const wchar_t *fname ) +{ + return ImportSettingsXml(fname); +} + +CSIEAPI bool DllExportSettingsXml( const wchar_t *fname ) +{ + return ExportSettingsXml(fname); +} + +// DLL Entry Point +extern "C" BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved ) +{ + if (dwReason==DLL_PROCESS_ATTACH) + { + wchar_t path[_MAX_PATH]; + GetModuleFileName(NULL,path,_countof(path)); + const wchar_t *exe=PathFindFileName(path); + if (_wcsicmp(exe,L"explorer.exe")==0) return FALSE; + if (_wcsicmp(exe,L"iexplore.exe")==0) + { + DWORD version=GetVersionEx(GetModuleHandle(NULL)); + if (version<0x09000000) return FALSE; + + CRegKey regSettings, regSettingsUser, regPolicy, regPolicyUser; + bool bUpgrade=OpenSettingsKeys(COMPONENT_EXPLORER,regSettings,regSettingsUser,regPolicy,regPolicyUser); + + CSetting settings[]={ + {L"ShowCaption",CSetting::TYPE_BOOL,0,0,1}, + {L"ShowProgress",CSetting::TYPE_BOOL,0,0,1}, + {L"ShowZone",CSetting::TYPE_BOOL,0,0,1}, + {NULL} + }; + + settings[0].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser); + settings[1].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser); + settings[2].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser); + + if (!GetSettingBool(settings[0]) && !GetSettingBool(settings[1]) && !GetSettingBool(settings[2])) return FALSE; + } + + g_Instance=hInstance; + + g_DllInitThread=CreateThread(NULL,0,DllInitThread,NULL,0,NULL); + } + + return _AtlModule.DllMain(dwReason, lpReserved); +} diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/dllmain.h b/ClassicShellSrc/ClassicIE/ClassicIEDLL/dllmain.h new file mode 100644 index 0000000..1224c86 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/dllmain.h @@ -0,0 +1,15 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#include "ClassicIEDLL_i.h" + +class CClassicIEDLLModule : public CAtlDllModuleT< CClassicIEDLLModule > +{ +public : + DECLARE_LIBID(LIBID_ClassicIEDLLLib) + DECLARE_REGISTRY_APPID_RESOURCEID(IDR_CLASSICIEDLL, "{DF3255F4-FF55-44FA-A728-E77B83E9E403}") +}; + +extern class CClassicIEDLLModule _AtlModule; diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/glow.bmp b/ClassicShellSrc/ClassicIE/ClassicIEDLL/glow.bmp new file mode 100644 index 0000000..c690d8a Binary files /dev/null and b/ClassicShellSrc/ClassicIE/ClassicIEDLL/glow.bmp differ diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/resource.h b/ClassicShellSrc/ClassicIE/ClassicIEDLL/resource.h new file mode 100644 index 0000000..e143bd2 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/resource.h @@ -0,0 +1,57 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ClassicIEDLL.rc +// +#define IDI_APPICON 1 +#define IDR_CLASSICIEDLL 101 +#define IDR_CLASSICIEBHO 102 +#define IDB_BITMAP1 201 +#define IDB_GLOW 201 +#define IDS_APP_TITLE 5000 +#define IDS_SETTINGS_TITLE 5001 +#define IDS_SETTINGS_TITLE_VER 5002 +#define IDS_NEW_SETTINGS 5003 +#define IDS_TITLE_SETTINGS 5004 +#define IDS_SHOW_CAPTION 5005 +#define IDS_SHOW_CAPTION_TIP 5006 +#define IDS_CENTER_CAPTION 5007 +#define IDS_CENTER_CAPTION_TIP 5008 +#define IDS_LANGUAGE_SETTINGS 5009 +#define IDS_CAPTION_FONT 5010 +#define IDS_CAPTION_FONT_TIP 5011 +#define IDS_TEXT_COLOR 5012 +#define IDS_TEXT_COLOR_TIP 5013 +#define IDS_MAXTEXT_COLOR 5014 +#define IDS_MAXTEXT_COLOR_TIP 5015 +#define IDS_INTEXT_COLOR 5016 +#define IDS_INTEXT_COLOR_TIP 5017 +#define IDS_MAXINTEXT_COLOR 5018 +#define IDS_MAXINTEXT_COLOR_TIP 5019 +#define IDS_GLOW 5020 +#define IDS_GLOW_TIP 5021 +#define IDS_GLOW_COLOR 5022 +#define IDS_GLOW_COLOR_TIP 5023 +#define IDS_MAXGLOW 5024 +#define IDS_MAXGLOW_TIP 5025 +#define IDS_MAXGLOW_COLOR 5026 +#define IDS_MAXGLOW_COLOR_TIP 5027 +#define IDS_STATUS_SETTINGS 5028 +#define IDS_SHOW_PROGRESS 5029 +#define IDS_SHOW_PROGRESS_TIP 5030 +#define IDS_SHOW_ZONE 5031 +#define IDS_SHOW_ZONE_TIP 5032 +#define IDS_SHOW_PROTECTED 5033 +#define IDS_SHOW_PROTECTED_TIP 5034 +#define IDS_SHOW_ICON 5035 +#define IDS_SHOW_ICON_TIP 5036 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 202 +#define _APS_NEXT_COMMAND_VALUE 32768 +#define _APS_NEXT_CONTROL_VALUE 201 +#define _APS_NEXT_SYMED_VALUE 103 +#endif +#endif diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/stdafx.cpp b/ClassicShellSrc/ClassicIE/ClassicIEDLL/stdafx.cpp new file mode 100644 index 0000000..7e034bd --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/stdafx.cpp @@ -0,0 +1,5 @@ +// stdafx.cpp : source file that includes just the standard includes +// ClassicIEDLL.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/stdafx.h b/ClassicShellSrc/ClassicIE/ClassicIEDLL/stdafx.h new file mode 100644 index 0000000..57d4d82 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/stdafx.h @@ -0,0 +1,35 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently + +#pragma once + +#ifndef STRICT +#define STRICT +#endif + +#include "targetver.h" + +#define ISOLATION_AWARE_ENABLED 1 +#define _ATL_APARTMENT_THREADED +#define _ATL_NO_AUTOMATIC_NAMESPACE + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +#include "resource.h" +#include +#include +#include +#include + +using namespace ATL; + +#ifdef BUILD_SETUP +#define INI_PATH L"" +#define DOC_PATH L"" +#else +#define INI_PATH L"..\\" +#define DOC_PATH L"..\\..\\Docs\\Help\\" +#endif + +#include "StringUtils.h" diff --git a/ClassicShellSrc/ClassicIE/ClassicIEDLL/targetver.h b/ClassicShellSrc/ClassicIE/ClassicIEDLL/targetver.h new file mode 100644 index 0000000..d4feea8 --- /dev/null +++ b/ClassicShellSrc/ClassicIE/ClassicIEDLL/targetver.h @@ -0,0 +1,24 @@ +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Specifies that the minimum required platform is Windows 7. +#define WINVER 0x0602 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows 7. +#define _WIN32_WINNT 0x0602 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. +#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. +#endif diff --git a/ClassicShellSrc/ClassicIE/Resource.h b/ClassicShellSrc/ClassicIE/Resource.h new file mode 100644 index 0000000..1e684ce --- /dev/null +++ b/ClassicShellSrc/ClassicIE/Resource.h @@ -0,0 +1,21 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ClassicIE.rc +// +#define IDC_MYICON 2 +#define IDD_CLASSICIE_DIALOG 102 +#define IDR_MAINFRAME 128 +#define IDI_ICON1 129 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 130 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/ClassicShellSrc/ClassicShell.sln b/ClassicShellSrc/ClassicShell.sln new file mode 100644 index 0000000..6c3f9e5 --- /dev/null +++ b/ClassicShellSrc/ClassicShell.sln @@ -0,0 +1,558 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassicExplorer", "ClassicExplorer\ClassicExplorer.vcproj", "{9AF324B7-F786-4D85-B2E1-6E51720F874E}" + ProjectSection(ProjectDependencies) = postProject + {D42FE717-485B-492D-884A-1999F6D51154} = {D42FE717-485B-492D-884A-1999F6D51154} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassicStartMenu", "ClassicStartMenu\ClassicStartMenu.vcproj", "{87D5FE20-AF86-458A-9AA3-3131EB06179B}" + ProjectSection(ProjectDependencies) = postProject + {5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089} = {5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089} + {D42FE717-485B-492D-884A-1999F6D51154} = {D42FE717-485B-492D-884A-1999F6D51154} + {066C9721-26D5-4C4D-868E-50C2BA0A8196} = {066C9721-26D5-4C4D-868E-50C2BA0A8196} + {81EB6336-366C-47DD-82CF-FF6C36CCD2B5} = {81EB6336-366C-47DD-82CF-FF6C36CCD2B5} + {63BAF573-170B-4FA0-AEE3-16E04F3E9DF5} = {63BAF573-170B-4FA0-AEE3-16E04F3E9DF5} + {CA5BFC96-428D-42F5-9F7D-CDDE048A357C} = {CA5BFC96-428D-42F5-9F7D-CDDE048A357C} + {A2CCDE9F-17CE-461E-8BD9-00261B8855A6} = {A2CCDE9F-17CE-461E-8BD9-00261B8855A6} + {66D1EAA4-65D1-45CC-9989-E616FC0575EB} = {66D1EAA4-65D1-45CC-9989-E616FC0575EB} + {9EC23CA9-384A-4EEB-979E-69879DC1A78C} = {9EC23CA9-384A-4EEB-979E-69879DC1A78C} + {ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94} = {ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94} + {598AB4AC-008E-4501-90B3-C5213834C1DA} = {598AB4AC-008E-4501-90B3-C5213834C1DA} + {7BD26CB3-5280-48FD-9A86-C13E321018D5} = {7BD26CB3-5280-48FD-9A86-C13E321018D5} + {85DEECBB-1F9B-4983-9D54-3BF42182B7E7} = {85DEECBB-1F9B-4983-9D54-3BF42182B7E7} + {404821C5-4EE4-4908-A759-5EF6DAC14AB6} = {404821C5-4EE4-4908-A759-5EF6DAC14AB6} + {EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75} = {EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75} + {31C016FB-9EA1-4AF5-987A-37210C04DA06} = {31C016FB-9EA1-4AF5-987A-37210C04DA06} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassicStartMenuDLL", "ClassicStartMenu\ClassicStartMenuDLL\ClassicStartMenuDLL.vcproj", "{85DEECBB-1F9B-4983-9D54-3BF42182B7E7}" + ProjectSection(ProjectDependencies) = postProject + {D42FE717-485B-492D-884A-1999F6D51154} = {D42FE717-485B-492D-884A-1999F6D51154} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassicShellSetup", "ClassicShellSetup\ClassicShellSetup.vcproj", "{A4A4D3B1-24E7-401E-A37C-72141D7603DC}" + ProjectSection(ProjectDependencies) = postProject + {D42FE717-485B-492D-884A-1999F6D51154} = {D42FE717-485B-492D-884A-1999F6D51154} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Skins", "Skins", "{409484D8-C0DB-4991-AF03-124128EDEF98}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Win7Aero", "Skins\Win7Aero\Win7Aero.vcproj", "{EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Win7Basic", "Skins\Win7Basic\Win7Basic.vcproj", "{404821C5-4EE4-4908-A759-5EF6DAC14AB6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassicSkin", "Skins\ClassicSkin\ClassicSkin.vcproj", "{9EC23CA9-384A-4EEB-979E-69879DC1A78C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FullGlass", "Skins\FullGlass\FullGlass.vcproj", "{066C9721-26D5-4C4D-868E-50C2BA0A8196}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SmokedGlass", "Skins\SmokedGlass\SmokedGlass.vcproj", "{66D1EAA4-65D1-45CC-9989-E616FC0575EB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinXP", "Skins\WinXP\WinXP.vcproj", "{81EB6336-366C-47DD-82CF-FF6C36CCD2B5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SetupHelper", "ClassicShellSetup\SetupHelper\SetupHelper.vcproj", "{E1017135-9916-4B11-9AC5-1EC0BD8F8CD6}" + ProjectSection(ProjectDependencies) = postProject + {D42FE717-485B-492D-884A-1999F6D51154} = {D42FE717-485B-492D-884A-1999F6D51154} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassicExplorerSettings", "ClassicExplorer\ClassicExplorerSettings\ClassicExplorerSettings.vcproj", "{E93271C8-0252-4A08-8227-1978C64C2D34}" + ProjectSection(ProjectDependencies) = postProject + {D42FE717-485B-492D-884A-1999F6D51154} = {D42FE717-485B-492D-884A-1999F6D51154} + {9AF324B7-F786-4D85-B2E1-6E51720F874E} = {9AF324B7-F786-4D85-B2E1-6E51720F874E} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "en-US", "ClassicShellSetup\en-US\en-US.vcproj", "{0A60FD06-3A81-4651-A869-9850DBC115EA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Setup", "Setup", "{B695E1F6-785D-45CB-BCE0-0E9635DFC1DE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassicShellLib", "ClassicShellLib\ClassicShellLib.vcproj", "{D42FE717-485B-492D-884A-1999F6D51154}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassicIE", "ClassicIE\ClassicIE.vcproj", "{65D5C193-E807-4094-AE19-19E6A310A312}" + ProjectSection(ProjectDependencies) = postProject + {D42FE717-485B-492D-884A-1999F6D51154} = {D42FE717-485B-492D-884A-1999F6D51154} + {BC0E6E7C-08C1-4F12-A754-4608E5A22FA8} = {BC0E6E7C-08C1-4F12-A754-4608E5A22FA8} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassicIEDLL", "ClassicIE\ClassicIEDLL\ClassicIEDLL.vcproj", "{BC0E6E7C-08C1-4F12-A754-4608E5A22FA8}" + ProjectSection(ProjectDependencies) = postProject + {D42FE717-485B-492D-884A-1999F6D51154} = {D42FE717-485B-492D-884A-1999F6D51154} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassicShellUpdate", "ClassicShellUpdate\ClassicShellUpdate.vcproj", "{171B46B0-6083-4D9E-BD33-946EA3BD76FA}" + ProjectSection(ProjectDependencies) = postProject + {D42FE717-485B-492D-884A-1999F6D51154} = {D42FE717-485B-492D-884A-1999F6D51154} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Win7Aero7", "Skins\Win7Aero7\Win7Aero7.vcproj", "{A2CCDE9F-17CE-461E-8BD9-00261B8855A6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassicSkin7", "Skins\ClassicSkin7\ClassicSkin7.vcproj", "{31C016FB-9EA1-4AF5-987A-37210C04DA06}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Win87", "Skins\Win87\Win87.vcproj", "{5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Win8", "Skins\Win8\Win8.vcproj", "{ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StartMenuHelper", "ClassicStartMenu\StartMenuHelper\StartMenuHelper.vcproj", "{A42C6159-ACA8-46D1-A0FB-19C398B137D5}" + ProjectSection(ProjectDependencies) = postProject + {D42FE717-485B-492D-884A-1999F6D51154} = {D42FE717-485B-492D-884A-1999F6D51154} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UpdateBin", "ClassicShellSetup\UpdateBin\UpdateBin.vcproj", "{F92A5473-F9E0-412F-923C-6632A66D13C1}" + ProjectSection(ProjectDependencies) = postProject + {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF} = {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassicShellUtility", "ClassicShellSetup\ClassicShellUtility\ClassicShellUtility.vcproj", "{DAE66C9B-05DC-4ACE-97DA-2547B490BBFF}" + ProjectSection(ProjectDependencies) = postProject + {D42FE717-485B-492D-884A-1999F6D51154} = {D42FE717-485B-492D-884A-1999F6D51154} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Midnight7", "Skins\Midnight7\Midnight7.vcproj", "{7BD26CB3-5280-48FD-9A86-C13E321018D5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Metro7", "Skins\Metro7\Metro7.vcproj", "{598AB4AC-008E-4501-90B3-C5213834C1DA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Metro", "Skins\Metro\Metro.vcproj", "{63BAF573-170B-4FA0-AEE3-16E04F3E9DF5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Metallic7", "Skins\Metallic7\Metallic7.vcproj", "{CA5BFC96-428D-42F5-9F7D-CDDE048A357C}" +EndProject +Global + GlobalSection(SourceCodeControl) = preSolution + SccNumberOfProjects = 29 + SccProjectUniqueName0 = ClassicExplorer\\ClassicExplorer.vcproj + SccLocalPath0 = . + SccProjectFilePathRelativizedFromConnection0 = ClassicExplorer\\ + SccProjectUniqueName1 = ClassicStartMenu\\ClassicStartMenu.vcproj + SccLocalPath1 = . + SccProjectFilePathRelativizedFromConnection1 = ClassicStartMenu\\ + SccProjectUniqueName2 = ClassicStartMenu\\ClassicStartMenuDLL\\ClassicStartMenuDLL.vcproj + SccLocalPath2 = . + SccProjectFilePathRelativizedFromConnection2 = ClassicStartMenu\\ClassicStartMenuDLL\\ + SccProjectUniqueName3 = Skins\\ClassicSkin\\ClassicSkin.vcproj + SccProjectTopLevelParentUniqueName3 = ClassicShell.sln + SccLocalPath3 = . + SccProjectFilePathRelativizedFromConnection3 = Skins\\ClassicSkin\\ + SccProjectUniqueName4 = ClassicExplorer\\ClassicExplorerSettings\\ClassicExplorerSettings.vcproj + SccLocalPath4 = . + SccProjectFilePathRelativizedFromConnection4 = ClassicExplorer\\ClassicExplorerSettings\\ + SccProjectUniqueName5 = ClassicShellSetup\\ClassicShellSetup.vcproj + SccProjectTopLevelParentUniqueName5 = ClassicShell.sln + SccLocalPath5 = . + SccProjectFilePathRelativizedFromConnection5 = ClassicShellSetup\\ + SccProjectUniqueName6 = ClassicShellLib\\ClassicShellLib.vcproj + SccLocalPath6 = . + SccProjectFilePathRelativizedFromConnection6 = ClassicShellLib\\ + SccProjectUniqueName7 = ClassicIE\\ClassicIE.vcproj + SccLocalPath7 = . + SccProjectFilePathRelativizedFromConnection7 = ClassicIE\\ + SccProjectUniqueName8 = ClassicIE\\ClassicIEDLL\\ClassicIEDLL.vcproj + SccLocalPath8 = . + SccProjectFilePathRelativizedFromConnection8 = ClassicIE\\ClassicIEDLL\\ + SccProjectUniqueName9 = ClassicShellUpdate\\ClassicShellUpdate.vcproj + SccLocalPath9 = . + SccProjectFilePathRelativizedFromConnection9 = ClassicShellUpdate\\ + SccProjectUniqueName10 = Skins\\ClassicSkin7\\ClassicSkin7.vcproj + SccProjectTopLevelParentUniqueName10 = ClassicShell.sln + SccLocalPath10 = . + SccProjectFilePathRelativizedFromConnection10 = Skins\\ClassicSkin7\\ + SccProjectUniqueName11 = ClassicShellSetup\\ClassicShellUtility\\ClassicShellUtility.vcproj + SccProjectTopLevelParentUniqueName11 = ClassicShell.sln + SccLocalPath11 = . + SccProjectFilePathRelativizedFromConnection11 = ClassicShellSetup\\ClassicShellUtility\\ + SccLocalPath12 = . + SccProjectUniqueName13 = Skins\\Win7Aero\\Win7Aero.vcproj + SccProjectTopLevelParentUniqueName13 = ClassicShell.sln + SccLocalPath13 = Skins\\Win7Aero + SccProjectUniqueName14 = Skins\\Win7Basic\\Win7Basic.vcproj + SccProjectTopLevelParentUniqueName14 = ClassicShell.sln + SccLocalPath14 = Skins\\Win7Basic + SccProjectUniqueName15 = Skins\\FullGlass\\FullGlass.vcproj + SccProjectTopLevelParentUniqueName15 = ClassicShell.sln + SccLocalPath15 = . + SccProjectFilePathRelativizedFromConnection15 = Skins\\FullGlass\\ + SccProjectUniqueName16 = Skins\\SmokedGlass\\SmokedGlass.vcproj + SccProjectTopLevelParentUniqueName16 = ClassicShell.sln + SccLocalPath16 = . + SccProjectFilePathRelativizedFromConnection16 = Skins\\SmokedGlass\\ + SccProjectUniqueName17 = Skins\\WinXP\\WinXP.vcproj + SccProjectTopLevelParentUniqueName17 = ClassicShell.sln + SccLocalPath17 = . + SccProjectFilePathRelativizedFromConnection17 = Skins\\WinXP\\ + SccProjectUniqueName18 = ClassicShellSetup\\SetupHelper\\SetupHelper.vcproj + SccProjectTopLevelParentUniqueName18 = ClassicShell.sln + SccLocalPath18 = . + SccProjectFilePathRelativizedFromConnection18 = ClassicShellSetup\\SetupHelper\\ + SccProjectUniqueName19 = ClassicShellSetup\\en-US\\en-US.vcproj + SccProjectTopLevelParentUniqueName19 = ClassicShell.sln + SccLocalPath19 = . + SccProjectFilePathRelativizedFromConnection19 = ClassicShellSetup\\en-US\\ + SccProjectUniqueName20 = Skins\\Win7Aero7\\Win7Aero7.vcproj + SccProjectTopLevelParentUniqueName20 = ClassicShell.sln + SccLocalPath20 = . + SccProjectFilePathRelativizedFromConnection20 = Skins\\Win7Aero7\\ + SccProjectUniqueName21 = Skins\\Win87\\Win87.vcproj + SccProjectTopLevelParentUniqueName21 = ClassicShell.sln + SccLocalPath21 = . + SccProjectFilePathRelativizedFromConnection21 = Skins\\Win87\\ + SccProjectUniqueName22 = Skins\\Win8\\Win8.vcproj + SccProjectTopLevelParentUniqueName22 = ClassicShell.sln + SccLocalPath22 = . + SccProjectFilePathRelativizedFromConnection22 = Skins\\Win8\\ + SccProjectUniqueName23 = ClassicStartMenu\\StartMenuHelper\\StartMenuHelper.vcproj + SccLocalPath23 = . + SccProjectFilePathRelativizedFromConnection23 = ClassicStartMenu\\StartMenuHelper\\ + SccProjectUniqueName24 = ClassicShellSetup\\UpdateBin\\UpdateBin.vcproj + SccProjectTopLevelParentUniqueName24 = ClassicShell.sln + SccLocalPath24 = . + SccProjectFilePathRelativizedFromConnection24 = ClassicShellSetup\\UpdateBin\\ + SccProjectUniqueName25 = Skins\\Midnight7\\Midnight7.vcproj + SccProjectTopLevelParentUniqueName25 = ClassicShell.sln + SccLocalPath25 = . + SccProjectFilePathRelativizedFromConnection25 = Skins\\Midnight7\\ + SccProjectUniqueName26 = Skins\\Metro7\\Metro7.vcproj + SccProjectTopLevelParentUniqueName26 = ClassicShell.sln + SccLocalPath26 = . + SccProjectFilePathRelativizedFromConnection26 = Skins\\Metro7\\ + SccProjectUniqueName27 = Skins\\Metro\\Metro.vcproj + SccProjectTopLevelParentUniqueName27 = ClassicShell.sln + SccLocalPath27 = . + SccProjectFilePathRelativizedFromConnection27 = Skins\\Metro\\ + SccProjectUniqueName28 = Skins\\Metallic7\\Metallic7.vcproj + SccProjectTopLevelParentUniqueName28 = ClassicShell.sln + SccLocalPath28 = . + SccProjectFilePathRelativizedFromConnection28 = Skins\\Metallic7\\ + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Setup|Win32 = Setup|Win32 + Setup|x64 = Setup|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9AF324B7-F786-4D85-B2E1-6E51720F874E}.Debug|Win32.ActiveCfg = Debug|Win32 + {9AF324B7-F786-4D85-B2E1-6E51720F874E}.Debug|Win32.Build.0 = Debug|Win32 + {9AF324B7-F786-4D85-B2E1-6E51720F874E}.Debug|x64.ActiveCfg = Debug|x64 + {9AF324B7-F786-4D85-B2E1-6E51720F874E}.Debug|x64.Build.0 = Debug|x64 + {9AF324B7-F786-4D85-B2E1-6E51720F874E}.Release|Win32.ActiveCfg = Release|Win32 + {9AF324B7-F786-4D85-B2E1-6E51720F874E}.Release|Win32.Build.0 = Release|Win32 + {9AF324B7-F786-4D85-B2E1-6E51720F874E}.Release|x64.ActiveCfg = Release|x64 + {9AF324B7-F786-4D85-B2E1-6E51720F874E}.Release|x64.Build.0 = Release|x64 + {9AF324B7-F786-4D85-B2E1-6E51720F874E}.Setup|Win32.ActiveCfg = Setup|Win32 + {9AF324B7-F786-4D85-B2E1-6E51720F874E}.Setup|Win32.Build.0 = Setup|Win32 + {9AF324B7-F786-4D85-B2E1-6E51720F874E}.Setup|x64.ActiveCfg = Setup|x64 + {9AF324B7-F786-4D85-B2E1-6E51720F874E}.Setup|x64.Build.0 = Setup|x64 + {87D5FE20-AF86-458A-9AA3-3131EB06179B}.Debug|Win32.ActiveCfg = Debug|Win32 + {87D5FE20-AF86-458A-9AA3-3131EB06179B}.Debug|Win32.Build.0 = Debug|Win32 + {87D5FE20-AF86-458A-9AA3-3131EB06179B}.Debug|x64.ActiveCfg = Debug|x64 + {87D5FE20-AF86-458A-9AA3-3131EB06179B}.Debug|x64.Build.0 = Debug|x64 + {87D5FE20-AF86-458A-9AA3-3131EB06179B}.Release|Win32.ActiveCfg = Release|Win32 + {87D5FE20-AF86-458A-9AA3-3131EB06179B}.Release|Win32.Build.0 = Release|Win32 + {87D5FE20-AF86-458A-9AA3-3131EB06179B}.Release|x64.ActiveCfg = Release|x64 + {87D5FE20-AF86-458A-9AA3-3131EB06179B}.Release|x64.Build.0 = Release|x64 + {87D5FE20-AF86-458A-9AA3-3131EB06179B}.Setup|Win32.ActiveCfg = Setup|Win32 + {87D5FE20-AF86-458A-9AA3-3131EB06179B}.Setup|Win32.Build.0 = Setup|Win32 + {87D5FE20-AF86-458A-9AA3-3131EB06179B}.Setup|x64.ActiveCfg = Setup|x64 + {87D5FE20-AF86-458A-9AA3-3131EB06179B}.Setup|x64.Build.0 = Setup|x64 + {85DEECBB-1F9B-4983-9D54-3BF42182B7E7}.Debug|Win32.ActiveCfg = Debug|Win32 + {85DEECBB-1F9B-4983-9D54-3BF42182B7E7}.Debug|Win32.Build.0 = Debug|Win32 + {85DEECBB-1F9B-4983-9D54-3BF42182B7E7}.Debug|x64.ActiveCfg = Debug|x64 + {85DEECBB-1F9B-4983-9D54-3BF42182B7E7}.Debug|x64.Build.0 = Debug|x64 + {85DEECBB-1F9B-4983-9D54-3BF42182B7E7}.Release|Win32.ActiveCfg = Release|Win32 + {85DEECBB-1F9B-4983-9D54-3BF42182B7E7}.Release|Win32.Build.0 = Release|Win32 + {85DEECBB-1F9B-4983-9D54-3BF42182B7E7}.Release|x64.ActiveCfg = Release|x64 + {85DEECBB-1F9B-4983-9D54-3BF42182B7E7}.Release|x64.Build.0 = Release|x64 + {85DEECBB-1F9B-4983-9D54-3BF42182B7E7}.Setup|Win32.ActiveCfg = Setup|Win32 + {85DEECBB-1F9B-4983-9D54-3BF42182B7E7}.Setup|Win32.Build.0 = Setup|Win32 + {85DEECBB-1F9B-4983-9D54-3BF42182B7E7}.Setup|x64.ActiveCfg = Setup|x64 + {85DEECBB-1F9B-4983-9D54-3BF42182B7E7}.Setup|x64.Build.0 = Setup|x64 + {A4A4D3B1-24E7-401E-A37C-72141D7603DC}.Debug|Win32.ActiveCfg = Debug|Win32 + {A4A4D3B1-24E7-401E-A37C-72141D7603DC}.Debug|Win32.Build.0 = Debug|Win32 + {A4A4D3B1-24E7-401E-A37C-72141D7603DC}.Debug|x64.ActiveCfg = Debug|Win32 + {A4A4D3B1-24E7-401E-A37C-72141D7603DC}.Release|Win32.ActiveCfg = Release|Win32 + {A4A4D3B1-24E7-401E-A37C-72141D7603DC}.Release|Win32.Build.0 = Release|Win32 + {A4A4D3B1-24E7-401E-A37C-72141D7603DC}.Release|x64.ActiveCfg = Release|Win32 + {A4A4D3B1-24E7-401E-A37C-72141D7603DC}.Setup|Win32.ActiveCfg = Release|Win32 + {A4A4D3B1-24E7-401E-A37C-72141D7603DC}.Setup|x64.ActiveCfg = Release|Win32 + {EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75}.Debug|Win32.ActiveCfg = Resource|Win32 + {EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75}.Debug|Win32.Build.0 = Resource|Win32 + {EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75}.Debug|x64.ActiveCfg = Resource|Win32 + {EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75}.Debug|x64.Build.0 = Resource|Win32 + {EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75}.Release|Win32.ActiveCfg = Resource|Win32 + {EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75}.Release|Win32.Build.0 = Resource|Win32 + {EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75}.Release|x64.ActiveCfg = Resource|Win32 + {EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75}.Release|x64.Build.0 = Resource|Win32 + {EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75}.Setup|Win32.ActiveCfg = Resource|Win32 + {EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75}.Setup|Win32.Build.0 = Resource|Win32 + {EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75}.Setup|x64.ActiveCfg = Resource|Win32 + {404821C5-4EE4-4908-A759-5EF6DAC14AB6}.Debug|Win32.ActiveCfg = Resource|Win32 + {404821C5-4EE4-4908-A759-5EF6DAC14AB6}.Debug|Win32.Build.0 = Resource|Win32 + {404821C5-4EE4-4908-A759-5EF6DAC14AB6}.Debug|x64.ActiveCfg = Resource|Win32 + {404821C5-4EE4-4908-A759-5EF6DAC14AB6}.Debug|x64.Build.0 = Resource|Win32 + {404821C5-4EE4-4908-A759-5EF6DAC14AB6}.Release|Win32.ActiveCfg = Resource|Win32 + {404821C5-4EE4-4908-A759-5EF6DAC14AB6}.Release|Win32.Build.0 = Resource|Win32 + {404821C5-4EE4-4908-A759-5EF6DAC14AB6}.Release|x64.ActiveCfg = Resource|Win32 + {404821C5-4EE4-4908-A759-5EF6DAC14AB6}.Release|x64.Build.0 = Resource|Win32 + {404821C5-4EE4-4908-A759-5EF6DAC14AB6}.Setup|Win32.ActiveCfg = Resource|Win32 + {404821C5-4EE4-4908-A759-5EF6DAC14AB6}.Setup|Win32.Build.0 = Resource|Win32 + {404821C5-4EE4-4908-A759-5EF6DAC14AB6}.Setup|x64.ActiveCfg = Resource|Win32 + {9EC23CA9-384A-4EEB-979E-69879DC1A78C}.Debug|Win32.ActiveCfg = Resource|Win32 + {9EC23CA9-384A-4EEB-979E-69879DC1A78C}.Debug|Win32.Build.0 = Resource|Win32 + {9EC23CA9-384A-4EEB-979E-69879DC1A78C}.Debug|x64.ActiveCfg = Resource|Win32 + {9EC23CA9-384A-4EEB-979E-69879DC1A78C}.Debug|x64.Build.0 = Resource|Win32 + {9EC23CA9-384A-4EEB-979E-69879DC1A78C}.Release|Win32.ActiveCfg = Resource|Win32 + {9EC23CA9-384A-4EEB-979E-69879DC1A78C}.Release|Win32.Build.0 = Resource|Win32 + {9EC23CA9-384A-4EEB-979E-69879DC1A78C}.Release|x64.ActiveCfg = Resource|Win32 + {9EC23CA9-384A-4EEB-979E-69879DC1A78C}.Release|x64.Build.0 = Resource|Win32 + {9EC23CA9-384A-4EEB-979E-69879DC1A78C}.Setup|Win32.ActiveCfg = Resource|Win32 + {9EC23CA9-384A-4EEB-979E-69879DC1A78C}.Setup|Win32.Build.0 = Resource|Win32 + {9EC23CA9-384A-4EEB-979E-69879DC1A78C}.Setup|x64.ActiveCfg = Resource|Win32 + {066C9721-26D5-4C4D-868E-50C2BA0A8196}.Debug|Win32.ActiveCfg = Resource|Win32 + {066C9721-26D5-4C4D-868E-50C2BA0A8196}.Debug|Win32.Build.0 = Resource|Win32 + {066C9721-26D5-4C4D-868E-50C2BA0A8196}.Debug|x64.ActiveCfg = Resource|Win32 + {066C9721-26D5-4C4D-868E-50C2BA0A8196}.Debug|x64.Build.0 = Resource|Win32 + {066C9721-26D5-4C4D-868E-50C2BA0A8196}.Release|Win32.ActiveCfg = Resource|Win32 + {066C9721-26D5-4C4D-868E-50C2BA0A8196}.Release|Win32.Build.0 = Resource|Win32 + {066C9721-26D5-4C4D-868E-50C2BA0A8196}.Release|x64.ActiveCfg = Resource|Win32 + {066C9721-26D5-4C4D-868E-50C2BA0A8196}.Release|x64.Build.0 = Resource|Win32 + {066C9721-26D5-4C4D-868E-50C2BA0A8196}.Setup|Win32.ActiveCfg = Resource|Win32 + {066C9721-26D5-4C4D-868E-50C2BA0A8196}.Setup|Win32.Build.0 = Resource|Win32 + {066C9721-26D5-4C4D-868E-50C2BA0A8196}.Setup|x64.ActiveCfg = Resource|Win32 + {66D1EAA4-65D1-45CC-9989-E616FC0575EB}.Debug|Win32.ActiveCfg = Resource|Win32 + {66D1EAA4-65D1-45CC-9989-E616FC0575EB}.Debug|Win32.Build.0 = Resource|Win32 + {66D1EAA4-65D1-45CC-9989-E616FC0575EB}.Debug|x64.ActiveCfg = Resource|Win32 + {66D1EAA4-65D1-45CC-9989-E616FC0575EB}.Debug|x64.Build.0 = Resource|Win32 + {66D1EAA4-65D1-45CC-9989-E616FC0575EB}.Release|Win32.ActiveCfg = Resource|Win32 + {66D1EAA4-65D1-45CC-9989-E616FC0575EB}.Release|Win32.Build.0 = Resource|Win32 + {66D1EAA4-65D1-45CC-9989-E616FC0575EB}.Release|x64.ActiveCfg = Resource|Win32 + {66D1EAA4-65D1-45CC-9989-E616FC0575EB}.Release|x64.Build.0 = Resource|Win32 + {66D1EAA4-65D1-45CC-9989-E616FC0575EB}.Setup|Win32.ActiveCfg = Resource|Win32 + {66D1EAA4-65D1-45CC-9989-E616FC0575EB}.Setup|Win32.Build.0 = Resource|Win32 + {66D1EAA4-65D1-45CC-9989-E616FC0575EB}.Setup|x64.ActiveCfg = Resource|Win32 + {81EB6336-366C-47DD-82CF-FF6C36CCD2B5}.Debug|Win32.ActiveCfg = Resource|Win32 + {81EB6336-366C-47DD-82CF-FF6C36CCD2B5}.Debug|Win32.Build.0 = Resource|Win32 + {81EB6336-366C-47DD-82CF-FF6C36CCD2B5}.Debug|x64.ActiveCfg = Resource|Win32 + {81EB6336-366C-47DD-82CF-FF6C36CCD2B5}.Debug|x64.Build.0 = Resource|Win32 + {81EB6336-366C-47DD-82CF-FF6C36CCD2B5}.Release|Win32.ActiveCfg = Resource|Win32 + {81EB6336-366C-47DD-82CF-FF6C36CCD2B5}.Release|Win32.Build.0 = Resource|Win32 + {81EB6336-366C-47DD-82CF-FF6C36CCD2B5}.Release|x64.ActiveCfg = Resource|Win32 + {81EB6336-366C-47DD-82CF-FF6C36CCD2B5}.Release|x64.Build.0 = Resource|Win32 + {81EB6336-366C-47DD-82CF-FF6C36CCD2B5}.Setup|Win32.ActiveCfg = Resource|Win32 + {81EB6336-366C-47DD-82CF-FF6C36CCD2B5}.Setup|Win32.Build.0 = Resource|Win32 + {81EB6336-366C-47DD-82CF-FF6C36CCD2B5}.Setup|x64.ActiveCfg = Resource|Win32 + {E1017135-9916-4B11-9AC5-1EC0BD8F8CD6}.Debug|Win32.ActiveCfg = Debug|Win32 + {E1017135-9916-4B11-9AC5-1EC0BD8F8CD6}.Debug|Win32.Build.0 = Debug|Win32 + {E1017135-9916-4B11-9AC5-1EC0BD8F8CD6}.Debug|x64.ActiveCfg = Debug|Win32 + {E1017135-9916-4B11-9AC5-1EC0BD8F8CD6}.Release|Win32.ActiveCfg = Release|Win32 + {E1017135-9916-4B11-9AC5-1EC0BD8F8CD6}.Release|Win32.Build.0 = Release|Win32 + {E1017135-9916-4B11-9AC5-1EC0BD8F8CD6}.Release|x64.ActiveCfg = Release|Win32 + {E1017135-9916-4B11-9AC5-1EC0BD8F8CD6}.Setup|Win32.ActiveCfg = Release|Win32 + {E1017135-9916-4B11-9AC5-1EC0BD8F8CD6}.Setup|Win32.Build.0 = Release|Win32 + {E1017135-9916-4B11-9AC5-1EC0BD8F8CD6}.Setup|x64.ActiveCfg = Release|Win32 + {E93271C8-0252-4A08-8227-1978C64C2D34}.Debug|Win32.ActiveCfg = Debug|Win32 + {E93271C8-0252-4A08-8227-1978C64C2D34}.Debug|Win32.Build.0 = Debug|Win32 + {E93271C8-0252-4A08-8227-1978C64C2D34}.Debug|x64.ActiveCfg = Debug|Win32 + {E93271C8-0252-4A08-8227-1978C64C2D34}.Release|Win32.ActiveCfg = Release|Win32 + {E93271C8-0252-4A08-8227-1978C64C2D34}.Release|Win32.Build.0 = Release|Win32 + {E93271C8-0252-4A08-8227-1978C64C2D34}.Release|x64.ActiveCfg = Release|Win32 + {E93271C8-0252-4A08-8227-1978C64C2D34}.Setup|Win32.ActiveCfg = Setup|Win32 + {E93271C8-0252-4A08-8227-1978C64C2D34}.Setup|Win32.Build.0 = Setup|Win32 + {E93271C8-0252-4A08-8227-1978C64C2D34}.Setup|x64.ActiveCfg = Setup|Win32 + {0A60FD06-3A81-4651-A869-9850DBC115EA}.Debug|Win32.ActiveCfg = Resource|Win32 + {0A60FD06-3A81-4651-A869-9850DBC115EA}.Debug|Win32.Build.0 = Resource|Win32 + {0A60FD06-3A81-4651-A869-9850DBC115EA}.Debug|x64.ActiveCfg = Resource|Win32 + {0A60FD06-3A81-4651-A869-9850DBC115EA}.Release|Win32.ActiveCfg = Resource|Win32 + {0A60FD06-3A81-4651-A869-9850DBC115EA}.Release|Win32.Build.0 = Resource|Win32 + {0A60FD06-3A81-4651-A869-9850DBC115EA}.Release|x64.ActiveCfg = Resource|Win32 + {0A60FD06-3A81-4651-A869-9850DBC115EA}.Setup|Win32.ActiveCfg = Resource|Win32 + {0A60FD06-3A81-4651-A869-9850DBC115EA}.Setup|Win32.Build.0 = Resource|Win32 + {0A60FD06-3A81-4651-A869-9850DBC115EA}.Setup|x64.ActiveCfg = Resource|Win32 + {D42FE717-485B-492D-884A-1999F6D51154}.Debug|Win32.ActiveCfg = Debug|Win32 + {D42FE717-485B-492D-884A-1999F6D51154}.Debug|Win32.Build.0 = Debug|Win32 + {D42FE717-485B-492D-884A-1999F6D51154}.Debug|x64.ActiveCfg = Debug|x64 + {D42FE717-485B-492D-884A-1999F6D51154}.Debug|x64.Build.0 = Debug|x64 + {D42FE717-485B-492D-884A-1999F6D51154}.Release|Win32.ActiveCfg = Release|Win32 + {D42FE717-485B-492D-884A-1999F6D51154}.Release|Win32.Build.0 = Release|Win32 + {D42FE717-485B-492D-884A-1999F6D51154}.Release|x64.ActiveCfg = Release|x64 + {D42FE717-485B-492D-884A-1999F6D51154}.Release|x64.Build.0 = Release|x64 + {D42FE717-485B-492D-884A-1999F6D51154}.Setup|Win32.ActiveCfg = Release|Win32 + {D42FE717-485B-492D-884A-1999F6D51154}.Setup|Win32.Build.0 = Release|Win32 + {D42FE717-485B-492D-884A-1999F6D51154}.Setup|x64.ActiveCfg = Release|x64 + {D42FE717-485B-492D-884A-1999F6D51154}.Setup|x64.Build.0 = Release|x64 + {65D5C193-E807-4094-AE19-19E6A310A312}.Debug|Win32.ActiveCfg = Debug|Win32 + {65D5C193-E807-4094-AE19-19E6A310A312}.Debug|Win32.Build.0 = Debug|Win32 + {65D5C193-E807-4094-AE19-19E6A310A312}.Debug|x64.ActiveCfg = Debug|x64 + {65D5C193-E807-4094-AE19-19E6A310A312}.Debug|x64.Build.0 = Debug|x64 + {65D5C193-E807-4094-AE19-19E6A310A312}.Release|Win32.ActiveCfg = Release|Win32 + {65D5C193-E807-4094-AE19-19E6A310A312}.Release|Win32.Build.0 = Release|Win32 + {65D5C193-E807-4094-AE19-19E6A310A312}.Release|x64.ActiveCfg = Release|x64 + {65D5C193-E807-4094-AE19-19E6A310A312}.Release|x64.Build.0 = Release|x64 + {65D5C193-E807-4094-AE19-19E6A310A312}.Setup|Win32.ActiveCfg = Setup|Win32 + {65D5C193-E807-4094-AE19-19E6A310A312}.Setup|Win32.Build.0 = Setup|Win32 + {65D5C193-E807-4094-AE19-19E6A310A312}.Setup|x64.ActiveCfg = Setup|x64 + {65D5C193-E807-4094-AE19-19E6A310A312}.Setup|x64.Build.0 = Setup|x64 + {BC0E6E7C-08C1-4F12-A754-4608E5A22FA8}.Debug|Win32.ActiveCfg = Debug|Win32 + {BC0E6E7C-08C1-4F12-A754-4608E5A22FA8}.Debug|Win32.Build.0 = Debug|Win32 + {BC0E6E7C-08C1-4F12-A754-4608E5A22FA8}.Debug|x64.ActiveCfg = Debug|x64 + {BC0E6E7C-08C1-4F12-A754-4608E5A22FA8}.Debug|x64.Build.0 = Debug|x64 + {BC0E6E7C-08C1-4F12-A754-4608E5A22FA8}.Release|Win32.ActiveCfg = Release|Win32 + {BC0E6E7C-08C1-4F12-A754-4608E5A22FA8}.Release|Win32.Build.0 = Release|Win32 + {BC0E6E7C-08C1-4F12-A754-4608E5A22FA8}.Release|x64.ActiveCfg = Release|x64 + {BC0E6E7C-08C1-4F12-A754-4608E5A22FA8}.Release|x64.Build.0 = Release|x64 + {BC0E6E7C-08C1-4F12-A754-4608E5A22FA8}.Setup|Win32.ActiveCfg = Setup|Win32 + {BC0E6E7C-08C1-4F12-A754-4608E5A22FA8}.Setup|Win32.Build.0 = Setup|Win32 + {BC0E6E7C-08C1-4F12-A754-4608E5A22FA8}.Setup|x64.ActiveCfg = Setup|x64 + {BC0E6E7C-08C1-4F12-A754-4608E5A22FA8}.Setup|x64.Build.0 = Setup|x64 + {171B46B0-6083-4D9E-BD33-946EA3BD76FA}.Debug|Win32.ActiveCfg = Debug|Win32 + {171B46B0-6083-4D9E-BD33-946EA3BD76FA}.Debug|Win32.Build.0 = Debug|Win32 + {171B46B0-6083-4D9E-BD33-946EA3BD76FA}.Debug|x64.ActiveCfg = Debug|Win32 + {171B46B0-6083-4D9E-BD33-946EA3BD76FA}.Release|Win32.ActiveCfg = Release|Win32 + {171B46B0-6083-4D9E-BD33-946EA3BD76FA}.Release|Win32.Build.0 = Release|Win32 + {171B46B0-6083-4D9E-BD33-946EA3BD76FA}.Release|x64.ActiveCfg = Release|Win32 + {171B46B0-6083-4D9E-BD33-946EA3BD76FA}.Setup|Win32.ActiveCfg = Release|Win32 + {171B46B0-6083-4D9E-BD33-946EA3BD76FA}.Setup|Win32.Build.0 = Release|Win32 + {171B46B0-6083-4D9E-BD33-946EA3BD76FA}.Setup|x64.ActiveCfg = Release|Win32 + {A2CCDE9F-17CE-461E-8BD9-00261B8855A6}.Debug|Win32.ActiveCfg = Resource|Win32 + {A2CCDE9F-17CE-461E-8BD9-00261B8855A6}.Debug|Win32.Build.0 = Resource|Win32 + {A2CCDE9F-17CE-461E-8BD9-00261B8855A6}.Debug|x64.ActiveCfg = Resource|Win32 + {A2CCDE9F-17CE-461E-8BD9-00261B8855A6}.Debug|x64.Build.0 = Resource|Win32 + {A2CCDE9F-17CE-461E-8BD9-00261B8855A6}.Release|Win32.ActiveCfg = Resource|Win32 + {A2CCDE9F-17CE-461E-8BD9-00261B8855A6}.Release|Win32.Build.0 = Resource|Win32 + {A2CCDE9F-17CE-461E-8BD9-00261B8855A6}.Release|x64.ActiveCfg = Resource|Win32 + {A2CCDE9F-17CE-461E-8BD9-00261B8855A6}.Release|x64.Build.0 = Resource|Win32 + {A2CCDE9F-17CE-461E-8BD9-00261B8855A6}.Setup|Win32.ActiveCfg = Resource|Win32 + {A2CCDE9F-17CE-461E-8BD9-00261B8855A6}.Setup|Win32.Build.0 = Resource|Win32 + {A2CCDE9F-17CE-461E-8BD9-00261B8855A6}.Setup|x64.ActiveCfg = Resource|Win32 + {31C016FB-9EA1-4AF5-987A-37210C04DA06}.Debug|Win32.ActiveCfg = Resource|Win32 + {31C016FB-9EA1-4AF5-987A-37210C04DA06}.Debug|Win32.Build.0 = Resource|Win32 + {31C016FB-9EA1-4AF5-987A-37210C04DA06}.Debug|x64.ActiveCfg = Resource|Win32 + {31C016FB-9EA1-4AF5-987A-37210C04DA06}.Debug|x64.Build.0 = Resource|Win32 + {31C016FB-9EA1-4AF5-987A-37210C04DA06}.Release|Win32.ActiveCfg = Resource|Win32 + {31C016FB-9EA1-4AF5-987A-37210C04DA06}.Release|Win32.Build.0 = Resource|Win32 + {31C016FB-9EA1-4AF5-987A-37210C04DA06}.Release|x64.ActiveCfg = Resource|Win32 + {31C016FB-9EA1-4AF5-987A-37210C04DA06}.Release|x64.Build.0 = Resource|Win32 + {31C016FB-9EA1-4AF5-987A-37210C04DA06}.Setup|Win32.ActiveCfg = Resource|Win32 + {31C016FB-9EA1-4AF5-987A-37210C04DA06}.Setup|Win32.Build.0 = Resource|Win32 + {31C016FB-9EA1-4AF5-987A-37210C04DA06}.Setup|x64.ActiveCfg = Resource|Win32 + {5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089}.Debug|Win32.ActiveCfg = Resource|Win32 + {5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089}.Debug|Win32.Build.0 = Resource|Win32 + {5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089}.Debug|x64.ActiveCfg = Resource|Win32 + {5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089}.Debug|x64.Build.0 = Resource|Win32 + {5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089}.Release|Win32.ActiveCfg = Resource|Win32 + {5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089}.Release|Win32.Build.0 = Resource|Win32 + {5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089}.Release|x64.ActiveCfg = Resource|Win32 + {5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089}.Release|x64.Build.0 = Resource|Win32 + {5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089}.Setup|Win32.ActiveCfg = Resource|Win32 + {5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089}.Setup|Win32.Build.0 = Resource|Win32 + {5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089}.Setup|x64.ActiveCfg = Resource|Win32 + {ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94}.Debug|Win32.ActiveCfg = Resource|Win32 + {ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94}.Debug|Win32.Build.0 = Resource|Win32 + {ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94}.Debug|x64.ActiveCfg = Resource|Win32 + {ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94}.Debug|x64.Build.0 = Resource|Win32 + {ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94}.Release|Win32.ActiveCfg = Resource|Win32 + {ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94}.Release|Win32.Build.0 = Resource|Win32 + {ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94}.Release|x64.ActiveCfg = Resource|Win32 + {ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94}.Release|x64.Build.0 = Resource|Win32 + {ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94}.Setup|Win32.ActiveCfg = Resource|Win32 + {ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94}.Setup|Win32.Build.0 = Resource|Win32 + {ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94}.Setup|x64.ActiveCfg = Resource|Win32 + {A42C6159-ACA8-46D1-A0FB-19C398B137D5}.Debug|Win32.ActiveCfg = Debug|Win32 + {A42C6159-ACA8-46D1-A0FB-19C398B137D5}.Debug|Win32.Build.0 = Debug|Win32 + {A42C6159-ACA8-46D1-A0FB-19C398B137D5}.Debug|x64.ActiveCfg = Debug|x64 + {A42C6159-ACA8-46D1-A0FB-19C398B137D5}.Debug|x64.Build.0 = Debug|x64 + {A42C6159-ACA8-46D1-A0FB-19C398B137D5}.Release|Win32.ActiveCfg = Release|Win32 + {A42C6159-ACA8-46D1-A0FB-19C398B137D5}.Release|Win32.Build.0 = Release|Win32 + {A42C6159-ACA8-46D1-A0FB-19C398B137D5}.Release|x64.ActiveCfg = Release|x64 + {A42C6159-ACA8-46D1-A0FB-19C398B137D5}.Release|x64.Build.0 = Release|x64 + {A42C6159-ACA8-46D1-A0FB-19C398B137D5}.Setup|Win32.ActiveCfg = Setup|Win32 + {A42C6159-ACA8-46D1-A0FB-19C398B137D5}.Setup|Win32.Build.0 = Setup|Win32 + {A42C6159-ACA8-46D1-A0FB-19C398B137D5}.Setup|x64.ActiveCfg = Setup|x64 + {A42C6159-ACA8-46D1-A0FB-19C398B137D5}.Setup|x64.Build.0 = Setup|x64 + {F92A5473-F9E0-412F-923C-6632A66D13C1}.Debug|Win32.ActiveCfg = update_4.3.1|Win32 + {F92A5473-F9E0-412F-923C-6632A66D13C1}.Debug|x64.ActiveCfg = update_4.2.7|Win32 + {F92A5473-F9E0-412F-923C-6632A66D13C1}.Release|Win32.ActiveCfg = update_4.2.7|Win32 + {F92A5473-F9E0-412F-923C-6632A66D13C1}.Release|Win32.Build.0 = update_4.2.7|Win32 + {F92A5473-F9E0-412F-923C-6632A66D13C1}.Release|x64.ActiveCfg = update_4.2.7|Win32 + {F92A5473-F9E0-412F-923C-6632A66D13C1}.Setup|Win32.ActiveCfg = update_4.2.7|Win32 + {F92A5473-F9E0-412F-923C-6632A66D13C1}.Setup|x64.ActiveCfg = update_4.3.0|Win32 + {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF}.Debug|Win32.ActiveCfg = Debug|Win32 + {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF}.Debug|Win32.Build.0 = Debug|Win32 + {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF}.Debug|x64.ActiveCfg = Debug|x64 + {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF}.Debug|x64.Build.0 = Debug|x64 + {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF}.Release|Win32.ActiveCfg = Release|Win32 + {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF}.Release|Win32.Build.0 = Release|Win32 + {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF}.Release|x64.ActiveCfg = Release|x64 + {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF}.Release|x64.Build.0 = Release|x64 + {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF}.Setup|Win32.ActiveCfg = Release|Win32 + {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF}.Setup|Win32.Build.0 = Release|Win32 + {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF}.Setup|x64.ActiveCfg = Release|x64 + {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF}.Setup|x64.Build.0 = Release|x64 + {7BD26CB3-5280-48FD-9A86-C13E321018D5}.Debug|Win32.ActiveCfg = Resource|Win32 + {7BD26CB3-5280-48FD-9A86-C13E321018D5}.Debug|Win32.Build.0 = Resource|Win32 + {7BD26CB3-5280-48FD-9A86-C13E321018D5}.Debug|x64.ActiveCfg = Resource|Win32 + {7BD26CB3-5280-48FD-9A86-C13E321018D5}.Debug|x64.Build.0 = Resource|Win32 + {7BD26CB3-5280-48FD-9A86-C13E321018D5}.Release|Win32.ActiveCfg = Resource|Win32 + {7BD26CB3-5280-48FD-9A86-C13E321018D5}.Release|Win32.Build.0 = Resource|Win32 + {7BD26CB3-5280-48FD-9A86-C13E321018D5}.Release|x64.ActiveCfg = Resource|Win32 + {7BD26CB3-5280-48FD-9A86-C13E321018D5}.Release|x64.Build.0 = Resource|Win32 + {7BD26CB3-5280-48FD-9A86-C13E321018D5}.Setup|Win32.ActiveCfg = Resource|Win32 + {7BD26CB3-5280-48FD-9A86-C13E321018D5}.Setup|Win32.Build.0 = Resource|Win32 + {7BD26CB3-5280-48FD-9A86-C13E321018D5}.Setup|x64.ActiveCfg = Resource|Win32 + {598AB4AC-008E-4501-90B3-C5213834C1DA}.Debug|Win32.ActiveCfg = Resource|Win32 + {598AB4AC-008E-4501-90B3-C5213834C1DA}.Debug|Win32.Build.0 = Resource|Win32 + {598AB4AC-008E-4501-90B3-C5213834C1DA}.Debug|x64.ActiveCfg = Resource|Win32 + {598AB4AC-008E-4501-90B3-C5213834C1DA}.Debug|x64.Build.0 = Resource|Win32 + {598AB4AC-008E-4501-90B3-C5213834C1DA}.Release|Win32.ActiveCfg = Resource|Win32 + {598AB4AC-008E-4501-90B3-C5213834C1DA}.Release|Win32.Build.0 = Resource|Win32 + {598AB4AC-008E-4501-90B3-C5213834C1DA}.Release|x64.ActiveCfg = Resource|Win32 + {598AB4AC-008E-4501-90B3-C5213834C1DA}.Release|x64.Build.0 = Resource|Win32 + {598AB4AC-008E-4501-90B3-C5213834C1DA}.Setup|Win32.ActiveCfg = Resource|Win32 + {598AB4AC-008E-4501-90B3-C5213834C1DA}.Setup|Win32.Build.0 = Resource|Win32 + {598AB4AC-008E-4501-90B3-C5213834C1DA}.Setup|x64.ActiveCfg = Resource|Win32 + {63BAF573-170B-4FA0-AEE3-16E04F3E9DF5}.Debug|Win32.ActiveCfg = Resource|Win32 + {63BAF573-170B-4FA0-AEE3-16E04F3E9DF5}.Debug|Win32.Build.0 = Resource|Win32 + {63BAF573-170B-4FA0-AEE3-16E04F3E9DF5}.Debug|x64.ActiveCfg = Resource|Win32 + {63BAF573-170B-4FA0-AEE3-16E04F3E9DF5}.Debug|x64.Build.0 = Resource|Win32 + {63BAF573-170B-4FA0-AEE3-16E04F3E9DF5}.Release|Win32.ActiveCfg = Resource|Win32 + {63BAF573-170B-4FA0-AEE3-16E04F3E9DF5}.Release|Win32.Build.0 = Resource|Win32 + {63BAF573-170B-4FA0-AEE3-16E04F3E9DF5}.Release|x64.ActiveCfg = Resource|Win32 + {63BAF573-170B-4FA0-AEE3-16E04F3E9DF5}.Release|x64.Build.0 = Resource|Win32 + {63BAF573-170B-4FA0-AEE3-16E04F3E9DF5}.Setup|Win32.ActiveCfg = Resource|Win32 + {63BAF573-170B-4FA0-AEE3-16E04F3E9DF5}.Setup|Win32.Build.0 = Resource|Win32 + {63BAF573-170B-4FA0-AEE3-16E04F3E9DF5}.Setup|x64.ActiveCfg = Resource|Win32 + {CA5BFC96-428D-42F5-9F7D-CDDE048A357C}.Debug|Win32.ActiveCfg = Resource|Win32 + {CA5BFC96-428D-42F5-9F7D-CDDE048A357C}.Debug|Win32.Build.0 = Resource|Win32 + {CA5BFC96-428D-42F5-9F7D-CDDE048A357C}.Debug|x64.ActiveCfg = Resource|Win32 + {CA5BFC96-428D-42F5-9F7D-CDDE048A357C}.Debug|x64.Build.0 = Resource|Win32 + {CA5BFC96-428D-42F5-9F7D-CDDE048A357C}.Release|Win32.ActiveCfg = Resource|Win32 + {CA5BFC96-428D-42F5-9F7D-CDDE048A357C}.Release|Win32.Build.0 = Resource|Win32 + {CA5BFC96-428D-42F5-9F7D-CDDE048A357C}.Release|x64.ActiveCfg = Resource|Win32 + {CA5BFC96-428D-42F5-9F7D-CDDE048A357C}.Release|x64.Build.0 = Resource|Win32 + {CA5BFC96-428D-42F5-9F7D-CDDE048A357C}.Setup|Win32.ActiveCfg = Resource|Win32 + {CA5BFC96-428D-42F5-9F7D-CDDE048A357C}.Setup|Win32.Build.0 = Resource|Win32 + {CA5BFC96-428D-42F5-9F7D-CDDE048A357C}.Setup|x64.ActiveCfg = Resource|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {E1017135-9916-4B11-9AC5-1EC0BD8F8CD6} = {B695E1F6-785D-45CB-BCE0-0E9635DFC1DE} + {0A60FD06-3A81-4651-A869-9850DBC115EA} = {B695E1F6-785D-45CB-BCE0-0E9635DFC1DE} + {A4A4D3B1-24E7-401E-A37C-72141D7603DC} = {B695E1F6-785D-45CB-BCE0-0E9635DFC1DE} + {F92A5473-F9E0-412F-923C-6632A66D13C1} = {B695E1F6-785D-45CB-BCE0-0E9635DFC1DE} + {DAE66C9B-05DC-4ACE-97DA-2547B490BBFF} = {B695E1F6-785D-45CB-BCE0-0E9635DFC1DE} + {EA65FDDD-CB77-417F-8BB4-2F3ECB5B3E75} = {409484D8-C0DB-4991-AF03-124128EDEF98} + {404821C5-4EE4-4908-A759-5EF6DAC14AB6} = {409484D8-C0DB-4991-AF03-124128EDEF98} + {9EC23CA9-384A-4EEB-979E-69879DC1A78C} = {409484D8-C0DB-4991-AF03-124128EDEF98} + {066C9721-26D5-4C4D-868E-50C2BA0A8196} = {409484D8-C0DB-4991-AF03-124128EDEF98} + {66D1EAA4-65D1-45CC-9989-E616FC0575EB} = {409484D8-C0DB-4991-AF03-124128EDEF98} + {81EB6336-366C-47DD-82CF-FF6C36CCD2B5} = {409484D8-C0DB-4991-AF03-124128EDEF98} + {A2CCDE9F-17CE-461E-8BD9-00261B8855A6} = {409484D8-C0DB-4991-AF03-124128EDEF98} + {31C016FB-9EA1-4AF5-987A-37210C04DA06} = {409484D8-C0DB-4991-AF03-124128EDEF98} + {5C875214-0E3A-4CF0-BC0C-BFF6FAA4C089} = {409484D8-C0DB-4991-AF03-124128EDEF98} + {ED74EBA9-1BCB-4B8F-9AE1-DC63B3C24A94} = {409484D8-C0DB-4991-AF03-124128EDEF98} + {7BD26CB3-5280-48FD-9A86-C13E321018D5} = {409484D8-C0DB-4991-AF03-124128EDEF98} + {598AB4AC-008E-4501-90B3-C5213834C1DA} = {409484D8-C0DB-4991-AF03-124128EDEF98} + {63BAF573-170B-4FA0-AEE3-16E04F3E9DF5} = {409484D8-C0DB-4991-AF03-124128EDEF98} + {CA5BFC96-428D-42F5-9F7D-CDDE048A357C} = {409484D8-C0DB-4991-AF03-124128EDEF98} + EndGlobalSection +EndGlobal diff --git a/ClassicShellSrc/ClassicShellLib/Assert.cpp b/ClassicShellSrc/ClassicShellLib/Assert.cpp new file mode 100644 index 0000000..9bcc31f --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/Assert.cpp @@ -0,0 +1,28 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include +#include "StringUtils.h" + +static DWORD _stdcall AssertThreadProc( void *param ) +{ + return MessageBoxA(NULL,(const char *)param,"Assertion Failed",MB_ABORTRETRYIGNORE|MB_TASKMODAL|MB_ICONERROR); +} + +// debug assert +bool dbg_assert( const char *exp, const char *file, unsigned line ) +{ + char buf[2048]; + Sprintf(buf,_countof(buf),"Expression: %s\r\nFile: %s\r\nLine: %d\n",exp,file,line); + HANDLE h=CreateThread(NULL,0,AssertThreadProc,buf,0,NULL); + if (h) + { + WaitForSingleObject(h,INFINITE); + DWORD res=IDRETRY; + GetExitCodeThread(h,&res); + if (res==IDABORT) + TerminateProcess(GetCurrentProcess(),1); + return (res==IDIGNORE); // true will continue, false will cause _CrtDbgBreak + } + return true; +} diff --git a/ClassicShellSrc/ClassicShellLib/Assert.h b/ClassicShellSrc/ClassicShellLib/Assert.h new file mode 100644 index 0000000..ab3904a --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/Assert.h @@ -0,0 +1,15 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#ifdef _DEBUG + +bool dbg_assert( const char *exp, const char *file, unsigned line ); +#define Assert(exp) do { if (!(exp) && !dbg_assert(#exp,__FILE__,__LINE__)) _CrtDbgBreak(); } while (0) + +#else + +#define Assert(exp) ((void)0) + +#endif diff --git a/ClassicShellSrc/ClassicShellLib/ClassicShellLib.rc b/ClassicShellSrc/ClassicShellLib/ClassicShellLib.rc new file mode 100644 index 0000000..20e332d --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/ClassicShellLib.rc @@ -0,0 +1,330 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_SETTINGSTREE DIALOGEX 0, 0, 350, 160 +STYLE DS_SETFONT | DS_CONTROL | WS_CHILD | WS_SYSMENU +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + CONTROL "",IDC_SETTINGS,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_INFOTIP | WS_BORDER | WS_HSCROLL | WS_TABSTOP,7,7,336,126 + LTEXT "The settings that are modified from the default will show in bold\r\nRight-click on a setting for more functions",IDC_STATICTIP,7,135,336,18 +END + +IDD_SETTINGS DIALOGEX 0, 0, 381, 213 +STYLE DS_SETFONT | DS_SETFOREGROUND | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Settings" +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + ICON "",IDC_ICONSEARCH,7,9,20,20 + EDITTEXT IDC_EDITSEARCH,22,7,120,12,ES_AUTOHSCROLL + CONTROL "Show all settings",IDC_CHECKALL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154,7,79,12 + CONTROL "Help...",IDC_LINKHELP,"SysLink",WS_TABSTOP,348,9,26,10,WS_EX_TRANSPARENT + CONTROL "",IDC_TABSETTINGS,"SysTabControl32",TCS_MULTILINE | TCS_FOCUSNEVER,7,20,367,169 + CONTROL "www.classicshell.net",IDC_LINKWEB,"SysLink",WS_TABSTOP,7,195,66,10,WS_EX_TRANSPARENT + CONTROL "Name of translator goes here",IDC_SYSLINKLOC, + "SysLink",NOT WS_VISIBLE | WS_TABSTOP,80,195,111,10 + PUSHBUTTON "&Backup",IDC_BUTTONBACKUP,200,192,60,14,WS_GROUP + DEFPUSHBUTTON "OK",IDOK,267,192,50,14 + PUSHBUTTON "Cancel",IDCANCEL,324,192,50,14 +END + +IDD_BROWSEFORICON DIALOGEX 0, 0, 317, 183 +STYLE DS_SETFONT | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +CAPTION "Select Icon" +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + LTEXT "File:",IDC_STATICFILE,7,7,19,14,SS_CENTERIMAGE + EDITTEXT IDC_EDITFILE,33,7,260,14,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BUTTONBROWSE,294,7,16,14 + CONTROL "",IDC_LISTICONS,"SysListView32",LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,26,303,132 + DEFPUSHBUTTON "OK",IDOK,205,162,50,14 + PUSHBUTTON "Cancel",IDCANCEL,260,162,50,14 +END + +IDD_LANGUAGE DIALOGEX 0, 0, 316, 144 +STYLE DS_SETFONT | DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN | WS_SYSMENU +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + CONTROL "",IDC_LISTLANGUAGE,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,18,302,99 + LTEXT "Select a language for the user interface:",IDC_STATICHINT,7,7,131,8 + PUSHBUTTON "&Check for Updates",IDC_BUTTONCHECK,7,123,75,14 + CONTROL "download link goes here",IDC_LINKDOWNLOAD,"SysLink",WS_TABSTOP,85,126,224,10 +END + +IDD_CUSTOMTREE DIALOGEX 0, 0, 365, 183 +STYLE DS_SETFONT | DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN | WS_SYSMENU +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + LTEXT "Current toolbar items:",IDC_STATICLEFT,7,7,167,8 + CONTROL "",IDC_TREEITEMS,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_EDITLABELS | TVS_SHOWSELALWAYS | TVS_INFOTIP | WS_BORDER | WS_HSCROLL | WS_TABSTOP,7,16,167,139 + LTEXT "Available commands:",IDC_STATICRIGHT,193,7,100,8 + CONTROL "",IDC_TREECOMMANDS,"SysTreeView32",TVS_SHOWSELALWAYS | TVS_INFOTIP | WS_BORDER | WS_HSCROLL | WS_TABSTOP,191,16,167,139 + LTEXT "<<",IDC_STATICMIDDLE,177,77,11,8 + LTEXT "Drag items from the right column to the left. Double-click to edit. Right-click for more functions",IDC_STATICHINT,7,159,351,17 +END + +IDD_PROGRESS DIALOGEX 0, 0, 209, 63 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION +CAPTION "Dialog" +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + PUSHBUTTON "Cancel",IDCANCEL,152,42,50,14 + CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,7,20,195,14 + LTEXT "Static",IDC_MESSAGE,7,7,195,12 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_SETTINGSTREE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 343 + TOPMARGIN, 7 + BOTTOMMARGIN, 153 + END + + IDD_SETTINGS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 374 + TOPMARGIN, 7 + BOTTOMMARGIN, 206 + END + + IDD_BROWSEFORICON, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 310 + TOPMARGIN, 7 + BOTTOMMARGIN, 176 + END + + IDD_LANGUAGE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 309 + TOPMARGIN, 7 + BOTTOMMARGIN, 137 + END + + IDD_CUSTOMTREE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 358 + TOPMARGIN, 7 + BOTTOMMARGIN, 176 + END + + IDD_PROGRESS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 202 + TOPMARGIN, 7 + BOTTOMMARGIN, 56 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICONLOCK ICON "padlock.ico" +IDI_ICONPLAY ICON "play.ico" +IDI_ICONWARNING ICON "warning.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_FLAGS BITMAP "flags.bmp" +IDB_FLAGS24 BITMAP "flags24.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_TOGGLE_SETTING "Toggle Setting\tSpace" + IDS_SELECT_SETTING "Select Setting\tSpace" + IDS_DEFAULT_SETTING "Set Default\tCtrl+Space" + IDS_PLAY_SETTING "Play Sound\tCtrl+P" + IDS_ICON_FILTERS "Icon files (*.ico, *.dll, *.exe)|*.ico;*.dll;*.exe|ICO files (*.ico)|*.ico|DLL files (*.dll)|*.dll|EXE files (*.exe)|*.exe|All Files (*.*)|*.*|" + IDS_ICON_TITLE "Select Source File" + IDS_WAV_FILTERS "WAV files (*.wav)|*.wav|" + IDS_WAV_TITLE "Select Sound File" + IDS_SETTING_LOCKED "This setting has been locked by the administrator" + IDS_SETTING_LOCKED_GP "This setting has been locked by a group policy" + IDS_BASIC_SETTINGS "Basic Settings" + IDS_ALWAYS_ON_TOP "&Always on Top" + IDS_MENU_EDIT "Edit Item" + IDS_MENU_DELETE "Delete Item" + IDS_MENU_RENAME "Rename Item" + IDS_PICK_LINK_TITLE "Select a file or a folder" +END + +STRINGTABLE +BEGIN + IDS_PICK_LINK_FILE "Select File" + IDS_PICK_LINK_FOLDER "Select Folder" + IDS_DUPLICATE_ITEM "Item named '%s' already exists." + IDS_ERROR_TITLE "Error" + IDS_ERROR_SEPARATOR "The item name cannot be '%s'." + IDS_ERROR_ASCII "This is an internal name of the item and must contain only English letters and numbers. Use the Text and Tip properties to enter the visible text." + IDS_ERROR_EMPTY "The item name cannot be empty." + IDS_RESET_TOOLBAR "Reset Toolbar" + IDS_RESET_TOOLBAR_WARN "Are you sure you want to reset all toolbar buttons?" + IDS_RESET_MENU "Reset Start Menu" + IDS_RESET_MENU_WARN "Are you sure you want to reset the whole start menu?" + IDS_ADD_TOOLBAR "Add to Toolbar" + IDS_ADD_MENU "Add to Menu" + IDS_INSERT_MENU "Create sub-menu" + IDS_EMPTY_MENU "" + IDS_TREE_TOOLBAR "Current toolbar buttons:" +END + +STRINGTABLE +BEGIN + IDS_TREE_MENU "Current menu items:" + IDS_XML_FILTERS "XML files (*.xml)|*.xml|" + IDS_XML_TITLE_LOAD "Load XML File" + IDS_XML_TITLE_SAVE "Save XML File" + IDS_RESET_CONFIRM "Are you sure you want to reset all settings?" + IDS_RESET_TITLE "Reset All Settings" + IDS_TOOLBAR_LOCKED "The toolbar is locked by the administrator" + IDS_MENU_LOCKED "The start menu is locked by the administrator" + IDS_BACKUP_SAVE "Save to XML File..." + IDS_BACKUP_LOAD "Load from XML File..." + IDS_BACKUP_RESET "Reset all settings" + IDS_ERROR_LOADING_XML "Error loading XML file '%s'." + IDS_ERROR_SAVING_XML "Error saving XML file '%s'." + IDS_DRAG_DROP_EXP_TIP "Drag buttons from the right column to the left. You can drop on top of a button to create a sub-menu.\nDouble-click in the left column to edit the button. Right-click for more functions." + IDS_DRAG_DROP_SM_TIP "Drag menu items from the right column to the left. You can drop on top of a menu item to create a sub-menu.\nDouble-click in the left column to edit the item. Right-click for more functions." + IDS_COMMAND_EXP_TIP "Drag the command or double-click on it to add it to the toolbar" +END + +STRINGTABLE +BEGIN + IDS_COMMAND_SM_TIP "Drag the command or double-click on it to add it to the start menu" + IDS_COMMAND_FILTERS "Programs (*.exe, *.com, *.pif, *.bat, *.cmd)|*.exe;*.com;*.pif;*.bat;*.cmd|All files (*.*)|*.*|" + IDS_OS_LANGUAGE "Current OS language" + IDS_BMP_FILTERS "Image files (*.bmp,*.png)|*.bmp;*.png|" + IDS_BMP_TITLE "Select Image File" + IDS_SEARCH_PROMPT "Search settings" + IDS_SETTING_SEARCH "Search Results" + IDS_WEBSITE_TIP "Visit Classic Shell on the web - http://www.classicshell.net" + IDS_LOCATE_SETTING "Locate setting" + IDS_LANGUAGE_UPDATED "The language %s is up to date." + IDS_LANGUAGE_MISSING "Update for language %s is not available." + IDS_LANGUAGE_DOWNLOAD "New update for language %s is available. Click here to install it." + IDS_LANGUAGE_SUCCESS "The language file was installed successfully.\nYou need to log off and back on for the update to take effect." + IDS_LANGUAGE_SUCCESS2 "The language file was installed successfully.\nYou need to log off and back on for the update to take effect.\n\nNote: This update provides only basic translations. It supports only the main text found in the start menu and in Explorer. The settings will not be translated." + IDS_LANGUAGE_FAIL "Failed to check for updates." + IDS_INTERNET_FAIL "Failed to connect to the Internet." +END + +STRINGTABLE +BEGIN + IDS_INITIATE_FAIL "Failed to initiate the download." + IDS_LANG_DOWNLOAD_FAIL "Failed to download the language file." + IDS_LANG_SAVE_FAIL "Failed to save language file '%s'." + IDS_UPDATE_TITLE "Classic Shell Update" + IDS_INST_DOWNLOAD_FAIL "Failed to download the new version." + IDS_INST_SAVE_FAIL "Failed to save file '%s'." + IDS_PROGRESS_CONNECT "Connecting..." + IDS_PROGRESS_DOWNLOAD "Downloading..." + IDS_PROGRESS_VERIFY "Verifying..." + IDS_PROGRESS_SAVE "Saving..." + IDS_PROGRESS_TITLE_CHECK "Checking for updates" + IDS_PROGRESS_TITLE_DOWNLOAD "Downloading update" + IDS_DOWNLOAD_TIP "You can try getting the file directly from the website:" + IDS_BMP_FILTERS2 "Image files (*.bmp,*.png,*.jpg)|*.bmp;*.png;*.jpg|" + IDS_UNSAVED_CHANGES "Do you want to save your changes to the settings?" + IDS_UNSAVED_TITLE "Unsaved changes" +END + +STRINGTABLE +BEGIN + IDS_VERSION_URL "http://www.classicshell.net/files/updates/update_" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/ClassicShellSrc/ClassicShellLib/ClassicShellLib.vcproj b/ClassicShellSrc/ClassicShellLib/ClassicShellLib.vcproj new file mode 100644 index 0000000..f31c188 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/ClassicShellLib.vcproj @@ -0,0 +1,510 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicShellLib/ComHelper.h b/ClassicShellSrc/ClassicShellLib/ComHelper.h new file mode 100644 index 0000000..193deb0 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/ComHelper.h @@ -0,0 +1,44 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#include +#include "Assert.h" + +class CAbsolutePidl +{ +public: + CAbsolutePidl( void ) { m_Pidl=NULL; } + CAbsolutePidl( const CAbsolutePidl &pidl ) { m_Pidl=pidl?ILCloneFull(pidl):NULL; } + ~CAbsolutePidl( void ) { Clear(); } + void operator=( const CAbsolutePidl &pidl ) { Clone(pidl); } + + void Clear( void ) { if (m_Pidl) ILFree(m_Pidl); m_Pidl=NULL; } + operator PIDLIST_ABSOLUTE( void ) const { return m_Pidl; } + PIDLIST_ABSOLUTE* operator&( void ) { Assert(m_Pidl==NULL); return &m_Pidl; } + void Swap( CAbsolutePidl &pidl ) { PIDLIST_ABSOLUTE q=pidl.m_Pidl; pidl.m_Pidl=m_Pidl; m_Pidl=q; } + void Attach( PIDLIST_ABSOLUTE pidl ) { Clear(); m_Pidl=pidl; } + PIDLIST_ABSOLUTE Detach( void ) { PIDLIST_ABSOLUTE pidl=m_Pidl; m_Pidl=NULL; return pidl; } + void Clone( PIDLIST_ABSOLUTE pidl ) { Clear(); m_Pidl=pidl?ILCloneFull(pidl):NULL; } + +private: + PIDLIST_ABSOLUTE m_Pidl; +}; + +class CComString +{ +public: + CComString( void ) { m_String=NULL; } + ~CComString( void ) { Clear(); } + + void Clear( void ) { if (m_String) CoTaskMemFree(m_String); m_String=NULL; } + operator const wchar_t*( void ) const { return m_String; } + wchar_t** operator&( void ) { Assert(m_String==NULL); return &m_String; } + void MakeUpper( void ) { if (m_String) CharUpper(m_String); } + +private: + CComString( const CComString &str ); + void operator=( const CComString &str ); + wchar_t *m_String; +}; diff --git a/ClassicShellSrc/ClassicShellLib/DownloadHelper.cpp b/ClassicShellSrc/ClassicShellLib/DownloadHelper.cpp new file mode 100644 index 0000000..dbdbf02 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/DownloadHelper.cpp @@ -0,0 +1,1144 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include +#include "resource.h" +#include "..\ClassicShellSetup\UpdateBin\resource.h" +#include "DownloadHelper.h" +#include "Settings.h" +#include "SettingsUIHelper.h" +#include "LanguageSettingsHelper.h" +#include "ResourceHelper.h" +#include "ComHelper.h" +#include "FNVHash.h" +#include "StringUtils.h" +#include "Translations.h" +#include +#include + +//#define UPDATE_LOG L"-|%LOCALAPPDATA%\\ClassicShell\\UpdateLog.txt" + +const __int64 TIME_DIVISOR=360000000; // divisor for FILETIME to get 0.01 hour precision +const int TIME_PRECISION=100; // 0.01 hour precision + +class CProgressDlg: public CResizeableDlg +{ +public: + CProgressDlg( void ); + BEGIN_MSG_MAP( CProgressDlg ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + MESSAGE_HANDLER( WM_CLEAR, OnClear ) + COMMAND_HANDLER( IDCANCEL, BN_CLICKED, OnCancel ) + END_MSG_MAP() + + BEGIN_RESIZE_MAP + END_RESIZE_MAP + + void Create( HWND owner, const wchar_t *title ); + void SetText( const wchar_t *text ); // may block if messages are not processed + void SetProgress( int progress ); // -1 for undefined + void EnableCancel( bool bEnabled ); + bool IsCanceled( void ) const { return m_bCanceled; } + +protected: + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnClear( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + +private: + bool m_bCanceled; + bool m_bMarquee; + CWindow m_Progress; + + enum + { + COMMAND_SET_PROGRESS, + COMMAND_ENABLE_CANCEL, + }; +}; + +CProgressDlg::CProgressDlg( void ) +{ + m_bCanceled=m_bMarquee=false; +} + +LRESULT CProgressDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + InitResize(MOVE_HORIZONTAL|MOVE_VERTICAL); + m_Progress=GetDlgItem(IDC_PROGRESS); + m_Progress.SendMessage(PBM_SETRANGE,0,MAKELPARAM(0,100)); + return TRUE; +} + +void CProgressDlg::Create( HWND owner, const wchar_t *title ) +{ + DLGTEMPLATE *pTemplate=LoadDialogEx(IDD_PROGRESS); + CResizeableDlg::Create(owner,pTemplate); + SetWindowText(title); + ShowWindow(SW_SHOW); + SetDlgItemText(IDC_MESSAGE,L""); +} + +void CProgressDlg::SetText( const wchar_t *text ) +{ + SetDlgItemText(IDC_MESSAGE,text); +} + +void CProgressDlg::SetProgress( int progress ) +{ + PostMessage(WM_CLEAR,COMMAND_SET_PROGRESS,progress); +} + +void CProgressDlg::EnableCancel( bool bEnabled ) +{ + PostMessage(WM_CLEAR,COMMAND_ENABLE_CANCEL,bEnabled?1:0); +} + +LRESULT CProgressDlg::OnClear( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==COMMAND_SET_PROGRESS) + { + int progress=(int)lParam; + if (progress>=0) + { + if (m_bMarquee) + { + m_Progress.SendMessage(PBM_SETMARQUEE,FALSE); + m_bMarquee=false; + } + m_Progress.SendMessage(PBM_SETPOS,progress); + } + else + { + if (!m_bMarquee) + { + m_Progress.SendMessage(PBM_SETMARQUEE,TRUE,50); + m_Progress.SetWindowLong(GWL_STYLE,m_Progress.GetWindowLong(GWL_STYLE)|PBS_MARQUEE); + m_bMarquee=true; + } + m_Progress.SendMessage(PBM_STEPIT); + } + } + else if (wParam==COMMAND_ENABLE_CANCEL) + { + GetDlgItem(IDCANCEL).EnableWindow(lParam!=0); + } + return 0; +} + +LRESULT CProgressDlg::OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + m_bCanceled=true; + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +static bool g_bCheckingVersion; + +static DWORD GetTimeStamp( const wchar_t *fname ) +{ + HANDLE h=CreateFile(fname,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + if (h==INVALID_HANDLE_VALUE) + return 0; + DWORD res=0; + DWORD q; + IMAGE_DOS_HEADER header; + if (ReadFile(h,&header,sizeof(header),&q,NULL) && q==sizeof(header)) + { + if (SetFilePointer(h,header.e_lfanew+8,NULL,FILE_BEGIN)!=INVALID_SET_FILE_POINTER) + { + if (!ReadFile(h,&res,4,&q,NULL) || q!=4) + res=0; + } + } + CloseHandle(h); + return res; +} + +enum TDownloadResult +{ + DOWNLOAD_OK, + DOWNLOAD_SAMETIME, + DOWNLOAD_CANCEL, + + // errors + DOWNLOAD_FIRST_ERROR, + DOWNLOAD_INTERNET=DOWNLOAD_FIRST_ERROR, + DOWNLOAD_START, + DOWNLOAD_FAIL, +}; + +// Downloads a file +// filename - returns the name of the downloaded file +// timestamp - if not zero, it is compared to the timestamp of the file and returns DOWNLOAD_SAMETIME if the same (and buf will be empty) +static TDownloadResult DownloadFile( const wchar_t *url, std::vector &buf, CString *pFilename, DWORD timestamp, bool bAcceptCached, CProgressDlg *pProgress, TSettingsComponent component ) +{ + const wchar_t *compName=L"Classic Shell"; + switch (component) + { + case COMPONENT_EXPLORER: compName=L"Classic Explorer"; break; + case COMPONENT_MENU: compName=L"Classic Start Menu"; break; + case COMPONENT_IE: compName=L"Classic IE"; break; + case COMPONENT_UPDATE: compName=L"Classic Shell Update"; break; + } + + DWORD compVersion=GetVersionEx(g_Instance); + + wchar_t agent[100]; + Sprintf(agent,_countof(agent),L"%s %d.%d.%d (Win %x)",compName,compVersion>>24,(compVersion>>16)&0xFF,compVersion&0xFFFF,GetWinVersion()); + + TDownloadResult res=DOWNLOAD_OK; + HINTERNET hInternet=InternetOpen(agent,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0); + if (!hInternet) + return DOWNLOAD_INTERNET; + if (pProgress && pProgress->IsCanceled()) + res=DOWNLOAD_CANCEL; + + wchar_t host[256]; + wchar_t file[256]; + URL_COMPONENTS components={sizeof(components)}; + components.lpszHostName=host; + components.dwHostNameLength=_countof(host); + components.lpszUrlPath=file; + components.dwUrlPathLength=_countof(file); + InternetCrackUrl(url,0,0,&components); + int time=GetTickCount(); + if (pProgress) + pProgress->SetText(LoadStringEx(IDS_PROGRESS_CONNECT)); + HINTERNET hConnect=InternetConnect(hInternet,host,INTERNET_DEFAULT_HTTP_PORT,L"",L"",INTERNET_SERVICE_HTTP,0,0); + if (hConnect) + { + if (pProgress && pProgress->IsCanceled()) + res=DOWNLOAD_CANCEL; + const wchar_t *accept[]={L"*/*",NULL}; + if (res==DOWNLOAD_OK) + { + HINTERNET hRequest=HttpOpenRequest(hConnect,L"GET",file,NULL,NULL,accept,bAcceptCached?0:INTERNET_FLAG_RELOAD,0); + if (hRequest) + { + if (pProgress && pProgress->IsCanceled()) + res=DOWNLOAD_CANCEL; + // get size (may be missing) + DWORD fileSize; + if (res==DOWNLOAD_OK) + { + if (HttpSendRequest(hRequest,NULL,0,NULL,0)) + { + DWORD len=sizeof(fileSize); + DWORD index=0; + if (!HttpQueryInfo(hRequest,HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER,&fileSize,&len,&index)) + fileSize=0; + } + else + res=DOWNLOAD_START; + } + + // get file name (must be after HttpSendRequest to resolve any redirections) + if (res==DOWNLOAD_OK && pFilename) + { + wchar_t buf[1024]; + DWORD len=sizeof(buf); + if (InternetQueryOption(hRequest,INTERNET_OPTION_URL,buf,&len)) + { + const wchar_t *name=wcsrchr(buf,'/'); + if (name && name[1]) + *pFilename=name+1; + else + res=DOWNLOAD_START; + } + else + res=DOWNLOAD_START; + } + + if (res==DOWNLOAD_OK) + { + if (pProgress) + { + pProgress->SetText(LoadStringEx(IDS_PROGRESS_DOWNLOAD)); + if (fileSize==0) + pProgress->SetProgress(-1); + } + int CHUNK_SIZE=timestamp?1024:32768; // start with small chunk to verify the timestamp + DWORD size=0; + buf.reserve(fileSize+CHUNK_SIZE); + while (1) + { + if (pProgress && pProgress->IsCanceled()) + { + res=DOWNLOAD_CANCEL; + break; + } + DWORD dwSize; + buf.resize(size+CHUNK_SIZE); + if (!InternetReadFile(hRequest,&buf[size],CHUNK_SIZE,&dwSize)) + { + res=DOWNLOAD_FAIL; + break; + } + if (dwSize==0) + break; + size+=dwSize; + if (pProgress && fileSize) + pProgress->SetProgress(size*100/fileSize); + if (timestamp && (size=sizeof(IMAGE_DOS_HEADER)) + { + DWORD pos=((IMAGE_DOS_HEADER*)&buf[0])->e_lfanew+8; + if (size>=pos+4) + { + if (timestamp==*(DWORD*)&buf[pos]) + { + res=DOWNLOAD_SAMETIME; + break; + } + timestamp=0; + CHUNK_SIZE=32768; + } + } + } + buf.resize(size); + } + InternetCloseHandle(hRequest); + } + else + res=DOWNLOAD_START; + } + InternetCloseHandle(hConnect); + } + else + res=DOWNLOAD_START; + + InternetCloseHandle(hInternet); + return res; +} + +static int SaveFile( const wchar_t *fname, const std::vector &buf ) +{ + HANDLE h=CreateFile(fname,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); + int err=0; + if (h!=INVALID_HANDLE_VALUE) + { + DWORD size=(DWORD)buf.size(); + DWORD q; + if (WriteFile(h,&buf[0],size,&q,NULL) && q==size) + CloseHandle(h); + else + { + err=GetLastError(); +#ifdef UPDATE_LOG + LogToFile(UPDATE_LOG,L"Failed to write file '%s': 0x%08X",fname,err); +#endif + CloseHandle(h); + DeleteFile(fname); + } + } + else + { + err=GetLastError(); +#ifdef UPDATE_LOG + LogToFile(UPDATE_LOG,L"Failed to save file '%s': 0x%08X",fname,err); +#endif + } + return err; +} + +struct VersionCheckParams +{ + TVersionCheck check; + TSettingsComponent component; + tNewVersionCallback callback; + CProgressDlg *progress; +}; + +// 0 - fail, 1 - success, 2 - cancel +static DWORD WINAPI ThreadVersionCheck( void *param ) +{ + VersionCheckParams params=*(VersionCheckParams*)param; + delete param; + param=NULL; + ULONGLONG curTimeL; + GetSystemTimeAsFileTime((FILETIME*)&curTimeL); + DWORD curTime=(DWORD)(curTimeL/TIME_DIVISOR); // in 0.01 hours + + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicShell")!=ERROR_SUCCESS) + { + g_bCheckingVersion=false; + return 0; + } + DWORD curVersion=GetVersionEx(g_Instance); + regKey.SetDWORDValue(L"LastUpdateVersion",curVersion); + + // download file + wchar_t fname[_MAX_PATH]=L"%ALLUSERSPROFILE%\\ClassicShell"; + DoEnvironmentSubst(fname,_countof(fname)); + SHCreateDirectory(NULL,fname); + PathAppend(fname,L"update.ver"); + + bool res=false; + CString urlBase=LoadStringEx(IDS_VERSION_URL); + VersionData data; + data.Clear(); + if (data.Load(fname,false)==VersionData::LOAD_OK) + { + if (!data.altUrl.IsEmpty()) + urlBase=data.altUrl; + WIN32_FILE_ATTRIBUTE_DATA attr; + if (GetFileAttributesEx(fname,GetFileExInfoStandard,&attr)) + { + DWORD writeTime=(DWORD)(((((ULONGLONG)attr.ftLastWriteTime.dwHighDateTime)<<32)|attr.ftLastWriteTime.dwLowDateTime)/TIME_DIVISOR); + if (curTime>writeTime && (curTime-writeTime)>24,(curVersion>>16)&0xFF,curVersion&0xFFFF); + + #ifdef UPDATE_LOG + LogToFile(UPDATE_LOG,L"URL: %s",url); + #endif + + std::vector buf; + TDownloadResult download=DownloadFile(url,buf,NULL,GetTimeStamp(fname),false,params.progress,params.component); + #ifdef UPDATE_LOG + LogToFile(UPDATE_LOG,L"Download result: %d",download); + #endif + if (download==DOWNLOAD_CANCEL) + { + g_bCheckingVersion=false; + return 2; + } + + if (downloadSetText(LoadStringEx(IDS_PROGRESS_VERIFY)); + params.progress->SetProgress(-1); + } + VersionData::TLoadResult load=data.Load(fname,false); + #ifdef UPDATE_LOG + LogToFile(UPDATE_LOG,L"Load result: %d",load); + #endif + if (load==VersionData::LOAD_BAD_FILE) + DeleteFile(fname); + res=(load==VersionData::LOAD_OK); + } + } + } + + curTime+=(rand()*TIME_PRECISION)/(RAND_MAX+1)-(TIME_PRECISION/2); // add between -30 and 30 minutes to randomize access + if (!res) + { + g_bCheckingVersion=false; + // if the check failed pretend we checked 5 days ago (so we check again in 48 hours) + if (curTime>24*5*TIME_PRECISION) + regKey.SetDWORDValue(L"LastUpdateTime",curTime-24*5*TIME_PRECISION); + return 0; + } + + regKey.SetDWORDValue(L"LastUpdateTime",curTime); + + { + DWORD remindedVersion; + if (regKey.QueryDWORDValue(L"RemindedVersion",remindedVersion)!=ERROR_SUCCESS) + remindedVersion=0; + data.bNewVersion=(data.newVersion>curVersion); + data.bIgnoreVersion=(data.bNewVersion && data.newVersion<=remindedVersion); + } + { + wchar_t languages[100]={0}; + CString language2=GetSettingString(L"Language"); + if (!language2.IsEmpty()) + { + Strcpy(languages,_countof(languages)-1,language2); + } + else + { + ULONG size=0; + ULONG len=_countof(languages); + GetUserPreferredUILanguages(MUI_LANGUAGE_NAME,&size,languages,&len); + } + + bool bNewLanguage=false; + for (wchar_t *lang=languages;*lang;lang+=Strlen(lang)+1) + { + if (_wcsicmp(lang,L"en")==0 || _wcsnicmp(lang,L"en-",3)==0) + break; // English + DWORD dllVersion=0, dllBuild=0; + HINSTANCE resInstance=LoadTranslationDll(lang); + if (resInstance) + { + dllVersion=GetVersionEx(resInstance,&dllBuild); + FreeLibrary(resInstance); + } + + DWORD newVersion=0, newBuild=0; + for (std::vector::const_iterator it=data.languages.begin();it!=data.languages.end();++it) + { + if (_wcsicmp(it->language,lang)==0) + { + newVersion=it->version; + newBuild=it->build; + break; + } + } + if (newVersion==0) + continue; + + if (newVersion>dllVersion || (newVersion==dllVersion && newBuild>dllBuild)) + { + // a new DLL for this language exists + data.bNewLanguage=true; + data.newLanguage=lang; + data.encodedLangVersion=(newVersion&0xFFFF0000)|((newVersion&0xFF)<<8)|(newBuild&0xFF); + DWORD remindedVersion; + if (regKey.QueryDWORDValue(L"RemindedLangVersion",remindedVersion)!=ERROR_SUCCESS) + remindedVersion=0; + data.bIgnoreLanguage=(data.encodedLangVersion<=remindedVersion); + } + break; + } + } + + data.bValid=true; + if (params.check==CHECK_UPDATE) + { + params.callback(data); + g_bCheckingVersion=false; + return 1; + } + if ((data.bNewVersion && !data.bIgnoreVersion) || (data.bNewLanguage && !data.bIgnoreLanguage)) + params.callback(data); + g_bCheckingVersion=false; + return 0; +} + +DWORD CheckForNewVersion( HWND owner, TSettingsComponent component, TVersionCheck check, tNewVersionCallback callback ) +{ + if (g_bCheckingVersion) return 0; + + if (check==CHECK_UPDATE) + { + g_bCheckingVersion=true; + VersionCheckParams *params=new VersionCheckParams; + params->check=check; + params->component=component; + params->callback=callback; + params->progress=NULL; + + if (!owner) + return ThreadVersionCheck(params); + + CProgressDlg progress; + params->progress=&progress; + progress.Create(owner,LoadStringEx(IDS_PROGRESS_TITLE_CHECK)); + + HANDLE hThread=CreateThread(NULL,0,ThreadVersionCheck,params,0,NULL); + + while (1) + { + DWORD wait=MsgWaitForMultipleObjects(1,&hThread,FALSE,INFINITE,QS_ALLINPUT); + if (wait!=WAIT_OBJECT_0+1) + break; + MSG msg; + while (PeekMessage(&msg,0,0,0,PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + progress.DestroyWindow(); + DWORD exit; + if (!GetExitCodeThread(hThread,&exit)) + exit=0; + CloseHandle(hThread); + return exit; + } + else + { + DWORD buildTime=0; + { + // skip the update if the update component is not found + wchar_t path[_MAX_PATH]; + GetModuleFileName(_AtlBaseModule.GetModuleInstance(),path,_countof(path)); + PathRemoveFileSpec(path); + PathAppend(path,L"ClassicShellUpdate.exe"); + + WIN32_FILE_ATTRIBUTE_DATA attr; + if (!GetFileAttributesEx(path,GetFileExInfoStandard,&attr)) + return 0; + + buildTime=(DWORD)(((((ULONGLONG)attr.ftCreationTime.dwHighDateTime)<<32)|attr.ftCreationTime.dwLowDateTime)/TIME_DIVISOR); // in 0.01 hours + } + + ULONGLONG curTimeL; + GetSystemTimeAsFileTime((FILETIME*)&curTimeL); + DWORD curTime=(DWORD)(curTimeL/TIME_DIVISOR); // in 0.01 hours + if (curTime-buildTime>24*365*TIME_PRECISION) + return 0; // the build is more than a year old, don't do automatic updates + + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicShell")!=ERROR_SUCCESS) + regKey.Create(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicShell"); + + DWORD lastVersion; + if (regKey.QueryDWORDValue(L"LastUpdateVersion",lastVersion)!=ERROR_SUCCESS) + lastVersion=0; + if (lastVersion==GetVersionEx(g_Instance)) + { + DWORD lastTime; + if (regKey.QueryDWORDValue(L"LastUpdateTime",lastTime)!=ERROR_SUCCESS) + lastTime=0; + if ((int)(curTime-lastTime)<168*TIME_PRECISION) + return 0; // check weekly + } + + // check the Update setting (uses the current value in the registry, not the one from memory + { + CRegKey regSettings, regSettingsUser, regPolicy, regPolicyUser; + bool bUpgrade=OpenSettingsKeys(COMPONENT_SHARED,regSettings,regSettingsUser,regPolicy,regPolicyUser); + + CSetting settings[]={ + {L"Update",CSetting::TYPE_BOOL,0,0,1}, + {NULL} + }; + + settings[0].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser); + + if (!GetSettingBool(settings[0])) + return 0; + } + + VersionCheckParams *params=new VersionCheckParams; + params->check=check; + params->component=component; + params->callback=callback; + params->progress=NULL; + + g_bCheckingVersion=true; + if (check==CHECK_AUTO_WAIT) + return ThreadVersionCheck(params); + HANDLE hThread=CreateThread(NULL,0,ThreadVersionCheck,params,0,NULL); + CloseHandle(hThread); + return hThread!=NULL?1:0; + } +} + +static CString LoadStringEx( HMODULE hModule, int stringId, int langId ) +{ + CString res; + + HRSRC hrsrc=FindResourceEx(hModule,RT_STRING,MAKEINTRESOURCE((stringId>>4)+1),(WORD)langId); + if (!hrsrc) return res; + HGLOBAL hglb=LoadResource(hModule,hrsrc); + if (!hglb) return res; + WORD *data=(WORD*)LockResource(hglb); + if (!data) return res; + + stringId&=15; + for (int i=0;i0) + { + std::vector signerInfo(len); + CMSG_SIGNER_INFO *pSignerInfo=(CMSG_SIGNER_INFO*)&signerInfo[0]; + if (CryptMsgGetParam(hMsg,CMSG_SIGNER_INFO_PARAM,0,pSignerInfo,&len)) + { + CERT_INFO certInfo; + certInfo.Issuer=pSignerInfo->Issuer; + certInfo.SerialNumber=pSignerInfo->SerialNumber; + PCCERT_CONTEXT pCertContext=CertFindCertificateInStore(hStore,X509_ASN_ENCODING|PKCS_7_ASN_ENCODING,0,CERT_FIND_SUBJECT_CERT,&certInfo,NULL); + if (pCertContext) + { + len=CertGetNameString(pCertContext,CERT_NAME_SIMPLE_DISPLAY_TYPE,0,NULL,NULL,0); + if (len>1) + { + wchar_t *buf=signerName.GetBuffer(len-1); + if (buf) + { + DWORD res=CertGetNameString(pCertContext,CERT_NAME_SIMPLE_DISPLAY_TYPE,0,NULL,buf,len); + signerName.ReleaseBufferSetLength(len-1); + if (!res) signerName.Empty(); + } + +#ifdef UPDATE_LOG + LogToFile(UPDATE_LOG,L"Signer: '%s', '%s'",signer,signerName); +#endif + } + else + { +#ifdef UPDATE_LOG + LogToFile(UPDATE_LOG,L"CertGetNameString failed"); +#endif + } + } + else + { +#ifdef UPDATE_LOG + LogToFile(UPDATE_LOG,L"CertFindCertificateInStore failed"); +#endif + } + } + else + { +#ifdef UPDATE_LOG + LogToFile(UPDATE_LOG,L"CryptMsgGetParam2 failed"); +#endif + } + } + else + { +#ifdef UPDATE_LOG + LogToFile(UPDATE_LOG,L"CryptMsgGetParam1 failed"); +#endif + } + if (hStore) CertCloseStore(hStore,0); + if (hMsg) CryptMsgClose(hMsg); + } + else + { +#ifdef UPDATE_LOG + LogToFile(UPDATE_LOG,L"CryptQueryObject failed"); +#endif + } + + return (signerName==signer); +} + +void VersionData::Clear( void ) +{ + bValid=false; + newVersion=encodedLangVersion=0; + downloadUrl.Empty(); + downloadSigner.Empty(); + news.Empty(); + updateLink.Empty(); + languageLink.Empty(); + altUrl.Empty(); + bNewVersion=bIgnoreVersion=bNewLanguage=bIgnoreLanguage=false; + newLanguage.Empty(); + for (std::vector::iterator it=languages.begin();it!=languages.end();++it) + if (it->bitmap) + DeleteObject(it->bitmap); + languages.clear(); +} + +void VersionData::Swap( VersionData &data ) +{ + std::swap(bValid,data.bValid); + std::swap(newVersion,data.newVersion); + std::swap(encodedLangVersion,data.encodedLangVersion); + std::swap(downloadUrl,data.downloadUrl); + std::swap(downloadSigner,data.downloadSigner); + std::swap(news,data.news); + std::swap(updateLink,data.updateLink); + std::swap(languageLink,data.languageLink); + std::swap(altUrl,data.altUrl); + std::swap(bNewVersion,data.bNewVersion); + std::swap(bIgnoreVersion,data.bIgnoreVersion); + std::swap(bNewLanguage,data.bNewLanguage); + std::swap(bIgnoreLanguage,data.bIgnoreLanguage); + std::swap(newLanguage,data.newLanguage); + std::swap(languages,data.languages); +} + +VersionData::TLoadResult VersionData::Load( const wchar_t *fname, bool bLoadFlags ) +{ + Clear(); + if (!VerifyDigitalCertificate(fname,L"Ivaylo Beltchev")) + return LOAD_BAD_FILE; + + HMODULE hModule=LoadLibraryEx(fname,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (!hModule) return LOAD_BAD_FILE; + + if (GetVersionEx(hModule)!=GetVersionEx(g_Instance)) + { + FreeLibrary(hModule); + return LOAD_BAD_VERSION; + } + + wchar_t defLang[100]=L""; + { + CRegKey regKeyLng; + if (regKeyLng.Open(HKEY_LOCAL_MACHINE,L"Software\\IvoSoft\\ClassicShell",KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + ULONG size=_countof(defLang); + if (regKeyLng.QueryStringValue(L"DefaultLanguage",defLang,&size)!=ERROR_SUCCESS) + defLang[0]=0; + } + } + + const int DEFAULT_LANGUAGE=0x409; + + int defLangId; + if (!defLang[0] || !GetLocaleInfoEx(defLang,LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER,(LPWSTR)&defLangId,4)) + defLangId=DEFAULT_LANGUAGE; + + downloadUrl=LoadStringEx(hModule,IDS_INSTALL_URL,defLangId); + // these are always in en-US + downloadSigner=LoadStringEx(hModule,IDS_INSTALL_SIGNER,DEFAULT_LANGUAGE); + CString strVer=LoadStringEx(hModule,IDS_VERSION,defLangId); + if (strVer.IsEmpty()) + strVer=LoadStringEx(hModule,IDS_VERSION,DEFAULT_LANGUAGE); + updateLink=LoadStringEx(hModule,IDS_UPDATE_LINK,DEFAULT_LANGUAGE); + languageLink=LoadStringEx(hModule,IDS_LANGUAGE_LINK,DEFAULT_LANGUAGE); + altUrl=LoadStringEx(hModule,IDS_ALT_URL,DEFAULT_LANGUAGE); + + int v1, v2, v3; + if (!downloadUrl.IsEmpty() && swscanf_s(strVer,L"%d.%d.%d",&v1,&v2,&v3)==3) + { + newVersion=(v1<<24)|(v2<<16)|v3; + news=LoadStringEx(hModule,IDS_NEWS,defLangId); + if (news.IsEmpty()) + news=LoadStringEx(hModule,IDS_NEWS,DEFAULT_LANGUAGE); + + EnumResourceLanguages(hModule,RT_STRING,MAKEINTRESOURCE((IDS_LNG_URL>>4)+1),EnumStringLanguages,(LONG_PTR)this); + for (std::vector::iterator it=languages.begin();it!=languages.end();++it) + it->bitmap=(HBITMAP)LoadImage(hModule,MAKEINTRESOURCE(it->languageId),IMAGE_BITMAP,22,27,LR_CREATEDIBSECTION); + } + + FreeLibrary(hModule); + + if (newVersion && !downloadUrl.IsEmpty() && !news.IsEmpty()) + return LOAD_OK; + Clear(); + return LOAD_ERROR; +} + +struct DownloadFileParams +{ + // input + const wchar_t *url; + const wchar_t *signer; + DWORD hash; + const wchar_t *path; + CString fname; // file name on input, full path on output + CProgressDlg *progress; + bool bAcceptCached; + TSettingsComponent component; + + // output + TDownloadResult downloadRes; + int saveRes; + bool valid; +}; + +static DWORD WINAPI ThreadDownloadFile( void *param ) +{ + DownloadFileParams ¶ms=*(DownloadFileParams*)param; + param=NULL; + params.valid=false; + params.saveRes=0; + + std::vector buf; + params.downloadRes=DownloadFile(params.url,buf,params.fname.IsEmpty()?¶ms.fname:NULL,0,params.bAcceptCached,params.progress,params.component); + if (params.downloadRes==DOWNLOAD_CANCEL || params.downloadRes>=DOWNLOAD_FIRST_ERROR) + return 0; + + params.valid=!buf.empty(); + if (!params.valid) + return 0; + + // validate hash + if (params.hash) + { + if (params.progress) + params.progress->SetText(LoadStringEx(IDS_PROGRESS_VERIFY)); + + params.valid=(CalcFNVHash(&buf[0],(int)buf.size(),FNV_HASH0)==params.hash); + if (!params.valid) + return 0; + } + + // save + if (params.progress) + { + params.progress->SetText(LoadStringEx(IDS_PROGRESS_SAVE)); + params.progress->EnableCancel(false); + params.progress->SetProgress(-1); + } + wchar_t fname[_MAX_PATH]; + Sprintf(fname,_countof(fname),L"%s\\%s",params.path,params.fname); + params.fname=fname; + params.saveRes=SaveFile(fname,buf); + if (params.saveRes) + return 0; + + // validate signer + if (params.signer) + { + if (params.progress) + params.progress->SetText(LoadStringEx(IDS_PROGRESS_VERIFY)); + params.valid=VerifyDigitalCertificate(fname,params.signer); + if (!params.valid) + { + DeleteFile(fname); + return 0; + } + } + + return 0; +} + +DWORD DownloadLanguageDll( HWND owner, TSettingsComponent component, const LanguageVersionData &data, CString &error ) +{ + // download file + wchar_t path[_MAX_PATH]=L"%ALLUSERSPROFILE%\\ClassicShell\\Languages"; + DoEnvironmentSubst(path,_countof(path)); + SHCreateDirectory(NULL,path); + wchar_t fname[_MAX_PATH]; + Sprintf(fname,_countof(fname),L"%s.dll",data.language); + + CProgressDlg progress; + progress.Create(owner,LoadStringEx(IDS_PROGRESS_TITLE_DOWNLOAD)); + + DownloadFileParams params; + params.url=data.url; + params.signer=NULL; + params.hash=data.hash; + params.path=path; + params.fname=fname; + params.progress=&progress; + params.bAcceptCached=true; + params.component=component; + + HANDLE hThread=CreateThread(NULL,0,ThreadDownloadFile,¶ms,0,NULL); + + while (1) + { + DWORD wait=MsgWaitForMultipleObjects(1,&hThread,FALSE,INFINITE,QS_ALLINPUT); + if (wait!=WAIT_OBJECT_0+1) + break; + MSG msg; + while (PeekMessage(&msg,0,0,0,PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + progress.DestroyWindow(); + CloseHandle(hThread); + + if (params.downloadRes==DOWNLOAD_CANCEL) + return 2; + if (params.downloadRes==DOWNLOAD_INTERNET) + { + error=LoadStringEx(IDS_INTERNET_FAIL); + return 0; + } + else if (params.downloadRes==DOWNLOAD_START) + { + error=LoadStringEx(IDS_INITIATE_FAIL); + return 0; + } + else if (params.downloadRes==DOWNLOAD_FAIL) + { + error=LoadStringEx(IDS_LANG_DOWNLOAD_FAIL); + return 0; + } + + if (params.saveRes) + { + wchar_t msg[256]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,NULL,params.saveRes,0,msg,_countof(msg),NULL); + error.Format(LoadStringEx(IDS_LANG_SAVE_FAIL),params.fname); + error+="\r\n"; + error+=msg; + return 0; + } + + if (!params.valid) + { + error=LoadStringEx(IDS_LANG_DOWNLOAD_FAIL); + return 0; + } + + return 1; +} + +DWORD DownloadNewVersion( HWND owner, TSettingsComponent component, const wchar_t *url, const wchar_t *signer, CString &fname, CString &error ) +{ + CComString pPath; + if (FAILED(SHGetKnownFolderPath(FOLDERID_Downloads,0,NULL,&pPath)) || !pPath) + { + if (FAILED(SHGetKnownFolderPath(FOLDERID_Documents,0,NULL,&pPath)) || !pPath) + { + if (FAILED(SHGetKnownFolderPath(FOLDERID_Desktop,0,NULL,&pPath)) || !pPath) + { + error=LoadStringEx(IDS_INST_DOWNLOAD_FAIL); + return 0; + } + } + } + + CProgressDlg progress; + progress.Create(owner,LoadStringEx(IDS_PROGRESS_TITLE_DOWNLOAD)); + + DownloadFileParams params; + params.url=url; + params.signer=signer; + params.hash=0; + params.path=pPath; + params.progress=&progress; + params.bAcceptCached=true; + params.component=component; + + HANDLE hThread=CreateThread(NULL,0,ThreadDownloadFile,¶ms,0,NULL); + + while (1) + { + DWORD wait=MsgWaitForMultipleObjects(1,&hThread,FALSE,INFINITE,QS_ALLINPUT); + if (wait!=WAIT_OBJECT_0+1) + break; + MSG msg; + while (PeekMessage(&msg,0,0,0,PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + progress.DestroyWindow(); + CloseHandle(hThread); + + if (params.downloadRes==DOWNLOAD_CANCEL) + return 2; + if (params.downloadRes==DOWNLOAD_INTERNET) + { + error=LoadStringEx(IDS_INTERNET_FAIL); + return 0; + } + else if (params.downloadRes==DOWNLOAD_START) + { + error=LoadStringEx(IDS_INITIATE_FAIL); + return 0; + } + else if (params.downloadRes==DOWNLOAD_FAIL) + { + error=LoadStringEx(IDS_INST_DOWNLOAD_FAIL); + return 0; + } + + if (params.saveRes) + { + wchar_t msg[256]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,NULL,params.saveRes,0,msg,_countof(msg),NULL); + error.Format(LoadStringEx(IDS_INST_SAVE_FAIL),params.fname); + error+="\r\n"; + error+=msg; + return 0; + } + + if (!params.valid) + { + error=LoadStringEx(IDS_INST_DOWNLOAD_FAIL); + return 0; + } + + fname=params.fname; + return 1; +} diff --git a/ClassicShellSrc/ClassicShellLib/DownloadHelper.h b/ClassicShellSrc/ClassicShellLib/DownloadHelper.h new file mode 100644 index 0000000..69be3d8 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/DownloadHelper.h @@ -0,0 +1,71 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#include + +enum TVersionCheck +{ + CHECK_AUTO, + CHECK_AUTO_WAIT, + CHECK_UPDATE, +}; + +enum TSettingsComponent; + +struct LanguageVersionData +{ + CString language; + CString url; + DWORD version; + DWORD build; + DWORD hash; + bool bBasic; + WORD languageId; + HBITMAP bitmap; + + LanguageVersionData( void ) { bBasic=false; bitmap=NULL; } +}; + +struct VersionData +{ + bool bValid; + DWORD newVersion; + DWORD encodedLangVersion; + CString downloadUrl; + CString downloadSigner; + CString news; + CString updateLink; + CString languageLink; + CString altUrl; + bool bNewVersion; + bool bIgnoreVersion; + bool bNewLanguage; + bool bIgnoreLanguage; + CString newLanguage; + std::vector languages; + + ~VersionData( void ) { Clear(); } + void Clear( void ); + void Swap( VersionData &data ); + + enum TLoadResult + { + LOAD_OK, + LOAD_ERROR, // the file is missing some data + LOAD_BAD_VERSION, // the version is wrong + LOAD_BAD_FILE, // the file is corrupted + }; + + TLoadResult Load( const wchar_t *fname, bool bLoadFlags ); +private: + void operator=( const VersionData& ); +}; + +typedef void (*tNewVersionCallback)( VersionData &data ); + +// 0 - fail, 1 - success, 2 - cancel +DWORD CheckForNewVersion( HWND owner, TSettingsComponent component, TVersionCheck check, tNewVersionCallback callback ); +DWORD DownloadLanguageDll( HWND owner, TSettingsComponent component, const LanguageVersionData &data, CString &error ); +DWORD DownloadNewVersion( HWND owner, TSettingsComponent component, const wchar_t *url, const wchar_t *signer, CString &fname, CString &error ); diff --git a/ClassicShellSrc/ClassicShellLib/FNVHash.cpp b/ClassicShellSrc/ClassicShellLib/FNVHash.cpp new file mode 100644 index 0000000..bf0c199 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/FNVHash.cpp @@ -0,0 +1,28 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include +#include "FNVHash.h" +#include "StringUtils.h" + +// FNV hash algorithm as described here: http://www.isthe.com/chongo/tech/comp/fnv/index.html + +// Calculate FNV hash for a memory buffer +unsigned int CalcFNVHash( const void *buf, int len, unsigned int hash ) +{ + for (int i=0;i pLink; + HRESULT hr=pLink.CoCreateInstance(CLSID_ShellLink); + if (FAILED(hr)) return false; + pLink->SetPath(source); + CComQIPtr pFile=pLink; + if (!pFile) return false; + hr=pFile->Save(path,TRUE); + if (FAILED(hr)) return false; + } + + // create desktop.ini + Sprintf(path,_countof(path),L"%s\\desktop.ini",fname); + HANDLE f=CreateFile(path,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,NULL); + if (f==INVALID_HANDLE_VALUE) return false; + const char *desktopIni="[.ShellClassInfo]\r\nCLSID2={0AFACED1-E828-11D1-9187-B532F1E9575D}\r\nFlags=2\r\n"; + DWORD q; + WriteFile(f,desktopIni,Strlen(desktopIni),&q,NULL); + CloseHandle(f); + return true; +} + +void DeleteFakeFolder( const wchar_t *fname ) +{ + wchar_t path[_MAX_PATH]; + Sprintf(path,_countof(path),L"%s\\target.lnk",fname); + BOOL res; + res=SetFileAttributes(path,GetFileAttributes(path)&~FILE_ATTRIBUTE_READONLY); + res=DeleteFile(path); + Sprintf(path,_countof(path),L"%s\\desktop.ini",fname); + res=SetFileAttributes(path,GetFileAttributes(path)&~FILE_ATTRIBUTE_READONLY); + res=DeleteFile(path); + res=SetFileAttributes(fname,GetFileAttributes(fname)&~FILE_ATTRIBUTE_READONLY); + res=RemoveDirectory(fname); +} + +bool IsFakeFolder( const wchar_t *fname ) +{ + wchar_t path[_MAX_PATH]; + Sprintf(path,_countof(path),L"%s\\target.lnk",fname); + if (GetFileAttributes(path)!=INVALID_FILE_ATTRIBUTES) + { + Sprintf(path,_countof(path),L"%s\\desktop.ini",fname); + DWORD attrib=GetFileAttributes(path); + if (attrib!=INVALID_FILE_ATTRIBUTES && (attrib&FILE_ATTRIBUTE_SYSTEM)) + return true; + } + return false; +} diff --git a/ClassicShellSrc/ClassicShellLib/FileHelper.h b/ClassicShellSrc/ClassicShellLib/FileHelper.h new file mode 100644 index 0000000..1c9c270 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/FileHelper.h @@ -0,0 +1,8 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +bool CreateFakeFolder( const wchar_t *source, const wchar_t *fname ); +void DeleteFakeFolder( const wchar_t *fname ); +bool IsFakeFolder( const wchar_t *fname ); diff --git a/ClassicShellSrc/ClassicShellLib/IatHookHelper.cpp b/ClassicShellSrc/ClassicShellLib/IatHookHelper.cpp new file mode 100644 index 0000000..faa0b4f --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/IatHookHelper.cpp @@ -0,0 +1,143 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include +#include "IatHookHelper.h" +#include "Assert.h" + +struct ImgDelayDescr +{ + DWORD grAttrs; // attributes + DWORD rvaDLLName; // RVA to dll name + DWORD rvaHmod; // RVA of module handle + DWORD rvaIAT; // RVA of the IAT + DWORD rvaINT; // RVA of the INT + DWORD rvaBoundIAT; // RVA of the optional bound IAT + DWORD rvaUnloadIAT; // RVA of optional copy of original IAT + DWORD dwTimeStamp; // 0 if not bound, O.W. date/time stamp of DLL bound to (Old BIND) +}; + +static void *PtrFromRva( IMAGE_DOS_HEADER *dosHeader, size_t offset ) +{ + return (BYTE*)dosHeader+offset; +} + +static IatHookData *g_IatHooks; +static int g_IatHookCount; + +const int MAX_IAT_HOOKS=4096/sizeof(IatHookData); + +void InitializeIatHooks( void ) +{ + Assert(!g_IatHooks); + g_IatHooks=(IatHookData*)VirtualAlloc(NULL,4096,MEM_COMMIT,PAGE_EXECUTE_READWRITE); + g_IatHookCount=0; +} + +void ClearIatHooks( void ) +{ + if (!g_IatHooks) return; + for (int i=0;iu1.Function;origThunk++,thunk++) + { + if (origThunk->u1.Ordinal&IMAGE_ORDINAL_FLAG) + { + if (IS_INTRESOURCE(targetProc) && IMAGE_ORDINAL(origThunk->u1.Ordinal)==(WORD)targetProc) + break; + } + else + { + IMAGE_IMPORT_BY_NAME *import=(IMAGE_IMPORT_BY_NAME*)PtrFromRva(dosHeader,origThunk->u1.AddressOfData); + if (!IS_INTRESOURCE(targetProc) && strcmp(targetProc,(char*)import->Name)==0) + break; + } + } + if (origThunk->u1.Function) + { + IatHookData *hook=g_IatHooks+g_IatHookCount; + g_IatHookCount++; + hook->jump[0]=hook->jump[1]=0x90; // NOP + hook->jump[2]=0xFF; hook->jump[3]=0x25; // JUMP +#ifdef _WIN64 + hook->jumpOffs=0; +#else + hook->jumpOffs=(DWORD)(hook)+8; +#endif + hook->newProc=newProc; + hook->oldProc=(void*)thunk->u1.Function; + hook->thunk=thunk; + DWORD oldProtect; + VirtualProtect(&thunk->u1.Function,sizeof(void*),PAGE_READWRITE,&oldProtect); + thunk->u1.Function=(DWORD_PTR)hook; + VirtualProtect(&thunk->u1.Function,sizeof(void*),oldProtect,&oldProtect); + return hook; + } + return NULL; +} + +IatHookData *SetIatHook( HMODULE hPatchedModule, const char *targetModule, const char *targetProc, void *newProc ) +{ + ATLASSERT(g_IatHooks); + if (g_IatHookCount>=MAX_IAT_HOOKS) return NULL; + IMAGE_DOS_HEADER *dosHeader=(IMAGE_DOS_HEADER*)hPatchedModule; + IMAGE_NT_HEADERS *ntHeader=(IMAGE_NT_HEADERS*)PtrFromRva(dosHeader,dosHeader->e_lfanew); + if (ntHeader->Signature!=IMAGE_NT_SIGNATURE) return NULL; + + IMAGE_IMPORT_DESCRIPTOR *importDescriptor=(IMAGE_IMPORT_DESCRIPTOR*)PtrFromRva(dosHeader,ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + + for (;importDescriptor->Characteristics!=0;importDescriptor++) + { + const char *dllName=(char*)PtrFromRva(dosHeader,importDescriptor->Name); + if (_stricmp(dllName,targetModule)!=0) continue; + + if (!importDescriptor->FirstThunk || !importDescriptor->OriginalFirstThunk) break; + + return SetIatHook(dosHeader,importDescriptor->FirstThunk,importDescriptor->OriginalFirstThunk,targetProc,newProc); + } + + ImgDelayDescr *delayDescriptor=(ImgDelayDescr*)PtrFromRva(dosHeader,ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress); + + for (;delayDescriptor->rvaDLLName!=0;delayDescriptor++) + { + const char *dllName=(char*)PtrFromRva(dosHeader,delayDescriptor->rvaDLLName); + if (_stricmp(dllName,targetModule)!=0) continue; + + if (!delayDescriptor->rvaIAT || !delayDescriptor->rvaINT) break; + + return SetIatHook(dosHeader,delayDescriptor->rvaIAT,delayDescriptor->rvaINT,targetProc,newProc); + } + return NULL; +} + +void ClearIatHook( IatHookData *hook ) +{ + if (!hook || !hook->jump[0]) return; + if (hook->thunk->u1.Function==(DWORD_PTR)hook) + { + // the hook was untouched by anybody else + DWORD oldProtect; + VirtualProtect(&hook->thunk->u1.Function,sizeof(void*),PAGE_READWRITE,&oldProtect); + void *cex=InterlockedCompareExchangePointer((void**)&hook->thunk->u1.Function,hook->oldProc,hook); + VirtualProtect(&hook->thunk->u1.Function,sizeof(void*),oldProtect,&oldProtect); + if (cex==hook) + { + hook->jump[0]=0; + return; // successfully replaced the original function + } + } + // failed to replace the original function, leave behind the thunk + hook->newProc=hook->oldProc; +} diff --git a/ClassicShellSrc/ClassicShellLib/IatHookHelper.h b/ClassicShellSrc/ClassicShellLib/IatHookHelper.h new file mode 100644 index 0000000..7f7027c --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/IatHookHelper.h @@ -0,0 +1,18 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +struct IatHookData +{ + unsigned char jump[4]; // jump instruction 0x90, 0x90, 0xFF, 0x25 + DWORD jumpOffs; // jump instruction offset + void *newProc; // the address of the new proc + void *oldProc; // the address of the old proc + IMAGE_THUNK_DATA *thunk; // the IAT thunk +}; + +void InitializeIatHooks( void ); +IatHookData *SetIatHook( HMODULE hPatchedModule, const char *targetModule, const char *targetProc, void *newProc ); +void ClearIatHook( IatHookData *hook ); +void ClearIatHooks( void ); diff --git a/ClassicShellSrc/ClassicShellLib/Instance.cpp b/ClassicShellSrc/ClassicShellLib/Instance.cpp new file mode 100644 index 0000000..0cdcc6c --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/Instance.cpp @@ -0,0 +1,6 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include + +HINSTANCE g_Instance; diff --git a/ClassicShellSrc/ClassicShellLib/LanguageSettingsHelper.cpp b/ClassicShellSrc/ClassicShellLib/LanguageSettingsHelper.cpp new file mode 100644 index 0000000..72c3e5f --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/LanguageSettingsHelper.cpp @@ -0,0 +1,600 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include +#include "resource.h" +#include "Settings.h" +#include "SettingsUIHelper.h" +#include "ResourceHelper.h" +#include "ComHelper.h" +#include "FNVHash.h" +#include "StringUtils.h" +#include "Translations.h" +#include "DownloadHelper.h" +#include +#include +#include + +int g_LanguageIDs[]={ + 0x0401, + 0x0402, + 0x0403, + 0x0405, + 0x0406, + 0x0407, + 0x0408, + 0x0409, + 0x0C0A, + 0x0425, + 0x0429, + 0x040B, + 0x040C, + 0x0491, + 0x040D, + 0x041A, + 0x040E, + 0x040F, + 0x0410, + 0x0411, + 0x0412, + 0x0427, + 0x0426, + 0x0414, + 0x0413, + 0x0415, + 0x0416, + 0x0816, + 0x0418, + 0x0419, + 0x041B, + 0x0424, + 0x081A, + 0x041D, + 0x041E, + 0x041F, + 0x0422, + 0x0804, + 0x0C04, + 0x0404, +}; + +int g_LanguageIDCount=_countof(g_LanguageIDs); + +class CLanguageSettingsDlg: public CResizeableDlg +{ +public: + BEGIN_MSG_MAP( CLanguageSettingsDlg ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + MESSAGE_HANDLER( WM_DESTROY, OnDestroy ) + MESSAGE_HANDLER( WM_SIZE, OnSize ) + COMMAND_ID_HANDLER( IDC_BUTTONCHECK, OnCheckUpdates ) + NOTIFY_HANDLER( IDC_LISTLANGUAGE, LVN_ITEMCHANGED, OnSelChange ) + NOTIFY_HANDLER( IDC_LISTLANGUAGE, LVN_ITEMCHANGING, OnSelChanging ) + NOTIFY_HANDLER( IDC_LISTLANGUAGE, NM_CUSTOMDRAW, OnCustomDraw ) + NOTIFY_HANDLER( IDC_LINKDOWNLOAD, NM_CLICK, OnDownload ) + END_MSG_MAP() + + BEGIN_RESIZE_MAP + RESIZE_CONTROL(IDC_LISTLANGUAGE,MOVE_SIZE_X|MOVE_SIZE_Y) + RESIZE_CONTROL(IDC_BUTTONCHECK,MOVE_MOVE_Y) + RESIZE_CONTROL(IDC_LINKDOWNLOAD,MOVE_SIZE_X|MOVE_MOVE_Y) + END_RESIZE_MAP + + void SetGroup( CSetting *pGroup ); + void SetComponent( TSettingsComponent component ) { m_Component=component; } + +protected: + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnCheckUpdates( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnSelChange( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnSelChanging( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnDownload( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + +private: + CSetting *m_pSetting; + TSettingsComponent m_Component; + CWindow m_Tooltip; + HIMAGELIST m_ImageList; + bool m_bLargeFlags; + bool m_bLocked; + + struct LangInfo + { + CString name; + int id; + int image; + bool operator<( const LangInfo &info ) { return _wcsicmp(name,info.name)<0; } + }; + std::vector m_LanguageIDs; // the order matches the items in the listbox + static VersionData s_VersionData; + static void NewVersionCallback( VersionData &data ); + + void UpdateFlags( void ); + void UpdateLink( const wchar_t *language ); + + void AddFlag( const wchar_t *langName, int langId, HBITMAP bmp ); +}; + +VersionData CLanguageSettingsDlg::s_VersionData; + +void CLanguageSettingsDlg::AddFlag( const wchar_t *langName, int langId, HBITMAP bmp ) +{ + std::vector::iterator it=m_LanguageIDs.begin()+1; + int idx=1; + for (;idx<(int)m_LanguageIDs.size();idx++) + { + if (_wcsicmp(langName,m_LanguageIDs[idx].name)<=0) + break; + } + if (idx==(int)m_LanguageIDs.size() || _wcsicmp(langName,m_LanguageIDs[idx].name)<0) + { + LangInfo info; + info.id=langId; + info.image=ImageList_AddMasked(m_ImageList,bmp,0xFF00FF); + info.name=langName; + m_LanguageIDs.insert(m_LanguageIDs.begin()+idx,info); + + CWindow list=GetDlgItem(IDC_LISTLANGUAGE); + wchar_t name[256]; + GetLocaleInfo(info.id,LOCALE_SLANGUAGE,name,_countof(name)); + wchar_t text[256]; + Sprintf(text,_countof(text),L"%s - %s",info.name,name); + LVITEM item={LVIF_IMAGE|LVIF_TEXT}; + item.iItem=idx; + item.iImage=info.image; + item.pszText=text; + ListView_InsertItem(list,&item); + } +} + +void CLanguageSettingsDlg::UpdateFlags( void ) +{ + // add flags from s_VersionData + for (std::vector::const_iterator it=s_VersionData.languages.begin();it!=s_VersionData.languages.end();++it) + { + if (it->bitmap) + { + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=m_bLargeFlags?32:24; + bi.bmiHeader.biHeight=m_bLargeFlags?16:11; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + + HDC hdc=CreateCompatibleDC(NULL); + HBITMAP bmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,NULL,NULL,0); + HGDIOBJ bmp0=SelectObject(hdc,bmp); + HDC hsrc=CreateCompatibleDC(hdc); + HGDIOBJ bmp02=SelectObject(hsrc,it->bitmap); + SetDCBrushColor(hdc,0xFF00FF); + RECT rc={0,0,bi.bmiHeader.biWidth,bi.bmiHeader.biHeight}; + FillRect(hdc,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + if (m_bLargeFlags) + BitBlt(hdc,3,0,22,16,hsrc,0,11,SRCCOPY); + else + BitBlt(hdc,2,0,16,11,hsrc,0,0,SRCCOPY); + SelectObject(hsrc,bmp02); + DeleteDC(hsrc); + SelectObject(hdc,bmp0); + DeleteDC(hdc); + AddFlag(it->language,it->languageId,bmp); + DeleteObject(bmp); + } + } + + // add flags from dlls + for (int pass=0;pass<2;pass++) + { + wchar_t path[_MAX_PATH]; + if (pass==0) + { + GetModuleFileName(g_Instance,path,_countof(path)); + *PathFindFileName(path)=0; + } + else + { + Strcpy(path,_countof(path),L"%ALLUSERSPROFILE%\\ClassicShell\\Languages"); + DoEnvironmentSubst(path,_countof(path)); + } + + CWindow list=GetDlgItem(IDC_LISTLANGUAGE); + + wchar_t find[_MAX_PATH]; + Sprintf(find,_countof(find),L"%s\\*.dll",path); + WIN32_FIND_DATA data; + HANDLE h=FindFirstFile(find,&data); + while (h!=INVALID_HANDLE_VALUE) + { + if (!(data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && wcschr(data.cFileName,'-')) + { + wchar_t fname[_MAX_PATH]; + Sprintf(fname,_countof(fname),L"%s\\%s",path,data.cFileName); + wchar_t language[_MAX_PATH]; + Strcpy(language,_countof(language),data.cFileName); + PathRemoveExtension(language); + + bool bFound=false; + for (std::vector::const_iterator it=m_LanguageIDs.begin();it!=m_LanguageIDs.end();++it) + { + if (_wcsicmp(it->name,language)==0) + { + bFound=true; + break; + } + } + int langId=0; + if (!bFound && GetLocaleInfoEx(language,LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER,(LPWSTR)&langId,4)) + { + HINSTANCE hModule=LoadLibraryEx(fname,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (hModule) + { + HBITMAP bmp; + if (m_bLargeFlags) + bmp=(HBITMAP)LoadImage(hModule,MAKEINTRESOURCE(1),IMAGE_BITMAP,32,16,LR_CREATEDIBSECTION); + else + bmp=(HBITMAP)LoadImage(hModule,MAKEINTRESOURCE(2),IMAGE_BITMAP,24,11,LR_CREATEDIBSECTION); + if (bmp) + { + AddFlag(language,langId,bmp); + DeleteObject(bmp); + } + FreeLibrary(hModule); + } + } + } + if (!FindNextFile(h,&data)) + { + FindClose(h); + break; + } + } + } +} + +LRESULT CLanguageSettingsDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + m_bLocked=false; + InitResize(); + EnableThemeDialogTexture(m_hWnd,ETDT_ENABLETAB); + + CWindow list=GetDlgItem(IDC_LISTLANGUAGE); + if (IsAppThemed()) + SetWindowTheme(list,L"Explorer",NULL); + HBITMAP bmp; + HDC hdc=::GetDC(NULL); + int dpi=GetDeviceCaps(hdc,LOGPIXELSY); + ::ReleaseDC(NULL,hdc); + m_bLargeFlags=dpi>=144; + if (m_bLargeFlags) + { + m_ImageList=ImageList_Create(32,16,ILC_COLOR24|ILC_MASK|(IsLanguageRTL()?ILC_MIRROR:0),0,0); + bmp=(HBITMAP)LoadImage(_AtlBaseModule.GetResourceInstance(),MAKEINTRESOURCE(IDB_FLAGS24),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION); + } + else + { + m_ImageList=ImageList_Create(24,11,ILC_COLOR24|ILC_MASK|(IsLanguageRTL()?ILC_MIRROR:0),0,0); + bmp=(HBITMAP)LoadImage(_AtlBaseModule.GetResourceInstance(),MAKEINTRESOURCE(IDB_FLAGS),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION); + } + ImageList_AddMasked(m_ImageList,bmp,0xFF00FF); + DeleteObject(bmp); + ListView_SetImageList(list,m_ImageList,LVSIL_SMALL); + RECT rc; + list.GetWindowRect(&rc); + ListView_SetExtendedListViewStyleEx(list,LVS_EX_DOUBLEBUFFER,LVS_EX_DOUBLEBUFFER); + LVCOLUMN column={LVCF_WIDTH,0,rc.right-rc.left}; + ListView_InsertColumn(list,0,&column); + SetDlgItemText(IDC_LINKDOWNLOAD,L""); + + m_LanguageIDs.resize(_countof(g_LanguageIDs)+1); + { + wchar_t languages[100]={0}; + ULONG size=0; + ULONG len=_countof(languages); + GetUserPreferredUILanguages(MUI_LANGUAGE_ID,&size,languages,&len); + wchar_t *end; + m_LanguageIDs[0].id=wcstol(languages,&end,16); + m_LanguageIDs[0].image=I_IMAGENONE; + } + + for (int i=0;i<=(int)_countof(g_LanguageIDs);i++) + { + if (i>0) + { + m_LanguageIDs[i].id=g_LanguageIDs[i-1]; + m_LanguageIDs[i].image=i-1; + } + wchar_t name[256]; + GetLocaleInfo(m_LanguageIDs[i].id,LOCALE_SNAME,name,_countof(name)); + m_LanguageIDs[i].name=name; + } + + std::sort(m_LanguageIDs.begin()+1,m_LanguageIDs.end()); + + LVITEM item={LVIF_IMAGE|LVIF_TEXT}; + for (int i=0;i<(int)m_LanguageIDs.size();i++) + { + wchar_t name[256]; + GetLocaleInfo(m_LanguageIDs[i].id,LOCALE_SLANGUAGE,name,_countof(name)); + wchar_t text[256]; + if (i==0) + Sprintf(text,_countof(text),L"%s (%s)",LoadStringEx(IDS_OS_LANGUAGE),m_LanguageIDs[i].name); + else + Sprintf(text,_countof(text),L"%s - %s",m_LanguageIDs[i].name,name); + item.iItem=i; + item.iImage=m_LanguageIDs[i].image; + item.pszText=text; + ListView_InsertItem(list,&item); + } + + // parse update.ver in data and add all flags + wchar_t path[_MAX_PATH]=L"%ALLUSERSPROFILE%\\ClassicShell\\update.ver"; + DoEnvironmentSubst(path,_countof(path)); + s_VersionData.bValid=(s_VersionData.Load(path,true)==VersionData::LOAD_OK); + + UpdateFlags(); + + m_Tooltip.Create(TOOLTIPS_CLASS,m_hWnd,NULL,NULL,WS_POPUP|TTS_NOPREFIX); + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS|TTF_IDISHWND,m_hWnd,'CLSH'}; + tool.uId=(UINT_PTR)list.m_hWnd; + tool.lpszText=L""; + m_Tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + return TRUE; +} + +LRESULT CLanguageSettingsDlg::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + m_Tooltip.Detach(); + return 0; +} + +LRESULT CLanguageSettingsDlg::OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + CResizeableDlg::OnSize(); + return 0; +} + +void CLanguageSettingsDlg::NewVersionCallback( VersionData &data ) +{ + s_VersionData.Swap(data); +} + +LRESULT CLanguageSettingsDlg::OnCheckUpdates( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + DWORD res=CheckForNewVersion(m_hWnd,m_Component,CHECK_UPDATE,NewVersionCallback); + if (res==2) return 0; + if (res) + { + UpdateFlags(); + CString language=GetSettingString(L"Language"); + CWindow list=GetDlgItem(IDC_LISTLANGUAGE); + for (int idx=0;idx<(int)m_LanguageIDs.size();idx++) + { + const wchar_t *name=idx>0?m_LanguageIDs[idx].name:L""; + if (_wcsicmp(language,name)==0) + { + ListView_SetItemState(list,idx,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED); + ListView_EnsureVisible(list,idx,FALSE); + break; + } + } + UpdateLink(language); + } + else + { + s_VersionData.Clear(); + SetDlgItemText(IDC_LINKDOWNLOAD,LoadStringEx(IDS_LANGUAGE_FAIL)); + } + return 0; +} + +LRESULT CLanguageSettingsDlg::OnSelChange( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + // set setting + CWindow list=GetDlgItem(IDC_LISTLANGUAGE); + int idx=ListView_GetNextItem(list,-1,LVNI_SELECTED); + if (idx<0) return 0; + + const wchar_t *name=idx>0?m_LanguageIDs[idx].name:L""; + CSettingsLockWrite lock; + CComVariant val(name); + if (m_pSetting->value!=val) + SetSettingsDirty(); + m_pSetting->value=val; + + if (_wcsicmp(m_pSetting->value.bstrVal,m_pSetting->defValue.bstrVal)==0) + m_pSetting->flags|=CSetting::FLAG_DEFAULT; + else + m_pSetting->flags&=~CSetting::FLAG_DEFAULT; + UpdateLink(name); + return 0; +} + +LRESULT CLanguageSettingsDlg::OnSelChanging( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + return m_bLocked?TRUE:FALSE; +} + +LRESULT CLanguageSettingsDlg::OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMLVCUSTOMDRAW *pDraw=(NMLVCUSTOMDRAW*)pnmh; + if (!m_bLocked) + { + bHandled=FALSE; + return 0; + } + if (pDraw->nmcd.dwDrawStage==CDDS_PREPAINT) + return CDRF_NOTIFYITEMDRAW; + if (pDraw->nmcd.dwDrawStage!=CDDS_ITEMPREPAINT) + { + bHandled=FALSE; + return 0; + } + pDraw->clrTextBk=GetSysColor(COLOR_BTNFACE); + return CDRF_DODEFAULT; +} + +static HRESULT CALLBACK TaskDialogCallbackProc( HWND hwnd, UINT uNotification, WPARAM wParam, LPARAM lParam, LONG_PTR dwRefData ) +{ + if (uNotification==TDN_HYPERLINK_CLICKED) + { + ShellExecute(hwnd,L"open",(const wchar_t*)lParam,NULL,NULL,SW_SHOWNORMAL); + } + return S_OK; +} + +LRESULT CLanguageSettingsDlg::OnDownload( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + CString language=GetSettingString(L"Language"); + if (language.IsEmpty()) + language=m_LanguageIDs[0].name; + + for (std::vector::const_iterator it=s_VersionData.languages.begin();it!=s_VersionData.languages.end();++it) + { + if (_wcsicmp(it->language,language)==0) + { + CString error; + DWORD res=DownloadLanguageDll(m_hWnd,m_Component,*it,error); + if (res==2) + return 0; + if (res) + MessageBox(LoadStringEx(it->bBasic?IDS_LANGUAGE_SUCCESS2:IDS_LANGUAGE_SUCCESS),LoadStringEx(IDS_UPDATE_TITLE),MB_OK|(it->bBasic?MB_ICONWARNING:MB_ICONINFORMATION)); + else + { + if (!s_VersionData.languageLink.IsEmpty()) + error+=L" "+LoadStringEx(IDS_DOWNLOAD_TIP)+L"\r\n\r\n"+s_VersionData.languageLink; + TASKDIALOGCONFIG task={sizeof(task),m_hWnd,NULL,TDF_ENABLE_HYPERLINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_USE_HICON_MAIN,TDCBF_OK_BUTTON}; + CString title=LoadStringEx(IDS_UPDATE_TITLE); + task.pszWindowTitle=title; + task.pszContent=error; + task.hMainIcon=LoadIcon(NULL,IDI_ERROR); + task.pfCallback=TaskDialogCallbackProc; + TaskDialogIndirect(&task,NULL,NULL,NULL); + } + UpdateLink(language); + break; + } + } + return 0; +} + +void CLanguageSettingsDlg::SetGroup( CSetting *pGroup ) +{ + m_bLocked=false; + m_pSetting=pGroup+1; + + const wchar_t *language=L""; + if (m_pSetting->value.vt==VT_BSTR && m_pSetting->value.bstrVal) + language=m_pSetting->value.bstrVal; + int len=Strlen(language); + + CWindow list=GetDlgItem(IDC_LISTLANGUAGE); + for (int idx=0;idx<(int)m_LanguageIDs.size();idx++) + { + const wchar_t *name=idx>0?m_LanguageIDs[idx].name:L""; + if (_wcsicmp(language,name)==0) + { + ListView_SetItemState(list,idx,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED); + ListView_EnsureVisible(list,idx,FALSE); + break; + } + } + UpdateLink(m_pSetting->value.bstrVal); + m_bLocked=m_pSetting->IsLocked(); + + TOOLINFO tool={sizeof(tool),0,m_hWnd,'CLSH'}; + tool.uId=(UINT_PTR)list.m_hWnd; + CString str; + if (m_bLocked) + str=LoadStringEx(IDS_SETTING_LOCKED); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + m_Tooltip.SendMessage(TTM_UPDATETIPTEXT,0,(LPARAM)&tool); + ListView_SetBkColor(list,GetSysColor(m_bLocked?COLOR_BTNFACE:COLOR_WINDOW)); +} + +void CLanguageSettingsDlg::UpdateLink( const wchar_t *language ) +{ + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS|TTF_IDISHWND,m_hWnd,'CLSH'}; + tool.uId=(UINT_PTR)GetDlgItem(IDC_LINKDOWNLOAD).m_hWnd; + m_Tooltip.SendMessage(TTM_DELTOOL,0,(LPARAM)&tool); + + if (!s_VersionData.bValid) + { + SetDlgItemText(IDC_LINKDOWNLOAD,L""); + return; + } + if (!*language) + language=m_LanguageIDs[0].name; + + wchar_t text[1024]; + for (std::vector::const_iterator it=s_VersionData.languages.begin();it!=s_VersionData.languages.end();++it) + { + if (_wcsicmp(it->language,language)==0) + { + DWORD dllVersion=0, dllBuild=0; + HINSTANCE resInstance=LoadTranslationDll(language); + if (resInstance) + { + dllVersion=GetVersionEx(resInstance,&dllBuild); + FreeLibrary(resInstance); + } + if (it->version>dllVersion || (it->version==dllVersion && it->build>dllBuild)) + { + Sprintf(text,_countof(text),LoadStringEx(IDS_LANGUAGE_DOWNLOAD),language); + SetDlgItemText(IDC_LINKDOWNLOAD,text); + + tool.lpszText=(LPWSTR)(LPCWSTR)it->url; + m_Tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + } + else + { + Sprintf(text,_countof(text),LoadStringEx(IDS_LANGUAGE_UPDATED),language); + SetDlgItemText(IDC_LINKDOWNLOAD,text); + } + return; + } + } + Sprintf(text,_countof(text),LoadStringEx(IDS_LANGUAGE_MISSING),language); + SetDlgItemText(IDC_LINKDOWNLOAD,text); +} + +class CLanguageSettingsPanel: public ISettingsPanel +{ +public: + CLanguageSettingsPanel( TSettingsComponent component ) { s_Dialog.SetComponent(component); } + virtual HWND Create( HWND parent ); + virtual HWND Activate( CSetting *pGroup, const RECT &rect, bool bReset ); + virtual bool Validate( HWND parent ) { return true; } + +private: + static CLanguageSettingsDlg s_Dialog; +}; + +CLanguageSettingsDlg CLanguageSettingsPanel::s_Dialog; + +ISettingsPanel *GetLanguageSettings( TSettingsComponent component ) +{ + static CLanguageSettingsPanel panel(component); + return &panel; +} + +HWND CLanguageSettingsPanel::Create( HWND parent ) +{ + if (!s_Dialog.m_hWnd) + s_Dialog.Create(parent,LoadDialogEx(IDD_LANGUAGE)); + return s_Dialog.m_hWnd; +} + +HWND CLanguageSettingsPanel::Activate( CSetting *pGroup, const RECT &rect, bool bReset ) +{ + s_Dialog.SetGroup(pGroup); + s_Dialog.SetWindowPos(HWND_TOP,&rect,SWP_SHOWWINDOW); + return s_Dialog.m_hWnd; +} diff --git a/ClassicShellSrc/ClassicShellLib/LanguageSettingsHelper.h b/ClassicShellSrc/ClassicShellLib/LanguageSettingsHelper.h new file mode 100644 index 0000000..99a1db4 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/LanguageSettingsHelper.h @@ -0,0 +1,11 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +class ISettingsPanel; + +extern int g_LanguageIDs[]; +extern int g_LanguageIDCount; + +ISettingsPanel *GetLanguageSettings( TSettingsComponent component ); diff --git a/ClassicShellSrc/ClassicShellLib/ResourceHelper.cpp b/ClassicShellSrc/ClassicShellLib/ResourceHelper.cpp new file mode 100644 index 0000000..58f176c --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/ResourceHelper.cpp @@ -0,0 +1,857 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include +#include "StringSet.h" +#include "StringUtils.h" +#include "Settings.h" +#include "Translations.h" +#include "ResourceHelper.h" +#include "Assert.h" +#include +#include +#include "TrackResources.h" + +static CStringSet g_ResStrings; +static std::map > g_ResDialogs; + +// Loads all strings and dialogs from hLngInstance +// pDialogs is a NULL-terminated list of dialog IDs. They are loaded from hLngInstance if possible, otherwise from g_Instance +void LoadTranslationResources( HINSTANCE hLngInstance, int *pDialogs ) +{ + Assert(g_Instance); + DWORD lngVersion=0; + if (hLngInstance) + { + LoadTranslationOverrides(hLngInstance); + g_ResStrings.Init(hLngInstance); + lngVersion=GetVersionEx(hLngInstance); + } + if (!pDialogs) + return; + for (int i=0;pDialogs[i];i+=2) + { + int dlgId=pDialogs[i]; + DWORD dlgVersion=pDialogs[i+1]; + HINSTANCE hInst=hLngInstance; + HRSRC hrsrc=NULL; + if (hLngInstance && lngVersion>=dlgVersion) + hrsrc=FindResource(hInst,MAKEINTRESOURCE(dlgId),RT_DIALOG); + if (!hrsrc) + { + hInst=g_Instance; + hrsrc=FindResource(hInst,MAKEINTRESOURCE(dlgId),RT_DIALOG); + } + if (hrsrc) + { + HGLOBAL hglb=LoadResource(hInst,hrsrc); + if (hglb) + { + // finally lock the resource + LPVOID res=LockResource(hglb); + std::vector &dlg=g_ResDialogs[dlgId]; + dlg.resize(SizeofResource(hInst,hrsrc)); + if (!dlg.empty()) + memcpy(&dlg[0],res,dlg.size()); + } + } + } +} + +// Loads the best DLL for the current language +HINSTANCE LoadTranslationDll( const wchar_t *langSetting ) +{ + Assert(g_Instance); + CString language=langSetting; + wchar_t languages[100]={0}; + if (!language.IsEmpty()) + { + Strcpy(languages,_countof(languages)-1,language); + } + else + { + ULONG size=0; + ULONG len=_countof(languages); + GetUserPreferredUILanguages(MUI_LANGUAGE_NAME,&size,languages,&len); + } + + wchar_t path1[_MAX_PATH]; + GetModuleFileName(g_Instance,path1,_countof(path1)); + *PathFindFileName(path1)=0; + + wchar_t path2[_MAX_PATH]=L"%ALLUSERSPROFILE%\\ClassicShell\\Languages\\"; + DoEnvironmentSubst(path2,_countof(path2)); + + DWORD curVersion=GetVersionEx(g_Instance); + HINSTANCE resInstance=NULL; + for (const wchar_t *lang=languages;*lang;lang+=Strlen(lang)+1) + { + if (_wcsicmp(lang,L"en")==0 || _wcsnicmp(lang,L"en-",3)==0) + break; // English + wchar_t fname[_MAX_PATH]; + DWORD ver1=0, ver2=0, build1=0, build2=0; + Sprintf(fname,_countof(fname),L"%s%s.dll",path1,lang); + HINSTANCE resInstance1=LoadLibraryEx(fname,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (resInstance1) + { + ver1=GetVersionEx(resInstance1,&build1); + if (ver1curVersion) + { + ver1=0; + FreeLibrary(resInstance1); + resInstance1=NULL; + } + } + Sprintf(fname,_countof(fname),L"%s%s.dll",path2,lang); + HINSTANCE resInstance2=LoadLibraryEx(fname,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (resInstance2) + { + ver2=GetVersionEx(resInstance2,&build2); + if (ver2curVersion) + { + ver2=0; + FreeLibrary(resInstance2); + resInstance2=NULL; + } + } + if (ver1 || ver2) + { + if (ver1>ver2 || (ver1==ver2 && build1>build2)) + { + resInstance=resInstance1; + if (resInstance2) FreeLibrary(resInstance2); + } + else + { + resInstance=resInstance2; + if (resInstance1) FreeLibrary(resInstance1); + } + break; + } + } + return resInstance; +} + +// Returns a localized string +CString LoadStringEx( int stringID ) +{ + CString str=g_ResStrings.GetString(stringID); + if (str.IsEmpty()) + str.LoadString(g_Instance,stringID); + return str; +} + +CString LoadStringEnglish( int stringID ) +{ + CString str; + str.LoadString(g_Instance,stringID); + return str; +} + +// Returns a localized dialog template +DLGTEMPLATE *LoadDialogEx( int dlgID ) +{ + std::map >::iterator it=g_ResDialogs.find(dlgID); + if (it==g_ResDialogs.end()) + return NULL; + if (it->second.empty()) + return NULL; + return (DLGTEMPLATE*)&it->second[0]; +} + +// Loads an icon. path can be a path to .ico file, or in the format "module.dll, number" +HICON LoadIcon( int iconSize, const wchar_t *path, std::vector &modules ) +{ + wchar_t text[1024]; + Strcpy(text,_countof(text),path); + DoEnvironmentSubst(text,_countof(text)); + wchar_t *c=wcsrchr(text,','); + if (c) + { + // resource file + *c=0; + const wchar_t *res=c+1; + int idx=_wtol(res); + if (idx>0) res=MAKEINTRESOURCE(idx); + if (!text[0]) + return (HICON)LoadImage(_AtlBaseModule.GetResourceInstance(),res,IMAGE_ICON,iconSize,iconSize,LR_DEFAULTCOLOR); + HMODULE hMod=GetModuleHandle(PathFindFileName(text)); + if (!hMod) + { + hMod=LoadLibraryEx(text,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (!hMod) return NULL; + modules.push_back(hMod); + } + return (HICON)LoadImage(hMod,res,IMAGE_ICON,iconSize,iconSize,LR_DEFAULTCOLOR); + } + else + { + return (HICON)LoadImage(NULL,text,IMAGE_ICON,iconSize,iconSize,LR_DEFAULTCOLOR|LR_LOADFROMFILE); + } +} + +HICON LoadIcon( int iconSize, PIDLIST_ABSOLUTE pidl ) +{ + HICON hIcon=NULL; + CComPtr pFolder; + PCITEMID_CHILD child; + if (SUCCEEDED(SHBindToParent(pidl,IID_IShellFolder,(void**)&pFolder,&child))) + { + bool bLarge=(iconSize>GetSystemMetrics(SM_CXSMICON)); + LONG lSize; + if (bLarge) + lSize=MAKELONG(iconSize,GetSystemMetrics(SM_CXSMICON)); + else + lSize=MAKELONG(GetSystemMetrics(SM_CXICON),iconSize); + CComPtr pExtract; + if (SUCCEEDED(pFolder->GetUIObjectOf(NULL,1,&child,IID_IExtractIcon,NULL,(void**)&pExtract))) + { + // get the icon location + wchar_t location[_MAX_PATH]; + int index=0; + UINT flags=0; + if (pExtract->GetIconLocation(0,location,_countof(location),&index,&flags)==S_OK) + { + if (flags&GIL_NOTFILENAME) + { + // extract the icon + HICON hIcon2=NULL; + HRESULT hr=pExtract->Extract(location,index,bLarge?&hIcon:&hIcon2,bLarge?&hIcon2:&hIcon,lSize); + if (FAILED(hr)) + hIcon=hIcon2=NULL; + if (hr==S_FALSE) + flags=0; + if (hIcon2) DestroyIcon(hIcon2); // HACK!!! Even though Extract should support NULL, not all implementations do. For example shfusion.dll crashes + } + if (!(flags&GIL_NOTFILENAME)) + { + if (ExtractIconEx(location,index==-1?0:index,bLarge?&hIcon:NULL,bLarge?NULL:&hIcon,1)!=1) + hIcon=NULL; + } + } + } + else + { + // try again using the ANSI version + CComPtr pExtractA; + if (SUCCEEDED(pFolder->GetUIObjectOf(NULL,1,&child,IID_IExtractIconA,NULL,(void**)&pExtractA))) + { + // get the icon location + char location[_MAX_PATH]; + int index=0; + UINT flags=0; + if (pExtractA->GetIconLocation(0,location,_countof(location),&index,&flags)==S_OK) + { + if (flags&GIL_NOTFILENAME) + { + // extract the icon + HICON hIcon2=NULL; + HRESULT hr=pExtractA->Extract(location,index,bLarge?&hIcon:&hIcon2,bLarge?&hIcon2:&hIcon,lSize); + if (FAILED(hr)) + hIcon=hIcon2=NULL; + if (hr==S_FALSE) + flags=0; + if (hIcon2) DestroyIcon(hIcon2); // HACK!!! Even though Extract should support NULL, not all implementations do. For example shfusion.dll crashes + } + if (!(flags&GIL_NOTFILENAME)) + { + if (ExtractIconExA(location,index==-1?0:index,bLarge?&hIcon:NULL,bLarge?NULL:&hIcon,1)!=1) + hIcon=NULL; + } + } + } + } + } + + return hIcon; +} + +HICON ShExtractIcon( const wchar_t *path, int index, int iconSize ) +{ + HICON hIcon; + + typedef UINT (WINAPI *FSHExtractIconsW)( LPCWSTR pszFileName, int nIconIndex, int cxIcon, int cyIcon, HICON *phIcon, UINT *pIconId, UINT nIcons, UINT flags ); + static FSHExtractIconsW s_SHExtractIconsW; + + if (!s_SHExtractIconsW) + { + HMODULE hShell32=GetModuleHandle(L"Shell32.dll"); + if (hShell32) + s_SHExtractIconsW=(FSHExtractIconsW)GetProcAddress(hShell32,"SHExtractIconsW"); + } + + if (s_SHExtractIconsW) + { + UINT id; + if (!s_SHExtractIconsW(path,index,iconSize,iconSize,&hIcon,&id,1,LR_DEFAULTCOLOR)) + hIcon=NULL; + } + else + { + if (ExtractIconEx(path,index,&hIcon,NULL,1)!=1) + return NULL; + } + if (hIcon) + { + AddTrackedIcon(hIcon); + } + return hIcon; +} + +HICON ShExtractIcon( const char *path, int index, int iconSize ) +{ + wchar_t pathW[_MAX_PATH]; + MbsToWcs(pathW,_countof(pathW),path); + return ShExtractIcon(pathW,index,iconSize); +} + +// Converts an icon to a bitmap. pBits may be NULL. If bDestroyIcon is true, hIcon will be destroyed +HBITMAP BitmapFromIcon( HICON hIcon, int iconSize, unsigned int **pBits, bool bDestroyIcon ) +{ + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=bi.bmiHeader.biHeight=iconSize; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + RECT rc={0,0,iconSize,iconSize}; + + HDC hdc=CreateCompatibleDC(NULL); + unsigned int *bits; + HBITMAP bmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&bits,NULL,0); + HGDIOBJ bmp0=SelectObject(hdc,bmp); + FillRect(hdc,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH)); + DrawIconEx(hdc,0,0,hIcon,iconSize,iconSize,0,NULL,DI_NORMAL); + SelectObject(hdc,bmp0); + DeleteDC(hdc); + if (bDestroyIcon) DestroyIcon(hIcon); + if (pBits) *pBits=bits; + return bmp; +} + +// Premultiplies a DIB section by the alpha channel and a given color +void PremultiplyBitmap( HBITMAP hBitmap, COLORREF rgb ) +{ + BITMAP info; + GetObject(hBitmap,sizeof(info),&info); + int n=info.bmWidth*info.bmHeight; + int mr=(rgb)&255; + int mg=(rgb>>8)&255; + int mb=(rgb>>16)&255; + // pre-multiply the alpha + for (int i=0;i>24); + int r=(pixel>>16)&255; + int g=(pixel>>8)&255; + int b=(pixel)&255; + r=(r*a*mr)/(255*255); + g=(g*a*mg)/(255*255); + b=(b*a*mb)/(255*255); + pixel=(a<<24)|(r<<16)|(g<<8)|b; + } +} + +// Creates a grayscale version of an icon +HICON CreateDisabledIcon( HICON hIcon, int iconSize ) +{ + // convert normal icon to grayscale + ICONINFO info; + GetIconInfo(hIcon,&info); + + unsigned int *bits; + HBITMAP bmp=BitmapFromIcon(hIcon,iconSize,&bits,false); + + int n=iconSize*iconSize; + for (int i=0;i>8)&255); + int b=((pixel>>16)&255); + int l=(77*r+151*g+28*b)/256; + pixel=(pixel&0xFF000000)|(l*0x010101); + } + + if (info.hbmColor) DeleteObject(info.hbmColor); + info.hbmColor=bmp; + hIcon=CreateIconIndirect(&info); + DeleteObject(bmp); + if (info.hbmMask) DeleteObject(info.hbmMask); + return hIcon; +} + +// Loads an image file into a bitmap and optionally resizes it +HBITMAP LoadImageFile( const wchar_t *path, const SIZE *pSize, bool bUseAlpha, bool bPremultiply, std::vector *pButtonAnim ) +{ + HBITMAP srcBmp=NULL; + if (_wcsicmp(PathFindExtension(path),L".bmp")==0) + { + srcBmp=(HBITMAP)LoadImage(NULL,path,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_LOADFROMFILE); + } + if (srcBmp && !pSize) + return srcBmp; + CComPtr pFactory; + if (FAILED(pFactory.CoCreateInstance(CLSID_WICImagingFactory))) + { + if (srcBmp) DeleteObject(srcBmp); + return NULL; + } + + CComPtr pBitmap; + if (srcBmp) + { + CComPtr pBitmap2; + if (FAILED(pFactory->CreateBitmapFromHBITMAP(srcBmp,NULL,bUseAlpha?WICBitmapUseAlpha:WICBitmapIgnoreAlpha,&pBitmap2))) + { + DeleteObject(srcBmp); + return NULL; + } + pBitmap=pBitmap2; + DeleteObject(srcBmp); + } + else + { + CComPtr pDecoder; + if (FAILED(pFactory->CreateDecoderFromFilename(path,NULL,GENERIC_READ,WICDecodeMetadataCacheOnLoad,&pDecoder))) + return NULL; + + CComPtr pFrame; + if (FAILED(pDecoder->GetFrame(0,&pFrame))) + return NULL; + pBitmap=pFrame; + } + + CComPtr pConverter; + if (FAILED(pFactory->CreateFormatConverter(&pConverter))) + return NULL; + pConverter->Initialize(pBitmap,bPremultiply?GUID_WICPixelFormat32bppPBGRA:GUID_WICPixelFormat32bppBGRA,WICBitmapDitherTypeNone,NULL,0,WICBitmapPaletteTypeMedianCut); + pBitmap=pConverter; + + int frameCount=1; + int Yoffset=0; + if (pButtonAnim) + { + frameCount=3; + UINT width=0, height=0; + pBitmap->GetSize(&width,&height); + if (width>=3) + { + unsigned int data[3]; + WICRect rect={0,0,3,1}; + if (SUCCEEDED(pBitmap->CopyPixels(&rect,12,12,(BYTE*)data)) && (data[0]&0xFFFFFF)==ANIM_BUTTON_TAG1 && (data[1]&0xFFFFFF)==ANIM_BUTTON_TAG2) + { + Yoffset=(data[2]>>16)&255; + if (Yoffset<(int)height) + { + frameCount=data[2]&255; + if (frameCount<1) frameCount=1; + if (frameCount>(int)(height-1)) frameCount=height-1; + pButtonAnim->resize(Yoffset*width); + rect.Width=width; + rect.Height=Yoffset; + pBitmap->CopyPixels(&rect,width*4,Yoffset*width*4,(BYTE*)&(*pButtonAnim)[0]); + } + } + } + } + + int frameWidthS, frameHeightS; + int frameWidthD, frameHeightD; + { + UINT width=0, height=0; + pBitmap->GetSize(&width,&height); + frameWidthS=width; + frameHeightS=(height-Yoffset)/frameCount; + frameWidthD=frameWidthS; + frameHeightD=frameHeightS; + + // if cx>0, use as width + // if cx<0, use -cx as width limit + // if cy==0, scale proportionally + if (pSize && pSize->cx && (pSize->cx>0 || -pSize->cxcx); + if (pSize->cy) + frameHeightD=pSize->cy; + else + frameHeightD=frameWidthD*frameHeightS/frameWidthS; + } + } + + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=frameWidthD; + bi.bmiHeader.biHeight=-frameHeightD*frameCount; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + + HDC hdc=CreateCompatibleDC(NULL); + BYTE *pBits; + HBITMAP bmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&pBits,NULL,0); + DeleteDC(hdc); + + for (int frame=0;frame pFrame=pBitmap; + if (frameCount>1) + { + CComPtr pClipper; + if (FAILED(pFactory->CreateBitmapClipper(&pClipper))) + { + DeleteObject(bmp); + bmp=NULL; + break; + } + WICRect rect={0,frameHeightS*frame+Yoffset,frameWidthS,frameHeightS}; + pClipper->Initialize(pBitmap,&rect); + pFrame=pClipper; + } + if (frameWidthS!=frameWidthD || frameHeightS!=frameHeightD) + { + CComPtr pScaler; + if (FAILED(pFactory->CreateBitmapScaler(&pScaler))) + { + DeleteObject(bmp); + bmp=NULL; + break; + } + pScaler->Initialize(pFrame,frameWidthD,frameHeightD,WICBitmapInterpolationModeFant); + pFrame=pScaler; + } + int stride=frameWidthD*4; + int frameSize=frameHeightD*stride; + pFrame->CopyPixels(NULL,stride,frameSize,pBits+frameSize*frame); + } + + return bmp; +} + +// Loads a bitmap from a IMAGE resource +HBITMAP LoadImageResource( HMODULE hModule, const wchar_t *name, bool bTopDown, bool bPremultiply ) +{ + CComPtr pFactory; + if (FAILED(pFactory.CoCreateInstance(CLSID_WICImagingFactory))) + return NULL; + + CComPtr pBitmap; + if (hModule) + { + HRSRC src=FindResource(hModule,name,L"IMAGE"); + if (!src) return NULL; + HGLOBAL hGlobal=LoadResource(hModule,src); + if (!hGlobal) return NULL; + void *pngData=LockResource(hGlobal); + if (!pngData) return NULL; + DWORD size=SizeofResource(hModule,src); + CComPtr pStream; + pStream.Attach(SHCreateMemStream((BYTE*)pngData,size)); + if (!pStream) return NULL; + + CComPtr pDecoder; + if (FAILED(pFactory->CreateDecoderFromStream(pStream,NULL,WICDecodeMetadataCacheOnLoad,&pDecoder))) + return NULL; + CComPtr pFrame; + if (FAILED(pDecoder->GetFrame(0,&pFrame))) + return NULL; + pBitmap=pFrame; + } + else + { + if (_wcsicmp(PathFindExtension(name),L".bmp")==0) + { + HBITMAP bmp=(HBITMAP)LoadImage(NULL,name,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_LOADFROMFILE); + if (!bmp) + return NULL; + CComPtr pBitmap2; + if (FAILED(pFactory->CreateBitmapFromHBITMAP(bmp,NULL,WICBitmapUseAlpha,&pBitmap2))) + pBitmap2=NULL; + DeleteObject(bmp); + if (!pBitmap2) + return NULL; + pBitmap=pBitmap2; + } + else + { + CComPtr pDecoder; + if (FAILED(pFactory->CreateDecoderFromFilename(name,NULL,GENERIC_READ,WICDecodeMetadataCacheOnLoad,&pDecoder))) + return NULL; + CComPtr pFrame; + if (FAILED(pDecoder->GetFrame(0,&pFrame))) + return NULL; + pBitmap=pFrame; + } + } + + CComPtr pConverter; + if (FAILED(pFactory->CreateFormatConverter(&pConverter))) + return NULL; + pConverter->Initialize(pBitmap,bPremultiply?GUID_WICPixelFormat32bppPBGRA:GUID_WICPixelFormat32bppBGRA,WICBitmapDitherTypeNone,NULL,0,WICBitmapPaletteTypeMedianCut); + + UINT width=0, height=0; + pConverter->GetSize(&width,&height); + + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=width; + bi.bmiHeader.biHeight=bTopDown?-(int)height:(int)height; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + + HDC hdc=CreateCompatibleDC(NULL); + BYTE *bits; + HBITMAP bmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&bits,NULL,0); + DeleteDC(hdc); + + if (bTopDown) + { + pConverter->CopyPixels(NULL,width*4,width*height*4,bits); + } + else + { + for (UINT y=0;yCopyPixels(&rc,width*4,width*4,bits+(height-y-1)*width*4); + } + } + + return bmp; +} + +// Returns the version of a given module +DWORD GetVersionEx( HINSTANCE hInstance, DWORD *pBuild ) +{ + // get the DLL version. this is a bit hacky. the standard way is to use GetFileVersionInfo and such API. + // but it takes a file name instead of module handle so it will probably load the DLL a second time. + // the header of the version resource is a fixed size so we can count on VS_FIXEDFILEINFO to always + // be at offset 40 + HRSRC hResInfo=FindResource(hInstance,MAKEINTRESOURCE(VS_VERSION_INFO),RT_VERSION); + if (!hResInfo) + return 0; + HGLOBAL hRes=LoadResource(hInstance,hResInfo); + void *pRes=LockResource(hRes); + if (!pRes) return 0; + + VS_FIXEDFILEINFO *pVer=(VS_FIXEDFILEINFO*)((char*)pRes+40); + if (pBuild) + *pBuild=LOWORD(pVer->dwProductVersionLS); + return ((HIWORD(pVer->dwProductVersionMS)&255)<<24)|((LOWORD(pVer->dwProductVersionMS)&255)<<16)|HIWORD(pVer->dwProductVersionLS); +} + +// Returns the Windows version - 0x600, 0x601, ... +WORD GetWinVersion( void ) +{ + static WORD version; + if (!version) + { + DWORD ver=GetVersion(); + version=MAKEWORD(HIBYTE(ver),LOBYTE(ver)); + } + return version; +} + +static bool IsWin81Update1Helper( void ) +{ + DWORD build; + DWORD ver=GetVersionEx(GetModuleHandle(L"user32.dll"),&build); + return HIWORD(ver)==WIN_VER_WIN81 && build>17000; +} + +// Returns true if the version is Win81 Update1 or later +bool IsWin81Update1( void ) +{ + static bool bIsUpdate1=IsWin81Update1Helper(); + return bIsUpdate1; +} + +static bool IsWin10RS1Helper( void ) +{ + DWORD build; + DWORD ver=GetVersionEx(GetModuleHandle(L"user32.dll"),&build); + return ver>MAKELONG(14000,10<<8); +} + +// Returns true if the version is Windows10 RS1 or later +bool IsWin10RS1( void ) +{ + static bool bIsRS1=IsWin10RS1Helper(); + return bIsRS1; +} + +// Wrapper for IShellFolder::ParseDisplayName +HRESULT ShParseDisplayName( const wchar_t *pszName, PIDLIST_ABSOLUTE *ppidl, SFGAOF sfgaoIn, SFGAOF *psfgaoOut ) +{ + static ITEMIDLIST ilRoot={0}; + static CComPtr pDesktop; + if (_wcsicmp(pszName,L"::{Desktop}")==0) + { + *ppidl=ILCloneFull((PIDLIST_ABSOLUTE)&ilRoot); + if (psfgaoOut) + { + *psfgaoOut=0; + if (sfgaoIn&SFGAO_FOLDER) + *psfgaoOut|=SFGAO_FOLDER; + } + return S_OK; + } + else + { + *ppidl=NULL; + if (!pDesktop) + { + HRESULT hr=SHGetDesktopFolder(&pDesktop); + if (FAILED(hr)) + return hr; + } + SFGAOF flags=sfgaoIn; + HRESULT hr=pDesktop->ParseDisplayName(NULL,NULL,(wchar_t*)pszName,NULL,(PIDLIST_RELATIVE*)ppidl,psfgaoOut?&flags:NULL); + if (FAILED(hr)) + return hr; + if (psfgaoOut) + *psfgaoOut=flags; + return hr; + } +} + +// Separates the arguments from the program +// May return NULL if no arguments are found +const wchar_t *SeparateArguments( const wchar_t *command, wchar_t *program ) +{ + if (command[0]=='"') + { + // quoted program - just GetToken will work + return GetToken(command,program,_MAX_PATH,L" "); + } + + // skip leading spaces + while (*command==' ') + command++; + const wchar_t *args=wcschr(command,' '); + if (!args) + { + // no spaces - the whole thing is a program + Strcpy(program,_MAX_PATH,command); + return NULL; + } + + int len=(int)(args-command); + if (len>_MAX_PATH-1) len=_MAX_PATH-1; + memcpy(program,command,len*2); + program[len]=0; + + const wchar_t *space=command; + while (*space) + { + space=wcschr(space+1,' '); + if (!space) + space=command+Strlen(command); + len=(int)(space-command); + if (len>=_MAX_PATH) break; + wchar_t prog2[_MAX_PATH]; + memcpy(prog2,command,len*2); + prog2[len]=0; + if (len>0 && prog2[len-1]=='\\') + prog2[len-1]=0; + WIN32_FIND_DATA data; + HANDLE h=FindFirstFile(prog2,&data); + if (h!=INVALID_HANDLE_VALUE) + { + // found a valid file + FindClose(h); + memcpy(program,command,len*2); + program[len]=0; + if (*space) + args=space+1; + else + args=NULL; + } + } + + while (args && *args==' ') + args++; + return args; +} +struct CommonEnvVar +{ + const wchar_t *name; + wchar_t value[_MAX_PATH]; + int len; +}; + +CommonEnvVar g_CommonEnvVars[]={ + {L"USERPROFILE"}, + {L"ALLUSERSPROFILE"}, + {L"SystemRoot"}, + {L"SystemDrive"}, +}; + +void UnExpandEnvStrings( const wchar_t *src, wchar_t *dst, int size ) +{ + static bool bInit=false; + if (!bInit) + { + bInit=true; + for (int i=0;i<_countof(g_CommonEnvVars);i++) + { + int len=GetEnvironmentVariable(g_CommonEnvVars[i].name,g_CommonEnvVars[i].value,_MAX_PATH); + if (len<=_MAX_PATH) + g_CommonEnvVars[i].len=len; + } + } + + for (int i=0;i<_countof(g_CommonEnvVars);i++) + { + int len=g_CommonEnvVars[i].len; + if (_wcsnicmp(src,g_CommonEnvVars[i].value,len)==0) + { + const wchar_t *name=g_CommonEnvVars[i].name; + if (Strlen(src)-len+Strlen(name)+3>size) + break; // not enough space + Sprintf(dst,size,L"%%%s%%%s",name,src+len); + return; + } + } + Strcpy(dst,size,src); +} + +void StringUpper( CString &str ) +{ + int len=str.GetLength(); + wchar_t *buf=str.GetBuffer(len); + CharUpper(buf); + str.ReleaseBufferSetLength(len); +} + +// Create a font from the user settings +HFONT CreateFontSetting( const wchar_t *fontStr, int dpi ) +{ + const wchar_t *str=fontStr; + if (!*str) return NULL; + + wchar_t name[256]; + while (*str==' ') + str++; + str=GetToken(str,name,_countof(name),L","); + int len=Strlen(name); + while (len>0 && name[len-1]==' ') + name[--len]=0; + while (*str==' ') + str++; + wchar_t token[256]; + str=GetToken(str,token,_countof(token),L","); + len=Strlen(token); + while (len>0 && token[len-1]==' ') + token[--len]=0; + int weight=FW_NORMAL; + bool bItalic=false; + if (_wcsicmp(token,L"bold")==0) + weight=FW_BOLD; + else if (_wcsicmp(token,L"italic")==0) + bItalic=1; + else if (_wcsicmp(token,L"bold_italic")==0) + weight=FW_BOLD, bItalic=true; + str=GetToken(str,token,_countof(token),L", \t"); + int size=-_wtol(token); + return CreateFont(size*dpi/72,0,0,0,weight,bItalic?1:0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,name); +} diff --git a/ClassicShellSrc/ClassicShellLib/ResourceHelper.h b/ClassicShellSrc/ClassicShellLib/ResourceHelper.h new file mode 100644 index 0000000..b6b3d2b --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/ResourceHelper.h @@ -0,0 +1,84 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#include +#include + +// Loads the best DLL for the given language +HINSTANCE LoadTranslationDll( const wchar_t *langSetting ); + +// Loads all strings and dialogs from hLngInstance +// pDialogs is a NULL-terminated list of dialog IDs. They are loaded from hLngInstance if possible, otherwise from g_Instance +void LoadTranslationResources( HINSTANCE hLngInstance, int *pDialogs ); + +// Returns a localized string +CString LoadStringEx( int stringID ); +CString LoadStringEnglish( int stringID ); + +// Returns a localized dialog template +DLGTEMPLATE *LoadDialogEx( int dlgID ); + +// Loads an icon. path can be a path to .ico file, or in the format "module.dll, number" +HICON LoadIcon( int iconSize, const wchar_t *path, std::vector &modules ); + +// Loads the icon for the given pidl (file or folder) +HICON LoadIcon( int iconSize, PIDLIST_ABSOLUTE pidl ); + +// Extracts icon of a given size from a specified location the way Shell does it +HICON ShExtractIcon( const wchar_t *path, int index, int iconSize ); +HICON ShExtractIcon( const char *path, int index, int iconSize ); + +// Converts an icon to a bitmap. pBits may be NULL. If bDestroyIcon is true, hIcon will be destroyed +HBITMAP BitmapFromIcon( HICON hIcon, int iconSize, unsigned int **pBits, bool bDestroyIcon ); + +// Loads an image file into a bitmap and optionally resizes it +HBITMAP LoadImageFile( const wchar_t *path, const SIZE *pSize, bool bUseAlpha, bool bPremultiply, std::vector *pButtonAnim ); + +// Loads a bitmap from a IMAGE resource +HBITMAP LoadImageResource( HMODULE hModule, const wchar_t *name, bool bTopDown, bool bPremultiply ); + +// Premultiplies a DIB section by the alpha channel and a given color +void PremultiplyBitmap( HBITMAP hBitmap, COLORREF rgb ); + +// Creates a grayscale version of an icon +HICON CreateDisabledIcon( HICON hIcon, int iconSize ); + +// Returns the version of a given module +DWORD GetVersionEx( HINSTANCE hInstance, DWORD *pBuild=NULL ); + +const int WIN_VER_VISTA=0x600; +const int WIN_VER_WIN7 =0x601; +const int WIN_VER_WIN8 =0x602; +const int WIN_VER_WIN81=0x603; +const int WIN_VER_WIN10=0xA00; + +// Returns the Windows version - 0x600, 0x601, ... +WORD GetWinVersion( void ); + +// Returns true if the version is Win81 Update1 +bool IsWin81Update1( void ); + +// Returns true if the version is Windows10 RS1 or later +bool IsWin10RS1( void ); + +// Wrapper for IShellFolder::ParseDisplayName +HRESULT ShParseDisplayName( const wchar_t *pszName, PIDLIST_ABSOLUTE *ppidl, SFGAOF sfgaoIn, SFGAOF *psfgaoOut ); + +// Separates the arguments from the program +// May return NULL if no arguments are found +const wchar_t *SeparateArguments( const wchar_t *command, wchar_t *program ); + +// Replaces some common paths with environment variables +void UnExpandEnvStrings( const wchar_t *src, wchar_t *dst, int size ); + +void StringUpper( CString &str ); + +// Create a font from the user settings +HFONT CreateFontSetting( const wchar_t *fontStr, int dpi ); + +extern HINSTANCE g_Instance; + +const int ANIM_BUTTON_TAG1='ANM'; +const int ANIM_BUTTON_TAG2='BTN'; diff --git a/ClassicShellSrc/ClassicShellLib/Settings.cpp b/ClassicShellSrc/ClassicShellLib/Settings.cpp new file mode 100644 index 0000000..cd90ff9 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/Settings.cpp @@ -0,0 +1,2843 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include +#include "resource.h" +#include "Settings.h" +#include "SettingsParser.h" +#include "SettingsUIHelper.h" +#include "ResourceHelper.h" +#include "StringUtils.h" +#include "FNVHash.h" +#include +#include +#include +#include +#include +#include +#include + +#ifdef BUILD_SETUP +#define DOC_PATH L"" +#else +#define DOC_PATH L"..\\..\\Docs\\Help\\" +#endif + +/////////////////////////////////////////////////////////////////////////////// + +// Read/Write lock for accessing the settings. Can't be acquired recursively. Only the main UI thread (the one displaying the settings UI) +// can write the settings, and because of that it shouldn't lock when reading the settings. The settings editing code shouldn't use +// GetSettings#### at all to avoid deadlocks +static SRWLOCK g_SettingsLock; + +#ifdef _DEBUG +static _declspec(thread) int g_LockState; // 0 - none, 1 - read, 2 - write +static _declspec(thread) bool g_bUIThread; // set to true in the thread that edits the settings +#endif + +CSettingsLockRead::CSettingsLockRead( void ) +{ +#ifdef _DEBUG + Assert(g_LockState==0); + g_LockState=1; +#endif + AcquireSRWLockShared(&g_SettingsLock); +} + +CSettingsLockRead::~CSettingsLockRead( void ) +{ +#ifdef _DEBUG + Assert(g_LockState==1); + g_LockState=0; +#endif + ReleaseSRWLockShared(&g_SettingsLock); +} + +CSettingsLockWrite::CSettingsLockWrite( void ) +{ +#ifdef _DEBUG + Assert(g_LockState==0); + g_LockState=2; +#endif + AcquireSRWLockExclusive(&g_SettingsLock); +} + +CSettingsLockWrite::~CSettingsLockWrite( void ) +{ +#ifdef _DEBUG + Assert(g_LockState==2); + g_LockState=0; +#endif + ReleaseSRWLockExclusive(&g_SettingsLock); +} + +static bool IsVariantTrue( const CComVariant &var ) +{ + return (var.vt==VT_I4 && var.intVal==1); +} + +bool CSetting::IsEnabled( void ) const +{ + if (IsLocked()) + return false; + + if (depend) + { + const wchar_t *name=depend; + bool checkEnabled=(*name=='#'); + if (checkEnabled) + name++; + + int len=Strlen(name); + int val=0; + wchar_t operation='~'; + const wchar_t operations[]=L"=~<>"; + for (const wchar_t *c=operations;*c;c++) + { + const wchar_t *p=wcschr(name,*c); + if (p) + { + operation=*c; + len=(int)(p-name); + val=_wtol(p+1); + break; + } + } + int style, styleMask; + GetSettingsStyle(style,styleMask); + for (const CSetting *pSetting=GetAllSettings();pSetting->name;pSetting++) + { + if (_wcsnicmp(pSetting->name,name,len)==0 && pSetting->name[len]==0) + { + if ((pSetting->flags&styleMask) && !(pSetting->flags&style)) + return true; // if the master setting is not visible in this style, ignore the dependency + if (checkEnabled && !pSetting->IsEnabled()) + return false; + if ((pSetting->type==CSetting::TYPE_BOOL || pSetting->type==CSetting::TYPE_INT) && pSetting->GetValue().vt==VT_I4) + { + if (operation=='=' && pSetting->GetValue().intVal!=val) + return false; + if (operation=='~' && pSetting->GetValue().intVal==val) + return false; + if (operation=='<' && pSetting->GetValue().intVal>=val) + return false; + if (operation=='>' && pSetting->GetValue().intVal<=val) + return false; + } + if ((pSetting->type==CSetting::TYPE_STRING || pSetting->type==CSetting::TYPE_BITMAP || pSetting->type==CSetting::TYPE_BITMAP_JPG) && pSetting->GetValue().vt==VT_BSTR) + { + if (operation=='~' && *pSetting->GetValue().bstrVal==0) + return false; + } + break; + } + } + } + return true; +} + +bool CSetting::MatchFilter( const wchar_t *filter ) const +{ + if (!*filter) return true; + CString string=LoadStringEx(nameID); + StringUpper(string); + if (wcsstr(string,filter)) return true; + string=LoadStringEnglish(nameID); + StringUpper(string); + if (wcsstr(string,filter)) return true; + return false; +} + +bool CSetting::ShouldLoad( bool bShared ) const +{ + if (type==TYPE_GROUP || type==TYPE_RADIO || pLinkTo) + return false; + return (flags&FLAG_SHARED)?bShared:!bShared; +} + +bool CSetting::ReadValue( CRegKey ®Key, const wchar_t *valName ) +{ + // bool, int, hotkey, color + if (type==CSetting::TYPE_BOOL || (type==CSetting::TYPE_INT && this[1].type!=CSetting::TYPE_RADIO) || type==CSetting::TYPE_HOTKEY || type==CSetting::TYPE_HOTKEY_ANY || type==CSetting::TYPE_COLOR) + { + DWORD val; + if (regKey.QueryDWORDValue(valName,val)==ERROR_SUCCESS) + { + if (type==CSetting::TYPE_BOOL) + value=CComVariant(val?1:0); + else + value=CComVariant((int)val); + return true; + } + return false; + } + + // radio + if (type==CSetting::TYPE_INT && this[1].type==CSetting::TYPE_RADIO) + { + ULONG len; + DWORD val; + if (regKey.QueryStringValue(valName,NULL,&len)==ERROR_SUCCESS) + { + CString text; + regKey.QueryStringValue(valName,text.GetBuffer(len),&len); + text.ReleaseBuffer(len); + val=0; + for (const CSetting *pRadio=this+1;pRadio->type==CSetting::TYPE_RADIO;pRadio++,val++) + { + if (_wcsicmp(text,pRadio->name)==0) + { + value=CComVariant((int)val); + return true; + } + } + } + else if (regKey.QueryDWORDValue(valName,val)==ERROR_SUCCESS) + { + value=CComVariant((int)val); + return true; + } + return false; + } + + // string + if (type>=CSetting::TYPE_STRING && type0) + { + value.bstrVal[len-1]='\n'; + value.bstrVal[len]=0; + } + return true; + } + return false; + } + + Assert(0); + return false; +} + +void CSetting::LoadValue( CRegKey ®Settings, CRegKey ®SettingsUser, CRegKey ®Policy, CRegKey ®PolicyUser ) +{ + if (!(flags&CSetting::FLAG_NODEFAULT)) + flags|=CSetting::FLAG_DEFAULT; + flags&=~CSetting::FLAG_LOCKED_REG; + value=defValue; + flags&=~CSetting::FLAG_FORCED_DEFAULT; + + wchar_t name2[256]; + + // load HKLM group policies + if (regPolicy) + { + Sprintf(name2,_countof(name2),L"%s_State",name); + DWORD val; + if (regPolicy.QueryDWORDValue(name2,val)==ERROR_SUCCESS && val<=2) + { + if (ReadValue(regPolicy,name)) + { + if (val==0) // locked to value + { + flags|=CSetting::FLAG_LOCKED_REG; + flags&=~CSetting::FLAG_DEFAULT; + return; + } + else if (val==1) // locked to default + { + flags|=CSetting::FLAG_LOCKED_REG; + return; + } + else // change default + { + defValue=value; + flags|=CSetting::FLAG_FORCED_DEFAULT; + } + } + } + } + + if (regSettings) + { + // load HKLM settings + DWORD val; + if (regSettings.QueryDWORDValue(name,val)==ERROR_SUCCESS && val==0xDEFA) + { + flags|=CSetting::FLAG_LOCKED_REG; + return; + } + else if (ReadValue(regSettings,name)) + { + flags|=CSetting::FLAG_LOCKED_REG; + flags&=~CSetting::FLAG_DEFAULT; + return; + } + else + { + // check if a default value is selected in HKLM + Sprintf(name2,_countof(name2),L"%s_Default",name); + if (ReadValue(regSettings,name2)) + { + defValue=value; + flags|=CSetting::FLAG_FORCED_DEFAULT; + } + } + } + + // load HKCU group policies + if (regPolicyUser) + { + Sprintf(name2,_countof(name2),L"%s_State",name); + DWORD val; + if (regPolicyUser.QueryDWORDValue(name2,val)==ERROR_SUCCESS && val<=2) + { + if (ReadValue(regPolicyUser,name)) + { + if (val==0) // locked to value + { + flags|=CSetting::FLAG_LOCKED_REG; + flags&=~CSetting::FLAG_DEFAULT; + return; + } + else if (val==1) // locked to default + { + flags|=CSetting::FLAG_LOCKED_REG; + return; + } + else // change default + { + defValue=value; + flags|=CSetting::FLAG_FORCED_DEFAULT; + } + } + } + } + + // load HKCU settings + if (regSettingsUser) + { + if (ReadValue(regSettingsUser,name)) + { + flags&=~CSetting::FLAG_DEFAULT; + return; + } + } +} + +class CSettingsManager +{ +public: + CSettingsManager( void ); + ~CSettingsManager( void ); + void Init( CSetting *pSettings, TSettingsComponent component, ICustomSettings *pCustom ); + + bool GetSettingBool( const wchar_t *name ) const; + bool GetSettingBool( const wchar_t *name, bool &bDef ) const; + int GetSettingInt( const wchar_t *name ) const; + int GetSettingInt( const wchar_t *name, bool &bDef ) const; + CString GetSettingString( const wchar_t *name ) const; + + void SaveSettings( bool bShared ); + void LoadSettings( bool bShared ); + CString LoadSettingsXml( const wchar_t *fname ); + CString SaveSettingsXml( const wchar_t *fname ); + void ResetSettings( void ); + + CSetting *GetSettings( void ) const { return m_pSettings; } + ICustomSettings *GetCustom( void ) const { return m_pCustom; } + bool SetSettingsStyle( int style, int mask ) { if (m_SettingsStyle==style && m_SettingsMask==mask) return false; m_SettingsStyle=style; m_SettingsMask=mask; return true; } + void GetSettingsStyle( int &style, int &mask ) const { style=m_SettingsStyle; mask=m_SettingsMask; } + HIMAGELIST GetImageList( HWND tree ); + void ResetImageList( void ); + const wchar_t *GetRegPath( void ) const { return m_RegPath; } + const wchar_t *GetXMLName( void ) const { return m_XMLName; } + +private: + CSetting *m_pSettings; + ICustomSettings *m_pCustom; + int m_SettingsStyle; + int m_SettingsMask; + HIMAGELIST m_ImageList; + const wchar_t *m_RegPath; + const wchar_t *m_RegPathShared; + const wchar_t *m_GpPath; + const wchar_t *m_GpPathShared; + const wchar_t *m_CompName; + const wchar_t *m_XMLName; +}; + +static CSettingsManager g_SettingsManager; + +CSettingsManager::CSettingsManager( void ) +{ + m_pSettings=NULL; + m_pCustom=NULL; + m_SettingsStyle=m_SettingsMask=0; + m_ImageList=NULL; + m_RegPath=m_RegPathShared=m_GpPath=m_GpPathShared=m_CompName=m_XMLName=NULL; +} + +static void GetRegPaths( TSettingsComponent component, const wchar_t *®Path, const wchar_t *&gpPath ) +{ + switch (component) + { + case COMPONENT_EXPLORER: + regPath=L"Software\\IvoSoft\\ClassicExplorer"; + gpPath=L"Software\\Policies\\IvoSoft\\ClassicExplorer"; + break; + case COMPONENT_MENU: + regPath=L"Software\\IvoSoft\\ClassicStartMenu"; + gpPath=L"Software\\Policies\\IvoSoft\\ClassicStartMenu"; + break; + case COMPONENT_IE: + regPath=L"Software\\IvoSoft\\ClassicIE"; + gpPath=L"Software\\Policies\\IvoSoft\\ClassicIE"; + break; + case COMPONENT_UPDATE: + regPath=L""; + gpPath=L""; + break; + case COMPONENT_SHARED: + regPath=L"Software\\IvoSoft\\ClassicShell"; + gpPath=L"Software\\Policies\\IvoSoft\\ClassicShell"; + break; + } +} + +void CSettingsManager::Init( CSetting *pSettings, TSettingsComponent component, ICustomSettings *pCustom ) +{ + GetRegPaths(component,m_RegPath,m_GpPath); + GetRegPaths(COMPONENT_SHARED,m_RegPathShared,m_GpPathShared); + switch (component) + { + case COMPONENT_EXPLORER: + m_CompName=L"Explorer"; + m_XMLName=L"Explorer Settings.xml"; + break; + case COMPONENT_MENU: + m_CompName=L"StartMenu"; + m_XMLName=L"Menu Settings.xml"; + break; + case COMPONENT_IE: + m_CompName=L"IE"; + m_XMLName=L"IE Settings.xml"; + break; + case COMPONENT_UPDATE: + m_CompName=L""; + m_XMLName=L""; + break; + } + + m_pSettings=pSettings; + m_pCustom=pCustom; + m_SettingsStyle=m_SettingsMask=0; + InitializeSRWLock(&g_SettingsLock); + CSettingsLockWrite lock; + for (CSetting *pSetting=m_pSettings;pSetting->name;pSetting++) + { + if (pSetting->type<0) continue; +#ifdef _DEBUG + if (pSetting->type==CSetting::TYPE_BOOL) + { + Assert(pSetting->defValue.vt==VT_I4 && (pSetting->defValue.intVal==0 || pSetting->defValue.intVal==1)); + } + else if (pSetting->type==CSetting::TYPE_INT || pSetting->type==CSetting::TYPE_HOTKEY || pSetting->type==CSetting::TYPE_HOTKEY_ANY || pSetting->type==CSetting::TYPE_COLOR) + { + Assert(pSetting->defValue.vt==VT_I4); + } + else if (pSetting->type>=CSetting::TYPE_STRING) + { + Assert(pSetting->defValue.vt==VT_BSTR); + } +#endif + pSetting->value=pSetting->defValue; + if (!(pSetting->flags&CSetting::FLAG_NODEFAULT)) + pSetting->flags|=CSetting::FLAG_DEFAULT; + } + LoadSettings(false); + LoadSettings(true); + UpdateSettings(); + m_ImageList=NULL; +} + +CSettingsManager::~CSettingsManager( void ) +{ + ResetImageList(); +} + +bool CSettingsManager::GetSettingBool( const wchar_t *name ) const +{ + for (const CSetting *pSetting=m_pSettings;pSetting->name;pSetting++) + { + if (pSetting->type==CSetting::TYPE_BOOL && _wcsicmp(pSetting->name,name)==0) + { + Assert(!pSetting->pLinkTo); + CSettingsLockRead lock; + return IsVariantTrue(pSetting->value); + } + } + Assert(0); + return false; +} + +bool CSettingsManager::GetSettingBool( const wchar_t *name, bool &bDef ) const +{ + for (const CSetting *pSetting=m_pSettings;pSetting->name;pSetting++) + { + if (pSetting->type==CSetting::TYPE_BOOL && _wcsicmp(pSetting->name,name)==0) + { + Assert(!pSetting->pLinkTo); + CSettingsLockRead lock; + bDef=pSetting->IsDefault() && !pSetting->IsForcedDefault(); + return IsVariantTrue(pSetting->value); + } + } + Assert(0); + bDef=false; + return 0; +} + +int CSettingsManager::GetSettingInt( const wchar_t *name ) const +{ + for (const CSetting *pSetting=m_pSettings;pSetting->name;pSetting++) + { + if ((pSetting->type==CSetting::TYPE_INT || pSetting->type==CSetting::TYPE_HOTKEY || pSetting->type==CSetting::TYPE_HOTKEY_ANY || pSetting->type==CSetting::TYPE_COLOR) && _wcsicmp(pSetting->name,name)==0) + { + Assert(!pSetting->pLinkTo); + CSettingsLockRead lock; + Assert(pSetting->value.vt==VT_I4); + return pSetting->value.intVal; + } + } + Assert(0); + return 0; +} + +int CSettingsManager::GetSettingInt( const wchar_t *name, bool &bDef ) const +{ + for (const CSetting *pSetting=m_pSettings;pSetting->name;pSetting++) + { + if ((pSetting->type==CSetting::TYPE_INT || pSetting->type==CSetting::TYPE_HOTKEY || pSetting->type==CSetting::TYPE_HOTKEY_ANY || pSetting->type==CSetting::TYPE_COLOR) && _wcsicmp(pSetting->name,name)==0) + { + Assert(!pSetting->pLinkTo); + CSettingsLockRead lock; + Assert(pSetting->value.vt==VT_I4); + bDef=pSetting->IsDefault() && !pSetting->IsForcedDefault(); + return pSetting->value.intVal; + } + } + Assert(0); + bDef=false; + return 0; +} + +CString CSettingsManager::GetSettingString( const wchar_t *name ) const +{ + for (const CSetting *pSetting=m_pSettings;pSetting->name;pSetting++) + { + if (pSetting->type>=CSetting::TYPE_STRING && _wcsicmp(pSetting->name,name)==0) + { + Assert(!pSetting->pLinkTo); + CSettingsLockRead lock; + Assert(pSetting->value.vt==VT_BSTR); + return pSetting->value.bstrVal; + } + } + Assert(0); + return CString(); +} + +static bool OpenSettingsKeys( const wchar_t *regPath, const wchar_t *gpPath, CRegKey ®Settings, CRegKey ®SettingsUser, CRegKey ®Policy, CRegKey ®PolicyUser ) +{ + bool bUpgrade=false; + if (*regPath) + { + regSettings.Open(HKEY_LOCAL_MACHINE,regPath,KEY_READ|KEY_WOW64_64KEY); + + wchar_t regPathNew[_MAX_PATH]; + Sprintf(regPathNew,_countof(regPathNew),L"%s\\Settings",regPath); + if (regSettingsUser.Open(HKEY_CURRENT_USER,regPathNew,KEY_READ|KEY_WOW64_64KEY)!=ERROR_SUCCESS) + { + if (regSettingsUser.Open(HKEY_CURRENT_USER,regPath,KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + bUpgrade=true; + } + } + + regPolicy.Open(HKEY_LOCAL_MACHINE,gpPath,KEY_READ|KEY_WOW64_64KEY); + regPolicyUser.Open(HKEY_CURRENT_USER,gpPath,KEY_READ|KEY_WOW64_64KEY); + return bUpgrade; +} + +void CSettingsManager::LoadSettings( bool bShared ) +{ + Assert(g_LockState==2); + + // load settings from registry + CRegKey regSettings, regSettingsUser, regPolicy, regPolicyUser; + bool bUpgrade=OpenSettingsKeys(bShared?m_RegPathShared:m_RegPath, bShared?m_GpPathShared:m_GpPath, regSettings, regSettingsUser, regPolicy, regPolicyUser); + + for (CSetting *pSetting=m_pSettings;pSetting->name;pSetting++) + { + if (pSetting->ShouldLoad(bShared)) + pSetting->LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser); + } + if (bUpgrade) + UpgradeSettings(bShared); +} + +void CSettingsManager::SaveSettings( bool bShared ) +{ + // doesn't need to acquire the lock because it can only run from the UI editing code + Assert(g_bUIThread); + + const wchar_t *regPath=bShared?m_RegPathShared:m_RegPath; + if (!*regPath) return; + wchar_t regPathNew[_MAX_PATH]; + Sprintf(regPathNew,_countof(regPathNew),L"%s\\Settings",regPath); + + // save non-default to HKCU + CRegKey regSettings; + if (regSettings.Open(HKEY_CURRENT_USER,regPathNew)!=ERROR_SUCCESS) + regSettings.Create(HKEY_CURRENT_USER,regPathNew); + + if (!bShared) + { + DWORD version=GetVersionEx(g_Instance); + regSettings.SetDWORDValue(L"Version",version); + } + for (const CSetting *pSetting=m_pSettings;pSetting->name;pSetting++) + { + if (pSetting->type==CSetting::TYPE_GROUP || pSetting->type==CSetting::TYPE_RADIO || pSetting->pLinkTo) + continue; + if (pSetting->flags&(CSetting::FLAG_LOCKED_REG|CSetting::FLAG_NOSAVE)) + continue; + if (pSetting->flags&CSetting::FLAG_SHARED) + { + if (!bShared) continue; + } + else + { + if (bShared) continue; + } + if (pSetting->flags&CSetting::FLAG_DEFAULT) + { + regSettings.DeleteValue(pSetting->name); + continue; + } + if (pSetting->type==CSetting::TYPE_BOOL || (pSetting->type==CSetting::TYPE_INT && pSetting[1].type!=CSetting::TYPE_RADIO) || pSetting->type==CSetting::TYPE_HOTKEY || pSetting->type==CSetting::TYPE_HOTKEY_ANY || pSetting->type==CSetting::TYPE_COLOR) + { + DWORD val=0; + if (pSetting->value.vt==VT_I4) + val=pSetting->value.intVal; + regSettings.SetDWORDValue(pSetting->name,val); + } + if (pSetting->type==CSetting::TYPE_INT && pSetting[1].type==CSetting::TYPE_RADIO) + { + DWORD val=0; + if (pSetting->value.vt==VT_I4) + val=pSetting->value.intVal; + for (const CSetting *pRadio=pSetting+1;pRadio->type==CSetting::TYPE_RADIO;pRadio++,val--) + { + if (val==0) + { + regSettings.SetStringValue(pSetting->name,pRadio->name); + break; + } + } + } + if (pSetting->type==CSetting::TYPE_MULTISTRING) + { + if (pSetting->value.vt==VT_BSTR) + { + int len=Strlen(pSetting->value.bstrVal); + for (int i=0;ivalue.bstrVal[i]=='\n') + pSetting->value.bstrVal[i]=0; + regSettings.SetMultiStringValue(pSetting->name,pSetting->value.bstrVal); + for (int i=0;ivalue.bstrVal[i]==0) + pSetting->value.bstrVal[i]='\n'; + } + else + regSettings.SetMultiStringValue(pSetting->name,L"\0"); + } + else if (pSetting->type>=CSetting::TYPE_STRING) + { + if (pSetting->value.vt==VT_BSTR) + regSettings.SetStringValue(pSetting->name,pSetting->value.bstrVal); + else + regSettings.SetStringValue(pSetting->name,L""); + } + } +} + +static CComBSTR g_bstrValue(L"value"); +static CComBSTR g_bstrTab(L"\n\t"); + +CString CSettingsManager::LoadSettingsXml( const wchar_t *fname ) +{ + CSettingsLockWrite lock; + CComPtr pDoc; + if (FAILED(pDoc.CoCreateInstance(L"Msxml2.FreeThreadedDOMDocument"))) + return L"Failed to initialize XML parser"; + pDoc->put_async(VARIANT_FALSE); + VARIANT_BOOL loaded; + if (pDoc->load(CComVariant(fname),&loaded)!=S_OK || loaded!=VARIANT_TRUE) + { + CComPtr pError; + pDoc->get_parseError(&pError); + CComBSTR reason; + if (pError && SUCCEEDED(pError->get_reason(&reason))) + { + return CString(L"XML parsing error: ")+reason; + } + return CString(L"XML parsing error"); + } + + CComPtr node; + HRESULT res=pDoc->selectSingleNode(CComBSTR(L"Settings"),&node); + if (res!=S_OK) + return CString(L"XML parsing error: The tag 'Settings' is missing."); + + DWORD ver=0; + { + CComVariant value; + CComQIPtr element=node; + if (!element || element->getAttribute(CComBSTR(L"component"),&value)!=S_OK || value.vt!=VT_BSTR) + return CString(L"XML parsing error: The tag 'Settings' is missing the 'component' attribute."); + if (_wcsicmp(value.bstrVal,m_CompName)!=0) + { + CString error; + error.Format(L"XML parsing error: This settings file is intended for another component '%s'.",value.bstrVal); + return error; + } + + value.Clear(); + if (element && element->getAttribute(CComBSTR(L"version"),&value)==S_OK && value.vt==VT_BSTR) + { + wchar_t token[10]; + const wchar_t *str=GetToken(value.bstrVal,token,_countof(token),L"."); + ver=(_wtol(token)&0xFF)<<24; + str=GetToken(str,token,_countof(token),L"."); + ver|=(_wtol(token)&0xFF)<<16; + ver|=_wtol(str)&0xFFFF; + } + } + + ResetSettings(); + CComPtr child; + node->get_firstChild(&child); + while (child) + { + CComBSTR name; + child->get_nodeName(&name); + + for (CSetting *pSetting=g_SettingsManager.GetSettings();pSetting->name;pSetting++) + { + if (pSetting->type==CSetting::TYPE_GROUP || pSetting->type==CSetting::TYPE_RADIO || pSetting->pLinkTo) + continue; + if (pSetting->type>=0 && _wcsicmp(pSetting->name,name)==0) + { + if (pSetting->flags&(CSetting::FLAG_LOCKED_REG|CSetting::FLAG_SHARED)) + break; + if (pSetting->type==CSetting::TYPE_MULTISTRING) + { + // load Lines + CComPtr child2; + child->get_firstChild(&child2); + std::vector string; + while (child2) + { + CComBSTR text; + if (child2->get_text(&text)==S_OK) + { + int len=(int)text.Length(); + int pos=(int)string.size(); + string.resize(pos+len+1); + memcpy(&string[pos],(const wchar_t*)text,len*2); + string[pos+len]='\n'; + } + CComPtr next; + child2->get_nextSibling(&next); + child2=next; + } + string.push_back(0); + pSetting->value=CComVariant(&string[0]); + pSetting->flags&=~CSetting::FLAG_DEFAULT; + } + else + { + CComQIPtr element=child; + if (element) + { + CComVariant value; + if (element->getAttribute(g_bstrValue,&value)==S_OK && value.vt==VT_BSTR) + { + if (pSetting->type>=CSetting::TYPE_STRING) + { + pSetting->value=value; + pSetting->flags&=~CSetting::FLAG_DEFAULT; + } + else if (pSetting->type==CSetting::TYPE_BOOL || (pSetting->type==CSetting::TYPE_INT && pSetting[1].type!=CSetting::TYPE_RADIO) || pSetting->type==CSetting::TYPE_HOTKEY || pSetting->type==CSetting::TYPE_HOTKEY_ANY || pSetting->type==CSetting::TYPE_COLOR) + { + int val=_wtol(value.bstrVal); + if (pSetting->type==CSetting::TYPE_BOOL) + pSetting->value=CComVariant(val?1:0); + else + pSetting->value=CComVariant(val); + pSetting->flags&=~CSetting::FLAG_DEFAULT; + } + else if (pSetting->type==CSetting::TYPE_INT && pSetting[1].type==CSetting::TYPE_RADIO) + { + int val=0; + for (CSetting *pRadio=pSetting+1;pRadio->type==CSetting::TYPE_RADIO;pRadio++,val++) + { + if (_wcsicmp(pRadio->name,value.bstrVal)==0) + { + pSetting->value=CComVariant(val); + pSetting->flags&=~CSetting::FLAG_DEFAULT; + break; + } + } + } + } + } + } + } + } + + CComPtr next; + if (child->get_nextSibling(&next)!=S_OK) + break; + child=next; + } + if (ver<0x03090000) + UpgradeSettings(false); + UpdateSettings(); + return CString(); +} + +static void SaveSettingValue( IXMLDOMDocument *pDoc, IXMLDOMNode *pParent, const wchar_t *name, const CComVariant &value ) +{ + CComPtr setting; + pDoc->createElement(CComBSTR(name),&setting); + setting->setAttribute(g_bstrValue,value); + CComPtr text; + CComPtr nu; + pDoc->createTextNode(g_bstrTab,&text); + pParent->appendChild(text,&nu); + nu=NULL; + pParent->appendChild(setting,&nu); +} + +CString CSettingsManager::SaveSettingsXml( const wchar_t *fname ) +{ + // doesn't need to acquire the lock because it can only run from the UI editing code + Assert(g_bUIThread); + + CComPtr pDoc; + HRESULT res=pDoc.CoCreateInstance(L"Msxml2.FreeThreadedDOMDocument"); + if (FAILED(res)) + return L"Failed to initialize XML parser"; + + CComPtr pRoot; + pDoc->createElement(CComBSTR(L"Settings"),&pRoot); + CComPtr pi; + if (SUCCEEDED(pDoc->createProcessingInstruction(CComBSTR(L"xml"),CComBSTR(L"version=\"1.0\""),&pi))) + { + CComPtr nu; + pDoc->appendChild(pi,&nu); + } + + { + CComPtr nu; + pDoc->appendChild(pRoot,&nu); + } + + pRoot->setAttribute(CComBSTR(L"component"),CComVariant(m_CompName)); + + wchar_t version[100]; + DWORD ver=GetVersionEx(g_Instance); + Sprintf(version,_countof(version),L"%d.%d.%d",ver>>24,(ver>>16)&0xFF,ver&0xFFFF); + pRoot->setAttribute(CComBSTR(L"version"),CComVariant(version)); + + for (const CSetting *pSetting=m_pSettings;pSetting->name;pSetting++) + { + if (pSetting->type==CSetting::TYPE_GROUP || pSetting->type==CSetting::TYPE_RADIO || pSetting->pLinkTo) + continue; + if (pSetting->flags&(CSetting::FLAG_LOCKED_REG|CSetting::FLAG_NOSAVE|CSetting::FLAG_DEFAULT|CSetting::FLAG_SHARED)) + continue; + if (pSetting->type==CSetting::TYPE_MULTISTRING) + { + CComPtr setting; + pDoc->createElement(CComBSTR(pSetting->name),&setting); + CComPtr text; + CComPtr nu; + pDoc->createTextNode(g_bstrTab,&text); + pRoot->appendChild(text,&nu); + nu=NULL; + pRoot->appendChild(setting,&nu); + CComBSTR tabs(L"\n\t\t"); + CComBSTR name(L"Line"); + if (pSetting->value.vt==VT_BSTR) + { + for (const wchar_t *str=pSetting->value.bstrVal;*str;) + { + int len; + const wchar_t *end=wcschr(str,'\n'); + if (end) + len=(int)(end-str); + else + len=Strlen(str); + CComPtr line; + pDoc->createElement(name,&line); + line->put_text(CComBSTR(len,str)); + nu=NULL; + text=NULL; + pDoc->createTextNode(tabs,&text); + setting->appendChild(text,&nu); + nu=NULL; + setting->appendChild(line,&nu); + if (!end) break; + str=end+1; + } + } + nu=NULL; + text=NULL; + pDoc->createTextNode(g_bstrTab,&text); + setting->appendChild(text,&nu); + continue; + } + else if (pSetting->type==CSetting::TYPE_BOOL || (pSetting->type==CSetting::TYPE_INT && pSetting[1].type!=CSetting::TYPE_RADIO) || pSetting->type>=CSetting::TYPE_HOTKEY || pSetting->type>=CSetting::TYPE_HOTKEY_ANY || pSetting->type>=CSetting::TYPE_STRING) + { + SaveSettingValue(pDoc,pRoot,pSetting->name,pSetting->value); + } + else if (pSetting->type==CSetting::TYPE_INT && pSetting[1].type==CSetting::TYPE_RADIO) + { + DWORD val=0; + if (pSetting->value.vt==VT_I4) + val=pSetting->value.intVal; + for (const CSetting *pRadio=pSetting+1;pRadio->type==CSetting::TYPE_RADIO;pRadio++,val--) + { + if (val==0) + { + SaveSettingValue(pDoc,pRoot,pSetting->name,CComVariant(pRadio->name)); + break; + } + } + } + } + CComPtr text; + CComPtr nu; + pDoc->createTextNode(CComBSTR(L"\n"),&text); + pRoot->appendChild(text,&nu); + if (FAILED(pDoc->save(CComVariant(fname)))) + return CString(L"Failed to save XML file ")+fname; + return CString(); +} + +void CSettingsManager::ResetSettings( void ) +{ + Assert(g_LockState==2); // must be locked for writing + for (CSetting *pSetting=m_pSettings;pSetting->name;pSetting++) + { + if (pSetting->type==CSetting::TYPE_GROUP || pSetting->type==CSetting::TYPE_RADIO || pSetting->pLinkTo) + continue; + if (pSetting->flags&(CSetting::FLAG_LOCKED_REG|CSetting::FLAG_NORESET)) + continue; + if (!(pSetting->flags&CSetting::FLAG_NODEFAULT)) + pSetting->flags|=CSetting::FLAG_DEFAULT; + pSetting->value=pSetting->defValue; + } +} + +HIMAGELIST CSettingsManager::GetImageList( HWND tree ) +{ + if (m_ImageList) return m_ImageList; + HTHEME theme=OpenThemeData(tree,L"button"); + HDC hdc=CreateCompatibleDC(NULL); + int iconSize=(TreeView_GetItemHeight(tree)<32)?16:32; + int checkSize=16; + if (theme) + { + SIZE val={16,16}; + if (GetThemePartSize(theme,hdc,BP_RADIOBUTTON,RBS_UNCHECKEDNORMAL,NULL,TS_DRAW,&val)==S_OK) + checkSize=val.cx; + } + int imageSize=iconSize>checkSize?iconSize:checkSize; + int iconOffset=(imageSize-iconSize)/2; + int checkOffset=(imageSize-checkSize)/2; + m_ImageList=ImageList_Create(imageSize,imageSize,ILC_COLOR32|ILC_MASK|((GetWindowLong(tree,GWL_EXSTYLE)&WS_EX_LAYOUTRTL)?ILC_MIRROR:0),0,23); + BITMAPINFO dib={sizeof(dib)}; + dib.bmiHeader.biWidth=imageSize; + dib.bmiHeader.biHeight=-imageSize; + dib.bmiHeader.biPlanes=1; + dib.bmiHeader.biBitCount=32; + dib.bmiHeader.biCompression=BI_RGB; + HDC hdcMask=CreateCompatibleDC(NULL); + HBITMAP bmp=CreateDIBSection(hdc,&dib,DIB_RGB_COLORS,NULL,NULL,0); + HBITMAP bmpMask=CreateDIBSection(hdcMask,&dib,DIB_RGB_COLORS,NULL,NULL,0); + + for (int i=0;i<13;i++) + { + HGDIOBJ bmp0=SelectObject(hdc,bmp); + HGDIOBJ bmp1=SelectObject(hdcMask,bmpMask); + RECT rc={0,0,imageSize,imageSize}; + FillRect(hdc,&rc,(HBRUSH)(COLOR_WINDOW+1)); + FillRect(hdcMask,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH)); + if (i==1) + { + HICON icon=(HICON)LoadImage(_AtlBaseModule.GetResourceInstance(),MAKEINTRESOURCE(IDI_ICONLOCK),IMAGE_ICON,iconSize,iconSize,LR_DEFAULTCOLOR); + DrawIconEx(hdc,iconOffset,iconOffset,icon,iconSize,iconSize,0,NULL,DI_NORMAL); + DrawIconEx(hdcMask,iconOffset,iconOffset,icon,iconSize,iconSize,0,NULL,DI_MASK); + DestroyIcon(icon); + } + else if (i==2 || i==3) + { + HMODULE hShell32=GetModuleHandle(L"shell32.dll"); + if (hShell32) + { + HICON icon=(HICON)LoadImage(hShell32,MAKEINTRESOURCE(151),IMAGE_ICON,iconSize,iconSize,LR_DEFAULTCOLOR); + DrawIconEx(hdc,iconOffset,iconOffset,icon,iconSize,iconSize,0,NULL,DI_NORMAL); + DestroyIcon(icon); + } + } + else if (i==12) + { + HICON icon=(HICON)LoadImage(_AtlBaseModule.GetResourceInstance(),MAKEINTRESOURCE(IDI_ICONWARNING),IMAGE_ICON,iconSize,iconSize,LR_DEFAULTCOLOR); + DrawIconEx(hdc,iconOffset,iconOffset,icon,iconSize,iconSize,0,NULL,DI_NORMAL); + DrawIconEx(hdcMask,iconOffset,iconOffset,icon,iconSize,iconSize,0,NULL,DI_MASK); + DestroyIcon(icon); + } + else if (i>3) + { + RECT rcCheck={checkOffset,checkOffset,checkOffset+checkSize,checkOffset+checkSize}; + if (theme) + { + if ((i-4)&4) + { + int state=(i-4)&3; + if (state==0) state=RBS_UNCHECKEDNORMAL; + else if (state==1) state=RBS_UNCHECKEDDISABLED; + else if (state==2) state=RBS_CHECKEDNORMAL; + else state=RBS_CHECKEDDISABLED; + DrawThemeBackground(theme,hdc,BP_RADIOBUTTON,state,&rcCheck,NULL); + } + else + { + int state=(i-4)&3; + if (state==0) state=CBS_UNCHECKEDNORMAL; + else if (state==1) state=CBS_UNCHECKEDDISABLED; + else if (state==2) state=CBS_CHECKEDNORMAL; + else state=CBS_CHECKEDDISABLED; + DrawThemeBackground(theme,hdc,BP_CHECKBOX,state,&rcCheck,NULL); + } + } + else + { + UINT state=DFCS_BUTTONCHECK|DFCS_FLAT; + if ((i-4)&1) state|=DFCS_INACTIVE; + if ((i-4)&2) state|=DFCS_CHECKED; + if ((i-4)&4) state|=DFCS_BUTTONRADIO; + DrawFrameControl(hdc,&rcCheck,DFC_BUTTON,state); + } + } + SelectObject(hdc,bmp0); + SelectObject(hdcMask,bmp1); + ImageList_Add(m_ImageList,bmp,bmpMask); + } + + // create color images + { + HGDIOBJ bmp0=SelectObject(hdc,bmp); + HGDIOBJ bmp1=SelectObject(hdcMask,bmpMask); + RECT rc={0,0,imageSize,imageSize}; + FillRect(hdc,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH)); + FillRect(hdcMask,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH)); + SelectObject(hdc,bmp0); + SelectObject(hdcMask,bmp1); + + for (int i=0;i<10;i++) + ImageList_Add(m_ImageList,bmp,bmpMask); + } + + DeleteObject(bmp); + DeleteObject(bmpMask); + DeleteDC(hdc); + DeleteDC(hdcMask); + + if (theme) CloseThemeData(theme); + ImageList_SetOverlayImage(m_ImageList,1,1); + ImageList_SetOverlayImage(m_ImageList,12,2); + return m_ImageList; +} + +void CSettingsManager::ResetImageList( void ) +{ + if (m_ImageList) ImageList_Destroy(m_ImageList); + m_ImageList=NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +class CSettingsDlg: public CResizeableDlg +{ +public: + CSettingsDlg( void ); + void Init( CSetting *pSettings, ICustomSettings *pCustom, int tab ); + + BEGIN_MSG_MAP( CSettingsDlg ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + MESSAGE_HANDLER( WM_DESTROY, OnDestroy ) + MESSAGE_HANDLER( WM_SIZE, OnSize ) + MESSAGE_HANDLER( WM_GETMINMAXINFO, OnGetMinMaxInfo ) + MESSAGE_HANDLER( WM_KEYDOWN, OnKeyDown ) + MESSAGE_HANDLER( WM_SYSCOMMAND, OnSysCommand ) + MESSAGE_HANDLER( WM_CLEAR, OnResetUI ) + COMMAND_HANDLER( IDOK, BN_CLICKED, OnOK ) + COMMAND_HANDLER( IDCANCEL, BN_CLICKED, OnCancel ) + COMMAND_HANDLER( IDC_BUTTONBACKUP, BN_CLICKED, OnBackup ) + COMMAND_HANDLER( IDC_CHECKALL, BN_CLICKED, OnCheckAll ) + COMMAND_HANDLER( IDC_EDITSEARCH, EN_CHANGE, OnSearchChange ) + NOTIFY_HANDLER( IDC_TABSETTINGS, TCN_SELCHANGING, OnSelChanging ) + NOTIFY_HANDLER( IDC_TABSETTINGS, TCN_SELCHANGE, OnSelChange ) + NOTIFY_HANDLER( IDC_BUTTONBACKUP, BCN_DROPDOWN, OnDropDown ) + NOTIFY_HANDLER( IDC_LINKHELP, NM_CLICK, OnHelp ) + NOTIFY_HANDLER( IDC_LINKHELP, NM_RETURN, OnHelp ) + NOTIFY_HANDLER( IDC_LINKWEB, NM_CLICK, OnWeb ) + NOTIFY_HANDLER( IDC_LINKWEB, NM_RETURN, OnWeb ) + NOTIFY_HANDLER( IDC_SYSLINKLOC, NM_CLICK, OnLink ) + NOTIFY_HANDLER( IDC_SYSLINKLOC, NM_RETURN, OnLink ) + END_MSG_MAP() + + BEGIN_RESIZE_MAP + RESIZE_CONTROL(IDC_TABSETTINGS,MOVE_SIZE_X|MOVE_SIZE_Y) + RESIZE_CONTROL(IDC_LINKHELP,MOVE_MOVE_X) + RESIZE_CONTROL(IDC_LINKWEB,MOVE_MOVE_Y) + RESIZE_CONTROL(IDC_SYSLINKLOC,MOVE_SIZE_X|MOVE_MOVE_Y) + RESIZE_CONTROL(IDC_BUTTONBACKUP,MOVE_MOVE_X|MOVE_MOVE_Y) + RESIZE_CONTROL(IDOK,MOVE_MOVE_X|MOVE_MOVE_Y) + RESIZE_CONTROL(IDCANCEL,MOVE_MOVE_X|MOVE_MOVE_Y) + END_RESIZE_MAP + + bool GetOnTop( void ) const { return m_bOnTop; } + void SetDirty( void ) { m_bDirty=true; } + +protected: + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnKeyDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSysCommand( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnResetUI( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnBackup( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCheckAll( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnSearchChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnSelChanging( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnSelChange( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnDropDown( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnHelp( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnWeb( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnLink( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + +private: + CSetting *m_pSettings; + ICustomSettings *m_pCustom; + CWindow m_Tabs; + int m_Index; + HWND m_Panel; + int m_InitialTab; + bool m_bBasic; + bool m_bOnTop; + bool m_bIgnoreEdit; + bool m_bDirty; + CString m_FilterText; + + void AddTabs( int name, const CSetting *pSelect=NULL ); + void SetCurTab( int index, bool bReset, const CSetting *pSelect=NULL ); + bool IsTabValid( void ); + void StorePlacement( void ); + + struct Placement + { + RECT rc; + unsigned int tab; + bool basic; + bool top; + BOOL maximized; + }; + + bool IsVisible( const CSetting *pSetting ) const; + + friend void SetSettingsStyle( int style, int mask ); + friend void SelectSettingsTab( int tab, bool bAdvanced, const CSetting *pSelect ); +}; + +CSettingsDlg::CSettingsDlg( void ) +{ + m_pSettings=NULL; + m_pCustom=NULL; + m_Index=0; + m_Panel=NULL; + m_InitialTab=0; + m_bBasic=false; + m_bOnTop=false; + m_bIgnoreEdit=false; + m_bDirty=false; +} + +void CSettingsDlg::Init( CSetting *pSettings, ICustomSettings *pCustom, int tab ) +{ + m_pSettings=pSettings; + m_pCustom=pCustom; + m_InitialTab=tab; + m_FilterText.Empty(); + m_bDirty=false; +} + +// Subclass the tooltip to delay the tip when the mouse moves from one tree item to the next +static LRESULT CALLBACK SubclassSearchBoxProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_GETDLGCODE && wParam==VK_ESCAPE) + return DLGC_WANTALLKEYS; + if (uMsg==WM_CHAR && wParam==VK_ESCAPE) + { + if (GetWindowTextLength(hWnd)>0) + SetWindowText(hWnd,L""); + else + SetFocus(GetParent(hWnd)); + return 0; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +LRESULT CSettingsDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ +#ifdef _DEBUG + g_bUIThread=true; +#endif +/* + // attempt to make the dialog have its own icon. doesn't work though. the icon changes, but to the default folder icon + CComPtr pStore; + if (SUCCEEDED(SHGetPropertyStoreForWindow(m_hWnd,IID_IPropertyStore,(void**)&pStore))) + { + PROPVARIANT val; + val.vt=VT_LPWSTR; + val.pwszVal=L"ClassicShell.Settings.Dialog"; + pStore->SetValue(PKEY_AppUserModel_ID,val); + } +*/ + InitResize(MOVE_MODAL); + HMENU menu=GetSystemMenu(FALSE); + bool bAdded=false; + int n=GetMenuItemCount(menu); + for (int i=0;iname;pSetting++) + { + if (pSetting->type!=CSetting::TYPE_GROUP) + continue; + ISettingsPanel *pPanel=pSetting->pPanel; + if (!pPanel) pPanel=GetDefaultSettings(NULL,NULL); + HWND panel=pPanel->Create(m_hWnd); + RECT rc; + ::GetWindowRect(panel,&rc); + if (maxSize.cxname;pSetting++) + { + pSetting->tempValue=pSetting->value; + pSetting->tempFlags=pSetting->flags; + } + } + + if (m_InitialTab) + pos.tab=m_InitialTab; + AddTabs(pos.tab); + if (pos.tab && bPosValid) + { + SetStoreRect(pos.rc); + if (pos.maximized) + ShowWindow(SW_MAXIMIZE); + } + + return TRUE; +} + +LRESULT CSettingsDlg::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + RemoveWindowSubclass(GetDlgItem(IDC_EDITSEARCH),SubclassSearchBoxProc,'CLSH'); + bHandled=FALSE; +#ifdef _DEBUG + g_bUIThread=false; +#endif + return 0; +} + +bool CSettingsDlg::IsVisible( const CSetting *pSetting ) const +{ + if (pSetting->flags&CSetting::FLAG_HIDDEN) + return false; + int style, mask; + GetSettingsStyle(style,mask); + if ((pSetting->flags&mask) && !(pSetting->flags&style)) + return false; + return true; +} + +void CSettingsDlg::AddTabs( int name, const CSetting *pSelect ) +{ + TabCtrl_DeleteAllItems(m_Tabs); + int idx=0; + if (pSelect) + { + m_bIgnoreEdit=true; + m_FilterText.Empty(); + SetDlgItemText(IDC_EDITSEARCH,L""); + m_bIgnoreEdit=false; + } + for (const CSetting *pSetting=m_pSettings;pSetting->name;pSetting++) + { + if (pSetting->type!=CSetting::TYPE_GROUP) + continue; + if (m_FilterText.IsEmpty()) + { + if (!m_bBasic && pSetting->nameID==IDS_BASIC_SETTINGS) + continue; + if (m_bBasic && pSetting->nameID!=IDS_BASIC_SETTINGS && !(pSetting->flags&CSetting::FLAG_BASIC)) + continue; + if (!IsVisible(pSetting)) + continue; + } + else + { + if (pSetting->nameID!=IDS_BASIC_SETTINGS) + continue; + } + CString str=LoadStringEx(m_FilterText.IsEmpty()?pSetting->nameID:IDS_SETTING_SEARCH); + TCITEM tab={TCIF_PARAM|TCIF_TEXT,0,0,(LPWSTR)(LPCWSTR)str,0,0,(LPARAM)pSetting}; + int i=TabCtrl_InsertItem(m_Tabs,1000,&tab); + if (pSetting->nameID==name) + idx=i; + } + m_Index=-1; + TabCtrl_SetCurSel(m_Tabs,idx); + m_Tabs.InvalidateRect(NULL); + SetCurTab(idx,false,pSelect); +} + +LRESULT CSettingsDlg::OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + CResizeableDlg::OnSize(); + RECT rc; + m_Tabs.GetWindowRect(&rc); + ::MapWindowPoints(NULL,m_hWnd,(POINT*)&rc,2); + TabCtrl_AdjustRect(m_Tabs,FALSE,&rc); + if (m_Panel) ::SetWindowPos(m_Panel,HWND_TOP,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,0); + return 0; +} + +LRESULT CSettingsDlg::OnKeyDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==VK_TAB && GetKeyState(VK_CONTROL)<0) + { + int sel=TabCtrl_GetCurSel(m_Tabs); + if (GetKeyState(VK_SHIFT)<0) + { + if (sel>0) + { + TabCtrl_SetCurSel(m_Tabs,sel-1); + SetCurTab(sel-1,false); + } + } + else + { + if (selnameID; + pos.basic=m_bBasic; + pos.top=m_bOnTop; + pos.maximized=IsZoomed(); + + CRegKey regSettings; + if (regSettings.Open(HKEY_CURRENT_USER,GetSettingsRegPath())!=ERROR_SUCCESS) + regSettings.Create(HKEY_CURRENT_USER,GetSettingsRegPath()); + regSettings.SetBinaryValue(L"CSettingsDlg",&pos,sizeof(pos)); +} + +LRESULT CSettingsDlg::OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (IsTabValid()) + { + int flags=0; + for (const CSetting *pSetting=m_pSettings;pSetting->name;pSetting++) + { + if (pSetting->type==CSetting::TYPE_GROUP || pSetting->type==CSetting::TYPE_RADIO || pSetting->pLinkTo) + continue; + if (pSetting->value!=pSetting->tempValue) + flags|=pSetting->flags&(CSetting::FLAG_WARM|CSetting::FLAG_COLD); + } + g_SettingsManager.SaveSettings(false); + g_SettingsManager.SaveSettings(true); + ClosingSettings(m_hWnd,flags,IDOK); + StorePlacement(); + DestroyWindow(); + } + return TRUE; +} + +LRESULT CSettingsDlg::OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (m_bDirty) + { + int res=MessageBox(LoadStringEx(IDS_UNSAVED_CHANGES),LoadStringEx(IDS_UNSAVED_TITLE),MB_YESNOCANCEL); + if (res==IDCANCEL) + { + return TRUE; + } + + if (res==IDYES) + { + if (IsTabValid()) + { + int flags=0; + for (const CSetting *pSetting=m_pSettings;pSetting->name;pSetting++) + { + if (pSetting->type==CSetting::TYPE_GROUP || pSetting->type==CSetting::TYPE_RADIO || pSetting->pLinkTo) + continue; + if (pSetting->value!=pSetting->tempValue) + flags|=pSetting->flags&(CSetting::FLAG_WARM|CSetting::FLAG_COLD); + } + g_SettingsManager.SaveSettings(false); + g_SettingsManager.SaveSettings(true); + ClosingSettings(m_hWnd,flags,IDOK); + StorePlacement(); + DestroyWindow(); + } + return TRUE; + } + } + + StorePlacement(); + DestroyWindow(); + // restore all settings + { + CSettingsLockWrite lock; + for (CSetting *pSetting=m_pSettings;pSetting->name;pSetting++) + { + pSetting->value=pSetting->tempValue; + pSetting->flags=pSetting->tempFlags; + } + } + ClosingSettings(m_hWnd,0,IDCANCEL); + return TRUE; +} + +LRESULT CSettingsDlg::OnBackup( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + HMENU menu=CreatePopupMenu(); + AppendMenu(menu,MF_STRING,1,LoadStringEx(IDS_BACKUP_SAVE)); + AppendMenu(menu,MF_STRING,2,LoadStringEx(IDS_BACKUP_LOAD)); + AppendMenu(menu,MF_STRING,3,LoadStringEx(IDS_BACKUP_RESET)); + if (m_pCustom) + m_pCustom->AppendBackupMenu(menu,4); + TPMPARAMS params={sizeof(params)}; + GetDlgItem(IDC_BUTTONBACKUP).GetWindowRect(¶ms.rcExclude); + if (GetWindowLong(GWL_EXSTYLE)&WS_EX_LAYOUTRTL) + { + int q=params.rcExclude.left; + params.rcExclude.left=params.rcExclude.right; + params.rcExclude.right=q; + } + int res=TrackPopupMenuEx(menu,TPM_RETURNCMD|TPM_VERTICAL,params.rcExclude.left,params.rcExclude.bottom,m_hWnd,¶ms); + DestroyMenu(menu); + + // remove the next mouse click if it is on the Backup button + MSG msg; + if (PeekMessage(&msg,NULL,WM_LBUTTONDOWN,WM_LBUTTONDBLCLK,PM_NOREMOVE) && PtInRect(¶ms.rcExclude,msg.pt)) + PeekMessage(&msg,NULL,WM_LBUTTONDOWN,WM_LBUTTONDBLCLK,PM_REMOVE); + + if (res==1) + { + // save + wchar_t path[_MAX_PATH]; + Strcpy(path,_countof(path),g_SettingsManager.GetXMLName()); + OPENFILENAME ofn={sizeof(ofn)}; + ofn.hwndOwner=m_hWnd; + wchar_t filters[256]; + Strcpy(filters,_countof(filters),LoadStringEx(IDS_XML_FILTERS)); + for (wchar_t *c=filters;*c;c++) + if (*c=='|') *c=0; + ofn.lpstrFilter=filters; + ofn.nFilterIndex=1; + ofn.lpstrFile=path; + ofn.nMaxFile=_MAX_PATH; + CString title=LoadStringEx(IDS_XML_TITLE_SAVE); + ofn.lpstrTitle=title; + ofn.lpstrDefExt=L".xml"; + ofn.Flags=OFN_DONTADDTORECENT|OFN_ENABLESIZING|OFN_EXPLORER|OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY|OFN_NOCHANGEDIR; + if (GetSaveFileName(&ofn)) + { + CString err=g_SettingsManager.SaveSettingsXml(path); + if (!err.IsEmpty()) + { + wchar_t text[1024]; + Sprintf(text,_countof(text),LoadStringEx(IDS_ERROR_SAVING_XML),path); + ::MessageBox(m_hWnd,text,LoadStringEx(IDS_ERROR_TITLE),MB_OK|MB_ICONERROR); + } + } + } + if (res==2) + { + // load + wchar_t path[_MAX_PATH]; + path[0]=0; + OPENFILENAME ofn={sizeof(ofn)}; + ofn.hwndOwner=m_hWnd; + wchar_t filters[256]; + Strcpy(filters,_countof(filters),LoadStringEx(IDS_XML_FILTERS)); + for (wchar_t *c=filters;*c;c++) + if (*c=='|') *c=0; + ofn.lpstrFilter=filters; + ofn.nFilterIndex=1; + ofn.lpstrFile=path; + ofn.nMaxFile=_MAX_PATH; + CString title=LoadStringEx(IDS_XML_TITLE_LOAD); + ofn.lpstrTitle=title; + ofn.Flags=OFN_DONTADDTORECENT|OFN_ENABLESIZING|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_NOCHANGEDIR; + if (GetOpenFileName(&ofn)) + { + CString error=g_SettingsManager.LoadSettingsXml(path); + if (!error.IsEmpty()) + { + wchar_t text[1024]; + int len=Sprintf(text,_countof(text),LoadStringEx(IDS_ERROR_LOADING_XML),path); + Sprintf(text+len,_countof(text)-len,L"\r\n\r\n%s",error); + ::MessageBox(m_hWnd,text,LoadStringEx(IDS_ERROR_TITLE),MB_OK|MB_ICONERROR); + } + SetSettingsDirty(); + SetCurTab(m_Index,true); + } + } + if (res==3) + { + // reset + if (::MessageBox(m_hWnd,LoadStringEx(IDS_RESET_CONFIRM),LoadStringEx(IDS_RESET_TITLE),MB_YESNO|MB_ICONWARNING)==IDYES) + { + { + CSettingsLockWrite lock; + g_SettingsManager.ResetSettings(); + UpdateSettings(); + SetSettingsDirty(); + } + SetCurTab(m_Index,true); + } + } + if (m_pCustom && res>3) + m_pCustom->ExecuteBackupMenu(res); + return TRUE; +} + +LRESULT CSettingsDlg::OnCheckAll( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + bool bBasic=!IsDlgButtonChecked(IDC_CHECKALL)==BST_CHECKED; + if (m_bBasic!=bBasic) + { + m_bBasic=bBasic; + AddTabs(-1); + } + return 0; +} + +LRESULT CSettingsDlg::OnSearchChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (!m_bIgnoreEdit) + { + GetDlgItemText(wID,m_FilterText); + m_FilterText.Trim(); + StringUpper(m_FilterText); + GetDlgItem(IDC_CHECKALL).EnableWindow(m_FilterText.IsEmpty()); + AddTabs(-1); + ::SetFocus(hWndCtl); + } + return 0; +} + +void CSettingsDlg::SetCurTab( int index, bool bReset, const CSetting *pSelect ) +{ + if (m_Index==index && !bReset) return; + m_Index=index; + TCITEM tab={TCIF_PARAM}; + BOOL res=TabCtrl_GetItem(m_Tabs,index,&tab); + if (!res) + { + if (m_Panel) ::ShowWindow(m_Panel,SW_HIDE); + m_Panel=NULL; + return; + } + CSetting *pGroup=(CSetting*)tab.lParam; + ISettingsPanel *pPanel=pGroup->pPanel; + if (!pPanel) pPanel=GetDefaultSettings(&m_FilterText,pSelect); + RECT rc; + m_Tabs.GetWindowRect(&rc); + ::MapWindowPoints(NULL,m_hWnd,(POINT*)&rc,2); + TabCtrl_AdjustRect(m_Tabs,FALSE,&rc); + HWND hwnd=pPanel->Activate(pGroup,rc,bReset); + if (hwnd!=m_Panel) + { + if (m_Panel) ::ShowWindow(m_Panel,SW_HIDE); + m_Panel=hwnd; + ::SetFocus(m_Panel); + } +} + +LRESULT CSettingsDlg::OnSelChanging( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + return !IsTabValid(); +} + +LRESULT CSettingsDlg::OnSelChange( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + SetCurTab(TabCtrl_GetCurSel(m_Tabs),false); + return 0; +} + +LRESULT CSettingsDlg::OnDropDown( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + SendMessage(WM_COMMAND,IDC_BUTTONBACKUP); + return 0; +} + +LRESULT CSettingsDlg::OnHelp( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + ShowHelp(); + return 0; +} + +LRESULT CSettingsDlg::OnWeb( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + ShellExecute(m_hWnd,NULL,L"http://www.classicshell.net",NULL,NULL,SW_SHOWNORMAL); + return 0; +} + +LRESULT CSettingsDlg::OnLink( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + CString text; + GetDlgItemText(idCtrl,text); + const wchar_t *str=text; + const wchar_t *link=wcswcs(str,L"href=\""); + if (!link) return 0; + link+=6; + const wchar_t *end=wcschr(link,'"'); + if (end) + { + CString url=text.Mid((int)(link-str),(int)(end-link)); + ShellExecute(m_hWnd,NULL,url,NULL,NULL,SW_SHOWNORMAL); + } + return 0; +} + +bool CSettingsDlg::IsTabValid( void ) +{ + int idx=TabCtrl_GetCurSel(m_Tabs); + if (idx<0) return true; + TCITEM tab={TCIF_PARAM}; + TabCtrl_GetItem(m_Tabs,idx,&tab); + CSetting *pGroup=(CSetting*)tab.lParam; + ISettingsPanel *pPanel=pGroup->pPanel; + if (!pPanel) pPanel=GetDefaultSettings(NULL,NULL); + return pPanel->Validate(m_hWnd); +} + +static CSettingsDlg g_SettingsDlg; + +void EditSettings( const wchar_t *title, bool bModal, int tab ) +{ + if (g_SettingsDlg.m_hWnd) + { + HWND top=GetWindow(g_SettingsDlg,GW_ENABLEDPOPUP); + if (!top) top=g_SettingsDlg.m_hWnd; + SetForegroundWindow(top); + SetActiveWindow(top); + } + else + { + { + CSettingsLockWrite lock; + g_SettingsManager.LoadSettings(true); + UpdateSettings(); + } + DLGTEMPLATE *pTemplate=LoadDialogEx(IDD_SETTINGS); + g_SettingsManager.ResetImageList(); + g_SettingsDlg.Init(g_SettingsManager.GetSettings(),g_SettingsManager.GetCustom(),tab); + g_SettingsDlg.Create(NULL,pTemplate); + g_SettingsDlg.SetWindowText(title); + g_SettingsDlg.SetWindowPos(HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|(g_SettingsDlg.GetOnTop()?0:SWP_NOZORDER)|SWP_SHOWWINDOW); + SetForegroundWindow(g_SettingsDlg.m_hWnd); + if (bModal) + { + MSG msg; + while (g_SettingsDlg.m_hWnd && GetMessage(&msg,0,0,0)) + { + if (IsSettingsMessage(&msg)) continue; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } +} + +void CloseSettings( void ) +{ + if (g_SettingsDlg.m_hWnd) + g_SettingsDlg.DestroyWindow(); +} + +void SetSettingsDirty( void ) +{ + g_SettingsDlg.SetDirty(); +} + +void SelectSettingsTab( int tab, bool bAdvanced, const CSetting *pSelect ) +{ + if (g_SettingsDlg.m_hWnd) + { + g_SettingsDlg.GetDlgItem(IDC_CHECKALL).EnableWindow(TRUE); + if (bAdvanced && g_SettingsDlg.m_bBasic) + { + g_SettingsDlg.m_bBasic=false; + g_SettingsDlg.CheckDlgButton(IDC_CHECKALL,BST_CHECKED); + } + g_SettingsDlg.AddTabs(tab,pSelect); + } +} + +// Process the dialog messages for the settings box +bool IsSettingsMessage( MSG *msg ) +{ + if (!g_SettingsDlg) return false; + if (msg->hwnd!=g_SettingsDlg && !IsChild(g_SettingsDlg,msg->hwnd)) return false; + // only process keyboard messages. if we process all messages the settings box gets stuck. I don't know why. + if (msg->messagemessage>WM_KEYLAST) return false; + + // don't process any messages if a menu is up + GUITHREADINFO threadInfo={sizeof(threadInfo)}; + GetGUIThreadInfo(GetCurrentThreadId(),&threadInfo); + if (threadInfo.flags&(GUI_INMENUMODE|GUI_INMOVESIZE)) return false; + + // handle global keys + if (msg->message==WM_KEYDOWN && msg->wParam==VK_TAB && GetKeyState(VK_CONTROL)<0) + { + g_SettingsDlg.SendMessage(WM_KEYDOWN,VK_TAB,msg->lParam); + return true; + } + if (msg->message==WM_KEYDOWN && msg->wParam==VK_RETURN && GetKeyState(VK_CONTROL)<0) + { + g_SettingsDlg.SendMessage(WM_COMMAND,IDOK,0); + return true; + } + if (msg->message==WM_KEYDOWN && msg->wParam==VK_F1 && GetKeyState(VK_CONTROL)>=0 && GetKeyState(VK_SHIFT)>=0 && GetKeyState(VK_MENU)>=0) + { + ShowHelp(); + } + if (msg->message==WM_KEYDOWN && (msg->wParam==VK_F3 || (msg->wParam=='F' && GetKeyState(VK_CONTROL)<0))) + { + g_SettingsDlg.GotoDlgCtrl(g_SettingsDlg.GetDlgItem(IDC_EDITSEARCH)); + return true; + } + return IsDialogMessage(g_SettingsDlg,msg)!=0; +} + +bool ImportSettingsXml( const wchar_t *fname ) +{ +#ifdef _DEBUG + g_bUIThread=true; // hack to allow settings to be loaded by this thread +#endif + CString error=g_SettingsManager.LoadSettingsXml(fname); + if (error.IsEmpty()) + { + g_SettingsManager.SaveSettings(false); + return true; + } + + if (AttachConsole(ATTACH_PARENT_PROCESS)) + { + HANDLE hConsole=GetStdHandle(STD_OUTPUT_HANDLE); + DWORD q; + WriteConsole(hConsole,L"\r\n",2,&q,0); + WriteConsole(hConsole,(const wchar_t*)error,error.GetLength(),&q,0); + WriteConsole(hConsole,L"\r\n",2,&q,0); + } + return false; +} + +bool ExportSettingsXml( const wchar_t *fname ) +{ +#ifdef _DEBUG + g_bUIThread=true; // hack to allow settings to be loaded by this thread +#endif + CString error=g_SettingsManager.SaveSettingsXml(fname); + if (error.IsEmpty()) + return true; + + if (AttachConsole(ATTACH_PARENT_PROCESS)) + { + HANDLE hConsole=GetStdHandle(STD_OUTPUT_HANDLE); + DWORD q; + WriteConsole(hConsole,L"\r\n",2,&q,0); + WriteConsole(hConsole,(const wchar_t*)error,error.GetLength(),&q,0); + WriteConsole(hConsole,L"\r\n",2,&q,0); + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + +void InitSettings( CSetting *pSettings, TSettingsComponent component, ICustomSettings *pCustom ) +{ + g_SettingsManager.Init(pSettings,component,pCustom); +} + +void LoadSettings( void ) +{ + CSettingsLockWrite lock; + g_SettingsManager.LoadSettings(false); + g_SettingsManager.LoadSettings(true); +} + +void SaveSettings( void ) +{ +#ifdef _DEBUG + g_bUIThread=true; +#endif + CSettingsLockRead lock; + g_SettingsManager.SaveSettings(false); + g_SettingsManager.SaveSettings(true); +} + +void UpdateDefaultSettings( void ) +{ + if (!g_SettingsDlg.m_hWnd) + UpdateSettings(); +} + +bool GetSettingBool( const wchar_t *name ) +{ + return g_SettingsManager.GetSettingBool(name); +} + +int GetSettingInt( const wchar_t *name ) +{ + return g_SettingsManager.GetSettingInt(name); +} + +int GetSettingInt( const wchar_t *name, bool &bDef ) +{ + return g_SettingsManager.GetSettingInt(name,bDef); +} + +bool GetSettingBool( const wchar_t *name, bool &bDef ) +{ + return g_SettingsManager.GetSettingBool(name,bDef); +} + +CString GetSettingString( const wchar_t *name ) +{ + return g_SettingsManager.GetSettingString(name); +} + +HIMAGELIST GetSettingsImageList( HWND tree ) +{ + return g_SettingsManager.GetImageList(tree); +} + +const wchar_t *GetSettingsRegPath( void ) +{ + return g_SettingsManager.GetRegPath(); +} + +// Finds a setting by name +CSetting *FindSetting( const wchar_t *name ) +{ + Assert(g_LockState==2); // must be locked for writing + for (CSetting *pSetting=g_SettingsManager.GetSettings();pSetting->name;pSetting++) + if (pSetting->type>=0 && wcscmp(pSetting->name,name)==0) + return pSetting; + Assert(0); + return NULL; +} + +bool IsSettingLocked( const wchar_t *name ) +{ + for (CSetting *pSetting=g_SettingsManager.GetSettings();pSetting->name;pSetting++) + if (pSetting->type>=0 && wcscmp(pSetting->name,name)==0) + { + Assert(!pSetting->pLinkTo); + CSettingsLockRead lock; + return (pSetting->flags&CSetting::FLAG_LOCKED_MASK)!=0; + } + Assert(0); + return false; +} + +bool IsSettingForcedDefault( const wchar_t *name ) +{ + for (CSetting *pSetting=g_SettingsManager.GetSettings();pSetting->name;pSetting++) + if (pSetting->type>=0 && wcscmp(pSetting->name,name)==0) + { + Assert(!pSetting->pLinkTo); + CSettingsLockRead lock; + return pSetting->IsForcedDefault(); + } + Assert(0); + return false; +} + +// Updates the setting with a new default value and locked flag +void UpdateSetting( const wchar_t *name, const CComVariant &defValue, bool bLockedGP ) +{ + CSetting *pSetting=FindSetting(name); + Assert(pSetting && !pSetting->pLinkTo); + if (bLockedGP) + pSetting->flags|=CSetting::FLAG_LOCKED_GP|CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_LOCKED_GP; + if (!(pSetting->flags&CSetting::FLAG_FORCED_DEFAULT)) + pSetting->defValue=defValue; + if (pSetting->flags&CSetting::FLAG_DEFAULT) + pSetting->value=pSetting->defValue; +} + +// Updates the setting with a new text and a warning flag +void UpdateSettingText( const wchar_t *name, int nameID, int tipID, bool bWarning ) +{ + CSetting *pSetting=FindSetting(name); + if (bWarning) + pSetting->flags|=CSetting::FLAG_WARNING; + else + pSetting->flags&=~CSetting::FLAG_WARNING; + if (nameID>=0) + pSetting->nameID=nameID; + if (tipID>=0) + pSetting->tipID=tipID; +} + +void HideSetting( const wchar_t *name, bool bHide ) +{ + CSetting *pSetting=FindSetting(name); + Assert(pSetting); + if (bHide) + pSetting->flags|=CSetting::FLAG_HIDDEN; + else + pSetting->flags&=~CSetting::FLAG_HIDDEN; +} + +void HideSettingGroup( const wchar_t *name, bool bHide ) +{ + Assert(g_LockState==2); // must be locked for writing + for (CSetting *pSetting=g_SettingsManager.GetSettings();pSetting->name;pSetting++) + if (pSetting->type==CSetting::TYPE_GROUP && wcscmp(pSetting->name,name)==0) + { + if (bHide) + pSetting->flags|=CSetting::FLAG_HIDDEN; + else + pSetting->flags&=~CSetting::FLAG_HIDDEN; + return; + } + Assert(0); +} + +void UpdateGroupText( const wchar_t *name, int nameID ) +{ + Assert(g_LockState==2); // must be locked for writing + for (CSetting *pSetting=g_SettingsManager.GetSettings();pSetting->name;pSetting++) + if (pSetting->type==CSetting::TYPE_GROUP && wcscmp(pSetting->name,name)==0) + { + pSetting->nameID=nameID; + return; + } + Assert(0); +} + +const CSetting *GetAllSettings( void ) +{ + Assert(g_bUIThread); + return g_SettingsManager.GetSettings(); +} + +void SetSettingsStyle( int style, int mask ) +{ + Assert((style&~mask)==0); + if (g_SettingsManager.SetSettingsStyle(style,mask) && g_SettingsDlg.m_hWnd) + g_SettingsDlg.PostMessage(WM_CLEAR); +} + +void GetSettingsStyle( int &style, int &mask ) +{ + g_SettingsManager.GetSettingsStyle(style,mask); +} + +bool HasHelp( void ) +{ + wchar_t path[_MAX_PATH]; + GetModuleFileName(_AtlBaseModule.GetResourceInstance(),path,_countof(path)); + *PathFindFileName(path)=0; + wchar_t topic[_MAX_PATH]; + Sprintf(topic,_countof(topic),L"%s%sClassicShell.chm",path,GetDocRelativePath()); + return (GetFileAttributes(topic)!=INVALID_FILE_ATTRIBUTES); +} + +void ShowHelp( void ) +{ + wchar_t path[_MAX_PATH]; + GetModuleFileName(_AtlBaseModule.GetResourceInstance(),path,_countof(path)); + *PathFindFileName(path)=0; + wchar_t topic[_MAX_PATH]; + Sprintf(topic,_countof(topic),L"%s%sClassicShell.chm::/%s.html",path,GetDocRelativePath(),PathFindFileName(g_SettingsManager.GetRegPath())); + HtmlHelp(GetDesktopWindow(),topic,HH_DISPLAY_TOPIC,NULL); +} + +// Opens the registry keys for the settings of the given component +// Returns true if the user settings were read from the old HKCU location. That means the settings may need to be upgraded +bool OpenSettingsKeys( TSettingsComponent component, CRegKey ®Settings, CRegKey ®SettingsUser, CRegKey ®Policy, CRegKey ®PolicyUser ) +{ + const wchar_t *regPath, *gpPath; + GetRegPaths(component,regPath,gpPath); + return OpenSettingsKeys(regPath,gpPath,regSettings,regSettingsUser,regPolicy,regPolicyUser); +} + +bool GetSettingBool( const CSetting &setting ) +{ + Assert(setting.type==CSetting::TYPE_BOOL); + return setting.value.vt==VT_I4 && setting.value.intVal==1; +} + +CString GetSettingString( const CSetting &setting ) +{ + Assert(setting.type==CSetting::TYPE_STRING); + if (setting.value.vt!=VT_BSTR) + return CString(); + return setting.value.bstrVal; +} + +#ifndef _WIN64 + +namespace +{ +enum TSupportedOn +{ + SUPPORTED_NEVER, + SUPPORTED_ALWAYS, + SUPPORTED_WIN7, + SUPPORTED_WIN78, + SUPPORTED_WIN781, + SUPPORTED_WIN8, + SUPPORTED_WIN881, + SUPPORTED_WIN81, + SUPPORTED_CLASSIC1_STYLE, + SUPPORTED_CLASSIC2_STYLE, + SUPPORTED_CLASSIC_STYLE, + SUPPORTED_WIN7_STYLE, +}; + +struct AdmxDoc +{ + AdmxDoc( void ) { supportedOn=SUPPORTED_ALWAYS; } + TSupportedOn supportedOn; + CStringA text; + CStringA nameOverride; + CStringA tipOverride; + CStringA tipAddition; +}; + +} + +static bool ParseAdmxDoc( const char *docFile, std::map &docMap ) +{ + FILE *fDoc; + if (fopen_s(&fDoc,docFile,"rt")!=0) + return false; + + char buf[2048]; + while (fgets(buf,_countof(buf),fDoc)) + { + const char *str=buf; + if (str[0]==(char)0xEF && str[1]==(char)0xBB && str[2]==(char)0xBF) + str+=3; + if (str[0]==';') continue; + char name[100]; + str=GetToken(str,name,_countof(name),". \r\n"); + char setting[100]; + str=GetToken(str,setting,_countof(setting),"= \r\n"); + while (*str==' ' || *str=='=') + str++; + char value[2048]; + GetToken(str,value,_countof(value),"\r\n"); + str=value; + CString nameStr(name); + if (strcmp(setting,"text")==0) + docMap[L"%"+nameStr+L"%"].text=str; + else if (strcmp(setting,"supportedOn")==0) + { + if (_stricmp(str,"never")==0) + docMap[nameStr].supportedOn=SUPPORTED_NEVER; + else if (_stricmp(str,"always")==0) + docMap[nameStr].supportedOn=SUPPORTED_ALWAYS; + else if (_stricmp(str,"win7")==0) + docMap[nameStr].supportedOn=SUPPORTED_WIN7; + else if (_stricmp(str,"win78")==0) + docMap[nameStr].supportedOn=SUPPORTED_WIN78; + else if (_stricmp(str,"win781")==0) + docMap[nameStr].supportedOn=SUPPORTED_WIN781; + else if (_stricmp(str,"win8")==0) + docMap[nameStr].supportedOn=SUPPORTED_WIN8; + else if (_stricmp(str,"win881")==0) + docMap[nameStr].supportedOn=SUPPORTED_WIN881; + else if (_stricmp(str,"win81")==0) + docMap[nameStr].supportedOn=SUPPORTED_WIN81; + else if (_stricmp(str,"classic1")==0) + docMap[nameStr].supportedOn=SUPPORTED_CLASSIC1_STYLE; + else if (_stricmp(str,"classic2")==0) + docMap[nameStr].supportedOn=SUPPORTED_CLASSIC2_STYLE; + else if (_stricmp(str,"classic")==0) + docMap[nameStr].supportedOn=SUPPORTED_CLASSIC_STYLE; + else if (_stricmp(str,"win7_style")==0) + docMap[nameStr].supportedOn=SUPPORTED_WIN7_STYLE; + } + else if (strcmp(setting,"nameOverride")==0) + { + docMap[nameStr].nameOverride=str; + } + else if (strcmp(setting,"tipOverride")==0) + { + docMap[nameStr].tipOverride=str; + docMap[nameStr].tipOverride.Replace("\\n","\r\n"); + } + else if (strcmp(setting,"tipAddition")==0) + { + docMap[nameStr].tipAddition=str; + docMap[nameStr].tipAddition.Replace("\\n","\r\n"); + } + } + + fclose(fDoc); + return true; +} + +static CStringA EscapeXmlString( CStringA text ) +{ + text.Replace("&","&"); + text.Replace("<","<"); + text.Replace(">",">"); + text.Replace("\"","""); + return text; +} + +static CStringA ReplaceStrings( CStringA text, const std::map &doc ) +{ + for (int i=0;ii) + { + CStringA key=text.Mid(i,end-i+1); + const std::map::const_iterator it=doc.find(CString(key)); + if (it!=doc.end()) + { + text.Replace(key,EscapeXmlString(CStringA(it->second.text))); + } + else + { + Assert(0); + } + } + } + } + return text; +} + +static CStringA LoadStringUTF8( int stringID ) +{ + CString wstr=LoadStringEx(stringID); + CStringA str; + if (!wstr.IsEmpty()) + { + int len=WideCharToMultiByte(CP_UTF8,0,wstr,-1,NULL,0,NULL,NULL)-1; + if (len>0) + { + char *buf=str.GetBuffer(len); + WideCharToMultiByte(CP_UTF8,0,wstr,-1,buf,len,NULL,NULL); + str.ReleaseBufferSetLength(len); + } + } + return str; +} + +static const char *g_AdmxText1a= +"\r\n" +"\r\n" +"\t\r\n"; + +static const char *g_AdmxText1cs= +"\t\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\t\r\n" +"\t\t\t\r\n" +"\t\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\t\r\n"; + +static const char *g_AdmxText1csm= +"\t\t\r\n" +"\t\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\t\r\n" +"\t\t\t\r\n" +"\t\t\t\r\n" +"\t\t\t\r\n" +"\t\t\t\r\n" +"\t\t\t\r\n" +"\t\t\t\r\n" +"\t\t\t\r\n" +"\t\t\t\r\n" +"\t\t\t\r\n" +"\t\t\t\r\n" +"\t\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\t\r\n" +"\t\t\t\r\n" +"\t\t\r\n"; + +static const char *g_AdmxText1ce= +"\t\t\r\n" +"\t\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\t\r\n" +"\t\t\t\r\n" +"\t\t\t\r\n" +"\t\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\t\r\n" +"\t\t\t\r\n" +"\t\t\r\n"; + +static const char *g_AdmxText1cie= +"\t\t\r\n" +"\t\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\t\r\n" +"\t\t\t\r\n" +"\t\t\r\n" +"\t\r\n" +"\t\r\n" +"\t\t\r\n" +"\t\t\t\r\n" +"\t\t\r\n"; + +static const char *g_AdmxText1b= +"\t\r\n" +"\t\r\n"; + +static const char *g_AdmxText2= +"\t\r\n" +"\r\n"; + +static const char *g_AdmlText1a= +"\r\n" +"\r\n" +"\t%Title%\r\n" +"\t%Title%\r\n" +"\t\r\n" +"\t\t\r\n" +"\t\t\t%State1%\r\n" +"\t\t\t%State2%\r\n" +"\t\t\t%State3%\r\n"; + +static const char *g_AdmlText1cs= +"\t\t\t%ClassicShellCat%\r\n" +"\t\t\t%ClassicShellCatHelp%\r\n" +"\t\t\t%SUPPORTED_CS404%\r\n"; + +static const char *g_AdmlText1csm= +"\t\t\t%ClassicStartMenuCat%\r\n" +"\t\t\t%ClassicStartMenuCatHelp%\r\n" +"\t\t\t%SUPPORTED_CS404%\r\n" +"%SUPPORTED_CS404_WIN7%\r\n" +"\t\t\t%SUPPORTED_CS404%\r\n" +"%SUPPORTED_CS404_WIN78%\r\n" +"\t\t\t%SUPPORTED_CS404%\r\n" +"%SUPPORTED_CS404_WIN781%\r\n" +"\t\t\t%SUPPORTED_CS404%\r\n" +"%SUPPORTED_CS404_WIN8%\r\n" +"\t\t\t%SUPPORTED_CS404%\r\n" +"%SUPPORTED_CS404_WIN881%\r\n" +"\t\t\t%SUPPORTED_CS404%\r\n" +"%SUPPORTED_CS404_WIN81%\r\n" +"\t\t\t%SUPPORTED_CS404%\r\n" +"%SUPPORTED_CS404_CLASSIC1_STYLE%\r\n" +"\t\t\t%SUPPORTED_CS404%\r\n" +"%SUPPORTED_CS404_CLASSIC2_STYLE%\r\n" +"\t\t\t%SUPPORTED_CS404%\r\n" +"%SUPPORTED_CS404_CLASSIC_STYLE%\r\n" +"\t\t\t%SUPPORTED_CS404%\r\n" +"%SUPPORTED_CS404_WIN7_STYLE%\r\n"; + +static const char *g_AdmlText1ce= +"\t\t\t%ClassicExplorerCat%\r\n" +"\t\t\t%ClassicExplorerCatHelp%\r\n" +"\t\t\t%SUPPORTED_CS404%\r\n" +"%SUPPORTED_CS404_WIN7%\r\n" +"\t\t\t%SUPPORTED_CS404%\r\n" +"%SUPPORTED_CS404_WIN881%\r\n"; + +static const char *g_AdmlText1cie= +"\t\t\tClassic IE\r\n" +"\t\t\tClassic IE group policy settings\r\n" +"\t\t\t%SUPPORTED_CS404%\r\n" +"%SUPPORTED_IE9%\r\n"; + +static const char *g_AdmlText2= +"\t\t\r\n" +"\t\t\r\n"; + +static const char *g_AdmlText3= +"\t\t\r\n" +"\t\r\n" +"\r\n"; + +static const char *g_StateTip= +"%State1Help%\r\n\r\n" +"%State2Help%\r\n\r\n" +"%State3Help%\r\n"; + +bool SaveAdmx( TSettingsComponent component, const char *admxFile, const char *admlFile, const char *docFile ) +{ + const char *keyName, *prefix, *catName; + const char *admxText1, *admlText1; + switch (component) + { + case COMPONENT_EXPLORER: + keyName="Software\\Policies\\IvoSoft\\ClassicExplorer"; + prefix="CE_"; + catName="ClassicExplorer"; + admxText1=g_AdmxText1ce; + admlText1=g_AdmlText1ce; + break; + case COMPONENT_MENU: + keyName="Software\\Policies\\IvoSoft\\ClassicStartMenu"; + prefix="CSM_"; + catName="ClassicStartMenu"; + admxText1=g_AdmxText1csm; + admlText1=g_AdmlText1csm; + break; + case COMPONENT_IE: + keyName="Software\\Policies\\IvoSoft\\ClassicIE"; + prefix="CIE_"; + catName="ClassicIE"; + admxText1=g_AdmxText1cie; + admlText1=g_AdmlText1cie; + break; + case COMPONENT_SHARED: + keyName="Software\\Policies\\IvoSoft\\ClassicShell"; + prefix="CS_"; + catName="ClassicShell"; + admxText1=g_AdmxText1cs; + admlText1=g_AdmlText1cs; + break; + } + + std::map docMap; + if (!ParseAdmxDoc(docFile,docMap)) + return false; + + FILE *fAdmx, *fAdml; + + if (fopen_s(&fAdmx,admxFile,"wb")!=0) + return false; + + if (fopen_s(&fAdml,admlFile,"wb")!=0) + { + fclose(fAdmx); + return false; + } + + fprintf_s(fAdmx,g_AdmxText1a); + fprintf_s(fAdmx,admxText1); + fprintf_s(fAdmx,g_AdmxText1b); + + fprintf_s(fAdml,"%s",ReplaceStrings(CStringA(g_AdmlText1a),docMap)); + fprintf_s(fAdml,"%s",ReplaceStrings(CStringA(admlText1),docMap)); + + // policies and strings + int stringIdx=1; + for (CSetting *pSetting=g_SettingsManager.GetSettings();pSetting->name;pSetting++) + { + if (pSetting->pLinkTo || pSetting->type==CSetting::TYPE_GROUP || pSetting->type==CSetting::TYPE_RADIO) + continue; + + if (pSetting->flags&CSetting::FLAG_SHARED) + { + if (component!=COMPONENT_SHARED) continue; + } + else + { + if (component==COMPONENT_SHARED) continue; + } + + AdmxDoc doc0; + const AdmxDoc *pDoc=&doc0; + { + std::map::const_iterator it=docMap.find(pSetting->name); + if (it!=docMap.end()) + pDoc=&it->second; + } + if (pDoc->supportedOn==SUPPORTED_NEVER) + continue; + + // name string + int nameIdx=stringIdx++; + fprintf_s(fAdml,"\t\t\t%s\r\n",prefix,nameIdx,EscapeXmlString(pDoc->nameOverride.IsEmpty()?LoadStringUTF8(pSetting->nameID):pDoc->nameOverride)); + + // tip string + int tipIdx=stringIdx++; + CStringA tip=pDoc->tipOverride; + if (tip.IsEmpty()) tip=LoadStringUTF8(pSetting->tipID); + tip+=pDoc->tipAddition; + fprintf_s(fAdml,"\t\t\t%s\r\n\r\n%s\r\n",prefix,tipIdx,EscapeXmlString(tip),ReplaceStrings(g_StateTip,docMap)); + + // policy + fprintf_s(fAdmx,"\t\t\r\n", + prefix,pSetting->name,prefix,nameIdx,prefix,tipIdx,prefix,pSetting->name,keyName); + fprintf_s(fAdmx,"\t\t\t\r\n",catName); + switch (pDoc->supportedOn) + { + case SUPPORTED_WIN7: + fprintf_s(fAdmx,"\t\t\t\r\n"); + break; + case SUPPORTED_WIN78: + fprintf_s(fAdmx,"\t\t\t\r\n"); + break; + case SUPPORTED_WIN781: + fprintf_s(fAdmx,"\t\t\t\r\n"); + break; + case SUPPORTED_WIN8: + fprintf_s(fAdmx,"\t\t\t\r\n"); + break; + case SUPPORTED_WIN881: + fprintf_s(fAdmx,"\t\t\t\r\n"); + break; + case SUPPORTED_WIN81: + fprintf_s(fAdmx,"\t\t\t\r\n"); + break; + case SUPPORTED_CLASSIC1_STYLE: + fprintf_s(fAdmx,"\t\t\t\r\n"); + break; + case SUPPORTED_CLASSIC2_STYLE: + fprintf_s(fAdmx,"\t\t\t\r\n"); + break; + case SUPPORTED_CLASSIC_STYLE: + fprintf_s(fAdmx,"\t\t\t\r\n"); + break; + case SUPPORTED_WIN7_STYLE: + fprintf_s(fAdmx,"\t\t\t\r\n"); + break; + default: + if (component==COMPONENT_SHARED || component==COMPONENT_IE) + fprintf_s(fAdmx,"\t\t\t\r\n"); + else + fprintf_s(fAdmx,"\t\t\t\r\n"); + break; + } + fprintf_s(fAdmx,"\t\t\t\r\n"); + + fprintf_s(fAdmx,"\t\t\t\t\r\n",pSetting->name); + fprintf_s(fAdmx,"\t\t\t\t\t\r\n",pSetting->name); + fprintf_s(fAdmx,"\t\t\t\t\t\r\n",pSetting->name); + fprintf_s(fAdmx,"\t\t\t\t\t\r\n",pSetting->name); + fprintf_s(fAdmx,"\t\t\t\t\r\n"); + + if (pSetting->type==CSetting::TYPE_BOOL) + { + fprintf_s(fAdmx,"\t\t\t\t\r\n",pSetting->name); + fprintf_s(fAdmx,"\t\t\t\t\t\r\n",pSetting->name); + fprintf_s(fAdmx,"\t\t\t\t\t\r\n",pSetting->name); + fprintf_s(fAdmx,"\t\t\t\t\r\n"); + } + else if (pSetting->type==CSetting::TYPE_INT && pSetting[1].type==CSetting::TYPE_RADIO) + { + // radio options + fprintf_s(fAdmx,"\t\t\t\t\r\n",pSetting->name); + for (int i=1;pSetting[i].type==CSetting::TYPE_RADIO;i++) + { + const AdmxDoc *pRadioDoc=&doc0; + { + wchar_t name[100]; + Sprintf(name,_countof(name),L"%s_%s",pSetting->name,pSetting[i].name); + std::map::const_iterator it=docMap.find(name); + if (it!=docMap.end()) + pRadioDoc=&it->second; + } + + int radioIdx=stringIdx++; + fprintf_s(fAdml,"\t\t\t%s\r\n",prefix,radioIdx,pRadioDoc->nameOverride.IsEmpty()?LoadStringUTF8(pSetting[i].nameID):pRadioDoc->nameOverride); + fprintf_s(fAdmx,"\t\t\t\t\t%S\r\n",prefix,radioIdx,pSetting[i].name); + } + fprintf_s(fAdmx,"\t\t\t\t\r\n"); + } + else if (pSetting->type==CSetting::TYPE_INT || pSetting->type==CSetting::TYPE_HOTKEY || pSetting->type==CSetting::TYPE_HOTKEY_ANY || pSetting->type==CSetting::TYPE_COLOR) + { + fprintf_s(fAdmx,"\t\t\t\t\r\n",pSetting->name); + } + else if (pSetting->type==CSetting::TYPE_STRING || pSetting->type==CSetting::TYPE_ICON || pSetting->type==CSetting::TYPE_BITMAP || pSetting->type==CSetting::TYPE_BITMAP_JPG || pSetting->type==CSetting::TYPE_SOUND || pSetting->type==CSetting::TYPE_FONT) + { + fprintf_s(fAdmx,"\t\t\t\t\r\n",pSetting->name); + } + else if (pSetting->type==CSetting::TYPE_MULTISTRING) + { + fprintf_s(fAdmx,"\t\t\t\t\r\n",pSetting->name); + } + else + { + Assert(0); + } + + fprintf_s(fAdmx,"\t\t\t\r\n"); + fprintf_s(fAdmx,"\t\t\r\n\r\n"); + } + + fprintf_s(fAdml,g_AdmlText2); + + CStringA stateText=ReplaceStrings(CStringA("\t\t\t\t%State%\r\n"),docMap); + // presentation + for (CSetting *pSetting=g_SettingsManager.GetSettings();pSetting->name;pSetting++) + { + if (pSetting->pLinkTo || pSetting->type==CSetting::TYPE_GROUP || pSetting->type==CSetting::TYPE_RADIO) + continue; + + if (pSetting->flags&CSetting::FLAG_SHARED) + { + if (component!=COMPONENT_SHARED) continue; + } + else + { + if (component==COMPONENT_SHARED) continue; + } + + AdmxDoc doc0; + const AdmxDoc *pDoc=&doc0; + std::map::const_iterator it=docMap.find(pSetting->name); + if (it!=docMap.end()) + pDoc=&it->second; + if (pDoc->supportedOn==SUPPORTED_NEVER) + continue; + + fprintf_s(fAdml,"\t\t\t\r\n",prefix,pSetting->name); + fprintf_s(fAdml,stateText); + + CStringA name=EscapeXmlString(pDoc->nameOverride.IsEmpty()?LoadStringUTF8(pSetting->nameID):pDoc->nameOverride); + + if (pSetting->type==CSetting::TYPE_BOOL) + { + fprintf_s(fAdml,"\t\t\t\t%s\r\n",name); + } + else if (pSetting->type==CSetting::TYPE_INT && pSetting[1].type==CSetting::TYPE_RADIO) + { + fprintf_s(fAdml,"\t\t\t\t%s\r\n",name); + } + else if (pSetting->type==CSetting::TYPE_INT || pSetting->type==CSetting::TYPE_HOTKEY || pSetting->type==CSetting::TYPE_HOTKEY_ANY || pSetting->type==CSetting::TYPE_COLOR) + { + fprintf_s(fAdml,"\t\t\t\t%s\r\n",name); + } + else if (pSetting->type==CSetting::TYPE_STRING || pSetting->type==CSetting::TYPE_ICON || pSetting->type==CSetting::TYPE_BITMAP || pSetting->type==CSetting::TYPE_BITMAP_JPG || pSetting->type==CSetting::TYPE_SOUND || pSetting->type==CSetting::TYPE_FONT) + { + fprintf_s(fAdml,"\t\t\t\t\r\n",name); + } + else if (pSetting->type==CSetting::TYPE_MULTISTRING) + { + fprintf_s(fAdml,"\t\t\t\t%s\r\n",name); + } + fprintf_s(fAdml,"\t\t\t\r\n"); + } + + fprintf_s(fAdmx,g_AdmxText2); + fprintf_s(fAdml,g_AdmlText3); + + fclose(fAdmx); + fclose(fAdml); + return true; +} + +#endif + +static wchar_t g_LogFileName[_MAX_PATH]; + +void VLogToFile( const wchar_t *location, const wchar_t *message, va_list args ) +{ + if (g_LogFileName[0]==0) + { + g_LogFileName[0]='*'; + wchar_t token[_MAX_PATH]; + location=GetToken(location,token,_countof(token),L"|"); + if (token[0]!='-') + { + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,token,KEY_READ|KEY_WOW64_64KEY)!=ERROR_SUCCESS) + return; + DWORD log; + location=GetToken(location,token,_countof(token),L"|"); + if (regKey.QueryDWORDValue(token,log)!=ERROR_SUCCESS || log==0) + return; + } + location=GetToken(location,token,_countof(token),L"|"); + DoEnvironmentSubst(token,_countof(token)); + Strcpy(g_LogFileName,_countof(g_LogFileName),token); + PathRemoveFileSpec(token); + SHCreateDirectory(NULL,token); + } + if (g_LogFileName[0]!='*') + { + wchar_t text[1024]; + int len=Sprintf(text,_countof(text),L"%10u %5u ",GetTickCount(),GetCurrentProcessId()); + len+=Vsprintf(text+len,_countof(text)-2-len,message,args); + Strcpy(text+len,3,L"\r\n"); + len+=2; + FILE *f; + if (_wfopen_s(&f,g_LogFileName,L"ab")==0) + { + fseek(f,0,SEEK_END); + if (ftell(f)==0) + fwrite(L"\xFEFF",2,1,f); + fwrite(text,2,len,f); + fclose(f); + } + } +} + +void LogToFile( const wchar_t *location, const wchar_t *message, ... ) +{ + if (g_LogFileName[0]=='*') return; + va_list args; + va_start(args,message); + VLogToFile(location,message,args); + va_end(args); +} diff --git a/ClassicShellSrc/ClassicShellLib/Settings.h b/ClassicShellSrc/ClassicShellLib/Settings.h new file mode 100644 index 0000000..0ae3c00 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/Settings.h @@ -0,0 +1,196 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +class ISettingsPanel +{ +public: + virtual HWND Create( HWND parent )=0; + virtual HWND Activate( struct CSetting *pGroup, const RECT &rect, bool bReset )=0; + virtual bool Validate( HWND parent )=0; +}; + +struct CSetting +{ + enum Type + { + TYPE_GROUP=-2, + TYPE_RADIO=-1, + TYPE_BOOL=1, + TYPE_INT, + TYPE_HOTKEY, + TYPE_HOTKEY_ANY, + TYPE_COLOR, // requires the high 8 bits of the flags to contain an index into the color palette + + // string types + TYPE_STRING, + TYPE_ICON, + TYPE_BITMAP, + TYPE_BITMAP_JPG, + TYPE_SOUND, + TYPE_FONT, + TYPE_MULTISTRING, + }; + + enum + { + // initial settings + FLAG_WARM= 0x00001, + FLAG_COLD= 0x00002, + FLAG_BASIC= 0x00004, + FLAG_HIDDEN= 0x00008, + FLAG_SHARED= 0x00010, + FLAG_NORESET= 0x00020, + FLAG_NODEFAULT= 0x00040, + FLAG_NOSAVE= 0x00080, + FLAG_CALLBACK= 0x00100, + + FLAG_MENU_CLASSIC1= 0x00200, + FLAG_MENU_CLASSIC2= 0x00400, + FLAG_MENU_CLASSIC_BOTH=FLAG_MENU_CLASSIC1|FLAG_MENU_CLASSIC2, + FLAG_MENU_WIN7= 0x00800, + FLAG_MENU_MASK=FLAG_MENU_CLASSIC1|FLAG_MENU_CLASSIC2|FLAG_MENU_WIN7, + + // for run-time use only + FLAG_DEFAULT= 0x01000, + FLAG_FORCED_DEFAULT= 0x02000, + FLAG_LOCKED_REG= 0x04000, // locked by HKLM registry setting + FLAG_LOCKED_GP= 0x08000, // locked by a group policy + FLAG_LOCKED_MASK=FLAG_LOCKED_REG|FLAG_LOCKED_GP, + FLAG_WARNING= 0x10000, // show a warning icon + // top 8 bits need to stay unused. that's where we store the color index + }; + + const wchar_t *name; + Type type; + int nameID, tipID; // resource strings + CComVariant defValue; // default value + unsigned int flags; + const wchar_t *depend; + const wchar_t *nest; + ISettingsPanel *pPanel; // custom panel for editing this group of settings + + CSetting *pLinkTo; // if this is not NULL, then the value is stored in the linked setting (the default value, radio settings, etc. must match between the two) + + // runtime use only + CComVariant value; // current value + CComVariant tempValue; // the value is stored here when editing begins and restored if the editing is canceled + unsigned int tempFlags; + + bool IsEnabled( void ) const; + bool IsDefault( void ) const { return ((pLinkTo?pLinkTo->flags:flags)&FLAG_DEFAULT)!=0; } + bool IsForcedDefault( void ) const { return ((pLinkTo?pLinkTo->flags:flags)&FLAG_FORCED_DEFAULT)!=0; } + bool IsLocked( void ) const { return ((pLinkTo?pLinkTo->flags:flags)&FLAG_LOCKED_MASK)!=0; } + bool IsLockedReg( void ) const { return ((pLinkTo?pLinkTo->flags:flags)&FLAG_LOCKED_REG)!=0; } + bool ShouldLoad( bool bShared ) const; + bool MatchFilter( const wchar_t *filter ) const; + const CComVariant &GetValue( void ) const { return pLinkTo?pLinkTo->value:value; } + + void LoadValue( CRegKey ®Settings, CRegKey ®SettingsUser, CRegKey ®Policy, CRegKey ®PolicyUser ); + +private: + bool ReadValue( CRegKey ®Key, const wchar_t *valName ); +}; + +// Images in the tree image list +enum { + SETTING_STATE_NONE=1, + SETTING_STATE_SETTING=2, + SETTING_STATE_CHECKBOX=4, + SETTING_STATE_RADIO=8, + + // additional flags + SETTING_STATE_DISABLED=1, + SETTING_STATE_CHECKED=2, + + SETTING_IMAGE_COLOR=13, // 10 blank images to use for custom colors +}; + +enum TSettingsComponent +{ + COMPONENT_EXPLORER, + COMPONENT_MENU, + COMPONENT_IE, + COMPONENT_UPDATE, + COMPONENT_SHARED, +}; + +class ICustomSettings +{ +public: + virtual int AppendBackupMenu( HMENU menu, int id ) = 0; + virtual void ExecuteBackupMenu( int id ) = 0; +}; + +void InitSettings( CSetting *pSettings, TSettingsComponent component, ICustomSettings *pCustom ); +void LoadSettings( void ); +void SaveSettings( void ); +void UpdateDefaultSettings( void ); +void EditSettings( const wchar_t *title, bool bModal, int tab ); +void CloseSettings( void ); +void SetSettingsDirty( void ); +void SelectSettingsTab( int tab, bool bAdvanced, const CSetting *pSelect ); +void UpdateSettings( void ); // implemented by the user +void UpgradeSettings( bool bShared ); // implemented by the user (called when converting 3.0 settings to 4.0) +void ClosingSettings( HWND hWnd, int flags, int command ); // implemented by the user +const wchar_t *GetDocRelativePath( void ); // implemented by the user +void SettingChangedCallback( const CSetting *pSetting ); // implemented by the user +bool IsSettingsMessage( MSG *msg ); +bool ImportSettingsXml( const wchar_t *fname ); +bool ExportSettingsXml( const wchar_t *fname ); +const CSetting *GetAllSettings( void ); +void SetSettingsStyle( int style, int mask ); +void GetSettingsStyle( int &style, int &mask ); + +// Finds a setting by name +CSetting *FindSetting( const wchar_t *name ); +// Updates the setting with a new default value and locked flag +void UpdateSetting( const wchar_t *name, const CComVariant &defValue, bool bLockedGP ); +// Updates the setting with a new tooltip and a warning flag +void UpdateSettingText( const wchar_t *name, int nameID, int tipID, bool bWarning ); + +void HideSetting( const wchar_t *name, bool bHide ); +void HideSettingGroup( const wchar_t *name, bool bHide ); +void UpdateGroupText( const wchar_t *name, int nameID ); + +bool GetSettingBool( const wchar_t *name ); +int GetSettingInt( const wchar_t *name ); +CString GetSettingString( const wchar_t *name ); +bool IsSettingLocked( const wchar_t *name ); +bool IsSettingForcedDefault( const wchar_t *name ); + +// In some cases the default can change dynamically, so the setting may be out of date. Use bDef to detect if the default value should be used +int GetSettingInt( const wchar_t *name, bool &bDef ); +bool GetSettingBool( const wchar_t *name, bool &bDef ); + +struct CSettingsLockRead +{ + CSettingsLockRead( void ); + ~CSettingsLockRead( void ); +}; + +struct CSettingsLockWrite +{ + CSettingsLockWrite( void ); + ~CSettingsLockWrite( void ); +}; + +bool HasHelp( void ); +void ShowHelp( void ); + +#ifndef _WIN64 +bool SaveAdmx( TSettingsComponent component, const char *admxFile, const char *admlFile, const char *docFile ); +#endif + +// Opens the registry keys for the settings of the given component +// Returns true if the user settings were read from the old HKCU location. That means the settings may need to be upgraded +bool OpenSettingsKeys( TSettingsComponent component, CRegKey ®Settings, CRegKey ®SettingsUser, CRegKey ®Policy, CRegKey ®PolicyUser ); + +// Get a value from a manually loaded setting +bool GetSettingBool( const CSetting &setting ); +CString GetSettingString( const CSetting &setting ); + +// the format for the location is key_name|value_name|file_name +void VLogToFile( const wchar_t *location, const wchar_t *message, va_list args ); +void LogToFile( const wchar_t *location, const wchar_t *message, ... ); diff --git a/ClassicShellSrc/ClassicShellLib/SettingsParser.cpp b/ClassicShellSrc/ClassicShellLib/SettingsParser.cpp new file mode 100644 index 0000000..d5b83cd --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/SettingsParser.cpp @@ -0,0 +1,553 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include +#include "SettingsParser.h" +#include "ResourceHelper.h" +#include "StringUtils.h" +#include + +const int MAX_TREE_LEVEL=10; + +// Reads a file into m_Text +bool CSettingsParser::LoadText( const wchar_t *fname ) +{ + // read settings file into buf + FILE *f=NULL; + if (_wfopen_s(&f,fname,L"rb")) return false; + if (!f) return false; + fseek(f,0,SEEK_END); + int size=ftell(f); + fseek(f,0,SEEK_SET); + std::vector buf(size); + if (size<4 || fread(&buf[0],1,size,f)!=size) + { + fclose(f); + return false; + } + fclose(f); + LoadText(&buf[0],size); + return true; +} + +// Reads a text resource into m_Text +bool CSettingsParser::LoadText( HMODULE hMod, HRSRC hResInfo ) +{ + HGLOBAL hRes=LoadResource(hMod,hResInfo); + int size=SizeofResource(hMod,hResInfo); + unsigned char *buf=(unsigned char*)LockResource(hRes); + if (!buf) return false; + LoadText(buf,size); + return true; +} + +void CSettingsParser::LoadText( const unsigned char *buf, int size ) +{ + // copy buf to text and convert to UTF16 + if (buf[0]==0xFF && buf[1]==0xFE) + { + // UTF16 + int len=(size-2)/2; + m_Text.resize(len+1); + memcpy(&m_Text[0],&buf[2],size-2); + m_Text[len]=0; + } + else if (buf[0]==0xEF && buf[1]==0xBB && buf[2]==0xBF) + { + // UTF8 + int len=MultiByteToWideChar(CP_UTF8,0,(const char*)&buf[3],size-3,NULL,0); + m_Text.resize(len+1); + MultiByteToWideChar(CP_UTF8,0,(const char*)&buf[3],size-3,&m_Text[0],len); + m_Text[len]=0; + } + else + { + // ACP + int len=MultiByteToWideChar(CP_ACP,0,(const char*)&buf[0],size,NULL,0); + m_Text.resize(len+1); + MultiByteToWideChar(CP_UTF8,0,(const char*)&buf[0],size,&m_Text[0],len); + m_Text[len]=0; + } +} + +void CSettingsParser::LoadText( const wchar_t *buf, int size ) +{ + m_Text.resize(size+1); + memcpy(&m_Text[0],buf,size*2); + m_Text[size]=0; +} + +// Splits m_Text into m_Lines +void CSettingsParser::ParseText( void ) +{ + if (m_Text.empty()) return; + // split into lines + wchar_t *str=&m_Text[0]; + while (*str) + { + if (*str!=';') // ignore lines starting with ; + { + // trim leading whitespace + while (*str==' ' || *str=='\t') + str++; + m_Lines.push_back(str); + } + wchar_t *p1=wcschr(str,'\r'); + wchar_t *p2=wcschr(str,'\n'); + wchar_t *end=&m_Text[m_Text.size()-1]; + if (p1) end=p1; + if (p2 && p2str && (*end==' ' || *end=='\t')) + end--; + *end=0; + str=next; + } +} + +// Filters the settings that belong to the given language +// languages is a 00-terminated list of language names ordered by priority +void CSettingsParser::FilterLanguages( const wchar_t *languages ) +{ + std::vector lines; + lines.swap(m_Lines); + for (const wchar_t *lang=languages;*lang;lang+=wcslen(lang)+1) + { + size_t langLen=wcslen(lang); + for (size_t i=0;i::const_reverse_iterator it=m_Lines.rbegin();it!=m_Lines.rend();++it) + { + const wchar_t *str=*it; + if (_wcsnicmp(name,str,len)==0) + { + str+=len; + while (*str==' ' || *str=='\t') + str++; + if (*str!='=') continue; + str++; + while (*str==' ' || *str=='\t') + str++; + return str; + } + } + + return NULL; +} + +// Frees all resources +void CSettingsParser::Reset( void ) +{ + m_Lines.clear(); + m_Text.clear(); +} + +// Parses a tree structure of items. The rootName setting must be a list of item names. +void CSettingsParser::ParseTree( const wchar_t *rootName, std::vector &items ) +{ + const wchar_t *str=FindSetting(rootName); + if (str) + { + CString names[MAX_TREE_LEVEL]; + ParseTreeRec(str,items,names,0); + } + else + { + TreeItem last={L"",-1}; + items.push_back(last); + } +} + +int CSettingsParser::ParseTreeRec( const wchar_t *str, std::vector &items, CString *names, int level ) +{ + size_t start=items.size(); + while (*str) + { + wchar_t token[256]; + str=GetToken(str,token,_countof(token),L", \t"); + if (token[0]) + { + // + bool bFound=false; + for (int i=0;i crash! + int idx=ParseTreeRec(str2,items,names,level+1); + items[i].children=idx; + } + } + } + return (int)start; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool CSkinParser::LoadVariation( const wchar_t *fname ) +{ + m_VarText.swap(m_Text); + bool res=LoadText(fname); + if (res) + { + std::vector lines; + lines.swap(m_Lines); + lines.push_back(L"[TRUE]"); + ParseText(); + m_Lines.insert(m_Lines.begin(),lines.begin(),lines.end()); + } + m_VarText.swap(m_Text); + return res; +} + +bool CSkinParser::LoadVariation( HMODULE hMod, HRSRC hResInfo ) +{ + m_VarText.swap(m_Text); + bool res=LoadText(hMod,hResInfo); + if (res) + { + std::vector lines; + lines.swap(m_Lines); + lines.push_back(L"[TRUE]"); + ParseText(); + m_Lines.insert(m_Lines.begin(),lines.begin(),lines.end()); + } + m_VarText.swap(m_Text); + return res; +} + +void CSkinParser::Reset( void ) +{ + CSettingsParser::Reset(); + m_VarText.clear(); +} + +static const wchar_t *g_OptionNames[SKIN_OPTION_TYPE_COUNT]={ + L"OPTION ", + L"OPTION_NUMBER ", + L"OPTION_STRING ", + L"OPTION_COLOR ", + L"OPTION_IMAGE ", +}; + +// Parses the option from m_Lines[index]. Returns false if index is out of bounds +bool CSkinParser::ParseOption( CString &name, TSkinOptionType &type, CString &label, bool &value, CString &condition, CString &disValue, int index ) +{ + if (index<0 || index>=(int)m_Lines.size()) + return false; + name.Empty(); + wchar_t buf[256]; + const wchar_t *line=m_Lines[index]; + if (_wcsnicmp(line,L"OPTION",6)!=0) + return true; + type=SKIN_OPTION_NONE; + for (int i=0;i lines; + lines.swap(m_Lines); + + bool bEnable=true; + + for (size_t i=0;i_countof(condition)-1) + continue; // too long + memcpy(condition,line+1,len*2); + condition[len]=0; + + // evaluate condition + if (EvalCondition(condition,values,count)==1) + bEnable=true; + continue; + } + if (bEnable) + m_Lines.push_back(line); + } +} + +// Substitutes the provided macro strings +void CSkinParser::ApplyMacros( const std::vector> ¯os ) +{ + std::vector names; + for (std::vector>::const_iterator it=macros.begin();it!=macros.end();++it) + { + wchar_t name[256]; + Sprintf(name,_countof(name),L"@%s@",it->first); + names.push_back(name); + } + + for (std::vector::iterator it=m_Lines.begin();it!=m_Lines.end();++it) + { + if (wcschr(*it,'@')) + { + CString string=*it; + for (size_t i=0;i=_countof(opStack)) return -1; // too much nesting + opStack[osp]=TYPE_PAR; + osp++; + condition++; + continue; + } + + if (*condition==')') + { + bool found=false; + while (osp>0) + { + osp--; + if (opStack[osp]==TYPE_PAR) + { + found=true; + break; + } + if (!ApplyOperator(valStack,vsp,opStack[osp])) return -1; // invalid operation + } + if (!found) return -1; // too many ) + condition++; + continue; + } + + // find token + const wchar_t *end=condition; + while (*end && *end!=' ' && *end!='\t' && *end!='(' && *end!=')') + end++; + + int len=(int)(end-condition); + if (len>=sizeof(token)) return -1; // too long token + memcpy(token,condition,len*2); + token[len]=0; + condition=end; + while (*condition==' ' || *condition=='\t') + condition++; + + if (_wcsicmp(token,L"and")==0 || _wcsicmp(token,L"or")==0) + { + while (osp>0 && opStack[osp-1]!=TYPE_PAR) + { + osp--; + if (!ApplyOperator(valStack,vsp,opStack[osp])) return -1; // invalid operation + } + if (osp>=_countof(opStack)) return -1; // too much nesting + opStack[osp]=(token[0]=='a' || token[0]=='A')?TYPE_AND:TYPE_OR; + osp++; + } + else if (_wcsicmp(token,L"not")==0) + { + while (osp>0 && opStack[osp-1]==TYPE_NOT) + { + osp--; + if (!ApplyOperator(valStack,vsp,opStack[osp])) return -1; // invalid operation + } + if (osp>=_countof(opStack)) return -1; // too much nesting + opStack[osp]=TYPE_NOT; + osp++; + } + else + { + if (vsp>=_countof(valStack)) return -1; // too much nesting + bool bValue=false; + if (_wcsicmp(token,L"true")==0) + bValue=true; + else + { + for (int i=0;i0) + { + osp--; + if (opStack[osp]==TYPE_PAR) return -1; // unclosed ( + if (!ApplyOperator(valStack,vsp,opStack[osp])) return -1; // invalid operation + } + + if (vsp!=1) return -1; // unbalanced expression + return valStack[0]?1:0; +} diff --git a/ClassicShellSrc/ClassicShellLib/SettingsParser.h b/ClassicShellSrc/ClassicShellLib/SettingsParser.h new file mode 100644 index 0000000..e5192da --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/SettingsParser.h @@ -0,0 +1,103 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#include + +/////////////////////////////////////////////////////////////////////////////// + +class CSettingsParser +{ +public: + // Reads a file into m_Text + bool LoadText( const wchar_t *fname ); + // Reads a text resource into m_Text + bool LoadText( HMODULE hMod, HRSRC hResInfo ); + + void LoadText( const unsigned char *buf, int size ); + void LoadText( const wchar_t *buf, int size ); + + // Splits m_Text into m_Lines + void ParseText( void ); + + // Filters the settings that belong to the given language + // languages is a 00-terminated list of language names ordered by priority + void FilterLanguages( const wchar_t *languages ); + + // Returns a setting with the given name. If no setting is found, returns def + const wchar_t *FindSetting( const wchar_t *name, const wchar_t *def=NULL ); + // Returns a setting with the given name, even if the value is blank. If the setting is not found, returns NULL + const wchar_t *FindSettingDirect( const wchar_t *name ); + + // Frees all resources + virtual void Reset( void ); + + struct TreeItem + { + CString name; // empty - last child + int children; // index to the first child. -1 - no children + }; + + // Parses a tree structure of items. The rootName setting must be a list of item names. + // Then for each name in the list the function will search for name.Items recursively. + // The last child in the list will have an empty name. + // Note - the rootName item will not be added to the list + void ParseTree( const wchar_t *rootName, std::vector &items ); + +protected: + std::vector m_Text; + std::vector m_Lines; + +private: + const wchar_t *FindSettingInt( const wchar_t *name, size_t len ); + + int ParseTreeRec( const wchar_t *rootName, std::vector &items, CString *names, int level ); +}; + +/////////////////////////////////////////////////////////////////////////////// + +enum TSkinOptionType +{ + SKIN_OPTION_GROUP=-2, + SKIN_OPTION_NONE=-1, + SKIN_OPTION_BOOL, + SKIN_OPTION_NUMBER, + SKIN_OPTION_STRING, + SKIN_OPTION_COLOR, + SKIN_OPTION_IMAGE, + + SKIN_OPTION_TYPE_COUNT +}; + +class CSkinParser: public CSettingsParser +{ +public: + CSkinParser( void ) { m_Aliases=NULL; } + bool LoadVariation( const wchar_t *fname ); + bool LoadVariation( HMODULE hMod, HRSRC hResInfo ); + void SetAliases( const wchar_t **aliases ) { m_Aliases=aliases; } + virtual void Reset( void ); + + // Parses the option from m_Lines[index]. Returns false if index is out of bounds + bool ParseOption( CString &name, TSkinOptionType &type, CString &label, bool &value, CString &condition, CString &disValue, int index ); + + // Filters the conditional groups + // values/count - list of true options. the rest are assumed to be false + void FilterConditions( const wchar_t **values, int count ); + + // Substitutes the provided macro strings + void ApplyMacros( const std::vector> ¯os ); + + // Returns a setting with the given name + const wchar_t *FindSetting( const wchar_t *name ); + +protected: + std::vector m_VarText; + const wchar_t **m_Aliases; + std::vector m_ExtraStrings; +}; + +/////////////////////////////////////////////////////////////////////////////// + +int EvalCondition( const wchar_t *condition, const wchar_t *const *values, int count ); diff --git a/ClassicShellSrc/ClassicShellLib/SettingsUIHelper.cpp b/ClassicShellSrc/ClassicShellLib/SettingsUIHelper.cpp new file mode 100644 index 0000000..2631fc7 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/SettingsUIHelper.cpp @@ -0,0 +1,3567 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include +#include "resource.h" +#include "Settings.h" +#include "SettingsUIHelper.h" +#include "ResourceHelper.h" +#include "ComHelper.h" +#include "FNVHash.h" +#include "StringUtils.h" +#include "Translations.h" +#include "DownloadHelper.h" +#include +#include +#include + +const KNOWNFOLDERID FOLDERID_DesktopRoot={'DESK', 'TO', 'P', {'D', 'E', 'S', 'K', 'T', 'O', 'P', 0x00}}; + +static bool IsVariantTrue( const CComVariant &var ) +{ + return (var.vt==VT_I4 && var.intVal==1); +} + +/////////////////////////////////////////////////////////////////////////////// + +void CTreeItem::SetCommand( CString command, const CStdCommand *pStdCommands, int style, int mask ) +{ + this->command=command; + pStdCommand=NULL; + for (int i=0;pStdCommands[i].name;i++) + { + if (!pStdCommands[i].IsStyle(style,mask)) continue; + if (_wcsicmp(pStdCommands[i].name,command)==0) + { + pStdCommand=&pStdCommands[i]; + return; + } + else if (pStdCommands[i].IsCustom()) + { + pStdCommand=&pStdCommands[i]; + } + } +} + +unsigned int CTreeItem::GetIconKey( void ) const +{ + if (!icon.IsEmpty()) + return CalcFNVHash(icon); + else if (pStdCommand && pStdCommand->knownFolder) + return CalcFNVHash(pStdCommand->knownFolder,sizeof(GUID)); + else if (!link.IsEmpty()) + return CalcFNVHash(link); + return 0; +} + +HICON CTreeItem::LoadIcon( bool bSmall, std::vector &modules ) const +{ + if (!icon.IsEmpty()) + { + if (_wcsicmp(icon,L"none")==0) + return bSmall?HICON_NONE:NULL; + return ::LoadIcon(GetSystemMetrics(bSmall?SM_CXSMICON:SM_CXICON),icon,modules); + } + else + { + CAbsolutePidl pidl; + if (pStdCommand && pStdCommand->knownFolder) + { + SHGetKnownFolderIDList(*pStdCommand->knownFolder,0,NULL,&pidl); + } + else if (!link.IsEmpty()) + { + const wchar_t *c=wcschr(link,'|'); + if (c) + { + for (c++;*c==' ';) + c++; + } + else + c=link; + wchar_t buf[_MAX_PATH]; + Strcpy(buf,_countof(buf),c); + DoEnvironmentSubst(buf,_countof(buf)); + + wchar_t *second=wcschr(buf,';'); + if (second) + { + wchar_t *end= second; + while (end>buf) + { + *end=0; + end--; + if (*end!=' ') + break; + } + } + + ShParseDisplayName(buf,&pidl,0,NULL); + } + if (pidl) + { + HICON hIcon=::LoadIcon(GetSystemMetrics(bSmall?SM_CXSMICON:SM_CXICON),pidl); + return hIcon; + } + } + return NULL; +} + +unsigned int CTreeItem::GetIconDKey( unsigned int iconKey ) const +{ + if (iconD.IsEmpty()) + return ~iconKey; + return CalcFNVHash(iconD); +} + +HICON CTreeItem::LoadIconD( HICON hIcon, std::vector &modules ) const +{ + if (!iconD.IsEmpty()) + { + if (_wcsicmp(iconD,L"none")==0) + return NULL; + return ::LoadIcon(GetSystemMetrics(SM_CXICON),iconD,modules); + } + else if (hIcon) + return CreateDisabledIcon(hIcon,GetSystemMetrics(SM_CXICON)); + else + return NULL; +} + +CString CTreeItem::GetDisplayName( bool bTitle ) const +{ + if (pStdCommand->IsCustom()) + { + if (!label.IsEmpty()) + { + if (label[0]!='$') + return label; + const wchar_t *pLabel=label; + return FindTranslation(pLabel+1,pLabel); + } + if (!bTitle && !link.IsEmpty()) + { + const wchar_t *c=wcschr(link,'|'); + if (c) + { + for (c++;*c==' ';) + c++; + } + else + c=link; + wchar_t buf[_MAX_PATH]; + Strcpy(buf,_countof(buf),c); + DoEnvironmentSubst(buf,_countof(buf)); + + wchar_t *second=wcschr(buf,';'); + if (second) + { + wchar_t *end= second; + while (end>buf) + { + *end=0; + end--; + if (*end!=' ') + break; + } + } + + CAbsolutePidl pidl; + ShParseDisplayName(buf,&pidl,0,NULL); + if (pidl) + { + CComPtr pItem; + if (SUCCEEDED(SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pItem))) + { + CComString pName; + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_NORMALDISPLAY,&pName))) + { + CString name; + name.Format(L"%s (%s)",LoadStringEx(pStdCommand->displayNameId),pName); + return name; + } + } + } + } + if (!bTitle && !tip.IsEmpty()) + { + const wchar_t *pTip=tip; + CString name; + if (pTip[0]=='$') + name.Format(L"%s (%s)",LoadStringEx(pStdCommand->displayNameId),FindTranslation(pTip+1,pTip)); + else + name.Format(L"%s (%s)",LoadStringEx(pStdCommand->displayNameId),pTip); + return name; + } + } + return LoadStringEx(pStdCommand->displayNameId); +} + +// Subclass the renaming editbox to handle Esc and Enter +static LRESULT CALLBACK SubclassEditboxProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_GETDLGCODE) + return DLGC_WANTALLKEYS; + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +class CSettingsTree: public CWindowImpl +{ +public: + BEGIN_MSG_MAP( CSettingsTree ) + MESSAGE_HANDLER( WM_DESTROY, OnDestroy ) + MESSAGE_HANDLER( WM_MOUSEMOVE, OnMouseMove ) + MESSAGE_HANDLER( WM_LBUTTONUP, OnLButtonUp ) + MESSAGE_HANDLER( WM_RBUTTONDOWN, OnRButtonDown ) + MESSAGE_HANDLER( WM_KEYUP, OnKeyUp ) + MESSAGE_HANDLER( WM_GETDLGCODE, OnGetDlgCode ) + MESSAGE_HANDLER( WM_CHAR, OnChar ) + MESSAGE_HANDLER( WM_CAPTURECHANGED, OnCaptureChanged ) + MESSAGE_HANDLER( WM_TIMER, OnTimer ) + REFLECTED_NOTIFY_CODE_HANDLER( TVN_DELETEITEM, OnDeleteItem ) + REFLECTED_NOTIFY_CODE_HANDLER( TVN_BEGINDRAG, OnBeginDrag ) + REFLECTED_NOTIFY_CODE_HANDLER( TVN_BEGINLABELEDIT, OnBeginLabelEdit ) + REFLECTED_NOTIFY_CODE_HANDLER( TVN_ENDLABELEDIT, OnEndLabelEdit ) + REFLECTED_NOTIFY_CODE_HANDLER( TVN_KEYDOWN, OnKeyDown ) + END_MSG_MAP() + + CSettingsTree( int mask ) { m_ImageList=NULL; m_StyleMask=mask; } + void SubclassWindow( HWND hWnd, CCustomTreeDlg *pOwner ); + int LoadIcon( const CTreeItem *pItem ); + int UpdateItem( CTreeItem *pItem, HTREEITEM hItem ); + void SetDisabled( bool bDisabled ) { m_bDisabled=bDisabled; } + bool IsDragging( void ) const { return m_DragMode!=DRAG_NONE; } + + void DeleteItem( HTREEITEM hItem ); + + void BeginDrag( const CStdCommand *pCommand ); + HTREEITEM CreateStdItem( const CStdCommand *pCommand, HTREEITEM hParent, HTREEITEM hAfter ); + + std::vector m_Modules; + +protected: + LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnLButtonUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnRButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnKeyUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnGetDlgCode( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnChar( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnCaptureChanged( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnDeleteItem( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnBeginDrag( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnBeginLabelEdit( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnEndLabelEdit( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnKeyDown( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + +private: + CCustomTreeDlg *m_pOwner; + std::map m_IconCache; + HIMAGELIST m_ImageList; + bool m_bDisabled; + + enum TDragMode + { + DRAG_NONE, + DRAG_DELETE, + DRAG_ERROR, + DRAG_MOVE, // these must be the last two + DRAG_COPY, + }; + + enum TDropLocation + { + DROP_NOWHERE, + DROP_INSIDE, + DROP_BEFORE, + DROP_AFTER, + DROP_LAST, + }; + + enum { + TIMER_SCROLL=1, + TIMER_HOVER=2, + }; + + int m_StyleMask; + TDragMode m_DragMode; + HCURSOR m_CursorError, m_CursorMove, m_CursorCopy, m_CursorDel; + HTREEITEM m_DragItem; + HTREEITEM m_DropTarget; + HTREEITEM m_DropSubmenu; + TDropLocation m_DropLocation; + int m_Scroll; + HTREEITEM m_HoverItem; + const CStdCommand *m_pStdDragItem; + bool m_bDragLink; // the item being dragged is a link + + bool FindItemByName( HTREEITEM hParent, const wchar_t *name, HTREEITEM hExclude ); + CString CreateUniqueName( CString oldName ); + HTREEITEM CreateDeepCopy( HTREEITEM hSource, HTREEITEM hParent, HTREEITEM hAfter, bool bRename ); +}; + +void CSettingsTree::SubclassWindow( HWND hWnd, CCustomTreeDlg *pOwner ) +{ + m_pOwner=pOwner; + int size=GetSystemMetrics(SM_CXSMICON); + if (!m_ImageList) + m_ImageList=ImageList_Create(size,size,ILC_COLOR32|ILC_MASK|ILC_MIRROR,1,16); + CWindowImpl::SubclassWindow(hWnd); + TreeView_SetImageList(hWnd,m_ImageList,TVSIL_NORMAL); + + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=bi.bmiHeader.biHeight=size; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + RECT rc={0,0,size,size}; + + HDC hdc=CreateCompatibleDC(NULL); + HBITMAP bmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,NULL,NULL,0); + HGDIOBJ bmp0=SelectObject(hdc,bmp); + FillRect(hdc,&rc,(HBRUSH)(COLOR_WINDOW+1)); + SelectObject(hdc,bmp0); + DeleteDC(hdc); + ImageList_AddMasked(m_ImageList,bmp,GetSysColor(COLOR_WINDOW)); + DeleteObject(bmp); + + SHFILEINFO info; + if (SHGetFileInfo(L"file",FILE_ATTRIBUTE_NORMAL,&info,sizeof(info),SHGFI_USEFILEATTRIBUTES|SHGFI_ICON|SHGFI_SMALLICON)) + { + ImageList_AddIcon(m_ImageList,info.hIcon); + DestroyIcon(info.hIcon); + } + m_DragMode=DRAG_NONE; + HMODULE hOle32=LoadLibrary(L"ole32.dll"); + if (hOle32) + { + m_CursorError=(HCURSOR)LoadImage(hOle32,MAKEINTRESOURCE(1),IMAGE_CURSOR,0,0,LR_DEFAULTSIZE); + m_CursorMove=(HCURSOR)LoadImage(hOle32,MAKEINTRESOURCE(2),IMAGE_CURSOR,0,0,LR_DEFAULTSIZE); + m_CursorCopy=(HCURSOR)LoadImage(hOle32,MAKEINTRESOURCE(3),IMAGE_CURSOR,0,0,LR_DEFAULTSIZE); + m_CursorDel=(HCURSOR)LoadImage(hOle32,MAKEINTRESOURCE(5),IMAGE_CURSOR,0,0,LR_DEFAULTSIZE); + FreeLibrary(hOle32); + } +} + +int CSettingsTree::LoadIcon( const CTreeItem *pItem ) +{ + unsigned int key=pItem->GetIconKey(); + std::map::const_iterator it=m_IconCache.find(key); + if (it!=m_IconCache.end()) + return it->second; + + // extract icon + HICON hIcon=pItem->LoadIcon(true,m_Modules); + if (hIcon==HICON_NONE) + { + m_IconCache[key]=0; + return 0; + } + int index=1; + if (hIcon) + { + index=ImageList_AddIcon(m_ImageList,hIcon); + DestroyIcon(hIcon); + } + m_IconCache[key]=index; + return index; +} + +int CSettingsTree::UpdateItem( CTreeItem *pItem, HTREEITEM hItem ) +{ + TVITEM item={TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT,hItem}; + + item.iImage=item.iSelectedImage=LoadIcon(pItem); + if (hItem) + { + CString dispName=pItem->GetDisplayName(false); + item.pszText=(LPWSTR)(LPCWSTR)dispName; + TreeView_SetItem(m_hWnd,&item); + } + return item.iImage; +} + +LRESULT CSettingsTree::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + for (std::vector::const_iterator it=m_Modules.begin();it!=m_Modules.end();++it) + FreeLibrary(*it); + m_Modules.clear(); + if (m_CursorError) DestroyCursor(m_CursorError); + if (m_CursorMove) DestroyCursor(m_CursorMove); + if (m_CursorCopy) DestroyCursor(m_CursorCopy); + if (m_CursorDel) DestroyCursor(m_CursorDel); + return 0; +} + +LRESULT CSettingsTree::OnDeleteItem( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + // free data + NMTREEVIEW *pItem=(NMTREEVIEW*)pnmh; + delete (CTreeItem*)pItem->itemOld.lParam; + return 0; +} + +void CSettingsTree::BeginDrag( const CStdCommand *pCommand ) +{ + if (m_bDisabled) return; + m_pStdDragItem=pCommand; + m_bDragLink=pCommand->knownFolder!=NULL; + m_DragItem=TreeView_GetSelection(m_hWnd); + SetFocus(); + SetCapture(); + m_DragMode=DRAG_COPY; + m_DropTarget=NULL; + m_DropLocation=DROP_NOWHERE; + m_Scroll=0; + m_HoverItem=NULL; + m_DropSubmenu=NULL; + SetCursor(m_CursorCopy); + TreeView_SelectItem(m_hWnd,NULL); +} + +LRESULT CSettingsTree::OnBeginDrag( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + if (m_bDisabled) return 0; + NMTREEVIEW *pDrag=(NMTREEVIEW*)pnmh; + CTreeItem *pItem=(CTreeItem*)pDrag->itemNew.lParam; + if (!pItem) return 0; + m_pStdDragItem=NULL; + m_DragItem=pDrag->itemNew.hItem; + m_bDragLink=(pItem->pStdCommand && pItem->pStdCommand->knownFolder) || !pItem->link.IsEmpty(); + TreeView_SelectItem(m_hWnd,m_DragItem); + SetCapture(); + m_DragMode=GetKeyState(VK_CONTROL)<0?DRAG_COPY:DRAG_MOVE; + m_DropTarget=NULL; + m_DropLocation=DROP_NOWHERE; + m_Scroll=0; + m_HoverItem=NULL; + m_DropSubmenu=NULL; + SetCursor(m_DragMode==DRAG_COPY?m_CursorCopy:m_CursorMove); + SetFocus(); + TreeView_SelectItem(m_hWnd,NULL); + return 0; +} + +LRESULT CSettingsTree::OnMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_DragMode==DRAG_NONE) + { + bHandled=FALSE; + return 0; + } + // find the drop location + m_DropTarget=NULL; + m_DropLocation=DROP_NOWHERE; + TVHITTESTINFO test={{(short)LOWORD(lParam),(short)HIWORD(lParam)}}; + RECT rc; + GetClientRect(&rc); + int h=TreeView_GetItemHeight(m_hWnd); + int scroll=0; + if (test.pt.yrc.bottom-h) + scroll=1; + if (m_Scroll!=scroll) + { + m_Scroll=scroll; + if (m_Scroll) + SetTimer(TIMER_SCROLL,100); + else + KillTimer(TIMER_SCROLL); + } + bool bDelete=!PtInRect(&rc,test.pt); + if (!bDelete) + { + HTREEITEM hLast=TreeView_GetLastVisible(m_hWnd); + if (hLast) + { + TreeView_GetItemRect(m_hWnd,hLast,&rc,FALSE); + if (TreeView_HitTest(m_hWnd,&test)) + { + m_DropTarget=test.hItem; + } + else + { + if (test.pt.y>=rc.bottom) + { + // after the last visible item + m_DropTarget=hLast; + } + } + } + else if (m_pStdDragItem) + m_DropLocation=DROP_LAST; + + if (m_DropTarget && !m_pStdDragItem) + { + // can't drop inside itself + for (HTREEITEM hItem=TreeView_GetParent(m_hWnd,m_DropTarget);hItem;hItem=TreeView_GetParent(m_hWnd,hItem)) + { + if (hItem==m_DragItem) + { + m_DropTarget=NULL; + break; + } + } + } + if (m_DropTarget) + { + TreeView_GetItemRect(m_hWnd,m_DropTarget,&rc,FALSE); + TVITEM item={TVIF_PARAM,m_DropTarget}; + TreeView_GetItem(m_hWnd,&item); + int dy=test.pt.y-rc.top; + int h1=(rc.bottom-rc.top)/4; + int h2=(rc.bottom-rc.top)-h1; + if (!item.lParam || ((CTreeItem*)item.lParam)->pStdCommand->IsSeparator()) + { + h1=(rc.bottom-rc.top)/2; + h2=(rc.bottom-rc.top)-h1; + } + if (dy=h2) + m_DropLocation=DROP_AFTER; + else + { + // can't drop in a separator or itself + if (!item.lParam || ((CTreeItem*)item.lParam)->pStdCommand->IsSeparator() || (m_DropTarget==m_DragItem && !m_pStdDragItem)) + m_DropTarget=NULL; + else + m_DropLocation=DROP_INSIDE; + } + } + } + // display drop location + if (!m_DropTarget) + { + TreeView_SelectDropTarget(m_hWnd,NULL); + TreeView_SetInsertMark(m_hWnd,NULL,FALSE); + if (m_DropLocation==DROP_LAST) + { + m_DragMode=DRAG_COPY; + SetCursor(m_CursorCopy); + } + else + { + if (m_pStdDragItem) + bDelete=false; + m_DragMode=bDelete?DRAG_DELETE:DRAG_ERROR; + SetCursor(bDelete?m_CursorDel:m_CursorError); + } + } + else + { + m_DragMode=(m_pStdDragItem || GetKeyState(VK_CONTROL)<0)?DRAG_COPY:DRAG_MOVE; + SetCursor(m_DragMode==DRAG_COPY?m_CursorCopy:m_CursorMove); + if (m_DropLocation==DROP_INSIDE) + { + TreeView_SelectDropTarget(m_hWnd,m_DropTarget); + TreeView_SetInsertMark(m_hWnd,NULL,FALSE); + } + else + { + TreeView_SelectDropTarget(m_hWnd,NULL); + TreeView_SetInsertMark(m_hWnd,m_DropTarget,m_DropLocation==DROP_AFTER); + } + } + + if (m_DropLocation==DROP_INSIDE) + { + if (m_HoverItem!=m_DropTarget) + { + SetTimer(TIMER_HOVER,400); + m_HoverItem=m_DropTarget; + } + } + else if (m_HoverItem) + { + m_HoverItem=NULL; + KillTimer(TIMER_HOVER); + } + return 0; +} + +bool CSettingsTree::FindItemByName( HTREEITEM hParent, const wchar_t *name, HTREEITEM hExclude ) +{ + for (HTREEITEM hItem=hParent?TreeView_GetChild(m_hWnd,hParent):TreeView_GetRoot(m_hWnd);hItem;hItem=TreeView_GetNextSibling(m_hWnd,hItem)) + { + if (FindItemByName(hItem,name,hExclude)) + return true; + if (hItem!=hExclude) + { + TVITEM item={TVIF_PARAM,hItem}; + TreeView_GetItem(m_hWnd,&item); + if (item.lParam && _wcsicmp(((CTreeItem*)item.lParam)->name,name)==0) + return true; + } + } + return false; +} + +CString CSettingsTree::CreateUniqueName( CString oldName ) +{ + if (!FindItemByName(NULL,oldName,NULL)) + return oldName; + wchar_t name[256]; + Strcpy(name,_countof(name)-3,oldName); + // find numeric part + int pos=Strlen(name); + while (pos>0 && name[pos-1]>='0' && name[pos-1]<='9') + pos--; + for (int i=2;;i++) + { + Sprintf(name+pos,_countof(name)-pos,L"%d",i); + if (!FindItemByName(NULL,name,NULL)) + break; + } + return name; +} + +HTREEITEM CSettingsTree::CreateDeepCopy( HTREEITEM hSource, HTREEITEM hParent, HTREEITEM hAfter, bool bRename ) +{ + TVINSERTSTRUCT insert={hParent,hAfter?hAfter:TVI_FIRST,{TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_STATE,hSource,0,TVIS_EXPANDED}}; + TreeView_GetItem(m_hWnd,&insert.item); + CTreeItem *pSource=(CTreeItem*)insert.item.lParam; + if (!pSource) return NULL; + CTreeItem *pNewItem=new CTreeItem(*pSource); + if (bRename && !pNewItem->pStdCommand->IsSeparator()) + { + pNewItem->name=CreateUniqueName(pNewItem->name); + } + insert.item.lParam=(LPARAM)pNewItem; + insert.item.mask|=TVIF_TEXT; + CString dispName=pNewItem->GetDisplayName(false); + insert.item.pszText=(LPWSTR)(LPCWSTR)dispName; + HTREEITEM hResult=TreeView_InsertItem(m_hWnd,&insert); + for (HTREEITEM hChild=TreeView_GetChild(m_hWnd,hSource);hChild;hChild=TreeView_GetNextSibling(m_hWnd,hChild)) + CreateDeepCopy(hChild,hResult,TVI_LAST,bRename); + return hResult; +} + +HTREEITEM CSettingsTree::CreateStdItem( const CStdCommand *pCommand, HTREEITEM hParent, HTREEITEM hAfter ) +{ + TVINSERTSTRUCT insert={hParent,hAfter?hAfter:TVI_FIRST,{TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_STATE|TVIF_TEXT,NULL,TVIS_EXPANDED,TVIS_EXPANDED}}; + CTreeItem *pNewItem=new CTreeItem; + pNewItem->label=pCommand->label; + pNewItem->tip=pCommand->tip; + pNewItem->icon=pCommand->icon; + pNewItem->iconD=pCommand->iconD; + pNewItem->pStdCommand=pCommand; + pNewItem->settings=pCommand->settings&~m_StyleMask; + + if (pCommand->IsSeparator()) + { + pNewItem->name=pCommand->name; + } + else + { + pNewItem->command=pCommand->name; + pNewItem->name=CreateUniqueName(pCommand->itemName); + insert.item.iImage=insert.item.iSelectedImage=UpdateItem(pNewItem,NULL); + } + + insert.item.lParam=(LPARAM)pNewItem; + CString dispName=pNewItem->GetDisplayName(false); + insert.item.pszText=(LPWSTR)(LPCWSTR)dispName; + return TreeView_InsertItem(m_hWnd,&insert); +} + +LRESULT CSettingsTree::OnRButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + // ignore right-click during dragging + if (m_DragMode==DRAG_NONE) + bHandled=FALSE; + return 0; +} + +LRESULT CSettingsTree::OnLButtonUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_DragMode!=DRAG_NONE) + { + TDragMode mode=m_DragMode; + HTREEITEM dragItem=m_DragItem; + if (m_DropSubmenu==m_DropTarget && mode>=DRAG_MOVE) + m_DropSubmenu=NULL; + m_DragItem=NULL; + ReleaseCapture(); + // perform drop operation + if (mode==DRAG_DELETE) + { + TreeView_EnsureVisible(m_hWnd,dragItem); + if (!m_pStdDragItem) + { + TreeView_DeleteItem(m_hWnd,dragItem); + m_pOwner->SerializeData(); + } + } + else if (mode>=DRAG_MOVE) + { + HTREEITEM hParent=m_DropTarget; + HTREEITEM hAfter=TVI_LAST; + if (m_DropLocation==DROP_AFTER) + { + hAfter=hParent; + hParent=TreeView_GetParent(m_hWnd,hParent); + } + else if (m_DropLocation==DROP_BEFORE) + { + hAfter=TreeView_GetPrevSibling(m_hWnd,hParent); + if (!hAfter) hAfter=TVI_FIRST; + hParent=TreeView_GetParent(m_hWnd,hParent); + } + if (hParent) + { + HTREEITEM hChild=TreeView_GetChild(m_hWnd,hParent); + if (hChild) + { + TVITEM item={TVIF_PARAM,hChild}; + TreeView_GetItem(m_hWnd,&item); + if (!item.lParam) + { + TreeView_DeleteItem(m_hWnd,hChild); + hAfter=TVI_LAST; + } + } + } + + HTREEITEM hNewItem; + if (m_pStdDragItem) + { + hNewItem=CreateStdItem(m_pStdDragItem,hParent,hAfter); + } + else + { + hNewItem=CreateDeepCopy(dragItem,hParent,hAfter,mode==DRAG_COPY); + if (mode==DRAG_MOVE) + TreeView_DeleteItem(m_hWnd,dragItem); + } + + TreeView_SelectItem(m_hWnd,hNewItem); + TreeView_EnsureVisible(m_hWnd,hNewItem); + m_pOwner->SerializeData(); + } + } + bHandled=FALSE; + return 0; +} + +LRESULT CSettingsTree::OnKeyUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_DragMode>=DRAG_MOVE) + { + m_DragMode=(m_pStdDragItem || GetKeyState(VK_CONTROL)<0)?DRAG_COPY:DRAG_MOVE; + SetCursor(m_DragMode==DRAG_COPY?m_CursorCopy:m_CursorMove); + } + bHandled=FALSE; + return 0; +} + +LRESULT CSettingsTree::OnGetDlgCode( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_DragMode!=DRAG_NONE || (lParam && ((MSG*)lParam)->message==WM_KEYDOWN && ((MSG*)lParam)->wParam==VK_RETURN)) + return DLGC_WANTALLKEYS; + bHandled=FALSE; + return 0; +} + +LRESULT CSettingsTree::OnChar( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==VK_RETURN) + return 0; + bHandled=FALSE; + return 0; +} + +LRESULT CSettingsTree::OnCaptureChanged( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_DragMode!=DRAG_NONE) + { + m_DragMode=DRAG_NONE; + TreeView_SelectDropTarget(m_hWnd,NULL); + TreeView_SetInsertMark(m_hWnd,NULL,FALSE); + SetCursor(LoadCursor(NULL,IDC_ARROW)); + if (m_DragItem) TreeView_SelectItem(m_hWnd,m_DragItem); + KillTimer(TIMER_SCROLL); + KillTimer(TIMER_HOVER); + if (m_DropSubmenu) + TreeView_DeleteItem(m_hWnd,m_DropSubmenu); + m_DropSubmenu=NULL; + m_HoverItem=NULL; + } + bHandled=FALSE; + return 0; +} + +LRESULT CSettingsTree::OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==TIMER_SCROLL) + { + if (m_Scroll>0) + SendMessage(WM_VSCROLL,SB_LINEDOWN); + else + SendMessage(WM_VSCROLL,SB_LINEUP); + } + else if (wParam==TIMER_HOVER) + { + if (m_HoverItem) + { + TreeView_Expand(m_hWnd,m_HoverItem,TVE_EXPAND); + if (!TreeView_GetChild(m_hWnd,m_HoverItem)) + { + if (m_DropSubmenu) + TreeView_DeleteItem(m_hWnd,m_DropSubmenu); + TVINSERTSTRUCT insert={m_HoverItem,TVI_FIRST,{TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_STATE|TVIF_TEXT,NULL,TVIS_EXPANDED,TVIS_EXPANDED}}; + CString text=LoadStringEx(IDS_EMPTY_MENU); + insert.item.pszText=(LPWSTR)(LPCWSTR)text; + m_DropSubmenu=TreeView_InsertItem(m_hWnd,&insert); + TreeView_SelectItem(m_hWnd,m_DropSubmenu); + TreeView_EnsureVisible(m_hWnd,m_DropSubmenu); + } + } + KillTimer(TIMER_HOVER); + } + else + bHandled=FALSE; + return 0; +} + +LRESULT CSettingsTree::OnBeginLabelEdit( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + if (m_bDisabled) return TRUE; + CWindow edit=TreeView_GetEditControl(m_hWnd); + SetWindowSubclass(edit,SubclassEditboxProc,'CLSH',0); + NMTVDISPINFO *pInfo=(NMTVDISPINFO*)pnmh; + if (!pInfo->item.lParam) + return TRUE; + CTreeItem *pItem=(CTreeItem*)pInfo->item.lParam; + if (!pItem->pStdCommand->IsCustom()) + return TRUE; + edit.SetWindowText(pItem->label); + return FALSE; +} + +LRESULT CSettingsTree::OnEndLabelEdit( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMTVDISPINFO *pInfo=(NMTVDISPINFO*)pnmh; + if (pInfo->item.pszText) + { + CTreeItem *pItem=(CTreeItem*)pInfo->item.lParam; + pItem->label=pInfo->item.pszText; + m_pOwner->SerializeData(); + UpdateItem(pItem,pInfo->item.hItem); + } + return FALSE; +} + +LRESULT CSettingsTree::OnKeyDown( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMTVKEYDOWN *pKey=(NMTVKEYDOWN*)pnmh; + if (m_DragMode!=DRAG_NONE) + { + if (pKey->wVKey==VK_ESCAPE) + { + ReleaseCapture(); + return TRUE; + } + if (m_DragMode>=DRAG_MOVE) + { + m_DragMode=(m_pStdDragItem || GetKeyState(VK_CONTROL)<0)?DRAG_COPY:DRAG_MOVE; + SetCursor(m_DragMode==DRAG_COPY?m_CursorCopy:m_CursorMove); + } + } + // F2 to rename + if (pKey->wVKey==VK_F2) + { + HTREEITEM hSelected=TreeView_GetSelection(m_hWnd); + if (hSelected) + TreeView_EditLabel(m_hWnd,hSelected); + } + // Del to delete + if (pKey->wVKey==VK_DELETE) + { + HTREEITEM hSelected=TreeView_GetSelection(m_hWnd); + if (hSelected) + DeleteItem(hSelected); + } + return 0; +} + +void CSettingsTree::DeleteItem( HTREEITEM hItem ) +{ + if (!m_bDisabled) + { + TreeView_DeleteItem(m_hWnd,hItem); + m_pOwner->SerializeData(); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +class CCommandsTree: public CWindowImpl +{ +public: + BEGIN_MSG_MAP( CCommandsTree ) + MESSAGE_HANDLER( WM_GETDLGCODE, OnGetDlgCode ) + MESSAGE_HANDLER( WM_CHAR, OnChar ) + END_MSG_MAP() + +protected: + LRESULT OnGetDlgCode( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnChar( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); +}; + +LRESULT CCommandsTree::OnGetDlgCode( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (lParam && ((MSG*)lParam)->message==WM_KEYDOWN && ((MSG*)lParam)->wParam==VK_RETURN) + return DLGC_WANTALLKEYS; + bHandled=FALSE; + return 0; +} + +LRESULT CCommandsTree::OnChar( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==VK_RETURN) + return 0; + bHandled=FALSE; + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +CEditCustomItemDlg::~CEditCustomItemDlg( void ) +{ + if (m_hIcon) DestroyIcon(m_hIcon); + if (m_hIconD) DestroyIcon(m_hIconD); +} + +void CEditCustomItemDlg::InitDialog( CWindow commandCombo, const CStdCommand *pStdcommands, int style, int mask, CWindow linkCombo, const KNOWNFOLDERID *const *pCommonLinks ) +{ + InitResize(MOVE_HORIZONTAL|MOVE_GRIPPER); + CString str; + GetWindowText(str); + CString title; + title.Format(str,m_pItem->GetDisplayName(true)); + SetWindowText(title); + + for (int i=0;pStdcommands[i].name;i++) + if (pStdcommands[i].IsStyle(style,mask) && !pStdcommands[i].IsSeparator() && !pStdcommands[i].IsCustom()) + commandCombo.SendMessage(CB_ADDSTRING,0,(LPARAM)pStdcommands[i].name); + + commandCombo.SetWindowText(m_pItem->command); + int idx=(int)commandCombo.SendMessage(CB_FINDSTRINGEXACT,-1,(LPARAM)(const wchar_t*)m_pItem->command); + if (idx>=0) + commandCombo.SendMessage(CB_SETCURSEL,idx); + + for (int i=0;pCommonLinks[i];i++) + { + if (*pCommonLinks[i]==FOLDERID_DesktopRoot) + { + linkCombo.SendMessage(CB_ADDSTRING,0,(LPARAM)L"Main Desktop | ::{Desktop}"); + } + else + { + CAbsolutePidl path; + if (FAILED(SHGetKnownFolderIDList(*pCommonLinks[i],0,NULL,&path)) || !path) continue; + CComString pName; + if (SUCCEEDED(SHGetNameFromIDList(path,SIGDN_NORMALDISPLAY,&pName))) + { + CComString pPath; + if (SUCCEEDED(SHGetNameFromIDList(path,SIGDN_DESKTOPABSOLUTEPARSING,&pPath))) + { + wchar_t text[_MAX_PATH*2]; + int len=Sprintf(text,_countof(text),L"%s | ",pName); + if (!PathUnExpandEnvStrings(pPath,text+len,_countof(text)-len)) + Strcpy(text+len,_countof(text)-len,pPath); + linkCombo.SendMessage(CB_ADDSTRING,0,(LPARAM)text); + } + } + } + } + + linkCombo.SetWindowText(m_pItem->link); + idx=(int)linkCombo.SendMessage(CB_FINDSTRINGEXACT,-1,(LPARAM)(const wchar_t*)m_pItem->link); + if (idx>=0) + linkCombo.SendMessage(CB_SETCURSEL,idx); + + m_hIcon=NULL; + m_IconKey=0; + m_hIconD=NULL; + m_IconDKey=0; + m_StoredItem=*m_pItem; + + RECT rc; + CRegKey regSettings; + if (regSettings.Open(HKEY_CURRENT_USER,GetSettingsRegPath())==ERROR_SUCCESS) + { + ULONG size=sizeof(rc); + if (regSettings.QueryBinaryValue(L"CEditCustomItemDlg",&rc,&size)==ERROR_SUCCESS && size==sizeof(rc)) + SetStoreRect(rc); + } + + COMBOBOXINFO info={sizeof(info)}; + commandCombo.SendMessage(CB_GETCOMBOBOXINFO,0,(LPARAM)&info); + SHAutoComplete(info.hwndItem,SHACF_FILESYSTEM); + linkCombo.SendMessage(CB_GETCOMBOBOXINFO,0,(LPARAM)&info); + SHAutoComplete(info.hwndItem,SHACF_FILESYSTEM); +} + +LRESULT CEditCustomItemDlg::OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + CResizeableDlg::OnSize(); + return 0; +} + +void CEditCustomItemDlg::StorePlacement( void ) +{ + RECT rc; + GetStoreRect(rc); + + CRegKey regSettings; + if (regSettings.Open(HKEY_CURRENT_USER,GetSettingsRegPath())!=ERROR_SUCCESS) + regSettings.Create(HKEY_CURRENT_USER,GetSettingsRegPath()); + regSettings.SetBinaryValue(L"CEditCustomItemDlg",&rc,sizeof(rc)); +} + +LRESULT CEditCustomItemDlg::OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + ::EnableWindow(m_EnableParent,TRUE); + m_bResult=true; + StorePlacement(); + DestroyWindow(); + return 0; +} + +LRESULT CEditCustomItemDlg::OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + ::EnableWindow(m_EnableParent,TRUE); + m_bResult=false; + StorePlacement(); + DestroyWindow(); + (*m_pItem)=m_StoredItem; + return 0; +} + +void CEditCustomItemDlg::UpdateIcons( int iconID, int iconDID ) +{ + unsigned int key=m_pItem->GetIconKey(); + + if (key!=m_IconKey) + { + m_IconKey=key; + if (m_hIcon) DestroyIcon(m_hIcon); + m_hIcon=m_pItem->LoadIcon(false,m_Modules); + SendDlgItemMessage(iconID,STM_SETICON,(WPARAM)m_hIcon); + } + + if (iconDID) + { + key=m_pItem->GetIconDKey(key); + if (key!=m_IconDKey) + { + m_IconDKey=key; + if (m_hIconD) DestroyIcon(m_hIconD); + m_hIconD=m_pItem->LoadIconD(m_hIcon,m_Modules); + SendDlgItemMessage(iconDID,STM_SETICON,(WPARAM)m_hIconD); + } + } +} + +CString CEditCustomItemDlg::GetComboText( WORD wNotifyCode, WORD wID ) +{ + CString text; + if (wNotifyCode==CBN_SELENDOK) + { + int idx=(int)SendDlgItemMessage(wID,CB_GETCURSEL); + text.Empty(); + if (idx>=0) + { + int len=(int)SendDlgItemMessage(wID,CB_GETLBTEXTLEN,idx); + SendDlgItemMessage(wID,CB_GETLBTEXT,idx,(LPARAM)text.GetBuffer(len+1)); + text.ReleaseBuffer(len); + } + } + else + GetDlgItemText(wID,text); + text.TrimLeft(); + text.TrimRight(); + return text; +} + +/////////////////////////////////////////////////////////////////////////////// + +class CBrowseLinkEvents: public IFileDialogEvents, public IFileDialogControlEvents +{ +public: + CBrowseLinkEvents( void ) { m_pResult=NULL; } + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void **ppvObject ); + virtual ULONG STDMETHODCALLTYPE AddRef( void ) { return 1; } + virtual ULONG STDMETHODCALLTYPE Release( void ) { return 1; } + + // IFileDialogEvents + STDMETHOD(OnFileOk)( IFileDialog *pfd ) { return S_OK; } + STDMETHOD(OnFolderChanging)( IFileDialog *pfd, IShellItem *psiFolder ) { return S_OK; } + STDMETHOD(OnFolderChange)( IFileDialog *pfd ) { return S_OK; } + STDMETHOD(OnSelectionChange)( IFileDialog *pfd ) { return S_OK; } + STDMETHOD(OnShareViolation)( IFileDialog *pfd, IShellItem *psi, FDE_SHAREVIOLATION_RESPONSE *pResponse ) { return S_OK; } + STDMETHOD(OnTypeChange)( IFileDialog *pfd ) { return S_OK; } + STDMETHOD(OnOverwrite)( IFileDialog *pfd, IShellItem *psi, FDE_OVERWRITE_RESPONSE *pResponse ) { return S_OK; } + + // IFileDialogControlEvents + STDMETHOD(OnItemSelected)( IFileDialogCustomize *pfdc, DWORD dwIDCtl, DWORD dwIDItem ) { return S_OK; } + STDMETHOD(OnButtonClicked)( IFileDialogCustomize *pfdc, DWORD dwIDCtl ); + STDMETHOD(OnCheckButtonToggled)( IFileDialogCustomize *pfdc, DWORD dwIDCtl, BOOL bChecked ) { return S_OK; } + STDMETHOD(OnControlActivating)( IFileDialogCustomize *pfdc, DWORD dwIDCtl ) { return S_OK; } + + CComPtr m_pResult; +}; + +HRESULT STDMETHODCALLTYPE CBrowseLinkEvents::QueryInterface( REFIID riid, void **ppvObject ) +{ + if (riid==IID_IUnknown) + { + *ppvObject=(IUnknown*)(IFileDialogEvents*)this; + return S_OK; + } + if (riid==IID_IFileDialogEvents) + { + *ppvObject=(IFileDialogEvents*)this; + return S_OK; + } + if (riid==IID_IFileDialogControlEvents) + { + *ppvObject=(IFileDialogControlEvents*)this; + return S_OK; + } + *ppvObject=NULL; + return E_NOINTERFACE; +} + +HRESULT STDMETHODCALLTYPE CBrowseLinkEvents::OnButtonClicked( IFileDialogCustomize *pfdc, DWORD dwIDCtl ) +{ + CComQIPtr pfd=pfdc; + if (!pfd) return E_INVALIDARG; + + CComPtr pItem; + if (SUCCEEDED(pfd->GetCurrentSelection(&pItem))) + { + SFGAOF attr; + if (SUCCEEDED(pItem->GetAttributes(SFGAO_FOLDER|SFGAO_STREAM,&attr)) && (attr&(SFGAO_FOLDER|SFGAO_STREAM))!=SFGAO_FOLDER) + pItem=NULL; + } + if (!pItem) + { + pfd->GetFolder(&pItem); + } + m_pResult=pItem; + pfd->Close(S_FALSE); + return S_OK; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool BrowseCommandHelper( HWND parent, wchar_t *text ) +{ + if (text[0]=='"') + { + // remove quotes + int len=Strlen(text); + if (len>1 && text[len-1]=='"') + { + len-=2; + memmove(text,text+1,len*2); + text[len]=0; + } + } + OPENFILENAME ofn={sizeof(ofn)}; + ofn.hwndOwner=parent; + wchar_t filters[256]; + Strcpy(filters,_countof(filters),LoadStringEx(IDS_COMMAND_FILTERS)); + for (wchar_t *c=filters;*c;c++) + if (*c=='|') *c=0; + ofn.lpstrFilter=filters; + ofn.nFilterIndex=1; + DoEnvironmentSubst(text,_MAX_PATH); + wchar_t dir[_MAX_PATH]; + Strcpy(dir,_countof(dir),text); + PathRemoveFileSpec(dir); + ofn.lpstrInitialDir=dir; + text[0]=0; + ofn.lpstrFile=text; + ofn.nMaxFile=_MAX_PATH; + ofn.Flags=OFN_DONTADDTORECENT|OFN_ENABLESIZING|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_NOCHANGEDIR|OFN_NODEREFERENCELINKS; + if (GetOpenFileName(&ofn)) + { + wchar_t buf[_MAX_PATH]; + UnExpandEnvStrings(text,buf,_countof(buf)); + // add quotes if needed + if (wcschr(buf,' ')) + { + int len=Strlen(buf); + if (len<_MAX_PATH-3) + { + memcpy(text+1,buf,len*2); + text[0]='"'; + text[len+1]='"'; + text[len+2]=0; + } + } + else + Strcpy(text,_MAX_PATH,buf); + return true; + } + return false; +} + +bool BrowseLinkHelper( HWND parent, wchar_t *text ) +{ + DoEnvironmentSubst(text,_MAX_PATH); + + CComPtr pDialog; + if (FAILED(pDialog.CoCreateInstance(CLSID_FileOpenDialog,NULL,CLSCTX_INPROC_SERVER))) + return false; + CComQIPtr pCustomize=pDialog; + if (!pCustomize) + return false; + + pDialog->SetTitle(LoadStringEx(IDS_PICK_LINK_TITLE)); + pDialog->SetOkButtonLabel(LoadStringEx(IDS_PICK_LINK_FILE)); + wchar_t button[256]; + Sprintf(button,_countof(button),L" %s ",LoadStringEx(IDS_PICK_LINK_FOLDER)); + pCustomize->AddPushButton(101,button); + + CBrowseLinkEvents events; + DWORD cookie; + pDialog->Advise(&events,&cookie); + pDialog->SetOptions(FOS_ALLNONSTORAGEITEMS|FOS_FILEMUSTEXIST|FOS_DONTADDTORECENT|FOS_DEFAULTNOMINIMODE|FOS_NODEREFERENCELINKS); + { + const wchar_t *c=wcschr(text,'|'); + if (c) + { + for (c++;*c==' ';) + c++; + } + else + c=text; + CComPtr pItem; + if (SUCCEEDED(SHCreateItemFromParsingName(c,NULL,IID_IShellItem,(void**)&pItem))) + pDialog->SetFolder(pItem); + } + + HRESULT hr=pDialog->Show(parent); + CComPtr pResult; + if (hr==S_OK) + pDialog->GetResult(&pResult); + else if (hr==S_FALSE) + pResult=events.m_pResult; + + pDialog->Unadvise(cookie); + + if (pResult) + { + CComString pName; + pResult->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName); + UnExpandEnvStrings(pName,text,_MAX_PATH); + } + + return pResult!=NULL; +} + +bool BrowseIconHelper( HWND parent, wchar_t *text ) +{ + int id=0; + if (*text) + { + wchar_t *c=wcsrchr(text,','); + if (c) + { + *c=0; + id=_wtol(c+1); + } + } + else + Strcpy(text,_MAX_PATH,L"shell32.dll"); + if (BrowseForIcon(parent,text,id)) + { + if (_wcsicmp(PathFindExtension(text),L".ico")==0) + return true; + if (id>0) + { + wchar_t buf[20]; + Sprintf(buf,_countof(buf),L", %d",id); + Strcat(text,_MAX_PATH,buf); + return true; + } + } + return false; +} + +bool CEditCustomItemDlg::Run( HWND parent, int dlgID ) +{ + parent=GetAncestor(parent,GA_ROOT); + DLGTEMPLATE *pTemplate=LoadDialogEx(dlgID); + Create(parent,pTemplate); + ShowWindow(SW_SHOWNORMAL); + ::EnableWindow(parent,FALSE); + SetEnableParent(parent); + MSG msg; + while (m_hWnd && GetMessage(&msg,0,0,0)) + { + if (IsDialogMessage(&msg)) continue; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return GetResult(); +} + +/////////////////////////////////////////////////////////////////////////////// + +// Subclass the tooltip to delay the tip when the mouse moves from one tree item to the next +static LRESULT CALLBACK SubclassInfoTipProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==TTM_UPDATE) + { + int time=(int)SendMessage(hWnd,TTM_GETDELAYTIME,TTDT_RESHOW,0); + SetTimer(hWnd,'CLSH',time,NULL); + return 0; + } + if (uMsg==WM_TIMER && wParam=='CLSH') + { + KillTimer(hWnd,wParam); + DefSubclassProc(hWnd,TTM_UPDATE,0,0); + return 0; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +LRESULT CCustomTreeDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + m_pSetting=NULL; + + InitResize(); + EnableThemeDialogTexture(m_hWnd,ETDT_ENABLETAB); + m_Tree.SubclassWindow(GetDlgItem(IDC_TREEITEMS),this); + m_CommandsTree.SubclassWindow(GetDlgItem(IDC_TREECOMMANDS)); + TreeView_SetImageList(m_CommandsTree,TreeView_GetImageList(m_Tree,TVSIL_NORMAL),TVSIL_NORMAL); + if (IsAppThemed()) + { + m_Tree.SetWindowLong(GWL_STYLE,m_Tree.GetWindowLong(GWL_STYLE)|TVS_TRACKSELECT); + SetWindowTheme(m_Tree,L"Explorer",NULL); + m_CommandsTree.SetWindowLong(GWL_STYLE,m_CommandsTree.GetWindowLong(GWL_STYLE)|TVS_TRACKSELECT); + SetWindowTheme(m_CommandsTree,L"Explorer",NULL); + } + + int height=TreeView_GetItemHeight(m_Tree); + int minHeight=GetSystemMetrics(SM_CXSMICON)+2; + if (height::OnSize(); + return 0; +} + +LRESULT CCustomTreeDlg::OnContextMenu( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + CWindow tree=(HWND)wParam; + if (tree.m_hWnd!=m_Tree.m_hWnd && tree.m_hWnd!=m_CommandsTree.m_hWnd) + return 0; + if (m_Tree.IsDragging()) + { + ReleaseCapture(); + return 0; + } + HTREEITEM hItem=NULL; + POINT pt; + if ((DWORD)lParam==0xFFFFFFFF) + { + // keyboard + hItem=TreeView_GetSelection(tree); + if (hItem) + { + RECT rc; + TreeView_GetItemRect(tree,hItem,&rc,TRUE); + pt.x=(rc.left+rc.right)/2; + pt.y=(rc.top+rc.bottom)/2; + } + else + pt.x=pt.y=0; + tree.ClientToScreen(&pt); + } + else + { + DWORD pos=GetMessagePos(); + pt.x=(short)LOWORD(pos); + pt.y=(short)HIWORD(pos); + TVHITTESTINFO test={pt}; + tree.ScreenToClient(&test.pt); + if (TreeView_HitTest(tree,&test) && (test.flags&(TVHT_ONITEMICON|TVHT_ONITEMLABEL))) + { + TreeView_SelectItem(tree,test.hItem); + hItem=test.hItem; + } + } + + CTreeItem *pItem=NULL; + if (tree.m_hWnd==m_Tree.m_hWnd) + { + if (hItem) + { + TVITEM item={TVIF_PARAM,hItem}; + TreeView_GetItem(m_Tree,&item); + pItem=(CTreeItem*)item.lParam; + } + } + else if (!hItem) + return 0; + + enum { + CMD_EDIT=1, + CMD_RENAME, + CMD_DELETE, + CMD_RESETALL, + CMD_ADD, + CMD_ADD_MENU, + }; + + HMENU menu=CreatePopupMenu(); + wchar_t text[256]; + if (tree.m_hWnd==m_Tree.m_hWnd) + { + if (pItem) + { + if (!pItem->pStdCommand->IsSeparator()) + { + Sprintf(text,_countof(text),L"%s\tEnter",LoadStringEx(IDS_MENU_EDIT)); + AppendMenu(menu,MF_STRING,CMD_EDIT,text); + SetMenuDefaultItem(menu,CMD_EDIT,FALSE); + Sprintf(text,_countof(text),L"%s\tF2",LoadStringEx(IDS_MENU_RENAME)); + AppendMenu(menu,MF_STRING,CMD_RENAME,text); + if (m_pSetting->IsLocked()) + { + EnableMenuItem(menu,CMD_EDIT,MF_BYCOMMAND|MF_GRAYED); + EnableMenuItem(menu,CMD_RENAME,MF_BYCOMMAND|MF_GRAYED); + } + else if (!pItem->pStdCommand->IsCustom()) + EnableMenuItem(menu,CMD_RENAME,MF_BYCOMMAND|MF_GRAYED); + if (!TreeView_GetChild(m_Tree,hItem)) + AppendMenu(menu,MF_STRING,CMD_ADD_MENU,LoadStringEx(IDS_INSERT_MENU)); + if (m_pSetting->IsLocked()) + EnableMenuItem(menu,CMD_ADD_MENU,MF_BYCOMMAND|MF_GRAYED); + } + Sprintf(text,_countof(text),L"%s\tDel",LoadStringEx(IDS_MENU_DELETE)); + AppendMenu(menu,MF_STRING,CMD_DELETE,text); + if (m_pSetting->IsLocked()) + EnableMenuItem(menu,CMD_DELETE,MF_BYCOMMAND|MF_GRAYED); + } + if (!m_pSetting->IsLocked()) + AppendMenu(menu,MF_STRING,CMD_RESETALL,LoadStringEx(m_bMenu?IDS_RESET_MENU:IDS_RESET_TOOLBAR)); + } + else + { + Sprintf(text,_countof(text),L"%s\tEnter",LoadStringEx(m_bMenu?IDS_ADD_MENU:IDS_ADD_TOOLBAR)); + AppendMenu(menu,MF_STRING,CMD_ADD,text); + SetMenuDefaultItem(menu,CMD_ADD,FALSE); + if (m_pSetting->IsLocked()) + EnableMenuItem(menu,CMD_ADD,MF_BYCOMMAND|MF_GRAYED); + } + + int res=TrackPopupMenu(menu,TPM_RIGHTBUTTON|TPM_RETURNCMD,pt.x,pt.y,0,m_hWnd,NULL); + DestroyMenu(menu); + if (res==CMD_EDIT) + EditItemInternal(pItem,hItem); + if (res==CMD_DELETE) + m_Tree.DeleteItem(hItem); + if (res==CMD_RENAME) + TreeView_EditLabel(m_Tree,hItem); + if (res==CMD_RESETALL) + { + if (::MessageBox(m_hWnd,LoadStringEx(m_bMenu?IDS_RESET_MENU_WARN:IDS_RESET_TOOLBAR_WARN),LoadStringEx(m_bMenu?IDS_RESET_MENU:IDS_RESET_TOOLBAR),MB_YESNO|MB_ICONWARNING)==IDYES) + { + { + CSettingsLockWrite lock; + m_pSetting->value=m_pSetting->defValue; + m_pSetting->flags|=CSetting::FLAG_DEFAULT; + ItemsChanged(); + SetSettingsDirty(); + } + SetGroup(m_pSetting-1,true); + } + } + if (res==CMD_ADD) + { + AddItem(hItem); + } + if (res==CMD_ADD_MENU) + { + TVINSERTSTRUCT insert={hItem,TVI_FIRST,{TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_STATE|TVIF_TEXT,NULL,TVIS_EXPANDED,TVIS_EXPANDED}}; + CString text=LoadStringEx(IDS_EMPTY_MENU); + insert.item.pszText=(LPWSTR)(LPCWSTR)text; + HTREEITEM hNew=TreeView_InsertItem(m_Tree,&insert); + TreeView_SelectItem(m_Tree,hNew); + TreeView_EnsureVisible(m_Tree,hNew); + } + return 0; +} + +const CStdCommand *CCustomTreeDlg::FindStdCommand( const wchar_t *name ) +{ + for (int i=0;m_pStdCommands[i].name;i++) + if (m_pStdCommands[i].IsStyle(m_Style,m_StyleMask) && _wcsicmp(m_pStdCommands[i].name,name)==0) + return &m_pStdCommands[i]; + return NULL; +} + +LRESULT CCustomTreeDlg::OnGetInfoTip( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMTVGETINFOTIP *pTip=(NMTVGETINFOTIP*)pnmh; + const CStdCommand *pCommand=NULL; + if (idCtrl==IDC_TREECOMMANDS) + pCommand=(CStdCommand*)pTip->lParam; + else if (!m_pSetting->IsLockedReg()) + { + CTreeItem *pItem=(CTreeItem*)pTip->lParam; + if (pItem) + pCommand=pItem->pStdCommand; + } + if (pCommand) + { + if (idCtrl==IDC_TREECOMMANDS) + Sprintf(pTip->pszText,pTip->cchTextMax,L"%s\n%s",LoadStringEx(pCommand->tipID),LoadStringEx(m_bMenu?IDS_COMMAND_SM_TIP:IDS_COMMAND_EXP_TIP)); + else + Strcpy(pTip->pszText,pTip->cchTextMax,LoadStringEx(pCommand->tipID)); + } + return 0; +} + +LRESULT CCustomTreeDlg::OnBeginDrag( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMTREEVIEW *pDrag=(NMTREEVIEW*)pnmh; + m_Tree.BeginDrag((CStdCommand*)pDrag->itemNew.lParam); + return 0; +} + +LRESULT CCustomTreeDlg::OnAddItem( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + if (pnmh->code==TVN_KEYDOWN) + { + NMTVKEYDOWN *pKey=(NMTVKEYDOWN*)pnmh; + if (pKey->wVKey!=VK_RETURN) + { + bHandled=FALSE; + return 0; + } + } + + HTREEITEM hItem=TreeView_GetSelection(m_CommandsTree); + if (hItem) + AddItem(hItem); + return TRUE; +} + +LRESULT CCustomTreeDlg::OnEditItem( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + if (pnmh->code==TVN_KEYDOWN) + { + NMTVKEYDOWN *pKey=(NMTVKEYDOWN*)pnmh; + if (pKey->wVKey!=VK_RETURN) + { + bHandled=FALSE; + return 0; + } + } + + TVITEM item={TVIF_PARAM,TreeView_GetSelection(m_Tree)}; + if (!item.hItem) return 0; + TreeView_GetItem(m_Tree,&item); + CTreeItem *pItem=(CTreeItem*)item.lParam; + if (pItem) + EditItemInternal(pItem,item.hItem); + return TRUE; +} + +void CCustomTreeDlg::AddItem( HTREEITEM hCommand ) +{ + if (m_pSetting->IsLocked()) return; + TVITEM item={TVIF_PARAM,hCommand}; + TreeView_GetItem(m_CommandsTree,&item); + const CStdCommand *pCommand=(CStdCommand*)item.lParam; + HTREEITEM hAfter=TreeView_GetSelection(m_Tree); + HTREEITEM hParent=NULL; + if (hAfter) + { + hParent=TreeView_GetParent(m_Tree,hAfter); + TVITEM item={TVIF_PARAM,hAfter}; + TreeView_GetItem(m_Tree,&item); + if (!item.lParam) + { + TreeView_DeleteItem(m_Tree,hAfter); + hAfter=TVI_LAST; + } + } + else + hAfter=TVI_LAST; + HTREEITEM hItem=m_Tree.CreateStdItem(pCommand,hParent,hAfter); + TreeView_SelectItem(m_Tree,hItem); + TreeView_EnsureVisible(m_Tree,hItem); + SerializeData(); +} + +HTREEITEM CCustomTreeDlg::GetRoot( void ) +{ + return TreeView_GetRoot(m_Tree); +} + +HTREEITEM CCustomTreeDlg::GetChild( HTREEITEM hParent ) +{ + return TreeView_GetChild(m_Tree,hParent); +} + +HTREEITEM CCustomTreeDlg::GetNext( HTREEITEM hItem ) +{ + return TreeView_GetNextSibling(m_Tree,hItem); +} + +CTreeItem *CCustomTreeDlg::GetItem( HTREEITEM hItem ) +{ + TVITEM item={TVIF_PARAM,hItem}; + TreeView_GetItem(m_Tree,&item); + return (CTreeItem*)item.lParam; +} + +void CCustomTreeDlg::EditItemInternal( CTreeItem *pItem, HTREEITEM hItem ) +{ + if (!m_pSetting->IsLocked() && !pItem->pStdCommand->IsSeparator() && EditItem(pItem,m_Tree,hItem,m_Tree.m_Modules)) + { + SerializeData(); + m_Tree.UpdateItem(pItem,hItem); + } +} + +bool CCustomTreeDlg::EditItem( CTreeItem *pItem, HWND tree, HTREEITEM hItem, std::vector &modules ) +{ + MessageBox(L"Edit Item",L"",MB_OK); + return false; +} + +LRESULT CCustomTreeDlg::OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMTVCUSTOMDRAW *pDraw=(NMTVCUSTOMDRAW*)pnmh; + if (pDraw->nmcd.dwDrawStage==CDDS_PREPAINT) + { + return CDRF_NOTIFYITEMDRAW; + } + else if (pDraw->nmcd.dwDrawStage==CDDS_ITEMPREPAINT && !pDraw->nmcd.lItemlParam) + { + if (!IsAppThemed()) + { + TVITEM item={TVIF_STATE,(HTREEITEM)pDraw->nmcd.dwItemSpec,0,TVIS_SELECTED}; + TreeView_GetItem(m_Tree,&item); + if (item.state&TVIS_SELECTED) + return CDRF_DODEFAULT; + } + pDraw->clrText=GetSysColor(COLOR_GRAYTEXT); + } + return CDRF_DODEFAULT; +} + +int CCustomTreeDlg::ParseTreeItem( CTreeItem *pItem, CSettingsParser &parser ) +{ + const CStdCommand *pStdCommand=FindStdCommand(pItem->name); + if (pStdCommand && pStdCommand->IsSeparator()) + { + pItem->pStdCommand=pStdCommand; + return 0; + } + wchar_t text[256]; + Sprintf(text,_countof(text),L"%s.Command",pItem->name); + pItem->SetCommand(parser.FindSetting(text,L""),m_pStdCommands,m_Style,m_StyleMask); + Sprintf(text,_countof(text),L"%s.Link",pItem->name); + pItem->link=parser.FindSetting(text,L""); + Sprintf(text,_countof(text),L"%s.Label",pItem->name); + pItem->label=parser.FindSetting(text,L""); + Sprintf(text,_countof(text),L"%s.Tip",pItem->name); + pItem->tip=parser.FindSetting(text,L""); + Sprintf(text,_countof(text),L"%s.Icon",pItem->name); + pItem->icon=parser.FindSetting(text,L""); + ParseTreeItemExtra(pItem,parser); + return m_Tree.UpdateItem(pItem,NULL); +} + +void CCustomTreeDlg::AppendString( std::vector &stringBuilder, const wchar_t *text ) +{ + stringBuilder.insert(stringBuilder.end(),text,text+Strlen(text)); +} + +void CCustomTreeDlg::SerializeItem( HTREEITEM hItem, std::vector &stringBuilder ) +{ + TVITEM item={TVIF_PARAM,hItem}; + CTreeItem *pItem=NULL; + if (hItem) + { + TreeView_GetItem(m_Tree,&item); + pItem=(CTreeItem*)item.lParam; + } + wchar_t text[2048]; + HTREEITEM hChild=hItem?TreeView_GetChild(m_Tree,hItem):TreeView_GetRoot(m_Tree); + if (hChild) + { + // save .Items + if (pItem) + Sprintf(text,_countof(text),L"%s.Items=",pItem->name); + else + Strcpy(text,_countof(text),L"Items="); + AppendString(stringBuilder,text); + + bool bFirst=true; + for (;hChild;hChild=TreeView_GetNextSibling(m_Tree,hChild), bFirst=false) + { + item.hItem=hChild; + TreeView_GetItem(m_Tree,&item); + CTreeItem *pChild=(CTreeItem*)item.lParam; + if (pChild) + { + Sprintf(text,_countof(text),bFirst?L"%s":L",%s",pChild->name); + AppendString(stringBuilder,text); + } + } + AppendString(stringBuilder,L"\n"); + } + + if (pItem && !pItem->pStdCommand->IsSeparator()) + { + // save other properties + if (!pItem->command.IsEmpty()) + { + Sprintf(text,_countof(text),L"%s.Command=%s\n",pItem->name,pItem->command); + AppendString(stringBuilder,text); + } + if (!pItem->link.IsEmpty()) + { + Sprintf(text,_countof(text),L"%s.Link=%s\n",pItem->name,pItem->link); + AppendString(stringBuilder,text); + } + if (!pItem->label.IsEmpty()) + { + Sprintf(text,_countof(text),L"%s.Label=%s\n",pItem->name,pItem->label); + AppendString(stringBuilder,text); + } + if (!pItem->tip.IsEmpty()) + { + Sprintf(text,_countof(text),L"%s.Tip=%s\n",pItem->name,pItem->tip); + AppendString(stringBuilder,text); + } + if (!pItem->icon.IsEmpty()) + { + Sprintf(text,_countof(text),L"%s.Icon=%s\n",pItem->name,pItem->icon); + AppendString(stringBuilder,text); + } + SerializeItemExtra(pItem,stringBuilder); + } + hChild=hItem?TreeView_GetChild(m_Tree,hItem):TreeView_GetRoot(m_Tree); + for (;hChild;hChild=TreeView_GetNextSibling(m_Tree,hChild)) + SerializeItem(hChild,stringBuilder); +} + +void CCustomTreeDlg::SerializeData( void ) +{ + std::vector stringBuilder; + SerializeItem(NULL,stringBuilder); + stringBuilder.push_back(0); + CSettingsLockWrite lock; + const wchar_t *strNew=&stringBuilder[0]; + const wchar_t *strOld=m_pSetting->value.vt==VT_BSTR?m_pSetting->value.bstrVal:L"???"; + if ((m_pSetting->flags&CSetting::FLAG_DEFAULT) || wcscmp(strNew,strOld)!=0) + SetSettingsDirty(); + m_pSetting->value=CComVariant(strNew); + m_pSetting->flags&=~CSetting::FLAG_DEFAULT; + ItemsChanged(); +} + +void CCustomTreeDlg::CreateTreeItems( CSettingsParser &parser, HTREEITEM hParent, const CSettingsParser::TreeItem *pItems, int index ) +{ + for (;!pItems[index].name.IsEmpty();index++) + { + CTreeItem *pNewItem=new CTreeItem; + pNewItem->name=pItems[index].name; + TVINSERTSTRUCT insert={hParent,TVI_LAST,{TVIF_STATE|TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE,NULL,TVIS_EXPANDED,TVIS_EXPANDED}}; + insert.item.iImage=insert.item.iSelectedImage=ParseTreeItem(pNewItem,parser); + insert.item.lParam=(LPARAM)pNewItem; + CString dispName=pNewItem->GetDisplayName(false); + insert.item.pszText=(LPWSTR)(LPCWSTR)dispName; + HTREEITEM hItem=TreeView_InsertItem(m_Tree,&insert); + + if (pItems[index].children>=0) + CreateTreeItems(parser,hItem,pItems,pItems[index].children); + } +} + +void CCustomTreeDlg::SetGroup( CSetting *pGroup, bool bReset ) +{ + if (!m_pSetting || bReset) // optimization - initialize the UI only the first time + { + TreeView_DeleteAllItems(m_Tree); + m_pSetting=pGroup+1; + Assert(!m_pSetting->pLinkTo); + m_Tree.SetDisabled(m_pSetting->IsLocked()); + const wchar_t *pText=L""; + if (m_pSetting->value.vt==VT_BSTR) + pText=m_pSetting->value.bstrVal; + + CSettingsParser parser; + parser.LoadText(pText,Strlen(pText)); + parser.ParseText(); + std::vector items; + parser.ParseTree(L"Items",items); + if (!items.empty()) + CreateTreeItems(parser,NULL,&items[0],0); + InitItems(); + } + // use the tooltip from m_CommandsTree to show the "locked" tooltip for m_Tree. otherwise it will behave like an infotip and move from item to item + CWindow tooltip=(HWND)m_CommandsTree.SendMessage(TVM_GETTOOLTIPS); + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS|TTF_IDISHWND,m_hWnd,(UINT_PTR)(HWND)m_Tree}; + CString str=LoadStringEx(m_bMenu?IDS_MENU_LOCKED:IDS_TOOLBAR_LOCKED); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + if (m_pSetting->IsLockedReg()) + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + else + tooltip.SendMessage(TTM_DELTOOL,0,(LPARAM)&tool); + + TreeView_SetBkColor(m_Tree,m_pSetting->IsLocked()?GetSysColor(COLOR_BTNFACE):-1); + TreeView_SetBkColor(m_CommandsTree,m_pSetting->IsLocked()?GetSysColor(COLOR_BTNFACE):-1); +} + +CCustomTreeDlg::CCustomTreeDlg( bool bMenu, const CStdCommand *pStdCommands, int style, int mask ): +m_Tree(*new CSettingsTree(mask)), m_CommandsTree(*new CCommandsTree) +{ + m_bMenu=bMenu; + m_pStdCommands=pStdCommands; + m_Style=style; + m_StyleMask=mask; +} + +CCustomTreeDlg::~CCustomTreeDlg( void ) +{ + delete &m_Tree; + delete &m_CommandsTree; +} + +/////////////////////////////////////////////////////////////////////////////// + +class CBrowseForIconDlg: public CResizeableDlg +{ +public: + CBrowseForIconDlg( wchar_t *path, int &id ): m_pPath(path), m_ID(id) { m_bResult=false; } + void SetEnableParent( HWND parent ) { m_EnableParent=parent; } + bool GetResult( void ) { return m_bResult; } + + BEGIN_MSG_MAP( CBrowseForIconDlg ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + MESSAGE_HANDLER( WM_SIZE, OnSize ) + MESSAGE_HANDLER( WM_GETMINMAXINFO, OnGetMinMaxInfo ) + COMMAND_ID_HANDLER( IDC_BUTTONBROWSE, OnBrowse ) + COMMAND_ID_HANDLER( IDOK, OnOK ) + COMMAND_ID_HANDLER( IDCANCEL, OnCancel ) + COMMAND_HANDLER( IDC_EDITFILE, EN_KILLFOCUS, OnKillFocus ) + NOTIFY_HANDLER( IDC_LISTICONS, LVN_ITEMACTIVATE, OnItemActivate ) + END_MSG_MAP() + + BEGIN_RESIZE_MAP + RESIZE_CONTROL(IDC_EDITFILE,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_BUTTONBROWSE,MOVE_MOVE_X) + RESIZE_CONTROL(IDC_LISTICONS,MOVE_SIZE_X|MOVE_SIZE_Y) + RESIZE_CONTROL(IDOK,MOVE_MOVE_X|MOVE_MOVE_Y) + RESIZE_CONTROL(IDCANCEL,MOVE_MOVE_X|MOVE_MOVE_Y) + END_RESIZE_MAP + +protected: + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnBrowse( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnKillFocus( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnItemActivate( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + +private: + HWND m_EnableParent; + bool m_bResult; + wchar_t *m_pPath; + int &m_ID; + CString m_LastName; + + void UpdateIcons( int id ); + void StorePlacement( void ); + static BOOL CALLBACK EnumIconsProc( HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam ); +}; + +LRESULT CBrowseForIconDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + SetDlgItemText(IDC_EDITFILE,m_pPath); + CWindow list=GetDlgItem(IDC_LISTICONS); + list.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_DOUBLEBUFFER,LVS_EX_DOUBLEBUFFER); + HDC hdc=CreateCompatibleDC(NULL); + HFONT font0=(HFONT)SelectObject(hdc,list.GetFont()); + TEXTMETRIC metrics; + GetTextMetrics(hdc,&metrics); + SelectObject(hdc,font0); + DeleteDC(hdc); + ListView_SetIconSpacing(list,GetSystemMetrics(SM_CXICON)+metrics.tmHeight+7,GetSystemMetrics(SM_CYICON)+metrics.tmHeight+7); + if (IsAppThemed()) + SetWindowTheme(list,L"Explorer",NULL); + UpdateIcons(m_ID); + InitResize(MOVE_MODAL); + SHAutoComplete(GetDlgItem(IDC_EDITFILE),SHACF_FILESYSTEM); + + RECT rc; + CRegKey regSettings; + if (regSettings.Open(HKEY_CURRENT_USER,GetSettingsRegPath())==ERROR_SUCCESS) + { + ULONG size=sizeof(rc); + if (regSettings.QueryBinaryValue(L"CBrowseForIconDlg",&rc,&size)==ERROR_SUCCESS && size==sizeof(rc)) + SetStoreRect(rc); + } + return TRUE; +} + +LRESULT CBrowseForIconDlg::OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + CResizeableDlg::OnSize(); + return 0; +} + +LRESULT CBrowseForIconDlg::OnBrowse( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + OPENFILENAME ofn={sizeof(ofn)}; + ofn.hwndOwner=m_hWnd; + wchar_t filters[256]; + Strcpy(filters,_countof(filters),LoadStringEx(IDS_ICON_FILTERS)); + for (wchar_t *c=filters;*c;c++) + if (*c=='|') *c=0; + ofn.lpstrFilter=filters; + ofn.nFilterIndex=1; + wchar_t path[_MAX_PATH]; + GetDlgItemText(IDC_EDITFILE,path,_countof(path)); + DoEnvironmentSubst(path,_countof(path)); + wchar_t dir[_MAX_PATH]; + Strcpy(dir,_countof(dir),path); + PathRemoveFileSpec(dir); + ofn.lpstrInitialDir=dir; + path[0]=0; + ofn.lpstrFile=path; + ofn.nMaxFile=_countof(path); + CString title=LoadStringEx(IDS_ICON_TITLE); + ofn.lpstrTitle=title; + ofn.Flags=OFN_DONTADDTORECENT|OFN_ENABLESIZING|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_NOCHANGEDIR; + if (GetOpenFileName(&ofn)) + { + wchar_t buf[_MAX_PATH]; + UnExpandEnvStrings(path,buf,_countof(buf)); + SetDlgItemText(IDC_EDITFILE,buf); + UpdateIcons(-1); + } + return 0; +} + +void CBrowseForIconDlg::StorePlacement( void ) +{ + RECT rc; + GetStoreRect(rc); + + CRegKey regSettings; + if (regSettings.Open(HKEY_CURRENT_USER,GetSettingsRegPath())!=ERROR_SUCCESS) + regSettings.Create(HKEY_CURRENT_USER,GetSettingsRegPath()); + regSettings.SetBinaryValue(L"CBrowseForIconDlg",&rc,sizeof(rc)); +} + +LRESULT CBrowseForIconDlg::OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (GetFocus()==GetDlgItem(IDC_EDITFILE)) + { + SendMessage(WM_NEXTDLGCTL,(WPARAM)GetDlgItem(IDOK).m_hWnd,TRUE); + return 0; + } + CString text; + GetDlgItemText(IDC_EDITFILE,text); + text.TrimLeft(); + text.TrimRight(); + Strcpy(m_pPath,_MAX_PATH,text); + CWindow list=GetDlgItem(IDC_LISTICONS); + int sel=ListView_GetNextItem(list,-1,LVNI_SELECTED); + if (sel>=0) + { + LVITEM item={LVIF_PARAM,sel}; + ListView_GetItem(list,&item); + m_ID=(int)item.lParam; + } + else + m_ID=0; + ::EnableWindow(m_EnableParent,TRUE); + m_bResult=true; + StorePlacement(); + DestroyWindow(); + return 0; +} + +LRESULT CBrowseForIconDlg::OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + ::EnableWindow(m_EnableParent,TRUE); + m_bResult=false; + StorePlacement(); + DestroyWindow(); + return 0; +} + +LRESULT CBrowseForIconDlg::OnKillFocus( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + UpdateIcons(-1); + return 0; +} + +LRESULT CBrowseForIconDlg::OnItemActivate( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + PostMessage(WM_COMMAND,IDOK,0); + return 0; +} + +BOOL CALLBACK CBrowseForIconDlg::EnumIconsProc( HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam ) +{ + if (IS_INTRESOURCE(lpszName)) + { + HWND list=(HWND)lParam; + HICON hIcon=(HICON)LoadImage(hModule,lpszName,IMAGE_ICON,0,0,LR_DEFAULTSIZE|LR_DEFAULTCOLOR); + if (hIcon) + { + HIMAGELIST images=ListView_GetImageList(list,LVSIL_NORMAL); + int idx=ImageList_AddIcon(images,hIcon); + DestroyIcon(hIcon); + LVITEM item={LVIF_IMAGE|LVIF_PARAM|LVIF_TEXT}; + item.iItem=idx; + item.iImage=idx; + item.lParam=(WORD)(DWORD_PTR)lpszName; + wchar_t text[20]; + Sprintf(text,_countof(text),L"%d",(int)item.lParam); + item.pszText=text; + ListView_InsertItem(list,&item); + } + } + return TRUE; +} + +void CBrowseForIconDlg::UpdateIcons( int id ) +{ + wchar_t path[1024]; + GetDlgItemText(IDC_EDITFILE,path,_countof(path)); + DoEnvironmentSubst(path,_countof(path)); + if (m_LastName==path && id==-1) return; + m_LastName=path; + + CWindow list=GetDlgItem(IDC_LISTICONS); + ListView_DeleteAllItems(list); + HIMAGELIST images=ImageList_Create(GetSystemMetrics(SM_CXICON),GetSystemMetrics(SM_CYICON),ILC_COLOR32|ILC_MASK,10,10); + ListView_SetImageList(list,images,LVSIL_NORMAL); + ImageList_RemoveAll(images); + + if (_wcsicmp(PathFindExtension(path),L".ico")==0) + { + // load icon file + HICON hIcon=(HICON)LoadImage(NULL,path,IMAGE_ICON,0,0,LR_DEFAULTSIZE|LR_DEFAULTCOLOR|LR_LOADFROMFILE); + if (hIcon) + { + ImageList_AddIcon(images,hIcon); + DestroyIcon(hIcon); + LVITEM item={LVIF_IMAGE|LVIF_PARAM|LVIF_STATE,0,0,LVIS_SELECTED,LVIS_SELECTED}; + item.iImage=0; + item.lParam=0; + ListView_InsertItem(list,&item); + } + } + else + { + // load module file + HINSTANCE hInstance=_AtlBaseModule.GetResourceInstance(); + HMODULE hModule; + if (*path) + hModule=LoadLibraryEx(path,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + else + hModule=hInstance; + if (hModule) + { + // enumerate icons, extract icons + list.SendMessage(WM_SETREDRAW,FALSE); + EnumResourceNames(hModule,RT_GROUP_ICON,EnumIconsProc,(LONG_PTR)list.m_hWnd); + list.SendMessage(WM_SETREDRAW,TRUE); + // free module + if (hModule!=hInstance) FreeLibrary(hModule); + } + if (ListView_GetItemCount(list)>0) + { + int idx=0; + if (id>0) + { + LVFINDINFO find={LVFI_PARAM,0,id}; + idx=ListView_FindItem(list,-1,&find); + if (idx<0) idx=0; + } + ListView_SetItemState(list,idx,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED); + ListView_EnsureVisible(list,idx,FALSE); + list.InvalidateRect(NULL); + } + } +} + +bool BrowseForIcon( HWND hWndParent, wchar_t *path, int &id ) +{ + CBrowseForIconDlg dlg(path,id); + + hWndParent=GetAncestor(hWndParent,GA_ROOT); + DLGTEMPLATE *pTemplate=LoadDialogEx(IDD_BROWSEFORICON); + dlg.Create(hWndParent,pTemplate); + dlg.ShowWindow(SW_SHOWNORMAL); + EnableWindow(hWndParent,FALSE); + dlg.SetEnableParent(hWndParent); + MSG msg; + while (dlg.m_hWnd && GetMessage(&msg,0,0,0)) + { + if (dlg.IsDialogMessage(&msg)) continue; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return dlg.GetResult(); +} + +/////////////////////////////////////////////////////////////////////////////// + +bool BrowseForBitmap( HWND hWndParent, wchar_t *path, bool bAllowJpeg ) +{ + OPENFILENAME ofn={sizeof(ofn)}; + ofn.hwndOwner=hWndParent; + wchar_t filters[256]; + Strcpy(filters,_countof(filters),LoadStringEx(bAllowJpeg?IDS_BMP_FILTERS2:IDS_BMP_FILTERS)); + for (wchar_t *c=filters;*c;c++) + if (*c=='|') *c=0; + ofn.lpstrFilter=filters; + ofn.nFilterIndex=1; + wchar_t dir[_MAX_PATH]; + Strcpy(dir,_countof(dir),path); + PathRemoveFileSpec(dir); + ofn.lpstrInitialDir=dir; + path[0]=0; + ofn.lpstrFile=path; + ofn.nMaxFile=_MAX_PATH; + CString title=LoadStringEx(IDS_BMP_TITLE); + ofn.lpstrTitle=title; + ofn.Flags=OFN_DONTADDTORECENT|OFN_ENABLESIZING|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_NOCHANGEDIR; + if (GetOpenFileName(&ofn)) + { + wchar_t buf[_MAX_PATH]; + UnExpandEnvStrings(path,buf,_countof(buf)); + Strcpy(path,_MAX_PATH,buf); + return true; + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool BrowseForSound( HWND hWndParent, wchar_t *path ) +{ + OPENFILENAME ofn={sizeof(ofn)}; + ofn.hwndOwner=hWndParent; + wchar_t filters[256]; + Strcpy(filters,_countof(filters),LoadStringEx(IDS_WAV_FILTERS)); + for (wchar_t *c=filters;*c;c++) + if (*c=='|') *c=0; + ofn.lpstrFilter=filters; + ofn.nFilterIndex=1; + wchar_t dir[_MAX_PATH]; + Strcpy(dir,_countof(dir),path); + PathRemoveFileSpec(dir); + ofn.lpstrInitialDir=dir; + path[0]=0; + ofn.lpstrFile=path; + ofn.nMaxFile=_MAX_PATH; + CString title=LoadStringEx(IDS_WAV_TITLE); + ofn.lpstrTitle=title; + ofn.Flags=OFN_DONTADDTORECENT|OFN_ENABLESIZING|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_NOCHANGEDIR; + if (GetOpenFileName(&ofn)) + { + wchar_t buf[_MAX_PATH]; + UnExpandEnvStrings(path,buf,_countof(buf)); + Strcpy(path,_MAX_PATH,buf); + return true; + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + +class CTreeSettingsDlg: public CResizeableDlg +{ +public: + enum { + IDC_EDITBOX=101, + IDC_BROWSEBTN=102, + IDC_PLAYBTN=103, + WM_EDITKEY=WM_APP+11, + }; + + enum TEditMode + { + EDIT_NONE, + EDIT_INT, + EDIT_STRING, + EDIT_ICON, + EDIT_BITMAP, + EDIT_BITMAP_JPG, + EDIT_SOUND, + EDIT_HOTKEY, + EDIT_HOTKEY_ANY, + EDIT_COLOR, + EDIT_FONT, + }; + + BEGIN_MSG_MAP( CTreeSettingsDlg ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + MESSAGE_HANDLER( WM_DESTROY, OnDestroy ) + MESSAGE_HANDLER( WM_SIZE, OnSize ) + MESSAGE_HANDLER( WM_EDITKEY, OnEditKey ) + MESSAGE_HANDLER( WM_CONTEXTMENU, OnContextMenu ) + COMMAND_HANDLER( IDC_EDITBOX, EN_CHANGE, OnEditChange ) + COMMAND_HANDLER( IDC_EDITBOX, EN_KILLFOCUS, OnKillFocus ) + COMMAND_HANDLER( IDC_BROWSEBTN, BN_CLICKED, OnBrowse ) + COMMAND_HANDLER( IDC_PLAYBTN, BN_CLICKED, OnPlay ) + COMMAND_HANDLER( IDC_BROWSEBTN, BN_KILLFOCUS, OnKillFocus ) + NOTIFY_HANDLER( IDC_SETTINGS, NM_CUSTOMDRAW, OnCustomDraw ) + NOTIFY_HANDLER( IDC_SETTINGS, NM_CLICK, OnClick ) + NOTIFY_HANDLER( IDC_SETTINGS, NM_DBLCLK, OnClick ) + NOTIFY_HANDLER( IDC_SETTINGS, TVN_KEYDOWN, OnKeyDown ) + NOTIFY_HANDLER( IDC_SETTINGS, TVN_GETINFOTIP, OnGetInfoTip ) + NOTIFY_HANDLER( IDC_SETTINGS, TVN_SELCHANGED, OnSelChanged ) + NOTIFY_HANDLER( IDC_SETTINGS, TVN_ITEMEXPANDING, OnExpanding ) + END_MSG_MAP() + + BEGIN_RESIZE_MAP + RESIZE_CONTROL(IDC_SETTINGS,MOVE_SIZE_X|MOVE_SIZE_Y) + RESIZE_CONTROL(IDC_STATICTIP,MOVE_SIZE_X|MOVE_MOVE_Y) + END_RESIZE_MAP + + void SetGroup( CSetting *pGroup, const CString &filter, const CSetting *pSelect ); + void Validate( void ) { ApplyEditBox(); } + +protected: + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnEditKey( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnContextMenu( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnEditChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnKillFocus( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnBrowse( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnPlay( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnKeyDown( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnGetInfoTip( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnSelChanged( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnExpanding( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) { return TRUE; } // prevent collapsing + +private: + CWindow m_Tree; + const CSetting *m_pGroup; + CWindow m_EditBox; + CWindow m_BrowseButton; + CWindow m_PlayButton; + HICON m_PlayIcon; + TEditMode m_EditMode; + HTREEITEM m_EditItem; + CSetting *m_pEditSetting; + bool m_bBasic; + bool m_bIgnoreFocus; + bool m_bSearch; + + void UpdateGroup( const CSetting *pModified ); + void ToggleItem( HTREEITEM hItem, bool bDefault ); + void PlayItem( HTREEITEM hItem ); + void LocateSetting( const CSetting *pSetting ); + void ItemSelected( HTREEITEM hItem, CSetting *pSetting, bool bEnabled ); + void ApplyEditBox( void ); + void UpdateEditPosition( void ); + const CSetting *GetNextSetting( const CSetting *pSetting, const wchar_t *filter ); + bool IsVisible( const CSetting *pSetting, const wchar_t *filter ) const; + HTREEITEM GetNextItem( HTREEITEM hItem, bool bChildren=true ); + HTREEITEM FindSettingsItem( const wchar_t *name ); +}; + +// Subclass the tree control to forward the command messages to the parent +static LRESULT CALLBACK SubclassTreeProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_COMMAND) + return SendMessage(GetParent(hWnd),uMsg,wParam,lParam); + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +static int g_HotKey; + +static bool GetKeyName( int key, wchar_t *text, int size, bool bCtrl, bool bAlt, bool bShift ) +{ + wchar_t name[100]; + text[0]=0; + int len=0; + if (bCtrl || (key&(HOTKEYF_CONTROL<<8))) + { + GetKeyNameText(MapVirtualKey(VK_CONTROL,MAPVK_VK_TO_VSC)<<16,name,_countof(name)); + len+=Sprintf(text+len,size-len,L"%s+",name); + } + if (bAlt || (key&(HOTKEYF_ALT<<8))) + { + GetKeyNameText(MapVirtualKey(VK_MENU,MAPVK_VK_TO_VSC)<<16,name,_countof(name)); + len+=Sprintf(text+len,size-len,L"%s+",name); + } + if (bShift || (key&(HOTKEYF_SHIFT<<8))) + { + GetKeyNameText(MapVirtualKey(VK_SHIFT,MAPVK_VK_TO_VSC)<<16,name,_countof(name)); + len+=Sprintf(text+len,size-len,L"%s+",name); + } + if (key) + { + int scan=MapVirtualKey(key&255,MAPVK_VK_TO_VSC); + if (scan==0) + { + text[0]=0; + return false; + } + if (!GetKeyNameText(scan<<16,name,_countof(name))) + { + text[0]=0; + return false; + } + Strcpy(text+len,size-len,name); + } + + return true; +} + +// Subclass the edit control to forward some keyboard messages to the parent and to act as a hotkey control +static LRESULT CALLBACK SubclassEditProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (dwRefData) + { + static bool s_bCtrl, s_bAlt, s_bShift; + + if (uMsg==WM_GETDLGCODE) + return DLGC_WANTALLKEYS; + + if (uMsg==WM_CHAR || uMsg==WM_SYSCHAR) + return 0; + + if (uMsg==WM_KEYDOWN || uMsg==WM_SYSKEYDOWN) + { + if ((wParam==VK_UP || wParam==VK_DOWN || wParam==VK_PRIOR || wParam==VK_NEXT) && GetKeyState(VK_CONTROL)>=0 && GetKeyState(VK_MENU)>=0 && GetKeyState(VK_SHIFT)>=0) + return SendMessage(GetParent(hWnd),uMsg,wParam,lParam); + if (wParam==VK_ESCAPE) + { // Esc - clears the key + g_HotKey=0; + SetWindowText(hWnd,L""); + return 0; + } + wchar_t text[100]; + if (wParam==VK_CONTROL) s_bCtrl=true, g_HotKey=0; + else if (wParam==VK_SHIFT) s_bShift=true, g_HotKey=0; + else if (wParam==VK_MENU) s_bAlt=true, g_HotKey=0; + else + { + g_HotKey=wParam&255; + if (s_bCtrl) g_HotKey|=(HOTKEYF_CONTROL<<8); + if (s_bAlt) g_HotKey|=(HOTKEYF_ALT<<8); + if (s_bShift) g_HotKey|=(HOTKEYF_SHIFT<<8); + if (dwRefData==1) + { + if (!s_bAlt && !(s_bCtrl && s_bShift)) + g_HotKey=0; + } + } + GetKeyName(g_HotKey,text,_countof(text),s_bCtrl,s_bAlt,s_bShift); + SetWindowText(hWnd,text); + return 0; + } + if (uMsg==WM_KEYUP || uMsg==WM_SYSKEYUP) + { + wchar_t text[100]; + if (wParam==VK_CONTROL) s_bCtrl=false; + if (wParam==VK_MENU) s_bAlt=false; + if (wParam==VK_SHIFT) s_bShift=false; + GetKeyName(g_HotKey,text,_countof(text),s_bCtrl,s_bAlt,s_bShift); + SetWindowText(hWnd,text); + return 0; + } + if (uMsg==WM_RBUTTONUP || uMsg==WM_CONTEXTMENU) + return 0; + } + if (uMsg==WM_CHAR && wParam==VK_SPACE && GetKeyState(VK_CONTROL)<0) + return SendMessage(GetParent(hWnd),WM_KEYDOWN,wParam,lParam); + if (uMsg==WM_CHAR && wParam==VK_RETURN) + return 0; + if (uMsg==WM_GETDLGCODE && wParam==VK_RETURN) + return DLGC_WANTALLKEYS; + if (uMsg==WM_KEYDOWN) + { + if (wParam==VK_UP || wParam==VK_DOWN || wParam==VK_PRIOR || wParam==VK_NEXT || (wParam=='P' && GetKeyState(VK_CONTROL)<0)) + return SendMessage(GetParent(hWnd),uMsg,wParam,lParam); + if (wParam==VK_RETURN || wParam==VK_ESCAPE) + return SendMessage(GetParent(GetParent(hWnd)),CTreeSettingsDlg::WM_EDITKEY,wParam,0); + } + if (uMsg==WM_KILLFOCUS) + { + if (wParam && (HWND)wParam==GetDlgItem(GetParent(hWnd),CTreeSettingsDlg::IDC_BROWSEBTN)) + return 0; + } + if (uMsg==WM_CHAR && wParam==16) + return 0; // prevent Ctrl+P from playing the default sound + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +LRESULT CTreeSettingsDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + InitResize(); + EnableThemeDialogTexture(m_hWnd,ETDT_ENABLETAB); + + m_Tree=GetDlgItem(IDC_SETTINGS); + m_Tree.SetWindowLong(GWL_STYLE,m_Tree.GetWindowLong(GWL_STYLE)|WS_CLIPCHILDREN); + if (IsAppThemed()) + { + m_Tree.SetWindowLong(GWL_STYLE,m_Tree.GetWindowLong(GWL_STYLE)|TVS_TRACKSELECT); + SetWindowTheme(m_Tree,L"Explorer",NULL); + } + m_Tree.SendMessage(TVM_SETEXTENDEDSTYLE,TVS_EX_DOUBLEBUFFER,TVS_EX_DOUBLEBUFFER); + SetWindowSubclass(m_Tree,SubclassTreeProc,'CLSH',0); + HINSTANCE hInstance=_AtlBaseModule.GetResourceInstance(); + + HIMAGELIST images=GetSettingsImageList(m_Tree); + TreeView_SetImageList(m_Tree,images,TVSIL_NORMAL); + int height=TreeView_GetItemHeight(m_Tree); + if (height<18) TreeView_SetItemHeight(m_Tree,18); + + HWND tooltip=TreeView_GetToolTips(m_Tree); + SendMessage(tooltip,TTM_SETDELAYTIME,TTDT_AUTOPOP,10000); + SendMessage(tooltip,TTM_SETDELAYTIME,TTDT_INITIAL,1000); + SendMessage(tooltip,TTM_SETDELAYTIME,TTDT_RESHOW,1000); + SetWindowSubclass(tooltip,SubclassInfoTipProc,'CLSH',0); + + HFONT font=m_Tree.GetFont(); + m_EditBox=CreateWindow(L"EDIT",NULL,WS_CHILD|WS_BORDER|ES_AUTOHSCROLL,0,0,0,0,m_Tree,(HMENU)IDC_EDITBOX,hInstance,NULL); + m_EditBox.SetFont(font); + SetWindowSubclass(m_EditBox,SubclassEditProc,'CLSH',0); + m_BrowseButton=CreateWindow(L"BUTTON",L"...",WS_CHILD|BS_PUSHBUTTON,0,0,0,0,m_Tree,(HMENU)IDC_BROWSEBTN,hInstance,NULL); + m_BrowseButton.SetFont(font); + m_PlayIcon=(HICON)LoadImage(hInstance,MAKEINTRESOURCE(IDI_ICONPLAY),IMAGE_ICON,0,0,0); + m_PlayButton=CreateWindow(L"BUTTON",L">",WS_CHILD|BS_PUSHBUTTON|BS_ICON,0,0,0,0,m_Tree,(HMENU)IDC_PLAYBTN,hInstance,NULL); + m_PlayButton.SendMessage(BM_SETIMAGE,IMAGE_ICON,(LPARAM)m_PlayIcon); + m_EditMode=EDIT_NONE; + m_EditItem=NULL; + m_pEditSetting=NULL; + m_bIgnoreFocus=false; + + return TRUE; +} + +LRESULT CTreeSettingsDlg::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + DestroyIcon(m_PlayIcon); + bHandled=FALSE; + m_EditMode=EDIT_NONE; + return 0; +} + +LRESULT CTreeSettingsDlg::OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + CResizeableDlg::OnSize(); + UpdateEditPosition(); + return 0; +} + +LRESULT CTreeSettingsDlg::OnEditKey( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==VK_RETURN && !(m_EditBox.GetWindowLong(GWL_STYLE)&ES_READONLY)) + ItemSelected(m_EditItem,m_pEditSetting,true); + return 0; +} + +LRESULT CTreeSettingsDlg::OnEditChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + UpdateEditPosition(); + return 0; +} + +LRESULT CTreeSettingsDlg::OnKillFocus( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (!m_bIgnoreFocus && m_pEditSetting) + { + ApplyEditBox(); + UpdateEditPosition(); + } + return 0; +} + +LRESULT CTreeSettingsDlg::OnBrowse( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (m_EditMode==EDIT_ICON) + { + m_bIgnoreFocus=true; + CString str; + m_EditBox.GetWindowText(str); + str.TrimLeft(); str.TrimRight(); + wchar_t text[_MAX_PATH*2]; + Strcpy(text,_countof(text),str); + int id=0; + if (*text) + { + wchar_t *c=wcsrchr(text,','); + if (c) + { + *c=0; + id=_wtol(c+1); + } + } + else + Strcpy(text,_countof(text),L"shell32.dll"); + if (BrowseForIcon(m_hWnd,text,id)) + { + if (id>0) + { + wchar_t buf[20]; + Sprintf(buf,_countof(buf),L", %d",id); + Strcat(text,_countof(text),buf); + } + m_EditBox.SetWindowText(text); + } + SendMessage(WM_NEXTDLGCTL,(LPARAM)m_EditBox.m_hWnd,TRUE); + m_bIgnoreFocus=false; + } + else if (m_EditMode==EDIT_BITMAP || m_EditMode==EDIT_BITMAP_JPG) + { + m_bIgnoreFocus=true; + CString str; + m_EditBox.GetWindowText(str); + str.TrimLeft(); str.TrimRight(); + wchar_t text[1024]; + if (_wcsicmp(PathFindExtension(str),L".bmp")==0 || _wcsicmp(PathFindExtension(str),L".png")==0 || (m_EditMode==EDIT_BITMAP_JPG && _wcsicmp(PathFindExtension(str),L".jpg")==0)) + { + Strcpy(text,_countof(text),str); + DoEnvironmentSubst(text,_countof(text)); + } + else + text[0]=0; + if (BrowseForBitmap(m_hWnd,text,m_EditMode==EDIT_BITMAP_JPG)) + { + m_EditBox.SetWindowText(text); + } + SendMessage(WM_NEXTDLGCTL,(LPARAM)m_EditBox.m_hWnd,TRUE); + m_EditBox.SetFocus(); + m_bIgnoreFocus=false; + } + else if (m_EditMode==EDIT_SOUND) + { + m_bIgnoreFocus=true; + CString str; + m_EditBox.GetWindowText(str); + str.TrimLeft(); str.TrimRight(); + wchar_t text[1024]; + if (_wcsicmp(PathFindExtension(str),L".wav")==0) + { + Strcpy(text,_countof(text),str); + DoEnvironmentSubst(text,_countof(text)); + } + else + text[0]=0; + if (BrowseForSound(m_hWnd,text)) + { + m_EditBox.SetWindowText(text); + } + SendMessage(WM_NEXTDLGCTL,(LPARAM)m_EditBox.m_hWnd,TRUE); + m_EditBox.SetFocus(); + m_bIgnoreFocus=false; + } + else if (m_EditMode==EDIT_COLOR) + { + m_bIgnoreFocus=true; + CString str; + m_EditBox.GetWindowText(str); + str.TrimLeft(); str.TrimRight(); + wchar_t *end; + int val=wcstol(str,&end,16)&0xFFFFFF; + static COLORREF customColors[16]; + CHOOSECOLOR choose={sizeof(choose),m_hWnd,NULL,val,customColors}; + choose.Flags=CC_ANYCOLOR|CC_FULLOPEN|CC_RGBINIT; + if (ChooseColor(&choose)) + { + wchar_t text[100]; + Sprintf(text,_countof(text),L"%06X",choose.rgbResult); + m_EditBox.SetWindowText(text); + ApplyEditBox(); + UpdateGroup(m_pEditSetting); + m_Tree.Invalidate(); + } + SendMessage(WM_NEXTDLGCTL,(LPARAM)m_EditBox.m_hWnd,TRUE); + m_EditBox.SetFocus(); + m_bIgnoreFocus=false; + } + else if (m_EditMode==EDIT_FONT) + { + m_bIgnoreFocus=true; + CString text; + m_EditBox.GetWindowText(text); + + HDC hdc=::GetDC(NULL); + int dpi=GetDeviceCaps(hdc,LOGPIXELSY); + ::ReleaseDC(NULL,hdc); + + LOGFONT font={0}; + const wchar_t *str=text; + while (*str==' ') + str++; + str=GetToken(str,font.lfFaceName,_countof(font.lfFaceName),L","); + int len=Strlen(font.lfFaceName); + while (len>0 && font.lfFaceName[len-1]==' ') + font.lfFaceName[--len]=0; + while (*str==' ') + str++; + wchar_t token[256]; + str=GetToken(str,token,_countof(token),L","); + len=Strlen(token); + while (len>0 && token[len-1]==' ') + token[--len]=0; + font.lfWeight=FW_NORMAL; + if (_wcsicmp(token,L"bold")==0) + font.lfWeight=FW_BOLD; + else if (_wcsicmp(token,L"italic")==0) + font.lfItalic=1; + else if (_wcsicmp(token,L"bold_italic")==0) + font.lfWeight=FW_BOLD, font.lfItalic=1; + str=GetToken(str,token,_countof(token),L", \t"); + font.lfHeight=-(_wtol(token)*dpi+36)/72; + + CHOOSEFONT choose={sizeof(choose),m_hWnd,NULL,&font}; + choose.Flags=CF_NOSCRIPTSEL; + if (*font.lfFaceName) + choose.Flags|=CF_INITTOLOGFONTSTRUCT; + if (ChooseFont(&choose)) + { + wchar_t text[256]; + const wchar_t *type=font.lfItalic?L"italic":L"normal"; + if (font.lfWeight>=FW_BOLD) + type=font.lfItalic?L"bold_italic":L"bold"; + Sprintf(text,_countof(text),L"%s, %s, %d",font.lfFaceName,type,(-font.lfHeight*72+dpi/2)/dpi); + m_EditBox.SetWindowText(text); + } + SendMessage(WM_NEXTDLGCTL,(LPARAM)m_EditBox.m_hWnd,TRUE); + m_EditBox.SetFocus(); + m_bIgnoreFocus=false; + } + return 0; +} + +LRESULT CTreeSettingsDlg::OnPlay( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + PlayItem(TreeView_GetSelection(m_Tree)); + return 0; +} + +LRESULT CTreeSettingsDlg::OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMTVCUSTOMDRAW *pDraw=(NMTVCUSTOMDRAW*)pnmh; + if (pDraw->nmcd.dwDrawStage==CDDS_PREPAINT) + { + UpdateEditPosition(); + return CDRF_NOTIFYITEMDRAW; + } + else if (pDraw->nmcd.dwDrawStage==CDDS_ITEMPREPAINT) + { + TVITEM item={TVIF_IMAGE|TVIF_STATE,(HTREEITEM)pDraw->nmcd.dwItemSpec,0,TVIS_SELECTED}; + TreeView_GetItem(m_Tree,&item); + if ((item.state&TVIS_CUT) && (!(item.state&TVIS_SELECTED) || IsAppThemed())) + pDraw->clrText=GetSysColor(COLOR_GRAYTEXT); + } + return CDRF_DODEFAULT; +} + +void CTreeSettingsDlg::ToggleItem( HTREEITEM hItem, bool bDefault ) +{ + if (!hItem) return; + TVITEM item={TVIF_PARAM|TVIF_IMAGE|TVIF_STATE,hItem,0,TVIS_CUT}; + TreeView_GetItem(m_Tree,&item); + if (item.state&TVIS_CUT) + return; + CSetting *pSetting=(CSetting*)item.lParam; + if (pSetting->pLinkTo) pSetting=pSetting->pLinkTo; + if (bDefault) + { + if (pSetting->flags&CSetting::FLAG_DEFAULT) + return; + { + CSettingsLockWrite lock; + pSetting->flags|=CSetting::FLAG_DEFAULT; + pSetting->value=pSetting->defValue; + SetSettingsDirty(); + } + if (m_pEditSetting && (m_pEditSetting==pSetting || m_pEditSetting->pLinkTo==pSetting)) + { + m_pEditSetting=NULL; + ItemSelected(item.hItem,pSetting,true); + } + if (pSetting->flags&CSetting::FLAG_CALLBACK) + { + SettingChangedCallback(pSetting); + } + UpdateGroup(pSetting); + } + else if (pSetting->type==CSetting::TYPE_BOOL) + { + // toggle + bool state=IsVariantTrue(pSetting->value); + { + CSettingsLockWrite lock; + pSetting->value=CComVariant(state?0:1); + pSetting->flags&=~CSetting::FLAG_DEFAULT; + SetSettingsDirty(); + } + if (pSetting->flags&CSetting::FLAG_CALLBACK) + { + SettingChangedCallback(pSetting); + } + UpdateGroup(pSetting); + } + else if (pSetting->type==CSetting::TYPE_RADIO) + { + // set parent's value + for (CSetting *pParent=pSetting-1;;pParent--) + { + if (pParent->type!=CSetting::TYPE_RADIO) + { + CSetting *pTarget=pParent->pLinkTo?pParent->pLinkTo:pParent; + Assert(pTarget->type==CSetting::TYPE_INT); + int val=(int)(pSetting-pParent-1); + if (pTarget->value.vt==VT_I4 && pTarget->value.intVal==val) + break; + { + CSettingsLockWrite lock; + pTarget->value=CComVariant(val); + pTarget->flags&=~CSetting::FLAG_DEFAULT; + SetSettingsDirty(); + } + if (pParent->flags&CSetting::FLAG_CALLBACK) + { + SettingChangedCallback(pParent); + } + UpdateGroup(pParent); + break; + } + } + } +} + +void CTreeSettingsDlg::PlayItem( HTREEITEM hItem ) +{ + if (!hItem) return; + TVITEM item={TVIF_PARAM,hItem}; + TreeView_GetItem(m_Tree,&item); + CSetting *pSetting=(CSetting*)item.lParam; + if (pSetting->type==CSetting::TYPE_SOUND && pSetting->GetValue().vt==VT_BSTR) + { + if (!*pSetting->GetValue().bstrVal) + return; + wchar_t path[_MAX_PATH]; + Strcpy(path,_countof(path),pSetting->GetValue().bstrVal); + DoEnvironmentSubst(path,_countof(path)); + if (_wcsicmp(PathFindExtension(path),L"wav")==0) + PlaySound(path,NULL,SND_FILENAME|SND_ASYNC|SND_NODEFAULT|SND_SYSTEM); + else + PlaySound(path,NULL,SND_APPLICATION|SND_ALIAS|SND_ASYNC|SND_NODEFAULT|SND_SYSTEM); + } +} + +void CTreeSettingsDlg::LocateSetting( const CSetting *pSetting ) +{ + for (const CSetting *pGroup=pSetting;;pGroup--) + { + if (pGroup->type==CSetting::TYPE_GROUP) + { + SelectSettingsTab(pGroup->nameID,true,pSetting); + return; + } + } +} + +LRESULT CTreeSettingsDlg::OnClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + DWORD pos=GetMessagePos(); + TVHITTESTINFO test={{(short)LOWORD(pos),(short)HIWORD(pos)}}; + m_Tree.ScreenToClient(&test.pt); + if (TreeView_HitTest(m_Tree,&test) && (test.flags&(TVHT_ONITEMICON|TVHT_ONITEMLABEL))) + ToggleItem(test.hItem,GetKeyState(VK_CONTROL)<0); + + return 0; +} + +LRESULT CTreeSettingsDlg::OnContextMenu( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if ((HWND)wParam!=m_Tree.m_hWnd) + return 0; + HTREEITEM hItem=NULL; + POINT pt; + if ((DWORD)lParam==0xFFFFFFFF) + { + // keyboard + hItem=TreeView_GetSelection(m_Tree); + if (hItem) + { + RECT rc; + TreeView_GetItemRect(m_Tree,hItem,&rc,TRUE); + pt.x=(rc.left+rc.right)/2; + pt.y=(rc.top+rc.bottom)/2; + } + else + pt.x=pt.y=0; + m_Tree.ClientToScreen(&pt); + } + else + { + DWORD pos=GetMessagePos(); + pt.x=(short)LOWORD(pos); + pt.y=(short)HIWORD(pos); + TVHITTESTINFO test={pt}; + m_Tree.ScreenToClient(&test.pt); + if (TreeView_HitTest(m_Tree,&test) && (test.flags&(TVHT_ONITEMICON|TVHT_ONITEMLABEL))) + { + TreeView_SelectItem(m_Tree,test.hItem); + hItem=test.hItem; + } + } + + if (!hItem) return 0; + + TVITEM item={TVIF_PARAM|TVIF_IMAGE|TVIF_STATE,hItem,0,TVIS_CUT}; + TreeView_GetItem(m_Tree,&item); + CSetting *pSetting=(CSetting*)item.lParam; + + enum + { + CMD_TOGGLE=1, + CMD_DEFAULT, + CMD_PLAY, + CMD_LOCATE, + }; + + HMENU menu=CreatePopupMenu(); + if (pSetting->type!=CSetting::TYPE_RADIO) + { + if (pSetting->type==CSetting::TYPE_BOOL) + { + AppendMenu(menu,MF_STRING,CMD_TOGGLE,LoadStringEx(IDS_TOGGLE_SETTING)); + if (item.state&TVIS_CUT) + EnableMenuItem(menu,CMD_TOGGLE,MF_BYCOMMAND|MF_GRAYED); + } + if (!(pSetting->flags&CSetting::FLAG_NODEFAULT)) + { + AppendMenu(menu,MF_STRING,CMD_DEFAULT,LoadStringEx(IDS_DEFAULT_SETTING)); + if ((item.state&TVIS_CUT) || pSetting->IsDefault()) + EnableMenuItem(menu,CMD_DEFAULT,MF_BYCOMMAND|MF_GRAYED); + } + } + else + { + AppendMenu(menu,MF_STRING,1,LoadStringEx(IDS_SELECT_SETTING)); + if (item.state&TVIS_CUT) + EnableMenuItem(menu,1,MF_BYCOMMAND|MF_GRAYED); + } + if (pSetting->type==CSetting::TYPE_SOUND) + { + AppendMenu(menu,MF_STRING,CMD_PLAY,LoadStringEx(IDS_PLAY_SETTING)); + if (pSetting->GetValue().vt!=VT_BSTR || *pSetting->GetValue().bstrVal==0) + EnableMenuItem(menu,CMD_PLAY,MF_BYCOMMAND|MF_GRAYED); + } + if (m_bSearch) + AppendMenu(menu,MF_STRING,CMD_LOCATE,LoadStringEx(IDS_LOCATE_SETTING)); + + int res=TrackPopupMenu(menu,TPM_RIGHTBUTTON|TPM_RETURNCMD,pt.x,pt.y,0,m_hWnd,NULL); + DestroyMenu(menu); + if (res==CMD_TOGGLE) + ToggleItem(hItem,false); + if (res==CMD_DEFAULT) + ToggleItem(hItem,true); + if (res==CMD_PLAY) + PlayItem(hItem); + if (res==CMD_LOCATE) + LocateSetting(pSetting); + + return 0; +} + +LRESULT CTreeSettingsDlg::OnKeyDown( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMTVKEYDOWN *pKey=(NMTVKEYDOWN*)pnmh; + if (pKey->wVKey==VK_SPACE && GetKeyState(VK_MENU)>=0) + { + ToggleItem(TreeView_GetSelection(m_Tree),(GetKeyState(VK_CONTROL)<0)); + return 1; + } + if (pKey->wVKey=='P' && GetKeyState(VK_CONTROL)<0) + { + PlayItem(TreeView_GetSelection(m_Tree)); + return 1; + } + bHandled=FALSE; + return 0; +} + +LRESULT CTreeSettingsDlg::OnGetInfoTip( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMTVGETINFOTIP *pTip=(NMTVGETINFOTIP*)pnmh; + const CSetting *pSetting=(CSetting*)pTip->lParam; + if (pSetting->IsLocked()) + Sprintf(pTip->pszText,pTip->cchTextMax,L"%s\n%s",LoadStringEx(pSetting->tipID),LoadStringEx(pSetting->IsLockedReg()?IDS_SETTING_LOCKED:IDS_SETTING_LOCKED_GP)); + else + Strcpy(pTip->pszText,pTip->cchTextMax,LoadStringEx(pSetting->tipID)); + return 0; +} + +LRESULT CTreeSettingsDlg::OnSelChanged( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + HTREEITEM hItem=TreeView_GetSelection(m_Tree); + if (hItem) + { + TVITEM item={TVIF_PARAM|TVIF_STATE,hItem,0,TVIS_CUT}; + TreeView_GetItem(m_Tree,&item); + CSetting *pSetting=(CSetting*)item.lParam; + ItemSelected(item.hItem,pSetting,(item.state&TVIS_CUT)==0); + } + else + ItemSelected(NULL,NULL,false); + return 0; +} + +void CTreeSettingsDlg::ApplyEditBox( void ) +{ + if (m_pEditSetting) + { + { + CSettingsLockWrite lock; + + CString str; + m_EditBox.GetWindowText(str); + str.TrimLeft(); str.TrimRight(); + CSetting *pSetting=m_pEditSetting->pLinkTo?m_pEditSetting->pLinkTo:m_pEditSetting; + if (pSetting->type==CSetting::TYPE_INT) + { + int val=_wtol(str); + if (pSetting->value.vt!=VT_I4 || pSetting->value.intVal!=val) + { + pSetting->value=CComVariant(val); + pSetting->flags&=~CSetting::FLAG_DEFAULT; + } + } + else if (pSetting->type==CSetting::TYPE_COLOR) + { + wchar_t *end; + int val=wcstol(str,&end,16)&0xFFFFFF; + if (pSetting->value.vt!=VT_I4 || pSetting->value.intVal!=val) + { + pSetting->value=CComVariant(val); + pSetting->flags&=~CSetting::FLAG_DEFAULT; + } + } + else if (pSetting->type==CSetting::TYPE_HOTKEY || pSetting->type==CSetting::TYPE_HOTKEY_ANY) + { + if (pSetting->value.vt!=VT_I4 || pSetting->value.intVal!=g_HotKey) + { + pSetting->value=CComVariant(g_HotKey); + pSetting->flags&=~CSetting::FLAG_DEFAULT; + } + } + else + { + if (pSetting->value.vt!=VT_BSTR || str!=pSetting->value.bstrVal) + { + pSetting->value=CComVariant(str); + pSetting->flags&=~CSetting::FLAG_DEFAULT; + } + } + SetSettingsDirty(); + } + if (m_pEditSetting->flags&CSetting::FLAG_CALLBACK) + { + SettingChangedCallback(m_pEditSetting); + } + } +} + +void CTreeSettingsDlg::ItemSelected( HTREEITEM hItem, CSetting *pSetting, bool bEnabled ) +{ + if (m_pEditSetting) + { + ApplyEditBox(); + const CSetting *pOld=m_pEditSetting; + m_pEditSetting=NULL; + UpdateGroup(pOld); + } + m_EditItem=NULL; + TEditMode mode=EDIT_NONE; + wchar_t text[2048]; + if (pSetting) + { + const CComVariant &valVar=pSetting->GetValue(); + if (pSetting->type==CSetting::TYPE_INT && pSetting[1].type!=CSetting::TYPE_RADIO) + { + mode=EDIT_INT; + int val=0; + if (valVar.vt==VT_I4) + val=valVar.intVal; + Sprintf(text,_countof(text),L"%d",val); + } + else if (pSetting->type==CSetting::TYPE_STRING || pSetting->type==CSetting::TYPE_ICON || pSetting->type==CSetting::TYPE_BITMAP || pSetting->type==CSetting::TYPE_BITMAP_JPG || pSetting->type==CSetting::TYPE_SOUND || pSetting->type==CSetting::TYPE_FONT) + { + if (valVar.vt==VT_BSTR) + Strcpy(text,_countof(text),valVar.bstrVal); + else + text[0]=0; + if (pSetting->type==CSetting::TYPE_STRING) + mode=EDIT_STRING; + else if (pSetting->type==CSetting::TYPE_ICON) + mode=EDIT_ICON; + else if (pSetting->type==CSetting::TYPE_BITMAP) + mode=EDIT_BITMAP; + else if (pSetting->type==CSetting::TYPE_BITMAP_JPG) + mode=EDIT_BITMAP_JPG; + else if (pSetting->type==CSetting::TYPE_SOUND) + mode=EDIT_SOUND; + else + mode=EDIT_FONT; + } + else if (pSetting->type==CSetting::TYPE_HOTKEY || pSetting->type==CSetting::TYPE_HOTKEY_ANY) + { + text[0]=0; + g_HotKey=0; + if (valVar.vt==VT_I4) + { + g_HotKey=valVar.intVal; + GetKeyName(valVar.intVal,text,_countof(text),false,false,false); + } + if (bEnabled) + mode=pSetting->type==CSetting::TYPE_HOTKEY_ANY?EDIT_HOTKEY_ANY:EDIT_HOTKEY; + } + else if (pSetting->type==CSetting::TYPE_COLOR) + { + mode=EDIT_COLOR; + int val=0; + if (valVar.vt==VT_I4) + val=valVar.intVal; + Sprintf(text,_countof(text),L"%06X",val); + } + } + + RECT rc; + m_EditMode=mode; + if (mode!=EDIT_NONE) + { + CString str=LoadStringEx(pSetting->nameID); + TVITEM item={TVIF_TEXT,hItem,0,0,(LPWSTR)(LPCWSTR)str}; + TreeView_SetItem(m_Tree,&item); + m_Tree.GetClientRect(&rc); + int w=rc.right; + TreeView_GetItemRect(m_Tree,hItem,&rc,TRUE); + rc.left=rc.right; + rc.right=w; + m_EditItem=hItem; + m_pEditSetting=pSetting; + } + + if (mode==EDIT_ICON || mode==EDIT_BITMAP || mode==EDIT_BITMAP_JPG || mode==EDIT_SOUND || mode==EDIT_FONT || mode==EDIT_COLOR) + { + RECT rc2=rc; + int width=(rc2.bottom-rc2.top)*3/2; + rc2.left=rc2.right-width; + if (mode==EDIT_SOUND) + { + m_PlayButton.SetWindowPos(NULL,&rc2,SWP_NOZORDER|SWP_SHOWWINDOW); + rc2.left-=width; + rc2.right-=width; + } + else + m_PlayButton.ShowWindow(SW_HIDE); + m_BrowseButton.SetWindowPos(NULL,&rc2,SWP_NOZORDER|SWP_SHOWWINDOW); + m_BrowseButton.EnableWindow(bEnabled); + rc.right=rc2.left; + } + else + { + m_BrowseButton.ShowWindow(SW_HIDE); + m_PlayButton.ShowWindow(SW_HIDE); + } + + if (mode!=EDIT_NONE) + { + m_EditBox.SetWindowText(text); + m_EditBox.SendMessage(EM_SETREADONLY,!bEnabled,0); + m_EditBox.SetWindowPos(NULL,&rc,SWP_NOZORDER|SWP_SHOWWINDOW); + SendMessage(WM_NEXTDLGCTL,(LPARAM)m_EditBox.m_hWnd,TRUE); + SetWindowSubclass(m_EditBox,SubclassEditProc,'CLSH',(mode==EDIT_HOTKEY)?1:((mode==EDIT_HOTKEY_ANY)?2:0)); + } + else + m_EditBox.ShowWindow(SW_HIDE); +} + +void CTreeSettingsDlg::UpdateEditPosition( void ) +{ + if (m_EditMode==EDIT_NONE) return; + + RECT rc; + m_Tree.GetClientRect(&rc); + int w=rc.right; + TreeView_GetItemRect(m_Tree,m_EditItem,&rc,TRUE); + rc.left=rc.right; + rc.right=w; + w-=rc.left; + int width=(rc.bottom-rc.top)*3/2; + + HDC hdc=CreateCompatibleDC(NULL); + HFONT font0=(HFONT)SelectObject(hdc,m_EditBox.GetFont()); + SIZE size; + CString str; + m_EditBox.GetWindowText(str); + GetTextExtentPoint(hdc,str,str.GetLength(),&size); + SelectObject(hdc,font0); + DeleteDC(hdc); + DWORD margins=(DWORD)m_EditBox.SendMessage(EM_GETMARGINS); + size.cx+=HIWORD(margins)+LOWORD(margins)+12; + if (m_EditMode==EDIT_ICON || m_EditMode==EDIT_BITMAP || m_EditMode==EDIT_BITMAP_JPG || m_EditMode==EDIT_FONT || m_EditMode==EDIT_COLOR) + size.cx+=width; + if (m_EditMode==EDIT_SOUND) + size.cx+=width*2; + if (size.cxflags&CSetting::FLAG_HIDDEN) + return false; + if (!pSetting->MatchFilter(filter)) + return false; + int style, mask; + GetSettingsStyle(style,mask); + if ((pSetting->flags&mask) && !(pSetting->flags&style)) + return false; + if (pSetting->type==CSetting::TYPE_RADIO) + { + while (pSetting->type==CSetting::TYPE_RADIO) + pSetting--; + return IsVisible(pSetting,filter); + } + return true; +} + +const CSetting *CTreeSettingsDlg::GetNextSetting( const CSetting *pSetting, const wchar_t *filter ) +{ + pSetting++; + while (pSetting->type==CSetting::TYPE_RADIO) + { + if (!(pSetting->flags&CSetting::FLAG_HIDDEN)) + return pSetting; + pSetting++; + } + + if (*filter) + { + while (pSetting->name && (pSetting->type==CSetting::TYPE_GROUP || !IsVisible(pSetting,filter) || !pSetting->MatchFilter(filter))) + { + if (pSetting->type==CSetting::TYPE_GROUP && (pSetting->flags&CSetting::FLAG_HIDDEN)) + { + // if this is a hidden group skip to the next + pSetting++; + while (pSetting->type!=CSetting::TYPE_GROUP) + pSetting++; + } + pSetting++; + } + } + else if (m_bBasic) + { + while (pSetting->name && (pSetting->type==CSetting::TYPE_GROUP || !IsVisible(pSetting,filter) || !(pSetting->flags&CSetting::FLAG_BASIC))) + pSetting++; + } + else + { + while (pSetting->name && pSetting->type!=CSetting::TYPE_GROUP && !IsVisible(pSetting,filter)) + pSetting++; + } + + if (pSetting->name && pSetting->type!=CSetting::TYPE_GROUP) + return pSetting; + return NULL; +} + +HTREEITEM CTreeSettingsDlg::GetNextItem( HTREEITEM hItem, bool bChildren ) +{ + if (!hItem) return NULL; + if (bChildren) + { + HTREEITEM hNext=TreeView_GetChild(m_Tree,hItem); + if (hNext) return hNext; + } + { + HTREEITEM hNext=TreeView_GetNextSibling(m_Tree,hItem); + if (hNext) return hNext; + } + return GetNextItem(TreeView_GetParent(m_Tree,hItem),false); +} + +HTREEITEM CTreeSettingsDlg::FindSettingsItem( const wchar_t *name ) +{ + HTREEITEM res=NULL; + for (HTREEITEM hItem=TreeView_GetRoot(m_Tree);hItem;hItem=GetNextItem(hItem)) + { + TVITEM item={TVIF_PARAM,hItem}; + TreeView_GetItem(m_Tree,&item); + const CSetting *pSetting=(CSetting*)item.lParam; + if (pSetting && wcscmp(name,pSetting->name)==0) + res=hItem; + } + return res; +} + +void CTreeSettingsDlg::SetGroup( CSetting *pGroup, const CString &filter, const CSetting *pSelect ) +{ + ItemSelected(NULL,NULL,false); + m_pGroup=pGroup; + // fill tree control + m_Tree.SendMessage(WM_SETREDRAW,FALSE); + TreeView_SelectItem(m_Tree,NULL); + TreeView_DeleteAllItems(m_Tree); + int level=0; + HTREEITEM hRadioParent=NULL; + m_bSearch=!filter.IsEmpty(); + m_bBasic=(pGroup->nameID==IDS_BASIC_SETTINGS); + HTREEITEM hSelect=NULL; + for (const CSetting *pSetting=GetNextSetting(pGroup,filter);pSetting;pSetting=GetNextSetting(pSetting,filter)) + { + wchar_t text[256]; + text[0]=0; + if (pSetting->type==CSetting::TYPE_BOOL || pSetting->type==CSetting::TYPE_RADIO || (pSetting->type==CSetting::TYPE_INT && pSetting[1].type==CSetting::TYPE_RADIO)) + { + // the text for BOOL, RADIO or RADIO's parent items doesn't change + Strcpy(text,_countof(text),LoadStringEx(pSetting->nameID)); + } + if (pSetting->type!=CSetting::TYPE_RADIO) + hRadioParent=NULL; + HTREEITEM hParent=hRadioParent; + if (pSetting->nest) + { + Assert(pSetting->type!=CSetting::TYPE_RADIO); + hParent=FindSettingsItem(pSetting->nest); + } + TVINSERTSTRUCT insert={hParent,TVI_LAST,{TVIF_STATE|TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM,NULL,TVIS_EXPANDED,TVIS_EXPANDED,text,0,SETTING_STATE_SETTING,SETTING_STATE_SETTING}}; + insert.item.lParam=(LPARAM)pSetting; + if (pSetting->IsLocked()) + { + insert.item.state|=INDEXTOOVERLAYMASK(1); + insert.item.stateMask|=TVIS_OVERLAYMASK; + } + else if (pSetting->flags&CSetting::FLAG_WARNING) + { + insert.item.state|=INDEXTOOVERLAYMASK(2); + insert.item.stateMask|=TVIS_OVERLAYMASK; + } + HTREEITEM hItem=TreeView_InsertItem(m_Tree,&insert); + if (pSetting->type!=CSetting::TYPE_RADIO) + hRadioParent=hItem; + if (pSetting==pSelect) + hSelect=hItem; + } + UpdateGroup(NULL); + m_Tree.SendMessage(WM_SETREDRAW,TRUE); + if (hSelect) + { + TreeView_SelectItem(m_Tree,hSelect); + m_Tree.PostMessage(TVM_ENSUREVISIBLE,0,(LPARAM)hSelect); // post instead of send, because the tree may be resized afterwards + } + m_Tree.Invalidate(); +} + +void CTreeSettingsDlg::UpdateGroup( const CSetting *pModified ) +{ + for (HTREEITEM hItem=TreeView_GetRoot(m_Tree);hItem;hItem=GetNextItem(hItem)) + { + wchar_t text[256]; + TVITEM item={TVIF_PARAM|TVIF_STATE|TVIF_IMAGE,hItem,0,TVIS_BOLD|TVIS_CUT,text}; + TreeView_GetItem(m_Tree,&item); + const CSetting *pSetting=(CSetting*)item.lParam; + if (pSetting->type==CSetting::TYPE_RADIO) continue; + + // check if the item is enabled + bool bEnabled=pSetting->IsEnabled(); + + // check if the item is default + bool bDefault=pSetting->IsDefault(); + const CComVariant &valVar=pSetting->GetValue(); + + // calculate text + if (pSetting!=m_pEditSetting) + { + if (pSetting->type==CSetting::TYPE_HOTKEY || pSetting->type==CSetting::TYPE_HOTKEY_ANY) + { + wchar_t val[100]; + val[0]=0; + if (valVar.vt==VT_I4) + GetKeyName(valVar.intVal,val,_countof(val),false,false,false); + CString str=LoadStringEx(pSetting->nameID); + Sprintf(text,_countof(text),L"%s: %s",str,val); + item.mask|=TVIF_TEXT; + } + else if (pSetting->type>=CSetting::TYPE_STRING) + { + CString str=LoadStringEx(pSetting->nameID); + const wchar_t *val=L""; + if (valVar.vt==VT_BSTR) + val=valVar.bstrVal; + Sprintf(text,_countof(text),L"%s: %s",str,val); + item.mask|=TVIF_TEXT; + } + else if (pSetting->type==CSetting::TYPE_INT && pSetting[1].type!=CSetting::TYPE_RADIO) + { + CString str=LoadStringEx(pSetting->nameID); + int val=0; + if (valVar.vt==VT_I4) + val=valVar.intVal; + Sprintf(text,_countof(text),L"%s: %d",str,val); + item.mask|=TVIF_TEXT; + } + else if (pSetting->type==CSetting::TYPE_COLOR) + { + CString str=LoadStringEx(pSetting->nameID); + int val=0; + if (valVar.vt==VT_I4) + val=valVar.intVal; + Sprintf(text,_countof(text),L"%s: %06X",str,val); + item.mask|=TVIF_TEXT; + } + } + + // calculate state + int image=SETTING_STATE_SETTING; + if (pSetting->type==CSetting::TYPE_BOOL) + image=SETTING_STATE_CHECKBOX|(IsVariantTrue(valVar)?SETTING_STATE_CHECKED:0); + if (pSetting->type==CSetting::TYPE_COLOR) + { + image=SETTING_IMAGE_COLOR+(pSetting->flags>>24); + + HIMAGELIST images=GetSettingsImageList(m_Tree); + int cx, cy; + ImageList_GetIconSize(images,&cx,&cy); + + BITMAPINFO dib={sizeof(dib)}; + dib.bmiHeader.biWidth=cx; + dib.bmiHeader.biHeight=cy; + dib.bmiHeader.biPlanes=1; + dib.bmiHeader.biBitCount=32; + dib.bmiHeader.biCompression=BI_RGB; + HDC hdc=CreateCompatibleDC(NULL); + HDC hdcMask=CreateCompatibleDC(NULL); + HBITMAP bmp=CreateDIBSection(hdc,&dib,DIB_RGB_COLORS,NULL,NULL,0); + HBITMAP bmpMask=CreateDIBSection(hdcMask,&dib,DIB_RGB_COLORS,NULL,NULL,0); + + HGDIOBJ bmp0=SelectObject(hdc,bmp); + HGDIOBJ bmp1=SelectObject(hdcMask,bmpMask); + SetDCBrushColor(hdc,valVar.intVal&0xFFFFFF); + SetDCPenColor(hdc,0); + SelectObject(hdc,GetStockObject(DC_BRUSH)); + SelectObject(hdc,GetStockObject(DC_PEN)); + Rectangle(hdc,0,0,cx,cy); + RECT rc={0,0,cx,cy}; + FillRect(hdcMask,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH)); + SelectObject(hdc,bmp0); + SelectObject(hdcMask,bmp1); + ImageList_Replace(images,image,bmp,bmpMask); + DeleteObject(bmp); + DeleteObject(bmpMask); + DeleteDC(hdc); + DeleteDC(hdcMask); + } + int state=bDefault?0:TVIS_BOLD; + if (!bEnabled) + { + if (pSetting->type!=CSetting::TYPE_COLOR) image|=SETTING_STATE_DISABLED; + state|=TVIS_CUT; + } + if (item.iImage==image) + item.mask&=~TVIF_IMAGE; + else + item.iImage=item.iSelectedImage=image; + + if ((item.state&(TVIS_BOLD|TVIS_CUT))==state) + item.mask&=~TVIF_STATE; + else + item.state=state; + if (item.mask!=0) + { + if (item.mask&TVIF_IMAGE) + item.mask|=TVIF_SELECTEDIMAGE; + TreeView_SetItem(m_Tree,&item); + RECT rc; + TreeView_GetItemRect(m_Tree,hItem,&rc,FALSE); + m_Tree.InvalidateRect(&rc); + } + + // update radio buttons + if (pSetting->type==CSetting::TYPE_INT && pSetting[1].type==CSetting::TYPE_RADIO) + { + int val=0; + if (valVar.vt==VT_I4) + val=valVar.intVal; + for (HTREEITEM hRadio=TreeView_GetChild(m_Tree,hItem);hRadio;hRadio=TreeView_GetNextSibling(m_Tree,hRadio)) + { + TVITEM radio={TVIF_IMAGE|TVIF_PARAM|TVIF_STATE,hRadio,0,TVIS_CUT}; + TreeView_GetItem(m_Tree,&radio); + int v=(int)((CSetting*)radio.lParam-pSetting-1); + + int image=SETTING_STATE_RADIO; + if (v==val) image|=SETTING_STATE_CHECKED; + int state=0; + if (!bEnabled) + { + if (pSetting->type!=CSetting::TYPE_COLOR) image|=SETTING_STATE_DISABLED; + state=TVIS_CUT; + } + + if (radio.iImage!=image || radio.state!=state) + { + radio.iImage=radio.iSelectedImage=image; + radio.mask=TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_STATE; + radio.state=state; + TreeView_SetItem(m_Tree,&radio); + RECT rc; + TreeView_GetItemRect(m_Tree,hRadio,&rc,FALSE); + m_Tree.InvalidateRect(&rc); + } + } + } + } +} + +class CDefaultSettingsPanel: public ISettingsPanel +{ +public: + virtual HWND Create( HWND parent ); + virtual HWND Activate( CSetting *pGroup, const RECT &rect, bool bReset ); + virtual bool Validate( HWND parent ); + void SetFilter( const CString &filter ) { m_Filter=filter; } + void Select( const CSetting *pSelect ) { m_pSelect=pSelect; } + +private: + static CTreeSettingsDlg s_Dialog; + CString m_Filter; + const CSetting *m_pSelect; +}; + +CTreeSettingsDlg CDefaultSettingsPanel::s_Dialog; + +ISettingsPanel *GetDefaultSettings( const CString *filter, const CSetting *pSelect ) +{ + static CDefaultSettingsPanel panel; + if (filter) + panel.SetFilter(*filter); + if (pSelect) + panel.Select(pSelect); + return &panel; +} + +HWND CDefaultSettingsPanel::Create( HWND parent ) +{ + if (!s_Dialog.m_hWnd) + s_Dialog.Create(parent,LoadDialogEx(IDD_SETTINGSTREE)); + return s_Dialog.m_hWnd; +} + +HWND CDefaultSettingsPanel::Activate( CSetting *pGroup, const RECT &rect, bool bReset ) +{ + s_Dialog.SetGroup(pGroup,m_Filter,m_pSelect); + m_pSelect=NULL; + s_Dialog.SetWindowPos(HWND_TOP,&rect,SWP_SHOWWINDOW); + return s_Dialog.m_hWnd; +} + +bool CDefaultSettingsPanel::Validate( HWND parent ) +{ + s_Dialog.Validate(); + return true; +} diff --git a/ClassicShellSrc/ClassicShellLib/SettingsUIHelper.h b/ClassicShellSrc/ClassicShellLib/SettingsUIHelper.h new file mode 100644 index 0000000..9863569 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/SettingsUIHelper.h @@ -0,0 +1,388 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#include "SettingsParser.h" +#include "resource.h" +#include "Assert.h" +#include + +class CCommandsTree; +class CSettingsTree; +class ISettingsPanel; +struct CSetting; + +/////////////////////////////////////////////////////////////////////////////// + +// CResizeableDlg - a dialog that rearranges its controls when it gets resized +template class CResizeableDlg: public CDialogImpl +{ +public: + CResizeableDlg( void ) + { + m_ClientSize.cx=m_ClientSize.cy=0; + m_WindowSize.cx=m_WindowSize.cy=0; + m_Flags=0; + } + + void Create( HWND hWndParent ) + { + CDialogImpl::Create(hWndParent); + } + + void Create( HWND hWndParent, DLGTEMPLATE *pTemplate ) + { + ATLASSUME(m_hWnd == NULL); + if (!m_thunk.Init(NULL,NULL)) + { + SetLastError(ERROR_OUTOFMEMORY); + return; + } + + _AtlWinModule.AddCreateWndData(&m_thunk.cd,(CDialogImplBaseT*)this); + HWND hWnd=::CreateDialogIndirect(_AtlBaseModule.GetResourceInstance(),pTemplate,hWndParent,T::StartDialogProc); + ATLASSUME(m_hWnd==hWnd); + } + +protected: + enum + { + MOVE_LEFT=1, + MOVE_LEFT2=2, + MOVE_RIGHT=4, + MOVE_RIGHT2=8, + MOVE_TOP=16, + MOVE_TOP2=32, + MOVE_BOTTOM=64, + MOVE_BOTTOM2=128, + + MOVE_MOVE_X=MOVE_LEFT|MOVE_RIGHT, + MOVE_MOVE_Y=MOVE_TOP|MOVE_BOTTOM, + MOVE_SIZE_X=MOVE_RIGHT, + MOVE_SIZE_Y=MOVE_BOTTOM, + MOVE_LEFT_HALF=MOVE_RIGHT2, + MOVE_RIGHT_HALF=MOVE_LEFT2|MOVE_RIGHT, + MOVE_CENTER=MOVE_LEFT2|MOVE_RIGHT2, + MOVE_TOP_HALF=MOVE_BOTTOM2, + MOVE_BOTTOM_HALF=MOVE_TOP2|MOVE_BOTTOM, + MOVE_VCENTER=MOVE_TOP2|MOVE_BOTTOM2, + + MOVE_HORIZONTAL=1, + MOVE_VERTICAL=2, + MOVE_GRIPPER=4, + MOVE_REINITIALIZE=8, // InitResize is called for a second time to recapture the control sizes + + MOVE_MODAL=MOVE_HORIZONTAL|MOVE_VERTICAL|MOVE_GRIPPER, + }; + + struct Control + { + int id; + unsigned int flags; + HWND hwnd; + RECT rect0; + }; + + void InitResize( int flags=MOVE_HORIZONTAL|MOVE_VERTICAL ) + { + m_Flags=flags; + T *pThis=static_cast(this); + + int count=0; + for (const Control *pControl=pThis->GetResizeControls();pControl->id;pControl++) + count++; + m_Controls.resize(count); + if (count>0) + memcpy(&m_Controls[0],pThis->GetResizeControls(),count*sizeof(Control)); + + RECT rc; + pThis->GetClientRect(&rc); + if (!(m_Flags&MOVE_REINITIALIZE)) + { + m_Gripper.m_hWnd=NULL; + if (m_Flags&MOVE_GRIPPER) + m_Gripper.Create(L"SCROLLBAR",pThis->m_hWnd,rc,NULL,WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|SBS_SIZEBOX|SBS_SIZEGRIP|SBS_SIZEBOXBOTTOMRIGHTALIGN); + } + m_ClientSize.cx=rc.right; + m_ClientSize.cy=rc.bottom; + pThis->GetWindowRect(&rc); + m_WindowSize.cx=rc.right-rc.left; + m_WindowSize.cy=rc.bottom-rc.top; + for (std::vector::iterator it=m_Controls.begin();it!=m_Controls.end();++it) + { + it->hwnd=pThis->GetDlgItem(it->id); + Assert(it->hwnd); + if (!it->hwnd) continue; + ::GetWindowRect(it->hwnd,&it->rect0); + ::MapWindowPoints(NULL,m_hWnd,(POINT*)&it->rect0,2); + } + } + + void OnSize( void ) + { + T *pThis=static_cast(this); + RECT rc; + pThis->GetClientRect(&rc); + int dx=rc.right-m_ClientSize.cx; + int dy=rc.bottom-m_ClientSize.cy; + int dx2=dx/2; + int dy2=dy/2; + for (std::vector::iterator it=m_Controls.begin();it!=m_Controls.end();++it) + { + if (!it->hwnd) continue; + int x1=it->rect0.left; + int y1=it->rect0.top; + int x2=it->rect0.right; + int y2=it->rect0.bottom; + if (it->flags&MOVE_LEFT) x1+=dx; + else if (it->flags&MOVE_LEFT2) x1+=dx2; + if (it->flags&MOVE_TOP) y1+=dy; + else if (it->flags&MOVE_TOP2) y1+=dy2; + if (it->flags&MOVE_RIGHT) x2+=dx; + else if (it->flags&MOVE_RIGHT2) x2+=dx2; + if (it->flags&MOVE_BOTTOM) y2+=dy; + else if (it->flags&MOVE_BOTTOM2) y2+=dy2; + ::SetWindowPos(it->hwnd,NULL,x1,y1,x2-x1,y2-y1,SWP_NOZORDER|SWP_NOCOPYBITS); + } + if (m_Gripper.m_hWnd) + { + RECT rc2; + m_Gripper.GetWindowRect(&rc2); + int w=rc2.right-rc2.left; + int h=rc2.bottom-rc2.top; + m_Gripper.SetWindowPos(HWND_BOTTOM,rc.right-w,rc.bottom-h,w,h,0); + } + } + + LRESULT OnGetMinMaxInfo( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) + { + MINMAXINFO *pInfo=(MINMAXINFO*)lParam; + pInfo->ptMinTrackSize.x=m_WindowSize.cx; + pInfo->ptMinTrackSize.y=m_WindowSize.cy; + if (!(m_Flags&MOVE_HORIZONTAL)) + pInfo->ptMaxTrackSize.x=pInfo->ptMinTrackSize.x; + if (!(m_Flags&MOVE_VERTICAL)) + pInfo->ptMaxTrackSize.y=pInfo->ptMinTrackSize.y; + return 0; + } + + void GetStoreRect( RECT &rc ) + { + GetWindowRect(&rc); + rc.right-=rc.left+m_WindowSize.cx; + rc.bottom-=rc.top+m_WindowSize.cy; + } + + void GetPlacementRect( RECT &rc ) + { + WINDOWPLACEMENT placement; + GetWindowPlacement(&placement); + rc=placement.rcNormalPosition; + rc.right-=rc.left+m_WindowSize.cx; + rc.bottom-=rc.top+m_WindowSize.cy; + } + + void SetStoreRect( const RECT &rc ) + { + SetWindowPos(NULL,rc.left,rc.top,m_WindowSize.cx+rc.right,m_WindowSize.cy+rc.bottom,SWP_NOZORDER|SWP_NOCOPYBITS); + SendMessage(DM_REPOSITION); + } + +private: + SIZE m_ClientSize; + SIZE m_WindowSize; + int m_Flags; + CWindow m_Gripper; + std::vector m_Controls; +}; + +#define BEGIN_RESIZE_MAP const Control *GetResizeControls( void ) { static Control controls[]={ +#define RESIZE_CONTROL(id,flags) {id,flags}, +#define END_RESIZE_MAP {0,0}}; return controls; } + +/////////////////////////////////////////////////////////////////////////////// + +struct CStdCommand +{ + const wchar_t *name; // NULL for the terminator item, empty for custom item + int displayNameId; // always valid + int tipID; + const wchar_t *itemName; // NULL for separators + const wchar_t *label; + const wchar_t *tip; + const wchar_t *icon; // NULL for separators, "none" - force no icon, "" for default icon + const KNOWNFOLDERID *knownFolder; + unsigned int settings; + const wchar_t *iconD; + + bool IsSeparator( void ) const { return !itemName; } + bool IsCustom( void ) const { return !*name; } + bool IsStyle( int style, int mask ) const { return (settings&mask)==0 || (settings&style); } +}; + +struct CTreeItem +{ + CString name; + CString command; + CString link; + CString label; + CString tip; + CString icon; + CString iconD; + unsigned int settings; + const CStdCommand *pStdCommand; // always valid + + CTreeItem( void ) { settings=0; pStdCommand=NULL; } + void SetCommand( CString command, const CStdCommand *pStdCommands, int style, int mask ); + unsigned int GetIconKey( void ) const; + HICON LoadIcon( bool bSmall, std::vector &modules ) const; + unsigned int GetIconDKey( unsigned int iconKey ) const; + HICON LoadIconD( HICON hIcon, std::vector &modules ) const; // always large + CString GetDisplayName( bool bTitle ) const; +}; + +/////////////////////////////////////////////////////////////////////////////// + +const HICON HICON_NONE=(HICON)-1; + +class CCustomTreeDlg: public CResizeableDlg +{ +public: + CCustomTreeDlg( bool bMenu, const CStdCommand *pStdCommands, int style, int mask ); + ~CCustomTreeDlg( void ); + + BEGIN_MSG_MAP( CCustomTreeDlg ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + MESSAGE_HANDLER( WM_SIZE, OnSize ) + MESSAGE_HANDLER( WM_CONTEXTMENU, OnContextMenu ) + + NOTIFY_HANDLER( IDC_TREECOMMANDS, TVN_GETINFOTIP, OnGetInfoTip ) + NOTIFY_HANDLER( IDC_TREECOMMANDS, TVN_BEGINDRAG, OnBeginDrag ) + NOTIFY_HANDLER( IDC_TREECOMMANDS, NM_DBLCLK, OnAddItem ) + NOTIFY_HANDLER( IDC_TREECOMMANDS, TVN_KEYDOWN, OnAddItem ) + NOTIFY_HANDLER( IDC_TREEITEMS, TVN_GETINFOTIP, OnGetInfoTip ) + NOTIFY_HANDLER( IDC_TREEITEMS, NM_DBLCLK, OnEditItem ) + NOTIFY_HANDLER( IDC_TREEITEMS, TVN_KEYDOWN, OnEditItem ) + NOTIFY_HANDLER( IDC_TREEITEMS, NM_CUSTOMDRAW, OnCustomDraw ) + REFLECT_NOTIFICATIONS() + END_MSG_MAP() + + BEGIN_RESIZE_MAP + RESIZE_CONTROL(IDC_TREEITEMS,MOVE_LEFT_HALF|MOVE_SIZE_Y) + RESIZE_CONTROL(IDC_STATICMIDDLE,MOVE_CENTER|MOVE_VCENTER) + RESIZE_CONTROL(IDC_STATICRIGHT,MOVE_CENTER) + RESIZE_CONTROL(IDC_TREECOMMANDS,MOVE_RIGHT_HALF|MOVE_SIZE_Y) + RESIZE_CONTROL(IDC_STATICHINT,MOVE_SIZE_X|MOVE_MOVE_Y) + END_RESIZE_MAP + + void SetGroup( CSetting *pGroup, bool bReset ); + void SerializeData( void ); + +protected: + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnContextMenu( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnGetInfoTip( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnBeginDrag( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnAddItem( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnEditItem( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + + virtual void InitItems( void ) {} + virtual void ItemsChanged( void ) {} + virtual void ParseTreeItemExtra( CTreeItem *pItem, CSettingsParser &parser ) {} + virtual void SerializeItemExtra( CTreeItem *pItem, std::vector &stringBuilder ) {} + virtual bool EditItem( CTreeItem *pItem, HWND tree, HTREEITEM hItem, std::vector &modules ); + void AddItem( HTREEITEM hCommand ); + + HTREEITEM GetRoot( void ); + HTREEITEM GetChild( HTREEITEM hParent ); + HTREEITEM GetNext( HTREEITEM hItem ); + CTreeItem *GetItem( HTREEITEM hItem ); + + static void AppendString( std::vector &stringBuilder, const wchar_t *text ); + + int m_Style, m_StyleMask; + +private: + CSettingsTree &m_Tree; + CCommandsTree &m_CommandsTree; + const CStdCommand *m_pStdCommands; + CSetting *m_pSetting; + bool m_bMenu; + + const CStdCommand *FindStdCommand( const wchar_t *name ); + + void EditItemInternal( CTreeItem *pItem, HTREEITEM hItem ); + int ParseTreeItem( CTreeItem *pItem, CSettingsParser &parser ); + void SerializeItem( HTREEITEM hItem, std::vector &stringBuilder ); + void CreateTreeItems( CSettingsParser &parser, HTREEITEM hParent, const CSettingsParser::TreeItem *pItems, int index ); +}; + +class CEditCustomItemDlg: public CResizeableDlg +{ +public: + CEditCustomItemDlg( CTreeItem *pItem, std::vector &modules ): m_Modules(modules) { m_pItem=pItem; } + virtual ~CEditCustomItemDlg( void ); + void SetEnableParent( HWND parent ) { m_EnableParent=parent; } + bool GetResult( void ) { return m_bResult; } + + BEGIN_MSG_MAP( CEditCustomItemDlg ) + MESSAGE_HANDLER( WM_SIZE, OnSize ) + MESSAGE_HANDLER( WM_GETMINMAXINFO, OnGetMinMaxInfo ) + END_MSG_MAP() + + virtual BEGIN_RESIZE_MAP + END_RESIZE_MAP + + bool Run( HWND parent, int dlgID ); + +protected: + CTreeItem *m_pItem; + + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnBrowse( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + + void InitDialog( CWindow commandCombo, const CStdCommand *pStdcommands, int style, int mask, CWindow linkCombo, const KNOWNFOLDERID *const *pCommonLinks ); + void UpdateIcons( int iconID, int iconDID ); + CString GetComboText( WORD wNotifyCode, WORD wID ); + +private: + std::vector &m_Modules; + HWND m_EnableParent; + bool m_bResult; + HICON m_hIcon; + unsigned int m_IconKey; + HICON m_hIconD; + unsigned int m_IconDKey; + CTreeItem m_StoredItem; + + void StorePlacement( void ); +}; + +/////////////////////////////////////////////////////////////////////////////// + +ISettingsPanel *GetDefaultSettings( const CString *filter, const CSetting *pSelect ); +HIMAGELIST GetSettingsImageList( HWND tree ); +bool BrowseForIcon( HWND hWndParent, wchar_t *path, int &id ); +bool BrowseForBitmap( HWND hWndParent, wchar_t *path, bool bAllowJpeg ); +bool BrowseForSound( HWND hWndParent, wchar_t *path ); +const wchar_t *GetSettingsRegPath( void ); + +// Special GUID for the real desktop +extern const GUID FOLDERID_DesktopRoot; + +bool BrowseCommandHelper( HWND parent, wchar_t *text ); +bool BrowseLinkHelper( HWND parent, wchar_t *text ); +bool BrowseIconHelper( HWND parent, wchar_t *text ); diff --git a/ClassicShellSrc/ClassicShellLib/StringSet.cpp b/ClassicShellSrc/ClassicShellLib/StringSet.cpp new file mode 100644 index 0000000..7934a33 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/StringSet.cpp @@ -0,0 +1,74 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include +#include "StringSet.h" + +static CString CreateString( const WORD *data ) +{ + int len=*data; + data++; + if (len==0) return NULL; + + CString str; + wchar_t *ptr=str.GetBuffer(len); + if (ptr) + { + memcpy(ptr,data,len*2); + ptr[len]=0; + str.ReleaseBufferSetLength(len); + } + + return str; +} + +BOOL CALLBACK CStringSet::EnumResNameProc( HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam ) +{ + CStringSet *set=(CStringSet*)lParam; + // find resource + HRSRC hr=FindResource(hModule,lpszName,RT_STRING); + if (!hr) return TRUE; + + HGLOBAL hg=LoadResource(hModule,hr); + if (hg) + { + const WORD *res=(WORD*)LockResource(hg); + if (res) + { + for (int i=0;i<16;i++) + { + UINT id=(((int)lpszName)<<4)+i-16; + + CString str=CreateString(res); + if (!str.IsEmpty()) + (*set)[id]=str; + res+=(*res)+1; + } + UnlockResource(hg); + } + } + return TRUE; +} + +// Initializes the string database +void CStringSet::Init( HINSTANCE hInstance ) +{ + clear(); + m_hInstance=hInstance; + if (hInstance) + EnumResourceNames(hInstance,RT_STRING,EnumResNameProc,(LONG_PTR)this); +} + +// Returns a string by ID (returns "" if the string is missing) +CString CStringSet::GetString( UINT uID ) +{ + // search in the database + const_iterator it=find(uID); + + if (it!=end()) + { + if (it->second) + return it->second; + } + return CString(); +} diff --git a/ClassicShellSrc/ClassicShellLib/StringSet.h b/ClassicShellSrc/ClassicShellLib/StringSet.h new file mode 100644 index 0000000..010f205 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/StringSet.h @@ -0,0 +1,22 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#include + +class CStringSet: public std::map +{ +public: + CStringSet( void ) { m_hInstance=NULL; } + // Initializes the string database + void Init( HINSTANCE hInstance ); + + // Returns a string by ID (returns "" if the string is missing) + CString GetString( UINT uID ); + +private: + HINSTANCE m_hInstance; + + static BOOL CALLBACK CStringSet::EnumResNameProc( HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam ); +}; diff --git a/ClassicShellSrc/ClassicShellLib/StringUtils.cpp b/ClassicShellSrc/ClassicShellLib/StringUtils.cpp new file mode 100644 index 0000000..8034f16 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/StringUtils.cpp @@ -0,0 +1,483 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// StringUtils is also available under the CPOL license as part of the FormatString article +// on CodeProject: http://www.codeproject.com/KB/string/FormatString.aspx + +#include +#include "StringUtils.h" +#include +#include + +#ifndef STR_USE_WIN32_CONV +#include +#endif + +/////////////////////////////////////////////////////////////////////////////// + +#ifdef STR_USE_WIN32_DBCS +static int g_MaxCharSize=0; +#endif + +// Returns 1 if the ANSI code page is single-byte, or 2 if it is double-byte (DBCS) +int GetMaxCharSize( void ) +{ +#ifdef STR_USE_WIN32_DBCS + if (!g_MaxCharSize) + { + CPINFO info; + if (GetCPInfo(CP_ACP,&info)) + g_MaxCharSize=info.MaxCharSize; + } + return g_MaxCharSize; +#else + return MB_CUR_MAX; +#endif +} + +// Copies src to dst. size is the size of dst in bytes, including the terminating 0. +// Returns the number of characters copied, excluding the terminating 0. +// The return value is <=size-1. If size is 0, returns 0 and does nothing. +// The result in dst is always 0 terminated. +int Strcpy( char *dst, int size, const char *src ) +{ + assert(dst); + assert(src); + assert(size>0); + if (size<=0) return 0; + char *dst0=dst; + if (GetMaxCharSize()==1) + { + // SBCS version + while (size>1) + { + if (*src==0) break; + *dst++=*src++; + size--; + } + } + else + { + // DBCS version + while (size>1) + { + if (*src==0) break; +#ifdef STR_USE_WIN32_DBCS + if (IsDBCSLeadByte((BYTE)*src)) + { +#else + if (isleadbyte((unsigned char)*src)) + { +#endif + if (size==2) break; + if (src[1]==0) break; + *dst++=*src++; + *dst++=*src++; + size-=2; + } + else + { + *dst++=*src++; + size--; + } + } + } + *dst=0; + return (int)(dst-dst0); +} + +int Strcpy( wchar_t *dst, int size, const wchar_t *src ) +{ + assert(dst); + assert(src); + assert(size>0); + if (size<=0) return 0; + int len=Strlen(src); + if (len>size-1) + len=size-1; + if (len>0 && src[len]>=0xDC00 && src[len]<=0xDFFF) // check for trailing surrogate + len--; + memcpy(dst,src,len*sizeof(wchar_t)); + dst[len]=0; + return len; +} + +// Copies src to dst. size is the size of dst in characters, including the terminating 0. +// Copies up to len characters and always appends terminating 0. +int Strncpy( char *dst, int size, const char *src, int len ) +{ + assert(dst); + assert(src); + assert(size>0); + if (size<=0) return 0; + char *dst0=dst; + const char *end=src+len; + if (GetMaxCharSize()==1) + { + // SBCS version + while (size>1) + { + if (src==end) break; + *dst++=*src++; + size--; + } + } + else + { + // DBCS version + while (size>1) + { + if (src==end) break; +#ifdef STR_USE_WIN32_DBCS + if (IsDBCSLeadByte((BYTE)*src)) + { +#else + if (isleadbyte((unsigned char)*src)) + { +#endif + if (size==2) break; + if (src+1==end) break; + *dst++=*src++; + *dst++=*src++; + size-=2; + } + else + { + *dst++=*src++; + size--; + } + } + } + *dst=0; + return (int)(dst-dst0); +} + +int Strncpy( wchar_t *dst, int size, const wchar_t *src, int len ) +{ + assert(dst); + assert(src); + assert(size>0); + if (size<=0) return 0; + if (len>size-1) + len=size-1; + if (len>0 && src[len]>=0xDC00 && src[len]<=0xDFFF) // check for trailing surrogate + len--; + memcpy(dst,src,len*sizeof(wchar_t)); + dst[len]=0; + return len; +} + +// Appends src to dst. size is the size of dst in bytes, including the terminating 0. +// Returns the number of characters copied, excluding the terminating 0. +// The return value is <=size-1-strlen(dst). If size>=strlen(dst), returns 0 and does nothing. +// The result in dst is always 0 terminated. +int Strcat( char *dst, int size, const char *src ) +{ + assert(dst); + int len=Strlen(dst); + assert(len0); + if (size<=0) return 0; +#if _MSC_VER>=1400 // VC8.0 + int len=_vsnprintf_s(dst,size,size-1,format,args); +#else + int len=_vsnprintf(dst,size-1,format,args); +#endif + if (len<0) + len=size-1; + dst[len]=0; + return len; +} + +int Vsprintf( wchar_t *dst, int size, const wchar_t *format, va_list args ) +{ + assert(dst); + assert(format); + assert(size>0); + if (size<=0) return 0; +#if _MSC_VER>=1400 // VC8.0 + int len=_vsnwprintf_s(dst,size,size-1,format,args); +#else + int len=_vsnwprintf(dst,size-1,format,args); +#endif + if (len<0) + len=size-1; + dst[len]=0; + return len; +} + +// Outputs a formatted debug string +void Trace( const char *format, ... ) +{ + va_list args; + va_start(args,format); + char buf[1024]; + Vsprintf(buf,_countof(buf)-2,format,args); + Strcat(buf,_countof(buf),"\r\n"); + OutputDebugStringA(buf); + va_end(args); +} + +void Trace( const wchar_t *format, ... ) +{ + va_list args; + va_start(args,format); + wchar_t buf[1024]; + Vsprintf(buf,_countof(buf)-2,format,args); + Strcat(buf,_countof(buf),L"\r\n"); + OutputDebugStringW(buf); + va_end(args); +} + +// Convert between multi-byte and wide characters. size is the size of dst in characters, including the +// terminating 0. +// Return the number of characters copied, excluding the terminating 0. +// The return value is <=size-1. If size is 0, returns 0 and does nothing. +// The result in dst is always 0 terminated. + +#ifdef STR_USE_WIN32_CONV +int MbsToWcs( wchar_t *dst, int size, const char *src, int codePage ) +{ + if (!dst) + return MultiByteToWideChar(codePage,0,src,Strlen(src),NULL,0); + + assert(size); + if (size==0) return 0; + if (size==1) + { + dst[0]=0; + return 0; + } + int len=Strlen(src); + dst[size-2]=0; + int res=MultiByteToWideChar(codePage,0,src,len,dst,size-1); + if (res) + { + // the result fits + dst[res]=0; + return res; + } + if (GetLastError()!=ERROR_INSUFFICIENT_BUFFER) + { // some unknown error + dst[0]=0; + return 0; + } + + if (!dst[size-2]) // could not fit a surrogate pair + return size-2; + dst[size-1]=0; + return size-1; +} + +int WcsToMbs( char *dst, int size, const wchar_t *src, int codePage ) +{ + if (!dst) + return WideCharToMultiByte(codePage,0,src,Strlen(src),NULL,0,NULL,NULL); + + assert(size); + if (size==0) return 0; + if (size==1) + { + dst[0]=0; + return 0; + } + int len=Strlen(src); + int l=size; + if (l>10) l=10; + memset(dst+size-l,0,l); // fill the end with zeros (up to 10 bytes) + int res=WideCharToMultiByte(codePage,0,src,len,dst,size-1,NULL,NULL); + if (res) + { + // the result fits + dst[res]=0; + return res; + } + if (GetLastError()!=ERROR_INSUFFICIENT_BUFFER) // some unknown error + { + dst[0]=0; + return 0; + } + + // find the last non-zero to return the correct length + for (len=size-1;len>0;len--) + if (dst[len-1]) + return len; + return 0; +} +#else +int MbsToWcs( wchar_t *dst, int size, const char *src ) +{ + if (!dst) + { +#if _MSC_VER>=1400 // VC8.0 + size_t res; + if (mbstowcs_s(&res,NULL,0,src,0)!=0) + return 0; + return (int)res-1; +#else + int res=(int)mbstowcs(NULL,src,0); + if (res<0) return 0; + return res; +#endif + } + + assert(size); + if (size==0) return 0; + if (size==1) + { + dst[0]=0; + return 0; + } +#if _MSC_VER>=1400 // VC8.0 + size_t res; + mbstowcs_s(&res,dst,size,src,_TRUNCATE); + return (int)res-1; +#else + int res=(int)mbstowcs(dst,src,size-1); + if (res<0) + { + dst[0]=0; + return 0; + } + if (res==size-1) + dst[res]=0; + return res; +#endif +} + +int WcsToMbs( char *dst, int size, const wchar_t *src ) +{ + if (!dst) + { +#if _MSC_VER>=1400 // VC8.0 + size_t res; + if (wcstombs_s(&res,NULL,0,src,0)!=0) + return 0; + return (int)res-1; +#else + int res=(int)wcstombs(NULL,src,0); + if (res<0) return 0; + return res; +#endif + } + + assert(size); + if (size==0) return 0; + if (size==1) + { + dst[0]=0; + return 0; + } + +#if _MSC_VER>=1400 // VC8.0 + size_t res; + if (wcstombs_s(&res,dst,size,src,_TRUNCATE)!=0) + { + dst[0]=0; + return 0; + } + return (int)res-1; +#else + int res=(int)wcstombs(dst,src,size-1); + if (res<0) + { + dst[0]=0; + return 0; + } + if (res==size-1) + dst[res]=0; + return res; +#endif +} +#endif + +/////////////////////////////////////////////////////////////////////////////// + +const char *GetToken( const char *text, char *token, int size, const char *separators ) +{ + while (*text && strchr(separators,*text)) + text++; + const char *c1=text,*c2; + if (text[0]=='\"') + { + c1++; + c2=strchr(c1,'\"'); + } + else + { + c2=c1; + while (*c2!=0 && !strchr(separators,*c2)) + c2++; + } + if (!c2) c2=text+strlen(text); + int l=(int)(c2-c1); + if (l>size-1) l=size-1; + memcpy(token,c1,l); + token[l]=0; + + if (*c2) return c2+1; + else return c2; +} + +const wchar_t *GetToken( const wchar_t *text, wchar_t *token, int size, const wchar_t *separators ) +{ + while (*text && wcschr(separators,*text)) + text++; + const wchar_t *c1=text,*c2; + if (text[0]=='\"') + { + c1++; + c2=wcschr(c1,'\"'); + } + else + { + c2=c1; + while (*c2!=0 && !wcschr(separators,*c2)) + c2++; + } + if (!c2) c2=text+wcslen(text); + int l=(int)(c2-c1); + if (l>size-1) l=size-1; + memcpy(token,c1,l*2); + token[l]=0; + + if (*c2) return c2+1; + else return c2; +} diff --git a/ClassicShellSrc/ClassicShellLib/StringUtils.h b/ClassicShellSrc/ClassicShellLib/StringUtils.h new file mode 100644 index 0000000..9d443a6 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/StringUtils.h @@ -0,0 +1,112 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// StringUtils is also available under the CPOL license as part of the FormatString article +// on CodeProject: http://www.codeproject.com/KB/string/FormatString.aspx + +#ifndef _STRINGUTILS_H +#define _STRINGUTILS_H + +// StringUtils provides secure implementations of common string functions. +// All strings are guaranteed to be zero-terminated and to not contain partial +// double-byte characters or partial surrogate pairs. +// It also provides char and wchar_t overrides of the same functions. +// +/////////////////////////////////////////////////////////////////////////////// + +// Configuration of the string functions + +// If defined, enables the use of WideCharToMultiByte and MultiByteToWideChar +// If not defined, wcstombs and mbstowcs are used instead. they always use the default code page +// and don't support surrogate pairs +#define STR_USE_WIN32_CONV + +// If defined, enables the use of Windows localization functions - GetNumberFormat, GetTimeFormat, etc +// If not defined, then the numbers, currency, time and date use fixed formats +#define STR_USE_WIN32_NLS + +// If defined, enables support for SYSTEMTIME, FILETIME and DATE +// If not defined, only time_t is supported as a time format +#define STR_USE_WIN32_TIME + +// If defined, enables the use of IsDBCSLeadByte to support DBCS code pages +// If not defined, isleadbyte is used instead +#define STR_USE_WIN32_DBCS + +// enables support for STL strings and streams +//#define STR_USE_STL + +#include +#include + +#if defined(_WIN32) || defined(_WIN64) +#include +#endif + +#ifdef STR_USE_STL +#include +#endif + +// _countof: compute the number of elements in a statically-allocated array +// VS2005 supports this, but earlier versions do not +#ifndef _countof +#define _countof(x) (sizeof(x)/sizeof((x)[0])) +#endif + +// Returns 1 if the ANSI code page is single-byte, or 2 if it is double-byte (DBCS) +int GetMaxCharSize( void ); + +// Returns the length of a string +inline int Strlen( const char *str ) { return (int)strlen(str); } +inline int Strlen( const wchar_t *str ) { return (int)wcslen(str); } + +// Copies src to dst. size is the size of dst in characters, including the terminating 0. +// Returns the number of characters copied, excluding the terminating 0. +// The return value is <=size-1. If size is 0, returns 0 and does nothing. +// The result in dst is always 0 terminated. +int Strcpy( char *dst, int size, const char *src ); +int Strcpy( wchar_t *dst, int size, const wchar_t *src ); + +// Copies src to dst. size is the size of dst in characters, including the terminating 0. +// Copies up to len characters and always appends terminating 0. +int Strncpy( char *dst, int size, const char *src, int len ); +int Strncpy( wchar_t *dst, int size, const wchar_t *src, int len ); + +// Appends src to dst. size is the size of dst in bytes, including the terminating 0. +// Returns the number of characters copied, excluding the terminating 0. +// The return value is <=size-1-strlen(dst). If size>=strlen(dst), returns 0 and does nothing. +// The result in dst is always 0 terminated. +int Strcat( char *dst, int size, const char *src ); +int Strcat( wchar_t *dst, int size, const wchar_t *src ); + +// Writes formatted string to dst. size is the size of dst in characters, including the terminating 0. +// Returns the number of characters written, excluding the terminating 0. +// The return value is <=size-1. If size is 0, returns 0 and does nothing. +// The result in dst is always 0 terminated. +int _cdecl Sprintf( char *dst, int size, const char *format, ... ); +int _cdecl Sprintf( wchar_t *dst, int size, const wchar_t *format, ... ); +int _cdecl Vsprintf( char *dst, int size, const char *format, va_list args ); +int _cdecl Vsprintf( wchar_t *dst, int size, const wchar_t *format, va_list args ); + +// Outputs a formatted debug string +void Trace( const char *format, ... ); +void Trace( const wchar_t *format, ... ); + +// Converts between multi-byte and wide characters. size is the size of dst in characters, including the +// terminating 0. +// Returns the number of characters copied, excluding the terminating 0. +// The return value is <=size-1. If size is 0, returns 0 and does nothing. +// The result in dst is always 0 terminated. +// If dst is NULL the size is ignored and the function just returns the number of characters (not counting the 0) +#ifdef STR_USE_WIN32_CONV +int MbsToWcs( wchar_t *dst, int size, const char *src, int codePage=CP_ACP ); +int WcsToMbs( char *dst, int size, const wchar_t *src, int codePage=CP_ACP ); +#else +int MbsToWcs( wchar_t *dst, int size, const char *src ); +int WcsToMbs( char *dst, int size, const wchar_t *src ); +#endif + +const char *GetToken( const char *text, char *token, int size, const char *separators ); +const wchar_t *GetToken( const wchar_t *text, wchar_t *token, int size, const wchar_t *separators ); + +#endif diff --git a/ClassicShellSrc/ClassicShellLib/TrackResources.cpp b/ClassicShellSrc/ClassicShellLib/TrackResources.cpp new file mode 100644 index 0000000..1a539d5 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/TrackResources.cpp @@ -0,0 +1,227 @@ +#include +#include +#include +#include "StringUtils.h" +#include "ResourceHelper.h" +#include "Assert.h" + +typedef std::pair TrackedResource; +typedef std::map TrackedResourceMap; + +static TrackedResourceMap g_TrackedGdiResources; +static TrackedResourceMap g_TrackedUserResources; + +HDC TrackCreateCompatibleDC( HDC hdc, const char *file, int line ) +{ + HDC res=CreateCompatibleDC(hdc); + if (res) + g_TrackedGdiResources[res]=TrackedResource(file,line); + return res; +} + +HFONT TrackCreateFont( int cHeight, int cWidth, int cEscapement, int cOrientation, int cWeight, DWORD bItalic, DWORD bUnderline, DWORD bStrikeOut, DWORD iCharSet, DWORD iOutPrecision, DWORD iClipPrecision, DWORD iQuality, DWORD iPitchAndFamily, LPCWSTR pszFaceName, const char *file, int line ) +{ + HFONT res=CreateFont(cHeight,cWidth,cEscapement,cOrientation,cWeight,bItalic,bUnderline,bStrikeOut,iCharSet,iOutPrecision,iClipPrecision,iQuality,iPitchAndFamily,pszFaceName); + if (res) + g_TrackedGdiResources[res]=TrackedResource(file,line); + return res; +} + +HFONT TrackCreateFontIndirect( const LOGFONT *lplf, const char *file, int line ) +{ + HFONT res=CreateFontIndirect(lplf); + if (res) + g_TrackedGdiResources[res]=TrackedResource(file,line); + return res; +} + +HANDLE TrackLoadImage( HINSTANCE hInst, LPCWSTR name, UINT type, int cx, int cy, UINT fuLoad, const char *file, int line ) +{ + HANDLE res=LoadImage(hInst,name,type,cx,cy,fuLoad); + if (type==IMAGE_BITMAP) + g_TrackedGdiResources[res]=TrackedResource(file,line); + else + g_TrackedUserResources[res]=TrackedResource(file,line); + return res; +} + +HBITMAP TrackCreateDIBSection( HDC hdc, CONST BITMAPINFO *lpbmi, UINT usage, VOID **ppvBits, HANDLE hSection, DWORD offset, const char *file, int line ) +{ + HBITMAP res=CreateDIBSection(hdc,lpbmi,usage,ppvBits,hSection,offset); + if (res) + g_TrackedGdiResources[res]=TrackedResource(file,line); + return res; +} + +HBITMAP TrackCreateBitmap( int nWidth, int nHeight, UINT nPlanes, UINT nBitCount, CONST VOID *lpBits, const char *file, int line ) +{ + HBITMAP res=CreateBitmap(nWidth,nHeight,nPlanes,nBitCount,lpBits); + if (res) + g_TrackedGdiResources[res]=TrackedResource(file,line); + return res; +} + +HBITMAP TrackCreateCompatibleBitmap( HDC hdc, int cx, int cy, const char *file, int line ) +{ + HBITMAP res=CreateCompatibleBitmap(hdc,cx,cy); + if (res) + g_TrackedGdiResources[res]=TrackedResource(file,line); + return res; +} + +void TrackAddTrackedObject( HGDIOBJ obj, const char *file, int line ) +{ + if (obj) + g_TrackedGdiResources[obj]=TrackedResource(file,line); +} + +void TrackAddTrackedIcon( HICON hIcon, const char *file, int line ) +{ + if (hIcon) + g_TrackedUserResources[hIcon]=TrackedResource(file,line); +} + + + +BOOL TrackDeleteDC( HDC hdc ) +{ + Assert(hdc); + if (g_TrackedGdiResources.find(hdc)!=g_TrackedGdiResources.end()) + g_TrackedGdiResources.erase(hdc); + else + Assert(0); + return DeleteDC(hdc); +} + +BOOL TrackDeleteObject( HGDIOBJ obj ) +{ + Assert(obj); + if (g_TrackedGdiResources.find(obj)!=g_TrackedGdiResources.end()) + g_TrackedGdiResources.erase(obj); + else + Assert(0); + return DeleteObject(obj); +} + +BOOL TrackDestroyIcon( HICON hIcon ) +{ + Assert(hIcon); + if (g_TrackedUserResources.find(hIcon)!=g_TrackedUserResources.end()) + g_TrackedUserResources.erase(hIcon); + else + Assert(0); + return DestroyIcon(hIcon); +} + + +static void DumpBitmapLeaks( const std::vector &bitmaps ) +{ + int index=0; + for (std::vector::const_iterator it=bitmaps.begin();it!=bitmaps.end();++it) + { + BITMAP info; + GetObject(*it,sizeof(info),&info); + // ... + } +} + + +struct GdiTableCell +{ + void *pKernel; + unsigned short nProcess; + unsigned short nCount; + unsigned short nUpper; + unsigned short nType; + void *pUser; +}; + +static const GdiTableCell *GetGdiTable( void ) +{ + HMODULE gdi32=GetModuleHandle(L"gdi32.dll"); + FARPROC GdiQueryTable=GetProcAddress(gdi32,"GdiQueryTable"); + if (GdiQueryTable) + { + // GdiQueryTable(); + if (GetWinVersion()>=WIN_VER_WIN8) + return *(GdiTableCell**)((char*)GdiQueryTable+0x6b1b0); + else + return *(GdiTableCell**)((char*)GdiQueryTable+0x29db0); + } + return NULL; +} + +void DumpResourceLeaks( void ) +{ + GdiFlush(); + Trace("GDI objects %d",GetGuiResources(GetCurrentProcess(),GR_GDIOBJECTS)); + Trace("USER objects %d",GetGuiResources(GetCurrentProcess(),GR_USEROBJECTS)); + const GdiTableCell *cells=GetGdiTable(); + if (!cells) return; + + int counts[16]={0}; + unsigned short pid=(unsigned short)GetCurrentProcessId(); + int n=65536; + std::vector bitmaps; + for (int i=0;isecond; + DWORD type=GetObjectType(handle); + if (!(type&~15)) + counts[type]++; + switch (type) + { + case OBJ_BITMAP: + { + BITMAP info; + GetObject(handle,sizeof(info),&info); + bitmaps.push_back((HBITMAP)handle); + } + break; + case OBJ_BRUSH: + { + LOGBRUSH info; + GetObject(handle,sizeof(info),&info); + int q=0; + } + break; + case OBJ_DC: + { + int q=0; + } + break; + case OBJ_FONT: + { + LOGFONT info; + GetObject(handle,sizeof(info),&info); + int q=0; + } + break; + case OBJ_PEN: + { + LOGPEN info; + GetObject(handle,sizeof(info),&info); + int q=0; + } + break; + case OBJ_REGION: + { + int q=0; + } + break; + case OBJ_MEMDC: + { + int q=0; + } + break; + } + } + } + DumpBitmapLeaks(bitmaps); +} diff --git a/ClassicShellSrc/ClassicShellLib/TrackResources.h b/ClassicShellSrc/ClassicShellLib/TrackResources.h new file mode 100644 index 0000000..a520285 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/TrackResources.h @@ -0,0 +1,50 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +//#define TRACK_GDI_RESOURCES +#ifndef _DEBUG +#undef TRACK_GDI_RESOURCES +#endif + +#ifdef TRACK_GDI_RESOURCES + +#undef CreateFont +#undef CreateFontIndirect +#undef LoadImage + +#define CreateCompatibleDC(hdc) TrackCreateCompatibleDC(hdc,__FILE__,__LINE__) +#define CreateFont(cHeight,cWidth,cEscapement,cOrientation,cWeight,bItalic,bUnderline,bStrikeOut,iCharSet,iOutPrecision,iClipPrecision,iQuality,iPitchAndFamily,pszFaceName) TrackCreateFont(cHeight,cWidth,cEscapement,cOrientation,cWeight,bItalic,bUnderline,bStrikeOut,iCharSet,iOutPrecision,iClipPrecision,iQuality,iPitchAndFamily,pszFaceName,__FILE__,__LINE__) +#define CreateFontIndirect(lplf) TrackCreateFontIndirect(lplf,__FILE__,__LINE__) +#define LoadImage(hInst,name,type,cx,cy,fuLoad) TrackLoadImage(hInst,name,type,cx,cy,fuLoad,__FILE__,__LINE__) +#define CreateDIBSection(hdc,lpbmi,usage,ppvBits,hSection,offset) TrackCreateDIBSection(hdc,lpbmi,usage,ppvBits,hSection,offset,__FILE__,__LINE__) +#define CreateBitmap(nWidth,nHeight,nPlanes,nBitCount,lpBits) TrackCreateBitmap(nWidth,nHeight,nPlanes,nBitCount,lpBits,__FILE__,__LINE__) +#define CreateCompatibleBitmap(hdc,cx,cy) TrackCreateCompatibleBitmap(hdc,cx,cy,__FILE__,__LINE__) +#define AddTrackedObject(obj) TrackAddTrackedObject(obj,__FILE__,__LINE__) +#define AddTrackedIcon(hIcon) TrackAddTrackedIcon(hIcon,__FILE__,__LINE__) + +#define DeleteDC(hdc) TrackDeleteDC(hdc) +#define DeleteObject(obj) TrackDeleteObject(obj) +#define DestroyIcon(hIcon) TrackDestroyIcon(hIcon) + +HDC TrackCreateCompatibleDC( HDC hdc, const char *file, int line ); +HFONT TrackCreateFont( int cHeight, int cWidth, int cEscapement, int cOrientation, int cWeight, DWORD bItalic, DWORD bUnderline, DWORD bStrikeOut, DWORD iCharSet, DWORD iOutPrecision, DWORD iClipPrecision, DWORD iQuality, DWORD iPitchAndFamily, LPCWSTR pszFaceName, const char *file, int line ); +HFONT TrackCreateFontIndirect( const LOGFONT *lplf, const char *file, int line ); +HANDLE TrackLoadImage( HINSTANCE hInst, LPCWSTR name, UINT type, int cx, int cy, UINT fuLoad, const char *file, int line ); +HBITMAP TrackCreateDIBSection( HDC hdc, CONST BITMAPINFO *lpbmi, UINT usage, VOID **ppvBits, HANDLE hSection, DWORD offset, const char *file, int line ); +HBITMAP TrackCreateBitmap( int nWidth, int nHeight, UINT nPlanes, UINT nBitCount, CONST VOID *lpBits, const char *file, int line ); +HBITMAP TrackCreateCompatibleBitmap( HDC hdc, int cx, int cy, const char *file, int line ); +void TrackAddTrackedObject( HGDIOBJ obj, const char *file, int line ); +void TrackAddTrackedIcon( HICON hIcon, const char *file, int line ); + +BOOL TrackDeleteDC( HDC hdc ); +BOOL TrackDeleteObject( HGDIOBJ obj ); +BOOL TrackDestroyIcon( HICON hIcon ); + +void DumpResourceLeaks( void ); + +#else +#define AddTrackedObject(obj) +#define AddTrackedIcon(hIcon) +#endif diff --git a/ClassicShellSrc/ClassicShellLib/Translations.cpp b/ClassicShellSrc/ClassicShellLib/Translations.cpp new file mode 100644 index 0000000..2de8f0b --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/Translations.cpp @@ -0,0 +1,82 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include +#include "SettingsParser.h" + +static CSettingsParser g_Translations; +static CSettingsParser g_TranslationOverrides; +static bool g_bRTL; + +// Parses the settings from an ini file. Supports UTF16, UTF8 or ANSI files +// Use forceLang for force a specific language +void ParseTranslations( const wchar_t *fname, const wchar_t *forceLang ) +{ + g_Translations.Reset(); + + if (fname) + { + if (!g_Translations.LoadText(fname)) return; + g_Translations.ParseText(); + } + + wchar_t languages[100]={0}; + if (forceLang && *forceLang) + { + int len=(int)wcslen(forceLang); + if (len>50) len=50; + memcpy(languages,forceLang,len*2); + memcpy(languages+len+1,L"default\0en-US\0",30); + } + else + { + ULONG size=0; + ULONG len=_countof(languages); + GetUserPreferredUILanguages(MUI_LANGUAGE_NAME,&size,languages,&len); + if (len>50) len=50; + if (len<1) len=1; + memcpy(languages+len-1,L"default\0en-US\0",30); + } + + g_Translations.FilterLanguages(languages); + + // Checks for right-to-left languages + g_bRTL=false; + LOCALESIGNATURE localesig; + LANGID language=GetUserDefaultUILanguage(); + if (forceLang && *forceLang) + { + if (GetLocaleInfoEx(forceLang,LOCALE_FONTSIGNATURE,(LPWSTR)&localesig,(sizeof(localesig)/sizeof(wchar_t))) && (localesig.lsUsb[3]&0x08000000)) + g_bRTL=true; + } + else + { + if (GetLocaleInfoW(language,LOCALE_FONTSIGNATURE,(LPWSTR)&localesig,(sizeof(localesig)/sizeof(wchar_t))) && (localesig.lsUsb[3]&0x08000000)) + g_bRTL=true; + } +} + +// Loads text overrides from the given module. They must be in a "L10N" resource with ID=1 +void LoadTranslationOverrides( HMODULE hModule ) +{ + HRSRC hResInfo=FindResource(hModule,MAKEINTRESOURCE(1),L"L10N"); + if (hResInfo) + { + g_TranslationOverrides.LoadText(hModule,hResInfo); + g_TranslationOverrides.ParseText(); + } +} + +// Returns a setting with the given name. If no setting is found, returns def +const wchar_t *FindTranslation( const wchar_t *name, const wchar_t *def ) +{ + const wchar_t *str=g_TranslationOverrides.FindSetting(name); + if (str) return str; + return g_Translations.FindSetting(name,def); +} + +// Checks for right-to-left languages +bool IsLanguageRTL( void ) +{ + return g_bRTL; +} diff --git a/ClassicShellSrc/ClassicShellLib/Translations.h b/ClassicShellSrc/ClassicShellLib/Translations.h new file mode 100644 index 0000000..9763c41 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/Translations.h @@ -0,0 +1,20 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +// Parses the settings from an ini file. Supports UTF16, UTF8 or ANSI files +// Use forceLang for force a specific language +void ParseTranslations( const wchar_t *fname, const wchar_t *forceLang ); + +// Loads text overrides from the given module. They must be in a "L10N" resource with ID=1 +void LoadTranslationOverrides( HMODULE hModule ); + +// Returns a setting with the given name. If no setting is found, returns def +const wchar_t *FindTranslation( const wchar_t *name, const wchar_t *def ); + +// Checks for right-to-left languages +bool IsLanguageRTL( void ); + +// Language DLLs between this version and the current version are acceptable +const int MIN_LANGUAGE_VERSION=0x03090005; diff --git a/ClassicShellSrc/ClassicShellLib/flags.bmp b/ClassicShellSrc/ClassicShellLib/flags.bmp new file mode 100644 index 0000000..a761ed3 Binary files /dev/null and b/ClassicShellSrc/ClassicShellLib/flags.bmp differ diff --git a/ClassicShellSrc/ClassicShellLib/flags24.bmp b/ClassicShellSrc/ClassicShellLib/flags24.bmp new file mode 100644 index 0000000..f53c58f Binary files /dev/null and b/ClassicShellSrc/ClassicShellLib/flags24.bmp differ diff --git a/ClassicShellSrc/ClassicShellLib/padlock.ico b/ClassicShellSrc/ClassicShellLib/padlock.ico new file mode 100644 index 0000000..8b011f5 Binary files /dev/null and b/ClassicShellSrc/ClassicShellLib/padlock.ico differ diff --git a/ClassicShellSrc/ClassicShellLib/play.ico b/ClassicShellSrc/ClassicShellLib/play.ico new file mode 100644 index 0000000..62a98a3 Binary files /dev/null and b/ClassicShellSrc/ClassicShellLib/play.ico differ diff --git a/ClassicShellSrc/ClassicShellLib/resource.h b/ClassicShellSrc/ClassicShellLib/resource.h new file mode 100644 index 0000000..4274bc0 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/resource.h @@ -0,0 +1,152 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ClassicShellLib.rc +// +#define IDS_VERSION_URL 100 +#define IDB_FLAGS 109 +#define IDB_FLAGS24 108 +#define IDC_STATICICON 209 +#define IDC_SETTINGS 236 +#define IDC_TREEITEMS 238 +#define IDC_COMBOCOMMAND 239 +#define IDC_EDITLABEL 240 +#define IDC_EDITTIP 241 +#define IDC_BUTTONLINK 242 +#define IDC_EDITLINK 244 +#define IDC_EDITICON 245 +#define IDC_BUTTONICON 246 +#define IDC_EDITICOND 247 +#define IDC_BUTTONICOND 248 +#define IDC_TABSETTINGS 250 +#define IDC_STATICCOMMAND 251 +#define IDC_STATICLINK 252 +#define IDC_STATICTEXT 253 +#define IDC_STATICINFOTIP 254 +#define IDC_STATICICOND 255 +#define IDC_ICONN 256 +#define IDC_ICOND 257 +#define IDC_COMBOLINK 258 +#define IDC_STATICHINT 259 +#define IDI_ICONLOCK 1000 +#define IDI_ICONWARNING 1001 +#define IDC_EDITFILE 1001 +#define IDI_ICONPLAY 1002 +#define IDC_BUTTONBROWSE 1002 +#define IDC_LISTICONS 1003 +#define IDC_LISTLANGUAGE 1004 +#define IDC_STATICTIP 1005 +#define IDC_TREE1 1006 +#define IDC_TREECOMMANDS 1006 +#define IDC_STATICLEFT 1007 +#define IDC_STATICRIGHT 1008 +#define IDC_STATICMIDDLE 1009 +#define IDC_LINKHELP 1010 +#define IDC_BUTTONBACKUP 1011 +#define IDC_STATICFILE 1013 +#define IDC_LINKWEB 1014 +#define IDC_EDITSEARCH 1025 +#define IDC_SYSLINKLOC 1026 +#define IDC_ICONSEARCH 1027 +#define IDC_CHECKALL 1031 +#define IDC_BUTTONCHECK 1032 +#define IDC_LINKDOWNLOAD 1035 +#define IDC_PROGRESS 1036 +#define IDC_MESSAGE 1037 +#define IDD_SETTINGS 4000 +#define IDS_TOGGLE_SETTING 4000 +#define IDD_SETTINGSTREE 4001 +#define IDS_SELECT_SETTING 4001 +#define IDD_BROWSEFORICON 4002 +#define IDS_DEFAULT_SETTING 4002 +#define IDD_LANGUAGE 4003 +#define IDS_PLAY_SETTING 4003 +#define IDD_CUSTOMTREE 4004 +#define IDS_ICON_FILTERS 4004 +#define IDD_PROGRESS 4005 +#define IDS_ICON_TITLE 4005 +#define IDS_WAV_FILTERS 4006 +#define IDS_WAV_TITLE 4007 +#define IDS_SETTING_LOCKED 4008 +#define IDS_SETTING_LOCKED_GP 4009 +#define IDS_BASIC_SETTINGS 4010 +#define IDS_ALWAYS_ON_TOP 4011 +#define IDS_MENU_EDIT 4012 +#define IDS_MENU_DELETE 4013 +#define IDS_MENU_RENAME 4014 +#define IDS_PICK_LINK_TITLE 4015 +#define IDS_PICK_LINK_FILE 4016 +#define IDS_PICK_LINK_FOLDER 4017 +#define IDS_DUPLICATE_ITEM 4018 +#define IDS_ERROR_TITLE 4019 +#define IDS_ERROR_SEPARATOR 4020 +#define IDS_ERROR_ASCII 4021 +#define IDS_ERROR_EMPTY 4022 +#define IDS_RESET_TOOLBAR 4023 +#define IDS_RESET_TOOLBAR_WARN 4024 +#define IDS_RESET_MENU 4025 +#define IDS_RESET_MENU_WARN 4026 +#define IDS_ADD_TOOLBAR 4027 +#define IDS_ADD_MENU 4028 +#define IDS_INSERT_MENU 4029 +#define IDS_EMPTY_MENU 4030 +#define IDS_TREE_TOOLBAR 4031 +#define IDS_TREE_MENU 4032 +#define IDS_XML_FILTERS 4033 +#define IDS_XML_TITLE_LOAD 4034 +#define IDS_XML_TITLE_SAVE 4035 +#define IDS_RESET_CONFIRM 4036 +#define IDS_RESET_TITLE 4037 +#define IDS_TOOLBAR_LOCKED 4038 +#define IDS_MENU_LOCKED 4039 +#define IDS_BACKUP_SAVE 4040 +#define IDS_BACKUP_LOAD 4041 +#define IDS_BACKUP_RESET 4042 +#define IDS_ERROR_LOADING_XML 4043 +#define IDS_ERROR_SAVING_XML 4044 +#define IDS_DRAG_DROP_EXP_TIP 4045 +#define IDS_DRAG_DROP_SM_TIP 4046 +#define IDS_COMMAND_EXP_TIP 4047 +#define IDS_STRING4048 4048 +#define IDS_COMMAND_SM_TIP 4048 +#define IDS_COMMAND_FILTERS 4049 +#define IDS_OS_LANGUAGE 4050 +#define IDS_BMP_FILTERS 4051 +#define IDS_BMP_TITLE 4052 +#define IDS_SEARCH_PROMPT 4053 +#define IDS_SETTING_SEARCH 4054 +#define IDS_WEBSITE_TIP 4055 +#define IDS_LOCATE_SETTING 4056 +#define IDS_LANGUAGE_UPDATED 4057 +#define IDS_LANGUAGE_MISSING 4058 +#define IDS_LANGUAGE_DOWNLOAD 4059 +#define IDS_LANGUAGE_SUCCESS 4060 +#define IDS_LANGUAGE_SUCCESS2 4061 +#define IDS_LANGUAGE_FAIL 4062 +#define IDS_INTERNET_FAIL 4063 +#define IDS_INITIATE_FAIL 4064 +#define IDS_LANG_DOWNLOAD_FAIL 4065 +#define IDS_LANG_SAVE_FAIL 4066 +#define IDS_UPDATE_TITLE 4067 +#define IDS_INST_DOWNLOAD_FAIL 4068 +#define IDS_INST_SAVE_FAIL 4069 +#define IDS_PROGRESS_CONNECT 4070 +#define IDS_PROGRESS_DOWNLOAD 4071 +#define IDS_PROGRESS_VERIFY 4072 +#define IDS_PROGRESS_SAVE 4073 +#define IDS_PROGRESS_TITLE_CHECK 4074 +#define IDS_PROGRESS_TITLE_DOWNLOAD 4075 +#define IDS_DOWNLOAD_TIP 4076 +#define IDS_BMP_FILTERS2 4077 +#define IDS_UNSAVED_CHANGES 4078 +#define IDS_UNSAVED_TITLE 4079 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 111 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1038 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/ClassicShellSrc/ClassicShellLib/stdafx.cpp b/ClassicShellSrc/ClassicShellLib/stdafx.cpp new file mode 100644 index 0000000..2556f38 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/stdafx.cpp @@ -0,0 +1,5 @@ +// stdafx.cpp : source file that includes just the standard includes +// ClassicStartMenuDLL.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/ClassicShellSrc/ClassicShellLib/stdafx.h b/ClassicShellSrc/ClassicShellLib/stdafx.h new file mode 100644 index 0000000..122f466 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/stdafx.h @@ -0,0 +1,22 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#define STRICT_TYPED_ITEMIDS +// Windows Header Files: +#include +#include +#include +#include + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +#include +#include +#include +#include diff --git a/ClassicShellSrc/ClassicShellLib/targetver.h b/ClassicShellSrc/ClassicShellLib/targetver.h new file mode 100644 index 0000000..d4feea8 --- /dev/null +++ b/ClassicShellSrc/ClassicShellLib/targetver.h @@ -0,0 +1,24 @@ +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Specifies that the minimum required platform is Windows 7. +#define WINVER 0x0602 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows 7. +#define _WIN32_WINNT 0x0602 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. +#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. +#endif diff --git a/ClassicShellSrc/ClassicShellLib/warning.ico b/ClassicShellSrc/ClassicShellLib/warning.ico new file mode 100644 index 0000000..8d1837f Binary files /dev/null and b/ClassicShellSrc/ClassicShellLib/warning.ico differ diff --git a/ClassicShellSrc/ClassicShellSetup/BuildArchives.bat b/ClassicShellSrc/ClassicShellSetup/BuildArchives.bat new file mode 100644 index 0000000..4cf5d31 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/BuildArchives.bat @@ -0,0 +1,18 @@ +REM ***** Collect PDBs + +del Final\ClassicShellPDB_%CS_VERSION_STR%.zip +"C:\Program Files\WinRAR\winrar" a -afzip -ep1 Final\ClassicShellPDB_%CS_VERSION_STR%.zip Output\PDB32 Output\PDB64 + +cd .. + +REM ***** Collect Sources + +del ClassicShellSetup\Final\ClassicShellSrc_%CS_VERSION_STR%.zip +"C:\Program Files\WinRAR\winrar" a -afzip -ep1 -ed -r -x*.intermediate.manifest -x*.embed.manifest -x*_i.h -xWebsite\ ClassicShellSetup\Final\ClassicShellSrc_%CS_VERSION_STR%.zip *.h *.cpp *.rc *.vcproj *.ini *.def *.ico *.idl *.rgs *.jpg *.manifest *.wxl *.wxs *.sln *.bat *.bmp *.txt *.html *.rtf *.gif *.png *.hhp *.hhc ??-??.dll + +REM ***** Collect Localization files + +del ClassicShellSetup\Final\ClassicShellLoc.zip +"C:\Program Files\WinRAR\winrar" a -afzip -ep1 -ed -r -x*WixUI_en-us.wxl -x*.adml -x*.admx -x*LocComments.txt ClassicShellSetup\Final\ClassicShellLoc.zip Localization\English ClassicExplorer\ExplorerL10N.ini ClassicStartMenu\StartMenuL10N.ini ClassicStartMenu\StartMenuHelper\StartMenuHelperL10N.ini Localization\English\ClassicShellText-en-US.wxl Localization\English\ClassicShellEULA.rtf + +cd ClassicShellSetup diff --git a/ClassicShellSrc/ClassicShellSetup/BuildBinaries.bat b/ClassicShellSrc/ClassicShellSetup/BuildBinaries.bat new file mode 100644 index 0000000..880d624 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/BuildBinaries.bat @@ -0,0 +1,127 @@ +@SET CS_ERROR=0 + +md Output +del /Q /S Output\*.* +md Output\x64 +md Output\PDB32 +md Output\PDB64 + +REM ********* Build 64-bit solution +"%VS90COMNTOOLS%..\IDE\devenv.com" ..\ClassicShell.sln /rebuild "Setup|x64" +@if ERRORLEVEL 1 goto end + + +REM ********* Build 32-bit solution (must be after 64-bit) +"%VS90COMNTOOLS%..\IDE\devenv.com" ..\ClassicShell.sln /rebuild "Setup|Win32" +@if ERRORLEVEL 1 goto end + + +REM ********* Make en-US.dll +cd .. +start /wait ClassicShellSetup\ClassicShellUtility\Release\ClassicShellUtility.exe makeEN ClassicExplorer\Setup\ClassicExplorer32.dll ClassicStartMenu\Setup\ClassicStartMenuDLL.dll ClassicIE\Setup\ClassicIEDLL_32.dll ClassicShellUpdate\Release\ClassicShellUpdate.exe +@if ERRORLEVEL 1 goto end + +start /wait ClassicShellSetup\ClassicShellUtility\Release\ClassicShellUtility.exe extract en-US.dll en-US.csv +copy en-US.dll Localization\English +move en-US.csv Localization\English + +cd ClassicShellSetup + + +REM ********* Copy binaries + +copy /B ..\ClassicExplorer\Setup\ClassicExplorer32.dll Output +copy /B ..\ClassicExplorer\Setup\ClassicExplorerSettings.exe Output +copy /B ..\ClassicIE\Setup\ClassicIEDLL_32.dll Output +copy /B ..\ClassicIE\Setup\ClassicIE_32.exe Output +copy /B ..\ClassicStartMenu\Setup\ClassicStartMenu.exe Output +copy /B ..\ClassicStartMenu\Setup\ClassicStartMenuDLL.dll Output +copy /B ..\ClassicShellUpdate\Release\ClassicShellUpdate.exe Output +copy /B ..\ClassicStartMenu\StartMenuHelper\Setup\StartMenuHelper32.dll Output +copy /B ..\ClassicShellSetup\SetupHelper\Release\SetupHelper.exe Output + +copy /B ..\ClassicExplorer\Setup64\ClassicExplorer64.dll Output\x64 +copy /B ..\ClassicIE\Setup64\ClassicIEDLL_64.dll Output\x64 +copy /B ..\ClassicIE\Setup64\ClassicIE_64.exe Output\x64 +copy /B ..\ClassicStartMenu\Setup64\ClassicStartMenu.exe Output\x64 +copy /B ..\ClassicStartMenu\Setup64\ClassicStartMenuDLL.dll Output\x64 +copy /B ..\ClassicStartMenu\StartMenuHelper\Setup64\StartMenuHelper64.dll Output\x64 + +copy /B "..\ClassicStartMenu\Skins\Classic Skin.skin" Output +copy /B "..\ClassicStartMenu\Skins\Full Glass.skin" Output +copy /B "..\ClassicStartMenu\Skins\Smoked Glass.skin" Output +copy /B "..\ClassicStartMenu\Skins\Windows Aero.skin" Output +copy /B "..\ClassicStartMenu\Skins\Windows Basic.skin" Output +copy /B "..\ClassicStartMenu\Skins\Windows XP Luna.skin" Output +copy /B "..\ClassicStartMenu\Skins\Windows 8.skin" Output +copy /B "..\ClassicStartMenu\Skins\Metro.skin" Output +copy /B "..\ClassicStartMenu\Skins\Classic Skin.skin7" Output +copy /B "..\ClassicStartMenu\Skins\Windows Aero.skin7" Output +copy /B "..\ClassicStartMenu\Skins\Windows 8.skin7" Output +copy /B "..\ClassicStartMenu\Skins\Midnight.skin7" Output +copy /B "..\ClassicStartMenu\Skins\Metro.skin7" Output +copy /B "..\ClassicStartMenu\Skins\Metallic.skin7" Output + + +REM ********* Collect debug info + +REM Explorer 32 +copy /B ..\ClassicExplorer\Setup\ClassicExplorer32.pdb Output\PDB32 +copy /B Output\ClassicExplorer32.dll Output\PDB32 +copy /B ..\ClassicExplorer\Setup\ClassicExplorerSettings.pdb Output\PDB32 +copy /B Output\ClassicExplorerSettings.exe Output\PDB32 + +REM Explorer 64 +copy /B ..\ClassicExplorer\Setup64\ClassicExplorer64.pdb Output\PDB64 +copy /B Output\x64\ClassicExplorer64.dll Output\PDB64 + +REM IE 32 +copy /B ..\ClassicIE\Setup\ClassicIEDLL_32.pdb Output\PDB32 +copy /B Output\ClassicIEDLL_32.dll Output\PDB32 +copy /B ..\ClassicIE\Setup\ClassicIE_32.exe Output\PDB32 +copy /B Output\ClassicIE_32.exe Output\PDB32 + +REM IE 64 +copy /B ..\ClassicIE\Setup64\ClassicIEDLL_64.pdb Output\PDB64 +copy /B Output\x64\ClassicIEDLL_64.dll Output\PDB64 +copy /B ..\ClassicIE\Setup64\ClassicIE_64.exe Output\PDB64 +copy /B Output\x64\ClassicIE_64.exe Output\PDB64 + +REM Menu 32 +copy /B ..\ClassicStartMenu\Setup\ClassicStartMenu.pdb Output\PDB32 +copy /B Output\ClassicStartMenu.exe Output\PDB32 +copy /B ..\ClassicStartMenu\Setup\ClassicStartMenuDLL.pdb Output\PDB32 +copy /B Output\ClassicStartMenuDLL.dll Output\PDB32 +copy /B ..\ClassicStartMenu\StartMenuHelper\Setup\StartMenuHelper32.pdb Output\PDB32 +copy /B Output\StartMenuHelper32.dll Output\PDB32 +copy /B ..\ClassicShellUpdate\Release\ClassicShellUpdate.pdb Output\PDB32 +copy /B Output\ClassicShellUpdate.exe Output\PDB32 + +REM Menu 64 +copy /B ..\ClassicStartMenu\Setup64\ClassicStartMenu.pdb Output\PDB64 +copy /B Output\x64\ClassicStartMenu.exe Output\PDB64 +copy /B ..\ClassicStartMenu\Setup64\ClassicStartMenuDLL.pdb Output\PDB64 +copy /B Output\x64\ClassicStartMenuDLL.dll Output\PDB64 +copy /B ..\ClassicStartMenu\StartMenuHelper\Setup64\StartMenuHelper64.pdb Output\PDB64 +copy /B Output\x64\StartMenuHelper64.dll Output\PDB64 + + +REM ********* Build ADMX +del Output\PolicyDefinitions.zip +cd ..\Localization\English +..\..\ClassicStartMenu\Setup\ClassicStartMenu.exe -saveadmx en-US +@if ERRORLEVEL 1 goto end +..\..\ClassicExplorer\Setup\ClassicExplorerSettings.exe -saveadmx en-US +@if ERRORLEVEL 1 goto end +..\..\ClassicIE\Setup\ClassicIE_32.exe -saveadmx en-US +@if ERRORLEVEL 1 goto end +"C:\Program Files\WinRAR\winrar" a -afzip -ep ..\..\ClassicShellSetup\Output\PolicyDefinitions.zip *.admx PolicyDefinitions.rtf +"C:\Program Files\WinRAR\winrar" a -afzip -ep -apen-US ..\..\ClassicShellSetup\Output\PolicyDefinitions.zip *.adml +cd ..\..\ClassicShellSetup + + +@goto EOF +:end +@SET CS_ERROR=1 +pause +:EOF diff --git a/ClassicShellSrc/ClassicShellSetup/BuildInstaller.bat b/ClassicShellSrc/ClassicShellSetup/BuildInstaller.bat new file mode 100644 index 0000000..95abfc2 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/BuildInstaller.bat @@ -0,0 +1,84 @@ +@REM !!!!! CHANGE THE GUIDS WHEN CHANGING THE VERSION !!!!! +SET CS_VERSION=4.3.1 +SET CS_VERSION_STR=4_3_1 +SET CS_VERSION_NUM=40301 +SET CS_GUID32=8A99142D-5D6E-40b6-AF88-8BD46F0C5CB4 +SET CS_GUID64=CABCE573-0A86-42fa-A52A-C7EA61D5BE08 + +SET CS_ERROR=0 + +REM ********* Build Help +@if %CS_HAS_HELP%==1 ( + if NOT %CS_LANG_FOLDER%==English mklink /J ..\Localization\%CS_LANG_FOLDER%\images ..\Localization\English\images + hhc ..\Localization\%CS_LANG_FOLDER%\ClassicShell.hhp + @REM looks like hhc returns 0 for error, >0 for success + @if NOT ERRORLEVEL 1 @SET CS_ERROR=1 + if NOT %CS_LANG_FOLDER%==English rmdir ..\Localization\%CS_LANG_FOLDER%\images + @if %CS_ERROR%==1 goto end +) +@if %CS_HAS_HELP%==0 ( + copy /Y ..\Localization\English\ClassicShell.chm ..\Localization\%CS_LANG_FOLDER%\ClassicShell.chm +) + +@if %CS_HAS_EULA%==0 copy /Y ..\Localization\English\ClassicShellEULA.rtf ..\Localization\%CS_LANG_FOLDER% +@if %CS_HAS_README%==0 copy /Y ..\Localization\English\ClassicShellReadme.rtf ..\Localization\%CS_LANG_FOLDER% + +@if _%CS_LANG_NAME%==_ echo Unrecognized language '%CS_LANG_FOLDER%' +@if _%CS_LANG_NAME%==_ goto end + +SET CS_INSTALLER_NAME=ClassicShellSetup_%CS_VERSION_STR%-%CS_LANG_NAME_SHORT% +if %CS_LANG_NAME_SHORT%==en SET CS_INSTALLER_NAME=ClassicShellSetup_%CS_VERSION_STR% + +md Temp +del /Q Temp\*.* + +@if not exist ..\Localization\%CS_LANG_FOLDER%\ClassicShellText-%CS_LANG_NAME%.wxl goto end + +REM ********* Build 32-bit MSI +candle ClassicShellSetup.wxs -out Temp\ClassicShellSetup32.wixobj -ext WixUIExtension -ext WixUtilExtension -dx64=0 -dCS_LANG_FOLDER=%CS_LANG_FOLDER% -dCS_LANG_NAME=%CS_LANG_NAME% +@if ERRORLEVEL 1 goto end + +@REM We need to suppress ICE38 and ICE43 because they apply only to per-user installation. We only support per-machine installs +@REM We need to suppress ICE09 because the helper DLLs need to go into the system directory (for safety reasons) +light Temp\ClassicShellSetup32.wixobj -out Temp\ClassicShellSetup32.msi -ext WixUIExtension -ext WixUtilExtension -loc ..\Localization\%CS_LANG_FOLDER%\ClassicShellText-%CS_LANG_NAME%.wxl -loc ..\Localization\%CS_LANG_FOLDER%\WixUI_%CS_LANG_NAME%.wxl -sice:ICE38 -sice:ICE43 -sice:ICE09 +@if ERRORLEVEL 1 goto end + + +REM ********* Build 64-bit MSI +candle ClassicShellSetup.wxs -out Temp\ClassicShellSetup64.wixobj -ext WixUIExtension -ext WixUtilExtension -dx64=1 -dCS_LANG_FOLDER=%CS_LANG_FOLDER% -dCS_LANG_NAME=%CS_LANG_NAME% +@if ERRORLEVEL 1 goto end + +@REM We need to suppress ICE38 and ICE43 because they apply only to per-user installation. We only support per-machine installs +@REM We need to suppress ICE09 because the helper DLLs need to go into the system directory (for safety reasons) +light Temp\ClassicShellSetup64.wixobj -out Temp\ClassicShellSetup64.msi -ext WixUIExtension -ext WixUtilExtension -loc ..\Localization\%CS_LANG_FOLDER%\ClassicShellText-%CS_LANG_NAME%.wxl -loc ..\Localization\%CS_LANG_FOLDER%\WixUI_%CS_LANG_NAME%.wxl -sice:ICE38 -sice:ICE43 -sice:ICE09 +@if ERRORLEVEL 1 goto end + + +REM ********* Build MSI Checksums +start /wait ClassicShellUtility\Release\ClassicShellUtility.exe crcmsi Temp +@if ERRORLEVEL 1 goto end + +REM ********* Build bootstrapper +"%VS90COMNTOOLS%..\IDE\devenv.com" ClassicShellSetup.sln /rebuild "Release|Win32" +@if ERRORLEVEL 1 goto end + +md Final + +del Final\%CS_INSTALLER_NAME%.exe +copy /B Release\ClassicShellSetup.exe Final\%CS_INSTALLER_NAME%.exe + +md Output\Releases +copy /B Final\%CS_INSTALLER_NAME%.exe Output\Releases\%CS_INSTALLER_NAME%.exe + + + + + +@goto EOF +:end +@SET CS_ERROR=1 +pause +:EOF +SET CS_LANG_FOLDER= +SET CS_LANG_NAME= +SET CS_LANG_NAME_SHORT= diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShell.ico b/ClassicShellSrc/ClassicShellSetup/ClassicShell.ico new file mode 100644 index 0000000..3ccb834 Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/ClassicShell.ico differ diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.cpp b/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.cpp new file mode 100644 index 0000000..7b73a24 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.cpp @@ -0,0 +1,437 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#define _WIN32_WINNT 0x0600 +#include +#include +#include +#include +#include +#include "resource.h" +#include "StringUtils.h" +#include "FNVHash.h" + +// ClassicShellSetup.exe is a bootstrap application that contains installers for 32-bit and 64-bit. +// It unpacks the right installer into the temp directory and executes it. + +typedef BOOL (WINAPI *FIsWow64Process)( HANDLE hProcess, PBOOL Wow64Process ); +typedef BOOL (WINAPI *FQueryFullProcessImageName)( HANDLE hProcess, DWORD dwFlags, LPTSTR lpExeName, PDWORD lpdwSize ); + + + +enum +{ + ERR_WRONG_OS=101, // the OS is too old, Windows 7 or up is required + ERR_OLD_VERSION, // detected version older than 1.0.0 + ERR_HASH_NOTFOUND, // the HASH resource is missing + ERR_MSIRES_NOTFOUND, // missing MSI resource + ERR_HASH_ERROR, + ERR_VERRES_NOTFOUND, // missing version resource + ERR_MSI_EXTRACTFAIL, // failed to extract the MSI file + ERR_MSIEXEC, // msiexec failed to start +}; + +struct Chunk +{ + int start1, start2, len; +}; + +static void WriteFileXOR( HANDLE hFile, const unsigned char *buf, int size ) +{ + if (size>0) + { + std::vector buf2; + buf2.reserve(size); + for (int i=0;idwProductVersionMS==0x20008 && pVer->dwProductVersionLS==0 && DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOGPWD),NULL,DialogProc)!=IDOK) + return 0; + + int count; + wchar_t *const *params=CommandLineToArgvW(lpCmdLine,&count); + if (!params) count=0; + + int extract=0; + bool bQuiet=false; + for (;count>0;count--,params++) + { + if (_wcsicmp(params[0],L"help")==0 || _wcsicmp(params[0],L"/?")==0) + { + wchar_t strTitle[256]; + if (!LoadString(hInstance,IDS_APP_TITLE,strTitle,_countof(strTitle))) strTitle[0]=0; + wchar_t strText[4096]; + if (!LoadString(hInstance,IDS_HELP,strText,_countof(strText))) strText[0]=0; + + MessageBox(NULL,strText,strTitle,MB_OK); + return 0; + } + if (_wcsicmp(params[0],L"extract32")==0) + extract=32; + if (_wcsicmp(params[0],L"extract64")==0) + extract=64; + if (_wcsicmp(params[0],L"/qn")==0 || _wcsicmp(params[0],L"/q")==0 || _wcsicmp(params[0],L"/quiet")==0 || _wcsicmp(params[0],L"/passive")==0) + { + bQuiet=true; + } + } + + if (!pVer) + { + if (!bQuiet) + { + wchar_t strTitle[256]; + if (!LoadString(hInstance,IDS_APP_TITLE,strTitle,_countof(strTitle))) strTitle[0]=0; + wchar_t strText[256]; + if (!LoadString(hInstance,IDS_ERR_INTERNAL,strText,_countof(strText))) strText[0]=0; + MessageBox(NULL,strText,strTitle,MB_OK|MB_ICONERROR); + } + return ERR_VERRES_NOTFOUND; + } + + if (extract) + { + wchar_t msiName[_MAX_PATH]; + Sprintf(msiName,_countof(msiName),L"ClassicShellSetup%d_%d_%d_%d.msi",extract,HIWORD(pVer->dwProductVersionMS),LOWORD(pVer->dwProductVersionMS),HIWORD(pVer->dwProductVersionLS)); + return ExtractMsi(hInstance,msiName,extract==64,bQuiet); + } + + // check Windows version + WORD winVer=LOWORD(GetVersion()); + winVer=MAKEWORD(HIBYTE(winVer),LOBYTE(winVer)); + if (winVer<0x601) + { + if (!bQuiet) + { + wchar_t strTitle[256]; + if (!LoadString(hInstance,IDS_APP_TITLE,strTitle,_countof(strTitle))) strTitle[0]=0; + wchar_t strText[256]; + if (!LoadString(hInstance,IDS_ERR_WIN7,strText,_countof(strText))) strText[0]=0; + MessageBox(NULL,strText,strTitle,MB_OK|MB_ICONERROR); + } + return ERR_WRONG_OS; + } + + // dynamically link to IsWow64Process because it is not available for Windows 2000 + HMODULE hKernel32=GetModuleHandle(L"kernel32.dll"); + FIsWow64Process isWow64Process=(FIsWow64Process)GetProcAddress(hKernel32,"IsWow64Process"); + if (!isWow64Process) + { + if (!bQuiet) + { + wchar_t strTitle[256]; + if (!LoadString(hInstance,IDS_APP_TITLE,strTitle,_countof(strTitle))) strTitle[0]=0; + wchar_t strText[256]; + if (!LoadString(hInstance,IDS_ERR_WIN7,strText,_countof(strText))) strText[0]=0; + MessageBox(NULL,strText,strTitle,MB_OK|MB_ICONERROR); + } + return ERR_WRONG_OS; + } + + BOOL b64=FALSE; + isWow64Process(GetCurrentProcess(),&b64); + + // look for an old version the start menu (2.0.0 or older) and show a warning if it is still running. the uninstaller for such old versions doesn't close the start menu + HWND hwnd=FindWindow(L"ClassicStartMenu.CStartHookWindow",L"StartHookWindow"); + if (hwnd) + { + bool bStartMenu=false; + + DWORD id; + GetWindowThreadProcessId(hwnd,&id); + HANDLE process=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,id); + if (process) + { + bStartMenu=true; + wchar_t path[_MAX_PATH]; + DWORD size=_countof(path); + + FQueryFullProcessImageName queryFullProcessImageName=(FQueryFullProcessImageName)GetProcAddress(hKernel32,"QueryFullProcessImageNameW"); + if (queryFullProcessImageName && queryFullProcessImageName(process,0,path,&size)) + { + DWORD q; + DWORD size=GetFileVersionInfoSize(path,&q); + if (size) + { + std::vector buf(size); + if (GetFileVersionInfo(path,0,size,&buf[0])) + { + VS_FIXEDFILEINFO *pVer; + UINT len; + if (VerQueryValue(&buf[0],L"\\",(void**)&pVer,&len) && pVer->dwProductVersionMS>0x20000) + bStartMenu=false; + } + } + } + CloseHandle(process); + } + if (bStartMenu) + { + wchar_t strTitle[256]; + if (!LoadString(hInstance,IDS_APP_TITLE,strTitle,_countof(strTitle))) strTitle[0]=0; + wchar_t strText[1024]; + if (!LoadString(hInstance,IDS_OLDSTARTMENU,strText,_countof(strText))) strText[0]=0; + MessageBox(NULL,strText,strTitle,MB_OK|MB_ICONWARNING); + } + } +/* + // warning about being beta + if (!bQuiet) + { + if (MessageBox(NULL,L"Warning!\nThis is a beta version of Classic Shell. It contains features that are not fully tested. Please report any problems in the Classic Shell forums. If you prefer a stable build over the latest features, you can download one of the \"general release\" versions like 3.6.8.\nDo you want to continue with the installation?",L"Classic Shell Setup",MB_YESNO|MB_ICONWARNING)==IDNO) + return 99; + } +*/ + + DWORD version; + { + HKEY hKey; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,L"SOFTWARE\\IvoSoft\\ClassicShell",0,KEY_READ|(b64?KEY_WOW64_64KEY:0),&hKey)==ERROR_SUCCESS) + { + DWORD size=sizeof(version); + if (RegQueryValueEx(hKey,L"Version",0,NULL,(BYTE*)&version,&size)!=ERROR_SUCCESS) + version=0; + RegCloseKey(hKey); + } + } + + wchar_t msiName[_MAX_PATH]; + Sprintf(msiName,_countof(msiName),L"%%ALLUSERSPROFILE%%\\ClassicShellSetup%d_%d_%d_%d.msi",b64?64:32,HIWORD(pVer->dwProductVersionMS),LOWORD(pVer->dwProductVersionMS),HIWORD(pVer->dwProductVersionLS)); + DoEnvironmentSubst(msiName,_countof(msiName)); + int ex=ExtractMsi(hInstance,msiName,b64!=FALSE,bQuiet); + if (ex) return ex; + + wchar_t cmdLine[2048]; + if (wcsstr(lpCmdLine,L"%MSI%") || wcsstr(lpCmdLine,L"%msi%")) + { + SetEnvironmentVariable(L"MSI",msiName); + Sprintf(cmdLine,_countof(cmdLine),L"msiexec.exe %s",lpCmdLine); + DoEnvironmentSubst(cmdLine,_countof(cmdLine)); + } + else + { + Sprintf(cmdLine,_countof(cmdLine),L"msiexec.exe /i \"%s\" %s",msiName,lpCmdLine); + } + + // start the installer + STARTUPINFO startupInfo={sizeof(startupInfo)}; + PROCESS_INFORMATION processInfo; + memset(&processInfo,0,sizeof(processInfo)); + if (!CreateProcess(NULL,cmdLine,NULL,NULL,TRUE,0,NULL,NULL,&startupInfo,&processInfo)) + { + DeleteFile(msiName); + if (!bQuiet) + { + wchar_t strTitle[256]; + if (!LoadString(hInstance,IDS_APP_TITLE,strTitle,_countof(strTitle))) strTitle[0]=0; + wchar_t strText[256]; + if (!LoadString(hInstance,IDS_ERR_MSIEXEC,strText,_countof(strText))) strText[0]=0; + MessageBox(NULL,strText,strTitle,MB_OK|MB_ICONERROR); + } + return ERR_MSIEXEC; + } + else + { + CloseHandle(processInfo.hThread); + // wait for the installer to finish + WaitForSingleObject(processInfo.hProcess,INFINITE); + DWORD code; + GetExitCodeProcess(processInfo.hProcess,&code); + CloseHandle(processInfo.hProcess); + DeleteFile(msiName); + return code; + } +} diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.manifest b/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.manifest new file mode 100644 index 0000000..46002e3 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.manifest @@ -0,0 +1,41 @@ + + + +Classic Shell Setup + + + + + + + + true + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.rc b/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.rc new file mode 100644 index 0000000..4764ce6 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.rc @@ -0,0 +1,182 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APPICON ICON "ClassicShell.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 4,3,1,0 + PRODUCTVERSION 4,3,1,0 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "IvoSoft" + VALUE "FileDescription", "Adds classic shell features to Windows 7 and Windows 8" + VALUE "FileVersion", "4, 3, 1, 0" + VALUE "InternalName", "ClassicShellSetup" + VALUE "LegalCopyright", "Copyright (C) 2009-2016, Ivo Beltchev" + VALUE "OriginalFilename", "ClassicShellSetup.exe" + VALUE "ProductName", "Classic Shell" + VALUE "ProductVersion", "4, 3, 1, 0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// MSI_FILE +// + +IDR_MSI_FILE32 MSI_FILE "Temp\\ClassicShellSetup32.msi_" +IDR_MSI_FILE64 MSI_FILE "Temp\\ClassicShellSetup64.msi_" +IDR_MSI_CHECKSUM MSI_FILE "msichecksum.bin" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOGPWD DIALOGEX 0, 0, 154, 75 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Classic Shell 2.8.0 (closed beta)" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "This beta version is password-protected. Please enter the password:",IDC_STATIC,7,7,140,17 + EDITTEXT IDC_EDITPWD,7,32,140,14,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,43,54,50,14 + PUSHBUTTON "Cancel",IDCANCEL,97,54,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DIALOGPWD, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 147 + TOPMARGIN, 7 + BOTTOMMARGIN, 68 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_APP_TITLE "Classic Shell Setup" + IDS_OLDSTARTMENU "Warning!\nAn old version of the classic start menu is still running. Please close it before installing the new version to avoid crashing Explorer. Right click on the start button and select ""Exit""." + IDS_ERR_CORRUPTED "Failed to extract setup file '%s'. The MSI resource is corrupted." +END + +STRINGTABLE +BEGIN + IDS_ERR_INTERNAL "Internal Setup Error" + IDS_ERR_EXTRACT "Failed to extract setup file '%s'." + IDS_ERR_WIN7 "Classic Shell requires Windows 7 or later." + IDS_ERR_MSIEXEC "Failed to run msiexec.exe." +END + +STRINGTABLE +BEGIN + IDS_HELP "Classic Shell Setup will install Classic Shell on your computer. Possible command lines:\n - runs the installer normally\n extract32 - extracts the 32-bit MSI\n extract64 - extracts the 64-bit MSI\n help, /? - shows the command line help\n - the options are passed to msiexec\n * if the options contain %MSI% (all caps) the token is replaced by the name of the extracted MSI file\n * if %MSI% is not found, the setup runs ""msiexec /i ""\n * run msiexec with no parameters to see the full list of msiexec options\n\nExamples:\n /qn - runs the installer in quiet mode\n /x %MSI% /qb - uninstalls the product in basic UI level\n /f %MSI% - repairs the product\n /l* log.txt - runs the installer and logs the process in the log.txt file\n /qn ADDLOCAL=ClassicExplorer - installs only Classic Explorer in quiet mode\n /qn ADDLOCAL=ClassicStartMenu APPLICATIONFOLDER=C:\\ClassicShell - installs only Classic Start Menu in quiet mode in the folder C:\\ClassicShell\n ADDLOCAL=ClassicStartMenu,ClassicIE - runs the installer in full UI mode with Classic Start Menu and Classic IE checked by default" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.sln b/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.sln new file mode 100644 index 0000000..b2573cc --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.sln @@ -0,0 +1,62 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassicShellSetup", "ClassicShellSetup.vcproj", "{A4A4D3B1-24E7-401E-A37C-72141D7603DC}" + ProjectSection(ProjectDependencies) = postProject + {D42FE717-485B-492D-884A-1999F6D51154} = {D42FE717-485B-492D-884A-1999F6D51154} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClassicShellLib", "..\ClassicShellLib\ClassicShellLib.vcproj", "{D42FE717-485B-492D-884A-1999F6D51154}" +EndProject +Global + GlobalSection(SourceCodeControl) = preSolution + SccNumberOfProjects = 3 + SccProjectName0 = Perforce\u0020Project + SccLocalPath0 = .. + SccProvider0 = MSSCCI:Perforce\u0020SCM + SccProjectFilePathRelativizedFromConnection0 = ClassicShellSetup\\ + SccProjectUniqueName1 = ClassicShellSetup.vcproj + SccLocalPath1 = .. + SccProjectFilePathRelativizedFromConnection1 = ClassicShellSetup\\ + SccProjectUniqueName2 = ..\\ClassicShellLib\\ClassicShellLib.vcproj + SccLocalPath2 = .. + SccProjectFilePathRelativizedFromConnection2 = ClassicShellLib\\ + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A4A4D3B1-24E7-401E-A37C-72141D7603DC}.Debug|Win32.ActiveCfg = Debug|Win32 + {A4A4D3B1-24E7-401E-A37C-72141D7603DC}.Debug|Win32.Build.0 = Debug|Win32 + {A4A4D3B1-24E7-401E-A37C-72141D7603DC}.Debug|x64.ActiveCfg = Debug|Win32 + {A4A4D3B1-24E7-401E-A37C-72141D7603DC}.Release|Win32.ActiveCfg = Release|Win32 + {A4A4D3B1-24E7-401E-A37C-72141D7603DC}.Release|Win32.Build.0 = Release|Win32 + {A4A4D3B1-24E7-401E-A37C-72141D7603DC}.Release|x64.ActiveCfg = Release|Win32 + {D42FE717-485B-492D-884A-1999F6D51154}.Debug|Win32.ActiveCfg = Debug|Win32 + {D42FE717-485B-492D-884A-1999F6D51154}.Debug|Win32.Build.0 = Debug|Win32 + {D42FE717-485B-492D-884A-1999F6D51154}.Debug|x64.ActiveCfg = Debug|x64 + {D42FE717-485B-492D-884A-1999F6D51154}.Debug|x64.Build.0 = Debug|x64 + {D42FE717-485B-492D-884A-1999F6D51154}.Release|Win32.ActiveCfg = Release|Win32 + {D42FE717-485B-492D-884A-1999F6D51154}.Release|Win32.Build.0 = Release|Win32 + {D42FE717-485B-492D-884A-1999F6D51154}.Release|x64.ActiveCfg = Release|x64 + {D42FE717-485B-492D-884A-1999F6D51154}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(SourceCodeControl) = preSolution + SccNumberOfProjects = 3 + SccProjectName0 = Perforce\u0020Project + SccLocalPath0 = .. + SccProvider0 = MSSCCI:Perforce\u0020SCM + SccProjectFilePathRelativizedFromConnection0 = ClassicShellSetup\\ + SccProjectUniqueName1 = ClassicShellSetup.vcproj + SccLocalPath1 = .. + SccProjectFilePathRelativizedFromConnection1 = ClassicShellSetup\\ + SccProjectUniqueName2 = ..\\StringUtils\\StringUtils.vcproj + SccLocalPath2 = ..\\StringUtils + EndGlobalSection +EndGlobal diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.vcproj b/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.vcproj new file mode 100644 index 0000000..6e0b96e --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.vcproj @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.wxs b/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.wxs new file mode 100644 index 0000000..8802b84 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellSetup.wxs @@ -0,0 +1,669 @@ + + + + + + + + + + + + + + + + + + + + + + not Msix64 + + VersionNT>=601 + NOT NEWERPRODUCTFOUND OR Installed + + + + + + + + + + + + START_MENU_FOLDER=1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IE_BUILD>=90000 + + + + + + + + + + + + + + + + + + + + + 1 + 1 + 1 + LicenseAccepted = "1" + Installed + NOT Installed + 1 + NOT Installed OR WixUI_InstallMode = "Change" + Installed + 1 + 1 + 1 + 1 + 1 + + + + 1 + + + + + + + + + NOT Installed + + + + + + CostingComplete = 1 + "1"]]> + LicenseAccepted = "1" + + + 1 + + + + + + + 1 + + + + + + + + + + 1 + Installed + Installed + + + + + + + 1 + + + + + + + + + + + + + + + + + + Installed + + + + Installed + + + Installed + + + Installed + + + + + + + + + + + + + + + + + + + + 1 + + + WixUI_InstallMode = "Remove" + + + + + + + + CostingComplete = 1 + + + 1 + + + + + + + + + Installed AND NOT RESUME AND NOT Preselected + + + + 1 + + + + 1 + + + + 1 + ARPNOREMOVE + + + ARPNOREMOVE + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + VersionNT>601 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + VersionNT>601 + + + + + + + + + + + + + + + + VersionNT>601 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + START_MENU_FOLDER=1 + + + + + START_MENU_FOLDER=1 + + + + + START_MENU_FOLDER=1 + + + + + + + START_MENU_FOLDER=1 + + + + + + + START_MENU_FOLDER=1 + + + + + + + START_MENU_FOLDER=1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1]]> + + + + + + + + diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ClassicShellUtility.cpp b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ClassicShellUtility.cpp new file mode 100644 index 0000000..56ae761 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ClassicShellUtility.cpp @@ -0,0 +1,1203 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#define STRICT_TYPED_ITEMIDS +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit +#include +#include +#include +#include +#include +#include "StringUtils.h" +#include "FNVHash.h" +#include "SettingsParser.h" +#include "resource.h" +#include "..\UpdateBin\resource.h" +#include "ResourceHelper.h" +#include +#include "SaveLogFile.h" + +// Manifest to enable the 6.0 common controls +#pragma comment(linker, \ + "\"/manifestdependency:type='Win32' "\ + "name='Microsoft.Windows.Common-Controls' "\ + "version='6.0.0.0' "\ + "processorArchitecture='*' "\ + "publicKeyToken='6595b64144ccf1df' "\ + "language='*'\"") + +HINSTANCE g_hInstance; + +void EditLoggingOptions( void ); +void ManualUninstall( void ); +void ShowMetroColorViewer( void ); + +#ifndef _WIN64 +/////////////////////////////////////////////////////////////////////////////// + +static void LoadFile( const wchar_t *fname, std::vector &buf ) +{ + buf.clear(); + FILE *f=NULL; + if (_wfopen_s(&f,fname,L"rb") || !f) return; + fseek(f,0,SEEK_END); + int size=ftell(f); + fseek(f,0,SEEK_SET); + buf.resize(size); + if (size==0 || fread(&buf[0],1,size,f)!=size) + buf.clear(); + fclose(f); +} + +static unsigned int CalcFileFNV( const wchar_t *fname ) +{ + std::vector buf; + LoadFile(fname,buf); + if (buf.empty()) return 0; + return CalcFNVHash(&buf[0],(int)buf.size(),FNV_HASH0); +} + +static void Printf( const char *format, ... ) +{ + char buf[1024]; + va_list args; + va_start(args,format); + int len=Vsprintf(buf,_countof(buf),format,args); + va_end(args); + DWORD q; + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),buf,len,&q,NULL); +#if _DEBUG + OutputDebugStringA(buf); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// + +struct Chunk +{ + int start1, start2, len; +}; + +int CalcMsiChecksum( wchar_t *const *params, int count ) +{ + if (count<2) return 2; + + AttachConsole(ATTACH_PARENT_PROCESS); + + // load files + wchar_t path1[_MAX_PATH]; + std::vector buf1, buf2; + Sprintf(path1,_countof(path1),L"%s\\ClassicShellSetup32.msi",params[1]); + LoadFile(path1,buf1); + if (buf1.empty()) + { + Printf("Failed to open file %s\n",path1); + return 1; + } + wchar_t path2[_MAX_PATH]; + Sprintf(path2,_countof(path2),L"%s\\ClassicShellSetup64.msi",params[1]); + LoadFile(path2,buf2); + if (buf2.empty()) + { + Printf("Failed to open file %s\n",path2); + return 1; + } + + int len1=(int)buf1.size(); + int len2=(int)buf2.size(); + + for (std::vector::iterator it=buf1.begin();it!=buf1.end();++it) + *it^=0xFF; + for (std::vector::iterator it=buf2.begin();it!=buf2.end();++it) + *it^=0xFF; + + // detect common blocks (assuming at least 256K in size and in the same order in both files) + const int BLOCK_SIZE=256*1024; + std::vector chunks; + int start2=0; + for (int i=0;i0 && chunk.start2>0 && buf1[chunk.start1-1]==buf2[chunk.start2-1]) + { + chunk.start1--; + chunk.start2--; + chunk.len++; + } + while (chunk.start1+chunk.len::const_iterator it=chunks.begin();it!=chunks.end();++it) + { + if (it->start2-start>0) + fwrite(&buf2[start],1,it->start2-start,f); + start=it->start2+it->len; + } + if (len2-start>0) + fwrite(&buf2[start],1,len2-start,f); + fclose(f); + } + + unsigned int fnvs[2]; + fnvs[0]=CalcFNVHash(&buf1[0],len1,FNV_HASH0); + fnvs[1]=CalcFNVHash(&buf2[0],len2,FNV_HASH0); + + // save fnvs and chunks + { + FILE *f=NULL; + if (_wfopen_s(&f,L"msichecksum.bin",L"wb") || !f) + { + Printf("Failed to write msichecksum.bin\n"); + return 1; + } + fwrite(fnvs,4,_countof(fnvs),f); + int count=(int)chunks.size(); + fwrite(&count,1,4,f); + fwrite(&chunks[0],sizeof(Chunk),count,f); + fclose(f); + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +int MakeEnglishDll( wchar_t *const *params, int count ) +{ + if (count<5) return 2; + + AttachConsole(ATTACH_PARENT_PROCESS); + + HMODULE hEn0=LoadLibraryEx(L"en-US.dll",NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (!hEn0) + { + Printf("Failed to open en-US.dll (err: %d)\n",GetLastError()); + return 1; + } + + std::vector version; + { + HRSRC hResInfo=FindResource(hEn0,MAKEINTRESOURCE(VS_VERSION_INFO),RT_VERSION); + if (hResInfo) + { + HGLOBAL hRes=LoadResource(hEn0,hResInfo); + void *pRes=LockResource(hRes); + if (pRes) + { + DWORD len=SizeofResource(hEn0,hResInfo); + if (len>=40+sizeof(VS_FIXEDFILEINFO)) + { + version.resize(len); + memcpy(&version[0],pRes,len); + } + } + } + } + FreeLibrary(hEn0); + if (version.empty()) + { + Printf("Can't find version resource in en-US.dll\n"); + return 1; + } + + HANDLE hEn=BeginUpdateResource(L"en-US.dll",FALSE); + if (!hEn) + { + Printf("Failed to open en-US.dll (err: %d)\n",GetLastError()); + return 1; + } + + int res=1; + HMODULE hExplorer=NULL, hMenu=NULL, hIE=NULL; + WORD language=MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US); + + // get version, strings and dialog from ClassicExplorer32.dll + hExplorer=LoadLibraryEx(params[1],NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (!hExplorer) + { + Printf("Failed to open %S (err: %d)\n",params[1],GetLastError()); + goto qqq; + } + + // copy version + { + HRSRC hResInfo=FindResource(hExplorer,MAKEINTRESOURCE(VS_VERSION_INFO),RT_VERSION); + void *pRes=NULL; + if (hResInfo) + { + HGLOBAL hRes=LoadResource(hExplorer,hResInfo); + pRes=LockResource(hRes); + } + if (!pRes) + { + Printf("Can't find version resource in %S\n",params[1]); + goto qqq; + } + VS_FIXEDFILEINFO *pVer=(VS_FIXEDFILEINFO*)((char*)pRes+40); + VS_FIXEDFILEINFO *pVer0=(VS_FIXEDFILEINFO*)(&version[40]); + pVer0->dwProductVersionMS=pVer->dwProductVersionMS; + pVer0->dwProductVersionLS=pVer->dwProductVersionLS; + pVer0->dwFileVersionMS=pVer->dwFileVersionMS; + pVer0->dwFileVersionLS=pVer->dwFileVersionLS; + UpdateResource(hEn,RT_VERSION,MAKEINTRESOURCE(VS_VERSION_INFO),language,&version[0],version.size()); + } + + // copy strings + for (int i=2000;i<3000;i+=16) + { + int id=i/16; + HRSRC hResInfo=FindResource(hExplorer,MAKEINTRESOURCE(id),RT_STRING); + if (!hResInfo) continue; + HGLOBAL hRes=LoadResource(hExplorer,hResInfo); + void *pRes=LockResource(hRes); + if (!pRes) continue; + UpdateResource(hEn,RT_STRING,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hExplorer,hResInfo)); + } + + // copy dialogs + for (int id=2000;id<2010;id++) + { + HRSRC hResInfo=FindResource(hExplorer,MAKEINTRESOURCE(id),RT_DIALOG); + if (!hResInfo) continue; + HGLOBAL hRes=LoadResource(hExplorer,hResInfo); + void *pRes=LockResource(hRes); + if (!pRes) continue; + UpdateResource(hEn,RT_DIALOG,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hExplorer,hResInfo)); + } + + // get strings and dialog from ClassicStartMenuDLL.dll + hMenu=LoadLibraryEx(params[2],NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (!hMenu) + { + Printf("Failed to open %S (err: %d)\n",params[2],GetLastError()); + goto qqq; + } + + // copy strings + for (int i=3000;i<5000;i+=16) + { + int id=i/16; + HRSRC hResInfo=FindResource(hMenu,MAKEINTRESOURCE(id),RT_STRING); + if (!hResInfo) continue; + HGLOBAL hRes=LoadResource(hMenu,hResInfo); + void *pRes=LockResource(hRes); + if (!pRes) continue; + UpdateResource(hEn,RT_STRING,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hMenu,hResInfo)); + } + for (int i=7000;i<8000;i+=16) + { + int id=i/16; + HRSRC hResInfo=FindResource(hMenu,MAKEINTRESOURCE(id),RT_STRING); + if (!hResInfo) continue; + HGLOBAL hRes=LoadResource(hMenu,hResInfo); + void *pRes=LockResource(hRes); + if (!pRes) continue; + UpdateResource(hEn,RT_STRING,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hMenu,hResInfo)); + } + + // copy dialogs + for (int id=3000;id<4010;id++) + { + HRSRC hResInfo=FindResource(hMenu,MAKEINTRESOURCE(id),RT_DIALOG); + if (!hResInfo) continue; + HGLOBAL hRes=LoadResource(hMenu,hResInfo); + void *pRes=LockResource(hRes); + if (!pRes) continue; + UpdateResource(hEn,RT_DIALOG,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hMenu,hResInfo)); + } + + // get strings from ClassicIEDLL.dll + hIE=LoadLibraryEx(params[3],NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (!hIE) + { + Printf("Failed to open %S (err: %d)\n",params[3],GetLastError()); + goto qqq; + } + + // copy strings + for (int i=5000;i<6000;i+=16) + { + int id=i/16; + HRSRC hResInfo=FindResource(hIE,MAKEINTRESOURCE(id),RT_STRING); + if (!hResInfo) continue; + HGLOBAL hRes=LoadResource(hIE,hResInfo); + void *pRes=LockResource(hRes); + if (!pRes) continue; + UpdateResource(hEn,RT_STRING,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hIE,hResInfo)); + } + + // get strings and dialog from ClassicShellUpdate.exe + hMenu=LoadLibraryEx(params[4],NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (!hMenu) + { + Printf("Failed to open %S (err: %d)\n",params[4],GetLastError()); + goto qqq; + } + + // copy strings + for (int i=6000;i<7000;i+=16) + { + int id=i/16; + HRSRC hResInfo=FindResource(hMenu,MAKEINTRESOURCE(id),RT_STRING); + if (!hResInfo) continue; + HGLOBAL hRes=LoadResource(hMenu,hResInfo); + void *pRes=LockResource(hRes); + if (!pRes) continue; + UpdateResource(hEn,RT_STRING,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hMenu,hResInfo)); + } + + // copy dialogs + for (int id=6000;id<6010;id++) + { + HRSRC hResInfo=FindResource(hMenu,MAKEINTRESOURCE(id),RT_DIALOG); + if (!hResInfo) continue; + HGLOBAL hRes=LoadResource(hMenu,hResInfo); + void *pRes=LockResource(hRes); + if (!pRes) continue; + UpdateResource(hEn,RT_DIALOG,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hMenu,hResInfo)); + } + + res=0; +qqq: + if (!EndUpdateResource(hEn,res!=0) && res==0) + { + Printf("Failed to update en-US.dll (err: %d)\n",GetLastError()); + res=1; + } + if (hExplorer) FreeLibrary(hExplorer); + if (hMenu) FreeLibrary(hMenu); + if (hIE) FreeLibrary(hIE); + + return res; +} + +/////////////////////////////////////////////////////////////////////////////// + +struct LanguageData +{ + std::map strings; + CString bitmap; +}; + +int GenerateUpdateFile( wchar_t *const *params, int count ) +{ + if (count<3) return 3; + + std::vector buf; + LoadFile(params[1],buf); + if (buf.empty()) return 1; + buf.push_back(0); + buf.push_back(0); + + wchar_t token[256]; + + std::map languages; + const int DEFAULT_LANGUAGE=0x409; + + const wchar_t *str0=(wchar_t*)&buf[0]; + if (*str0==0xFEFF) str0++; + const wchar_t *str; + + // old (current) version + str=wcsstr(str0,L"{OLD_VER}"); + if (!str) return 1; + GetToken(str+9,token,_countof(token),L"\r\n"); + int v1, v2, v3; + swscanf_s(token,L"%d.%d.%d",&v1,&v2,&v3); + + // new version + str=wcsstr(str0,L"{NEW_VER}"); + if (!str) return 1; + GetToken(str+9,token,_countof(token),L"\r\n"); + languages[DEFAULT_LANGUAGE].strings[IDS_VERSION]=token; + + // signer + str=wcsstr(str0,L"{SIGNER}"); + if (!str) return 1; + GetToken(str+8,token,_countof(token),L"\r\n"); + languages[DEFAULT_LANGUAGE].strings[IDS_INSTALL_SIGNER]=token; + + // update + str=wcsstr(str0,L"{UPDATE}"); + if (!str) return 1; + GetToken(str+8,token,_countof(token),L"\r\n"); + languages[DEFAULT_LANGUAGE].strings[IDS_UPDATE_LINK]=token; + + // languages + str=wcsstr(str0,L"{LANGUAGES}"); + if (!str) return 1; + GetToken(str+11,token,_countof(token),L"\r\n"); + languages[DEFAULT_LANGUAGE].strings[IDS_LANGUAGE_LINK]=token; + + // language folder + str=wcsstr(str0,L"{LANGFOLDER}"); + if (!str) return 1; + wchar_t langFolder[_MAX_PATH]; + GetToken(str+12,langFolder,_countof(langFolder),L"\r\n"); + + // alt url + str=wcsstr(str0,L"{ALT}"); + if (str) + { + GetToken(str+5,token,_countof(token),L"\r\n"); + languages[DEFAULT_LANGUAGE].strings[IDS_ALT_URL]=token; + } + + // news + str=wcsstr(str0,L"{NEWS}"); + if (!str) return 1; + languages[DEFAULT_LANGUAGE].strings[IDS_NEWS]=str+6; + + // look for {INST: + str=str0; + bool res=true; + while (1) + { + str=wcsstr(str,L"{INST: "); + res=true; + if (!str) break; + res=false; + str+=7; + str=GetToken(str,token,_countof(token),L"}\r\n"); + int language; + if (!GetLocaleInfoEx(token,LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER,(LPWSTR)&language,4)) + break; + str=GetToken(str,token,_countof(token),L"\r\n"); + languages[language].strings[IDS_INSTALL_URL]=token; + // languages[language].strings[IDS_VERSION]=...; // TODO: allow per-language version of the installer + } + + if (!res) return 1; + + str=str0; + while (1) + { + str=wcsstr(str,L"{LANG: "); + res=true; + if (!str) break; + res=false; + str+=7; + str=GetToken(str,token,_countof(token),L"}\r\n"); + int len=Strlen(token); + bool bBasic=(len>0 && token[len-1]=='*'); + if (bBasic) token[len-1]=0; + int language; + if (!GetLocaleInfoEx(token,LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER,(LPWSTR)&language,4)) + break; + + wchar_t fname[_MAX_PATH]; + Sprintf(fname,_countof(fname),L"%s\\%s.dll",langFolder,token); +/* if (GetFileAttributes(fname)==INVALID_FILE_ATTRIBUTES) + { + fname[0]=0; + wchar_t find[_MAX_PATH]; + Sprintf(find,_countof(find),L"%s\\*.*",langFolder); + WIN32_FIND_DATA data; + HANDLE h=FindFirstFile(find,&data); + while (h!=INVALID_HANDLE_VALUE) + { + if ((data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && data.cFileName[0]!='.') + { + Sprintf(fname,_countof(fname),L"%s\\%s\\%s.dll",langFolder,data.cFileName,token); + if (GetFileAttributes(fname)!=INVALID_FILE_ATTRIBUTES) + { + FindClose(h); + break; + } + } + if (!FindNextFile(h,&data)) + { + FindClose(h); + break; + } + } + }*/ + if (!fname[0]) break; + + unsigned long hash=0; + wchar_t version[100]; + + hash=CalcFileFNV(fname); + if (!hash) break; + + DWORD dllBuild; + DWORD dllVer=GetFileVersion(fname,&dllBuild); + if (!dllVer) break; + if (dllVer>(DWORD)((v1<<24)|(v2<<16)|v3)) break; + + Sprintf(version,_countof(version),L"%d.%d.%d.%d%s",dllVer>>24,(dllVer>>16)&255,dllVer&65535,dllBuild,bBasic?L"*":L""); + + Sprintf(token,_countof(token),L"%08X",hash); + languages[language].strings[IDS_LNG_CRC]=token; + + languages[language].strings[IDS_LNG_VERSION]=version; + str=GetToken(str,token,_countof(token),L"\r\n"); + languages[language].strings[IDS_LNG_URL]=token; + } + + if (!res) return 1; + + // look for {FLAG: + str=str0; + while (1) + { + str=wcsstr(str,L"{FLAG: "); + res=true; + if (!str) break; + res=false; + str+=7; + str=GetToken(str,token,_countof(token),L"}\r\n"); + int language; + if (!GetLocaleInfoEx(token,LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER,(LPWSTR)&language,4)) + break; + str=GetToken(str,token,_countof(token),L"\r\n"); + languages[language].bitmap=token; + } + + if (!res) return 1; + + FILE *f=NULL; + if (_wfopen_s(&f,params[2],L"wb") || !f) + { + return 1; + } + fwprintf(f,L"\xFEFF"); + for (std::map::const_iterator it=languages.begin();it!=languages.end();++it) + { + fwprintf(f,L"/////////////////////////////////////////////////////////////////////////////\r\n"); + GetLocaleInfo(it->first,LOCALE_SLANGUAGE,token,_countof(token)); + fwprintf(f,L"// %s\r\n\r\n",token); + fwprintf(f,L"LANGUAGE 0x%02X, 0x%X\r\n",it->first&0x3FF,it->first>>10); + fwprintf(f,L"\r\nSTRINGTABLE\r\nBEGIN\r\n"); + for (std::map::const_iterator it2=it->second.strings.begin();it2!=it->second.strings.end();++it2) + { + CString str=it2->second; + str.Replace(L"\r\n",L"\\r\\n"); + str.Replace(L"\"",L"\"\""); + fwprintf(f,L"%4d \"%s\"\r\n",it2->first,str); + } + fwprintf(f,L"END\r\n\r\n"); + + if (it->first==DEFAULT_LANGUAGE) + { + fwprintf(f,L"1 VERSIONINFO\r\n"); + fwprintf(f,L" FILEVERSION %d,%d,%d,0\r\n",v1,v2,v3); + fwprintf(f,L" PRODUCTVERSION %d,%d,%d,0\r\n",v1,v2,v3); + fwprintf(f,L" FILEFLAGSMASK 0x17L\r\n"); + fwprintf(f,L" FILEFLAGS 0x0L\r\n"); + fwprintf(f,L" FILEOS 0x4L\r\n"); + fwprintf(f,L" FILETYPE 0x1L\r\n"); + fwprintf(f,L" FILESUBTYPE 0x0L\r\n"); + fwprintf(f,L"BEGIN\r\n"); + fwprintf(f,L"\tBLOCK \"StringFileInfo\"\r\n"); + fwprintf(f,L"\tBEGIN\r\n"); + fwprintf(f,L"\t\tBLOCK \"040904b0\"\r\n"); + fwprintf(f,L"\t\tBEGIN\r\n"); + fwprintf(f,L"\t\t\tVALUE \"CompanyName\", \"IvoSoft\"\r\n"); + fwprintf(f,L"\t\t\tVALUE \"FileDescription\", \"Update information\"\r\n"); + fwprintf(f,L"\t\t\tVALUE \"FileVersion\", \"%d, %d, %d, 0\"\r\n",v1,v2,v3); + fwprintf(f,L"\t\t\tVALUE \"InternalName\", \"Update\"\r\n"); + fwprintf(f,L"\t\t\tVALUE \"LegalCopyright\", \"Copyright (C) 2009-2016, Ivo Beltchev\"\r\n"); + fwprintf(f,L"\t\t\tVALUE \"OriginalFilename\", \"update.ver\"\r\n"); + fwprintf(f,L"\t\t\tVALUE \"ProductName\", \"Classic Shell\"\r\n"); + fwprintf(f,L"\t\t\tVALUE \"ProductVersion\", \"%d, %d, %d, 0\"\r\n",v1,v2,v3); + fwprintf(f,L"\t\tEND\r\n"); + fwprintf(f,L"\tEND\r\n"); + fwprintf(f,L"\tBLOCK \"VarFileInfo\"\r\n"); + fwprintf(f,L"\tBEGIN\r\n"); + fwprintf(f,L"\t\tVALUE \"Translation\", 0x409, 1200\r\n"); + fwprintf(f,L"\tEND\r\n"); + fwprintf(f,L"END\r\n\r\n"); + + for (std::map::const_iterator it3=languages.begin();it3!=languages.end();++it3) + { + if (!it3->second.bitmap.IsEmpty()) + fwprintf(f,L"%d BITMAP \"%s\"\r\n",it3->first,it3->second.bitmap); + } + fwprintf(f,L"\r\n"); + } + } + fclose(f); + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +static void UnsescapeString( wchar_t *string ) +{ + wchar_t *dst=string; + int len=Strlen(string); + bool bQuoted=false; + if (string[0]=='"' && string[len-1]=='"') + { + bQuoted=true; + string[len-1]=0; + if (*string) string++; + } + + for (const wchar_t *src=string;*src;src++) + { + if (*src=='\\') + { + src++; + if (!*src) break; + if (*src=='t') + *dst++='\t'; + else if (*src=='r') + *dst++='\r'; + else if (*src=='n') + *dst++='\n'; + else + *dst++=*src; + } + else if (*src=='"' && bQuoted) + { + src++; + if (!*src) break; + *dst++=*src; + } + else + *dst++=*src; + } + *dst=0; +} + +static void WriteString( HANDLE csv, int id, const wchar_t *string1, int len1, const wchar_t *string2, int len2, CSettingsParser &parser, int subid=INT_MAX ) +{ + DWORD q; + wchar_t buf[256]; + int len3; + if (subid!=INT_MAX) + len3=Sprintf(buf,_countof(buf),L"%d/%d",id,subid&65535); + else + len3=Sprintf(buf,_countof(buf),L"%d",id); + + const wchar_t *comment=parser.FindSetting(buf); + if (comment && _wcsicmp(comment,L"ignore")==0) + return; + + WriteFile(csv,buf,len3*2,&q,NULL); + WriteFile(csv,L"\t",2,&q,NULL); + + for (int i=0;iflags&=~SWP_SHOWWINDOW; + } + return FALSE; +} + +static void WriteDialog( HWND parent, HANDLE csv, int id, HINSTANCE hInstance1, const DLGTEMPLATE *pTemplate1, HINSTANCE hInstance2, const DLGTEMPLATE *pTemplate2, CSettingsParser &parser ) +{ + HWND dlg1=CreateDialogIndirect(hInstance1,pTemplate1,parent,DefaultDlgProc); + if (dlg1) + { + HWND dlg2=pTemplate2?CreateDialogIndirect(hInstance2,pTemplate2,parent,DefaultDlgProc):NULL; + + wchar_t text1[1024]; + wchar_t text2[1024]; + GetWindowText(dlg1,text1,_countof(text1)); + if (*text1) + { + if (dlg2) + GetWindowText(dlg2,text2,_countof(text2)); + else + text2[0]=0; + WriteString(csv,id,text1,Strlen(text1),text2,Strlen(text2),parser,0); + } + for (HWND child1=GetWindow(dlg1,GW_CHILD);child1;child1=GetWindow(child1,GW_HWNDNEXT)) + { + GetWindowText(child1,text1,_countof(text1)); + if (*text1) + { + int childId=(int)GetWindowLong(child1,GWL_ID); + HWND child2=dlg2?GetDlgItem(dlg2,childId):NULL; + if (child2) + GetWindowText(child2,text2,_countof(text2)); + else + text2[0]=0; + WriteString(csv,id,text1,Strlen(text1),text2,Strlen(text2),parser,childId); + } + } + DestroyWindow(dlg1); + if (dlg2) + DestroyWindow(dlg2); + } +} + +int ExtractStrings( wchar_t *const *params, int count ) +{ + if (count<3) return 3; + + const wchar_t *dllName1=params[1]; + const wchar_t *dllName2=NULL; + const wchar_t *csvName=params[2]; + if (count>3) + { + dllName2=csvName; + csvName=params[3]; + } + + + HMODULE hDLL1=LoadLibraryEx(dllName1,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (!hDLL1) + { + Printf("Failed to open %S (err: %d)\n",dllName1,GetLastError()); + return 1; + } + + HMODULE hDLL2=NULL; + if (dllName2) + { + hDLL2=LoadLibraryEx(dllName2,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (!hDLL2) + { + Printf("Failed to open %S (err: %d)\n",dllName2,GetLastError()); + return 1; + } + } + + int res=1; + CSettingsParser parser; + parser.LoadText(L"LocComments.txt"); + parser.ParseText(); + + HANDLE hCSV=CreateFile(csvName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); + if (hCSV==INVALID_HANDLE_VALUE) + { + Printf("Failed to write %S\n",csvName); + FreeLibrary(hDLL1); + if (hDLL2) FreeLibrary(hDLL2); + return 1; + } + + wchar_t title[]=L"\xFEFFID\tEnglish\tTranslation\tComment\r\n"; + DWORD q; + WriteFile(hCSV,title,Strlen(title)*2,&q,NULL); + + // copy strings + for (int i=2000;i<8000;i+=16) + { + int id=i/16; + HRSRC hResInfo=FindResource(hDLL1,MAKEINTRESOURCE(id),RT_STRING); + if (!hResInfo) continue; + HGLOBAL hRes=LoadResource(hDLL1,hResInfo); + void *pRes=LockResource(hRes); + if (!pRes) continue; + const WORD *data=(WORD*)pRes; + for (int j=0;j<16;j++) + { + int len=*data; + if (len>0) + { + int stringId=(id-1)*16+j; + wchar_t buf[1024]; + if (!hDLL2 || !LoadString(hDLL2,stringId,buf,_countof(buf))) + buf[0]=0; + WriteString(hCSV,stringId,(const wchar_t*)data+1,len,buf,Strlen(buf),parser); + } + data+=len+1; + } + } + + HWND parent=CreateWindow(L"button",NULL,WS_POPUP,0,0,10,10,NULL,NULL,NULL,NULL); + + // copy dialogs + for (int id=2000;id<7000;id++) + { + if (id>=2010 && id<3000) continue; + if (id>=3010 && id<4000) continue; + if (id>=4010 && id<5000) continue; + if (id>=5010 && id<6000) continue; + if (id>=6010 && id<7000) continue; + HRSRC hResInfo1=FindResource(hDLL1,MAKEINTRESOURCE(id),RT_DIALOG); + if (!hResInfo1) continue; + void *pRes1=LockResource(LoadResource(hDLL1,hResInfo1)); + if (!pRes1) continue; + + void *pRes2=NULL; + if (hDLL2) + { + HRSRC hResInfo2=FindResource(hDLL2,MAKEINTRESOURCE(id),RT_DIALOG); + if (hResInfo2) + pRes2=LockResource(LoadResource(hDLL2,hResInfo2)); + } + + WriteDialog(parent,hCSV,id,hDLL1,(DLGTEMPLATE*)pRes1,hDLL2,(DLGTEMPLATE*)pRes2,parser); + } + + // additional strings + { + HRSRC hResInfo=FindResource(hDLL1,MAKEINTRESOURCE(1),L"L10N"); + if (hResInfo) + { + HGLOBAL hRes=LoadResource(hDLL1,hResInfo); + const wchar_t *pRes=(wchar_t*)LockResource(hRes); + if (pRes) + { + int size=SizeofResource(hDLL1,hResInfo)/2; + if (*pRes==L'\xFEFF') + pRes++, size--; + wchar_t *pBuf=new wchar_t[size+1]; + memcpy(pBuf,pRes,size*2); + pBuf[size]=0; + for (int i=0;i> &oldStrings=*(std::vector>*)lParam; + oldStrings.push_back(std::pair(PtrToInt(lpszName),wIDLanguage)); + } + return TRUE; +} + +static BOOL CALLBACK EnumResNameProc( HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam ) +{ + EnumResourceLanguages(hModule,lpszType,lpszName,EnumResLangProc,lParam); + return TRUE; +} + +static int ImportStrings( wchar_t *const *params, int count ) +{ + if (count<3) return 3; + const wchar_t *dllName=params[1]; + const wchar_t *csvName=params[2]; + + HANDLE hCSV=CreateFile(csvName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + if (hCSV==INVALID_HANDLE_VALUE) + { + Printf("Failed to read %S\n",csvName); + return 1; + } + + int size=SetFilePointer(hCSV,0,NULL,FILE_END)/2; + SetFilePointer(hCSV,0,NULL,FILE_BEGIN); + std::vector buf(size+1); + DWORD q; + ReadFile(hCSV,&buf[0],size*2,&q,NULL); + CloseHandle(hCSV); + buf[size]=0; + for (int i=0;i lines; + wchar_t *str=&buf[0]; + int min=100000, max=0; + while (str<&buf[size]) + { + int len=Strlen(str); + wchar_t *next=str+len+1; + wchar_t *tab=wcschr(str,'\t'); + if (tab) + { + *tab=0; + int id=_wtol(str); + bool bNumber=id>0; + for (;*str;str++) + if (*str<'0' || *str>'9') + { + bNumber=false; + break; + } + if (bNumber) + { + tab=wcschr(tab+1,'\t'); + if (tab) + { + str=tab+1; + tab=wcschr(str,'\t'); + if (tab) *tab=0; + if (lines.find(id)!=lines.end()) + { + Printf("Duplicate string ID %d\n",id); + return 1; + } + UnsescapeString(str); + lines[id]=str; + if (min>id) min=id; + if (max> oldStrings; + EnumResourceNames(hDll,RT_STRING,EnumResNameProc,(LONG_PTR)&oldStrings); + FreeLibrary(hDll); + + HANDLE hUpdate=BeginUpdateResource(dllName,FALSE); + if (!hUpdate) + { + Printf("Failed to open %S (err: %d)\n",dllName,GetLastError()); + return 1; + } + + // delete all string resources + for (int i=0;i<(int)oldStrings.size();i++) + { + UpdateResource(hUpdate,RT_STRING,MAKEINTRESOURCE(oldStrings[i].first),oldStrings[i].second,NULL,0); + } + + // add new string lines + max+=32; + for (int i=min;i res; + for (int j=0;j<16;j++,idx++) + { + std::map::const_iterator it=lines.find(idx); + const wchar_t *str=L""; + if (it!=lines.end()) + str=it->second; + int len=Strlen(str); + res.push_back((wchar_t)len); + for (int c=0;c16) + UpdateResource(hUpdate,RT_STRING,MAKEINTRESOURCE(id),LANG_NEUTRAL,&res[0],res.size()*2); + } + + if (!EndUpdateResource(hUpdate,FALSE)) + { + Printf("Failed to update %S (err: %d)\n",dllName,GetLastError()); + return 1; + } + return 0; +} +#endif + +/////////////////////////////////////////////////////////////////////////////// + +static HRESULT CALLBACK TaskDialogCallback( HWND hwnd, UINT uNotification, WPARAM wParam, LPARAM lParam, LONG_PTR dwRefData ) +{ + if (uNotification==TDN_HYPERLINK_CLICKED) + { + const wchar_t *link=(const wchar_t*)lParam; + ShellExecute(hwnd,NULL,link,NULL,NULL,SW_SHOWNORMAL); + } + return S_OK; +} + +/////////////////////////////////////////////////////////////////////////////// + +// Classic Shell utility - multiple utilities for building and maintaining Classic Shell +// Usage: +// no parameters - saves a troubleshooting log +// crcmsi // creates a file with checksum of both msi files +// makeEN // extracts the localization resources and creates a sample en-US.DLL +// extract // extracts the string table, the dialog text, and the L10N text from a DLL and stores it in a CSV +// extract en-us.dll // extracts the string table, the dialog text, and the L10N text from two DLL and stores it in a CSV +// import // replaces the string table in the DLL with the text from the CSV +// update // generates a resource file for UpdateBin.dll by calculating the DLL hashes + +int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstrCmdLine, int nCmdShow ) +{ + g_hInstance=hInstance; + + if (!*lpstrCmdLine) + { +#ifndef _WIN64 + DWORD winVer=GetVersionEx(GetModuleHandle(L"user32.dll")); + + TASKDIALOG_BUTTON taskButtons[4]={ + {101,L"Save system log\nSaves detailed information about your system for troubleshooting purposes."}, + {102,L"Classic Shell logging options\nEnable or disable various logging options."}, + {103,L"Remove Classic Shell\nManually removes Classic Shell from your system. Use only if the conventional methods for uninstallation do not work."}, + {104,L"Show Metro colors\nSee the color palette that can be used in start menu skins."}, + }; + TASKDIALOGCONFIG tasks={sizeof(tasks)}; + tasks.dwFlags=TDF_USE_HICON_MAIN|TDF_USE_COMMAND_LINKS|TDF_ENABLE_HYPERLINKS; + tasks.dwCommonButtons=TDCBF_CANCEL_BUTTON; + tasks.pszWindowTitle=L"Classic Shell Utility"; + tasks.hMainIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1)); + tasks.pszMainInstruction=L"Select task to perform"; + tasks.cButtons=HIWORD(winVer)>=0x0602?4:3; + tasks.pButtons=taskButtons; + tasks.pszFooter=L"www.classicshell.net"; + tasks.pfCallback=TaskDialogCallback; + + int seleciton; + if (TaskDialogIndirect(&tasks,&seleciton,NULL,NULL)==IDCANCEL) + return 0; + if (seleciton==101) + { + ShowSaveLogFile(); + } + else if (seleciton==102) + { + EditLoggingOptions(); + } + else if (seleciton==103) + { + wchar_t exe[_MAX_PATH]; + GetModuleFileName(NULL,exe,_countof(exe)); + CoInitialize(NULL); + ShellExecute(NULL,L"runas",exe,L"uninstall",NULL,SW_SHOWNORMAL); + CoUninitialize(); + } + else if (seleciton==104) + { + ShowMetroColorViewer(); + } +#endif + return 0; + } + + int count; + wchar_t *const *params=CommandLineToArgvW(lpstrCmdLine,&count); + +#ifndef _WIN64 + if (_wcsicmp(params[0],L"crcmsi")==0) + { + return CalcMsiChecksum(params,count); + } + + if (_wcsicmp(params[0],L"makeEN")==0) + { + return MakeEnglishDll(params,count); + } + + if (_wcsicmp(params[0],L"extract")==0) + { + return ExtractStrings(params,count); + } + + if (_wcsicmp(params[0],L"import")==0) + { + return ImportStrings(params,count); + } + + if (_wcsicmp(params[0],L"update")==0) + { + return GenerateUpdateFile(params,count); + } + + if (_wcsicmp(params[0],L"colors")==0) + { + ShowMetroColorViewer(); + return 0; + } + if (_wcsicmp(params[0],L"uninstall")==0) + { + ManualUninstall(); + return 0; + } +#endif + + if (_wcsicmp(params[0],L"savelog")==0 || _wcsicmp(params[0],L"saveloga")==0) + { + if (count<=1) + return 1; + return SaveLogFile(params[1],_wcsicmp(params[0],L"saveloga")==0); + } + + return 1; +} diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ClassicShellUtility.manifest b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ClassicShellUtility.manifest new file mode 100644 index 0000000..79871e0 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ClassicShellUtility.manifest @@ -0,0 +1,27 @@ + + + +Classic Shell Setup + + + + + + + + true + + + diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ClassicShellUtility.rc b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ClassicShellUtility.rc new file mode 100644 index 0000000..1ab14f9 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ClassicShellUtility.rc @@ -0,0 +1,224 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// FILE +// + +1 FILE "Release64\\ClassicShellUtility.exe" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON "tool.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_COLORS DIALOGEX 0, 0, 407, 281 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU +CAPTION "Metro Colors" +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + LTEXT "Color set:",IDC_STATIC,7,7,31,14,SS_CENTERIMAGE + EDITTEXT IDC_EDIT1,39,7,47,14,ES_AUTOHSCROLL + CONTROL "",IDC_SPIN1,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,79,7,10,14 + LTEXT "use -1 for the current set",IDC_STATIC,90,7,79,14,SS_CENTERIMAGE + LTEXT "Search:",IDC_STATIC,215,7,24,14,SS_CENTERIMAGE + EDITTEXT IDC_EDIT2,240,7,160,14,ES_AUTOHSCROLL + CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_EDITLABELS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,23,393,251 +END + +IDD_UNINSTALL DIALOGEX 0, 0, 315, 201 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Remove Classic Shell" +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,67,301,1 + LTEXT "The tool has determined that Classic Shell is installed in the following folder. If this is incorrect, use the Browse button to pick another location.",IDC_STATICPATH,7,72,301,19 + EDITTEXT IDC_EDITPATH,7,93,262,14,ES_AUTOHSCROLL | ES_READONLY + PUSHBUTTON "Browse",IDC_BUTTONBROWSEPATH,270,93,38,14 + LTEXT "Select which settings to remove:\n (it is safe to keep the settings - they will not affect the operation of your computer)",IDC_STATIC,7,113,277,17 + CONTROL "Remove admin settings - will remove the settings from the Local Machine registry",IDC_CHECKADMIN, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,132,274,10 + CONTROL "Remove user settings - will remove the settings for the current user",IDC_CHECKSETTINGS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,144,233,10 + CONTROL "Remove settings for all users - will remove the user settings for all users",IDC_CHECKALLUSERS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,156,236,10 + LTEXT "Please, make sure that no other users are currently signed in",IDC_STATICALLUSERS,41,167,203,8,NOT WS_VISIBLE + DEFPUSHBUTTON "OK",IDOK,205,180,50,14 + PUSHBUTTON "Cancel",IDCANCEL,258,180,50,14 + LTEXT "Warning: This tool will remove Classic Shell from your system by directly accessing the registry and the file system. A reboot may be required.\nUse it only if you have tried the conventional methods for uinstalling Classic Shell and they were unsuccessful.",IDC_STATICWARNING,7,7,301,35 + CONTROL "The preferred method for uninstallation is to use the Programs and Features page in the Control Panel.",IDC_SYSLINK1, + "SysLink",WS_TABSTOP,7,44,301,18 +END + +IDD_UNINSTALL_RESULTS DIALOGEX 0, 0, 471, 302 +STYLE DS_SETFONT | DS_CENTER | WS_POPUP | WS_CAPTION | WS_THICKFRAME +CAPTION "Remove Classic Shell" +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + LTEXT "Static",IDC_STATICRESULT,7,7,457,25 + EDITTEXT IDC_EDITRESULT,7,39,457,238,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL + PUSHBUTTON "Restart Now",IDC_BUTTONREBOOT,319,281,70,14 + PUSHBUTTON "Close",IDC_BUTTONCLOSE,394,281,70,14 +END + +IDD_UNINSTALL_PROGRESS DIALOGEX 0, 0, 240, 75 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "Removing Classic Shell" +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + CONTROL "",IDC_PROGRESS1,"msctls_progress32",WS_BORDER,7,27,226,14 + LTEXT "Please, wait...",IDC_STATICWAIT,7,7,83,8 +END + +IDD_LOGSETTINGS DIALOGEX 0, 0, 201, 245 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Classic Shell Logging" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Warning: Turning on the logging options may negatively affect the performance of Classic Shell.",IDC_STATIC,7,7,187,17 + LTEXT "Log start menu",IDC_STATIC,7,31,52,12,SS_CENTERIMAGE + CONTROL "Open/close menus",IDC_CHECKOPEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,44,75,10 + CONTROL "Menu contents",IDC_CHECKITEMS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,107,44,63,10 + CONTROL "Executed items",IDC_CHECKEXECUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,58,65,10 + CONTROL "MFU items",IDC_CHECKMFU,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,107,58,49,10 + CONTROL "New programs",IDC_CHECKNEW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,72,62,10 + CONTROL "Metro apps",IDC_CHECKAPPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,107,72,52,10 + CONTROL "Search results",IDC_CHECKSEARCH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,86,61,10 + CONTROL "SQL commands",IDC_CHECKSEARCH_SQL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,107,86,64,10 + CONTROL "Mouse events",IDC_CHECKMOUSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,100,61,10 + CONTROL "Data cache",IDC_CHECKCACHE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,107,100,52,10 + CONTROL "Start menu log file",IDC_SYSLINKSTART,"SysLink",WS_TABSTOP,22,113,80,10 + CONTROL "Data cache log file",IDC_SYSLINKCACHE,"SysLink",WS_TABSTOP,22,125,80,10 + CONTROL "Log startup",IDC_CHECKSTARTUP,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,7,140,57,12 + CONTROL "Startup log file",IDC_SYSLINKSTARTUP,"SysLink",WS_TABSTOP,22,153,80,10 + CONTROL "Log Classic Explorer",IDC_CHECKEXPLORER,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,7,167,84,12 + CONTROL "Classic Explorer log file",IDC_SYSLINKEXPLORER, + "SysLink",WS_TABSTOP,22,180,80,10 + CONTROL "Log Classic IE",IDC_CHECKIE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,7,194,65,12 + CONTROL "Classic IE log file",IDC_SYSLINKIE,"SysLink",WS_TABSTOP,22,207,80,10 + DEFPUSHBUTTON "OK",IDOK,85,224,50,14 + PUSHBUTTON "Cancel",IDCANCEL,144,224,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_COLORS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 400 + TOPMARGIN, 7 + BOTTOMMARGIN, 274 + END + + IDD_UNINSTALL, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 308 + TOPMARGIN, 7 + BOTTOMMARGIN, 194 + END + + IDD_UNINSTALL_RESULTS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 464 + TOPMARGIN, 7 + BOTTOMMARGIN, 295 + END + + IDD_UNINSTALL_PROGRESS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 233 + TOPMARGIN, 7 + BOTTOMMARGIN, 68 + END + + IDD_LOGSETTINGS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 194 + TOPMARGIN, 7 + BOTTOMMARGIN, 238 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ClassicShellUtility.vcproj b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ClassicShellUtility.vcproj new file mode 100644 index 0000000..6eea497 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ClassicShellUtility.vcproj @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/LoggingOptions.cpp b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/LoggingOptions.cpp new file mode 100644 index 0000000..890d221 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/LoggingOptions.cpp @@ -0,0 +1,225 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#ifndef _WIN64 + +#include "resource.h" +#include +#include +#include +#include +#include "..\ClassicStartMenu\ClassicStartMenuDLL\LogManager.h" +#include "StringUtils.h" +#include + +static int g_MenuCheckboxes[][2]= +{ + {IDC_CHECKOPEN, LOG_OPEN}, + {IDC_CHECKITEMS, LOG_ITEMS}, + {IDC_CHECKEXECUTE, LOG_EXECUTE}, + {IDC_CHECKMFU, LOG_MFU}, + {IDC_CHECKNEW, LOG_NEW}, + {IDC_CHECKAPPS, LOG_APPS}, + {IDC_CHECKSEARCH, LOG_SEARCH}, + {IDC_CHECKSEARCH_SQL, LOG_SEARCH_SQL}, + {IDC_CHECKMOUSE, LOG_MOUSE}, + {IDC_CHECKCACHE, LOG_CACHE}, +}; + +static int g_FileLinks[]= +{ + IDC_SYSLINKSTART, + IDC_SYSLINKCACHE, + IDC_SYSLINKSTARTUP, + IDC_SYSLINKEXPLORER, + IDC_SYSLINKIE, +}; + +class CLoggingDialog: public CDialogImpl +{ +public: + CLoggingDialog( void ) {} + + BEGIN_MSG_MAP( CLoggingDialog ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + COMMAND_HANDLER( IDOK, BN_CLICKED, OnOK ) + COMMAND_HANDLER( IDCANCEL, BN_CLICKED, OnCancel ) + NOTIFY_HANDLER( IDC_SYSLINKSTART, NM_CLICK, OnLink ) + NOTIFY_HANDLER( IDC_SYSLINKSTART, NM_RETURN, OnLink ) + NOTIFY_HANDLER( IDC_SYSLINKCACHE, NM_CLICK, OnLink ) + NOTIFY_HANDLER( IDC_SYSLINKCACHE, NM_RETURN, OnLink ) + NOTIFY_HANDLER( IDC_SYSLINKSTARTUP, NM_CLICK, OnLink ) + NOTIFY_HANDLER( IDC_SYSLINKSTARTUP, NM_RETURN, OnLink ) + NOTIFY_HANDLER( IDC_SYSLINKEXPLORER, NM_CLICK, OnLink ) + NOTIFY_HANDLER( IDC_SYSLINKEXPLORER, NM_RETURN, OnLink ) + NOTIFY_HANDLER( IDC_SYSLINKIE, NM_CLICK, OnLink ) + NOTIFY_HANDLER( IDC_SYSLINKIE, NM_RETURN, OnLink ) + REFLECT_NOTIFICATIONS() + END_MSG_MAP() + + enum { IDD=IDD_LOGSETTINGS }; + +protected: + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnLink( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + +private: + DWORD GetSetting( const wchar_t *regPath, const wchar_t *name ); + void SetSetting( const wchar_t *regPath, const wchar_t *name, DWORD value ); + CString GetPathForLink( int link ); +}; + +DWORD CLoggingDialog::GetSetting( const wchar_t *regPath, const wchar_t *name ) +{ + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,regPath,KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + DWORD value; + if (regKey.QueryDWORDValue(name,value)==ERROR_SUCCESS) + return value; + } + return 0; +} + +void CLoggingDialog::SetSetting( const wchar_t *regPath, const wchar_t *name, DWORD value ) +{ + CRegKey regKey; + if (regKey.Create(HKEY_CURRENT_USER,regPath)==ERROR_SUCCESS) + regKey.SetDWORDValue(name,value); +} + +CString CLoggingDialog::GetPathForLink( int link ) +{ + const wchar_t *path=NULL; + if (link==IDC_SYSLINKSTART) + path=L"%LOCALAPPDATA%\\ClassicShell\\StartMenuLog.txt"; + else if (link==IDC_SYSLINKCACHE) + path=L"%LOCALAPPDATA%\\ClassicShell\\DataCache.txt"; + else if (link==IDC_SYSLINKSTARTUP) + path=L"%LOCALAPPDATA%\\ClassicShell\\StartupLog.txt"; + else if (link==IDC_SYSLINKEXPLORER) + path=L"%LOCALAPPDATA%\\ClassicShell\\ExplorerLog.txt"; + else if (link==IDC_SYSLINKIE) + path=L"%LOCALAPPDATA%\\ClassicShell\\ClassicIELog.txt"; + else + return CString(); + + wchar_t fname[_MAX_PATH]; + Strcpy(fname,_countof(fname),path); + DoEnvironmentSubst(fname,_countof(fname)); + return fname; +} + +LRESULT CLoggingDialog::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + DWORD log=GetSetting(L"Software\\IvoSoft\\ClassicStartMenu\\Settings",L"LogCategories"); + for (int i=0;i<_countof(g_MenuCheckboxes);i++) + { + if (log&g_MenuCheckboxes[i][1]) + CheckDlgButton(g_MenuCheckboxes[i][0],BST_CHECKED); + } + + log=GetSetting(L"Software\\IvoSoft\\ClassicStartMenu\\Settings",L"LogStartup"); + if (log) + CheckDlgButton(IDC_CHECKSTARTUP,BST_CHECKED); + + log=GetSetting(L"Software\\IvoSoft\\ClassicExplorer\\Settings",L"LogLevel"); + if (log) + CheckDlgButton(IDC_CHECKEXPLORER,BST_CHECKED); + + log=GetSetting(L"Software\\IvoSoft\\ClassicIE\\Settings",L"LogLevel"); + if (log) + CheckDlgButton(IDC_CHECKIE,BST_CHECKED); + + CWindow tooltip; + tooltip.Create(TOOLTIPS_CLASS,m_hWnd,NULL,NULL,WS_POPUP|TTS_NOPREFIX); + for (int i=0;i<_countof(g_FileLinks);i++) + { + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS|TTF_IDISHWND,m_hWnd,(UINT_PTR)GetDlgItem(g_FileLinks[i]).m_hWnd}; + CString str=GetPathForLink(g_FileLinks[i]); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + } + + return TRUE; +} + +LRESULT CLoggingDialog::OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + int res=0; + DWORD log=0; + for (int i=0;i<_countof(g_MenuCheckboxes);i++) + { + if (IsDlgButtonChecked(g_MenuCheckboxes[i][0])==BST_CHECKED) + log|=g_MenuCheckboxes[i][1]; + } + if (log!=GetSetting(L"Software\\IvoSoft\\ClassicStartMenu\\Settings",L"LogCategories")) + { + SetSetting(L"Software\\IvoSoft\\ClassicStartMenu\\Settings",L"LogCategories",log); + res=1; + } + + log=IsDlgButtonChecked(IDC_CHECKSTARTUP)==BST_CHECKED?1:0; + if (log!=GetSetting(L"Software\\IvoSoft\\ClassicStartMenu\\Settings",L"LogStartup")) + { + SetSetting(L"Software\\IvoSoft\\ClassicStartMenu\\Settings",L"LogStartup",log); + res=1; + } + + log=IsDlgButtonChecked(IDC_CHECKEXPLORER)==BST_CHECKED?1:0; + if (log!=GetSetting(L"Software\\IvoSoft\\ClassicExplorer\\Settings",L"LogLevel")) + { + SetSetting(L"Software\\IvoSoft\\ClassicExplorer\\Settings",L"LogLevel",log); + res=1; + } + + log=IsDlgButtonChecked(IDC_CHECKIE)==BST_CHECKED?1:0; + if (log!=GetSetting(L"Software\\IvoSoft\\ClassicIE\\Settings",L"LogLevel")) + { + SetSetting(L"Software\\IvoSoft\\ClassicIE\\Settings",L"LogLevel",log); + res=1; + } + + EndDialog(res); + return 0; +} + +LRESULT CLoggingDialog::OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + EndDialog(0); + return 0; +} + +LRESULT CLoggingDialog::OnLink( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + CString path=GetPathForLink(idCtrl); + if (!path.IsEmpty()) + { + PIDLIST_ABSOLUTE pidl; + if (SUCCEEDED(SHParseDisplayName(path,NULL,&pidl,0,NULL))) + { + HRESULT hr=SHOpenFolderAndSelectItems(pidl,0,NULL,0); + ILFree(pidl); + } + else + { + wchar_t dir[_MAX_PATH]; + Strcpy(dir,_countof(dir),path); + PathRemoveFileSpec(dir); + ShellExecute(NULL,L"open",dir,NULL,dir,SW_SHOWNORMAL); + } + } + return 0; +} + +void EditLoggingOptions( void ) +{ + if (CLoggingDialog().DoModal(NULL)) + { + MessageBox(NULL,L"The changes to the logging options will take effect after you restart.",L"Logging options",MB_OK|MB_ICONINFORMATION); + } +} + +#endif diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ManualUninstall.cpp b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ManualUninstall.cpp new file mode 100644 index 0000000..fd9db19 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/ManualUninstall.cpp @@ -0,0 +1,1195 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#ifndef _WIN64 + +#define STRICT_TYPED_ITEMIDS +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +#include "resource.h" +#include +#include +#include +#include +#include +#include "ResourceHelper.h" +#include "ComHelper.h" +#include "StringUtils.h" +#include "SettingsUIHelper.h" +#include +#include "..\ClassicStartMenu\ClassicStartMenuDLL\ClassicStartMenuDLL.h" + +#define EXPLORER_CLSID L"{ECD4FC4D-521C-11D0-B792-00A0C90312E1}" +#define EMULATION_KEY L"TreatAs" + + +//#define SAFE_MODE + +#ifdef SAFE_MODE +#define RegDeleteTree2(x,y) 5 +#define RegDeleteValue2(x,y) 5 +#define DeleteFile2(x) (SetLastError(3), FALSE) +#define MoveFileEx2(x,y,z) (SetLastError(5), FALSE) +#define SHFileOperation2(x) 0x78 +#define RemoveDirectory2(x) FALSE +#else +#define RegDeleteTree2(x,y) RegDeleteTree(x,y) +#define RegDeleteValue2(x,y) RegDeleteValue(x,y) +#define DeleteFile2(x) DeleteFile(x) +#define MoveFileEx2(x,y,z) MoveFileEx(x,y,z) +#define SHFileOperation2(x) SHFileOperation(x) +#define RemoveDirectory2(x) RemoveDirectory(x) +#endif + +// files to delete from the Classic Shell folder +static const wchar_t *g_InstalledFiles[]= +{ + L"ClassicExplorer32.dll", + L"ClassicExplorer64.dll", + L"ClassicExplorerSettings.exe", + L"ClassicIEDLL_32.dll", + L"ClassicIEDLL_64.dll", + L"ClassicIE_32.exe", + L"ClassicIE_64.exe", + L"ClassicShell.chm", + L"ClassicShellReadme.rtf", + L"ClassicShellUpdate.exe", + L"ClassicStartMenu.exe", + L"ClassicStartMenuDLL.dll", + L"ExplorerL10N.ini", + L"HISTORY.txt", + L"IE Settings.lnk", + L"PolicyDefinitions.zip", + L"Start Menu Settings.lnk", + L"Start Screen.lnk", + L"StartMenuHelperL10N.ini", + L"StartMenuL10N.ini", + + L"de-DE.dll", + L"fr-FR.dll", + L"it-IT.dll", + L"pl-PL.dll", + L"ru-RU.dll", + L"zh-CN.dll", + L"zh-TW.dll", +}; + +// skin files to delete from the Classic Shell\Skins folder +static const wchar_t *g_InstalledSkins[]= +{ + L"Classic Skin.skin", + L"Classic Skin.skin7", + L"Full Glass.skin", + L"Metallic.skin7", + L"Metro.skin", + L"Metro.skin7", + L"Midnight.skin7", + L"Smoked Glass.skin", + L"Windows 8.skin", + L"Windows 8.skin7", + L"Windows Aero.skin", + L"Windows Aero.skin7", + L"Windows Basic.skin", + L"Windows XP Luna.skin", +}; + +// shortcuts to delete from the Programs\Classic Shell folder +static const wchar_t *g_InstalledShortcuts[]= +{ + L"Classic Explorer Settings.lnk", + L"Classic IE Settings.lnk", + L"Classic Shell Help.lnk", + L"Classic Shell Readme.lnk", + L"Classic Shell Update.lnk", + L"Classic Start Menu Settings.lnk", +}; + +// files to delete from the LOCALAPPDATA folder +static const wchar_t *g_LocalFiles[]= +{ + L"StartupLog.txt", + L"UpdateLog.txt", + L"ClassicIELog.txt", + L"StartMenuLog.txt", + L"DataCache.db", +}; + +// files to delete from the ALLUSERSPROFILE folder +static const wchar_t *g_ProgramDataFiles[]= +{ + L"update.ver", +}; + +/////////////////////////////////////////////////////////////////////////////// + +static bool DirectoryExists( const wchar_t *directory ) +{ + DWORD attrib=GetFileAttributes(directory); + return (attrib!=INVALID_FILE_ATTRIBUTES && (attrib&FILE_ATTRIBUTE_DIRECTORY)); +} + +static bool FileExists( const wchar_t *fname ) +{ + return GetFileAttributes(fname)!=INVALID_FILE_ATTRIBUTES; +} + +/////////////////////////////////////////////////////////////////////////////// + +class CUninstallDlg: public CDialogImpl +{ +public: + BEGIN_MSG_MAP( CUninstallDlg ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + MESSAGE_HANDLER( WM_CTLCOLORSTATIC, OnColorStatic ) + COMMAND_HANDLER( IDCANCEL, BN_CLICKED, OnCancel ) + COMMAND_HANDLER( IDOK, BN_CLICKED, OnOK ) + COMMAND_HANDLER( IDC_BUTTONBROWSEPATH, BN_CLICKED, OnBrowse ) + COMMAND_HANDLER( IDC_CHECKALLUSERS, BN_CLICKED, OnCheck ) + NOTIFY_HANDLER( IDC_SYSLINK1, NM_CLICK, OnLink ) + NOTIFY_HANDLER( IDC_SYSLINK1, NM_RETURN, OnLink ) + REFLECT_NOTIFICATIONS() + END_MSG_MAP() + + enum { IDD=IDD_UNINSTALL }; + + CString GetPath( void ) const { return m_Path; } + bool GetRemoveUserSettings( void ) const { return m_bRemoveUserSettings; } + bool GetRemoveAllUserSettings( void ) const { return m_bRemoveAllUserSettings; } + bool GetRemoveAdminSettings( void ) const { return m_bRemoveAdminSettings; } + +protected: + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnColorStatic( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnBrowse( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCheck( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnLink( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + +private: + CString m_Path; + bool m_bRemoveUserSettings; + bool m_bRemoveAllUserSettings; + bool m_bRemoveAdminSettings; + bool m_bEmptyPath; +}; + +LRESULT CUninstallDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + m_bRemoveUserSettings=m_bRemoveAllUserSettings=m_bRemoveAdminSettings=false; + m_bEmptyPath=false; + + wchar_t path[_MAX_PATH]={0}; + { + HKEY hkey=NULL; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,L"SOFTWARE\\IvoSoft\\ClassicShell",0,KEY_READ|KEY_QUERY_VALUE|KEY_WOW64_64KEY,&hkey)==ERROR_SUCCESS) + { + DWORD type=0; + DWORD size=sizeof(path); + if (RegQueryValueEx(hkey,L"Path",0,&type,(BYTE*)path,&size)!=ERROR_SUCCESS || type!=REG_SZ) + path[0]=0; + } + } + + if (path[0]==0) + { + BOOL bWow64=FALSE; + if (!IsWow64Process(GetCurrentProcess(),&bWow64)) + bWow64=FALSE; + wchar_t defaultPath[_MAX_PATH]; + Strcpy(defaultPath,_countof(defaultPath),bWow64?L"%ProgramW6432%\\Classic Shell":L"%ProgramFiles%\\Classic Shell"); + DoEnvironmentSubst(defaultPath,_countof(defaultPath)); + wchar_t fname1[_MAX_PATH], fname2[_MAX_PATH], fname3[_MAX_PATH]; + Sprintf(fname1,_countof(fname1),L"%s\\ClassicStartMenu.exe",defaultPath); + Sprintf(fname2,_countof(fname2),L"%s\\ClassicExplorer32.dll",defaultPath); + Sprintf(fname3,_countof(fname3),L"%s\\ClassicIEDLL_32.dll",defaultPath); + if (FileExists(fname1) || FileExists(fname2) || FileExists(fname3)) + Strcpy(path,_countof(path),defaultPath); + } + + m_bEmptyPath=path[0]==0; + if (m_bEmptyPath) + SetDlgItemText(IDC_STATICPATH,L"The tool failed to locate the Classic Shell installation folder. Use the Browse button to locate the correct folder if you want the files in it to be deleted."); + else + { + PathRemoveBackslash(path); + SetDlgItemText(IDC_EDITPATH,path); + } + + return TRUE; +} + +LRESULT CUninstallDlg::OnColorStatic( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if ((HWND)lParam==GetDlgItem(IDC_STATICWARNING) || (HWND)lParam==GetDlgItem(IDC_STATICALLUSERS) || (m_bEmptyPath && (HWND)lParam==GetDlgItem(IDC_STATICPATH))) + { + SetTextColor((HDC)wParam,0x0000CF); + SetBkMode((HDC)wParam,TRANSPARENT); + return (LRESULT)GetStockObject(NULL_BRUSH); + } + bHandled=FALSE; + return 0; +} + +LRESULT CUninstallDlg::OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + EndDialog(0); + return 0; +} + +LRESULT CUninstallDlg::OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + GetDlgItemText(IDC_EDITPATH,m_Path); + m_bRemoveUserSettings=IsDlgButtonChecked(IDC_CHECKSETTINGS)==BST_CHECKED; + m_bRemoveAllUserSettings=IsDlgButtonChecked(IDC_CHECKALLUSERS)==BST_CHECKED; + m_bRemoveAdminSettings=IsDlgButtonChecked(IDC_CHECKADMIN)==BST_CHECKED; + EndDialog(1); + return 0; +} + +LRESULT CUninstallDlg::OnBrowse( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CComPtr pDialog; + if (SUCCEEDED(pDialog.CoCreateInstance(CLSID_FileOpenDialog,NULL,CLSCTX_INPROC_SERVER))) + { + pDialog->SetTitle(L"Locate the Classic Shell install folder"); + pDialog->SetOptions(FOS_FILEMUSTEXIST|FOS_DONTADDTORECENT|FOS_DEFAULTNOMINIMODE|FOS_NOCHANGEDIR|FOS_PICKFOLDERS); + HRESULT hr=pDialog->Show(m_hWnd); + CComPtr pResult; + if (hr==S_OK) + pDialog->GetResult(&pResult); + + if (pResult) + { + CComString pName; + pResult->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName); + SetDlgItemText(IDC_EDITPATH,pName); + m_bEmptyPath=false; + GetDlgItem(IDC_STATICPATH).Invalidate(); + } + } + return 0; +} + +LRESULT CUninstallDlg::OnCheck( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + GetDlgItem(IDC_STATICALLUSERS).ShowWindow(IsDlgButtonChecked(IDC_CHECKALLUSERS)==BST_CHECKED?SW_SHOW:SW_HIDE); + return 0; +} + +LRESULT CUninstallDlg::OnLink( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + ShellExecute(m_hWnd,NULL,L"control",L"appwiz.cpl",NULL,SW_SHOWNORMAL); + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +class CResultsDlg: public CResizeableDlg +{ +public: + CResultsDlg( bool bErrors, bool bReboot, CString report ) { m_bErrors=bErrors; m_bReboot=bReboot; m_Report=report; } + + BEGIN_MSG_MAP( CResultsDlg ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + MESSAGE_HANDLER( WM_CTLCOLORSTATIC, OnColorStatic ) + MESSAGE_HANDLER( WM_SIZE, OnSize ) + MESSAGE_HANDLER( WM_GETMINMAXINFO, OnGetMinMaxInfo ) + COMMAND_HANDLER( IDC_BUTTONCLOSE, BN_CLICKED, OnClose ) + COMMAND_HANDLER( IDC_BUTTONREBOOT, BN_CLICKED, OnReboot ) + REFLECT_NOTIFICATIONS() + END_MSG_MAP() + + BEGIN_RESIZE_MAP + RESIZE_CONTROL(IDC_STATICRESULT,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_EDITRESULT,MOVE_SIZE_X|MOVE_SIZE_Y) + RESIZE_CONTROL(IDC_BUTTONREBOOT,MOVE_MOVE_X|MOVE_MOVE_Y) + RESIZE_CONTROL(IDC_BUTTONCLOSE,MOVE_MOVE_X|MOVE_MOVE_Y) + END_RESIZE_MAP + + enum { IDD=IDD_UNINSTALL_RESULTS }; + +protected: + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnColorStatic( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnClose( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnReboot( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + +private: + bool m_bErrors; + bool m_bReboot; + CString m_Report; +}; + +LRESULT CResultsDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + InitResize(MOVE_MODAL); + if (m_bErrors) + { + SetDlgItemText(IDC_STATICRESULT,L"The Classic Shell removal tool encountered some errors. Please, restart your computer and try again. If the problem is not resolved" + L" seek help in the Classic Shell forums: www.classicshell.net/forum. Copy the following report and post it in the forum. The report is also saved in a file ClassicShellReport.txt on your desktop."); + } + else if (m_bReboot) + { + SetDlgItemText(IDC_STATICRESULT,L"The Classic Shell removal tool finished. A restart is required to complete the process." + L"Copy the following report for your records. The report is also saved in a file ClassicShellReport.txt on your desktop."); + } + else + { + SetDlgItemText(IDC_STATICRESULT,L"The Classic Shell removal tool finished." + L"Copy the following report for your records. The report is also saved in a file ClassicShellReport.txt on your desktop."); + } + + SetDlgItemText(IDC_EDITRESULT,m_Report); + + GetDlgItem(IDC_BUTTONREBOOT).ShowWindow((m_bErrors || m_bReboot)?SW_SHOW:SW_HIDE); + SetDlgItemText(IDC_BUTTONCLOSE,(m_bErrors || m_bReboot)?L"Restart Later":L"Close"); + GetDlgItem(IDC_EDITRESULT).SetFocus(); + return FALSE; +} + +LRESULT CResultsDlg::OnColorStatic( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_bErrors && (HWND)lParam==GetDlgItem(IDC_STATICRESULT)) + { + SetTextColor((HDC)wParam,0x0000CF); + SetBkMode((HDC)wParam,TRANSPARENT); + return (LRESULT)GetStockObject(NULL_BRUSH); + } + bHandled=FALSE; + return 0; +} + +LRESULT CResultsDlg::OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + CResizeableDlg::OnSize(); + return 0; +} + +LRESULT CResultsDlg::OnClose( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + EndDialog(0); + return 0; +} + +LRESULT CResultsDlg::OnReboot( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + EndDialog(1); + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +class CProgressDlg: public CDialogImpl +{ +public: + BEGIN_MSG_MAP( CProgressDlg ) + END_MSG_MAP() + + enum { IDD=IDD_UNINSTALL_PROGRESS }; +}; + +/////////////////////////////////////////////////////////////////////////////// + +static bool g_bHasErrors=false; +static bool g_bRebootRequired=false; +static std::vector g_Report; + +static void AdjustPrivileges( void ) +{ + HANDLE hToken; + if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken)) + { + { + TOKEN_PRIVILEGES tp={1}; + if (LookupPrivilegeValue(NULL,L"SeBackupPrivilege",&tp.Privileges[0].Luid)) + tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; + AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL); + } + { + TOKEN_PRIVILEGES tp={1}; + if (LookupPrivilegeValue(NULL,L"SeRestorePrivilege",&tp.Privileges[0].Luid)) + tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; + AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL); + } + CloseHandle(hToken); + } +} + +static void LogMessage( int error, const wchar_t *format, ... ) +{ + wchar_t message[1024]; + int len=0; + if (error!=-1) + len+=Strcpy(message,_countof(message),L"ERROR: "); + va_list args; + va_start(args,format); + len+=Vsprintf(message+len,_countof(message)-len,format,args); + va_end(args); + if (error!=-1) + { + g_bHasErrors=true; + len+=Sprintf(message+len,_countof(message)-len,L" "); + len+=FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,NULL,error,0,message+len,_countof(message)-len,NULL); + } + len+=Sprintf(message+len,_countof(message)-len,L"\r\n"); + OutputDebugString(message); + g_Report.insert(g_Report.end(),message,message+len); +} + +static void SaveReportFile( void ) +{ + wchar_t path[_MAX_PATH]=L"%USERPROFILE%\\Desktop\\ClassicShellReport.txt"; + DoEnvironmentSubst(path,_countof(path)); + FILE *f; + if (_wfopen_s(&f,path,L"wb")==0) + { + if (!g_Report.empty()) + fwrite(&g_Report[0],2,g_Report.size(),f); + fclose(f); + } +} + +static bool RemoveRegistryKeys( bool bPin ) +{ + HKEY hkey=NULL; + int error; + error=RegOpenKeyEx(HKEY_CLASSES_ROOT,L"CLSID\\" EXPLORER_CLSID L"\\" EMULATION_KEY,0,KEY_READ|KEY_WOW64_64KEY,&hkey); + if (error==ERROR_SUCCESS) + { + RegCloseKey(hkey); + LogMessage(-1,L"Deleting registry key HKEY_CLASSES_ROOT\\CLSID\\" EXPLORER_CLSID L"\\" EMULATION_KEY); + error=RegCreateKeyEx(HKEY_CLASSES_ROOT,L"CLSID\\" EXPLORER_CLSID,NULL,NULL,REG_OPTION_BACKUP_RESTORE,KEY_WRITE|DELETE|KEY_WOW64_64KEY,NULL,&hkey,NULL); + if (error==ERROR_SUCCESS) + { + error=RegDeleteTree2(hkey,EMULATION_KEY); + if (error!=ERROR_SUCCESS) + LogMessage(error,L"Failed to delete registry key HKEY_CLASSES_ROOT\\CLSID\\" EXPLORER_CLSID L"\\" EMULATION_KEY L"."); + RegCloseKey(hkey); + } + else + LogMessage(error,L"Failed to open registry key HKEY_CLASSES_ROOT\\CLSID\\" EXPLORER_CLSID L" for writing."); + + if (RegOpenKeyEx(HKEY_CLASSES_ROOT,L"CLSID\\" EXPLORER_CLSID L"\\" EMULATION_KEY,0,KEY_READ|KEY_WOW64_64KEY,&hkey)==ERROR_SUCCESS) + { + RegCloseKey(hkey); + SaveReportFile(); + wchar_t path[_MAX_PATH]=L"%USERPROFILE%\\Desktop\\ClassicShellReport.txt"; + DoEnvironmentSubst(path,_countof(path)); + wchar_t message[1024]; + Sprintf(message,_countof(message),L"Failed to delete registry key HKEY_CLASSES_ROOT\\CLSID\\" EXPLORER_CLSID L"\\" EMULATION_KEY L".\r\n" + L"You will have to delete it manually using regedit and then run this tool again.\r\n" + L"The problem may be related to incorrect permissions or corrupted owner of the registry key or its parent.\r\n\r\n" + L"Look at the file %s for more details about the failure.",path); + MessageBox(NULL,message,L"Classic Shell Uninstaller",MB_OK|MB_ICONERROR); + return false; + } + } + + hkey=NULL; + if (bPin) + { + if (RegOpenKeyEx(HKEY_CLASSES_ROOT,L"Launcher.ImmersiveApplication\\ShellEx\\ContextMenuHandlers\\StartMenuExt",0,KEY_READ|KEY_WOW64_64KEY,&hkey)==ERROR_SUCCESS) + { + RegCloseKey(hkey); + LogMessage(-1,L"Deleting registry key HKEY_CLASSES_ROOT\\Launcher.ImmersiveApplication\\ShellEx\\ContextMenuHandlers\\StartMenuExt"); + error=RegCreateKeyEx(HKEY_CLASSES_ROOT,L"Launcher.ImmersiveApplication\\ShellEx\\ContextMenuHandlers",NULL,NULL,REG_OPTION_BACKUP_RESTORE,KEY_WRITE|DELETE|KEY_WOW64_64KEY,NULL,&hkey,NULL); + if (error==ERROR_SUCCESS) + { + error=RegDeleteTree2(hkey,L"StartMenuExt"); + if (error!=ERROR_SUCCESS && error!=ERROR_FILE_NOT_FOUND) + LogMessage(error,L"Failed to delete registry key HKEY_CLASSES_ROOT\\Launcher.ImmersiveApplication\\ShellEx\\ContextMenuHandlers\\StartMenuExt."); + RegCloseKey(hkey); + } + else if (error!=ERROR_FILE_NOT_FOUND) + LogMessage(error,L"Failed to open registry key HKEY_CLASSES_ROOT\\Launcher.ImmersiveApplication\\ShellEx\\ContextMenuHandlers for writing."); + } + + if (RegOpenKeyEx(HKEY_CLASSES_ROOT,L"Launcher.SystemSettings\\ShellEx\\ContextMenuHandlers\\StartMenuExt",0,KEY_READ|KEY_WOW64_64KEY,&hkey)==ERROR_SUCCESS) + { + RegCloseKey(hkey); + LogMessage(-1,L"Deleting registry key HKEY_CLASSES_ROOT\\Launcher.SystemSettings\\ShellEx\\ContextMenuHandlers\\StartMenuExt"); + error=RegCreateKeyEx(HKEY_CLASSES_ROOT,L"Launcher.SystemSettings\\ShellEx\\ContextMenuHandlers",NULL,NULL,REG_OPTION_BACKUP_RESTORE,KEY_WRITE|DELETE|KEY_WOW64_64KEY,NULL,&hkey,NULL); + if (error==ERROR_SUCCESS) + { + error=RegDeleteTree2(hkey,L"StartMenuExt"); + if (error!=ERROR_SUCCESS && error!=ERROR_FILE_NOT_FOUND) + LogMessage(error,L"Failed to delete registry key HKEY_CLASSES_ROOT\\Launcher.SystemSettings\\ShellEx\\ContextMenuHandlers\\StartMenuExt."); + RegCloseKey(hkey); + } + else if (error!=ERROR_FILE_NOT_FOUND) + LogMessage(error,L"Failed to open registry key HKEY_CLASSES_ROOT\\Launcher.SystemSettings\\ShellEx\\ContextMenuHandlers for writing."); + } + } + + return true; +} + +static void DeleteRegKeyHKCR( const wchar_t *keyName ) +{ + int error=RegDeleteTree2(HKEY_CLASSES_ROOT,keyName); + if (error!=ERROR_FILE_NOT_FOUND) + { + LogMessage(-1,L"Deleting registry key HKEY_CLASSES_ROOT\\%s",keyName); + if (error!=ERROR_SUCCESS) + LogMessage(error,L"Failed to delete registry key HKEY_CLASSES_ROOT\\%s.",keyName); + } +} + +static void DeleteRegKeyCLSID( const wchar_t *keyName, bool bIsWow64 ) +{ + { + // delete native key (32-bit on 32-bit OS and 64-bit on 64-bit OS) + HKEY hkey=NULL; + int error=RegOpenKeyEx(HKEY_CLASSES_ROOT,L"CLSID",0,KEY_WRITE|DELETE|KEY_WOW64_64KEY,&hkey); + if (error==ERROR_SUCCESS) + { + int error=RegDeleteTree2(hkey,keyName); + if (error!=ERROR_FILE_NOT_FOUND) + { + LogMessage(-1,L"Deleting registry key HKEY_CLASSES_ROOT\\CLSID\\%s",keyName); + if (error!=ERROR_SUCCESS) + LogMessage(error,L"Failed to delete registry key HKEY_CLASSES_ROOT\\CLSID\\%s.",keyName); + } + RegCloseKey(hkey); + } + else + { + LogMessage(-1,L"Deleting registry key HKEY_CLASSES_ROOT\\CLSID\\%s",keyName); + LogMessage(error,L"Failed to open registry key HKEY_CLASSES_ROOT\\CLSID for writing."); + } + } + + if (bIsWow64) + { + // delete 32-bit on 64-bit OS + HKEY hkey=NULL; + int error=RegOpenKeyEx(HKEY_CLASSES_ROOT,L"CLSID",0,KEY_WRITE|DELETE|KEY_WOW64_32KEY,&hkey); + if (error==ERROR_SUCCESS) + { + int error=RegDeleteTree2(hkey,keyName); + if (error!=ERROR_FILE_NOT_FOUND) + { + LogMessage(-1,L"Deleting registry key HKEY_CLASSES_ROOT\\Wow6432Node\\CLSID\\%s",keyName); + if (error!=ERROR_SUCCESS) + LogMessage(error,L"Failed to delete registry key HKEY_CLASSES_ROOT\\Wow6432Node\\CLSID\\%s.",keyName); + } + RegCloseKey(hkey); + } + else + { + LogMessage(-1,L"Deleting registry key HKEY_CLASSES_ROOT\\Wow6432Node\\CLSID\\%s",keyName); + LogMessage(error,L"Failed to open registry key HKEY_CLASSES_ROOT\\Wow6432Node\\CLSID for writing."); + } + } +} + +static void DeleteRegKeySOFTWARE( const wchar_t *keyName, bool bIsWow64 ) +{ + { + // delete native key (32-bit on 32-bit OS and 64-bit on 64-bit OS) + HKEY hkey=NULL; + int error=RegOpenKeyEx(HKEY_LOCAL_MACHINE,L"SOFTWARE",0,KEY_WRITE|DELETE|KEY_WOW64_64KEY,&hkey); + if (error==ERROR_SUCCESS) + { + int error=RegDeleteTree2(hkey,keyName); + if (error!=ERROR_FILE_NOT_FOUND) + { + LogMessage(-1,L"Deleting registry key HKEY_LOCAL_MACHINE\\SOFTWARE\\%s",keyName); + if (error!=ERROR_SUCCESS) + LogMessage(error,L"Failed to delete registry key HKEY_LOCAL_MACHINE\\SOFTWARE\\%s.",keyName); + } + RegCloseKey(hkey); + } + else + { + LogMessage(-1,L"Deleting registry key HKEY_LOCAL_MACHINE\\SOFTWARE\\%s",keyName); + LogMessage(error,L"Failed to open registry key HKEY_LOCAL_MACHINE\\SOFTWARE for writing."); + } + } + + if (bIsWow64) + { + // delete 32-bit on 64-bit OS + HKEY hkey=NULL; + int error=RegOpenKeyEx(HKEY_LOCAL_MACHINE,L"SOFTWARE",0,KEY_WRITE|DELETE|KEY_WOW64_32KEY,&hkey); + if (error==ERROR_SUCCESS) + { + int error=RegDeleteTree2(hkey,keyName); + if (error!=ERROR_FILE_NOT_FOUND) + { + LogMessage(-1,L"Deleting registry key HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\%s",keyName); + if (error!=ERROR_SUCCESS) + LogMessage(error,L"Failed to delete registry key HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\%s.",keyName); + } + RegCloseKey(hkey); + } + else + { + LogMessage(-1,L"Deleting registry key HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\%s",keyName); + LogMessage(error,L"Failed to open registry key HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node for writing."); + } + } +} + +static void DeleteRegValueSOFTWARE( const wchar_t *keyName, const wchar_t *valueName, bool bIsWow64 ) +{ + wchar_t keyName2[256]; + Sprintf(keyName2,_countof(keyName2),L"SOFTWARE\\%s",keyName); + + { + // delete native value (32-bit on 32-bit OS and 64-bit on 64-bit OS) + HKEY hkey=NULL; + int error=RegOpenKeyEx(HKEY_LOCAL_MACHINE,keyName2,0,KEY_WRITE|DELETE|KEY_WOW64_64KEY,&hkey); + if (error==ERROR_SUCCESS) + { + int error=RegDeleteValue2(hkey,keyName); + if (error!=ERROR_FILE_NOT_FOUND) + { + LogMessage(-1,L"Deleting registry value HKEY_LOCAL_MACHINE\\SOFTWARE\\%s:%s",keyName,valueName); + if (error!=ERROR_SUCCESS) + LogMessage(error,L"Failed to delete registry value HKEY_LOCAL_MACHINE\\SOFTWARE\\%s:%s.",keyName,valueName); + } + RegCloseKey(hkey); + } + else if (error!=ERROR_FILE_NOT_FOUND) + { + LogMessage(-1,L"Deleting registry value HKEY_LOCAL_MACHINE\\SOFTWARE\\%s:%s",keyName,valueName); + LogMessage(error,L"Failed to open registry key HKEY_LOCAL_MACHINE\\SOFTWARE\\%s for writing.",keyName); + } + } + + if (bIsWow64) + { + // delete 32-bit on 64-bit OS + HKEY hkey=NULL; + int error=RegOpenKeyEx(HKEY_LOCAL_MACHINE,keyName2,0,KEY_WRITE|DELETE|KEY_WOW64_32KEY,&hkey); + if (error==ERROR_SUCCESS) + { + int error=RegDeleteValue2(hkey,keyName); + if (error!=ERROR_FILE_NOT_FOUND) + { + LogMessage(-1,L"Deleting registry value HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\%s:%s",keyName,valueName); + if (error!=ERROR_SUCCESS) + LogMessage(error,L"Failed to delete registry value HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\%s:%s.",keyName,valueName); + } + RegCloseKey(hkey); + } + else if (error!=ERROR_FILE_NOT_FOUND) + { + LogMessage(-1,L"Deleting registry value HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\%s:%s",keyName,valueName); + LogMessage(error,L"Failed to open registry key HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\%s for writing.",keyName); + } + } +} + +static void DeleteInstallerKey( HKEY root, const wchar_t *rootName, const wchar_t *keyName, const wchar_t *valueName, const wchar_t *value ) +{ + LogMessage(-1,L"Searching for installer registry key in %s\\%s",rootName,keyName); + HKEY hkey=NULL; + int error=RegOpenKeyEx(root,keyName,0,KEY_WRITE|DELETE|KEY_ENUMERATE_SUB_KEYS|KEY_WOW64_64KEY,&hkey); + if (error==ERROR_SUCCESS) + { + std::vector subKeyNames; + for (int index=0;;index++) + { + wchar_t subKeyName[100]; + DWORD len=_countof(subKeyName); + if (RegEnumKeyEx(hkey,index,subKeyName,&len,NULL,NULL,NULL,NULL)!=ERROR_SUCCESS) + break; + wchar_t buf[256]; + len=sizeof(buf); + if (RegGetValue(hkey,subKeyName,valueName,RRF_RT_REG_SZ,NULL,(void*)buf,&len)==ERROR_SUCCESS) + { + if (len==wcslen(value)*2+2 && _wcsicmp(value,buf)==0) + subKeyNames.push_back(subKeyName); + } + } + for (std::vector::const_iterator it=subKeyNames.begin();it!=subKeyNames.end();++it) + { + LogMessage(-1,L"Deleting registry key %s\\%s\\%s",rootName,keyName,it->c_str()); + error=RegDeleteTree2(hkey,it->c_str()); + if (error!=ERROR_SUCCESS) + LogMessage(error,L"Failed to delete registry key %s\\%s\\%s.",rootName,keyName,it->c_str()); + } + RegCloseKey(hkey); + } + else if (error!=ERROR_FILE_NOT_FOUND) + LogMessage(error,L"Failed to open registry key %s\\%s for writing.",rootName,keyName); +} + +static void DeleteSettings( HKEY root, const wchar_t *rootName, const wchar_t *keyName ) +{ + HKEY hkey=NULL; + int error=RegOpenKeyEx(root,keyName,0,KEY_WRITE|DELETE|KEY_WOW64_64KEY,&hkey); + if (error==ERROR_SUCCESS) + { + error=RegDeleteTree2(hkey,L"ClassicExplorer"); + if (error==ERROR_SUCCESS) + LogMessage(-1,L"Deleting registry key %s\\%s\\ClassicExplorer",rootName,keyName); + else if (error!=ERROR_FILE_NOT_FOUND) + LogMessage(error,L"Failed to delete registry key %s\\%s\\ClassicExplorer.",rootName,keyName); + error=RegDeleteTree2(hkey,L"ClassicIE"); + if (error==ERROR_SUCCESS) + LogMessage(-1,L"Deleting registry key %s\\%s\\ClassicIE",rootName,keyName); + else if (error!=ERROR_FILE_NOT_FOUND) + LogMessage(error,L"Failed to delete registry key %s\\%s\\ClassicIE.",rootName,keyName); + error=RegDeleteTree2(hkey,L"ClassicShell"); + if (error==ERROR_SUCCESS) + LogMessage(-1,L"Deleting registry key %s\\%s\\ClassicShell",rootName,keyName); + else if (error!=ERROR_FILE_NOT_FOUND) + LogMessage(error,L"Failed to delete registry key %s\\%s\\ClassicShell.",rootName,keyName); + error=RegDeleteTree2(hkey,L"ClassicStartMenu"); + if (error==ERROR_SUCCESS) + LogMessage(-1,L"Deleting registry key %s\\%s\\ClassicStartMenu",rootName,keyName); + else if (error!=ERROR_FILE_NOT_FOUND) + LogMessage(error,L"Failed to delete registry key %s\\%s\\ClassicStartMenu.",rootName,keyName); + RegCloseKey(hkey); + + HKEY root2; + error=RegOpenKeyEx(root,NULL,0,KEY_WRITE|DELETE|KEY_WOW64_64KEY,&root2); + if (error==ERROR_SUCCESS) + { + error=RegDeleteKey(root2,keyName); + if (error==ERROR_SUCCESS) + LogMessage(-1,L"Deleting registry key %s\\%s",rootName,keyName); + else if (error!=ERROR_FILE_NOT_FOUND) + LogMessage(error,L"Failed to delete registry key %s\\%s.",rootName,keyName); + RegCloseKey(root2); + } + else + LogMessage(error,L"Failed to open registry key %s for writing.",rootName); + } + else if (error!=ERROR_FILE_NOT_FOUND) + LogMessage(error,L"Failed to open registry key %s\\%s for writing.",rootName,keyName); +} + +// returns true if a file was delay-deleted +static bool DeleteFileEx( const wchar_t *fname, bool bAllowDelay ) +{ + DWORD attribs=GetFileAttributes(fname); + if (attribs!=INVALID_FILE_ATTRIBUTES) + { + if (attribs&FILE_ATTRIBUTE_READONLY) + SetFileAttributes(fname,attribs&~FILE_ATTRIBUTE_READONLY); + LogMessage(-1,L"Deleting file %s",fname); + if (!DeleteFile2(fname)) + { + int error=GetLastError(); + if (error==ERROR_ACCESS_DENIED && bAllowDelay) + { + LogMessage(-1,L"Delay deleting file %s",fname); + wchar_t fname2[_MAX_PATH]; + Sprintf(fname2,_countof(fname2),L"%s_",fname); + const wchar_t *delName=fname; + if (MoveFileEx2(fname,fname2,0)) + { + delName=fname2; + } + if (MoveFileEx2(delName,NULL,MOVEFILE_DELAY_UNTIL_REBOOT)) + { + g_bRebootRequired=true; + return true; + } + else + { + int error=GetLastError(); + LogMessage(error,L"Failed to delete file %s.",fname); + } + } + else + LogMessage(error,L"Failed to delete file %s.",fname); + } + } + return false; +} + +static void DeleteDirectoryEx( const wchar_t *path, bool bDelay ) +{ + if (!DirectoryExists(path)) + return; + if (bDelay) + { + LogMessage(-1,L"Delay deleting directory %s",path); + if (MoveFileEx2(path,NULL,MOVEFILE_DELAY_UNTIL_REBOOT)) + g_bRebootRequired=true; + else + { + int error=GetLastError(); + LogMessage(error,L"Failed to delete directory %s.",path); + } + } + else + { + LogMessage(-1,L"Deleting directory %s",path); + if (!RemoveDirectory2(path)) + { + int error=GetLastError(); + bool bOldHasErrors=g_bHasErrors; + LogMessage(error,L"Failed to delete directory %s.",path); + if (error==ERROR_DIR_NOT_EMPTY) + { + // failing to delete non-empty directory is not a fatal error + g_bHasErrors=bOldHasErrors; + } + } + } +} + +// returns true if any files were delay-deleted +static bool DeleteFiles( const wchar_t *directory, const wchar_t **files, int fileCount, bool bAllowDelay ) +{ + bool res=false; + if (DirectoryExists(directory)) + { + for (int i=0;i100) pos=100; + progress.GetDlgItem(IDC_PROGRESS1).SendMessage(PBM_SETPOS,pos); + MSG msg; + while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + int dt=time+i*50-GetTickCount(); + if (dt>0) Sleep(dt); + } + } + + progress.GetDlgItem(IDC_PROGRESS1).SendMessage(PBM_SETPOS,100); + + AdjustPrivileges(); + + LogMessage(-1,L"Classic Shell Utility - removing Classic Shell from the system\r\n\r\n"); + + // remove TreatAs, app launcher keys + WORD winVer=HIWORD(GetVersionEx(GetModuleHandle(L"user32.dll"))); + if (winVer>=WIN_VER_WIN8) + { + if (!RemoveRegistryKeys(winVer>=WIN_VER_WIN10)) + { + progress.DestroyWindow(); + return; + } + } + + BOOL bWow64=FALSE; + bool bIsWow64=IsWow64Process(GetCurrentProcess(),&bWow64) && bWow64; + + DeleteRegKeyHKCR(L"AppID\\ClassicExplorer.DLL"); + DeleteRegKeyHKCR(L"AppID\\ClassicIE.DLL"); + DeleteRegKeyHKCR(L"AppID\\StartMenuHelper.DLL"); + DeleteRegKeyHKCR(L"AppID\\{62D2FBE4-89F7-48A5-A35F-DA2B8A3C54B7}"); + DeleteRegKeyHKCR(L"AppID\\{65843E27-A491-429F-84A0-30A947E20F92}"); + DeleteRegKeyHKCR(L"AppID\\{DF3255F4-FF55-44FA-A728-E77B83E9E403}"); + + DeleteRegKeyHKCR(L"Directory\\shellex\\DragDropHandlers\\ClassicCopyExt"); + DeleteRegKeyHKCR(L"Drive\\shellex\\DragDropHandlers\\ClassicCopyExt"); + DeleteRegKeyHKCR(L"exefile\\shellex\\ContextMenuHandlers\\StartMenuExt"); + DeleteRegKeyHKCR(L"Folder\\shellex\\ContextMenuHandlers\\StartMenuExt"); + DeleteRegKeyHKCR(L"Folder\\shellex\\DragDropHandlers\\ClassicCopyExt"); + DeleteRegKeyHKCR(L"lnkfile\\shellex\\ContextMenuHandlers\\StartMenuExt"); + DeleteRegKeyHKCR(L"ClassicExplorer.ClassicCopyExt"); + DeleteRegKeyHKCR(L"ClassicExplorer.ClassicCopyExt.1"); + DeleteRegKeyHKCR(L"ClassicExplorer.ExplorerBHO"); + DeleteRegKeyHKCR(L"ClassicExplorer.ExplorerBHO.1"); + DeleteRegKeyHKCR(L"ClassicExplorer.ExplorerBand"); + DeleteRegKeyHKCR(L"ClassicExplorer.ExplorerBand.1"); + DeleteRegKeyHKCR(L"ClassicExplorer.ShareOverlay"); + DeleteRegKeyHKCR(L"ClassicExplorer.ShareOverlay.1"); + DeleteRegKeyHKCR(L"ClassicIE.ClassicIEBHO"); + DeleteRegKeyHKCR(L"ClassicIE.ClassicIEBHO.1"); + DeleteRegKeyHKCR(L"StartMenuHelper.StartMenuExt"); + DeleteRegKeyHKCR(L"StartMenuHelper.StartMenuExt.1"); + + DeleteRegKeyCLSID(L"{449D0D6E-2412-4E61-B68F-1CB625CD9E52}",bIsWow64); + DeleteRegKeyCLSID(L"{553891B7-A0D5-4526-BE18-D3CE461D6310}",bIsWow64); + DeleteRegKeyCLSID(L"{594D4122-1F87-41E2-96C7-825FB4796516}",bIsWow64); + DeleteRegKeyCLSID(L"{8C83ACB1-75C3-45D2-882C-EFA32333491C}",bIsWow64); + DeleteRegKeyCLSID(L"{D3214FBB-3CA1-406A-B3E8-3EB7C393A15E}",bIsWow64); + DeleteRegKeyCLSID(L"{E595F05F-903F-4318-8B0A-7F633B520D2B}",bIsWow64); + + DeleteRegKeySOFTWARE(L"Microsoft\\Internet Explorer\\Extensions\\{56753E59-AF1D-4FBA-9E15-31557124ADA2}",bIsWow64); + DeleteRegKeySOFTWARE(L"Microsoft\\Internet Explorer\\Low Rights\\ElevationPolicy\\{02E6771D-8375-42B9-9F83-B4730F697900}",bIsWow64); + DeleteRegKeySOFTWARE(L"Microsoft\\Internet Explorer\\Low Rights\\ElevationPolicy\\{56753E59-AF1D-4FBA-9E15-31557124ADA2}",bIsWow64); + DeleteRegKeySOFTWARE(L"Microsoft\\Internet Explorer\\Low Rights\\ElevationPolicy\\{C0393554-9B48-458A-B91B-3F684D003B2F}",bIsWow64); + DeleteRegKeySOFTWARE(L"Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects\\{449D0D6E-2412-4E61-B68F-1CB625CD9E52}",bIsWow64); + DeleteRegKeySOFTWARE(L"Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects\\{EA801577-E6AD-4BD5-8F71-4BE0154331A4}",bIsWow64); + DeleteRegKeySOFTWARE(L"Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\ShareOverlay",bIsWow64); + DeleteRegKeySOFTWARE(L"IvoSoft\\ClassicShell",bIsWow64); + + DeleteRegValueSOFTWARE(L"Microsoft\\Internet Explorer\\Toolbar",L"{553891B7-A0D5-4526-BE18-D3CE461D6310}",bIsWow64); + DeleteRegValueSOFTWARE(L"Microsoft\\Windows\\CurrentVersion\\Policies\\Ext\\CLSID",L"{449D0D6E-2412-4E61-B68F-1CB625CD9E52}",bIsWow64); + DeleteRegValueSOFTWARE(L"Microsoft\\Windows\\CurrentVersion\\Policies\\Ext\\CLSID",L"{553891B7-A0D5-4526-BE18-D3CE461D6310}",bIsWow64); + DeleteRegValueSOFTWARE(L"Microsoft\\Windows\\CurrentVersion\\Policies\\Ext\\CLSID",L"{EA801577-E6AD-4BD5-8F71-4BE0154331A4}",bIsWow64); + DeleteRegValueSOFTWARE(L"Microsoft\\Windows\\CurrentVersion\\Run",L"Classic Start Menu",bIsWow64); + + DeleteInstallerKey(HKEY_CLASSES_ROOT,L"HKEY_CLASSES_ROOT",L"Installer\\Features",L"ClassicShell",L""); + DeleteInstallerKey(HKEY_CLASSES_ROOT,L"HKEY_CLASSES_ROOT",L"Installer\\Products",L"ProductName",L"Classic Shell"); + DeleteInstallerKey(HKEY_LOCAL_MACHINE,L"HKEY_LOCAL_MACHINE",L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",L"DisplayName",L"Classic Shell"); + + if (dlg.GetRemoveUserSettings() || dlg.GetRemoveAllUserSettings()) + { + // delete settings for the current user + LogMessage(-1,L"Deleting user settings from HKEY_CURRENT_USER\\Software\\IvoSoft"); + DeleteSettings(HKEY_CURRENT_USER,L"HKEY_CURRENT_USER",L"Software\\IvoSoft"); + + wchar_t local[_MAX_PATH]=L"%LOCALAPPDATA%\\ClassicShell"; + DoEnvironmentSubst(local,_countof(local)); + wchar_t roaming[_MAX_PATH]=L"%APPDATA%\\ClassicShell"; + DoEnvironmentSubst(roaming,_countof(roaming)); + DeleteUserFiles(local,roaming); + } + + if (dlg.GetRemoveAllUserSettings()) + { + // delete settings for all users + std::vector userNames; + wchar_t usersFolder[_MAX_PATH]; + { + CComString pUsersFolder; + if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_UserProfiles,0,NULL,&pUsersFolder))) + Strcpy(usersFolder,_countof(usersFolder),pUsersFolder); + else + { + Strcpy(usersFolder,_countof(usersFolder),L"%systemdrive%\\Users"); + DoEnvironmentSubst(usersFolder,_countof(usersFolder)); + } + } + { + wchar_t userName[256]=L"%USERNAME%"; + DoEnvironmentSubst(userName,_countof(userName)); + USER_INFO_1 *users; + DWORD userCount, userCount2; + if (NetUserEnum(NULL,1,FILTER_NORMAL_ACCOUNT,(BYTE**)&users,MAX_PREFERRED_LENGTH,&userCount,&userCount2,NULL)==NERR_Success) + { + for (DWORD userIdx=0;userIdx::const_iterator it=userNames.begin();it!=userNames.end();++it) + { + LogMessage(-1,L"Deleting settings for user %s",*it); + + wchar_t local[_MAX_PATH]; + Sprintf(local,_countof(local),L"%s\\%s\\AppData\\Local\\ClassicShell",usersFolder,*it); + wchar_t roaming[_MAX_PATH]; + Sprintf(roaming,_countof(roaming),L"%s\\%s\\AppData\\Roaming\\ClassicShell",usersFolder,*it); + DeleteUserFiles(local,roaming); + + wchar_t regFile[_MAX_PATH]; + Sprintf(regFile,_countof(regFile),L"%s\\%s\\NTUSER.DAT",usersFolder,*it); + if (GetFileAttributes(regFile)==INVALID_FILE_ATTRIBUTES) + { + int error=GetLastError(); + if (error!=ERROR_FILE_NOT_FOUND && error!=ERROR_PATH_NOT_FOUND) + LogMessage(error,L"Failed to load registry hive %s.",regFile); + continue; + } + int error=RegLoadKey(HKEY_USERS,L"CSUTempUser",regFile); + if (error==ERROR_SUCCESS) + { + DeleteSettings(HKEY_USERS,L"HKEY_USERS",L"CSUTempUser\\Software\\IvoSoft"); + RegUnLoadKey(HKEY_USERS,L"CSUTempUser"); + } + else if (error!=ERROR_FILE_NOT_FOUND) + LogMessage(error,L"Failed to load registry hive %s.",regFile); + } + } + + if (dlg.GetRemoveAdminSettings()) + { + // delete admin settings + LogMessage(-1,L"Deleting settings from HKEY_LOCAL_MACHINE\\Software\\IvoSoft"); + DeleteSettings(HKEY_LOCAL_MACHINE,L"HKEY_LOCAL_MACHINE",L"Software\\IvoSoft"); + } + + // delete program data + { + wchar_t dataPath[_MAX_PATH]=L"%ALLUSERSPROFILE%\\ClassicShell"; + DoEnvironmentSubst(dataPath,_countof(dataPath)); + wchar_t langPath[_MAX_PATH]; + Sprintf(langPath,_countof(langPath),L"%s\\Languages",dataPath); + DeleteFiles(langPath,L"*.dll",false); + DeleteDirectoryEx(langPath,false); + DeleteFiles(dataPath,g_ProgramDataFiles,_countof(g_ProgramDataFiles),false); + DeleteDirectoryEx(dataPath,false); + } + + // delete installation folder + CString installPath=dlg.GetPath(); + if (DirectoryExists(installPath) && !PathIsRelative(installPath)) + { + wchar_t skinPath[_MAX_PATH]; + Sprintf(skinPath,_countof(skinPath),L"%s\\Skins",installPath); + bool bDelay=DeleteFiles(skinPath,g_InstalledSkins,_countof(g_InstalledSkins),true); + if (DirectoryExists(skinPath)) + DeleteDirectoryEx(skinPath,bDelay); + if (DeleteFiles(installPath,g_InstalledFiles,_countof(g_InstalledFiles),true)) + bDelay=true; + DeleteDirectoryEx(installPath,bDelay); + } + + // delete start menu shortcuts + { + CComString pPath; + if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_CommonPrograms,0,NULL,&pPath))) + { + wchar_t startMenuPath[_MAX_PATH]; + Sprintf(startMenuPath,_countof(startMenuPath),L"%s\\Classic Shell",(const wchar_t*)pPath); + if (DirectoryExists(startMenuPath)) + { + for (int i=0;i<_countof(g_InstalledShortcuts);i++) + { + wchar_t path[_MAX_PATH]; + Sprintf(path,_countof(path),L"%s\\%s",startMenuPath,g_InstalledShortcuts[i]); + DeleteFileEx(path,false); + } + DeleteDirectoryEx(startMenuPath,false); + } + } + } + + // delete start menu helpers + wchar_t winDir[_MAX_PATH]=L"%WinDir%"; + DoEnvironmentSubst(winDir,_countof(winDir)); + if (bIsWow64) + { + // 64-bit OS + wchar_t path[_MAX_PATH]; + Sprintf(path,_countof(path),L"%s\\System32\\StartMenuHelper64.dll",winDir); + Wow64EnableWow64FsRedirection(FALSE); + DeleteFileEx(path,true); + Sprintf(path,_countof(path),L"%s\\SysWOW64\\StartMenuHelper32.dll",winDir); + DeleteFileEx(path,true); + Wow64EnableWow64FsRedirection(TRUE); + } + else + { + // 32-bit OS + wchar_t path[_MAX_PATH]; + Sprintf(path,_countof(path),L"%s\\System32\\StartMenuHelper32.dll",winDir); + DeleteFileEx(path,true); + } + +/////////////////////////////////////////////////////////////////////////////// + + SaveReportFile(); + g_Report.push_back(0); + + progress.DestroyWindow(); + + if (CResultsDlg(g_bHasErrors,g_bRebootRequired,&g_Report[0]).DoModal(NULL)==1) + { + // restart was requested + HANDLE hToken; + if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken)) + { + TOKEN_PRIVILEGES tp={1}; + if (LookupPrivilegeValue(NULL,L"SeShutdownPrivilege",&tp.Privileges[0].Luid)) + tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; + AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL); + CloseHandle(hToken); + } +#ifndef SAFE_MODE + ExitWindowsEx(EWX_REBOOT,SHTDN_REASON_FLAG_PLANNED); +#endif + } + else if (g_bHasErrors || g_bRebootRequired) + { + MessageBox(NULL,L"It is important that you restart as soon as possible. If you attempt to install another software before then it may get corrupted.",L"Classic Shell Uninstaller",MB_OK|MB_ICONWARNING); + } +} + +void ManualUninstall( void ) +{ + CoInitialize(NULL); + ManualUninstallInternal(); + CoUninitialize(); +} + +#endif diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/MetroColorViewer.cpp b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/MetroColorViewer.cpp new file mode 100644 index 0000000..50f5b2d --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/MetroColorViewer.cpp @@ -0,0 +1,440 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#ifndef _WIN64 + +#define STRICT_TYPED_ITEMIDS +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit +#include +#include +#include +#include +#include "resource.h" +#include "StringUtils.h" +#include "ResourceHelper.h" + +//#define WRITE_COLORS +//#define READ_COLORS + +#ifdef READ_COLORS +#undef WRITE_COLORS +#endif + +static struct +{ + const wchar_t *name; + int code; +} g_SystemColors[]= +{ + {L"SystemScrollbar",COLOR_SCROLLBAR}, + {L"SystemBackground",COLOR_BACKGROUND}, + {L"SystemActiveCaption",COLOR_ACTIVECAPTION}, + {L"SystemInactiveCaption",COLOR_INACTIVECAPTION}, + {L"SystemMenu",COLOR_MENU}, + {L"SystemWindow",COLOR_WINDOW}, + {L"SystemWindowFrame",COLOR_WINDOWFRAME}, + {L"SystemMenuText",COLOR_MENUTEXT}, + {L"SystemWindowText",COLOR_WINDOWTEXT}, + {L"SystemCaptionText",COLOR_CAPTIONTEXT}, + {L"SystemActiveBorder",COLOR_ACTIVEBORDER}, + {L"SystemInactiveBorder",COLOR_INACTIVEBORDER}, + {L"SystemAppWorkspace",COLOR_APPWORKSPACE}, + {L"SystemHighlight",COLOR_HIGHLIGHT}, + {L"SystemHighlightText",COLOR_HIGHLIGHTTEXT}, + {L"SystemBtnFace",COLOR_BTNFACE}, + {L"SystemBtnShadow",COLOR_BTNSHADOW}, + {L"SystemGrayText",COLOR_GRAYTEXT}, + {L"SystemBtnText",COLOR_BTNTEXT}, + {L"SystemInactiveCaptionText",COLOR_INACTIVECAPTIONTEXT}, + {L"SystemBtnHighlight",COLOR_BTNHIGHLIGHT}, + {L"System3DDKShadow",COLOR_3DDKSHADOW}, + {L"System3DLight",COLOR_3DLIGHT}, + {L"SystemInfoText",COLOR_INFOTEXT}, + {L"SystemInfoBK",COLOR_INFOBK}, + {L"SystemHotLight",COLOR_HOTLIGHT}, + {L"SystemGradientActiveCaption",COLOR_GRADIENTACTIVECAPTION}, + {L"SystemGradientInactiveCaption",COLOR_GRADIENTINACTIVECAPTION}, + {L"SystemMenuHilight",COLOR_MENUHILIGHT}, + {L"SystemMenuBar",COLOR_MENUBAR}, +}; + +#ifndef READ_COLORS +typedef int (WINAPI *TGetImmersiveUserColorSetPreference)(bool bForceCheckRegistry, bool bSkipCheckOnFail); +typedef int (WINAPI *TGetImmersiveColorSetCount)(); +typedef DWORD (WINAPI *TGetImmersiveColorFromColorSetEx)(UINT dwImmersiveColorSet, UINT dwImmersiveColorType, bool bIgnoreHighContrast, UINT dwHighContrastCacheMode); +typedef const wchar_t **(WINAPI *TGetImmersiveColorNamedTypeByIndex)(UINT dwImmersiveColorType); +typedef int (WINAPI *TGetImmersiveColorTypeFromName)(const wchar_t *name); + +static TGetImmersiveUserColorSetPreference GetImmersiveUserColorSetPreference; +static TGetImmersiveColorFromColorSetEx GetImmersiveColorFromColorSetEx; +static TGetImmersiveColorSetCount GetImmersiveColorSetCount; +static TGetImmersiveColorNamedTypeByIndex GetImmersiveColorNamedTypeByIndex; +static TGetImmersiveColorTypeFromName GetImmersiveColorTypeFromName; +#endif + +struct MetroColor +{ + CString name; + CString NAME; + int type; + DWORD color; +}; + +static std::vector g_MetroColors; +static int g_MaxMetroColorType; + +class CMetroColorViewer: public CDialogImpl +{ +public: + CMetroColorViewer( void ); + + BEGIN_MSG_MAP( CMetroColorViewer ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + MESSAGE_HANDLER( WM_CLOSE, OnClose ) + COMMAND_HANDLER( IDCANCEL, BN_CLICKED, OnCancel ) + COMMAND_HANDLER( IDC_EDIT1, EN_UPDATE, OnUpdateSet ) + COMMAND_HANDLER( IDC_EDIT2, EN_UPDATE, OnUpdateFilter ) + NOTIFY_HANDLER( IDC_LIST1, NM_CUSTOMDRAW, OnCustomDraw ) + NOTIFY_HANDLER( IDC_LIST1, LVN_COLUMNCLICK, OnColumnClick ) + REFLECT_NOTIFICATIONS() + END_MSG_MAP() + + enum { IDD=IDD_COLORS }; + +protected: + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnClose( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnUpdateSet( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnUpdateFilter( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnColumnClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + +private: + int m_ColorSet; + int m_SortColumn; + CString m_Filter; + void UpdateRows( void ); + void UpdateColors( void ); + void SetSortColumn( int sort ); + + static int CALLBACK CompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort ); +}; + +CMetroColorViewer::CMetroColorViewer( void ) +{ + m_ColorSet=-1; + m_SortColumn=-1; +} + +int CALLBACK CMetroColorViewer::CompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort ) +{ + if (lParamSort==1) + { + // type + lParam1=g_MetroColors[lParam1].type; + lParam2=g_MetroColors[lParam2].type; + } + if (lParam1lParam2) return 1; + return 0; +} + +LRESULT CMetroColorViewer::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ +#ifdef READ_COLORS + m_ColorSet=0; + int setCount=1; + GetDlgItem(IDC_EDIT1).EnableWindow(FALSE); +#else + int setCount=GetImmersiveColorSetCount(); +#endif + SendDlgItemMessage(IDC_SPIN1,UDM_SETRANGE,0,MAKELONG(setCount-1,-1)); + SetDlgItemInt(IDC_EDIT1,-1,TRUE); + SendDlgItemMessage(IDC_LIST1,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT|LVS_EX_DOUBLEBUFFER,LVS_EX_FULLROWSELECT|LVS_EX_DOUBLEBUFFER); + + HWND list=GetDlgItem(IDC_LIST1); + { + LVCOLUMN column={LVCF_WIDTH|LVCF_TEXT,0,380,L"Name"}; + ListView_InsertColumn(list,0,&column); + } + { + LVCOLUMN column={LVCF_WIDTH|LVCF_TEXT,0,50,L"#"}; + ListView_InsertColumn(list,1,&column); + } + { + LVCOLUMN column={LVCF_WIDTH|LVCF_TEXT,0,100,L"Code"}; + ListView_InsertColumn(list,2,&column); + } + { + LVCOLUMN column={LVCF_WIDTH|LVCF_TEXT,0,100,L"Color"}; + ListView_InsertColumn(list,3,&column); + } + int order[]={1,0,2,3}; + ListView_SetColumnOrderArray(list,_countof(order),order); + SetSortColumn(1); + + UpdateRows(); + return TRUE; +} + +void CMetroColorViewer::SetSortColumn( int sort ) +{ + CWindow list=GetDlgItem(IDC_LIST1); + list.SendMessage(LVM_SETSELECTEDCOLUMN,m_SortColumn); + CWindow header=ListView_GetHeader(list); + HDITEM hdItem= {HDI_FORMAT}; + hdItem.fmt= HDF_LEFT|HDF_STRING; + if (m_SortColumn>=0) + header.SendMessage(HDM_SETITEM,m_SortColumn,(LPARAM)&hdItem); + hdItem.fmt|= HDF_SORTDOWN; + m_SortColumn=sort; + header.SendMessage(HDM_SETITEM,m_SortColumn,(LPARAM)&hdItem); +} + +void CMetroColorViewer::UpdateRows( void ) +{ + CWindow list=GetDlgItem(IDC_LIST1); + if (!list.IsWindow()) return; + + std::vector tokens; + for (const wchar_t *str=m_Filter;*str;) + { + wchar_t token[256]; + str=GetToken(str,token,_countof(token),L" "); + if (token[0]) + tokens.push_back(token); + } + list.SetRedraw(FALSE); + ListView_DeleteAllItems(list); + for (int i=0;i<(int)g_MetroColors.size();i++) + { + const MetroColor &color=g_MetroColors[i]; + bool found=true; + for (std::vector::const_iterator it=tokens.begin();it!=tokens.end();++it) + { + if (!wcsstr(color.NAME,*it)) + { + found=false; + break; + } + } + if (!found) continue; + LVITEM item={LVIF_PARAM|LVIF_TEXT}; + item.lParam=i; + item.pszText=(wchar_t*)(const wchar_t*)color.name; + item.iItem=10000; + int idx=ListView_InsertItem(list,&item); + + wchar_t text[20]; + Sprintf(text,_countof(text),L"%d",color.type); + ListView_SetItemText(list,idx,1,text); + } + ListView_SortItems(list,CompareFunc,m_SortColumn); + list.SetRedraw(TRUE); + UpdateColors(); +} + +void CMetroColorViewer::UpdateColors( void ) +{ + CWindow list=GetDlgItem(IDC_LIST1); + if (!list.IsWindow()) return; +#ifndef READ_COLORS + int set=m_ColorSet>=0?m_ColorSet:GetImmersiveUserColorSetPreference(false,false); +#endif + int count=ListView_GetItemCount(list); + list.SetRedraw(FALSE); + for (int i=0;i>24)&0xFF,color&0xFF,(color>>8)&0xFF,(color>>16)&0xFF); + ListView_SetItemText(list,i,2,text); + } + list.SetRedraw(TRUE); + ::InvalidateRect(list,NULL,TRUE); +} + +LRESULT CMetroColorViewer::OnClose( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + EndDialog(0); + return 0; +} + +LRESULT CMetroColorViewer::OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (GetFocus()==GetDlgItem(IDC_EDIT2)) + SetDlgItemText(IDC_EDIT2,L""); + return 0; +} + +LRESULT CMetroColorViewer::OnUpdateSet( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + m_ColorSet=GetDlgItemInt(IDC_EDIT1); + UpdateColors(); + return 0; +} + +LRESULT CMetroColorViewer::OnUpdateFilter( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CString filter; + GetDlgItemText(IDC_EDIT2,filter); + filter.MakeUpper(); + if (filter!=m_Filter) + { + m_Filter=filter; + UpdateRows(); + } + return 0; +} + +LRESULT CMetroColorViewer::OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMLVCUSTOMDRAW *pDraw=(NMLVCUSTOMDRAW*)pnmh; + if (pDraw->nmcd.dwDrawStage==CDDS_PREPAINT) + return CDRF_NOTIFYITEMDRAW; + if (pDraw->nmcd.dwDrawStage==CDDS_ITEMPREPAINT) + return CDRF_NOTIFYSUBITEMDRAW; + if (pDraw->nmcd.dwDrawStage==(CDDS_ITEMPREPAINT|CDDS_SUBITEM) && pDraw->iSubItem==3) + { + RECT rc; + ListView_GetSubItemRect(pnmh->hwndFrom,pDraw->nmcd.dwItemSpec,pDraw->iSubItem,LVIR_BOUNDS,&rc); + DWORD color; +#ifndef READ_COLORS + if (g_MetroColors[pDraw->nmcd.lItemlParam].type<=g_MaxMetroColorType) + { + int set=m_ColorSet>=0?m_ColorSet:GetImmersiveUserColorSetPreference(false,false); + color=GetImmersiveColorFromColorSetEx(set,g_MetroColors[pDraw->nmcd.lItemlParam].type,true,0); + } + else +#endif + color=g_MetroColors[pDraw->nmcd.lItemlParam].color; + SetDCBrushColor(pDraw->nmcd.hdc,color&0xFFFFFF); + FillRect(pDraw->nmcd.hdc,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + return CDRF_SKIPDEFAULT; + } + return CDRF_DODEFAULT; +} + +LRESULT CMetroColorViewer::OnColumnClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMLISTVIEW *pSort=(NMLISTVIEW *)pnmh; + if (pSort->iSubItem==0 || pSort->iSubItem==1) + { + SetSortColumn(pSort->iSubItem); + ListView_SortItems(pnmh->hwndFrom,CompareFunc,m_SortColumn); + } + return 0; +} + +void ShowMetroColorViewer( void ) +{ +#ifndef READ_COLORS + HMODULE hUxTheme=LoadLibrary(L"uxtheme.dll"); + DWORD ver=GetVersionEx(hUxTheme); + if (hUxTheme && ver>=0x6020000) + { + GetImmersiveUserColorSetPreference=(TGetImmersiveUserColorSetPreference)GetProcAddress(hUxTheme,MAKEINTRESOURCEA(98)); + GetImmersiveColorFromColorSetEx=(TGetImmersiveColorFromColorSetEx)GetProcAddress(hUxTheme,MAKEINTRESOURCEA(95)); + GetImmersiveColorSetCount=(TGetImmersiveColorSetCount)GetProcAddress(hUxTheme,MAKEINTRESOURCEA(94)); + GetImmersiveColorNamedTypeByIndex=(TGetImmersiveColorNamedTypeByIndex)GetProcAddress(hUxTheme,MAKEINTRESOURCEA(100)); + GetImmersiveColorTypeFromName=(TGetImmersiveColorTypeFromName)GetProcAddress(hUxTheme,MAKEINTRESOURCEA(96)); + } + if (GetImmersiveUserColorSetPreference && GetImmersiveColorFromColorSetEx && GetImmersiveColorSetCount && GetImmersiveColorNamedTypeByIndex && GetImmersiveColorTypeFromName) +#endif + { +#ifdef READ_COLORS + FILE *fin=NULL; + fopen_s(&fin,"d:\\colors.txt","rt"); +#endif +#ifdef WRITE_COLORS + FILE *fout=NULL; + fopen_s(&fout,"d:\\colors.txt","wt"); +#endif +#ifndef READ_COLORS + int set=GetImmersiveUserColorSetPreference(false,false); +#endif + g_MaxMetroColorType=0; + for (int i=0;;i++) + { + const wchar_t *name=NULL; + int type=i; + COLORREF color=0; + +#ifdef READ_COLORS + char buf[200]={0}; + if (fin) fgets(buf,_countof(buf),fin); +#endif + wchar_t text[256]; +#ifdef READ_COLORS + CStringW str; + if (Strlen(buf)>9) + { + str=buf+9; + str.Trim(L"\r\n"); + name=str; + } +#else + const wchar_t **ptr=GetImmersiveColorNamedTypeByIndex(i); + if (ptr) + name=*ptr; +#endif + if (!name) + break; + Sprintf(text,_countof(text),L"Immersive%s",name); +#ifdef READ_COLORS + char *end; + color=strtoul(buf,&end,16); + color=(color&0xFF00FF00)|((color>>16)&0xFF)|((color&0xFF)<<16); +#else + type=GetImmersiveColorTypeFromName(text); +#endif +#ifdef WRITE_COLORS + color=GetImmersiveColorFromColorSetEx(set,type,true,0); + if (fout) fprintf(fout,"%02X%02X%02X%02X %S\n",(color>>24)&0xFF,color&0xFF,(color>>8)&0xFF,(color>>16)&0xFF,name); +#endif + MetroColor mc; + mc.name=name; + mc.NAME=mc.name; + mc.NAME.MakeUpper(); + mc.type=type; + if (g_MaxMetroColorType +#include +#include +#include "ResourceHelper.h" +#include "ComHelper.h" +#include "StringUtils.h" +#include "Settings.h" +#include +#include +#include +#include +#include +#define SECURITY_WIN32 +#include +#include +#include +#include + +extern HINSTANCE g_hInstance; + +struct CompareStrings +{ + bool operator()( const CString &str1, const CString &str2 ) const + { + return _wcsicmp(str1,str2)<0; + } +}; + +const CLSID CLSID_CSearchManager2={0x7D096C5F,0xAC08,0x4f1f,{0xBE,0xB7,0x5C,0x22,0xC5,0x17,0xCE,0x39}}; + +/////////////////////////////////////////////////////////////////////////////// +// dummy functions + +void ClosingSettings( HWND hWnd, int flags, int command ) +{ +} + +void SettingChangedCallback( const CSetting *pSetting ) +{ +} + +void UpgradeSettings( bool bShared ) +{ +} + +void UpdateSettings( void ) +{ +} + +const wchar_t *GetDocRelativePath( void ) +{ + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +static const wchar_t *g_Tabs=L"\t\t\t\t\t\t\t\t\t\t"; +static const wchar_t *GetTabs( int count ) +{ + if (count>10) count=10; + return g_Tabs+(10-count); +} + +DWORD GetFileVersion( const wchar_t *fname, DWORD *pBuild ) +{ + DWORD dwHandle; + DWORD dwLen=GetFileVersionInfoSize(fname,&dwHandle); + if (!dwLen) + return 0; + + std::vector buf(dwLen); + if (!GetFileVersionInfo(fname,dwHandle,dwLen,&buf[0])) + return 0; + + VS_FIXEDFILEINFO *pFileInfo; + UINT len; + if (!VerQueryValue(&buf[0],L"\\",(void**)&pFileInfo,&len)) + return 0; + if (pBuild) + *pBuild=LOWORD(pFileInfo->dwFileVersionLS); + return (HIWORD(pFileInfo->dwFileVersionMS)<<24)|(LOWORD(pFileInfo->dwFileVersionMS)<<16)|HIWORD(pFileInfo->dwFileVersionLS); +} + +static LONG ReadRegistryValue( HKEY root, const wchar_t *keyName, const wchar_t *valName, DWORD &value ) +{ + CRegKey regKey; + LONG res=regKey.Open(root,keyName,KEY_READ|KEY_WOW64_64KEY); + if (res==ERROR_SUCCESS) + res=regKey.QueryDWORDValue(valName,value); + return res; +} + +static LONG ReadRegistryValue( HKEY root, const wchar_t *keyName, const wchar_t *valName, CString &value ) +{ + value.Empty(); + wchar_t text[1024]; + ULONG size=_countof(text); + CRegKey regKey; + LONG res=regKey.Open(root,keyName,KEY_READ|KEY_WOW64_64KEY); + if (res==ERROR_SUCCESS) + { + res=regKey.QueryStringValue(valName,text,&size); + if (res==ERROR_SUCCESS) + value=text; + } + return res; +} + +static void WriteRegKey( FILE *f, CRegKey &key, int tabs, const wchar_t *annotations[][2]=NULL ) +{ + std::vector buf(65536); + for (int index=0;;index++) + { + wchar_t name[256]; + DWORD len=_countof(name); + DWORD type; + DWORD size=(int)buf.size(); + if (RegEnumValue(key,index,name,&len,NULL,&type,&buf[0],&size)!=ERROR_SUCCESS) + break; + fwprintf(f,L"%s%s: ",GetTabs(tabs),name); + switch (type) + { + case REG_DWORD: + { + DWORD val=*(DWORD*)&buf[0]; + fwprintf(f,L"0x%08X (%d)",val,val); + } + break; + case REG_SZ: + case REG_EXPAND_SZ: + { + CString val=(wchar_t*)&buf[0]; + val.Replace(L"\r",L"\\r"); + val.Replace(L"\n",L"\\n"); + fwprintf(f,L"%s",val); + } + break; + case REG_MULTI_SZ: + for (const wchar_t *str=(wchar_t*)&buf[0];*str;str+=Strlen(str)+1) + { + CString val=str; + val.Replace(L"\r",L"\\r"); + val.Replace(L"\n",L"\\n"); + fwprintf(f,L"%s\\0",val); + } + break; + } + if (annotations) + { + for (const wchar_t **a=&annotations[0][0];*a;a+=2) + { + if (_wcsicmp(a[0],name)==0) + { + fwprintf(f,L" - %s",a[1]); + break; + } + } + } + fwprintf(f,L"\r\n"); + } +} + +static void WriteFolder( FILE *f, const wchar_t *path, int tabs, bool bRecursive ) +{ + wchar_t find[_MAX_PATH]; + Sprintf(find,_countof(find),L"%s\\*.*",path); + std::vector folders; + WIN32_FIND_DATA data; + HANDLE h=FindFirstFile(find,&data); + while (h!=INVALID_HANDLE_VALUE) + { + wchar_t fname[_MAX_PATH]; + Sprintf(fname,_countof(fname),L"%s\\%s",path,data.cFileName); + if (data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) + { + if (bRecursive && wcscmp(data.cFileName,L".")!=0 && wcscmp(data.cFileName,L"..")!=0) + folders.push_back(fname); + } + else + { + fwprintf(f,L"%s%s",GetTabs(tabs),data.cFileName); + FILETIME localTime; + FileTimeToLocalFileTime(&data.ftLastWriteTime,&localTime); + SYSTEMTIME sysTime; + FileTimeToSystemTime(&localTime,&sysTime); + fwprintf(f,L", date: %04d/%02d/%02d, time: %02d:%02d:%02d",sysTime.wYear,sysTime.wMonth,sysTime.wDay,sysTime.wHour,sysTime.wMinute,sysTime.wSecond); + const wchar_t *ext=PathFindExtension(data.cFileName); + if (_wcsicmp(ext,L".lnk")==0) + { + // find target, args and appid + CComPtr pItem; + SHCreateItemFromParsingName(fname,NULL,IID_IShellItem,(void**)&pItem); + if (pItem) + { + CComPtr pLink; + if (SUCCEEDED(pItem->BindToHandler(NULL,BHID_SFUIObject,IID_IShellLink,(void**)&pLink))) + { + CComPtr pTarget; + CComString target; + CAbsolutePidl pidl; + if (FAILED(pLink->GetIDList(&pidl))) + fwprintf(f,L" target='no pidl'"); + else if (FAILED(SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pTarget))) + fwprintf(f,L" target='no item'"); + else if (FAILED(pTarget->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&target))) + fwprintf(f,L" target='no name'"); + else + fwprintf(f,L" target='%s'",target); + wchar_t args[256]; + if (FAILED(pLink->GetArguments(args,_countof(args)))) + args[0]=0; + CComQIPtr pStore=pLink; + CString appid; + if (pStore) + { + PROPVARIANT val; + PropVariantInit(&val); + if (SUCCEEDED(pStore->GetValue(PKEY_AppUserModel_ID,&val)) && val.vt==VT_BSTR && val.bstrVal) + appid=val.bstrVal; + PropVariantClear(&val); + if (!args[0] && SUCCEEDED(pStore->GetValue(PKEY_Link_Arguments,&val)) && val.vt==VT_BSTR && val.bstrVal) + Strcpy(args,_countof(args),val.bstrVal); + PropVariantClear(&val); + } + if (args[0]) + fwprintf(f,L" args='%s'",args); + if (!appid.IsEmpty()) + fwprintf(f,L" appid='%s'",appid); + } + } + } + else + { + DWORD build; + DWORD ver=GetFileVersion(fname,&build); + if (ver) + fwprintf(f,L", version: %d.%d.%d.%d",ver>>24,(ver>>16)&255,ver&65535,build); + if (_wcsicmp(ext,L".exe")==0) + { + CString policy; + ReadRegistryValue(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers",fname,policy); + if (!policy.IsEmpty()) + fwprintf(f,L" usercompat='%s'",policy); + ReadRegistryValue(HKEY_LOCAL_MACHINE,L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers",fname,policy); + if (!policy.IsEmpty()) + fwprintf(f,L" compat='%s'",policy); + } + } + fwprintf(f,L"\r\n"); + } + if (!FindNextFile(h,&data)) + { + FindClose(h); + break; + } + } + for (std::vector::const_iterator it=folders.begin();it!=folders.end();++it) + { + fwprintf(f,L"%s%s\r\n",GetTabs(tabs),PathFindFileName(*it)); + WriteFolder(f,*it,tabs+1,true); + } +} + +static void WriteSettings( FILE *f, TSettingsComponent component ) +{ + CRegKey regSettings, regSettingsUser, regPolicy, regPolicyUser; + bool bUpgrade=OpenSettingsKeys(component,regSettings,regSettingsUser,regPolicy,regPolicyUser); + if (regSettingsUser) + { + fwprintf(f,L"\t\t%s:\r\n",bUpgrade?L"User settings (old)":L"User settings"); + WriteRegKey(f,regSettingsUser,3); + fwprintf(f,L"\r\n"); + } + if (regSettings) + { + fwprintf(f,L"\t\tCommon settings:\r\n"); + WriteRegKey(f,regSettings,3); + fwprintf(f,L"\r\n"); + } + if (regPolicyUser) + { + fwprintf(f,L"\t\tUser policies:\r\n"); + WriteRegKey(f,regPolicyUser,3); + fwprintf(f,L"\r\n"); + } + if (regPolicy) + { + fwprintf(f,L"\t\tCommon policies:\r\n"); + WriteRegKey(f,regPolicy,3); + fwprintf(f,L"\r\n"); + } +} + +static void WriteProcessInfo( FILE *f, HANDLE hProcess, int tabs ) +{ + HMODULE hMods[1024]; + std::set names; + DWORD cbNeeded; + if (EnumProcessModules(hProcess,hMods,sizeof(hMods),&cbNeeded)) + { + int count=cbNeeded/sizeof(HMODULE); + for (int i=0;i::const_iterator it=names.begin();it!=names.end();++it) + { + DWORD ver=GetFileVersion(*it,NULL); + fwprintf(f,L"%s%s (%d.%d.%d)\r\n",GetTabs(tabs),*it,ver>>24,(ver>>16)&255,ver&65535); + } +} + +PROPERTYKEY PKEY_ProductVersion={{0x0CEF7D53, 0xFA64, 0x11D1, {0xA2, 0x03, 0x00, 0x00, 0xF8, 0x1F, 0xED, 0xEE}}, 8}; + +static BOOL CALLBACK MonitorEnumProc( HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData ) +{ + FILE *f=(FILE*)dwData; + HWND taskbar=FindWindowEx(NULL,NULL,L"Shell_TrayWnd",NULL); + HMONITOR mon=taskbar?MonitorFromWindow(taskbar,MONITOR_DEFAULTTONULL):NULL; + if (mon!=hMonitor) + { + for (taskbar=FindWindowEx(NULL,NULL,L"Shell_SecondaryTrayWnd",NULL);taskbar;taskbar=FindWindowEx(NULL,taskbar,L"Shell_SecondaryTrayWnd",NULL)) + { + mon=MonitorFromWindow(taskbar,MONITOR_DEFAULTTONULL); + if (mon==hMonitor) + break; + } + } + fwprintf(f,L"\tMonitor: %d, %d - (%d x %d)\r\n",lprcMonitor->left,lprcMonitor->top,lprcMonitor->right-lprcMonitor->left,lprcMonitor->bottom-lprcMonitor->top); + if (mon==hMonitor) + { + RECT rc; + GetWindowRect(taskbar,&rc); + fwprintf(f,L"\t\tTaskbar: %d, %d - (%d x %d)\r\n",rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top); + } + return TRUE; +} + +static const wchar_t *g_ExplorerRegAnnotations[][2]={ + {L"Start_TrackDocs",L"track documents"}, + {L"Start_TrackProgs",L"track programs"}, + {L"TaskbarSizeMove",L"unlocked taskbar"}, + {L"TaskbarSmallIcons",L"small icons"}, + {NULL} +}; + +struct GroupInfo +{ + CString desc; + CString group; + const wchar_t *status; +}; + +static void WriteLogFile( FILE *f ) +{ + // windows version + BOOL b64=FALSE; +#ifdef _WIN64 + b64=TRUE; +#else + IsWow64Process(GetCurrentProcess(),&b64); +#endif + DWORD winVer=GetVersionEx(GetModuleHandle(L"user32.dll")); + fwprintf(f,L"System\r\n"); + fwprintf(f,L"\tWindows version (real): %d.%02d.%d %d-bit\r\n",(winVer>>24),(winVer>>16)&255,winVer&65535,b64?64:32); + DWORD ver2=GetWinVersion(); + fwprintf(f,L"\tWindows version (reported): %d.%02d\r\n",(ver2>>8),ver2&255); + CString strVer1, strVer2; + ReadRegistryValue(HKEY_LOCAL_MACHINE,L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",L"ProductName",strVer1); + ReadRegistryValue(HKEY_LOCAL_MACHINE,L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",L"CurrentVersion",strVer2); + fwprintf(f,L"\tWindows version (registry): %s %s\r\n",strVer1,strVer2); + + wchar_t user1[256]={0}, user2[256]={0}; + ULONG size=_countof(user1); + GetComputerName(user1,&size); + fwprintf(f,L"\tComputer: %s\r\n",user1); + size=_countof(user1); + GetUserName(user1,&size); + size=_countof(user2); + if (GetUserNameEx(NameDisplay,user2,&size)) + fwprintf(f,L"\tUser: %s (%s)\r\n",user1,user2); + else + fwprintf(f,L"\tUser: %s (0x%08X)\r\n",user1,GetLastError()); + + { + wchar_t languages[100]; + ULONG count=0; + ULONG len=_countof(languages); + GetUserPreferredUILanguages(MUI_LANGUAGE_NAME,&size,languages,&len); + if (len>1) + { + for (ULONG i=0;i1) + { + for (ULONG i=0;i=2) + touchCaps[Strlen(touchCaps)-2]=0; + else + Strcpy(touchCaps,_countof(touchCaps),L"None"); + fwprintf(f,L"\tTouch capabilities: %s\r\n",touchCaps); + } + + { + CComString pPath; + if (FAILED(SHGetKnownFolderPath(FOLDERID_StartMenu,0,NULL,&pPath))) + pPath.Clear(); + fwprintf(f,L"\tStart Menu folder: '%s'\r\n",pPath?pPath:L""); + pPath.Clear(); + if (FAILED(SHGetKnownFolderPath(FOLDERID_Programs,0,NULL,&pPath))) + pPath.Clear(); + fwprintf(f,L"\tPrograms folder: '%s'\r\n",pPath?pPath:L""); + pPath.Clear(); + if (FAILED(SHGetKnownFolderPath(FOLDERID_CommonStartMenu,0,NULL,&pPath))) + pPath.Clear(); + fwprintf(f,L"\tCommon Start Menu folder: '%s'\r\n",pPath?pPath:L""); + pPath.Clear(); + if (FAILED(SHGetKnownFolderPath(FOLDERID_CommonPrograms,0,NULL,&pPath))) + pPath.Clear(); + fwprintf(f,L"\tCommon Programs folder: '%s'\r\n",pPath?pPath:L""); + } + if (HIWORD(winVer) pSysInfo; + pSysInfo.CoCreateInstance(CLSID_SystemInformation); + if (pSysInfo) + { + VARIANT_BOOL reboot; + if (SUCCEEDED(pSysInfo->get_RebootRequired(&reboot)) && reboot) + { + fwprintf(f,L"\tWindows Update: Reboot required\r\n"); + } + } + } + + if (HIWORD(winVer)>=WIN_VER_WIN81) + { + DWORD metro; + if (ReadRegistryValue(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage",L"OpenAtLogon",metro)==ERROR_SUCCESS) + fwprintf(f,L"\tSkip to Desktop: %d\r\n",1-metro); + else + fwprintf(f,L"\tSkip to Desktop: unset\r\n"); + } + + { + CRegKey regKey; + const wchar_t *key=L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"; + if (regKey.Open(HKEY_CURRENT_USER,key,KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + fwprintf(f,L"\t\r\n\tHKCU\\%s:\r\n",key); + WriteRegKey(f,regKey,2,g_ExplorerRegAnnotations); + fwprintf(f,L"\r\n"); + } + } + + fwprintf(f,L"\tPolicies:\r\n"); + fwprintf(f,L"\t\tSHRestricted(REST_HASFINDCOMPUTERS)=%d\r\n",SHRestricted(REST_HASFINDCOMPUTERS)); + fwprintf(f,L"\t\tSHRestricted(REST_NOCHANGESTARMENU)=%d\r\n",SHRestricted(REST_NOCHANGESTARMENU)); + fwprintf(f,L"\t\tSHRestricted(REST_NOCLOSE)=%d\r\n",SHRestricted(REST_NOCLOSE)); + fwprintf(f,L"\t\tSHRestricted(REST_NOCOMMONGROUPS)=%d\r\n",SHRestricted(REST_NOCOMMONGROUPS)); + fwprintf(f,L"\t\tSHRestricted(REST_NOCONTROLPANEL)=%d\r\n",SHRestricted(REST_NOCONTROLPANEL)); + fwprintf(f,L"\t\tSHRestricted(REST_NODISCONNECT)=%d\r\n",SHRestricted(REST_NODISCONNECT)); + fwprintf(f,L"\t\tSHRestricted(REST_NOFAVORITESMENU)=%d\r\n",SHRestricted(REST_NOFAVORITESMENU)); + fwprintf(f,L"\t\tSHRestricted(REST_NOFIND)=%d\r\n",SHRestricted(REST_NOFIND)); + fwprintf(f,L"\t\tSHRestricted(REST_NONETWORKCONNECTIONS)=%d\r\n",SHRestricted(REST_NONETWORKCONNECTIONS)); + fwprintf(f,L"\t\tSHRestricted(REST_NORECENTDOCSMENU)=%d\r\n",SHRestricted(REST_NORECENTDOCSMENU)); + fwprintf(f,L"\t\tSHRestricted(REST_NORUN)=%d\r\n",SHRestricted(REST_NORUN)); + fwprintf(f,L"\t\tSHRestricted(REST_NOSETFOLDERS)=%d\r\n",SHRestricted(REST_NOSETFOLDERS)); + fwprintf(f,L"\t\tSHRestricted(REST_NOSETTASKBAR)=%d\r\n",SHRestricted(REST_NOSETTASKBAR)); + fwprintf(f,L"\t\tSHRestricted(REST_NOSMEJECTPC)=%d\r\n",SHRestricted(REST_NOSMEJECTPC)); + fwprintf(f,L"\t\tSHRestricted(REST_NOSMHELP)=%d\r\n",SHRestricted(REST_NOSMHELP)); + fwprintf(f,L"\t\tSHRestricted(REST_NOSMMYDOCS)=%d\r\n",SHRestricted(REST_NOSMMYDOCS)); + fwprintf(f,L"\t\tSHRestricted(REST_NOSTRCMPLOGICAL)=%d\r\n",SHRestricted(REST_NOSTRCMPLOGICAL)); + fwprintf(f,L"\t\tSHRestricted(REST_STARTMENULOGOFF)=%d\r\n",SHRestricted(REST_STARTMENULOGOFF)); + fwprintf(f,L"\t\tSHRestricted(REST_FORCESTARTMENULOGOFF)=%d\r\n",SHRestricted(REST_FORCESTARTMENULOGOFF)); + + { + CRegKey regKey; + const wchar_t *key=L"Software\\Microsoft\\Windows\\CurrentVersion\\Run"; + if (regKey.Open(HKEY_LOCAL_MACHINE,key,KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + fwprintf(f,L"\r\n\tHKLM\\%s:\r\n",key); + WriteRegKey(f,regKey,2); + fwprintf(f,L"\r\n"); + } + } + + { + CRegKey regKey; + const wchar_t *key=L"Software\\Microsoft\\Windows\\CurrentVersion\\Run"; + if (regKey.Open(HKEY_CURRENT_USER,key,KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + fwprintf(f,L"\r\n\tHKCU\\%s:\r\n",key); + WriteRegKey(f,regKey,2); + fwprintf(f,L"\r\n"); + } + } + + { + CComString pPath; + if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Startup,0,NULL,&pPath))) + { + fwprintf(f,L"\r\n\t%s:\r\n",pPath); + WriteFolder(f,pPath,2,false); + fwprintf(f,L"\r\n"); + } + } + + { + CComString pPath; + if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_CommonStartup,0,NULL,&pPath))) + { + fwprintf(f,L"\r\n\t%s:\r\n",pPath); + WriteFolder(f,pPath,2,false); + fwprintf(f,L"\r\n"); + } + } + + { + CComPtr pSearchManager; + pSearchManager.CoCreateInstance(CLSID_CSearchManager2); + if (pSearchManager) + { + CComPtr pCatalogManager; + pSearchManager->GetCatalog(L"SystemIndex",&pCatalogManager); + if (pCatalogManager) + { + CComPtr pSearchCrawlScopeManager; + pCatalogManager->GetCrawlScopeManager(&pSearchCrawlScopeManager); + if (pSearchCrawlScopeManager) + { + CComPtr pSearchRoots; + pSearchCrawlScopeManager->EnumerateRoots(&pSearchRoots); + if (pSearchRoots) + { + fwprintf(f,L"\r\nSearch Roots:\r\n"); + CComPtr pSearchRoot; + while (pSearchRoots->Next(1,&pSearchRoot,NULL)==S_OK) + { + PWSTR pszUrl=NULL; + if (SUCCEEDED(pSearchRoot->get_RootURL(&pszUrl))) + { + fwprintf(f,L"\t%s\r\n",pszUrl); + CoTaskMemFree(pszUrl); + } + pSearchRoot=NULL; + } + fwprintf(f,L"\r\n"); + } + + CComPtr pSearchRules; + pSearchCrawlScopeManager->EnumerateScopeRules(&pSearchRules); + if (pSearchRoots) + { + fwprintf(f,L"Search Rules:\r\n"); + CComPtr pSearchRule; + while (pSearchRules->Next(1,&pSearchRule,NULL)==S_OK) + { + BOOL fIncluded=FALSE; + pSearchRule->get_IsIncluded(&fIncluded); + PWSTR pszUrl=NULL; + if (SUCCEEDED(pSearchRule->get_PatternOrURL(&pszUrl))) + { + fwprintf(f,L"\t%s: %s\r\n",fIncluded?L"Include":L"Exclude",pszUrl); + CoTaskMemFree(pszUrl); + } + pSearchRule=NULL; + } + fwprintf(f,L"\r\n"); + } + } + } + } + } + + // programs + fwprintf(f,L"\r\n\tInstalled Programs:\r\n"); + std::set programs; + + CComPtr pPrograms; + SHGetKnownFolderItem(FOLDERID_ChangeRemovePrograms,KF_FLAG_DEFAULT,NULL,IID_IShellItem,(void**)&pPrograms); + if (pPrograms) + { + CComPtr pEnum; + pPrograms->BindToHandler(NULL,BHID_EnumItems,IID_IEnumShellItems,(void**)&pEnum); + CComPtr pProgram; + while (pEnum && (pProgram=NULL,pEnum->Next(1,&pProgram,NULL))==S_OK) + { + CComString pName; + pProgram->GetDisplayName(SIGDN_NORMALDISPLAY,&pName); + CString name=pName; + CComQIPtr pProgram2=pProgram; + if (pProgram2) + { + CComString pVersion; + if (SUCCEEDED(pProgram2->GetString(PKEY_ProductVersion,&pVersion))) + name+=L" ("+CString(pVersion)+L")"; + } + programs.insert(name); + } + } + + for (std::set::const_iterator it=programs.begin();it!=programs.end();++it) + fwprintf(f,L"\t\t%s\r\n",*it); + + fwprintf(f,L"\r\nClassic Shell\r\n"); + wchar_t csPath[_MAX_PATH]=L""; + // classic shell version + { + CRegKey regKey; + DWORD err=regKey.Open(HKEY_LOCAL_MACHINE,L"Software\\IvoSoft\\ClassicShell",KEY_READ|KEY_WOW64_64KEY); + if (err!=ERROR_SUCCESS) + { + fwprintf(f,L"\tFailed to read HKLM\\Software\\IvoSoft\\ClassicShell - 0x%08X\r\n",err); + } + else + { + wchar_t language[100]=L""; + ULONG size=_countof(language); + if (regKey.QueryStringValue(L"DefaultLanguage",language,&size)==ERROR_SUCCESS) + fwprintf(f,L"\tDefault language: '%s'\r\n",language); + + size=_countof(csPath); + if (regKey.QueryStringValue(L"Path",csPath,&size)==ERROR_SUCCESS) + { + fwprintf(f,L"\tClassic Shell path: '%s'\r\n",csPath); + PathRemoveBackslash(csPath); + } + + DWORD val; + if (regKey.QueryDWORDValue(L"Version",val)==ERROR_SUCCESS) + fwprintf(f,L"\tClassic Shell version: %d.%d.%d\r\n",val/10000,(val/100)%100,val%100); + + if (regKey.QueryDWORDValue(L"WinVersion",val)==ERROR_SUCCESS) + fwprintf(f,L"\tWin version during installation: %d.%02d.%d\r\n",val>>24,(val>>16)&0xFF,val&0xFFFF); + } + } + + // language files + fwprintf(f,L"\t%s:\r\n",csPath); + if (csPath[0]) + WriteFolder(f,csPath,2,true); + + { + wchar_t path[_MAX_PATH]; + Strcpy(path,_countof(path),L"%ALLUSERSPROFILE%\\ClassicShell"); + DoEnvironmentSubst(path,_countof(path)); + fwprintf(f,L"\t%s:\r\n",path); + WriteFolder(f,path,2,true); + } + + // installed components and settings + wchar_t fname[_MAX_PATH]; + Sprintf(fname,_countof(fname),L"%s\\ClassicExplorer32.dll",csPath); + bool bClassicExplorer=GetFileAttributes(fname)!=INVALID_FILE_ATTRIBUTES; + Sprintf(fname,_countof(fname),L"%s\\ClassicStartMenu.exe",csPath); + bool bClassicMenu=GetFileAttributes(fname)!=INVALID_FILE_ATTRIBUTES; + Sprintf(fname,_countof(fname),L"%s\\ClassicIE_32.exe",csPath); + bool bClassicIE=GetFileAttributes(fname)!=INVALID_FILE_ATTRIBUTES; + Sprintf(fname,_countof(fname),L"%s\\ClassicShellUpdate.exe",csPath); + bool bClassicUpdate=GetFileAttributes(fname)!=INVALID_FILE_ATTRIBUTES; + + fwprintf(f,L"\r\nInstalled components:\r\n"); + if (bClassicExplorer) + { + fwprintf(f,L" Classic Explorer\r\n"); + WriteSettings(f,COMPONENT_EXPLORER); + } + if (bClassicMenu) + { + fwprintf(f,L" Classic Start Menu\r\n"); + WriteSettings(f,COMPONENT_MENU); + } + if (bClassicIE) + { + fwprintf(f,L" Classic IE\r\n"); + WriteSettings(f,COMPONENT_IE); + } + if (bClassicUpdate) + { + fwprintf(f,L" Classic Shell Update\r\n\r\n"); + } + fwprintf(f,L" Shared Settings\r\n"); + WriteSettings(f,COMPONENT_SHARED); + + + // check for disabled addons + if (bClassicExplorer || bClassicIE) + { + fwprintf(f,L"Explorer addons:\r\n"); + CString text; + if (ReadRegistryValue(HKEY_CURRENT_USER,L"Software\\Microsoft\\Internet Explorer\\Main",L"Enable Browser Extensions",text)==ERROR_SUCCESS) + fwprintf(f,L"\tEnable Browser Extensions (user): %s\r\n",text); + if (ReadRegistryValue(HKEY_LOCAL_MACHINE,L"Software\\Microsoft\\Internet Explorer\\Main",L"Enable Browser Extensions",text)==ERROR_SUCCESS) + fwprintf(f,L"\tEnable Browser Extensions: %s\r\n",text); + if (ReadRegistryValue(HKEY_CURRENT_USER,L"Software\\Microsoft\\Internet Explorer\\Main",L"Isolation",text)==ERROR_SUCCESS) + fwprintf(f,L"\tIsolation (user): %s\r\n",text); + if (ReadRegistryValue(HKEY_LOCAL_MACHINE,L"Software\\Microsoft\\Internet Explorer\\Main",L"Isolation",text)==ERROR_SUCCESS) + fwprintf(f,L"\tIsolation: %s\r\n",text); + } + if (bClassicExplorer) + { + DWORD flags; + if (ReadRegistryValue(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Ext\\Settings\\{553891B7-A0D5-4526-BE18-D3CE461D6310}",L"Flags",flags)==ERROR_SUCCESS) + fwprintf(f,L"\tExplorerBand flags: 0x%08X\r\n",flags); + CString policy; + if (ReadRegistryValue(HKEY_LOCAL_MACHINE,L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Ext\\CLSID",L"{553891B7-A0D5-4526-BE18-D3CE461D6310}",policy)==ERROR_SUCCESS) + fwprintf(f,L"\tExplorerBand policy: %s\r\n",policy); + if (ReadRegistryValue(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Ext\\Settings\\{449D0D6E-2412-4E61-B68F-1CB625CD9E52}",L"Flags",flags)==ERROR_SUCCESS) + fwprintf(f,L"\tExplorerBHO flags: 0x%08X\r\n",flags); + if (ReadRegistryValue(HKEY_LOCAL_MACHINE,L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Ext\\CLSID",L"{449D0D6E-2412-4E61-B68F-1CB625CD9E52}",policy)==ERROR_SUCCESS) + fwprintf(f,L"\tExplorerBHO policy: %s\r\n",policy); + } + if (bClassicIE) + { + DWORD flags; + CString policy; + if (ReadRegistryValue(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Ext\\Settings\\{EA801577-E6AD-4BD5-8F71-4BE0154331A4}",L"Flags",flags)==ERROR_SUCCESS) + fwprintf(f,L"\tClassicIE flags: 0x%08X\r\n",flags); + if (ReadRegistryValue(HKEY_LOCAL_MACHINE,L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Ext\\CLSID",L"{EA801577-E6AD-4BD5-8F71-4BE0154331A4}",policy)==ERROR_SUCCESS) + fwprintf(f,L"\tClassicIE policy: %s\r\n",policy); + } + if (bClassicExplorer || bClassicIE) + fwprintf(f,L"\r\n"); + + if (bClassicMenu) + { + if (HIWORD(winVer)>=WIN_VER_WIN8) + { + CString guid; + LONG res=ReadRegistryValue(HKEY_CLASSES_ROOT,L"CLSID\\{ECD4FC4D-521C-11D0-B792-00A0C90312E1}\\TreatAs",NULL,guid); + if (res!=ERROR_SUCCESS) + fwprintf(f,L"TreatAs: 0x%08X\r\n",res); + else + { + if (guid.IsEmpty()) + guid=L"(empty)"; + fwprintf(f,L"TreatAs: %s%s\r\n",guid,_wcsicmp(guid,L"{D3214FBB-3CA1-406a-B3E8-3EB7C393A15E}")==0?L" (correct)":L" (wrong)"); + } + + CString emulation; + res=ReadRegistryValue(HKEY_CLASSES_ROOT,L"CLSID\\{D3214FBB-3CA1-406A-B3E8-3EB7C393A15E}",NULL,emulation); + if (res!=ERROR_SUCCESS) + fwprintf(f,L"Emulation: 0x%08X\r\n",res); + else + { + if (emulation.IsEmpty()) + emulation=L"(empty)"; + fwprintf(f,L"Emulation: %s%s\r\n",emulation,_wcsicmp(emulation,L"StartMenuEmulation")==0?L" (correct)":L" (wrong)"); + } + + CString server; + res=ReadRegistryValue(HKEY_CLASSES_ROOT,L"CLSID\\{D3214FBB-3CA1-406A-B3E8-3EB7C393A15E}\\InprocServer32",NULL,server); + if (res!=ERROR_SUCCESS) + fwprintf(f,L"Server: 0x%08X\r\n",res); + else + { + const wchar_t *state=L" (wrong)"; + if (server.IsEmpty()) + server=L"(empty)"; + else if (GetFileAttributes(server)==INVALID_FILE_ATTRIBUTES) + state=L" (missing file)"; + else + state=L" (correct)"; + fwprintf(f,L"Server: %s%s\r\n",server,state); + } + } + } +} + +static void WriteLogFileAdmin( FILE *f ) +{ + fwprintf(f,L"\r\nServices:\r\n"); + { + CRegKey regKey; + if (regKey.Open(HKEY_LOCAL_MACHINE,L"SYSTEM\\ControlSet001\\Control\\ServiceGroupOrder",KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + WriteRegKey(f,regKey,1); + SC_HANDLE hManager=OpenSCManager(NULL,NULL,SC_MANAGER_ENUMERATE_SERVICE); + + if (hManager) + { + const wchar_t *status[]={ + L"", + L"stopped", + L"start pending", + L"stop pending", + L"running", + L"continue pending", + L"pause pending", + L"paused", + }; + std::vector buf(256*1024); + DWORD size=0, count=0, resume=0; + std::map services; + if (EnumServicesStatusEx(hManager,SC_ENUM_PROCESS_INFO,SERVICE_DRIVER|SERVICE_WIN32,SERVICE_STATE_ALL,&buf[0],(int)buf.size(),&size,&count,&resume,NULL)) + { + const ENUM_SERVICE_STATUS_PROCESS *pService=(ENUM_SERVICE_STATUS_PROCESS*)&buf[0]; + for (DWORD i=0;iServiceStatusProcess.dwCurrentState; + if (idx>=_countof(status)) idx=0; + GroupInfo &info=services[pService->lpServiceName]; + info.desc=pService->lpDisplayName; + info.status=status[idx]; + CString name; + name.Format(L"SYSTEM\\ControlSet001\\services\\%s",pService->lpServiceName); + ReadRegistryValue(HKEY_LOCAL_MACHINE,name,L"Group",info.group); + } + } + CloseServiceHandle(hManager); + for (std::map::const_iterator it=services.begin();it!=services.end();++it) + if (it->second.group.IsEmpty()) + fwprintf(f,L"\t%s (%s): %s\r\n",it->first,it->second.desc,it->second.status); + else + fwprintf(f,L"\t%s (%s): %s (%s)\r\n",it->first,it->second.desc,it->second.status,it->second.group); + } + } + + HANDLE hToken; + if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken)) + { + TOKEN_PRIVILEGES tp={1}; + if (LookupPrivilegeValue(NULL,L"SeDebugPrivilege",&tp.Privileges[0].Luid)) + tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; + AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL); + CloseHandle(hToken); + } + + // processes + fwprintf(f,L"\r\nProcesses:\r\n"); + std::vector explorers; + std::vector menus; + { + DWORD processes[1024]; + DWORD cbNeeded; + if (EnumProcesses(processes,sizeof(processes),&cbNeeded)) + { + int count=cbNeeded/sizeof(DWORD); + std::sort(processes,processes+count); + for (int i=0;iLabel.Sid,(DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTIL->Label.Sid)-1)); + if (dwIntegrityLevel>=SECURITY_MANDATORY_SYSTEM_RID) + level=L"System"; + else if (dwIntegrityLevel>=SECURITY_MANDATORY_HIGH_RID) + level=L"High"; + else if (dwIntegrityLevel>=SECURITY_MANDATORY_MEDIUM_RID) + level=L"Medium"; + else + level=L"Low"; + } + free(pTIL); + } + } + CloseHandle(hToken); + } + fwprintf(f,L" (%s integrity level)\r\n",level); + CloseHandle(hProcess); + } + } + } + } + + HWND progWin=FindWindowEx(NULL,NULL,L"Progman",NULL); + DWORD desktopId=0; + if (progWin) + GetWindowThreadProcessId(progWin,&desktopId); + + // interesting processes + for (std::vector::const_iterator it=explorers.begin();it!=explorers.end();++it) + { + fwprintf(f,L"\r\nExplorer process: %d%s\r\n",*it,(*it==desktopId)?L" (desktop)":L""); + HANDLE hProcess=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,*it); + if (hProcess) + { + WriteProcessInfo(f,hProcess,1); + CloseHandle(hProcess); + } + else + fwprintf(f,L"\tFailed to get modules\r\n"); + } + for (std::vector::const_iterator it=menus.begin();it!=menus.end();++it) + { + fwprintf(f,L"\r\nClassicStartMenu process: %d\r\n",*it); + HANDLE hProcess=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,*it); + if (hProcess) + { + WriteProcessInfo(f,hProcess,1); + CloseHandle(hProcess); + } + else + fwprintf(f,L"\tFailed to get modules\r\n"); + } +} + +int SaveLogFile( const wchar_t *fname, bool bAdmin ) +{ + FILE *f=NULL; + if (_wfopen_s(&f,fname,bAdmin?L"ab":L"wb")!=0 || !f) + return 1; + + fseek(f,0,SEEK_END); + if (ftell(f)==0) + fwrite(L"\xFEFF",2,1,f); + CoInitialize(NULL); + if (bAdmin) + WriteLogFileAdmin(f); + else + WriteLogFile(f); + fclose(f); + + if (!bAdmin) + { + wchar_t exe[_MAX_PATH]; + GetModuleFileName(NULL,exe,_countof(exe)); + wchar_t cmdLine[1024]; + Sprintf(cmdLine,_countof(cmdLine),L"saveloga \"%s\"",fname); + if ((int)ShellExecute(NULL,L"runas",exe,cmdLine,NULL,SW_SHOWNORMAL)<=32) + { + f=NULL; + if (_wfopen_s(&f,fname,L"ab")==0 && f) + { + WriteLogFileAdmin(f); + fclose(f); + } + } + } + + CoUninitialize(); + return 0; +} + +bool ExtractUtility64( const wchar_t *fname, wchar_t *exe ) +{ + FILE *f=NULL; + if (_wfopen_s(&f,fname,L"wb")!=0 || !f) + return false; + + fwprintf(f,L"\xFEFF"); + + + HRSRC hResInfo=FindResource(g_hInstance,MAKEINTRESOURCE(1),L"FILE"); + if (!hResInfo) + { + fwprintf(f,L"Error extracting ClassicShellUtility64.exe\r\n"); + fclose(f); + return false; + } + HGLOBAL hRes=LoadResource(g_hInstance,hResInfo); + void *ptr=LockResource(hRes); + DWORD size=SizeofResource(g_hInstance,hResInfo); + bool res=false; + Strcpy(exe,_MAX_PATH,L"%TEMP%\\ClassicShellUtility64.exe"); + DoEnvironmentSubst(exe,_MAX_PATH); + HANDLE h=CreateFile(exe,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); + if (h) + { + DWORD q; + res=(WriteFile(h,ptr,size,&q,NULL) && q==size); + CloseHandle(h); + } + if (!res) + fwprintf(f,L"Error saving %s\r\n",exe); + fclose(f); + return res; +} + +static void ShowSaveLogFileInternal( void ) +{ + // save log file + wchar_t fname[_MAX_PATH]; + fname[0]=0; + OPENFILENAME ofn={sizeof(ofn)}; + ofn.lpstrFilter=L"Text files (*.txt)\0*.txt\0"; + ofn.nFilterIndex=1; + ofn.lpstrFile=fname; + ofn.nMaxFile=_MAX_PATH; + ofn.lpstrTitle=L"Save log file"; + ofn.lpstrDefExt=L".txt"; + ofn.Flags=OFN_ENABLESIZING|OFN_EXPLORER|OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY|OFN_NOCHANGEDIR; + if (GetSaveFileName(&ofn)) + { + wchar_t exe[_MAX_PATH]; + BOOL bWow64=FALSE; + IsWow64Process(GetCurrentProcess(),&bWow64); + if (bWow64) + { + if (!ExtractUtility64(fname,exe)) + return; + } + else + GetModuleFileName(NULL,exe,_countof(exe)); + + STARTUPINFO startupInfo={sizeof(startupInfo)}; + PROCESS_INFORMATION processInfo; + memset(&processInfo,0,sizeof(processInfo)); + wchar_t cmdLine[1024]; + Sprintf(cmdLine,_countof(cmdLine),L"%s savelog \"%s\"",PathFindFileName(exe),fname); + if (CreateProcess(exe,cmdLine,NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) + { + CloseHandle(processInfo.hThread); + WaitForSingleObject(processInfo.hProcess,INFINITE); + CloseHandle(processInfo.hProcess); + } + } +} + +void ShowSaveLogFile( void ) +{ + CoInitialize(NULL); + ShowSaveLogFileInternal(); + CoUninitialize(); +} diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/SaveLogFile.h b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/SaveLogFile.h new file mode 100644 index 0000000..53c6a51 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/SaveLogFile.h @@ -0,0 +1,8 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +void ShowSaveLogFile( void ); +int SaveLogFile( const wchar_t *fname, bool bAdmin ); +DWORD GetFileVersion( const wchar_t *fname, DWORD *pBuild ); diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/resource.h b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/resource.h new file mode 100644 index 0000000..16251b6 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/resource.h @@ -0,0 +1,61 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ClassicShellUtility.rc +// +#define IDI_ICON1 101 +#define IDD_DIALOG1 102 +#define IDD_COLORS 102 +#define IDD_UNINSTALL 103 +#define IDD_UNINSTALL_RESULTS 104 +#define IDD_UNINSTALL_PROGRESS 105 +#define IDD_LOGSETTINGS 106 +#define IDC_EDIT1 1001 +#define IDC_SPIN1 1002 +#define IDC_LIST1 1003 +#define IDC_EDIT2 1004 +#define IDC_BUTTONBROWSEPATH 1005 +#define IDC_CHECKADMIN 1006 +#define IDC_CHECKSETTINGS 1007 +#define IDC_CHECKALLUSERS 1008 +#define IDC_SYSLINK1 1009 +#define IDC_EDITPATH 1010 +#define IDC_SYSLINKSTARTUP 1010 +#define IDC_STATICPATH 1011 +#define IDC_SYSLINKEXPLORER 1011 +#define IDC_STATICWARNING 1012 +#define IDC_SYSLINKIE 1012 +#define IDC_STATICRESULT 1013 +#define IDC_EDITRESULT 1014 +#define IDC_BUTTONREBOOT 1015 +#define IDC_BUTTONCLOSE 1016 +#define IDC_PROGRESS1 1017 +#define IDC_STATICWIAT 1018 +#define IDC_STATICWAIT 1018 +#define IDC_STATICALLUSERS 1019 +#define IDC_CHECKEXPLORER 1020 +#define IDC_CHECKSTARTUP 1022 +#define IDC_CHECKIE 1023 +#define IDC_CHECKEXECUTE 1028 +#define IDC_CHECKOPEN 1029 +#define IDC_CHECKITEMS 1030 +#define IDC_CHECKMOUSE 1031 +#define IDC_CHECKMFU 1032 +#define IDC_CHECKSEARCH 1033 +#define IDC_CHECKSEARCH_SQL 1034 +#define IDC_CHECKNEW 1035 +#define IDC_CHECKAPPS 1036 +#define IDC_CHECKCACHE 1037 +#define IDC_SYSLINKSTART 1038 +#define IDC_SYSLINKSTART2 1039 +#define IDC_SYSLINKCACHE 1039 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 108 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1039 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/tool.ico b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/tool.ico new file mode 100644 index 0000000..30b6d8e Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/ClassicShellUtility/tool.ico differ diff --git a/ClassicShellSrc/ClassicShellSetup/SetupHelper/SetupHelper.cpp b/ClassicShellSrc/ClassicShellSetup/SetupHelper/SetupHelper.cpp new file mode 100644 index 0000000..055db45 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/SetupHelper/SetupHelper.cpp @@ -0,0 +1,90 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#define STRICT_TYPED_ITEMIDS +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit +#include +#include +#include "ResourceHelper.h" + +HINSTANCE g_hInstance; + +/////////////////////////////////////////////////////////////////////////////// + +int ExitStartMenu( void ) +{ + HKEY hKey=NULL; + if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,L"SOFTWARE\\IvoSoft\\ClassicShell",0,NULL,REG_OPTION_NON_VOLATILE,KEY_READ|KEY_QUERY_VALUE|KEY_WOW64_64KEY,NULL,&hKey,NULL)==ERROR_SUCCESS) + { + DWORD type=0; + wchar_t path[_MAX_PATH]; + DWORD size=sizeof(path); + if (RegQueryValueEx(hKey,L"Path",0,&type,(BYTE*)path,&size)==ERROR_SUCCESS && type==REG_SZ) + { + STARTUPINFO startupInfo={sizeof(startupInfo)}; + PROCESS_INFORMATION processInfo; + memset(&processInfo,0,sizeof(processInfo)); + wcscat_s(path,L"ClassicStartMenu.exe"); + HANDLE h=CreateFile(path,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + if (h!=INVALID_HANDLE_VALUE) + { + CloseHandle(h); + wcscat_s(path,L" -exit"); + if (CreateProcess(NULL,path,NULL,NULL,TRUE,0,NULL,NULL,&startupInfo,&processInfo)) + { + CloseHandle(processInfo.hThread); + WaitForSingleObject(processInfo.hProcess,5000); + CloseHandle(processInfo.hProcess); + } + } + } + RegCloseKey(hKey); + } + HWND updateOwner=FindWindow(L"ClassicShellUpdate.COwnerWindow",NULL); + if (updateOwner) + PostMessage(updateOwner,WM_CLEAR,0,0); + return 0; +} + +int FixVersion( void ) +{ + HKEY hKey=NULL; + if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,L"SOFTWARE\\IvoSoft\\ClassicShell",0,NULL,REG_OPTION_NON_VOLATILE,KEY_READ|KEY_WRITE|KEY_WOW64_64KEY,NULL,&hKey,NULL)==ERROR_SUCCESS) + { + DWORD winVer=GetVersionEx(GetModuleHandle(L"user32.dll")); + RegSetValueEx(hKey,L"WinVersion",NULL,REG_DWORD,(BYTE*)&winVer,sizeof(DWORD)); + RegCloseKey(hKey); + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +// Setup Helper - performs custom actions during Classic Shell install/uninstall +// Usage: +// exitSM // exits the start menu if it is running +// fixVersion // sets the correct OS version + +int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstrCmdLine, int nCmdShow ) +{ +// MessageBox(NULL,lpstrCmdLine,L"Command Line",MB_OK|MB_SYSTEMMODAL); + + int count; + wchar_t *const *params=CommandLineToArgvW(lpstrCmdLine,&count); + if (!params) return 1; + + g_hInstance=hInstance; + + for (;count>0;count--,params++) + { + if (_wcsicmp(params[0],L"exitSM")==0) + { + return ExitStartMenu(); + } + if (_wcsicmp(params[0],L"fixVersion")==0) + { + return FixVersion(); + } + } + return 1; +} diff --git a/ClassicShellSrc/ClassicShellSetup/SetupHelper/SetupHelper.manifest b/ClassicShellSrc/ClassicShellSetup/SetupHelper/SetupHelper.manifest new file mode 100644 index 0000000..3012511 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/SetupHelper/SetupHelper.manifest @@ -0,0 +1,36 @@ + + + +Setup Helper + + + + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicShellSetup/SetupHelper/SetupHelper.vcproj b/ClassicShellSrc/ClassicShellSetup/SetupHelper/SetupHelper.vcproj new file mode 100644 index 0000000..235533f --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/SetupHelper/SetupHelper.vcproj @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/Flags/gd-GB.bmp b/ClassicShellSrc/ClassicShellSetup/UpdateBin/Flags/gd-GB.bmp new file mode 100644 index 0000000..a3cabea Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/UpdateBin/Flags/gd-GB.bmp differ diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/UpdateBin.rc b/ClassicShellSrc/ClassicShellSetup/UpdateBin/UpdateBin.rc new file mode 100644 index 0000000..8b31b0b Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/UpdateBin/UpdateBin.rc differ diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/UpdateBin.vcproj b/ClassicShellSrc/ClassicShellSetup/UpdateBin/UpdateBin.vcproj new file mode 100644 index 0000000..73bf15d --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/UpdateBin/UpdateBin.vcproj @@ -0,0 +1,951 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/resource.h b/ClassicShellSrc/ClassicShellSetup/UpdateBin/resource.h new file mode 100644 index 0000000..06d0a79 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/UpdateBin/resource.h @@ -0,0 +1,10 @@ +#define IDS_VERSION 16 +#define IDS_NEWS 17 +#define IDS_INSTALL_URL 18 +#define IDS_INSTALL_SIGNER 19 +#define IDS_LNG_URL 20 +#define IDS_LNG_VERSION 21 +#define IDS_LNG_CRC 22 +#define IDS_UPDATE_LINK 23 +#define IDS_LANGUAGE_LINK 24 +#define IDS_ALT_URL 25 diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.1.0.txt b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.1.0.txt new file mode 100644 index 0000000..9c7d268 Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.1.0.txt differ diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.0.txt b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.0.txt new file mode 100644 index 0000000..d401d1b Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.0.txt differ diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.1.txt b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.1.txt new file mode 100644 index 0000000..181ce7a Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.1.txt differ diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.2.txt b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.2.txt new file mode 100644 index 0000000..c4fe7e6 Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.2.txt differ diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.3.txt b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.3.txt new file mode 100644 index 0000000..244df88 Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.3.txt differ diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.4.txt b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.4.txt new file mode 100644 index 0000000..d8974cb Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.4.txt differ diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.5.txt b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.5.txt new file mode 100644 index 0000000..a82fa45 Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.5.txt differ diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.6.txt b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.6.txt new file mode 100644 index 0000000..5523b9d Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.6.txt differ diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.7.txt b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.7.txt new file mode 100644 index 0000000..b674d78 Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.2.7.txt differ diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.3.0.txt b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.3.0.txt new file mode 100644 index 0000000..4270010 Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.3.0.txt differ diff --git a/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.3.1.txt b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.3.1.txt new file mode 100644 index 0000000..c75f89e Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/UpdateBin/update_4.3.1.txt differ diff --git a/ClassicShellSrc/ClassicShellSetup/_BuildChineseCN.bat b/ClassicShellSrc/ClassicShellSetup/_BuildChineseCN.bat new file mode 100644 index 0000000..bb33ff2 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/_BuildChineseCN.bat @@ -0,0 +1,8 @@ +SET CS_LANG_FOLDER=Chinese +SET CS_LANG_NAME=zh-CN +SET CS_LANG_NAME_SHORT=zhCN +SET CS_HAS_HELP=0 +SET CS_HAS_EULA=1 +SET CS_HAS_README=1 + +call BuildInstaller.bat diff --git a/ClassicShellSrc/ClassicShellSetup/_BuildChineseTW.bat b/ClassicShellSrc/ClassicShellSetup/_BuildChineseTW.bat new file mode 100644 index 0000000..0188177 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/_BuildChineseTW.bat @@ -0,0 +1,8 @@ +SET CS_LANG_FOLDER=ChineseTW +SET CS_LANG_NAME=zh-TW +SET CS_LANG_NAME_SHORT=zhTW +SET CS_HAS_HELP=1 +SET CS_HAS_EULA=1 +SET CS_HAS_README=1 + +call BuildInstaller.bat diff --git a/ClassicShellSrc/ClassicShellSetup/_BuildEnglish.bat b/ClassicShellSrc/ClassicShellSetup/_BuildEnglish.bat new file mode 100644 index 0000000..29a4b3b --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/_BuildEnglish.bat @@ -0,0 +1,8 @@ +SET CS_LANG_FOLDER=English +SET CS_LANG_NAME=en-US +SET CS_LANG_NAME_SHORT=en +SET CS_HAS_HELP=1 +SET CS_HAS_EULA=1 +SET CS_HAS_README=1 + +call BuildInstaller.bat diff --git a/ClassicShellSrc/ClassicShellSetup/_BuildFrench.bat b/ClassicShellSrc/ClassicShellSetup/_BuildFrench.bat new file mode 100644 index 0000000..bf4ca3d --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/_BuildFrench.bat @@ -0,0 +1,8 @@ +SET CS_LANG_FOLDER=French +SET CS_LANG_NAME=fr-FR +SET CS_LANG_NAME_SHORT=fr +SET CS_HAS_HELP=1 +SET CS_HAS_EULA=1 +SET CS_HAS_README=1 + +call BuildInstaller.bat diff --git a/ClassicShellSrc/ClassicShellSetup/_BuildGerman.bat b/ClassicShellSrc/ClassicShellSetup/_BuildGerman.bat new file mode 100644 index 0000000..db41549 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/_BuildGerman.bat @@ -0,0 +1,8 @@ +SET CS_LANG_FOLDER=German +SET CS_LANG_NAME=de-DE +SET CS_LANG_NAME_SHORT=de +SET CS_HAS_HELP=0 +SET CS_HAS_EULA=1 +SET CS_HAS_README=1 + +call BuildInstaller.bat diff --git a/ClassicShellSrc/ClassicShellSetup/_BuildItalian.bat b/ClassicShellSrc/ClassicShellSetup/_BuildItalian.bat new file mode 100644 index 0000000..1ff54e2 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/_BuildItalian.bat @@ -0,0 +1,8 @@ +SET CS_LANG_FOLDER=Italian +SET CS_LANG_NAME=it-IT +SET CS_LANG_NAME_SHORT=it +SET CS_HAS_HELP=0 +SET CS_HAS_EULA=1 +SET CS_HAS_README=1 + +call BuildInstaller.bat diff --git a/ClassicShellSrc/ClassicShellSetup/_BuildPolish.bat b/ClassicShellSrc/ClassicShellSetup/_BuildPolish.bat new file mode 100644 index 0000000..c141d8d --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/_BuildPolish.bat @@ -0,0 +1,8 @@ +SET CS_LANG_FOLDER=Polish +SET CS_LANG_NAME=pl-PL +SET CS_LANG_NAME_SHORT=pl +SET CS_HAS_HELP=1 +SET CS_HAS_EULA=1 +SET CS_HAS_README=1 + +call BuildInstaller.bat diff --git a/ClassicShellSrc/ClassicShellSetup/_BuildRussian.bat b/ClassicShellSrc/ClassicShellSetup/_BuildRussian.bat new file mode 100644 index 0000000..7a0ec31 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/_BuildRussian.bat @@ -0,0 +1,8 @@ +SET CS_LANG_FOLDER=Russian +SET CS_LANG_NAME=ru-RU +SET CS_LANG_NAME_SHORT=ru +SET CS_HAS_HELP=1 +SET CS_HAS_EULA=1 +SET CS_HAS_README=1 + +call BuildInstaller.bat diff --git a/ClassicShellSrc/ClassicShellSetup/_BuildSpanish.bat b/ClassicShellSrc/ClassicShellSetup/_BuildSpanish.bat new file mode 100644 index 0000000..2444695 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/_BuildSpanish.bat @@ -0,0 +1,8 @@ +SET CS_LANG_FOLDER=Spanish +SET CS_LANG_NAME=es-ES +SET CS_LANG_NAME_SHORT=es +SET CS_HAS_HELP=1 +SET CS_HAS_EULA=1 +SET CS_HAS_README=1 + +call BuildInstaller.bat diff --git a/ClassicShellSrc/ClassicShellSetup/__MakeFinal.bat b/ClassicShellSrc/ClassicShellSetup/__MakeFinal.bat new file mode 100644 index 0000000..824e036 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/__MakeFinal.bat @@ -0,0 +1,9 @@ +@call BuildBinaries.bat +@if %CS_ERROR%==1 goto end + +@call _BuildEnglish.bat +@if %CS_ERROR%==1 goto end + +call BuildArchives.bat + +:end diff --git a/ClassicShellSrc/ClassicShellSetup/banner.jpg b/ClassicShellSrc/ClassicShellSetup/banner.jpg new file mode 100644 index 0000000..f1d2ce1 Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/banner.jpg differ diff --git a/ClassicShellSrc/ClassicShellSetup/dialog.jpg b/ClassicShellSrc/ClassicShellSetup/dialog.jpg new file mode 100644 index 0000000..b92341c Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/dialog.jpg differ diff --git a/ClassicShellSrc/ClassicShellSetup/dialog2.jpg b/ClassicShellSrc/ClassicShellSetup/dialog2.jpg new file mode 100644 index 0000000..dc0946b Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/dialog2.jpg differ diff --git a/ClassicShellSrc/ClassicShellSetup/donate.ico b/ClassicShellSrc/ClassicShellSetup/donate.ico new file mode 100644 index 0000000..d562fc4 Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/donate.ico differ diff --git a/ClassicShellSrc/ClassicShellSetup/en-US/en-US.rc b/ClassicShellSrc/ClassicShellSetup/en-US/en-US.rc new file mode 100644 index 0000000..8b4e784 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/en-US/en-US.rc @@ -0,0 +1,109 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "IvoSoft" + VALUE "FileDescription", "en-US" + VALUE "FileVersion", "1, 0, 0, 1" + VALUE "InternalName", "en-US" + VALUE "LegalCopyright", "Copyright (C) 2009-2016, Ivo Beltchev" + VALUE "OriginalFilename", "en-US" + VALUE "ProductName", "Classic Shell" + VALUE "ProductVersion", "1, 0, 0, 1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// L10N +// + +1 L10N "en-US.txt" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/ClassicShellSrc/ClassicShellSetup/en-US/en-US.txt b/ClassicShellSrc/ClassicShellSetup/en-US/en-US.txt new file mode 100644 index 0000000..7ff01fc Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/en-US/en-US.txt differ diff --git a/ClassicShellSrc/ClassicShellSetup/en-US/en-US.vcproj b/ClassicShellSrc/ClassicShellSetup/en-US/en-US.vcproj new file mode 100644 index 0000000..85765e1 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/en-US/en-US.vcproj @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicShellSetup/en-US/resource.h b/ClassicShellSrc/ClassicShellSetup/en-US/resource.h new file mode 100644 index 0000000..1727fe0 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/en-US/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by en-US.rc +// +#define IDR_L10N1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/ClassicShellSrc/ClassicShellSetup/facebook.ico b/ClassicShellSrc/ClassicShellSetup/facebook.ico new file mode 100644 index 0000000..98839e3 Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/facebook.ico differ diff --git a/ClassicShellSrc/ClassicShellSetup/resource.h b/ClassicShellSrc/ClassicShellSetup/resource.h new file mode 100644 index 0000000..64c72a4 --- /dev/null +++ b/ClassicShellSrc/ClassicShellSetup/resource.h @@ -0,0 +1,31 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ClassicShellSetup.rc +// +#define IDS_APP_NAME 100 +#define IDS_APP_TITLE 100 +#define IDI_APPICON 101 +#define IDS_OLDSTARTMENU 101 +#define IDS_ERR_CORRUPTED 102 +#define IDR_MSI_FILE32 132 +#define IDR_MSI_FILE64 164 +#define IDS_ERR_INTERNAL 166 +#define IDD_DIALOGPWD 166 +#define IDS_ERR_EXTRACT 167 +#define IDR_MSI_CHECKSUM 167 +#define IDS_ERR_WIN7 169 +#define IDS_ERR_MSIEXEC 170 +#define IDS_HELP 200 +#define IDC_EDIT1 1001 +#define IDC_EDITPWD 1001 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 168 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1002 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/ClassicShellSrc/ClassicShellSetup/web.ico b/ClassicShellSrc/ClassicShellSetup/web.ico new file mode 100644 index 0000000..1f8c012 Binary files /dev/null and b/ClassicShellSrc/ClassicShellSetup/web.ico differ diff --git a/ClassicShellSrc/ClassicShellUpdate/ClassicShellUpdate.cpp b/ClassicShellSrc/ClassicShellUpdate/ClassicShellUpdate.cpp new file mode 100644 index 0000000..5a20cf3 --- /dev/null +++ b/ClassicShellSrc/ClassicShellUpdate/ClassicShellUpdate.cpp @@ -0,0 +1,567 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#define STRICT_TYPED_ITEMIDS +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit +#include +#include +#include +#include +#include "resource.h" +#include "StringUtils.h" +#include "Settings.h" +#include "SettingsUIHelper.h" +#include "DownloadHelper.h" +#include "ResourceHelper.h" +#include "Translations.h" +#include + + +void ClosingSettings( HWND hWnd, int flags, int command ) +{ +} + +void SettingChangedCallback( const CSetting *pSetting ) +{ +} + +void UpgradeSettings( bool bShared ) +{ +} + +void UpdateSettings( void ) +{ + CRegKey regKey; + wchar_t language[100]=L""; + if (regKey.Open(HKEY_LOCAL_MACHINE,L"Software\\IvoSoft\\ClassicShell",KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + ULONG size=_countof(language); + if (regKey.QueryStringValue(L"DefaultLanguage",language,&size)!=ERROR_SUCCESS) + language[0]=0; + } + UpdateSetting(L"Language",language,false); +} + +const wchar_t *GetDocRelativePath( void ) +{ + return NULL; +} + +static int g_LoadDialogs[]= +{ + IDD_UPDATE,0x04000000, + IDD_PROGRESS,0x04000004, + 0 +}; + +static CSetting g_Settings[]={ +{L"Update",CSetting::TYPE_GROUP}, + {L"Language",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_SHARED}, + {L"Update",CSetting::TYPE_BOOL,0,0,1,CSetting::FLAG_SHARED}, + + {NULL} +}; + +const int SETTING_UPDATE=2; + +/////////////////////////////////////////////////////////////////////////////// + +class CUpdateDlg: public CResizeableDlg +{ +public: + CUpdateDlg( void ) { m_Version=GetVersionEx(g_Instance); m_Data.Clear(); m_Data.newVersion=0xFFFFFFFF; m_Font=NULL; } + BEGIN_MSG_MAP( CUpdateDlg ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + MESSAGE_HANDLER( WM_DESTROY, OnDestroy ) + MESSAGE_HANDLER( WM_SIZE, OnSize ) + MESSAGE_HANDLER( WM_GETMINMAXINFO, OnGetMinMaxInfo ) + MESSAGE_HANDLER( WM_CTLCOLORSTATIC, OnColorStatic ) + COMMAND_HANDLER( IDC_CHECKAUTOCHECK, BN_CLICKED, OnCheckAuto ) + COMMAND_HANDLER( IDC_BUTTONCHECKNOW, BN_CLICKED, OnCheckNow ) + COMMAND_HANDLER( IDC_BUTTONDOWNLOAD, BN_CLICKED, OnDownload ) + COMMAND_HANDLER( IDC_CHECKDONT, BN_CLICKED, OnDontRemind ) + COMMAND_HANDLER( IDOK, BN_CLICKED, OnOK ) + COMMAND_HANDLER( IDCANCEL, BN_CLICKED, OnCancel ) + NOTIFY_HANDLER( IDC_LINKWEB, NM_CLICK, OnWeb ) + NOTIFY_HANDLER( IDC_LINKWEB, NM_RETURN, OnWeb ) + END_MSG_MAP() + + BEGIN_RESIZE_MAP + RESIZE_CONTROL(IDC_STATICLATEST,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_EDITTEXT,MOVE_SIZE_X|MOVE_SIZE_Y) + RESIZE_CONTROL(IDC_BUTTONDOWNLOAD,MOVE_MOVE_Y) + RESIZE_CONTROL(IDC_CHECKDONT,MOVE_MOVE_Y) + RESIZE_CONTROL(IDC_LINKWEB,MOVE_MOVE_Y) + RESIZE_CONTROL(IDOK,MOVE_MOVE_X|MOVE_MOVE_Y) + RESIZE_CONTROL(IDCANCEL,MOVE_MOVE_X|MOVE_MOVE_Y) + END_RESIZE_MAP + + void Run( void ); + void UpdateData( void ); + bool HasNewLanguage( void ) { return (m_Data.bNewLanguage && !m_Data.bIgnoreLanguage) && !(m_Data.bNewVersion && !m_Data.bIgnoreVersion); } + +protected: + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnColorStatic( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnCheckAuto( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCheckNow( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnDownload( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnDontRemind( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnWeb( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + +private: + CWindow m_Tooltip; + VersionData m_Data; + DWORD m_Version; + HFONT m_Font; + + void UpdateUI( void ); + + static void NewVersionCallback( VersionData &data ); +}; + +static CUpdateDlg g_UpdateDlg; + +LRESULT CUpdateDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + InitResize(MOVE_MODAL); + + HICON icon=(HICON)LoadImage(g_Instance,MAKEINTRESOURCE(IDI_APPICON),IMAGE_ICON,GetSystemMetrics(SM_CXICON),GetSystemMetrics(SM_CYICON),LR_DEFAULTCOLOR); + SendMessage(WM_SETICON,ICON_BIG,(LPARAM)icon); + icon=(HICON)LoadImage(g_Instance,MAKEINTRESOURCE(IDI_APPICON),IMAGE_ICON,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),LR_DEFAULTCOLOR); + SendMessage(WM_SETICON,ICON_SMALL,(LPARAM)icon); + SetDlgItemText(IDC_STATICLATEST,L""); + + HDC hdc=::GetDC(NULL); + int dpi=GetDeviceCaps(hdc,LOGPIXELSY); + ::ReleaseDC(NULL,hdc); + m_Font=CreateFont(-9*dpi/72,0,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH,L"Consolas"); + if (m_Font) + GetDlgItem(IDC_EDITTEXT).SetFont(m_Font); + m_Tooltip.Create(TOOLTIPS_CLASS,m_hWnd,NULL,NULL,WS_POPUP|TTS_NOPREFIX); + + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS|TTF_IDISHWND,m_hWnd,(UINT_PTR)GetDlgItem(IDC_LINKWEB).m_hWnd}; + CString str=LoadStringEx(IDS_WEBSITE_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + m_Tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + bool check=true; + if (g_Settings[SETTING_UPDATE].value.vt==VT_I4) + check=g_Settings[SETTING_UPDATE].value.intVal!=0; + CheckDlgButton(IDC_CHECKAUTOCHECK,check?BST_CHECKED:BST_UNCHECKED); + GetDlgItem(IDC_CHECKAUTOCHECK).EnableWindow(!(g_Settings[SETTING_UPDATE].flags&CSetting::FLAG_LOCKED_MASK)); + GetDlgItem(IDC_BUTTONCHECKNOW).EnableWindow(!(g_Settings[SETTING_UPDATE].flags&CSetting::FLAG_LOCKED_MASK) || check); + UpdateUI(); + + return TRUE; +} + +LRESULT CUpdateDlg::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_Font) DeleteObject(m_Font); + return 0; +} + +LRESULT CUpdateDlg::OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + CResizeableDlg::OnSize(); + return 0; +} + +LRESULT CUpdateDlg::OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + SaveSettings(); + DestroyWindow(); + return 0; +} + +LRESULT CUpdateDlg::OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + DestroyWindow(); + return 0; +} + +LRESULT CUpdateDlg::OnColorStatic( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if ((m_Data.bNewVersion || m_Data.bNewLanguage) && lParam==(LPARAM)GetDlgItem(IDC_STATICLATEST).m_hWnd) + { + HDC hdc=(HDC)wParam; + SetTextColor(hdc,0xFF); + SetBkMode(hdc,TRANSPARENT); + return (LRESULT)GetSysColorBrush(COLOR_3DFACE); + } + bHandled=FALSE; + return 0; +} + +LRESULT CUpdateDlg::OnCheckAuto( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CSettingsLockWrite lock; + bool check=IsDlgButtonChecked(IDC_CHECKAUTOCHECK)==BST_CHECKED; + g_Settings[SETTING_UPDATE].value=CComVariant(check?1:0); + g_Settings[SETTING_UPDATE].flags&=~CSetting::FLAG_DEFAULT; + UpdateUI(); + return 0; +} + +LRESULT CUpdateDlg::OnCheckNow( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + UpdateData(); + UpdateUI(); + return 0; +} + +static HRESULT CALLBACK TaskDialogCallbackProc( HWND hwnd, UINT uNotification, WPARAM wParam, LPARAM lParam, LONG_PTR dwRefData ) +{ + if (uNotification==TDN_HYPERLINK_CLICKED) + { + ShellExecute(hwnd,L"open",(const wchar_t*)lParam,NULL,NULL,SW_SHOWNORMAL); + } + return S_OK; +} + +LRESULT CUpdateDlg::OnDownload( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (m_Data.bNewVersion) + { + if (!m_Data.downloadUrl.IsEmpty()) + { + CString fname, error; + DWORD res=DownloadNewVersion(m_hWnd,COMPONENT_UPDATE,m_Data.downloadUrl,m_Data.downloadSigner,fname,error); + if (res==2) + return 0; + if (res) + { + SetDlgItemText(IDC_STATICLATEST,L""); + PIDLIST_ABSOLUTE pidl; + if (SUCCEEDED(SHParseDisplayName(fname,NULL,&pidl,0,NULL))) + { + HRESULT hr=SHOpenFolderAndSelectItems(pidl,0,NULL,0); + ILFree(pidl); + if (SUCCEEDED(hr)) + return 0; + } + ShellExecute(NULL,NULL,fname,NULL,NULL,SW_SHOWNORMAL); + } + else + { + error+=LoadStringEx(IDS_DOWNLOAD_TIP)+L"\r\n\r\n"+m_Data.updateLink; + TASKDIALOGCONFIG task={sizeof(task),m_hWnd,NULL,TDF_ENABLE_HYPERLINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_USE_HICON_MAIN,TDCBF_OK_BUTTON}; + CString title=LoadStringEx(IDS_UPDATE_TITLE); + task.pszWindowTitle=title; + task.pszContent=error; + task.hMainIcon=LoadIcon(NULL,IDI_ERROR); + task.pfCallback=TaskDialogCallbackProc; + TaskDialogIndirect(&task,NULL,NULL,NULL); + } + } + } + else if (m_Data.bNewLanguage) + { + for (std::vector::const_iterator it=m_Data.languages.begin();it!=m_Data.languages.end();++it) + { + if (_wcsicmp(m_Data.newLanguage,it->language)==0) + { + CString error; + DWORD res=DownloadLanguageDll(m_hWnd,COMPONENT_UPDATE,*it,error); + if (res==2) + return 0; + if (res) + { + MessageBox(LoadStringEx(it->bBasic?IDS_LANGUAGE_SUCCESS2:IDS_LANGUAGE_SUCCESS),LoadStringEx(IDS_UPDATE_TITLE),MB_OK|(it->bBasic?MB_ICONWARNING:MB_ICONINFORMATION)); + SetDlgItemText(IDC_STATICLATEST,L""); + } + else + { + error+=LoadStringEx(IDS_DOWNLOAD_TIP)+L"\r\n\r\n"+m_Data.languageLink; + TASKDIALOGCONFIG task={sizeof(task),m_hWnd,NULL,TDF_ENABLE_HYPERLINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_USE_HICON_MAIN,TDCBF_OK_BUTTON}; + CString title=LoadStringEx(IDS_UPDATE_TITLE); + task.pszWindowTitle=title; + task.pszContent=error; + task.hMainIcon=LoadIcon(NULL,IDI_ERROR); + task.pfCallback=TaskDialogCallbackProc; + TaskDialogIndirect(&task,NULL,NULL,NULL); + } + return 0; + } + } + Assert(0); // NEWLanguage is not in the list + } + return 0; +} + +LRESULT CUpdateDlg::OnDontRemind( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicShell",KEY_READ|KEY_WRITE)!=ERROR_SUCCESS) + regKey.Create(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicShell"); + if (m_Data.bNewVersion) + { + m_Data.bIgnoreVersion=(IsDlgButtonChecked(IDC_CHECKDONT)==BST_CHECKED); + regKey.SetDWORDValue(L"RemindedVersion",m_Data.bIgnoreVersion?m_Data.newVersion:0); + } + else if (m_Data.bNewLanguage) + { + m_Data.bIgnoreLanguage=(IsDlgButtonChecked(IDC_CHECKDONT)==BST_CHECKED); + regKey.SetDWORDValue(L"RemindedLangVersion",m_Data.bIgnoreLanguage?m_Data.encodedLangVersion:0); + } + return 0; +} + +LRESULT CUpdateDlg::OnWeb( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + ShellExecute(m_hWnd,NULL,L"http://www.classicshell.net",NULL,NULL,SW_SHOWNORMAL); + return 0; +} + +void CUpdateDlg::NewVersionCallback( VersionData &data ) +{ + g_UpdateDlg.m_Data.Swap(data); +} + +void CUpdateDlg::UpdateData( void ) +{ + if (!CheckForNewVersion(m_hWnd,COMPONENT_UPDATE,CHECK_UPDATE,NewVersionCallback)) + { + m_Data.Clear(); + } +} + +void CUpdateDlg::UpdateUI( void ) +{ + if (m_Data.bValid) + { + if (m_Data.bNewVersion) + { + SetDlgItemText(IDC_STATICLATEST,LoadStringEx(IDS_OUTOFDATE)); + SetDlgItemText(IDC_EDITTEXT,m_Data.news); + GetDlgItem(IDC_EDITTEXT).ShowWindow(SW_SHOW); + GetDlgItem(IDC_BUTTONDOWNLOAD).ShowWindow(SW_SHOW); + bool check=true; + if (g_Settings[SETTING_UPDATE].value.vt==VT_I4) + check=g_Settings[SETTING_UPDATE].value.intVal!=0; + GetDlgItem(IDC_CHECKDONT).ShowWindow(check?SW_SHOW:SW_HIDE); + CheckDlgButton(IDC_CHECKDONT,m_Data.bIgnoreVersion?BST_CHECKED:BST_UNCHECKED); + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS|TTF_IDISHWND,m_hWnd,(UINT_PTR)GetDlgItem(IDC_BUTTONDOWNLOAD).m_hWnd}; + tool.lpszText=(LPWSTR)(LPCWSTR)m_Data.downloadUrl; + m_Tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + } + else if (m_Data.bNewLanguage) + { + SetDlgItemText(IDC_STATICLATEST,LoadStringEx(IDS_LANG_OUTOFDATE)); + SetDlgItemText(IDC_EDITTEXT,L""); + GetDlgItem(IDC_EDITTEXT).ShowWindow(SW_HIDE); + GetDlgItem(IDC_BUTTONDOWNLOAD).ShowWindow(SW_SHOW); + bool check=true; + if (g_Settings[SETTING_UPDATE].value.vt==VT_I4) + check=g_Settings[SETTING_UPDATE].value.intVal!=0; + GetDlgItem(IDC_CHECKDONT).ShowWindow(check?SW_SHOW:SW_HIDE); + CheckDlgButton(IDC_CHECKDONT,m_Data.bIgnoreLanguage?BST_CHECKED:BST_UNCHECKED); + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS|TTF_IDISHWND,m_hWnd,(UINT_PTR)GetDlgItem(IDC_BUTTONDOWNLOAD).m_hWnd}; + for (std::vector::const_iterator it=m_Data.languages.begin();it!=m_Data.languages.end();++it) + { + if (_wcsicmp(m_Data.newLanguage,it->language)==0) + { + tool.lpszText=(LPWSTR)(LPCWSTR)it->url; + break; + } + } + m_Tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + } + else + { + SetDlgItemText(IDC_STATICLATEST,LoadStringEx(IDS_UPDATED)); + SetDlgItemText(IDC_EDITTEXT,L""); + GetDlgItem(IDC_EDITTEXT).ShowWindow(SW_HIDE); + GetDlgItem(IDC_BUTTONDOWNLOAD).ShowWindow(SW_HIDE); + GetDlgItem(IDC_CHECKDONT).ShowWindow(SW_HIDE); + } + } + else + { + SetDlgItemText(IDC_STATICLATEST,(m_Data.newVersion==0)?LoadStringEx(IDS_UPDATE_FAIL):L""); + SetDlgItemText(IDC_EDITTEXT,L""); + GetDlgItem(IDC_EDITTEXT).ShowWindow(SW_HIDE); + GetDlgItem(IDC_BUTTONDOWNLOAD).ShowWindow(SW_HIDE); + GetDlgItem(IDC_CHECKDONT).ShowWindow(SW_HIDE); + } + Invalidate(); +} + +void CUpdateDlg::Run( void ) +{ + DLGTEMPLATE *pTemplate=LoadDialogEx(IDD_UPDATE); + Create(NULL,pTemplate); + MSG msg; + while (m_hWnd && GetMessage(&msg,0,0,0)) + { + if ((msg.hwnd==m_hWnd || IsChild(msg.hwnd)) && IsDialogMessage(&msg)) + continue; + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +LRESULT CALLBACK SubclassBalloonProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_LBUTTONUP) + { + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + if (SendMessage(hWnd,TTM_GETCURRENTTOOL,0,0)) + { + TOOLINFO tool={sizeof(tool)}; + tool.uId=1; + SendMessage(hWnd,TTM_TRACKACTIVATE,FALSE,(LPARAM)&tool); + g_UpdateDlg.Run(); + } + return res; + } + if (uMsg==WM_MOUSEACTIVATE) + return MA_NOACTIVATE; + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +/////////////////////////////////////////////////////////////////////////////// + +class COwnerWindow: public CWindowImpl +{ +public: + DECLARE_WND_CLASS_EX(L"ClassicShellUpdate.COwnerWindow",0,COLOR_MENU) + + // message handlers + BEGIN_MSG_MAP( COwnerWindow ) + MESSAGE_HANDLER( WM_CLEAR, OnClear ) + END_MSG_MAP() + +protected: + LRESULT OnClear( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) + { + if (g_UpdateDlg) + { + g_UpdateDlg.PostMessage(WM_CLOSE); + } + return 0; + } +}; + +/////////////////////////////////////////////////////////////////////////////// + +int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstrCmdLine, int nCmdShow ) +{ + INITCOMMONCONTROLSEX init={sizeof(init),ICC_STANDARD_CLASSES}; + InitCommonControlsEx(&init); +/* + VersionData data; + data.Load(L"D:\\Work\\ClassicShell\\ClassicShellSetup\\Final\\update_4.0.4.ver",false); + return 0; +*/ + // prevent multiple instances from running on the same desktop + // the assumption is that multiple desktops for the same user will have different name (but may repeat across users) + wchar_t userName[256]; + DWORD len=_countof(userName); + GetUserName(userName,&len); + len=0; + HANDLE desktop=GetThreadDesktop(GetCurrentThreadId()); + GetUserObjectInformation(desktop,UOI_NAME,NULL,0,&len); + wchar_t *deskName=(wchar_t*)malloc(len); + GetUserObjectInformation(desktop,UOI_NAME,deskName,len,&len); + + wchar_t mutexName[1024]; + Sprintf(mutexName,_countof(mutexName),L"ClassicShellUpdate.Mutex.%s.%s",userName,deskName); + free(deskName); + + HANDLE hMutex=CreateMutex(NULL,TRUE,mutexName); + if (GetLastError()==ERROR_ALREADY_EXISTS || GetLastError()==ERROR_ACCESS_DENIED) + return 0; + + CoInitialize(NULL); + g_Instance=hInstance; + InitSettings(g_Settings,COMPONENT_UPDATE,NULL); + CString language=GetSettingString(L"Language"); + ParseTranslations(NULL,language); + + g_Instance=hInstance; + + HINSTANCE resInstance=LoadTranslationDll(language); + + LoadTranslationResources(resInstance,g_LoadDialogs); + + if (resInstance) + FreeLibrary(resInstance); + + int time0=timeGetTime(); + + COwnerWindow ownerWindow; + ownerWindow.Create(NULL,0,0,WS_POPUP); + if (wcsstr(lpstrCmdLine,L"-popup")!=NULL) + { + g_UpdateDlg.UpdateData(); + // wait at least 5 seconds before showing the balloon + int sleep=5000-(timeGetTime()-time0); + if (sleep>0) + Sleep(sleep); + HWND balloon=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|(IsLanguageRTL()?WS_EX_LAYOUTRTL:0),TOOLTIPS_CLASS,NULL,WS_POPUP|TTS_CLOSE|TTS_NOPREFIX,0,0,0,0,NULL,NULL,g_Instance,NULL); + SendMessage(balloon,TTM_SETMAXTIPWIDTH,0,500); + TOOLINFO tool={sizeof(tool),TTF_ABSOLUTE|TTF_TRANSPARENT|TTF_TRACK|(IsLanguageRTL()?TTF_RTLREADING:0)}; + tool.uId=1; + CString message=LoadStringEx(g_UpdateDlg.HasNewLanguage()?IDS_LANG_NEWVERSION:IDS_NEWVERSION); + tool.lpszText=(wchar_t*)(const wchar_t*)message; + SendMessage(balloon,TTM_ADDTOOL,0,(LPARAM)&tool); + SendMessage(balloon,TTM_SETTITLE,(WPARAM)LoadIcon(g_Instance,MAKEINTRESOURCE(IDI_APPICON)),(LPARAM)(const wchar_t*)LoadStringEx(IDS_UPDATE_TITLE)); + APPBARDATA appbar={sizeof(appbar)}; + SHAppBarMessage(ABM_GETTASKBARPOS,&appbar); + MONITORINFO info={sizeof(info)}; + GetMonitorInfo(MonitorFromWindow(appbar.hWnd,MONITOR_DEFAULTTOPRIMARY),&info); + SendMessage(balloon,TTM_TRACKPOSITION,0,0); + SendMessage(balloon,TTM_TRACKACTIVATE,TRUE,(LPARAM)&tool); + RECT rc; + GetWindowRect(balloon,&rc); + LONG pos; + if (appbar.uEdge==ABE_LEFT) + pos=MAKELONG(info.rcWork.left,info.rcWork.bottom-rc.bottom+rc.top); + else if (appbar.uEdge==ABE_RIGHT) + pos=MAKELONG(info.rcWork.right-rc.right+rc.left,info.rcWork.bottom-rc.bottom+rc.top); + else if (appbar.uEdge==ABE_TOP) + pos=MAKELONG(IsLanguageRTL()?info.rcWork.left:info.rcWork.right-rc.right+rc.left,info.rcWork.top); + else + pos=MAKELONG(IsLanguageRTL()?info.rcWork.left:info.rcWork.right-rc.right+rc.left,info.rcWork.bottom-rc.bottom+rc.top); + SendMessage(balloon,TTM_TRACKPOSITION,0,pos); + SetWindowSubclass(balloon,SubclassBalloonProc,0,'CLSH'); + PlaySound(L"SystemNotification",NULL,SND_APPLICATION|SND_ALIAS|SND_ASYNC|SND_NODEFAULT|SND_SYSTEM); + int time0=timeGetTime(); + while (IsWindowVisible(balloon)) + { + if (time0 && (timeGetTime()-time0)>=15000) + { + time0=0; + TOOLINFO tool={sizeof(tool)}; + tool.uId=1; + SendMessage(balloon,TTM_TRACKACTIVATE,FALSE,(LPARAM)&tool); + } + MSG msg; + while (PeekMessage(&msg,0,0,0,PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + Sleep(10); + } + } + else + { + g_UpdateDlg.Run(); + } + ownerWindow.DestroyWindow(); + CoUninitialize(); + return 0; +} diff --git a/ClassicShellSrc/ClassicShellUpdate/ClassicShellUpdate.manifest b/ClassicShellSrc/ClassicShellUpdate/ClassicShellUpdate.manifest new file mode 100644 index 0000000..07d928d --- /dev/null +++ b/ClassicShellSrc/ClassicShellUpdate/ClassicShellUpdate.manifest @@ -0,0 +1,41 @@ + + + +Classic Shell Update + + + + + + + + true + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicShellUpdate/ClassicShellUpdate.rc b/ClassicShellSrc/ClassicShellUpdate/ClassicShellUpdate.rc new file mode 100644 index 0000000..397d4e5 --- /dev/null +++ b/ClassicShellSrc/ClassicShellUpdate/ClassicShellUpdate.rc @@ -0,0 +1,202 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" +#include "..\ClassicShellLib\resource.h" +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "#include ""..\\ClassicShellLib\\resource.h""\0" +END + +3 TEXTINCLUDE +BEGIN + "#include ""..\\ClassicShellLib\\resource.h""\r\n" + "#include ""..\\ClassicShellLib\\ClassicShellLib.rc""\r\0" +END + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "#include ""..\\ClassicShellLib\\resource.h""\r\n" + "#include ""..\\ClassicShellLib\\ClassicShellLib.rc""\r\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\0" +END + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#ifndef APSTUDIO_INVOKED\r\n" + "#include ""targetver.h""\r\n" + "#endif\r\n" + "#include ""winres.h""\r\n" + "#include ""..\\ClassicShellLib\\resource.h""\r\n" + "#include ""..\\ClassicShellLib\\ClassicShellLib.rc""\r\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 4,3,1,0 + PRODUCTVERSION 4,3,1,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "IvoSoft" + VALUE "FileDescription", "Checks for a new version of Classic Shell" + VALUE "FileVersion", "4, 3, 1, 0" + VALUE "InternalName", "ClassicShellUpdate.exe" + VALUE "LegalCopyright", "Copyright (C) 2009-2016, Ivo Beltchev" + VALUE "OriginalFilename", "ClassicShellUpdate.exe" + VALUE "ProductName", "Classic Shell" + VALUE "ProductVersion", "4, 3, 1, 0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_UPDATE DIALOGEX 0, 0, 316, 181 +STYLE DS_SETFONT | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +CAPTION "Classic Shell Update" +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + CONTROL "Automatically check for new versions",IDC_CHECKAUTOCHECK, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,129,10 + PUSHBUTTON "Check now",IDC_BUTTONCHECKNOW,7,17,50,14 + LTEXT "message",IDC_STATICLATEST,7,33,302,10,SS_CENTERIMAGE + EDITTEXT IDC_EDITTEXT,7,45,302,97,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | NOT WS_VISIBLE | WS_VSCROLL + PUSHBUTTON "Download",IDC_BUTTONDOWNLOAD,7,144,50,14,NOT WS_VISIBLE + CONTROL "Don't remind me again about this version",IDC_CHECKDONT, + "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,61,144,141,14 + CONTROL "www.classicshell.net",IDC_LINKWEB,"SysLink",WS_TABSTOP,7,164,66,10,WS_EX_TRANSPARENT + DEFPUSHBUTTON "OK",IDOK,202,160,50,14 + PUSHBUTTON "Cancel",IDCANCEL,259,160,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_UPDATE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 309 + TOPMARGIN, 7 + BOTTOMMARGIN, 174 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APPICON ICON "..\\ClassicShellSetup\\ClassicShell.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_UPDATED "Your version of Classic Shell is up to date" + IDS_OUTOFDATE "There is a new version of Classic Shell" + IDS_NEWVERSION "There is a new version of Classic Shell.\nClick here to see what's new or to change the reminder settings." + IDS_UPDATE_FAIL "Failed to check for new version" + IDS_LANG_OUTOFDATE "There is a new language file for this version of Classic Shell" + IDS_LANG_NEWVERSION "There is a new language file for this version of Classic Shell.\nClick here to install it or to change the reminder settings." +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "..\ClassicShellLib\resource.h" +#include "..\ClassicShellLib\ClassicShellLib.rc" +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/ClassicShellSrc/ClassicShellUpdate/ClassicShellUpdate.vcproj b/ClassicShellSrc/ClassicShellUpdate/ClassicShellUpdate.vcproj new file mode 100644 index 0000000..4bfc719 --- /dev/null +++ b/ClassicShellSrc/ClassicShellUpdate/ClassicShellUpdate.vcproj @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicShellUpdate/resource.h b/ClassicShellSrc/ClassicShellUpdate/resource.h new file mode 100644 index 0000000..602ab8a --- /dev/null +++ b/ClassicShellSrc/ClassicShellUpdate/resource.h @@ -0,0 +1,29 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ClassicShellUpdate.rc +// +#define IDI_APPICON 101 +#define IDC_STATICLATEST 1001 +#define IDC_EDITTEXT 1002 +#define IDC_BUTTONDOWNLOAD 1003 +#define IDC_CHECKDONT 1004 +#define IDC_BUTTONCHECKNOW 1005 +#define IDC_CHECKAUTOCHECK 1006 +#define IDD_UPDATE 6001 +#define IDS_UPDATED 6001 +#define IDS_OUTOFDATE 6002 +#define IDS_NEWVERSION 6003 +#define IDS_UPDATE_FAIL 6005 +#define IDS_LANG_OUTOFDATE 6006 +#define IDS_LANG_NEWVERSION 6007 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 227 +#define _APS_NEXT_COMMAND_VALUE 32769 +#define _APS_NEXT_CONTROL_VALUE 262 +#define _APS_NEXT_SYMED_VALUE 106 +#endif +#endif diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenu.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenu.cpp new file mode 100644 index 0000000..cd91947 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenu.cpp @@ -0,0 +1,696 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include +#include +#include +#include "StringUtils.h" +#include "ResourceHelper.h" +#include "TrackResources.h" +#include "ComHelper.h" +#include "Settings.h" +#include "psapi.h" + +#include "ClassicStartMenuDLL\ClassicStartMenuDLL.h" +#include "ClassicStartMenuDLL\SettingsUI.h" +#include "ClassicStartMenuDLL\resource.h" +#include "ClassicStartMenuDLL\LogManager.h" + +static HHOOK g_StartHook; + +static void UnhookStartMenu( void ) +{ + if (g_StartHook) + UnhookWindowsHookEx(g_StartHook); + g_StartHook=NULL; +} + +enum THookMode +{ + HOOK_NONE, // don't hook Explorer, running as a separate exe + HOOK_NORMAL, // hook Explorer normally, no retry + HOOK_STARTUP, // retry to hook Explorer + HOOK_STARTUP2, // retry to hook Explorer (for secondary desktops) +}; + +static bool HookStartMenu( THookMode mode, HWND &menu ) +{ + HMODULE hHookModule=GetModuleHandle(L"ClassicStartMenuDLL.dll"); + + // find the Progman window and the start button + + DllLogToFile(STARTUP_LOG,L"StartMenu: hooking Explorer"); + HWND progWin=NULL; + bool bFindAppManager=(mode==HOOK_STARTUP && GetWinVersion()>=WIN_VER_WIN8 && GetWinVersion()<=WIN_VER_WIN81); + for (int i=0;i<120;i++) // retry for 1 minute + { + if (bFindAppManager) + bFindAppManager=!FindWindow(L"ApplicationManager_DesktopShellWindow",NULL); + if (!bFindAppManager) + { + progWin=FindWindowEx(NULL,NULL,L"Progman",NULL); + if (progWin) break; + if (mode!=HOOK_STARTUP && mode!=HOOK_STARTUP2) return true; // the Progman window may not be created yet (if Explorer is currently restarting) + } + DllLogToFile(STARTUP_LOG,L"StartMenu: can't find Progman, retrying"); + Sleep(500); + } + if (!progWin) + return true; + DWORD process=0; + DWORD thread=GetWindowThreadProcessId(progWin,&process); + HANDLE hProcess=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,process); + if (hProcess) + { + bool success=false; + wchar_t path[MAX_PATH]; + if (GetModuleFileNameEx(hProcess,NULL,path,_countof(path))) + { + if (_wcsicmp(PathFindFileName(path),L"explorer.exe")==0) + success=true; + else + DllLogToFile(STARTUP_LOG,L"StartMenu: found wrong process %s",path); + } + else + DllLogToFile(STARTUP_LOG,L"StartMenu: failed to get process name"); + CloseHandle(hProcess); + if (!success) + return false; + } + else + DllLogToFile(STARTUP_LOG,L"StartMenu: failed to open process %d",process); + + for (int i=0;i<10;i++) // retry for 5 sec + { + if (FindTaskBar(process)) break; + if (mode!=HOOK_STARTUP && mode!=HOOK_STARTUP2) return false; // the taskbar may not be created yet (if Explorer is currently restarting) + DllLogToFile(STARTUP_LOG,L"StartMenu: can't find taskbar, retrying"); + Sleep(500); + } + + if (mode==HOOK_NONE) + { + menu=ToggleStartMenu(-1,false); + return true; + } + + // install hooks in the explorer process + thread=GetWindowThreadProcessId(g_TaskBar,NULL); + g_StartHook=SetWindowsHookEx(WH_GETMESSAGE,HookInject,hHookModule,thread); + if (!g_StartHook) + { + int err=GetLastError(); + DllLogToFile(STARTUP_LOG,L"StartMenu: hook failed: 0x%08X",err); + } + PostMessage(g_TaskBar,WM_NULL,0,0); // make sure there is one message in the queue + + return true; +} + +static UINT g_TaskbarCreatedMsg; // the "TaskbarCreated" message + +// CStartHookWindow is a hidden window that waits for the "TaskbarCreated" message and rehooks the explorer process +// Also when the start menu wants to shut down it sends WM_CLOSE to this window, which unhooks explorer and exits + +const int WM_OPEN=WM_USER+10; + +const int TIMER_HOOK=1; + +class CStartHookWindow: public CWindowImpl +{ +public: + + DECLARE_WND_CLASS(L"ClassicStartMenu.CStartHookWindow") + + BEGIN_MSG_MAP( CStartHookWindow ) + MESSAGE_HANDLER( WM_OPEN, OnOpen ) + MESSAGE_HANDLER( WM_CLOSE, OnClose ) + MESSAGE_HANDLER( WM_CLEAR, OnClear ) + MESSAGE_HANDLER( WM_TIMER, OnTimer ) + MESSAGE_HANDLER( g_TaskbarCreatedMsg, OnTaskbarCreated ) + END_MSG_MAP() + +protected: + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnOpen( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnClose( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnClear( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnTaskbarCreated( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); +}; + +LRESULT CStartHookWindow::OnOpen( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (g_TaskBar) ::PostMessage(g_TaskBar,RegisterWindowMessage(L"ClassicStartMenu.StartMenuMsg"),wParam,lParam); + return 0; +} + +LRESULT CStartHookWindow::OnClose( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + UnhookStartMenu(); + Sleep(100); + PostQuitMessage(0); + return 0; +} + +LRESULT CStartHookWindow::OnClear( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + UnhookStartMenu(); + return 0; +} + +LRESULT CStartHookWindow::OnTaskbarCreated( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + DllLogToFile(STARTUP_LOG,L"StartMenu: Taskbar Created"); + SetTimer(TIMER_HOOK,100); + return 0; +} + +LRESULT CStartHookWindow::OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==TIMER_HOOK) + { + UnhookStartMenu(); + HWND menu; + HookStartMenu(HOOK_NORMAL,menu); + if (g_StartHook) + KillTimer(TIMER_HOOK); + } + return 0; +} + +enum +{ + CMD_NONE=-1, + CMD_TOGGLE_NEW=-2, +}; + +static const GUID IID_IWpnTileSink={0xe716b283,0x6be7,0x4e6f,{0xa8,0x8f,0x1c,0xde,0x47,0xd5,0xe3,0x55}}; +interface IWpnTileSink : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE TileSessionUpdated(unsigned long,void const *,unsigned long) = 0; + virtual HRESULT STDMETHODCALLTYPE TileSessionNotificationCleared(unsigned long,void const *,unsigned long) = 0; + virtual HRESULT STDMETHODCALLTYPE TileSessionImageDownloadUpdated(unsigned long,int) = 0; + virtual HRESULT STDMETHODCALLTYPE TileRequestNotificationCompleted(void const * ptr64,unsigned long) = 0; + virtual HRESULT STDMETHODCALLTYPE TileSessionImageDownloadUpdated2(unsigned long,int) = 0; +}; + +class CWpnTileSink : public IWpnTileSink +{ + // from IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void **ppvObject ); + virtual ULONG STDMETHODCALLTYPE AddRef( void ) { return 1; } + virtual ULONG STDMETHODCALLTYPE Release( void ) { return 1; } + + virtual HRESULT STDMETHODCALLTYPE TileSessionUpdated(unsigned long a,void const *b,unsigned long c) + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE TileSessionNotificationCleared(unsigned long a,void const *b,unsigned long c) + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE TileSessionImageDownloadUpdated(unsigned long a,int b) + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE TileRequestNotificationCompleted(void const * a,unsigned long b) + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE TileSessionImageDownloadUpdated2(unsigned long a,int b) + { + return S_OK; + } +}; + +HRESULT STDMETHODCALLTYPE CWpnTileSink::QueryInterface( REFIID riid, void **ppvObject ) +{ + *ppvObject=NULL; + if (riid==IID_IUnknown || riid==IID_IWpnTileSink) + { + *ppvObject=this; + return S_OK; + } + return E_NOINTERFACE; +} + +MIDL_INTERFACE("0e467ac1-65f2-48d6-8bf2-375430548a87") +IWpnPresentationEndpoint : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE TileCreateSession( unsigned long * ) = 0; + virtual HRESULT STDMETHODCALLTYPE TileCloseSession( unsigned long ) = 0; + virtual HRESULT STDMETHODCALLTYPE TileUpdateSession( unsigned long,const void *,unsigned long ) = 0; // (1, str, 1) + virtual HRESULT STDMETHODCALLTYPE TileRequestNotification( const void *, unsigned long ) = 0; // (str, 1)*/ +}; + +const CLSID CLSID_WpnPlatform={0x0c9281f9, 0x6da1, 0x4006, {0x87, 0x29, 0xde, 0x6e, 0x6b, 0x61, 0x58, 0x1c}}; +MIDL_INTERFACE("9fa045cb-b9b3-47ba-842f-e2ab458f2b0c") +IWpnPlatform : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE CreateAppEndpoint( struct IWpnAppEndpoint **ppEndpoint ) = 0; + virtual HRESULT STDMETHODCALLTYPE CreatePresentationEndpoint(struct IWpnPresentationEndpoint ** ppEndpoint ) = 0; +/* virtual HRESULT STDMETHODCALLTYPE CreateRegistrationEndpoint(struct IWpnRegistrationEndpoint * ptr64 * ptr64) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateSettingsEndpoint(struct IWpnSettingsEndpoint * ptr64 * ptr64) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateIdleTaskEndpoint(struct IWpnIdleTaskEndpoint * ptr64 * ptr64) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateTestEndpoint(struct IWpnTestEndpoint * ptr64 * ptr64) = 0;*/ +}; + +//const wchar_t *g_AppId=L"microsoft.windowscommunicationsapps_8wekyb3d8bbwe!microsoft.windowslive.mail"; +//const wchar_t *g_AppId=L"Microsoft.BingNews_8wekyb3d8bbwe!AppexNews"; +//const wchar_t *g_AppId=L"Microsoft.WindowsStore_8wekyb3d8bbwe!App"; +//const wchar_t *g_AppId=L"Microsoft.BingWeather_8wekyb3d8bbwe!App"; +const wchar_t *g_AppId=L"microsoft.windowscommunicationsapps_8wekyb3d8bbwe!microsoft.windowslive.calendar"; + +int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstrCmdLine, int nCmdShow ) +{ +/* CoInitialize(NULL); + { + CComPtr pWpnPlatform; + HRESULT hr=pWpnPlatform.CoCreateInstance(CLSID_WpnPlatform); + CComPtr pUnknown; + hr=pWpnPlatform->CreatePresentationEndpoint(&pUnknown); + CWpnTileSink sink; + DWORD cookie; + CComQIPtr pConnectionPoint=pUnknown; + hr=pConnectionPoint->Advise(&sink,&cookie); + CComPtr pWpnPresentationEndpoint=pUnknown; + DWORD session; + hr=pWpnPresentationEndpoint->TileCreateSession(&session); + struct + { + const wchar_t *appid; + void *ptr1; + void *ptr2; + __int64 idx; + } request={g_AppId,0,0,1}; + hr=pWpnPresentationEndpoint->TileRequestNotification(&request,1); + + MSG msg; + while(true) + { + struct + { + const wchar_t *appid; + __int64 idx; + } updateData={g_AppId,1}; + hr=pWpnPresentationEndpoint->TileUpdateSession(session,&updateData,1); + + while (PeekMessage(&msg,0,0,0,PM_REMOVE)) +// while (GetMessage(&msg,0,0,0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + Sleep(100); + } + int q=0; + } + CoUninitialize(); + return 0;*/ +/* DWORD count; + pStore->GetCount(&count); + for (DWORD i=0;iGetAt(i,&key))) + { + CComString pPropName; + PSGetNameFromPropertyKey(key,&pPropName); + PROPVARIANT val; + PropVariantInit(&val); + pStore->GetValue(key,&val); + PropVariantClear(&val); + } + }*/ + + DllLogToFile(STARTUP_LOG,L"StartMenu: start '%s'",lpstrCmdLine); + DWORD winVer=GetVersionEx(GetModuleHandle(L"user32.dll")); + if (wcsstr(lpstrCmdLine,L"-startup") || (wcsstr(lpstrCmdLine,L"-autorun") && HIWORD(winVer)0) + Sleep(sleep); + } + else if (wcsstr(lpstrCmdLine,L"-autorun")) // on Win8+ + { + WaitDllInitThread(); + CRegKey regKey; + if (regKey.Open(HKEY_LOCAL_MACHINE,L"Software\\IvoSoft\\ClassicShell",KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + DWORD ver1; + if (regKey.QueryDWORDValue(L"WinVersion",ver1)==ERROR_SUCCESS) + { + if (ver10) + Sleep(sleep); + } + + if (wcsstr(lpstrCmdLine,L"-upgrade")) + { + WaitDllInitThread(); + CRegKey regKey; + DWORD error=regKey.Open(HKEY_LOCAL_MACHINE,L"Software\\IvoSoft\\ClassicShell",KEY_WRITE|KEY_WOW64_64KEY); + const wchar_t *nl=error==ERROR_SUCCESS?L"\r\n\r\n":L"\r\n"; + if (error==ERROR_SUCCESS) + { + regKey.SetDWORDValue(L"WinVersion",winVer); + + // run regsvr32 StartMenuHelper +#ifdef _WIN64 + wchar_t cmdLine[_MAX_PATH]=L"regsvr32 /s \"%windir%\\System32\\StartMenuHelper64.dll\""; +#else + wchar_t cmdLine[_MAX_PATH]=L"regsvr32 /s \"%windir%\\System32\\StartMenuHelper32.dll\""; +#endif + DoEnvironmentSubst(cmdLine,_countof(cmdLine)); + + wchar_t exe[_MAX_PATH]=L"%windir%\\System32\\regsvr32.exe"; + DoEnvironmentSubst(exe,_countof(exe)); + + STARTUPINFO startupInfo={sizeof(startupInfo)}; + PROCESS_INFORMATION processInfo; + memset(&processInfo,0,sizeof(processInfo)); + if (CreateProcess(exe,cmdLine,NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) + { + CloseHandle(processInfo.hThread); + WaitForSingleObject(processInfo.hProcess,INFINITE); + GetExitCodeProcess(processInfo.hProcess,&error); + CloseHandle(processInfo.hProcess); + } + else + error=GetLastError(); + } + if (error) + { + wchar_t msg[1024]; + int len=Sprintf(msg,_countof(msg),L"%s%s",DllLoadStringEx(IDS_UPGRADE_ERROR),nl); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,NULL,error,0,msg+len,_countof(msg)-len,NULL); + MessageBox(NULL,msg,DllLoadStringEx(IDS_APP_TITLE),MB_OK|MB_ICONERROR); + } + else + { + MessageBox(NULL,DllLoadStringEx(IDS_UPGRADE_SUCCESS),DllLoadStringEx(IDS_APP_TITLE),MB_OK|MB_ICONINFORMATION); + } + return error; + } + + const wchar_t *pCmd=wcsstr(lpstrCmdLine,L"-cmd "); + if (pCmd) + { + WaitDllInitThread(); + CoInitialize(NULL); + wchar_t command[100]; + GetToken(pCmd+5,command,_countof(command),L" "); + if (DllExecuteNamedCommand(command)) + { + MSG msg; + while (PeekMessage(&msg,0,0,0,PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + CoUninitialize(); + return 0; + } + +#ifndef _WIN64 + const wchar_t *pSaveAdmx=wcsstr(lpstrCmdLine,L"-saveadmx "); + if (pSaveAdmx) + { + WaitDllInitThread(); + wchar_t language[100]; + GetToken(pSaveAdmx+10,language,_countof(language),L" "); + HMODULE dll=NULL; + if (language[0]) + { + wchar_t path[_MAX_PATH]; + GetCurrentDirectory(_countof(path),path); + PathAppend(path,language); + PathAddExtension(path,L".dll"); + dll=LoadLibraryEx(path,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); + } + DllLoadTranslationResources(dll,NULL); + if (!DllSaveAdmx(COMPONENT_MENU,"ClassicStartMenu.admx","ClassicStartMenu.adml","ClassicStartMenuADMX.txt")) + return 1; + if (!DllSaveAdmx(COMPONENT_SHARED,"ClassicShell.admx","ClassicShell.adml","ClassicShellADMX.txt")) + return 1; + return 0; + } +#endif + + wchar_t path[_MAX_PATH]; + GetModuleFileName(NULL,path,_countof(path)); + *PathFindFileName(path)=0; + SetCurrentDirectory(path); + const wchar_t *pRunAs=wcsstr(lpstrCmdLine,L"-runas"); + if (pRunAs) + { + pRunAs+=7; + CoInitialize(NULL); + wchar_t exe[_MAX_PATH]; + const wchar_t *args=NULL; + CComString strExe, strArgs; + if (SUCCEEDED(SHEvaluateSystemCommandTemplate(pRunAs,&strExe,NULL,&strArgs))) + { + args=strArgs; + Strcpy(exe,_countof(exe),strExe); + } + else + { + args=SeparateArguments(pRunAs,exe); + } + SHELLEXECUTEINFO execute={sizeof(execute),SEE_MASK_DOENVSUBST|SEE_MASK_FLAG_LOG_USAGE}; + execute.lpFile=exe; + execute.lpParameters=args; + execute.nShow=SW_SHOWNORMAL; + ShellExecuteEx(&execute); + CoUninitialize(); + return 0; + } + + WaitDllInitThread(); + int open=CMD_NONE; + if (wcsstr(lpstrCmdLine,L"-togglenew")!=NULL) open=CMD_TOGGLE_NEW; + else if (wcsstr(lpstrCmdLine,L"-toggle")!=NULL) open=MSG_TOGGLE; + else if (wcsstr(lpstrCmdLine,L"-open")!=NULL) open=MSG_OPEN; + else if (wcsstr(lpstrCmdLine,L"-settings")!=NULL) open=MSG_SETTINGS; + else if (wcsstr(lpstrCmdLine,L"-exit")!=NULL) open=MSG_EXIT; + + { + const wchar_t *pXml=wcsstr(lpstrCmdLine,L"-xml "); + if (pXml) + { + wchar_t xml[_MAX_PATH]; + GetToken(pXml+5,xml,_countof(xml),L" "); + CoInitialize(NULL); + bool res=DllImportSettingsXml(xml); + CoUninitialize(); + if (res) + open=MSG_RELOADSETTINGS; + else + return 1; + } + } + + { + const wchar_t *pBackup=wcsstr(lpstrCmdLine,L"-backup "); + if (pBackup) + { + wchar_t xml[_MAX_PATH]; + GetToken(pBackup+8,xml,_countof(xml),L" "); + CoInitialize(NULL); + bool res=DllExportSettingsXml(xml); + CoUninitialize(); + return res?0:1; + } + } + + const wchar_t *pNoHook=wcsstr(lpstrCmdLine,L"-nohook"); + bool bHookExplorer=!pNoHook; + if (pNoHook) + { + pNoHook+=7; + if (*pNoHook=='1') MiniDumpType=MiniDumpNormal; + if (*pNoHook=='2') MiniDumpType=MiniDumpWithDataSegs; + if (*pNoHook=='3') MiniDumpType=MiniDumpWithFullMemory; + } + + if (!bHookExplorer) + SetUnhandledExceptionFilter(TopLevelFilter); + +#ifndef BUILD_SETUP + if (wcsstr(lpstrCmdLine,L"-testsettings")!=NULL || GetKeyState(VK_SHIFT)<0) + { + CoInitialize(NULL); + InitManagers(true); + EditSettings(true,0); + CloseManagers(true); + CoUninitialize(); +#ifdef TRACK_GDI_RESOURCES + DllDumpResourceLeaks(); +#endif + return 0; + } +#endif + + // prevent multiple instances from running on the same desktop + // the assumption is that multiple desktops for the same user will have different name (but may repeat across users) + wchar_t userName[256]; + DWORD len=_countof(userName); + GetUserName(userName,&len); + len=0; + HANDLE desktop=GetThreadDesktop(GetCurrentThreadId()); + GetUserObjectInformation(desktop,UOI_NAME,NULL,0,&len); + wchar_t *deskName=(wchar_t*)malloc(len); + GetUserObjectInformation(desktop,UOI_NAME,deskName,len,&len); + bool bDefaultDesktop=(_wcsicmp(deskName,L"Default")==0); + + wchar_t mutexName[1024]; + Sprintf(mutexName,_countof(mutexName),L"ClassicStartMenu.Mutex.%s.%s",userName,deskName); + free(deskName); + + if (open==CMD_NONE) + DllLogToFile(STARTUP_LOG,L"StartMenu: mutex %s",mutexName); + HWND progWin=FindWindowEx(NULL,NULL,L"Progman",NULL); + DWORD process; + if (progWin) + GetWindowThreadProcessId(progWin,&process); + + HANDLE hMutex=NULL; + if (bHookExplorer) + { + hMutex=CreateMutex(NULL,TRUE,mutexName); + if (GetLastError()==ERROR_ALREADY_EXISTS || GetLastError()==ERROR_ACCESS_DENIED) + { + if (open==MSG_TOGGLE || open==CMD_TOGGLE_NEW) + { + if (progWin) + { + AllowSetForegroundWindow(process); + HWND taskBar=FindTaskBar(process); + if (taskBar) + PostMessage(taskBar,RegisterWindowMessage(L"ClassicStartMenu.StartMenuMsg"),(open==CMD_TOGGLE_NEW)?MSG_TOGGLENEW:MSG_TOGGLE,0); + else + PostMessage(progWin,WM_SYSCOMMAND,SC_TASKLIST,(open==CMD_TOGGLE_NEW)?'WSMK':'CSM'); + } + } + else if (open!=CMD_NONE) + { + AllowSetForegroundWindow(process); + HWND hwnd=FindWindow(L"ClassicStartMenu.CStartHookWindow",L"StartHookWindow"); + if (hwnd) PostMessage(hwnd,WM_OPEN,open,0); + } + if (open==MSG_EXIT && hMutex && WaitForSingleObject(hMutex,2000)==WAIT_OBJECT_0) + ReleaseMutex(hMutex); + if (open==CMD_NONE) + DllLogToFile(STARTUP_LOG,L"StartMenu: exit (mutex exists)"); + return 0; + } + } + if (open!=CMD_NONE && open!=MSG_OPEN && open!=MSG_SETTINGS) + { + if (hMutex) ReleaseMutex(hMutex); + return 0; + } + + OleInitialize(NULL); + if (!bHookExplorer) + { + DllUpdateSettings(); + InitManagers(true); + } + CStartHookWindow window; + window.Create(NULL,NULL,L"StartHookWindow",WS_POPUP); + + g_TaskbarCreatedMsg=RegisterWindowMessage(L"TaskbarCreated"); + typedef BOOL (WINAPI *tChangeWindowMessageFilterEx)(HWND hWnd, UINT message, DWORD action, PCHANGEFILTERSTRUCT pChangeFilterStruct ); + HMODULE hUser32=GetModuleHandle(L"user32.dll"); + tChangeWindowMessageFilterEx ChangeWindowMessageFilterEx=(tChangeWindowMessageFilterEx)GetProcAddress(hUser32,"ChangeWindowMessageFilterEx"); + if (ChangeWindowMessageFilterEx) + { + ChangeWindowMessageFilterEx(window,g_TaskbarCreatedMsg,MSGFLT_ADD,NULL); + ChangeWindowMessageFilterEx(window,WM_CLEAR,MSGFLT_ADD,NULL); + ChangeWindowMessageFilterEx(window,WM_OPEN,MSGFLT_ADD,NULL); + ChangeWindowMessageFilterEx(window,WM_CLOSE,MSGFLT_ADD,NULL); + } + else + { + ChangeWindowMessageFilter(g_TaskbarCreatedMsg,MSGFLT_ADD); + ChangeWindowMessageFilter(WM_CLEAR,MSGFLT_ADD); + ChangeWindowMessageFilter(WM_OPEN,MSGFLT_ADD); + ChangeWindowMessageFilter(WM_CLOSE,MSGFLT_ADD); + } + + MSG msg; + HWND menu=NULL; + if (HookStartMenu(bHookExplorer?(bDefaultDesktop?HOOK_STARTUP:HOOK_STARTUP2):HOOK_NONE,menu)) + { + if (bHookExplorer && open>=0) + window.PostMessage(WM_OPEN,open,MSG_OPEN); + DllLogToFile(STARTUP_LOG,L"StartMenu: start message loop"); + while ((bHookExplorer || IsWindow(menu)) && GetMessage(&msg,0,0,0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + DllLogToFile(STARTUP_LOG,L"StartMenu: end message loop"); + window.DestroyWindow(); + if (!bHookExplorer) + { + CloseManagers(true); + } + OleUninitialize(); + + if (hMutex) ReleaseMutex(hMutex); +#ifdef TRACK_GDI_RESOURCES + DllDumpResourceLeaks(); +#endif + return 0; +} diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenu.manifest b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenu.manifest new file mode 100644 index 0000000..7e37f84 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenu.manifest @@ -0,0 +1,41 @@ + + + +Classic Start Menu + + + + + + + + true + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenu.rc b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenu.rc new file mode 100644 index 0000000..6845b97 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenu.rc @@ -0,0 +1,111 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 4,3,1,0 + PRODUCTVERSION 4,3,1,0 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "IvoSoft" + VALUE "FileDescription", "Classic Start Menu" + VALUE "FileVersion", "4, 3, 1, 0" + VALUE "InternalName", "ClassicStartMenu" + VALUE "LegalCopyright", "Copyright (C) 2009-2016, Ivo Beltchev" + VALUE "OriginalFilename", "ClassicStartMenu.exe" + VALUE "ProductName", "Classic Shell" + VALUE "ProductVersion", "4, 3, 1, 0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APPICON ICON "..\\ClassicShellSetup\\ClassicShell.ico" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenu.vcproj b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenu.vcproj new file mode 100644 index 0000000..60a62bc --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenu.vcproj @@ -0,0 +1,597 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/Accessibility.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/Accessibility.cpp new file mode 100644 index 0000000..0d51cc8 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/Accessibility.cpp @@ -0,0 +1,322 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// Accessibility.cpp - contains the accessibility class CMenuAccessible, used by CMenuContainer + +#include "stdafx.h" +#include "Accessibility.h" +#include "MenuContainer.h" +#include "Translations.h" + +CMenuAccessible::CMenuAccessible( CMenuContainer *pOwner ) +{ + m_RefCount=0; + m_pOwner=pOwner; + CreateStdAccessibleObject(pOwner->m_hWnd,OBJID_CLIENT,IID_IAccessible,(void**)&m_pStdAccessible); +} + +CMenuAccessible::~CMenuAccessible( void ) +{ +} + +void CMenuAccessible::Reset( void ) +{ + m_pOwner=NULL; + m_pStdAccessible=NULL; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::get_accParent( IDispatch **ppdispParent ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + if (m_pStdAccessible) + return m_pStdAccessible->get_accParent(ppdispParent); + *ppdispParent=NULL; + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::get_accChildCount( long *pcountChildren ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + *pcountChildren=(long)m_pOwner->m_Items.size(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::get_accChild( VARIANT varChild, IDispatch **ppdispChild ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + *ppdispChild=NULL; // no child IAccessibles + if (varChild.vt!=VT_I4) return E_INVALIDARG; + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::get_accName( VARIANT varChild, BSTR *pszName ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + *pszName=NULL; + if (varChild.vt!=VT_I4) return S_FALSE; + if (varChild.lVal==CHILDID_SELF) return S_FALSE; + int index=varChild.lVal-1; + if (index<0 || index>=(int)m_pOwner->m_Items.size()) return S_FALSE; + if (m_pOwner->m_Items[index].id==MENU_SEPARATOR) return S_FALSE; + wchar_t text[256]; + Strcpy(text,_countof(text),m_pOwner->m_Items[index].name); + for (wchar_t *c1=text,*c2=text;;c1++) + { + if (*c1!='&') + *c2++=*c1; + if (*c1==0) break; + } + *pszName=SysAllocString(text); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::get_accDescription( VARIANT varChild, BSTR *pszDescription ) +{ + return get_accName(varChild,pszDescription); +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::get_accRole( VARIANT varChild, VARIANT *pvarRole ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + pvarRole->vt=VT_EMPTY; + if (varChild.vt!=VT_I4) return E_INVALIDARG; + if (varChild.lVal==CHILDID_SELF) + { + pvarRole->vt=VT_I4; + pvarRole->lVal=ROLE_SYSTEM_MENUPOPUP; + return S_OK; + } + int index=varChild.lVal-1; + if (index<0 || index>=(int)m_pOwner->m_Items.size()) return E_INVALIDARG; + pvarRole->vt=VT_I4; + pvarRole->lVal=m_pOwner->m_Items[index].id==MENU_SEPARATOR?ROLE_SYSTEM_SEPARATOR:ROLE_SYSTEM_MENUITEM; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::get_accState( VARIANT varChild, VARIANT *pvarState ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + pvarState->vt=VT_EMPTY; + if (varChild.vt!=VT_I4) return E_INVALIDARG; + int flags=STATE_SYSTEM_FOCUSABLE; + int index=varChild.lVal-1; + if (index>=0 && index<(int)m_pOwner->m_Items.size()) + { + const CMenuContainer::MenuItem &item=m_pOwner->m_Items[index]; + if (m_pOwner->m_HotItem==index) + flags|=STATE_SYSTEM_FOCUSED; + if (item.bFolder) + flags|=STATE_SYSTEM_HASPOPUP; + if (item.id==MENU_SEPARATOR) + flags=0; + RECT rc; + if (!m_pOwner->GetItemRect(index,rc)) + flags|=STATE_SYSTEM_INVISIBLE; + } + pvarState->vt=VT_I4; + pvarState->lVal=flags; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::get_accKeyboardShortcut( VARIANT varChild, BSTR *pszKeyboardShortcut ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + *pszKeyboardShortcut=NULL; + if (varChild.vt!=VT_I4) return E_INVALIDARG; + int flags=0; + int index=varChild.lVal-1; + if (index<0 || index>=(int)m_pOwner->m_Items.size()) + return S_FALSE; + const CMenuContainer::MenuItem &item=m_pOwner->m_Items[index]; + wchar_t str[2]={item.accelerator,0}; + *pszKeyboardShortcut=SysAllocString(str); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::get_accFocus( VARIANT *pvarChild ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + HWND focus=GetFocus(); + pvarChild->vt=VT_EMPTY; + if (m_pOwner->m_hWnd==focus && m_pOwner->m_HotItem>=0) + { + pvarChild->vt=VT_I4; + pvarChild->lVal=m_pOwner->m_HotItem+1; + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::get_accSelection( VARIANT *pvarChildren ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + pvarChildren->vt=VT_EMPTY; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::get_accDefaultAction( VARIANT varChild, BSTR *pszDefaultAction ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + *pszDefaultAction=NULL; + if (varChild.vt!=VT_I4) return E_INVALIDARG; + if (varChild.lVal==CHILDID_SELF) + { + *pszDefaultAction=SysAllocString(FindTranslation(L"Menu.ActionClose",L"Close")); + return S_OK; + } + int index=varChild.lVal-1; + if (index<0 || index>=(int)m_pOwner->m_Items.size()) + return S_FALSE; + const CMenuContainer::MenuItem &item=m_pOwner->m_Items[index]; + if (item.id!=MENU_SEPARATOR && item.id!=MENU_EMPTY && item.id!=MENU_EMPTY_TOP) + *pszDefaultAction=SysAllocString(item.bFolder?FindTranslation(L"Menu.ActionOpen",L"Open"):FindTranslation(L"Menu.ActionExecute",L"Execute")); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::accSelect( long flagsSelect, VARIANT varChild ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + if (varChild.vt!=VT_I4) return E_INVALIDARG; + if (flagsSelect&SELFLAG_TAKEFOCUS) + { + int index=varChild.lVal-1; + if (index<0 || index>=(int)m_pOwner->m_Items.size()) + return S_FALSE; + m_pOwner->ActivateItem(index,CMenuContainer::ACTIVATE_SELECT,NULL,false); + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::accLocation( long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varChild ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + if (varChild.vt!=VT_I4) return E_INVALIDARG; + RECT rc; + if (varChild.lVal==CHILDID_SELF) + { + m_pOwner->GetWindowRect(&rc); + } + else + { + int index=varChild.lVal-1; + if (index<0 || index>=(int)m_pOwner->m_Items.size()) + return S_FALSE; + m_pOwner->GetItemRect(index,rc); + m_pOwner->MapWindowPoints(NULL,&rc); + } + *pxLeft=rc.left; + *pyTop=rc.top; + *pcxWidth=rc.right-rc.left; + *pcyHeight=rc.bottom-rc.top; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::accNavigate( long navDir, VARIANT varStart, VARIANT *pvarEndUpAt ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + pvarEndUpAt->vt=VT_EMPTY; + if (varStart.vt!=VT_I4) return E_INVALIDARG; + + switch (navDir) + { + case NAVDIR_FIRSTCHILD: + if (varStart.lVal!=CHILDID_SELF) return S_FALSE; + pvarEndUpAt->vt=VT_I4; + pvarEndUpAt->lVal=1; + break; + + case NAVDIR_LASTCHILD: + if (varStart.lVal!=CHILDID_SELF) return S_FALSE; + pvarEndUpAt->vt=VT_I4; + pvarEndUpAt->lVal=(int)m_pOwner->m_Items.size(); + break; + + case NAVDIR_NEXT: + case NAVDIR_DOWN: + if (varStart.lVal==CHILDID_SELF) + { + if (m_pStdAccessible) + return m_pStdAccessible->accNavigate(navDir,varStart,pvarEndUpAt); + return S_FALSE; + } + if (varStart.lVal>=(int)m_pOwner->m_Items.size()) + pvarEndUpAt->vt=VT_EMPTY; + else + { + pvarEndUpAt->vt=VT_I4; + pvarEndUpAt->lVal=varStart.lVal+1; + } + break; + + case NAVDIR_PREVIOUS: + case NAVDIR_UP: + if (varStart.lVal==CHILDID_SELF) + { + if (m_pStdAccessible) + return m_pStdAccessible->accNavigate(navDir,varStart,pvarEndUpAt); + return S_FALSE; + } + if (varStart.lVal<1) + pvarEndUpAt->vt=VT_EMPTY; + else + { + pvarEndUpAt->vt=VT_I4; + pvarEndUpAt->lVal=varStart.lVal-1; + } + break; + + // Unsupported directions. + case NAVDIR_LEFT: + case NAVDIR_RIGHT: + if (varStart.lVal==CHILDID_SELF) + { + if (m_pStdAccessible) + return m_pStdAccessible->accNavigate(navDir,varStart,pvarEndUpAt); + } + return S_FALSE; + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::accHitTest( long xLeft, long yTop, VARIANT *pvarChild ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + POINT pt={xLeft,yTop}; + RECT rc; + m_pOwner->GetWindowRect(&rc); + if (!PtInRect(&rc,pt)) + { + pvarChild->vt=VT_EMPTY; + return S_FALSE; + } + POINT pt2=pt; + m_pOwner->ScreenToClient(&pt2); + int index=m_pOwner->HitTest(pt2,NULL); + if (index>=0) + { + pvarChild->vt=VT_I4; + pvarChild->lVal=index+1; + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuAccessible::accDoDefaultAction( VARIANT varChild ) +{ + if (!m_pOwner) return RPC_E_DISCONNECTED; + if (varChild.vt!=VT_I4) return E_INVALIDARG; + if (varChild.lVal==CHILDID_SELF) + { + // close + for (std::vector::reverse_iterator it=CMenuContainer::s_Menus.rbegin();*it!=m_pOwner;++it) + (*it)->PostMessage(WM_CLOSE); + m_pOwner->PostMessage(WM_CLOSE); + return S_OK; + } + int index=varChild.lVal-1; + if (index<0 || index>=(int)m_pOwner->m_Items.size()) + return S_FALSE; + // open or execute + const CMenuContainer::MenuItem &item=m_pOwner->m_Items[index]; + if (item.id!=MENU_SEPARATOR && item.id!=MENU_EMPTY && item.id!=MENU_EMPTY_TOP) + m_pOwner->ActivateItem(index,item.bFolder?CMenuContainer::ACTIVATE_OPEN:CMenuContainer::ACTIVATE_EXECUTE,NULL,NULL); + return S_OK; +} diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/Accessibility.h b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/Accessibility.h new file mode 100644 index 0000000..e376ea8 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/Accessibility.h @@ -0,0 +1,74 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +class CMenuContainer; + +// CMenuAccessible - provides accessibility services for a CMenuContainer +class CMenuAccessible: public IAccessible +{ +public: + CMenuAccessible( CMenuContainer *pOwner ); + ~CMenuAccessible( void ); + void Reset( void ); // called by the owner when it is destroyed + + // IUnknown + virtual STDMETHODIMP QueryInterface( REFIID riid, void **ppvObject ) + { + *ppvObject=NULL; + if (IID_IUnknown==riid || IID_IDispatch==riid || IID_IAccessible==riid) + { + AddRef(); + *ppvObject=static_cast(this); + return S_OK; + } + return E_NOINTERFACE; + } + + virtual ULONG STDMETHODCALLTYPE AddRef( void ) + { + return InterlockedIncrement(&m_RefCount); + } + + virtual ULONG STDMETHODCALLTYPE Release( void ) + { + long nTemp=InterlockedDecrement(&m_RefCount); + if (!nTemp) delete this; + return nTemp; + } + + // IDispatch + virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount( UINT *pctinfo ) { return E_NOTIMPL; } + virtual HRESULT STDMETHODCALLTYPE GetTypeInfo( UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo ) { *ppTInfo=NULL; return E_NOTIMPL; } + virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames( REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId ) { return E_NOTIMPL; } + virtual HRESULT STDMETHODCALLTYPE Invoke( DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr ) { return E_NOTIMPL; } + + // IAccessible + virtual HRESULT STDMETHODCALLTYPE get_accParent( IDispatch **ppdispParent ); + virtual HRESULT STDMETHODCALLTYPE get_accChildCount( long *pcountChildren ); + virtual HRESULT STDMETHODCALLTYPE get_accChild( VARIANT varChild, IDispatch **ppdispChild ); + virtual HRESULT STDMETHODCALLTYPE get_accName( VARIANT varChild, BSTR *pszName ); + virtual HRESULT STDMETHODCALLTYPE get_accValue( VARIANT varChild, BSTR *pszValue ) { *pszValue=NULL; return DISP_E_MEMBERNOTFOUND; } + virtual HRESULT STDMETHODCALLTYPE get_accDescription( VARIANT varChild, BSTR *pszDescription ); + virtual HRESULT STDMETHODCALLTYPE get_accRole( VARIANT varChild, VARIANT *pvarRole ); + virtual HRESULT STDMETHODCALLTYPE get_accState( VARIANT varChild, VARIANT *pvarState ); + virtual HRESULT STDMETHODCALLTYPE get_accHelp( VARIANT varChild, BSTR *pszHelp ) { *pszHelp=NULL; return S_FALSE; } + virtual HRESULT STDMETHODCALLTYPE get_accHelpTopic( BSTR *pszHelpFile, VARIANT varChild, long *pidTopic ) { *pszHelpFile=NULL; return S_FALSE; } + virtual HRESULT STDMETHODCALLTYPE get_accKeyboardShortcut( VARIANT varChild, BSTR *pszKeyboardShortcut ); + virtual HRESULT STDMETHODCALLTYPE get_accFocus( VARIANT *pvarChild ); + virtual HRESULT STDMETHODCALLTYPE get_accSelection( VARIANT *pvarChildren ); + virtual HRESULT STDMETHODCALLTYPE get_accDefaultAction( VARIANT varChild, BSTR *pszDefaultAction ); + virtual HRESULT STDMETHODCALLTYPE accSelect( long flagsSelect, VARIANT varChild ); + virtual HRESULT STDMETHODCALLTYPE accLocation( long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varChild ); + virtual HRESULT STDMETHODCALLTYPE accNavigate( long navDir, VARIANT varStart, VARIANT *pvarEndUpAt ); + virtual HRESULT STDMETHODCALLTYPE accHitTest( long xLeft, long yTop, VARIANT *pvarChild ); + virtual HRESULT STDMETHODCALLTYPE accDoDefaultAction( VARIANT varChild ); + virtual HRESULT STDMETHODCALLTYPE put_accName( VARIANT varChild, BSTR szName ) { return E_NOTIMPL; } + virtual HRESULT STDMETHODCALLTYPE put_accValue( VARIANT varChild, BSTR szValue ) { return DISP_E_MEMBERNOTFOUND; } + +private: + LONG m_RefCount; + CMenuContainer *m_pOwner; + CComPtr m_pStdAccessible; +}; diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartButton.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartButton.cpp new file mode 100644 index 0000000..603db68 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartButton.cpp @@ -0,0 +1,714 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "resource.h" +#include "Translations.h" +#include "Settings.h" +#include "SettingsUI.h" +#include "ResourceHelper.h" +#include "ItemManager.h" +#include "ClassicStartMenuDLL.h" +#include "ClassicStartButton.h" +#include "MenuContainer.h" +#include "TouchHelper.h" +#include "dllmain.h" +#include +#include +#include +#include + +static int START_ICON_SIZE=0; +const int START_BUTTON_PADDING=3; +const int START_BUTTON_OFFSET=2; +const int START_TEXT_PADDING=2; +const int BLEND_PRECISION=1000; + +bool g_bAllowMoveButton; + +// CStartButton - implementation of a start button (for Windows 8) +class CStartButton: public CWindowImpl +{ +public: + DECLARE_WND_CLASS_EX(L"ClassicShell.CStartButton",CS_DBLCLKS,COLOR_MENU) + CStartButton( void ); + + // message handlers + BEGIN_MSG_MAP( CStartButton ) + MESSAGE_HANDLER( WM_CREATE, OnCreate ) + MESSAGE_HANDLER( WM_DESTROY, OnDestroy ) + MESSAGE_HANDLER( WM_CLOSE, OnClose ) + MESSAGE_HANDLER( WM_MOUSEACTIVATE, OnMouseActivate ) + MESSAGE_HANDLER( WM_MOUSEMOVE, OnMouseMove ) + MESSAGE_HANDLER( WM_ERASEBKGND, OnEraseBkgnd ) + MESSAGE_HANDLER( WM_TIMER, OnTimer ) + MESSAGE_HANDLER( WM_SETTINGCHANGE, OnSettingChange ) + MESSAGE_HANDLER( WM_THEMECHANGED, OnThemeChanged ) + MESSAGE_HANDLER( WM_POINTERDOWN, OnPointer ) + MESSAGE_HANDLER( WM_POINTERUPDATE, OnPointer ) + MESSAGE_HANDLER( WM_POINTERUP, OnPointer ) + END_MSG_MAP() + + void SetPressed( bool bPressed ); + void UpdateButton( void ); + void TaskBarMouseMove( void ); + + SIZE GetSize( void ) const { return m_Size; } + bool GetSmallIcons( void ) const { return m_bSmallIcons; } + +protected: + LRESULT OnCreate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnClose( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { return 0; } + LRESULT OnEraseBkgnd( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { return 1; } + LRESULT OnMouseActivate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { return MA_NOACTIVATE; } + LRESULT OnMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSettingChange( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnThemeChanged( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnPointer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + +private: + enum { TIMER_BLEND=1, TIMER_LEAVE=2 }; + + int m_TaskbarId; + SIZE m_Size; + HBITMAP m_Bitmap, m_Blendmap; + unsigned int *m_Bits, *m_BlendBits; + HICON m_Icon; + HFONT m_Font; + bool m_bHot, m_bPressed; + bool m_bTrackMouse; + bool m_bClassic; + bool m_bRTL; + bool m_bSmallIcons; + int m_HotBlend; // 0..BLEND_PRECISION + CWindow m_Tooltip; + HTHEME m_Theme; + + // animations + int m_YOffset; + int m_Frames[3]; + + struct Animation + { + std::vector frames; + int duration; // in ms + bool bBlend; + }; + Animation m_Animations[2]; + + void ParseAnimation( Animation &animation, const std::vector &pixels, int &index, int totalFrames ); + void LoadBitmap( void ); + void SetHot( bool bHot ); +}; + +CStartButton::CStartButton( void ) +{ + m_Size.cx=m_Size.cy=0; + m_TaskbarId=-1; + m_Bitmap=m_Blendmap=NULL; + m_Bits=m_BlendBits=NULL; + m_Icon=NULL; + m_Font=NULL; + m_bHot=m_bPressed=false; + m_bTrackMouse=false; + m_bClassic=m_bSmallIcons=false; + m_bRTL=false; + m_HotBlend=0; + m_Theme=NULL; +} + +LRESULT CStartButton::OnCreate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + int params=(int)(((CREATESTRUCT*)lParam)->lpCreateParams); + m_bRTL=(params&1)!=0; + m_TaskbarId=params>>1; + m_bSmallIcons=IsTaskbarSmallIcons(); + std::vector modules; + m_Icon=NULL; + START_ICON_SIZE=0; + CString iconPath=GetSettingString(L"StartButtonIcon"); + if (_wcsicmp(iconPath,L"none")!=0) + { + START_ICON_SIZE=GetSettingInt(L"StartButtonIconSize"); + if (START_ICON_SIZE==0) + START_ICON_SIZE=GetSystemMetrics(m_bSmallIcons?SM_CXSMICON:SM_CXICON); + if (START_ICON_SIZE<8) START_ICON_SIZE=8; + if (START_ICON_SIZE>64) START_ICON_SIZE=64; + m_Icon=LoadIcon(START_ICON_SIZE,iconPath,modules); + for (std::vector::const_iterator it=modules.begin();it!=modules.end();++it) + FreeLibrary(*it); + if (!m_Icon) + m_Icon=(HICON)LoadImage(g_Instance,MAKEINTRESOURCE(IDI_APPICON),IMAGE_ICON,START_ICON_SIZE,START_ICON_SIZE,LR_DEFAULTCOLOR); + } + int dpi=CItemManager::GetDPI(false); + m_Font=CreateFont(10*dpi/72,0,0,0,FW_BOLD,0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,L"Tahoma"); + int val=1; + DwmSetWindowAttribute(m_hWnd,DWMWA_EXCLUDED_FROM_PEEK,&val,sizeof(val)); + val=DWMFLIP3D_EXCLUDEABOVE; + DwmSetWindowAttribute(m_hWnd,DWMWA_FLIP3D_POLICY,&val,sizeof(val)); + LoadBitmap(); + m_Tooltip=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_TRANSPARENT|(m_bRTL?WS_EX_LAYOUTRTL:0),TOOLTIPS_CLASS,NULL,WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP,0,0,0,0,NULL,NULL,g_Instance,NULL); + OnThemeChanged(WM_THEMECHANGED,0,0,bHandled); + m_bPressed=true; + SetPressed(false); + bHandled=FALSE; + return 0; +} + +LRESULT CStartButton::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_Bitmap) DeleteObject(m_Bitmap); + if (m_Blendmap) DeleteObject(m_Blendmap); + if (m_Icon) DestroyIcon(m_Icon); + if (m_Font) DeleteObject(m_Font); + if (m_Theme) CloseThemeData(m_Theme); + m_Tooltip.DestroyWindow(); + KillTimer(TIMER_BLEND); + bHandled=FALSE; + return 0; +} + +void CStartButton::UpdateButton( void ) +{ + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + + HDC hSrc=CreateCompatibleDC(NULL); + RECT rc; + GetWindowRect(&rc); + SIZE size={rc.right-rc.left,rc.bottom-rc.top}; + if (m_bClassic) + { + if (m_bRTL) + SetLayout(hSrc,LAYOUT_RTL); + HGDIOBJ bmp0=SelectObject(hSrc,m_Blendmap); + RECT rc={0,0,m_Size.cx,m_Size.cy}; + FillRect(hSrc,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH)); + InflateRect(&rc,-START_BUTTON_OFFSET,-START_BUTTON_OFFSET); + int offset=0; + if (m_Theme) + { + int state=m_bPressed?PBS_PRESSED:(m_bHot?PBS_HOT:PBS_NORMAL); + DrawThemeBackground(m_Theme,hSrc,BP_PUSHBUTTON,state,&rc,NULL); + } + else + { + DrawFrameControl(hSrc,&rc,DFC_BUTTON,DFCS_BUTTONPUSH|(m_bPressed?DFCS_PUSHED:0)); + offset=m_bPressed?1:0; + } + if (m_Icon) + DrawIconEx(hSrc,START_BUTTON_PADDING+START_BUTTON_OFFSET+offset,(m_Size.cy-START_ICON_SIZE)/2+offset,m_Icon,0,0,0,NULL,DI_NORMAL|DI_NOMIRROR); + rc.left+=START_BUTTON_PADDING+START_ICON_SIZE+START_TEXT_PADDING+offset; + rc.top+=START_BUTTON_PADDING+offset; + rc.right-=START_BUTTON_PADDING+START_TEXT_PADDING-offset; + rc.bottom-=START_BUTTON_PADDING-offset; + HFONT font0=(HFONT)SelectObject(hSrc,m_Font); + COLORREF color=GetSysColor(COLOR_BTNTEXT); + if (m_Theme) + { + int state=m_bPressed?PBS_PRESSED:(m_bHot?PBS_HOT:PBS_NORMAL); + if (FAILED(GetThemeColor(m_Theme,BP_PUSHBUTTON,state,TMT_TEXTCOLOR,&color))) + color=GetSysColor(COLOR_BTNTEXT); + } + SetTextColor(hSrc,color); + SetBkMode(hSrc,TRANSPARENT); + CString startStr=GetSettingString(L"StartButtonText"); + const wchar_t *startText=startStr; + if (startText[0]=='$') + startText=FindTranslation(startText+1,L"Start"); + DrawText(hSrc,startText,-1,&rc,DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER); + SelectObject(hSrc,bmp0); + // mark the button pixels as opaque + for (int y=START_BUTTON_OFFSET;y>24); + int r1=(pixel1>>16)&255; + int g1=(pixel1>>8)&255; + int b1=(pixel1)&255; + int a2=(pixel2>>24); + int r2=(pixel2>>16)&255; + int g2=(pixel2>>8)&255; + int b2=(pixel2)&255; + int a=a1+(a2-a1)*blend/BLEND_PRECISION; + int r=r1+(r2-r1)*blend/BLEND_PRECISION; + int g=g1+(g2-g1)*blend/BLEND_PRECISION; + int b=b1+(b2-b1)*blend/BLEND_PRECISION; + m_BlendBits[i]=(a<<24)|(r<<16)|(g<<8)|b; + } + HGDIOBJ bmp0=SelectObject(hSrc,m_Blendmap); + POINT pos={0,0}; + UpdateLayeredWindow(m_hWnd,NULL,NULL,&size,hSrc,&pos,0,&func,ULW_ALPHA); + SelectObject(hSrc,bmp0); + } + } + DeleteDC(hSrc); +} + +void CStartButton::SetHot( bool bHot ) +{ + if (m_bHot!=bHot) + { + m_bHot=bHot; + if (!m_bPressed) + { + if (bHot) + CMenuContainer::PlayMenuSound(SOUND_BUTTON_HOVER); + SetTimer(TIMER_BLEND,30); + } + } +} + +LRESULT CStartButton::OnMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + SetTimer(TIMER_LEAVE,30); + SetHot(true); + return 0; +} + +void CStartButton::TaskBarMouseMove( void ) +{ + SetHot(true); + SetTimer(CStartButton::TIMER_LEAVE,30); +} + +LRESULT CStartButton::OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==TIMER_BLEND) + { + int duration=m_Animations[m_bHot?0:1].duration; + int blend; + if (duration>0) + { + int dp=(30*BLEND_PRECISION)/duration; + blend=m_HotBlend+(m_bHot?dp:-dp); + if (blend<0) blend=0; + if (blend>BLEND_PRECISION) blend=BLEND_PRECISION; + } + else + { + blend=m_bHot?BLEND_PRECISION:0; + } + if (blend!=m_HotBlend) + { + m_HotBlend=blend; + UpdateButton(); + } + else + KillTimer(TIMER_BLEND); + } + else if (wParam==TIMER_LEAVE) + { + CPoint pt(GetMessagePos()); + if (WindowFromPoint(pt)!=m_hWnd && !PointAroundStartButton(m_TaskbarId)) + { + KillTimer(TIMER_LEAVE); + SetHot(false); + } + } + else + bHandled=FALSE; + return 0; +} + +LRESULT CStartButton::OnSettingChange( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + UpdateButton(); + bHandled=FALSE; + return 0; +} + +LRESULT CStartButton::OnThemeChanged( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_Theme) CloseThemeData(m_Theme); + m_Theme=NULL; + HIGHCONTRAST contrast={sizeof(contrast)}; + if (GetWinVersion()>=WIN_VER_WIN8 && SystemParametersInfo(SPI_GETHIGHCONTRAST,sizeof(contrast),&contrast,0) && (contrast.dwFlags&HCF_HIGHCONTRASTON)) + { + // only use themes on Win8 with high contrast + m_Theme=OpenThemeData(m_hWnd,L"button"); + UpdateButton(); + } + return 0; +} + +LRESULT CStartButton::OnPointer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + POINTER_INPUT_TYPE type; + GetPointerType2(GET_POINTERID_WPARAM(wParam),&type); + if (type==PT_TOUCH) + return GetParent().SendMessage(uMsg,wParam,lParam); + bHandled=FALSE; + return 0; +} + +void CStartButton::SetPressed( bool bPressed ) +{ + if (m_bPressed!=bPressed) + { + m_bPressed=bPressed; + m_HotBlend=m_bHot?BLEND_PRECISION:0; + KillTimer(TIMER_BLEND); + TOOLINFO tool={sizeof(tool),TTF_CENTERTIP|TTF_SUBCLASS|TTF_IDISHWND|TTF_TRANSPARENT|(m_bRTL?TTF_RTLREADING:0),m_hWnd}; + tool.uId=(UINT_PTR)m_hWnd; + CString startStr=GetSettingString(L"StartButtonTip"); + const wchar_t *startText=startStr; + if (startText[0]=='$') + startText=FindTranslation(startText+1,L"Start"); + wchar_t buf[256]; + Strcpy(buf,_countof(buf),startText); + DoEnvironmentSubst(buf,_countof(buf)); + tool.lpszText=buf; + m_Tooltip.SendMessage(bPressed?TTM_DELTOOL:TTM_ADDTOOL,0,(LPARAM)&tool); + UpdateButton(); + } +} + +TStartButtonType GetStartButtonType( void ) +{ + bool bDef; + TStartButtonType buttonType=(TStartButtonType)GetSettingInt(L"StartButtonType",bDef); + if (bDef) + { + bool bClassic; + if (GetWinVersion() &pixels, int &index, int totalFrames ) +{ + animation.duration=0; + animation.bBlend=true; + if (index>=(int)pixels.size()) + { + animation.frames.clear(); + return; + } + + animation.duration=((pixels[index]&255)*1000)/60; + animation.bBlend=((pixels[index]>>16)&255)==1; + int ranges=(pixels[index]>>8)&255; + if (ranges>0 && index+ranges<(int)pixels.size()) + { + animation.frames.clear(); + for (int r=1;r<=ranges;r++) + { + int from=pixels[index+r]&255; + if (from>totalFrames-1) from=totalFrames-1; + int to=(pixels[index+r]>>16)&255; + if (to>totalFrames-1) to=totalFrames-1; + if (fromto) + { + for (int i=from;i>=to;i--) + animation.frames.push_back(i); + } + else + { + animation.frames.push_back(from); + } + } + } + index+=ranges+1; +} + +void CStartButton::LoadBitmap( void ) +{ + m_Size.cx=m_Size.cy=0; + if (m_Bitmap) DeleteObject(m_Bitmap); + if (m_Blendmap) DeleteObject(m_Blendmap); + m_Bitmap=m_Blendmap=NULL; + m_Bits=m_BlendBits=NULL; + TStartButtonType buttonType=GetStartButtonType(); + m_bClassic=(buttonType==START_BUTTON_CLASSIC); + wchar_t path[_MAX_PATH]; + SIZE size={0,0}; + if (buttonType==START_BUTTON_CUSTOM) + { + Strcpy(path,_countof(path),GetSettingString(L"StartButtonPath")); + DoEnvironmentSubst(path,_countof(path)); + size.cx=GetSettingInt(L"StartButtonSize"); + } + + m_YOffset=0; + m_Frames[0]=0; // Normal + m_Frames[1]=1; // Hot + m_Frames[2]=2; // Pressed + m_Animations[0].frames.resize(2); m_Animations[0].frames[0]=0; m_Animations[0].frames[1]=1; m_Animations[0].duration=300; m_Animations[0].bBlend=true; // NH + m_Animations[1].frames.resize(2); m_Animations[1].frames[0]=1; m_Animations[1].frames[1]=0; m_Animations[1].duration=300; m_Animations[1].bBlend=true; // HN + + if (m_bClassic) + { + // classic theme + HDC hdc=CreateCompatibleDC(NULL); + HFONT font0=(HFONT)SelectObject(hdc,m_Font); + RECT rc={0,0,0,0}; + CString startStr=GetSettingString(L"StartButtonText"); + const wchar_t *startText=startStr; + if (startText[0]=='$') + startText=FindTranslation(startText+1,L"Start"); + DrawText(hdc,startText,-1,&rc,DT_NOPREFIX|DT_SINGLELINE|DT_CALCRECT); + m_Size.cx=rc.right+START_ICON_SIZE+2*START_TEXT_PADDING+2*START_BUTTON_PADDING+2*START_BUTTON_OFFSET; + m_Size.cy=rc.bottom; + if (m_Size.cy buttonAnim; + if (*path) + { + m_Bitmap=LoadImageFile(path,&size,true,true,&buttonAnim); + } + if (!m_Bitmap) + { + int id; + int dpi=CItemManager::GetDPI(false); + if (dpi<120) + id=IDB_BUTTON96; + else if (dpi<144) + id=IDB_BUTTON120; + else if (dpi<180) + id=IDB_BUTTON144; + else + id=IDB_BUTTON180; + m_Bitmap=LoadImageResource(g_Instance,MAKEINTRESOURCE(id),true,true); + bResource=true; + } + BITMAP info; + GetObject(m_Bitmap,sizeof(info),&info); + m_Size.cx=info.bmWidth; + m_Size.cy=info.bmHeight; + m_Bits=(unsigned int*)info.bmBits; + if (buttonAnim.empty() && info.bmWidth>=10 && (m_Bits[0]&0xFFFFFF)==ANIM_BUTTON_TAG1 && (m_Bits[1]&0xFFFFFF)==ANIM_BUTTON_TAG2) + { + m_YOffset=(m_Bits[2]>>16)&255; + if (m_YOffset>info.bmHeight) m_YOffset=info.bmHeight; + if (m_YOffset>0) + { + int size=info.bmWidth*m_YOffset; + buttonAnim.resize(size); + memcpy(&buttonAnim[0],m_Bits,size*4); + m_Bits+=size; + m_Size.cy=info.bmHeight-m_YOffset; + } + } + if (!buttonAnim.empty()) + { + int total=buttonAnim[2]&255; + if (total<1) total=1; + if (total>info.bmHeight-1) total=info.bmHeight-1; + m_Size.cy/=total; + m_Frames[0]=buttonAnim[3]&255; // Normal + if (m_Frames[0]>total-1) m_Frames[0]=total-1; + m_Frames[1]=buttonAnim[4]&255; // Hot + if (m_Frames[1]>total-1) m_Frames[1]=total-1; + m_Frames[2]=buttonAnim[5]&255; // Pressed + if (m_Frames[2]>total-1) m_Frames[2]=total-1; + + m_Animations[0].frames[0]=m_Animations[1].frames[1]=m_Frames[0]; + m_Animations[0].frames[1]=m_Animations[1].frames[0]=m_Frames[1]; + int index=6; + ParseAnimation(m_Animations[0],buttonAnim,index,total); + ParseAnimation(m_Animations[1],buttonAnim,index,total); + } + else + { + m_Size.cy/=3; + } + } + if (m_Size.cx>0) + { + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=m_Size.cx; + bi.bmiHeader.biHeight=-m_Size.cy; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + HDC hdc=CreateCompatibleDC(NULL); + m_Blendmap=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&m_BlendBits,NULL,0); + DeleteDC(hdc); + } +} + +static std::map g_StartButtons; + +HWND CreateStartButton( int taskbarId, HWND taskBar, HWND rebar, const RECT &rcTask ) +{ + bool bRTL=(GetWindowLong(rebar,GWL_EXSTYLE)&WS_EX_LAYOUTRTL)!=0; + DWORD styleTopmost=GetWindowLong(taskBar,GWL_EXSTYLE)&WS_EX_TOPMOST; + CStartButton &button=g_StartButtons[taskbarId]; + button.Create(taskBar,NULL,NULL,WS_POPUP,styleTopmost|WS_EX_TOOLWINDOW|WS_EX_LAYERED,0U,(void*)(taskbarId*2+(bRTL?1:0))); + SIZE size=button.GetSize(); + RECT rcButton; + MONITORINFO info; + UINT uEdge=GetTaskbarPosition(taskBar,&info,NULL,NULL); + if (uEdge==ABE_LEFT || uEdge==ABE_RIGHT) + { + if (GetSettingInt(L"StartButtonType")!=START_BUTTON_CUSTOM || !GetSettingBool(L"StartButtonAlign")) + rcButton.left=(rcTask.left+rcTask.right-size.cx)/2; + else if (uEdge==ABE_LEFT) + rcButton.left=rcTask.left; + else + rcButton.left=rcTask.right-size.cx; + rcButton.top=rcTask.top; + } + else + { + if (bRTL) + rcButton.left=rcTask.right-size.cx; + else + rcButton.left=rcTask.left; + if (GetSettingInt(L"StartButtonType")!=START_BUTTON_CUSTOM || !GetSettingBool(L"StartButtonAlign")) + rcButton.top=(rcTask.top+rcTask.bottom-size.cy)/2; + else if (uEdge==ABE_TOP) + rcButton.top=rcTask.top; + else + rcButton.top=rcTask.bottom-size.cy; + } + rcButton.right=rcButton.left+size.cx; + rcButton.bottom=rcButton.top+size.cy; + g_bAllowMoveButton=true; + button.SetWindowPos(HWND_TOP,&rcButton,SWP_SHOWWINDOW|SWP_NOOWNERZORDER|SWP_NOACTIVATE); + g_bAllowMoveButton=false; + + RECT rc; + IntersectRect(&rc,&rcButton,&info.rcMonitor); + HRGN rgn=CreateRectRgn(rc.left-rcButton.left,rc.top-rcButton.top,rc.right-rcButton.left,rc.bottom-rcButton.top); + if (!SetWindowRgn(button,rgn,FALSE)) + { + AddTrackedObject(rgn); + DeleteObject(rgn); + } + + button.UpdateButton(); + return button.m_hWnd; +} + +void DestroyStartButton( int taskbarId ) +{ + std::map::iterator it=g_StartButtons.find(taskbarId); + if (it!=g_StartButtons.end()) + { + if (it->second.m_hWnd) + it->second.DestroyWindow(); + g_StartButtons.erase(it); + } +} + +void UpdateStartButton( int taskbarId ) +{ + std::map::iterator it=g_StartButtons.find(taskbarId); + if (it!=g_StartButtons.end()) + it->second.UpdateButton(); +} + +void PressStartButton( int taskbarId, bool bPressed ) +{ + std::map::iterator it=g_StartButtons.find(taskbarId); + if (it!=g_StartButtons.end()) + it->second.SetPressed(bPressed); +} + +SIZE GetStartButtonSize( int taskbarId ) +{ + std::map::iterator it=g_StartButtons.find(taskbarId); + if (it!=g_StartButtons.end()) + return it->second.GetSize(); + SIZE size={0,0}; + return size; +} + +bool IsStartButtonSmallIcons( int taskbarId ) +{ + std::map::iterator it=g_StartButtons.find(taskbarId); + if (it!=g_StartButtons.end()) + return it->second.GetSmallIcons(); + return false; +} + +bool IsTaskbarSmallIcons( void ) +{ + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced")!=ERROR_SUCCESS) + return true; + DWORD val; + return regKey.QueryDWORDValue(L"TaskbarSmallIcons",val)!=ERROR_SUCCESS || val; +} + +void TaskBarMouseMove( int taskbarId ) +{ + std::map::iterator it=g_StartButtons.find(taskbarId); + if (it!=g_StartButtons.end()) + it->second.TaskBarMouseMove(); +} diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartButton.h b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartButton.h new file mode 100644 index 0000000..8fb7e1e --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartButton.h @@ -0,0 +1,24 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +enum TStartButtonType +{ + START_BUTTON_AERO, + START_BUTTON_CLASSIC, + START_BUTTON_CUSTOM, +// START_BUTTON_METRO, +}; + +HWND CreateStartButton( int taskbarId, HWND taskBar, HWND rebar, const RECT &rcTask ); +void DestroyStartButton( int taskbarId ); +void UpdateStartButton( int taskbarId ); +void PressStartButton( int taskbarId, bool bPressed ); +TStartButtonType GetStartButtonType( void ); +SIZE GetStartButtonSize( int taskbarId ); +bool IsStartButtonSmallIcons( int taskbarId ); +bool IsTaskbarSmallIcons( void ); +void TaskBarMouseMove( int taskbarId ); + +extern bool g_bAllowMoveButton; diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartMenuDLL.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartMenuDLL.cpp new file mode 100644 index 0000000..943c31f --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartMenuDLL.cpp @@ -0,0 +1,4088 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "resource.h" +#include "ClassicStartMenuDLL.h" +#include "ClassicStartButton.h" +#include "MenuContainer.h" +#include "SettingsParser.h" +#include "Translations.h" +#include "Settings.h" +#include "SettingsUI.h" +#include "ResourceHelper.h" +#include "LogManager.h" +#include "TouchHelper.h" +#include "IatHookHelper.h" +#include "dllmain.h" +#include +#include +#include +#include +#include +#include + +#define HOOK_DROPTARGET // define this to replace the IDropTarget of the start button +#define START_TOUCH // touch support for the start button + +#ifdef BUILD_SETUP +#ifndef HOOK_DROPTARGET +#define HOOK_DROPTARGET // make sure it is defined in Setup +#endif +#endif + +const int MAIN_TASK_BAR=0; +std::map g_TaskbarInfos; +static int g_LastTaskbar=MAIN_TASK_BAR; +static int g_NextTaskbar=0; +HWND g_TaskBar, g_OwnerWindow; +HWND g_TopWin7Menu, g_AllPrograms, g_ProgramsButton, g_UserPic; // from the Windows menu +HWND g_ProgWin; +HMONITOR g_WSMHMonitor; +static HWND g_WinStartButton; +static UINT g_StartMenuMsg; +static HWND g_Tooltip; +static TOOLINFO g_StartButtonTool; +static bool g_bHotkeyShift; +static int g_HotkeyCSM, g_HotkeyWSM, g_HotkeyShiftID, g_HotkeyCSMID, g_HotkeyWSMID; +static HHOOK g_ProgHook, g_StartHook, g_AppManagerHook, g_NewWindowHook, g_StartMenuHook; +static bool g_bAllProgramsTimer; +static bool g_bInMenu; +static DWORD g_LastClickTime; +static DWORD g_LastHoverPos; +static bool g_bCrashDump; +static int g_SkipMetroCount; +static DWORD g_StartButtonOldSizes[12]; +const int FIRST_BUTTON_BITMAP=6801; +static HWND g_TopDesktopBar; +static DWORD g_AppManagerThread; +static std::set g_EdgeWindows; +static bool g_bTrimHooks; +static DWORD g_TaskbarThreadId; +static HWND g_CurrentTaskList, g_CurrentTaskChevron, g_CurrentRebar, g_CurrentTaskbarPart, g_CurrentTaskbarButton, g_CurrentDesktopButton; +static HBITMAP g_TaskbarTexture; +static SIZE g_TaskbarTextureSize; +static TTaskbarTile g_TaskbarTileH, g_TaskbarTileV; +static RECT g_TaskbarMargins; +int g_CurrentCSMTaskbar=-1, g_CurrentWSMTaskbar=-1; + +static void FindWindowsMenu( void ); +static void RecreateStartButton( int taskbarId ); +static bool WindowsMenuOpened( void ); + +static tSetWindowCompositionAttribute SetWindowCompositionAttribute; + +enum +{ + OPEN_NOTHING, + OPEN_CLASSIC, + OPEN_WINDOWS, + OPEN_BOTH, + OPEN_DESKTOP, + OPEN_CORTANA, +}; + +// MiniDumpNormal - minimal information +// MiniDumpWithDataSegs - include global variables +// MiniDumpWithFullMemory - include heap +MINIDUMP_TYPE MiniDumpType=MiniDumpNormal; + +static DWORD WINAPI SaveCrashDump( void *pExceptionInfo ) +{ + HMODULE dbghelp=NULL; + { + wchar_t path[_MAX_PATH]=L"%LOCALAPPDATA%"; + DoEnvironmentSubst(path,_countof(path)); + + dbghelp=LoadLibrary(L"dbghelp.dll"); + + LPCTSTR szResult = NULL; + + typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, + CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, + CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, + CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam + ); + MINIDUMPWRITEDUMP dump=NULL; + if (dbghelp) + dump=(MINIDUMPWRITEDUMP)GetProcAddress(dbghelp,"MiniDumpWriteDump"); + if (dump) + { + HANDLE file; + for (int i=1;;i++) + { + wchar_t fname[_MAX_PATH]; + Sprintf(fname,_countof(fname),L"%s\\CSM_Crash%d.dmp",path,i); + file=CreateFile(fname,GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL); + if (file!=INVALID_HANDLE_VALUE || GetLastError()!=ERROR_FILE_EXISTS) break; + } + if (file!=INVALID_HANDLE_VALUE) + { + _MINIDUMP_EXCEPTION_INFORMATION ExInfo; + ExInfo.ThreadId = GetCurrentThreadId(); + ExInfo.ExceptionPointers = (_EXCEPTION_POINTERS*)pExceptionInfo; + ExInfo.ClientPointers = NULL; + + dump(GetCurrentProcess(),GetCurrentProcessId(),file,MiniDumpType,&ExInfo,NULL,NULL); + CloseHandle(file); + } + } + } + if (dbghelp) FreeLibrary(dbghelp); + TerminateProcess(GetCurrentProcess(),10); + return 0; +} + +LONG _stdcall TopLevelFilter( _EXCEPTION_POINTERS *pExceptionInfo ) +{ + if (pExceptionInfo->ExceptionRecord->ExceptionCode==EXCEPTION_STACK_OVERFLOW) + { + // start a new thread to get a fresh stack (hoping there is enough stack left for CreateThread) + HANDLE thread=CreateThread(NULL,0,SaveCrashDump,pExceptionInfo,0,NULL); + WaitForSingleObject(thread,INFINITE); + CloseHandle(thread); + } + else + SaveCrashDump(pExceptionInfo); + return EXCEPTION_CONTINUE_SEARCH; +} + +void InvalidParameterHandler( const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved ) +{ + *(int*)0=0; // force a crash to generate a dump +} + +/////////////////////////////////////////////////////////////////////////////// + +interface ISwitchModeManager: public IUnknown +{ + STDMETHOD(method3)(); + STDMETHOD(method4)(); + STDMETHOD(method5)(); + STDMETHOD(method6)(); + STDMETHOD(method7)(); + STDMETHOD(ShowLauncherTipContextMenu)( POINT *pt ); +}; + +interface IImmersiveLauncherThumbnailProvider: public IUnknown +{ + STDMETHOD(GetBitmap)( SIZE size, int scale, int, ISharedBitmap **ppBitmap ); +}; + +interface IImmersiveMonitor: public IUnknown +{ + STDMETHOD(method3)(); + STDMETHOD(method4)(); + STDMETHOD(GetHandle)(HMONITOR*); +}; + +interface IImmersiveLauncher80: public IUnknown +{ + STDMETHOD(ShowStartView)( int method ); + STDMETHOD(method4)(); + STDMETHOD(method5)(); + STDMETHOD(method6)(); + STDMETHOD(method7)(); + STDMETHOD(Dismiss)( int method ); +}; + +interface IImmersiveLauncher81: public IUnknown +{ + STDMETHOD(ShowStartView)( int method, int flags ); + STDMETHOD(method4)(); + STDMETHOD(method5)(); + STDMETHOD(method6)(); + STDMETHOD(method7)(); + STDMETHOD(method8)(); + STDMETHOD(method9)(); + STDMETHOD(IsVisible)(BOOL *); + STDMETHOD(method11)(); + STDMETHOD(method12)(); + STDMETHOD(method13)(); + STDMETHOD(method14)(); + STDMETHOD(method15)(); + STDMETHOD(method16)(); + STDMETHOD(method17)(); + STDMETHOD(ConnectToMonitor)(IUnknown *); + STDMETHOD(GetMonitor)(IImmersiveMonitor **); +}; + +interface IImmersiveLauncher10RS: public IUnknown +{ + STDMETHOD(ShowStartView)( int method, int flags ); + STDMETHOD(method4)(); + STDMETHOD(method5)(); + STDMETHOD(method6)(); + STDMETHOD(IsVisible)(BOOL *); + STDMETHOD(method8)(); + STDMETHOD(method9)(); + STDMETHOD(ConnectToMonitor)(IUnknown *); + STDMETHOD(GetMonitor)(IImmersiveMonitor **); +}; + +static const GUID SID_SwitchModeManager={0x085920a1,0x28d3,0x44c1,{0x89,0x7d,0x3b,0xe6,0xd0,0x4b,0x2e,0x07}}; +static const GUID IID_ISwitchModeManager={0x976c17be,0xe2d5,0x4f36,{0x93,0x4a,0x7e,0x82,0xf7,0x10,0xea,0xe1}}; + +static const GUID SID_ImmersiveLauncherThumbnailProvider={0x66ce8036,0x400c,0x42f7,{0x99,0x34,0x02,0xf8,0x84,0xfe,0x27,0x4f}}; +static const GUID IID_IImmersiveLauncherThumbnailProvider={0x35c01454,0x53f4,0x4818,{0xba,0x8c,0x7a,0xba,0xdc,0x0f,0xfe,0xe6}}; + +static const GUID SID_ImmersiveLauncher={0x6f86e01c,0xc649,0x4d61,{0xbe,0x23,0xf1,0x32,0x2d,0xde,0xca,0x9d}}; +static const GUID IID_IImmersiveLauncher80={0xfd8b3e33,0xa1f7,0x4e9a,{0x80,0xad,0x80,0x02,0xc7,0x46,0xbe,0x37}}; +static const GUID IID_IImmersiveLauncher81={0x93f91f5a,0xa4ca,0x4205,{0x9b,0xeb,0xce,0x4d,0x17,0xc7,0x08,0xf9}}; +static const GUID IID_IImmersiveLauncher10RS={0xd8d60399,0xa0f1,0xf987,{0x55,0x51,0x32,0x1f,0xd1,0xb4,0x98,0x64}}; // 14257 + +static const GUID IID_IImmersiveLauncherProvider={0x6d5140c1,0x7436,0x11ce,{0x80,0x34,0x00,0xaa,0x00,0x60,0x09,0xfa}}; + +static const CLSID CLSID_ImmersiveShell={0xc2f03a33, 0x21f5, 0x47fa, {0xb4, 0xbb, 0x15, 0x63, 0x62, 0xa2, 0xf2, 0x39}}; + +static const GUID SID_LauncherTipContextMenu={0xb8c1db5f, 0xcbb3, 0x48bc, {0xaf, 0xd9, 0xce, 0x6b, 0x88, 0x0c, 0x79, 0xed}}; + +interface ILauncherTipContextMenu: public IUnknown +{ + STDMETHOD(ShowLauncherTipContextMenu)( POINT *pt ); +}; + +interface IImmersiveMonitorService: public IUnknown +{ + STDMETHOD(method3)(); + STDMETHOD(method4)(); + STDMETHOD(method5)(); + STDMETHOD(GetFromHandle)(HMONITOR, IUnknown **); + STDMETHOD(method7)(); + STDMETHOD(method8)(); + STDMETHOD(method9)(); + STDMETHOD(method10)(); + STDMETHOD(method11)(); + STDMETHOD(method12)(); + STDMETHOD(method13)(); + STDMETHOD(SetImmersiveMonitor)(IUnknown *); +}; + +static const GUID SID_IImmersiveMonitorService={0x47094e3a,0x0cf2,0x430f,{0x80,0x6f,0xcf,0x9e,0x4f,0x0f,0x12,0xdd}}; +static const GUID IID_IImmersiveMonitorService={0x4d4c1e64,0xe410,0x4faa,{0xba,0xfa,0x59,0xca,0x06,0x9b,0xfe,0xc2}}; + + +struct StartScreenThumbInfo +{ + SIZE size; + HBITMAP bitmap; + HANDLE event; +}; + +static bool CreateImmersiveShell( CComPtr &ptr ) +{ + if (GetWinVersion() +{ +public: + DECLARE_WND_CLASS_EX(L"ClassicShell.COwnerWindow",0,COLOR_MENU) + + // message handlers + BEGIN_MSG_MAP( COwnerWindow ) + MESSAGE_HANDLER( WM_ACTIVATE, OnActivate ) + MESSAGE_HANDLER( WM_CLEAR, OnClear ) + MESSAGE_HANDLER( WM_SYSCOLORCHANGE, OnColorChange ) + MESSAGE_HANDLER( WM_SETTINGCHANGE, OnSettingChange ) + MESSAGE_HANDLER( WM_DISPLAYCHANGE, OnDisplayChange ) + END_MSG_MAP() + +protected: + LRESULT OnActivate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) + { + if (LOWORD(wParam)!=WA_INACTIVE) + return 0; + + if (CMenuContainer::s_bPreventClosing && lParam && (::GetWindowLong((HWND)lParam,GWL_EXSTYLE)&WS_EX_TOPMOST)) + return 0; + + // check if another menu window is being activated + // if not, close all menus + for (std::vector::const_iterator it=CMenuContainer::s_Menus.begin();it!=CMenuContainer::s_Menus.end();++it) + if ((*it)->m_hWnd==(HWND)lParam) + return 0; + + if (CMenuContainer::s_bPreventClosing) + { + CMenuContainer::HideTemp(true); + } + else + { + for (std::vector::reverse_iterator it=CMenuContainer::s_Menus.rbegin();it!=CMenuContainer::s_Menus.rend();++it) + if (!(*it)->m_bDestroyed) + (*it)->PostMessage(WM_CLOSE); + } + return 0; + } + + LRESULT OnClear( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) + { + bool bHide=(wParam!=0); // hide or destroy + if (CMenuContainer::s_bTempHidden!=bHide) + { + CMenuContainer::s_bTempHidden=bHide; + if (bHide && CMenuContainer::s_UserPicture.m_hWnd) + CMenuContainer::s_UserPicture.ShowWindow(SW_HIDE); + for (std::vector::iterator it=CMenuContainer::s_Menus.begin();it!=CMenuContainer::s_Menus.end();++it) + { + if ((*it)->m_hWnd && !(*it)->m_bDestroyed) + { + (*it)->m_bClosing=true; + if (!bHide) + (*it)->PostMessage(WM_CLOSE); + else + (*it)->ShowWindow(SW_HIDE); + } + } + } + return 0; + } + + LRESULT OnColorChange( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) + { + CMenuContainer::s_Skin.Hash=0; + return 0; + } + + + LRESULT OnSettingChange( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) + { + if (wParam==SPI_SETWORKAREA) + { + if (!CMenuContainer::s_Menus.empty()) + CMenuContainer::s_Menus[0]->NotifyDisplayChange(); + } + return 0; + } + + + LRESULT OnDisplayChange( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) + { + if (!CMenuContainer::s_Menus.empty()) + CMenuContainer::s_Menus[0]->NotifyDisplayChange(); + return 0; + } +}; + +static COwnerWindow g_Owner; + +/////////////////////////////////////////////////////////////////////////////// + +bool TaskbarInfo::HasPart( HWND part ) const +{ + for (std::vector::const_iterator it=taskbarParts.begin();it!=taskbarParts.end();++it) + if (*it==part) + return true; + return false; +} + +static const TaskbarInfo *GetDefaultTaskbarInfo( void ) +{ + if (GetSettingBool(L"AllTaskbars")) + { + HMONITOR monitor=MonitorFromPoint(CPoint(GetMessagePos()),MONITOR_DEFAULTTONEAREST); + for (std::map::const_iterator it=g_TaskbarInfos.begin();it!=g_TaskbarInfos.end();++it) + { + MONITORINFO info; + HMONITOR monitor2=NULL; + if (GetTaskbarPosition(it->second.taskBar,&info,&monitor2,NULL)!=0xFFFFFFFF && monitor2==monitor) + return &it->second; + } + std::map::const_iterator it=g_TaskbarInfos.find(g_LastTaskbar); + if (it!=g_TaskbarInfos.end()) + return &it->second; + } + return &g_TaskbarInfos.begin()->second; +} + +TaskbarInfo *GetTaskbarInfo( int taskbarId ) +{ + std::map::iterator it=g_TaskbarInfos.find(taskbarId); + return (it==g_TaskbarInfos.end())?NULL:&it->second; +} + +static TaskbarInfo *FindTaskBarInfoButton( HWND button ) +{ + for (std::map::iterator it=g_TaskbarInfos.begin();it!=g_TaskbarInfos.end();++it) + if (it->second.startButton==button || it->second.oldButton==button) + return &it->second; + return NULL; +} + +static TaskbarInfo *FindTaskBarInfoBar( HWND bar ) +{ + for (std::map::iterator it=g_TaskbarInfos.begin();it!=g_TaskbarInfos.end();++it) + if (it->second.taskBar==bar) + return &it->second; + return NULL; +} + +static LRESULT CALLBACK HookProgManThread( int code, WPARAM wParam, LPARAM lParam ); +static LRESULT CALLBACK HookDesktopThread( int code, WPARAM wParam, LPARAM lParam ); + +static BOOL CALLBACK FindTooltipEnum( HWND hwnd, LPARAM lParam ) +{ + // look for tooltip control in the current thread that has a tool for g_TaskBar+g_StartButton + wchar_t name[256]; + GetClassName(hwnd,name,_countof(name)); + if (_wcsicmp(name,TOOLTIPS_CLASS)!=0) return TRUE; + TOOLINFO info={sizeof(info),0,g_TaskBar,(UINT_PTR)g_WinStartButton}; + if (SendMessage(hwnd,TTM_GETTOOLINFO,0,(LPARAM)&info)) + { + g_Tooltip=hwnd; + return FALSE; + } + return TRUE; +} + +static BOOL CALLBACK FindStartButtonEnum( HWND hwnd, LPARAM lParam ) +{ + // look for top-level window in the current thread with class "button" + wchar_t name[256]; + GetClassName(hwnd,name,_countof(name)); + if (_wcsicmp(name,L"button")!=0) return TRUE; + g_WinStartButton=hwnd; + return FALSE; +} + +static BOOL CALLBACK FindTaskBarEnum( HWND hwnd, LPARAM lParam ) +{ + // look for top-level window with class "Shell_TrayWnd" and process ID=lParam + DWORD process; + GetWindowThreadProcessId(hwnd,&process); + if (process!=lParam) return TRUE; + wchar_t name[256]; + GetClassName(hwnd,name,_countof(name)); + if (_wcsicmp(name,L"Shell_TrayWnd")!=0) return TRUE; + g_TaskBar=hwnd; + return FALSE; +} + +// Find the taskbar window for the given process +STARTMENUAPI HWND FindTaskBar( DWORD process ) +{ + g_WinStartButton=NULL; + g_TaskBar=NULL; + g_Tooltip=NULL; + // find the taskbar + EnumWindows(FindTaskBarEnum,process); + if (!g_TaskBar) + g_TaskBar=FindWindowEx(GetDesktopWindow(),NULL,L"Shell_TrayWnd",NULL); + if (g_TaskBar) + { + // find start button + if (GetWinVersion()==WIN_VER_WIN7) + EnumThreadWindows(GetWindowThreadProcessId(g_TaskBar,NULL),FindStartButtonEnum,NULL); + if (GetWindowThreadProcessId(g_TaskBar,NULL)==GetCurrentThreadId()) + { + // find tooltip + if (g_WinStartButton) + { + EnumThreadWindows(GetWindowThreadProcessId(g_TaskBar,NULL),FindTooltipEnum,NULL); + if (g_Tooltip) + { + g_StartButtonTool.cbSize=sizeof(g_StartButtonTool); + g_StartButtonTool.hwnd=g_TaskBar; + g_StartButtonTool.uId=(UINT_PTR)g_WinStartButton; + SendMessage(g_Tooltip,TTM_GETTOOLINFO,0,(LPARAM)&g_StartButtonTool); + } + } + g_OwnerWindow=g_Owner.Create(NULL,0,0,WS_POPUP,WS_EX_TOOLWINDOW|WS_EX_TOPMOST); + } + } + return g_TaskBar; +} + +#ifdef HOOK_DROPTARGET +class CStartMenuTarget: public IDropTarget +{ +public: + CStartMenuTarget( int taskbarId ) { m_RefCount=1; m_TaskbarId=taskbarId; } + // IUnknown + virtual STDMETHODIMP QueryInterface( REFIID riid, void **ppvObject ) + { + *ppvObject=NULL; + if (IID_IUnknown==riid || IID_IDropTarget==riid) + { + AddRef(); + *ppvObject=(IDropTarget*)this; + return S_OK; + } + return E_NOINTERFACE; + } + + virtual ULONG STDMETHODCALLTYPE AddRef( void ) + { + return InterlockedIncrement(&m_RefCount); + } + + virtual ULONG STDMETHODCALLTYPE Release( void ) + { + long nTemp=InterlockedDecrement(&m_RefCount); + if (!nTemp) delete this; + return nTemp; + } + + // IDropTarget + virtual HRESULT STDMETHODCALLTYPE DragEnter( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ) + { + FORMATETC format1={RegisterClipboardFormat(CFSTR_SHELLIDLIST),NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}; + FORMATETC format2={RegisterClipboardFormat(CFSTR_INETURL),NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}; + if (pDataObj->QueryGetData(&format1)==S_OK || pDataObj->QueryGetData(&format2)==S_OK) + { + PostMessage(g_TaskBar,g_StartMenuMsg,(grfKeyState&MK_SHIFT)?MSG_SHIFTDRAG:MSG_DRAG,m_TaskbarId); + } + *pdwEffect=DROPEFFECT_NONE; + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE DragOver( DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ) { return *pdwEffect=DROPEFFECT_NONE; return S_OK; } + virtual HRESULT STDMETHODCALLTYPE DragLeave( void ) { return S_OK; } + virtual HRESULT STDMETHODCALLTYPE Drop( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ) { return *pdwEffect=DROPEFFECT_NONE; return S_OK; } + +private: + LONG m_RefCount; + int m_TaskbarId; +}; + +#endif + +static CComPtr g_pOriginalTarget; + +static void FindTaskBar( void ) +{ + if (!g_TaskBar) + { + g_StartMenuMsg=RegisterWindowMessage(L"ClassicStartMenu.StartMenuMsg"); + FindTaskBar(GetCurrentProcessId()); + if (g_TaskBar) + { + g_HotkeyShiftID=GlobalAddAtom(L"ClassicStartMenu.HotkeyShift"); + g_HotkeyCSMID=GlobalAddAtom(L"ClassicStartMenu.HotkeyCSM"); + g_HotkeyWSMID=GlobalAddAtom(L"ClassicStartMenu.HotkeyWSM"); + EnableHotkeys(HOTKEYS_NORMAL); + srand(GetTickCount()); + } + if (!g_TaskBar) g_TaskBar=(HWND)1; + } +} + +void EnableStartTooltip( bool bEnable ) +{ + if (g_Tooltip) + { + SendMessage(g_Tooltip,TTM_POP,0,0); + if (bEnable) + SendMessage(g_Tooltip,TTM_UPDATETIPTEXT,0,(LPARAM)&g_StartButtonTool); + else + { + TOOLINFO info=g_StartButtonTool; + info.lpszText=L""; + SendMessage(g_Tooltip,TTM_UPDATETIPTEXT,0,(LPARAM)&info); + } + } +} + +// Restore the original drop target +static void UnhookDropTarget( void ) +{ + if (g_pOriginalTarget) + { + RevokeDragDrop(g_WinStartButton); + if (g_pOriginalTarget) + RegisterDragDrop(g_WinStartButton,g_pOriginalTarget); + g_pOriginalTarget=NULL; + } +} + +// Toggle the start menu. bKeyboard - set to true to show the keyboard cues +STARTMENUAPI HWND ToggleStartMenu( int taskbarId, bool bKeyboard ) +{ + if (taskbarId==-1) + { + if (g_TaskbarInfos.find(-1)==g_TaskbarInfos.end()) + { + g_TaskbarInfos[-1].taskBar=g_TaskBar; + } + } + g_LastTaskbar=taskbarId; + return CMenuContainer::ToggleStartMenu(taskbarId,bKeyboard,false); +} + +UINT GetTaskbarPosition( HWND taskBar, MONITORINFO *pInfo, HMONITOR *pMonitor, RECT *pRc ) +{ + if (!IsWindow(taskBar)) + return 0xFFFFFFFF; + if (taskBar==g_TaskBar) + { + APPBARDATA appbar={sizeof(appbar),taskBar}; + SHAppBarMessage(ABM_GETTASKBARPOS,&appbar); + if (pRc) + { + *pRc=appbar.rc; + RECT rc; + GetWindowRect(taskBar,&rc); + if (appbar.uEdge==ABE_LEFT || appbar.uEdge==ABE_RIGHT) + { + if (pRc->toptop=rc.top; + if (pRc->bottom>rc.bottom) pRc->bottom=rc.bottom; + } + else if (appbar.uEdge==ABE_TOP || appbar.uEdge==ABE_BOTTOM) + { + if (pRc->leftleft=rc.left; + if (pRc->right>rc.right) pRc->right=rc.right; + } + } + if (pInfo) + { + pInfo->cbSize=sizeof(MONITORINFO); + HMONITOR monitor=MonitorFromRect(&appbar.rc,MONITOR_DEFAULTTONEAREST); + GetMonitorInfo(monitor,pInfo); + if (pMonitor) *pMonitor=monitor; + } + return appbar.uEdge; + } + RECT rc; + if (GetWindowRgnBox(taskBar,&rc)!=ERROR) + MapWindowPoints(taskBar,NULL,(POINT*)&rc,2); + else + GetWindowRect(taskBar,&rc); + MONITORINFO info={sizeof(info)}; + HMONITOR monitor=MonitorFromRect(&rc,MONITOR_DEFAULTTONEAREST); + GetMonitorInfo(monitor,&info); + if (pMonitor) *pMonitor=monitor; + int dx=rc.left+rc.right-info.rcWork.left-info.rcWork.right; + int dy=rc.top+rc.bottom-info.rcWork.top-info.rcWork.bottom; + if (pInfo) *pInfo=info; + bool bAutoHide=false; + if (pRc) + { + GetWindowRect(taskBar,pRc); + APPBARDATA appbar={sizeof(appbar)}; + bAutoHide=(SHAppBarMessage(ABM_GETSTATE,&appbar)&ABS_AUTOHIDE)!=0; + } + if (dx<-abs(dy)) + { + if (bAutoHide && pRc->leftleft,0); + return ABE_LEFT; + } + if (dx>abs(dy)) + { + if (bAutoHide && pRc->right>info.rcWork.right) + OffsetRect(pRc,info.rcWork.right-pRc->right,0); + return ABE_RIGHT; + } + if (dy<-abs(dx)) + { + if (bAutoHide && pRc->toptop); + return ABE_TOP; + } + if (bAutoHide && pRc->bottom>info.rcWork.bottom) + OffsetRect(pRc,0,info.rcWork.bottom-pRc->bottom); + return ABE_BOTTOM; +} + +// Returns true if the mouse is on the taskbar portion of the start button +bool PointAroundStartButton( int taskbarId, const CPoint &pt ) +{ + const TaskbarInfo *taskBar=GetTaskbarInfo(taskbarId); + if (!taskBar || !taskBar->startButton) return false; + RECT rc; + GetWindowRect(taskBar->taskBar,&rc); + if (!PtInRect(&rc,pt)) + return false; + + UINT uEdge=GetTaskbarPosition(taskBar->taskBar,NULL,NULL,NULL); + // check if the point is inside the start button rect + GetWindowRect(taskBar->startButton,&rc); + if (uEdge==ABE_LEFT || uEdge==ABE_RIGHT) + return pt.ytaskBar,GWL_EXSTYLE)&WS_EX_LAYOUTRTL) + return pt.x>rc.left; + else + return pt.x::const_iterator it=g_EdgeWindows.begin();it!=g_EdgeWindows.end();++it) + ShowWindow(*it,SW_SHOW); + g_EdgeWindows.clear(); +} + +void RedrawTaskbars( void ) +{ + for (std::map::const_iterator it=g_TaskbarInfos.begin();it!=g_TaskbarInfos.end();++it) + InvalidateRect(it->second.taskBar,NULL,TRUE); +} + +static CComPtr g_pAppVisibility; +static DWORD g_AppVisibilityMonitorCookie; + +class CMonitorModeEvents: public IAppVisibilityEvents +{ +public: + CMonitorModeEvents( void ) { m_RefCount=1; } + // IUnknown + virtual STDMETHODIMP QueryInterface( REFIID riid, void **ppvObject ) + { + *ppvObject=NULL; + if (IID_IUnknown==riid || __uuidof(IAppVisibilityEvents)==riid) + { + AddRef(); + *ppvObject=(IDropTarget*)this; + return S_OK; + } + return E_NOINTERFACE; + } + + virtual ULONG STDMETHODCALLTYPE AddRef( void ) + { + return InterlockedIncrement(&m_RefCount); + } + + virtual ULONG STDMETHODCALLTYPE Release( void ) + { + long nTemp=InterlockedDecrement(&m_RefCount); + if (!nTemp) delete this; + return nTemp; + } + + // IAppVisibilityEvents + virtual HRESULT STDMETHODCALLTYPE AppVisibilityOnMonitorChanged( HMONITOR hMonitor, MONITOR_APP_VISIBILITY previousMode, MONITOR_APP_VISIBILITY currentMode ) + { + if (GetWinVersion() pImmersiveShell; + if (GetWinVersion()>=WIN_VER_WIN10 && CreateImmersiveShell(pImmersiveShell)) + { + int taskbarId=-1; + if (currentVisibleState) + { + taskbarId=MAIN_TASK_BAR; + CComPtr pMonitor; + { + CComPtr pLauncher; + IUnknown_QueryService(pImmersiveShell,SID_ImmersiveLauncher,IID_IImmersiveLauncher81,(void**)&pLauncher); + if (pLauncher) + pLauncher->GetMonitor(&pMonitor); + } + if (!pMonitor) + { + CComPtr pLauncher; + IUnknown_QueryService(pImmersiveShell,SID_ImmersiveLauncher,IID_IImmersiveLauncher10RS,(void**)&pLauncher); + if (pLauncher) + pLauncher->GetMonitor(&pMonitor); + } + if (pMonitor) + { + HMONITOR monitor; + if (SUCCEEDED(pMonitor->GetHandle(&monitor))) + { + for (std::map::const_iterator it=g_TaskbarInfos.begin();it!=g_TaskbarInfos.end();++it) + { + if (monitor==MonitorFromWindow(it->second.taskBar,MONITOR_DEFAULTTONULL)) + { + taskbarId=it->second.taskbarId; + break; + } + } + } + } + } + if (g_CurrentWSMTaskbar!=taskbarId) + { + if (g_CurrentWSMTaskbar!=-1 && g_CurrentWSMTaskbar!=g_CurrentCSMTaskbar) + PressStartButton(g_CurrentWSMTaskbar,false); + g_CurrentWSMTaskbar=taskbarId; + if (g_CurrentWSMTaskbar!=-1) + PressStartButton(g_CurrentWSMTaskbar,true); + } + } + else + { + ResetHotCorners(); + if (IsWin81Update1() && GetSettingBool(L"CustomTaskbar")) + PostMessage(g_TaskBar,g_StartMenuMsg,MSG_REDRAWTASKBAR,0); + } + return S_OK; + } + +private: + LONG m_RefCount; +}; + +static const CLSID CLSID_MetroMode={0x7E5FE3D9,0x985F,0x4908,{0x91, 0xF9, 0xEE, 0x19, 0xF9, 0xFD, 0x15, 0x14}}; + +BOOL CALLBACK AppVisibleProc( HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData ) +{ + bool *pData=(bool*)dwData; + MONITOR_APP_VISIBILITY mode; + if (SUCCEEDED(g_pAppVisibility->GetAppVisibilityOnMonitor(hMonitor,&mode)) && mode==MAV_APP_VISIBLE) + *pData=true; + return !*pData; +} + +enum TMetroMode +{ + METRO_NONE, + METRO_LAUNCHER, + METRO_APP, +}; + +static TMetroMode GetMetroMode( HMONITOR hMonitor ) +{ + if (!g_pAppVisibility) return METRO_NONE; + + BOOL bLauncher; + if (SUCCEEDED(g_pAppVisibility->IsLauncherVisible(&bLauncher)) && bLauncher) + { + if (!hMonitor) return METRO_LAUNCHER; + HWND launcher=FindWindow(L"ImmersiveLauncher",NULL); + if (launcher && hMonitor==MonitorFromWindow(launcher,MONITOR_DEFAULTTONULL)) + return METRO_LAUNCHER; + } + + if (hMonitor) + { + MONITOR_APP_VISIBILITY mode; + if (SUCCEEDED(g_pAppVisibility->GetAppVisibilityOnMonitor(hMonitor,&mode)) && mode==MAV_APP_VISIBLE) + return METRO_APP; + } + else + { + bool bAppVisible=false; + EnumDisplayMonitors(NULL,NULL,AppVisibleProc,(LPARAM)&bAppVisible); + if (bAppVisible) return METRO_APP; + } + return METRO_NONE; +} + +static bool GetWin10TabletMode( void ) +{ + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\ImmersiveShell",KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + DWORD val; + return regKey.QueryDWORDValue(L"TabletMode",val)==ERROR_SUCCESS && val; + } + return false; +} + +static LRESULT CALLBACK HookAppManager( int code, WPARAM wParam, LPARAM lParam ) +{ + if (code==HC_ACTION && wParam) + { + MSG *msg=(MSG*)lParam; + if (msg->message==g_StartMenuMsg && (msg->wParam==MSG_WINXMENU || msg->wParam==MSG_METROTHUMBNAIL || msg->wParam==MSG_SHIFTWIN)) + { + HWND hwnd=FindWindow(L"ModeInputWnd",NULL); + if (hwnd) + { + DWORD process; + GetWindowThreadProcessId(hwnd,&process); + if (process==GetCurrentProcessId()) + { + IObjectWithSite *pObject=(IObjectWithSite*)GetWindowLongPtr(hwnd,0); + if (pObject) + { + CComPtr pSite; + pObject->GetSite(IID_IUnknown,(void**)&pSite); + if (pSite) + { + if (msg->wParam==MSG_WINXMENU) + { + CPoint pt(msg->lParam); + CComPtr pSwitchModeManager; + IUnknown_QueryService(pSite,SID_SwitchModeManager,IID_ISwitchModeManager,(void**)&pSwitchModeManager); + if (pSwitchModeManager) + { + pSwitchModeManager->ShowLauncherTipContextMenu(&pt); + // set the current immersive monitor AFTER the menu returns (this way Search is shown in the correct monitor) + CComPtr pMonitorService; + IUnknown_QueryService(pSite,SID_IImmersiveMonitorService,IID_IImmersiveMonitorService,(void**)&pMonitorService); + if (pMonitorService) + { + HMONITOR monitor=MonitorFromPoint(pt,MONITOR_DEFAULTTONEAREST); + if (GetWinVersion()==WIN_VER_WIN8) + { + CComPtr pMonitor; + pMonitorService->GetFromHandle(monitor,&pMonitor); + if (pMonitor) + pMonitorService->SetImmersiveMonitor(pMonitor); + } + else if (GetWinVersion()>WIN_VER_WIN8) + { + // doesn't seem to be doing anything on 8.1, but do it just in case + CComPtr pMonitor; + pMonitorService->GetFromHandle(monitor,&pMonitor); + if (pMonitor) + { + CComPtr pLauncher; + IUnknown_QueryService(pSite,SID_ImmersiveLauncher,IID_IImmersiveLauncher81,(void**)&pLauncher); + if (pLauncher) + pLauncher->ConnectToMonitor(pMonitor); + } + } + } + } + } + if (msg->wParam==MSG_METROTHUMBNAIL) + { + StartScreenThumbInfo &info=*(StartScreenThumbInfo*)msg->lParam; + CComPtr pLauncher; + IUnknown_QueryService(pSite,SID_ImmersiveLauncher,IID_IImmersiveLauncherProvider,(void**)&pLauncher); + if (pLauncher) + { + CComPtr pProvider; + IUnknown_QueryService(pLauncher,SID_ImmersiveLauncherThumbnailProvider,IID_IImmersiveLauncherThumbnailProvider,(void**)&pProvider); + if (pProvider) + { + CComPtr pBitmap; + if (SUCCEEDED(pProvider->GetBitmap(info.size,100,1,&pBitmap)) && pBitmap) + { + pBitmap->Detach(&info.bitmap); + } + } + } + } + if (msg->wParam==MSG_SHIFTWIN) + { + if (GetWinVersion()==WIN_VER_WIN8) + { + HMONITOR monitor=(HMONITOR)msg->lParam; + if (monitor) + { + CComPtr pMonitorService; + IUnknown_QueryService(pSite,SID_IImmersiveMonitorService,IID_IImmersiveMonitorService,(void**)&pMonitorService); + if (pMonitorService) + { + CComPtr pMonitor; + pMonitorService->GetFromHandle(monitor,&pMonitor); + if (pMonitor) + pMonitorService->SetImmersiveMonitor(pMonitor); + } + } + CComPtr pLauncher; + IUnknown_QueryService(pSite,SID_ImmersiveLauncher,IID_IImmersiveLauncher80,(void**)&pLauncher); + if (pLauncher) + pLauncher->ShowStartView(5); + } + } + } + } + } + } + if (msg->wParam==MSG_METROTHUMBNAIL) + { + // set the event no matter if successful + StartScreenThumbInfo &info=*(StartScreenThumbInfo*)msg->lParam; + SetEvent(info.event); + } + } + int corner; + if ((msg->message==WM_MOUSEMOVE || msg->message==WM_LBUTTONDOWN) && (corner=GetSettingInt(L"DisableHotCorner"))>0) + { + { + // ignore the mouse messages if there is a menu + GUITHREADINFO info={sizeof(info)}; + if (GetGUIThreadInfo(GetCurrentThreadId(),&info) && (info.flags&GUI_INMENUMODE)) + return CallNextHookEx(NULL,code,wParam,lParam); + } + CPoint pt(GetMessagePos()); + HMONITOR monitor=MonitorFromPoint(pt,MONITOR_DEFAULTTONEAREST); + if (GetMetroMode(monitor)!=METRO_NONE) + { + if (!IsWin81Update1()) + return CallNextHookEx(NULL,code,wParam,lParam); + typedef BOOL (WINAPI *tGetWindowBand)(HWND,DWORD*); + static tGetWindowBand GetWindowBand=(tGetWindowBand)GetProcAddress(GetModuleHandle(L"user32.dll"),"GetWindowBand"); + for (std::map::const_iterator it=g_TaskbarInfos.begin();it!=g_TaskbarInfos.end();++it) + { + DWORD band; + if (!GetWindowBand || !GetWindowBand(it->second.taskBar,&band) || band==1) + continue; + UINT uEdge=GetTaskbarPosition(it->second.taskBar,NULL,NULL,NULL); + if (uEdge!=ABE_BOTTOM) + continue; + + // check if the mouse is over the taskbar + RECT taskRect; + GetWindowRect(it->second.taskBar,&taskRect); + if (PtInRect(&taskRect,pt)) + { + POINT pt2=pt; + ScreenToClient(it->second.taskBar,&pt2); + if (pt2.x<32) + { + if (msg->message==WM_LBUTTONDOWN) + { + // forward the mouse click to the taskbar + PostMessage(it->second.taskBar,WM_NCLBUTTONDOWN,MK_LBUTTON,MAKELONG(pt.x,pt.y)); + msg->message=WM_NULL; + } + wchar_t className[256]={0}; + GetClassName(msg->hwnd,className,_countof(className)); + if (wcscmp(className,L"ImmersiveSwitchList")==0) + { + // suppress the opening of the ImmersiveSwitchList + msg->message=WM_NULL; + ShowWindow(msg->hwnd,SW_HIDE); // hide the popup + } + if (wcscmp(className,L"EdgeUiInputWndClass")==0) + { + // suppress the hot corners + msg->message=WM_NULL; + } + } + break; + } + } + return CallNextHookEx(NULL,code,wParam,lParam); + } + if (corner==1) + { + for (std::map::const_iterator it=g_TaskbarInfos.begin();it!=g_TaskbarInfos.end();++it) + { + UINT uEdge=GetTaskbarPosition(it->second.taskBar,NULL,NULL,NULL); + if (uEdge==ABE_BOTTOM) + { + // check if the mouse is over the taskbar + RECT taskRect; + GetWindowRect(it->second.taskBar,&taskRect); + if (PtInRect(&taskRect,pt)) + { + POINT pt2=pt; + ScreenToClient(it->second.taskBar,&pt2); + if (pt2.x<32) + { + corner=2; + if (msg->message==WM_LBUTTONDOWN) + { + // forward the mouse click to the taskbar + PostMessage(it->second.taskBar,WM_NCLBUTTONDOWN,MK_LBUTTON,MAKELONG(pt.x,pt.y)); + msg->message=WM_NULL; + } + wchar_t className[256]={0}; + GetClassName(msg->hwnd,className,_countof(className)); + if (wcscmp(className,L"ImmersiveSwitchList")==0) + { + // suppress the opening of the ImmersiveSwitchList + msg->message=WM_NULL; + ShowWindow(msg->hwnd,SW_HIDE); // hide the popup + } + } + break; + } + } + } + } + if (corner==2) + { + wchar_t className[256]={0}; + GetClassName(msg->hwnd,className,_countof(className)); + if (wcscmp(className,L"EdgeUiInputWndClass")==0) + { + // suppress the hot corners + msg->message=WM_NULL; + ShowWindow(msg->hwnd,SW_HIDE); + g_EdgeWindows.insert(msg->hwnd); + } + } + } + } + return CallNextHookEx(NULL,code,wParam,lParam); +} + +static LRESULT CALLBACK HookNewWindow( int code, WPARAM wParam, LPARAM lParam ) +{ + if (code==HCBT_CREATEWND) + { + CBT_CREATEWND *pCreate=(CBT_CREATEWND*)lParam; + if (pCreate->lpcs->lpszClass>(LPTSTR)0xFFFF && (_wcsicmp(pCreate->lpcs->lpszClass,L"Shell_SecondaryTrayWnd")==0 || + _wcsicmp(pCreate->lpcs->lpszClass,L"ToolbarWindow32")==0 || _wcsicmp(pCreate->lpcs->lpszClass,L"TrayClockWClass")==0 || _wcsicmp(pCreate->lpcs->lpszClass,L"ClockButton")==0)) + PostMessage(g_TaskBar,g_StartMenuMsg,MSG_NEWTASKBAR,wParam); + } + return CallNextHookEx(NULL,code,wParam,lParam); +} + +// Set the hotkeys and controls for the start menu +void EnableHotkeys( THotkeys enable ) +{ + if (g_bTrimHooks) return; + if (!g_TaskBar) + return; + if (GetWindowThreadProcessId(g_TaskBar,NULL)!=GetCurrentThreadId()) + { + PostMessage(g_TaskBar,g_StartMenuMsg,MSG_HOTKEYS,enable); + return; + } + + // must be executed in the same thread as the start button (otherwise RegisterHotKey doesn't work). also prevents race conditions + bool bHook=(enable==HOTKEYS_SETTINGS || (enable==HOTKEYS_NORMAL && GetSettingInt(L"ShiftWin")!=0)); + if (bHook) + { + RegisterHotKey(g_TaskBar,g_HotkeyShiftID,MOD_SHIFT|MOD_WIN,0); + g_bHotkeyShift=true; + } + else if (g_bHotkeyShift) + { + UnregisterHotKey(g_TaskBar,g_HotkeyShiftID); + g_bHotkeyShift=false; + } + + if (g_HotkeyCSM) + UnregisterHotKey(g_TaskBar,g_HotkeyCSMID); + g_HotkeyCSM=0; + + if (g_HotkeyWSM) + UnregisterHotKey(g_TaskBar,g_HotkeyWSMID); + g_HotkeyWSM=0; + + if (enable==HOTKEYS_NORMAL) + { + g_HotkeyCSM=GetSettingInt(L"CSMHotkey"); + if (g_HotkeyCSM) + { + int mod=MOD_NOREPEAT; + if (g_HotkeyCSM&(HOTKEYF_SHIFT<<8)) mod|=MOD_SHIFT; + if (g_HotkeyCSM&(HOTKEYF_CONTROL<<8)) mod|=MOD_CONTROL; + if (g_HotkeyCSM&(HOTKEYF_ALT<<8)) mod|=MOD_ALT; + RegisterHotKey(g_TaskBar,g_HotkeyCSMID,mod,g_HotkeyCSM&255); + } + + g_HotkeyWSM=GetSettingInt(L"WSMHotkey"); + if (g_HotkeyWSM) + { + int mod=MOD_NOREPEAT; + if (g_HotkeyWSM&(HOTKEYF_SHIFT<<8)) mod|=MOD_SHIFT; + if (g_HotkeyWSM&(HOTKEYF_CONTROL<<8)) mod|=MOD_CONTROL; + if (g_HotkeyWSM&(HOTKEYF_ALT<<8)) mod|=MOD_ALT; + RegisterHotKey(g_TaskBar,g_HotkeyWSMID,mod,g_HotkeyWSM&255); + } + } +} + +static LRESULT CALLBACK SubclassWin81StartButton( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_WINDOWPOSCHANGING) + { + // keep the original start button hidden at all times + const TaskbarInfo *taskBar=GetTaskbarInfo((int)dwRefData); + if (taskBar && taskBar->bHideButton) + { + ((WINDOWPOS*)lParam)->flags&=~SWP_SHOWWINDOW; + } + } + if (uMsg==WM_SIZE) + { + RECT rc; + GetWindowRect(hWnd,&rc); + rc.right-=rc.left; + rc.bottom-=rc.top; + TaskbarInfo *taskBar=GetTaskbarInfo((int)dwRefData); + if (taskBar && (taskBar->oldButtonSize.cx!=rc.right || taskBar->oldButtonSize.cy!=rc.bottom)) + { + taskBar->oldButtonSize.cx=rc.right; + taskBar->oldButtonSize.cy=rc.bottom; + RECT rcTask; + GetWindowRect(taskBar->taskBar,&rcTask); + PostMessage(taskBar->taskBar,WM_SIZE,SIZE_RESTORED,MAKELONG(rcTask.right-rcTask.left,rcTask.bottom-rcTask.top)); + } + } + if (uMsg==WM_POINTERACTIVATE && CMenuContainer::IsMenuOpened()) + return MA_NOACTIVATE; +#ifdef START_TOUCH + if (uMsg==WM_POINTERUP || uMsg==WM_POINTERUPDATE || uMsg==WM_POINTERUP) + { + POINTER_INPUT_TYPE type; + GetPointerType2(GET_POINTERID_WPARAM(wParam),&type); + if (type==PT_TOUCH) + { + return SendMessage(GetParent(hWnd),uMsg,wParam,lParam); + } + } +#endif + if (uMsg==WM_PAINT && GetWinVersion()>=WIN_VER_WIN10) + { + g_CurrentTaskbarButton=hWnd; + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + g_CurrentTaskbarButton=NULL; + return res; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +static bool g_bSuppressMessage243; + +static LRESULT CALLBACK SubclassWin7StartButton( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==243 && g_bSuppressMessage243) + { + // HACK: if the start button is smaller than the original, some NC clicks on the taskbar may be interpreted as clicks on the start button and open the WSM + // This is prevented by suppressing message 243 while processing WM_NCLBUTTONDOWN on the taskbar + return 0; + } + if (uMsg==WM_WINDOWPOSCHANGING) + { + // keep the Win7 start button hidden at all times + ((WINDOWPOS*)lParam)->flags&=~SWP_SHOWWINDOW; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +static LRESULT CALLBACK SubclassUserPicProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_WINDOWPOSCHANGING && !(((WINDOWPOS*)lParam)->flags&SWP_NOMOVE)) + { + if (GetSettingBool(L"HideUserPic")) + { + ((WINDOWPOS*)lParam)->x=-32000; + ((WINDOWPOS*)lParam)->y=-32000; + } + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +static LRESULT CALLBACK SubclassTopMenuProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_ACTIVATE && GetSettingBool(L"CascadeAll")) + { + if (!wParam) + { + if (CMenuContainer::s_bPreventClosing) return 0; + // check if another menu window is being activated + // if not, close all menus + for (std::vector::const_iterator it=CMenuContainer::s_Menus.begin();it!=CMenuContainer::s_Menus.end();++it) + if ((*it)->m_hWnd==(HWND)lParam) + return 0; + } + } + if (uMsg==WM_WINDOWPOSCHANGED && (((WINDOWPOS*)lParam)->flags&SWP_SHOWWINDOW)) + { + g_LastHoverPos=GetMessagePos(); + if (g_ProgramsButton && GetSettingInt(L"InitiallySelect")==1) + PostMessage(hWnd,WM_CLEAR,'CLSH',0); + g_CurrentWSMTaskbar=MAIN_TASK_BAR; + PressStartButton(MAIN_TASK_BAR,true); + } + if (uMsg==WM_CLEAR && wParam=='CLSH' && g_ProgramsButton) + { + SetFocus(g_ProgramsButton); + return 0; + } + if (uMsg==WM_SHOWWINDOW) + { + if (!wParam) + { + CMenuContainer::CloseProgramsMenu(); + g_CurrentWSMTaskbar=-1; + PressStartButton(MAIN_TASK_BAR,false); + } + g_bAllProgramsTimer=false; + if (g_ProgramsButton) KillTimer(g_ProgramsButton,'CLSM'); + } + if (uMsg==WM_DESTROY) + g_TopWin7Menu=NULL; + if (uMsg==WM_ACTIVATEAPP && !wParam) + { + if (CMenuContainer::s_bPreventClosing) return 0; + } + if (uMsg==WM_MOUSEACTIVATE && GetSettingBool(L"CascadeAll") && CMenuContainer::IsMenuOpened()) + { + CPoint pt(GetMessagePos()); + if (g_ProgramsButton && WindowFromPoint(pt)==g_ProgramsButton) + return MA_NOACTIVATEANDEAT; + CMenuContainer::CloseProgramsMenu(); + return MA_ACTIVATEANDEAT; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +static LRESULT CALLBACK SubclassProgramsProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_COMMAND && wParam==IDOK && GetSettingBool(L"CascadeAll")) + { + if (GetKeyState(VK_SHIFT)<0) + { + if (CMenuContainer::IsMenuOpened()) + return 0; // ignore shift+click when the menu is opened + } + else + { + if (!CMenuContainer::IsMenuOpened()) + CMenuContainer::ToggleStartMenu(MAIN_TASK_BAR,GetKeyState(VK_SPACE)<0 || GetKeyState(VK_RETURN)<0 || GetKeyState(VK_LEFT)<0 || GetKeyState(VK_RIGHT)<0,true); + return 0; + } + } + if (uMsg==WM_DRAWITEM && wParam==IDOK && CMenuContainer::IsMenuOpened()) + { + DRAWITEMSTRUCT *pDraw=(DRAWITEMSTRUCT*)lParam; + pDraw->itemState=ODS_HOTLIGHT; // draw highlighted when the menu is open + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +static BOOL CALLBACK FindWindowsMenuProc( HWND hwnd, LPARAM lParam ) +{ + wchar_t name[100]; + GetClassName(hwnd,name,_countof(name)); + if (_wcsicmp(name,L"DV2ControlHost")==0) + { + HWND w1=hwnd; + if (GetWinVersion()==WIN_VER_VISTA) + { + w1=FindWindowEx(w1,NULL,L"Desktop Open Pane Host",NULL); + if (!w1) return TRUE; + } + w1=FindWindowEx(w1,NULL,L"Desktop More Programs Pane",NULL); + if (!w1) return TRUE; + + g_TopWin7Menu=hwnd; + g_AllPrograms=w1; + g_ProgramsButton=GetDlgItem(w1,IDOK); // this may not exist + return FALSE; + } + return TRUE; +} + +static void FindWindowsMenu( void ) +{ + if (g_TopWin7Menu) return; + if (GetWinVersion()=rcPaint.bottom) break; + for (int x=0;x=rcPaint.right) break; + MarginsBlit(hsrc,hdc,rSrc,rDst,g_TaskbarMargins,true); + } + } + + SelectObject(hsrc,bmp0); + DeleteDC(hsrc); +} + +static void ComputeTaskbarColors( int *data ) +{ + bool bDefLook; + int look=GetSettingInt(L"TaskbarLook",bDefLook); + if (GetWinVersion()255) a=255; + bool bDefColor; + DWORD color=GetSettingInt(L"TaskbarColor",bDefColor); + if (bDefColor) + color=color0; + data[2]=(color&0xFFFFFF)|(a<<24); + } + data[3]=0; +} + +static void ShowWinX( void ) +{ + if (GetWinVersion()>=WIN_VER_WIN10) + { + CComPtr pImmersiveShell; + if (CreateImmersiveShell(pImmersiveShell)) + { + CComPtr pMonitorService; + IUnknown_QueryService(pImmersiveShell,SID_IImmersiveMonitorService,IID_IImmersiveMonitorService,(void**)&pMonitorService); + if (pMonitorService) + { + CPoint pt(GetMessagePos()); + HMONITOR monitor=MonitorFromPoint(pt,MONITOR_DEFAULTTONEAREST); + CComPtr pMonitor; + pMonitorService->GetFromHandle(monitor,&pMonitor); + if (pMonitorService) + { + CComPtr pMenu; + IUnknown_QueryService(pMonitor,SID_LauncherTipContextMenu,SID_LauncherTipContextMenu,(void**)&pMenu); + if (pMenu) + pMenu->ShowLauncherTipContextMenu(&pt); + } + } + } + } + else if (g_AppManagerThread) + PostThreadMessage(g_AppManagerThread,g_StartMenuMsg,MSG_WINXMENU,GetMessagePos()); +} + +static LRESULT CALLBACK SubclassTrayButtonProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_WINDOWPOSCHANGING) + { + const TaskbarInfo *taskBar=GetTaskbarInfo((int)dwRefData); + if (taskBar && (taskBar->bReplaceButton || taskBar->bHideButton)) + { + WINDOWPOS *pPos=(WINDOWPOS*)lParam; + if (!(pPos->flags&SWP_NOMOVE) || !(pPos->flags&SWP_NOSIZE)) + { + if (pPos->flags&(SWP_NOMOVE|SWP_NOSIZE)) + { + RECT rc; + GetWindowRect(hWnd,&rc); + MapWindowPoints(NULL,GetParent(hWnd),(POINT*)&rc,2); + if (pPos->flags&SWP_NOMOVE) + { + pPos->x=rc.left; + pPos->y=rc.top; + } + else + { + pPos->cx=rc.right-rc.left; + pPos->cy=rc.bottom-rc.top; + } + } + int dx=0, dy=0; + UINT uEdge=GetTaskbarPosition(taskBar->taskBar,NULL,NULL,NULL); + if (uEdge==ABE_LEFT || uEdge==ABE_RIGHT) + { + dy=taskBar->startButtonSize.cy-taskBar->oldButtonSize.cy; + } + else + { + dx=taskBar->startButtonSize.cx-taskBar->oldButtonSize.cx; + } + if (dx || dy) + { + pPos->x+=dx; + pPos->y+=dy; + pPos->flags&=~(SWP_NOMOVE); + } + } + } + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +static LRESULT CALLBACK SubclassTaskBarProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_MOUSEACTIVATE && (HIWORD(lParam)==WM_MBUTTONDOWN || GetWinVersion()>=WIN_VER_WIN10)) + { + if (GetWinVersion()>=WIN_VER_WIN10 && CMenuContainer::IsMenuOpened() && CMenuContainer::HasInputHandler() && GetFocus()) + { + // Win10: if the taskbar is clicked while the menu is opened, check if the touch keyboard button was clicked and ignore the activation + // Otherwise the click on the touch keyboard button will deactivate the menu (possibly because both run on the same thread) + // On Win8.1 the button already handles this and returns MA_NOACTIVATE + HWND hwnd=WindowFromPoint(CPoint(GetMessagePos())); + if (hwnd) + { + wchar_t className[256]; + GetClassName(hwnd,className,_countof(className)); + if (_wcsicmp(className,L"TIPBand")==0) + return MA_NOACTIVATE; + } + } + FindWindowsMenu(); + if (g_TopWin7Menu && WindowsMenuOpened()) + { + DefSubclassProc(hWnd,uMsg,wParam,lParam); + return MA_ACTIVATEANDEAT; // ignore the next middle click, so it doesn't re-open the start menu + } + } + TaskbarInfo *taskBar=GetTaskbarInfo((int)dwRefData); + if (taskBar && (uMsg==WM_NCMOUSEMOVE || uMsg==WM_MOUSEMOVE) && PointAroundStartButton((int)dwRefData)) + TaskBarMouseMove(taskBar->taskbarId); + if (taskBar && uMsg==WM_POINTERACTIVATE && CMenuContainer::IsMenuOpened()) + return MA_NOACTIVATE; + static int touchTime; +#ifdef START_TOUCH + if (taskBar && (uMsg==WM_NCPOINTERDOWN || (uMsg==WM_POINTERDOWN && IS_POINTER_INCONTACT_WPARAM(wParam) && IS_POINTER_PRIMARY_WPARAM(wParam) && IS_POINTER_FIRSTBUTTON_WPARAM(wParam)))) + { + POINTER_INPUT_TYPE type; + GetPointerType2(GET_POINTERID_WPARAM(wParam),&type); + if (type==PT_TOUCH) + { + if (PointAroundStartButton((int)dwRefData,CPoint(lParam))) + { + taskBar->pointerId=GET_POINTERID_WPARAM(wParam); + touchTime=GetMessageTime(); + return 0; + } + } + } + if (taskBar && (uMsg==WM_NCPOINTERUPDATE || uMsg==WM_POINTERUPDATE) && taskBar->pointerId==GET_POINTERID_WPARAM(wParam)) + { + if (uMsg==WM_NCPOINTERUPDATE) + { + POINTER_INFO info; + if (GetPointerInfo2(taskBar->pointerId,&info) && (info.pointerFlags&4)!=0) + { + int time=GetMessageTime(); + if (time-touchTime>500) + { + taskBar->pointerId=0; + ShowWinX(); + return 0; + } + } + } + else if (IS_POINTER_INCONTACT_WPARAM(wParam)) + { + int time=GetMessageTime(); + if (time-touchTime>500) + { + taskBar->pointerId=0; + PostMessage(taskBar->startButton,WM_RBUTTONUP,0,MAKELPARAM(-1,-1)); + return 0; + } + } + else + uMsg=WM_POINTERUP; + } + if (taskBar && (uMsg==WM_POINTERUP || uMsg==WM_NCPOINTERUP) && taskBar->pointerId==GET_POINTERID_WPARAM(wParam)) + { + if (PointAroundStartButton((int)dwRefData,CPoint(lParam))) + { + int control=GetSettingInt(L"MouseClick"); + if (control==OPEN_BOTH && GetWinVersion()>=WIN_VER_WIN10) + control=GetWin10TabletMode()?OPEN_WINDOWS:OPEN_CLASSIC; + if (control==OPEN_CLASSIC) + ToggleStartMenu(taskBar->taskbarId,false); + else if (control==OPEN_WINDOWS) + PostMessage(g_ProgWin,WM_SYSCOMMAND,SC_TASKLIST,'WSMM'); + } + taskBar->pointerId=0; + return 0; + } +#endif + if (uMsg==WM_SHOWWINDOW && taskBar) + { + if (taskBar->bReplaceButton) + ShowWindow(taskBar->startButton,wParam?SW_SHOW:SW_HIDE); + } + if (uMsg==WM_WINDOWPOSCHANGING && taskBar && taskBar->bReplaceButton) + { + WINDOWPOS *pPos=(WINDOWPOS*)lParam; + if (!(pPos->flags&SWP_NOZORDER) && pPos->hwndInsertAfter==HWND_BOTTOM) + { + SetWindowPos(taskBar->startButton,HWND_BOTTOM,0,0,0,0,SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOMOVE); + pPos->hwndInsertAfter=taskBar->startButton; + } + } + if (uMsg==WM_WINDOWPOSCHANGED && taskBar) + { + if (taskBar->bReplaceButton) + { + if (IsStartButtonSmallIcons(taskBar->taskbarId)!=IsTaskbarSmallIcons()) + RecreateStartButton((int)dwRefData); + + WINDOWPOS *pPos=(WINDOWPOS*)lParam; + RECT rcTask; + GetWindowRect(hWnd,&rcTask); + MONITORINFO info; + UINT uEdge=GetTaskbarPosition(hWnd,&info,NULL,NULL); + DWORD buttonFlags=SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE; + if (IsWindowVisible(taskBar->taskBar)) + buttonFlags|=SWP_SHOWWINDOW; + else + buttonFlags|=SWP_HIDEWINDOW; + + APPBARDATA appbar={sizeof(appbar)}; + if (SHAppBarMessage(ABM_GETSTATE,&appbar)&ABS_AUTOHIDE) + { + bool bHide=false; + if (uEdge==ABE_LEFT) + bHide=(rcTask.rightinfo.rcMonitor.right-5); + else if (uEdge==ABE_TOP) + bHide=(rcTask.bottominfo.rcMonitor.bottom-5); + if (bHide) + buttonFlags=(buttonFlags&~SWP_SHOWWINDOW)|SWP_HIDEWINDOW; + } + if (uEdge==ABE_TOP || uEdge==ABE_BOTTOM) + { + if (rcTask.leftinfo.rcMonitor.right) rcTask.right=info.rcMonitor.right; + } + else + { + if (rcTask.toptaskbarId)) + { + bool bClassic; + if (GetWinVersion()flags&SWP_NOZORDER) + buttonFlags|=SWP_NOZORDER; + else + { + zPos=pPos->hwndInsertAfter; + if (zPos==HWND_TOP && !(GetWindowLong(taskBar->startButton,GWL_EXSTYLE)&WS_EX_TOPMOST)) + zPos=HWND_TOPMOST; + if (zPos==HWND_TOPMOST && !(GetWindowLong(hWnd,GWL_EXSTYLE)&WS_EX_TOPMOST)) + zPos=HWND_TOP; + if (zPos==HWND_BOTTOM) + buttonFlags|=SWP_NOZORDER; + if (zPos==taskBar->startButton) + buttonFlags|=SWP_NOZORDER; + } + + int x, y; + if (uEdge==ABE_LEFT || uEdge==ABE_RIGHT) + { + if (GetSettingInt(L"StartButtonType")!=START_BUTTON_CUSTOM || !GetSettingBool(L"StartButtonAlign")) + x=(rcTask.left+rcTask.right-taskBar->startButtonSize.cx)/2; + else if (uEdge==ABE_LEFT) + x=rcTask.left; + else + x=rcTask.right-taskBar->startButtonSize.cx; + y=rcTask.top; + } + else + { + if (GetWindowLong(taskBar->rebar,GWL_EXSTYLE)&WS_EX_LAYOUTRTL) + x=rcTask.right-taskBar->startButtonSize.cx; + else + x=rcTask.left; + if (GetSettingInt(L"StartButtonType")!=START_BUTTON_CUSTOM || !GetSettingBool(L"StartButtonAlign")) + y=(rcTask.top+rcTask.bottom-taskBar->startButtonSize.cy)/2; + else if (uEdge==ABE_TOP) + y=rcTask.top; + else + y=rcTask.bottom-taskBar->startButtonSize.cy; + } + RECT rcButton={x,y,x+taskBar->startButtonSize.cx,y+taskBar->startButtonSize.cy}; + RECT rc; + IntersectRect(&rc,&rcButton,&info.rcMonitor); + HRGN rgn=CreateRectRgn(rc.left-x,rc.top-y,rc.right-x,rc.bottom-y); + if (!SetWindowRgn(taskBar->startButton,rgn,FALSE)) + { + AddTrackedObject(rgn); + DeleteObject(rgn); + } + g_bAllowMoveButton=true; + SetWindowPos(taskBar->startButton,zPos,x,y,0,0,buttonFlags); + g_bAllowMoveButton=false; + if (buttonFlags&SWP_SHOWWINDOW) + UpdateStartButton(taskBar->taskbarId); + } + if (taskBar->oldButton && GetWinVersion()oldButton,NULL,x,0,0,0,SWP_NOSIZE|SWP_NOZORDER); + } + } + if (uMsg==WM_THEMECHANGED && taskBar) + { + if (taskBar->bReplaceButton) + { + RecreateStartButton((int)dwRefData); + } + taskBar->bThemeChanging=true; + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + taskBar->bThemeChanging=false; + return res; + } + if ((uMsg==WM_DWMCOLORIZATIONCOLORCHANGED || uMsg==WM_SETTINGCHANGE || uMsg==0x5CB || uMsg==0x5BB) && taskBar && taskBar->bCustomLook && SetWindowCompositionAttribute && GetWinVersion()>=WIN_VER_WIN10) + { + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + int data[4]; + ComputeTaskbarColors(data); + WINCOMPATTRDATA attrData={0x13,&data,sizeof(data)}; + SetWindowCompositionAttribute(hWnd,&attrData); + return res; + } + if ((uMsg==WM_DWMCOLORIZATIONCOLORCHANGED || uMsg==WM_SETTINGCHANGE) && taskBar && taskBar->bCustomLook && SetWindowCompositionAttribute && GetWinVersion()bCustomLook) + { + TTaskbarLook look=(TTaskbarLook)GetSettingInt(L"TaskbarLook"); + WORD winVer=GetWinVersion(); + BOOL blurBehind; + int margin; + enum { FLAG_BLUR=1, FLAG_MARGIN=2, FLAG_ATTRIBUTE=4}; + int flags=0; + if (winVer==WIN_VER_WIN7) + { + blurBehind=look==TASKBAR_GLASS; + margin=look==TASKBAR_OPAQUE?0:-1; + flags=FLAG_BLUR|FLAG_MARGIN; + } + else if (winVer==WIN_VER_WIN8) + { + blurBehind=look==TASKBAR_OPAQUE; + margin=look==TASKBAR_OPAQUE?0:-1; + flags=FLAG_BLUR|FLAG_MARGIN|((look==TASKBAR_TRANSPARENT && g_TaskbarTexture)?FLAG_ATTRIBUTE:0); + } + else if (winVer==WIN_VER_WIN81) + { + blurBehind=look==TASKBAR_OPAQUE; + margin=look==TASKBAR_OPAQUE?0:-1; + flags=FLAG_BLUR|FLAG_MARGIN|((look==TASKBAR_OPAQUE || g_TaskbarTexture)?FLAG_ATTRIBUTE:0); + } + else if (winVer>=WIN_VER_WIN10) + { + blurBehind=TRUE; + margin=look==TASKBAR_OPAQUE?0:-1; + flags=(look==TASKBAR_AEROGLASS?FLAG_BLUR:0)|(look!=TASKBAR_GLASS?FLAG_MARGIN:0)|FLAG_ATTRIBUTE; + } + + if (flags&FLAG_BLUR) + { + DWM_BLURBEHIND blur={DWM_BB_ENABLE,blurBehind}; + DwmEnableBlurBehindWindow(hWnd,&blur); + } + if (flags&FLAG_MARGIN) + { + MARGINS margins={margin}; + DwmExtendFrameIntoClientArea(hWnd,&margins); + } + if (SetWindowCompositionAttribute && (flags&FLAG_ATTRIBUTE)) + { + int data[4]; + ComputeTaskbarColors(data); + WINCOMPATTRDATA attrData={0x13,&data,sizeof(data)}; + SetWindowCompositionAttribute(hWnd,&attrData); + } + if (g_TaskbarTexture && IsAppThemed()) + { + // draw taskbar background (behind start button and separators) + PAINTSTRUCT ps; + HDC hdc=BeginPaint(hWnd,&ps); + RECT rc; + GetClientRect(hWnd,&rc); + UINT uEdge=GetTaskbarPosition(hWnd,NULL,NULL,NULL); + PrintTaskbarBackground(hdc,rc,ps.rcPaint,uEdge); + EndPaint(hWnd,&ps); + return 0; + } + } + if (taskBar->bReplaceButton && g_WinStartButton && !IsAppThemed()) + { + // prevent painting of the default classic button + PAINTSTRUCT ps; + HDC hdc=BeginPaint(hWnd,&ps); + EndPaint(hWnd,&ps); + return 0; + } + } + if (uMsg==WM_PRINTCLIENT && g_TaskbarTexture) + { + // print taskbar background - for background of buttons and tray area + HDC hdc=(HDC)wParam; + RECT rc; + GetClientRect(hWnd,&rc); + UINT uEdge=GetTaskbarPosition(hWnd,NULL,NULL,NULL); + PrintTaskbarBackground(hdc,rc,rc,uEdge); + return 0; + } + if (uMsg==0x5C5 && taskBar && taskBar->bCustomLook && IsWin81Update1()) // some secret message when the taskbar is raised to the top + { + // reset the opaqueness + PostMessage(g_TaskBar,g_StartMenuMsg,MSG_REDRAWTASKBAR,(LPARAM)hWnd); + } + if (uMsg==WM_DESTROY && taskBar) + { + if (taskBar->bReplaceButton) + DestroyStartButton(taskBar->taskbarId); + g_TaskbarInfos.erase(g_TaskbarInfos.find(taskBar->taskbarId)); + } + if (uMsg==WM_TIMER && wParam=='CLSM') + { + if (GetMetroMode(NULL)==METRO_NONE) + { + KillTimer(hWnd,'CLSM'); + return 0; + } + SetForegroundWindow(hWnd); + LogToFile(STARTUP_LOG,L"StartMenu DLL: skipping Metro"); + if (GetSettingInt(L"SkipMetroCount")<0) + { + INPUT inputs[4]={ + {INPUT_KEYBOARD}, + {INPUT_KEYBOARD}, + {INPUT_KEYBOARD}, + {INPUT_KEYBOARD}, + }; + inputs[0].ki.wVk=VK_LWIN; + inputs[1].ki.wVk='D'; + inputs[2].ki.wVk='D'; + inputs[2].ki.dwFlags=KEYEVENTF_KEYUP; + inputs[3].ki.wVk=VK_LWIN; + inputs[3].ki.dwFlags=KEYEVENTF_KEYUP; + SendInput(_countof(inputs),inputs,sizeof(INPUT)); + } + else + { + HWND hwnd=FindWindow(L"ModeInputWnd",NULL); + if (hwnd) + { + DWORD process; + GetWindowThreadProcessId(hwnd,&process); + if (process==GetCurrentProcessId()) + { + IObjectWithSite *pObject=(IObjectWithSite*)GetWindowLongPtr(hwnd,0); + if (pObject) + { + CComPtr pSite; + pObject->GetSite(IID_IUnknown,(void**)&pSite); + if (pSite) + { + CComPtr pLauncher; + IUnknown_QueryService(pSite,SID_ImmersiveLauncher,IID_IImmersiveLauncher80,(void**)&pLauncher); + if (pLauncher) + pLauncher->Dismiss(5); + } + } + } + } + } + g_SkipMetroCount--; + if (g_SkipMetroCount<=0) + KillTimer(hWnd,'CLSM'); + return 0; + } + if (uMsg==WM_MOVE) + { + ResetHotCorners(); + } + if (uMsg==WM_NCLBUTTONDOWN && taskBar && GetWinVersion()==WIN_VER_WIN7 && taskBar->bReplaceButton) + { + g_bSuppressMessage243=true; + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + g_bSuppressMessage243=false; + return res; + } + if (uMsg==WM_PARENTNOTIFY && taskBar && LOWORD(wParam)==WM_CREATE && GetWinVersion()>=WIN_VER_WIN10) + { + wchar_t name[100]; + HWND child=(HWND)lParam; + GetClassName(child,name,_countof(name)); + if (_wcsicmp(name,L"TrayButton")==0 && GetParent(child)==hWnd) + { + bool bFound=false; + for (std::vector::const_iterator it=taskBar->trayButtons.begin();it!=taskBar->trayButtons.end();++it) + if (*it==child) + { + bFound=true; + break; + } + if (!bFound) + { + taskBar->trayButtons.push_back(child); + SetWindowSubclass(child,SubclassTrayButtonProc,'CLSH',taskBar->taskbarId); + } + } + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +static LRESULT CALLBACK SubclassTaskListProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_PAINT || uMsg==WM_PRINT || uMsg==WM_PRINTCLIENT) + { + g_CurrentTaskList=hWnd; + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + g_CurrentTaskList=NULL; + return res; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +static LRESULT CALLBACK SubclassTrayChevronProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_PAINT || uMsg==WM_PRINT || uMsg==WM_PRINTCLIENT) + { + g_CurrentTaskChevron=hWnd; + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + g_CurrentTaskChevron=NULL; + return res; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +static LRESULT CALLBACK SubclassDesktopButtonProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_PAINT || uMsg==WM_PRINT || uMsg==WM_PRINTCLIENT) + { + g_CurrentDesktopButton=hWnd; + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + g_CurrentDesktopButton=NULL; + return res; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +static LRESULT CALLBACK SubclassRebarProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_WINDOWPOSCHANGING) + { + const TaskbarInfo *taskBar=GetTaskbarInfo((int)dwRefData); + if (taskBar && (taskBar->bReplaceButton || taskBar->bHideButton)) + { + WINDOWPOS *pPos=(WINDOWPOS*)lParam; + if (!(pPos->flags&SWP_NOMOVE) || !(pPos->flags&SWP_NOSIZE)) + { + if (pPos->flags&(SWP_NOMOVE|SWP_NOSIZE)) + { + RECT rc; + GetWindowRect(hWnd,&rc); + MapWindowPoints(NULL,GetParent(hWnd),(POINT*)&rc,2); + if (pPos->flags&SWP_NOMOVE) + { + pPos->x=rc.left; + pPos->y=rc.top; + } + else + { + pPos->cx=rc.right-rc.left; + pPos->cy=rc.bottom-rc.top; + } + } + int dx=0, dy=0; + UINT uEdge=GetTaskbarPosition(taskBar->taskBar,NULL,NULL,NULL); + if (taskBar->oldButton) + { + if (uEdge==ABE_LEFT || uEdge==ABE_RIGHT) + { + dy=taskBar->startButtonSize.cy-taskBar->oldButtonSize.cy; + } + else + { + dx=taskBar->startButtonSize.cx-taskBar->oldButtonSize.cx; + } + } + else + { + if (uEdge==ABE_LEFT || uEdge==ABE_RIGHT) + { + dy=taskBar->startButtonSize.cy-pPos->y; + } + else + { + dx=taskBar->startButtonSize.cx-pPos->x; + } + } + if (dx || dy) + { + pPos->x+=dx; + pPos->cx-=dx; + pPos->y+=dy; + pPos->cy-=dy; + pPos->flags&=~(SWP_NOMOVE|SWP_NOSIZE); + } + } + } + } + if (uMsg==WM_PAINT || uMsg==WM_PRINT || uMsg==WM_PRINTCLIENT) + { + g_CurrentRebar=hWnd; + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + g_CurrentRebar=NULL; + return res; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +static LRESULT CALLBACK SubclassTaskbarPartProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_PAINT || uMsg==WM_PRINT || uMsg==WM_PRINTCLIENT) + { + g_CurrentTaskbarPart=hWnd; + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + g_CurrentTaskbarPart=NULL; + return res; + } + if (uMsg==WM_NCDESTROY) + { + TaskbarInfo *info=GetTaskbarInfo((int)dwRefData); + if (info) + { + for (std::vector::const_iterator it=info->taskbarParts.begin();it!=info->taskbarParts.end();++it) + if (*it==hWnd) + { + info->taskbarParts.erase(it); + break; + } + } + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +static void HandleTaskbarParts( TaskbarInfo &taskBar, bool bPrimary ) +{ + if (taskBar.rebar) + { + int count=(int)SendMessage(taskBar.rebar,RB_GETBANDCOUNT,0,0); + for (int i=0;i=WIN_VER_WIN10) + { + HWND clock=FindWindowEx(taskBar.taskBar,NULL,L"ClockButton",NULL); + if (clock && !taskBar.HasPart(clock)) + { + SetWindowSubclass(clock,SubclassTaskbarPartProc,'CLSH',taskBar.taskbarId); + taskBar.taskbarParts.push_back(clock); + } + } +} + +static void HandleSecondaryTaskbar( HWND hwnd ) +{ + int taskbarId=g_NextTaskbar++; + TaskbarInfo &taskBar=g_TaskbarInfos[taskbarId]; + taskBar.taskBar=hwnd; + taskBar.taskbarId=taskbarId; + + taskBar.rebar=FindWindowEx(hwnd,NULL,L"WorkerW",NULL); + if (taskBar.rebar) + { + SetWindowSubclass(taskBar.rebar,SubclassRebarProc,'CLSH',taskbarId); + taskBar.taskList=FindWindowEx(taskBar.rebar,NULL,L"MSTaskListWClass",NULL); + if (taskBar.taskList) + SetWindowSubclass(taskBar.taskList,SubclassTaskListProc,'CLSH',taskbarId); + } + if (GetWinVersion()>WIN_VER_WIN8) + { + taskBar.oldButton=FindWindowEx(taskBar.taskBar,NULL,L"Start",NULL); + if (taskBar.oldButton) + { + if (GetWinVersion()>=WIN_VER_WIN10) + { + taskBar.pOriginalTarget=(IDropTarget*)GetProp(taskBar.oldButton,L"OleDropTargetInterface"); + if (taskBar.pOriginalTarget) + RevokeDragDrop(taskBar.oldButton); + } + + CStartMenuTarget *pNewTarget=new CStartMenuTarget(taskBar.taskbarId); + RegisterDragDrop(taskBar.oldButton,pNewTarget); + pNewTarget->Release(); + if (GetWinVersion()=WIN_VER_WIN10) + { + for (HWND button=FindWindowEx(taskBar.taskBar,NULL,L"TrayButton",NULL);button;button=FindWindowEx(taskBar.taskBar,button,L"TrayButton",NULL)) + { + taskBar.trayButtons.push_back(button); + SetWindowSubclass(button,SubclassTrayButtonProc,'CLSH',taskBar.taskbarId); + } + HWND search=FindWindowEx(taskBar.taskBar,NULL,L"TrayDummySearchControl",NULL); + if (search) + { + taskBar.trayButtons.push_back(search); + SetWindowSubclass(search,SubclassTrayButtonProc,'CLSH',taskBar.taskbarId); + } + } + HandleTaskbarParts(taskBar,false); + SetWindowSubclass(taskBar.taskBar,SubclassTaskBarProc,'CLSH',taskbarId); + UpdateTaskBars(TASKBAR_UPDATE); + UpdateTaskBars(TASKBAR_UPDATE_TEXTURE); +} + +static BOOL CALLBACK HookAllTaskbarsEnum( HWND hwnd, LPARAM lParam ) +{ + // look for top-level windows with class "Shell_SecondaryTrayWnd" in the current thread + if (GetWindowThreadProcessId(hwnd,NULL)!=GetCurrentThreadId()) return TRUE; + wchar_t name[256]; + GetClassName(hwnd,name,_countof(name)); + if (_wcsicmp(name,L"Shell_SecondaryTrayWnd")==0) + HandleSecondaryTaskbar(hwnd); + return TRUE; +} + +void UpdateTaskBars( TUpdateTaskbar update ) +{ + if (update==TASKBAR_UPDATE_TEXTURE) + { + if (g_TaskbarTexture) + DeleteObject(g_TaskbarTexture); + g_TaskbarTexture=NULL; + if (GetSettingBool(L"CustomTaskbar")) + { + g_TaskbarTileH=g_TaskbarTileV=TILE_STRETCH; + g_TaskbarMargins.left=g_TaskbarMargins.right=g_TaskbarMargins.top=g_TaskbarMargins.bottom=0; + TTaskbarLook look=(TTaskbarLook)GetSettingInt(L"TaskbarLook"); + bool bDefOpacity; + int opacity=GetSettingInt(L"TaskbarOpacity",bDefOpacity); + if (look==TASKBAR_OPAQUE) + opacity=100, bDefOpacity=true; + bool bDefColor; + COLORREF color=GetSettingInt(L"TaskbarColor",bDefColor); + wchar_t fname[_MAX_PATH]; + Strcpy(fname,_countof(fname),GetSettingString(L"TaskbarTexture")); + DoEnvironmentSubst(fname,_countof(fname)); + if (*fname) + { + g_TaskbarTexture=LoadImageResource(NULL,fname,false,true); + g_TaskbarTileH=(TTaskbarTile)GetSettingInt(L"TaskbarTileH"); + g_TaskbarTileV=(TTaskbarTile)GetSettingInt(L"TaskbarTileV"); + if (g_TaskbarTileH==TILE_STRETCH) + { + CString borders=GetSettingString(L"TaskbarBordersH"); + if (!borders.IsEmpty()) + { + wchar_t token[256]; + const wchar_t *str=GetToken(borders,token,_countof(token),L", \t"); + g_TaskbarMargins.left=_wtol(token); + if (g_TaskbarMargins.left<0) g_TaskbarMargins.left=0; + str=GetToken(str,token,_countof(token),L", \t"); + g_TaskbarMargins.right=_wtol(token); + if (g_TaskbarMargins.right<0) g_TaskbarMargins.right=0; + } + } + if (g_TaskbarTileV==TILE_STRETCH) + { + CString borders=GetSettingString(L"TaskbarBordersV"); + if (!borders.IsEmpty()) + { + wchar_t token[256]; + const wchar_t *str=GetToken(borders,token,_countof(token),L", \t"); + g_TaskbarMargins.top=_wtol(token); + if (g_TaskbarMargins.top<0) g_TaskbarMargins.top=0; + str=GetToken(str,token,_countof(token),L", \t"); + g_TaskbarMargins.bottom=_wtol(token); + if (g_TaskbarMargins.bottom<0) g_TaskbarMargins.bottom=0; + } + } + } + else if (GetWinVersion()WIN_VER_WIN7) + { + color=GetSystemGlassColor8(); + color=((color&0xFF)<<16)|(color&0xFF00)|((color>>16)&0xFF); + } + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=bi.bmiHeader.biHeight=32; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + + HDC hdc=CreateCompatibleDC(NULL); + unsigned int *bits; + g_TaskbarTexture=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&bits,NULL,0); + if (g_TaskbarTexture) + { + unsigned int val=((color&0xFF)<<16)|(color&0x00FF00)|((color>>16)&0xFF)|0xFF000000; + int count=bi.bmiHeader.biWidth*bi.bmiHeader.biHeight; + for (int i=0;i1 || countV>1) + { + // pretile texture + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=countH*info.bmWidth; + bi.bmiHeader.biHeight=countV*info.bmHeight; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + + HDC hdc=CreateCompatibleDC(NULL); + HDC hsrc=CreateCompatibleDC(hdc); + unsigned int *bits; + HBITMAP bmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&bits,NULL,0); + if (bmp) + { + HGDIOBJ bmp01=SelectObject(hdc,bmp); + HGDIOBJ bmp02=SelectObject(hsrc,g_TaskbarTexture); + for (int y=0;y::iterator it=g_TaskbarInfos.begin();it!=g_TaskbarInfos.end();++it) + RedrawWindow(it->second.taskBar,NULL,NULL,RDW_INVALIDATE|RDW_ALLCHILDREN); + } + return; + } + bool bButton=false, bCustomLook= false, bAll= false; + if (update==TASKBAR_CLEAR) + { + if (g_TaskbarTexture) + DeleteObject(g_TaskbarTexture); + g_TaskbarTexture=NULL; + } + else + { + bButton=GetSettingBool(L"EnableStartButton"); + bCustomLook=GetSettingBool(L"CustomTaskbar"); + bAll=GetSettingBool(L"AllTaskbars"); + } + if (g_bTrimHooks) + bButton=false; + for (std::map::iterator it=g_TaskbarInfos.begin();it!=g_TaskbarInfos.end();++it) + { + TaskbarInfo &taskBar=it->second; + bool bButton2=bButton && (bAll || taskBar.taskBar==g_TaskBar); + bool bHideButton2=bButton; + if (taskBar.oldButton) + { + if (bHideButton2 && !bButton2) + { + // reposition rebar + if (taskBar.oldButton) + { + RECT rc; + GetWindowRect(taskBar.oldButton,&rc); + taskBar.oldButtonSize.cx=rc.right-rc.left; + taskBar.oldButtonSize.cy=rc.bottom-rc.top; + } + RECT rcTask; + GetWindowRect(taskBar.taskBar,&rcTask); + PostMessage(taskBar.taskBar,WM_SIZE,SIZE_RESTORED,MAKELONG(rcTask.right-rcTask.left,rcTask.bottom-rcTask.top)); + } + if (taskBar.bHideButton!=bHideButton2) + { + // show/hide 8.1 button + taskBar.bHideButton=bHideButton2; + if (bHideButton2) + { + ShowWindow(taskBar.oldButton,SW_HIDE); + } + else + { + ShowWindow(taskBar.oldButton,SW_SHOW); + } + } + } + if (taskBar.bReplaceButton!=bButton2) + { + // create or destroy button + taskBar.bReplaceButton=bButton2; + + if (bButton2) + { + RecreateStartButton(it->first); + if (g_WinStartButton) + { + ShowWindow(g_WinStartButton,SW_HIDE); + SetWindowSubclass(g_WinStartButton,SubclassWin7StartButton,'CLSH',0); + if (GetWinVersion()==WIN_VER_WIN7) + { + // Windows 7 draws the start button on the taskbar as well + // so we zero out the bitmap resources + HMODULE hExplorer=GetModuleHandle(NULL); + for (int res=0;res<_countof(g_StartButtonOldSizes);res++) + { + HRSRC hrSrc=FindResource(hExplorer,MAKEINTRESOURCE(res+FIRST_BUTTON_BITMAP),RT_BITMAP); + if (hrSrc) + { + HGLOBAL hRes=LoadResource(hExplorer,hrSrc); + if (hRes) + { + void *pRes=LockResource(hRes); + if (pRes) + { + DWORD old; + BITMAPINFOHEADER *pHeader=(BITMAPINFOHEADER*)pRes; + if (pHeader->biWidth) + { + g_StartButtonOldSizes[res]=MAKELONG(pHeader->biWidth,pHeader->biHeight); + VirtualProtect(pRes,sizeof(BITMAPINFOHEADER),PAGE_READWRITE,&old); + pHeader->biHeight=pHeader->biWidth=0; + VirtualProtect(pRes,sizeof(BITMAPINFOHEADER),old,&old); + } + } + } + } + } + } + SendMessage(taskBar.taskBar,WM_SETTINGCHANGE,0,0); + } + } + else + { + if (taskBar.startButton && taskBar.startButton!=g_WinStartButton) + { + RevokeDragDrop(taskBar.startButton); + DestroyStartButton(taskBar.taskbarId); + } + taskBar.startButton=taskBar.taskBar==g_TaskBar?g_WinStartButton:NULL; + taskBar.startButtonSize.cx=taskBar.startButtonSize.cy=0; + if (g_WinStartButton && g_WinStartButton==taskBar.startButton) + { + // restore the bitmap sizes + HMODULE hExplorer=GetModuleHandle(NULL); + for (int res=0;res<_countof(g_StartButtonOldSizes);res++) + { + HRSRC hrSrc=FindResource(hExplorer,MAKEINTRESOURCE(res+FIRST_BUTTON_BITMAP),RT_BITMAP); + if (hrSrc) + { + HGLOBAL hRes=LoadResource(hExplorer,hrSrc); + if (hRes) + { + void *pRes=LockResource(hRes); + if (pRes) + { + DWORD old; + BITMAPINFOHEADER *pHeader=(BITMAPINFOHEADER*)pRes; + if (g_StartButtonOldSizes[res]) + { + VirtualProtect(pRes,sizeof(BITMAPINFOHEADER),PAGE_READWRITE,&old); + pHeader->biWidth=LOWORD(g_StartButtonOldSizes[res]); + pHeader->biHeight=HIWORD(g_StartButtonOldSizes[res]); + VirtualProtect(pRes,sizeof(BITMAPINFOHEADER),old,&old); + } + } + } + } + } + RemoveWindowSubclass(g_WinStartButton,SubclassWin7StartButton,'CLSH'); + SendMessage(g_WinStartButton,WM_THEMECHANGED,0,0); + ShowWindow(g_WinStartButton,SW_SHOW); + } + } + } + else if (update==TASKBAR_RECREATE_BUTTONS && bButton2) + { + RecreateStartButton(it->first); + } + if (taskBar.bCustomLook!=bCustomLook) + { + // set custom look + taskBar.bCustomLook=bCustomLook; + + if (!bCustomLook && GetWinVersion()::iterator it=g_TaskbarInfos.begin();it!=g_TaskbarInfos.end();++it) + { + TaskbarInfo &taskBar=it->second; + SendMessage(taskBar.taskBar,WM_SETTINGCHANGE,0,0); + InvalidateRect(taskBar.taskBar,NULL,TRUE); + PostMessage(taskBar.taskBar,WM_THEMECHANGED,0,0); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// hooks for animating the start button + +typedef void (WINAPI *tDwmpBeginTransitionRequest)(int param); +typedef void (WINAPI *tDwmpTransitionWindowWithRects)(HWND,int,RECT*,RECT*,RECT*,RECT*,RECT*); +typedef void (WINAPI *tDwmpEndTransitionRequest)(int param); + +static IatHookData *g_DwmpBTRHook, *g_DwmpTWWRHook, *g_DwmpETRHook; + +static tDwmpBeginTransitionRequest g_DwmpBeginTransitionRequest; +static tDwmpTransitionWindowWithRects g_DwmpTransitionWindowWithRects; +static tDwmpEndTransitionRequest g_DwmpEndTransitionRequest; + +static HWND g_TransitionButton; +static HWND g_TransitionBar; +static RECT g_TransitionClip; +static POINT g_TransitionVector; +static bool g_bTransitionIn; + +void WINAPI DwmpBeginTransitionRequest2( int param ) +{ + g_TransitionButton=NULL; + ((tDwmpBeginTransitionRequest)g_DwmpBTRHook->oldProc)(param); +} + +void WINAPI DwmpTransitionWindowWithRects2( HWND hWnd, int flags, RECT *prcClient1, RECT *prcStart, RECT *prcClient2, RECT *prcEnd, RECT *prcClip ) +{ + g_TransitionButton=NULL; + const TaskbarInfo *taskBar=FindTaskBarInfoBar(hWnd); + if (taskBar && taskBar->bCustomLook) + { + g_TransitionBar=hWnd; + TTaskbarLook look=(TTaskbarLook)GetSettingInt(L"TaskbarLook"); + DWM_BLURBEHIND blur={DWM_BB_ENABLE,look==TASKBAR_OPAQUE}; + DwmEnableBlurBehindWindow(hWnd,&blur); + int data[4]; + ComputeTaskbarColors(data); + WINCOMPATTRDATA attrData={0x13,&data,sizeof(data)}; + SetWindowCompositionAttribute(hWnd,&attrData); + } + if (taskBar && taskBar->startButton && prcStart && prcEnd && prcClip) + { + g_TransitionButton=taskBar->startButton; + g_TransitionVector.x=prcEnd->left-prcStart->left; + g_TransitionVector.y=prcEnd->top-prcStart->top; + g_TransitionClip=*prcClip; + g_bTransitionIn=true; + switch (GetTaskbarPosition(taskBar->taskBar,NULL,NULL,NULL)) + { + case ABE_LEFT: + g_bTransitionIn=g_TransitionVector.x>0; + break; + case ABE_TOP: + g_bTransitionIn=g_TransitionVector.y>0; + break; + case ABE_RIGHT: + g_bTransitionIn=g_TransitionVector.x<0; + break; + default: + g_bTransitionIn=g_TransitionVector.y<0; + } + } + ((tDwmpTransitionWindowWithRects)g_DwmpTWWRHook->oldProc)(hWnd,flags,prcClient1,prcStart,prcClient2,prcEnd,prcClip); +} + +void WINAPI DwmpEndTransitionRequest2( int param ) +{ + ((tDwmpEndTransitionRequest)g_DwmpETRHook->oldProc)(param); + if (g_TransitionBar) + { + TTaskbarLook look=(TTaskbarLook)GetSettingInt(L"TaskbarLook"); + DWM_BLURBEHIND blur={DWM_BB_ENABLE,look==TASKBAR_OPAQUE}; + DwmEnableBlurBehindWindow(g_TransitionBar,&blur); + int data[4]; + ComputeTaskbarColors(data); + WINCOMPATTRDATA attrData={0x13,&data,sizeof(data)}; + SetWindowCompositionAttribute(g_TransitionBar,&attrData); + g_TransitionBar=NULL; + } + if (g_TransitionButton) + { + HWND button=g_TransitionButton; + g_TransitionButton=NULL; + g_DwmpBeginTransitionRequest(15); + RECT rcClient; + GetClientRect(button,&rcClient); + RECT rcStart, rcEnd; + if (g_bTransitionIn) + { + GetWindowRect(button,&rcEnd); + rcStart=rcEnd; + OffsetRect(&rcStart,-g_TransitionVector.x,-g_TransitionVector.y); + } + else + { + GetWindowRect(button,&rcStart); + rcEnd=rcStart; + int dx=0, dy=0; + if (g_TransitionVector.x<0) // left + { + dx=g_TransitionClip.left-rcStart.right; + if (dx>0) dx=g_TransitionVector.x; + } + else if (g_TransitionVector.x>0) // right + { + dx=g_TransitionClip.right-rcStart.left; + if (dx<0) dx=g_TransitionVector.x; + } + else if (g_TransitionVector.y<0) // top + { + dy=g_TransitionClip.top-rcStart.bottom; + if (dy>0) dy=g_TransitionVector.y; + } + else if (g_TransitionVector.y>0) // bottom + { + dy=g_TransitionClip.bottom-rcStart.top; + if (dy<0) dy=g_TransitionVector.y; + } + OffsetRect(&rcEnd,dx,dy); + } + g_DwmpTransitionWindowWithRects(button,0x21800046,&rcClient,&rcStart,&rcClient,&rcEnd,&g_TransitionClip); + g_DwmpEndTransitionRequest(15); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// hooks for skinning the taskbar + +typedef void (WINAPI *tSHFillRectClr)(HDC hdc, const RECT *pRect, COLORREF color); + +static IatHookData *g_SHFillRectClrHook, *g_StretchDIBitsHook; +static IatHookData *g_DrawThemeBackgroundHook, *g_DrawThemeTextHook, *g_DrawThemeTextExHook, *g_DrawThemeTextCtlHook, *g_SetWindowCompositionAttributeHook; + +static tSHFillRectClr g_SHFillRectClr; + +static void WINAPI SHFillRectClr2( HDC hdc, const RECT *pRect, COLORREF color ) +{ + if (!g_CurrentTaskList || !g_TaskbarTexture || GetCurrentThreadId()!=g_TaskbarThreadId) + g_SHFillRectClr(hdc,pRect,color); +} + +static HRESULT STDAPICALLTYPE DrawThemeBackground2( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCRECT pRect, LPCRECT pClipRect ) +{ + if (g_CurrentTaskList && g_TaskbarTexture && iPartId==1 && iStateId==0 && GetCurrentThreadId()==g_TaskbarThreadId) + { + HWND taskbar=GetAncestor(g_CurrentTaskList,GA_ROOT); + RECT rcClient; + GetClientRect(taskbar,&rcClient); + MapWindowPoints(taskbar,g_CurrentTaskList,(POINT*)&rcClient,2); + PrintTaskbarBackground(hdc,rcClient,*pRect,0); + return S_OK; + } + if (g_CurrentDesktopButton && g_TaskbarTexture && GetCurrentThreadId()==g_TaskbarThreadId && hTheme==GetWindowTheme(g_CurrentDesktopButton)) + { + HWND taskbar=GetAncestor(g_CurrentDesktopButton,GA_ROOT); + RECT rcClient; + GetClientRect(taskbar,&rcClient); + MapWindowPoints(taskbar,g_CurrentDesktopButton,(POINT*)&rcClient,2); + UINT uEdge=GetTaskbarPosition(taskbar,NULL,NULL,NULL); + PrintTaskbarBackground(hdc,rcClient,*pRect,uEdge); + return DrawThemeBackground(hTheme,hdc,iPartId,iStateId,pRect,pClipRect); + } + return DrawThemeBackground(hTheme,hdc,iPartId,iStateId,pRect,pClipRect); +} + +// toolbar text, rebar band titles, clock +static HRESULT STDAPICALLTYPE DrawThemeText2( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect ) +{ + if ((g_CurrentRebar || g_CurrentTaskbarPart) && GetCurrentThreadId()==g_TaskbarThreadId && GetSettingBool(L"CustomTaskbar")) + { + bool bDef; + COLORREF color=GetSettingInt(L"TaskbarTextColor",bDef)&0xFFFFFF; + if (!bDef) + { + // change the color for the toolbar titles, the toolbar buttons and the clock + DTTOPTS options={sizeof(options),DTT_TEXTCOLOR}; + options.crText=color; + return DrawThemeTextEx(hTheme,hdc,iPartId,iStateId,pszText,iCharCount,dwTextFlags,(RECT*)pRect,&options); + } + } + return DrawThemeText(hTheme,hdc,iPartId,iStateId,pszText,iCharCount,dwTextFlags,dwTextFlags2,pRect); +} + +// taskbar text +static HRESULT STDAPICALLTYPE DrawThemeTextEx2( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwFlags, LPRECT pRect, const DTTOPTS *pOptions ) +{ + if ((g_CurrentTaskList || g_CurrentTaskbarPart) && GetCurrentThreadId()==g_TaskbarThreadId && GetSettingBool(L"CustomTaskbar")) + { + bool bDef; + COLORREF color=GetSettingInt(L"TaskbarTextColor",bDef)&0xFFFFFF; + if (!bDef) + { + // change the color dor the taskbar buttons + DTTOPTS options=*pOptions; + options.dwFlags|=DTT_TEXTCOLOR; + options.crText=color; + return DrawThemeTextEx(hTheme,hdc,iPartId,iStateId,pszText,iCharCount,dwFlags,pRect,&options); + } + } + return DrawThemeTextEx(hTheme,hdc,iPartId,iStateId,pszText,iCharCount,dwFlags,pRect,pOptions); +} + +static BLENDFUNCTION g_AlphaFunc={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + +static int WINAPI StretchDIBits2( HDC hdc, int xDest, int yDest, int DestWidth, int DestHeight, int xSrc, int ySrc, int SrcWidth, int SrcHeight, CONST VOID *lpBits, CONST BITMAPINFO *lpbmi, UINT iUsage, DWORD rop ) +{ + if ((g_CurrentTaskChevron || g_CurrentTaskbarButton) && g_TaskbarTexture && GetCurrentThreadId()==g_TaskbarThreadId) + { + HDC hsrc=CreateCompatibleDC(hdc); + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=DestWidth; + bi.bmiHeader.biHeight=DestHeight; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + HBITMAP bitmap=CreateDIBSection(hsrc,&bi,DIB_RGB_COLORS,NULL,NULL,0); + HGDIOBJ bmp0=SelectObject(hsrc,bitmap); + int res=StretchDIBits(hsrc,0,0,DestWidth,DestHeight,xSrc,ySrc,SrcWidth,SrcHeight,lpBits,lpbmi,iUsage,SRCCOPY); + AlphaBlend(hdc,xDest,yDest,DestWidth,DestHeight,hsrc,0,0,DestWidth,DestHeight,g_AlphaFunc); + SelectObject(hsrc,bmp0); + DeleteObject(bitmap); + DeleteDC(hsrc); + return res; + } + return StretchDIBits(hdc,xDest,yDest,DestWidth,DestHeight,xSrc,ySrc,SrcWidth,SrcHeight,lpBits,lpbmi,iUsage,rop); +} + +static BOOL WINAPI SetWindowCompositionAttribute2( HWND hwnd, WINCOMPATTRDATA *pAttrData ) +{ + if (pAttrData->attribute==0x13 && GetCurrentThreadId()==g_TaskbarThreadId) + { + const TaskbarInfo *taskBar=FindTaskBarInfoBar(hwnd); + if (taskBar && taskBar->bCustomLook) + { + int data[4]; + ComputeTaskbarColors(data); + WINCOMPATTRDATA attrData={0x13,&data,sizeof(data)}; + if (data[0]==3 && taskBar->bThemeChanging) + { + // send extra attribute when dealing with glass. without it the image behind the glass may not update when the taskbar is resized + SetWindowCompositionAttribute(hwnd,pAttrData); + } + return SetWindowCompositionAttribute(hwnd,&attrData); + } + } + return SetWindowCompositionAttribute(hwnd,pAttrData); +} + +/////////////////////////////////////////////////////////////////////////////// + +static void OpenCortana( void ) +{ + if (GetWinVersion()>=WIN_VER_WIN10) + ShellExecute(NULL,NULL,L"shell:::{2559a1f8-21d7-11d4-bdaf-00c04f60b9f0}",NULL,NULL,SW_SHOWNORMAL); +} + +static void InitStartMenuDLL( void ) +{ + InitializeIatHooks(); + if (IsWin81Update1()) + { + HMODULE dwm=GetModuleHandle(L"dwmapi.dll"); + if (dwm) + { + g_DwmpBeginTransitionRequest=(tDwmpBeginTransitionRequest)GetProcAddress(dwm,MAKEINTRESOURCEA(138)); + g_DwmpTransitionWindowWithRects=(tDwmpTransitionWindowWithRects)GetProcAddress(dwm,MAKEINTRESOURCEA(141)); + g_DwmpEndTransitionRequest=(tDwmpEndTransitionRequest)GetProcAddress(dwm,MAKEINTRESOURCEA(140)); + if (g_DwmpBeginTransitionRequest && g_DwmpTransitionWindowWithRects && g_DwmpEndTransitionRequest) + { + g_DwmpBTRHook=SetIatHook(GetModuleHandle(NULL),"dwmapi.dll",MAKEINTRESOURCEA(138),DwmpBeginTransitionRequest2); + g_DwmpTWWRHook=SetIatHook(GetModuleHandle(NULL),"dwmapi.dll",MAKEINTRESOURCEA(141),DwmpTransitionWindowWithRects2); + g_DwmpETRHook=SetIatHook(GetModuleHandle(NULL),"dwmapi.dll",MAKEINTRESOURCEA(140),DwmpEndTransitionRequest2); + if (!g_DwmpBTRHook || !g_DwmpTWWRHook || !g_DwmpETRHook) + { + ClearIatHook(g_DwmpBTRHook); + g_DwmpBTRHook=NULL; + ClearIatHook(g_DwmpTWWRHook); + g_DwmpTWWRHook=NULL; + ClearIatHook(g_DwmpETRHook); + g_DwmpETRHook=NULL; + } + } + } + } + + if (GetWinVersion()>=WIN_VER_WIN10) + { + HMODULE shlwapi=GetModuleHandle(L"shlwapi.dll"); + if (shlwapi) + { + g_SHFillRectClr=(tSHFillRectClr)GetProcAddress(shlwapi,MAKEINTRESOURCEA(197)); + if (g_SHFillRectClr) + { + g_SHFillRectClrHook=SetIatHook(GetModuleHandle(NULL),"shlwapi.dll",MAKEINTRESOURCEA(197),SHFillRectClr2); + if (!g_SHFillRectClrHook) + g_SHFillRectClrHook=SetIatHook(GetModuleHandle(NULL),"api-ms-win-shlwapi-winrt-storage-l1-1-1.dll",MAKEINTRESOURCEA(197),SHFillRectClr2); + } + } + g_StretchDIBitsHook=SetIatHook(GetModuleHandle(NULL),"gdi32.dll","StretchDIBits",StretchDIBits2); + } + + { + HWND dlg=CreateWindow(L"#32770",L"",WS_POPUP,0,0,0,0,NULL,0,0,0); + HWND toolbar=CreateWindow(TOOLBARCLASSNAME,L"",WS_CHILD|TBS_TOOLTIPS,0,0,0,0,dlg,0,0,0); + DestroyWindow(dlg); + } + + if (GetWinVersion()<=WIN_VER_WIN81) + g_DrawThemeBackgroundHook=SetIatHook(GetModuleHandle(NULL),"uxtheme.dll","DrawThemeBackground",DrawThemeBackground2); + g_DrawThemeTextHook=SetIatHook(GetModuleHandle(NULL),"uxtheme.dll","DrawThemeText",DrawThemeText2); + g_DrawThemeTextExHook=SetIatHook(GetModuleHandle(NULL),"uxtheme.dll","DrawThemeTextEx",DrawThemeTextEx2); + g_DrawThemeTextCtlHook=SetIatHook(GetModuleHandle(L"comctl32.dll"),"uxtheme.dll","DrawThemeText",DrawThemeText2); + if (GetWinVersion()>=WIN_VER_WIN10) + g_SetWindowCompositionAttributeHook=SetIatHook(GetModuleHandle(NULL),"user32.dll","SetWindowCompositionAttribute",SetWindowCompositionAttribute2); + + g_TaskbarThreadId=GetCurrentThreadId(); + LogToFile(STARTUP_LOG,L"StartMenu DLL: InitStartMenuDLL"); + WaitDllInitThread(); + g_bTrimHooks=GetWinVersion()==WIN_VER_WIN7 && (GetSettingInt(L"CompatibilityFixes")&COMPATIBILITY_TRIM_HOOKS); + InitManagers(false); + int level=GetSettingInt(L"CrashDump"); + if (level>=1 && level<=3) + { + if (level==1) MiniDumpType=MiniDumpNormal; + if (level==2) MiniDumpType=MiniDumpWithDataSegs; + if (level==3) MiniDumpType=MiniDumpWithFullMemory; + SetUnhandledExceptionFilter(TopLevelFilter); + _set_invalid_parameter_handler(InvalidParameterHandler); + g_bCrashDump=true; + } + FindTaskBar(); + g_ProgWin=FindWindowEx(NULL,NULL,L"Progman",NULL); + DWORD progThread=GetWindowThreadProcessId(g_ProgWin,NULL); + g_ProgHook=SetWindowsHookEx(WH_GETMESSAGE,HookProgManThread,NULL,progThread); + g_StartHook=SetWindowsHookEx(WH_GETMESSAGE,HookDesktopThread,NULL,GetCurrentThreadId()); + HWND hwnd=FindWindow(L"ClassicStartMenu.CStartHookWindow",L"StartHookWindow"); + LoadLibrary(L"ClassicStartMenuDLL.dll"); // keep the DLL from unloading + if (hwnd) PostMessage(hwnd,WM_CLEAR,0,0); // tell the exe to unhook this hook + if (GetWinVersion()>=WIN_VER_WIN8) + { + SetWindowCompositionAttribute=(tSetWindowCompositionAttribute)GetProcAddress(GetModuleHandle(L"user32.dll"),"SetWindowCompositionAttribute"); + } + int taskbarId=g_NextTaskbar++; + TaskbarInfo &taskBar=g_TaskbarInfos[taskbarId]; + taskBar.taskBar=g_TaskBar; + taskBar.taskbarId=taskbarId; + taskBar.rebar=FindWindowEx(g_TaskBar,NULL,REBARCLASSNAME,NULL); + if (taskBar.rebar) + { + SetWindowSubclass(taskBar.rebar,SubclassRebarProc,'CLSH',taskbarId); + HWND hwnd=FindWindowEx(taskBar.rebar,NULL,L"MSTaskSwWClass",NULL); + if (hwnd) + taskBar.taskList=FindWindowEx(hwnd,NULL,L"MSTaskListWClass",NULL); + if (taskBar.taskList) + SetWindowSubclass(taskBar.taskList,SubclassTaskListProc,'CLSH',taskbarId); + } + if (GetWinVersion()>WIN_VER_WIN8) + { + taskBar.oldButton=FindWindowEx(taskBar.taskBar,NULL,L"Start",NULL); + if (taskBar.oldButton) + { + if (GetWinVersion()>=WIN_VER_WIN10) + { + taskBar.pOriginalTarget=(IDropTarget*)GetProp(taskBar.oldButton,L"OleDropTargetInterface"); + if (taskBar.pOriginalTarget) + RevokeDragDrop(taskBar.oldButton); + } + + CStartMenuTarget *pNewTarget=new CStartMenuTarget(taskBar.taskbarId); + RegisterDragDrop(taskBar.oldButton,pNewTarget); + pNewTarget->Release(); + if (GetWinVersion()=WIN_VER_WIN10) + { + for (HWND button=FindWindowEx(g_TaskBar,NULL,L"TrayButton",NULL);button;button=FindWindowEx(g_TaskBar,button,L"TrayButton",NULL)) + { + taskBar.trayButtons.push_back(button); + SetWindowSubclass(button,SubclassTrayButtonProc,'CLSH',taskBar.taskbarId); + } + HWND search=FindWindowEx(g_TaskBar,NULL,L"TrayDummySearchControl",NULL); + if (search) + { + taskBar.trayButtons.push_back(search); + SetWindowSubclass(search,SubclassTrayButtonProc,'CLSH',taskBar.taskbarId); + } + HWND tray=FindWindowEx(g_TaskBar,NULL,L"TrayNotifyWnd",NULL); + if (tray) + taskBar.chevron=FindWindowEx(tray,NULL,L"Button",NULL); + if (taskBar.chevron) + SetWindowSubclass(taskBar.chevron,SubclassTrayChevronProc,'CLSH',taskBar.taskbarId); + } + + HandleTaskbarParts(taskBar,true); +if (!g_bTrimHooks) + SetWindowSubclass(taskBar.taskBar,SubclassTaskBarProc,'CLSH',taskbarId); + taskBar.startButton=g_WinStartButton; + +#ifdef HOOK_DROPTARGET + if (g_WinStartButton) + { + g_pOriginalTarget=(IDropTarget*)GetProp(g_WinStartButton,L"OleDropTargetInterface"); + if (g_pOriginalTarget) + RevokeDragDrop(g_WinStartButton); + + CStartMenuTarget *pNewTarget=new CStartMenuTarget(taskbarId); + RegisterDragDrop(g_WinStartButton,pNewTarget); + pNewTarget->Release(); + } +#endif + + if (GetWinVersion()>=WIN_VER_WIN8) + { + g_pAppVisibility.CoCreateInstance(CLSID_MetroMode); + if (g_pAppVisibility) + { + CMonitorModeEvents *monitor=new CMonitorModeEvents(); + g_pAppVisibility->Advise(monitor,&g_AppVisibilityMonitorCookie); + monitor->Release(); + } + if (GetWinVersion()::iterator it=g_TaskbarInfos.begin();it!=g_TaskbarInfos.end();++it) + { + TaskbarInfo &taskBar=it->second; + if (taskbarId>=0 && taskBar.taskbarId!=taskbarId) + continue; + if (taskBar.bRecreatingButton) + continue; + RECT rcTask; + GetWindowRect(taskBar.taskBar,&rcTask); + RECT rcTask2=rcTask; + MONITORINFO info; + UINT uEdge=GetTaskbarPosition(taskBar.taskBar,&info,NULL,NULL); + if (uEdge==ABE_TOP || uEdge==ABE_BOTTOM) + { + if (rcTask2.leftinfo.rcMonitor.right) rcTask2.right=info.rcMonitor.right; + } + else + { + if (rcTask2.topRelease(); + } + taskBar.bRecreatingButton=false; + + taskBar.startButtonSize=GetStartButtonSize(taskBar.taskbarId); + if (taskBar.oldButton) + { + RECT rc; + GetWindowRect(taskBar.oldButton,&rc); + taskBar.oldButtonSize.cx=rc.right-rc.left; + taskBar.oldButtonSize.cy=rc.bottom-rc.top; + } + + PostMessage(taskBar.taskBar,WM_SIZE,SIZE_RESTORED,MAKELONG(rcTask.right-rcTask.left,rcTask.bottom-rcTask.top)); + } +} + +static DWORD WINAPI ExitThreadProc( void *param ) +{ + Sleep(1000); // wait a second! hopefully by then the hooks will be finished and no more of our code will be executing + // send WM_CLOSE to the window in ClassicStartMenu.exe to close that process + if (param) PostMessage((HWND)param,WM_CLOSE,0,0); + FreeLibraryAndExitThread(g_Instance,0); +} + +static void CleanStartMenuDLL( void ) +{ + ClearIatHook(g_DwmpBTRHook); + g_DwmpBTRHook=NULL; + ClearIatHook(g_DwmpTWWRHook); + g_DwmpTWWRHook=NULL; + ClearIatHook(g_DwmpETRHook); + g_DwmpETRHook=NULL; + ClearIatHook(g_SHFillRectClrHook); + g_SHFillRectClrHook=NULL; + ClearIatHook(g_StretchDIBitsHook); + g_StretchDIBitsHook=NULL; + + ClearIatHook(g_DrawThemeBackgroundHook); + g_DrawThemeBackgroundHook=NULL; + ClearIatHook(g_DrawThemeTextHook); + g_DrawThemeTextHook=NULL; + ClearIatHook(g_DrawThemeTextExHook); + g_DrawThemeTextExHook=NULL; + ClearIatHook(g_DrawThemeTextCtlHook); + g_DrawThemeTextCtlHook=NULL; + ClearIatHook(g_SetWindowCompositionAttributeHook); + g_SetWindowCompositionAttributeHook=NULL; + + CloseManagers(false); + ClearIatHooks(); + + // cleanup + if (g_Owner.m_hWnd) g_Owner.DestroyWindow(); + CloseSettings(); + CMenuContainer::CloseStartMenu(); + CMenuFader::ClearAll(); + UnhookDropTarget(); + EnableHotkeys(HOTKEYS_CLEAR); + HWND hwnd=FindWindow(L"ClassicStartMenu.CStartHookWindow",L"StartHookWindow"); + UnhookWindowsHookEx(g_ProgHook); + UnhookWindowsHookEx(g_StartHook); + if (g_AppManagerHook) UnhookWindowsHookEx(g_AppManagerHook); + g_AppManagerHook=NULL; + if (g_NewWindowHook) UnhookWindowsHookEx(g_NewWindowHook); + g_NewWindowHook=NULL; + if (g_pAppVisibility) + { + g_pAppVisibility->Unadvise(g_AppVisibilityMonitorCookie); + g_pAppVisibility=NULL; + } + ResetHotCorners(); + UpdateTaskBars(TASKBAR_CLEAR); + g_WinStartButton=NULL; + for (std::map::const_iterator it=g_TaskbarInfos.begin();it!=g_TaskbarInfos.end();++it) + { + if (it->second.rebar) + RemoveWindowSubclass(it->second.rebar,SubclassRebarProc,'CLSH'); + if (it->second.taskList) + RemoveWindowSubclass(it->second.taskList,SubclassTaskListProc,'CLSH'); + if (it->second.oldButton) + { + RemoveWindowSubclass(it->second.oldButton,SubclassWin81StartButton,'CLSH'); + SetWindowPos(it->second.oldButton,NULL,0,0,0,0,SWP_NOSIZE|SWP_NOZORDER); + RevokeDragDrop(it->second.oldButton); + if (it->second.pOriginalTarget) + RegisterDragDrop(it->second.oldButton,it->second.pOriginalTarget); + } +if (!g_bTrimHooks) + RemoveWindowSubclass(it->second.taskBar,SubclassTaskBarProc,'CLSH'); + for (std::vector::const_iterator it2=it->second.trayButtons.begin();it2!=it->second.trayButtons.end();++it2) + { + RemoveWindowSubclass(*it2,SubclassTrayButtonProc,'CLSH'); + } + for (std::vector::const_iterator it2=it->second.taskbarParts.begin();it2!=it->second.taskbarParts.end();++it2) + { + RemoveWindowSubclass(*it2,SubclassTaskbarPartProc,'CLSH'); + } + if (it->second.chevron) + RemoveWindowSubclass(it->second.chevron,SubclassTrayChevronProc,'CLSH'); + if (it->second.desktop) + RemoveWindowSubclass(it->second.desktop,SubclassDesktopButtonProc,'CLSH'); + if (it->second.bTimer) + KillTimer(it->second.startButton,'CLSM'); + RECT rcTask; + GetWindowRect(it->second.taskBar,&rcTask); + PostMessage(it->second.taskBar,WM_SIZE,SIZE_RESTORED,MAKELONG(rcTask.right-rcTask.left,rcTask.bottom-rcTask.top)); + PostMessage(it->second.taskBar,WM_THEMECHANGED,0,0); + } + g_TaskbarInfos.clear(); + if (g_TopWin7Menu) + { + RemoveWindowSubclass(g_UserPic,SubclassUserPicProc,'CLSH'); + RemoveWindowSubclass(g_TopWin7Menu,SubclassTopMenuProc,'CLSH'); + RemoveWindowSubclass(g_AllPrograms,SubclassProgramsProc,'CLSH'); + } + if (g_bCrashDump) + { + SetUnhandledExceptionFilter(NULL); + g_bCrashDump=false; + } + + // we need to unload the DLL here. but we can't just call FreeLibrary because it will unload the code + // while it is still executing. So we create a separate thread and use FreeLibraryAndExitThread + CreateThread(NULL,0,ExitThreadProc,(void*)hwnd,0,NULL); +} + +/////////////////////////////////////////////////////////////////////////////// + + +static BOOL CALLBACK FindImmersiveWindows( HWND hwnd, LPARAM lParam ) +{ + wchar_t name[100]; + GetClassName(hwnd,name,_countof(name)); + if (wcscmp(name,L"ImmersiveLauncher")==0) + ((HWND*)lParam)[0]=hwnd; + if (wcscmp(name,L"ImmersiveBackgroundWindow")==0) + ((HWND*)lParam)[1]=hwnd; + if (wcscmp(name,L"SearchPane")==0) + ((HWND*)lParam)[2]=hwnd; + return TRUE; +} + +static bool WindowsMenuOpened( void ) +{ + FindWindowsMenu(); + CComPtr pImmersiveShell; + if (GetWinVersion()>=WIN_VER_WIN10 && CreateImmersiveShell(pImmersiveShell)) + { + { + CComPtr pLauncher; + IUnknown_QueryService(pImmersiveShell,SID_ImmersiveLauncher,IID_IImmersiveLauncher81,(void**)&pLauncher); + BOOL bIsVisible; + if (pLauncher && SUCCEEDED(pLauncher->IsVisible(&bIsVisible))) + return bIsVisible!=0; + } + { + CComPtr pLauncher; + IUnknown_QueryService(pImmersiveShell,SID_ImmersiveLauncher,IID_IImmersiveLauncher10RS,(void**)&pLauncher); + BOOL bIsVisible; + if (pLauncher && SUCCEEDED(pLauncher->IsVisible(&bIsVisible))) + return bIsVisible!=0; + } + } + if (GetWinVersion()>=WIN_VER_WIN8) + { + return GetMetroMode(NULL)!=METRO_NONE; + } + else + { + return g_TopWin7Menu && IsWindowVisible(g_TopWin7Menu); + } +} + +static void OpenStartScreen( HMONITOR monitor ) +{ + CComPtr pImmersiveShell; + if (CreateImmersiveShell(pImmersiveShell)) + { + CComPtr pMonitor; + if (GetWinVersion()==WIN_VER_WIN8) + { + if (monitor) + { + CComPtr pMonitorService; + IUnknown_QueryService(pImmersiveShell,SID_IImmersiveMonitorService,IID_IImmersiveMonitorService,(void**)&pMonitorService); + if (pMonitorService) + { + CComPtr pMonitor; + pMonitorService->GetFromHandle(monitor,&pMonitor); + if (pMonitor) + pMonitorService->SetImmersiveMonitor(pMonitor); + } + } + CComPtr pLauncher; + IUnknown_QueryService(pImmersiveShell,SID_ImmersiveLauncher,IID_IImmersiveLauncher80,(void**)&pLauncher); + if (pLauncher) + pLauncher->ShowStartView(5); + return; + } + if (monitor) + { + CComPtr pMonitorService; + IUnknown_QueryService(pImmersiveShell,SID_IImmersiveMonitorService,IID_IImmersiveMonitorService,(void**)&pMonitorService); + if (pMonitorService) + pMonitorService->GetFromHandle(monitor,&pMonitor); + } + { + CComPtr pLauncher; + IUnknown_QueryService(pImmersiveShell,SID_ImmersiveLauncher,IID_IImmersiveLauncher81,(void**)&pLauncher); + if (pLauncher) + { + if (pMonitor) + pLauncher->ConnectToMonitor(pMonitor); + HRESULT hr=pLauncher->ShowStartView(GetWinVersion()>=WIN_VER_WIN10?11:5,0); + return; + } + } + { + CComPtr pLauncher; + IUnknown_QueryService(pImmersiveShell,SID_ImmersiveLauncher,IID_IImmersiveLauncher10RS,(void**)&pLauncher); + if (pLauncher) + { + if (pMonitor) + pLauncher->ConnectToMonitor(pMonitor); + HRESULT hr=pLauncher->ShowStartView(GetWinVersion()>=WIN_VER_WIN10?11:5,0); + return; + } + } + } + else if (g_AppManagerThread) + PostThreadMessage(g_AppManagerThread,g_StartMenuMsg,MSG_SHIFTWIN,(LPARAM)monitor); +} + +// WH_GETMESSAGE hook for the Progman window +static LRESULT CALLBACK HookProgManThread( int code, WPARAM wParam, LPARAM lParam ) +{ + if (code==HC_ACTION && wParam) + { + MSG *msg=(MSG*)lParam; + if (msg->message==WM_SYSCOMMAND && (msg->wParam&0xFFF0)==SC_TASKLIST) + { + if (GetWinVersion()message=WM_NULL; + // Win button pressed + if (msg->lParam=='WSMK' || msg->lParam=='WSMM' || msg->lParam=='WSMH') + { + if ((g_AppManagerThread || GetWinVersion()>=WIN_VER_WIN10) && (msg->lParam=='WSMM' || msg->lParam=='WSMH' || (g_TaskbarInfos.size()>1 && GetSettingBool(L"OpenMouseMonitor")))) + { + if (!WindowsMenuOpened()) + { + HMONITOR monitor=msg->lParam=='WSMH'?g_WSMHMonitor:MonitorFromPoint(CPoint(GetMessagePos()),MONITOR_DEFAULTTONULL); + OpenStartScreen(monitor); + msg->message=WM_NULL; + } + } + } + else if (msg->lParam=='CSM') + { + msg->message=WM_NULL; + PostMessage(g_TaskBar,g_StartMenuMsg,MSG_TOGGLE,0); + } + else + { + FindTaskBar(); + int control=GetSettingInt(L"WinKey"); + if (control==OPEN_BOTH) + { + if (GetWinVersion()>=WIN_VER_WIN10) + control=GetWin10TabletMode()?OPEN_WINDOWS:OPEN_CLASSIC; + else + control=GetMetroMode(MonitorFromPoint(CPoint(GetMessagePos()),MONITOR_DEFAULTTONEAREST))?OPEN_WINDOWS:OPEN_CLASSIC; + } + if (control==OPEN_DESKTOP) + { + TMetroMode metro=GetMetroMode(MonitorFromPoint(CPoint(GetMessagePos()),MONITOR_DEFAULTTONEAREST)); + if (metro==METRO_NONE) + control=OPEN_CLASSIC; + else if (metro==METRO_APP) + control=OPEN_WINDOWS; + else + { + msg->message=WM_NULL; + SetForegroundWindow(GetDefaultTaskbarInfo()->taskBar); + } + } + + if (control==OPEN_WINDOWS) + { + FindWindowsMenu(); + if (g_TopWin7Menu && WindowsMenuOpened()) + { + const TaskbarInfo *taskBar=GetDefaultTaskbarInfo(); + SetForegroundWindow(taskBar->startButton?taskBar->startButton:taskBar->taskBar); + msg->message=WM_NULL; + } + else if (GetWinVersion()>=WIN_VER_WIN8 && g_TaskbarInfos.size()>1 && GetSettingBool(L"OpenMouseMonitor") && !WindowsMenuOpened()) + { + HMONITOR monitor=MonitorFromPoint(CPoint(GetMessagePos()),MONITOR_DEFAULTTONULL); + OpenStartScreen(monitor); + msg->message=WM_NULL; + } + else + { + PostMessage(g_TaskBar,g_StartMenuMsg,MSG_NOP,0); + } + } + else + { + msg->message=WM_NULL; + if (control==OPEN_CLASSIC) + PostMessage(g_TaskBar,g_StartMenuMsg,MSG_TOGGLE,0); + } + } + } + if ((msg->message==WM_MOUSEMOVE || msg->message==WM_LBUTTONDOWN) && GetWinVersion()>=WIN_VER_WIN8 && HIWORD(msg->lParam)<10 && GetSettingInt(L"DisableHotCorner")==2) + { + if (msg->hwnd!=g_TopDesktopBar || !g_TopDesktopBar || !IsWindow(g_TopDesktopBar)) + { + wchar_t name[100]; + if (!GetClassName(msg->hwnd,name,_countof(name)) || _wcsicmp(name,L"WorkerW")!=0) + return CallNextHookEx(NULL,code,wParam,lParam); + HWND parent=GetParent(msg->hwnd); + if (parent!=g_ProgWin && !FindWindowEx(parent,NULL,L"SHELLDLL_DefView",NULL)) + return CallNextHookEx(NULL,code,wParam,lParam); + g_EdgeWindows.erase(g_TopDesktopBar); + g_TopDesktopBar=msg->hwnd; + } + g_EdgeWindows.insert(g_TopDesktopBar); + ShowWindow(g_TopDesktopBar,SW_HIDE); + msg->message=WM_NULL; + } + } + return CallNextHookEx(NULL,code,wParam,lParam); +} + +// WH_GETMESSAGE hook for the taskbar thread +static LRESULT CALLBACK HookDesktopThread( int code, WPARAM wParam, LPARAM lParam ) +{ + if (code==HC_ACTION && wParam && !g_bInMenu) + { + MSG *msg=(MSG*)lParam; + FindTaskBar(); + if (IsSettingsMessage(msg)) + { + msg->message=WM_NULL; + return 0; + } +if (!g_bTrimHooks) +{ + if (((msg->message>=WM_MOUSEFIRST && msg->message<=WM_MOUSELAST) || msg->message==WM_MOUSEHOVER || msg->message==WM_MOUSELEAVE) && GetWinVersion()<=WIN_VER_WIN7 && CMenuContainer::ProcessMouseMessage(msg->hwnd,msg->message,msg->wParam,msg->lParam)) + { + msg->message=WM_NULL; + return 0; + } +} + if (msg->message==g_StartMenuMsg && msg->hwnd==g_TaskBar) + { + msg->message=WM_NULL; + static bool bProcessing; // prevent reentry + if (!bProcessing) + { + FindWindowsMenu(); + bProcessing=true; + if (msg->wParam==MSG_TOGGLE || (msg->wParam==MSG_OPEN && !CMenuContainer::IsMenuOpened())) + { + const TaskbarInfo *taskBar=GetDefaultTaskbarInfo(); + ToggleStartMenu(taskBar->taskbarId,true); + } + else if (msg->wParam==MSG_TOGGLENEW) + { + PostMessage(g_ProgWin,WM_SYSCOMMAND,SC_TASKLIST,'WSMK'); + } + else if (msg->wParam==MSG_SETTINGS) + { + if (GetSettingBool(L"EnableSettings")) + EditSettings(false,0); + } + else if (msg->wParam==MSG_SHIFTWIN) + { + const TaskbarInfo *taskBar=GetDefaultTaskbarInfo(); + int control=GetSettingInt(L"ShiftWin"); + if (control==OPEN_BOTH) + { + if (GetWinVersion()>=WIN_VER_WIN10) + control=GetWin10TabletMode()?OPEN_WINDOWS:OPEN_CLASSIC; + else + control=GetMetroMode(MonitorFromPoint(CPoint(GetMessagePos()),MONITOR_DEFAULTTONEAREST))?OPEN_WINDOWS:OPEN_CLASSIC; + } + if (control==OPEN_CLASSIC) + ToggleStartMenu(taskBar->taskbarId,true); + else if (control==OPEN_WINDOWS) + PostMessage(g_ProgWin,WM_SYSCOMMAND,SC_TASKLIST,'WSMK'); + else if (control==OPEN_CORTANA) + OpenCortana(); + } + else if (msg->wParam==MSG_DRAG || msg->wParam==MSG_SHIFTDRAG) + { + const TaskbarInfo *taskBar=GetTaskbarInfo((int)msg->lParam); + if (taskBar) + { + int control=GetSettingInt((msg->wParam==MSG_DRAG)?L"MouseClick":L"ShiftClick"); + if (control==OPEN_BOTH && GetWinVersion()>=WIN_VER_WIN10) + control=GetWin10TabletMode()?OPEN_WINDOWS:OPEN_CLASSIC; + if (control==OPEN_CLASSIC || (control==OPEN_WINDOWS && GetWinVersion()>=WIN_VER_WIN8)) + ToggleStartMenu(taskBar->taskbarId,true); + else if (control==OPEN_WINDOWS) + PostMessage(g_ProgWin,WM_SYSCOMMAND,SC_TASKLIST,'WSMM'); + } + } + else if (msg->wParam==MSG_EXIT && CMenuContainer::CanShowMenu()) + { + LRESULT res=CallNextHookEx(NULL,code,wParam,lParam); + CleanStartMenuDLL(); + return res; // we should exit as quickly as possible now. the DLL is about to be unloaded + } + else if (msg->wParam==MSG_HOTKEYS) + { + EnableHotkeys((THotkeys)msg->lParam); + } + else if (msg->wParam==MSG_NEWTASKBAR) + { + HWND child=(HWND)msg->lParam; + if (IsWindow(child)) + { + wchar_t className[100]; + GetClassName(child,className,_countof(className)); + if (_wcsicmp(className,L"Shell_SecondaryTrayWnd")==0) + HandleSecondaryTaskbar((HWND)msg->lParam); + else if (_wcsicmp(className,L"ToolbarWindow32")==0) + { + HWND taskbar=GetAncestor(child,GA_ROOT); + TaskbarInfo *info=FindTaskBarInfoBar(taskbar); + if (info && !info->HasPart(child) && GetParent(child)==info->rebar) + { + SetWindowSubclass(child,SubclassTaskbarPartProc,'CLSH',info->taskbarId); + info->taskbarParts.push_back(child); + } + } + else if (_wcsicmp(className,L"TrayClockWClass")==0 || _wcsicmp(className,L"ClockButton")==0) + { + HWND taskbar=GetAncestor(child,GA_ROOT); + TaskbarInfo *info=FindTaskBarInfoBar(taskbar); + if (info && !info->HasPart(child)) + { + SetWindowSubclass(child,SubclassTaskbarPartProc,'CLSH',info->taskbarId); + info->taskbarParts.push_back(child); + } + } + } + } + else if (msg->wParam==MSG_REDRAWTASKBAR) + { + if (msg->lParam) + InvalidateRect((HWND)msg->lParam,NULL,TRUE); + else + RedrawTaskbars(); + } + else if (msg->wParam==MSG_RELOADSETTINGS) + { + LoadSettings(); + UpdateTaskBars(TASKBAR_RECREATE_BUTTONS); + UpdateTaskBars(TASKBAR_UPDATE_TEXTURE); + ResetHotCorners(); + RedrawTaskbars(); + } + bProcessing=false; + } + } +if (!g_bTrimHooks) +{ + if (msg->message==WM_HOTKEY && msg->hwnd==g_TaskBar) + { + if (msg->wParam==g_HotkeyShiftID) + PostMessage(g_TaskBar,g_StartMenuMsg,MSG_SHIFTWIN,0); + else if (msg->wParam==g_HotkeyCSMID) + { + msg->message=WM_NULL; + const TaskbarInfo *taskBar=GetDefaultTaskbarInfo(); + if (taskBar->startButton) + SetForegroundWindow(taskBar->startButton); + ToggleStartMenu(taskBar->taskbarId,true); + } + else if (msg->wParam==g_HotkeyWSMID) + PostMessage(g_ProgWin,WM_SYSCOMMAND,SC_TASKLIST,'WSMK'); + } + + if (msg->message==WM_KEYDOWN && msg->hwnd==g_TaskBar && (msg->wParam==VK_SPACE || msg->wParam==VK_RETURN)) + { + GUITHREADINFO info={sizeof(info)}; + if (!GetGUIThreadInfo(GetCurrentThreadId(),&info) || !(info.flags&GUI_INMENUMODE)) + { + FindWindowsMenu(); + int control=GetSettingInt(L"WinKey"); + if (control==OPEN_BOTH) + { + if (GetWinVersion()>=WIN_VER_WIN10) + control=GetWin10TabletMode()?OPEN_WINDOWS:OPEN_CLASSIC; + else + control=GetMetroMode(MonitorFromWindow(g_TaskBar,MONITOR_DEFAULTTONEAREST))?OPEN_WINDOWS:OPEN_CLASSIC; + } + if (control==OPEN_CLASSIC) + { + msg->message=WM_NULL; + const TaskbarInfo *taskBar=FindTaskBarInfoBar(g_TaskBar); + if (taskBar->startButton) + SetForegroundWindow(taskBar->startButton); + ToggleStartMenu(taskBar->taskbarId,true); + } + } + } + + if (msg->message==WM_KEYDOWN && msg->wParam==VK_TAB && CMenuContainer::IsMenuWindow(msg->hwnd)) + { + // the taskbar steals the Tab key. we need to forward it to the menu instead + SendMessage(msg->hwnd,msg->message,msg->wParam,msg->lParam); + msg->message=WM_NULL; + } + + if (msg->message==WM_SYSKEYDOWN && msg->wParam==VK_RETURN && CMenuContainer::IsMenuWindow(msg->hwnd)) + { + // the taskbar steals the Alt+Enter key. we need to forward it to the menu instead + SendMessage(msg->hwnd,msg->message,msg->wParam,msg->lParam); + msg->message=WM_NULL; + } +} + bool bClick=(msg->message==WM_LBUTTONDOWN || msg->message==WM_LBUTTONDBLCLK || msg->message==WM_MBUTTONDOWN || msg->message==WM_MBUTTONDBLCLK); + bool bNcClick=(msg->message==WM_NCLBUTTONDOWN || msg->message==WM_NCLBUTTONDBLCLK || msg->message==WM_NCMBUTTONDOWN || msg->message==WM_NCMBUTTONDBLCLK); + bool bMiddle=(msg->message==WM_NCMBUTTONDOWN || msg->message==WM_MBUTTONDOWN || msg->message==WM_NCMBUTTONDBLCLK || msg->message==WM_MBUTTONDBLCLK); + if (bClick || bNcClick) + { + const TaskbarInfo *taskBar=NULL; + if (bClick) + taskBar=FindTaskBarInfoButton(msg->hwnd); // click on start button + if (!taskBar) + { + taskBar=FindTaskBarInfoBar(msg->hwnd); // click on taskbar + if (taskBar && !PointAroundStartButton(taskBar->taskbarId)) + taskBar=NULL; + } + if (taskBar) + { + if (msg->message==WM_LBUTTONDOWN && GetWinVersion()==WIN_VER_WIN7 && msg->hwnd==taskBar->startButton) + { + // on Win7 ignore the click if the mouse is not over the start button (clicks on the context menu are sent to the start button) + CPoint pt(GetMessagePos()); + if (WindowFromPoint(pt)!=msg->hwnd) + { + return CallNextHookEx(NULL,code,wParam,lParam); + } + } + // left or middle click on start button + FindWindowsMenu(); + const wchar_t *name; + if (bMiddle) + name=L"MiddleClick"; + else if (GetKeyState(VK_SHIFT)<0) + name=L"ShiftClick"; + else + name=L"MouseClick"; + + int control=GetSettingInt(name); + if (control==OPEN_BOTH && GetWinVersion()>=WIN_VER_WIN10) + control=GetWin10TabletMode()?OPEN_WINDOWS:OPEN_CLASSIC; + if (control==OPEN_CLASSIC) + { + // click on the start button - toggle the menu + DWORD keyboard; + SystemParametersInfo(SPI_GETKEYBOARDCUES,NULL,&keyboard,0); + ToggleStartMenu(taskBar->taskbarId,keyboard!=0); + } + else if (control==OPEN_WINDOWS) + PostMessage(g_ProgWin,WM_SYSCOMMAND,SC_TASKLIST,'WSMM'); + else if (control==OPEN_CORTANA) + OpenCortana(); + msg->message=WM_NULL; + } + } + + if (msg->message==WM_LBUTTONUP) + { + // ignore button up on the win81 start button + const TaskbarInfo *taskBar=FindTaskBarInfoButton(msg->hwnd); + if (taskBar && taskBar->oldButton==msg->hwnd) + msg->message=WM_NULL; + } +if (!g_bTrimHooks) +{ + if (msg->message==WM_TIMER && FindTaskBarInfoBar(msg->hwnd) && CMenuContainer::IgnoreTaskbarTimers()) + { + // stop the taskbar timer messages. prevents the auto-hide taskbar from closing + msg->message=WM_NULL; + } + + if (msg->message==WM_MOUSEMOVE && g_ProgramsButton && msg->hwnd==g_ProgramsButton && GetSettingBool(L"CascadeAll") && !(msg->wParam&MK_SHIFT)) + { + DWORD pos=GetMessagePos(); + if (pos!=g_LastHoverPos && !g_bAllProgramsTimer) + { + g_bAllProgramsTimer=true; + bool bDef; + DWORD time=GetSettingInt(L"AllProgramsDelay",bDef); + if (bDef) + SystemParametersInfo(SPI_GETMENUSHOWDELAY,NULL,&time,0); + SetTimer(g_ProgramsButton,'CLSM',time,NULL); + } + g_LastHoverPos=pos; + } + if (msg->message==WM_TIMER && msg->wParam=='CLSM' && g_ProgramsButton && msg->hwnd==g_ProgramsButton) + { + g_bAllProgramsTimer=false; + KillTimer(g_ProgramsButton,'CLSM'); + DWORD pos=GetMessagePos(); + if (pos==g_LastHoverPos) + PostMessage(g_AllPrograms,WM_COMMAND,IDOK,(LPARAM)g_ProgramsButton); + msg->message=WM_NULL; + } + if (msg->message==WM_MOUSELEAVE && g_ProgramsButton && msg->hwnd==g_ProgramsButton) + { + g_bAllProgramsTimer=false; + KillTimer(g_ProgramsButton,'CLSM'); + } + + // handle hover + if (msg->message==WM_MOUSEMOVE) + { + TaskbarInfo *taskBar=FindTaskBarInfoButton(msg->hwnd); + if (taskBar && !CMenuContainer::IsMenuOpened() && !WindowsMenuOpened()) + { + if (GetSettingInt(L"Hover") && !taskBar->bTimer) + { + taskBar->bTimer=true; + int time=GetSettingInt(L"StartHoverDelay"); + SetTimer(msg->hwnd,'CLSM',time,NULL); + } + if (msg->hwnd==taskBar->oldButton) + { + APPBARDATA appbar={sizeof(appbar)}; + if (SHAppBarMessage(ABM_GETSTATE,&appbar)&ABS_AUTOHIDE) + SendMessage(taskBar->taskBar,WM_NCHITTEST,0,GetMessagePos()); + } + } + } + if (msg->message==WM_MOUSELEAVE) + { + TaskbarInfo *taskBar=FindTaskBarInfoButton(msg->hwnd); + if (taskBar) + { + taskBar->bTimer=false; + KillTimer(msg->hwnd,'CLSM'); + if (taskBar->oldButton==msg->hwnd) + { + RECT rc; + GetWindowRect(taskBar->oldButton,&rc); + CPoint pt(GetMessagePos()); + if (PtInRect(&rc,pt)) + { + wchar_t className[256]={0}; + GetClassName(WindowFromPoint(pt),className,_countof(className)); + if (wcscmp(className,L"ImmersiveSwitchList")==0 || wcscmp(className,L"EdgeUiInputWndClass")==0) + { + msg->message=WM_NULL; + TRACKMOUSEEVENT track={sizeof(track),TME_LEAVE,msg->hwnd,0}; + TrackMouseEvent(&track); + } + } + } + } + } + if ((msg->message==WM_NCMOUSEMOVE || msg->message==WM_NCMOUSELEAVE) && (msg->wParam==HTCAPTION || !IsAppThemed()) && GetSettingInt(L"Hover")) // HACK: in Classic mode the start menu can show up even if wParam is not HTCAPTION (most likely a bug in Windows) + { + TaskbarInfo *taskBar=FindTaskBarInfoBar(msg->hwnd); + if (taskBar) + { + if (!CMenuContainer::IsMenuOpened() && !WindowsMenuOpened() && PointAroundStartButton(taskBar->taskbarId)) + { + if (!taskBar->bTimer) + { + taskBar->bTimer=true; + int time=GetSettingInt(L"StartHoverDelay"); + SetTimer(taskBar->startButton,'CLSM',time,NULL); + } + } + else + { + if (taskBar->bTimer) + { + taskBar->bTimer=false; + KillTimer(taskBar->startButton,'CLSM'); + } + } + } + } + if (msg->message==WM_TIMER && msg->wParam=='CLSM' && CMenuContainer::CanShowMenu()) + { + TaskbarInfo *taskBar=FindTaskBarInfoButton(msg->hwnd); + if (taskBar) + { + KillTimer(msg->hwnd,'CLSM'); + msg->message=WM_NULL; + if (taskBar->bTimer && !CMenuContainer::IsMenuOpened() && !WindowsMenuOpened()) + { + CPoint pt(GetMessagePos()); + if (WindowFromPoint(pt)==msg->hwnd || PointAroundStartButton(taskBar->taskbarId)) + { + int control=GetSettingInt(L"Hover"); + if (control==OPEN_CLASSIC) + { + PostMessage(g_ProgWin,WM_SYSCOMMAND,SC_TASKLIST,'CSM'); + } + else if (control==OPEN_WINDOWS) + { + FindWindowsMenu(); + PostMessage(g_ProgWin,WM_SYSCOMMAND,SC_TASKLIST,'WSMM'); + } + } + } + taskBar->bTimer=false; + } + } +} + // context menu + if (msg->message==WM_NCRBUTTONUP || msg->message==WM_RBUTTONUP) + { + CPoint pt0(GetMessagePos()); + TaskbarInfo *taskBar=FindTaskBarInfoButton(msg->hwnd); + DWORD winVer=GetWinVersion(); + if (!taskBar && winVer>=WIN_VER_WIN8) + { + taskBar=FindTaskBarInfoBar(msg->hwnd); + if (taskBar && !PointAroundStartButton(taskBar->taskbarId)) + taskBar=NULL; + } + if (taskBar) + { + if (msg->message==WM_RBUTTONUP && msg->hwnd==taskBar->startButton && msg->lParam==MAKELPARAM(-1,-1)) + { + RECT rc; + GetWindowRect(msg->hwnd,&rc); + pt0.x=(rc.left+rc.right)/2; + pt0.y=(rc.top+rc.bottom)/2; + } + bool bShowCSMenu=false, bShowWinX=false, bShowWin7=false; + if (msg->hwnd==taskBar->taskBar && taskBar->bReplaceButton) + bShowWinX=true; + else + { + bShowCSMenu=(GetSettingBool(L"ShiftRight")==(GetKeyState(VK_SHIFT)<0)); + bShowWinX=winVer>=WIN_VER_WIN8 && !bShowCSMenu; + } + bShowWin7=!bShowCSMenu && g_WinStartButton && msg->hwnd!=g_WinStartButton; + + if (bShowCSMenu || bShowWinX || bShowWin7) + { + msg->message=WM_NULL; + if (CMenuContainer::IsMenuOpened()) + CMenuContainer::CloseStartMenu(); + } + if (bShowCSMenu) + { + // additional commands for the context menu + enum + { + CMD_SETTINGS=1, + CMD_HELP, + CMD_EXIT, + CMD_OPEN, + CMD_OPEN_ALL, + CMD_EXPLORER, + }; + + // right-click on the start button - open the context menu (Settings, Help, Exit) + HMENU menu=CreatePopupMenu(); + CString title=LoadStringEx(IDS_MENU_TITLE); + if (!title.IsEmpty()) + { + AppendMenu(menu,MF_STRING,0,title); + EnableMenuItem(menu,0,MF_BYPOSITION|MF_DISABLED); + SetMenuDefaultItem(menu,0,TRUE); + AppendMenu(menu,MF_SEPARATOR,0,0); + } + int count0=GetMenuItemCount(menu); + if (GetSettingBool(L"EnableExplorer")) + { + if (!GetSettingString(L"ExplorerPath").IsEmpty()) + AppendMenu(menu,MF_STRING,CMD_EXPLORER,FindTranslation(L"Menu.Explorer",L"Windows Explorer")); + AppendMenu(menu,MF_STRING,CMD_OPEN,FindTranslation(L"Menu.Open",L"&Open")); + if (!SHRestricted(REST_NOCOMMONGROUPS)) + AppendMenu(menu,MF_STRING,CMD_OPEN_ALL,FindTranslation(L"Menu.OpenAll",L"O&pen All Users")); + AppendMenu(menu,MF_SEPARATOR,0,0); + } + if (GetSettingBool(L"EnableSettings")) + AppendMenu(menu,MF_STRING,CMD_SETTINGS,FindTranslation(L"Menu.MenuSettings",L"Settings")); + if (HasHelp()) + AppendMenu(menu,MF_STRING,CMD_HELP,FindTranslation(L"Menu.MenuHelp",L"Help")); + if (GetSettingBool(L"EnableExit")) + { + AppendMenu(menu,MF_STRING,CMD_EXIT,FindTranslation(L"Menu.MenuExit",L"Exit")); + if (!CMenuContainer::CanShowMenu()) + EnableMenuItem(menu,CMD_EXIT,MF_BYCOMMAND|MF_DISABLED); + } + if (GetMenuItemCount(menu)>count0) + { + MENUITEMINFO mii={sizeof(mii)}; + mii.fMask=MIIM_BITMAP; + mii.hbmpItem=HBMMENU_POPUP_CLOSE; + SetMenuItemInfo(menu,CMD_EXIT,FALSE,&mii); + MENUINFO info={sizeof(info),MIM_STYLE,MNS_CHECKORBMP}; + SetMenuInfo(menu,&info); + g_bInMenu=true; + SetForegroundWindow(msg->hwnd); + int res=TrackPopupMenu(menu,TPM_RIGHTBUTTON|TPM_RETURNCMD|(IsLanguageRTL()?TPM_LAYOUTRTL:0),pt0.x,pt0.y,0,msg->hwnd,NULL); + DestroyMenu(menu); + g_bInMenu=false; + if (res==CMD_SETTINGS) + { + EditSettings(false,0); + } + if (res==CMD_HELP) + { + ShowHelp(); + return TRUE; + } + if (res==CMD_EXIT) + { + LRESULT res=CallNextHookEx(NULL,code,wParam,lParam); + CleanStartMenuDLL(); + return res; // we should exit as quickly as possible now. the DLL is about to be unloaded + } + if (res==CMD_OPEN || res==CMD_OPEN_ALL) + { + CComString pPath; + if (SUCCEEDED(ShGetKnownFolderPath((res==CMD_OPEN)?FOLDERID_StartMenu:FOLDERID_CommonStartMenu,&pPath))) + ShellExecute(NULL,L"open",pPath,NULL,NULL,SW_SHOWNORMAL); + } + if (res==CMD_EXPLORER) + { + CString path=GetSettingString(L"ExplorerPath"); + ITEMIDLIST blank={0}; + SHELLEXECUTEINFO execute={sizeof(execute)}; + execute.lpVerb=L"open"; + execute.lpFile=path; + execute.nShow=SW_SHOWNORMAL; + if (_wcsicmp(path,L"computer")==0) + execute.lpFile=L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"; + else if (_wcsicmp(path,L"libraries")==0) + execute.lpFile=L"::{031E4825-7B94-4DC3-B131-E946B44C8DD5}"; + else if (_wcsicmp(path,L"desktop")==0) + { + execute.fMask=SEE_MASK_IDLIST; + execute.lpIDList=␣ + execute.lpFile=NULL; + } + else + { + execute.fMask=SEE_MASK_DOENVSUBST; + } + ShellExecuteEx(&execute); + } + } + } + else if (bShowWinX) + { + ShowWinX(); + } + else if (bShowWin7) + { + CPoint pt(GetMessagePos()); + ScreenToClient(g_WinStartButton,&pt); + PostMessage(g_WinStartButton,WM_RBUTTONUP,wParam,MAKELONG(pt.x,pt.y)); + } + } + } + + } + return CallNextHookEx(NULL,code,wParam,lParam); +} + +HBITMAP GetStartScreenIcon( int size ) +{ + // for sizes >=64, use image directly + // for sizes>=32, get 64x64 and scale down + // for sizes<32 use the system background color + StartScreenThumbInfo info={{size<64?64:size}}; + info.size.cy=info.size.cx; + if (size>=32 && g_AppManagerThread && GetWinVersion()==WIN_VER_WIN8) + { + info.event=CreateEvent(NULL,TRUE,FALSE,NULL); + PostThreadMessage(g_AppManagerThread,g_StartMenuMsg,MSG_METROTHUMBNAIL,(LPARAM)&info); + WaitForSingleObject(info.event,100); // if it takes more than 100ms, screw it + CloseHandle(info.event); + } + info.size.cy=info.size.cx*3/4; + + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=bi.bmiHeader.biHeight=size; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + + HDC hDst=CreateCompatibleDC(NULL); + unsigned int *bits; + HBITMAP bitmap=CreateDIBSection(hDst,&bi,DIB_RGB_COLORS,(void**)&bits,NULL,0); + HGDIOBJ bmp0=SelectObject(hDst,bitmap); + RECT rc={0,size/8,size,size*7/8}; + + if (info.bitmap) + { + HDC hSrc=CreateCompatibleDC(hDst); + HGDIOBJ bmp02=SelectObject(hSrc,info.bitmap); + SetStretchBltMode(hDst,HALFTONE); + StretchBlt(hDst,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,hSrc,0,0,info.size.cx,info.size.cy,SRCCOPY); + SelectObject(hSrc,bmp02); + DeleteDC(hSrc); + DeleteObject(info.bitmap); + } + else + { + typedef int (WINAPI *TGetImmersiveUserColorSetPreference)(bool bForceCheckRegistry, bool bSkipCheckOnFail); + typedef DWORD (WINAPI *TGetImmersiveColorFromColorSetEx)(UINT dwImmersiveColorSet, UINT dwImmersiveColorType, bool bIgnoreHighContrast, UINT dwHighContrastCacheMode); + typedef int (WINAPI *TGetImmersiveColorTypeFromName)(const wchar_t *name); + COLORREF color=0; + HMODULE hUxTheme=GetModuleHandle(L"uxtheme.dll"); + if (hUxTheme) + { + TGetImmersiveUserColorSetPreference GetImmersiveUserColorSetPreference=(TGetImmersiveUserColorSetPreference)GetProcAddress(hUxTheme,MAKEINTRESOURCEA(98)); + TGetImmersiveColorFromColorSetEx GetImmersiveColorFromColorSetEx=(TGetImmersiveColorFromColorSetEx)GetProcAddress(hUxTheme,MAKEINTRESOURCEA(95)); + TGetImmersiveColorTypeFromName GetImmersiveColorTypeFromName=(TGetImmersiveColorTypeFromName)GetProcAddress(hUxTheme,MAKEINTRESOURCEA(96)); + if (GetImmersiveUserColorSetPreference && GetImmersiveColorFromColorSetEx && GetImmersiveColorTypeFromName) + { + int type=GetImmersiveColorTypeFromName(L"ImmersiveStartBackground"); + int set=GetImmersiveUserColorSetPreference(false,false); + color=GetImmersiveColorFromColorSetEx(set,type,false,0)&0xFFFFFF; + } + } + SetDCBrushColor(hDst,color); + FillRect(hDst,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + HICON hIcon=(HICON)LoadImage(g_Instance,MAKEINTRESOURCE(GetWinVersion()>=WIN_VER_WIN10?IDI_START10:IDI_START),IMAGE_ICON,size,size,LR_DEFAULTCOLOR); + DrawIconEx(hDst,0,0,hIcon,size,size,0,NULL,DI_NORMAL); + DestroyIcon(hIcon); + } + SelectObject(hDst,bmp0); + DeleteDC(hDst); + + int i=0; + int n=size*rc.top; + for (;i + +#ifdef CLASSICSTARTMENUDLL_EXPORTS +#define STARTMENUAPI __declspec(dllexport) +#else +#define STARTMENUAPI __declspec(dllimport) +#endif + +// Find the taskbar window for the given process +STARTMENUAPI HWND FindTaskBar( DWORD process ); + +// WH_GETMESSAGE hook for the explorer's GUI thread. The start menu exe uses this hook to inject code into the explorer process +STARTMENUAPI LRESULT CALLBACK HookInject( int code, WPARAM wParam, LPARAM lParam ); + +// Toggle the start menu. bKeyboard - set to true to show the keyboard cues +STARTMENUAPI HWND ToggleStartMenu( int taskbarId, bool bKeyboard ); + +STARTMENUAPI void InitManagers( bool bNohook ); +STARTMENUAPI void CloseManagers( bool bNohook ); +STARTMENUAPI void WaitDllInitThread( void ); + +STARTMENUAPI bool DllGetSettingBool( const wchar_t *name ); +STARTMENUAPI int DllGetSettingInt( const wchar_t *name ); +STARTMENUAPI void DllUpdateSettings( void ); +STARTMENUAPI CString DllLoadStringEx( int stringID ); +STARTMENUAPI void DllLogToFile( const wchar_t *location, const wchar_t *message, ... ); + +#ifndef _WIN64 +enum TSettingsComponent; +STARTMENUAPI bool DllSaveAdmx( TSettingsComponent component, const char *admxFile, const char *admlFile, const char *docFile ); +STARTMENUAPI void DllLoadTranslationResources( HINSTANCE hLngInstance, int *pDialogs ); +#endif +STARTMENUAPI bool DllExecuteNamedCommand( const wchar_t *command ); + +#ifdef TRACK_GDI_RESOURCES +STARTMENUAPI void DllDumpResourceLeaks( void ); +#endif + +// Enable or disable the tooltip for the start button +void EnableStartTooltip( bool bEnable ); + +struct TaskbarInfo +{ + TaskbarInfo( void ) { taskbarId=pointerId=0; taskBar=startButton=oldButton=rebar=taskList=chevron=desktop=NULL; startButtonSize.cx=startButtonSize.cy=0; oldButtonSize.cx=oldButtonSize.cy=0; bTimer=bCustomLook=bReplaceButton=bHideButton=bRecreatingButton=bThemeChanging=false; } + int taskbarId; + HWND taskBar; + HWND startButton; // either own start button or the win7 start button (depending on bReplaceButton) + HWND oldButton; // win81 start button (child of taskBar) + HWND rebar; + HWND taskList; + HWND chevron; + HWND desktop; + SIZE startButtonSize; + SIZE oldButtonSize; + int pointerId; + bool bTimer; + bool bCustomLook; + bool bReplaceButton; + bool bHideButton; + bool bRecreatingButton; + bool bThemeChanging; + std::vector trayButtons; // ordered by Z order (for win10) + std::vector taskbarParts; + CComPtr pOriginalTarget; + + bool HasPart( HWND part ) const; +}; + +TaskbarInfo *GetTaskbarInfo( int taskbarId ); +UINT GetTaskbarPosition( HWND taskBar, MONITORINFO *pInfo, HMONITOR *pMonitor, RECT *pRc ); + +extern HWND STARTMENUAPI g_TaskBar, g_OwnerWindow; +extern HWND g_TopWin7Menu, g_AllPrograms, g_ProgramsButton, g_UserPic; // from the Windows menu +extern HWND g_ProgWin; +extern HMONITOR g_WSMHMonitor; +extern int g_CurrentCSMTaskbar, g_CurrentWSMTaskbar; + +enum TMenuMsgParam // wParam for the ClassicStartMenu.StartMenuMsg message +{ + MSG_TOGGLE, // toggles the classic start menu + MSG_TOGGLENEW, // toggles the Windows start menu + MSG_OPEN, // opens the classic start menu + MSG_SETTINGS, // show Settings + MSG_SHIFTWIN, // Shift+Win was pressed + MSG_DRAG, // an item is dragged on the start button + MSG_SHIFTDRAG, // an item is dragged on the start button (Shift is pressed) + MSG_NOP, // does nothing (basically just finds the Windows menu) + MSG_EXIT, // unhook everything and exit + MSG_HOTKEYS, // updates the hotkeys + MSG_NEWTASKBAR, // new taskbar is created, lParam is the HWND + MSG_WINXMENU, // open the Win+X menu + MSG_METROTHUMBNAIL, // refresh the Metro thumbnail + MSG_REDRAWTASKBAR, // redraw taskbar, lParam is the HWND (NULL for all) + MSG_RELOADSETTINGS, // reloads the settings from the registry + MSG_SETMONITOR, // sets the start screen monitor +}; + +STARTMENUAPI extern enum _MINIDUMP_TYPE MiniDumpType; +STARTMENUAPI LONG _stdcall TopLevelFilter( _EXCEPTION_POINTERS *pExceptionInfo ); + +enum THotkeys +{ + HOTKEYS_NORMAL, + HOTKEYS_SETTINGS, + HOTKEYS_CLEAR, +}; + +// Set the hotkeys and controls for the start menu +void EnableHotkeys( THotkeys enable ); + +bool PointAroundStartButton( int taskbarId, const CPoint &pt=CPoint(GetMessagePos()) ); +void ResetHotCorners( void ); +void RedrawTaskbars( void ); + +enum TUpdateTaskbar +{ + TASKBAR_CLEAR, + TASKBAR_UPDATE, + TASKBAR_UPDATE_TEXTURE, + TASKBAR_RECREATE_BUTTONS, +}; + +void UpdateTaskBars( TUpdateTaskbar update ); +HBITMAP GetStartScreenIcon( int size ); diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartMenuDLL.rc b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartMenuDLL.rc new file mode 100644 index 0000000..9430e4e --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartMenuDLL.rc @@ -0,0 +1,1304 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\0" +END + +3 TEXTINCLUDE +BEGIN + "#include ""..\\..\\ClassicShellLib\\resource.h""\r\n" + "#include ""..\\..\\ClassicShellLib\\ClassicShellLib.rc""\r\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_RENAME DIALOGEX 0, 0, 227, 54 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_TOPMOST +CAPTION "Rename" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "&New name:",IDC_LABEL,7,7,44,14,SS_CENTERIMAGE + EDITTEXT IDC_EDITNAME,56,7,163,14,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,116,33,50,14 + PUSHBUTTON "Cancel",IDCANCEL,170,33,50,14 +END + +IDD_RENAMER DIALOGEX 0, 0, 227, 54 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_TOPMOST | WS_EX_LAYOUTRTL +CAPTION "Rename" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "&New name:",IDC_LABEL,7,7,44,14,SS_CENTERIMAGE + EDITTEXT IDC_EDITNAME,56,7,163,14,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,116,33,50,14 + PUSHBUTTON "Cancel",IDCANCEL,170,33,50,14 +END + +IDD_LOGOFF DIALOGEX 0, 0, 179, 59 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Log Off Windows" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "&Log Off",IDOK,55,38,55,14 + PUSHBUTTON "&No",IDCANCEL,117,38,55,14 + ICON "",IDC_STATICICON1,7,7,20,20 + LTEXT "Are you sure you want to log off?",IDC_PROMPT,35,7,137,20,SS_CENTERIMAGE +END + +IDD_LOGOFFR DIALOGEX 0, 0, 179, 59 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_LAYOUTRTL +CAPTION "Log Off Windows" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "&Log Off",IDOK,55,38,55,14 + PUSHBUTTON "&No",IDCANCEL,117,38,55,14 + ICON "",IDC_STATICICON1,7,7,20,20 + LTEXT "Are you sure you want to log off?",IDC_PROMPT,35,7,137,20,SS_CENTERIMAGE +END + +IDD_SKINSETTINGS DIALOGEX 0, 0, 311, 165 +STYLE DS_SETFONT | DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN | WS_SYSMENU +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + LTEXT "Skin:",IDC_STATICSKIN,7,7,16,12,SS_CENTERIMAGE + COMBOBOX IDC_COMBOSKIN,28,7,141,96,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "About this skin",IDC_ABOUT,176,7,60,14 + PUSHBUTTON "Reset skin",IDC_BUTTONRESET,244,7,60,14 + LTEXT "The selected skin is not compatible with this version of the start menu.",IDC_STATICVER,7,24,229,22 + CONTROL "",IDC_SKINOPTIONS,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_INFOTIP | WS_BORDER | WS_HSCROLL | WS_TABSTOP,7,35,297,113 + LTEXT "Skin options:",IDC_STATICOPT,7,24,49,8,SS_CENTERIMAGE + LTEXT "This skin is used by the cascading All Programs menu in the Windows start menu",IDC_STATICALLPROGS,7,150,297,8 +END + +IDD_CUSTOMMENU DIALOGEX 0, 0, 249, 236 +STYLE DS_SETFONT | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +CAPTION "Edit Menu Item (%s)" +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + LTEXT "Command:",IDC_STATICCOMMAND,7,7,35,12,SS_CENTERIMAGE + COMBOBOX IDC_COMBOCOMMAND,47,7,180,30,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "...",IDC_BUTTONCOMMAND,228,7,14,12 + LTEXT "Link:",IDC_STATICLINK,7,24,16,12,SS_CENTERIMAGE + COMBOBOX IDC_COMBOLINK,47,24,180,30,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "...",IDC_BUTTONLINK,228,24,14,12 + LTEXT "Label:",IDC_STATICTEXT,7,41,22,12,SS_CENTERIMAGE + EDITTEXT IDC_EDITLABEL,47,41,195,12,ES_AUTOHSCROLL + LTEXT "Tip:",IDC_STATICINFOTIP,7,58,13,12,SS_CENTERIMAGE + EDITTEXT IDC_EDITTIP,47,58,195,12,ES_AUTOHSCROLL + LTEXT "Icon:",IDC_STATICICON,7,74,18,12,SS_CENTERIMAGE + EDITTEXT IDC_EDITICON,47,74,180,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BUTTONICON,228,74,14,12 + ICON "",IDC_ICONN,9,89,20,20 + CONTROL "Sort Z->A",IDC_CHECKSORTZA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,116,48,10 + CONTROL "Sort Z->A (for sub-menus)",IDC_CHECKSORTZAREC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,129,101,10 + CONTROL "Sort once",IDC_CHECKSORTONCE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,142,48,10 + CONTROL "Open up",IDC_CHECKOPENUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,155,44,10 + CONTROL "Open up (for sub-menus)",IDC_CHECKOPENUPREC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,168,97,10 + CONTROL "Insert sub-items as buttons",IDC_CHECKINLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,181,106,10 + CONTROL "Split button item",IDC_CHECKSPLIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,194,65,10 + CONTROL "Don't expand",IDC_CHECKNOEXPAND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,116,59,10 + CONTROL "Multi-column",IDC_CHECKMULTICOLUMN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,129,60,10 + CONTROL "Track recent items",IDC_CHECKTRACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,142,78,10 + CONTROL "Don't track recent items",IDC_CHECKNOTRACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,155,97,10 + CONTROL "Place items first",IDC_CHECKITEMSFIRST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,168,69,10 + CONTROL "Hide extensions",IDC_CHECKNOEXT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,181,72,10 + PUSHBUTTON "Restore Defaults",IDC_BUTTONRESET,7,215,90,14 + DEFPUSHBUTTON "OK",IDOK,135,215,50,14 + PUSHBUTTON "Cancel",IDCANCEL,192,215,50,14 +END + +IDD_STYLESETTINGS DIALOGEX 0, 0, 362, 249 +STYLE DS_SETFONT | DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN | WS_SYSMENU +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + LTEXT "Select the style for the start menu.",IDC_STATICTITLE,7,7,291,10 + CONTROL "Classic style",IDC_RADIO_CLASSIC,"Button",BS_AUTORADIOBUTTON,7,18,52,10 + CONTROL "Classic with two columns",IDC_RADIO_TWO_COLUMNS,"Button",BS_AUTORADIOBUTTON,95,18,93,10 + CONTROL "Windows 7 style",IDC_RADIO_WIN7,"Button",BS_AUTORADIOBUTTON,219,18,65,10 + CONTROL 120,IDC_STATIC_CLASSIC,"Static",SS_BITMAP | SS_NOTIFY | SS_REALSIZEIMAGE,7,28,69,120 + CONTROL 121,IDC_STATIC_TWO_COLUMNS,"Static",SS_BITMAP | SS_NOTIFY | SS_REALSIZEIMAGE,94,28,103,120 + CONTROL 122,IDC_STATIC_WIN7,"Static",SS_BITMAP | SS_NOTIFY | SS_REALSIZEIMAGE,218,28,109,120 + CONTROL "Select skin...",IDC_SKIN_CLASSIC,"SysLink",WS_TABSTOP,11,152,60,8 + CONTROL "Select skin...",IDC_SKIN_CLASSIC2,"SysLink",WS_TABSTOP,98,152,60,8 + CONTROL "Select skin...",IDC_SKIN_WIN7,"SysLink",WS_TABSTOP,222,152,60,8 + CONTROL "",IDC_STATICEDGE,"Static",SS_ETCHEDHORZ,7,165,347,1 + CONTROL "Replace Start button",IDC_CHECKENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,170,77,10 + CONTROL "Advanced button options...",IDC_LINKADVANCED, + "SysLink",WS_TABSTOP,114,170,157,10 + CONTROL "Aero",IDC_RADIOAERO,"Button",BS_AUTORADIOBUTTON,25,185,30,10 + CONTROL "Classic",IDC_RADIOCLASSIC,"Button",BS_AUTORADIOBUTTON,80,185,37,10 + CONTROL "Custom",IDC_RADIOCUSTOM,"Button",BS_AUTORADIOBUTTON,145,185,40,10 + ICON IDI_BTN_CLASSIC,IDC_STATICAERO,30,198,18,17,SS_NOTIFY | SS_REALSIZEIMAGE + CONTROL 124,IDC_STATICCLASSIC,"Static",SS_BITMAP | SS_NOTIFY | SS_REALSIZEIMAGE,85,203,33,13 + ICON "",IDC_STATICCUSTOM,150,198,18,17,SS_NOTIFY + PUSHBUTTON "Pick image...",IDC_BUTTONPICK,188,201,50,14 +END + +IDD_CUSTOMMENU7 DIALOGEX 0, 0, 249, 210 +STYLE DS_SETFONT | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +CAPTION "Edit Menu Item" +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + LTEXT "Command:",IDC_STATICCOMMAND,7,7,35,12,SS_CENTERIMAGE + COMBOBOX IDC_COMBOCOMMAND,47,7,180,30,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "...",IDC_BUTTONCOMMAND,228,7,14,12 + LTEXT "Link:",IDC_STATICLINK,7,24,16,12,SS_CENTERIMAGE + EDITTEXT IDC_EDITLINK2,47,24,180,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BUTTONLINK,228,24,14,12 + LTEXT "Label:",IDC_STATICTEXT,7,41,22,12,SS_CENTERIMAGE + EDITTEXT IDC_EDITLABEL,47,41,195,12,ES_AUTOHSCROLL + LTEXT "Tip:",IDC_STATICINFOTIP,7,58,13,12,SS_CENTERIMAGE + EDITTEXT IDC_EDITTIP,47,58,195,12,ES_AUTOHSCROLL + LTEXT "Icon:",IDC_STATICICON,7,74,18,12,SS_CENTERIMAGE + EDITTEXT IDC_EDITICON,47,74,180,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BUTTONICON,228,74,14,12 + ICON "",IDC_ICONN,9,89,20,20 + CONTROL "Sort Z->A",IDC_CHECKSORTZA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,116,48,10 + CONTROL "Sort Z->A (for sub-menus)",IDC_CHECKSORTZAREC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,129,101,10 + CONTROL "Sort once",IDC_CHECKSORTONCE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,142,48,10 + CONTROL "Open up",IDC_CHECKOPENUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,155,44,10 + CONTROL "Open up (for sub-menus)",IDC_CHECKOPENUPREC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,168,97,10 + CONTROL "Multi-column",IDC_CHECKMULTICOLUMN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,116,60,10 + CONTROL "Track recent items",IDC_CHECKTRACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,129,78,10 + CONTROL "Hide extensions",IDC_CHECKNOEXT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,142,72,10 + PUSHBUTTON "Restore Defaults",IDC_BUTTONRESET,7,189,90,14 + DEFPUSHBUTTON "OK",IDOK,135,189,50,14 + PUSHBUTTON "Cancel",IDCANCEL,192,189,50,14 +END + +IDD_CUSTOMLIST DIALOGEX 0, 0, 365, 183 +STYLE DS_SETFONT | DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN | WS_SYSMENU +FONT 9, "Segoe UI", 400, 0, 0x0 +BEGIN + LTEXT "Current menu items:",IDC_STATIC,7,7,167,8 + LTEXT "Click on each item to change it. Double-click the icon to edit the additional settings. Drag to change order. Right-click for more functions. Use Tab or Shift+Tab to navigate with the keyboard",IDC_STATICHINT,7,151,351,25 + CONTROL "",IDC_LISTITEMS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,16,351,133 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_RENAME, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 220 + TOPMARGIN, 7 + BOTTOMMARGIN, 47 + END + + IDD_RENAMER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 220 + TOPMARGIN, 7 + BOTTOMMARGIN, 47 + END + + IDD_LOGOFF, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 172 + TOPMARGIN, 7 + BOTTOMMARGIN, 52 + END + + IDD_LOGOFFR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 172 + TOPMARGIN, 7 + BOTTOMMARGIN, 52 + END + + IDD_SKINSETTINGS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 304 + TOPMARGIN, 7 + BOTTOMMARGIN, 158 + END + + IDD_CUSTOMMENU, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 242 + TOPMARGIN, 7 + BOTTOMMARGIN, 229 + END + + IDD_STYLESETTINGS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 354 + TOPMARGIN, 7 + BOTTOMMARGIN, 242 + END + + IDD_CUSTOMMENU7, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 242 + TOPMARGIN, 7 + BOTTOMMARGIN, 203 + END + + IDD_CUSTOMLIST, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 358 + TOPMARGIN, 7 + BOTTOMMARGIN, 176 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 4,3,1,0 + PRODUCTVERSION 4,3,1,0 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "IvoSoft" + VALUE "FileDescription", "Classic Start Menu" + VALUE "FileVersion", "4, 3, 1, 0" + VALUE "InternalName", "ClassicStartMenuDLL" + VALUE "LegalCopyright", "Copyright (C) 2009-2016, Ivo Beltchev" + VALUE "OriginalFilename", "ClassicStartMenuDLL.dll" + VALUE "ProductName", "Classic Shell" + VALUE "ProductVersion", "4, 3, 1, 0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APPICON ICON "..\\..\\ClassicShellSetup\\ClassicShell.ico" +IDI_APPSICON ICON "apps.ico" +IDI_BTN_CLASSIC ICON "btn_aero.ico" +IDI_START ICON "start.ico" +IDI_START10 ICON "start10.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// SKIN +// + +1 SKIN "SkinDescription.txt" +2 SKIN "SkinDescription7.txt" + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_ARROWS BITMAP "menu_arrows.bmp" +IDB_ARROWS150 BITMAP "menu_arrows150.bmp" +IDB_SEARCH_ICONS BITMAP "search_icons.bmp" +IDB_STYLE_CLASSIC1 BITMAP "style_classic.bmp" +IDB_STYLE_CLASSIC2 BITMAP "style_vista.bmp" +IDB_STYLE_WIN7 BITMAP "style_7.bmp" +IDB_BTN_CLASSIC BITMAP "btn_classic.bmp" +IDB_STYLE_CLASSIC1150 BITMAP "style_classic150.bmp" +IDB_STYLE_CLASSIC2150 BITMAP "style_vista150.bmp" +IDB_STYLE_WIN7150 BITMAP "style_7150.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// IMAGE +// + +IDB_BUTTON96 IMAGE "button96.png" +IDB_BUTTON120 IMAGE "button120.png" +IDB_BUTTON144 IMAGE "button144.png" +IDB_BUTTON180 IMAGE "button180.png" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_APP_TITLE "Classic Start Menu" + IDS_SETTINGS_TITLE "Settings for Classic Start Menu" + IDS_SETTINGS_TITLE_VER "Settings for Classic Start Menu %d.%d.%d" + IDS_NEW_SETTINGS "You need to restart the menu for the new settings to take effect: Right-click on the start button and select ""Exit"". Then run ClassicStartMenu.exe again. It will read the new settings." + IDS_NO_TEXT "" +END + +STRINGTABLE +BEGIN + IDS_SKIN_ERR_UNKNOWN "Unknown error.\r\n" + IDS_SKIN_ERR_DISABLE "\r\nYou can disable this popup from the settings." + IDS_SKIN_ERR "Skin Error" + IDS_SKIN_WARN "Skin Warning" + IDS_SKIN_ABOUT "About skin %s" + IDS_SKIN_FAIL "Failed to load skin." + IDS_SKIN_ERR_BMPRES "Failed to load bitmap resource with ID=%d.\r\n%s" + IDS_SKIN_ERR_BMPFILE "Failed to load bitmap file %s.\r\n%s" + IDS_SKIN_ERR_MASKRES "Failed to load mask bitmap resource with ID=%d.\r\n%s" + IDS_SKIN_ERR_MASKFILE "Failed to load mask bitmap file %s.\r\n%s" + IDS_SKIN_ERR_MASKSIZE "The background bitmap %d and the mask bitmap %d have different sizes.\r\n" + IDS_SKIN_ERR_FIND_RES1 "Can't find the main ""SKIN"" resource with ID=1.\r\n" + IDS_SKIN_ERR_LOAD_RES1 "Failed to load the main ""SKIN"" resource with ID=1.\r\n" + IDS_SKIN_ERR_LOAD_FILE1 "Failed to load the main skin file %s.\r\n" +END + +STRINGTABLE +BEGIN + IDS_SKIN_ERR_FIND_RES "Can't find the variation ""SKIN"" resource with ID=%d.\r\n" + IDS_SKIN_ERR_LOAD_RES "Failed to load the variation ""SKIN"" resource with ID=%d.\r\n" + IDS_SKIN_ERR_LOAD_FILE "Failed to load the variation skin file %s.\r\n" + IDS_SKIN_ERR_LOAD "Error loading %s\n%s" + IDS_SKIN_ERR_VERSION "The selected skin is not compatible with this version of the start menu.\r\n" + IDS_MENU_TITLE "== Classic Start Menu ==" + IDS_DEFAULT_SKIN "" + IDS_CONTROLS_SETTINGS "Controls" + IDS_OPEN_NOTHING "Nothing" + IDS_OPEN_NOTHING_TIP "The action will do nothing" + IDS_OPEN_CSM "Classic Start Menu" + IDS_OPEN_CSM_TIP "The action will open the classic start menu" + IDS_OPEN_WSM "Windows Start Menu" + IDS_OPEN_WSM_TIP "The action will open the default start menu" + IDS_LCLICK "Left Click opens:" + IDS_LCLICK_TIP "Select what happens when you click the left mouse button on the Start Button" +END + +STRINGTABLE +BEGIN + IDS_SHIFT_LCLICK "Shift+Click opens:" + IDS_SHIFT_LCLICK_TIP "Select what happens when you hold Shift and click the left mouse button on the Start Button" + IDS_WIN_KEY "Windows Key opens:" + IDS_WIN_KEY_TIP "Select what happens when you press the Windows key" + IDS_SHIFT_WIN "Shift+Win opens:" + IDS_SHIFT_WIN_TIP "Select what happens when you hold Shift and press the Windows key" + IDS_MCLICK "Middle Click opens:" + IDS_MCLICK_TIP "Select what happens when you click the middle mouse button on the Start Button" + IDS_HOVER "Hover opens:" + IDS_HOVER_TIP "Select what happens when you hover the mouse over the Start Button" + IDS_HOVER_DELAY "Hover delay" + IDS_HOVER_DELAY_TIP "Enter the delay (in ms) for hovering over the Start Button" + IDS_CSM_HOTKEY "Additional Classic Menu hotkey" + IDS_CSM_HOTKEY_TIP "Enter an additional hotkey for opening the classic start menu" + IDS_WSM_HOTKEY "Additional Windows Menu hotkey" + IDS_WSM_HOTKEY_TIP "Enter an additional hotkey for opening the Windows start menu" +END + +STRINGTABLE +BEGIN + IDS_SHOW_ITEMS "Special Items" + IDS_ITEM_HIDE "Don't display this item" + IDS_ITEM_HIDE_TIP "This item will not appear in the start menu" + IDS_ITEM_SHOW "Display as a link" + IDS_ITEM_SHOW_TIP "This item will appear as a link you can click" + IDS_ITEM_MENU "Display as a menu" + IDS_ITEM_MENU_TIP "This item will appear as a sub-menu" + IDS_SHOW_FAVORITES "Favorites" + IDS_SHOW_FAVORITES_TIP "Select how to display Favorites in the start menu" + IDS_SHOW_DOCUMENTS "Recent documents" + IDS_SHOW_DOCUMENTS_TIP "Select how to display the recent documents in the start menu" + IDS_MAX_DOCS "Max recent documents" + IDS_MAX_DOCS_TIP "Limit the number of recent documents in the start menu" + IDS_SHOW_USERFILES "User files" + IDS_SHOW_USERFILES_TIP "Select how to display the user's files in the start menu" + IDS_SHOW_USERDOCS "User documents" +END + +STRINGTABLE +BEGIN + IDS_SHOW_USERDOCS_TIP "Select how to display the user's documents in the start menu" + IDS_SHOW_USERPICS "User pictures" + IDS_SHOW_USERPICS_TIP "Select how to display the user's pictures in the start menu" + IDS_SHOW_CP "Control Panel" + IDS_SHOW_CP_TIP "Select how to display the Control Panel in the start menu" + IDS_SHOW_NETWORK "Network Connections" + IDS_SHOW_NETWORK_TIP "Select how to display Network in the start menu" + IDS_SHOW_PRINTERS "Printers" + IDS_SHOW_PRINTERS_TIP "Select how to display Printers in the start menu" + IDS_SHOW_SEARCH "Show Search Menu" + IDS_SHOW_SEARCH_TIP "Enable the Search menu" + IDS_SHOW_HELP "Show Help and Support" + IDS_SHOW_HELP_TIP "Enable the Help and Support item" + IDS_SHOW_RUN "Show Run" + IDS_SHOW_RUN_TIP "Enable the Run item" + IDS_SHOW_LOGOFF "Show Log Off" +END + +STRINGTABLE +BEGIN + IDS_CUSTOM_TIP "This is a custom menu item. Use the command property to launch a program, or the link property to add a folder to the start menu" + IDS_SEARCH_TIP "This is the top item for the Search menu" + IDS_SETTINGS_MENU_TIP "This is the top item for the Settings menu" + IDS_FEATURES_TIP "Opens the Programs and Features window" + IDS_RESTORE_TIP "Restores all properties (text, icon and more) to the defaults for the selected command" + IDS_SEARCH_BOX_TIP "This is a search box where you can type the text you want to find" + IDS_SEARCH_BOX "Search Box" + IDS_SHOW_SEARCH_BOX "Show search box" + IDS_SHOW_SEARCH_BOX_TIP "Enable the search for programs" + IDS_SEARCH_BOX_HIDE "No search box" + IDS_SEARCH_BOX_HIDE_TIP "The search box is not shown" + IDS_SEARCH_BOX_SHOW "Access normally" + IDS_SEARCH_BOX_SHOW_TIP "The search box will be accessible with the arrow keys and the mouse" + IDS_SEARCH_BOX_TAB "Access with Tab" + IDS_SEARCH_BOX_TAB_TIP "The search box will be accessible only with the Tab key and the mouse" + IDS_SEARCH_BOX_SEL "Selected by default" +END + +STRINGTABLE +BEGIN + IDS_SEARCH_BOX_SEL_TIP "When this is checked, the search box will be selected when you open the menu" + IDS_SEARCH_PATH "Search the system path" + IDS_SEARCH_PATH_TIP "When this is checked, the search will look in the folders listed in the PATH environment variable" + IDS_SUB_WORD "Match parts of words" + IDS_SUB_WORD_TIP "The search will match parts in the middle of words. For example 'enu' will match 'Classic Menu'" + IDS_SEARCH_TRACK "Track frequency of use" + IDS_SEARCH_TRACK_TIP "When this is checked, the start menu will track how frequently you use programs and will sort the search results by usage" + IDS_SEARCH_MAX "Max search results" + IDS_SEARCH_MAX_TIP "Limit the number of the search results. If the search finds more than this number, no results will be shown unless you press Tab" + IDS_SEARCH_AUTO "Enable Auto-Complete" + IDS_SEARCH_AUTO_TIP "When this is checked, typing a path in the search box will auto-complete names of files and folders" + IDS_INLINE_TIP "The sub-items of this menu item will appear as a row of buttons instead of a sub-menu" + IDS_NOEXTENSIONS_TIP "This menu and its sub-menus will hide the file extensions" + IDS_DELAY_ICONS "Delay loading of icons" +END + +STRINGTABLE +BEGIN + IDS_SHOW_LOGOFF_TIP "Enable the Log Off item" + IDS_CONFIRM_LOGOFF "Confirm Log Off" + IDS_CONFIRM_LOGOFF_TIP "The Log Off command will show a confirmation prompt before logging off" + IDS_SHOW_UNDOCK "Show Undock" + IDS_SHOW_UNDOCK_TIP "Enable the Undock item (for laptops only)" + IDS_SHOW_SHUTDOWN "Shutdown" + IDS_SHOW_SHUTDOWN_TIP "Select how to display Shutdown in the start menu" + IDS_SHOW_RSHUTDOWN "Show Shutdown during remote sessions" + IDS_SHOW_RSHUTDOWN_TIP "Enable the Shutdown item during a Remote Desktop connection" + IDS_SHOW_RECENT_OLD "Show recent programs" + IDS_SHOW_RECENT_TIP_OLD "Enable the display of recently-used programs" + IDS_MAX_PROGS "Max recent programs (use negative number to reverse the order)" + IDS_MAX_PROGS_TIP "Limit the number of recent programs. If the number is negative, the most recent program will be at the bottom" + IDS_RECENT_TOP "Show recent programs on top" + IDS_RECENT_TOP_TIP "Select if you want the recent programs to be before or after the other programs in the main menu" + IDS_RECENT_KEYS "Shortcuts for the recent programs" +END + +STRINGTABLE +BEGIN + IDS_RECENT_KEYS_TIP "Select the style of the keyboard shortcuts for the recent programs" + IDS_KEY_NOTHING "No shortcuts" + IDS_KEY_NOTHING_TIP "Disables the shortcuts completely" + IDS_KEY_NORMAL "Normal shortcuts" + IDS_KEY_NORMAL_TIP "Use the first letter of the program for the shortcut" + IDS_KEY_DIGITS "Digits" + IDS_KEY_DIGITS_TIP "Use digits for the shortcuts (1, 2, 3, etc)" + IDS_KEY_HIDDEN "Hidden digits" + IDS_KEY_HIDDEN_TIP "Same as above, but the digits are not shown" + IDS_BEHAVIOR_SETTINGS "General Behavior" + IDS_EXPAND_LINKS "Expand folder shortcuts" + IDS_EXPAND_LINKS_TIP "When this is checked, shortcuts (links) to folders will open as sub-menus" + IDS_MENU_DELAY "Menu delay" + IDS_MENU_DELAY_TIP "The delay (in ms) for opening sub-menus when the mouse hovers over a folder item" + IDS_TIP_DELAY "Infotip delay" + IDS_TIP_DELAY_TIP "The delay for the infotip. The first number is the delay for showing the infotip and the second is the delay for hiding it. Use '0,0' to disable the tips" +END + +STRINGTABLE +BEGIN + IDS_FTIP_DELAY "Infotip delay (for folders)" + IDS_FTIP_DELAY_TIP "Same as the above, but for folder items. This is disabled by default because the folder infotips are usually not very helpful" + IDS_ANIM_NONE "No animation" + IDS_ANIM_NONE_TIP "The menu pops in with no animation" + IDS_ANIM_FADE "Fade" + IDS_ANIM_FADE_TIP "The menu fades into view" + IDS_ANIM_SLIDE "Slide" + IDS_ANIM_SLIDE_TIP "The menu slides into view" + IDS_ANIMATION "Main menu animation" + IDS_ANIMATION_TIP "Pick the type of the animation for the main menu" + IDS_ANIM_SPEED "Main menu animation speed" + IDS_ANIM_SPEED_TIP "The duration (in ms) for the main menu animation" + IDS_SUB_ANIMATION "Sub-menu animation" + IDS_SUB_ANIMATION_TIP "Pick the type of the animation for the sub-menus" + IDS_SUB_ANIM_SPEED "Sub-menu animation speed" + IDS_SUB_ANIM_SPEED_TIP "The duration (in ms) for the sub-menu animation" +END + +STRINGTABLE +BEGIN + IDS_SCROLL_SPEED "Main menu scroll speed (1..10)" + IDS_SCROLL_SPEED_TIP "The speed (from 1 to 10) when scrolling the items in the main menu" + IDS_SUB_SCROLL_SPEED "Sub-menu scroll speed (1..10)" + IDS_SUB_SCROLL_SPEED_TIP + "The speed (from 1 to 10) when scrolling the items in the sub-menus" + IDS_FADE_SPEED "Fade speed" + IDS_FADE_SPEED_TIP "The duration (in ms) of the fade animation for the selected menu item" + IDS_DRAG_DELAY "Drag/drop hide delay" + IDS_DRAG_DELAY_TIP "The delay (in ms), after which the menu will close when you are dragging an item outside of the menu. Lets you drag from the menu to the Desktop or other programs" + IDS_ACCESSIBILITY "Enable accessibility" + IDS_ACCESSIBILITY_TIP "Enable the active accessibility features of the start menu" + IDS_NEXTTASKBAR "Show next to taskbar (when the taskbar is vertical)" + IDS_NEXTTASKBAR_TIP "When this is checked and the taskbar is docked to the left or right edge of the screen, the start menu will appear next to the taskbar instead of on top of it" + IDS_SEARCH_COMMAND "Custom search command" + IDS_SEARCH_COMMAND_TIP "Enter a custom command to run when you pick Search -> For Files or Folders" + IDS_CASCADE_MENU "Cascading right-click menu" + IDS_CASCADE_MENU_TIP "When this is checked, the additional items of the right-click menu (like New Folder, or Sort by Name) are placed in a sub-menu of their own" +END + +STRINGTABLE +BEGIN + IDS_CACHE_ICONS "Pre-cache icons" + IDS_CACHE_ICONS_TIP "When this is checked, the system will begin pre-loading the icons as soon as you log in, so the start menu will open faster" + IDS_SKIN_ERRORS "Report skin errors" + IDS_SKIN_ERRORS_TIP "When this is checked, the menu will report problems with the current skin. This is useful when creating and troubleshooting new skins" + IDS_LOOK_SETTINGS "Menu Look" + IDS_MENU_WIDTH "Main menu width" + IDS_MENU_WIDTH_TIP "Set the width of the main menu text to fit this many average-width characters" + IDS_SUBMENU_WIDTH "Sub-menu width" + IDS_SUBMENU_WIDTH_TIP "Set the width of the sub-menu text to fit this many average-width characters" + IDS_SAME_COLUMNS "All columns are same size" + IDS_SAME_COLUMNS_TIP "When this is checked, all columns of a menu will be forced to be the same size" + IDS_MENU_CAPTION "Menu caption" + IDS_MENU_CAPTION_TIP "Enter the text you want to see on the side of the menu (for skins that support caption)" + IDS_MENU_USERNAME "User name text" + IDS_MENU_USERNAME_TIP "Enter the text you want to see in the user-name portion of the menu (for skins that show the user name)" + IDS_PIC_COMMAND "User picture command" +END + +STRINGTABLE +BEGIN + IDS_PIC_COMMAND_TIP "Enter the command you want to run when you click on the user picture" + IDS_NAME_COMMAND "User name command" + IDS_NAME_COMMAND_TIP "Enter the command you want to run when you click on the user name" + IDS_SMALL_SIZE_SM "Small icon size" + IDS_SMALL_SIZE_SM_TIP "Set the small icon size. The default is 16 for DPI<=96, 20 for 96120" + IDS_LARGE_SIZE_SM "Large icon size" + IDS_LARGE_SIZE_SM_TIP "Set the large icon size. The default is 32 for DPI<=96, 40 for 96120" + IDS_NUMERIC_SORT "Use numeric sorting" + IDS_NUMERIC_SORT_TIP "When this is checked, the start menu will use numeric (logical) sorting instead of alphabetical sorting for names that contain numbers" + IDS_FONT_SMOOTHING "Font smoothing" + IDS_FONT_SMOOTHING_TIP "Select the font smoothing for the menu text" + IDS_SMOOTH_DEFAULT "Default" + IDS_SMOOTH_DEFAULT_TIP "The text will use the system default" + IDS_SMOOTH_NONE "No smoothing" + IDS_SMOOTH_NONE_TIP "The text will have no smoothing" + IDS_SMOOTH_STD "Standard" +END + +STRINGTABLE +BEGIN + IDS_SMOOTH_STD_TIP "The text will use the the standard anti-aliasing smoothing" + IDS_SMOOTH_CLEAR "Clear Type" + IDS_SMOOTH_CLEAR_TIP "The text will use the ClearType smoothing" + IDS_CONTEXT_MENU_SETTINGS "Context Menu" + IDS_DRAG_DROP "Enable Drag and Drop" + IDS_DRAG_DROP_TIP "When this is checked, the user will be allowed to drag and drop items in the start menu" + IDS_CONTEXT_MENU "Enable right-click menu" + IDS_CONTEXT_MENU_TIP "When this is checked, the user will be allowed to right-click on an item and use its context menu" + IDS_NEW_FOLDER "Enable New Folder and New Shortcut" + IDS_NEW_FOLDER_TIP "When this is checked, the user will be allowed to right-click in the start menu and create new folders and shortcuts" + IDS_EXIT "Enable Exit" + IDS_EXIT_TIP "When this is checked, the user can right-click on the start button and select 'Exit'" + IDS_SOUND_SETTINGS "Sounds" + IDS_SOUND_MAIN "Main menu sound" + IDS_SOUND_MAIN_TIP "This sound plays when the start menu is opened" + IDS_SOUND_POPUP "Sub-menu sound" +END + +STRINGTABLE +BEGIN + IDS_SOUND_POPUP_TIP "This sound plays when a sub-menu is opened" + IDS_SOUND_COMMAND "Command sound" + IDS_SOUND_COMMAND_TIP "This sound plays when a start menu item is executed" + IDS_SOUND_DROP "Drop sound" + IDS_SOUND_DROP_TIP "This sound plays when something is dropped on the start menu" + IDS_WSM_SETTINGS "Windows Start Menu" + IDS_CASCADE_ALL "Cascading All Programs menu" + IDS_CASCADE_ALL_TIP "When this is checked, the 'All Programs' item in the Windows start menu will expand as a cascading sub-menu" + IDS_ALL_DELAY "Hover delay" + IDS_ALL_DELAY_TIP "Enter the delay (in ms) for hovering over the 'All Programs' item" + IDS_ALL_SELECT "Initially focus on:" + IDS_ALL_SELECT_TIP "Select which item will be selected by default when you open the Windows start menu" + IDS_SELECT_SEARCH "Search box" + IDS_SELECT_SEARCH_TIP "The search box will be selected by default" + IDS_SELECT_BUTTON "All Programs" + IDS_SELECT_BUTTON_TIP "The 'All Programs' item will be selected by default" +END + +STRINGTABLE +BEGIN + IDS_SKIN_SETTINGS "Skin" + IDS_ALL_SKIN_SETTINGS "All Programs Skin" + IDS_CUSTOM_SETTINGS "Customize Start Menu" + IDS_LANGUAGE_SETTINGS_SM "Language" + IDS_SCROLL_TYPE "Multiple columns in sub-menus" + IDS_SCROLL_TYPE_TIP "Select what to do when a sub-menu doesn't fit in a single column" + IDS_SCROLL_NO "Use multiple columns" + IDS_SCROLL_NO_TIP "If the menu doesn't fit in one column it will use multiple columns" + IDS_SCROLL_YES "Use single column (scroll)" + IDS_SCROLL_YES_TIP "If the menu doesn't fit in one column it will start scrolling" + IDS_SCROLL_AUTO "Auto (multiple columns if they fit)" + IDS_SCROLL_AUTO_TIP "The menu will use multiple columns only if all columns fit on screen. Otherwise it will use a single scrolling column" + IDS_ANIM_RANDOM "Random" + IDS_ANIM_RANDOM_TIP "The menu will use either slide or fade randomly" + IDC_SKINVARIATION "Skin Variation" + IDS_COMMAND_TIP "Pick a command for the menu item. The command determines what the item does when clicked" +END + +STRINGTABLE +BEGIN + IDS_LINK_TIP "Type a full path of a file or a folder. If you select a file, it will be executed. If you select a folder, it will be opened as a sub-menu. You can use environment variables like %windir%\\Notepad.exe. Note: Buttons with sub-menus cannot have a link" + IDS_TEXT_TIP "Enter the text for the menu item. If the text starts with $ (like $Menu.Network) it will be looked up in the file StartMenuL10N.ini" + IDS_TIP_TIP "Enter the infotip for the menu item. If the text starts with $ (like $Menu.NetworkTip) it will be looked up in the file StartMenuL10N.ini" + IDS_ICON_TIP "Enter the icon for the button. If the icon is blank, the default icon of the link will be used instead. Use either a path to a .ico file, or a combination of a .dll file and an icon ID. Use 'none' to get no icon at all" + IDS_SORTZA_TIP "The menu will be sorted in descending order by default" + IDS_SORTZAREC_TIP "The sub-menus of this menu will be sorted in descending order" + IDS_SORTONCE_TIP "The menu will be sorted automatically the first time it is opened. Any items added later will be at the bottom" + IDS_OPENUP_TIP "The menu will open up instead of down (if there is room)" + IDS_OPENUPREC_TIP "The sub-menus of this menu will open up instead of down" + IDS_NOEXPAND_TIP "If this item has a link to a folder, it will not expand as a sub-menu" + IDS_MULTICOLUMN_TIP "The menu will use multiple columns if it doesn't fit on screen" + IDS_TRACK_TIP "The items from this menu will be tracked by the 'Recent Programs' database" + IDS_NOTRACK_TIP "The items from this menu will not be tracked by the 'Recent Programs' database" + IDS_ITEMSFIRST_TIP "If the menu has both a link to a folder and child items, the child items will appear before the files of the folder" + IDS_MAIN_SORTZA "Sort the main menu in Z->A order" + IDS_MAIN_SORTONCE "Sort the main menu only the first time" +END + +STRINGTABLE +BEGIN + IDS_SEPARATOR_TIP "This item separates items in the menu" + IDS_BREAK_TIP "(only for two-column main menus) marks the start of the second column" + IDS_PADDING_TIP "(only for two-column main menus) moves the rest of the items in the column to the bottom" + IDS_PROGRAMS_TIP "The Programs folder - contains all installed programs" + IDS_FAVORITES_TIP "The Favorites folder" + IDS_DOCUMENTS_TIP "Shows the recent documents" + IDS_USERFILES_TIP "Shows the user files folder" + IDS_USERDOCS_TIP "Shows the user documents folder" + IDS_USERPICS_TIP "Shows the user pictures folder" + IDS_CONTROLPANEL_TIP "Shows the contents of the Control Panel" + IDS_CONTROLPANEL2_TIP "Shows the contents of the Control Panel. When double-clicked, will show the Control Panel in Categories view" + IDS_SECURITY_TIP "Shows the Windows Security menu (with Task Manager, Change Password, etc). This only works via Remote Desktop" + IDS_NETWORK_TIP "Shows the network connections" + IDS_PRINTERS_TIP "Shows the available printers" + IDS_RUN_TIP "Shows the Run dialog" + IDS_HELP_TIP "Shows the Windows help" +END + +STRINGTABLE +BEGIN + IDS_LOGOFF_TIP "Logs off the current user" + IDS_UNDOCK_TIP "Undocks the laptop from the docking station" + IDS_DISCONNECT_TIP "Disconnects the computer from the terminal session (like Remote Desktop)" + IDS_SHUTDOWNBOX_TIP "Shows the shutdown dialog" + IDS_SEARCHFI_TIP "Searches for files and folders" + IDS_SEARCHPR_TIP "Searches for a printer" + IDS_SEARCHCO_TIP "Searches for computers on the network" + IDS_SEARCHPE_TIP "Searches for people. May be disabled if Windows Mail is not available" + IDS_TASKBAR_TIP "Opens the Taskbar and Start Menu settings" + IDS_MENU_TIP "Opens the Classic Start Menu settings" + IDS_RECENT_TIP "Creates a sub-menu with the recently executed items" + IDS_SLEEP_TIP "Suspends the computer in sleep state" + IDS_HIBERNATE_TIP "Suspends the computer in hibernate state" + IDS_RESTART_TIP "Restarts the computer" + IDS_SHUTDOWN_TIP "Shuts down the computer" + IDS_SWITCH_TIP "Exits the current session and enters the 'switch user' screen" +END + +STRINGTABLE +BEGIN + IDS_DELAY_ICONS_TIP "When this is checked, the menu will show first and the icons will continue to load after that" + IDS_SHOW_FAVORITES_TIP2 "Select how to display Favorites in the start menu\nWarning: You don't have a Favorites item in your custom menu, so this setting will be ignored" + IDS_SHOW_DOCUMENTS_TIP2 "Select how to display the recent documents in the start menu\nWarning: You don't have a Documents item in your custom menu, so this setting will be ignored" + IDS_SHOW_USERFILES_TIP2 "Select how to display the user's files in the start menu\nWarning: You don't have a User Files item in your custom menu, so this setting will be ignored" + IDS_SHOW_USERDOCS_TIP2 "Select how to display the user's documents in the start menu\nWarning: You don't have a User Documents item in your custom menu, so this setting will be ignored" + IDS_SHOW_USERPICS_TIP2 "Select how to display the user's pictures in the start menu\nWarning: You don't have a User Pictures item in your custom menu, so this setting will be ignored" + IDS_SHOW_CP_TIP2 "Select how to display the Control Panel in the start menu\nWarning: You don't have a Control Panel item in your custom menu, so this setting will be ignored" + IDS_SHOW_NETWORK_TIP2 "Select how to display Network in the start menu\nWarning: You don't have a Network Connections item in your custom menu, so this setting will be ignored" + IDS_SHOW_PRINTERS_TIP2 "Select how to display Printers in the start menu\nWarning: You don't have a Printers item in your custom menu, so this setting will be ignored" + IDS_SHOW_SHUTDOWN_TIP2 "Select how to display Shutdown in the start menu\nWarning: You don't have a 'Shutdown dialog' item in your custom menu, so this setting will be ignored" + IDS_SHOW_SEARCH_BOX_TIP2 + "Enable the search for programs\nWarning: You don't have a Search Box item in your custom menu, so this setting will be ignored" + IDS_SHOW_SEARCH_TIP2 "Enable the Search menu\nWarning: You don't have a Search Menu item in your custom menu, so this setting will be ignored" + IDS_SHOW_HELP_TIP2 "Enable the Help and Support item\nWarning: You don't have a Help item in your custom menu, so this setting will be ignored" + IDS_SHOW_RUN_TIP2 "Enable the Run item\nWarning: You don't have a Run item in your custom menu, so this setting will be ignored" + IDS_SHOW_LOGOFF_TIP2 "Enable the Log Off item\nWarning: You don't have a Log Off item in your custom menu, so this setting will be ignored" + IDS_SHOW_UNDOCK_TIP2 "Enable the Undock item (for laptops only)\nWarning: You don't have a Undock item in your custom menu, so this setting will be ignored" +END + +STRINGTABLE +BEGIN + IDS_LOCK_TIP "Locks the computer" + IDS_SUB_ANIM_ALWAYS "Always animate sub-menus" + IDS_SUB_ANIM_ALWAYS_TIP "When this is checked, the sub-menus will animate every time they open" + IDS_EXPLORER "Enable Windows Explorer" + IDS_EXPLORER_TIP "Uncheck this to prevent opening folders in Windows Explorer" + IDS_EXPLORER_PATH "Default Explorer path" + IDS_EXPLORER_PATH_TIP "Set the default path for the Windows Explorer command in the Start Button menu. Leave blank to remove the Windows Explorer command. The special locations 'computer', 'desktop' and 'libraries' are also supported" + IDS_HIDE_PIC "Hide user picture" + IDS_HIDE_PIC_TIP "When this is checked, the user picture is removed from the Windows start menu" + IDS_SORT_DOCS "Sort Recent Documents" + IDS_SORT_DOCS_TIP "Select how you want the recent documents to be sorted" + IDS_SORT_NAME "By name" + IDS_SORT_NAME_TIP "The recent documents will be sorted by name" + IDS_SORT_EXT "By extension" + IDS_SORT_EXT_TIP "The recent documents will be sorted by extension" + IDS_MENU_SHADOW "Enable menu shadow" +END + +STRINGTABLE +BEGIN + IDS_MENU_SHADOW_TIP "When this is checked, the menus will have a shadow" + IDS_START_BUTTON "Start Button" + IDS_ENABLE_BUTTON "Enable Start button" + IDS_ENABLE_BUTTON_TIP "When this is checked, a Start button will be added to the taskbar" + IDS_BUTTON_TYPE "Button look" + IDS_BUTTON_TYPE_TIP "Select the look of the Start button" + IDS_CLASSIC_BUTTON "Classic button" + IDS_CLASSIC_BUTTON_TIP "Select the Classic look for Start button" + IDS_AERO_BUTTON "Aero button" + IDS_AERO_BUTTON_TIP "Select the Aero look for the Start button" + IDS_CUSTOM_BUTTON "Custom button" + IDS_CUSTOM_BUTTON_TIP "Select a custom bitmap for the Start button" + IDS_BUTTON_IMAGE "Button image" + IDS_BUTTON_IMAGE_TIP "Select a bitmap to be used for the Start button" +END + +STRINGTABLE +BEGIN + IDS_BUTTON_SIZE "Button size" + IDS_BUTTON_SIZE_TIP "Select the width for the button when using a custom image" + IDS_HOT_CORNERS "Disable active corners" + IDS_HOT_CORNERS_TIP "Select which active corners to disable" + IDS_SKIP_METRO "Skip Metro screen" + IDS_SKIP_METRO_TIP "Automatically skip the Metro screen after login and enter the Desktop" + IDS_BUTTON_ICON "Button icon" + IDS_BUTTON_ICON_TIP "Select the icon for the classic Start button" + IDS_BUTTON_TIP "Button tooltip" + IDS_BUTTON_TIP_TIP "Select the tooltip for the Start button" + IDS_BUTTON_TEXT "Button text" + IDS_BUTTON_TEXT_TIP "Select the text for the classic Start button" + IDS_METRO_SETTINGS "Windows 8 Settings" + IDS_DISABLE_NONE "None" + IDS_DISABLE_NONE_TIP "Don't disable any corners" + IDS_DISABLE_START "Start screen" +END + +STRINGTABLE +BEGIN + IDS_DISABLE_START_TIP "Disable the Start screen popup at the bottom corner when the taskbar is at the bottom" + IDS_DISABLE_ALL "All" + IDS_DISABLE_ALL_TIP "Disable all corners" + IDS_ENABLE_BUTTON2 "Replace Start button" + IDS_ENABLE_BUTTON_TIP2 "When this is checked, the Start button will be replaced with a custom image" + IDS_SPLIT_TIP "The item will be split into separate parts for the command and for the sub-menu arrow" + IDS_STYLE_SETTINGS "Start Menu Style" + IDS_OPEN_WSS "Windows Start Screen" + IDS_OPEN_WSS_TIP "The action will open the Start screen" + IDS_WSS_HOTKEY "Additional Start screen hotkey" + IDS_WSS_HOTKEY_TIP "Enter an additional hotkey for opening the Start screen" + IDS_JUMPLISTS "Enable jumplists" + IDS_JUMPLISTS_TIP "When this is checked, programs in the main menu will have a sub-menu of recently used documents and common tasks" + IDS_MAX_JUMPLISTS "Max items in jumplists" + IDS_MAX_JUMPLISTS_TIP "Limit the number of items in the jumplists" +END + +STRINGTABLE +BEGIN + IDS_JUMPLIST_KEYS "Keyboard shortcuts for programs with jumplists" + IDS_JUMPLISTS_KEY_TIP "Select the action to happen when you press the keyboard shortcut for a program with a jumplist" + IDS_KEY_SELECT "Select" + IDS_KEY_SELECT_TIP "The program will be selected" + IDS_KEY_RUN "Run" + IDS_KEY_RUN_TIP "The program will run" + IDS_KEY_OPEN "Open jumplist" + IDS_KEY_OPEN_TIP "The program will be selected and the jumplist will open" + IDS_APPS_TIP "The Apps folder - contains all Windows Store apps (for Windows 8 and up)" + IDS_SPLIT_DELAY "Delay multiplier for split buttons (%)" + IDS_SPLIT_DELAY_TIP "Select percentage of the menu delay to use when hovering over the main portion of the split button. For example 200% means two times longer delay than normal" + IDS_OPEN_BOTH "Start Menu in Desktop and Start Screen in Metro" + IDS_OPEN_BOTH_TIP "The button will open the classic start menu when pressed in the Desktop and open the Windows start screen when pressed in a Metro app" + IDS_SHOW_COMPUTER "Computer" + IDS_COMPUTER_TIP "Show the contents of the computer" + IDS_SHOW_COMPUTER_TIP "Select how to display the computer in the start menu" +END + +STRINGTABLE +BEGIN + IDS_SHOW_COMPUTER_TIP2 "Select how to display the computer in the start menu\nWarning: You don't have a Computer item in your custom menu, so this setting will be ignored" + IDS_OPEN_DESKTOP "Start Menu in Desktop and shows Desktop in Metro" + IDS_OPEN_DESKTOP_TIP "The button will open the classic start menu when pressed in the Desktop and show the Desktop when pressed in the start screen" + IDS_SORT_DATE "By date" + IDS_SORT_DATE_TIP "The recent documents will be sorted by date of last use" + IDS_ENABLE_TASKBARS "Show on all taskbars" + IDS_ENABLE_TASKBARS_TIP "When this is checked, each taskbar will have its own start button" + IDS_TASKBAR_TRANS "Disable taskbar transparency" + IDS_TASKBAR_TRANS_TIP "When this is checked, the taskbar will be opaque" + IDS_SEARCH_PROGRAMS "Search programs and settings" + IDS_SEARCH_PROGRAMS_TIP "When this is checked, the search results will include programs and settings" + IDS_SEARCH_METRO "Search Metro apps" + IDS_SEARCH_METRO_TIP "When this is checked, the search results will include Metro apps" + IDS_SEARCH_KEYWORDS "Search for keywords" +END + +STRINGTABLE +BEGIN + IDS_SEARCH_KEYWORDS_TIP "When this is checked, the search will look at the keywords associated with the settings" + IDS_SEARCH_FILES "Search files" + IDS_SEARCH_FILES_TIP "When this is checked, the search results will include files, emails and other items from indexed locations" + IDS_SEARCH_FILES_TIP2 "When this is checked, the search results will include files, emails and other items from indexed locations\nWarning: the search service is disabled" + IDS_SEARCH_CONTENTS "Search contents" + IDS_SEARCH_CONTENTS_TIP "When this is checked, the search will look at the file contents and metadata" + IDS_SEARCH_CATEGORIES "Organize by library" + IDS_SEARCH_CATEGORIES_TIP + "When this is checked, the files will be grouped by the library they are in - Documents, Music, Pictures, etc" + IDS_SEARCH_EVERYWHERE "Search all indexed locations" + IDS_SEARCH_EVERYWHERE_TIP + "When this is checked, the search for files will look in all indexed folders. Otherwise only libraries and the Desktop will be searched" + IDS_SEARCH_INTERNET "Search the Internet" + IDS_SEARCH_INTERNET_TIP "When this is checked, the start menu will have an option to search the Internet" + IDS_NO_RECENT "Don't show" + IDS_NO_RECENT_TIP "No recently used programs will be shown" + IDS_RECENT_PROGRAMS "Show recent or frequent programs" + IDS_RECENT_PROGRAMS_TIP "Enable the display of used programs in the start menu" +END + +STRINGTABLE +BEGIN + IDS_SHOW_RECENT "Recent programs" + IDS_SHOW_RECENT_TIP "The start menu will show the programs that were recently launched from the start menu" + IDS_SHOW_FREQUENT "Frequent programs" + IDS_SHOW_FREQUENT_TIP "The start menu will show the programs that are frequently launched by the user" + IDS_RECENT_METRO "Show recent Metro apps" + IDS_RECENT_METRO_TIP "When this is checked, the recent programs list will include Metro apps" + IDS_HIGHLIGHT_NEW "Highlight newly installed programs" + IDS_HIGHLIGHT_NEW_TIP "When this is checked, the start menu will highlight the programs that were recently installed" + IDS_CP_CATEGORIES "Use Categories view" + IDS_CP_CATEGORIES2 "Use Categories view for the Control Panel" + IDS_CP_CATEGORIES_TIP "When this is checked, the Control Panel will open in Categories view" + IDS_CLASSIC_STYLE_TIP "The Classic style has a cascading Programs menu. It gives you unlimited freedom to arrange the menu items in any configuration." + IDS_TWO_COLUMN_STYLE_TIP + "This style has 2 columns and fits more items. You can arrange the menu items in any configuration." + IDS_WIN7_STYLE_TIP "The Windows 7 style shows the Programs list and the search results inside the menu. It offers limited customizability." + IDS_SHUTDOWN_COMMAND "Shutdown command" + IDS_SHUTDOWN_COMMAND_TIP + "Select the default command for the Shutdown button in the menu" +END + +STRINGTABLE +BEGIN + IDS_SHUTDOWN_NONE "None (hide the button)" + IDS_SHUTDOWN_NONE_TIP "The shutdown button will be removed from the menu" + IDS_SHUTDOWN_SHUTDOWN "Shutdown" + IDS_SHUTDOWN_SHUTDOWN_TIP + "The shutdown button will shut down the computer" + IDS_SHUTDOWN_RESTART "Restart" + IDS_SHUTDOWN_RESTART_TIP "The shutdown button will restart the computer" + IDS_SHUTDOWN_LOGOFF "Log off" + IDS_SHUTDOWN_LOGOFF_TIP "The shutdown button will close all programs and log off" + IDS_SHUTDOWN_SLEEP "Sleep" + IDS_SHUTDOWN_SLEEP_TIP "The shutdown button will put the computer to sleep" + IDS_SHUTDOWN_HIBERNATE "Hibernate" + IDS_SHUTDOWN_HIBERNATE_TIP + "The shutdown button will hibernate the computer" + IDS_SHUTDOWN_LOCK "Lock" + IDS_SHUTDOWN_LOCK_TIP "The shutdown button will lock the computer" + IDS_SHUTDOWN_SWITCH "Switch User" + IDS_SHUTDOWN_SWITCH_TIP "The shutdown button will switch to another user" +END + +STRINGTABLE +BEGIN + IDS_SHUTDOWN_SHUTDOWN_BOX "Shutdown dialog" + IDS_SHUTDOWN_SHUTDOWN_BOX_TIP + "The shutdown button will show a dialog box to select the next operation" + IDS_UNDOCK_ITEM "Undock" + IDS_DISCONNECT_ITEM "Disconnect" + IDS_ITEM_SHOW2 "Display this item" + IDS_SEPARATOR_ITEM "SEPARATOR" + IDS_COLUMN_BREAK_ITEM "COLUMN BREAK" + IDS_COLUMN_PADDING_ITEM "COLUMN PADDING" + IDS_CUSTOM_ITEM "Custom" + IDS_HELP_ITEM "Help" + IDS_RUN_ITEM "Run" + IDS_SECURITY_ITEM "Windows security" + IDS_LIB_DOCS_ITEM "Documents library" + IDS_LIB_PICS_ITEM "Pictures library" + IDS_LIB_VIDEOS_ITEM "Videos library" + IDS_LIB_MUSIC_ITEM "Music library" +END + +STRINGTABLE +BEGIN + IDS_LIB_TV_ITEM "Recorded TV" + IDS_PROGRAMS_ITEM "Programs" + IDS_APPS_ITEM "Apps" + IDS_SETTINGS_ITEM "Settings" + IDS_SEARCH_MENU_ITEM "Search menu" + IDS_SEARCH_BOX_ITEM "Search box" + IDS_TASKBAR_ITEM "Taskbar settings" + IDS_FEATURES_ITEM "Programs and Features" + IDS_MENU_SETTINGS_ITEM "Menu settings" + IDS_SEARCH_FILES_ITEM "Search files" + IDS_SEARCH_PRINTER_ITEM "Search printer" + IDS_SEARCH_COMP_ITEM "Search computers" + IDS_SEARCH_PEOPLE_ITEM "Search people" + IDS_MONITOR_OFF_ITEM "Monitor off" + IDS_MENU_MOVE_UP "Move Up" + IDS_MENU_MOVE_DOWN "Move Down" +END + +STRINGTABLE +BEGIN + IDS_MENU_INSERT "Insert New Item" + IDS_MENU_DUPLICATE "Duplicate Item" + IDS_METRO_APPS "Metro Apps" + IDS_PROGRAMS_DELAY "Delay multiplier for the All Programs button (%)" + IDS_PROGRAMS_DELAY_TIP "Select percentage of the menu delay to use when hovering over the All Programs button. For example 200% means two times longer delay than normal" + IDS_SEARCH_MAX2 "Results per category" + IDS_SEARCH_MAX_TIP2 "Limit the number of results shown per category" + IDS_SEARCH_MAX3 "Results per maximized category" + IDS_SEARCH_MAX_TIP3 "Limit the number of results shown for the maximized category" + IDS_SHOW_APPS "Show Metro apps" + IDS_SHOW_APPS_TIP "When this is checked, the programs tree will include a folder for the Metro apps" + IDS_FOLDERS_FIRST "Show folders first" + IDS_FOLDERS_FIRST_TIP "When this is checked, the All Programs tree will show the folders first and the programs last" + IDS_PINNED_PROGRAMS "Pinned Programs folder" + IDS_PINNED_PROGRAMS_TIP "Select the location to store the pinned programs" + IDS_FAST_ITEMS "Use Start Menu folder" +END + +STRINGTABLE +BEGIN + IDS_FAST_ITEMS_TIP "The pinned programs will be stored in the system Start Menu folder" + IDS_PINNED_ITEMS "Use Pinned folder" + IDS_PINNED_ITEMS_TIP "The pinned programs will be stored in a dedicated Pinned folder" + IDS_BUTTON_ICON_SIZE "Icon size" + IDS_BUTTON_ICON_SIZE_TIP + "Select the size for the button icon. Enter 0 to use the default icon size" + IDS_BUTTON_SIZE_TIP2 "Select the width for the button when using a custom image. Enter 0 to use the actual bitmap size" + IDS_MONITOR_OFF_TIP "Turns off the monitor" + IDS_AUTOSTART "Start automatically for this user" + IDS_AUTOSTART_TIP "The start menu will run automatically when you log in" + IDS_CHECK_UPDATES "Check for Windows updates on shutdown" + IDS_CHECK_UPDATES_TIP "When this is checked, the start menu will check if there are any pending updates and will install them on shutdown" + IDS_ITEM_DRIVES "Display as a list of drives" + IDS_ITEM_DRIVES_TIP "This item will appear as a sub-menu showing the available drives" + IDS_MENU_GLASS "Enable Aero Glass (requires Aero Glass mod)" + IDS_MENU_GLASS_TIP "Check this to use glass transparency (requires the Aero Glass mod to be installed)" + IDS_MAIN_MENU_SETTINGS "Main Menu" +END + +STRINGTABLE +BEGIN + IDS_RIGHT_SHIFT "Right click opens the Windows context menu" + IDS_RIGHT_SHIFT_TIP "When this is checked, right-click on the start button will open the standard Windows context menu instead of the Classic Shell menu. Otherwise Shift+right-click will open it" + IDS_RIGHT_SHIFTX "Right click opens Win+X menu" + IDS_RIGHT_SHIFTX_TIP "When this is checked, right-click on the start button will open the Win+X power menu instead of the Classic Shell menu. Otherwise Shift+right-click will open it" + IDS_STARTSCREEN_ITEM "Show Start screen shortcut" + IDS_STARTSCREEN_ITEM_TIP + "When this is checked, the main menu will contain a shortcut to open the Start screen" + IDS_MIN_HEIGHT "Minimum menu height" + IDS_MIN_HEIGHT_TIP "The main menu will be at least as tall as this many search results" + IDS_GLASS_OVERRIDE "Override glass color" + IDS_GLASS_OVERRIDE_TIP "Check this to override the system glass color to use in the menu" + IDS_GLASS_COLOR "Menu glass color" + IDS_GLASS_COLOR_TIP "Select the glass color to use in the menu. How much this color affects the menu will depend on the selected skin" + IDS_GLASS_INTENSITY "Menu glass intensity" + IDS_GLASS_INTENSITY_TIP "Select the intensity (brightness) for the glass color in the menu (0 - dark, 100 - bright)" +END + +STRINGTABLE +BEGIN + IDS_GLASS_BLENDING "Menu color blending" + IDS_GLASS_BLENDING_TIP "Select how much of the menu skin color to blend (0 - less, 100 - more)" + IDS_INLINE_PROGS "All Programs style" + IDS_INLINE_PROGS_TIP "Select how to show the All Programs list in the main menu" + IDS_MAIN_INLINE "Inside main menu" + IDS_MAIN_INLINE_TIP "The programs will be shown as a tree inside the main menu" + IDS_MAIN_CASCADE "Cascading sub-menu" + IDS_MAIN_CASCADE_TIP "The programs will be shown as a cascading sub-menu" + IDS_ANIMATION7 "Animated transitions in main menu" + IDS_ANIMATION7_TIP "When this is checked, the transitions in the main menu will be animated" + IDS_METRO_SETTINGS81 "Windows 8.1 Settings" + IDS_MENU_BUSY "Please wait for the Start menu to finish the initial collection of information" + IDS_OPEN_PROGRAMS "Open automatically" + IDS_OPEN_PROGRAMS_TIP "When this is checked, the All Programs list will be automatically shown when you open the start menu" + IDS_MOUSE_MONITOR "Open Start screen on monitor with the mouse" + IDS_MOUSE_MONITOR_TIP "When this is checked, pressing Shift+Win will open the Start screen on the same monitor as the mouse pointer" +END + +STRINGTABLE +BEGIN + IDS_STRING7001 "Black buttons on glass#The buttons and frames in the second column of the main menu will be black" + IDS_STRING7002 "Black text on glass#The text in the second column of the main menu will be black" + IDS_STRING7003 "Caption#The main menu will show a caption text on the side" + IDS_STRING7004 "Center user name#The user name will be centered horizontally" + IDS_STRING7005 "Reduce glass color#The menu color will depend less on the system glass color" + IDS_STRING7006 "Large font#The main menu and the sub-menus will use larger font" + IDS_STRING7007 "Large font#The sub-menus will use larger font" +END + +STRINGTABLE +BEGIN + IDS_STRING7008 "No icons in second column#The items in the second column of the main menu will not have icons" + IDS_STRING7009 "Disable glass transparency#The colored parts of the menu will be opaque" + IDS_STRING7010 "Transparency level#Select how transparent the menu should be" + IDS_STRING7011 "Small icons#The main menu will use small icons" + IDS_STRING7012 "Solid color selection#The selection will use the system color instead of a gradient" + IDS_STRING7013 "3D border (requires Classic theme)#The menus will have a 3D look (only for Windows 7 with Classic theme)" + IDS_STRING7014 "Show user picture#The main menu will show the user picture" + IDS_STRING7015 "Show user name#The main menu will show the user name" + IDS_STRING7016 "White sub-menus#The sub-menus will have a white background instead of the system menu color" + IDS_STRING7017 "Default" + IDS_STRING7018 "Less transparent" + IDS_STRING7019 "More transparent" + IDS_STRING7020 "Blue" + IDS_STRING7021 "Olive green" + IDS_STRING7022 "Silver" + IDS_STRING7023 "Show icon frames#The icons in the main menu will have a frame around them" +END + +STRINGTABLE +BEGIN + IDS_STRING7024 "Shadows on glass#The text and the arrows in the second column of the main menu will have a drop shadow" + IDS_STRING7025 "Opaque" + IDS_STRING7026 "Main menu color" + IDS_STRING7027 "Custom color#Select custom color for the main menu" + IDS_STRING7028 "Sub-menu color" + IDS_STRING7029 "Custom color#Select custom color for the sub-menus" + IDS_STRING7030 "Silver" + IDS_STRING7031 "Gold" + IDS_STRING7032 "Steel" + IDS_STRING7033 "Titanium" + IDS_STRING7034 "Image for first column#Select custom image for the first column of the main menu" + IDS_STRING7035 "Image for second column#Select custom image for the second column of the main menu" + IDS_STRING7036 "Text color for first column#Select custom color for the first column of the main menu text" + IDS_STRING7037 "Text color for second column#Select custom color for the second column of the main menu text" + IDS_STRING7038 "Text size#Select custom size for the main menu text" +END + +STRINGTABLE +BEGIN + IDS_STRING7100 "This is the default skin when no other skin is selected or if the selected skin fails to load.\n\nPart of Classic Shell (c) 2009-2016, Ivo Beltchev" + IDS_STRING7101 "Windows Aero skin\n\nDefault skin to use for the Windows Aero theme.\n\nPart of Classic Shell (c) 2009-2016, Ivo Beltchev" + IDS_STRING7102 "Windows Basic skin\n\nDefault skin to use for the Windows Basic theme.\n\nPart of Classic Shell (c) 2009-2016, Ivo Beltchev" + IDS_STRING7103 "Classic skin\n\nClassic look with large or small icons.\n\nPart of Classic Shell (c) 2009-2016, Ivo Beltchev" +END + +STRINGTABLE +BEGIN + IDS_STRING7104 "Full Glass skin\n\nTransparent menu with large or small icons.\n\nPart of Classic Shell (c) 2009-2016, Ivo Beltchev" + IDS_STRING7105 "Smoked Glass skin\n\nSimple transparent menu with dark background.\n\nPart of Classic Shell (c) 2009-2016, Ivo Beltchev" + IDS_STRING7106 "Windows XP Luna skin\n\nA start menu similar to the one in Windows XP.\n\nPart of Classic Shell (c) 2009-2016, Ivo Beltchev" + IDS_STRING7107 "Windows 8 skin\n\nDefault skin to use for Windows 8.\n\nPart of Classic Shell (c) 2009-2016, Ivo Beltchev" + IDS_STRING7108 "Midnight skin\n\nSkin with dark background.\n\nPart of Classic Shell (c) 2009-2016, Ivo Beltchev" + IDS_STRING7109 "Metro skin\n\nSkin that uses the start screen colors.\n\nPart of Classic Shell (c) 2009-2016, Ivo Beltchev" + IDS_STRING7110 "Metallic skin\n\nA start menu skin with metallic look.\n\nPart of Classic Shell (c) 2009-2016, Ivo Beltchev" +END + +STRINGTABLE +BEGIN + IDS_COLUMN_ICON "Icon" + IDS_COLUMN_COMMAND "Command" + IDS_COLUMN_DISPLAY "Display" + IDS_HIDE_APPS "Hide app shortcuts" + IDS_HIDE_APPS_TIP "When this is checked, the shortcuts to Metro apps that are outside of the dedicated Apps folder will be hidden" + IDS_HYBRID_SHUTDOWN "Enable hybrid shutdown" + IDS_HYBRID_SHUTDOWN_TIP "When this is checked, the shutdown button will perform the faster hybrid shutdown. You can still do a full shutdown by holding down Shift" + IDS_UPGRADE_WIN "Classic Shell needs to configure itself for the new operating system." + IDS_UPGRADE_ERROR "There was an error configuring Classic Shell. It is recommended that you uninstall the software, restart, and install it again." + IDS_UPGRADE_SUCCESS "The configuration was successful." + IDS_INVERT_ICONS "Invert Metro icon color" + IDS_INVERT_ICONS_TIP "When this is checked, the Metro icons will appear as colored symbols on transparent background" + IDS_SHUTDOWN7 "Shutdown menu items" + IDS_SHUTDOWN7_TIP "Select the commands to appear in the shutdown menu in the Windows 7 style. The choices are: switch_user, windows_security, logoff, lock, disconnect, undock, restart, sleep, hibernate, shutdown. Separate the commands with a comma or semicolon. The order is not important. You must list at least one. If the list is empty, all commands are enabled (unless disabled by other rules)." + IDS_PROG_WIDTH "Programs pane width" + IDS_PROG_WIDTH_TIP "Set the width of the program column in the Windows 7 style in characters." +END + +STRINGTABLE +BEGIN + IDS_JUMP_WIDTH "Jumplist pane width" + IDS_JUMP_WIDTH_TIP "Set the width of the jumplist column in the Windows 7 style in characters." + IDS_NOPIN "Disable the Pin shell extension" + IDS_NOPIN_TIP "When this is checked, the shell extension that allows pinning to the Classic Shell start menu will be disabled." + IDS_RECENT_NAME "Sort by name" + IDS_RECENT_NAME_TIP "When this is checked, the recent programs will be sorted by name." + IDS_DPI_OVERRIDE "Override system DPI" + IDS_DPI_OVERRIDE_TIP "Select a different DPI value to be used by the menu. The setting controls the size of the menu icons, text, and other graphical elements. The acceptable values are between 96 and 480. Use 0 to disable the override." + IDS_ENABLE_TOUCH "Enable touch features" + IDS_ENABLE_TOUCH_TIP "When this is checked, the start menu will enable its touch and stylus features." + IDS_METRO_SETTINGS10 "Windows 10 Settings" + IDS_MOUSE_MONITOR2 "Open Windows Start menu on monitor with the mouse" + IDS_MOUSE_MONITOR_TIP2 "When this is checked, pressing Shift+Win will open the Windows Start menu on the same monitor as the mouse pointer" + IDS_PIC_PATH "User picture" + IDS_PIC_PATH_TIP "Override the default user picture with another image" + IDS_SEARCH_METROS "Search PC settings" +END + +STRINGTABLE +BEGIN + IDS_SEARCH_METROS_TIP "When this is checked, the search results will include the modern PC settings" + IDS_SHOW_APPS_MENU "Show Apps menu" + IDS_SHOW_APPS_MENU_TIP "Enable the Apps menu" + IDS_SHOW_APPS_MENU_TIP2 "Enable the Apps menu\nWarning: You don't have the Apps item in your custom menu, so this setting will be ignored" + IDS_SKIN_ERR_METRO_COLOR + "The selected skin is not compatible with Windows 7.\r\n" + IDS_BUTTON_ALIGN "Align to corner of the screen" + IDS_BUTTON_ALIGN_TIP "When this is checked, the button will be aligned to the corner of the screen instead of the middle of the taskbar" + IDS_MENU_GLASS2 "Enable menu glass" + IDS_MENU_GLASS2_TIP "Check this to use glass transparency in the menu" + IDS_GLASS_OPACITY "Glass opacity" + IDS_GLASS_OPACITY_TIP "Set the opacity for the glass in the menu (0 - transparent, 100 - opaque)" + IDS_TASK_CUSTOM "Customize taskbar" + IDS_TASK_CUSTOM_TIP "When this is checked, you can customize the look of the taskbar" + IDS_TASK_LOOK "Taskbar look" + IDS_TASK_LOOK_TIP "Select the look for the taskbar" + IDS_TASK_OPAQUE "Opaque" +END + +STRINGTABLE +BEGIN + IDS_TASK_OPAQUE_TIP "The taskbar will be opaque" + IDS_TASK_TRANS "Transparent" + IDS_TASK_TRANS_TIP "The taskbar will be transparent" + IDS_TASK_GLASS "Glass" + IDS_TASK_GLASS_TIP "The taskbar will have glass transparency" + IDS_TASK_AEROGLASS "Aero Glass" + IDS_TASK_AEROGLASS_TIP "The taskbar will have glass transparency that is compatible with the Aero Glass mod" + IDS_TASK_OPACITY "Taskbar opacity" + IDS_TASK_OPACITY_TIP "Set the opacity for the taskbar (0 - transparent, 100 - opaque)" + IDS_TASK_COLOR "Taskbar color" + IDS_TASK_COLOR_TIP "Set the color for the taskbar" + IDS_PCSETTINGS "PC Settings" + IDS_PCSETTINGS_TIP "Shows the modern PC settings" + IDS_HIGHLIGHT_NEWAPPS "Highlight newly installed apps" + IDS_HIGHLIGHT_NEWAPPS_TIP + "When this is checked, the start menu will highlight the apps that were recently installed" + IDS_OPEN_CORTANA "Cortana" +END + +STRINGTABLE +BEGIN + IDS_OPEN_CORTANA_TIP "The action will open the Cortana search interface" + IDS_SKIN_ERR_RECBITMAP "Skin element %s must be a bitmap.\r\n" + IDS_MAIN_HIDDEN "Hidden" + IDS_MAIN_HIDDEN_TIP "The All Programs list will be hidden" + IDS_SOUND_HOVER "Start button hover sound" + IDS_SOUND_HOVER_TIP "This sound plays when the mouse hovers over the start button" + IDS_SHUTDOWN_SHUTDOWN_NU "Shutdown (no updates)" + IDS_SHUTDOWN_NU_TIP "Shuts down the computer without installing updates" + IDS_SHUTDOWN_RESTART_NU "Restart (no updates)" + IDS_RESTART_NU_TIP "Restarts the computer without installing updates" + IDS_TASK_TEXTURE "Taskbar texture" + IDS_TASK_TEXTURE_TIP "Select a texture image for the taskbar" + IDS_TASK_STRETCHH "Horizontal stretching" + IDS_TASK_STRETCHH_TIP "Choose how to stretch the texture horizontally" + IDS_TASK_STRETCHV "Vertical stretching" + IDS_TASK_STRETCHV_TIP "Choose how to stretch the texture vertically" +END + +STRINGTABLE +BEGIN + IDS_TASK_STRETCH "Stretch" + IDS_TASK_STRETCH_TIP "The texture will be stretched to fit the size" + IDS_TASK_TILE "Tile" + IDS_TASK_TILE_TIP "The texture will be repeated multiple times" + IDS_TASK_BORDERS "Border sizes" + IDS_TASK_BORDERS_TIP "Select how many pixel on each side of the texture to exclude from stretching" + IDS_TASKBAR_SETTINGS "Taskbar" + IDS_TASK_TEXTCOLOR "Taskbar text color" + IDS_TASK_TEXTCOLOR_TIP "Select the color for the text on the taskbar" + IDS_SELECT_LAST "Select the last item in shutdown menu" + IDS_SELECT_LAST_TIP "When this is checked, the last item will be selected by default when the shutdown menu is opened with the keyboard" + IDS_CLEAR_CACHE "Clear cached information" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "..\..\ClassicShellLib\resource.h" +#include "..\..\ClassicShellLib\ClassicShellLib.rc" +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartMenuDLL.vcproj b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartMenuDLL.vcproj new file mode 100644 index 0000000..a7dddc0 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ClassicStartMenuDLL.vcproj @@ -0,0 +1,877 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/CustomMenu.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/CustomMenu.cpp new file mode 100644 index 0000000..ade707c --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/CustomMenu.cpp @@ -0,0 +1,617 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "CustomMenu.h" +#include "SettingsParser.h" +#include "Translations.h" +#include "MenuContainer.h" +#include "Settings.h" +#include "SettingsUI.h" +#include "FNVHash.h" +#include "ResourceHelper.h" +#include "resource.h" +#include + +// This table defines the standard menu items +static StdMenuItem g_StdMenu[]= +{ + // * means the command is not executable (for things like Settings, or for items that have FOLDERID) + {L"*programs",MENU_PROGRAMS,&FOLDERID_Programs,&FOLDERID_CommonPrograms}, + {L"*favorites",MENU_FAVORITES,&FOLDERID_Favorites}, + {L"*computer",MENU_COMPUTER,&FOLDERID_ComputerFolder}, + {L"*recent_documents",MENU_DOCUMENTS,&FOLDERID_Recent}, + {L"*settings",MENU_SETTINGS}, + {L"*search",MENU_SEARCH}, + {L"help",MENU_HELP}, + {L"run",MENU_RUN}, + {L"logoff",MENU_LOGOFF}, + {L"undock",MENU_UNDOCK}, + {L"monitor_off",MENU_MONITOROFF}, + {L"disconnect",MENU_DISCONNECT}, + {L"shutdown_box",MENU_SHUTDOWN_BOX}, + {L"*user_files",MENU_USERFILES,&FOLDERID_UsersFiles}, + {L"*user_documents",MENU_USERDOCUMENTS,&FOLDERID_Documents}, + {L"*user_pictures",MENU_USERPICTURES,&FOLDERID_Pictures}, + {L"*control_panel",MENU_CONTROLPANEL,&FOLDERID_ControlPanelFolder}, + {L"pc_settings",MENU_PCSETTINGS}, + {L"windows_security",MENU_SECURITY}, + {L"*network_connections",MENU_NETWORK,&FOLDERID_ConnectionsFolder}, + {L"*printers",MENU_PRINTERS,&FOLDERID_PrintersFolder}, + {L"taskbar_settings",MENU_TASKBAR}, + {L"programs_features",MENU_FEATURES}, + {L"menu_settings",MENU_CLASSIC_SETTINGS}, + {L"search_files",MENU_SEARCH_FILES}, + {L"search_printer",MENU_SEARCH_PRINTER}, + {L"search_computers",MENU_SEARCH_COMPUTERS}, + {L"search_people",MENU_SEARCH_PEOPLE}, + {L"sleep",MENU_SLEEP}, + {L"hibernate",MENU_HIBERNATE}, + {L"restart",MENU_RESTART}, + {L"restart_noupdate",MENU_RESTART_NOUPDATE}, + {L"shutdown",MENU_SHUTDOWN}, + {L"shutdown_noupdate",MENU_SHUTDOWN_NOUPDATE}, + {L"switch_user",MENU_SWITCHUSER}, + {L"lock",MENU_LOCK}, + {L"*recent_programs",MENU_RECENT_PROGRAMS}, + {L"search_box",MENU_SEARCH_BOX}, + {L"*apps",MENU_APPS}, + + {L"*fonts",MENU_CUSTOM,&FOLDERID_Fonts}, + {L"*desktop",MENU_CUSTOM,&FOLDERID_Desktop}, + {L"*admin",MENU_CUSTOM,&FOLDERID_CommonAdminTools,&FOLDERID_AdminTools}, + {L"*startup",MENU_CUSTOM,&FOLDERID_Startup,&FOLDERID_CommonStartup}, + {L"*user_music",MENU_CUSTOM,&FOLDERID_Music}, + {L"*user_videos",MENU_CUSTOM,&FOLDERID_Videos}, + {L"*downloads",MENU_CUSTOM,&FOLDERID_Downloads}, + {L"*games",MENU_CUSTOM,&FOLDERID_Games}, + {L"*links",MENU_CUSTOM,&FOLDERID_Links}, + {L"*libraries",MENU_CUSTOM,&FOLDERID_Libraries}, + {L"*lib_documents",MENU_CUSTOM,&FOLDERID_DocumentsLibrary}, + {L"*lib_music",MENU_CUSTOM,&FOLDERID_MusicLibrary}, + {L"*lib_pictures",MENU_CUSTOM,&FOLDERID_PicturesLibrary}, + {L"*lib_videos",MENU_CUSTOM,&FOLDERID_VideosLibrary}, + {L"*lib_tv",MENU_CUSTOM,&FOLDERID_RecordedTVLibrary}, + {L"*homegroup",MENU_CUSTOM,&FOLDERID_HomeGroup}, + {L"*network",MENU_CUSTOM,&FOLDERID_NetworkFolder}, + {L"*devices",MENU_CUSTOM}, + {L"*defaults",MENU_CUSTOM}, +}; + +CStdCommand7 g_StdCommands7[]={ + {L"separator",IDS_SEPARATOR_ITEM,NULL,NULL,NULL,NULL,NULL,0,CStdCommand7::ITEM_SINGLE}, // must be first + + {L"favorites",0,NULL,NULL,L"imageres.dll,1024",&FOLDERID_Favorites,NULL,StdMenuItem::MENU_TRACK}, + {L"recent_documents",0,NULL,NULL,NULL,&FOLDERID_Recent}, + {L"computer",0,NULL,NULL,NULL,&FOLDERID_ComputerFolder,NULL,0,CStdCommand7::ITEM_COMPUTER}, + {L"help",IDS_HELP_ITEM,L"$Menu.Help",L"$Menu.HelpTip",L"imageres.dll,99",NULL,NULL,0,CStdCommand7::ITEM_SINGLE}, + {L"run",IDS_RUN_ITEM,L"$Menu.Run",L"$Menu.RunTip",L"imageres.dll,100",NULL,NULL,0,CStdCommand7::ITEM_SINGLE}, + {L"windows_security",IDS_SECURITY_ITEM,L"$Menu.Security",L"$Menu.SecurityTip",L"shell32.dll,48",NULL,NULL,0,CStdCommand7::ITEM_SINGLE}, + {L"user_files",IDS_SHOW_USERFILES,NULL,L"$Menu.UserFilesTip",NULL,&FOLDERID_UsersFiles}, + {L"user_documents",0,NULL,L"$Menu.UserDocumentsTip",NULL,&FOLDERID_Documents}, + {L"user_pictures",0,NULL,L"$Menu.UserPicturesTip",NULL,&FOLDERID_Pictures}, + {L"user_music",0,NULL,L"$Menu.UserMusicTip",NULL,&FOLDERID_Music}, + {L"user_videos",0,NULL,L"$Menu.UserVideosTip",NULL,&FOLDERID_Videos}, + {L"control_panel",0,L"$Menu.ControlPanel",L"$Menu.ControlPanelTip",NULL,&FOLDERID_ControlPanelFolder,NULL,StdMenuItem::MENU_TRACK}, + {L"pc_settings",IDS_PCSETTINGS,L"$Menu.PCSettings",L"",L"%windir%\\ImmersiveControlPanel\\SystemSettings.exe,10",NULL,NULL,StdMenuItem::MENU_TRACK,CStdCommand7::ITEM_SINGLE}, + {L"network_connections",0,NULL,L"$Menu.NetworkTip",NULL,&FOLDERID_ConnectionsFolder}, + {L"network",0,NULL,NULL,NULL,&FOLDERID_NetworkFolder,NULL,0,CStdCommand7::ITEM_SINGLE}, + {L"printers",0,NULL,L"$Menu.PrintersTip",NULL,&FOLDERID_PrintersFolder}, + {L"fonts",0,NULL,NULL,NULL,&FOLDERID_Fonts}, + {L"desktop",0,NULL,NULL,NULL,&FOLDERID_Desktop}, + {L"admin",0,NULL,L"$Menu.AdminToolsTip",L"imageres.dll,114",&FOLDERID_CommonAdminTools,NULL,StdMenuItem::MENU_TRACK}, + {L"startup",0,NULL,NULL,NULL,&FOLDERID_Startup,NULL,StdMenuItem::MENU_TRACK}, + {L"downloads",0,NULL,L"$Menu.DownloadTip",NULL,&FOLDERID_Downloads}, + {L"games",0,NULL,L"$Menu.GamesTip",NULL,&FOLDERID_Games,NULL,StdMenuItem::MENU_TRACK}, + {L"links",0,NULL,NULL,NULL,&FOLDERID_Links}, + {L"libraries",0,NULL,NULL,NULL,&FOLDERID_Libraries}, + {L"lib_documents",IDS_LIB_DOCS_ITEM,NULL,L"$Menu.DocumentsLibTip",NULL,&FOLDERID_DocumentsLibrary}, + {L"lib_music",IDS_LIB_MUSIC_ITEM,NULL,L"$Menu.MusicLibTip",NULL,&FOLDERID_MusicLibrary}, + {L"lib_pictures",IDS_LIB_PICS_ITEM,NULL,L"$Menu.PicturesLibTip",NULL,&FOLDERID_PicturesLibrary}, + {L"lib_videos",IDS_LIB_VIDEOS_ITEM,NULL,L"$Menu.VideosLibTip",NULL,&FOLDERID_VideosLibrary}, + {L"lib_tv",IDS_LIB_TV_ITEM,NULL,L"$Menu.RecordingsLibTip",NULL,&FOLDERID_RecordedTVLibrary}, + {L"homegroup",0,NULL,L"$Menu.HomegroupTip",NULL,&FOLDERID_HomeGroup,NULL,0,CStdCommand7::ITEM_SINGLE}, + {L"devices",0,NULL,NULL,NULL,NULL,L"::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0\\::{A8A91A66-3A7D-4424-8D24-04E180695C7A}"}, + {L"defaults",0,NULL,NULL,NULL,NULL,L"::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0\\::{17CD9488-1228-4B2F-88CE-4298E93E0966}",0,CStdCommand7::ITEM_SINGLE}, + {L"apps",IDS_METRO_APPS,L"$Menu.Apps",NULL,L",2",NULL,NULL,StdMenuItem::MENU_TRACK,CStdCommand7::ITEM_FOLDER}, + + {L"",IDS_CUSTOM_ITEM} // must be last +}; + +const int g_StdCommands7Count=_countof(g_StdCommands7); + +// This table defines folders that need special treatment +SpecialFolder g_SpecialFolders[]= +{ + {&FOLDERID_Games,SpecialFolder::FOLDER_NONEWFOLDER}, + {&FOLDERID_ComputerFolder,SpecialFolder::FOLDER_NONEWFOLDER}, + {&FOLDERID_RecycleBinFolder,SpecialFolder::FOLDER_NOSUBFOLDERS|SpecialFolder::FOLDER_NODROP}, + {&FOLDERID_NetworkFolder,SpecialFolder::FOLDER_NODROP}, + {&FOLDERID_ConnectionsFolder,SpecialFolder::FOLDER_NODROP|SpecialFolder::FOLDER_NOPATH}, + {&FOLDERID_Recent,SpecialFolder::FOLDER_NODROP}, + {&FOLDERID_ControlPanelFolder,SpecialFolder::FOLDER_NODROP}, + {&FOLDERID_PrintersFolder,SpecialFolder::FOLDER_NODROP}, + {&FOLDERID_HomeGroup,SpecialFolder::FOLDER_NODROP}, + {NULL} +}; + +static std::vector g_CustomMenu; +static unsigned int g_RootSettings; +static unsigned int g_MenuItemsHash; +static CSettingsParser g_CustomMenuParser; +static bool g_bSpecialFoldersInitialized; + +void InitializeSpecialFolders( void ) +{ + if (!g_bSpecialFoldersInitialized) + { + g_bSpecialFoldersInitialized=true; + for (int i=0;g_SpecialFolders[i].folder;i++) + { + CComPtr pItem; + if (SUCCEEDED(ShGetKnownFolderItem(*g_SpecialFolders[i].folder,&pItem)) && pItem) + { + CComString pPath; + pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pPath); + pPath.MakeUpper(); + Strcpy(g_SpecialFolders[i].PATH,_countof(g_SpecialFolders[i].PATH),pPath); + } + } + } +} + +static const StdMenuItem *FindStdMenuItem( const wchar_t *command ) +{ + for (int i=0;i<_countof(g_StdMenu);i++) + { + const wchar_t *cmd=g_StdMenu[i].command; + if (*cmd=='*') cmd++; + if (_wcsicmp(cmd,command)==0) + return &g_StdMenu[i]; + } + return NULL; +} + +static unsigned int ParseItemSettings( const wchar_t *name ) +{ + wchar_t buf[256]; + Sprintf(buf,_countof(buf),L"%s.Settings",name); + const wchar_t *str=g_CustomMenuParser.FindSetting(buf); + if (!str) return 0; + + unsigned int settings=0; + while(*str) + { + wchar_t token[256]; + str=GetToken(str,token,_countof(token),L", \t|;"); + if (_wcsicmp(token,L"OPEN_UP")==0) settings|=StdMenuItem::MENU_OPENUP; + if (_wcsicmp(token,L"OPEN_UP_CHILDREN")==0) settings|=StdMenuItem::MENU_OPENUP_REC; + if (_wcsicmp(token,L"SORT_ZA")==0) settings|=StdMenuItem::MENU_SORTZA; + if (_wcsicmp(token,L"SORT_ZA_CHILDREN")==0) settings|=StdMenuItem::MENU_SORTZA_REC; + if (_wcsicmp(token,L"SORT_ONCE")==0) settings|=StdMenuItem::MENU_SORTONCE; + if (_wcsicmp(token,L"ITEMS_FIRST")==0) settings|=StdMenuItem::MENU_ITEMS_FIRST; + if (_wcsicmp(token,L"TRACK_RECENT")==0) settings|=StdMenuItem::MENU_TRACK; + if (_wcsicmp(token,L"NOTRACK_RECENT")==0) settings|=StdMenuItem::MENU_NOTRACK; + if (_wcsicmp(token,L"NOEXPAND")==0) settings|=StdMenuItem::MENU_NOEXPAND; + if (_wcsicmp(token,L"SINGLE_EXPAND")==0) settings|=StdMenuItem::MENU_SINGLE_EXPAND; + if (_wcsicmp(token,L"MULTICOLUMN")==0) settings|=StdMenuItem::MENU_MULTICOLUMN; + if (_wcsicmp(token,L"NOEXTENSIONS")==0) settings|=StdMenuItem::MENU_NOEXTENSIONS; + if (_wcsicmp(token,L"INLINE")==0) settings|=StdMenuItem::MENU_INLINE; + if (_wcsicmp(token,L"SPLIT")==0) settings|=StdMenuItem::MENU_SPLIT_BUTTON; + } + return settings; +} + +static void ParseMenuItem( StdMenuItem &item, const wchar_t *name ) +{ + wchar_t buf[1024]; + const wchar_t *str; + Sprintf(buf,_countof(buf),L"%s.Link",name); + str=g_CustomMenuParser.FindSetting(buf); + if (str) + { + // parse link + item.link=str; + const wchar_t *c=wcschr(item.link,'|'); + if (c) + { + for (c++;*c==' ';) + c++; + item.link=c; + } + } + + Sprintf(buf,_countof(buf),L"%s.Command",name); + str=g_CustomMenuParser.FindSetting(buf); + int custom7=-1; + if (str) + { + // parse command + const StdMenuItem *pItem=FindStdMenuItem(str); + if (pItem) + { + item.id=pItem->id; + item.folder1=pItem->folder1; + item.folder2=pItem->folder2; + if (item.id==MENU_CONTROLPANEL && GetSettingBool(L"ControlPanelCategories")) + item.command=L"::{26EE0668-A00A-44D7-9371-BEB064C98683}"; + else if (item.id==MENU_SHUTDOWN_BOX && GetSettingInt(L"MenuStyle")==MENU_WIN7) + item.id=MENU_SHUTDOWN_BUTTON; + else if (*pItem->command!='*') + item.command=pItem->command; + } + else + { + item.id=MENU_CUSTOM; + item.command=str; + } + + for (int i=0;i=0) + { + if (g_StdCommands7[custom7].flags&CStdCommand7::ITEM_SINGLE) + item.settings|=StdMenuItem::MENU_NOEXPAND; + if (g_StdCommands7[custom7].flags&CStdCommand7::ITEM_FOLDER) + item.settings&=~StdMenuItem::MENU_NOEXPAND; + } +} + +const wchar_t *g_StartMenuItems7a=L"Items=COLUMN_PADDING, ProgramsMenu, SearchBoxItem, COLUMN_BREAK, "; +const wchar_t *g_StartMenuItems7b= +L" COLUMN_PADDING, ShutdownBoxItem\n" +L"ProgramsMenu.Command=programs\n" +L"ProgramsMenu.Label=$Menu.Programs\n" +L"ProgramsMenu.Tip=$Menu.ProgramsTip\n" +L"ProgramsMenu.Icon=none\n" +L"ProgramsMenu.Items=AppsMenu\n" +L"ProgramsMenu.Settings=ITEMS_FIRST\n" +L"AppsMenu.Command=apps\n" +L"AppsMenu.Label=$Menu.Apps\n" +L"AppsMenu.Icon=,2\n" +L"SearchBoxItem.Command=search_box\n" +L"SearchBoxItem.Label=$Menu.SearchPrograms\n" +L"SearchBoxItem.Icon=none\n" +L"SearchBoxItem.Settings=TRACK_RECENT, OPEN_UP\n" +L"ShutdownBoxItem.Command=shutdown_box\n" +L"ShutdownBoxItem.Label=shutdown\n" +L"ShutdownBoxItem.Icon=none\n" +L"ShutdownBoxItem.Items=SwitchUserItem, SecurityItem, LogOffItem, LockItem, DisconnectItem, UndockItem, SEPARATOR, RestartNUItem, RestartItem, SEPARATOR, SleepItem, HibernateItem, ShutdownNUItem, ShutdownItem\n" +L"ShutdownBoxItem.Settings=SPLIT\n" +L"SwitchUserItem.Command=switch_user\n" +L"SwitchUserItem.Label=$Menu.SwitchUser\n" +L"SwitchUserItem.Tip=$Menu.SwitchUserTip\n" +L"SwitchUserItem.Icon=none\n" +L"SecurityItem.Command=windows_security\n" +L"SecurityItem.Icon=none\n" +L"SecurityItem.Label=$Menu.Security\n" +L"SecurityItem.Tip=$Menu.SecurityTip\n" +L"LogOffItem.Command=logoff\n" +L"LogOffItem.Label=$Menu.LogOffShort\n" +L"LogOffItem.Tip=$Menu.LogOffTip\n" +L"LogOffItem.Icon=none\n" +L"LockItem.Command=lock\n" +L"LockItem.Label=$Menu.Lock\n" +L"LockItem.Tip=$Menu.LockTip\n" +L"LockItem.Icon=none\n" +L"DisconnectItem.Command=disconnect\n" +L"DisconnectItem.Label=$Menu.Disconnect\n" +L"DisconnectItem.Tip=$Menu.DisconnectTip\n" +L"DisconnectItem.Icon=none\n" +L"UndockItem.Command=undock\n" +L"UndockItem.Label=$Menu.Undock\n" +L"UndockItem.Tip=$Menu.UndockTip\n" +L"UndockItem.Icon=none\n" +L"RestartNUItem.Command=restart_noupdate\n" +L"RestartNUItem.Label=$Menu.Restart\n" +L"RestartNUItem.Tip=$Menu.RestartTip\n" +L"RestartNUItem.Icon=none\n" +L"RestartItem.Command=restart\n" +L"RestartItem.Label=$Menu.Restart\n" +L"RestartItem.Tip=$Menu.RestartTip\n" +L"RestartItem.Icon=none\n" +L"SleepItem.Command=sleep\n" +L"SleepItem.Label=$Menu.Sleep\n" +L"SleepItem.Tip=$Menu.SleepTip\n" +L"SleepItem.Icon=none\n" +L"HibernateItem.Command=hibernate\n" +L"HibernateItem.Label=$Menu.Hibernate\n" +L"HibernateItem.Tip=$Menu.HibernateTip\n" +L"HibernateItem.Icon=none\n" +L"ShutdownNUItem.Command=shutdown_noupdate\n" +L"ShutdownNUItem.Label=$Menu.Shutdown\n" +L"ShutdownNUItem.Tip=$Menu.ShutdownTip\n" +L"ShutdownNUItem.Icon=none\n" +L"ShutdownItem.Command=shutdown\n" +L"ShutdownItem.Label=$Menu.Shutdown\n" +L"ShutdownItem.Tip=$Menu.ShutdownTip\n" +L"ShutdownItem.Icon=none\n" +; + +const StdMenuItem *ParseCustomMenu( unsigned int &rootSettings ) +{ + TMenuStyle menuStyle=(TMenuStyle)GetSettingInt(L"MenuStyle"); + CString menuText; + if (menuStyle==MENU_CLASSIC1) + menuText=GetSettingString(L"MenuItems1"); + else if (menuStyle==MENU_CLASSIC2) + menuText=GetSettingString(L"MenuItems2"); + else + menuText=GetSettingString(L"MenuItems7"); + unsigned int hash=FNV_HASH0; + if (GetSettingBool(L"ControlPanelCategories")) hash+=1; + if (GetSettingInt(L"ProgramsStyle")==PROGRAMS_INLINE) hash+=2; + if (GetSettingBool(L"AllProgramsMetro")) hash+=4; + hash=CalcFNVHash(menuText,hash); + + if (hash!=g_MenuItemsHash) + { + if (GetSettingInt(L"MenuStyle")==MENU_WIN7) + { + wchar_t buf[16384]; + int len=Strcpy(buf,_countof(buf),g_StartMenuItems7a); + + CSettingsParser parser; + parser.LoadText(menuText,menuText.GetLength()); + parser.ParseText(); + for (int i=1;;i++) + { + wchar_t item[100]; + Sprintf(item,_countof(item),L"Item%d.Settings",i); + const wchar_t *settings=parser.FindSetting(item); + if (settings && wcsstr(settings,L"ITEM_DISABLED")) + continue; + Sprintf(item,_countof(item),L"Item%d.Command",i); + const wchar_t *command=parser.FindSetting(item); + if (!command) + { + Sprintf(item,_countof(item),L"Item%d.Link",i); + if (!parser.FindSetting(item)) + break; + } + if (command && (_wcsicmp(command,L"shutdown_box")==0 || _wcsicmp(command,L"recent_programs")==0 || _wcsicmp(command,L"search_box")==0 || _wcsicmp(command,L"programs")==0)) + { + // these commands can't be in the right column because they are already in other parts of the menu + continue; + } + if (command && _wcsicmp(command,L"separator")==0) + { + len+=Sprintf(buf+len,_countof(buf)-len,L"SEPARATOR, "); + } + else + { + len+=Sprintf(buf+len,_countof(buf)-len,L"Item%d, ",i); + } + } + len+=Strcat(buf+len,_countof(buf)-len,g_StartMenuItems7b); + len+=Strcat(buf+len,_countof(buf)-len,menuText); + + for (int i=1;;i++) + { + wchar_t item[100]; + Sprintf(item,_countof(item),L"Item%d.Settings",i); + const wchar_t *settings=parser.FindSetting(item); + if (settings && wcsstr(settings,L"ITEM_DISABLED")) + continue; + Sprintf(item,_countof(item),L"Item%d.Command",i); + const wchar_t *command=parser.FindSetting(item); + Sprintf(item,_countof(item),L"Item%d.Link",i); + const wchar_t *link=parser.FindSetting(item); + if (!command) + { + if (!link) + break; + else + continue; + } + + Sprintf(item,_countof(item),L"Item%d.Label",i); + const wchar_t *label=parser.FindSetting(item); + Sprintf(item,_countof(item),L"Item%d.icon",i); + const wchar_t *icon=parser.FindSetting(item); + Sprintf(item,_countof(item),L"Item%d.Tip",i); + const wchar_t *tip=parser.FindSetting(item); + + // handle special items + for (int j=1;j items; + g_CustomMenuParser.ParseTree(L"Items",items); + g_CustomMenu.resize(items.size()); + for (size_t i=0;i=0) + item.submenu=&g_CustomMenu[idx]; + } + + for (std::vector::iterator it=g_CustomMenu.begin();it!=g_CustomMenu.end();++it) + if (it->id==MENU_RECENT_PROGRAMS) + { + g_RootSettings|=StdMenuItem::MENU_NORECENT; + break; + } + + // if there is no break, add one after Programs + if (!g_CustomMenu.empty()) + { + bool bBreak=false; + int after=-1; + for (int i=0;g_CustomMenu[i].id!=MENU_LAST;i++) + { + if (g_CustomMenu[i].id==MENU_COLUMN_BREAK) + bBreak=true; + if (g_CustomMenu[i].id==MENU_PROGRAMS) + after=i; + } + if (!bBreak && after>=0) + { + // add break + StdMenuItem br={NULL,MENU_COLUMN_BREAK}; + const StdMenuItem *pBase=&g_CustomMenu[0]; + g_CustomMenu.insert(g_CustomMenu.begin()+after+1,br); + + // fix submenu pointers + for (std::vector::iterator it=g_CustomMenu.begin();it!=g_CustomMenu.end();++it) + if (it->submenu) + { + int idx=(int)(it->submenu-pBase); + if (idx>after+1) + idx++; + it->submenu=&g_CustomMenu[idx]; + } + } + } + // ignore extra search boxes + bool bSearchBox=false; + for (std::vector::iterator it=g_CustomMenu.begin();it!=g_CustomMenu.end();++it) + { + if (it->id==MENU_SEARCH_BOX) + { + if (!bSearchBox) + bSearchBox=true; + else + it->id=MENU_IGNORE; + } + } + } + + rootSettings=g_RootSettings; + return &g_CustomMenu[0]; +} + +void InitStdCommands7( void ) +{ + for (int i=0;i + +class CMetroDataObject: public IDataObject +{ +public: + CMetroDataObject( const wchar_t *path ); + ~CMetroDataObject( void ); + + // from IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void **ppvObject ); + virtual ULONG STDMETHODCALLTYPE AddRef( void ) + { + return ++m_RefCount; + } + virtual ULONG STDMETHODCALLTYPE Release( void ) + { + if (m_RefCount==1) + { + delete this; + return 0; + } + return --m_RefCount; + } + + // from IDataObject + virtual HRESULT STDMETHODCALLTYPE GetData( FORMATETC *pformatetcIn, STGMEDIUM *pmedium ); + virtual HRESULT STDMETHODCALLTYPE SetData( FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease ) { return E_NOTIMPL; } + virtual HRESULT STDMETHODCALLTYPE GetDataHere( FORMATETC *pformatetc, STGMEDIUM *pmedium ) { return E_NOTIMPL; } + virtual HRESULT STDMETHODCALLTYPE QueryGetData( FORMATETC *pformatetc ); + virtual HRESULT STDMETHODCALLTYPE GetCanonicalFormatEtc( FORMATETC *pformatectIn, FORMATETC *pformatetcOut ); + virtual HRESULT STDMETHODCALLTYPE EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc ); + virtual HRESULT STDMETHODCALLTYPE DAdvise( FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection ) { return OLE_E_ADVISENOTSUPPORTED; } + virtual HRESULT STDMETHODCALLTYPE DUnadvise( DWORD dwConnection ) { return E_NOTIMPL; } + virtual HRESULT STDMETHODCALLTYPE EnumDAdvise( IEnumSTATDATA **ppenumAdvise ) { return OLE_E_ADVISENOTSUPPORTED; } + +private: + int m_RefCount; + std::map m_Data; + bool m_bContents; + + void SetData( CLIPFORMAT format, HGLOBAL data ); +}; + +static CLIPFORMAT g_PreferredEffectFormat; + +CMetroDataObject::CMetroDataObject( const wchar_t *path ) +{ + m_RefCount=0; + m_bContents=false; + SetData(CMenuContainer::s_MetroLinkFormat,NULL); + + if (!path) return; + HANDLE file=CreateFile(path,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + if (file!=INVALID_HANDLE_VALUE) + { + DWORD size=GetFileSize(file,NULL); + if (size>0) + { + HGLOBAL hContents=NULL, hDesc=NULL; + hContents=GlobalAlloc(GMEM_MOVEABLE,size); + if (hContents) + hDesc=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(FILEGROUPDESCRIPTOR)); + if (hDesc) + { + FILEGROUPDESCRIPTOR *desc=(FILEGROUPDESCRIPTOR*)GlobalLock(hDesc); + desc->cItems=1; + desc->fgd->dwFlags=FD_ATTRIBUTES|FD_FILESIZE|FD_LINKUI|FD_UNICODE; + desc->fgd->dwFileAttributes=FILE_ATTRIBUTE_NORMAL; + desc->fgd->nFileSizeLow=size; + Strcpy(desc->fgd->cFileName,_countof(desc->fgd->cFileName),PathFindFileName(path)); + GlobalUnlock(hDesc); + SetData(CMenuContainer::s_DescriptorFormat,hDesc); + hDesc=NULL; + + DWORD q; + if (!ReadFile(file,GlobalLock(hContents),size,&q,NULL)) + q=0; + GlobalUnlock(hContents); + if (q==size) + { + SetData(CMenuContainer::s_ContentsFormat,hContents); + hContents=NULL; + m_bContents=true; + } + } + if (hContents) GlobalFree(hContents); + if (hDesc) GlobalFree(hDesc); + } + CloseHandle(file); + } +} + +CMetroDataObject::~CMetroDataObject( void ) +{ + for (std::map::iterator it=m_Data.begin();it!=m_Data.end();++it) + if (it->second) + GlobalFree(it->second); +} + +HRESULT STDMETHODCALLTYPE CMetroDataObject::QueryInterface( REFIID riid, void **ppvObject ) +{ + if (riid==IID_IDataObject || riid==IID_IUnknown) + { + AddRef(); + *ppvObject=this; + return S_OK; + } + *ppvObject=NULL; + return E_NOINTERFACE; +} + +HRESULT STDMETHODCALLTYPE CMetroDataObject::GetData( FORMATETC *pformatetcIn, STGMEDIUM *pmedium ) +{ + if (!pformatetcIn || !pmedium) + return E_INVALIDARG; + + pmedium->hGlobal=NULL; + pmedium->pUnkForRelease=NULL; + + if (pformatetcIn->dwAspect!=DVASPECT_CONTENT) return DV_E_DVASPECT; + if (!(pformatetcIn->tymed&TYMED_HGLOBAL)) return DV_E_TYMED; + + std::map::iterator it=m_Data.find(pformatetcIn->cfFormat); + if (it==m_Data.end()) return DV_E_FORMATETC; + + wchar_t name[100]; + GetClipboardFormatName(pformatetcIn->cfFormat,name,100); + Trace(L"GetData: %s, %d",name,pformatetcIn->cfFormat); + + pmedium->tymed=TYMED_HGLOBAL; + SIZE_T size=GlobalSize(it->second); + pmedium->hGlobal=GlobalAlloc(GMEM_MOVEABLE,size); + if (!pmedium->hGlobal) return E_OUTOFMEMORY; + + void *src=GlobalLock(it->second); + void *dst=GlobalLock(pmedium->hGlobal); + memcpy(dst,src,size); + GlobalUnlock(pmedium->hGlobal); + GlobalUnlock(it->second); + return S_OK; +} + +void CMetroDataObject::SetData( CLIPFORMAT format, HGLOBAL data ) +{ + Assert(m_Data.find(format)==m_Data.end()); + m_Data[format]=data; +} + +HRESULT STDMETHODCALLTYPE CMetroDataObject::QueryGetData( FORMATETC *pformatetc ) +{ + if (!pformatetc) return E_INVALIDARG; + if (pformatetc->dwAspect!=DVASPECT_CONTENT) return DV_E_DVASPECT; + if (!(pformatetc->tymed&TYMED_HGLOBAL)) return DV_E_TYMED; + if (m_Data.find(pformatetc->cfFormat)==m_Data.end()) return DV_E_CLIPFORMAT; + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMetroDataObject::GetCanonicalFormatEtc( FORMATETC *pformatectIn, FORMATETC *pformatetcOut ) +{ + return pformatetcOut?DATA_S_SAMEFORMATETC:E_INVALIDARG; +} + +HRESULT STDMETHODCALLTYPE CMetroDataObject::EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc ) +{ + if (!ppenumFormatEtc) return E_POINTER; + *ppenumFormatEtc=NULL; + if (dwDirection == DATADIR_GET) + { + FORMATETC formats[] = + { + {CMenuContainer::s_MetroLinkFormat,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}, + {CMenuContainer::s_DescriptorFormat,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}, + {CMenuContainer::s_ContentsFormat,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}, + }; + HRESULT hr = SHCreateStdEnumFmtEtc(m_bContents?3:1,formats,ppenumFormatEtc); + return hr; + } + return E_NOTIMPL; +} + +CComPtr CMenuContainer::CreateMetroDataObject( const CItemManager::ItemInfo *pInfo ) +{ + CString path; + if (!pInfo->PATH.IsEmpty()) + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + path=pInfo->GetPath(); + } + IDataObject *pDataObjectIn=new CMetroDataObject(path); + CComPtr pDataObject; + SHCreateDataObject(NULL,0,NULL,pDataObjectIn,IID_IDataObject,(void**)&pDataObject); + if (pDataObject) + { + if (m_pDragSourceHelper) + { + g_ItemManager.UpdateItemInfo(pInfo,CItemManager::INFO_EXTRA_LARGE_ICON|CItemManager::INFO_REFRESH_NOW,false); + int iconSize=CItemManager::EXTRA_LARGE_ICON_SIZE; + SHDRAGIMAGE di={{iconSize,iconSize},{iconSize/2,iconSize},NULL,CLR_NONE}; + di.hbmpDragImage=(HBITMAP)CopyImage(pInfo->extraLargeIcon->bitmap,IMAGE_BITMAP,0,0,0); + m_pDragSourceHelper->SetFlags(DSH_ALLOWDROPDESCRIPTIONTEXT); + if (di.hbmpDragImage) + m_pDragSourceHelper->InitializeFromBitmap(&di,pDataObject); + } + } + else + { + pDataObjectIn->Release(); + } + return pDataObject; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool CMenuContainer::DragOutApps( const CItemManager::ItemInfo *pInfo ) +{ + // drag the Apps tree item for reordering + CComPtr pDataObj=CreateMetroDataObject(pInfo); + + // do drag drop + s_pDragSource=NULL; + s_bDragFromTree=false; + m_DragIndex=-1; + s_bPreventClosing=true; + m_DragTime=GetMessageTime(); + SetTimer(TIMER_DRAG,100); + s_bDragClosed=false; + DWORD dwEffect=DROPEFFECT_MOVE; + HRESULT res=SHDoDragDrop(NULL,pDataObj,NULL,dwEffect,&dwEffect); + + s_pDragSource=NULL; + s_bDragFromTree=false; + if (!m_bDestroyed) + KillTimer(TIMER_DRAG); + HideTemp(false); + s_bPreventClosing=false; + + if (s_bDragClosed) + { + for (std::vector::iterator it=s_Menus.begin();it!=s_Menus.end();++it) + if (!(*it)->m_bDestroyed) + (*it)->PostMessage(WM_CLOSE); + } + return true; +} + +bool CMenuContainer::DragOut( int index, bool bApp ) +{ + if (!(m_Options&CONTAINER_DRAG) || s_bNoDragDrop) return false; + const MenuItem &item=m_Items[index]; + if (!item.pItem1 || (item.id!=MENU_NO && item.id!=MENU_RECENT)) return false; + + bool bLeft=(GetKeyState(VK_LBUTTON)<0); + bool bRight=(GetKeyState(VK_RBUTTON)<0); + if (!bLeft && !bRight) return false; + + CComPtr pFolder; + PCUITEMID_CHILD child; + + // get IDataObject for the current item + CComPtr pDataObj; + bool bProtectedLink=false; + if (bApp && GetWinVersion()GetUIObjectOf(NULL,1,&child,IID_IDataObject,NULL,(void**)&pDataObj))) + return true; + + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + bProtectedLink=!m_bSubMenu || item.pItemInfo->IsProtectedLink(); + bMetroLink=item.pItemInfo->IsMetroLink(); + } + if (m_pDragSourceHelper && bMetroLink) + { + g_ItemManager.UpdateItemInfo(item.pItemInfo,CItemManager::INFO_EXTRA_LARGE_ICON|CItemManager::INFO_REFRESH_NOW,false); + int iconSize=CItemManager::EXTRA_LARGE_ICON_SIZE; + SHDRAGIMAGE di={{iconSize,iconSize},{iconSize/2,iconSize},NULL,CLR_NONE}; + di.hbmpDragImage=(HBITMAP)CopyImage(item.pItemInfo->extraLargeIcon->bitmap,IMAGE_BITMAP,0,0,0); + m_pDragSourceHelper->SetFlags(DSH_ALLOWDROPDESCRIPTIONTEXT); + if (di.hbmpDragImage) + m_pDragSourceHelper->InitializeFromBitmap(&di,pDataObj); + } + } + if (bProtectedLink) + { + // protected links default to DROPEFFECT_LINK + HGLOBAL hGlobal=GlobalAlloc(GMEM_MOVEABLE,4); + if (hGlobal) + { + *(DWORD*)GlobalLock(hGlobal)=DROPEFFECT_LINK; + GlobalUnlock(hGlobal); + FORMATETC format={s_PreferredEffectFormat,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}; + STGMEDIUM medium={TYMED_HGLOBAL}; + medium.hGlobal=hGlobal; + if (FAILED(pDataObj->SetData(&format,&medium,TRUE))) + GlobalFree(hGlobal); + } + } + + // force synchronous operation + { + CComQIPtr pAsync=pDataObj; + if (pAsync) + pAsync->SetAsyncMode(FALSE); + } + + // do drag drop + s_pDragSource=this; + s_bDragFromTree=(index==m_ProgramTreeIndex); + m_DragIndex=index; + s_bDragMovable=(item.id==MENU_NO && index=0 && s_JumpList.groups[LOWORD(item.jumpIndex)].type==CJumpGroup::TYPE_PINNED); + + s_bPreventClosing=true; + m_DragTime=GetMessageTime(); + s_bDragClosed=false; + SetTimer(TIMER_DRAG,100); + DWORD dwEffect=DROPEFFECT_COPY|DROPEFFECT_MOVE|DROPEFFECT_LINK; + HRESULT res=SHDoDragDrop(NULL,pDataObj,NULL,dwEffect,&dwEffect); + + s_pDragSource=NULL; + s_bDragFromTree=false; + if (!m_bDestroyed) + KillTimer(TIMER_DRAG); + s_bDragMovable=false; + HideTemp(false); + s_bPreventClosing=false; + + if (s_bDragClosed) + { + for (std::vector::iterator it=s_Menus.begin();it!=s_Menus.end();++it) + if (!(*it)->m_bDestroyed) + (*it)->PostMessage(WM_CLOSE); + return true; + } + + if (pFolder && res==DRAGDROP_S_DROP && !m_bDestroyed) + { + // check if the item still exists. refresh the menu if it doesn't + SFGAOF flags=SFGAO_VALIDATE; + if (FAILED(pFolder->GetAttributesOf(1,&child,&flags))) + { + SetActiveWindow(); + // close all submenus + for (int i=(int)s_Menus.size()-1;s_Menus[i]!=this;i--) + if (!s_Menus[i]->m_bDestroyed) + s_Menus[i]->DestroyWindow(); + // update menu + PostRefreshMessage(); + } + } + + // activate the top non-destroyed menu + for (int i=(int)s_Menus.size()-1;i>=0;i--) + if (!s_Menus[i]->m_bDestroyed) + { + SetForegroundWindow(s_Menus[i]->m_hWnd); + s_Menus[i]->SetActiveWindow(); + break; + } + + return true; +} + +void CMenuContainer::SetDropTip( IDataObject *pDataObj, bool bPin ) +{ + DROPDESCRIPTION desc={bPin?DROPIMAGE_LINK:DROPIMAGE_INVALID}; + Strcpy(desc.szMessage,_countof(desc.szMessage),bPin?FindTranslation(L"Menu.PinStart",L"Pin to Start menu"):L""); + HGLOBAL hDesc=GlobalAlloc(GMEM_MOVEABLE,sizeof(desc)); + if (hDesc) + { + memcpy(GlobalLock(hDesc),&desc,sizeof(desc)); + GlobalUnlock(hDesc); + FORMATETC fmte={CMenuContainer::s_DropDescriptionFormat,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}; + STGMEDIUM medium={}; + medium.tymed=TYMED_HGLOBAL; + medium.hGlobal=hDesc; + + if (FAILED(pDataObj->SetData(&fmte,&medium,TRUE))) + { + GlobalFree(hDesc); + } + } +} + +void CMenuContainer::GetDragEffect( DWORD &grfKeyState, DWORD *pdwEffect ) +{ + grfKeyState&=MK_SHIFT|MK_CONTROL|MK_ALT; + if (s_bNoDragDrop || !(m_Options&CONTAINER_DROP)) + { + *pdwEffect=DROPEFFECT_NONE; // can't drop here + return; + } + if (!m_pDropFolder[0] && !(s_pDragSource==this && s_bDragMovable && !s_bDragFromTree)) + { + *pdwEffect=DROPEFFECT_NONE; // can't drop here + return; + } + + // only accept known data formats + FORMATETC format1={s_ShellFormat,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}; + FORMATETC format2={s_ShellUrlFormat,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}; + FORMATETC format3={s_MetroLinkFormat,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}; + if (m_pDragObject->QueryGetData(&format1)!=S_OK && m_pDragObject->QueryGetData(&format2)!=S_OK && m_pDragObject->QueryGetData(&format3)!=S_OK) + { + *pdwEffect=DROPEFFECT_NONE; + return; + } + + if (s_pDragSource) + { + if (s_pDragSource->m_Items[s_pDragSource->m_DragIndex].id==MENU_RECENT) + *pdwEffect&=DROPEFFECT_LINK; // dragging a recent item (allow only link) + else if (grfKeyState==0 && !s_bRightDrag && s_pDragSource==this && s_bDragMovable && !s_bDragFromTree) + *pdwEffect&=DROPEFFECT_MOVE; // dragging within the same menu - use move by default + else if (grfKeyState==0 && !s_bRightDrag) + *pdwEffect&=(s_bDragMovable && m_bSubMenu && (s_pDragSource->m_Options&CONTAINER_PROGRAMS))?DROPEFFECT_MOVE:DROPEFFECT_LINK; // dragging normal item to a different menu - default to move or link + } + + if (m_pDragObject->QueryGetData(&format3)==S_OK) + { + if (m_Options&CONTAINER_APPS) + *pdwEffect&=(s_pDragSource==this && !s_bDragFromTree)?DROPEFFECT_MOVE:DROPEFFECT_NONE; // dragging a metro link to Apps folder + else + *pdwEffect&=DROPEFFECT_LINK; // dragging a metro link to another folder + } + + // handle keys + if (!s_bRightDrag) + { + if (grfKeyState==MK_SHIFT) + *pdwEffect&=DROPEFFECT_MOVE; + if (grfKeyState==MK_CONTROL) + *pdwEffect&=DROPEFFECT_COPY; + if (grfKeyState==(MK_CONTROL|MK_SHIFT) || grfKeyState==MK_ALT) + *pdwEffect&=DROPEFFECT_LINK; + } + else if (!m_bSubMenu && grfKeyState==0 && (*pdwEffect&DROPEFFECT_LINK)) + { + // when a file is dragged to the start menu he usually wants to make a shortcut + // so when right-dragging, and linking is allowed, make it the default + grfKeyState=MK_SHIFT|MK_CONTROL; + } +} + +HRESULT STDMETHODCALLTYPE CMenuContainer::DragEnter( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ) +{ + s_bRightDrag=(grfKeyState&MK_RBUTTON)!=0; + m_pDragObject=pDataObj; + if (m_pDropTargetHelper) + { + POINT p={pt.x,pt.y}; + m_pDropTargetHelper->DragEnter(m_hWnd,m_pDragObject,&p,*pdwEffect); + } + if (!m_bSubMenu && !s_bShowTopEmpty) + { + // when dragging over the main menu, show an (Empty) item at the top so the user can drop items there + for (size_t i=0;i0 && m_FolderHash[0]) + s_MenuScrolls[m_FolderHash[0]]=m_ScrollOffset; + else + s_MenuScrolls.erase(m_FolderHash[0]); + InitWindow(); + break; + } + } + m_DragHoverTime=GetMessageTime()-10000; + m_DragHoverItem=-1; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuContainer::DragOver( DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ) +{ + POINT p0={pt.x,pt.y}; + if (m_pDropTargetHelper) + m_pDropTargetHelper->DragOver(&p0,*pdwEffect); + + POINT p=p0; + ScreenToClient(&p); + int index=HitTest(p,NULL,true); + + int mark=-1; + bool bAfter=false; + + const CItemManager::ItemInfo *pInfo=NULL; + RECT rcItem; + if (index>=0) + { + GetItemRect(index,rcItem); + if (!m_bSubMenu && index=rcItem.top+h && p.yDragLeave(); + m_pDropTarget=NULL; + } + if (pInfo && pInfo->GetPidl()) + { + m_pDropTargetInfo=pInfo; + CComPtr pItem; + SHCreateItemFromIDList(pInfo->GetPidl(),IID_IShellItem,(void**)&pItem); + if (pItem) + { + pItem->BindToHandler(NULL,BHID_SFUIObject,IID_IDropTarget,(void**)&m_pDropTarget); + if (m_pDropTarget) + { + m_pDropTarget->DragEnter(m_pDragObject,grfKeyState,pt,pdwEffect); + if (*pdwEffect==0) + m_pDropTargetInfo=NULL; + } + } + } + else + m_pDropTargetInfo=NULL; + } + if (!m_pDropTargetInfo) + { + dropTargetIndex=-1; + m_pDropTarget=NULL; + } + if (dropTargetIndex!=m_DropTargetIndex) + { + InvalidateItem(dropTargetIndex); + InvalidateItem(m_DropTargetIndex); + m_DropTargetIndex=dropTargetIndex; + } + if (m_pDropTarget) + { + SetDropTip(m_pDragObject,false); + SetInsertMark(-1,false); + return m_pDropTarget->DragOver(grfKeyState,pt,pdwEffect); + } + + s_bRightDrag=(grfKeyState&MK_RBUTTON)!=0; + GetDragEffect(grfKeyState,pdwEffect); + + if (index>=0 && index=0 && index>=0 && m_Items[index].jumpIndex>=0) + { + int groupIndex=LOWORD(m_Items[m_DragIndex].jumpIndex); + if (s_JumpList.groups[groupIndex].type==CJumpGroup::TYPE_PINNED && LOWORD(m_Items[index].jumpIndex)==groupIndex && (*pdwEffect&DROPEFFECT_MOVE)) + { + // reorder jump list + *pdwEffect=DROPEFFECT_MOVE; + int y=(rcItem.top+rcItem.bottom)/2; + bAfter=p.y>=y; + SetHotItem(-1); + } + else + index=-1; + mark=index; + } + else + { + if (!m_bSubMenu && index=0 && index==m_DragHoverItem) + { + int hoverTime=(int)s_HoverTime; + if (m_Items[index].id==MENU_PROGRAMS && GetSettingInt(L"ProgramsStyle")==PROGRAMS_INLINE) + hoverTime=(int)s_ProgramsHoverTime; + if ((GetMessageTime()-m_DragHoverTime)>hoverTime && m_Submenu!=m_DragHoverItem) + { + // expand m_DragHoverItem + if (index=0 && m_bInsertAfter && (before!=0 || (m_Items[0].id!=MENU_EMPTY && m_Items[0].id!=MENU_EMPTY_TOP))) + before++; + if (before>=0 && !m_bSubMenu && (*pdwEffect&DROPEFFECT_LINK) && (s_pDragSource!=this || s_bDragFromTree || !s_bDragMovable)) + { + *pdwEffect=DROPEFFECT_LINK; + SetDropTip(m_pDragObject,true); + } + else + SetDropTip(m_pDragObject,false); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuContainer::DragLeave( void ) +{ + if (m_pDropTarget) + { + m_pDropTarget->DragLeave(); + m_pDropTarget=NULL; + } + InvalidateItem(m_DropTargetIndex); + m_DropTargetIndex=-1; + m_pDropTargetInfo=NULL; + if (m_pDropTargetHelper) + m_pDropTargetHelper->DragLeave(); + SetDropTip(m_pDragObject,false); + SetInsertMark(-1,false); + m_pDragObject=NULL; + UpdateScroll(NULL,false); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuContainer::Drop( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ) +{ + if (s_pDragSource) + { + if (!s_pDragSource->m_bDestroyed) + s_pDragSource->KillTimer(TIMER_DRAG); + } + if (m_pDropTargetHelper) + { + POINT p={pt.x,pt.y}; + m_pDropTargetHelper->Drop(pDataObj,&p,*pdwEffect); + } + if (m_pDropTarget) + { + m_pDragObject=NULL; + HRESULT res=m_pDropTarget->Drop(pDataObj,grfKeyState,pt,pdwEffect); + m_pDropTarget=NULL; + return res; + } + + GetDragEffect(grfKeyState,pdwEffect); + m_pDragObject=NULL; + + int before=m_InsertMark; + if (before<0) return S_OK; + if (before>=0 && m_bInsertAfter && (before!=0 || (m_Items[0].id!=MENU_EMPTY && m_Items[0].id!=MENU_EMPTY_TOP))) + before++; + + // clear the insert mark + SetInsertMark(-1,false); + + int folderIndex=0; + if (before>=0) + folderIndex=m_Items[min(before,(int)m_Items.size()-1)].priority>1?1:0; + + if (s_pDragSource==this && !s_bDragFromTree && s_bDragMovable && (*pdwEffect&DROPEFFECT_MOVE) && m_DragIndex!=m_ProgramTreeIndex && m_Items[m_DragIndex].priority==(m_Items[min(before,(int)m_Items.size()-1)].priority&2)) + { + if (before==m_DragIndex || before==m_DragIndex+1) + return S_OK; + // dropped in the same menu, just rearrange the items + PlayMenuSound(SOUND_DROP); + if (m_Items[m_DragIndex].jumpIndex>=0 && s_JumpList.groups[LOWORD(m_Items[m_DragIndex].jumpIndex)].type==CJumpGroup::TYPE_PINNED) + { + // reordering pinned item + int groupIdx=LOWORD(m_Items[m_DragIndex].jumpIndex); + int itemIdx=HIWORD(m_Items[m_DragIndex].jumpIndex); + for (int i=0;i<=m_DragIndex;i++) + { + if (m_Items[i].jumpIndex>=0 && LOWORD(m_Items[i].jumpIndex)==groupIdx) + { + // found first pinned index + PinJumpItem(s_JumpAppInfo,s_JumpList,groupIdx,itemIdx,true,before-i); + PostRefreshMessage(); + break; + } + } + } + else if (!(m_Options&CONTAINER_AUTOSORT)) + { + std::vector items; + int skip1=0, skip2=0; + for (int i=0;im_DragIndex-skip1) + before--; + items.insert(items.begin()+(before-skip2),drag); + SaveItemOrder(items); + if (m_bTwoColumns && s_MenuMode==MODE_JUMPLIST) + SetMenuMode(MODE_NORMAL); + PostRefreshMessage(); + } + } + else if (m_pDropFolder[folderIndex]) + { + // simulate dropping the object into the original folder + PlayMenuSound(SOUND_DROP); + + if (before>=0 && !m_bSubMenu && (*pdwEffect&DROPEFFECT_LINK) && (s_pDragSource!=this || s_bDragFromTree || !s_bDragMovable)) + *pdwEffect=DROPEFFECT_LINK; + + bool bDropped=false; + if (!m_bSubMenu && (*pdwEffect&DROPEFFECT_LINK) && !s_bRightDrag) + { + // if dropping a single folder onto the main menu, create a fake folder + CComPtr pArray; + if (SUCCEEDED(SHCreateShellItemArrayFromDataObject(pDataObj,IID_IShellItemArray,(void**)&pArray))) + { + DWORD count; + CComPtr pItem; + if (SUCCEEDED(pArray->GetCount(&count)) && count==1 && SUCCEEDED(pArray->GetItemAt(0,&pItem))) + { + CComString pPath; + if (pItem->GetDisplayName(SIGDN_FILESYSPATH,&pPath)==S_OK && PathIsDirectory(pPath)) + { + wchar_t path[_MAX_PATH]; + if (SUCCEEDED(SHGetPathFromIDList(m_Path1[0],path))) + { + wchar_t fname[_MAX_FNAME]; + Strcpy(fname,_countof(fname),PathFindFileName(pPath)); + int len=Strlen(fname); + while (len>0 && (fname[len-1]=='\\' || fname[len-1]==':')) + len--; + fname[len]=0; + PathAppend(path,fname); + wchar_t finalPath[_MAX_PATH]; + PathYetAnotherMakeUniqueName(finalPath,path,NULL,PathFindFileName(path)); + if (CreateFakeFolder(pPath,finalPath)) + { + bDropped=true; + wchar_t locName[_MAX_PATH]; + int locIndex; + if (SHGetLocalizedName(pPath,locName,_countof(locName),&locIndex)==S_OK) + { + SHSetLocalizedName(finalPath,locName,locIndex); + } + } + } + } + } + } + } + if (!bDropped) + { + // must use IShellFolder to get to the drop target because the BindToHandler doesn't support passing the parent window (easily) + CComPtr pDesktop; + SHGetDesktopFolder(&pDesktop); + CComPtr pFolder; + CComPtr pTarget; + if (!pDesktop || FAILED(pDesktop->BindToObject(m_Path1[folderIndex],NULL,IID_IShellFolder,(void**)&pFolder)) || FAILED(pFolder->CreateViewObject(g_OwnerWindow,IID_IDropTarget,(void**)&pTarget))) + return S_OK; + + DWORD dwEffect=*pdwEffect; + + if (s_bRightDrag) + { + if (FAILED(pTarget->DragEnter(pDataObj,MK_RBUTTON|grfKeyState,pt,&dwEffect))) + return S_OK; + dwEffect=*pdwEffect; + pTarget->DragOver(MK_RBUTTON|grfKeyState,pt,&dwEffect); + } + else + { + if (FAILED(pTarget->DragEnter(pDataObj,MK_LBUTTON|grfKeyState,pt,&dwEffect))) + return S_OK; + dwEffect=*pdwEffect; + pTarget->DragOver(MK_LBUTTON|grfKeyState,pt,pdwEffect); + } + CComQIPtr pAsync=pDataObj; + if (pAsync) + pAsync->SetAsyncMode(FALSE); + for (std::vector::iterator it=s_Menus.begin();it!=s_Menus.end();++it) + if (!(*it)->m_bDestroyed) + (*it)->EnableWindow(FALSE); // disable all menus + bool bAllPrograms=s_bAllPrograms; + if (bAllPrograms) ::EnableWindow(g_TopWin7Menu,FALSE); + bool bOld=s_bPreventClosing; + s_bPreventClosing=true; + AddRef(); + pTarget->Drop(pDataObj,grfKeyState,pt,pdwEffect); + if (!bOld) + HideTemp(false); + s_bPreventClosing=bOld; + for (std::vector::iterator it=s_Menus.begin();it!=s_Menus.end();++it) + if (!(*it)->m_bDestroyed) + (*it)->EnableWindow(TRUE); // enable all menus + if (bAllPrograms) ::EnableWindow(g_TopWin7Menu,TRUE); + } + else + { + AddRef(); + } + + if (!m_bDestroyed) + { + SetForegroundWindow(m_hWnd); + SetActiveWindow(); + SetFocus(); + } + + if (before>=0 && !(m_Options&CONTAINER_AUTOSORT)) + { + std::vector items; + int skip=0; + for (int i=0;iDragEnter(pDataObj,grfKeyState,pt,pdwEffect); +} + +HRESULT STDMETHODCALLTYPE CDropTargetProxy::DragOver( DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ) +{ + if (!m_pOwner) return E_FAIL; + return m_pOwner->DragOver(grfKeyState,pt,pdwEffect); +} + +HRESULT STDMETHODCALLTYPE CDropTargetProxy::DragLeave( void ) +{ + if (!m_pOwner) return E_FAIL; + return m_pOwner->DragLeave(); +} + +HRESULT STDMETHODCALLTYPE CDropTargetProxy::Drop( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ) +{ + if (!m_pOwner) return E_FAIL; + return m_pOwner->Drop(pDataObj,grfKeyState,pt,pdwEffect); +} diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/DragDrop.h b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/DragDrop.h new file mode 100644 index 0000000..dd395e3 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/DragDrop.h @@ -0,0 +1,60 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +// CDropTargetProxy - a wrapper for another object's IDropTarget. On Windows 8.1 the interface is not properly released +// when the window is destroyed during a drag operation. So the wrapper is used as a decoy to minimize the leaked resources +class CDropTargetProxy: public IDropTarget +{ +public: + CDropTargetProxy( IDropTarget *pOwner ) + { + m_pOwner=pOwner; + m_RefCount=0; + } + + ~CDropTargetProxy( void ) + { + } + + void Reset( void ) + { + m_pOwner=NULL; + } + + // IUnknown + virtual STDMETHODIMP QueryInterface( REFIID riid, void **ppvObject ) + { + *ppvObject=NULL; + if (IID_IUnknown==riid || IID_IDropTarget==riid) + { + AddRef(); + *ppvObject=static_cast(this); + return S_OK; + } + return E_NOINTERFACE; + } + + virtual ULONG STDMETHODCALLTYPE AddRef( void ) + { + return InterlockedIncrement(&m_RefCount); + } + + virtual ULONG STDMETHODCALLTYPE Release( void ) + { + long nTemp=InterlockedDecrement(&m_RefCount); + if (!nTemp) delete this; + return nTemp; + } + + // IDropTarget + virtual HRESULT STDMETHODCALLTYPE DragEnter( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ); + virtual HRESULT STDMETHODCALLTYPE DragOver( DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ); + virtual HRESULT STDMETHODCALLTYPE DragLeave( void ); + virtual HRESULT STDMETHODCALLTYPE Drop( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ); + +private: + IDropTarget *m_pOwner; + LONG m_RefCount; +}; diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ItemManager.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ItemManager.cpp new file mode 100644 index 0000000..9d1ed82 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ItemManager.cpp @@ -0,0 +1,3808 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "ItemManager.h" +#include "MetroLinkManager.h" +#include "FNVHash.h" +#include "Settings.h" +#include "SettingsUI.h" +#include "Translations.h" +#include "ResourceHelper.h" +#include "MenuContainer.h" +#include "LogManager.h" +#include "ClassicStartMenuDLL.h" +#include "resource.h" +#include +#include +#include +#include + +//#define DISABLE_CACHE +//#define FORCE_ALL_NEW + +#ifdef BUILD_SETUP +#undef DISABLE_CACHE +#undef FORCE_ALL_NEW +#endif + +#ifdef _DEBUG +_declspec(thread) int CItemManager::RWLock::g_LockState[CItemManager::RWLOCK_COUNT]; // 0 - none, 1 - read, 2 - write +#endif + +static bool g_bInvertMetroIcons; + +const int MAX_FOLDER_LEVELS=10; // don't go more than 10 levels deep +const int REFRESH_DELAY=5000; +const int CACHE_FILE_VERSION=2; + +PROPERTYKEY PKEY_MetroIcon={{0x86D40B4D, 0x9069, 0x443C, {0x81, 0x9A, 0x2A, 0x54, 0x09, 0x0D, 0xCC, 0xEC}}, 2}; + +// app ID resolver interface as described here: http://www.binrand.com/post/1510934-out-using-system-using-system-collections-generic-using-system.html +interface IApplicationResolver: public IUnknown +{ + STDMETHOD(GetAppIDForShortcut)( IShellItem *psi, LPWSTR *ppszAppID ); + // .... we don't care about the rest of the methods .... +}; + +GUID CLSID_ApplicationResolver={0x660b90c8,0x73a9,0x4b58,{0x8c,0xae,0x35,0x5b,0x7f,0x55,0x34,0x1b}}; +// different IIDs for Win8 and Win8: http://a-whiter.livejournal.com/1266.html +GUID IID_IApplicationResolver7={0x46a6eeff,0x908e,0x4dc6,{0x92,0xa6,0x64,0xbe,0x91,0x77,0xb4,0x1c}}; +GUID IID_IApplicationResolver8={0xde25675a,0x72de,0x44b4,{0x93,0x73,0x05,0x17,0x04,0x50,0xc1,0x40}}; + +/////////////////////////////////////////////////////////////////////////////// + +interface IResourceContext; + +const GUID IID_IResourceMap={0x6e21e72b, 0xb9b0, 0x42ae, {0xa6, 0x86, 0x98, 0x3c, 0xf7, 0x84, 0xed, 0xcd}}; +interface IResourceMap : public IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE GetUri(const wchar_t **pUri ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetSubtree(const wchar_t *propName, IResourceMap **pSubTree ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetString( const wchar_t *propName, wchar_t *pString ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetStringForContext( IResourceContext *pContext, const wchar_t *propName, wchar_t *pString ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFilePath( const wchar_t *propName, wchar_t **pPath ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFilePathForContext( IResourceContext *pContext, const wchar_t *propName, wchar_t **pPath ) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// + +enum RESOURCE_SCALE +{ + RES_SCALE_100=0, + RES_SCALE_140=1, + RES_SCALE_180=2, + RES_SCALE_80 =3, +}; + +const GUID IID_ResourceContext={0xe3c22b30, 0x8502, 0x4b2f, {0x91, 0x33, 0x55, 0x96, 0x74, 0x58, 0x7e, 0x51}}; +interface IResourceContext : public IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE GetLanguage( void ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetHomeRegion( wchar_t *pRegion ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetLayoutDirection( enum RESOURCE_LAYOUT_DIRECTION *pDirection ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetTargetSize( WORD *pSize ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetScale( RESOURCE_SCALE *pScale ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetContrast( enum RESOURCE_CONTRAST *pContrast ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetAlternateForm( wchar_t *pForm ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetQualifierValue( const wchar_t *name, wchar_t *pValue ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetLanguage( const wchar_t *language ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetHomeRegion( const wchar_t *region ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetLayoutDirection( enum RESOURCE_LAYOUT_DIRECTION direction ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetTargetSize( WORD size ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetScale( RESOURCE_SCALE scale ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetContrast( void ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetAlternateForm( const wchar_t *form ) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// + +const CLSID CLSID_ResourceManager={0xdbce7e40, 0x7345, 0x439d, {0xb1, 0x2c, 0x11, 0x4a, 0x11, 0x81, 0x9a, 0x09}}; +MIDL_INTERFACE("130a2f65-2be7-4309-9a58-a9052ff2b61c") +IResourceManager : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE Initialize( void ) = 0; + virtual HRESULT STDMETHODCALLTYPE InitializeForCurrentApplication( void ) = 0; + virtual HRESULT STDMETHODCALLTYPE InitializeForPackage( const wchar_t *name ) = 0; + virtual HRESULT STDMETHODCALLTYPE InitializeForFile( const wchar_t *fname ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetMainResourceMap( REFIID riid, void **ppvObject ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetResourceMap( void ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDefaultContext( REFIID riid, void **ppvObject ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetReference( void ) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// + +extern PROPERTYKEY PKEY_MetroPackagePath; +extern PROPERTYKEY PKEY_MetroPackageName; + +static CComPtr g_pAppResolver; + +// Creates the app id resolver object +static void CreateAppResolver( void ) +{ + if (GetWinVersion()>=WIN_VER_WIN7) + { + CComPtr pUnknown; + pUnknown.CoCreateInstance(CLSID_ApplicationResolver); + if (GetWinVersion()==WIN_VER_WIN7) + g_pAppResolver=CComQIPtr(pUnknown); + else + g_pAppResolver=CComQIPtr(pUnknown); + } +} + +static bool DetectGrayscaleImage( const unsigned int *bits, int stride, int width, int height ) +{ + int transparent=0; + for (int y=0;y>16)&255; + int g=(pixel>>8)&255; + int b=(pixel)&255; + if (abs(r-g)>2 || abs(r-b)>2 || abs(g-b)>2) + return false; // found colored pixel + if (!(pixel&0xFF000000)) + transparent++; + } + } + if ((transparent*100)/(width*height)<5) + return false; // less than 5% transparent pixels + return true; +} + +static void CreateMonochromeImage( unsigned int *bits, int stride, int width, int height, DWORD metroColor ) +{ + int r0=(metroColor)&255; + int g0=(metroColor>>8)&255; + int b0=(metroColor>>16)&255; + for (int y=0;y>24; + int r=(r0*a)/255; + int g=(g0*a)/255; + int b=(b0*a)/255; + pixel=(a<<24)|(r<<16)|(g<<8)|b; + } + } +} + +static HBITMAP BitmapFromMetroIcon( HICON hIcon, int bitmapSize, int iconSize, DWORD metroColor, bool bDestroyIcon=true ) +{ + ICONINFO info; + BITMAP bmpInfo; + GetIconInfo(hIcon,&info); + AddTrackedObject(info.hbmColor); + AddTrackedObject(info.hbmMask); + if (info.hbmColor) + { + GetObject(info.hbmColor,sizeof(bmpInfo),&bmpInfo); + iconSize=bmpInfo.bmWidth; + if (iconSize>bitmapSize) + iconSize=bitmapSize; + } + if (info.hbmColor) DeleteObject(info.hbmColor); + if (info.hbmMask) DeleteObject(info.hbmMask); + + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=bi.bmiHeader.biHeight=bitmapSize; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + RECT rc={0,0,bitmapSize,bitmapSize}; + + HDC hdc=CreateCompatibleDC(NULL); + unsigned int *bits; + HBITMAP bmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&bits,NULL,0); + HGDIOBJ bmp0=SelectObject(hdc,bmp); + int offset=(bitmapSize-iconSize)/2; + bool bInvert=g_bInvertMetroIcons; + if (g_bInvertMetroIcons) + { + FillRect(hdc,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH)); + DrawIconEx(hdc,offset,offset,hIcon,iconSize,iconSize,0,NULL,DI_NORMAL); + SelectObject(hdc,bmp0); + unsigned int *bits2=bits+offset*(bitmapSize+1); + if (DetectGrayscaleImage(bits2,bitmapSize,iconSize,iconSize)) + { + CreateMonochromeImage(bits2,bitmapSize,iconSize,iconSize,metroColor); + } + else + { + SelectObject(hdc,bmp); + bInvert=false; + } + } + + if (!bInvert) + { + SetDCBrushColor(hdc,metroColor&0xFFFFFF); + FillRect(hdc,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + DrawIconEx(hdc,offset,offset,hIcon,iconSize,iconSize,0,NULL,DI_NORMAL); + SelectObject(hdc,bmp0); + int n=bitmapSize*bitmapSize; + for (int i=0;i='0' && scale[0]<='9' && scale[1]>='0' && scale[1]<='9') + { + int digits=2; + while (scale[digits]>='0' && scale[digits]<='9') + digits++; + scale[0]='%'; + scale[1]='d'; + if (digits>2) + memmove(scale+2,scale+digits,Strlen(scale+digits)*2+2); + return true; + } + } + else + scale+=6; + location=scale; + } +} + +static int g_MetroIconScales[]={80,100,140,180}; // 24, 30, 42, 54 pixels + +static HBITMAP LoadMetroBitmap( const wchar_t *location, int bitmapSize, DWORD metroColor ) +{ + // pick the best sized icon + int start; + if (bitmapSize<=26) + start=0; + else if (bitmapSize<=32) + start=1; + else if (bitmapSize<=44) + start=2; + else + start=3; + wchar_t path[_MAX_PATH]; + bool bFound=false; + for (int i=start;i<_countof(g_MetroIconScales);i++) // correct size or bigger (will scale down) + { + Sprintf(path,_countof(path),location,g_MetroIconScales[i]); + if (GetFileAttributes(path)!=INVALID_FILE_ATTRIBUTES) + { + bFound=true; + break; + } + } + if (!bFound) + { + for (int i=start-1;i>=0;i--) // smaller (will scale up) + { + Sprintf(path,_countof(path),location,g_MetroIconScales[i]); + if (GetFileAttributes(path)!=INVALID_FILE_ATTRIBUTES) + { + bFound=true; + break; + } + } + } + if (bFound) + { + SIZE size={2-bitmapSize,bitmapSize-2}; + HBITMAP hBitmap=LoadImageFile(path,&size,true,true,NULL); + if (hBitmap) + return BitmapFromMetroBitmap(hBitmap,bitmapSize,metroColor); + } + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +static bool ParseMetroBitmapLocation2( wchar_t *location ) +{ + CharUpper(location); + wchar_t *png=wcswcs(location,L".PNG-"); + if (!png) return false; + Strcpy(png,100,L".TARGETSIZE-%d.PNG"); + return true; +} + +static int g_MetroIconSizes2[]={16,20,24,32,40,48,64}; + +static HBITMAP LoadMetroBitmap2( const wchar_t *location, int bitmapSize, DWORD metroColor ) +{ + // pick the best sized icon + int start=-1; + for (int i=0;i<_countof(g_MetroIconSizes2);i++) + { + if (g_MetroIconSizes2[i]>=bitmapSize) + break; + start++; + } + if (start<0) start=0; + wchar_t path[_MAX_PATH]; + int iconSize=0; + for (int i=start;i<_countof(g_MetroIconSizes2);i++) // correct size or bigger (will scale down) + { + Sprintf(path,_countof(path),location,g_MetroIconSizes2[i]); + if (GetFileAttributes(path)!=INVALID_FILE_ATTRIBUTES) + { + iconSize=g_MetroIconSizes2[i]; + break; + } + } + if (!iconSize) + { + for (int i=start-1;i>=0;i--) // smaller (will scale up) + { + Sprintf(path,_countof(path),location,g_MetroIconSizes2[i]); + if (GetFileAttributes(path)!=INVALID_FILE_ATTRIBUTES) + { + iconSize=g_MetroIconSizes2[i]; + break; + } + } + } + if (iconSize) + { + if (g_bInvertMetroIcons) + { + if (iconSize>bitmapSize) + iconSize=bitmapSize; + } + else + { + if (iconSize>bitmapSize-2) + iconSize=bitmapSize-2; + } + SIZE size={iconSize,iconSize}; + HBITMAP hBitmap=LoadImageFile(path,&size,true,true,NULL); + if (hBitmap) + return BitmapFromMetroBitmap(hBitmap,bitmapSize,metroColor); + } + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +void CItemManager::LoadIconData::Init( void ) +{ + m_IconSizes[0]=SMALL_ICON_SIZE; + m_IconSizes[1]=LARGE_ICON_SIZE; + m_IconSizes[2]=EXTRA_LARGE_ICON_SIZE; + m_IconSizes[3]=SMALL_ICON_SIZE-2; + m_IconSizes[4]=LARGE_ICON_SIZE-2; + m_IconSizes[5]=EXTRA_LARGE_ICON_SIZE-2; + + for (int i=0;i<_countof(m_TempLists);i++) + { + m_TempLists[i]=ImageList_Create(m_IconSizes[i],m_IconSizes[i],ILC_COLOR32,0,1); + if (m_TempLists[i]) + { + ImageList_SetImageCount(m_TempLists[i],1); + HIMAGELIST_QueryInterface(m_TempLists[i],IID_IImageList2,(void**)&m_pTempLists[i]); + } + } + m_pFactory.CoCreateInstance(CLSID_WICImagingFactory); +} + +void CItemManager::LoadIconData::Close( void ) +{ + for (int i=0;i<_countof(m_TempLists);i++) + { + m_pTempLists[i]=NULL; + if (m_TempLists[i]) + ImageList_Destroy(m_TempLists[i]); + } + m_pFactory=NULL; +} + +int CItemManager::SMALL_ICON_SIZE; +int CItemManager::LARGE_ICON_SIZE; +int CItemManager::EXTRA_LARGE_ICON_SIZE=64; +int CItemManager::s_DPI; +int CItemManager::s_DPIOverride; + +CItemManager g_ItemManager; + +CItemManager::CItemManager( void ) +{ + m_bInitialized=false; + + memset(m_CriticalSections,0,sizeof(m_CriticalSections)); + memset(m_CriticalSectionOwners,0,sizeof(m_CriticalSectionOwners)); + m_StartEvent=m_WorkEvent=m_ExitEvent=m_DoneEvent=m_PreloadItemsThread=m_RefreshInfoThread=m_SaveCacheThread=NULL; + m_MainThreadId=m_PreloadItemsThreadId=m_RefreshInfoThreadId=0; + m_DefaultSmallIcon=m_DefaultLargeIcon=m_DefaultExtraLargeIcon=NULL; + m_bHasNewPrograms[0]=m_bHasNewPrograms[1]=m_bHasNewApps[0]=m_bHasNewApps[1]=m_bPreloadIcons=m_bPreloadFavorites=false; + m_LoadingStage=LOAD_STOPPED; + m_LastCacheSave=0; + m_TransientHash=1; +} + +CItemManager::~CItemManager( void ) +{ + Close(); +} + +void CItemManager::Init( void ) +{ + m_MainThreadId=GetCurrentThreadId(); + + { + // get the DPI setting + HDC hdc=GetDC(NULL); + s_DPI=GetDeviceCaps(hdc,LOGPIXELSY); + ReleaseDC(NULL,hdc); + s_DPIOverride=GetSettingInt(L"OverrideDPI"); + if (s_DPIOverride!=0) + { + if (s_DPIOverride<96) s_DPIOverride=96; + if (s_DPIOverride>480) s_DPIOverride=480; + } + } + + SMALL_ICON_SIZE=GetSettingInt(L"SmallIconSize"); + LARGE_ICON_SIZE=GetSettingInt(L"LargeIconSize"); + m_OldSysAccentColor=GetSystemAccentColor(); + g_bInvertMetroIcons=GetSettingBool(L"InvertMetroIcons"); + m_bOldInvertIcons=g_bInvertMetroIcons; + m_LoadIconData[0].Init(); + + bool bRTL=IsLanguageRTL(); + + CComString pPath; + if (SUCCEEDED(ShGetKnownFolderPath(FOLDERID_StartMenu,&pPath))) + { + m_RootStartMenu1=pPath; + m_RootStartMenu1+=L"\\"; + StringUpper(m_RootStartMenu1); + } + pPath.Clear(); + if (SUCCEEDED(ShGetKnownFolderPath(FOLDERID_CommonStartMenu,&pPath))) + { + m_RootStartMenu2=pPath; + m_RootStartMenu2+=L"\\"; + StringUpper(m_RootStartMenu2); + } + pPath.Clear(); + if (SUCCEEDED(ShGetKnownFolderPath(FOLDERID_CommonPrograms,&pPath))) + { + m_RootCommonPrograms=pPath; + m_RootCommonPrograms+=L"\\"; + StringUpper(m_RootCommonPrograms); + } + pPath.Clear(); + if (SUCCEEDED(ShGetKnownFolderPath(FOLDERID_Desktop,&pPath))) + { + m_RootDesktop=pPath; + m_RootDesktop+=L"\\"; + StringUpper(m_RootDesktop); + } + pPath.Clear(); + + m_RootGames=L"::{ED228FDF-9EA8-4870-83B1-96B02CFE0D52}\\"; + wchar_t text[_MAX_PATH]; + Strcpy(text,_countof(text),START_MENU_PINNED_ROOT L"\\"); + DoEnvironmentSubst(text,_countof(text)); + m_RootStartMenu3=text; + StringUpper(m_RootStartMenu3); + Strcpy(text,_countof(text),TASKBAR_PINNED_ROOT L"\\"); + DoEnvironmentSubst(text,_countof(text)); + m_RootTaskbar=text; + StringUpper(m_RootTaskbar); + Strcpy(text,_countof(text),METRO_APP_ROOT L"\\"); + DoEnvironmentSubst(text,_countof(text)); + m_RootMetro=text; + StringUpper(m_RootMetro); + + for (int i=0;i<=SHIL_LAST;i++) + { + CComPtr pList; + if (SUCCEEDED(SHGetImageList(i,IID_IImageList,(void**)&pList))) + { + int width, height; + pList->GetIconSize(&width,&height); + m_ListSizes.push_back(std::pair(width,i)); + } + } + std::sort(m_ListSizes.begin(),m_ListSizes.end()); + + CreateDefaultIcons(); + LoadCacheFile(); + + ItemInfo &item=m_ItemInfos.insert(std::pair(0,ItemInfo()))->second; + item.bIconOnly=true; + item.smallIcon=m_DefaultSmallIcon; + item.largeIcon=m_DefaultLargeIcon; + item.extraLargeIcon=m_DefaultExtraLargeIcon; + + for (int i=0;i::const_iterator it=m_IconInfos.begin();it!=m_IconInfos.end();++it) + { + if (it->second.bitmap) + DeleteObject(it->second.bitmap); + } + + for (int i=0;i=0) + icon.bitmap=BitmapFromIcon(LoadShellIcon(index,SMALL_ICON_SIZE),SMALL_ICON_SIZE); + else + icon.bitmap=NULL; + m_DefaultSmallIcon=&m_IconInfos.insert(std::pair(0,icon))->second; + + icon.sizeType=ICON_SIZE_TYPE_LARGE; + if (index>=0) + icon.bitmap=BitmapFromIcon(LoadShellIcon(index,LARGE_ICON_SIZE),LARGE_ICON_SIZE); + else + icon.bitmap=NULL; + m_DefaultLargeIcon=&m_IconInfos.insert(std::pair(0,icon))->second; + + icon.sizeType=ICON_SIZE_TYPE_EXTRA_LARGE; + if (index>=0) + icon.bitmap=BitmapFromIcon(LoadShellIcon(index,EXTRA_LARGE_ICON_SIZE),EXTRA_LARGE_ICON_SIZE); + else + icon.bitmap=NULL; + m_DefaultExtraLargeIcon=&m_IconInfos.insert(std::pair(0,icon))->second; +} + +CItemManager::LoadIconData &CItemManager::GetLoadIconData( void ) +{ + DWORD thread=GetCurrentThreadId(); + if (thread==m_RefreshInfoThreadId) + return m_LoadIconData[2]; + if (thread==m_PreloadItemsThreadId) + return m_LoadIconData[1]; + Assert(thread==m_MainThreadId); + return m_LoadIconData[0]; +} + +void CItemManager::ResetTempIcons( void ) +{ + Assert(GetCurrentThreadId()==m_MainThreadId); + Lock cleanupLock(this,LOCK_CLEANUP); + RWLock itemLock(this,true,RWLOCK_ITEMS); + RWLock iconLock(this,true,RWLOCK_ICONS); + + COLORREF sysColor=GetSystemAccentColor(); + bool bResetMetro=m_OldSysAccentColor!=sysColor; + m_OldSysAccentColor=sysColor; + + g_bInvertMetroIcons=GetSettingBool(L"InvertMetroIcons"); + if (m_bOldInvertIcons!=g_bInvertMetroIcons) + bResetMetro=true; + m_bOldInvertIcons=g_bInvertMetroIcons; + + if (bResetMetro) + { + for (std::map::iterator it=m_MetroItemInfos10.begin();it!=m_MetroItemInfos10.end();) + { + std::map::iterator next=it; ++next; + if (it->second && !it->second->packagePath.IsEmpty()) + { + const_cast(it->second)->validFlags&=~(INFO_ICON|INFO_METRO); + m_MetroItemInfos10.erase(it); + } + it=next; + } + } + { + // remove temp items from the queue + std::list::iterator it=m_ItemQueue.begin(); + while (it!=m_ItemQueue.end()) + { + std::list::iterator next=it; ++next; + if ((*it)->bTemp) + { + Assert(!(*it)->largeIcon && !(*it)->extraLargeIcon && ((*it)->smallIcon==m_DefaultSmallIcon || (*it)->smallIcon->bTemp)); + m_ItemQueue.erase(it); + } + it=next; + } + } + + int metroFlags=bResetMetro?INFO_METRO:0; + { + // remove temp items from the cache + std::multimap::iterator it=m_ItemInfos.begin(); + while (it!=m_ItemInfos.end()) + { + std::multimap::iterator next=it; ++next; + if (it->second.bTemp) + { + Assert(it->second.largeIcon==m_DefaultLargeIcon && it->second.extraLargeIcon==m_DefaultExtraLargeIcon && (it->second.smallIcon==m_DefaultSmallIcon || it->second.smallIcon->bTemp)); + m_ItemInfos.erase(it); + } + else + { + if (it->second.smallIcon && (it->second.smallIcon->bTemp || (it->second.smallIcon->bMetro && bResetMetro))) + { + it->second.smallIcon=m_DefaultSmallIcon; + it->second.validFlags&=~(INFO_SMALL_ICON|metroFlags); + } + if (it->second.largeIcon && (it->second.largeIcon->bTemp || (it->second.largeIcon->bMetro && bResetMetro))) + { + it->second.largeIcon=m_DefaultLargeIcon; + it->second.validFlags&=~(INFO_LARGE_ICON|metroFlags); + } + if (it->second.extraLargeIcon && (it->second.extraLargeIcon->bTemp || (it->second.extraLargeIcon->bMetro && bResetMetro))) + { + it->second.extraLargeIcon=m_DefaultExtraLargeIcon; + it->second.validFlags&=~(INFO_EXTRA_LARGE_ICON|metroFlags); + } + } + it=next; + } + } + + { + // remove temp icons + std::multimap::iterator it=m_IconInfos.begin(); + while (it!=m_IconInfos.end()) + { + std::multimap::iterator next=it; ++next; + if (it->second.bTemp || (it->second.bMetro && bResetMetro)) + { + if (it->second.bitmap) + DeleteObject(it->second.bitmap); + m_IconInfos.erase(it); + } + it=next; + } + } + + { + // delete old bitmaps + for (std::vector::iterator it=m_OldBitmaps.begin();it!=m_OldBitmaps.end();++it) + DeleteObject(*it); + m_OldBitmaps.clear(); + } + m_TransientHash=1; +} + +static bool ComparePidls( PIDLIST_ABSOLUTE pidl1, PIDLIST_ABSOLUTE pidl2 ) +{ + if (!pidl1 && !pidl2) return true; + if (!pidl1 || !pidl2) return false; + int size1=ILGetSize(pidl1); + int size2=ILGetSize(pidl2); + if (size1!=size2) return false; + return memcmp(pidl1,pidl2,size1)==0; +} + +const CItemManager::ItemInfo *CItemManager::GetItemInfo( IShellItem *pItem, PIDLIST_ABSOLUTE pidl, int refreshFlags, TLocation location ) +{ + Assert(!RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); + if ((refreshFlags&INFO_METRO) && GetWinVersion()GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName); + + CString path, PATH; + unsigned int hash; + if (pName) + { + path=pName; + PATH=path; + StringUpper(PATH); + hash=CalcFNVHash(PATH); + } + else + { + hash=CalcFNVHash(pidl,ILGetSize(pidl)); + } + + FILETIME writeTime={0}, createTime={0}; + if (!path.IsEmpty()) + { + if (!MenuGetFileTimestamp(path,&writeTime,&createTime)) + { + if (refreshFlags&INFO_VALIDATE_FILE) + return NULL; + path.Empty(); + } + } + + bool bDelay=GetSettingBool(L"DelayIcons"); + ItemInfo *pInfo=NULL; + { + RWLock lock(this,true,RWLOCK_ITEMS); + std::multimap::iterator it=m_ItemInfos.find(hash); + for (;it!=m_ItemInfos.end() && it->first==hash;++it) + { + if ((!PATH.IsEmpty() && wcscmp(PATH,it->second.PATH)==0) || (PATH.IsEmpty() && ILIsEqual(pidl,it->second.GetPidl()))) + { + pInfo=&it->second; + break; + } + } + if (!pInfo) + { + pInfo=&m_ItemInfos.insert(std::pair(hash,ItemInfo()))->second; + pInfo->pidl.Clone(pidl); + pInfo->path=path; + pInfo->PATH=PATH; + pInfo->createstamp=createTime; + pInfo->writestamp=writeTime; + pInfo->smallIcon=m_DefaultSmallIcon; + pInfo->largeIcon=m_DefaultLargeIcon; + pInfo->extraLargeIcon=m_DefaultExtraLargeIcon; + pInfo->validFlags=0; + } + else + { + if (!pInfo->packagePath.IsEmpty()) + MenuGetFileTimestamp(pInfo->packagePath,&writeTime,&createTime); + if (CompareFileTime(&pInfo->writestamp,&writeTime)!=0) + { + if (!PATH.IsEmpty() && !ComparePidls(pInfo->pidl,pidl) && !ComparePidls(pInfo->newPidl,pidl)) + pInfo->newPidl.Clone(pidl); + pInfo->writestamp=writeTime; + pInfo->validFlags=0; + } + } + if (pInfo->location==LOCATION_UNKNOWN && !pInfo->PATH.IsEmpty()) + { + if (location!=LOCATION_UNKNOWN) + pInfo->location=location; + else + pInfo->location=DetermineLocation(pInfo->PATH); + } + refreshFlags&=~pInfo->validFlags; + } + + if (refreshFlags) + { + int refreshMask=bDelay?INFO_DATA:(INFO_DATA|INFO_ICON); + if (refreshFlags&refreshMask) + RefreshItemInfo(pInfo,refreshFlags&refreshMask,pItem,false); + refreshFlags&=~refreshMask; + if (refreshFlags) + { + RWLock lock(this,true,RWLOCK_ITEMS); + QueueItemInfo(pInfo,refreshFlags); + } + } + + return pInfo; +} + +const CItemManager::ItemInfo *CItemManager::GetItemInfo( CString path, int refreshFlags, TLocation location ) +{ + Assert(!RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); + Assert(!path.IsEmpty()); + if ((refreshFlags&INFO_METRO) && GetWinVersion()::iterator it=m_ItemInfos.find(hash); + for (;it!=m_ItemInfos.end() && it->first==hash;++it) + { + if (wcscmp(PATH,it->second.PATH)==0) + { + pInfo=&it->second; + break; + } + } + if (!pInfo) + { + pInfo=&m_ItemInfos.insert(std::pair(hash,ItemInfo()))->second; + if (!PATH.IsEmpty()) + MenuParseDisplayName(path,&pInfo->pidl,NULL,NULL); + if (pInfo->pidl) + pInfo->path=path; + pInfo->PATH=PATH; + pInfo->createstamp=createTime; + pInfo->writestamp=writeTime; + pInfo->smallIcon=m_DefaultSmallIcon; + pInfo->largeIcon=m_DefaultLargeIcon; + pInfo->extraLargeIcon=m_DefaultExtraLargeIcon; + pInfo->validFlags=0; + } + else + { + if (!pInfo->packagePath.IsEmpty()) + MenuGetFileTimestamp(pInfo->packagePath,&writeTime,&createTime); + if (CompareFileTime(&pInfo->writestamp,&writeTime)!=0) + { + CAbsolutePidl pidl; + if (!PATH.IsEmpty()) + MenuParseDisplayName(PATH,&pidl,NULL,NULL); + if (!ComparePidls(pInfo->pidl,pidl) && !ComparePidls(pInfo->newPidl,pidl)) + pInfo->newPidl.Swap(pidl); + pInfo->writestamp=writeTime; + pInfo->validFlags=0; + } + } + if (pInfo->location==LOCATION_UNKNOWN && !pInfo->PATH.IsEmpty()) + { + if (location!=LOCATION_UNKNOWN) + pInfo->location=location; + else + pInfo->location=DetermineLocation(pInfo->PATH); + } + refreshFlags&=~pInfo->validFlags; + } + + if (refreshFlags) + { + int refreshMask=bDelay?INFO_DATA:(INFO_DATA|INFO_ICON); + if (refreshFlags&refreshMask) + RefreshItemInfo(pInfo,refreshFlags&refreshMask,NULL,false); + refreshFlags&=~refreshMask; + if (refreshFlags) + { + RWLock lock(this,true,RWLOCK_ITEMS); + QueueItemInfo(pInfo,refreshFlags); + } + } + + return pInfo; +} + +void CItemManager::UpdateItemInfo( const ItemInfo *pInfo, int refreshFlags, bool bHasWriteLock ) +{ + if (bHasWriteLock) + { + Assert(RWLock::ThreadHasWriteLock(RWLOCK_ITEMS)); + } + else + { + Assert(!RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); + } + refreshFlags&=~pInfo->validFlags; // potentially out of lock, assuming validFlags is atomic + if (refreshFlags) + { + RWLock lock(this,true,bHasWriteLock?RWLOCK_COUNT:RWLOCK_ITEMS); + if ((refreshFlags&INFO_ICON) && !(refreshFlags&INFO_REFRESH_NOW) && GetSettingBool(L"DelayIcons")) + { + QueueItemInfo(const_cast(pInfo),refreshFlags&INFO_ICON); + refreshFlags&=~INFO_ICON; + } + if (refreshFlags) + RefreshItemInfo(const_cast(pInfo),refreshFlags,NULL,true); + } +} + +const CItemManager::ItemInfo *CItemManager::GetCustomIcon( const wchar_t *location, int index, TIconSizeType iconSizeType, bool bTemp ) +{ + Assert(!RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); + unsigned int hash=CalcFNVHash(location,CalcFNVHash(&index,4)); + ItemInfo *pInfo=NULL; + bool bDelay=GetSettingBool(L"DelayIcons"); + int refreshFlags=0; + { + RWLock lock(this,true,RWLOCK_ITEMS); + std::multimap::iterator it=m_ItemInfos.find(hash); + for (;it!=m_ItemInfos.end() && it->first==hash;++it) + { + if (it->second.bIconOnly && it->second.bTemp==bTemp) + { + pInfo=&it->second; + break; + } + } + if (!pInfo) + { + pInfo=&m_ItemInfos.insert(std::pair(hash,ItemInfo()))->second; + pInfo->bIconOnly=true; + pInfo->bTemp=bTemp; + pInfo->iconPath=location; + pInfo->iconIndex=index; + pInfo->smallIcon=m_DefaultSmallIcon; + pInfo->largeIcon=m_DefaultLargeIcon; + pInfo->extraLargeIcon=m_DefaultExtraLargeIcon; + } + + if (iconSizeType==ICON_SIZE_TYPE_SMALL) refreshFlags|=INFO_SMALL_ICON; + if (iconSizeType==ICON_SIZE_TYPE_LARGE) refreshFlags|=INFO_LARGE_ICON; + if (iconSizeType==ICON_SIZE_TYPE_EXTRA_LARGE) refreshFlags|=INFO_EXTRA_LARGE_ICON; + refreshFlags&=~pInfo->validFlags; + + if (refreshFlags && bDelay) + { + QueueItemInfo(pInfo,refreshFlags); + refreshFlags=0; + } + } + if (!bDelay && refreshFlags) + { + RefreshItemInfo(pInfo,refreshFlags,NULL,false); + } + return pInfo; +} + +const CItemManager::ItemInfo *CItemManager::GetCustomIcon( const wchar_t *path, TIconSizeType iconSizeType ) +{ + Assert(!RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); + if (!path) + { + RWLock lock(this,false,RWLOCK_ITEMS); + return &m_ItemInfos.find(0)->second; + } + wchar_t text[1024]; + Strcpy(text,_countof(text),path); + DoEnvironmentSubst(text,_countof(text)); + wchar_t *c=wcsrchr(text,','); + int index=0; + if (c) + { + *c=0; + index=-_wtol(c+1); + } + return GetCustomIcon(text,index,iconSizeType,false); +} + +const CItemManager::ItemInfo *CItemManager::GetMetroAppInfo10( const wchar_t *appid ) +{ + wchar_t APPID[256]; + Strcpy(APPID,_countof(APPID),appid); + CharUpper(APPID); + if (APPID[0]=='\\' || APPID[0]=='{' || APPID[1]==':' || wcsstr(APPID,L".AUTOGENERATED.")) + return NULL; // attempt to recognize appids that are for sure not Metro + unsigned int hash=CalcFNVHash(APPID); + const ItemInfo *pInfo=NULL; + { + RWLock lock(this,false,RWLOCK_ITEMS); + // the key is a hash of the uppercase appid + std::map::const_iterator it=m_MetroItemInfos10.find(hash); + if (it!=m_MetroItemInfos10.end()) + pInfo=it->second; + else if (m_BlackListInfos10.find(hash)!=m_BlackListInfos10.end()) + return NULL; + } + if (pInfo) + { + UpdateItemInfo(pInfo,INFO_LINK|INFO_METRO); + return pInfo; + } + + CComPtr pItem; + if (SUCCEEDED(SHCreateItemInKnownFolder(FOLDERID_AppsFolder2,0,appid,IID_IShellItem,(void**)&pItem))) + { + CAbsolutePidl pidl; + if (SUCCEEDED(SHGetIDListFromObject(pItem,&pidl))) + pInfo=GetItemInfo(pItem,pidl,INFO_LINK|INFO_METRO,LOCATION_METRO); + } + + { + RWLock lock(this,true,RWLOCK_ITEMS); + std::map::const_iterator it=m_MetroItemInfos10.find(hash); + if (it!=m_MetroItemInfos10.end() && it->second) + return it->second; + else + { + if (!pInfo) + m_BlackListInfos10.insert(hash); + if (pInfo && !pInfo->IsMetroApp()) + pInfo=NULL; + m_MetroItemInfos10[hash]=pInfo; + return pInfo; + } + } +} + +// requires LOCK_ITEMS to be held +void CItemManager::QueueItemInfo( ItemInfo *pInfo, int refreshFlags ) +{ + Assert(RWLock::ThreadHasWriteLock(RWLOCK_ITEMS)); + DWORD thread=GetCurrentThreadId(); + Assert(thread!=m_RefreshInfoThreadId); + pInfo->refreshFlags|=refreshFlags&~pInfo->validFlags&(INFO_DATA|INFO_ICON); + if (pInfo->refreshFlags) + { + std::list &queue=(thread==m_PreloadItemsThreadId)?m_ItemQueueLow:m_ItemQueue; + for (std::list::const_iterator it=queue.begin();it!=queue.end();++it) + { + if (*it==pInfo) + return; + } + queue.push_back(pInfo); + SetEvent(m_WorkEvent); + if (thread!=m_PreloadItemsThreadId) + SetEvent(m_StartEvent); + } +} + +void CItemManager::WaitForShortcuts( const POINT &balloonPos ) +{ + if (m_PreloadItemsThreadId) + { + if (WaitForSingleObject(m_DoneEvent,1000)!=WAIT_TIMEOUT) + return; + CWindow tooltip=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|(IsLanguageRTL()?WS_EX_LAYOUTRTL:0),TOOLTIPS_CLASS,NULL,WS_POPUP|TTS_BALLOON|TTS_NOPREFIX,0,0,0,0,NULL,NULL,g_Instance,NULL); + tooltip.SendMessage(TTM_SETMAXTIPWIDTH,0,500); + TOOLINFO tool={sizeof(tool),TTF_TRANSPARENT|TTF_TRACK|(IsLanguageRTL()?TTF_RTLREADING:0)}; + tool.uId=1; + CString message=LoadStringEx(IDS_MENU_BUSY); + tool.lpszText=(LPWSTR)(const wchar_t*)message; + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + tooltip.SendMessage(TTM_SETTITLE,TTI_INFO,(LPARAM)(const wchar_t*)LoadStringEx(IDS_APP_TITLE)); + tooltip.SendMessage(TTM_TRACKPOSITION,0,MAKELONG(balloonPos.x,balloonPos.y)); + tooltip.SendMessage(TTM_TRACKACTIVATE,TRUE,(LPARAM)&tool); + tooltip.SendMessage(TTM_UPDATE); + WaitForSingleObject(m_DoneEvent,INFINITE); + tooltip.DestroyWindow(); + } +} + +bool CItemManager::IsTaskbarPinned( const wchar_t *appid ) +{ + Assert(GetCurrentThreadId()==m_MainThreadId); + RWLock lock(this,true,RWLOCK_ITEMS); + const ItemInfo *pInfo=NULL; + for (std::multimap::const_iterator it=m_ItemInfos.begin();it!=m_ItemInfos.end();++it) + { + if (it->second.bLink && it->second.location==LOCATION_TASKBAR) + { + UpdateItemInfo(&it->second,INFO_LINK_APPID,true); + if (wcscmp(it->second.appid,appid)==0) + { + if (GetFileAttributes(it->second.path)!=INVALID_FILE_ATTRIBUTES) + return true; + } + } + } + return false; +} + +void EncodeRot13( wchar_t *text ) +{ + for (;*text;text++) + { + if (*text>='a' && *text<='z') + *text=(*text-'a'+13)%26+'a'; + else if (*text>='A' && *text<='Z') + *text=(*text-'A'+13)%26+'A'; + } +} + +static KNOWNFOLDERID g_KnownPrefixes[]= +{ + FOLDERID_SystemX86, + FOLDERID_System, + FOLDERID_Windows, + FOLDERID_ProgramFilesX86, + FOLDERID_ProgramFilesX64, + FOLDERID_Programs, + FOLDERID_CommonPrograms, + FOLDERID_StartMenu, + FOLDERID_CommonStartMenu, +}; + +void EncodeUserAssistPath( wchar_t *path ) +{ + for (int i=0;i<_countof(g_KnownPrefixes);i++) + { + CComString knownPath; + if (FAILED(SHGetKnownFolderPath(g_KnownPrefixes[i],0,NULL,&knownPath))) + continue; + int len=Strlen(knownPath); + if (_wcsnicmp(path,knownPath,len)==0) + { + CComString guid; + StringFromCLSID(g_KnownPrefixes[i],&guid); + wchar_t name[_MAX_PATH]; + Sprintf(name,_countof(name),L"%s%s",guid,path+len); + Strcpy(path,_MAX_PATH,name); + return; + } + } +} + +bool CItemManager::IsPathUsed( CRegKey ®Key, const wchar_t *path, const FILETIME &createstamp, const KnownPathGuid *knownPaths, int knownPathsCount, bool bMetroApp ) +{ + { + unsigned int hash=CalcFNVHash(path); + OldItemInfo key={hash}; + std::vector::const_iterator it=std::lower_bound(m_OldItemInfos.begin(),m_OldItemInfos.end(),key); + if (it!=m_OldItemInfos.end() && it->hash==hash) + { + if (CompareFileTime(&createstamp,&it->timestamp)<0) + return true; + } + } + + wchar_t name[_MAX_PATH]; + if (knownPaths) + { + for (int i=0;i0 && CompareFileTime(&createstamp,&data.timestamp)<0); + } + } + return false; +} + +void CItemManager::UpdateNewPrograms( const POINT &balloonPos ) +{ + Assert(GetCurrentThreadId()==m_MainThreadId); + m_NewPrograms.clear(); + m_NewProgramRoots.clear(); + m_bHasNewPrograms[0]=m_bHasNewPrograms[1]=m_bHasNewApps[0]=m_bHasNewApps[1]=false; +#ifdef FORCE_ALL_NEW + m_bHasNewPrograms[0]=m_bHasNewPrograms[1]=m_bHasNewApps[0]=m_bHasNewApps[1]=true; +#endif + if (!GetSettingBool(L"HighlightNew")) + return; + bool bNewApps=GetSettingBool(L"HighlightNewApps"); +/* { + // the new programs need the MFU system to be enabled + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",KEY_READ)!=ERROR_SUCCESS) + return; + DWORD val; + if (regKey.QueryDWORDValue(L"Start_TrackProgs",val)==ERROR_SUCCESS && !val) + return; + } +*/ + LONGLONG installTime=0; + { + CRegKey regKey; + if (regKey.Open(HKEY_LOCAL_MACHINE,L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",KEY_READ)==ERROR_SUCCESS) + { + DWORD time=0; + if (regKey.QueryDWORDValue(L"InstallDate",time)==ERROR_SUCCESS) + { + installTime=Int32x32To64(time,10000000)+116444736000000000; + } + } + FILETIME ft={(DWORD)installTime,installTime>>32}; + SYSTEMTIME st; + GetSystemTime(&st); + LOG_MENU(LOG_NEW,L"Current time: %02d.%02d.%04d:%02d:%02d",st.wDay,st.wMonth,st.wYear,st.wHour,st.wMinute); + FileTimeToSystemTime(&ft,&st); + LOG_MENU(LOG_NEW,L"Install time: %02d.%02d.%04d:%02d:%02d",st.wDay,st.wMonth,st.wYear,st.wHour,st.wMinute); + } + + CRegKey regKeyExe; + regKeyExe.Open(HKEY_CURRENT_USER,USERASSIST_APPIDS_KEY,KEY_READ); + CRegKey regKeyLink; + regKeyLink.Open(HKEY_CURRENT_USER,USERASSIST_LINKS_KEY,KEY_READ); + + KnownPathGuid knownPaths[_countof(g_KnownPrefixes)+1]; + + int OLD_PROGRAMS_AGE=GetSettingInt(L"OldProgramsAge"); + if (OLD_PROGRAMS_AGE<0) OLD_PROGRAMS_AGE=0; + if (OLD_PROGRAMS_AGE>48) OLD_PROGRAMS_AGE=48; + const int INSTALL_GRACE_PERIOD=12; // ignore programs installed within 12 hours of system install + int knownPathsCount=0; + for (int i=0;i<_countof(g_KnownPrefixes);i++) + { + if (SUCCEEDED(SHGetKnownFolderPath(g_KnownPrefixes[i],0,NULL,&knownPaths[knownPathsCount].path))) + { + StringFromCLSID(g_KnownPrefixes[i],&knownPaths[knownPathsCount].guid); + knownPaths[knownPathsCount].path.MakeUpper(); + knownPaths[knownPathsCount].pathLen=Strlen(knownPaths[knownPathsCount].path); + knownPathsCount++; + } + } + knownPaths[knownPathsCount++].pathLen=0; + + LONGLONG curTime; + GetSystemTimeAsFileTime((FILETIME*)&curTime); + WaitForShortcuts(balloonPos); + LARGE_INTEGER newestProgram={0}, newestApp={0}; + { + RWLock lock(this,true,RWLOCK_ITEMS); + for (std::multimap::const_iterator it=m_ItemInfos.begin();it!=m_ItemInfos.end();++it) + { + if (it->second.location!=LOCATION_START_MENU && it->second.location!=LOCATION_METRO) + continue; + if ((it->second.bMetroLink || it->second.bMetroApp) && !bNewApps) + continue; + if (!it->second.bLink && !it->second.bMetroApp) + { + LOG_MENU(LOG_NEW,L"Ignoring new: %s not a link",it->second.path); + continue; + } + if (it->second.bNoNew) + { + LOG_MENU(LOG_NEW,L"Ignoring new: %s suppressed",it->second.path); + continue; + } +#ifdef FORCE_ALL_NEW + m_NewPrograms.push_back(&it->second); + continue; +#endif + LONGLONG timestamp=it->second.createstamp.dwLowDateTime|(((LONGLONG)it->second.createstamp.dwHighDateTime)<<32); + int hours1=(int)((curTime-timestamp)/36000000000); + if (hours1<0) + { + LOG_MENU(LOG_NEW,L"Ignoring new: %s creation time too new - %d hours",it->second.path,hours1); + continue; + } + if (hours1>OLD_PROGRAMS_AGE) + { + LOG_MENU(LOG_NEW,L"Ignoring new: %s creation time too old - %d hours",it->second.path,hours1); + continue; + } + if (wcswcs(PathFindFileName(it->second.PATH),L"UNINSTALL")) + { + LOG_MENU(LOG_NEW,L"Ignoring new: %s contains UNINSTALL",it->second.path); + continue; + } + if (it->second.location==LOCATION_START_MENU) + { + if (wcscmp(PathFindExtension(it->second.targetPATH),L".EXE")!=0) + { + LOG_MENU(LOG_NEW,L"Ignoring new: %s target not exe",it->second.path); + continue; + } + } + + if (it->second.bLink && GetFileAttributes(it->second.path)==INVALID_FILE_ATTRIBUTES) + { + LOG_MENU(LOG_NEW,L"Ignoring new: %s missing file",it->second.path); + continue; + } + // existing link to exe that is newer than 48 hours + int hours2=0, hours3=0; + if (it->second.location==LOCATION_START_MENU) + { + HANDLE h=CreateFile(it->second.targetPATH,FILE_READ_ATTRIBUTES,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,NULL,OPEN_EXISTING,0,NULL); + if (h==INVALID_HANDLE_VALUE) + { + LOG_MENU(LOG_NEW,L"Ignoring new: %s failed to read attributes",it->second.path); + continue; + } + + FILE_BASIC_INFO info; + hours2=0; + if (GetFileInformationByHandleEx(h,FileBasicInfo,&info,sizeof(info))) + hours2=(int)((curTime-info.ChangeTime.QuadPart)/36000000000); + CloseHandle(h); + if (hours2<0) + { + LOG_MENU(LOG_NEW,L"Ignoring new: %s target change time too new - %d hours",it->second.path,hours2); + continue; // the exe is too old + } + if (hours2>OLD_PROGRAMS_AGE) + { + LOG_MENU(LOG_NEW,L"Ignoring new: %s target change time too old - %d hours",it->second.path,hours2); + continue; // the exe is too old + } + hours3=(int)((info.ChangeTime.QuadPart-installTime)/36000000000); + if (hours3second.path,hours3); + continue; // too soon after install + } + + if (regKeyLink.m_hKey && IsPathUsed(regKeyLink,it->second.PATH,it->second.createstamp,knownPaths,knownPathsCount,it->second.bMetroApp)) + { + LOG_MENU(LOG_NEW,L"Ignoring new: %s shortcut used after it was created",it->second.path); + continue; // the shortcut was used after it was created + } + if (regKeyExe.m_hKey) + { + UpdateItemInfo(&it->second,INFO_LINK_APPID,true); + CString appid=it->second.appid; + appid.MakeUpper(); + if (IsPathUsed(regKeyExe,appid,it->second.createstamp,NULL,0,it->second.bMetroApp)) + { + LOG_MENU(LOG_NEW,L"Ignoring new: %s exe used after the shortcut was created",it->second.path); + continue; // the exe was used after the shortcut was created + } + } + if (newestProgram.QuadPartsecond.location==LOCATION_METRO) + { + hours3=(int)((timestamp-installTime)/36000000000); + if (hours3second.path,hours3); + continue; // too soon after install + } + CString appid=it->second.appid; + appid.MakeUpper(); + if (regKeyExe.m_hKey && IsPathUsed(regKeyExe,appid,it->second.createstamp,NULL,0,it->second.bMetroApp)) + { + LOG_MENU(LOG_NEW,L"Ignoring new: %s app id used after app was created",it->second.path); + continue; // the exe was used after the shortcut was created + } + if (it->second.bLink && regKeyLink.m_hKey && IsPathUsed(regKeyLink,it->second.PATH,it->second.createstamp,knownPaths,knownPathsCount,it->second.bMetroApp)) + { + LOG_MENU(LOG_NEW,L"Ignoring new: %s shortcut used after it was created",it->second.path); + continue; // the shortcut was used after it was created + } + if (newestApp.QuadPartsecond); + LOG_MENU(LOG_NEW,L"Accepting new: highlighting %s, created %d hours, target changed %d hours, since install %d hours, %I64X",it->second.path,hours1,hours2,hours3,timestamp); + } + } + + if (newestProgram.QuadPart || newestApp.QuadPart) + { + CRegKey regKey; + ULONGLONG val1, val2; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu",KEY_READ)==ERROR_SUCCESS) + { + if (regKey.QueryQWORDValue(L"LastProgramsTime",val1)!=ERROR_SUCCESS) + val1=0; + if (regKey.QueryQWORDValue(L"LastAppsTime",val2)!=ERROR_SUCCESS) + val2=0; + } + if (newestProgram.QuadPart) + { + LOG_MENU(LOG_NEW,L"LastProgramsTime: %I64X",val1); + m_bHasNewPrograms[0]=true; + m_bHasNewPrograms[1]=(val1<(ULONGLONG)newestProgram.QuadPart); + } + if (newestApp.QuadPart) + { + LOG_MENU(LOG_NEW,L"LastAppsTime: %I64X",val2); + m_bHasNewApps[0]=true; + m_bHasNewApps[1]=(val2<(ULONGLONG)newestApp.QuadPart); + } + } + + static const KNOWNFOLDERID *newProgramRoots[]={ + &FOLDERID_StartMenu, + &FOLDERID_CommonStartMenu, + &FOLDERID_Programs, + &FOLDERID_CommonPrograms, + }; + for (int i=0;i<_countof(newProgramRoots);i++) + { + CComPtr pFolder; + if (SUCCEEDED(ShGetKnownFolderItem(*newProgramRoots[i],&pFolder))) + { + CAbsolutePidl pidl; + if (SUCCEEDED(SHGetIDListFromObject(pFolder,&pidl))) + m_NewProgramRoots.push_back(GetItemInfo(pFolder,pidl,0)); + } + } + if (GetWinVersion()>=WIN_VER_WIN8) + { + wchar_t path[_MAX_PATH]=METRO_APP_ROOT; + DoEnvironmentSubst(path,_countof(path)); + CAbsolutePidl pidl; + pidl.Attach(ILCreateFromPath(path)); + CComPtr pFolder; + if (SUCCEEDED(SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pFolder))) + m_NewProgramRoots.push_back(GetItemInfo(pFolder,pidl,0)); + } +} + +bool CItemManager::IsNewProgram( PIDLIST_ABSOLUTE pidl, bool bFolder, bool bMetroApp ) +{ + Assert(GetCurrentThreadId()==m_MainThreadId); + if (m_NewPrograms.empty()) return false; + if (!bMetroApp) + { + // check if the item is under the approved roots + bool bValid=false; + for (std::vector::const_iterator it=m_NewProgramRoots.begin();it!=m_NewProgramRoots.end();++it) + { + if (ILIsParent((*it)->GetPidl(),pidl,FALSE)) + { + bValid=true; + break; + } + } + if (!bValid) return false; + } + for (std::vector::const_iterator it=m_NewPrograms.begin();it!=m_NewPrograms.end();++it) + { + if (bFolder && ILIsParent(pidl,(*it)->GetPidl(),FALSE)) + return true; + if (!bFolder && ILIsEqual(pidl,(*it)->GetPidl())) + return true; + } + return false; +} + +void CItemManager::LoadOldItems( void ) +{ + m_OldItemInfos.clear(); + CRegKey regItems; + if (regItems.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu",KEY_READ)==ERROR_SUCCESS) + { + ULONG size=0; + regItems.QueryBinaryValue(L"OldItems",NULL,&size); + if (size>0 && (size%sizeof(OldItemInfo))==0) + { + m_OldItemInfos.resize(size/sizeof(OldItemInfo)); + regItems.QueryBinaryValue(L"OldItems",&m_OldItemInfos[0],&size); + } + } + + std::sort(m_OldItemInfos.begin(),m_OldItemInfos.end()); +} + +void CItemManager::RemoveNewItem( PIDLIST_ABSOLUTE pItem1, PIDLIST_ABSOLUTE pItem2, bool bFolder ) +{ + std::vector hashes; + { + RWLock lock(this,false,RWLOCK_ITEMS); + for (size_t i=0;iGetPidl(),FALSE) || (pItem2 && ILIsParent(pItem2,pInfo->GetPidl(),FALSE)))) + bFound=true; + if (!bFound && !bFolder && ILIsEqual(pItem1,pInfo->GetPidl())) + bFound=true; + if (bFound) + { + unsigned hash; + if (pInfo->bMetroApp) + { + CString appid=pInfo->appid; + appid.MakeUpper(); + hash=CalcFNVHash(appid); + } + else if (pInfo->bLink) + { + hash=CalcFNVHash(pInfo->PATH); + } + else continue; + m_NewPrograms.erase(m_NewPrograms.begin()+i); + hashes.push_back(hash); + i--; + } + } + } + AddOldItems(hashes); +} + +void CItemManager::RemoveNewItems( bool bPrograms, bool bMetro ) +{ + std::vector hashes; + { + RWLock lock(this,false,RWLOCK_ITEMS); + for (size_t i=0;ilocation==LOCATION_METRO && !bMetro) + continue; + if (pInfo->location!=LOCATION_METRO && !bPrograms) + continue; + unsigned hash; + if (pInfo->bMetroApp) + { + CString appid=pInfo->appid; + appid.MakeUpper(); + hash=CalcFNVHash(appid); + } + else if (pInfo->bLink) + { + hash=CalcFNVHash(pInfo->PATH); + } + else continue; + m_NewPrograms.erase(m_NewPrograms.begin()+i); + hashes.push_back(hash); + i--; + } + } + AddOldItems(hashes); + if (bMetro) + m_bHasNewApps[0]=m_bHasNewApps[1]=false; + if (bPrograms) + m_bHasNewPrograms[0]=m_bHasNewPrograms[1]=false; +} + +void CItemManager::AddOldItems( const std::vector &hashes ) +{ + // purge items older than 48 hours + LONGLONG timestamp; + GetSystemTimeAsFileTime((FILETIME*)×tamp); + timestamp-=36000000000ll*48; + for (size_t i=0;i0) + { + m_OldItemInfos.erase(m_OldItemInfos.begin()+i); + i--; + } + } + + for (std::vector::const_iterator it=hashes.begin();it!=hashes.end();++it) + { + OldItemInfo key={*it}; + GetSystemTimeAsFileTime(&key.timestamp); + std::vector::iterator it2=std::lower_bound(m_OldItemInfos.begin(),m_OldItemInfos.end(),key); + if (it2!=m_OldItemInfos.end() && it2->hash==*it) + it2->timestamp=key.timestamp; + else + m_OldItemInfos.insert(it2,key); + } + + CRegKey regItems; + if (regItems.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu")!=ERROR_SUCCESS) + regItems.Create(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu"); + + if (m_OldItemInfos.empty()) + regItems.SetBinaryValue(L"OldItems",NULL,0); + else + regItems.SetBinaryValue(L"OldItems",&m_OldItemInfos[0],(int)m_OldItemInfos.size()*sizeof(OldItemInfo)); +} + +CString GetPropertyStoreString( IPropertyStore *pStore, REFPROPERTYKEY key ) +{ + PROPVARIANT val; + PropVariantInit(&val); + CString res; + if (SUCCEEDED(pStore->GetValue(key,&val))) + { + if (val.vt==VT_LPWSTR || val.vt==VT_BSTR) + res=val.pwszVal; + else if (val.vt==VT_LPSTR) + res=val.pszVal; + } + PropVariantClear(&val); + return res; +} + +// doesn't require the lock to be held +void CItemManager::RefreshItemInfo( ItemInfo *pInfo, int refreshFlags, IShellItem *pItem0, bool bHasWriteLock ) +{ + ItemInfo newInfo; + + { + // get info from pInfo + RWLock lock(this,false,bHasWriteLock?RWLOCK_COUNT:RWLOCK_ITEMS); + newInfo=*pInfo; + } + + CComPtr pItem; + CComPtr pAppItem; + bool bStartScreen= +#ifndef STARTSCREEN_WIN7 + GetWinVersion()>=WIN_VER_WIN8 && +#endif + (_wcsicmp(PathFindFileName(newInfo.PATH),STARTSCREEN_COMMAND)==0); + bool bValidateIcons=!bStartScreen; // hack - don't mark the icon as valid, so we have to load it next time + { + // do the real work + + int pInfo=0; // shadow the pInfo parameter while in this block + if ((refreshFlags&INFO_DATA) || !(newInfo.bIconOnly || newInfo.bMetroLink)) + { + if (pItem0) + pItem=pItem0; + else + { + const CAbsolutePidl &pidl=newInfo.newPidl?newInfo.newPidl:newInfo.pidl; + if (pidl) + { + if (FAILED(SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pItem))) + return; + } + } + } + + if (refreshFlags&INFO_DATA) + { + Assert(!newInfo.bIconOnly); + + // these two are always updated even if INFO_LINK is not requested + newInfo.bLink=false; + newInfo.bNoPin=false; + newInfo.bNoNew=false; + newInfo.bExplicitAppId=false; + newInfo.targetPATH.Empty(); + newInfo.targetPidl.Clear(); + if (refreshFlags&INFO_LINK_APPID) + { + newInfo.appid.Empty(); + } + + if (refreshFlags&INFO_METRO) + { + newInfo.bMetroLink=false; + newInfo.bMetroApp=false; + newInfo.bProtectedLink=false; + newInfo.metroName.Empty(); + newInfo.iconPath.Empty(); + newInfo.iconColor=0; + } + + // refresh link and metro + SFGAOF flags=0; + if (pItem && SUCCEEDED(pItem->GetAttributes(SFGAO_LINK|SFGAO_FILESYSTEM,&flags))) + { + CComQIPtr pStore; + if (flags&SFGAO_LINK) + { + // get link properties + CComPtr pLink; + if (SUCCEEDED(pItem->BindToHandler(NULL,BHID_SFUIObject,IID_IShellLink,(void**)&pLink))) + { + newInfo.bLink=true; + pStore=pLink; + + if (SUCCEEDED(pLink->GetIDList(&newInfo.targetPidl))) + { + wchar_t path[_MAX_PATH]; + if (SUCCEEDED(SHGetPathFromIDList(newInfo.targetPidl,path))) + { + CharUpper(path); + newInfo.targetPATH=path; + } + } + } + } + else if (!(flags&SFGAO_FILESYSTEM)) + { + newInfo.bLink=false; + pItem->BindToHandler(NULL,BHID_PropertyStore,IID_IPropertyStore,(void**)&pStore); + } + if (pStore) + { + if (GetWinVersion()>=WIN_VER_WIN7) + { + newInfo.appid=GetPropertyStoreString(pStore,PKEY_AppUserModel_ID); + newInfo.bExplicitAppId=!newInfo.appid.IsEmpty(); + } + if (!newInfo.appid.IsEmpty() && (refreshFlags&INFO_METRO) && (GetWinVersion()<=WIN_VER_WIN8 || _wcsicmp(newInfo.appid,SEARCH_APP_ID)!=0)) + { + PROPVARIANT val; + PropVariantInit(&val); + if (SUCCEEDED(pStore->GetValue(PKEY_MetroAppLauncher,&val)) && (val.vt==VT_I4 || val.vt==VT_UI4) && val.intVal) + { + // get Metro properties + PropVariantClear(&val); + newInfo.bMetroLink=newInfo.bLink; + newInfo.bMetroApp=!newInfo.bLink; + newInfo.bProtectedLink=false; + if (newInfo.bMetroApp) + { + pAppItem=pItem; + newInfo.packagePath=GetPropertyStoreString(pStore,PKEY_MetroPackagePath); + if (!newInfo.packagePath.IsEmpty()) + { + FILETIME writeTime={0}, createTime={0}; + if (MenuGetFileTimestamp(newInfo.packagePath,&writeTime,&createTime)) + { + newInfo.writestamp=writeTime; + newInfo.createstamp=createTime; + } + } + } + if (newInfo.bMetroLink && wcsncmp(newInfo.PATH,m_RootCommonPrograms,m_RootCommonPrograms.GetLength())==0) + { + const wchar_t *str=newInfo.PATH; + newInfo.bProtectedLink=m_RootCommonPrograms.GetLength()==(PathFindFileName(str)-str); + } + if (SUCCEEDED(pStore->GetValue(PKEY_MetroIconColor,&val)) && (val.vt==VT_I4 || val.vt==VT_UI4)) + newInfo.iconColor=val.intVal; + if (pAppItem || SUCCEEDED(SHCreateItemInKnownFolder(FOLDERID_AppsFolder2,0,newInfo.appid,IID_IShellItem,(void**)&pAppItem))) + { + CComString pName; + if (SUCCEEDED(pAppItem->GetDisplayName(SIGDN_NORMALDISPLAY,&pName))) + { + newInfo.metroName=pName; + } + } + } + PropVariantClear(&val); + } + if (!newInfo.bMetroLink && !newInfo.bMetroApp) + { + PROPVARIANT val; + PropVariantInit(&val); + if (SUCCEEDED(pStore->GetValue(PKEY_AppUserModel_PreventPinning,&val)) && val.vt==VT_BOOL && val.boolVal) + newInfo.bNoPin=true; + PropVariantClear(&val); + if (SUCCEEDED(pStore->GetValue(PKEY_AppUserModel_ExcludeFromShowInNewInstall,&val)) && val.vt==VT_BOOL && val.boolVal) + newInfo.bNoNew=true; + PropVariantClear(&val); + } + } + + if (newInfo.bLink && newInfo.appid.IsEmpty() && (refreshFlags&INFO_LINK_APPID)) + { + Assert(GetCurrentThreadId()==m_MainThreadId); + if (!g_pAppResolver) + CreateAppResolver(); + if (g_pAppResolver) + { + CComString pAppId; + if (SUCCEEDED(g_pAppResolver->GetAppIDForShortcut(pItem,&pAppId))) + newInfo.appid=pAppId; + } + } + } + } + if (!newInfo.bIconOnly) + { + if (!newInfo.bLink) + { + newInfo.targetPidl.Clear(); + newInfo.targetPATH.Empty(); + newInfo.metroName.Empty(); + newInfo.iconPath.Empty(); + newInfo.bNoPin=newInfo.bNoNew=false; + if (!newInfo.bMetroApp) + { + newInfo.bExplicitAppId=false; + newInfo.appid.Empty(); + newInfo.packagePath.Empty(); + } + } + else if (newInfo.bMetroLink) + { + newInfo.targetPidl.Clear(); + newInfo.targetPATH.Empty(); + } + } + + if (refreshFlags&INFO_ICON) + { + // load icons + if (newInfo.bIconOnly) + { + LoadCustomIcon(newInfo.iconPath,newInfo.iconIndex,refreshFlags&INFO_ICON,newInfo.smallIcon,newInfo.largeIcon,newInfo.extraLargeIcon,newInfo.bTemp); + } + else if (newInfo.bMetroLink || newInfo.bMetroApp) + { + if (pAppItem || SUCCEEDED(SHCreateItemInKnownFolder(FOLDERID_AppsFolder2,0,newInfo.appid,IID_IShellItem,(void**)&pAppItem))) + { + int iconFlags=refreshFlags&INFO_ICON; + LoadMetroIcon(pAppItem,iconFlags,newInfo.smallIcon,newInfo.largeIcon,newInfo.extraLargeIcon,&newInfo.iconColor); + if (iconFlags) + LoadShellIcon(pItem?pItem:pAppItem,iconFlags,newInfo.smallIcon,newInfo.largeIcon,newInfo.extraLargeIcon,&newInfo.iconColor); + } + } + else if (_wcsicmp(PathFindExtension(newInfo.path),L".settingcontent-ms")==0) + { + wchar_t iconPath[_MAX_PATH]=L"%windir%\\ImmersiveControlPanel\\systemsettings.exe"; + DoEnvironmentSubst(iconPath,_countof(iconPath)); + newInfo.iconPath=iconPath; + newInfo.iconIndex=-10; + LoadCustomIcon(newInfo.iconPath,newInfo.iconIndex,refreshFlags&INFO_ICON,newInfo.smallIcon,newInfo.largeIcon,newInfo.extraLargeIcon,false); + } + else + { + LoadShellIcon(pItem,(refreshFlags&INFO_ICON)|(bStartScreen?INFO_STARTSCREEN_ICON:0),newInfo.smallIcon,newInfo.largeIcon,newInfo.extraLargeIcon,NULL); + } + } + } + + { + // store info in pInfo + RWLock lock(this,true,bHasWriteLock?RWLOCK_COUNT:RWLOCK_ITEMS); + + if (refreshFlags&INFO_DATA) + { + pInfo->bLink=newInfo.bLink; + pInfo->bMetroLink=newInfo.bMetroLink; + pInfo->bMetroApp=newInfo.bMetroApp; + pInfo->bProtectedLink=newInfo.bProtectedLink; + pInfo->bNoPin=newInfo.bNoPin; + pInfo->bNoNew=newInfo.bNoNew; + pInfo->bExplicitAppId=newInfo.bExplicitAppId; + pInfo->targetPidl.Swap(newInfo.targetPidl); + pInfo->targetPATH=newInfo.targetPATH; + pInfo->packagePath=newInfo.packagePath; + if ((refreshFlags&INFO_LINK_APPID) || !newInfo.appid.IsEmpty()) + pInfo->appid=newInfo.appid; + if (!pInfo->appid.IsEmpty()) + refreshFlags|=INFO_LINK_APPID; // appid is valid, no need to resolve + pInfo->metroName=newInfo.metroName; + pInfo->iconPath=newInfo.iconPath; + pInfo->iconColor=newInfo.iconColor; + if (pInfo->bMetroApp) + { + pInfo->writestamp=newInfo.writestamp; + pInfo->createstamp=newInfo.createstamp; + } + } + + if (refreshFlags&INFO_SMALL_ICON) + pInfo->smallIcon=newInfo.smallIcon; + if (refreshFlags&INFO_LARGE_ICON) + pInfo->largeIcon=newInfo.largeIcon; + if (refreshFlags&INFO_EXTRA_LARGE_ICON) + pInfo->extraLargeIcon=newInfo.extraLargeIcon; + if (bValidateIcons) + pInfo->validFlags|=refreshFlags&(INFO_DATA|INFO_ICON); + else + pInfo->validFlags|=refreshFlags&INFO_DATA; + pInfo->refreshFlags&=~refreshFlags; + } +} + +void CItemManager::RefreshInfos( void ) +{ + Assert(GetCurrentThreadId()==m_MainThreadId); + RWLock lock(this,true,RWLOCK_ITEMS); + for (std::multimap::iterator it=m_ItemInfos.begin();it!=m_ItemInfos.end();++it) + { + if (it->second.newPidl) + { + it->second.pidl.Swap(it->second.newPidl); + it->second.newPidl.Clear(); + it->second.validFlags=0; + } + } +} + +HBITMAP CItemManager::BitmapFromIcon( HICON hIcon, int iconSize, bool bDestroyIcon ) +{ + if (!hIcon) return NULL; + LoadIconData &data=GetLoadIconData(); + if (!data.m_pFactory) + { + if (bDestroyIcon) + DestroyIcon(hIcon); + return NULL; + } + + CComPtr pBitmap; + HRESULT hr=data.m_pFactory->CreateBitmapFromHICON(hIcon,&pBitmap); + if (bDestroyIcon) + DestroyIcon(hIcon); + if (FAILED(hr)) + return NULL; + + CComPtr pConverter; + if (FAILED(data.m_pFactory->CreateFormatConverter(&pConverter))) + return NULL; + + UINT width=0, height=0; + if (SUCCEEDED(pBitmap->GetSize(&width,&height)) && width==iconSize && height==iconSize) + { + pConverter->Initialize(pBitmap,GUID_WICPixelFormat32bppPBGRA,WICBitmapDitherTypeNone,NULL,0,WICBitmapPaletteTypeMedianCut); + } + else + { + CComPtr pScaler; + if (FAILED(data.m_pFactory->CreateBitmapScaler(&pScaler))) + return NULL; + pScaler->Initialize(pBitmap,iconSize,iconSize,WICBitmapInterpolationModeFant); + pConverter->Initialize(pScaler,GUID_WICPixelFormat32bppPBGRA,WICBitmapDitherTypeNone,NULL,0,WICBitmapPaletteTypeMedianCut); + } + + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=iconSize; + bi.bmiHeader.biHeight=-iconSize; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + HDC hdc=CreateCompatibleDC(NULL); + BYTE *bits; + HBITMAP bmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&bits,NULL,0); + DeleteDC(hdc); + if (!bmp) return NULL; + hr=pConverter->CopyPixels(NULL,iconSize*4,iconSize*iconSize*4,bits); + if (FAILED(hr)) + { + DeleteObject(bmp); + return NULL; + } + return bmp; +} + +HICON CItemManager::LoadShellIcon( int index, int iconSize ) +{ + LoadIconData &data=GetLoadIconData(); + int sizeIndex=-1; + for (int i=0;i<_countof(data.m_IconSizes);i++) + { + if (data.m_IconSizes[i]==iconSize) + { + sizeIndex=i; + break; + } + } + if (sizeIndex==-1) return NULL; + int listType=0; + for (std::vector>::const_iterator it=m_ListSizes.begin();it!=m_ListSizes.end();++it) + { + listType=it->second; + if (it->first>=iconSize) + break; + } + CComPtr pImageList; + if (FAILED(SHGetImageList(listType,IID_IImageList,(void**)&pImageList))) + return NULL; + HICON hIcon; + + if (data.m_pTempLists[sizeIndex]) + { + if (SUCCEEDED(data.m_pTempLists[sizeIndex]->ReplaceFromImageList(0,pImageList,index,NULL,0)) && SUCCEEDED(data.m_pTempLists[sizeIndex]->GetIcon(0,ILD_TRANSPARENT,&hIcon))) + { + AddTrackedIcon(hIcon); + return hIcon; + } + } + if (FAILED(pImageList->GetIcon(index,ILD_TRANSPARENT,&hIcon))) + return NULL; + AddTrackedIcon(hIcon); + return hIcon; +} + +HICON CItemManager::LoadShellIcon( int iconSize, IExtractIcon *pExtractW, const wchar_t *location, IExtractIconA *pExtractA, const char *locationA, int index ) +{ + HICON hIcon=NULL, hIcon2=NULL; + HRESULT hr; + if (iconSize<=GetSystemMetrics(SM_CXSMICON)) + { + // small icon is closer + if (pExtractW) + hr=pExtractW->Extract(location,index,&hIcon2,&hIcon,MAKELONG(iconSize,iconSize)); + else + hr=pExtractA->Extract(locationA,index,&hIcon2,&hIcon,MAKELONG(iconSize,iconSize)); + } + else + { + // large icon is closer + if (pExtractW) + hr=pExtractW->Extract(location,index,&hIcon,&hIcon2,MAKELONG(iconSize,iconSize)); + else + hr=pExtractA->Extract(locationA,index,&hIcon,&hIcon2,MAKELONG(iconSize,iconSize)); + } + if (FAILED(hr)) return NULL; + + if (hIcon2) DestroyIcon(hIcon2); + return hIcon; +} + +void CItemManager::LoadShellIcon( IShellItem *pItem, int refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon, const DWORD *pMetroColor ) +{ + if (!pItem) + return; + + wchar_t location[_MAX_PATH]; + int index=0; + if (refreshFlags&INFO_STARTSCREEN_ICON) + { + CComPtr pLink; + if (SUCCEEDED(pItem->BindToHandler(NULL,BHID_SFUIObject,IID_IShellLink,(void**)&pLink))) + { + if (SUCCEEDED(pLink->GetIconLocation(location,_countof(location),&index)) && (!location[0] || _wcsicmp(PathFindFileName(location),L"StartScreen.exe")==0)) + { + unsigned int hash=CalcFNVHash(STARTSCREEN_COMMAND); + HBITMAP hSmallBitmap=NULL, hLargeBitmap=NULL, hExtraLargeBitmap=NULL; + if (refreshFlags&INFO_SMALL_ICON) + { + hSmallBitmap=GetStartScreenIcon(SMALL_ICON_SIZE); + } + + if (refreshFlags&INFO_LARGE_ICON) + { + hLargeBitmap=GetStartScreenIcon(LARGE_ICON_SIZE); + } + + if (refreshFlags&INFO_EXTRA_LARGE_ICON) + { + hExtraLargeBitmap=GetStartScreenIcon(EXTRA_LARGE_ICON_SIZE); + } + + StoreInCache(hash,NULL,hSmallBitmap,hLargeBitmap,hExtraLargeBitmap,refreshFlags,smallIcon,largeIcon,extraLargeIcon,false,false); + return; + } + } + } + + // get the IExtractIcon object + CComPtr pExtractW; + CComPtr pExtractA; + + bool bNotFileName; + bool bTransient=false; + char locationA[_MAX_PATH]; + + // get the icon location + if (SUCCEEDED(pItem->BindToHandler(NULL,BHID_SFUIObject,IID_IExtractIconW,(void**)&pExtractW))) + { + UINT iconFlags=0; + if (pExtractW->GetIconLocation(0,location,_countof(location),&index,&iconFlags)!=S_OK) + return; + + bNotFileName=(iconFlags&GIL_NOTFILENAME)!=0; + bTransient=(iconFlags&GIL_DONTCACHE)!=0; + } + else if (SUCCEEDED(pItem->BindToHandler(NULL,BHID_SFUIObject,IID_IExtractIconA,(void**)&pExtractA))) + { + UINT iconFlags=0; + if (pExtractA->GetIconLocation(0,locationA,_countof(locationA),&index,&iconFlags)!=S_OK) + return; + + MbsToWcs(location,_countof(location),locationA); + bNotFileName=(iconFlags&GIL_NOTFILENAME)!=0; + bTransient=(iconFlags&GIL_DONTCACHE)!=0; + } + else + return; + + unsigned int hash; + if (bTransient) + hash=m_TransientHash++; + else if (location[0]) + hash=CalcFNVHash(location,CalcFNVHash(&index,4)); + else + { + // if the location is blank, use the parsing name for the hash + CComString pName; + pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName); + hash=CalcFNVHash(pName,CalcFNVHash(&index,4)); + } + + if (pMetroColor) + hash=CalcFNVHash(pMetroColor,4,hash); + + if (!bTransient) + FindInCache(hash,refreshFlags,smallIcon,largeIcon,extraLargeIcon); + if (!refreshFlags) return; + + // extract icon + HBITMAP hSmallBitmap=NULL, hLargeBitmap=NULL, hExtraLargeBitmap=NULL; + + wchar_t metroLocation[_MAX_PATH]; + Strcpy(metroLocation,_countof(metroLocation),location); + if (pMetroColor && ParseMetroBitmapLocation(metroLocation)) + { + if (refreshFlags&INFO_SMALL_ICON) + { + hSmallBitmap=LoadMetroBitmap(metroLocation,SMALL_ICON_SIZE,*pMetroColor); + } + if (refreshFlags&INFO_LARGE_ICON) + { + hLargeBitmap=LoadMetroBitmap(metroLocation,LARGE_ICON_SIZE,*pMetroColor); + } + if (refreshFlags&INFO_EXTRA_LARGE_ICON) + { + hExtraLargeBitmap=LoadMetroBitmap(metroLocation,EXTRA_LARGE_ICON_SIZE,*pMetroColor); + } + if (hSmallBitmap || hLargeBitmap || hExtraLargeBitmap) + { + metroLocation[1]='#'; + StoreInCache(hash,metroLocation,hSmallBitmap,hLargeBitmap,hExtraLargeBitmap,refreshFlags,smallIcon,largeIcon,extraLargeIcon,bTransient,true); + return; + } + } + + Strcpy(metroLocation,_countof(metroLocation),location); + if (pMetroColor && GetWinVersion()>=WIN_VER_WIN10 && ParseMetroBitmapLocation2(metroLocation)) + { + if (refreshFlags&INFO_SMALL_ICON) + { + hSmallBitmap=LoadMetroBitmap2(metroLocation,SMALL_ICON_SIZE,*pMetroColor); + } + if (refreshFlags&INFO_LARGE_ICON) + { + hLargeBitmap=LoadMetroBitmap2(metroLocation,LARGE_ICON_SIZE,*pMetroColor); + } + if (refreshFlags&INFO_EXTRA_LARGE_ICON) + { + hExtraLargeBitmap=LoadMetroBitmap2(metroLocation,EXTRA_LARGE_ICON_SIZE,*pMetroColor); + } + if (hSmallBitmap || hLargeBitmap || hExtraLargeBitmap) + { + metroLocation[1]='#'; + StoreInCache(hash,metroLocation,hSmallBitmap,hLargeBitmap,hExtraLargeBitmap,refreshFlags,smallIcon,largeIcon,extraLargeIcon,bTransient,true); + return; + } + } + + if (GetWinVersion()>=WIN_VER_WIN10) + pMetroColor=NULL; + + int smallIconSize=SMALL_ICON_SIZE; + int largeIconSize=LARGE_ICON_SIZE; + int extraLargeIconSize=EXTRA_LARGE_ICON_SIZE; + if (pMetroColor) + { + smallIconSize-=2; + largeIconSize-=2; + extraLargeIconSize-=2; + } + HICON hSmallIcon=NULL, hLargeIcon=NULL, hExtraLargeIcon=NULL; + if (bNotFileName) + { + CAbsolutePidl pidl; + SHFILEINFO info; + if (SUCCEEDED(SHGetIDListFromObject(pItem,&pidl)) && SHGetFileInfo((const wchar_t*)(PIDLIST_ABSOLUTE)pidl,0,&info,sizeof(info),SHGFI_PIDL|SHGFI_SYSICONINDEX)) + { + if (refreshFlags&INFO_SMALL_ICON) + hSmallIcon=LoadShellIcon(info.iIcon,smallIconSize); + if (refreshFlags&INFO_LARGE_ICON) + hLargeIcon=LoadShellIcon(info.iIcon,largeIconSize); + if (refreshFlags&INFO_EXTRA_LARGE_ICON) + hExtraLargeIcon=LoadShellIcon(info.iIcon,extraLargeIconSize); + } + else + { + // fall back to the extractor + if (refreshFlags&INFO_SMALL_ICON) + hSmallIcon=LoadShellIcon(smallIconSize,pExtractW,location,pExtractA,locationA,index); + if (refreshFlags&INFO_LARGE_ICON) + hLargeIcon=LoadShellIcon(largeIconSize,pExtractW,location,pExtractA,locationA,index); + if (refreshFlags&INFO_EXTRA_LARGE_ICON) + hExtraLargeIcon=LoadShellIcon(extraLargeIconSize,pExtractW,location,pExtractA,locationA,index); + } + } + else + { + DoEnvironmentSubst(location,_countof(location)); + if (refreshFlags&INFO_SMALL_ICON) + hSmallIcon=ShExtractIcon(location,index==-1?0:index,smallIconSize); + if (refreshFlags&INFO_LARGE_ICON) + hLargeIcon=ShExtractIcon(location,index==-1?0:index,largeIconSize); + if (refreshFlags&INFO_EXTRA_LARGE_ICON) + hExtraLargeIcon=ShExtractIcon(location,index==-1?0:index,extraLargeIconSize); + } + if (hSmallIcon) + { + if (pMetroColor) + hSmallBitmap=BitmapFromMetroIcon(hSmallIcon,SMALL_ICON_SIZE,smallIconSize,*pMetroColor); + else + hSmallBitmap=BitmapFromIcon(hSmallIcon,smallIconSize); + } + if (hLargeIcon) + { + if (pMetroColor) + hLargeBitmap=BitmapFromMetroIcon(hLargeIcon,LARGE_ICON_SIZE,largeIconSize,*pMetroColor); + else + hLargeBitmap=BitmapFromIcon(hLargeIcon,largeIconSize); + } + if (hExtraLargeIcon) + { + if (pMetroColor) + hExtraLargeBitmap=BitmapFromMetroIcon(hExtraLargeIcon,EXTRA_LARGE_ICON_SIZE,extraLargeIconSize,*pMetroColor); + else + hExtraLargeBitmap=BitmapFromIcon(hExtraLargeIcon,extraLargeIconSize); + } + if (pMetroColor) + location[1]='#'; + StoreInCache(hash,bNotFileName?NULL:location,hSmallBitmap,hLargeBitmap,hExtraLargeBitmap,refreshFlags,smallIcon,largeIcon,extraLargeIcon,bTransient,false); +} + +static bool SetResContextTargetSize( IResourceContext *pResContext, int size ) +{ + if (GetWinVersion()>=WIN_VER_WIN10) + { + if (SUCCEEDED(pResContext->SetTargetSize(size))) + return true; + } + RESOURCE_SCALE scale; + if (size<=24) + scale=RES_SCALE_80; + else if (size<=30) + scale=RES_SCALE_100; + else if (size<=42) + scale=RES_SCALE_140; + else + scale=RES_SCALE_180; + return SUCCEEDED(pResContext->SetScale(scale)); +} + +void CItemManager::LoadMetroIcon( IShellItem *pItem, int &refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon, const DWORD *pMetroColor ) +{ + unsigned int hash; + { + CComString pName; + pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName); + hash=CalcFNVHash(pName); + } + + hash=CalcFNVHash(pMetroColor,4,hash); + + FindInCache(hash,refreshFlags,smallIcon,largeIcon,extraLargeIcon); + if (!refreshFlags) return; + + // extract icon + HBITMAP hSmallBitmap=NULL, hLargeBitmap=NULL, hExtraLargeBitmap=NULL; + + CComPtr pStore; + pItem->BindToHandler(NULL,BHID_PropertyStore,IID_IPropertyStore,(void**)&pStore); + if (!pStore) return; + + CString packageName=GetPropertyStoreString(pStore,PKEY_MetroPackageName); + if (packageName.IsEmpty()) return; + CString iconName=GetPropertyStoreString(pStore,PKEY_MetroIcon); + if (iconName.IsEmpty()) return; + + CComPtr pResManager; + if (FAILED(pResManager.CoCreateInstance(CLSID_ResourceManager))) + return; + if (FAILED(pResManager->InitializeForPackage(packageName))) + return; + CComPtr pResMap; + if (FAILED(pResManager->GetMainResourceMap(IID_IResourceMap,(void**)&pResMap))) + return; + CComPtr pResContext; + if (FAILED(pResManager->GetDefaultContext(IID_ResourceContext,(void**)&pResContext))) + return; + int iconFlags=0; + int delta=g_bInvertMetroIcons?0:2; + if ((refreshFlags&INFO_SMALL_ICON) && SetResContextTargetSize(pResContext,SMALL_ICON_SIZE-delta)) + { + CComString pLocation; + if (SUCCEEDED(pResMap->GetFilePath(iconName,&pLocation))) + { + hSmallBitmap=LoadMetroBitmap0(pLocation,SMALL_ICON_SIZE,*pMetroColor); + refreshFlags&=~INFO_SMALL_ICON; + StoreInCache(hash,L"",hSmallBitmap,NULL,NULL,INFO_SMALL_ICON,smallIcon,largeIcon,extraLargeIcon,false,true); + } + } + if ((refreshFlags&INFO_LARGE_ICON) && SetResContextTargetSize(pResContext,LARGE_ICON_SIZE-delta)) + { + CComString pLocation; + if (SUCCEEDED(pResMap->GetFilePath(iconName,&pLocation))) + { + hLargeBitmap=LoadMetroBitmap0(pLocation,LARGE_ICON_SIZE,*pMetroColor); + refreshFlags&=~INFO_LARGE_ICON; + StoreInCache(hash,L"",NULL,hLargeBitmap,NULL,INFO_LARGE_ICON,smallIcon,largeIcon,extraLargeIcon,false,true); + } + } + if ((refreshFlags&INFO_SMALL_ICON) && SetResContextTargetSize(pResContext,EXTRA_LARGE_ICON_SIZE-delta)) + { + CComString pLocation; + if (SUCCEEDED(pResMap->GetFilePath(iconName,&pLocation))) + { + hExtraLargeBitmap=LoadMetroBitmap0(pLocation,EXTRA_LARGE_ICON_SIZE,*pMetroColor); + refreshFlags&=~INFO_EXTRA_LARGE_ICON; + StoreInCache(hash,L"",NULL,NULL,hExtraLargeBitmap,INFO_EXTRA_LARGE_ICON,smallIcon,largeIcon,extraLargeIcon,false,true); + } + } +} + +void CItemManager::FindInCache( unsigned int hash, int &refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon ) +{ + // look in the cache + RWLock lock(this,false,RWLOCK_ICONS); + std::multimap::iterator it=m_IconInfos.find(hash); + for (;it!=m_IconInfos.end() && it->first==hash;++it) + { + if ((refreshFlags&INFO_SMALL_ICON) && it->second.sizeType==ICON_SIZE_TYPE_SMALL) + { + smallIcon=&it->second; + refreshFlags&=~INFO_SMALL_ICON; + } + if ((refreshFlags&INFO_LARGE_ICON) && it->second.sizeType==ICON_SIZE_TYPE_LARGE) + { + largeIcon=&it->second; + refreshFlags&=~INFO_LARGE_ICON; + } + if ((refreshFlags&INFO_EXTRA_LARGE_ICON) && it->second.sizeType==ICON_SIZE_TYPE_EXTRA_LARGE) + { + extraLargeIcon=&it->second; + refreshFlags&=~INFO_EXTRA_LARGE_ICON; + } + } +} + +void CItemManager::StoreInCache( unsigned int hash, const wchar_t *path, HBITMAP hSmallBitmap, HBITMAP hLargeBitmap, HBITMAP hExtraLargeBitmap, int refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon, bool bTemp, bool bMetro ) +{ + RWLock lock(this,true,RWLOCK_ICONS); + std::multimap::iterator it=m_IconInfos.find(hash); + for (;it!=m_IconInfos.end() && it->first==hash;++it) + { + if ((refreshFlags&INFO_SMALL_ICON) && it->second.sizeType==ICON_SIZE_TYPE_SMALL) + { + if (hSmallBitmap) + { + HBITMAP old=it->second.bitmap; + it->second.bitmap=hSmallBitmap; + if (old) m_OldBitmaps.push_back(old); + hSmallBitmap=NULL; + } + smallIcon=&it->second; + refreshFlags&=~INFO_SMALL_ICON; + } + if ((refreshFlags&INFO_LARGE_ICON) && it->second.sizeType==ICON_SIZE_TYPE_LARGE) + { + if (hLargeBitmap) + { + HBITMAP old=it->second.bitmap; + it->second.bitmap=hLargeBitmap; + if (old) m_OldBitmaps.push_back(old); + hLargeBitmap=NULL; + } + largeIcon=&it->second; + refreshFlags&=~INFO_LARGE_ICON; + } + if ((refreshFlags&INFO_EXTRA_LARGE_ICON) && it->second.sizeType==ICON_SIZE_TYPE_EXTRA_LARGE) + { + if (hExtraLargeBitmap) + { + HBITMAP old=it->second.bitmap; + it->second.bitmap=hExtraLargeBitmap; + if (old) m_OldBitmaps.push_back(old); + hExtraLargeBitmap=NULL; + } + extraLargeIcon=&it->second; + refreshFlags&=~INFO_EXTRA_LARGE_ICON; + } + } + + if ((refreshFlags&INFO_SMALL_ICON) && hSmallBitmap) + { + IconInfo *pInfo=&m_IconInfos.insert(std::pair(hash,IconInfo()))->second; + pInfo->sizeType=ICON_SIZE_TYPE_SMALL; + pInfo->bTemp=bTemp; + pInfo->bMetro=bMetro; + pInfo->SetPath(path); + pInfo->bitmap=hSmallBitmap; + smallIcon=pInfo; + } + if ((refreshFlags&INFO_LARGE_ICON) && hLargeBitmap) + { + IconInfo *pInfo=&m_IconInfos.insert(std::pair(hash,IconInfo()))->second; + pInfo->sizeType=ICON_SIZE_TYPE_LARGE; + pInfo->bTemp=bTemp; + pInfo->bMetro=bMetro; + pInfo->SetPath(path); + pInfo->bitmap=hLargeBitmap; + largeIcon=pInfo; + } + if ((refreshFlags&INFO_EXTRA_LARGE_ICON) && hExtraLargeBitmap) + { + IconInfo *pInfo=&m_IconInfos.insert(std::pair(hash,IconInfo()))->second; + pInfo->sizeType=ICON_SIZE_TYPE_EXTRA_LARGE; + pInfo->bTemp=bTemp; + pInfo->bMetro=bMetro; + pInfo->SetPath(path); + pInfo->bitmap=hExtraLargeBitmap; + extraLargeIcon=pInfo; + } +} + +void CItemManager::IconInfo::SetPath( const wchar_t *path ) +{ + Assert(RWLock::ThreadHasWriteLock(RWLOCK_ICONS)); + if (path && (_wcsicmp(path,L"shell32.dll")==0 || _wcsicmp(path,L"imageres.dll")==0)) + { + PATH=path; + StringUpper(PATH); + timestamp.dwHighDateTime=timestamp.dwLowDateTime=0; + return; + } + if (path && path[0] && path[1]=='#') + { + PATH=path; + StringUpper(PATH); + timestamp.dwHighDateTime=timestamp.dwLowDateTime=0; + return; + } + if (path && path[0] && path[1]==':' && !PathIsNetworkPath(path)) + { + WIN32_FILE_ATTRIBUTE_DATA attributes={0}; + if (GetFileAttributesEx(path,GetFileExInfoStandard,&attributes)) + { + PATH=path; + StringUpper(PATH); + timestamp=attributes.ftLastWriteTime; + return; + } + } + PATH.Empty(); + timestamp.dwHighDateTime=timestamp.dwLowDateTime=0; +} + +void CItemManager::LoadCustomIcon( const wchar_t *iconPath, int iconIndex, int refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon, bool bTemp ) +{ + unsigned int hash=CalcFNVHash(iconPath,CalcFNVHash(&iconIndex,4)); + + FindInCache(hash,refreshFlags,smallIcon,largeIcon,extraLargeIcon); + if (!refreshFlags) return; + + // extract icon + HBITMAP hSmallBitmap=NULL, hLargeBitmap=NULL, hExtraLargeBitmap=NULL; + if (refreshFlags&INFO_SMALL_ICON) + { + HICON hIcon; + if (!*iconPath) + hIcon=(HICON)LoadImage(g_Instance,MAKEINTRESOURCE(-iconIndex),IMAGE_ICON,SMALL_ICON_SIZE,SMALL_ICON_SIZE,LR_DEFAULTCOLOR); + else + hIcon=ShExtractIcon(iconPath,iconIndex==-1?0:iconIndex,SMALL_ICON_SIZE); + if (hIcon) + hSmallBitmap=BitmapFromIcon(hIcon,SMALL_ICON_SIZE); + } + + if (refreshFlags&INFO_LARGE_ICON) + { + HICON hIcon; + if (!*iconPath) + hIcon=(HICON)LoadImage(g_Instance,MAKEINTRESOURCE(-iconIndex),IMAGE_ICON,LARGE_ICON_SIZE,LARGE_ICON_SIZE,LR_DEFAULTCOLOR); + else + hIcon=ShExtractIcon(iconPath,iconIndex==-1?0:iconIndex,LARGE_ICON_SIZE); + if (hIcon) + hLargeBitmap=BitmapFromIcon(hIcon,LARGE_ICON_SIZE); + } + + if (refreshFlags&INFO_EXTRA_LARGE_ICON) + { + HICON hIcon; + if (!*iconPath) + hIcon=(HICON)LoadImage(g_Instance,MAKEINTRESOURCE(-iconIndex),IMAGE_ICON,EXTRA_LARGE_ICON_SIZE,EXTRA_LARGE_ICON_SIZE,LR_DEFAULTCOLOR); + else + hIcon=ShExtractIcon(iconPath,iconIndex==-1?0:iconIndex,EXTRA_LARGE_ICON_SIZE); + if (hIcon) + hExtraLargeBitmap=BitmapFromIcon(hIcon,EXTRA_LARGE_ICON_SIZE); + } + + StoreInCache(hash,bTemp?NULL:iconPath,hSmallBitmap,hLargeBitmap,hExtraLargeBitmap,refreshFlags,smallIcon,largeIcon,extraLargeIcon,bTemp,false); +} + +// Recursive function to preload the items for a folder +void CItemManager::LoadFolderItems( IShellItem *pFolder, int refreshFlags, int levels, TLocation location ) +{ + CShellItemEnumerator enumerator(pFolder); + if (!enumerator.IsValid()) return; + + int queueFlags=refreshFlags&INFO_ICON; + refreshFlags&=~INFO_ICON; + CComPtr pChild; + CAbsolutePidl childPidl; + while (enumerator.GetNext(pChild,childPidl)) + { + if (location==CItemManager::LOCATION_DESKTOP) + { + // collect only links from the desktop. this is an attempt to skip the SkyDrive item, which is causing problems. + SFGAOF attr=0; + if (FAILED(pChild->GetAttributes(SFGAO_LINK,&attr)) || !(attr&SFGAO_LINK)) + continue; + } + if (m_LoadingStage!=LOAD_LOADING) break; + + ItemInfo *pItemInfo=const_cast(GetItemInfo(pChild,childPidl,refreshFlags,location)); + if (queueFlags) + { + RWLock lock(this,true,RWLOCK_ITEMS); + QueueItemInfo(pItemInfo,queueFlags); + } + + if (levels>1) + { + SFGAOF flags=0; + if (SUCCEEDED(pChild->GetAttributes(SFGAO_FOLDER|SFGAO_STREAM|SFGAO_LINK,&flags)) && (flags&(SFGAO_FOLDER|SFGAO_STREAM|SFGAO_LINK))==SFGAO_FOLDER) + { + // go into subfolders but not archives or links to folders + LoadFolderItems(pChild,refreshFlags|queueFlags,levels-1,location); + } + } + } +} + +CItemManager::TLocation CItemManager::DetermineLocation( const wchar_t *PATH ) +{ + if (wcsncmp(PATH,m_RootStartMenu1,m_RootStartMenu1.GetLength())==0) + return LOCATION_START_MENU; + if (wcsncmp(PATH,m_RootStartMenu2,m_RootStartMenu2.GetLength())==0) + return LOCATION_START_MENU; + if (wcsncmp(PATH,m_RootStartMenu3,m_RootStartMenu3.GetLength())==0) + return LOCATION_START_MENU; + if (wcsncmp(PATH,m_RootGames,m_RootGames.GetLength())==0) + return LOCATION_GAMES; + if (wcsncmp(PATH,m_RootDesktop,m_RootDesktop.GetLength())==0) + return LOCATION_DESKTOP; + if (wcsncmp(PATH,m_RootTaskbar,m_RootTaskbar.GetLength())==0) + return LOCATION_TASKBAR; + if (wcsncmp(PATH,m_RootMetro,m_RootMetro.GetLength())==0) + return LOCATION_METRO; + return LOCATION_UNKNOWN; +} + +// Recursive function to preload the metro apps +void CItemManager::LoadMetroItems( int refreshFlags ) +{ + std::vector links; + std::vector nonApps10; + GetMetroLinks(links,false,&nonApps10); + int queueFlags=refreshFlags&INFO_ICON; + refreshFlags&=~queueFlags; + for (std::vector::const_iterator it=links.begin();it!=links.end();++it) + { + ItemInfo *pItemInfo=const_cast(GetItemInfo(it->pItem,it->pidl,refreshFlags,LOCATION_METRO)); + if (queueFlags) + { + RWLock lock(this,true,RWLOCK_ITEMS); + QueueItemInfo(pItemInfo,queueFlags); + } + if (m_LoadingStage!=LOAD_LOADING) break; + } + if (GetWinVersion()>=WIN_VER_WIN10) + { + wchar_t APPID[256]; + for (std::vector::const_iterator it=links.begin();it!=links.end();++it) + { + const ItemInfo *pInfo=GetItemInfo(it->pItem,it->pidl,INFO_LINK|INFO_LINK_APPID|INFO_METRO); + Strcpy(APPID,_countof(APPID),it->appid); + CharUpper(APPID); + unsigned int hash=CalcFNVHash(APPID); + { + RWLock lock(this,true,RWLOCK_ITEMS); + std::map::const_iterator it2=m_MetroItemInfos10.find(hash); + if (it2==m_MetroItemInfos10.end()) + m_MetroItemInfos10[hash]=pInfo; + std::set::iterator it3=m_BlackListInfos10.find(hash); + if (it3!=m_BlackListInfos10.end()) + m_BlackListInfos10.erase(it3); + } + } + + { + RWLock lock(this,true,RWLOCK_ITEMS); + for (std::vector::const_iterator it=nonApps10.begin();it!=nonApps10.end();++it) + { + Strcpy(APPID,_countof(APPID),*it); + CharUpper(APPID); + unsigned int hash=CalcFNVHash(APPID); + std::map::const_iterator it2=m_MetroItemInfos10.find(hash); + if (it2==m_MetroItemInfos10.end()) + m_MetroItemInfos10[hash]=NULL; + std::set::iterator it3=m_BlackListInfos10.find(hash); + if (it3!=m_BlackListInfos10.end()) + m_BlackListInfos10.erase(it3); + } + } + } +} + +static KNOWNFOLDERID FOLDERID_TaskbarPinned={'TASK', 'BA', 'R', {'P', 'I', 'N', 'N', 'E', 'D'}}; +static KNOWNFOLDERID FOLDERID_ClassicPinned={'CLAS', 'SI', 'C', {'P', 'I', 'N', 'N', 'E', 'D'}}; +static KNOWNFOLDERID FOLDERID_MetroApps={'MET', 'R', 'O', {'A', 'P', 'P', 'S'}}; + +static struct +{ + KNOWNFOLDERID folder; + int refreshFlags; + int levels; + CItemManager::TLocation location; +} g_CacheFolders[]= +{ + {FOLDERID_StartMenu,CItemManager::INFO_LINK|CItemManager::INFO_METRO|CItemManager::INFO_SMALL_ICON,MAX_FOLDER_LEVELS,CItemManager::LOCATION_START_MENU}, + {FOLDERID_CommonStartMenu,CItemManager::INFO_LINK|CItemManager::INFO_METRO|CItemManager::INFO_SMALL_ICON,MAX_FOLDER_LEVELS,CItemManager::LOCATION_START_MENU}, + {FOLDERID_Desktop,CItemManager::INFO_LINK,1,CItemManager::LOCATION_DESKTOP}, + {FOLDERID_PublicDesktop,CItemManager::INFO_LINK,1,CItemManager::LOCATION_DESKTOP}, + {FOLDERID_TaskbarPinned,CItemManager::INFO_LINK,1,CItemManager::LOCATION_TASKBAR}, + {FOLDERID_ClassicPinned,CItemManager::INFO_LINK|CItemManager::INFO_METRO|CItemManager::INFO_SMALL_ICON,1,CItemManager::LOCATION_START_MENU}, + {FOLDERID_MetroApps,CItemManager::INFO_LINK|CItemManager::INFO_METRO,1,CItemManager::LOCATION_METRO}, + {FOLDERID_ControlPanelFolder,CItemManager::INFO_SMALL_ICON,1,CItemManager::LOCATION_UNKNOWN}, + {FOLDERID_Favorites,CItemManager::INFO_SMALL_ICON,MAX_FOLDER_LEVELS,CItemManager::LOCATION_UNKNOWN}, +}; + +const int NUM_WATCHED_DIRS=7; + +void CItemManager::PreloadItemsThread( void ) +{ + int dirCount=0; + HANDLE handles[NUM_WATCHED_DIRS+1]; + DWORD dirMasks[NUM_WATCHED_DIRS]={0}; + DWORD dirMask=0xFFFFFFFF; + while (1) + { + for (int i=0;i<_countof(g_CacheFolders);i++) + { + if (m_LoadingStage!=LOAD_LOADING) break; + if (i==NUM_WATCHED_DIRS && dirMask==0xFFFFFFFF) + SetEvent(m_DoneEvent); + if (!(dirMask&(1< pFolder; + if (g_CacheFolders[i].folder==FOLDERID_TaskbarPinned) + { + wchar_t path[_MAX_PATH]=TASKBAR_PINNED_ROOT; + DoEnvironmentSubst(path,_countof(path)); + if (FAILED(SHParseDisplayName(path,NULL,&pidl,0,NULL)) || !pidl) continue; + if (FAILED(SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pFolder)) || !pFolder) continue; + } + else if (g_CacheFolders[i].folder==FOLDERID_ClassicPinned) + { + if (GetSettingInt(L"PinnedPrograms")!=PINNED_PROGRAMS_PINNED) continue; + wchar_t path[_MAX_PATH]=START_MENU_PINNED_ROOT; + DoEnvironmentSubst(path,_countof(path)); + if (FAILED(SHParseDisplayName(path,NULL,&pidl,0,NULL)) || !pidl) continue; + if (FAILED(SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pFolder)) || !pFolder) continue; + } + else if (g_CacheFolders[i].folder==FOLDERID_MetroApps) + { + if (GetWinVersion()WAIT_OBJECT_0+dirCount-1) + break; + + int dir=wait-WAIT_OBJECT_0; + dirMask=dirMasks[dir]; + + if (!FindNextChangeNotification(handles[dir])) + ResetEvent(handles[dir]); // so we don't wake on this event again + Sleep(1000); // hopefully whatever file operation is in progress will finish in a second + } + for (int i=0;im_LoadIconData[1].Init(); + wchar_t path[_MAX_PATH]; + GetModuleFileName(g_Instance,path,_countof(path)); + LoadLibrary(path); // stop the DLL from unloading + pThis->PreloadItemsThread(); + pThis->m_LoadIconData[1].Close(); + CoUninitialize(); + FreeLibraryAndExitThread(g_Instance,0); // release the DLL + return 0; +} + +void CItemManager::RefreshInfoThread( void ) +{ + WaitForSingleObject(m_StartEvent,REFRESH_DELAY); + bool bRefresh=false; + while (1) + { + HANDLE handles[2]={m_WorkEvent,m_ExitEvent}; + WaitForMultipleObjects(2,handles,FALSE,INFINITE); + bRefresh=false; + int t0=GetTickCount(); + while (1) + { + if (m_LoadingStage!=LOAD_LOADING) + return; + + ItemInfo *pItemInfo=NULL; + int refreshFlags=0; + { + Lock cleanupLock(this,LOCK_CLEANUP); + { + RWLock lock(this,true,RWLOCK_ITEMS); + if (!m_ItemQueue.empty()) + { + pItemInfo=*m_ItemQueue.begin(); + m_ItemQueue.pop_front(); + } + else if (!m_ItemQueueLow.empty()) + { + pItemInfo=*m_ItemQueueLow.begin(); + m_ItemQueueLow.pop_front(); + } + else + break; + refreshFlags=pItemInfo->refreshFlags; + } + if (refreshFlags && pItemInfo->bTemp) + { + // temp items must be refreshed inside LOCK_CLEANUP because the cleanup process will delete all such items + RefreshItemInfo(pItemInfo,refreshFlags,NULL,false); + refreshFlags=0; + } + } + if (refreshFlags) + { + // non-temp items should be refreshed outside LOCK_CLEANUP + RefreshItemInfo(pItemInfo,refreshFlags,NULL,false); + } + + bRefresh=true; + int t=GetTickCount(); + if (t-t0>100) + { + CMenuContainer::RefreshIcons(); + t0=t; + bRefresh=false; + } + } + if (bRefresh) + CMenuContainer::RefreshIcons(); + } +} + +DWORD CALLBACK CItemManager::StaticRefreshInfoThread( void *param ) +{ + CItemManager *pThis=(CItemManager*)param; + volatile DWORD MAIN_THREAD=pThis->m_MainThreadId; + SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_IDLE); + CoInitialize(NULL); + pThis->m_LoadIconData[2].Init(); + pThis->RefreshInfoThread(); + pThis->m_LoadIconData[2].Close(); + CoUninitialize(); + return MAIN_THREAD-MAIN_THREAD; +} + +namespace +{ + struct IconData + { + unsigned int key; + CItemManager::TIconSizeType sizeType; + int PATHLen; + FILETIME timestamp; + int bitmapW, bitmapH; + }; + + struct ItemData + { + unsigned int key; + FILETIME writestamp; + FILETIME createstamp; + bool bIconOnly; + bool bLink; + bool bMetroLink; + bool bProtectedLink; + bool bNoPin; + bool bNoNew; + bool bExplicitAppId; + int pidlSize; + int pathLen; + int PATHLen; + int smallIcon; + int largeIcon; + int extraLargeIcon; + int validFlags; + int targetPidlSize; + int targetPATHLen; + int appidLen; + int metroNameLen; + int iconPathLen; + DWORD iconColor; + int iconIndex; + }; +} + +static DWORD ReadCacheFile( HANDLE file ) +{ + DWORD data; + DWORD q; + if (!ReadFile(file,&data,4,&q,NULL) || q!=4) + return 0; + return data; +} + +static bool ReadCacheFile( HANDLE file, IconData &data ) +{ + DWORD q; + return ReadFile(file,&data,sizeof(data),&q,NULL)!=0 && q==sizeof(data); +} + +static bool ReadCacheFile( HANDLE file, ItemData &data ) +{ + DWORD q; + return ReadFile(file,&data,sizeof(data),&q,NULL)!=0 && q==sizeof(data); +} + +static bool ReadCacheFile( HANDLE file, CAbsolutePidl &data, int size ) +{ + if (size>0) + { + PIDLIST_ABSOLUTE pidl=(PIDLIST_ABSOLUTE)CoTaskMemAlloc(size); + if (!pidl) return false; + DWORD q; + if (!ReadFile(file,pidl,size,&q,NULL) || q!=size) + { + ILFree(pidl); + return false; + } + data.Attach(pidl); + } + return true; +} + +static bool ReadCacheFile( HANDLE file, CString &data, int len ) +{ + if (len>0) + { + DWORD q; + if (!ReadFile(file,data.GetBuffer(len),len*2,&q,NULL) || q!=len*2) + { + data.Empty(); + return false; + } + data.ReleaseBuffer(len); + } + return true; +} + +static bool ReadCacheFile( HANDLE file, HDC hdc, HBITMAP &data, int width, int height ) +{ + std::vector bits(width*height); + if (bits.empty()) return false; + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=width; + bi.bmiHeader.biHeight=height; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + DWORD q; + int size=width*height*4; + if (!ReadFile(file,&bits[0],size,&q,NULL) || q!=size) + return false; + unsigned int *pBits; + data=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&pBits,NULL,0); + if (!data) + return false; + memcpy(pBits,&bits[0],size); + return true; +} + +static void WriteCacheFile( HANDLE file, DWORD data ) +{ + DWORD q; + WriteFile(file,&data,sizeof(data),&q,NULL); +} + +static void WriteCacheFile( HANDLE file, const IconData &data ) +{ + DWORD q; + WriteFile(file,&data,sizeof(data),&q,NULL); +} + +static void WriteCacheFile( HANDLE file, const ItemData &data ) +{ + DWORD q; + WriteFile(file,&data,sizeof(data),&q,NULL); +} + +static void WriteCacheFile( HANDLE file, PIDLIST_ABSOLUTE data, int size ) +{ + if (size>0) + { + DWORD q; + WriteFile(file,data,size,&q,NULL); + } +} + +static void WriteCacheFile( HANDLE file, const CString &data ) +{ + if (!data.IsEmpty()) + { + DWORD q; + WriteFile(file,(const wchar_t*)data,data.GetLength()*2,&q,NULL); + } +} + +static void WriteCacheFile( HANDLE file, HDC hdc, HBITMAP data, int width, int height ) +{ + std::vector bits(width*height); + if (bits.empty()) return; + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=width; + bi.bmiHeader.biHeight=height; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + GetDIBits(hdc,data,0,height,&bits[0],&bi,DIB_RGB_COLORS); + DWORD q; + WriteFile(file,&bits[0],width*height*4,&q,NULL); +} + +bool CItemManager::CompareModuleTimeStamp( const CString &PATH, const FILETIME ×tamp, std::vector &modules ) +{ + for (std::vector::const_iterator it=modules.begin();it!=modules.end();++it) + { + if (it->PATH==PATH) + return (CompareFileTime(×tamp,&it->timestamp)==0); + } + WIN32_FILE_ATTRIBUTE_DATA attributes={0}; + if (GetFileAttributesEx(PATH,GetFileExInfoStandard,&attributes)) + { + ModuleInfo info={PATH,attributes.ftLastWriteTime}; + modules.push_back(info); + return (CompareFileTime(×tamp,&info.timestamp)==0); + } + else + { + ModuleInfo info={PATH}; + modules.push_back(info); + return false; + } +} + +void CItemManager::LoadCacheFile( void ) +{ +#ifdef DISABLE_CACHE + return; +#endif + // load cached icons and info + wchar_t path[_MAX_PATH]=L"%LOCALAPPDATA%\\ClassicShell\\DataCache.db"; + DoEnvironmentSubst(path,_MAX_PATH); + + HANDLE file=CreateFile(path,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + if (file==INVALID_HANDLE_VALUE) return; + + bool bError=true; + DWORD tag=ReadCacheFile(file); + std::vector modules; + ModuleInfo stdInfo={L"SHELL32.DLL"}; + modules.push_back(stdInfo); + stdInfo.PATH=L"IMAGERES.DLL"; + modules.push_back(stdInfo); + m_BlackListInfos10.clear(); + if (tag=='CLSH') + { + tag=ReadCacheFile(file); + std::vector remapIcons(1); + remapIcons[0]=NULL; + DWORD build; + if (tag==GetVersionEx(g_Instance,&build) && ReadCacheFile(file)==CACHE_FILE_VERSION) + { + int size1=ReadCacheFile(file); + int size2=ReadCacheFile(file); + int size3=ReadCacheFile(file); + int langHash=ReadCacheFile(file); + bError=false; + tag=ReadCacheFile(file); + HDC hdc=CreateCompatibleDC(NULL); + while (tag=='ICON') + { + IconData data; + if (!ReadCacheFile(file,data)) + { + bError=true; + break; + } + IconInfo info; + info.sizeType=data.sizeType; + info.timestamp=data.timestamp; + info.bTemp=false; + info.bMetro=false; + if (!ReadCacheFile(file,info.PATH,data.PATHLen)) + { + bError=true; + break; + } + if (size1==SMALL_ICON_SIZE && size2==LARGE_ICON_SIZE && size3==EXTRA_LARGE_ICON_SIZE && CompareModuleTimeStamp(info.PATH,info.timestamp,modules)) + { + if (!ReadCacheFile(file,hdc,info.bitmap,data.bitmapW,data.bitmapH)) + { + bError=true; + break; + } + remapIcons.push_back(&m_IconInfos.insert(std::pair(data.key,info))->second); + } + else + { + int size=data.bitmapW*data.bitmapH*4; + SetFilePointer(file,size,NULL,FILE_CURRENT); + remapIcons.push_back(NULL); + } + tag=ReadCacheFile(file); + } + DeleteDC(hdc); + if (tag!='ITEM') + { + bError=true; + } + else + { + wchar_t languages[100]; + DWORD size=0; + DWORD len=_countof(languages); + GetUserPreferredUILanguages(MUI_LANGUAGE_ID,&size,languages,&len); + bError=(CalcFNVHash(languages,len*2,FNV_HASH0)!=langHash); + } + while (!bError && tag=='ITEM') + { + ItemData data; + if (!ReadCacheFile(file,data)) + { + bError=true; + break; + } + ItemInfo &info=m_ItemInfos.insert(std::pair(data.key,ItemInfo()))->second; + + info.writestamp=data.writestamp; + info.createstamp=data.createstamp; + info.bIconOnly=data.bIconOnly; + info.bTemp=false; + info.bLink=data.bLink; + info.bMetroLink=data.bMetroLink; + info.bProtectedLink=data.bProtectedLink; + info.bNoPin=data.bNoPin; + info.bNoNew=data.bNoNew; + info.bExplicitAppId=data.bExplicitAppId; + info.validFlags=data.validFlags; + info.refreshFlags=0; + info.iconColor=data.iconColor; + info.iconIndex=data.iconIndex; + + info.smallIcon=data.smallIcon<(int)remapIcons.size()?remapIcons[data.smallIcon]:NULL; + if (!info.smallIcon) + { + info.validFlags&=~INFO_SMALL_ICON; + info.smallIcon=m_DefaultSmallIcon; + } + info.largeIcon=data.largeIcon<(int)remapIcons.size()?remapIcons[data.largeIcon]:NULL; + if (!info.largeIcon) + { + info.validFlags&=~INFO_LARGE_ICON; + info.largeIcon=m_DefaultLargeIcon; + } + info.extraLargeIcon=data.extraLargeIcon<(int)remapIcons.size()?remapIcons[data.extraLargeIcon]:NULL; + if (!info.extraLargeIcon) + { + info.validFlags&=~INFO_EXTRA_LARGE_ICON; + info.extraLargeIcon=m_DefaultExtraLargeIcon; + } + + bError=bError || !ReadCacheFile(file,info.pidl,data.pidlSize); + bError=bError || !ReadCacheFile(file,info.path,data.pathLen); + bError=bError || !ReadCacheFile(file,info.PATH,data.PATHLen); + bError=bError || !ReadCacheFile(file,info.targetPidl,data.targetPidlSize); + bError=bError || !ReadCacheFile(file,info.targetPATH,data.targetPATHLen); + bError=bError || !ReadCacheFile(file,info.appid,data.appidLen); + bError=bError || !ReadCacheFile(file,info.metroName,data.metroNameLen); + bError=bError || !ReadCacheFile(file,info.iconPath,data.iconPathLen); + + tag=ReadCacheFile(file); + } + if (tag=='BLAK') + { + int count=ReadCacheFile(file); + for (int i=0;i::const_iterator it=m_IconInfos.begin();it!=m_IconInfos.end();++it) + { + if (it->second.bitmap) + DeleteObject(it->second.bitmap); + } + m_IconInfos.clear(); + CreateDefaultIcons(); + } +} + +DWORD CALLBACK CItemManager::SaveCacheFileThread( void *param ) +{ + CItemManager *pThis=(CItemManager*)param; + wchar_t path[_MAX_PATH]=L"%LOCALAPPDATA%\\ClassicShell"; + DoEnvironmentSubst(path,_MAX_PATH); + SHCreateDirectory(NULL,path); + Strcat(path,_countof(path),L"\\DataCache.tmp"); + HANDLE file=CreateFile(path,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); + if (file==INVALID_HANDLE_VALUE) return 0; + + WriteCacheFile(file,'CLSH'); + WriteCacheFile(file,GetVersionEx(g_Instance)); + WriteCacheFile(file,CACHE_FILE_VERSION); + WriteCacheFile(file,SMALL_ICON_SIZE); + WriteCacheFile(file,LARGE_ICON_SIZE); + WriteCacheFile(file,EXTRA_LARGE_ICON_SIZE); + { + wchar_t languages[100]; + DWORD size=0; + DWORD len=_countof(languages); + GetUserPreferredUILanguages(MUI_LANGUAGE_ID,&size,languages,&len); + WriteCacheFile(file,CalcFNVHash(languages,len*2,FNV_HASH0)); + } + + std::vector*> iconInfos; + { + RWLock lock(pThis,false,RWLOCK_ICONS); + for (std::multimap::const_iterator it=pThis->m_IconInfos.begin();it!=pThis->m_IconInfos.end();++it) + { + if (!it->second.PATH.IsEmpty() && it->second.PATH[1]!='#' && it->first!=0) + iconInfos.push_back(&*it); + } + } + + std::vector*> itemInfos; + std::vector blackList; + { + RWLock lock(pThis,false,RWLOCK_ITEMS); + for (std::multimap::const_iterator it=pThis->m_ItemInfos.begin();it!=pThis->m_ItemInfos.end();++it) + { + if (it->first!=0) + itemInfos.push_back(&*it); + } + for (std::set::const_iterator it=pThis->m_BlackListInfos10.begin();it!=pThis->m_BlackListInfos10.end();++it) + blackList.push_back(*it); + } + + HDC hdc=CreateCompatibleDC(NULL); + std::map remapIcons; + int iconIndex=1; + // save cached icons and info + for (std::vector*>::const_iterator it=iconInfos.begin();it!=iconInfos.end();++it) + { + RWLock lock(pThis,false,RWLOCK_ICONS); + if ((*it)->second.bTemp || (*it)->second.bMetro) continue; + remapIcons[&(*it)->second]=iconIndex++; + IconData data; + data.key=(*it)->first; + data.sizeType=(*it)->second.sizeType; + data.timestamp=(*it)->second.timestamp; + data.PATHLen=(*it)->second.PATH.GetLength(); + BITMAP bmp; + GetObject((*it)->second.bitmap,sizeof(bmp),&bmp); + data.bitmapW=bmp.bmWidth; + data.bitmapH=bmp.bmHeight; + + WriteCacheFile(file,'ICON'); + WriteCacheFile(file,data); + WriteCacheFile(file,(*it)->second.PATH); + WriteCacheFile(file,hdc,(*it)->second.bitmap,data.bitmapW,data.bitmapH); + } + DeleteDC(hdc); + + FILE *log=NULL; + if (g_LogCategories&LOG_CACHE) + { + wchar_t path3[_MAX_PATH]=L"%LOCALAPPDATA%\\ClassicShell\\DataCache.txt"; + DoEnvironmentSubst(path3,_countof(path3)); + if (_wfopen_s(&log,path3,L"wb")==0) + { + wchar_t bom=0xFEFF; + fwrite(&bom,2,1,log); + } + } + for (std::vector*>::const_iterator it=itemInfos.begin();it!=itemInfos.end();++it) + { + RWLock lock(pThis,false,RWLOCK_ITEMS); + if ((*it)->second.bTemp || (*it)->second.path.IsEmpty()) continue; + + ItemData data; + data.key=(*it)->first; + data.writestamp=(*it)->second.writestamp; + data.createstamp=(*it)->second.createstamp; + data.bIconOnly=(*it)->second.bIconOnly; + data.bLink=(*it)->second.bLink; + data.bMetroLink=(*it)->second.bMetroLink; + data.bProtectedLink=(*it)->second.bProtectedLink; + data.bNoPin=(*it)->second.bNoPin; + data.bNoNew=(*it)->second.bNoNew; + data.bExplicitAppId=(*it)->second.bExplicitAppId; + data.pidlSize=(*it)->second.GetLatestPidl()?ILGetSize((*it)->second.GetLatestPidl()):0; + data.pathLen=(*it)->second.path.GetLength(); + data.PATHLen=(*it)->second.PATH.GetLength(); + + std::map::const_iterator remapIt=remapIcons.find((*it)->second.smallIcon); + data.smallIcon=(remapIt==remapIcons.end()?0:remapIt->second); + remapIt=remapIcons.find((*it)->second.largeIcon); + data.largeIcon=(remapIt==remapIcons.end()?0:remapIt->second); + remapIt=remapIcons.find((*it)->second.extraLargeIcon); + data.extraLargeIcon=(remapIt==remapIcons.end()?0:remapIt->second); + + data.validFlags=(*it)->second.validFlags; + data.targetPidlSize=(*it)->second.targetPidl?ILGetSize((*it)->second.targetPidl):0; + data.targetPATHLen=(*it)->second.targetPATH.GetLength(); + data.appidLen=(*it)->second.appid.GetLength(); + data.metroNameLen=(*it)->second.metroName.GetLength(); + data.iconPathLen=(*it)->second.iconPath.GetLength(); + data.iconColor=(*it)->second.iconColor; + data.iconIndex=(*it)->second.iconIndex; + + WriteCacheFile(file,'ITEM'); + WriteCacheFile(file,data); + WriteCacheFile(file,(*it)->second.GetLatestPidl(),data.pidlSize); + WriteCacheFile(file,(*it)->second.path); + WriteCacheFile(file,(*it)->second.PATH); + WriteCacheFile(file,(*it)->second.targetPidl,data.targetPidlSize); + WriteCacheFile(file,(*it)->second.targetPATH); + WriteCacheFile(file,(*it)->second.appid); + WriteCacheFile(file,(*it)->second.metroName); + WriteCacheFile(file,(*it)->second.iconPath); + if (log) fwprintf(log,L"0x%08X - %s\r\n",(*it)->first,(*it)->second.PATH); + } + { + WriteCacheFile(file,'BLAK'); + WriteCacheFile(file,(DWORD)blackList.size()); + for (std::vector::const_iterator it=blackList.begin();it!=blackList.end();++it) + WriteCacheFile(file,*it); + } + if (log) fclose(log); + + CloseHandle(file); + wchar_t path2[_MAX_PATH]=L"%LOCALAPPDATA%\\ClassicShell\\DataCache.db"; + DoEnvironmentSubst(path2,_MAX_PATH); + MoveFileEx(path,path2,MOVEFILE_REPLACE_EXISTING); + return 0; +} + +void CItemManager::SaveCacheFile( void ) +{ +#ifdef DISABLE_CACHE + return; +#endif + if (g_LogCategories&LOG_CACHE) + { + SaveCacheFileThread(this); + return; + } + int time=GetTickCount(); + if (m_LastCacheSave && (time-m_LastCacheSave)<300000) // at least 5 minutes since the last save + return; + m_LastCacheSave=time; + if (m_SaveCacheThread) + { + if (WaitForSingleObject(m_SaveCacheThread,0)==WAIT_TIMEOUT) + return; + CloseHandle(m_SaveCacheThread); + m_SaveCacheThread=NULL; + } + m_SaveCacheThread=CreateThread(NULL,0,SaveCacheFileThread,this,0,NULL); +} + +void CItemManager::ClearCache( void ) +{ + Lock cleanupLock(this,LOCK_CLEANUP); + RWLock itemLock(this,true,RWLOCK_ITEMS); + RWLock iconLock(this,true,RWLOCK_ICONS); + + wchar_t path[_MAX_PATH]=L"%LOCALAPPDATA%\\ClassicShell\\DataCache.db"; + DoEnvironmentSubst(path,_MAX_PATH); + DeleteFile(path); + + m_BlackListInfos10.clear(); + m_ItemInfos.clear(); + for (std::multimap::const_iterator it=m_IconInfos.begin();it!=m_IconInfos.end();++it) + { + if (it->second.bitmap) + DeleteObject(it->second.bitmap); + } + m_IconInfos.clear(); + m_MetroItemInfos10.clear(); + CreateDefaultIcons(); + ItemInfo &item=m_ItemInfos.insert(std::pair(0,ItemInfo()))->second; + item.bIconOnly=true; + item.smallIcon=m_DefaultSmallIcon; + item.largeIcon=m_DefaultLargeIcon; + item.extraLargeIcon=m_DefaultExtraLargeIcon; +} + +// retrieves the pidl and the SFGAO_FOLDER, SFGAO_STREAM, SFGAO_LINK flags for the path +// for paths starting with \\ tries to guess if it is a folder or a link based on the extension +HRESULT MenuParseDisplayName( const wchar_t *path, PIDLIST_ABSOLUTE *pPidl, SFGAOF *pFlags, TNetworkType *pNetworkType ) +{ + if (pFlags) + *pFlags=0; + *pPidl=NULL; + if (pNetworkType) + *pNetworkType=NETWORK_NONE; + if (PathIsNetworkPath(path)) + { + *pPidl=SHSimpleIDListFromPath(path); + if (!*pPidl) + return E_FAIL; + if (pFlags || pNetworkType) + { + const wchar_t *ext=PathFindExtension(path); + if (!*ext) + { + if (pFlags) + *pFlags=SFGAO_FOLDER; + if (pNetworkType) + { + if (path[1]==':') + { + // drive: + if (path[2]=='\\' && path[3]) // drive:\folder + *pNetworkType=NETWORK_FOLDER; + else + *pNetworkType=NETWORK_DRIVE; + } + else if (path[0]=='\\' && path[1]=='\\') + { + // \\server + const wchar_t *c=wcschr(path+2,'\\'); + if (c) + { + // \\server\share[\folder] + *pNetworkType=wcschr(c+2,'\\')?NETWORK_FOLDER:NETWORK_SHARE; + } + else + *pNetworkType=NETWORK_SERVER; + } + else + { + // something else + *pNetworkType=NETWORK_FOLDER; + } + } + } + else if (_wcsicmp(ext,L".lnk")==0) + { + if (pFlags) + *pFlags=SFGAO_LINK; + if (pNetworkType) + *pNetworkType=NETWORK_FILE; + } + else + { + if (pFlags) + *pFlags=0; + if (pNetworkType) + *pNetworkType=NETWORK_FILE; + } + } + return S_OK; + } + else + { + return ShParseDisplayName(path,pPidl,SFGAO_FOLDER|SFGAO_STREAM|SFGAO_LINK,pFlags); + } +} + +const wchar_t *GetDefaultNetworkIcon( TNetworkType networkType ) +{ + switch (networkType) + { + case NETWORK_SERVER: + return L"imageres.dll,109"; + case NETWORK_SHARE: + return L"imageres.dll,143"; + case NETWORK_DRIVE: + return L"imageres.dll,33"; + case NETWORK_FOLDER: + return L"imageres.dll,3"; + default: + return L"imageres.dll,2"; + } +} + +bool MenuGetFileTimestamp( const wchar_t *path, FILETIME *pWriteTime, FILETIME *pCreateTime ) +{ + if (PathIsNetworkPath(path)) + { + memset(pWriteTime,0,sizeof(FILETIME)); + memset(pCreateTime,0,sizeof(FILETIME)); + return true; + } + else + { + WIN32_FILE_ATTRIBUTE_DATA attributes={0}; + if (!GetFileAttributesEx(path,GetFileExInfoStandard,&attributes)) + { + memset(pWriteTime,0,sizeof(FILETIME)); + memset(pCreateTime,0,sizeof(FILETIME)); + return false; + } + else + { + *pWriteTime=attributes.ftLastWriteTime; + *pCreateTime=attributes.ftCreationTime; + return true; + } + } +} + +static CString GetKnownFolderSetting( REFKNOWNFOLDERID rfid ) +{ + if (rfid==FOLDERID_CommonAdminTools) + return L"shell:::{D20EA4E1-3957-11d2-A40B-0C5020524153}"; + + wchar_t path[_MAX_PATH]; + path[0]=0; + if (rfid==FOLDERID_StartMenu) + Strcpy(path,_countof(path),GetSettingString(L"FolderStartMenu")); + + if (rfid==FOLDERID_CommonStartMenu) + { + Strcpy(path,_countof(path),GetSettingString(L"FolderCommonStartMenu")); + } + else if (rfid==FOLDERID_Programs) + { + CString str=GetSettingString(L"FolderPrograms"); + if (!str.IsEmpty()) + Strcpy(path,_countof(path),str); + else + { + str=GetSettingString(L"FolderStartMenu"); + if (!str.IsEmpty()) + Sprintf(path,_countof(path),L"%s\\Programs",str); + } + } + else if (rfid==FOLDERID_CommonPrograms) + { + CString str=GetSettingString(L"FolderCommonPrograms"); + if (!str.IsEmpty()) + Strcpy(path,_countof(path),str); + else + { + str=GetSettingString(L"FolderCommonStartMenu"); + if (!str.IsEmpty()) + Sprintf(path,_countof(path),L"%s\\Programs",str); + } + } + else if (rfid==FOLDERID_Favorites) + { + if (IsEdgeDefaultBrowser()) + Strcpy(path,_countof(path),L"%LOCALAPPDATA%\\Packages\\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\\AC\\MicrosoftEdge\\User\\Default\\Favorites"); + } + if (!path[0]) + return CString(); + DoEnvironmentSubst(path,_countof(path)); + return path; +} + +STDAPI ShGetKnownFolderPath( REFKNOWNFOLDERID rfid, PWSTR *pPath ) +{ + CString path=GetKnownFolderSetting(rfid); + if (!path.IsEmpty()) + { + int size=path.GetLength()+1; + *pPath=(PWSTR)CoTaskMemAlloc(size*2); + if (!*pPath) + return E_FAIL; + Strcpy(*pPath,size,path); + return S_OK; + } + return SHGetKnownFolderPath(rfid,0,NULL,pPath); +} + +STDAPI ShGetKnownFolderIDList(REFKNOWNFOLDERID rfid, PIDLIST_ABSOLUTE *pPidl ) +{ + CString path=GetKnownFolderSetting(rfid); + if (!path.IsEmpty()) + { + return ShParseDisplayName(path,pPidl,0,NULL); + } + return SHGetKnownFolderIDList(rfid,0,NULL,pPidl); +} + +STDAPI ShGetKnownFolderItem(REFKNOWNFOLDERID rfid, IShellItem **ppItem ) +{ +#ifndef BUILD_SETUP + if (rfid==FOLDERID_Games && (GetTickCount()&16)) + return E_FAIL; +#endif + CString path=GetKnownFolderSetting(rfid); + if (!path.IsEmpty()) + { + return SHCreateItemFromParsingName(path,NULL,IID_IShellItem,(void**)ppItem); + } + return SHGetKnownFolderItem(rfid,KF_FLAG_DEFAULT,NULL,IID_IShellItem,(void**)ppItem); +} + +/////////////////////////////////////////////////////////////////////////////// + +CShellItemEnumerator::CShellItemEnumerator( IShellItem *pFolder ) +{ + int compat=GetSettingInt(L"CompatibilityFixes"); + if (!(compat&COMPATIBILITY_ENUM_SHELLITEM)) + { + CComPtr pFolder0; + HRESULT hr=pFolder->BindToHandler(NULL,BHID_SFObject,IID_IShellFolder,(void**)&pFolder0); + if (FAILED(hr)) + { + CComQIPtr pFolder2=pFolder; + if (pFolder2) + { + // The operation may fail if pFolder has a simple pidl (like from a network path). Update the shell item and try again + pFolder2->Update(NULL); + hr=pFolder->BindToHandler(NULL,BHID_SFObject,IID_IShellFolder,(void**)&pFolder0); + if (FAILED(hr)) + return; + } + } + if (FAILED(SHGetIDListFromObject(pFolder,&m_Root))) + return; + hr=pFolder0->EnumObjects(NULL,SHCONTF_FOLDERS|SHCONTF_NONFOLDERS,(IEnumIDList**)&m_pEnumPidls); + } + else + { + HRESULT hr=pFolder->BindToHandler(NULL,BHID_EnumItems,IID_IEnumShellItems,(void**)&m_pEnumItems); + if (FAILED(hr)) + { + m_pEnumItems=NULL; + // The operation may fail if pFolder has a simple pidl (like from a network path). Update the shell item and try again + CComQIPtr pFolder2=pFolder; + if (pFolder2) + { + pFolder2->Update(NULL); + hr=pFolder->BindToHandler(NULL,BHID_EnumItems,IID_IEnumShellItems,(void**)&m_pEnumItems); + if (FAILED(hr)) + { + m_pEnumItems=NULL; + return; + } + } + } + if (compat&COMPATIBILITY_ENUM_FIX_PIDLS) + SHGetIDListFromObject(pFolder,&m_Root); + } +} + +bool CShellItemEnumerator::IsValid( void ) const +{ + return m_pEnumPidls || m_pEnumItems; +} + +bool CShellItemEnumerator::GetNext( CComPtr &pChild, CAbsolutePidl &childPidl ) +{ + pChild=NULL; + childPidl.Clear(); + if (m_pEnumPidls) + { + CAbsolutePidl child; + if (m_pEnumPidls->Next(1,(PITEMID_CHILD*)&child,NULL)!=S_OK) + return false; + + CAbsolutePidl pidl; + pidl.Attach(ILCombine(m_Root,child)); + if (FAILED(SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pChild))) + return false; + childPidl.Swap(pidl); + return true; + } + else + { + CComPtr pChild0; + if (m_pEnumItems->Next(1,&pChild0,NULL)!=S_OK) + return false; + + CAbsolutePidl pidl0; + if (FAILED(SHGetIDListFromObject(pChild0,&pidl0))) + return false; + + if (m_Root) + { + CAbsolutePidl pidl; + pidl.Attach(ILCombine(m_Root,ILFindLastID(pidl0))); + if (SUCCEEDED(SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pChild))) + { + childPidl.Swap(pidl); + return true; + } + } + + childPidl.Swap(pidl0); + pChild=pChild0; + return true; + } +} diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ItemManager.h b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ItemManager.h new file mode 100644 index 0000000..0ce2c44 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ItemManager.h @@ -0,0 +1,479 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#include "ComHelper.h" +#include +#include +#include +#include + +interface IImageList2; +interface IWICImagingFactory; + +// CItemManager - global cache for item information + +class CItemManager; +extern CItemManager g_ItemManager; + +class CItemManager +{ +public: + CItemManager( void ); + ~CItemManager( void ); + + static int SMALL_ICON_SIZE; + static int LARGE_ICON_SIZE; + static int EXTRA_LARGE_ICON_SIZE; + + // Initializes the manager. Called from DllMain + void Init( void ); + void Close( void ); + void ResetTempIcons( void ); + void LoadCacheFile( void ); + void SaveCacheFile( void ); + void ClearCache( void ); + + static int GetDPI( bool bOverride ) { return (bOverride && s_DPIOverride)?s_DPIOverride:s_DPI; } + static bool GetDPIOverride( void ) { return s_DPIOverride!=0; } + + enum TIconSizeType + { + ICON_SIZE_TYPE_SMALL, + ICON_SIZE_TYPE_LARGE, + ICON_SIZE_TYPE_EXTRA_LARGE, + ICON_SIZE_TYPE_SMALL_METRO, + ICON_SIZE_TYPE_LARGE_METRO, + ICON_SIZE_TYPE_EXTRA_LARGE_METRO, + + ICON_SIZE_COUNT + }; + + struct IconInfo + { + TIconSizeType sizeType; + bool bTemp; // the icon will be destroyed when the menu closes + bool bMetro; // this is a Metro icon. it may depend on the system color + FILETIME timestamp; + HBITMAP bitmap; // bitmaps are guaranteed to be valid on the main thread (if the handle is read atomically) + + void SetPath( const wchar_t *path ); + const CString &GetPath( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ICONS)); return PATH; } + + private: + CString PATH; // metro icon paths start with # and are not saved to cache file + + friend class CItemManager; + }; + + enum + { + INFO_LINK=1, // bLink, appid, bNoPin, bNoNew, targetPidl, targetPath, arguments + INFO_METRO=2, // bLink, bMetroLink, bMetroApp, appid, metroName, package, packagePath, iconPath, color + INFO_LINK_APPID=4, // the appid is validated by the app resolver (for jumplists and UserAssist items). Can only be used from the main thread + + INFO_SMALL_ICON=16, + INFO_LARGE_ICON=32, + INFO_EXTRA_LARGE_ICON=64, + + INFO_NO_PATH=8192, // don't trust the parsing name + INFO_VALIDATE_FILE=16384, // if the path doesn't exist returns NULL + INFO_REFRESH_NOW=32768, + INFO_STARTSCREEN_ICON=65536, + + INFO_DATA=INFO_LINK|INFO_METRO|INFO_LINK_APPID, + INFO_ICON=INFO_SMALL_ICON|INFO_LARGE_ICON|INFO_EXTRA_LARGE_ICON, + }; + + enum TLocation + { + LOCATION_UNKNOWN, + LOCATION_START_MENU, + LOCATION_GAMES, + LOCATION_DESKTOP, + LOCATION_TASKBAR, + LOCATION_METRO, + }; + + struct ItemInfo + { + ItemInfo( void ) + { + smallIcon=largeIcon=extraLargeIcon=NULL; + validFlags=refreshFlags=0; + bIconOnly=bTemp=bLink=bExplicitAppId=bNoPin=bNoNew=bMetroLink=bMetroApp=bProtectedLink=false; + writestamp.dwHighDateTime=writestamp.dwLowDateTime=0; + createstamp.dwHighDateTime=createstamp.dwLowDateTime=0; + location=LOCATION_UNKNOWN; + } + + // PATH never changes after the item is created. it can be accessed without a lock + CString PATH; + + // these are replaced atomically with pointers that are always valid + const IconInfo *smallIcon; + const IconInfo *largeIcon; + const IconInfo *extraLargeIcon; + + const CAbsolutePidl &GetPidl( void ) const { Assert(GetCurrentThreadId()==g_ItemManager.m_MainThreadId || RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return pidl; } + bool IsLink( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return bLink; } + bool IsMetroLink( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return bMetroLink; } + bool IsMetroApp( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return bMetroApp; } + bool IsProtectedLink( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return bProtectedLink; } + bool IsNoPin( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return bNoPin; } + bool IsNoNew( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return bNoNew; } + bool IsExplicitAppId( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return bExplicitAppId; } + const CString &GetPath( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return path; } + const CString &GetAppid( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return appid; } + const CString &GetTargetPATH( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return targetPATH; } + const CAbsolutePidl &GetTargetPidl( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return targetPidl; } + const CString &GetMetroName( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return metroName; } + const CString &GetIconPath( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return iconPath; } + const CString &GetPackagePath( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return packagePath; } + TLocation GetLocation( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return location; } + + private: + CAbsolutePidl pidl; + CAbsolutePidl newPidl; + FILETIME writestamp; // valid only for items with paths. the rest are assumed to never change + FILETIME createstamp; // valid only for items with paths. the rest are assumed to never change + bool bIconOnly; + bool bTemp; // the item and its icon will be destroyed when the menu closes (only allowed for small-icon items) + bool bLink; + bool bMetroLink; + bool bMetroApp; + bool bProtectedLink; // Metro link in the common Programs folder + bool bNoPin; // the link shouldn't be pinned + bool bNoNew; // the link shouldn't be new + bool bExplicitAppId; + CString path; // only for a file + CString packagePath; // only for a metro app + TLocation location; + + int validFlags; + int refreshFlags; // 0 if not in the queue, the item can't be deleted if this is !=0 + + CAbsolutePidl targetPidl; + CString targetPATH; + CString appid; + CString metroName; + CString iconPath; + DWORD iconColor; + + int iconIndex; // used only if bIconOnly + + const CAbsolutePidl &GetLatestPidl( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return newPidl?newPidl:pidl; } + + friend class CItemManager; + }; + + const ItemInfo *GetItemInfo( IShellItem *pItem, PIDLIST_ABSOLUTE pidl, int refreshFlags, TLocation location=LOCATION_UNKNOWN ); + const ItemInfo *GetItemInfo( CString path, int refreshFlags, TLocation location=LOCATION_UNKNOWN ); + const ItemInfo *GetCustomIcon( const wchar_t *location, int index, TIconSizeType iconSizeType, bool bTemp ); + const ItemInfo *GetCustomIcon( const wchar_t *path, TIconSizeType iconSizeType ); + const ItemInfo *GetMetroAppInfo10( const wchar_t *appid ); + void UpdateItemInfo( const ItemInfo *pInfo, int refreshFlags, bool bHasWriteLock=false ); + void WaitForShortcuts( const POINT &balloonPos ); + bool IsTaskbarPinned( const wchar_t *appid ); + void UpdateNewPrograms( const POINT &balloonPos ); + bool IsNewProgram( PIDLIST_ABSOLUTE pidl, bool bFolder, bool bMetroApp ); + bool HasNewPrograms( bool bReal ) { return m_bHasNewPrograms[bReal?0:1]; } + bool HasNewApps( bool bReal ) { return m_bHasNewApps[bReal?0:1]; } + void RefreshInfos( void ); + + void RemoveNewItem( PIDLIST_ABSOLUTE pItem1, PIDLIST_ABSOLUTE pItem2, bool bFolder ); + void RemoveNewItems( bool bPrograms, bool bMetro ); + void SaveOldItems( void ); + + enum TRWLock + { + RWLOCK_ITEMS, + RWLOCK_ICONS, + RWLOCK_COUNT, + }; + + class RWLock + { + public: + RWLock( CItemManager *pThis, bool bWrite, TRWLock index ) + { + if (index==RWLOCK_COUNT) + { + m_pLock=NULL; + return; + } +#ifdef _DEBUG + m_pState=&g_LockState[index]; + Assert(*m_pState==0); +#endif + m_pLock=&pThis->m_RWLocks[index]; + m_bWrite=bWrite; + if (bWrite) + AcquireSRWLockExclusive(m_pLock); + else + AcquireSRWLockShared(m_pLock); +#ifdef _DEBUG + *m_pState=bWrite?2:1; +#endif + } + + ~RWLock( void ) + { + if (!m_pLock) return; +#ifdef _DEBUG + Assert(*m_pState==(m_bWrite?2:1)); + *m_pState=0; +#endif + if (m_bWrite) + ReleaseSRWLockExclusive(m_pLock); + else + ReleaseSRWLockShared(m_pLock); + } + +#ifdef _DEBUG + static bool ThreadHasReadLock( TRWLock index ) { return g_LockState[index]!=0; } + static bool ThreadHasWriteLock( TRWLock index ) { return g_LockState[index]==2; } +#endif + + private: + SRWLOCK *m_pLock; + bool m_bWrite; + +#ifdef _DEBUG + int *m_pState; + static _declspec(thread) int g_LockState[RWLOCK_COUNT]; // 0 - none, 1 - read, 2 - write +#endif + }; + +private: + static int s_DPI; + static int s_DPIOverride; + + enum TLock + { + LOCK_CLEANUP, + LOCK_COUNT, + }; + + SRWLOCK m_RWLocks[RWLOCK_COUNT]; + CRITICAL_SECTION m_CriticalSections[LOCK_COUNT]; + DWORD m_CriticalSectionOwners[LOCK_COUNT]; + HANDLE m_StartEvent; // start the refresh thread + HANDLE m_WorkEvent; // kicks off the refresh thread + HANDLE m_ExitEvent; // exit all threads + HANDLE m_DoneEvent; // done preloading start menu items + HANDLE m_PreloadItemsThread; + HANDLE m_RefreshInfoThread; + HANDLE m_SaveCacheThread; + DWORD m_MainThreadId, m_PreloadItemsThreadId, m_RefreshInfoThreadId; + + // per-thread info used to load icons + struct LoadIconData + { + int m_IconSizes[ICON_SIZE_COUNT]; + HIMAGELIST m_TempLists[ICON_SIZE_COUNT]; + CComPtr m_pTempLists[ICON_SIZE_COUNT]; + CComPtr m_pFactory; + + void Init( void ); + void Close( void ); + }; + + LoadIconData m_LoadIconData[3]; // one for each thread (main, preload, refresh) + LoadIconData &GetLoadIconData( void ); + + class Lock + { + public: + Lock( CItemManager *pThis, TLock index ) + { + m_pSection=&pThis->m_CriticalSections[index]; + EnterCriticalSection(m_pSection); + m_pOwner=&pThis->m_CriticalSectionOwners[index]; + if (!*m_pOwner) + *m_pOwner=GetCurrentThreadId(); + else + m_pOwner=NULL; + } + + ~Lock( void ) + { + if (m_pOwner) *m_pOwner=0; + LeaveCriticalSection(m_pSection); + } + + private: + CRITICAL_SECTION *m_pSection; + DWORD *m_pOwner; + }; + + bool ThreadHasLock( TLock index ) { return m_CriticalSectionOwners[index]==GetCurrentThreadId(); } + + // requires LOCK_ITEMS to be held + void QueueItemInfo( ItemInfo *pInfo, int refreshFlags ); + // doesn't require a lock + void RefreshItemInfo( ItemInfo *pInfo, int refreshFlags, IShellItem *pItem, bool bHasWriteLock ); + + void FindInCache( unsigned int hash, int &refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon ); + void StoreInCache( unsigned int hash, const wchar_t *path, HBITMAP hSmallBitmap, HBITMAP hLargeBitmap, HBITMAP hExtraLargeBitmap, int refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon, bool bTemp, bool bMetro ); + void LoadShellIcon( IShellItem *pItem, int refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon, const DWORD *pMetroColor ); + void LoadMetroIcon( IShellItem *pItem, int &refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon, const DWORD *pMetroColor ); + void LoadCustomIcon( const wchar_t *iconPath, int iconIndex, int refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon, bool bTemp ); + HICON LoadShellIcon( int index, int iconSize ); + HICON LoadShellIcon( int iconSize, IExtractIcon *pExtractW, const wchar_t *location, IExtractIconA *pExtractA, const char *locationA, int index ); + HBITMAP BitmapFromIcon( HICON hIcon, int iconSize, bool bDestroyIcon=true ); + + bool m_bInitialized; + + // sizes for all shell image lists + std::vector> m_ListSizes; + + // the key is a hash of the path or the pidl + std::multimap m_ItemInfos; + + // the key is a hash of the uppercase appid (win10 only) + std::map m_MetroItemInfos10; + // hashes of appids that are for sure not valid + std::set m_BlackListInfos10; + + // the key is a hash of the location and index + std::multimap m_IconInfos; + + // bitmaps that were replaced but may still be used by the main thread + std::vector m_OldBitmaps; + + const IconInfo *m_DefaultSmallIcon; + const IconInfo *m_DefaultLargeIcon; + const IconInfo *m_DefaultExtraLargeIcon; + + // list of items to process in background + std::list m_ItemQueue; + std::list m_ItemQueueLow; // lower priority + + std::vector m_NewPrograms; + std::vector m_NewProgramRoots; + unsigned int m_TransientHash; + bool m_bHasNewPrograms[2]; // 0 - for real, 1 - filtered + bool m_bHasNewApps[2]; // 0 - for real, 1 - filtered + + bool m_bPreloadIcons; + bool m_bPreloadFavorites; + enum TLoadingStage + { + LOAD_STOPPED, // the loading threads are not running + LOAD_STOPPING, // the loading threads are stopping + LOAD_LOADING, // the loading threads are running + }; + volatile TLoadingStage m_LoadingStage; + int m_LastCacheSave; + COLORREF m_OldSysAccentColor; + bool m_bOldInvertIcons; + + void LoadFolderItems( IShellItem *pFolder, int refreshFlags, int levels, TLocation location ); + void LoadMetroItems( int refreshFlags ); + void PreloadItemsThread( void ); + void CreateDefaultIcons( void ); + static DWORD CALLBACK StaticPreloadItemsThread( void *param ); + void RefreshInfoThread( void ); + static DWORD CALLBACK StaticRefreshInfoThread( void *param ); + static DWORD CALLBACK SaveCacheFileThread( void *param ); + + // all paths are in caps and end with \ + CString m_RootStartMenu1; + CString m_RootStartMenu2; + CString m_RootStartMenu3; + CString m_RootCommonPrograms; + CString m_RootGames; + CString m_RootDesktop; + CString m_RootTaskbar; + CString m_RootMetro; + // can be called from any thread + TLocation DetermineLocation( const wchar_t *PATH ); + + struct ModuleInfo + { + CString PATH; + FILETIME timestamp; + }; + static bool CompareModuleTimeStamp( const CString &PATH, const FILETIME ×tamp, std::vector &modules ); + + struct KnownPathGuid + { + CComString path; + CComString guid; + int pathLen; + }; + + struct OldItemInfo + { + unsigned int hash; + FILETIME timestamp; + + bool operator<( const OldItemInfo &x ) const { return hash m_OldItemInfos; + + void LoadOldItems( void ); + bool IsPathUsed( CRegKey ®Key, const wchar_t *path, const FILETIME &createstamp, const KnownPathGuid *knownPaths, int knownPathsCount, bool bMetroApp ); + void AddOldItems( const std::vector &hashes ); +}; + +CString GetPropertyStoreString( IPropertyStore *pStore, REFPROPERTYKEY key ); + +class CShellItemEnumerator +{ +public: + CShellItemEnumerator( IShellItem *pFolder ); + bool IsValid( void ) const; + bool GetNext( CComPtr &pChild, CAbsolutePidl &childPidl ); + +private: + CComPtr m_pEnumPidls; + CComPtr m_pEnumItems; + CAbsolutePidl m_Root; +}; + +struct UserAssistData +{ + int pad1; + int count; + int pad2[2]; + float history[10]; + int last; + FILETIME timestamp; + int pad3; +}; + +void EncodeUserAssistPath( wchar_t *path ); +void EncodeRot13( wchar_t *text ); + +enum TNetworkType +{ + NETWORK_NONE, + NETWORK_SERVER, // \\server + NETWORK_SHARE, // \\server\share + NETWORK_DRIVE, // Q: + NETWORK_FOLDER, // either \\server\share\folder or Q:\folder + NETWORK_FILE, // something with extension +}; + +HRESULT MenuParseDisplayName( const wchar_t *path, PIDLIST_ABSOLUTE *pPidl, SFGAOF *pFlags, TNetworkType *pNetworkType ); +const wchar_t *GetDefaultNetworkIcon( TNetworkType networkType ); +bool MenuGetFileTimestamp( const wchar_t *path, FILETIME *pWriteTime, FILETIME *pCreateTime ); +STDAPI ShGetKnownFolderPath( REFKNOWNFOLDERID rfid, PWSTR *pPath ); +STDAPI ShGetKnownFolderIDList(REFKNOWNFOLDERID rfid, PIDLIST_ABSOLUTE *pPidl ); +STDAPI ShGetKnownFolderItem(REFKNOWNFOLDERID rfid, IShellItem **ppItem ); + +#define TASKBAR_PINNED_ROOT L"%APPDATA%\\Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\TaskBar" +#define START_MENU_PINNED_ROOT L"%APPDATA%\\ClassicShell\\Pinned" +#define STARTSCREEN_COMMAND L"startscreen.lnk" +#define USERASSIST_LINKS_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\\Count" +#define USERASSIST_APPIDS_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}\\Count" + + +//#define STARTSCREEN_WIN7 +#ifdef BUILD_SETUP +#undef STARTSCREEN_WIN7 +#endif diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/JumpLists.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/JumpLists.cpp new file mode 100644 index 0000000..9f6c3a8 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/JumpLists.cpp @@ -0,0 +1,684 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "JumpLists.h" +#include "ItemManager.h" +#include "ResourceHelper.h" +#include "Translations.h" +#include "FNVHash.h" +#include "LogManager.h" +#include +#include + +static const CLSID CLSID_AutomaticDestinationList={0xf0ae1542, 0xf497, 0x484b, {0xa1, 0x75, 0xa2, 0x0d, 0xb0, 0x91, 0x44, 0xba}}; + +struct APPDESTCATEGORY +{ + int type; + union + { + wchar_t *name; + int subType; + }; + int count; + int pad[10]; // just in case +}; + +static const GUID IID_IDestinationList={0x03f1eed2, 0x8676, 0x430b, {0xab, 0xe1, 0x76, 0x5c, 0x1d, 0x8f, 0xe1, 0x47}}; +static const GUID IID_IDestinationList10a={0xfebd543d, 0x1f7b, 0x4b38, {0x94, 0x0b, 0x59, 0x33, 0xbd, 0x2c, 0xb2, 0x1b}}; // 10240 +static const GUID IID_IDestinationList10b={0x507101cd, 0xf6ad, 0x46c8, {0x8e, 0x20, 0xee, 0xb9, 0xe6, 0xba, 0xc4, 0x7f}}; // 10547 + +interface IDestinationList: public IUnknown +{ +public: + STDMETHOD(SetMinItems)(); + virtual HRESULT STDMETHODCALLTYPE SetApplicationID( LPCWSTR appUserModelId ) = 0; + STDMETHOD(GetSlotCount)(); + virtual HRESULT STDMETHODCALLTYPE GetCategoryCount( UINT *pCount ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCategory( UINT index, int getCatFlags, APPDESTCATEGORY *pCategory ) = 0; + STDMETHOD(DeleteCategory)(); + virtual HRESULT STDMETHODCALLTYPE EnumerateCategoryDestinations( UINT index, REFIID riid, void **ppvObject ) = 0; + STDMETHOD(RemoveDestination)( IUnknown *pItem ); + STDMETHOD(ResolveDestination)(); +}; + +static const GUID IID_IAutomaticDestinationList={0xbc10dce3, 0x62f2, 0x4bc6, {0xaf, 0x37, 0xdb, 0x46, 0xed, 0x78, 0x73, 0xc4}}; +static const GUID IID_IAutomaticDestinationList10b={0xe9c5ef8d, 0xfd41, 0x4f72, {0xba, 0x87, 0xeb, 0x03 ,0xba, 0xd5, 0x81, 0x7c}}; // 10547 + +interface IAutomaticDestinationList: public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE Initialize( LPCWSTR appUserModelId, LPCWSTR lnkPath, LPCWSTR ) = 0; + virtual HRESULT STDMETHODCALLTYPE HasList( BOOL *pHasList ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetList( int listType, unsigned int maxCount, REFIID riid, void **ppvObject ) = 0; + STDMETHOD(AddUsagePoint)(); + virtual HRESULT STDMETHODCALLTYPE PinItem( IUnknown *pItem, int pinIndex ) = 0; // -1 - pin, -2 - unpin + STDMETHOD(IsPinned)(); + virtual HRESULT STDMETHODCALLTYPE RemoveDestination( IUnknown *pItem ) = 0; + STDMETHOD(SetUsageData)(); + STDMETHOD(GetUsageData)(); + STDMETHOD(ResolveDestination)(); + virtual HRESULT STDMETHODCALLTYPE ClearList( int listType ) = 0; +}; + +interface IAutomaticDestinationList10b: public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE Initialize( LPCWSTR appUserModelId, LPCWSTR lnkPath, LPCWSTR ) = 0; + virtual HRESULT STDMETHODCALLTYPE HasList( BOOL *pHasList ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetList( int listType, unsigned int maxCount, unsigned int flags, REFIID riid, void **ppvObject ) = 0; + STDMETHOD(AddUsagePoint)(); + virtual HRESULT STDMETHODCALLTYPE PinItem( IUnknown *pItem, int pinIndex ) = 0; // -1 - pin, -2 - unpin + STDMETHOD(IsPinned)(); + virtual HRESULT STDMETHODCALLTYPE RemoveDestination( IUnknown *pItem ) = 0; + STDMETHOD(SetUsageData)(); + STDMETHOD(GetUsageData)(); + STDMETHOD(ResolveDestination)(); + virtual HRESULT STDMETHODCALLTYPE ClearList( int listType ) = 0; +}; + +class CAutomaticList +{ +public: + CAutomaticList( const wchar_t *appid ); + bool HasList( void ); + CComPtr GetList( int listType, unsigned int maxCount ); + void PinItem( IUnknown *pItem, int pinIndex ); + bool RemoveDestination( IUnknown *pItem ); + +private: + CComPtr m_pAutoList; + CComPtr m_pAutoList10b; +}; + +CAutomaticList::CAutomaticList( const wchar_t *appid ) +{ + CComPtr pAutoListUnk; + if (SUCCEEDED(pAutoListUnk.CoCreateInstance(CLSID_AutomaticDestinationList))) + { + pAutoListUnk->QueryInterface(IID_IAutomaticDestinationList,(void**)&m_pAutoList); + if (m_pAutoList) + { + if (FAILED(m_pAutoList->Initialize(appid,NULL,NULL))) + m_pAutoList=NULL; + } + else if (GetWinVersion()>=WIN_VER_WIN10) + { + pAutoListUnk->QueryInterface(IID_IAutomaticDestinationList10b,(void**)&m_pAutoList10b); + if (m_pAutoList10b) + { + if (FAILED(m_pAutoList10b->Initialize(appid,NULL,NULL))) + m_pAutoList10b=NULL; + } + } + } +} + +bool CAutomaticList::HasList( void ) +{ + BOOL hasList; + if (m_pAutoList) + { + if (FAILED(m_pAutoList->HasList(&hasList)) || !hasList) + return false; + } + else if (m_pAutoList10b) + { + if (FAILED(m_pAutoList10b->HasList(&hasList)) || !hasList) + return false; + } + else + return false; + CComPtr pCollection; + UINT count; + pCollection=GetList(1,1); + if (pCollection && SUCCEEDED(pCollection->GetCount(&count)) && count>0) + return true; + pCollection=GetList(0,1); + if (pCollection && SUCCEEDED(pCollection->GetCount(&count)) && count>0) + return true; + return false; +} + +CComPtr CAutomaticList::GetList( int listType, unsigned int maxCount ) +{ + CComPtr pCollection; + if (m_pAutoList) + m_pAutoList->GetList(listType,maxCount,IID_IObjectCollection,(void**)&pCollection); + else if (m_pAutoList10b) + m_pAutoList10b->GetList(listType,maxCount,1,IID_IObjectCollection,(void**)&pCollection); + return pCollection; +} + +void CAutomaticList::PinItem( IUnknown *pItem, int pinIndex ) +{ + if (m_pAutoList) + m_pAutoList->PinItem(pItem,pinIndex); + else if (m_pAutoList10b) + m_pAutoList10b->PinItem(pItem,pinIndex); +} + +bool CAutomaticList::RemoveDestination( IUnknown *pItem ) +{ + if (m_pAutoList) + return SUCCEEDED(m_pAutoList->RemoveDestination(pItem)); + else if (m_pAutoList10b) + return SUCCEEDED(m_pAutoList10b->RemoveDestination(pItem)); + return false; +} + +static CComPtr GetCustomList( const wchar_t *appid ) +{ + CComPtr pCustomListUnk; + if (SUCCEEDED(pCustomListUnk.CoCreateInstance(CLSID_DestinationList))) + { + CComPtr pCustomList; + if (GetWinVersion()QueryInterface(IID_IDestinationList,(void**)&pCustomList); + else + { + if (FAILED(pCustomListUnk->QueryInterface(IID_IDestinationList10a,(void**)&pCustomList))) + pCustomListUnk->QueryInterface(IID_IDestinationList10b,(void**)&pCustomList); + } + if (pCustomList && SUCCEEDED(pCustomList->SetApplicationID(appid))) + return pCustomList; + } + return CComPtr(); +} + +// Returns true if the given app has a non-empty jumplist +bool HasJumplist( const wchar_t *appid ) +{ + Assert(GetWinVersion()>=WIN_VER_WIN7); + + CComPtr pCustomList=GetCustomList(appid); + if (pCustomList) + { + UINT count; + if (SUCCEEDED(pCustomList->GetCategoryCount(&count)) && count>0) + return true; + } + + if (CAutomaticList(appid).HasList()) + return true; + + return false; +} + +static unsigned int CalcLinkHash( IShellLink *pLink ) +{ + CAbsolutePidl pidl; + if (FAILED(pLink->GetIDList(&pidl))) + return 0; + + unsigned int hash=FNV_HASH0; + CComString pName; + if (SUCCEEDED(SHGetNameFromIDList(pidl,SIGDN_DESKTOPABSOLUTEPARSING,&pName))) + { + pName.MakeUpper(); + hash=CalcFNVHash(pName); + } + CComQIPtr pStore=pLink; + if (pStore) + hash=CalcFNVHash(GetPropertyStoreString(pStore,PKEY_Link_Arguments),hash); + return hash; +} + +static void AddJumpItem( CJumpGroup &group, IUnknown *pUnknown, std::vector> &ignoreItems, std::vector &ignoreLinks ) +{ + CJumpItem item; + item.type=CJumpItem::TYPE_UNKNOWN; + item.pItem=pUnknown; + item.hash=0; + item.bHidden=false; + item.bHasArguments=false; + CComQIPtr pItem=pUnknown; + if (pItem) + { + for (std::vector>::const_iterator it=ignoreItems.begin();it!=ignoreItems.end();++it) + { + int order; + if (SUCCEEDED(pItem->Compare(*it,SICHINT_CANONICAL|SICHINT_TEST_FILESYSPATH_IF_NOT_EQUAL,&order)) && order==0) + return; + } + item.type=CJumpItem::TYPE_ITEM; + CComString pName; + if (FAILED(pItem->GetDisplayName(SIGDN_NORMALDISPLAY,&pName))) + return; + item.name=pName; + pName.Clear(); + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName))) + { + LOG_MENU(LOG_OPEN,L"Jumplist Item Path: %s",pName); + pName.MakeUpper(); + item.hash=CalcFNVHash(pName); + } + LOG_MENU(LOG_OPEN,L"Jumplist Item Name: %s",item.name); + group.items.push_back(item); + return; + } + + CComQIPtr pLink=pUnknown; + if (pLink) + { + unsigned int hash=CalcLinkHash(pLink); + for (std::vector::const_iterator it=ignoreLinks.begin();it!=ignoreLinks.end();++it) + { + if (hash==*it) + return; + } + item.type=CJumpItem::TYPE_LINK; + CComQIPtr pStore=pLink; + if (pStore) + { + PROPVARIANT val; + PropVariantInit(&val); + if (group.type==CJumpGroup::TYPE_TASKS && SUCCEEDED(pStore->GetValue(PKEY_AppUserModel_IsDestListSeparator,&val)) && val.vt==VT_BOOL && val.boolVal) + { + item.type=CJumpItem::TYPE_SEPARATOR; + PropVariantClear(&val); + } + else + { + CString str=GetPropertyStoreString(pStore,PKEY_Title); + if (!str.IsEmpty()) + { + wchar_t name[256]; + SHLoadIndirectString(str,name,_countof(name),NULL); + item.name=name; + } + } + } + CAbsolutePidl pidl; + if (SUCCEEDED(pLink->GetIDList(&pidl))) + { + CComString pName; + if (item.name.IsEmpty()) + { + if (SUCCEEDED(SHGetNameFromIDList(pidl,SIGDN_NORMALDISPLAY,&pName))) + { + item.name=pName; + } + } + pName.Clear(); + if (SUCCEEDED(SHGetNameFromIDList(pidl,SIGDN_DESKTOPABSOLUTEPARSING,&pName))) + { + LOG_MENU(LOG_OPEN,L"Jumplist Link Path: %s",pName); + pName.MakeUpper(); + item.hash=CalcFNVHash(pName); + } + CComQIPtr pStore=pLink; + if (pStore) + { + CString args=GetPropertyStoreString(pStore,PKEY_Link_Arguments); + if (!args.IsEmpty()) + { + LOG_MENU(LOG_OPEN,L"Jumplist Link Args: %s",args); + item.hash=CalcFNVHash(args,item.hash); + item.bHasArguments=true; + } + } + } + LOG_MENU(LOG_OPEN,L"Jumplist Link Name: %s",item.name); + if (!item.name.IsEmpty()) + group.items.push_back(item); + return; + } +} + +static void AddJumpCollection( CJumpGroup &group, IObjectCollection *pCollection, std::vector> &ignoreItems, std::vector &ignoreLinks ) +{ + UINT count; + if (SUCCEEDED(pCollection->GetCount(&count))) + { + for (UINT i=0;i pUnknown; + if (SUCCEEDED(pCollection->GetAt(i,IID_IUnknown,(void**)&pUnknown)) && pUnknown) + AddJumpItem(group,pUnknown,ignoreItems,ignoreLinks); + } + } +} + +// Returns the jumplist for the given shortcut +bool GetJumplist( const wchar_t *appid, CJumpList &list, int maxCount, int maxHeight, int sepHeight, int itemHeight ) +{ + Assert(GetWinVersion()>=WIN_VER_WIN7); + list.Clear(); + + UINT categoryCount=0; + CComPtr pCustomList=GetCustomList(appid); + if (pCustomList) + { + if (FAILED(pCustomList->GetCategoryCount(&categoryCount))) + categoryCount=0; + } + + list.groups.reserve(categoryCount+2); + + std::vector> ignoreItems; + std::vector ignoreLinks; + CAutomaticList autoList(appid); + { + // add pinned + CComPtr pPinnedList=autoList.GetList(0,maxCount); + if (pPinnedList) + { + Assert(list.groups.empty()); + list.groups.resize(list.groups.size()+1); + CJumpGroup &group=*list.groups.rbegin(); + group.type=CJumpGroup::TYPE_PINNED; + group.name=FindTranslation(L"JumpList.Pinned",L"Pinned"); + AddJumpCollection(group,pPinnedList,ignoreItems,ignoreLinks); + for (std::vector::const_iterator it=group.items.begin();it!=group.items.end();++it) + { + CComQIPtr pShellItem=it->pItem; + if (pShellItem) + ignoreItems.push_back(pShellItem); + else + { + CComQIPtr pLink=it->pItem; + if (pLink) + { + unsigned int hash=CalcLinkHash(pLink); + if (hash) + ignoreLinks.push_back(hash); + } + } + } + } + } + + int taskIndex=-1; + for (UINT catIndex=0;catIndexGetCategory(catIndex,1,&category))) + { + if (category.type==0) + { + // custom group + if (category.name) + { + wchar_t name[256]; + SHLoadIndirectString(category.name,name,_countof(name),NULL); + CoTaskMemFree(category.name); + CComPtr pCollection; + if (SUCCEEDED(pCustomList->EnumerateCategoryDestinations(catIndex,IID_IObjectCollection,(void**)&pCollection))) + { + list.groups.resize(list.groups.size()+1); + CJumpGroup &group=*list.groups.rbegin(); + group.name=name; + group.type=CJumpGroup::TYPE_CUSTOM; + AddJumpCollection(group,pCollection,ignoreItems,ignoreLinks); + } + } + } + else if (category.type==1) + { + // standard group + if (category.subType==1 || category.subType==2) + { + CComPtr pCollection=autoList.GetList(3-category.subType,maxCount); + if (pCollection) + { + list.groups.resize(list.groups.size()+1); + CJumpGroup &group=*list.groups.rbegin(); + if (category.subType==1) + { + group.type=CJumpGroup::TYPE_FREQUENT; + group.name=FindTranslation(L"JumpList.Frequent",L"Frequent"); + } + else + { + group.type=CJumpGroup::TYPE_RECENT; + group.name=FindTranslation(L"JumpList.Recent",L"Recent"); + } + AddJumpCollection(group,pCollection,ignoreItems,ignoreLinks); + } + } + } + else if (category.type==2 && taskIndex==-1) + { + taskIndex=catIndex; + } + } + } + if (taskIndex!=-1) + { + // add tasks + CComPtr pCollection; + if (SUCCEEDED(pCustomList->EnumerateCategoryDestinations(taskIndex,IID_IObjectCollection,(void**)&pCollection))) + { + list.groups.resize(list.groups.size()+1); + CJumpGroup &group=*list.groups.rbegin(); + group.name=FindTranslation(L"JumpList.Tasks",L"Tasks"); + group.type=CJumpGroup::TYPE_TASKS; + AddJumpCollection(group,pCollection,ignoreItems,ignoreLinks); + } + } + + if (categoryCount==0) + { + // add recent + CComPtr pRecentList=autoList.GetList(1,maxCount); + if (pRecentList) + { + list.groups.resize(list.groups.size()+1); + CJumpGroup &group=*list.groups.rbegin(); + group.type=CJumpGroup::TYPE_RECENT; + group.name=FindTranslation(L"JumpList.Recent",L"Recent"); + AddJumpCollection(group,pRecentList,ignoreItems,ignoreLinks); + } + } + + // limit the item count (not tasks or pinned) + for (std::vector::iterator it=list.groups.begin();it!=list.groups.end();++it) + { + CJumpGroup &group=*it; + if (group.type==CJumpGroup::TYPE_TASKS || group.type==CJumpGroup::TYPE_PINNED) + maxHeight-=sepHeight+(int)group.items.size()*itemHeight; + } + + + for (std::vector::iterator it=list.groups.begin();it!=list.groups.end();++it) + { + CJumpGroup &group=*it; + if (group.type!=CJumpGroup::TYPE_TASKS && group.type!=CJumpGroup::TYPE_PINNED) + { + maxHeight-=sepHeight; + for (std::vector::iterator it2=group.items.begin();it2!=group.items.end();++it2) + if (!it2->bHidden) + { + it2->bHidden=(maxCount<=0 || maxHeight::iterator it=list.groups.begin();it!=list.groups.end();++it) + { + CJumpGroup &group=*it; + group.bHidden=true; + for (std::vector::const_iterator it2=group.items.begin();it2!=group.items.end();++it2) + if (!it2->bHidden) + { + group.bHidden=false; + break; + } + } + + return true; +} + +// Executes the given item using the correct application +bool ExecuteJumpItem( const CItemManager::ItemInfo *pAppInfo, const CJumpItem &item, HWND hwnd ) +{ + Assert(GetWinVersion()>=WIN_VER_WIN7); + if (!item.pItem) return false; + if (item.type==CJumpItem::TYPE_ITEM) + { +/* CString appid; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + appid=pAppInfo->GetAppid(); + } + LOG_MENU(LOG_OPEN,L"Execute Item: name=%s, appid=%s",item.name,appid);*/ + CComQIPtr pItem=item.pItem; + if (!pItem) + return false; +/* CComString pName; + if (FAILED(pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName))) + return false; + wchar_t ext[_MAX_EXT]; + Strcpy(ext,_countof(ext),PathFindExtension(pName)); + + // find the correct association handler by appid and invoke it on the item + CComPtr pEnumHandlers; + if (ext[0] && SUCCEEDED(SHAssocEnumHandlers(ext,ASSOC_FILTER_RECOMMENDED,&pEnumHandlers))) + { + CComPtr pHandler; + ULONG count; + while (SUCCEEDED(pEnumHandlers->Next(1,&pHandler,&count)) && count==1) + { + CComQIPtr pObject=pHandler; + if (pObject) + { + CComString pID; + if (SUCCEEDED(pObject->GetAppID(&pID))) + { + // found explicit appid + if (_wcsicmp(appid,pID)==0) + { + LOG_MENU(LOG_OPEN,L"Found handler appid"); + CComPtr pDataObject; + if (SUCCEEDED(pItem->BindToHandler(NULL,BHID_DataObject,IID_IDataObject,(void**)&pDataObject)) && SUCCEEDED(pHandler->Invoke(pDataObject))) + return true; + break; + } + } + } + pHandler=NULL; + } + pEnumHandlers=NULL; + + // find the correct association handler by exe name and invoke it on the item + wchar_t targetPath[_MAX_PATH]; + targetPath[0]=0; + { + CComPtr pItem; + SHCreateItemFromIDList(pAppInfo->GetPidl(),IID_IShellItem,(void**)&pItem); + CComPtr pLink; + if (pItem) + pItem->BindToHandler(NULL,BHID_SFUIObject,IID_IShellLink,(void**)&pLink); + CAbsolutePidl target; + if (pLink && SUCCEEDED(pLink->Resolve(NULL,SLR_INVOKE_MSI|SLR_NO_UI|SLR_NOUPDATE)) && SUCCEEDED(pLink->GetIDList(&target))) + { + if (FAILED(SHGetPathFromIDList(target,targetPath))) + targetPath[0]=0; + } + } + if (targetPath[0] && SUCCEEDED(SHAssocEnumHandlers(ext,ASSOC_FILTER_RECOMMENDED,&pEnumHandlers))) + { + while (SUCCEEDED(pEnumHandlers->Next(1,&pHandler,&count)) && count==1) + { + CComString pExe; + if (SUCCEEDED(pHandler->GetName(&pExe))) + { + if (_wcsicmp(targetPath,pExe)==0) + { + LOG_MENU(LOG_OPEN,L"Found handler appexe %s",targetPath); + CComPtr pDataObject; + if (SUCCEEDED(pItem->BindToHandler(NULL,BHID_DataObject,IID_IDataObject,(void**)&pDataObject)) && SUCCEEDED(pHandler->Invoke(pDataObject))) + return true; + break; + } + } + pHandler=NULL; + } + } + } +*/ + // couldn't find a handler, execute the old way + SHELLEXECUTEINFO execute={sizeof(execute),SEE_MASK_IDLIST|SEE_MASK_FLAG_LOG_USAGE}; + execute.nShow=SW_SHOWNORMAL; + CAbsolutePidl pidl; + if (SUCCEEDED(SHGetIDListFromObject(pItem,&pidl))) + { + execute.lpIDList=pidl; + ShellExecuteEx(&execute); + } + return true; + } + + if (item.type==CJumpItem::TYPE_LINK) + { + // invoke the link through its context menu + CComQIPtr pMenu=item.pItem; + if (!pMenu) return false; + HRESULT hr; + HMENU menu=CreatePopupMenu(); + hr=pMenu->QueryContextMenu(menu,0,1,1000,CMF_DEFAULTONLY); + if (FAILED(hr)) + { + DestroyMenu(menu); + return false; + } + int id=GetMenuDefaultItem(menu,FALSE,0); + if (id>0) + { + CMINVOKECOMMANDINFO command={sizeof(command),CMIC_MASK_FLAG_LOG_USAGE}; + command.lpVerb=MAKEINTRESOURCEA(id-1); + wchar_t path[_MAX_PATH]; + GetModuleFileName(NULL,path,_countof(path)); + if (_wcsicmp(PathFindFileName(path),L"explorer.exe")==0) + command.fMask|=CMIC_MASK_ASYNCOK; + command.hwnd=hwnd; + command.nShow=SW_SHOWNORMAL; + hr=pMenu->InvokeCommand(&command); + } + DestroyMenu(menu); + } + + return true; +} + +// Removes the given item from the jumplist +void RemoveJumpItem( const CItemManager::ItemInfo *pAppInfo, CJumpList &list, int groupIdx, int itemIdx ) +{ + CString appid; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + appid=pAppInfo->GetAppid(); + } + CJumpGroup &group=list.groups[groupIdx]; + if (group.type==CJumpGroup::TYPE_FREQUENT || group.type==CJumpGroup::TYPE_RECENT) + { + if (CAutomaticList(appid).RemoveDestination(group.items[itemIdx].pItem)) + group.items.erase(group.items.begin()+itemIdx); + } + else + { + CComPtr pCustomList=GetCustomList(appid); + if (pCustomList) + { + if (SUCCEEDED(pCustomList->RemoveDestination(group.items[itemIdx].pItem))) + group.items.erase(group.items.begin()+itemIdx); + } + } +} + +// Pins or unpins the given item from the jumplist +void PinJumpItem( const CItemManager::ItemInfo *pAppInfo, const CJumpList &list, int groupIdx, int itemIdx, bool bPin, int pinIndex ) +{ + CString appid; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + appid=pAppInfo->GetAppid(); + } + const CJumpGroup &group=list.groups[groupIdx]; + CAutomaticList(appid).PinItem(group.items[itemIdx].pItem,bPin?pinIndex:-2); +} diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/JumpLists.h b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/JumpLists.h new file mode 100644 index 0000000..2574acf --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/JumpLists.h @@ -0,0 +1,65 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#include +#include "ItemManager.h" + +// Returns true if the given app has a non-empty jumplist +bool HasJumplist( const wchar_t *appid ); + +struct CJumpItem +{ + CJumpItem( void ) { type=TYPE_UNKNOWN; hash=0; bHidden=bHasArguments=false; } + enum Type + { + TYPE_UNKNOWN, + TYPE_ITEM, // IShellItem + TYPE_LINK, // IShellLink + TYPE_SEPARATOR, + }; + Type type; + unsigned int hash; + bool bHidden; + bool bHasArguments; + CString name; + CComPtr pItem; +}; + +struct CJumpGroup +{ + CJumpGroup( void ) { type=TYPE_RECENT; bHidden=false; } + enum Type + { + TYPE_RECENT, + TYPE_FREQUENT, + TYPE_TASKS, + TYPE_CUSTOM, + TYPE_PINNED, + }; + + Type type; + bool bHidden; + CString name; + std::vector items; +}; + +struct CJumpList +{ + std::vector groups; + + void Clear( void ) { groups.clear(); } +}; + +// Returns the jumplist for the given shortcut +bool GetJumplist( const wchar_t *appid, CJumpList &list, int maxCount, int maxHeight, int sepHeight, int itemHeight ); + +// Executes the given item using the correct application +bool ExecuteJumpItem( const CItemManager::ItemInfo *pAppInfo, const CJumpItem &item, HWND hwnd ); + +// Removes the given item from the jumplist +void RemoveJumpItem( const CItemManager::ItemInfo *pAppInfo, CJumpList &list, int groupIdx, int itemIdx ); + +// Pins or unpins the given item from the jumplist +void PinJumpItem( const CItemManager::ItemInfo *pAppInfo, const CJumpList &list, int groupIdx, int itemIdx, bool bPin, int pinIndex ); diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/LogManager.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/LogManager.cpp new file mode 100644 index 0000000..3ea17a4 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/LogManager.cpp @@ -0,0 +1,52 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// LogManager.cpp - logging functionality (for debugging) + +#include "stdafx.h" +#include "LogManager.h" +#include "ResourceHelper.h" + +int g_LogCategories; +static FILE *g_LogFile; +static int g_LogTime; + +void InitLog( int categories, const wchar_t *fname ) +{ + CloseLog(); + if (categories==0) return; + if (_wfopen_s(&g_LogFile,fname,L"wb")==0) + { + wchar_t bom=0xFEFF; + fwrite(&bom,2,1,g_LogFile); + g_LogCategories=categories; + g_LogTime=GetTickCount(); + LogMessage(L"version=%x, PID=%d, TID=%d, Categories=%08x\r\n",GetWinVersion(),GetCurrentProcessId(),GetCurrentThreadId(),categories); + } +} + +void CloseLog( void ) +{ + if (g_LogFile) fclose(g_LogFile); + g_LogFile=NULL; + g_LogCategories=0; +} + +void LogMessage( const wchar_t *text, ... ) +{ + if (!g_LogFile) return; + + wchar_t buf[2048]; + int len=Sprintf(buf,_countof(buf),L"%8d: ",GetTickCount()-g_LogTime); + fwrite(buf,2,len,g_LogFile); + + va_list args; + va_start(args,text); + len=Vsprintf(buf,_countof(buf),text,args); + va_end(args); + fwrite(buf,2,len,g_LogFile); + + fwrite(L"\r\n",2,2,g_LogFile); + + fflush(g_LogFile); +} diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/LogManager.h b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/LogManager.h new file mode 100644 index 0000000..1cbe383 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/LogManager.h @@ -0,0 +1,34 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +// LogManager.h - logging functionality (for debugging) +// Logs different events in the start menu +// Turn it on by setting the LogLevel setting in the registry +// The logging is consuming very little resources when it is turned off + +enum TLogCategory +{ + LOG_OPEN= 0x001, // logs opening and closing of menus + LOG_ITEMS= 0x002, // logs the menu items + LOG_EXECUTE= 0x004, // logs when items are executed + LOG_MFU= 0x008, // logs the MFU items and ranks + LOG_NEW= 0x010, // logs the highlighted programs + LOG_APPS= 0x120, // logs the found metro apps + LOG_SEARCH= 0x040, // logs the search results and ranks + LOG_SEARCH_SQL= 0x080, // logs the SQL search queries and results + LOG_MOUSE= 0x100, // logs mouse events (only hovering for now) + LOG_CACHE= 0x200, // logs the contents of the cache file + + LOG_ALL= 0xFFF +}; + +#define LOG_MENU( CATEGORY, TEXT, ... ) if (g_LogCategories&CATEGORY) { LogMessage(TEXT,__VA_ARGS__); } + +extern int g_LogCategories; +void InitLog( int categories, const wchar_t *fname ); +void CloseLog( void ); +void LogMessage( const wchar_t *text, ... ); + +#define STARTUP_LOG L"Software\\IvoSoft\\ClassicStartMenu\\Settings|LogStartup|%LOCALAPPDATA%\\ClassicShell\\StartupLog.txt" diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MenuCommands.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MenuCommands.cpp new file mode 100644 index 0000000..9a316ee --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MenuCommands.cpp @@ -0,0 +1,3208 @@ +// ## MenuContainer.h +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// MenuCommands.cpp - handles the commands and actions of CMenuContainer + +#include "stdafx.h" +#include "MenuContainer.h" +#include "ClassicStartMenuDLL.h" +#include "Settings.h" +#include "SettingsUI.h" +#include "SettingsUIHelper.h" +#include "Translations.h" +#include "LogManager.h" +#include "FNVHash.h" +#include "ResourceHelper.h" +#include "MetroLinkManager.h" +#include "ProgramsTree.h" +#include "resource.h" +#include +#include +#include +#include +#include + +static CString g_RenameText; +static POINT g_RenamePos; + +// Dialog proc for the Rename dialog box +static INT_PTR CALLBACK RenameDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if (uMsg==WM_INITDIALOG) + { + // translate text + SetWindowText(hwndDlg,FindTranslation(L"Menu.RenameTitle",L"Rename")); + SetDlgItemText(hwndDlg,IDC_LABEL,FindTranslation(L"Menu.RenamePrompt",L"&New name:")); + SetDlgItemText(hwndDlg,IDOK,FindTranslation(L"Menu.RenameOK",L"OK")); + SetDlgItemText(hwndDlg,IDCANCEL,FindTranslation(L"Menu.RenameCancel",L"Cancel")); + SetDlgItemText(hwndDlg,IDC_EDITNAME,g_RenameText); + // position near the item + SetWindowPos(hwndDlg,NULL,g_RenamePos.x,g_RenamePos.y,0,0,SWP_NOZORDER|SWP_NOSIZE); + SendMessage(hwndDlg,DM_REPOSITION,0,0); + return TRUE; + } + if (uMsg==WM_COMMAND && wParam==IDOK) + { + wchar_t buf[1024]; + GetDlgItemText(hwndDlg,IDC_EDITNAME,buf,_countof(buf)); + g_RenameText=buf; + + EndDialog(hwndDlg,1); + return TRUE; + } + if (uMsg==WM_COMMAND && wParam==IDCANCEL) + { + EndDialog(hwndDlg,0); + return TRUE; + } + return FALSE; +} + +static void SetShutdownPrivileges( void ) +{ + HANDLE hToken; + if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken)) + { + TOKEN_PRIVILEGES tp={1}; + if (LookupPrivilegeValue(NULL,L"SeShutdownPrivilege",&tp.Privileges[0].Luid)) + tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; + AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL); + CloseHandle(hToken); + } +} + +static void DoSearchSubst( wchar_t *buf, int size, const wchar_t *search ) +{ + wchar_t search2[256]; + char utf8[1024]; + WcsToMbs(utf8,_countof(utf8),search,CP_UTF8); + int len=0; + for (const char *c=utf8;*c;c++) + { + if ((*c>='a' && *c<='z') || (*c>='A' && *c<='Z') || (*c>='0' && *c<='9')) + { + search2[len++]=*c; + } + else if (len<_countof(search2)-4) + { + len+=Sprintf(search2+len,_countof(search2)-len,L"%%%02X",(unsigned char)*c); + } + else + break; + } + search2[len]=0; + DWORD_PTR args[100]={(DWORD_PTR)search,(DWORD_PTR)search2}; + wchar_t *pBuf=buf; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_ARGUMENT_ARRAY|FORMAT_MESSAGE_FROM_STRING,buf,0,0,(LPWSTR)&pBuf,0,(va_list*)args); + Strcpy(buf,size,pBuf); + LocalFree(pBuf); +} + +static DWORD CALLBACK ExecuteCommandThread( void *param ) +{ + CoInitialize(NULL); + const wchar_t *command=(wchar_t*)param; + wchar_t exe[_MAX_PATH]; + const wchar_t *args=NULL; + CComString strExe, strArgs; + if (SUCCEEDED(SHEvaluateSystemCommandTemplate(command,&strExe,NULL,&strArgs))) + { + args=strArgs; + Strcpy(exe,_countof(exe),strExe); + } + else + { + args=SeparateArguments(command,exe); + } + SHELLEXECUTEINFO execute={sizeof(execute),SEE_MASK_FLAG_LOG_USAGE}; + execute.lpFile=exe; + execute.lpParameters=args; + execute.nShow=SW_SHOWNORMAL; + ShellExecuteEx(&execute); + free(param); + CoUninitialize(); + return 0; +} + +void CMenuContainer::ExecuteCommand( const wchar_t *command, bool bElevated, bool bEnvSubst ) +{ + wchar_t text[1024]; + if (bEnvSubst) + { + Strcpy(text,_countof(text),command); + DoEnvironmentSubst(text,_countof(text)); + command=text; + } + if (bElevated) + { + wchar_t cmdLine[1024]; + Sprintf(cmdLine,_countof(cmdLine),L"-runas %s",command); + + wchar_t exe[_MAX_PATH]; + GetModuleFileName(_AtlBaseModule.GetModuleInstance(),exe,_countof(exe)); + PathRemoveFileSpec(exe); + PathAppend(exe,L"ClassicStartMenu.exe"); + + RECT rc; + if (m_bDestroyed) + ::GetWindowRect(g_TaskBar,&rc); + else + GetWindowRect(&rc); + ::SetForegroundWindow(g_OwnerWindow); + ::SetWindowPos(g_OwnerWindow,HWND_TOPMOST,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,0); + ShellExecute(g_OwnerWindow,L"runas",exe,cmdLine,NULL,SW_SHOWNORMAL); + } + else + { + CreateThread(NULL,0,ExecuteCommandThread,_wcsdup(command),0,NULL); + } +} + +// Dialog proc for the Log Off dialog box +static INT_PTR CALLBACK LogOffDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if (uMsg==WM_INITDIALOG) + { + // translate text + SendDlgItemMessage(hwndDlg,IDC_STATICICON1,STM_SETICON,lParam,0); + SetWindowText(hwndDlg,FindTranslation(L"Menu.LogoffTitle",L"Log Off Windows")); + SetDlgItemText(hwndDlg,IDC_PROMPT,FindTranslation(L"Menu.LogoffPrompt",L"Are you sure you want to log off?")); + SetDlgItemText(hwndDlg,IDOK,FindTranslation(L"Menu.LogoffYes",L"&Log Off")); + SetDlgItemText(hwndDlg,IDCANCEL,FindTranslation(L"Menu.LogoffNo",L"&No")); + return TRUE; + } + if (uMsg==WM_COMMAND && wParam==IDOK) + { + EndDialog(hwndDlg,1); + return TRUE; + } + if (uMsg==WM_COMMAND && wParam==IDCANCEL) + { + EndDialog(hwndDlg,0); + return TRUE; + } + return FALSE; +} + +struct ShortcutParams +{ + ShortcutParams( void ) { memset(this,0,sizeof(*this)); } + wchar_t target[_MAX_PATH+1]; + wchar_t temp[_MAX_PATH]; + wchar_t fname[_MAX_PATH+1]; +}; + +static DWORD WINAPI NewShortcutThread( void *param ) +{ + ShortcutParams *pParams=(ShortcutParams*)param; + HANDLE hFile=CreateFile(pParams->fname,0,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + if (hFile!=INVALID_HANDLE_VALUE) + { + // run the shortcut wizard + wchar_t cmdLine[1024]; + Sprintf(cmdLine,_countof(cmdLine),L"rundll32.exe appwiz.cpl,NewLinkHere %s",pParams->fname); + + STARTUPINFO startupInfo={sizeof(startupInfo)}; + PROCESS_INFORMATION processInfo; + memset(&processInfo,0,sizeof(processInfo)); + wchar_t exe[_MAX_PATH]=L"%windir%\\system32\\rundll32.exe"; + DoEnvironmentSubst(exe,_countof(exe)); + if (CreateProcess(exe,cmdLine,NULL,NULL,FALSE,0,NULL,pParams->temp,&startupInfo,&processInfo)) + { + CloseHandle(processInfo.hThread); + WaitForSingleObject(processInfo.hProcess,INFINITE); + CloseHandle(processInfo.hProcess); + + // see what the file was renamed to + struct { + DWORD FileNameLength; + wchar_t FileName[_MAX_PATH]; + } nameInfo={0}; + BOOL bInfo=GetFileInformationByHandleEx(hFile,FileNameInfo,&nameInfo,sizeof(nameInfo)); + CloseHandle(hFile); + if (bInfo) + { + // move to the final target folder + int len=Sprintf(pParams->fname,_countof(pParams->fname)-1,L"%s\\%s",pParams->temp,PathFindFileName(nameInfo.FileName)); + pParams->fname[len+1]=0; + SHFILEOPSTRUCT shfop={g_OwnerWindow,FO_MOVE,pParams->fname,pParams->target}; + SHFileOperation(&shfop); + } + } + else + CloseHandle(hFile); + DeleteFile(pParams->fname); + } + delete pParams; + return 0; +} + +static DWORD WINAPI SleepThread( void *param ) +{ + SetSuspendState((BOOL)param,FALSE,FALSE); + return 0; +} + +void CMenuContainer::CloseSubMenus( int flags, CMenuContainer *pAfter ) +{ + if (s_MenuMode==MODE_JUMPLIST && !(flags&CLOSE_KEEP_MODE)) + { + if (pAfter && !pAfter->m_bSubMenu) + { + pAfter->SetMenuMode(MODE_NORMAL); + } + } + for (int i=(int)s_Menus.size()-((flags&CLOSE_SKIP_LAST)?2:1);i>=0 && s_Menus[i]!=pAfter;i--) + if (!s_Menus[i]->m_bDestroyed) + { + if ((flags&CLOSE_SKIP_SEARCH) && (s_Menus[i]->m_Options&CONTAINER_SEARCH)) + continue; + if ((flags&CLOSE_ONLY_SEARCH) && !(s_Menus[i]->m_Options&CONTAINER_SEARCH)) + continue; + if (flags&CLOSE_POST) + { + s_Menus[i]->ShowWindow(SW_HIDE); + s_Menus[i]->PostMessage(WM_CLOSE); + s_Menus[i]->m_bClosing=true; + } + else + s_Menus[i]->DestroyWindow(); + } +} + +void CMenuContainer::OpenSubMenu( int index, TActivateType type, bool bShift ) +{ + const MenuItem &item=m_Items[index]; + if (m_bTwoColumns && s_bWin7Style) + { + if (item.bHasJumpList) + { + SetActiveWindow(); + CloseSubMenus(CLOSE_KEEP_MODE,this); + OpenJumpList(index,type==ACTIVATE_OPEN_KBD); + return; + } + if (item.id==MENU_SEARCH_BOX) + { + SetActiveWindow(); + CloseSubMenus(CLOSE_KEEP_MODE,this); + OpenSearchList(); + return; + } + if (item.id==MENU_PROGRAMS && GetSettingInt(L"ProgramsStyle")==PROGRAMS_INLINE) + { + SetActiveWindow(); + CloseSubMenus(CLOSE_KEEP_MODE,this); + SetMenuMode(s_MenuMode==MODE_PROGRAMS?MODE_NORMAL:MODE_PROGRAMS); + if (s_MenuMode==MODE_NORMAL) + SetHotItem(m_ProgramButtonIndex); + return; + } + } + // open a submenu - create a new menu object + const StdMenuItem *pSubMenu=item.pStdItem?item.pStdItem->submenu:NULL; + bool bOpenUp=false; + + int options=(type==ACTIVATE_OPEN_SEARCH)?CONTAINER_DRAG|CONTAINER_SEARCH:CONTAINER_DRAG|CONTAINER_DROP; + if (item.id==MENU_CONTROLPANEL) + options|=CONTAINER_CONTROLPANEL; + if (item.id==MENU_DOCUMENTS) + options|=CONTAINER_DOCUMENTS; + if (item.id==MENU_APPS) + options|=CONTAINER_APPS; + if (item.bPrograms) + options|=CONTAINER_PROGRAMS; + if (item.bLink || (m_Options&CONTAINER_LINK)) + options|=CONTAINER_LINK; + if ((m_Options&CONTAINER_TRACK) || item.id==MENU_PROGRAMS || item.id==MENU_APPS) + options|=CONTAINER_TRACK; + + if (item.id==MENU_PROGRAMS && GetSettingInt(L"PinnedPrograms")==PINNED_PROGRAMS_PINNED) + options|=CONTAINER_ALLPROGRAMS; + + if (item.id==MENU_RECENT_PROGRAMS) + options|=CONTAINER_RECENT; + + if (m_Options&CONTAINER_OPENUP_REC) + { + options|=CONTAINER_OPENUP_REC; + bOpenUp=true; + } + if (m_Options&CONTAINER_SORTZA_REC) + options|=CONTAINER_SORTZA|CONTAINER_SORTZA_REC; + + if (item.pStdItem) + { + if (item.pStdItem->settings&StdMenuItem::MENU_OPENUP) + bOpenUp=true; + if (item.pStdItem->settings&StdMenuItem::MENU_OPENUP_REC) + options|=CONTAINER_OPENUP_REC; + if (item.pStdItem->settings&StdMenuItem::MENU_SORTZA) + options|=CONTAINER_SORTZA; + if (item.pStdItem->settings&StdMenuItem::MENU_SORTZA_REC) + options|=CONTAINER_SORTZA_REC; + if (item.pStdItem->settings&StdMenuItem::MENU_SORTONCE) + options|=CONTAINER_SORTONCE; + if (item.pStdItem->settings&StdMenuItem::MENU_ITEMS_FIRST) + options|=CONTAINER_ITEMS_FIRST; + if (item.pStdItem->settings&StdMenuItem::MENU_TRACK) + options|=CONTAINER_TRACK; + if (item.pStdItem->settings&StdMenuItem::MENU_NOTRACK) + options&=~CONTAINER_TRACK; + if (item.pStdItem->settings&StdMenuItem::MENU_MULTICOLUMN) + options|=CONTAINER_MULTICOL_REC; + if (item.pStdItem->settings&StdMenuItem::MENU_NOEXTENSIONS) + options|=CONTAINER_NOEXTENSIONS; + if (item.pStdItem->settings&StdMenuItem::MENU_SINGLE_EXPAND) + options|=CONTAINER_NOSUBFOLDERS; + } + + if (item.id==MENU_NETWORK) + options|=CONTAINER_NOPATH; + + if (item.bHasJumpList) + options=CONTAINER_JUMPLIST|CONTAINER_DRAG|CONTAINER_DROP; + else if (item.id==MENU_COMPUTER && !s_bWin7Style) + { + if (GetSettingInt(L"Computer")==3) + options|=CONTAINER_NOSUBFOLDERS; + } + else if (item.pItem1 && item.pItemInfo) + { + CString PATH; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + if (item.bLink) + PATH=item.pItemInfo->GetTargetPATH(); + if (PATH.IsEmpty()) + PATH=item.pItemInfo->PATH; + } + if (!PATH.IsEmpty()) + { + for (int i=0;g_SpecialFolders[i].folder;i++) + { + if (PATH==g_SpecialFolders[i].PATH) + { + if (g_SpecialFolders[i].settings&SpecialFolder::FOLDER_NOSUBFOLDERS) + options|=CONTAINER_NOSUBFOLDERS; + if (g_SpecialFolders[i].settings&SpecialFolder::FOLDER_NONEWFOLDER) + options|=CONTAINER_NONEWFOLDER; + if (g_SpecialFolders[i].settings&SpecialFolder::FOLDER_NOPATH) + options|=CONTAINER_NOPATH; + if (g_SpecialFolders[i].settings&SpecialFolder::FOLDER_NODROP) + options&=~CONTAINER_DROP; + break; + } + } + } + } + + if (m_Options&CONTAINER_NOEXTENSIONS) + options|=CONTAINER_NOEXTENSIONS; + + if (item.id==MENU_PROGRAMS || item.id==MENU_APPS || (m_Options&CONTAINER_MULTICOL_REC)) + options|=CONTAINER_MULTICOL_REC; + if ((options&CONTAINER_MULTICOL_REC) && !bShift) + options|=CONTAINER_MULTICOLUMN; + if (options&CONTAINER_SEARCH) + options&=~(CONTAINER_MULTICOL_REC|CONTAINER_MULTICOLUMN); + + CMenuContainer *pMenu=new CSubMenuContainer(this,index,options,pSubMenu,item.pItem1,item.pItem2); + if (type==ACTIVATE_OPEN_SEARCH) + { + pMenu->InitSearchItems(); + } + else + { + s_JumpAppInfo=item.bHasJumpList?item.pItemInfo:NULL; + pMenu->InitItems(); + } + + RECT itemRect; + GetItemRect(index,itemRect); + MapWindowPoints(NULL,&itemRect); + RECT border={-s_Skin.Submenu_padding.left+s_Skin.Submenu_offset,-s_Skin.Submenu_padding.top,s_Skin.Submenu_padding.right-s_Skin.Submenu_offset,s_Skin.Submenu_padding.bottom}; + if (s_bRTL) + { + // swap and change signs + int q=border.left; border.left=-border.right; border.right=-q; + } + AdjustWindowRect(&border,s_SubmenuStyle,FALSE); + + if (m_bSubMenu) + pMenu->m_MaxWidth=s_MenuLimits.right-s_MenuLimits.left; + else if (s_bExpandRight) + pMenu->m_MaxWidth=s_MenuLimits.right-itemRect.right-border.left; + else + pMenu->m_MaxWidth=itemRect.left+border.right-s_MenuLimits.left; + + DWORD animFlags=AW_TOPMOST; + { + bool bDef; + int anim=GetSettingInt(L"SubMenuAnimation",bDef); + if (bDef) + { + DWORD fade; + SystemParametersInfo(SPI_GETMENUFADE,NULL,&fade,0); + anim=fade?1:2; + } + if (anim==3) animFlags|=((rand()=0 && !GetSettingBool(L"SubMenuAnimationAlways"))) + animate=FALSE; + else + SystemParametersInfo(SPI_GETMENUANIMATION,NULL,&animate,0); + + // destroy old submenus + SetActiveWindow(); + CloseSubMenus(CLOSE_SKIP_LAST,this); + + // open submenu + HWND parent=GetParent(); + pMenu->Create(parent,NULL,s_SubmenuStyle,WS_EX_TOOLWINDOW|WS_EX_TOPMOST|(s_bRTL?WS_EX_LAYOUTRTL:0)); + + if (GetSettingBool(L"MenuShadow") && s_Skin.Submenu_shadow==MenuSkin::SHADOW_ON) + SetClassLong(pMenu->m_hWnd,GCL_STYLE,GetClassLong(pMenu->m_hWnd,GCL_STYLE)|CS_DROPSHADOW); + else + SetClassLong(pMenu->m_hWnd,GCL_STYLE,GetClassLong(pMenu->m_hWnd,GCL_STYLE)&~CS_DROPSHADOW); + + if (!parent && s_TaskBar) + { + // place sub-menus in front of the taskbar + if (type==ACTIVATE_OPEN_SEARCH) + pMenu->SetWindowPos(s_TaskBar,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); + else + pMenu->SetWindowPos(s_TaskBar,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE); + } + RECT rc2; + pMenu->GetWindowRect(&rc2); + + // position new menu + int w=rc2.right-rc2.left; + int h=rc2.bottom-rc2.top; + + if (s_bExpandRight) + { + if (itemRect.right+border.left+w<=s_MenuLimits.right) + { + // right + rc2.left=itemRect.right+border.left; + rc2.right=rc2.left+w; + animFlags|=AW_HOR_POSITIVE; + pMenu->m_Options|=CONTAINER_LEFT; + } + else if (itemRect.left+border.right-w>=s_MenuLimits.left) + { + // left + rc2.right=itemRect.left+border.right; + rc2.left=rc2.right-w; + animFlags|=AW_HOR_NEGATIVE; + } + else + { + // right again + rc2.right=s_MenuLimits.right; + rc2.left=rc2.right-w; + if (!s_bRTL) + { + int minx=m_bSubMenu?s_MenuLimits.left:(itemRect.right+border.left); + if (rc2.leftm_Options|=CONTAINER_LEFT; + } + } + else + { + if (itemRect.left+border.right-w>=s_MenuLimits.left) + { + // left + rc2.right=itemRect.left+border.right; + rc2.left=rc2.right-w; + animFlags|=AW_HOR_NEGATIVE; + } + else if (itemRect.right+border.left+w<=s_MenuLimits.right) + { + // right + rc2.left=itemRect.right+border.left; + rc2.right=rc2.left+w; + animFlags|=AW_HOR_POSITIVE; + pMenu->m_Options|=CONTAINER_LEFT; + } + else + { + // left again + rc2.left=s_MenuLimits.left; + rc2.right=rc2.left+w; + if (s_bRTL) + { + int maxx=m_bSubMenu?s_MenuLimits.right:(itemRect.left+border.right); + if (rc2.right>maxx) + { + rc2.left=maxx-w; + rc2.right=maxx; + } + } + animFlags|=AW_HOR_NEGATIVE; + } + } + + if (s_bRTL) + animFlags^=(AW_HOR_POSITIVE|AW_HOR_NEGATIVE); // RTL flips the animation + + if (bOpenUp) + { + if (itemRect.bottom+border.bottom-h>=s_MenuLimits.top) + { + // up + rc2.bottom=itemRect.bottom+border.bottom; + rc2.top=rc2.bottom-h; + } + else if (itemRect.top+border.top+h<=s_MenuLimits.bottom) + { + // down + rc2.top=itemRect.top+border.top; + rc2.bottom=rc2.top+h; + pMenu->m_Options|=CONTAINER_TOP; + } + else + { + // up again + rc2.top=s_MenuLimits.top-pMenu->m_ExtraBorder; + rc2.bottom=rc2.top+h; + } + } + else + { + if (itemRect.top+border.top+h<=s_MenuLimits.bottom) + { + // down + rc2.top=itemRect.top+border.top; + rc2.bottom=rc2.top+h; + pMenu->m_Options|=CONTAINER_TOP; + } + else if (itemRect.bottom+border.bottom-h>=s_MenuLimits.top) + { + // up + rc2.bottom=itemRect.bottom+border.bottom; + rc2.top=rc2.bottom-h; + } + else + { + // down again + rc2.bottom=s_MenuLimits.bottom+pMenu->m_ExtraBorder; + rc2.top=rc2.bottom-h; + pMenu->m_Options|=CONTAINER_TOP; + } + } + + SetSubmenu(index); + m_SubShowTime=0; + InvalidateItem(index); + if (type!=ACTIVATE_OPEN_SEARCH) + SetHotItem(index); + UpdateWindow(); + + if (type!=ACTIVATE_OPEN_SEARCH) + { + pMenu->SetFocus(); + + int hotItem=-1; + if (type==ACTIVATE_OPEN_KBD) + { + bool bLast=item.id==MENU_SHUTDOWN_BUTTON && GetSettingBool(L"SelectLastShutdown"); + for (int i=0;i<(int)pMenu->m_Items.size();i++) + if (pMenu->CanSelectItem(i)) + { + hotItem=i; + if (!bLast) + break; + } + } + pMenu->SetHotItem(hotItem); + } + + int speed=0; + if (animate) + { + speed=GetSettingInt(L"SubMenuAnimationSpeed"); + if (speed<=0) speed=MENU_ANIM_SPEED_SUBMENU; + else if (speed>=10000) speed=10000; + } + pMenu->AnimateMenu(animFlags,speed,rc2); + + if (s_Tooltip.m_hWnd) + s_Tooltip.SetWindowPos(HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); +} + +class ExitGuard +{ +public: + ExitGuard( void ) { m_bArmed=true; } + ~ExitGuard( void ) { Assert(!m_bArmed); } + void Disarm( void ) { m_bArmed=false; } +private: + bool m_bArmed; +}; + +#ifndef EWX_HYBRID_SHUTDOWN +#define EWX_HYBRID_SHUTDOWN 0x00400000 +#endif +#define EWX_INSTALL_UPDATES 0x00100000 // undocumented switch to install updates on shutdown + +static bool ExecuteSysCommand( TMenuID menuCommand ) +{ + CComPtr pShellDisp; + HRESULT hr; + switch (menuCommand) + { + case MENU_TASKBAR: // show taskbar properties + hr=CoCreateInstance(CLSID_Shell,NULL,CLSCTX_SERVER,IID_IShellDispatch2,(void**)&pShellDisp); + if (SUCCEEDED(hr)) + { + hr=pShellDisp->TrayProperties(); + if (FAILED(hr)) + LOG_MENU(LOG_EXECUTE,L"Failed to TrayProperties, 0x08%x",hr); + } + else + LOG_MENU(LOG_EXECUTE,L"Failed to create dispatch, 0x08%x",hr); + return true; + + case MENU_FEATURES: + hr=CoCreateInstance(CLSID_Shell,NULL,CLSCTX_SERVER,IID_IShellDispatch2,(void**)&pShellDisp); + if (SUCCEEDED(hr)) + { + hr=pShellDisp->ControlPanelItem(CComBSTR(L"appwiz.cpl")); + if (FAILED(hr)) + LOG_MENU(LOG_EXECUTE,L"Failed to ControlPanelItem(appwiz.cpl), 0x08%x",hr); + } + else + LOG_MENU(LOG_EXECUTE,L"Failed to create dispatch, 0x08%x",hr); + return true; + + case MENU_SECURITY: + { + CComPtr pShellDisp4; + hr=CoCreateInstance(CLSID_Shell,NULL,CLSCTX_SERVER,IID_IShellDispatch4,(void**)&pShellDisp4); + if (SUCCEEDED(hr)) + { + hr=pShellDisp4->WindowsSecurity(); + if (FAILED(hr)) + LOG_MENU(LOG_EXECUTE,L"Failed to WindowsSecurity, 0x08%x",hr); + } + else + LOG_MENU(LOG_EXECUTE,L"Failed to create dispatch, 0x08%x",hr); + } + return true; + + case MENU_SEARCH_FILES: // show the search UI + hr=CoCreateInstance(CLSID_Shell,NULL,CLSCTX_SERVER,IID_IShellDispatch2,(void**)&pShellDisp); + if (SUCCEEDED(hr)) + { + hr=pShellDisp->FindFiles(); + if (FAILED(hr)) + LOG_MENU(LOG_EXECUTE,L"Failed to FindFiles, 0x08%x",hr); + } + else + LOG_MENU(LOG_EXECUTE,L"Failed to create dispatch, 0x08%x",hr); + return true; + + case MENU_SEARCH_PRINTER: // search for network printers + hr=CoCreateInstance(CLSID_Shell,NULL,CLSCTX_SERVER,IID_IShellDispatch2,(void**)&pShellDisp); + if (SUCCEEDED(hr)) + { + hr=pShellDisp->FindPrinter(CComBSTR(L""),CComBSTR(L""),CComBSTR(L"")); + if (FAILED(hr)) + LOG_MENU(LOG_EXECUTE,L"Failed to FindPrinter, 0x08%x",hr); + } + else + LOG_MENU(LOG_EXECUTE,L"Failed to create dispatch, 0x08%x",hr); + return true; + + case MENU_SEARCH_COMPUTERS: // search for computers + hr=CoCreateInstance(CLSID_Shell,NULL,CLSCTX_SERVER,IID_IShellDispatch2,(void**)&pShellDisp); + if (SUCCEEDED(hr)) + { + hr=pShellDisp->FindComputer(); + if (FAILED(hr)) + LOG_MENU(LOG_EXECUTE,L"Failed to FindComputer, 0x08%x",hr); + } + else + LOG_MENU(LOG_EXECUTE,L"Failed to create dispatch, 0x08%x",hr); + return true; + + case MENU_SEARCH_PEOPLE: // search for people using Windows Mail + { + SHELLEXECUTEINFO execute={sizeof(execute),SEE_MASK_DOENVSUBST,NULL,L"open"}; + execute.lpFile=L"%ProgramFiles%\\Windows Mail\\wab.exe"; + execute.lpParameters=L"/find"; + execute.lpDirectory=L"%ProgramFiles%\\Windows Mail"; + execute.nShow=SW_SHOWNORMAL; + ShellExecuteEx(&execute); + } + return true; + + case MENU_HELP: // show Windows help + hr=CoCreateInstance(CLSID_Shell,NULL,CLSCTX_SERVER,IID_IShellDispatch2,(void**)&pShellDisp); + if (SUCCEEDED(hr)) + { + hr=pShellDisp->Help(); + if (FAILED(hr)) + LOG_MENU(LOG_EXECUTE,L"Failed to Help, 0x08%x",hr); + } + else + LOG_MENU(LOG_EXECUTE,L"Failed to create dispatch, 0x08%x",hr); + return true; + + case MENU_RUN: // show the Run box + if (GetWinVersion()>=WIN_VER_WIN10) + { + ShellExecute(NULL,NULL,L"shell:::{2559a1f3-21d7-11d4-bdaf-00c04f60b9f0}",NULL,NULL,SW_SHOWNORMAL); + } + else + { + hr=CoCreateInstance(CLSID_Shell,NULL,CLSCTX_SERVER,IID_IShellDispatch2,(void**)&pShellDisp); + if (SUCCEEDED(hr)) + { + hr=pShellDisp->FileRun(); + if (FAILED(hr)) + LOG_MENU(LOG_EXECUTE,L"Failed to FileRun, 0x08%x",hr); + } + else + LOG_MENU(LOG_EXECUTE,L"Failed to create dispatch, 0x08%x",hr); + } + return true; + + case MENU_LOGOFF: // log off + ExitWindowsEx(EWX_LOGOFF,0); + return true; + + case MENU_LOGOFF_CONFIRM: + { + HMODULE hShell32=GetModuleHandle(L"Shell32.dll"); + HICON icon=LoadIcon(hShell32,MAKEINTRESOURCE(45)); + INT_PTR res=DialogBoxParam(g_Instance,MAKEINTRESOURCE(IsLanguageRTL()?IDD_LOGOFFR:IDD_LOGOFF),NULL,LogOffDlgProc,(LPARAM)icon); + DestroyIcon(icon); + if (res) + ExitWindowsEx(EWX_LOGOFF,0); + } + return true; + + case MENU_RESTART: // restart + case MENU_RESTART_NOUPDATE: + SetShutdownPrivileges(); + ExitWindowsEx(EWX_REBOOT,SHTDN_REASON_FLAG_PLANNED); + return true; + + case MENU_RESTART_ADVANCED: // advanced restart + if (GetWinVersion()>=WIN_VER_WIN8) + { + STARTUPINFO startupInfo={sizeof(startupInfo)}; + PROCESS_INFORMATION processInfo; + memset(&processInfo,0,sizeof(processInfo)); + wchar_t exe[_MAX_PATH]=L"%windir%\\system32\\shutdown.exe"; + DoEnvironmentSubst(exe,_countof(exe)); + if (CreateProcess(exe,L"shutdown.exe /r /o /t 0",NULL,NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&startupInfo,&processInfo)) + { + CloseHandle(processInfo.hThread); + CloseHandle(processInfo.hProcess); + } + } + else + ExitWindowsEx(EWX_REBOOT,SHTDN_REASON_FLAG_PLANNED); + return true; + + case MENU_RESTART_UPDATE: // update and restart + { + UINT flags=EWX_REBOOT; + if (GetWinVersion()>=WIN_VER_WIN8) + flags|=EWX_INSTALL_UPDATES; + SetShutdownPrivileges(); + ExitWindowsEx(flags,SHTDN_REASON_FLAG_PLANNED); + } + return true; + + case MENU_SWITCHUSER: // switch_user + if (GetWinVersion()>=WIN_VER_WIN10) + { + // on Windows 10 this value must be set to 1. For some reason non-admin code has permissions to do so + CRegKey regSwitch; + if (regSwitch.Create(HKEY_LOCAL_MACHINE,L"Software\\Microsoft\\Windows\\CurrentVersion\\Authentication\\LogonUI\\UserSwitch",NULL,0,KEY_SET_VALUE)==ERROR_SUCCESS) + regSwitch.SetDWORDValue(L"Enabled",1); + } + WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE,WTS_CURRENT_SESSION,FALSE); // same as "disconnect" + return true; + + case MENU_LOCK: // lock + LockWorkStation(); + return true; + + case MENU_SHUTDOWN: // shutdown + case MENU_SHUTDOWN_NOUPDATE: + SetShutdownPrivileges(); + ExitWindowsEx(EWX_SHUTDOWN,SHTDN_REASON_FLAG_PLANNED); + return true; + + case MENU_SHUTDOWN_UPDATE: // update and shutdown + SetShutdownPrivileges(); + ExitWindowsEx(EWX_SHUTDOWN|EWX_INSTALL_UPDATES,SHTDN_REASON_FLAG_PLANNED); + return true; + + case MENU_SHUTDOWN_HYBRID: // hybrid shutdown + SetShutdownPrivileges(); + { + UINT flags=EWX_SHUTDOWN; + if (GetWinVersion()>=WIN_VER_WIN8) + { + CRegKey regPower; + if (regPower.Open(HKEY_LOCAL_MACHINE,L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power",KEY_READ)==ERROR_SUCCESS) + { + DWORD val; + if (regPower.QueryDWORDValue(L"HiberbootEnabled",val)==ERROR_SUCCESS && val==1) + flags|=EWX_HYBRID_SHUTDOWN; + } + } + ExitWindowsEx(flags,SHTDN_REASON_FLAG_PLANNED); + } + return true; + + case MENU_SLEEP: + if (GetSystemMetrics(SM_REMOTESESSION)) + { + WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE,WTS_CURRENT_SESSION,FALSE); + Sleep(250); + } + CreateThread(NULL,0,SleepThread,(void*)FALSE,0,NULL); + return true; + + case MENU_HIBERNATE: + if (GetSystemMetrics(SM_REMOTESESSION)) + { + WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE,WTS_CURRENT_SESSION,FALSE); + Sleep(250); + } + CreateThread(NULL,0,SleepThread,(void*)TRUE,0,NULL); + return true; + + case MENU_DISCONNECT: // disconnect the current Terminal Services session (remote desktop) + WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE,WTS_CURRENT_SESSION,FALSE); + return true; + + case MENU_UNDOCK: // undock the PC + hr=CoCreateInstance(CLSID_Shell,NULL,CLSCTX_SERVER,IID_IShellDispatch2,(void**)&pShellDisp); + if (SUCCEEDED(hr)) + { + hr=pShellDisp->EjectPC(); + if (FAILED(hr)) + LOG_MENU(LOG_EXECUTE,L"Failed to EjectPC, 0x08%x",hr); + } + else + LOG_MENU(LOG_EXECUTE,L"Failed to create dispatch, 0x08%x",hr); + return true; + + case MENU_MONITOROFF: + ::SendMessage(g_TaskBar,WM_SYSCOMMAND,SC_MONITORPOWER,2); + return true; + + case MENU_SHUTDOWN_BOX: // shutdown - ask to shutdown, log off, sleep, etc + hr=CoCreateInstance(CLSID_Shell,NULL,CLSCTX_SERVER,IID_IShellDispatch2,(void**)&pShellDisp); + if (SUCCEEDED(hr)) + { + hr=pShellDisp->ShutdownWindows(); + if (FAILED(hr)) + LOG_MENU(LOG_EXECUTE,L"Failed to ShutdownWindows, 0x08%x",hr); + } + else + LOG_MENU(LOG_EXECUTE,L"Failed to create dispatch, 0x08%x",hr); + return true; + + case MENU_PCSETTINGS: + if (GetWinVersion()>=WIN_VER_WIN8) + { + ShellExecute(NULL,NULL,L"shell:appsfolder\\windows.immersivecontrolpanel_cw5n1h2txyewy!microsoft.windows.immersivecontrolpanel",NULL,NULL,SW_SHOWNORMAL); + } + return true; + + default: + return false; + } +} + +STARTMENUAPI bool DllExecuteNamedCommand( const wchar_t *command ) +{ + static struct NamedCommand + { + const wchar_t *name; + TMenuID command; + } s_NamedCommands[]= + { + {L"help",MENU_HELP}, + {L"run",MENU_RUN}, + {L"logoff",MENU_LOGOFF}, + {L"undock",MENU_UNDOCK}, + {L"monitor_off",MENU_MONITOROFF}, + {L"disconnect",MENU_DISCONNECT}, + {L"shutdown_box",MENU_SHUTDOWN_BOX}, + {L"windows_security",MENU_SECURITY}, + {L"taskbar_settings",MENU_TASKBAR}, + {L"search_files",MENU_SEARCH_FILES}, + {L"search_printer",MENU_SEARCH_PRINTER}, + {L"search_computers",MENU_SEARCH_COMPUTERS}, + {L"search_people",MENU_SEARCH_PEOPLE}, + {L"sleep",MENU_SLEEP}, + {L"hibernate",MENU_HIBERNATE}, + {L"restart",MENU_RESTART}, + {L"shutdown",MENU_SHUTDOWN}, + {L"switch_user",MENU_SWITCHUSER}, + {L"lock",MENU_LOCK}, + {L"programs_features",MENU_FEATURES}, + + {L"confirm_logoff",MENU_LOGOFF_CONFIRM}, + {L"advanced_boot",MENU_RESTART_ADVANCED}, + {L"update_restart",MENU_RESTART_UPDATE}, + {L"update_shutdown",MENU_SHUTDOWN_UPDATE}, + {L"hybrid_shutdown",MENU_SHUTDOWN_HYBRID}, + }; + + TMenuID menuCommand=MENU_NO; + for (int i=0;i<_countof(s_NamedCommands);i++) + { + if (wcscmp(command,s_NamedCommands[i].name)==0) + { + menuCommand=s_NamedCommands[i].command; + break; + } + } + + switch (menuCommand) + { + case MENU_NO: + return false; + + case MENU_HELP: + if (SHRestricted(REST_NOSMHELP)) return false; + break; + + case MENU_RUN: + if (SHRestricted(REST_NORUN)) return false; + break; + + case MENU_LOGOFF: + case MENU_LOGOFF_CONFIRM: + if (SHRestricted(REST_STARTMENULOGOFF)==1) return false; + break; + + case MENU_DISCONNECT: + if (SHRestricted(REST_NODISCONNECT)) return false; + break; + + case MENU_UNDOCK: + if (SHRestricted(REST_NOSMEJECTPC)) return false; + break; + + case MENU_SEARCH_COMPUTERS: + if (SHRestricted(REST_HASFINDCOMPUTERS)) return false; + break; + + case MENU_SWITCHUSER: + { + CComPtr pShellDisp; + if (SUCCEEDED(CoCreateInstance(CLSID_Shell,NULL,CLSCTX_SERVER,IID_IShellDispatch2,(void**)&pShellDisp))) + { + long val; + if (SUCCEEDED(pShellDisp->IsRestricted(CComBSTR(L"System"),CComBSTR(L"HideFastUserSwitching"),&val)) && val) + return false; + } + } + break; + + case MENU_TASKBAR: + if (SHRestricted(REST_NOSETTASKBAR)) return false; + break; + + case MENU_FEATURES: + if (SHRestricted(REST_NOSETFOLDERS) || SHRestricted(REST_NOCONTROLPANEL)) return false; + break; + + case MENU_RESTART: + case MENU_SHUTDOWN: + case MENU_RESTART_ADVANCED: + case MENU_RESTART_UPDATE: + case MENU_SHUTDOWN_UPDATE: + case MENU_SHUTDOWN_HYBRID: + if (SHRestricted(REST_NOCLOSE)) return false; + break; + } + + ExecuteSysCommand(menuCommand); + return true; +} + +static HRESULT CreatePinLink( PCIDLIST_ABSOLUTE sourcePidl, const wchar_t *name, const wchar_t *iconPath, int iconIndex ) +{ + wchar_t path[_MAX_PATH]; + Sprintf(path,_countof(path),L"%s\\%s.lnk",CMenuContainer::s_PinFolder,name); + wchar_t finalPath[_MAX_PATH]; + PathYetAnotherMakeUniqueName(finalPath,path,NULL,PathFindFileName(path)); + + HRESULT hr; + { + CComPtr pLink; + hr=pLink.CoCreateInstance(CLSID_ShellLink); + if (FAILED(hr)) return hr; + + hr=pLink->SetIDList(sourcePidl); + if (FAILED(hr)) return hr; + + if (iconPath) + { + hr=pLink->SetIconLocation(iconPath,iconIndex); + if (FAILED(hr)) return hr; + } + + CComQIPtr pFile=pLink; + if (!pFile) return E_FAIL; + hr=pFile->Save(finalPath,TRUE); + } + { + // reopen the link and set the "no new" property. without reopening the original properties are lost + CComPtr pLink; + hr=pLink.CoCreateInstance(CLSID_ShellLink); + CComQIPtr pFile=pLink; + hr=pFile->Load(finalPath,STGM_READWRITE); + CComQIPtr pStore=pLink; + if (pStore) + { + PROPVARIANT val; + InitPropVariantFromBoolean(TRUE,&val); + pStore->SetValue(PKEY_AppUserModel_ExcludeFromShowInNewInstall,val); + PropVariantClear(&val); + pStore->Commit(); + } + hr=pFile->Save(finalPath,TRUE); + } + HANDLE h=CreateFile(finalPath,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + if (h!=INVALID_HANDLE_VALUE) + { + FILETIME curTime; + GetSystemTimeAsFileTime(&curTime); + SetFileTime(h,&curTime,&curTime,&curTime); + CloseHandle(h); + } + return S_OK; +} + +// This function "activates" an item. The item can be activated in multiple ways: +// ACTIVATE_SELECT - select the item, make sure it is visible +// ACTIVATE_OPEN - if the item is a submenu, it is opened. otherwise the item is just selected (but all submenus are closed first) +// ACTIVATE_OPEN_KBD - same as above, but when done with a keyboard +// ACTIVATE_OPEN_SEARCH - opens the search results submenu +// ACTIVATE_EXECUTE - executes the item. it can be a shell item or a command item +// ACTIVATE_MENU - shows the context menu for the item +// ACTIVATE_RENAME - renames the item +// ACTIVATE_DELETE - deletes the item +// ACTIVATE_PROPERTIES - shows the properties of the item +void CMenuContainer::ActivateItem( int index, TActivateType type, const POINT *pPt, ActivateData *pData ) +{ + LOG_MENU(LOG_EXECUTE,L"Activate Item, ptr=%p, index=%d, type=%d",this,index,type); + if (index<0) + { + if (type==ACTIVATE_SELECT) + { + if (!(m_Options&CONTAINER_SEARCH)) + SetFocus(); + SetHotItem(-1); + return; + } + else if (type==ACTIVATE_MENU) + { + index=0; + type=ACTIVATE_MENU_BACKGROUND; + } + else + return; + } + + // make a const copy of the item and use it instead. the m_Items array can be reallocated at any time + const MenuItem item=m_Items[index]; + CAbsolutePidl pItemPidl1, pItemPidl2; + pItemPidl1.Clone(item.pItem1); + pItemPidl2.Clone(item.pItem2); + ((MenuItem&)item).pItem1=NULL; // hack to ensure the pidls are not used anywhere here + ((MenuItem&)item).pItem2=NULL; + + if (type==ACTIVATE_SELECT) + { + // set the hot item + if (item.id==MENU_SEARCH_BOX) + { + m_SearchBox.SetFocus(); + SetHotItem(-1); + } + else + { + if (item.id==MENU_PROGRAMS_TREE && m_pProgramsTree && m_pProgramsTree->m_hWnd) + m_pProgramsTree->SetFocus(); + else if (!(m_Options&CONTAINER_SEARCH) && (m_bSubMenu || s_MenuMode!=MODE_SEARCH)) + SetFocus(); + SetHotItem(index,false,true); + } + if (m_ScrollHeight>0 && indexrc.top-m_ScrollButtonSize) + pos=rc.top-m_ScrollButtonSize; + else if (postotal) pos=total; + if (m_ScrollOffset!=pos) + { + m_ScrollOffset=pos; + UpdateScroll(); + Invalidate(); + } + } + if (m_SearchScrollCount>m_SearchScrollHeight && index>=m_OriginalCount) + { + // scroll the search results to make this item visible + int idx=index-m_OriginalCount; + int pos=m_SearchScrollPos; + if (pos>idx) pos=idx; + if (pos+m_SearchScrollHeightbNoModifiers) && GetKeyState(VK_SHIFT)<0; + bool bCtrl=(!pData || !pData->bNoModifiers) && GetKeyState(VK_CONTROL)<0; + + if (type==ACTIVATE_OPEN || type==ACTIVATE_OPEN_KBD || type==ACTIVATE_OPEN_SEARCH) + { + if (item.id==MENU_SEARCH_BOX && type!=ACTIVATE_OPEN_SEARCH) + return; + s_HotPos=GetMessagePos(); + if (!item.bFolder && item.id!=MENU_SEARCH_BOX) + { + SetActiveWindow(); + // destroy old submenus + CloseSubMenus(0,this); + + // just select the item + ActivateItem(index,ACTIVATE_SELECT,NULL); + return; + } + + OpenSubMenu(index,type,bShift); + return; + } + + bool bKeepOpen=(type==ACTIVATE_EXECUTE) && bShift && !bCtrl && (!item.bMetroLink || GetWinVersion()>=WIN_VER_WIN10); + bool bTrackRecent=false; + if (s_RecentPrograms!=RECENT_PROGRAMS_NONE) + { + if (item.id==MENU_RECENT) + bTrackRecent=true; + else if (!m_bSubMenu || (m_Options&CONTAINER_TRACK)) + bTrackRecent=item.id==MENU_NO && (!item.bFolder || item.bHasJumpList) && !item.pStdItem && (item.categoryHash&15)<=CSearchManager::CATEGORY_SETTING; + } + + CString searchText; + for (CMenuContainer *pSearchMenu=this;pSearchMenu;pSearchMenu=pSearchMenu->m_pParent) + if (pSearchMenu->m_SearchBox.m_hWnd) + { + pSearchMenu->m_SearchBox.GetWindowText(searchText); + break; + } + + if (type==ACTIVATE_EXECUTE) + { + if (item.id==MENU_EMPTY || item.id==MENU_EMPTY_TOP) return; + if (item.bFolder && pItemPidl1 && !item.bSplit && !GetSettingBool(L"EnableExplorer")) + return; + if (item.id==MENU_SEARCH_BOX) + { + // the search button was pressed + m_SearchBox.SetFocus(); + CloseSubMenus(CLOSE_POST,this); + m_SearchBox.SetWindowText(L""); + return; + } + if (item.id==MENU_SEARCH_CATEGORY) + { + if (bCtrl || (pData && pData->bArrow)) + { + for (std::list::const_iterator it=s_SearchResults.indexed.begin();it!=s_SearchResults.indexed.end();++it) + { + if (item.categoryHash==it->categoryHash) + { + if (bKeepOpen) + LockSetForegroundWindow(LSFW_LOCK); + else + { + LockSetForegroundWindow(LSFW_UNLOCK); + FadeOutItem(index); + CloseSubMenus(CLOSE_POST,NULL); + } + PlayMenuSound(SOUND_COMMAND); + g_SearchManager.LaunchExternalSearch(it->search,it->categoryHash,searchText); + break; + } + } + } + else + { + m_SearchCategoryHash=(m_SearchCategoryHash==item.categoryHash)?CSearchManager::CATEGORY_INVALID:item.categoryHash; + RefreshSearch(); + } + return; + } + + if (item.jumpIndex>=0) + { + if (item.id==MENU_NO) + { + if (bKeepOpen) + LockSetForegroundWindow(LSFW_LOCK); + else + { + LockSetForegroundWindow(LSFW_UNLOCK); + FadeOutItem(index); + CloseSubMenus(CLOSE_POST,NULL); + } + PlayMenuSound(SOUND_COMMAND); + ExecuteJumpItem(s_JumpAppInfo,s_JumpList.groups[LOWORD(item.jumpIndex)].items[HIWORD(item.jumpIndex)],g_OwnerWindow); + } + return; + } + if (g_LogCategories&LOG_ITEMS) + { + LOG_MENU(LOG_EXECUTE,L"item.bLink: %d",item.bLink?1:0); + LOG_MENU(LOG_EXECUTE,L"item.bMetroLink: %d",item.bMetroLink?1:0); + LOG_MENU(LOG_EXECUTE,L"item.bMetroApp: %d",item.bMetroApp?1:0); + if (!item.pItemInfo) + { + LOG_MENU(LOG_EXECUTE,L"No pItemInfo"); + } + else + { + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + LOG_MENU(LOG_EXECUTE,L"bLink: %d",item.pItemInfo->IsLink()?1:0); + LOG_MENU(LOG_EXECUTE,L"bMetroLink: %d",item.pItemInfo->IsMetroLink()?1:0); + LOG_MENU(LOG_EXECUTE,L"bMetroApp: %d",item.pItemInfo->IsMetroApp()?1:0); + LOG_MENU(LOG_EXECUTE,L"bProtectedLink: %d",item.pItemInfo->IsProtectedLink()?1:0); + LOG_MENU(LOG_EXECUTE,L"bNoPin: %d",item.pItemInfo->IsNoPin()?1:0); + LOG_MENU(LOG_EXECUTE,L"bNoNew: %d",item.pItemInfo->IsNoNew()?1:0); + LOG_MENU(LOG_EXECUTE,L"path: %s",item.pItemInfo->GetPath()); + LOG_MENU(LOG_EXECUTE,L"PATH: %s",item.pItemInfo->PATH); + LOG_MENU(LOG_EXECUTE,L"targetPATH: %s",item.pItemInfo->GetTargetPATH()); + LOG_MENU(LOG_EXECUTE,L"appid: %s",item.pItemInfo->GetAppid()); + LOG_MENU(LOG_EXECUTE,L"metroName: %s",item.pItemInfo->GetMetroName()); + LOG_MENU(LOG_EXECUTE,L"iconPath: %s",item.pItemInfo->GetIconPath()); + } + if (item.pItemInfo->smallIcon) + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ICONS); + LOG_MENU(LOG_EXECUTE,L"smallIcon: %s",item.pItemInfo->smallIcon->GetPath()); + } + if (item.pItemInfo->largeIcon) + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ICONS); + LOG_MENU(LOG_EXECUTE,L"largeIcon: %s",item.pItemInfo->largeIcon->GetPath()); + } + } + } + if (item.bMetroLink) + { + LockSetForegroundWindow(LSFW_UNLOCK); + FadeOutItem(index); + PlayMenuSound(SOUND_COMMAND); + ExecuteMetroLink(item.pItemInfo); + if (bTrackRecent) + { + CString path; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + path=item.pItemInfo->GetPath(); + } + AddMRUShortcut(path); + } + g_ItemManager.RemoveNewItem(pItemPidl1,NULL,false); + if (!(m_Options&CONTAINER_LINK)) + g_SearchManager.AddItemRank(item.nameHash); + // close all menus when launching Metro apps + CloseSubMenus(CLOSE_POST,NULL); + return; + } + if (!pItemPidl1) + { + if (item.idsubmenu && !item.pStdItem->command && item.id!=MENU_SHUTDOWN_BUTTON) + return; // non-executable item + } + + // when executing an item close the whole menu + if (!bKeepOpen) + { + if (g_TopWin7Menu && s_bAllPrograms) + { + // send, don't post. the top menu must be closed immediately. otherwise its closing may interfere with launching the command + ::SendMessage(g_TopWin7Menu,WM_CLOSE,0,0); + } + else + { + s_bPreventClosing=true; // hack: prevents any other closing behavior to occur while the item is being executed + CloseSubMenus(CLOSE_POST,NULL); + s_bPreventClosing=false; + } + } + } + + if (type==ACTIVATE_MENU || type==ACTIVATE_MENU_BACKGROUND) + { + // when showing the context menu close all submenus + if (!(m_Options&CONTAINER_SEARCH)) + SetActiveWindow(); + if (s_MenuMode==MODE_NORMAL) + CloseSubMenus(0,this); + if (m_bTwoColumns && s_MenuMode==MODE_JUMPLIST && indexcommand && *item.pStdItem->command) || item.id==MENU_SEARCH_EXECUTE || item.bStartScreen || !pItemPidl1; // this is a special executable command + + if (type==ACTIVATE_EXECUTE && bCommand) + { + if (item.bStartScreen) + { + g_WSMHMonitor=MonitorFromWindow(m_hWnd,MONITOR_DEFAULTTONULL); + ::PostMessage(g_ProgWin,WM_SYSCOMMAND,SC_TASKLIST,'WSMH'); + return; + } + + if (bKeepOpen) + LockSetForegroundWindow(LSFW_LOCK); + else + { + LockSetForegroundWindow(LSFW_UNLOCK); + if (item.id!=MENU_SLEEP && item.id!=MENU_HIBERNATE) + FadeOutItem(index); + // flush all messages to close the menus + // m_hWnd is not valid after this point + MSG msg; + while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + PlayMenuSound(SOUND_COMMAND); + + // special handling for command items + TMenuID menuCommand=(item.id==MENU_SHUTDOWN_BUTTON)?s_ShutdownCommand:item.id; + + // translate command + switch (menuCommand) + { + case MENU_SEARCH_FILES: + if (!GetSettingString(L"SearchFilesCommand").IsEmpty()) + menuCommand=MENU_SEARCH_FILES_CUSTOM; + break; + case MENU_LOGOFF: // log off + if (GetSettingBool(L"ConfirmLogOff")) + menuCommand=MENU_LOGOFF_CONFIRM; + break; + case MENU_RESTART: + if (GetWinVersion()>=WIN_VER_WIN8 && bShift) + menuCommand=MENU_RESTART_ADVANCED; + else if (s_bHasUpdates && GetWinVersion()>=WIN_VER_WIN8) + menuCommand=MENU_RESTART_UPDATE; + else + menuCommand=MENU_RESTART_NOUPDATE; + break; + case MENU_SHUTDOWN: + if (s_bHasUpdates) + menuCommand=MENU_SHUTDOWN_UPDATE; + else if (GetWinVersion()>=WIN_VER_WIN8 && !bShift && GetSettingBool(L"HybridShutdown")) + menuCommand=MENU_SHUTDOWN_HYBRID; + else + menuCommand=MENU_SHUTDOWN_NOUPDATE; + break; + } + + switch (menuCommand) + { + case MENU_CLASSIC_SETTINGS: // show our settings +#ifdef PREVENT_CLOSING + EditSettings(true,0); +#else + EditSettings(false,0); +#endif + break; + case MENU_MORE_RESULTS: + g_SearchManager.LaunchExternalSearch(NULL,CSearchManager::CATEGORY_INVALID,searchText); + break; + case MENU_SEARCH_INTERNET: + g_SearchManager.LaunchInternetSearch(searchText); + break; + case MENU_SEARCH_EXECUTE: + ExecuteCommand(item.name,bShift && bCtrl,true); + break; + case MENU_SEARCH_FILES_CUSTOM: + ExecuteCommand(GetSettingString(L"SearchFilesCommand"),bShift && bCtrl,true); + break; + + default: + if (!ExecuteSysCommand(menuCommand) && item.pStdItem && item.pStdItem->command && *item.pStdItem->command) + { + wchar_t buf[1024]; + Strcpy(buf,_countof(buf),item.pStdItem->command); + DoEnvironmentSubst(buf,_countof(buf)); + if (!searchText.IsEmpty() && (wcswcs(buf,L"%1") || wcswcs(buf,L"%2"))) + DoSearchSubst(buf,_countof(buf),searchText); + ExecuteCommand(buf,bShift && bCtrl,false); + } + } + return; + } + + bool bHasMenu=false; + if (pItemPidl1) + bHasMenu=true; + else if (type==ACTIVATE_MENU && (item.id==MENU_EMPTY || item.id==MENU_EMPTY_TOP || item.id==MENU_SEARCH_CATEGORY)) + bHasMenu=true; + else if (type==ACTIVATE_MENU && item.id==MENU_APPS && (g_ItemManager.HasNewApps(true) || (pData && pData->bProgramsTree))) + bHasMenu=true; + if (!bHasMenu) + return; + + bool bUninstallPolicy=GetUninstallPolicy(); + + bool _bProtectedLink=false; + bool _bMetroApp=false; + bool _bExplicitAppId=false; + bool _bIsLink=false; + CString _path; + CItemManager::TLocation _location=CItemManager::LOCATION_UNKNOWN; + CString _appId; + if (item.pItemInfo && item.id!=MENU_APPS) + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + _bProtectedLink=item.pItemInfo->IsProtectedLink(); + _bMetroApp=item.pItemInfo->IsMetroApp(); + _path=item.pItemInfo->GetPath(); + _location=item.pItemInfo->GetLocation(); + _appId=item.pItemInfo->GetAppid(); + _bIsLink=item.pItemInfo->IsLink(); + _bExplicitAppId=item.pItemInfo->IsExplicitAppId(); + } + + // create a context menu for the selected item. the context menu can be shown (ACTIVATE_MENU) or its default + // item can be executed automatically (ACTIVATE_EXECUTE) + CComPtr pMenu; + HMENU menu=CreatePopupMenu(); + CComPtr pSecondaryMenu; + int secondaryCmd=CMD_LAST; + + CComPtr pItem; + int insertBefore=-1, insertSecondary=-1; + if (item.id==MENU_APPS) + { + insertBefore=0; + if (g_ItemManager.HasNewApps(true)) + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_MARKOLD,FindTranslation(L"Menu.RemoveHighlight",L"Remove highlight")); + else if (!pData || !pData->bProgramsTree) + return; + } + else if (item.id==MENU_EMPTY || item.id==MENU_EMPTY_TOP || item.id==MENU_SEARCH_CATEGORY || type==ACTIVATE_MENU_BACKGROUND) + { + insertBefore=0; + } + else + { + bool bQueryMenu=true; + if (item.jumpIndex>=0) + { + const CJumpItem &jumpItem=s_JumpList.groups[LOWORD(item.jumpIndex)].items[HIWORD(item.jumpIndex)]; + // only items or links with no arguments can have a context menu + bQueryMenu=((type==ACTIVATE_MENU || type==ACTIVATE_PROPERTIES) && (jumpItem.type==CJumpItem::TYPE_ITEM || (jumpItem.type==CJumpItem::TYPE_LINK && !jumpItem.bHasArguments)) && !_path.IsEmpty()); + } + if (bQueryMenu) + { + SHCreateItemFromIDList(pItemPidl1,IID_IShellItem,(void**)&pItem); + CComQIPtr pItem2=pItem; + if (pItem2 && + ((item.categoryHash&CSearchManager::CATEGORY_MASK)!=CSearchManager::CATEGORY_ITEM || + (GetSettingInt(L"CompatibilityFixes")&COMPATIBILITY_UPDATE_ITEMS))) // don't update search items because we don't have the right bind context for them + pItem2->Update(NULL); + if (!pItem || FAILED(pItem->BindToHandler(NULL,BHID_SFUIObject,IID_IContextMenu,(void**)&pMenu))) + { + DestroyMenu(menu); + return; + } + + UINT flags=CMF_DEFAULTONLY; + if (type==ACTIVATE_MENU) + { + flags=CMF_NORMAL|CMF_CANRENAME; + if (bShift) flags|=CMF_EXTENDEDVERBS; + } + if (type==ACTIVATE_DELETE || type==ACTIVATE_PROPERTIES) + flags=CMF_NORMAL; + if (type==ACTIVATE_RENAME) + flags=CMF_NORMAL|CMF_CANRENAME; + if (type==ACTIVATE_EXECUTE && bShift && bCtrl) + flags|=CMF_EXTENDEDVERBS; + HRESULT hr=pMenu->QueryContextMenu(menu,0,CMD_LAST,CMD_MAX,flags); + if (FAILED(hr)) + { + DestroyMenu(menu); + return; + } + secondaryCmd=CMD_LAST+LOWORD(hr)+10; + } + + if (item.bFolder && pItemPidl2) + { + // context menu for a double folder - remove most commands, add Open All Users + int n=GetMenuItemCount(menu); + for (int i=0;iCMD_MAX || FAILED(pMenu->GetCommandString(id-CMD_LAST,GCS_VERBA,NULL,command,_countof(command)))) + command[0]=0; + if (_stricmp(command,"open")==0) + { + if (GetSettingBool(L"EnableExplorer")) + { + if (!s_bNoCommonFolders) + InsertMenu(menu,i+1,MF_BYPOSITION|MF_STRING,CMD_OPEN_ALL,FindTranslation(L"Menu.OpenAll",L"O&pen All Users")); + InsertMenu(menu,i+2,MF_BYPOSITION|MF_SEPARATOR,0,0); + i+=2; + n+=2; + continue; + } + } + else if (_stricmp(command,"rename")==0 || _stricmp(command,"delete")==0) + { + if (item.id!=MENU_PROGRAMS) continue; + } + else if (_stricmp(command,"properties")==0) + { + insertBefore=i; + continue; + } + DeleteMenu(menu,i,MF_BYPOSITION); + i--; + n--; + } + } + else if (type==ACTIVATE_MENU && item.id==MENU_RECENT) + { + // context menu for a recent item - leave just open and runas + bool bHasUninstall=false; + int n=GetMenuItemCount(menu); + for (int i=0;iCMD_MAX || FAILED(pMenu->GetCommandString(id-CMD_LAST,GCS_VERBA,NULL,command,_countof(command)))) + command[0]=0; + if (_stricmp(command,"properties")==0) + { + insertBefore=i; + continue; + } + if (item.bMetroLink) + { + if (_stricmp(command,"pin_classic")==0 || _stricmp(command,"properties")==0) + continue; + } + else + { + if (bShift) + { + if (_stricmp(command,"delete")!=0 && _stricmp(command,"rename")!=0) + continue; + } + else + { + if (_stricmp(command,"open")==0 || _stricmp(command,"opencontaining")==0 || _stricmp(command,"runas")==0 || _stricmp(command,"runasuser")==0 + || _stricmp(command,"taskbarpin")==0 || _stricmp(command,"taskbarunpin")==0 || _stricmp(command,"pin_classic")==0 || _stricmp(command,"properties")==0) + continue; + if (_stricmp(command,"uninstall")==0) + { + bHasUninstall=true; + if (item.bMetroApp && bUninstallPolicy && !IsProtectedApp(_appId)) + continue; + } + } + } + DeleteMenu(menu,i,MF_BYPOSITION); + i--; + n--; + } + if (insertBefore==-1) + insertBefore=n; + + if (item.bMetroLink) + { + InsertMenu(menu,0,MF_BYPOSITION|MF_STRING,CMD_OPEN,FindTranslation(L"Menu.Open",L"&Open")); + SetMenuDefaultItem(menu,0,TRUE); + insertBefore++; + if (GetWinVersion()0) + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_SEPARATOR,0,0); + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_DELETEMRU,FindTranslation(L"Menu.RemoveList",L"Remove &from this list")); + if (s_RecentPrograms==RECENT_PROGRAMS_RECENT) + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_DELETEALL,FindTranslation(L"Menu.RemoveAll",L"C&lear recent items list")); + if (pItemPidl1 && GetSettingBool(L"EnableExplorer")) + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_EXPLORE,FindTranslation(L"Menu.Explore",L"&Explore")); + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_SEPARATOR,0,0); + } + else if (type==ACTIVATE_MENU && item.bMetroLink && (_bProtectedLink || (m_Options&(CONTAINER_APPS|CONTAINER_SEARCH)))) + { + // context menu for a Metro link - just open, properties and Explore + int n=GetMenuItemCount(menu); + for (int i=0;iCMD_MAX || FAILED(pMenu->GetCommandString(id-CMD_LAST,GCS_VERBA,NULL,command,_countof(command)))) + command[0]=0; + if (_stricmp(command,"properties")==0 || _stricmp(command,"pin_classic")==0) + { + insertBefore=i; + continue; + } + DeleteMenu(menu,i,MF_BYPOSITION); + i--; + n--; + } + InsertMenu(menu,0,MF_BYPOSITION|MF_STRING,CMD_OPEN,FindTranslation(L"Menu.Open",L"&Open")); + SetMenuDefaultItem(menu,0,TRUE); + insertBefore++; + if (GetWinVersion()m_OriginalCount))) + { + // context menu for a search item - remove delete, rename and link + int n=GetMenuItemCount(menu); + for (int i=0;iCMD_MAX || FAILED(pMenu->GetCommandString(id-CMD_LAST,GCS_VERBA,NULL,command,_countof(command)))) + command[0]=0; + if (_stricmp(command,"properties")==0) + { + insertBefore=i; + continue; + } + if (_stricmp(command,"delete")!=0 && _stricmp(command,"rename")!=0) + continue; + DeleteMenu(menu,i,MF_BYPOSITION); + i--; + n--; + } + bool last=insertBefore==-1; + if (last) + insertBefore=n; + + CSearchManager::TItemCategory cat=(CSearchManager::TItemCategory)(item.categoryHash&CSearchManager::CATEGORY_MASK); + if (pItemPidl1 && (cat<=CSearchManager::CATEGORY_FILE || cat==CSearchManager::CATEGORY_AUTOCOMPLETE)) + { + bool bExplore=GetSettingBool(L"EnableExplorer"); + bool bPin=!s_PinFolder.IsEmpty() && (cat==CSearchManager::CATEGORY_SETTING || cat==CSearchManager::CATEGORY_METROSETTING); + if (bExplore || bPin) + { + if (n>0) + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_SEPARATOR,0,0); + if (bPin) + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_PINSETTING,FindTranslation(L"Menu.PinStartCs",L"Pin to Start menu (Classic Shell)")); + if (bExplore) + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_EXPLORE,FindTranslation(L"Menu.Explore",L"&Explore")); + if (!last) + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_SEPARATOR,0,0); + } + } + } + else if (item.jumpIndex>=0) + { + // context menu for a jumplist item - just properties + int n=GetMenuItemCount(menu); + for (int i=0;iCMD_MAX || FAILED(pMenu->GetCommandString(id-CMD_LAST,GCS_VERBA,NULL,command,_countof(command)))) + command[0]=0; + if (_stricmp(command,"properties")==0) + continue; + DeleteMenu(menu,i,MF_BYPOSITION); + i--; + n--; + } + insertBefore=0; + const CJumpGroup &group=s_JumpList.groups[LOWORD(item.jumpIndex)]; + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_OPEN,FindTranslation(L"Menu.Open",L"&Open")); + SetMenuDefaultItem(menu,0,TRUE); + if (group.type!=CJumpGroup::TYPE_TASKS) + { + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_SEPARATOR,0,0); + if (group.type==CJumpGroup::TYPE_PINNED) + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_PIN,FindTranslation(L"JumpList.Unpin",L"&Unpin from this list")); + else + { + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_PIN,FindTranslation(L"JumpList.Pin",L"P&in to this list")); + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_DELETEMRU,FindTranslation(L"JumpList.Remove",L"Remove &from this list")); + } + if (n>0) + { + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_SEPARATOR,0,0); + if (GetSettingBool(L"EnableExplorer")) + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_EXPLORE,FindTranslation(L"Menu.Explore",L"&Explore")); + } + } + } + else + { + bool bHasUninstall=false; + int n=GetMenuItemCount(menu); + for (int i=0;iCMD_MAX || FAILED(pMenu->GetCommandString(id-CMD_LAST,GCS_VERBA,NULL,command,_countof(command)))) + command[0]=0; + if (_stricmp(command,"properties")==0) + { + insertBefore=i; + continue; + } + bool bDelete=false; + if (item.pStdItem && (_stricmp(command,"rename")==0 || _stricmp(command,"delete")==0)) + bDelete=true; + else if (item.bMetroLink && _stricmp(command,"rename")==0) + bDelete=true; + else if (_stricmp(command,"uninstall")==0) + { + bHasUninstall=true; + if ((!item.bMetroApp && !item.bMetroLink) || !bUninstallPolicy || IsProtectedApp(_appId)) + bDelete=true; + } + else if (item.bStartScreen) + { + if (_stricmp(command,"rename")==0 || _stricmp(command,"delete")==0) + EnableMenuItem(menu,i,MF_GRAYED|MF_BYPOSITION); + else if (_stricmp(command,"pin_classic")==0 && IsSettingLocked(L"StartScreenShortcut")) + EnableMenuItem(menu,i,MF_GRAYED|MF_BYPOSITION); + else if (_stricmp(command,"open")==0 || _stricmp(command,"opencontaining")==0 || _stricmp(command,"runas")==0) + bDelete=true; + } + if (bDelete) + { + DeleteMenu(menu,i,MF_BYPOSITION); + i--; + n--; + } + } + if (insertBefore==-1) + insertBefore=n; + if (item.bMetroLink) + { + InsertMenu(menu,0,MF_BYPOSITION|MF_STRING,CMD_OPEN,FindTranslation(L"Menu.Open",L"&Open")); + SetMenuDefaultItem(menu,0,TRUE); + insertBefore++; + if (GetWinVersion()=0) + { + pSecondaryMenu=GetMetroPinMenu(_appId); + if (pSecondaryMenu) + { + pSecondaryMenu->QueryContextMenu(menu,insertSecondary,secondaryCmd,CMD_MAX,CMF_NORMAL); + } + } + + s_HotPos=GetMessagePos(); + int res=0; + if (type==ACTIVATE_EXECUTE) + { + // just pick the default item + res=GetMenuDefaultItem(menu,FALSE,0); + if (bShift && bCtrl) + { + // find the runas verb if available + res=-1; + char command[256]; + int n=GetMenuItemCount(menu); + for (int i=0;i=CMD_LAST && id<=CMD_MAX && SUCCEEDED(pMenu->GetCommandString(id-CMD_LAST,GCS_VERBA,NULL,command,_countof(command)))) + { + if (_stricmp(command,"runas")==0) + { + res=id; + break; + } + } + } + if (res==-1) + { + CComString pName; + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName))) + { + ExecuteCommand(pName,true,false); + DestroyMenu(menu); + s_HotPos=GetMessagePos(); + return; + } + res=0; + } + } + if (res<0) res=0; + } + else if (type==ACTIVATE_RENAME || type==ACTIVATE_DELETE || type==ACTIVATE_PROPERTIES) + { + if ((type==ACTIVATE_RENAME || type==ACTIVATE_DELETE) && item.bStartScreen) + res=0; + else if (type==ACTIVATE_DELETE && item.id==MENU_RECENT) + res=CMD_DELETEMRU; + else if ((type==ACTIVATE_RENAME || type==ACTIVATE_DELETE) && item.bMetroLink && (_bProtectedLink || (m_Options&(CONTAINER_APPS|CONTAINER_SEARCH)))) + res=0; + else + { + const char *name; + switch (type) + { + case ACTIVATE_RENAME: name="rename"; break; + case ACTIVATE_DELETE: name="delete"; break; + case ACTIVATE_PROPERTIES: name="properties"; break; + } + char command[256]; + int n=GetMenuItemCount(menu); + for (int i=0;i=CMD_LAST && id<=CMD_MAX && SUCCEEDED(pMenu->GetCommandString(id-CMD_LAST,GCS_VERBA,NULL,command,_countof(command)))) + { + if (_stricmp(command,name)==0) + { + res=id; + break; + } + } + } + if (res<0) res=0; + } + } + else + { + if (!GetSettingBool(L"EnableExplorer")) + { + // disable the Open verb + char command[256]; + int n=GetMenuItemCount(menu); + for (int i=0;i=CMD_LAST && id<=CMD_MAX && SUCCEEDED(pMenu->GetCommandString(id-CMD_LAST,GCS_VERBA,NULL,command,_countof(command)))) + { + if ((item.bFolder && !item.bSplit && pItemPidl1 && _stricmp(command,"open")==0) || _stricmp(command,"opencontaining")==0) + { + EnableMenuItem(menu,i,MF_BYPOSITION|MF_GRAYED); + } + } + } + } + + // show the context menu + m_pMenu2=pMenu; + m_pMenu3=pMenu; + HBITMAP shellBmp=NULL; + HBITMAP newFolderBmp=NULL; + HBITMAP newShortcutBmp=NULL; + if ((item.id==MENU_NO || item.id==MENU_EMPTY || type==ACTIVATE_MENU_BACKGROUND || (item.id==MENU_APPS && pData && pData->bProgramsTree)) && item.jumpIndex<0 && index0) + { + if (GetSettingBool(L"CascadingMenu")) + { + menu2=CreatePopupMenu(); + subMenuIdx=insertBefore; + insertBefore=0; + } + } + bool bSort=false, bAutoSort=false, bNew=false, bMarkOld=false; + if (pData && pData->bProgramsTree) + { + bNew=!(item.pItemInfo && _location==CItemManager::LOCATION_METRO) && !pData->bApps && GetSettingBool(L"ShowNewFolder"); + bSort=true; + bAutoSort=pData->bAutoSort; + } + else + { + int n=0; + for (std::vector::const_iterator it=m_Items.begin();it!=m_Items.end();++it) + if (it->id==MENU_NO) + n++; + if (n>1) + bSort=true; // more than 1 movable items + wchar_t path[_MAX_PATH]; + if (!(m_Options&CONTAINER_APPS) && !(item.pItemInfo && _location==CItemManager::LOCATION_METRO) && !(m_Options&CONTAINER_NONEWFOLDER) && GetSettingBool(L"ShowNewFolder") && SHGetPathFromIDList(m_Path1[item.priority==2?1:0],path)) + bNew=true; + bAutoSort=(m_Options&CONTAINER_AUTOSORT)!=0; + } + bMarkOld=item.bNew && pItemPidl1; + + if (bSort) + InsertMenu(menu2,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_SORT,FindTranslation(L"Menu.SortByName",L"Sort &by Name")); + + if (m_FolderHash[0]) + InsertMenu(menu2,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_AUTOSORT,FindTranslation(L"Menu.AutoArrange",L"&Auto Arrange")); + if (bAutoSort) + { + EnableMenuItem(menu2,CMD_SORT,MF_BYCOMMAND|MF_GRAYED); + CheckMenuItem(menu2,CMD_AUTOSORT,MF_BYCOMMAND|MF_CHECKED); + } + if (bNew) + { + InsertMenu(menu2,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_NEWFOLDER,FindTranslation(L"Menu.NewFolder",L"New Folder")); + InsertMenu(menu2,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_NEWSHORTCUT,FindTranslation(L"Menu.NewShortcut",L"New Shortcut")); + } + if (bMarkOld) + InsertMenu(menu2,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_MARKOLD,FindTranslation(L"Menu.RemoveHighlight",L"Remove highlight")); + if (menu!=menu2 && GetMenuItemCount(menu2)==0) + { + DestroyMenu(menu2); + menu2=menu; + } + else + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_SEPARATOR,0,0); + + if (bNew || menu!=menu2) + { + int size=GetSystemMetrics(SM_CXSMICON); + if (bNew) + { + HMODULE hShell32=GetModuleHandle(L"shell32.dll"); + HICON hIcon=(HICON)LoadImage(hShell32,MAKEINTRESOURCE(319),IMAGE_ICON,size,size,LR_DEFAULTCOLOR); + if (hIcon) + { + newFolderBmp=BitmapFromIcon(hIcon,size,NULL,true); + MENUITEMINFO mii={sizeof(mii)}; + mii.fMask=MIIM_BITMAP; + mii.hbmpItem=newFolderBmp; + SetMenuItemInfo(menu2,CMD_NEWFOLDER,FALSE,&mii); + } + hIcon=(HICON)LoadImage(hShell32,MAKEINTRESOURCE(16769),IMAGE_ICON,size,size,LR_DEFAULTCOLOR); + if (hIcon) + { + newShortcutBmp=BitmapFromIcon(hIcon,size,NULL,true); + MENUITEMINFO mii={sizeof(mii)}; + mii.fMask=MIIM_BITMAP; + mii.hbmpItem=newShortcutBmp; + SetMenuItemInfo(menu2,CMD_NEWSHORTCUT,FALSE,&mii); + } + } + if (menu!=menu2) + { + InsertMenu(menu,subMenuIdx,MF_BYPOSITION|MF_POPUP,(UINT_PTR)menu2,FindTranslation(L"Menu.Organize",L"Organize Start menu")); + HICON hIcon=(HICON)LoadImage(g_Instance,MAKEINTRESOURCE(IDI_APPICON),IMAGE_ICON,size,size,LR_DEFAULTCOLOR); + if (hIcon) + { + shellBmp=BitmapFromIcon(hIcon,size,NULL,true); + MENUITEMINFO mii={sizeof(mii)}; + mii.fMask=MIIM_BITMAP; + mii.hbmpItem=shellBmp; + SetMenuItemInfo(menu,subMenuIdx,TRUE,&mii); + } + } + } + } + if (item.id==MENU_SEARCH_CATEGORY) + { + InsertMenu(menu,0,MF_BYPOSITION|MF_STRING,CMD_TOGGLE,item.categoryHash==m_SearchCategoryHash?FindTranslation(L"Menu.Collapse",L"Coll&apse"):FindTranslation(L"Menu.Expand",L"Exp&and")); + if (item.categoryHash>=CSearchManager::CATEGORY_FILE) + { + wchar_t text[256]; + Sprintf(text,_countof(text),L"%s\t(Ctrl+Enter)",FindTranslation(L"Menu.MoreResults",L"See more results")); + InsertMenu(menu,1,MF_BYPOSITION|MF_STRING,CMD_EXPLORE,text); + } + SetMenuDefaultItem(menu,(pData && pData->bArrow)?1:0,TRUE); + } + + if (item.id==MENU_PROGRAMS) + { + bool bNew; + if (s_bWin7Style && GetWinVersion()>=WIN_VER_WIN8 && GetSettingBool(L"AllProgramsMetro")) + bNew=g_ItemManager.HasNewPrograms(true) || g_ItemManager.HasNewApps(true); + else + bNew=g_ItemManager.HasNewPrograms(true); + if (bNew) + InsertMenu(menu,insertBefore++,MF_BYPOSITION|MF_STRING,CMD_MARKOLD,FindTranslation(L"Menu.RemoveHighlight",L"Remove highlight")); + } + if (pData && pData->bProgramsTree && item.bFolder && type==ACTIVATE_MENU) + { + InsertMenu(menu,0,MF_BYPOSITION|MF_STRING,CMD_TOGGLE,pData->bExpanded?FindTranslation(L"Menu.Collapse",L"Coll&apse"):FindTranslation(L"Menu.Expand",L"Exp&and")); + SetMenuDefaultItem(menu,0,TRUE); + InsertMenu(menu,1,MF_BYPOSITION|MF_SEPARATOR,0,0); + } + + // remove multiple separators + { + bool bSeparator=true; + int n=GetMenuItemCount(menu); + for (int i=0;i0 && bSeparator) + DeleteMenu(menu,n-1,MF_BYPOSITION); + } + + TPMPARAMS params={sizeof(params)}, *pParams=NULL; + POINT pt2; + if (pPt) + pt2=*pPt; + else + { + GetItemRect(index,params.rcExclude); + MapWindowPoints(NULL,¶ms.rcExclude); + pt2.x=params.rcExclude.left; + pt2.y=params.rcExclude.top; + pParams=¶ms; + } + SetContextItem(index); + InvalidateItem(index); + KillTimer(TIMER_HOVER); + res=0; + if (GetMenuItemCount(menu)>0) + { + LOG_MENU(LOG_EXECUTE,L"Open context menu, ptr=%p",this); + res=TrackPopupMenuEx(menu,TPM_RIGHTBUTTON|TPM_RETURNCMD|TPM_VERTICAL|(IsLanguageRTL()?TPM_LAYOUTRTL:0),pt2.x,pt2.y,m_hWnd,pParams); + LOG_MENU(LOG_EXECUTE,L"Select context menu, ptr=%p, index=%d",this,res); + } + SetContextItem(-1); + if (m_HotItem<0 && !m_bDestroyed) SetHotItem(index); + if (m_pMenu2) m_pMenu2.Release(); + if (m_pMenu3) m_pMenu3.Release(); + if (newFolderBmp) DeleteObject(newFolderBmp); + if (newShortcutBmp) DeleteObject(newShortcutBmp); + if (shellBmp) DeleteObject(shellBmp); + } + + ExitGuard guard; // no returns are allowed until the end cleanup + if (pData) pData->command=res; + + + if (type==ACTIVATE_EXECUTE) + { + if (bKeepOpen) + LockSetForegroundWindow(LSFW_LOCK); + else + { + LockSetForegroundWindow(LSFW_UNLOCK); + FadeOutItem(index); + } + PlayMenuSound(SOUND_COMMAND); + } + + if (res==CMD_PINSETTING) + { + CSearchManager::TItemCategory cat=(CSearchManager::TItemCategory)(item.categoryHash&CSearchManager::CATEGORY_MASK); + if (cat==CSearchManager::CATEGORY_SETTING) + CreatePinLink(pItemPidl1,item.name,NULL,0); + else if (cat==CSearchManager::CATEGORY_METROSETTING) + CreatePinLink(pItemPidl1,item.name,L"%windir%\\ImmersiveControlPanel\\systemsettings.exe",0); + m_bRefreshItems=true; + } + + // handle our standard commands + if (item.jumpIndex>=0 && res!=CMD_EXPLORE && resbProgramsTree) + { + m_pProgramsTree->OrderElements(pData->hTreeItem,TreeView_GetParent(m_pProgramsTree->m_hWnd,pData->hTreeItem),std::vector(),false,true); + } + else + { + std::vector items; + for (int i=0;i=WIN_VER_WIN8 && GetSettingBool(L"AllProgramsMetro")); + if (m_pProgramsTree) + m_pProgramsTree->ClearAllNew(); + } + else + g_ItemManager.RemoveNewItem(pItemPidl1,pItemPidl2,item.bFolder); + PostRefreshMessage(); + } + if (res==CMD_AUTOSORT) + { + if (pData && pData->bProgramsTree) + { + m_pProgramsTree->OrderElements(pData->hTreeItem,TreeView_GetParent(m_pProgramsTree->m_hWnd,pData->hTreeItem),std::vector(),!pData->bAutoSort,true); + } + else + { + if (m_FolderHash[0]) + { + CRegKey regOrder; + if (regOrder.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu\\Order")!=ERROR_SUCCESS) + regOrder.Create(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu\\Order"); + wchar_t name[100]; + Sprintf(name,_countof(name),L"%08X",m_FolderHash[0]); + if (m_Options&CONTAINER_AUTOSORT) + regOrder.SetBinaryValue(name,NULL,0); + else + { + DWORD cAuto='AUTO'; + regOrder.SetBinaryValue(name,&cAuto,4); + } + if (m_FolderHash[1]) + { + Sprintf(name,_countof(name),L"%08X",m_FolderHash[1]); + if (m_Options&CONTAINER_AUTOSORT) + regOrder.SetBinaryValue(name,NULL,0); + else + { + DWORD cAuto='AUTO'; + regOrder.SetBinaryValue(name,&cAuto,4); + } + } + } + PostRefreshMessage(); + } + res=0; + } + + if (res==CMD_NEWFOLDER) + { + g_RenameText=item.name; + if (pPt) + g_RenamePos=*pPt; + else + { + g_RenamePos.x=item.itemRect.left; + g_RenamePos.y=item.itemRect.top; + ClientToScreen(&g_RenamePos); + } + bool bAllPrograms=s_bAllPrograms; + for (std::vector::iterator it=s_Menus.begin();it!=s_Menus.end();++it) + (*it)->EnableWindow(FALSE); // disable all menus + if (bAllPrograms) ::EnableWindow(g_TopWin7Menu,FALSE); + + CComPtr pFolder; // have to use IShellFolder for renaming because it's the only one that supports changing the display name + if (pItemPidl1) + { + PCUITEMID_CHILD pidl; + SHBindToParent(pItemPidl1,IID_IShellFolder,(void**)&pFolder,&pidl); + } + else if (pData && pData->bProgramsTree) + { + CComPtr pDesktop; + if (SUCCEEDED(SHGetDesktopFolder(&pDesktop))) + pDesktop->BindToObject(pData->parent,NULL,IID_IShellFolder,(void**)&pFolder); + } + else + { + CComPtr pDesktop; + if (SUCCEEDED(SHGetDesktopFolder(&pDesktop))) + pDesktop->BindToObject(m_Path1[0],NULL,IID_IShellFolder,(void**)&pFolder); + } + + if (pFolder) + { + CComPtr pMenu2; + HMENU menu2=CreatePopupMenu(); + + std::vector items; + { + CComPtr pEnum; + if (pFolder->EnumObjects(NULL,SHCONTF_FOLDERS,&pEnum)!=S_OK) pEnum=NULL; + + PITEMID_CHILD child; + while (pEnum && pEnum->Next(1,&child,NULL)==S_OK) + { + STRRET str; + if (SUCCEEDED(pFolder->GetDisplayNameOf(child,SHGDN_INFOLDER|SHGDN_FORPARSING,&str))) + { + CComString pName; + StrRetToStr(&str,child,&pName); + items.push_back(CalcFNVHash(pName)); + } + ILFree(child); + } + } + + s_bPreventClosing=true; + if (SUCCEEDED(pFolder->CreateViewObject(g_OwnerWindow,IID_IContextMenu,(void**)&pMenu2))) + { + if (SUCCEEDED(pMenu2->QueryContextMenu(menu2,0,1,32767,CMF_NORMAL))) + { + CMINVOKECOMMANDINFOEX info={sizeof(info),CMIC_MASK_UNICODE}; + info.lpVerb="NewFolder"; + info.lpVerbW=L"NewFolder"; + info.nShow=SW_SHOWNORMAL; + info.fMask|=CMIC_MASK_NOASYNC; + info.hwnd=g_OwnerWindow; + pMenu2->InvokeCommand((CMINVOKECOMMANDINFO*)&info); + } + } + DestroyMenu(menu2); + HideTemp(false); + s_bPreventClosing=false; + + PITEMID_CHILD newPidl=NULL; + unsigned int newHash=0; + { + CComPtr pEnum; + if (pFolder->EnumObjects(NULL,SHCONTF_FOLDERS,&pEnum)!=S_OK) pEnum=NULL; + + PITEMID_CHILD child; + while (pEnum && pEnum->Next(1,&child,NULL)==S_OK) + { + STRRET str; + if (SUCCEEDED(pFolder->GetDisplayNameOf(child,SHGDN_INFOLDER|SHGDN_FORPARSING,&str))) + { + CComString pName; + StrRetToStr(&str,child,&pName); + unsigned int hash=CalcFNVHash(pName); + if (std::find(items.begin(),items.end(),hash)==items.end()) + { + if (SUCCEEDED(pFolder->GetDisplayNameOf(child,SHGDN_INFOLDER|SHGDN_FOREDITING,&str))) + { + CComString pName2; + StrRetToStr(&str,child,&pName2); + g_RenameText=pName2; + } + else + g_RenameText=pName; + pName.MakeUpper(); + newHash=CalcFNVHash(pName,item.priority==2?CalcFNVHash(L"\\"):FNV_HASH0); + newPidl=child; + break; + } + } + ILFree(child); + } + } + + if (!pData || !pData->bProgramsTree) + { + PostRefreshMessage(); + if (!m_bDestroyed) + PostMessage(MCM_SETCONTEXTITEM,newHash); + } + // show the Rename dialog box + s_bPreventClosing=true; + if (newPidl && DialogBox(g_Instance,MAKEINTRESOURCE(s_bRTL?IDD_RENAMER:IDD_RENAME),g_OwnerWindow,RenameDlgProc)) + { + PITEMID_CHILD newPidl2=NULL; + if (SUCCEEDED(pFolder->SetNameOf(g_OwnerWindow,newPidl,g_RenameText,SHGDN_INFOLDER,&newPidl2))) + { + ILFree(newPidl); + newPidl=newPidl2; + if (!pData || !pData->bProgramsTree) + { + PostRefreshMessage(); + StringUpper(g_RenameText); + newHash=CalcFNVHash(g_RenameText,item.priority==2?CalcFNVHash(L"\\"):FNV_HASH0); + if (!m_bDestroyed) + PostMessage(MCM_SETCONTEXTITEM,newHash); + } + } + } + if (newPidl && pData && pData->bProgramsTree) + { + CComPtr pNewItem; + if (SUCCEEDED(SHCreateItemWithParent(NULL,pFolder,newPidl,IID_IShellItem,(void**)&pNewItem))) + { + CAbsolutePidl newAbsPidl; + if (SUCCEEDED(SHGetIDListFromObject(pNewItem,&newAbsPidl))) + pData->pNewItemInfo=g_ItemManager.GetItemInfo(pNewItem,newAbsPidl,0); + } + } + if (newPidl) ILFree(newPidl); + for (std::vector::iterator it=s_Menus.begin();it!=s_Menus.end();++it) + if (!(*it)->m_bDestroyed) + (*it)->EnableWindow(TRUE); // enable all menus + if (bAllPrograms) ::EnableWindow(g_TopWin7Menu,TRUE); + if (!m_bDestroyed) + { + SetForegroundWindow(m_hWnd); + SetActiveWindow(); + if (pData && pData->bProgramsTree) + m_pProgramsTree->SetFocus(); + else + SetFocus(); + Invalidate(); + if (m_HotItem<0) SetHotItem(index); + } + HideTemp(false); + s_bPreventClosing=false; + } + SetContextItem(-1); + res=0; + } + + if (res==CMD_NEWSHORTCUT) + { + wchar_t target[_MAX_PATH+1]; + if (pData && pData->bProgramsTree) + SHGetPathFromIDList(pData->parent,target); + else + SHGetPathFromIDList(m_Path1[0],target); + target[Strlen(target)+1]=0; + wchar_t fname[_MAX_PATH+1]; + + // first try in the original folder + PathMakeUniqueName(fname,_countof(fname)-1,L"scut.lnk",L"New Shortcut.lnk",target); + HANDLE hFile=CreateFile(fname,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); + if (hFile!=INVALID_HANDLE_VALUE) + { + CloseHandle(hFile); + + // just run the shortcut wizard + wchar_t cmdLine[1024]; + Sprintf(cmdLine,_countof(cmdLine),L"rundll32.exe appwiz.cpl,NewLinkHere %s",fname); + + STARTUPINFO startupInfo={sizeof(startupInfo)}; + PROCESS_INFORMATION processInfo; + memset(&processInfo,0,sizeof(processInfo)); + wchar_t exe[_MAX_PATH]=L"%windir%\\system32\\rundll32.exe"; + DoEnvironmentSubst(exe,_countof(exe)); + if (CreateProcess(exe,cmdLine,NULL,NULL,FALSE,0,NULL,target,&startupInfo,&processInfo)) + { + CloseHandle(processInfo.hThread); + CloseHandle(processInfo.hProcess); + } + } + else if (GetLastError()==ERROR_ACCESS_DENIED) + { + // there was a problem, most likely UAC didn't let us create a folder + + // create a temp folder just for us + wchar_t temp[_MAX_PATH]; + GetTempPath(_countof(temp),temp); + Strcat(temp,_countof(temp),L"ClassicShell"); + CreateDirectory(temp,NULL); + + // make a unique link file and keep a handle to the file + PathMakeUniqueName(fname,_countof(fname)-1,L"scut.lnk",L"New Shortcut.lnk",temp); + + HANDLE hFile=CreateFile(fname,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); + if (hFile!=INVALID_HANDLE_VALUE) + { + CloseHandle(hFile); + // wait for the wizard to finish in a separate thread and close the menu + // otherwise it appears behind the menu + ShortcutParams *pParams=new ShortcutParams; + memcpy(pParams->target,target,sizeof(target)); + memcpy(pParams->temp,temp,sizeof(temp)); + memcpy(pParams->fname,fname,sizeof(fname)); + CreateThread(NULL,0,NewShortcutThread,pParams,0,NULL); + } + } + res=0; + } + + if (res==CMD_DELETEMRU && item.id==MENU_RECENT && s_RecentPrograms!=RECENT_PROGRAMS_NONE) + { + if (s_RecentPrograms==RECENT_PROGRAMS_RECENT) + { + CComString pName; + if (_bMetroApp) + DeleteMRUAppId(_appId); + else if (SUCCEEDED(pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName))) + DeleteMRUShortcut(pName); + } + else if (s_RecentPrograms==RECENT_PROGRAMS_FREQUENT) + { + RemoveMFUShortcut(item.mfuHash,_bMetroApp); + } + PostRefreshMessage(); + res=0; + } + if (res==CMD_DELETEALL && item.id==MENU_RECENT && s_RecentPrograms==RECENT_PROGRAMS_RECENT) + { + DeleteMRUShortcut(NULL); + PostRefreshMessage(); + res=0; + } + + if (res==CMD_EXPLORE) + { + if (item.id==MENU_SEARCH_CATEGORY) + { + for (std::list::const_iterator it=s_SearchResults.indexed.begin();it!=s_SearchResults.indexed.end();++it) + { + if (item.categoryHash==it->categoryHash) + { + FadeOutItem(index); + PlayMenuSound(SOUND_COMMAND); + g_SearchManager.LaunchExternalSearch(it->search,it->categoryHash,searchText); + break; + } + } + } + else + { + SHOpenFolderAndSelectItems(pItemPidl1,0,NULL,0); + } + res=0; + } + + if (res==CMD_UNINSTALL) + { + UninstallMetroApp(g_OwnerWindow,item.name,_appId); + res=0; + } + + if (item.id==MENU_SEARCH_CATEGORY && res==CMD_TOGGLE) + { + m_SearchCategoryHash=(m_SearchCategoryHash==item.categoryHash)?CSearchManager::CATEGORY_INVALID:item.categoryHash; + RefreshSearch(); + res=0; + } + + // handle the shell commands + if (res>=CMD_LAST) + { + // handle special verbs + char command[256]; + if (FAILED(pMenu->GetCommandString(res-CMD_LAST,GCS_VERBA,NULL,command,_countof(command)))) + command[0]=0; + if (_stricmp(command,"rename")==0) + { + // show the Rename dialog box + CComPtr pFolder; // have to use IShellFolder for renaming because it's the only one that supports changing the display name + PCUITEMID_CHILD pidl; + s_bPreventClosing=true; + STRRET str; + if (SUCCEEDED(SHBindToParent(pItemPidl1,IID_IShellFolder,(void**)&pFolder,&pidl)) && SUCCEEDED(pFolder->GetDisplayNameOf(pidl,SHGDN_FOREDITING,&str))) + { + CComString pName; + StrRetToStr(&str,pidl,&pName); + g_RenameText=pName; + } + else + g_RenameText=item.name; + if (pPt) + g_RenamePos=*pPt; + else + { + g_RenamePos.x=item.itemRect.left; + g_RenamePos.y=item.itemRect.top; + ClientToScreen(&g_RenamePos); + } + for (std::vector::iterator it=s_Menus.begin();it!=s_Menus.end();++it) + (*it)->EnableWindow(FALSE); // disable all menus + bool bAllPrograms=s_bAllPrograms; + if (bAllPrograms) ::EnableWindow(g_TopWin7Menu,FALSE); + + SetContextItem(index); + InvalidateItem(index); + bool bRenamed=DialogBox(g_Instance,MAKEINTRESOURCE(s_bRTL?IDD_RENAMER:IDD_RENAME),g_OwnerWindow,RenameDlgProc)!=0; + SetContextItem(-1); + if (m_HotItem<0) SetHotItem(index); + + if (bRenamed) + { + if (GetWinVersion()>=WIN_VER_WIN8) + { + SetForegroundWindow(m_hWnd); + SetActiveWindow(); + if (pData && pData->bProgramsTree) + m_pProgramsTree->SetFocus(); + else + SetFocus(); + } + // perform the rename operation + PITEMID_CHILD newPidl; + if (SUCCEEDED(pFolder->SetNameOf(g_OwnerWindow,pidl,g_RenameText,SHGDN_INFOLDER,&newPidl))) + { + STRRET str; + if (SUCCEEDED(pFolder->GetDisplayNameOf(newPidl,SHGDN_INFOLDER|SHGDN_FORPARSING,&str))) + { + CComString pName; + StrRetToStr(&str,newPidl,&pName); + pName.MakeUpper(); + m_Items[index].name=g_RenameText; + m_Items[index].nameHash=CalcFNVHash(pName); + + if (!(m_Options&CONTAINER_AUTOSORT) && (!pData || !pData->bProgramsTree)) + { + std::vector items; + for (int i=0;iGetDisplayNameOf(newPidl,SHGDN_FORPARSING,&str))) + { + CComString pPath; + StrRetToStr(&str,newPidl,&pPath); + CComPtr pLink; + pLink.CoCreateInstance(CLSID_ShellLink); + CComQIPtr pFile=pLink; + if (pFile && SUCCEEDED(pFile->Load(pPath,STGM_READWRITE))) + { + CComQIPtr pStore=pLink; + if (pStore) + { + PROPVARIANT val; + InitPropVariantFromString(_appId,&val); + if (SUCCEEDED(pStore->SetValue(PKEY_AppUserModel_ID,val)) && SUCCEEDED(pStore->Commit())) + pFile->Save(pPath,TRUE); + PropVariantClear(&val); + } + } + } + + if (pData) + { + CComPtr pNewItem; + if (SUCCEEDED(SHCreateItemWithParent(NULL,pFolder,newPidl,IID_IShellItem,(void**)&pNewItem))) + { + CAbsolutePidl newAbsPidl; + if (SUCCEEDED(SHGetIDListFromObject(pNewItem,&newAbsPidl))) + pData->pNewItemInfo=g_ItemManager.GetItemInfo(pNewItem,newAbsPidl,0); + } + } + } + ILFree(newPidl); + } + if (!pData || !pData->bProgramsTree) + PostRefreshMessage(); + } + for (std::vector::iterator it=s_Menus.begin();it!=s_Menus.end();++it) + if (!(*it)->m_bDestroyed) + (*it)->EnableWindow(TRUE); // enable all menus + if (bAllPrograms) ::EnableWindow(g_TopWin7Menu,TRUE); + if (!m_bDestroyed) + { + SetForegroundWindow(m_hWnd); + SetActiveWindow(); + if (pData && pData->bProgramsTree) + m_pProgramsTree->SetFocus(); + else + SetFocus(); + } + HideTemp(false); + s_bPreventClosing=false; + s_HotPos=GetMessagePos(); + res=CMD_RENAME; + } + else if (_stricmp(command,"uninstall")==0 && _bMetroApp && !_appId.IsEmpty()) + { + UninstallMetroApp(g_OwnerWindow,item.name,_appId); + } + else + { + bool bRefreshMain=_stricmp(command,"pin_classic")==0; + bool bRefresh=(_stricmp(command,"delete")==0 || _stricmp(command,"link")==0); + + if (item.bStartScreen && _stricmp(command,"pin_classic")==0) + { + { + CSettingsLockWrite lock; + CSetting *pSetting=FindSetting(L"StartScreenShortcut"); + if (!pSetting->IsLocked()) + { + pSetting->value=CComVariant(0); + pSetting->flags&=~CSetting::FLAG_DEFAULT; + } + } + SaveSettings(); + } + + IContextMenu *pInvokeMenu=pMenu; + int verbOffset=CMD_LAST; + if (pSecondaryMenu && res>=secondaryCmd) + { + pInvokeMenu=pSecondaryMenu; + verbOffset=secondaryCmd; + } + CMINVOKECOMMANDINFOEX info={sizeof(info),CMIC_MASK_UNICODE|CMIC_MASK_FLAG_LOG_USAGE}; + info.lpVerb=MAKEINTRESOURCEA(res-verbOffset); + info.lpVerbW=MAKEINTRESOURCEW(res-verbOffset); + info.nShow=SW_SHOWNORMAL; + wchar_t dir[_MAX_PATH]; + if (SHGetPathFromIDList(pItemPidl1,dir)) + { + PathRemoveFileSpec(dir); + if (GetFileAttributes(dir)!=INVALID_FILE_ATTRIBUTES) + info.lpDirectoryW=dir; + } + if (pPt) + { + info.fMask|=CMIC_MASK_PTINVOKE; + info.ptInvoke=*pPt; + } + if (type==ACTIVATE_MENU) + { + if (bCtrl) info.fMask|=CMIC_MASK_CONTROL_DOWN; + if (bShift) info.fMask|=CMIC_MASK_SHIFT_DOWN; + } + + if (bRefresh || bRefreshMain) + info.fMask|=CMIC_MASK_NOASYNC; // wait for delete/link commands to finish so we can refresh the menu + + if ((type!=ACTIVATE_MENU && type!=ACTIVATE_DELETE) || GetWinVersion()::iterator it=s_Menus.begin();it!=s_Menus.end();++it) + (*it)->EnableWindow(FALSE); // disable all menus + bool bAllPrograms=s_bAllPrograms; + if (bAllPrograms) ::EnableWindow(g_TopWin7Menu,FALSE); + info.hwnd=g_OwnerWindow; + + RECT rc; + GetWindowRect(&rc); + ::SetForegroundWindow(g_OwnerWindow); + ::SetWindowPos(g_OwnerWindow,HWND_TOPMOST,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,0); + LOG_MENU(LOG_EXECUTE,L"Invoke command, ptr=%p, command='%S'",this,command); + HRESULT hr=pInvokeMenu->InvokeCommand((LPCMINVOKECOMMANDINFO)&info); + LOG_MENU(LOG_EXECUTE,L"Invoke command, ptr=%p, res=%d",this,hr); + if (type==ACTIVATE_EXECUTE && SUCCEEDED(hr)) + { + if (bTrackRecent) + { + if (_bMetroApp) + AddMRUAppId(_appId); + else if (_path.IsEmpty()) + { + CComString pName; + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName))) + AddMRUShortcut(pName); + } + else + AddMRUShortcut(_path); + } + g_ItemManager.RemoveNewItem(pItemPidl1,NULL,false); + if (!(m_Options&CONTAINER_LINK)) + { + // update item ranks + CComString pName; + if (_bMetroApp) + { + CString APPID=_appId; + APPID.MakeUpper(); + g_SearchManager.AddItemRank(CalcFNVHash(APPID)); + } + else if (SUCCEEDED(pItem->GetDisplayName(SIGDN_PARENTRELATIVEPARSING,&pName))) // can't use item.name because the extension may be removed + { + pName.MakeUpper(); + g_SearchManager.AddItemRank(CalcFNVHash(pName)); + } + } + } + for (std::vector::iterator it=s_Menus.begin();it!=s_Menus.end();++it) + if (!(*it)->m_bDestroyed) + (*it)->EnableWindow(TRUE); // enable all menus + if (bAllPrograms) ::EnableWindow(g_TopWin7Menu,TRUE); + if (bRefreshMain && m_bSubMenu) + { + CMenuContainer *pMain=s_Menus[0]; + if (!pMain->m_bSubMenu && !pMain->m_bDestroyed) + { + SetForegroundWindow(pMain->m_hWnd); + pMain->SetActiveWindow(); + pMain->SetFocus(); + CloseSubMenus(CLOSE_POST,pMain); + pMain->PostRefreshMessage(); + } + } + else if ((bRefresh || bKeepOpen || bRefreshMain) && !m_bDestroyed) + { + SetForegroundWindow(m_hWnd); + SetActiveWindow(); + if (m_Options&CONTAINER_SEARCH) + { + m_pParent->m_SearchBox.SetFocus(); + SetWindowPos(HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); + } + else if (pData && pData->bProgramsTree) + m_pProgramsTree->SetFocus(); + else + SetFocus(); + } + HideTemp(false); + s_bPreventClosing=false; + + if (!bKeepOpen && !bRefresh && !bRefreshMain) + { + HWND active=GetActiveWindow(); + if (active!=m_hWnd && active!=g_OwnerWindow) + { + // if after all the window is not active, then another application was launched - close all menus + CloseSubMenus(CLOSE_POST,NULL); + if (g_TopWin7Menu && s_bAllPrograms) ::PostMessage(g_TopWin7Menu,WM_CLOSE,0,0); + } + } + if (_stricmp(command,"delete")==0) + res=CMD_DELETE; + + if ((bRefresh && (!pData || !pData->bProgramsTree)) || (bRefreshMain && !m_bSubMenu)) + { + if (bRefreshMain && !m_bSubMenu && (s_MenuMode==MODE_SEARCH || s_MenuMode==MODE_JUMPLIST)) + m_bRefreshItems=true; + else + PostRefreshMessage(); // refresh the menu after an item was deleted or created + } + } + } + DestroyMenu(menu); + s_HotPos=GetMessagePos(); + if (pData && res) pData->command=res; + LOG_MENU(LOG_EXECUTE,L"Exit activate, ptr=%p",this); + guard.Disarm(); +} + +void CMenuContainer::ActivateTreeItem( const void *treeItem, RECT &itemRect, TActivateType type, const POINT *pPt, ActivateData *pData ) +{ + AddRef(); // prevent the menu from being deleted while processing the operation + Assert(pData && pData->bProgramsTree); + const CProgramsTree::CTreeItem *pTreeItem=(CProgramsTree::CTreeItem*)treeItem; + MenuItem &item=m_Items[m_ProgramTreeIndex]; + item.id=MENU_NO; + if (pTreeItem->bApps) + item.id=MENU_APPS; + else if (pTreeItem->bEmpty) + item.id=MENU_EMPTY; + item.name=pTreeItem->name; + item.pItemInfo=pTreeItem->pItemInfo1; + RECT rc=item.itemRect; + item.itemRect=itemRect; + item.pItem1=pTreeItem->pItemInfo1?(PIDLIST_ABSOLUTE)pTreeItem->pItemInfo1->GetPidl():NULL; + item.pItem2=pTreeItem->pItemInfo2?(PIDLIST_ABSOLUTE)pTreeItem->pItemInfo2->GetPidl():NULL; + item.bFolder=pTreeItem->bFolder; + item.bMetroLink=false; + item.bMetroApp=false; + item.bNew=pTreeItem->bNew; + if (pTreeItem->pItemInfo1) + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + item.bMetroLink=pTreeItem->pItemInfo1->IsMetroLink(); + item.bMetroApp=pTreeItem->pItemInfo1->IsMetroApp(); + } + pData->bApps=pTreeItem->bApps; + ActivateItem(m_ProgramTreeIndex,type,pPt,pData); + item.id=MENU_PROGRAMS_TREE; + item.itemRect=rc; + item.name.Empty(); + item.pItemInfo=NULL; + item.pItem1=NULL; + item.pItem2=NULL; + Release(); +} + +void CMenuContainer::DragTreeItem( const void *treeItem, bool bApp ) +{ + const CProgramsTree::CTreeItem *pTreeItem=(CProgramsTree::CTreeItem*)treeItem; + MenuItem &item=m_Items[m_ProgramTreeIndex]; + item.id=MENU_NO; + item.name=pTreeItem->name; + item.pItemInfo=pTreeItem->pItemInfo1; + item.pItem1=pTreeItem->pItemInfo1->GetPidl(); + item.pItem2=pTreeItem->pItemInfo2?(PIDLIST_ABSOLUTE)pTreeItem->pItemInfo2->GetPidl():NULL; + item.bFolder=pTreeItem->bFolder; + item.bMetroLink=false; + item.bMetroApp=false; + if (pTreeItem->pItemInfo1) + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + item.bMetroLink=pTreeItem->pItemInfo1->IsMetroLink(); + item.bMetroApp=pTreeItem->pItemInfo1->IsMetroApp(); + } + DragOut(m_ProgramTreeIndex,bApp); + item.id=MENU_PROGRAMS_TREE; + item.name.Empty(); + item.pItemInfo=NULL; + item.pItem1=NULL; + item.pItem2=NULL; +} + +void CMenuContainer::RunUserCommand( bool bPicture ) +{ + CString command=GetSettingString(bPicture?L"UserPictureCommand":L"UserNameCommand"); + if (!command.IsEmpty()) + ExecuteCommand(command,false,true); +} + +static DWORD WINAPI FaderThreadProc( void *param ) +{ + ((CMenuFader*)param)->Create(); + MSG msg; + while (GetMessage(&msg,NULL,0,0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return 0; +} + +void CMenuContainer::FadeOutItem( int index ) +{ + int speed=GetSettingInt(L"MenuFadeSpeed"); + if (speed<=0) return; + + RECT rc; + + HBITMAP bmp=NULL; + HRGN region=NULL; + if (index==m_ProgramTreeIndex) + { + HWND tree=m_pProgramsTree->m_hWnd; + HTREEITEM hItem=TreeView_GetSelection(tree); + TreeView_GetItemRect(tree,hItem,&rc,FALSE); + + BITMAPINFO dib={sizeof(dib)}; + dib.bmiHeader.biWidth=rc.right-rc.left; + dib.bmiHeader.biHeight=rc.top-rc.bottom; + dib.bmiHeader.biPlanes=1; + dib.bmiHeader.biBitCount=32; + dib.bmiHeader.biCompression=BI_RGB; + + HDC hdc=CreateCompatibleDC(NULL); + if (s_bRTL) SetLayout(hdc,LAYOUT_RTL); + unsigned int *bits; + bmp=CreateDIBSection(hdc,&dib,DIB_RGB_COLORS,(void**)&bits,NULL,0); + HGDIOBJ bmp0=SelectObject(hdc,bmp); + SetViewportOrgEx(hdc,-rc.left,-rc.top,NULL); + m_pProgramsTree->SendMessage(WM_PRINTCLIENT,(WPARAM)hdc,PRF_CLIENT); + SelectObject(hdc,bmp0); + DeleteDC(hdc); + m_pProgramsTree->MapWindowPoints(NULL,&rc); + } + else + { + GetItemRect(index,rc); + BITMAPINFO dib={sizeof(dib)}; + dib.bmiHeader.biWidth=rc.right-rc.left; + dib.bmiHeader.biHeight=rc.top-rc.bottom; + dib.bmiHeader.biPlanes=1; + dib.bmiHeader.biBitCount=32; + dib.bmiHeader.biCompression=BI_RGB; + + HDC hdc=CreateCompatibleDC(NULL); + if (s_bRTL) SetLayout(hdc,LAYOUT_RTL); + unsigned int *bits; + bmp=CreateDIBSection(hdc,&dib,DIB_RGB_COLORS,(void**)&bits,NULL,0); + HGDIOBJ bmp0=SelectObject(hdc,bmp); + SetViewportOrgEx(hdc,-rc.left,-rc.top,NULL); + + // create a region from the opaque pixels of the selection bitmap + MenuSkin::TItemDrawType drawType=m_Items[index].drawType; + if (drawType==MenuSkin::COLUMN1_NEW) + drawType=MenuSkin::COLUMN1_ITEM; + else if (drawType==MenuSkin::COLUMN2_NEW) + drawType=MenuSkin::COLUMN2_ITEM; + else if (drawType==MenuSkin::SUBMENU_NEW) + drawType=MenuSkin::SUBMENU_ITEM; + const MenuSkin::ItemDrawSettings &settings=s_Skin.ItemSettings[drawType]; + if (settings.bmpSelection.GetBitmap() && settings.bmpSelection.bIs32) + { + HDC hdc2=CreateCompatibleDC(hdc); + SetLayout(hdc2,0); + HGDIOBJ bmp02=SelectObject(hdc2,settings.bmpSelection.GetBitmap()); + FillRect(hdc,&rc,(HBRUSH)GetStockObject(WHITE_BRUSH)); + RECT rSrc={0,0,settings.selSlicesX[0]+settings.selSlicesX[1]+settings.selSlicesX[2],settings.selSlicesY[0]+settings.selSlicesY[1]+settings.selSlicesY[2]}; + RECT rMargins={settings.selSlicesX[0],settings.selSlicesY[0],settings.selSlicesX[2],settings.selSlicesY[2]}; + if (m_Items[index].id==MENU_SHUTDOWN_BUTTON) + { + rSrc.right+=settings.selSlicesX[3]+settings.selSlicesX[4]+settings.selSlicesX[5]; + rMargins.right=settings.selSlicesX[5]; + } + int w=dib.bmiHeader.biWidth; + int h=-dib.bmiHeader.biHeight; + if (rMargins.left>w) rMargins.left=w; + if (rMargins.right>w) rMargins.right=w; + if (rMargins.top>h) rMargins.top=h; + if (rMargins.bottom>h) rMargins.bottom=h; + MarginsBlit(hdc2,hdc,rSrc,rc,rMargins,false); + SelectObject(hdc2,bmp02); + DeleteDC(hdc2); + SelectObject(hdc,bmp0); + + for (int y=0;y>24)>=32) + { + if (minx==-1) minx=x; // first non-transparent pixel + if (maxx=0) + { + maxx++; + HRGN r=CreateRectRgn(minx,y,maxx,y+1); + AddTrackedObject(r); + if (!region) + region=r; + else + { + CombineRgn(region,region,r,RGN_OR); + DeleteObject(r); + } + } + } + + SelectObject(hdc,bmp); + } + + DrawBackground(hdc,rc); + + SelectObject(hdc,bmp0); + DeleteDC(hdc); + MapWindowPoints(NULL,&rc); + } + + if (bmp) + { + CMenuFader *pFader=new CMenuFader(bmp,region,speed,rc); + CreateThread(NULL,0,FaderThreadProc,pFader,0,NULL); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +CMenuFader::CMenuFader( HBITMAP bmp, HRGN region, int duration, RECT &rect ) +{ + m_Bitmap=bmp; + m_Region=region; + m_Duration=duration; + m_Rect=rect; + s_Faders.push_back(this); +} + +CMenuFader::~CMenuFader( void ) +{ + if (m_Bitmap) DeleteObject(m_Bitmap); + if (m_Region) DeleteObject(m_Region); + s_Faders.erase(std::find(s_Faders.begin(),s_Faders.end(),this)); +} + +void CMenuFader::Create( void ) +{ + bool bRtl=false; + if (m_Rect.left>m_Rect.right) + { + bRtl=true; + int q=m_Rect.left; m_Rect.left=m_Rect.right; m_Rect.right=q; + } + CWindowImpl::Create(NULL,&m_Rect,NULL,WS_POPUP,WS_EX_TOOLWINDOW|WS_EX_TOPMOST|WS_EX_LAYERED|(bRtl?WS_EX_LAYOUTRTL:0)); + ShowWindow(SW_SHOWNOACTIVATE); + if (m_Region) + { + SetWindowRgn(m_Region); + m_Region=NULL; + } + SetTimer(1,20); + m_Time0=0; + m_LastTime=0; + PostMessage(WM_TIMER,0,0); + SetLayeredWindowAttributes(m_hWnd,0,255,LWA_ALPHA); +} + +LRESULT CMenuFader::OnEraseBkgnd( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + RECT rc; + GetClientRect(&rc); + HDC hdc=(HDC)wParam; + + // draw the background + HDC hdc2=CreateCompatibleDC(hdc); + HGDIOBJ bmp0=SelectObject(hdc2,m_Bitmap); + BitBlt(hdc,0,0,rc.right,rc.bottom,hdc2,0,0,SRCCOPY); + SelectObject(hdc2,bmp0); + DeleteDC(hdc2); + return 1; +} + +LRESULT CMenuFader::OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_Time0==0) + m_Time0=GetMessageTime(); + int t=GetMessageTime()-m_Time0; + const int MAX_DELTA=80; // allow at most 80ms between redraws. if more, slow down time + if (t>MAX_DELTA+m_LastTime) + { + m_Time0+=t-MAX_DELTA-m_LastTime; + t=MAX_DELTA+m_LastTime; + } + m_LastTime=t; + if (tSendMessage(WM_CLOSE); +} diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MenuContainer.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MenuContainer.cpp new file mode 100644 index 0000000..fb3b92d --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MenuContainer.cpp @@ -0,0 +1,9137 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// MenuContainer.cpp - contains the main logic of CMenuContainer + +#include "stdafx.h" +#include "MenuContainer.h" +#include "Accessibility.h" +#include "ClassicStartMenuDLL.h" +#include "ClassicStartButton.h" +#include "Settings.h" +#include "Translations.h" +#include "CustomMenu.h" +#include "LogManager.h" +#include "FNVHash.h" +#include "ResourceHelper.h" +#include "SettingsUIHelper.h" +#include "DownloadHelper.h" +#include "SettingsUI.h" +#include "MetroLinkManager.h" +#include "ProgramsTree.h" +#include "dllmain.h" +#include "resource.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define SECURITY_WIN32 +#include +#include +#include + +struct StdMenuOption +{ + TMenuID id; + int options; +}; + +// Options for special menu items +enum +{ + MENU_NONE = 0, + MENU_ENABLED = 1, // the item shows in the menu + MENU_EXPANDED = 2, // the item is expanded +}; + +static StdMenuOption g_StdOptions[]= +{ + {MENU_COMPUTER,MENU_NONE}, // MENU_ENABLED|MENU_EXPANDED from settings + {MENU_FAVORITES,MENU_NONE}, // MENU_ENABLED|MENU_EXPANDED from settings, check policy + {MENU_DOCUMENTS,MENU_NONE}, // MENU_ENABLED|MENU_EXPANDED from settings, check policy + {MENU_HELP,MENU_ENABLED}, // check policy + {MENU_RUN,MENU_ENABLED}, // check policy + {MENU_LOGOFF,MENU_ENABLED}, // MENU_ENABLED from settings, check policy + {MENU_RESTART,MENU_ENABLED}, // MENU_ENABLED + {MENU_RESTART_NOUPDATE,MENU_ENABLED}, // only available when there are updates + {MENU_DISCONNECT,MENU_NONE}, // MENU_ENABLED if in a remote session, check policy + {MENU_SHUTDOWN_BOX,MENU_ENABLED}, // MENU_NONE if in a remote session, check policy + {MENU_SHUTDOWN_BUTTON,MENU_ENABLED|MENU_EXPANDED}, // MENU_ENABLED|MENU_EXPANDED from the settings + {MENU_SHUTDOWN,MENU_ENABLED}, // MENU_NONE if in a remote session, check policy + {MENU_SHUTDOWN_NOUPDATE,MENU_ENABLED}, // only available when there are updates + {MENU_UNDOCK,MENU_ENABLED}, // from settings, check policy + {MENU_CONTROLPANEL,MENU_ENABLED|MENU_EXPANDED}, // MENU_EXPANDED from settings, check policy + {MENU_NETWORK,MENU_ENABLED}, // MENU_EXPANDED from settings, check policy + {MENU_SECURITY,MENU_ENABLED}, // MENU_ENABLED if in a remote session + {MENU_PRINTERS,MENU_ENABLED}, // MENU_EXPANDED from settings, check policy + {MENU_TASKBAR,MENU_ENABLED}, // check policy + {MENU_FEATURES,MENU_ENABLED}, // no setting (prevents the Programs and Features from expanding), check policy (for control panel) + {MENU_CLASSIC_SETTINGS,MENU_ENABLED}, // MENU_ENABLED from ini file + {MENU_SEARCH,MENU_ENABLED}, // check policy + {MENU_SEARCH_BOX,MENU_NONE}, // check settings + {MENU_SEARCH_PRINTER,MENU_NONE}, // MENU_ENABLED if Active Directory is available + {MENU_SEARCH_COMPUTERS,MENU_NONE}, // MENU_ENABLED if Active Directory is available, check policy + {MENU_SEARCH_PEOPLE,MENU_NONE}, // MENU_ENABLED if %ProgramFiles%\Windows Mail\wab.exe exists + {MENU_USERFILES,MENU_ENABLED}, // check policy + {MENU_USERDOCUMENTS,MENU_ENABLED}, // check policy + {MENU_USERPICTURES,MENU_ENABLED}, // check policy + {MENU_SLEEP,MENU_ENABLED}, // check power caps + {MENU_HIBERNATE,MENU_ENABLED}, // check power caps + {MENU_SWITCHUSER,MENU_ENABLED}, // check group policy + {MENU_APPS,MENU_ENABLED}, // enable on Win8+ + {MENU_PCSETTINGS,MENU_ENABLED}, // enable on Win8+ +}; + +static CLSID CLSID_FrameworkInputPane={0xD5120AA3,0x46BA,0x44C5,{0x82,0x2D,0xCA,0x80,0x92,0xC1,0xFC,0x72}}; + +/////////////////////////////////////////////////////////////////////////////// + +void CUserWindow::Init( CMenuContainer *pOwner ) +{ + const MenuSkin &skin=CMenuContainer::s_Skin; + m_pOwner=pOwner; + m_Size=skin.User_bitmapSize; + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=m_Size.cx; + bi.bmiHeader.biHeight=m_Size.cy; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + HDC hdc=CreateCompatibleDC(NULL); + m_Bitmap=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&m_Bits,NULL,0); + DeleteDC(hdc); + memset(m_Bits,0,m_Size.cx*m_Size.cy*4); + m_Source.resize(m_Size.cx*m_Size.cy*2); + m_bUserBitmapMask=(skin.User_mask.bIsBitmap && skin.User_mask.bIs32 && skin.User_maskSize.cx==skin.User_image_size && skin.User_maskSize.cy==skin.User_image_size); + if (m_bUserBitmapMask) + m_UserBitmap=CMenuContainer::LoadUserImage(skin.User_image_size,skin.User_mask.GetBitmap()); + else + m_UserBitmap=CMenuContainer::LoadUserImage(skin.User_image_size,NULL); + m_TimerBitmap=(HBITMAP)1; + SetImage(NULL,false); +} + +void CUserWindow::StartImageTimer( HBITMAP bmp ) +{ + if (m_TimerBitmap==bmp) return; + m_TimerBitmap=bmp; + DWORD time; + SystemParametersInfo(SPI_GETMOUSEHOVERTIME,NULL,&time,0); + SetTimer(TIMER_SET,time); +} + +void CUserWindow::SetImage( HBITMAP bmp, bool bAnimate ) +{ + m_bDefaultImage=!bmp; + EnableWindow(m_bDefaultImage); + int size=m_Size.cx*m_Size.cy; + memcpy(&m_Source[0],m_Bits,size*4); + + HDC hdst=CreateCompatibleDC(NULL); + RECT rc={0,0,m_Size.cx,m_Size.cy}; + HGDIOBJ bmp0=SelectObject(hdst,m_Bitmap); + FillRect(hdst,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH)); + HDC hsrc=CreateCompatibleDC(NULL); + HGDIOBJ bmp01=GetCurrentObject(hsrc,OBJ_BITMAP); + int iconSize=bmp?CItemManager::EXTRA_LARGE_ICON_SIZE:CMenuContainer::s_Skin.User_image_size; + if (bmp) + { + SelectObject(hsrc,bmp); + BitBlt(hdst,(m_Size.cx-iconSize)/2,(m_Size.cy-iconSize)/2,iconSize,iconSize,hsrc,0,0,SRCCOPY); + } + else + { + if (m_UserBitmap) + { + SelectObject(hsrc,m_UserBitmap); + BitBlt(hdst,CMenuContainer::s_Skin.User_image_offset.x,CMenuContainer::s_Skin.User_image_offset.y,iconSize,iconSize,hsrc,0,0,SRCCOPY); + } + if (CMenuContainer::s_Skin.User_bitmap.GetBitmap()) + { + SelectObject(hsrc,CMenuContainer::s_Skin.User_bitmap.GetBitmap()); + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + AlphaBlend(hdst,0,0,m_Size.cx,m_Size.cy,hsrc,0,0,m_Size.cx,m_Size.cy,func); + } + } + SelectObject(hsrc,bmp01); + DeleteDC(hsrc); + SelectObject(hdst,bmp0); + DeleteDC(hdst); + + memcpy(&m_Source[size],m_Bits,size*4); + if (!bmp && !m_bUserBitmapMask) + { + int dx=CMenuContainer::s_Skin.User_image_offset.x; + int dy=m_Size.cy-CMenuContainer::s_Skin.User_image_offset.y-1; + for (int y=0;yleft) + { + int dx=pClipRect->left-pos.x; + pos.x+=dx; + size.cx-=dx; + srcPos.x+=dx; + } + if (pos.x+size.cx>pClipRect->right) + size.cx=pClipRect->right-pos.x; + + if (pos.ytop) + { + int dy=pClipRect->top-pos.y; + pos.y+=dy; + size.cy-=dy; + srcPos.y+=dy; + } + if (pos.y+size.cy>pClipRect->bottom) + size.cy=pClipRect->bottom-pos.y; + } + if (size.cx<0) size.cx=0; + if (size.cy<0) size.cy=0; + + HDC hSrc=CreateCompatibleDC(NULL); + HGDIOBJ bmp0=SelectObject(hSrc,m_Bitmap); + UpdateLayeredWindow(m_hWnd,NULL,&pos,&size,hSrc,&srcPos,0,&func,ULW_ALPHA); + SelectObject(hSrc,bmp0); + DeleteDC(hSrc); +} + +LRESULT CUserWindow::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_Bitmap) DeleteObject(m_Bitmap); + m_Bitmap=NULL; + if (m_UserBitmap) DeleteObject(m_UserBitmap); + m_UserBitmap=NULL; + return 0; +} + +LRESULT CUserWindow::OnLButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_bDefaultImage) + m_pOwner->RunUserCommand(true); + return 0; +} + +LRESULT CUserWindow::OnSetCursor( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_bDefaultImage) + SetCursor(LoadCursor(NULL,IDC_HAND)); + else + bHandled=FALSE; + return TRUE; +} + +LRESULT CUserWindow::OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + const int BLEND_STEP=5; + if (wParam==TIMER_BLEND) + { + m_Timer+=BLEND_STEP; + if (m_Timer>100) m_Timer=100; + + // blend the two images + int n=m_Size.cx*m_Size.cy; + for (int i=0;i>24); + int r1=(pixel1>>16)&255; + int g1=(pixel1>>8)&255; + int b1=(pixel1)&255; + int a2=(pixel2>>24); + int r2=(pixel2>>16)&255; + int g2=(pixel2>>8)&255; + int b2=(pixel2)&255; + int a=a1+(a2-a1)*m_Timer/100; + int r=r1+(r2-r1)*m_Timer/100; + int g=g1+(g2-g1)*m_Timer/100; + int b=b1+(b2-b1)*m_Timer/100; + m_Bits[i]=(a<<24)|(r<<16)|(g<<8)|b; + } + + Update(); + if (m_Timer==100) + KillTimer(TIMER_BLEND); + } + if (wParam==TIMER_SET) + { + SetImage(m_TimerBitmap,true); + m_TimerBitmap=(HBITMAP)1; + KillTimer(TIMER_SET); + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +int CMenuContainer::s_MaxRecentDocuments=15; +int CMenuContainer::s_ScrollMenus=0; +bool CMenuContainer::s_bRTL=false; +bool CMenuContainer::s_bKeyboardCues=false; +bool CMenuContainer::s_bOverrideFirstDown=false; +bool CMenuContainer::s_bExpandRight=true; +TRecentPrograms CMenuContainer::s_RecentPrograms=RECENT_PROGRAMS_NONE; +bool CMenuContainer::s_bBehindTaskbar=true; +bool CMenuContainer::s_bShowTopEmpty=false; +bool CMenuContainer::s_bNoDragDrop=false; +bool CMenuContainer::s_bNoContextMenu=false; +bool CMenuContainer::s_bExpandLinks=false; +bool CMenuContainer::s_bLogicalSort=false; +bool CMenuContainer::s_bExtensionSort=false; +bool CMenuContainer::s_bAllPrograms=false; +bool CMenuContainer::s_bNoCommonFolders=false; +bool CMenuContainer::s_bNoRun=false; +bool CMenuContainer::s_bNoClose=false; +bool CMenuContainer::s_bHasTouch=false; +char CMenuContainer::s_bActiveDirectory=-1; +bool CMenuContainer::s_bPreventClosing=false; +bool CMenuContainer::s_bDragClosed=false; +bool CMenuContainer::s_bTempHidden=false; +bool CMenuContainer::s_bDisableHover=false; +bool CMenuContainer::s_bHasUpdates=false; +CMenuContainer *CMenuContainer::s_pDragSource=NULL; +bool CMenuContainer::s_bDragFromTree; +bool CMenuContainer::s_bDragMovable; +bool CMenuContainer::s_bRightDrag; +bool CMenuContainer::s_bLockWorkArea; +bool CMenuContainer::s_bPendingSearchEnter; +std::vector CMenuContainer::s_Menus; +volatile HWND CMenuContainer::s_FirstMenu, CMenuContainer::s_SearchMenu; +CSearchManager::SearchResults CMenuContainer::s_SearchResults; +std::map CMenuContainer::s_MenuScrolls; +CString CMenuContainer::s_MRUShortcuts[MRU_PROGRAMS_COUNT]; +bool CMenuContainer::s_bMRULoaded=false; +const CItemManager::ItemInfo *CMenuContainer::s_JumpAppInfo; +CJumpList CMenuContainer::s_JumpList; +int CMenuContainer::s_TaskBarId; +HWND CMenuContainer::s_TaskBar, CMenuContainer::s_StartButton; +UINT CMenuContainer::s_TaskBarEdge; +RECT CMenuContainer::s_StartRect; +HWND CMenuContainer::s_LastFGWindow; +HTHEME CMenuContainer::s_Theme; +HTHEME CMenuContainer::s_PagerTheme; +CWindow CMenuContainer::s_Tooltip; +CWindow CMenuContainer::s_TooltipBalloon; +int CMenuContainer::s_TipShowTime; +int CMenuContainer::s_TipHideTime; +int CMenuContainer::s_TipShowTimeFolder; +int CMenuContainer::s_TipHideTimeFolder; +DWORD CMenuContainer::s_HotPos; +int CMenuContainer::s_HotItem; +CMenuContainer *CMenuContainer::s_pHotMenu; +int CMenuContainer::s_TipItem; +CMenuContainer *CMenuContainer::s_pTipMenu; +RECT CMenuContainer::s_MenuLimits; +RECT CMenuContainer::s_MainMenuLimits; +DWORD CMenuContainer::s_TaskbarState; +DWORD CMenuContainer::s_HoverTime; +DWORD CMenuContainer::s_SplitHoverTime; +DWORD CMenuContainer::s_ProgramsHoverTime; +DWORD CMenuContainer::s_XMouse; +DWORD CMenuContainer::s_SubmenuStyle; +CLIPFORMAT CMenuContainer::s_ShellFormat; +CLIPFORMAT CMenuContainer::s_ShellUrlFormat; +CLIPFORMAT CMenuContainer::s_DescriptorFormat; +CLIPFORMAT CMenuContainer::s_ContentsFormat; +CLIPFORMAT CMenuContainer::s_MetroLinkFormat; +CLIPFORMAT CMenuContainer::s_PreferredEffectFormat; +CLIPFORMAT CMenuContainer::s_DropDescriptionFormat; +MenuSkin CMenuContainer::s_Skin; +CMenuContainer::StartMenuParams CMenuContainer::s_StartMenuParams; +UINT CMenuContainer::s_StartMenuMsg; +std::vector CMenuFader::s_Faders; +bool CMenuContainer::s_bWin7Style; +CMenuContainer::TMenuMode CMenuContainer::s_MenuMode; +CMenuContainer::TMenuMode CMenuContainer::s_PreSearchMenuMode; +TMenuID CMenuContainer::s_ShutdownCommand; +int CMenuContainer::s_MenuHeight; +int CMenuContainer::s_MenuMaxHeight[2]; +int CMenuContainer::s_MenuWidthNormal; +int CMenuContainer::s_MenuWidthJump; +int CMenuContainer::s_MenuWidthMax; +int CMenuContainer::s_BackgroundW1, CMenuContainer::s_BackgroundW2, CMenuContainer::s_BackgroundH1, CMenuContainer::s_BackgroundH2; +CMenuContainer::OldMenuState CMenuContainer::s_OldMenuState; +CUserWindow CMenuContainer::s_UserPicture; +RECT CMenuContainer::s_UserPictureRect; +int CMenuContainer::s_ProgramsScrollPos; +HBITMAP CMenuContainer::s_ArrowsBitmap; +unsigned int CMenuContainer::s_LastArrowColor; +char CMenuContainer::s_HasMoreResults; +int CMenuContainer::s_ProgramsWidth, CMenuContainer::s_JumplistWidth; +CComPtr CMenuContainer::s_pFrameworkInputPane; +CString CMenuContainer::s_PinFolder; + +LRESULT CALLBACK CMenuContainer::SubclassSearchBox( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + CMenuContainer *pParent=(CMenuContainer*)uIdSubclass; + CWindow box(hWnd); + if (uMsg==WM_PAINT && !pParent->m_bNoSearchDraw) + { + // use buffered paint to allow the edit box to appear on a glass background + pParent->m_bNoSearchDraw=true; + + PAINTSTRUCT ps; + HDC hdc=box.BeginPaint(&ps); + + BP_PAINTPARAMS paintParams={sizeof(paintParams)}; + HDC hdcPaint=NULL; + HPAINTBUFFER hBufferedPaint=BeginBufferedPaint(hdc,&ps.rcPaint,BPBF_TOPDOWNDIB,&paintParams,&hdcPaint); + if (hdcPaint) + { + SendMessage(hWnd,WM_PRINTCLIENT,(WPARAM)hdcPaint,PRF_CLIENT); + BufferedPaintSetAlpha(hBufferedPaint,&ps.rcPaint,255); + EndBufferedPaint(hBufferedPaint,TRUE); + } + box.EndPaint(&ps); + + pParent->m_bSearchDrawn=true; + pParent->m_bNoSearchDraw=false; + return 0; + } + if (uMsg==WM_PRINTCLIENT) + { + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + HDC hdc=(HDC)wParam; + if ((lParam&PRF_CLIENT) && ::GetWindowTextLength(hWnd)==0 && ((GetSettingInt(L"SearchBox")==SEARCHBOX_NORMAL && GetSettingBool(L"SearchSelect")) || GetFocus()!=hWnd) && pParent->m_SearchIndex>=0) + { + RECT rc; + ::SendMessage(hWnd,EM_GETRECT,0,(LPARAM)&rc); + if (s_bRTL) + rc.right-=3; + else + rc.left+=3; + HGDIOBJ font0=SelectObject(hdc,s_Skin.Search_hint_font); + SetBkColor(hdc,GetSysColor(COLOR_WINDOW)); + SetBkMode(hdc,TRANSPARENT); + SetTextColor(hdc,s_Skin.Search_text_colors[1]); + DrawText(hdc,pParent->m_Items[pParent->m_SearchIndex].name,-1,&rc,DT_SINGLELINE|DT_EDITCONTROL|(s_bRTL?DT_RIGHT:DT_LEFT)); + SelectObject(hdc,font0); + } + return res; + } + if (uMsg==WM_KEYDOWN) + { + if (wParam==VK_TAB) + { + s_bPendingSearchEnter=false; + // forward Tabs to the parent + return pParent->SendMessage(uMsg,wParam,lParam); + } + if (wParam==VK_UP || wParam==VK_DOWN) + { + s_bPendingSearchEnter=false; + // forward up/down keys + CMenuContainer *pSearchMenu=s_Menus[s_Menus.size()-1]; + if (pSearchMenu->m_Options&CONTAINER_SEARCH) + return pSearchMenu->SendMessage(uMsg,wParam,lParam); // forward to the search menu + else + return pParent->SendMessage(uMsg,wParam,lParam); // forward to the parent + } + if (wParam==VK_PRIOR || wParam==VK_NEXT) + { + s_bPendingSearchEnter=false; + // forward page keys + CMenuContainer *pSearchMenu=s_Menus[s_Menus.size()-1]; + if (pSearchMenu->m_Options&CONTAINER_SEARCH) + return pSearchMenu->SendMessage(uMsg,wParam,lParam); // forward to the search menu + else + return pParent->SendMessage(uMsg,wParam,lParam); // forward to the parent + } + if (wParam==VK_LEFT || wParam==VK_RIGHT) + { + // forward left/right keys + if (::GetWindowTextLength(hWnd)==0) + return pParent->SendMessage(uMsg,wParam,lParam); // forward to the parent + } + if (wParam==VK_RETURN) + { + // forward Enter to the submenu, or execute the current string + CMenuContainer *pSearchMenu=s_Menus[s_Menus.size()-1]; + bool bShift=GetKeyState(VK_SHIFT)<0; + bool bCtrl=GetKeyState(VK_CONTROL)<0; + if ((pSearchMenu->m_Options&CONTAINER_SEARCH) || (!pSearchMenu->m_bSubMenu && s_MenuMode==MODE_SEARCH)) + { + if (pSearchMenu->m_HotItem>=0 && pSearchMenu->m_HotItem<(int)pSearchMenu->m_Items.size() && + pSearchMenu->m_Items[pSearchMenu->m_HotItem].id!=MENU_EMPTY && pSearchMenu->m_Items[pSearchMenu->m_HotItem].id!=MENU_SEARCH_EMPTY) + { + pSearchMenu->SendMessage(WM_KEYDOWN,VK_RETURN); + } + else if (!s_bNoRun && (!s_SearchResults.bSearching || s_SearchResults.bResults)) + { + CString command; + CWindow(hWnd).GetWindowText(command); + if (!command.IsEmpty()) + pSearchMenu->ExecuteCommand(command,bShift && bCtrl,true); + } + else if (s_SearchResults.bSearching && !s_SearchResults.bResults) + { + s_bPendingSearchEnter=true; + } + } + return 0; + } + if (wParam==VK_ESCAPE) + { + s_bPendingSearchEnter=false; + // forward Esc to the parent or clear the string + if (box.GetWindowTextLength()==0) + pParent->PostMessage(WM_KEYDOWN,VK_ESCAPE); + else + box.SetWindowText(L""); + return 0; + } + if (wParam==VK_BACK && GetKeyState(VK_CONTROL)<0) + { + wchar_t text[1024]; + ::GetWindowText(hWnd,text,_countof(text)); + int len=Strlen(text); + int pos=(int)::SendMessage(hWnd,EM_GETSEL,0,0); + if (LOWORD(pos)==HIWORD(pos)) + { + pos=LOWORD(pos); + if (pos>len) pos=len; + int start=0; + for (int i=0;i0 && (text[i-1]==' ' || text[i-1]=='\\') && text[i]!=text[i-1]) + start=i; + } + pos=MAKELONG(start,pos); + } + int start=LOWORD(pos); + int end=HIWORD(pos); + if (start>len) start=len; + if (end>len) end=len; + memmove(text+start,text+end,(len-end+1)*2); + ::SetWindowText(hWnd,text); + ::SendMessage(hWnd,EM_SETSEL,start,start); + return 0; + } + } + if (uMsg==WM_SYSCHAR) + { + CMenuContainer *pSearchMenu=s_Menus[s_Menus.size()-1]; + if (pSearchMenu->m_Options&CONTAINER_SEARCH) + { + if (!pSearchMenu->SendMessage(WM_CHAR,wParam,lParam)) + return 0; + } + pParent->SendMessage(WM_CHAR,wParam,lParam); + } + if (uMsg==WM_SYSKEYDOWN) + { + if (s_bWin7Style) + { + pParent->SendMessage(WM_SYSKEYDOWN,wParam,lParam); + if (wParam==VK_MENU) + pParent->ShowKeyboardCues(); + } + else + { + CMenuContainer *pSearchMenu=s_Menus[s_Menus.size()-1]; + if (pSearchMenu->m_Options&CONTAINER_SEARCH) + pSearchMenu->SendMessage(WM_SYSKEYDOWN,wParam,lParam); + } + } + if (uMsg==WM_CHAR && (wParam==VK_RETURN || wParam==10 || wParam==VK_ESCAPE || wParam==VK_TAB || wParam==127)) + { + // prevent a beep when Enter, Esc or Tab is pressed + return 0; + } + if (uMsg==WM_MOUSEACTIVATE) + { + pParent->ActivateItem(pParent->m_SearchIndex,ACTIVATE_SELECT,NULL); + s_bDisableHover=!s_bWin7Style; + // close all sub-menus + CloseSubMenus(CLOSE_SKIP_SEARCH,pParent); + ::SetFocus(hWnd); + if (s_bBehindTaskbar && s_TaskBar) + pParent->SetWindowPos(s_TaskBar,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE); + return MA_NOACTIVATE; + } + if (uMsg==WM_SETFOCUS) + { + pParent->SetSearchState(::GetWindowTextLength(hWnd)>0?SEARCH_TEXT:SEARCH_BLANK); + } + if (uMsg==WM_KILLFOCUS) + { + s_bPendingSearchEnter=false; + if (!s_bPreventClosing) + { +#ifndef PREVENT_CLOSING + box.SetWindowText(L""); + pParent->SetSearchState(SEARCH_NONE); +#endif + } + } + if (uMsg==WM_CONTEXTMENU && (lParam&0xFFFFFFFF)==0xFFFFFFFF) + { + if (s_bWin7Style) + return pParent->SendMessage(WM_CONTEXTMENU,wParam,lParam); + else + { + CMenuContainer *pSearchMenu=s_Menus[s_Menus.size()-1]; + if (pSearchMenu->m_Options&CONTAINER_SEARCH) + return pSearchMenu->SendMessage(WM_CONTEXTMENU,wParam,lParam); + } + } + if (uMsg==WM_MOUSEWHEEL) + { + if (s_bWin7Style) + return pParent->SendMessage(WM_MOUSEWHEEL,wParam,lParam); + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +LRESULT CALLBACK CMenuContainer::SubclassScrollbar( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + CMenuContainer *pParent=(CMenuContainer*)uIdSubclass; + if (!pParent->m_ScrollTheme) + { + return DefSubclassProc(hWnd,uMsg,wParam,lParam); + } + DWORD oldThread=g_CustomScrollbarThread; + g_CustomScrollbarThread=GetCurrentThreadId(); + g_CustomScrollbarTheme=pParent->m_ScrollTheme; + LRESULT res=DefSubclassProc(hWnd,uMsg,wParam,lParam); + g_CustomScrollbarThread=oldThread; + if (!oldThread) + g_CustomScrollbarTheme=NULL; + return res; +} + +int CMenuContainer::CompareMenuString( const wchar_t *str1, const wchar_t *str2 ) +{ + if (s_bExtensionSort) + { + const wchar_t *ext1=PathFindExtension(str1); + const wchar_t *ext2=PathFindExtension(str2); + int cmp=CompareString(LOCALE_USER_DEFAULT,LINGUISTIC_IGNORECASE,ext1,-1,ext2,-1)-CSTR_EQUAL; + if (cmp) return cmp; + } + if (s_bLogicalSort) + return StrCmpLogicalW(str1,str2); + else + return CompareString(LOCALE_USER_DEFAULT,LINGUISTIC_IGNORECASE,str1,-1,str2,-1)-CSTR_EQUAL; +} + +CMenuContainer::CMenuContainer( CMenuContainer *pParent, int index, int options, const StdMenuItem *pStdItem, PIDLIST_ABSOLUTE path1, PIDLIST_ABSOLUTE path2 ) +{ + m_RefCount=1; + m_bSubMenu=(index>=0); // this may be true even if pParent is NULL (in case you want to show only sub-menus somewhere, use index=0 and pParent=NULL) + m_HoverItem=m_ContextItem=m_HotItem=m_InsertMark=-1; + m_DragHoverItem=m_DragIndex=-1; + m_ClickIndex=GetKeyState(VK_LBUTTON)<0?-2:-1; + m_bHoverArrow=m_bClickArrow=false; + m_pParent=pParent; + m_ParentIndex=pParent?index:-1; + m_Options=options; + m_pStdItem=pStdItem; + m_Bitmap=NULL; + m_BitmapOffset=0; + m_Region=NULL; + m_PaintOffset.x=m_PaintOffset.y=0; + m_Path1[0].Clone(path1); + if (!s_bNoCommonFolders) + m_Path2[0].Clone(path2); + + if (options&CONTAINER_ALLPROGRAMS) + { + ShGetKnownFolderIDList(FOLDERID_Programs,&m_Path1[1]); + if (!s_bNoCommonFolders) + ShGetKnownFolderIDList(FOLDERID_CommonPrograms,&m_Path2[1]); + } + + Assert(path1 || !path2); + + m_FolderHash[0]=m_FolderHash[1]=0; + if (m_Options&CONTAINER_APPS) + m_FolderHash[0]=CalcFNVHash(L"apps"); + + InitializeSpecialFolders(); + + m_bDestroyed=false; + s_Menus.push_back(this); + m_Submenu=-1; + m_SubJumpItem=-1; + m_bTrackMouse=false; + m_RefreshPosted=0; + + m_SubShowTime=0; + m_bInsertAfter=false; + m_bHotArrow=false; + + m_DragHoverTime=0; + + m_MaxWidth=0; + m_bTwoColumns=false; + memset(&m_rMenu,0,sizeof(m_rMenu)); + memset(&m_rContent,0,sizeof(m_rContent)); + memset(&m_rContent2,0,sizeof(m_rContent2)); + memset(&m_rUser1,0,sizeof(m_rUser1)); + memset(&m_rUser2,0,sizeof(m_rUser2)); + memset(&m_rPadding,0,sizeof(m_rPadding)); + + m_ExtraTop=m_ExtraBottom=m_ExtraBorder=0; + m_MouseWheel=0; + m_ScrollCount=m_ScrollHeight=m_ScrollOffset=m_ScrollButtonSize=0; + m_bScrollUp=m_bScrollDown=m_bScrollUpHot=m_bScrollDownHot=false; + m_SearchIndex=-1; + m_SearchItemCount=0; + m_SearchProvidersCount=0; + m_bScrollTimerMouse=false; + m_bScrollTimerTouch=false; + m_bNoSearchDraw=false; + m_bSearchDrawn=false; + m_bInSearchUpdate=false; + m_bDisableProgHover=false; + m_bClosing=false; + m_bRefreshItems=false; + m_bWorkAreaPosted=false; + m_SearchIcons=NULL; + m_SearchState=SEARCH_NONE; + m_SearchCategoryHash=CSearchManager::CATEGORY_INVALID; + m_pProgramsTree=NULL; + m_ProgramButtonIndex=m_ProgramTreeIndex=-1; + m_OriginalCount=0; + m_OriginalScrollCount=-1; + m_SearchScrollCount=m_SearchScrollHeight=m_SearchScrollPos=0; + m_SearchHash=0; + m_pDropTargetInfo=NULL; + m_DropTargetIndex=-1; + m_PanPosY=m_Overpan=m_PointerId=0; + m_InputCookie=0; + m_ScrollTheme=NULL; + + CoCreateInstance(CLSID_DragDropHelper,NULL,CLSCTX_INPROC_SERVER,IID_IDropTargetHelper,(void**)&m_pDropTargetHelper); + m_pDragSourceHelper=CComQIPtr(m_pDropTargetHelper); + LOG_MENU(LOG_OPEN,L"Open Menu, ptr=%p, index=%d, options=%08X",this,index,options); +} + +CMenuContainer::~CMenuContainer( void ) +{ + ClearItems(m_Items.begin(),m_Items.end()); + if (std::find(s_Menus.begin(),s_Menus.end(),m_pParent)!=s_Menus.end()) // check if the parent is still alive + { + if (m_pParent->m_Submenu==m_ParentIndex) + { + if (!m_pParent->m_bDestroyed) + { + m_pParent->InvalidateItem(m_ParentIndex); + if (m_pParent->m_HotItem<0 && !(m_Options&CONTAINER_SEARCH) && (!m_pParent->m_pProgramsTree || !m_pParent->m_pProgramsTree->m_hWnd || m_pParent->m_pProgramsTree->m_hWnd!=GetFocus())) + m_pParent->SetHotItem(m_ParentIndex); + } + m_pParent->SetSubmenu(-1); + } + } + if (m_Bitmap) DeleteObject(m_Bitmap); + if (m_Region) DeleteObject(m_Region); + + // must be here and not in OnDestroy because during drag/drop a menu can close while still processing messages + s_Menus.erase(std::find(s_Menus.begin(),s_Menus.end(),this)); + if (m_SearchIcons) + DeleteObject(m_SearchIcons); + if (m_pProgramsTree) m_pProgramsTree->Release(); + + if (s_pFrameworkInputPane && m_InputCookie) + s_pFrameworkInputPane->Unadvise(m_InputCookie); +} + +void CMenuContainer::AddFirstFolder( IShellItem *pFolder, std::vector &items, int options ) +{ + CAbsolutePidl ignore; + if (!m_pParent || (m_Options&CONTAINER_ALLPROGRAMS)) + { + // remove the Programs subfolder from the main menu. it will be added separately + ShGetKnownFolderIDList(FOLDERID_Programs,&ignore); + } + + CShellItemEnumerator enumerator(pFolder); + if (!enumerator.IsValid()) return; + + CComPtr pChild; + CAbsolutePidl childPidl; + int refreshFlags=CItemManager::INFO_SMALL_ICON; + if (!m_bSubMenu) + { + if (s_Skin.Main_icon_size==MenuSkin::ICON_SIZE_LARGE) + refreshFlags=CItemManager::INFO_LARGE_ICON; + else if (s_Skin.Main_icon_size==MenuSkin::ICON_SIZE_NONE) + refreshFlags=0; + } + if (options&CONTAINER_PROGRAMS) + refreshFlags|=CItemManager::INFO_LINK|CItemManager::INFO_METRO; + if (options&CONTAINER_NOPATH) + refreshFlags|=CItemManager::INFO_NO_PATH; + while (enumerator.GetNext(pChild,childPidl)) + { + SFGAOF flags=0; + HRESULT hrFlags=pChild->GetAttributes(SFGAO_FOLDER|SFGAO_STREAM|SFGAO_LINK|SFGAO_HIDDEN,&flags); + if (FAILED(hrFlags)) // check if the item is a folder, archive or a link + flags=0; + if (flags&SFGAO_HIDDEN) + continue; + CComString pName; + if (SUCCEEDED(pChild->GetDisplayName(SIGDN_PARENTRELATIVEPARSING,&pName))) + { + LOG_MENU(LOG_OPEN,L"%s, 0x%08X, 0x%08X",pName,flags,hrFlags); + MenuItem item(MENU_NO); + if (ignore && ILIsEqual(childPidl,ignore)) + continue; + item.pItemInfo=g_ItemManager.GetItemInfo(pChild,childPidl,refreshFlags); + bool bLibrary=_wcsicmp(PathFindExtension(pName),L".library-ms")==0; + bool bStartScreen=( +#ifndef STARTSCREEN_WIN7 + GetWinVersion()>=WIN_VER_WIN8 && +#endif + wcscmp(pName,STARTSCREEN_COMMAND)==0); + const wchar_t *pStr=pName; + if (!(pStr[0]&0xFF00) && isalpha(pStr[0]) && pStr[1]==':' && Strlen(pStr)<=3) + item.drive=(char)toupper(pStr[0]); + if (bStartScreen) + { + if (GetWinVersion()>=WIN_VER_WIN10) + item.name=FindTranslation(L"Menu.StartMenu",L"Start Menu"); + else + item.name=FindTranslation(L"Menu.StartScreen",L"Start Screen"); + pName.MakeUpper(); + item.nameHash=CalcFNVHash(pName); + } + else + { + CComString pName2; + if (SUCCEEDED(pChild->GetDisplayName(SIGDN_NORMALDISPLAY,&pName2))) + { + if ((options&CONTAINER_CONTROLPANEL) && (_wcsnicmp(pName2,L"::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0",42)==0 || Strlen(pName2)==0)) + continue; // if the display name starts with the control panel GUID, something's wrong (like the Intel crap) + pName.MakeUpper(); + item.nameHash=CalcFNVHash(pName); + pName.Clear(); + item.SetName(pName2,(options&CONTAINER_NOEXTENSIONS)!=0); + } + else + { + if (options&CONTAINER_CONTROLPANEL) + continue; // control panel items should have a normal name + item.SetName(pName,(options&CONTAINER_NOEXTENSIONS)!=0); + pName.MakeUpper(); + item.nameHash=CalcFNVHash(pName); + } + + if (bLibrary) flags&=~SFGAO_STREAM; + item.bLink=(flags&SFGAO_LINK)!=0; + item.bFolder=(!(options&CONTAINER_CONTROLPANEL) && !(options&CONTAINER_NOSUBFOLDERS) && (flags&SFGAO_FOLDER) && (!(flags&(SFGAO_STREAM|SFGAO_LINK)) || (s_bExpandLinks && item.bLink))); + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + if (item.pItemInfo->IsMetroLink()) + { + if ((m_bSubMenu && GetSettingBool(L"HideProgramsMetro")) || _wcsicmp(item.pItemInfo->GetAppid(),DESKTOP_APP_ID)==0) + continue; + item.bLink=item.bMetroLink=true; + if (!item.pItemInfo->GetMetroName().IsEmpty()) + item.name=item.pItemInfo->GetMetroName(); + } + item.bMetroApp=item.pItemInfo->IsMetroApp(); + } + } + item.pItem1=childPidl.Detach(); + item.bStartScreen=bStartScreen; + item.bPrograms=(options&CONTAINER_PROGRAMS)!=0; + items.push_back(item); +#ifdef REPEAT_ITEMS + for (int i=0;i &items, int options ) +{ + CAbsolutePidl ignore; + if (!m_pParent || (m_Options&CONTAINER_ALLPROGRAMS)) + { + // remove the Programs subfolder from the main menu. it will be added separately + ShGetKnownFolderIDList(FOLDERID_CommonPrograms,&ignore); + } + + CShellItemEnumerator enumerator(pFolder); + if (!enumerator.IsValid()) return; + + CComPtr pChild; + CAbsolutePidl childPidl; + int refreshFlags=CItemManager::INFO_SMALL_ICON; + if (!m_bSubMenu) + { + if (s_Skin.Main_icon_size==MenuSkin::ICON_SIZE_LARGE) + refreshFlags=CItemManager::INFO_LARGE_ICON; + else if (s_Skin.Main_icon_size==MenuSkin::ICON_SIZE_NONE) + refreshFlags=0; + } + if (options&CONTAINER_PROGRAMS) + refreshFlags|=CItemManager::INFO_LINK|CItemManager::INFO_METRO; + while (enumerator.GetNext(pChild,childPidl)) + { + SFGAOF flags=0; + HRESULT hrFlags=pChild->GetAttributes(SFGAO_FOLDER|SFGAO_STREAM|SFGAO_LINK|SFGAO_HIDDEN,&flags); + if (FAILED(hrFlags)) // check if the item is a folder, archive or a link + flags=0; + if (flags&SFGAO_HIDDEN) + continue; + CComString pName; + if (SUCCEEDED(pChild->GetDisplayName(SIGDN_PARENTRELATIVEPARSING,&pName))) + { + LOG_MENU(LOG_OPEN,L"%s, 0x%08X, 0x%08X",pName,flags,hrFlags); + bool bLibrary=_wcsicmp(PathFindExtension(pName),L".library-ms")==0; + bool bStartScreen=( +#ifndef STARTSCREEN_WIN7 + GetWinVersion()>=WIN_VER_WIN8 && +#endif + wcscmp(pName,STARTSCREEN_COMMAND)==0); + MenuItem item(MENU_NO); + if (bStartScreen) + { + if (GetWinVersion()>=WIN_VER_WIN10) + item.name=FindTranslation(L"Menu.StartMenu",L"Start Menu"); + else + item.name=FindTranslation(L"Menu.StartScreen",L"Start Screen"); + pName.MakeUpper(); + item.nameHash=CalcFNVHash(pName); + } + else + { + CComString pName2; + if (SUCCEEDED(pChild->GetDisplayName(SIGDN_NORMALDISPLAY,&pName2))) + { + pName.MakeUpper(); + item.nameHash=CalcFNVHash(pName); + pName.Clear(); + item.SetName(pName2,(options&CONTAINER_NOEXTENSIONS)!=0); + } + else + { + item.SetName(pName,(options&CONTAINER_NOEXTENSIONS)!=0); + pName.MakeUpper(); + item.nameHash=CalcFNVHash(pName); + } + } + pName.Clear(); + + if (ignore && ILIsEqual(childPidl,ignore)) + continue; + + // look for another item with the same name + bool bFound=false; + for (std::vector::iterator it=items.begin();it!=items.end();++it) + { + if (item.nameHash==it->nameHash) + { + it->pItem2=childPidl.Detach(); + bFound=true; + break; + } + } + + if (!bFound) + { + // new item + if (!bStartScreen) + { + item.pItemInfo=g_ItemManager.GetItemInfo(pChild,childPidl,refreshFlags); + + if (bLibrary) flags&=~SFGAO_STREAM; + item.bLink=(flags&SFGAO_LINK)!=0; + item.bFolder=(!(options&CONTAINER_CONTROLPANEL) && !(options&CONTAINER_NOSUBFOLDERS) && (flags&SFGAO_FOLDER) && (!(flags&(SFGAO_STREAM|SFGAO_LINK)) || (s_bExpandLinks && item.bLink))); + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + if (item.pItemInfo->IsMetroLink()) + { + if ((m_bSubMenu && GetSettingBool(L"HideProgramsMetro")) || _wcsicmp(item.pItemInfo->GetAppid(),DESKTOP_APP_ID)==0) + continue; + item.bLink=item.bMetroLink=true; + if (!item.pItemInfo->GetMetroName().IsEmpty()) + item.name=item.pItemInfo->GetMetroName(); + item.bMetroApp=item.pItemInfo->IsMetroApp(); + } + } + } + item.pItem1=childPidl.Detach(); + item.bStartScreen=bStartScreen; + item.bPrograms=(options&CONTAINER_PROGRAMS)!=0; + items.push_back(item); +#ifdef REPEAT_ITEMS + for (int i=0;i pItem; + if (pidl && SUCCEEDED(SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pItem))) + return g_ItemManager.GetItemInfo(pItem,pidl,CItemManager::INFO_SMALL_ICON); + } + return g_ItemManager.GetCustomIcon(L"shell32.dll,14",CItemManager::ICON_SIZE_TYPE_SMALL); +} + +void CMenuContainer::AddInternetSearch( size_t index ) +{ + MenuItem item(MENU_SEARCH_INTERNET); + item.name=FindTranslation(L"Menu.SearchInternet",L"Search the Internet"); + item.pItemInfo=GetInternetIcon(false); + m_Items.insert(m_Items.begin()+index,1,item); +} + +void CMenuContainer::AddStandardItems( void ) +{ + if (m_pStdItem && m_pStdItem->id!=MENU_NO) + { + bool bItemsFirst=(m_Options&(CONTAINER_ITEMS_FIRST|CONTAINER_SEARCH))==CONTAINER_ITEMS_FIRST; + if (!m_Items.empty() && !(s_bWin7Style && !m_bSubMenu && GetSettingInt(L"ProgramsStyle")==PROGRAMS_HIDDEN)) + { + MenuItem item(MENU_SEPARATOR); + if (m_pStdItem->id==MENU_COLUMN_PADDING) + item.bAlignBottom=true; + if (bItemsFirst) + m_Items.insert(m_Items.begin(),item); + else + m_Items.push_back(item); + } + size_t menuIdx=bItemsFirst?0:m_Items.size(); + bool bBreak=false, bAlignBottom=false, bInlineFirst=false; + const StdMenuItem *pInlineParent=NULL; + int searchProviderIndex=-1; + m_SearchProvidersCount=0; + MenuSkin::TIconSize mainIconSize=s_Skin.Main_icon_size; + for (const StdMenuItem *pStdItem=m_pStdItem;;pStdItem++) + { + if (pStdItem->id==MENU_LAST) + { + if (pInlineParent) + { + pStdItem=pInlineParent; + pInlineParent=NULL; + continue; + } + break; + } + if (pStdItem->id==MENU_IGNORE) + continue; + if (m_bSubMenu && pStdItem->id==s_ShutdownCommand) + continue; + + if (pStdItem->id==MENU_COLUMN_BREAK && m_bTwoColumns) + mainIconSize=s_Skin.Main2_icon_size; + + int stdOptions=GetStdOptions(pStdItem->id); + if (!(stdOptions&MENU_ENABLED)) continue; + + if (s_bWin7Style && m_bSubMenu && pStdItem->command && (pStdItem->id==MENU_SWITCHUSER || pStdItem->id==MENU_SECURITY || pStdItem->id==MENU_LOGOFF || pStdItem->id==MENU_LOCK || pStdItem->id==MENU_DISCONNECT + || pStdItem->id==MENU_UNDOCK || pStdItem->id==MENU_RESTART || pStdItem->id==MENU_SLEEP || pStdItem->id==MENU_HIBERNATE || pStdItem->id==MENU_SHUTDOWN + || pStdItem->id==MENU_RESTART_NOUPDATE || pStdItem->id==MENU_SHUTDOWN_NOUPDATE)) + { + CString commands=GetSettingString(L"ShutdownW7"); + const wchar_t *str=commands; + bool bFound=false, bEmpty=true; + const wchar_t *commandName=pStdItem->command; + if (pStdItem->id==MENU_SHUTDOWN_NOUPDATE) + commandName=L"shutdown"; + else if (pStdItem->id==MENU_RESTART_NOUPDATE) + commandName=L"restart"; + while (*str) + { + wchar_t token[100]; + str=GetToken(str,token,_countof(token),L" \t;,"); + if (*token) bEmpty=false; + if (_wcsicmp(commandName,token)==0) + { + bFound=true; + break; + } + } + if (!bFound && !bEmpty) continue; + } + + if (pStdItem->id==MENU_SEPARATOR && menuIdx>0 && m_Items[menuIdx-1].id==MENU_SEPARATOR) + { + // prevent double separators unless that's exactly what is requested + if (pStdItem>m_pStdItem && pStdItem[-1].id!=MENU_SEPARATOR) + continue; + } + if (pStdItem->id==MENU_COLUMN_BREAK) + { + bBreak=true; + continue; + } + if (pStdItem->id==MENU_COLUMN_PADDING) + { + bAlignBottom=true; + continue; + } + + if (!pInlineParent && pStdItem->submenu && (pStdItem->settings&StdMenuItem::MENU_INLINE)) + { + pInlineParent=pStdItem; + pStdItem=pInlineParent->submenu-1; + bInlineFirst=true; + continue; + } + if (s_bWin7Style && pStdItem->id==MENU_SEARCH_BOX) + { + MenuItem item(MENU_EMPTY); + m_Items.insert(m_Items.begin()+menuIdx,1,item); + menuIdx++; + searchProviderIndex=(int)menuIdx; + if (GetSettingBool(L"SearchInternet")) + { + AddInternetSearch(menuIdx); + menuIdx++; + m_SearchProvidersCount++; + } + } + + bool bSearchProvider7=false; + if (s_bWin7Style && !m_bSubMenu && pStdItem->command) + { + // if after environment substitution there are %1 or %2 left, this is likely a search provider + wchar_t buf[1024]; + Strcpy(buf,_countof(buf),pStdItem->command); + DoEnvironmentSubst(buf,_countof(buf)); + const wchar_t *ptr=wcsstr(buf,L"%1"); + if (ptr && !isalnum(ptr[2])) + bSearchProvider7=true; + else + { + ptr=wcsstr(buf,L"%2"); + if (ptr && !isalnum(ptr[2])) + bSearchProvider7=true; + } + } + + MenuItem item(pStdItem->id); + item.pStdItem=pStdItem; + if (pInlineParent) + item.bInline=true; + + if (!bSearchProvider7) + { + item.bBreak=bBreak; + bBreak=false; + } + item.bAlignBottom=bAlignBottom; + item.bInlineFirst=bInlineFirst; + bAlignBottom=bInlineFirst=false; + TNetworkType networkType=NETWORK_NONE; + + Assert(pStdItem->folder1 || !pStdItem->folder2); + if (pStdItem->id==MENU_APPS) + { + wchar_t path[_MAX_PATH]=METRO_APP_ROOT; + DoEnvironmentSubst(path,_countof(path)); + item.pItem1=ILCreateFromPath(path); + item.bFolder=true; + item.name=FindTranslation(L"Menu.Apps",L"Apps"); + } + else if (pStdItem->id==MENU_PROGRAMS && GetSettingInt(L"PinnedPrograms")==PINNED_PROGRAMS_PINNED) + { + ShGetKnownFolderIDList(FOLDERID_StartMenu,&item.pItem1); + if (!s_bNoCommonFolders) + ShGetKnownFolderIDList(FOLDERID_CommonStartMenu,&item.pItem2); + item.bFolder=true; + } + else if (pStdItem->folder1) + { + ShGetKnownFolderIDList(*pStdItem->folder1,&item.pItem1); + if (pStdItem->folder2) + ShGetKnownFolderIDList(*pStdItem->folder2,&item.pItem2); + if (!item.pItem1 && item.pItem2) + { + item.pItem1=item.pItem2; + item.pItem2=NULL; + } + item.bFolder=(stdOptions&MENU_EXPANDED) && !(item.pStdItem->settings&StdMenuItem::MENU_NOEXPAND); + } + else if (pStdItem->link) + { + SFGAOF flags=0; + wchar_t buf[1024]; + Strcpy(buf,_countof(buf),item.pStdItem->link); + DoEnvironmentSubst(buf,_countof(buf)); + bool bLibrary=_wcsicmp(PathFindExtension(buf),L".library-ms")==0; + wchar_t *second=wcschr(buf,';'); + if (!bLibrary && second && !(item.pStdItem->settings&StdMenuItem::MENU_NOEXPAND)) + { + wchar_t *end= second; + while (end>buf) + { + *end=0; + end--; + if (*end!=' ') + break; + } + MenuParseDisplayName(buf,&item.pItem1,&flags,&networkType); + second++; + while (*second==' ') + second++; + SFGAOF flags2=0; + TNetworkType networkType2; + MenuParseDisplayName(second,&item.pItem2,&flags2,&networkType2); + if (!item.pItem1 && item.pItem2) + { + item.pItem1=item.pItem2; + item.pItem2=NULL; + flags=flags2; + networkType=networkType2; + } + if (item.pItem1) + { + item.bLink=(flags&SFGAO_LINK)!=0; + item.bFolder=((flags&SFGAO_FOLDER) && (!(flags&(SFGAO_STREAM|SFGAO_LINK)) || (s_bExpandLinks && item.bLink))); + } + } + else if (SUCCEEDED(MenuParseDisplayName(buf,&item.pItem1,&flags,&networkType))) + { + if (bLibrary) flags&=~SFGAO_STREAM; + item.bLink=(flags&SFGAO_LINK)!=0; + item.bFolder=((flags&SFGAO_FOLDER) && !(item.pStdItem->settings&StdMenuItem::MENU_NOEXPAND) && (!(flags&(SFGAO_STREAM|SFGAO_LINK)) || (s_bExpandLinks && item.bLink))); + } + } + if ((pStdItem->submenu && pStdItem->id!=MENU_SEARCH_BOX && (stdOptions&MENU_EXPANDED)) || pStdItem->id==MENU_RECENT_PROGRAMS) + item.bFolder=true; + + item.bSplit=item.bFolder && (item.pStdItem->settings&StdMenuItem::MENU_SPLIT_BUTTON)!=0; + + // get icon + CItemManager::TIconSizeType iconSizeType; + int refreshFlags; + if (bSearchProvider7 || m_bSubMenu) + { + iconSizeType=CItemManager::ICON_SIZE_TYPE_SMALL; + refreshFlags=CItemManager::INFO_SMALL_ICON; + } + else if (s_bWin7Style) + { + iconSizeType=CItemManager::ICON_SIZE_TYPE_EXTRA_LARGE; + refreshFlags=CItemManager::INFO_EXTRA_LARGE_ICON; + } + else if (mainIconSize==MenuSkin::ICON_SIZE_LARGE) + { + iconSizeType=CItemManager::ICON_SIZE_TYPE_LARGE; + refreshFlags=CItemManager::INFO_LARGE_ICON; + } + else if (mainIconSize==MenuSkin::ICON_SIZE_SMALL) + { + iconSizeType=CItemManager::ICON_SIZE_TYPE_SMALL; + refreshFlags=CItemManager::INFO_SMALL_ICON; + } + else + { + iconSizeType=CItemManager::ICON_SIZE_TYPE_SMALL; + refreshFlags=0; + } + if (pStdItem->link) + refreshFlags|=CItemManager::INFO_LINK|CItemManager::INFO_METRO; + if ((refreshFlags&CItemManager::INFO_ICON)==0) + item.pItemInfo=NULL; + else if (pStdItem->iconPath) + { + if (_wcsicmp(pStdItem->iconPath,L"none")==0) + item.pItemInfo=NULL; + else + item.pItemInfo=g_ItemManager.GetCustomIcon(pStdItem->iconPath,iconSizeType); + } + else if (networkType!=NETWORK_NONE && networkType!=NETWORK_FILE) + { + item.pItemInfo=g_ItemManager.GetCustomIcon(GetDefaultNetworkIcon(networkType),iconSizeType); + } + else if (item.pItem1) + { + CComPtr pItem; + if (SUCCEEDED(SHCreateItemFromIDList(item.pItem1,IID_IShellItem,(void**)&pItem))) + { + item.pItemInfo=g_ItemManager.GetItemInfo(pItem,item.pItem1,refreshFlags); + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + item.bLink=item.bMetroLink=item.pItemInfo->IsMetroLink(); + item.bMetroApp=item.pItemInfo->IsMetroApp(); + } + } + else + item.pItemInfo=g_ItemManager.GetCustomIcon(NULL,iconSizeType); + + // get name + if (pStdItem->label && _wcsicmp(pStdItem->label,L"none")==0) + { + item.name.Empty(); + } + else if (pStdItem->label) + { + if (item.id==MENU_LOGOFF) + { + // construct the text Log Off ... + wchar_t user[256]={0}; + ULONG size=_countof(user); + if (!GetUserNameEx(NameDisplay,user,&size)) + { + // GetUserNameEx may fail (for example on Home editions). use the login name + size=_countof(user); + GetUserName(user,&size); + } + item.name.Format(pStdItem->label,user); + } + else if (item.id==MENU_SHUTDOWN_BUTTON) + { + s_ShutdownCommand=MENU_NO; + int shutdown=GetSettingInt(L"ShutdownCommand"); + if (shutdown<0) shutdown=0; + if (shutdown>=SHUTDOWN_TYPE_COUNT) shutdown=SHUTDOWN_TYPE_COUNT-1; + + bool enabled[SHUTDOWN_TYPE_COUNT]={0}; + enabled[SHUTDOWN_TYPE_SHUTDOWN]=(GetStdOptions(MENU_SHUTDOWN)&MENU_ENABLED)!=0; + enabled[SHUTDOWN_TYPE_RESTART]=(GetStdOptions(MENU_RESTART)&MENU_ENABLED)!=0; + enabled[SHUTDOWN_TYPE_LOGOFF]=(GetStdOptions(MENU_LOGOFF)&MENU_ENABLED)!=0; + enabled[SHUTDOWN_TYPE_SLEEP]=(GetStdOptions(MENU_SLEEP)&MENU_ENABLED)!=0; + enabled[SHUTDOWN_TYPE_HIBERNATE]=(GetStdOptions(MENU_HIBERNATE)&MENU_ENABLED)!=0; + enabled[SHUTDOWN_TYPE_LOCK]=(GetStdOptions(MENU_LOCK)&MENU_ENABLED)!=0; + enabled[SHUTDOWN_TYPE_SWITCHUSER]=(GetStdOptions(MENU_SWITCHUSER)&MENU_ENABLED)!=0; + enabled[SHUTDOWN_TYPE_SHUTDOWN_BOX]=(GetStdOptions(MENU_SHUTDOWN_BOX)&MENU_ENABLED)!=0; + if (!enabled[shutdown]) + { + for (int i=1;i(item.pStdItem)->tip=FindTranslation(L"Menu.ShutdownUpdate",L"Update and shut down"); + else + const_cast(item.pStdItem)->tip=FindTranslation(L"Menu.ShutdownTip",L""); + s_ShutdownCommand=MENU_SHUTDOWN; + } + if (shutdown==SHUTDOWN_TYPE_RESTART) + { + item.name=FindTranslation(L"Menu.Restart",L"&Restart"); + if (s_bHasUpdates && GetWinVersion()>=WIN_VER_WIN8) + const_cast(item.pStdItem)->tip=FindTranslation(L"Menu.RestartUpdate",L"Update and restart"); + else + const_cast(item.pStdItem)->tip=FindTranslation(L"Menu.RestartTip",L""); + s_ShutdownCommand=MENU_RESTART; + } + if (shutdown==SHUTDOWN_TYPE_LOGOFF) + { + item.name=FindTranslation(L"Menu.LogOffShort",L"Log off"); + const_cast(item.pStdItem)->tip=FindTranslation(L"Menu.LogOffTip",L""); + s_ShutdownCommand=MENU_LOGOFF; + } + if (shutdown==SHUTDOWN_TYPE_SLEEP) + { + item.name=FindTranslation(L"Menu.Sleep",L"&Sleep"); + const_cast(item.pStdItem)->tip=FindTranslation(L"Menu.SleepTip",L""); + s_ShutdownCommand=MENU_SLEEP; + } + if (shutdown==SHUTDOWN_TYPE_HIBERNATE) + { + item.name=FindTranslation(L"Menu.Hibernate",L"&Hibernate"); + const_cast(item.pStdItem)->tip=FindTranslation(L"Menu.HibernateTip",L""); + s_ShutdownCommand=MENU_HIBERNATE; + } + if (shutdown==SHUTDOWN_TYPE_SHUTDOWN_BOX) + { + item.name=FindTranslation(L"Menu.ShutdownBox",L"Sh&ut Down..."); + const_cast(item.pStdItem)->tip=L""; + s_ShutdownCommand=MENU_SHUTDOWN_BOX; + } + if (shutdown==SHUTDOWN_TYPE_LOCK) + { + item.name=FindTranslation(L"Menu.Lock",L"Lock"); + const_cast(item.pStdItem)->tip=FindTranslation(L"Menu.LockTip",L""); + s_ShutdownCommand=MENU_LOCK; + } + if (shutdown==SHUTDOWN_TYPE_SWITCHUSER) + { + item.name=FindTranslation(L"Menu.SwitchUser",L"Switch User"); + const_cast(item.pStdItem)->tip=FindTranslation(L"Menu.SwitchUserTip",L""); + s_ShutdownCommand=MENU_SWITCHUSER; + } + } + else if (s_bHasUpdates && m_bSubMenu && item.id==MENU_SHUTDOWN) + item.name=FindTranslation(L"Menu.ShutdownUpdate",L"Update and shut down"); + else if (s_bHasUpdates && m_bSubMenu && item.id==MENU_RESTART && GetWinVersion()>=WIN_VER_WIN8) + item.name=FindTranslation(L"Menu.RestartUpdate",L"Update and restart"); + else + item.name=pStdItem->label; + } + else if (item.pItem1) + { + if (item.pItemInfo) + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + if (item.pItemInfo->IsMetroLink()) + item.name=item.pItemInfo->GetMetroName(); + } + if (item.name.IsEmpty()) + { + SHFILEINFO info={0}; + SHGetFileInfo((LPCWSTR)item.pItem1,0,&info,sizeof(info),SHGFI_PIDL|SHGFI_DISPLAYNAME); + item.name=info.szDisplayName; + } + if (wcschr(item.name,'&')) + item.name.Replace(L"&",L"&&"); + } + else if (item.name.IsEmpty() && item.id!=MENU_SEPARATOR && item.id!=MENU_SEARCH_BOX && !item.bInline) + { + if ((pStdItem->command && wcscmp(pStdItem->command,L"")!=0) || pStdItem->link || pStdItem->folder1 || pStdItem->submenu || pStdItem->id!=MENU_CUSTOM) + item.name=LoadStringEx(IDS_NO_TEXT); + else + { + item.id=MENU_SEPARATOR; + item.bBlankSeparator=true; + } + } + + item.bPrograms=(item.id==MENU_PROGRAMS || item.id==MENU_FAVORITES); + if (item.bInline) + item.bFolder=false; + + if (bSearchProvider7) + { + item.bInline=false; + item.bFolder=false; + item.id=MENU_SEARCH_PROVIDER; + if (searchProviderIndex>=0) + { + m_Items.insert(m_Items.begin()+searchProviderIndex,1,item); + searchProviderIndex++; + menuIdx++; + m_SearchProvidersCount++; + } + } + else + { + m_Items.insert(m_Items.begin()+menuIdx,1,item); + menuIdx++; + } + } + } +} + +void CMenuContainer::UpdateAccelerators( int first, int last ) +{ + TRecentKeys recentKeys=(TRecentKeys)GetSettingInt(L"RecentProgKeys"); + + for (int i=first;iitem.rank) || (rank==item.rank && CompareFileTime(×tamp,&item.timestamp)>0); } +}; + +static const wchar_t *g_MfuIgnoreWords[]={ + L"DOCUMENTATION", + L"HELP", + L"INSTALL", + L"MORE INFO", + L"READ ME", + L"READ FIRST", + L"README", + L"REMOVE", + L"SETUP", + L"SUPPORT", + L"WHAT'S NEW", +}; + +static const wchar_t *g_MfuIgnoreExes[]={ + L"APPLAUNCH.EXE", + L"CONTROL.EXE", + L"DFSVC.EXE", + L"DLLHOST.EXE", + L"GUESTMODEMSG.EXE", + L"HH.EXE", + L"INSTALL.EXE", + L"ISUNINST.EXE", + L"LNKSTUB.EXE", + L"MMC.EXE", + L"MSHTA.EXE", + L"MSIEXEC.EXE", + L"MSOOBE.EXE", + L"RUNDLL32.EXE", + L"SETUP.EXE", + L"ST5UNST.EXE", + L"UNWISE.EXE", + L"UNWISE32.EXE", + L"WERFAULT.EXE", + L"WINHLP32.EXE", + L"WLRMDR.EXE", + L"WUAPP.EXE", +}; + +void CMenuContainer::GetRecentPrograms( std::vector &items, int maxCount ) +{ + bool bShowMetro=GetSettingBool(L"RecentMetroApps"); + const std::vector &mainItems=s_Menus[0]->m_Items; + + int iconSizeFlag=(!m_bSubMenu && s_Skin.Main_icon_size==MenuSkin::ICON_SIZE_LARGE)?CItemManager::INFO_LARGE_ICON:CItemManager::INFO_SMALL_ICON; + if (s_RecentPrograms==RECENT_PROGRAMS_RECENT) + { + for (int i=0;i pItem; + CAbsolutePidl pidl; + bool bApp=(wcsncmp(s_MRUShortcuts[i],L"APP:",4)==0); + if (bApp) + { + if (SUCCEEDED(SHCreateItemInKnownFolder(FOLDERID_AppsFolder2,0,(const wchar_t*)s_MRUShortcuts[i]+4,IID_IShellItem,(void**)&pItem)) && FAILED(SHGetIDListFromObject(pItem,&pidl))) + pItem=NULL; + } + else if (SUCCEEDED(MenuParseDisplayName(s_MRUShortcuts[i],&pidl,NULL,NULL))) + SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pItem); + if (pItem) + { + CComString pName; + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_NORMALDISPLAY,&pName))) + { + if (bApp && wcsncmp(pName,L"@{",2)==0) + continue; + // new item + MenuItem item(MENU_RECENT); + item.bLink=true; + int refreshFlags=CItemManager::INFO_LINK|CItemManager::INFO_LINK_APPID|CItemManager::INFO_METRO|iconSizeFlag; + item.pItemInfo=g_ItemManager.GetItemInfo(pItem,pidl,refreshFlags); + + // see if it is already in the main menu + bool bFound=false; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + for (std::vector::const_iterator it=mainItems.begin();it!=mainItems.end();++it) + { + if (!it->pItemInfo) continue; + if (it->pItemInfo==item.pItemInfo) + { + bFound=true; + break; + } + if (!it->pItemInfo->IsLink() && !it->pItemInfo->IsMetroApp()) + continue; + // if the item is an app, check if the link has the same target pidl + // if the item has appid, compare by appid. otherwise compare by target path (shouldn't happen) + if (bApp && it->pItemInfo->IsLink()) + { + // for apps compare by pidl + if (ILIsEqual(pidl,it->pItemInfo->GetTargetPidl())) + { + bFound=true; + break; + } + } + else if (!item.pItemInfo->GetAppid().IsEmpty()) + { + if (_wcsicmp(item.pItemInfo->GetAppid(),it->pItemInfo->GetAppid())==0) + { + bFound=true; + break; + } + } + else + { + if (!item.pItemInfo->GetTargetPATH().IsEmpty() && wcscmp(item.pItemInfo->GetTargetPATH(),it->pItemInfo->GetTargetPATH())==0) + { + bFound=true; + break; + } + } + } + } + if (bFound) continue; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + if (item.pItemInfo->IsMetroApp() && !bShowMetro) + continue; + if (item.pItemInfo->IsMetroLink()) + { + if (!bShowMetro) continue; + item.bMetroLink=true; + if (_wcsicmp(item.pItemInfo->GetAppid(),DESKTOP_APP_ID)==0) + continue; + if (item.pItemInfo->GetMetroName().IsEmpty()) + item.SetName(pName,(m_Options&CONTAINER_NOEXTENSIONS)!=0); + else + item.SetName(item.pItemInfo->GetMetroName(),false); + } + else + item.SetName(pName,(m_Options&CONTAINER_NOEXTENSIONS)!=0); + item.bMetroApp=item.pItemInfo->IsMetroApp(); + } + item.pItem1=pidl.Detach(); + + items.push_back(item); + } + } + if ((int)items.size()==maxCount) + break; + } + } + else if (s_RecentPrograms==RECENT_PROGRAMS_FREQUENT) + { + ULONGLONG curTime; + GetSystemTimeAsFileTime((FILETIME*)&curTime); + std::vector uaItems; + CRegKey regKeyApp, regKeyLink; + if (regKeyApp.Open(HKEY_CURRENT_USER,USERASSIST_APPIDS_KEY,KEY_READ)!=ERROR_SUCCESS || + regKeyLink.Open(HKEY_CURRENT_USER,USERASSIST_LINKS_KEY,KEY_READ)!=ERROR_SUCCESS) + { + LOG_MENU(LOG_MFU,L"Failed to open UserAssist registry key"); + return; + } + + // collect links with positive rank from regKeyLink + for (int idx=0;;idx++) + { + UserAssistItem uaItem; + memset(&uaItem,0,sizeof(uaItem)); + DWORD len=_countof(uaItem.name); + UserAssistData data; + memset(&data,0,sizeof(data)); + DWORD size=sizeof(data); + DWORD type; + LONG res=RegEnumValue(regKeyLink,idx,uaItem.name,&len,NULL,&type,(BYTE*)&data,&size); + if (res==ERROR_NO_MORE_ITEMS) + break; + if (!*uaItem.name) + continue; + if (type!=REG_BINARY) + { + LOG_MENU(LOG_MFU,L"Not binary: '%s'",uaItem.name); + continue; + } + if (size!=sizeof(data)) + { + LOG_MENU(LOG_MFU,L"Wrong size (%d): '%s'",size,uaItem.name); + continue; + } + uaItem.mfuHash=CalcFNVHash(uaItem.name); + EncodeRot13(uaItem.name); + if (data.timestamp.dwLowDateTime==0 && data.timestamp.dwHighDateTime==0) + { + LOG_MENU(LOG_MFU,L"Zero timestamp: '%s'",uaItem.name); + continue; + } + // determine rank + uaItem.rank=data.count/10.f; + float weight=0.95f; + for (int i=0, idx=data.last;i<_countof(data.history);i++,idx=(idx+9)%10,weight-=0.07f) + { + float h=data.history[idx]; + if (h<0 || h>1) break; + uaItem.rank+=h*weight; + } + if (uaItem.rank==0) + { + LOG_MENU(LOG_MFU,L"Zero rank: '%s'",uaItem.name); + continue; + } + + // decode name + const wchar_t *ext=PathFindExtension(uaItem.name); + if (uaItem.name[0]=='{') + { + wchar_t *end=wcschr(uaItem.name+1,'}'); + if (end && end[1]=='\\') + { + end[1]=0; + GUID guid; + HRESULT hr=CLSIDFromString(uaItem.name,&guid); + end[1]='\\'; + if (SUCCEEDED(hr)) + { + CComString pPath; + if (SUCCEEDED(SHGetKnownFolderPath(guid,KF_FLAG_DONT_VERIFY,NULL,&pPath))) + { + wchar_t path[_MAX_PATH]; + Sprintf(path,_countof(path),L"%s%s",pPath,end+1); + Strcpy(uaItem.name,_countof(uaItem.name),path); + } + } + } + } + LOG_MENU(LOG_MFU,L"UserAssist: '%s', %d, %.3f",uaItem.name,data.count,uaItem.rank); + bool bIgnore=false; + wchar_t NAME[_MAX_PATH]; + Strcpy(NAME,_countof(NAME),uaItem.name); + CharUpper(NAME); + uaItem.nameHash=CalcFNVHash(NAME); + for (std::vector::const_iterator it=uaItems.begin();it!=uaItems.end();++it) + { + if (uaItem.nameHash==it->nameHash) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: Already in list"); + bIgnore=true; + break; + } + } + if (bIgnore) continue; + const wchar_t *fname=PathFindFileName(NAME); + for (int i=0;i<_countof(g_MfuIgnoreWords);i++) + if (wcswcs(fname,g_MfuIgnoreWords[i])) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: Contains bad word"); + bIgnore=true; + break; + } + if (bIgnore) continue; + + uaItem.pLinkInfo=g_ItemManager.GetItemInfo(uaItem.name,CItemManager::INFO_LINK|CItemManager::INFO_LINK_APPID|CItemManager::INFO_METRO|CItemManager::INFO_VALIDATE_FILE); + if (!uaItem.pLinkInfo) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: File missing"); + continue; + } + wchar_t appid[_MAX_PATH]; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + if (uaItem.pLinkInfo->GetLocation()!=CItemManager::LOCATION_START_MENU && uaItem.pLinkInfo->GetLocation()!=CItemManager::LOCATION_METRO && uaItem.pLinkInfo->GetLocation()!=CItemManager::LOCATION_GAMES) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: Not from start menu"); + continue; + } + if (uaItem.pLinkInfo->IsNoPin()) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: No pin"); + continue; + } + if (uaItem.pLinkInfo->GetAppid().IsEmpty()) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: No AppId"); + continue; + } + if (!uaItem.pLinkInfo->GetTargetPATH().IsEmpty()) + { + const wchar_t *fname=PathFindFileName(uaItem.pLinkInfo->GetTargetPATH()); + for (int i=0;i<_countof(g_MfuIgnoreExes);i++) + if (wcswcs(fname,g_MfuIgnoreExes[i])) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: Target contains bad word: '%s'",uaItem.pLinkInfo->GetTargetPATH()); + bIgnore=true; + break; + } + } + if (uaItem.pLinkInfo->IsMetroLink()) + { + if (!bShowMetro) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: No show metro"); + continue; + } + if (_wcsicmp(uaItem.pLinkInfo->GetAppid(),DESKTOP_APP_ID)==0) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: Ignore desktop"); + continue; + } + if (uaItem.pLinkInfo->GetMetroName().IsEmpty()) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: No Metro name"); + continue; + } + } + if (bIgnore) continue; + Strcpy(appid,_countof(appid),uaItem.pLinkInfo->GetAppid()); + } + + uaItem.timestamp=data.timestamp; + size=sizeof(data); + EncodeRot13(appid); + if (regKeyApp.QueryBinaryValue(appid,&data,&size)!=ERROR_SUCCESS) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: Missing appid entry: '%s'",appid); + continue; + } + if (CompareFileTime(&uaItem.timestamp,&data.timestamp)<0) + uaItem.timestamp=data.timestamp; + + { + float rank=data.count/10.f; + float weight=0.95f; + for (int i=0, idx=data.last;i<_countof(data.history);i++,idx=(idx+9)%10,weight-=0.07f) + { + float h=data.history[idx]; + if (h<0 || h>1) break; + rank+=h*weight; + } + if (uaItem.rank=WIN_VER_WIN10 && bShowMetro) + { + // collect apps with positive rank from regKeyApp + for (int idx=0;;idx++) + { + UserAssistItem uaItem; + memset(&uaItem,0,sizeof(uaItem)); + DWORD len=_countof(uaItem.name); + UserAssistData data; + memset(&data,0,sizeof(data)); + DWORD size=sizeof(data); + DWORD type; + LONG res=RegEnumValue(regKeyApp,idx,uaItem.name,&len,NULL,&type,(BYTE*)&data,&size); + if (res==ERROR_NO_MORE_ITEMS) + break; + if (!*uaItem.name) + continue; + if (type!=REG_BINARY) + { + LOG_MENU(LOG_MFU,L"Not binary: '%s'",uaItem.name); + continue; + } + if (size!=sizeof(data)) + { + LOG_MENU(LOG_MFU,L"Wrong size (%d): '%s'",size,uaItem.name); + continue; + } + uaItem.mfuHash=CalcFNVHash(uaItem.name); + EncodeRot13(uaItem.name); + if (data.timestamp.dwLowDateTime==0 && data.timestamp.dwHighDateTime==0) + { + LOG_MENU(LOG_MFU,L"Zero timestamp: '%s'",uaItem.name); + continue; + } + + // determine rank + uaItem.rank=data.count/10.f; + float weight=0.95f; + for (int i=0, idx=data.last;i<_countof(data.history);i++,idx=(idx+9)%10,weight-=0.07f) + { + float h=data.history[idx]; + if (h<0 || h>1) break; + uaItem.rank+=h*weight; + } + if (uaItem.rank==0) + { + LOG_MENU(LOG_MFU,L"Zero rank: '%s'",uaItem.name); + continue; + } + + if (_wcsicmp(uaItem.name,DESKTOP_APP_ID)==0) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: Ignore desktop"); + continue; + } + + { + CComPtr pAppItem; + if (FAILED(SHCreateItemInKnownFolder(FOLDERID_AppsFolder2,0,uaItem.name,IID_IShellItem,(void**)&pAppItem))) + continue; + CComString pName; + if (FAILED(pAppItem->GetDisplayName(SIGDN_NORMALDISPLAY,&pName)) || wcsncmp(pName,L"@{",2)==0) + continue; + } + + uaItem.pLinkInfo=g_ItemManager.GetMetroAppInfo10(uaItem.name); + if (!uaItem.pLinkInfo) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping '%s': Not a valid app",uaItem.name); + continue; + } + + LOG_MENU(LOG_MFU,L"UserAssist: '%s', %d, %.3f",uaItem.name,data.count,uaItem.rank); + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + if (uaItem.pLinkInfo->IsNoPin()) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: No pin"); + continue; + } + if (uaItem.pLinkInfo->GetPackagePath().IsEmpty() || GetFileAttributes(uaItem.pLinkInfo->GetPackagePath())==INVALID_FILE_ATTRIBUTES) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: Missing package path"); + continue; + } + + CAbsolutePidl pidl=uaItem.pLinkInfo->GetPidl(); + + // see if it is already in the main menu + bool bFound=false; + for (std::vector::const_iterator it=mainItems.begin();it!=mainItems.end();++it) + { + if (!it->pItemInfo) continue; + if (!it->pItemInfo->IsLink()) continue; + if (ILIsEqual(pidl,it->pItemInfo->GetTargetPidl())) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping '%s', already in main menu",uaItem.name); + bFound=true; + break; + } + } + if (bFound) continue; + } + + uaItem.timestamp=data.timestamp; + uaItems.push_back(uaItem); + } + } + + // sort by rank + std::sort(uaItems.begin(),uaItems.end()); + + g_ItemManager.WaitForShortcuts(CPoint((s_StartRect.left+s_StartRect.right)/2,(s_StartRect.top+s_StartRect.bottom)/2)); + + // create a menu item for each program + for (int i=0;i<(int)uaItems.size();i++) + { + UserAssistItem &uaItem=uaItems[i]; + if (!uaItem.pLinkInfo) continue; + + bool bMetroLink, bExplicitAppId, bMetroApp; + CString appid, targetPATH, metroName; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + bMetroLink=uaItem.pLinkInfo->IsMetroLink(); + bMetroApp=uaItem.pLinkInfo->IsMetroApp(); + bExplicitAppId=uaItem.pLinkInfo->IsExplicitAppId(); + appid=uaItem.pLinkInfo->GetAppid(); + targetPATH=uaItem.pLinkInfo->GetTargetPATH(); + if (bMetroLink) + metroName=uaItem.pLinkInfo->GetMetroName(); + // clear all other items with the same link target + for (int j=i+1;j<(int)uaItems.size();j++) + { + UserAssistItem &uaItem2=uaItems[j]; + if (!uaItem2.pLinkInfo) continue; + if (_wcsicmp(appid,uaItem2.pLinkInfo->GetAppid())==0) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping '%s', duplicate appid '%s'",uaItem2.name,appid); + uaItem2.pLinkInfo=NULL; + } + } + } + + if (bExplicitAppId) + { + CRegKey keyPin; + if (keyPin.Open(HKEY_LOCAL_MACHINE,L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileAssociation\\NoStartPageAppUserModelIDs",KEY_READ)==ERROR_SUCCESS) + { + if (keyPin.QueryValue(appid,NULL,NULL,NULL)==ERROR_SUCCESS) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping '%s', NoStartPageAppUserModelIDs",uaItem.name); + continue; + } + } + } + else + { + wchar_t text[1024]; + { + Sprintf(text,_countof(text),L"Applications\\%s",PathFindFileName(targetPATH)); + CRegKey keyPin; + if (keyPin.Open(HKEY_CLASSES_ROOT,text,KEY_READ)==ERROR_SUCCESS) + { + if (keyPin.QueryValue(L"NoStartPage",NULL,NULL,NULL)==ERROR_SUCCESS) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping '%s', NoStartPage",uaItem.name); + continue; + } + } + } + if (wcschr(appid,'\\')) + { + Sprintf(text,_countof(text),L"Applications\\%s",PathFindFileName(appid)); + CRegKey keyPin; + if (keyPin.Open(HKEY_CLASSES_ROOT,text,KEY_READ)==ERROR_SUCCESS) + { + if (keyPin.QueryValue(L"NoStartPage",NULL,NULL,NULL)==ERROR_SUCCESS) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping '%s', NoStartPage",uaItem.name); + continue; + } + } + } + } + + // see if it is in the taskbar + if (!bMetroLink && g_ItemManager.IsTaskbarPinned(appid)) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping '%s', pinned to taskbar",uaItem.name); + continue; + } + // see if it is already in the main menu + bool bFound=false; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + for (std::vector::const_iterator it=mainItems.begin();it!=mainItems.end();++it) + { + if (!it->pItemInfo) continue; + if (it->pItemInfo==uaItem.pLinkInfo) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping '%s', already in main menu",uaItem.name); + bFound=true; + break; + } + if (!it->pItemInfo->IsLink() && !it->pItemInfo->IsMetroApp()) + continue; + if (_wcsicmp(appid,it->pItemInfo->GetAppid())==0) + { + LOG_MENU(LOG_MFU,L"UserAssist: Dropping '%s', already in main menu",uaItem.name); + bFound=true; + break; + } + } + } + if (bFound) continue; + + MenuItem item(MENU_RECENT); + item.bLink=true; + item.pItemInfo=uaItem.pLinkInfo; + item.mfuHash=uaItem.mfuHash; + item.bMetroLink=bMetroLink; + item.bMetroApp=bMetroApp; + g_ItemManager.UpdateItemInfo(uaItem.pLinkInfo,iconSizeFlag); + CComPtr pItem; + if (bMetroLink) + { + item.SetName(metroName,false); + item.pItem1=ILCloneFull(uaItem.pLinkInfo->GetPidl()); + items.push_back(item); + } + else if (item.name.IsEmpty() && SUCCEEDED(SHCreateItemFromIDList(uaItem.pLinkInfo->GetPidl(),IID_IShellItem,(void**)&pItem))) + { + CComString pName; + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_NORMALDISPLAY,&pName))) + { + item.SetName(pName,(m_Options&CONTAINER_NOEXTENSIONS)!=0); + item.pItem1=ILCloneFull(uaItem.pLinkInfo->GetPidl()); + items.push_back(item); + } + } + + if ((int)items.size()==maxCount) + break; + } + } + + TRecentKeys recentKeys=(TRecentKeys)GetSettingInt(L"RecentProgKeys"); + for (int idx=0;idx<(int)items.size();idx++) + { + MenuItem &item=items[idx]; + item.mruOrder=idx; + if (recentKeys==RECENT_KEYS_DIGITS) + item.name.Replace(L"&",L"&&"); + if (idx<10) + { + if (recentKeys>=RECENT_KEYS_DIGITS) + { + item.accelerator=((idx+1)%10)+'0'; + item.bCustomAccelerator=true; + } + if (recentKeys==RECENT_KEYS_DIGITS) + { + CString str=item.name; + item.name.Format(L"&%d %s",(idx+1)%10,str); + item.nameOffset=item.name.GetLength()-str.GetLength(); + } + } + } +} + +void CMenuContainer::ClearItems( const std::vector::iterator &begin, const std::vector::iterator &end ) +{ + for (std::vector::iterator it=begin;it!=end;++it) + { + if (it->pItem1) ILFree(it->pItem1); + if (it->pItem2) ILFree(it->pItem2); + } + if (s_pDragSource==this && m_Items.begin()+m_DragIndex>=begin) + s_pDragSource=NULL; // freeing the dragged item + m_Items.erase(begin,end); +} + +void CMenuContainer::AddJumpListItems( std::vector &items ) +{ + s_JumpList.Clear(); + g_ItemManager.UpdateItemInfo(s_JumpAppInfo,CItemManager::INFO_LINK_APPID); + CString appid; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + appid=s_JumpAppInfo->GetAppid(); + } + if (!appid.IsEmpty()) + { + int maxHeight=65536, sepHeight=0, itemHeight=0; + if (s_bWin7Style) + { + itemHeight=s_Skin.ItemSettings[MenuSkin::LIST_ITEM].itemHeight; + sepHeight=s_Skin.ItemSettings[MenuSkin::LIST_SEPARATOR].itemHeight; + maxHeight=m_Items[m_OriginalCount-1].itemRect.top-s_Skin.Main_jump_padding.top; + } + GetJumplist(appid,s_JumpList,GetSettingInt(L"MaxJumplists"),maxHeight,sepHeight,itemHeight); + } + + for (int g=0;g<(int)s_JumpList.groups.size();g++) + { + const CJumpGroup &group=s_JumpList.groups[g]; + if (group.bHidden) continue; + { + MenuItem item(MENU_SEPARATOR); + item.SetName(group.name,false); + items.push_back(item); + } + for (int i=0;i<(int)group.items.size();i++) + { + const CJumpItem &jumpItem=group.items[i]; + if (jumpItem.bHidden) continue; + + MenuItem item(MENU_NO); + if (jumpItem.type==CJumpItem::TYPE_LINK) + { + item.SetName(jumpItem.name,false); + CComQIPtr pLink=jumpItem.pItem; + if (pLink) + { + pLink->GetIDList(&item.pItem1); + wchar_t location[_MAX_PATH]; + int index; + if (pLink->GetIconLocation(location,_countof(location),&index)==S_OK && location[0]) + item.pItemInfo=g_ItemManager.GetCustomIcon(location,index,CItemManager::ICON_SIZE_TYPE_SMALL,(index==0)); // assuming that if index!=0 the icon comes from a permanent location like a dll or exe + } + } + else if (jumpItem.type==CJumpItem::TYPE_ITEM) + { + item.SetName(jumpItem.name,false); + CComQIPtr pItem=jumpItem.pItem; + if (pItem) + SHGetIDListFromObject(pItem,&item.pItem1); + } + else if (jumpItem.type==CJumpItem::TYPE_SEPARATOR) + { + item.id=MENU_SEPARATOR; + } + item.bSplit=(jumpItem.type!=CJumpItem::TYPE_SEPARATOR && group.type!=CJumpGroup::TYPE_TASKS); + if (item.pItem1 && !item.pItemInfo) + { + CComPtr pItem; + if (SUCCEEDED(SHCreateItemFromIDList(item.pItem1,IID_IShellItem,(void**)&pItem))) + { + // do some pidl laundering. sometimes the pidls from the jumplists may contain weird hidden data, which affects the icon + // so do a round-trip convertion of the pidl to a display name + CComString pName; + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName))) + { + CComPtr pItem2; + CAbsolutePidl pidl2; + if (SUCCEEDED(MenuParseDisplayName(pName,&pidl2,NULL,NULL)) && SUCCEEDED(SHCreateItemFromIDList(pidl2,IID_IShellItem,(void**)&pItem2))) + { + int order; + if (SUCCEEDED(pItem->Compare(pItem2,SICHINT_CANONICAL,&order)) && order==0) + { + ILFree(item.pItem1); + item.pItem1=pidl2.Detach(); + pItem=pItem2; + } + } + } + item.pItemInfo=g_ItemManager.GetItemInfo(pItem,item.pItem1,CItemManager::INFO_SMALL_ICON); + } + } + item.jumpIndex=MAKELONG(g,i); + items.push_back(item); +#ifdef REPEAT_JUMPLIST_ITEMS + for (int i=0;i0 && m_Items[0].id!=MENU_EMPTY) + m_ScrollCount=(int)m_Items.size(); + m_OriginalScrollCount=m_ScrollCount; + UpdateAccelerators(0,(int)m_Items.size()); + return; + } + + if ((m_Options&CONTAINER_DOCUMENTS) && s_MaxRecentDocuments>0) // create the recent documents list + { + Assert(m_Path1[0] && !m_Path2[0]); + + // find all documents + + // with many recent files it takes a long time to go through the IShellFolder enumeration + // so use FindFirstFile directly + wchar_t recentPath[_MAX_PATH]; + SHGetPathFromIDList(m_Path1[0],recentPath); + wchar_t find[_MAX_PATH]; + Sprintf(find,_countof(find),L"%s\\*.lnk",recentPath); + + std::vector docs; + + WIN32_FIND_DATA data; + HANDLE h=FindFirstFile(find,&data); + while (h!=INVALID_HANDLE_VALUE) + { + Document doc; + doc.name.Format(L"%s\\%s",recentPath,data.cFileName); + doc.time=data.ftLastWriteTime; + docs.push_back(doc); + if (!FindNextFile(h,&data)) + { + FindClose(h); + break; + } + } + + // sort by time + std::sort(docs.begin(),docs.end()); + + size_t count=0; + CComPtr pLink; + if (SUCCEEDED(pLink.CoCreateInstance(CLSID_ShellLink))) + { + CComQIPtr pFile=pLink; + if (pFile) + { + // go through the items until we find s_MaxRecentDocuments documents + for (std::vector::const_iterator it=docs.begin();it!=docs.end();++it) + { + wchar_t path[_MAX_PATH]; + // find the target of the lnk file + if (SUCCEEDED(pFile->Load(it->name,STGM_READ)) && SUCCEEDED(pLink->GetPath(path,_countof(path),&data,0))) + { + // check if it is link to a file or directory + if (path[0] && !(data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)) + { + CAbsolutePidl pidl; + MenuParseDisplayName(it->name,&pidl,NULL,NULL); + CComPtr pItem; + CComString pName; + if (pidl && SUCCEEDED(SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pItem)) && SUCCEEDED(pItem->GetDisplayName(SIGDN_NORMALDISPLAY,&pName))) + { + if (_wcsicmp(PathFindExtension(pName),L".lnk")==0) + continue; + MenuItem item(MENU_NO); + item.pItem1=pidl.Detach(); + item.pItemInfo=g_ItemManager.GetItemInfo(pItem,item.pItem1,CItemManager::INFO_SMALL_ICON); + item.SetName(pName,(m_Options&CONTAINER_NOEXTENSIONS)!=0); + + m_Items.push_back(item); + count++; + if ((int)count>=s_MaxRecentDocuments) break; + } + } + } + } + } + } + } + + if ((m_Options&CONTAINER_APPS) && GetWinVersion()>=WIN_VER_WIN8) + { + std::vector links; + GetMetroLinks(links,true); + + for (std::vector::iterator it=links.begin();it!=links.end();++it) + { + const CItemManager::ItemInfo *pInfo=g_ItemManager.GetItemInfo(it->pItem,it->pidl,CItemManager::INFO_METRO|CItemManager::INFO_SMALL_ICON); + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + if (_wcsicmp(pInfo->GetAppid(),DESKTOP_APP_ID)==0) + continue; + CString name; + if (pInfo->IsMetroLink()) + name=pInfo->GetMetroName(); + else + { + CComString pName; + if (FAILED(it->pItem->GetDisplayName(SIGDN_NORMALDISPLAY,&pName))) + continue; + if (wcsncmp(pName,L"@{",2)==0) + continue; // bad name + name=pName; + } + MenuItem item(MENU_NO); + item.SetName(name,false); + StringUpper(name); + item.nameHash=CalcFNVHash(name); + item.pItemInfo=pInfo; + item.pItem1=it->pidl.Detach(); + item.bMetroLink=pInfo->IsMetroLink(); + item.bMetroApp=item.pItemInfo->IsMetroApp(); + m_Items.push_back(item); + } + } + + // add first folder + if (!(m_Options&CONTAINER_DOCUMENTS) && !(m_Options&CONTAINER_APPS)) + { + if (m_Path1[0]) + { + CComPtr pItem; + if (SUCCEEDED(SHCreateItemFromIDList(m_Path1[0],IID_IShellItem,(void**)&pItem))) + { + pItem->BindToHandler(NULL,BHID_SFViewObject,IID_IShellView,(void**)&m_pShellView); + m_pDropFolder[0]=pItem; + CComString pName; + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName))) + { + pName.MakeUpper(); + m_FolderHash[0]=CalcFNVHash(pName); + } + AddFirstFolder(pItem,m_Items,m_Options); + } + } + + // add second folder + if (m_Path2[0]) + { + CComPtr pItem; + if (SUCCEEDED(SHCreateItemFromIDList(m_Path2[0],IID_IShellItem,(void**)&pItem))) + { + CComString pName; + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName))) + { + pName.MakeUpper(); + m_FolderHash[0]=CalcFNVHash(pName,m_FolderHash[0]); + } + AddSecondFolder(pItem,m_Items,m_Options); + } + } + } + + if (m_Options&CONTAINER_ALLPROGRAMS) + { + std::vector items; + if (m_Path1[1]) + { + CComPtr pItem; + if (SUCCEEDED(SHCreateItemFromIDList(m_Path1[1],IID_IShellItem,(void**)&pItem))) + { + m_pDropFolder[1]=pItem; + CComString pName; + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName))) + { + pName.MakeUpper(); + m_FolderHash[1]=CalcFNVHash(pName); + } + AddFirstFolder(pItem,items,m_Options); + } + } + + // add second folder + if (m_Path2[1]) + { + CComPtr pItem; + if (SUCCEEDED(SHCreateItemFromIDList(m_Path2[1],IID_IShellItem,(void**)&pItem))) + { + CComString pName; + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName))) + { + pName.MakeUpper(); + m_FolderHash[1]=CalcFNVHash(pName,m_FolderHash[1]); + } + AddSecondFolder(pItem,items,m_Options); + } + } + if (!items.empty()) + { + if (!m_Items.empty()) + { + MenuItem item(MENU_SEPARATOR); + item.priority=1; + m_Items.push_back(item); + } + for (std::vector::iterator it=items.begin();it!=items.end();++it) + it->priority=2; + m_Items.insert(m_Items.end(),items.begin(),items.end()); + } + } + + // sort m_Items or read order from the registry + LoadItemOrder(); + + if (m_Items.size()>MAX_MENU_ITEMS) + { + for (size_t i=MAX_MENU_ITEMS;i::iterator it=m_Items.begin();it!=m_Items.end();++it) + if (it->nameHash==AdminToolsHash) + { + it->bFolder=true; + break; + } + } + + if (m_Items.empty() && m_Path1[0] && m_pDropFolder[0]) + { + // add (Empty) item to the empty submenus + MenuItem item(m_bSubMenu?MENU_EMPTY:MENU_EMPTY_TOP); + item.name=FindTranslation(L"Menu.Empty",L"(Empty)"); + m_Items.push_back(item); + } + + if (!m_bSubMenu) + { + for (std::vector::iterator it=m_Items.begin();it!=m_Items.end();++it) + { + MenuItem &item=*it; + if (item.bLink && !item.bFolder && item.pItem1) + g_ItemManager.UpdateItemInfo(item.pItemInfo,CItemManager::INFO_LINK_APPID); + } + } + + if (m_Options&CONTAINER_RECENT) + { + int nRecent=GetSettingInt(L"MaxRecentPrograms"); + if (nRecent<0) + nRecent=-nRecent; + if (nRecent>MRU_PROGRAMS_COUNT) nRecent=MRU_PROGRAMS_COUNT; + if (nRecent>0) + { + // prepend recent programs + std::vector items; + GetRecentPrograms(items,nRecent); + if (!items.empty()) + { + MenuItem item(MENU_SEPARATOR); + if (GetSettingBool(L"RecentProgsTop")) + { + items.push_back(item); + m_Items.insert(m_Items.begin(),items.begin(),items.end()); + } + else + { + m_Items.push_back(item); + m_Items.insert(m_Items.end(),items.begin(),items.end()); + } + } + } + } + + if (!m_bSubMenu && GetSettingBool(L"EnableJumplists")) + { + for (std::vector::iterator it=m_Items.begin();it!=m_Items.end();++it) + { + MenuItem &item=*it; + if (item.bLink && !item.bFolder && item.pItem1) + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + item.bFolder=(!item.pItemInfo->GetAppid().IsEmpty() && HasJumplist(item.pItemInfo->GetAppid())); + item.bHasJumpList=item.bFolder; + item.bSplit=item.bFolder; + } + } + } + + m_ScrollCount=(int)m_Items.size(); + if (m_ScrollCount>0 && m_Items[m_ScrollCount-1].id==MENU_PROGRAMS_TREE) + m_ScrollCount--; + + if (s_bWin7Style && !m_bSubMenu && GetSettingInt(L"ProgramsStyle")!=PROGRAMS_HIDDEN) + { + MenuItem item(MENU_PROGRAMS_TREE); + m_Items.push_back(item); + } + AddStandardItems(); + + // remove trailing separators + while (!m_Items.empty() && m_Items[m_Items.size()-1].id==MENU_SEPARATOR && !m_Items[m_Items.size()-1].bInline) + m_Items.pop_back(); + + if (m_Items.empty()) + { + // add (Empty) item to the empty submenus + MenuItem item(MENU_EMPTY); + item.name=FindTranslation(L"Menu.Empty",L"(Empty)"); + m_Items.push_back(item); + } + + if (m_bSubMenu) + { + m_ScrollCount=(int)m_Items.size(); + m_SearchIndex=-1; + for (int i=0;i<(int)m_Items.size();i++) + { + if (m_Items[i].id==MENU_SEARCH_BOX) + m_SearchIndex=i; + } + } + else + { + m_ProgramButtonIndex=m_ProgramTreeIndex=-1; + m_SearchIndex=-1; + for (int i=0;i<(int)m_Items.size();i++) + { + if (m_Items[i].id==MENU_PROGRAMS_TREE) + m_ProgramTreeIndex=i; + if (m_Items[i].id==MENU_PROGRAMS) + m_ProgramButtonIndex=i; + if (m_Items[i].id==MENU_SEARCH_BOX) + m_SearchIndex=i; + } + m_SearchItemCount=1; + if (s_bWin7Style) + m_SearchItemCount=m_SearchProvidersCount+2; + } + + m_OriginalCount=(int)m_Items.size(); + m_OriginalScrollCount=m_ScrollCount; + UpdateAccelerators(0,m_OriginalCount); +} + +int CMenuContainer::AddSearchItems( const std::vector &items, const CString &categoryName, unsigned int categoryHash, int originalCount ) +{ + if (m_Items.size()>MAX_MENU_ITEMS-2) + return 0; + bool bFirst=true; + int count=0; + for (std::vector::const_iterator it=items.begin();it!=items.end();++it) + { + CComPtr pItem; + if (FAILED(SHCreateItemFromIDList(it->info->GetPidl(),IID_IShellItem,(void**)&pItem))) + continue; + + CComString pName; + if (SUCCEEDED(pItem->GetDisplayName(categoryHash==CSearchManager::CATEGORY_AUTOCOMPLETE?SIGDN_PARENTRELATIVEEDITING:SIGDN_NORMALDISPLAY,&pName))) + { + if (bFirst) + { + bFirst=false; + if (!categoryName.IsEmpty()) + { + MenuItem item(MENU_SEARCH_CATEGORY); + if (categoryHash==CSearchManager::CATEGORY_PROGRAM || categoryHash==CSearchManager::CATEGORY_SETTING) + { + item.name.Format(L"%s (%d)",categoryName,originalCount); + } + else + { + item.name=categoryName; + item.bSplit=(s_Skin.More_bitmap_Size.cx>0); + } + item.nameHash=CalcFNVHash(categoryName); + item.categoryHash=categoryHash; + m_Items.push_back(item); + } + } + + MenuItem item(MENU_NO); + item.categoryHash=categoryHash; + item.pItemInfo=it->info; + g_ItemManager.UpdateItemInfo(it->info,CItemManager::INFO_SMALL_ICON); + bool bMetroLink, bMetroApp; + CString metroName; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + bMetroLink=item.pItemInfo->IsMetroLink(); + bMetroApp=item.pItemInfo->IsMetroApp(); + if (bMetroLink) + metroName=item.pItemInfo->GetMetroName(); + } + if (!it->name.IsEmpty()) + item.SetName(it->name,false); + else if (bMetroLink && !metroName.IsEmpty()) + item.SetName(metroName,false); + else + item.SetName(pName,(m_Options&CONTAINER_NOEXTENSIONS)!=0); + item.bMetroLink=bMetroLink; + item.bMetroApp=bMetroApp; + item.pItem1=ILCloneFull(it->info->GetPidl()); + wchar_t name[_MAX_PATH]; + Strcpy(name,_countof(name),item.name); + CharUpper(name); + item.nameHash=CalcFNVHash(name,categoryHash); + m_Items.push_back(item); + count++; + } + } + return count; +} + +// Initialize the m_Items list with the search results +bool CMenuContainer::InitSearchItems( void ) +{ + if (m_bSubMenu) + ClearItems(m_Items.begin(),m_Items.end()); + else + ClearItems(m_Items.begin()+m_OriginalCount,m_Items.end()); + m_RefreshPosted=0; + SetSubmenu(-1); + SetContextItem(-1); + s_HotPos=GetMessagePos(); + m_ScrollCount=0; + g_SearchManager.GetSearchResults(s_SearchResults); + bool bAutoComlpete=!s_SearchResults.autoCompletePath.IsEmpty(); + m_SearchScrollCount=0; + m_SearchScrollHeight=0; + m_SearchScrollPos=0; + unsigned int runCategoryHash=0; + CString runCommand; + CComString runExe; + if (!bAutoComlpete && !s_bNoRun && s_SearchResults.programs.empty() && s_SearchResults.settings.empty()) + { + if (s_bWin7Style) + m_SearchBox.GetWindowText(runCommand); + else + m_pParent->m_SearchBox.GetWindowText(runCommand); + + // validate execute item + if (_wcsnicmp(runCommand,L"www.",4)==0 || _wcsnicmp(runCommand,L"http:",5)==0) + runCategoryHash=CSearchManager::CATEGORY_INTERNET; + else if (_wcsnicmp(runCommand,L"shell:",6)==0) + { + CAbsolutePidl pidl; + if (SUCCEEDED(SHParseDisplayName(runCommand,NULL,&pidl,0,NULL))) + runCategoryHash=CSearchManager::CATEGORY_PROGRAM; + } + else if (wcsncmp(runCommand,L"\\\\",2)!=0 && SUCCEEDED(SHEvaluateSystemCommandTemplate(runCommand,&runExe,NULL,NULL))) + runCategoryHash=CSearchManager::CATEGORY_PROGRAM; + if (runCategoryHash) + s_SearchResults.programs.push_back(NULL); + } + std::vector items; + std::vector counts; + int sepHeight=0, itemHeight=0, maxHeight=0, reservedHeight=0; + int maxCount=0; + if (s_bWin7Style) + { + sepHeight=s_Skin.ItemSettings[s_Skin.More_bitmap_Size.cx?MenuSkin::LIST_SEPARATOR_SPLIT:MenuSkin::LIST_SEPARATOR].itemHeight; + itemHeight=s_Skin.ItemSettings[MenuSkin::LIST_ITEM].itemHeight; + // total height minus the search box and the "more results"/"search internet" + maxHeight=m_Items[m_SearchIndex].itemRect.top-s_Skin.Main_search_padding.top-s_Skin.Search_padding.top; + maxHeight-=itemHeight*(m_SearchItemCount-1); + if (!s_SearchResults.bSearching && !HasMoreResults()) + maxHeight+=itemHeight; + } + if (bAutoComlpete) + { + items.reserve(s_SearchResults.autocomplete.size()); + for (std::vector::const_iterator it=s_SearchResults.autocomplete.begin();it!=s_SearchResults.autocomplete.end() && (int)items.size()::const_iterator it=s_SearchResults.indexed.begin();it!=s_SearchResults.indexed.end();++it) + { + if (!it->items.empty()) + { + counts.push_back((int)it->items.size()); + if (m_SearchCategoryHash==it->categoryHash) + selectedCount=(int)it->items.size(); + } + } + + int n=(int)counts.size(); + if (n>0) + { + int totalCount=(maxHeight-n*sepHeight)/itemHeight; + maxCount=1; + if (totalCount>n) + { + std::sort(counts.begin(),counts.end()); + for (int i=0;i0?(sepHeight+selectedCount*itemHeight):0; + if (reservedHeight>maxHeight) reservedHeight=maxHeight; + maxHeight-=reservedHeight; + } + } + + // add categories + std::list::const_iterator it=s_SearchResults.indexed.begin(); + for (size_t idx=0;idxcategoryHash; + + int count=0; + if (s_bWin7Style) + { + int h=(categoryHash==m_SearchCategoryHash?reservedHeight:maxHeight); + count=(h-sepHeight)/itemHeight; + if (categoryHash!=m_SearchCategoryHash && count>maxCount) + count=maxCount; + } + else + { + count=GetSettingInt(categoryHash==m_SearchCategoryHash?L"SearchResultsMax":L"SearchResults"); + } + if (count<=0) + { + if (idx>=2) ++it; + continue; + } + + const wchar_t *name; + int originalCount=0; + if (idx==0) + { + originalCount=(int)s_SearchResults.programs.size(); + if (count>originalCount) + count=originalCount; + items.reserve(count); + for (std::vector::const_iterator it=s_SearchResults.programs.begin();it!=s_SearchResults.programs.end() && (int)items.size()originalCount) + count=originalCount; + items.reserve(count); + for (std::vector::const_iterator it=s_SearchResults.settings.begin();it!=s_SearchResults.settings.end() && (int)items.size()items.size(); + if (count>originalCount) + count=originalCount; + items.reserve(count); + for (int i=0;iitems[i].pidl; + CComPtr pItem; + if (SUCCEEDED(SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pItem))) + items.push_back(SearchItem(it->items[i].name,g_ItemManager.GetItemInfo(pItem,pidl,0))); + } + name=it->name; + ++it; + } + if (items.empty()) + continue; + if (idx==0 && runCategoryHash) + { + MenuItem item1(MENU_SEARCH_CATEGORY); + item1.categoryHash=runCategoryHash; + item1.name=runCategoryHash==CSearchManager::CATEGORY_INTERNET?FindTranslation(L"Search.CategoryInternet",L"Internet"):FindTranslation(L"Search.CategoryPrograms",L"Programs"); + item1.nameHash=CalcFNVHash(item1.name); + m_Items.push_back(item1); + + MenuItem item2(MENU_SEARCH_EXECUTE); + item2.name=runCommand; + if (runCategoryHash==CSearchManager::CATEGORY_INTERNET) + item2.pItemInfo=GetInternetIcon(true); + else if (runExe) + { + item2.pItemInfo=g_ItemManager.GetItemInfo(CString(runExe),CItemManager::INFO_SMALL_ICON); + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + item2.pItem1=ILCloneFull(item2.pItemInfo->GetPidl()); + } + else + item2.pItemInfo=g_ItemManager.GetCustomIcon(L"imageres.dll,100",CItemManager::ICON_SIZE_TYPE_SMALL); + m_Items.push_back(item2); + count=1; + } + else + { + count=AddSearchItems(items,name,categoryHash,originalCount); + } + if (s_bWin7Style && categoryHash!=m_SearchCategoryHash && count>0) + maxHeight-=sepHeight+count*itemHeight; + } + if (s_bWin7Style) + { + UpdateAccelerators(m_OriginalCount,(int)m_Items.size()); + MenuItem &item=m_Items[m_SearchIndex-m_SearchItemCount+1]; + if (s_SearchResults.bSearching) + { + item.id=MENU_SEARCH_EMPTY; + item.name=FindTranslation(L"Menu.Searching",L"Searching..."); + item.pItemInfo=g_ItemManager.GetCustomIcon(L"imageres.dll,8",CItemManager::ICON_SIZE_TYPE_SMALL); + } + else + { + item.id=MENU_MORE_RESULTS; + item.name=FindTranslation(L"Menu.MoreResults",L"See more results"); + item.pItemInfo=g_ItemManager.GetCustomIcon(L"imageres.dll,177",CItemManager::ICON_SIZE_TYPE_SMALL); + } + } + else + { + m_ScrollCount=(int)m_Items.size(); + bool bInternet=GetSettingBool(L"SearchInternet"); + if (s_SearchResults.bSearching) + { + MenuItem item(MENU_SEARCH_EMPTY); + item.name=FindTranslation(L"Menu.Searching",L"Searching..."); + item.pItemInfo=g_ItemManager.GetCustomIcon(L"imageres.dll,8",CItemManager::ICON_SIZE_TYPE_SMALL); + m_Items.push_back(item); + } + else + { + if (m_Items.empty()) + { + MenuItem item(MENU_SEARCH_EMPTY); + item.name=FindTranslation(L"Menu.NoMatch",L"No items match your search."); + m_Items.push_back(item); + } + if (HasMoreResults()) + { + { + MenuItem item(MENU_SEPARATOR); + m_Items.push_back(item); + } + MenuItem item(MENU_MORE_RESULTS); + item.name=FindTranslation(L"Menu.MoreResults",L"See more results"); + item.pItemInfo=g_ItemManager.GetCustomIcon(L"imageres.dll,177",CItemManager::ICON_SIZE_TYPE_SMALL); + m_Items.push_back(item); + } + else if (bInternet) + { + MenuItem item(MENU_SEPARATOR); + m_Items.push_back(item); + } + if (bInternet) + AddInternetSearch(m_Items.size()); + } + AddStandardItems(); + UpdateAccelerators(m_ScrollCount,(int)m_Items.size()); + } + + if (!s_SearchResults.bSearching && (m_Items.empty() || (m_bTwoColumns && m_Items.size()==m_OriginalCount))) + { + MenuItem item(MENU_SEARCH_EMPTY); + item.name=FindTranslation(L"Menu.NoMatch",L"No items match your search."); + m_Items.push_back(item); + } + return s_SearchResults.bSearching; +} + +HBITMAP CMenuContainer::GetArrowsBitmap( unsigned int color ) +{ + if (!s_ArrowsBitmap) + { + int id=s_Skin.Dpi>=144?IDB_ARROWS150:IDB_ARROWS; + s_ArrowsBitmap=(HBITMAP)LoadImage(g_Instance,MAKEINTRESOURCE(id),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION); + s_LastArrowColor=0xFFFFFF; + } + if (s_LastArrowColor!=color) + { + s_LastArrowColor=color; + color=0xFF000000|(color<<16)|(color&0xFF00)|((color>>16)&0xFF); + BITMAP info; + GetObject(s_ArrowsBitmap,sizeof(info),&info); + int n=info.bmWidth*info.bmHeight; + for (int p=0;p>24)*0x01010101)&color; + } + } + return s_ArrowsBitmap; +} + +// Calculate the size and create the background bitmaps +void CMenuContainer::InitWindow( bool bDontShrink ) +{ + POINT corner; + RECT rc; + GetWindowRect(&rc); + corner.x=(m_Options&CONTAINER_LEFT)?rc.left:rc.right; + corner.y=(m_Options&CONTAINER_TOP)?rc.top:rc.bottom; + RECT menuRect; + InitWindowInternal(bDontShrink,corner,menuRect); + InitWindowFinalize(menuRect); +} + +void CMenuContainer::InitWindowInternal( bool bDontShrink, const POINT &corner, RECT &menuRect ) +{ + bool bRecentReverse=GetSettingInt(L"MaxRecentPrograms")<0; + bool bRecentByName=GetSettingBool(L"RecentSortName"); + + int firstRecent=-1, lastRecent=-1; + if ((bRecentReverse || bRecentByName) && (!m_bSubMenu || (m_Options&CONTAINER_RECENT))) + { + for (int i=0;i<(int)m_Items.size();i++) + { + if (m_Items[i].id==MENU_RECENT) + { + if (firstRecent==-1) firstRecent=i; + lastRecent=i+1; + } + else if (firstRecent!=-1) + break; + } + if (firstRecent>=0) + std::sort(m_Items.begin()+firstRecent,m_Items.begin()+lastRecent,MenuItem::MruOrderComparator()); + } + + m_bTwoColumns=(!m_bSubMenu && s_Skin.TwoColumns); + if (!m_pParent && !s_Theme && IsAppThemed()) + { + s_Theme=OpenThemeData(m_hWnd,L"toolbar"); + s_PagerTheme=OpenThemeData(m_hWnd,L"scrollbar"); + } + if (!m_pParent && !s_Tooltip.m_hWnd) + { + s_Tooltip=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_TRANSPARENT|(s_bRTL?WS_EX_LAYOUTRTL:0),TOOLTIPS_CLASS,NULL,WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP,0,0,0,0,NULL,NULL,g_Instance,NULL); + s_Tooltip.SendMessage(TTM_SETMAXTIPWIDTH,0,500); + TOOLINFO tool={sizeof(tool),TTF_ABSOLUTE|TTF_TRACK|TTF_TRANSPARENT|(s_bRTL?TTF_RTLREADING:0)}; + tool.uId=1; + s_Tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + } + RECT menuPadding[2]; + if (m_bSubMenu) + { + menuPadding[0]=s_Skin.Submenu_padding; + memset(&menuPadding[1],0,sizeof(menuPadding[1])); + } + else if (s_MenuMode==MODE_SEARCH) + { + menuPadding[0]=s_Skin.Main_search_padding; + memset(&menuPadding[1],0,sizeof(menuPadding[1])); + } + else if (s_MenuMode==MODE_JUMPLIST) + { + menuPadding[0]=s_Skin.Main_padding; + menuPadding[1]=s_Skin.Main_jump_padding; + } + else + { + menuPadding[0]=s_Skin.Main_padding; + menuPadding[1]=s_Skin.Main2_padding; + } + + // calculate maximum height + int maxHeight[2]; // excluding padding + int maxWidth=m_MaxWidth; + int borderHeight=0; + { + const RECT &mainRect=m_bSubMenu?s_MenuLimits:s_MainMenuLimits; + maxHeight[0]=maxHeight[1]=(mainRect.bottom-mainRect.top); + // adjust for padding + RECT rc={0,0,0,0}; + AdjustWindowRect(&rc,GetWindowLong(GWL_STYLE),FALSE); + maxWidth-=rc.right-rc.left; + maxWidth-=menuPadding[0].left+menuPadding[0].right; + if (m_bSubMenu) + { + borderHeight=rc.bottom; + maxHeight[0]-=menuPadding[0].top+menuPadding[0].bottom; + } + else + { + if (m_Options&CONTAINER_TOP) + maxHeight[0]=maxHeight[1]=mainRect.bottom-corner.y; + else + maxHeight[0]=maxHeight[1]=corner.y-mainRect.top; + maxHeight[0]-=rc.bottom-rc.top; + maxHeight[1]-=rc.bottom-rc.top; + maxHeight[0]-=menuPadding[0].top+menuPadding[0].bottom; + maxHeight[1]-=menuPadding[1].top+menuPadding[1].bottom; + if (s_UserPicture.m_hWnd && !(m_Options&CONTAINER_TOP) && s_Skin.User_bitmap_outside) + { + maxHeight[0]-=s_Skin.User_bitmapSize.cy-s_Skin.User_frame_position.x; + maxHeight[1]-=s_Skin.User_bitmapSize.cy-s_Skin.User_frame_position.x; + } + } + } +#ifdef _DEBUG +// maxHeight[0]/=3; maxHeight[1]/=3; // uncomment to test for smaller screen +#endif + + HDC hdc=CreateCompatibleDC(NULL); + int arrowSize[2]; + if (m_bSubMenu) + { + const MenuSkin::ItemDrawSettings &settings=s_Skin.ItemSettings[MenuSkin::SUBMENU_ITEM]; + arrowSize[0]=settings.arrPadding.cx+settings.arrPadding.cy; + if (m_Options&CONTAINER_JUMPLIST) + arrowSize[0]+=s_Skin.Pin_bitmap_Size.cx; + else + arrowSize[0]+=settings.arrSize.cx; + } + else + { + const MenuSkin::ItemDrawSettings &settings=s_Skin.ItemSettings[MenuSkin::COLUMN1_ITEM]; + arrowSize[0]=settings.arrPadding.cx+settings.arrPadding.cy+settings.arrSize.cx; + } + { + const MenuSkin::ItemDrawSettings &settings=s_Skin.ItemSettings[MenuSkin::COLUMN2_ITEM]; + arrowSize[1]=settings.arrPadding.cx+settings.arrPadding.cy+settings.arrSize.cx; + } + int expandoSize=s_Skin.GetArrowsBitmapSizes()[6].y; + + HGDIOBJ font0=GetCurrentObject(hdc,OBJ_FONT); + int fixedWidth[2]={-1,-1}; + int maxItemWidth[2]={65536,65536}; + if (m_bSubMenu) + { + int numChar=GetSettingInt(L"MaxMenuWidth"); + maxItemWidth[0]=numChar?s_Skin.ItemSettings[MenuSkin::SUBMENU_ITEM].textMetrics.tmAveCharWidth*numChar:65536; + } + else + { + int numChar=GetSettingInt(L"MaxMainMenuWidth"); + int width=s_Skin.ItemSettings[MenuSkin::COLUMN1_ITEM].textMetrics.tmAveCharWidth; + maxItemWidth[0]=numChar?width*numChar:65536; + maxItemWidth[1]=numChar?s_Skin.ItemSettings[MenuSkin::COLUMN2_ITEM].textMetrics.tmAveCharWidth*numChar:65536; + if (s_bWin7Style) + { + if (s_MenuMode==MODE_SEARCH) + { + fixedWidth[0]=s_MenuWidthNormal-s_Skin.Main_search_padding.left-s_Skin.Main_search_padding.right; + fixedWidth[1]=0; + maxItemWidth[0]=65536; + } + else if (s_MenuMode==MODE_JUMPLIST) + { + fixedWidth[0]=width*s_ProgramsWidth; + fixedWidth[1]=width*s_JumplistWidth; + maxItemWidth[0]=65536; + maxItemWidth[1]=65536; + } + else + { + fixedWidth[0]=width*s_ProgramsWidth; + maxItemWidth[0]=65536; + maxItemWidth[1]=65536; + } + } + s_MenuWidthJump=width*(s_ProgramsWidth+s_JumplistWidth)+s_Skin.Main_padding.left+s_Skin.Main_padding.right+s_Skin.Main_jump_padding.left+s_Skin.Main_jump_padding.right; + } + m_ScrollButtonSize=s_Skin.ItemSettings[m_bSubMenu?MenuSkin::SUBMENU_ITEM:MenuSkin::COLUMN1_ITEM].itemHeight; + if (!s_bHasTouch) + m_ScrollButtonSize/=2; + if (m_ScrollButtonSize columnWidths; + columnWidths.push_back(0); + + bool bMultiColumn=s_ScrollMenus!=0 && (m_Options&CONTAINER_MULTICOLUMN); + int shutdownIndex=-1; + + { + int row=0, column=0, subColumn=0; + int y=0; + int maxw=0; + int index=0; + for (int i=0;i<(int)m_Items.size();i++) + { + MenuItem &item=m_Items[i]; + + if (m_bTwoColumns && column==0 && i>0 && item.bBreak) + { + // start a new column + column++; + columnWidths.push_back(0); + row=0; + y=0; + if (s_UserPicture.m_hWnd) + { + if (!s_Skin.User_bitmap_outside || (m_Options&CONTAINER_TOP)) + y=s_Skin.User_bitmapSize.cy+s_Skin.User_image_padding.x+s_Skin.User_image_padding.y; + else + y=s_Skin.User_frame_position.x+s_Skin.User_image_padding.y-menuPadding[0].top; + } + index=1; + } + item.bNew=false; + if (m_bTwoColumns && im_SearchIndex) && item.id!=MENU_SHUTDOWN_BUTTON) + { + // hide original items based on mode + if (s_MenuMode==MODE_JUMPLIST) + { + if (column==1) + { + item.itemRect.top=item.itemRect.bottom=0; + continue; + } + } + if (s_MenuMode==MODE_SEARCH) + { + item.itemRect.top=item.itemRect.bottom=0; + continue; + } + } + if (i==m_OriginalCount) + { + y=0; + row=0; + column=index=(s_MenuMode==MODE_JUMPLIST)?1:0; + if (column==1 && columnWidths.size()==1) + columnWidths.push_back(0); + } + if (item.id!=MENU_RECENT && !(m_Options&CONTAINER_SEARCH) && s_Skin.bHasNewItem && i=WIN_VER_WIN8 && GetSettingBool(L"AllProgramsMetro")) + item.bNew=g_ItemManager.HasNewPrograms(false) || g_ItemManager.HasNewApps(false); + else + item.bNew=g_ItemManager.HasNewPrograms(false); + } + else if (item.id==MENU_APPS) + item.bNew=g_ItemManager.HasNewApps(false); + else if (item.bFolder) + item.bNew=(item.pItem1 && g_ItemManager.IsNewProgram(item.pItem1,true,false)) || (item.pItem2 && g_ItemManager.IsNewProgram(item.pItem2,true,false)); + else if (item.pItemInfo) + item.bNew=(item.pItem1 && g_ItemManager.IsNewProgram(item.pItem1,false,item.bMetroApp)); + } + if (item.id==MENU_SHUTDOWN_BUTTON) + { + if (s_MenuMode==MODE_SEARCH) + item.drawType=MenuSkin::SHUTDOWN_BUTTON_SEARCH; + else if (s_MenuMode==MODE_JUMPLIST) + item.drawType=MenuSkin::SHUTDOWN_BUTTON_JUMP; + else + item.drawType=MenuSkin::SHUTDOWN_BUTTON; + } + else if (s_bWin7Style && item.id==MENU_SEARCH_CATEGORY) + { + item.drawType=(item.bSplit)?MenuSkin::LIST_SEPARATOR_SPLIT:MenuSkin::LIST_SEPARATOR; + } + else if (s_bWin7Style && item.id==MENU_PROGRAMS) + { + if (GetSettingInt(L"ProgramsStyle")==PROGRAMS_INLINE) + item.drawType=item.bNew?MenuSkin::PROGRAMS_BUTTON_NEW:MenuSkin::PROGRAMS_BUTTON; + else + item.drawType=item.bNew?MenuSkin::PROGRAMS_CASCADING_NEW:MenuSkin::PROGRAMS_CASCADING; + } + else if (s_bWin7Style && m_bTwoColumns && (s_MenuMode==MODE_SEARCH || s_MenuMode==MODE_JUMPLIST) && i>=m_OriginalCount) + { + if (item.id==MENU_SEPARATOR) + item.drawType=MenuSkin::LIST_SEPARATOR; + else if (item.jumpIndex<0) + item.drawType=MenuSkin::LIST_ITEM; + else + item.drawType=(s_JumpList.groups[LOWORD(item.jumpIndex)].type==CJumpGroup::TYPE_TASKS)?MenuSkin::LIST_ITEM:MenuSkin::LIST_SPLIT; + } + else if (s_bWin7Style && (i>m_SearchIndex-m_SearchItemCount && i1 && (m_Items[i].id==MENU_EMPTY_TOP || (i>0 && m_Items[i-1].id==MENU_EMPTY_TOP))) + h=0; // this is the first (Empty) item in the top menu. hide it for now + else if (item.bInline) + { + h=iconSize+settings.iconPadding.top+settings.iconPadding.bottom; + w=iconSize+settings.iconPadding.left+settings.iconPadding.right; + } + else if ((item.id==MENU_SEPARATOR || item.id==MENU_SEARCH_CATEGORY) && !item.bBlankSeparator) + { + if (!item.name.IsEmpty()) + { + h=settings.itemHeight; + RECT rcText={0,0,0,0}; + DrawText(hdc,item.name,-1,&rcText,DT_CALCRECT|DT_SINGLELINE|DT_HIDEPREFIX); + w=rcText.right; + if (w>maxItemWidth[index]) w=maxItemWidth[index]; + int textEnd=w; + w+=settings.textPadding.left+settings.textPadding.right+arrowSize[index]; + int textStart=settings.textPadding.left; + if (item.id==MENU_SEARCH_CATEGORY) + { + w+=settings.iconPadding.left+settings.iconPadding.right+expandoSize; + textStart+=settings.iconPadding.left+settings.iconPadding.right+expandoSize; + if (item.bSplit) + w+=settings.arrPadding.cx+settings.arrPadding.cy+s_Skin.More_bitmap_Size.cx+1; + } + textEnd+=textStart; + item.textStart=(short)textStart; + item.textEnd=(short)textEnd; + } + else if (y>0 || (i>0 && i==m_ProgramTreeIndex+1)) + h=settings.sepHeight; + else + h=0; // ignore separators at the top of the column + } + else if (item.id==MENU_SEARCH_BOX) + { + h=settings.textMetrics.tmHeight*12/8+s_Skin.Search_padding.top+s_Skin.Search_padding.bottom; // 12 DLUs + w=settings.textMetrics.tmAveCharWidth*25; + } + else if (s_bWin7Style && i>m_SearchIndex-m_SearchItemCount && imaxItemWidth[index]) w=maxItemWidth[index]; + w+=settings.iconPadding.left+settings.iconPadding.right+settings.textPadding.left+settings.textPadding.right+arrowSize[index]+iconSize; + } + if (bMultiColumn && y>0 && y+h>maxHeight[0]) + { + if (item.id==MENU_SEPARATOR && !item.bBlankSeparator && !item.bInline) + h=0; // ignore separators at the bottom of the column + else + { + // start a new column + column++; + columnWidths.push_back(0); + row=0; + y=0; + } + } + else if (item.id==MENU_SEPARATOR && !item.bBlankSeparator && !item.bInline && m_bTwoColumns && column==0 && i+1<(int)m_Items.size() && m_Items[i+1].bBreak) + h=0; + item.row=row; + item.column=column; + item.itemRect.top=y; + item.itemRect.bottom=y+h; + item.itemRect.left=0; + if (item.bInline) + { + if (item.bInlineFirst) + { + subColumn=0; + } + else + { + item.row=row=row-1; + item.itemRect.top-=h; + item.itemRect.bottom-=h; + h=0; + } + item.itemRect.left=w*subColumn; + if (item.id==MENU_SEPARATOR) + { + w=0; + subColumn--; + } + subColumn++; + } + item.itemRect.right=item.itemRect.left+w; + if (columnWidths[column]=0) + columnWidths[0]=fixedWidth[0]; + if (fixedWidth[1]>=0) + columnWidths[1]=fixedWidth[1]; + } + + if (s_ScrollMenus==2 && columnWidths.size()>1 && m_bSubMenu) + { + // auto - determine if we should have 1 column or many + int width=0; + for (size_t i=0;i0) width+=s_Skin.Submenu_separatorWidth; + width+=columnWidths[i]; + } + if (width>maxWidth) + { + bMultiColumn=false; + // the columns don't fit on screen, switch to one scrollable column + int y=0; + columnWidths.resize(1); + columnWidths[0]=0; + for (size_t i=0;i0) maxw+=m_bSubMenu?s_Skin.Submenu_separatorWidth:s_Skin.Main_separatorWidth; + m_ColumnOffsets[i]=maxw; + maxw+=columnWidths[i]; + } + columnWidths.push_back(maxw); + bool bInline=false; + for (int i=0;i<(int)m_Items.size();i++) + { + MenuItem &item=m_Items[i]; + if (item.bInline) + { + item.itemRect.left+=m_ColumnOffsets[item.column]; + item.itemRect.right+=m_ColumnOffsets[item.column]; + bInline=true; + } + else if (item.id==MENU_SHUTDOWN_BUTTON) + { + int x=s_Skin.ItemSettings[MenuSkin::COLUMN1_ITEM].textMetrics.tmAveCharWidth*s_ProgramsWidth; + x+=s_Skin.Main_padding.left+s_Skin.Main_padding.right+s_Skin.Main2_padding.left; + item.itemRect.right+=x-item.itemRect.left; + item.itemRect.left=x; + } + else if (s_bWin7Style && item.id==MENU_SEARCH_BOX) + { + item.itemRect.left=0; + item.itemRect.right=s_Skin.ItemSettings[MenuSkin::COLUMN1_ITEM].textMetrics.tmAveCharWidth*s_ProgramsWidth; + } + else + { + item.itemRect.left=m_ColumnOffsets[item.column]; + item.itemRect.right=item.itemRect.left+columnWidths[item.column]; + if (s_MenuMode==MODE_SEARCH && !m_bSubMenu && (item.id==MENU_NO || item.id==MENU_SEARCH_EXECUTE) && i>=m_OriginalCount) + { + if ((item.categoryHash&CSearchManager::CATEGORY_MASK)!=CSearchManager::CATEGORY_AUTOCOMPLETE) + item.itemRect.left+=s_Skin.Main_search_indent; + else if (s_bWin7Style) + item.itemRect.right-=scrollWidth; + } + } + if (m_bTwoColumns) + { + if (maxh[item.column]=0) + { + m_Items[first].bInlineFirst=true; + m_Items[last].bInlineLast=true; + } + } + } + } + } + + if (m_Bitmap) + { + DeleteObject(m_Bitmap); + m_Bitmap=NULL; + } + if (m_Region) + { + DeleteObject(m_Region); + m_Region=NULL; + } + + m_ExtraTop=m_ExtraBottom=m_ExtraBorder=0; + if (!bMultiColumn && maxh[0]>maxHeight[0] && m_ScrollCount>0 && m_bSubMenu) + { + int d=menuPadding[0].top+menuPadding[0].bottom+maxh[0]-maxHeight[1]; + if (d<=menuPadding[0].top) + m_ExtraTop=d; + else + { + m_ExtraTop=menuPadding[0].top; + d-=menuPadding[0].top; + if (d<=menuPadding[0].bottom) + m_ExtraBottom=d; + else + m_ExtraBottom=menuPadding[0].bottom; + } + m_ExtraBorder=borderHeight; + maxHeight[0]=maxHeight[1]; + } + + int totalWidth, totalHeight; + memset(&m_rContent2,0,sizeof(m_rContent2)); + bool bSetMenuSize=(s_MenuHeight==-1); + if (!m_bSubMenu) + { + if (s_MenuMaxHeight[0]==-1) + { + s_MenuMaxHeight[0]=maxh[0]; + s_MenuMaxHeight[1]=maxh[1]; + } + else if (bSetMenuSize) + { + maxh[0]=s_MenuMaxHeight[0]; + maxh[1]=s_MenuMaxHeight[1]; + } + } + { + int w1=maxw, w2=0; + int h1=(maxh[0]2) + { + w1=columnWidths[0]; + w2=columnWidths[1]; + + if (s_bWin7Style) + { + if (bSetMenuSize) + { + int minh=s_Skin.ItemSettings[MenuSkin::LIST_ITEM].itemHeight*GetSettingInt(L"MinMainHeight"); + if (h1q) + s_MenuHeight=q; + } + h1=s_MenuHeight-menuPadding[0].top-menuPadding[0].bottom; + h2=s_MenuHeight-menuPadding[1].top-menuPadding[1].bottom; + } + } + if (!m_bSubMenu) + { + if (s_bWin7Style) + { + s_BackgroundW1=w1; + s_BackgroundW2=w2; + s_BackgroundH1=h1; + s_BackgroundH2=h2; + if (s_OldMenuState.mode==MODE_UNKNOWN) + CreateBackground(w1,w2,h1,h2,totalWidth,totalHeight,true); + else + CreateContentRects(w1,w2,h1,h2,totalWidth,totalHeight); + } + else if (s_Skin.Main_bitmap.GetBitmap() || s_Skin.User_image_size || m_bTwoColumns || s_Skin.User_name_position.left!=s_Skin.User_name_position.right) + { + CreateBackground(w1,w2,h1,h2,totalWidth,totalHeight,true); + } + else + { + m_rContent.left=menuPadding[0].left; + m_rContent.top=menuPadding[0].top; + m_rContent.right=menuPadding[0].left+w1; + m_rContent.bottom=menuPadding[0].top+h1; + totalWidth=menuPadding[0].left+menuPadding[0].right+w1; + totalHeight=menuPadding[0].top+menuPadding[0].bottom+h1; + } + if (bSetMenuSize) + { + s_MenuWidthMax=s_MenuWidthJump; + if (s_MenuWidthMax2) + { + int dh1=0, dh2=0; + for (int i=0;i0) + { + // remove extra programs + std::vector::reverse_iterator pBegin=m_Items.rend(), pEnd=m_Items.rend(); // pinned + std::vector::reverse_iterator rBegin=m_Items.rend(), rEnd=m_Items.rend(); // recent + for (std::vector::reverse_iterator it=m_Items.rbegin();it!=m_Items.rend();++it) + { + if (it->id==MENU_NO && it->column==0) + { + if (pBegin==m_Items.rend()) + pBegin=it; + } + else + { + if (pEnd==m_Items.rend() && pBegin!=m_Items.rend()) + pEnd=it; + } + + if (it->id==MENU_RECENT && it->column==0) + { + if (rBegin==m_Items.rend()) + rBegin=it; + } + else + { + if (rEnd==m_Items.rend() && rBegin!=m_Items.rend()) + rEnd=it; + } + } + + // remove recent + int dy=0; + for (std::vector::reverse_iterator it=rBegin;it!=rEnd;++it) + { + int h=it->itemRect.bottom-it->itemRect.top; + it->itemRect.bottom=it->itemRect.top; + extra-=h; + dy+=h; + if (it+1==rEnd && pBegin!=pEnd) + { + // removing the last recent, remove the separator between recent and pinned + if (GetSettingBool(L"RecentProgsTop")) + it=pEnd; + else + it=rEnd; + Assert(it->id==MENU_SEPARATOR); + h=it->itemRect.bottom-it->itemRect.top; + it->itemRect.bottom=it->itemRect.top; + extra-=h; + dy+=h; + break; + } + if (extra<=0) break; + } + + if (dy>0 && GetSettingBool(L"RecentProgsTop") && pBegin!=pEnd) + { + // move pinned and the separator + for (std::vector::reverse_iterator it=pBegin;it!=rBegin;++it) + { + it->itemRect.top-=dy; + it->itemRect.bottom-=dy; + } + } + + // remove pinned + for (std::vector::reverse_iterator it=pBegin;it!=pEnd && extra>0;++it) + { + int h=it->itemRect.bottom-it->itemRect.top; + it->itemRect.bottom=it->itemRect.top; + extra-=h; + if (extra<=0) break; + } + } + } + if (s_MenuMode==MODE_NORMAL || s_MenuMode==MODE_PROGRAMS) + { + int extra=-dh2; + if (extra>0) + { + // remove extra items + for (std::vector::reverse_iterator it=m_Items.rbegin();it!=m_Items.rend();++it) + { + if (it->id==MENU_SHUTDOWN_BUTTON) continue; + if (it->column==0) break; + int h=it->itemRect.bottom-it->itemRect.top; + it->itemRect.bottom=it->itemRect.top; + extra-=h; + if (extra<=0) break; + } + } + } + } + + if (firstRecent>=0) + { + // reorder recent items + int top=m_Items[firstRecent].itemRect.top; + int firstRow=m_Items[firstRecent].row; + if (bRecentByName) + std::sort(m_Items.begin()+firstRecent,m_Items.begin()+lastRecent,MenuItem::MruNameComparator()); + + TRecentKeys recentKeys=(TRecentKeys)GetSettingInt(L"RecentProgKeys"); + if (recentKeys>=RECENT_KEYS_DIGITS) + { + // reassign accelerators + int num=0; + for (int idx=firstRecent;idx0) + str=(const wchar_t*)item.name+item.nameOffset; + else + str=item.name; + if (num<10) + item.name.Format(L"&%d %s",(num+1)%10,str); + else + item.name=str; + item.nameOffset=item.name.GetLength()-str.GetLength(); + } + if (item.itemRect.bottom>item.itemRect.top) + num++; + } + } + + if (bRecentReverse) + std::reverse(m_Items.begin()+firstRecent,m_Items.begin()+lastRecent); + for (int i=firstRecent;imaxHeight[0] && m_ScrollCount>0 && (m_bSubMenu || !s_bWin7Style)) + { + int d=maxh[0]-maxHeight[0]; + m_ScrollHeight=m_Items[m_ScrollCount-1].itemRect.bottom-d-m_rContent.top; + if (m_ScrollHeight<=0) + { + if (m_ScrollCount<(int)m_Items.size()) + d=m_Items[m_ScrollCount].itemRect.bottom-m_rContent.top; + m_ScrollOffset=m_ScrollHeight=0; + for (int i=0;i::iterator it=s_MenuScrolls.find(m_FolderHash[0]); + if (it!=s_MenuScrolls.end()) + { + m_ScrollOffset=it->second; // restore the scroll position if the same menu has been opened before + if (m_ScrollOffset>d) m_ScrollOffset=d; + } + else if ((m_Options&CONTAINER_SEARCH) && !bDontShrink) + { + // fit current category + if (m_SearchCategoryHash!=CSearchManager::CATEGORY_INVALID) + { + for (int i=0;itop) + m_ScrollOffset=top; + break; + } + } + } + else + m_ScrollOffset=0; + } + else + m_ScrollOffset=m_ScrollHeight=0; + UpdateScroll(); + m_bScrollUpHot=m_bScrollDownHot=false; + + // hide items that didn't fit + if (!m_bSubMenu) + { + for (int i=m_ScrollCount;ibottom) + m_Items[i].itemRect.bottom=m_Items[i].itemRect.top; + } + } + + m_rMenu.left=m_rMenu.top=0; + m_rMenu.right=totalWidth; + m_rMenu.bottom=totalHeight; + int oldOffset=m_BitmapOffset; + if (!m_bSubMenu) + { + m_BitmapOffset=0; + if (s_bWin7Style && s_Skin.Main_opacity!=MenuSkin::OPACITY_SOLID) + { + if (!(m_Options&CONTAINER_LEFT) && !s_bRTL) + m_BitmapOffset=s_MenuWidthMax-totalWidth; + if ((m_Options&CONTAINER_LEFT) && s_bRTL) + m_BitmapOffset=s_MenuWidthMax-totalWidth; + totalWidth=s_MenuWidthMax; + } + } + if (m_BitmapOffset>0) + { + OffsetRect(&m_rMenu,m_BitmapOffset,0); + OffsetRect(&m_rContent,m_BitmapOffset,0); + OffsetRect(&m_rContent2,m_BitmapOffset,0); + if (m_Region && !s_bRTL) + OffsetRgn(m_Region,m_BitmapOffset,0); + for (std::vector::iterator it=m_Items.begin();it!=m_Items.end();++it) + OffsetRect(&it->itemRect,m_BitmapOffset,0); + } + if (m_SearchIndex>=0) + { + m_Items[m_SearchIndex].itemRect.left+=s_Skin.Search_padding.left; + m_Items[m_SearchIndex].itemRect.top+=s_Skin.Search_padding.top; + m_Items[m_SearchIndex].itemRect.bottom-=s_Skin.Search_padding.bottom; + m_Items[m_SearchIndex].itemRect.right-=s_Skin.Search_padding.right; + RECT itemRect; + GetItemRect(m_SearchIndex,itemRect); + itemRect.right-=(itemRect.bottom-itemRect.top); + if (!s_Skin.Search_frame) + InflateRect(&itemRect,-1,-3); + if (m_SearchBox.m_hWnd) + { + if (oldOffset==m_BitmapOffset) + m_SearchBox.SetWindowPos(NULL,&itemRect,SWP_NOZORDER); + } + else + { + m_SearchBox.Create(L"EDIT",m_hWnd,itemRect,NULL,WS_CHILD|(s_Skin.Search_frame?WS_BORDER:0)|ES_AUTOHSCROLL|ES_WANTRETURN); + SetWindowSubclass(m_SearchBox,SubclassSearchBox,(UINT_PTR)this,0); + int index=(m_bTwoColumns && m_Items[m_SearchIndex].column==1)?1:0; + if (index==1 && (m_SearchIndex==0 || m_Items[m_SearchIndex-1].column==0)) + m_SearchBox.SetFont(s_Skin.ItemSettings[MenuSkin::COLUMN2_ITEM].font); + else + m_SearchBox.SetFont(s_Skin.ItemSettings[MenuSkin::COLUMN1_ITEM].font); + m_SearchIcons=(HBITMAP)LoadImage(g_Instance,MAKEINTRESOURCE(IDB_SEARCH_ICONS),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION); + PremultiplyBitmap(m_SearchIcons,0xFFFFFF); + } + } + + if (m_bTwoColumns && s_MenuMode==MODE_JUMPLIST) + { + // trim jumplist items after creating the search box + int maxH=m_rContent2.bottom; + if (m_SearchIndex>=0) + { + int h=m_Items[m_SearchIndex].itemRect.top-s_Skin.Search_padding.top-s_Skin.Search_background_jump_padding.top; + if (maxH>h) maxH=h; + } + if (shutdownIndex>=0) + { + int h=m_Items[shutdownIndex].itemRect.top; + if (maxH>h) maxH=h; + } + + for (std::vector::iterator it=m_Items.begin()+m_OriginalCount;it!=m_Items.end();++it) + { + if (it->itemRect.bottom>maxH) + it->itemRect.bottom=it->itemRect.top; + } + } + + // calculate padding rect + if (m_bSubMenu) + { + m_rPadding.top=-1; + m_rPadding.left=m_rPadding.right=m_rPadding.bottom=0; + int padColumn=-1; + for (size_t i=0;i=0 && m_rPadding.bottom==-1) + { + m_rPadding.bottom=totalHeight-(m_bSubMenu?menuPadding[0].bottom:menuPadding[0].bottom); + } + } + menuRect.top=menuRect.left=0; + menuRect.right=totalWidth; + menuRect.bottom=totalHeight; + if ((m_bSubMenu?s_Skin.Submenu_opacity:s_Skin.Main_opacity)==MenuSkin::OPACITY_SOLID) + AdjustWindowRect(&menuRect,GetWindowLong(GWL_STYLE),FALSE); + int dx=corner.x-((m_Options&CONTAINER_LEFT)?menuRect.left:menuRect.right); + int dy; + if (m_Options&CONTAINER_SEARCH) + { + RECT itemRect; + m_pParent->GetItemRect(m_ParentIndex,itemRect); + m_pParent->MapWindowPoints(NULL,&itemRect); + dy=(m_Options&CONTAINER_TOP)?(itemRect.top-menuPadding[0].top-menuRect.top):(itemRect.bottom+menuPadding[0].bottom-menuRect.bottom); + } + else + { + dy=corner.y-((m_Options&CONTAINER_TOP)?menuRect.top:menuRect.bottom); + } + OffsetRect(&menuRect,dx,dy); + if (m_bSubMenu) + { + // make the menu fit on screen + int dy2=0; + if (menuRect.bottom>s_MenuLimits.bottom) + dy2=s_MenuLimits.bottom-menuRect.bottom; + if (menuRect.top+dy22 && columnWidths[1]==0) + { + s_UserPicture.DestroyWindow(); + s_UserPictureRect.top=s_UserPictureRect.bottom=0; + } + if (s_UserPicture.m_hWnd) + { + s_UserPictureRect.bottom=s_Skin.User_frame_position.x; + if (!s_Skin.User_bitmap_outside || (m_Options&CONTAINER_TOP)) + s_UserPictureRect.bottom=m_rContent2.top+s_Skin.User_bitmapSize.cy+s_Skin.User_image_padding.x; + s_UserPictureRect.bottom+=menuRect.top; + s_UserPictureRect.top=s_UserPictureRect.bottom-s_Skin.User_bitmapSize.cy; + if (s_bRTL) + s_UserPictureRect.left=menuRect.right-(m_rContent2.left+m_rContent2.right+s_Skin.User_bitmapSize.cx)/2; + else + s_UserPictureRect.left=menuRect.left+(m_rContent2.left+m_rContent2.right-s_Skin.User_bitmapSize.cx)/2; + s_UserPictureRect.right=s_UserPictureRect.left+s_Skin.User_bitmapSize.cx; + } + + // create scrollbar + if (m_SearchScrollCount>m_SearchScrollHeight) + { + if (!m_Scrollbar.m_hWnd) + { + m_Scrollbar.Create(WC_SCROLLBAR,m_hWnd,NULL,NULL,WS_CHILD|SBS_VERT); + SetWindowSubclass(m_Scrollbar,SubclassScrollbar,(UINT_PTR)this,0); + if (s_Skin.BHasScrollbar) + m_ScrollTheme=OpenThemeData(m_Scrollbar,L"scrollbar"); + } + RECT rcScroll=m_rContent; + rcScroll.bottom=rcScroll.top+m_SearchScrollHeight*s_Skin.ItemSettings[MenuSkin::LIST_ITEM].itemHeight; + rcScroll.left=rcScroll.right-scrollWidth; + SCROLLINFO info={sizeof(info),SIF_ALL,0,m_SearchScrollCount-1,m_SearchScrollHeight}; + m_Scrollbar.SetScrollInfo(SB_CTL,&info,FALSE); + m_Scrollbar.SetWindowPos(NULL,&rcScroll,SWP_NOZORDER|SWP_SHOWWINDOW); + } + else if (m_Scrollbar.m_hWnd) + m_Scrollbar.ShowWindow(SW_HIDE); + + m_bTrackMouse=false; + m_bScrollTimerMouse=false; + m_bScrollTimerTouch=false; + m_InsertMark=-1; + m_HotItem=-1; + m_bHotArrow=false; + SetSubmenu(-1); + m_MouseWheel=0; + + if (!m_bSubMenu) + { + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS|TTF_TRANSPARENT|(s_bRTL?TTF_RTLREADING:0)}; + tool.hwnd=m_hWnd; + tool.uId=2; + s_Tooltip.SendMessage(TTM_DELTOOL,0,(LPARAM)&tool); + tool.uId=3; + s_Tooltip.SendMessage(TTM_DELTOOL,0,(LPARAM)&tool); + tool.uId=(UINT_PTR)s_UserPicture.m_hWnd; + s_Tooltip.SendMessage(TTM_DELTOOL,0,(LPARAM)&tool); + + if (m_rUser1.left... + wchar_t user[256]={0}; + ULONG size=_countof(user); + if (!GetUserNameEx(NameDisplay,user,&size)) + { + // GetUserNameEx may fail (for example on Home editions). use the login name + DWORD size=_countof(user); + GetUserName(user,&size); + } + tool.lpszText=user; + + if (m_rUser1.leftm_Items[m_ParentIndex].id==MENU_PROGRAMS || m_pParent->m_Items[m_ParentIndex].id==MENU_APPS)) + { + ULONGLONG curTime; + GetSystemTimeAsFileTime((FILETIME*)&curTime); + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu",KEY_WRITE)!=ERROR_SUCCESS) + regKey.Create(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu"); + + if (m_pParent->m_Items[m_ParentIndex].id==MENU_PROGRAMS) + regKey.SetQWORDValue(L"LastProgramsTime",curTime); + else if (m_pParent->m_Items[m_ParentIndex].id==MENU_APPS) + regKey.SetQWORDValue(L"LastAppsTime",curTime); + } +} + +void CMenuContainer::InitWindowFinalize( const RECT &menuRect ) +{ + SetWindowPos(NULL,&menuRect,SWP_NOZORDER|SWP_NOACTIVATE|SWP_DEFERERASE); + // for some reason the region must be set after the call to SetWindowPos. otherwise it doesn't work for RTL windows + if (m_bSubMenu || !s_bWin7Style || s_OldMenuState.mode==MODE_UNKNOWN) + ApplyRegion(TRUE); + Invalidate(); +} + +void CMenuContainer::ApplyRegion( BOOL bRedraw ) +{ + if (m_Region) + { + int size=GetRegionData(m_Region,0,NULL); + std::vector buf(size); + GetRegionData(m_Region,size,(RGNDATA*)&buf[0]); + XFORM xform={1,0,0,1}; + if (s_bRTL) + { + // mirror the region (again) + xform.eM11=-1; + xform.eDx=(float)(m_rMenu.right+m_rMenu.left-m_BitmapOffset); + } + HRGN rgn=ExtCreateRegion(&xform,size,(RGNDATA*)&buf[0]); + + if (!SetWindowRgn(rgn,bRedraw)) + DeleteObject(rgn); // otherwise the OS takes ownership of the region, no need to free + } + else + SetWindowRgn(NULL,bRedraw); +} + +void CMenuContainer::UpdateScroll( void ) +{ + if (m_ScrollHeight==0) + m_bScrollUp=m_bScrollDown=false; + else + { + m_bScrollUp=(m_ScrollOffset>0); + m_bScrollDown=(m_ScrollOffset+m_ScrollHeight=WIN_VER_WIN10) + { + tSetWindowCompositionAttribute SetWindowCompositionAttribute=(tSetWindowCompositionAttribute)GetProcAddress(GetModuleHandle(L"user32.dll"),"SetWindowCompositionAttribute"); + if (SetWindowCompositionAttribute) + { + int a=((GetSettingInt(L"GlassOpacity")*255)/100)<<24; + int data[4]={3,0x13}; + bool bDef=true; + if (GetSettingBool(L"GlassOverride")) + data[2]=(GetSettingInt(L"GlassColor",bDef)&0xFFFFFF)|a; + if (bDef) + { + int dr, dg, db; + GetMetroGlassColor(dr,dg,db); + data[2]=dr|(dg<<8)|(db<<16)|a; + } + WINCOMPATTRDATA attrData={0x13,&data,sizeof(data)}; + SetWindowCompositionAttribute(m_hWnd,&attrData); + } + } + + if (!m_pParent) + BufferedPaintInit(); + if (this==s_Menus[0]) + s_FirstMenu=m_hWnd; + else + InitWindow(); + if (m_Options&CONTAINER_SEARCH) + s_SearchMenu=m_hWnd; + s_HotPos=GetMessagePos(); + if (GetSettingBool(L"EnableAccessibility")) + { + m_pAccessible=new CMenuAccessible(this); + NotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART,m_hWnd,OBJID_CLIENT,CHILDID_SELF); + } + else + m_pAccessible=NULL; + m_pDropTargetProxy=new CDropTargetProxy(this); + RegisterDragDrop(m_hWnd,m_pDropTargetProxy); + if (!m_bSubMenu && s_pFrameworkInputPane) + s_pFrameworkInputPane->AdviseWithHWND(m_hWnd,this,&m_InputCookie); + PlayMenuSound(m_bSubMenu?SOUND_POPUP:SOUND_MAIN); + return 0; +} + +bool CMenuContainer::GetItemRect( int index, RECT &rc ) +{ + if (index>=0 && index<(int)m_Items.size()) + { + rc=m_Items[index].itemRect; + if (m_ScrollHeight>0 && index=m_rContent.top+m_ScrollHeight-m_ScrollButtonSize) + return false; + } + if (m_SearchScrollCount>m_SearchScrollHeight && index>=m_OriginalCount) + { + OffsetRect(&rc,0,-m_SearchScrollPos*(rc.bottom-rc.top)); + } + } + return true; +} + +int CMenuContainer::HitTest( const POINT &pt, bool *bArrow, bool bDrop ) +{ + if (m_bScrollUp && pt.y=m_rContent.top+m_ScrollHeight-m_ScrollButtonSize) + start=m_ScrollCount; + int n=(int)m_Items.size(); + for (int i=start;i0 && im_SearchScrollHeight && i>=m_OriginalCount) + { + OffsetRect(&rc,0,-m_SearchScrollPos*(rc.bottom-rc.top)); + } + else if (bDrop && m_bTwoColumns && i=0) + arrWidth+=s_Skin.Pin_bitmap_Size.cx; + else if (item.id==MENU_SEARCH_CATEGORY) + arrWidth+=s_Skin.More_bitmap_Size.cx; + else + arrWidth+=settings.arrSize.cx; + *bArrow=(pt.x>=item.itemRect.right-arrWidth); + } + else if (item.id==MENU_SEARCH_CATEGORY && item.categoryHash>=CSearchManager::CATEGORY_FILE) + { + int x=pt.x-rc.left; + *bArrow=(x>=item.textStart && x=0) + { + RECT rc; + GetItemRect(index,rc); + InvalidateRect(&rc); + } +} + +void CMenuContainer::SetHotItem( int index, bool bArrow, bool bShowTip ) +{ + if (index<0 && (m_Options&CONTAINER_SEARCH)) + return; + if (index>=0) + s_bOverrideFirstDown=false; + if (index==m_HotItem && bArrow==m_bHotArrow) return; + if ((index>=0)!=(m_HotItem>=0)) + { + InvalidateItem(m_Submenu); + InvalidateItem(m_ContextItem); + } + if (m_HotItem>=0 && m_HotItem==m_ProgramTreeIndex && s_MenuMode==MODE_PROGRAMS) + m_pProgramsTree->Invalidate(); + else + InvalidateItem(m_HotItem); + if (index>=0 && index==m_ProgramTreeIndex && s_MenuMode==MODE_PROGRAMS) + m_pProgramsTree->Invalidate(); + else + { + InvalidateItem(index); + if (index>=0 && m_pProgramsTree && m_pProgramsTree->m_hWnd && m_pProgramsTree->m_hWnd==GetFocus()) + SetFocus(); + } + m_HotItem=index; + m_bHotArrow=bArrow; + s_pTipMenu=NULL; + s_TipItem=-1; + UpdateUserPicture(); + if (index>=0) + { + s_pHotMenu=this; + s_HotItem=index; + } + else if (s_pHotMenu==this) + { + s_pHotMenu=NULL; + s_HotItem=-1; + if (s_Tooltip.m_hWnd) + { + TOOLINFO tool={sizeof(tool),TTF_ABSOLUTE|TTF_TRACK|TTF_TRANSPARENT}; + tool.uId=1; + s_Tooltip.SendMessage(TTM_TRACKACTIVATE,FALSE,(LPARAM)&tool); + } + } + else + return; + if (index>=0 && index<(int)m_Items.size()) + { + if (bShowTip) + { + int show, hide; + if (m_Items[index].bFolder && m_Items[index].id!=MENU_SHUTDOWN_BUTTON) + show=s_TipShowTimeFolder, hide=s_TipHideTimeFolder; + else + show=s_TipShowTime, hide=s_TipHideTime; + if (s_Tooltip.m_hWnd) + { + TOOLINFO tool={sizeof(tool),TTF_ABSOLUTE|TTF_TRACK|TTF_TRANSPARENT}; + tool.uId=1; + s_Tooltip.SendMessage(TTM_TRACKACTIVATE,FALSE,(LPARAM)&tool); + if (!s_Menus[0]->m_bDestroyed && hide>0) + { + s_pTipMenu=s_pHotMenu; + s_TipItem=s_HotItem; + s_Menus[0]->SetTimer(TIMER_TOOLTIP_SHOW,show); + } + } + } + NotifyWinEvent(EVENT_OBJECT_FOCUS,m_hWnd,OBJID_CLIENT,index+1); + } +} + +void CMenuContainer::SetSubmenu( int index ) +{ + if (m_Submenu==index) return; + m_Submenu=index; + UpdateUserPicture(); +} + +void CMenuContainer::SetContextItem( int index ) +{ + if (m_ContextItem==index) return; + m_ContextItem=index; + UpdateUserPicture(); +} + +void CMenuContainer::SetClickItem( int index ) +{ + if (m_ClickIndex==index) return; + m_ClickIndex=index; + InvalidateItem(m_ClickIndex); +} + +void CMenuContainer::UpdateUserPicture( void ) +{ + if (m_bTwoColumns && s_UserPicture.m_hWnd && s_UserPicture.IsWindowVisible()) + { + HBITMAP bmp=NULL; + int bmpIndex=m_HotItem>=0?m_HotItem:(m_ContextItem>=0?m_ContextItem:m_Submenu); + if (bmpIndex>=0 && bmpIndexextraLargeIcon) + bmp=m_Items[bmpIndex].pItemInfo->extraLargeIcon->bitmap; + s_UserPicture.StartImageTimer(bmp); + } +} + +void CMenuContainer::SetInsertMark( int index, bool bAfter ) +{ + if (index==m_InsertMark && bAfter==m_bInsertAfter) return; + RECT rc; + if (GetInsertRect(rc)) + InvalidateRect(&rc); + m_InsertMark=index; + m_bInsertAfter=bAfter; + if (GetInsertRect(rc)) + InvalidateRect(&rc); +} + +bool CMenuContainer::GetInsertRect( RECT &rc ) +{ + if (m_InsertMark<0 || m_InsertMark>=(int)m_Items.size()) + return false; + const MenuItem &item=m_Items[m_InsertMark]; + rc=item.itemRect; + if (m_bInsertAfter) + rc.top=rc.bottom; + if (m_ScrollHeight>0 && m_InsertMark=0) + { + SetActiveWindow(); + CloseSubMenus(0,this); + } + if (info.dwFlags&GF_BEGIN) + { + m_PanPosY=info.ptsLocation.y; + BeginPanningFeedback(m_hWnd); + m_Overpan=0; + } + else if (info.dwFlags&GF_END) + { + EndPanningFeedback(m_hWnd,TRUE); + m_Overpan=0; + s_HotPos=GetMessagePos(); + } + else + { + int dy=info.ptsLocation.y-m_PanPosY; + m_Overpan+=dy; + if (dy!=0 && (m_ScrollHeight>0 || m_SearchScrollCount>0)) + { + bool bOverpan=false; + if (m_SearchScrollCount>0) + { + int height=s_Skin.ItemSettings[MenuSkin::LIST_ITEM].itemHeight; + int count=dy/height; + m_PanPosY+=count*height; + int pos0=m_SearchScrollPos; + int pos=m_SearchScrollPos-count; + m_SearchScrollPos=m_Scrollbar.SetScrollPos(SB_CTL,pos); + if (m_SearchScrollPos!=pos0) + InvalidateRect(&m_rContent); + bOverpan=(m_SearchScrollPos!=pos); + } + else + { + m_PanPosY=info.ptsLocation.y; + int scroll=m_ScrollOffset; + scroll-=dy; + if (scroll<0) + { + scroll=0; + bOverpan=true; + } + int total=m_Items[m_ScrollCount-1].itemRect.bottom-m_rContent.top-m_ScrollHeight; + if (scroll>total) + { + scroll=total; + bOverpan=true; + } + if (m_ScrollOffset!=scroll) + { + m_ScrollOffset=scroll; + UpdateScroll(); + Invalidate(); + s_HotPos=-1; + } + } + if (bOverpan) + UpdatePanningFeedback(m_hWnd,0,m_Overpan,info.dwFlags&GF_INERTIA); + else + m_Overpan=0; + } + } + CloseGestureInfoHandle((HGESTUREINFO)lParam); + return 0; + } + bHandled=FALSE; + return 0; +} + +LRESULT CMenuContainer::OnGestureNotify( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (!s_bHasTouch) + { + bHandled=FALSE; + return 0; + } + GESTURENOTIFYSTRUCT *pNotify=(GESTURENOTIFYSTRUCT*)lParam; + if (pNotify->hwndTarget==m_hWnd) + { + // if clicked on a scrollable item + bool bScrollable=false; + POINT pt={pNotify->ptsLocation.x,pNotify->ptsLocation.y}; + ScreenToClient(&pt); + int idx=HitTest(pt,NULL); + if (idx>=0) + { + if (idx0) + bScrollable=true; + else if (idx>=m_OriginalCount && m_SearchScrollCount>0) + bScrollable=true; + } + if (bScrollable) + { + GESTURECONFIG config={GID_PAN,GC_PAN_WITH_SINGLE_FINGER_VERTICALLY|GC_PAN_WITH_INERTIA,GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY}; + SetGestureConfig(pNotify->hwndTarget,0,1,&config,sizeof(config)); + } + else + { + GESTURECONFIG config={0,0,GC_ALLGESTURES}; + SetGestureConfig(pNotify->hwndTarget,0,1,&config,sizeof(config)); + } + } + else if (m_pProgramsTree && pNotify->hwndTarget==m_pProgramsTree->m_hWnd) + { + GESTURECONFIG config={0,GC_ALLGESTURES,0}; + SetGestureConfig(pNotify->hwndTarget,0,1,&config,sizeof(config)); + } + else if (pNotify->hwndTarget==m_Scrollbar.m_hWnd) + { + GESTURECONFIG config={0,0,GC_ALLGESTURES}; + SetGestureConfig(pNotify->hwndTarget,0,1,&config,sizeof(config)); + } + bHandled=FALSE; + return 0; +} + +LRESULT CMenuContainer::OnPointerDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + m_PointerId=0; + if (s_bHasTouch && IS_POINTER_INCONTACT_WPARAM(wParam) && IS_POINTER_PRIMARY_WPARAM(wParam) && IS_POINTER_FIRSTBUTTON_WPARAM(wParam)) + { + CPoint pt(lParam); + ScreenToClient(&pt); + UpdateScroll(&pt,true); + if (m_bScrollTimerTouch) + { + m_PointerId=GET_POINTERID_WPARAM(wParam); + return 0; + } + } + bHandled=FALSE; + return 0; +} + +LRESULT CMenuContainer::OnPointerUpdate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (s_bHasTouch && m_PointerId==GET_POINTERID_WPARAM(wParam)) + { + if (IS_POINTER_INCONTACT_WPARAM(wParam) && IS_POINTER_FIRSTBUTTON_WPARAM(wParam)) + { + CPoint pt(lParam); + ScreenToClient(&pt); + UpdateScroll(&pt,true); + } + else + { + KillTimer(TIMER_SCROLL_TOUCH); + m_bScrollTimerTouch=false; + if (m_bScrollUpHot || m_bScrollDownHot) + { + m_bScrollUpHot=m_bScrollDownHot=false; + Invalidate(); + } + m_PointerId=0; + } + return 0; + } + bHandled=FALSE; + return 0; +} + +LRESULT CMenuContainer::OnPointerUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (s_bHasTouch && m_PointerId==GET_POINTERID_WPARAM(wParam)) + { + KillTimer(TIMER_SCROLL_TOUCH); + m_bScrollTimerTouch=false; + if (m_bScrollUpHot || m_bScrollDownHot) + { + m_bScrollUpHot=m_bScrollDownHot=false; + Invalidate(); + } + m_PointerId=0; + return 0; + } + bHandled=FALSE; + return 0; +} + +STDMETHODIMP CMenuContainer::QueryInterface( REFIID riid, void **ppvObject ) +{ + if (riid==IID_IUnknown || riid==IID_IDropTarget) + { + *ppvObject=static_cast(this); + AddRef(); + return S_OK; + } + if (riid==__uuidof(IFrameworkInputPaneHandler)) + { + *ppvObject=static_cast(this); + AddRef(); + return S_OK; + } + *ppvObject=NULL; + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CMenuContainer::Showing( RECT *prcInputPaneScreenLocation, BOOL fEnsureFocusedElementInView ) +{ + NotifyDisplayChange(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CMenuContainer::Hiding( BOOL fEnsureFocusedElementInView ) +{ + NotifyDisplayChange(); + return S_OK; +} + +LRESULT CMenuContainer::OnRedrawEdit( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + m_SearchBox.RedrawWindow(); + return 0; +} + +LRESULT CMenuContainer::OnRefreshIcons( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + for (std::vector::iterator it=s_Menus.begin();it!=s_Menus.end();++it) + if (!(*it)->m_bDestroyed) + { + (*it)->Invalidate(); + if (m_pProgramsTree && m_pProgramsTree->m_hWnd) + m_pProgramsTree->Invalidate(); + } + return 0; +} + +void CMenuContainer::RefreshIcons( void ) +{ + // this is called from the background thread + HWND first=s_FirstMenu; // must copy into a temp variable because we don't want the value to change in the middle of the next two lines + if (first) + ::PostMessage(first,MCM_REFRESHICONS,0,0); +} + +void CMenuContainer::RefreshSearch( void ) +{ + // this is called from the background thread + HWND search=s_SearchMenu; // must copy into a temp variable because we don't want the value to change in the middle of the next two lines + if (search) + ::PostMessage(search,MCM_REFRESH,0,0); +} + +LRESULT CMenuContainer::OnSetHotItem( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + int index=(int)wParam; + while (index<(int)m_Items.size() && !CanSelectItem(index,false)) + index++; + if (index<(int)m_Items.size()) + SetHotItem(index,false,true); + return 0; +} + +LRESULT CMenuContainer::OnStartMenuMsg( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (lParam) + s_StartMenuParams=*(StartMenuParams*)lParam; + return 0; +} + +void CMenuContainer::SetSearchState( TSearchState state ) +{ + if (m_SearchState==state) + return; + if (m_Submenu!=-1) + { + InvalidateRect(&m_Items[m_Submenu].itemRect); + SetSubmenu(-1); + } + InvalidateRect(&m_Items[m_SearchIndex].itemRect); + if (m_SearchState==SEARCH_TEXT && state!=SEARCH_TEXT) + { + // close the search menu + m_SearchScrollCount=0; + if (s_MenuMode==MODE_SEARCH) + SetMenuMode(s_PreSearchMenuMode); + else + CloseSubMenus(CLOSE_ONLY_SEARCH,this); // can't use CLOSE_POST here because the menu needs to be closed while m_bInSearchUpdate is set + g_SearchManager.BeginSearch(CString()); + } + m_SearchState=state; + if (m_SearchState==SEARCH_NONE) + s_bDisableHover=false; +} + +LRESULT CMenuContainer::OnEditChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + s_bPendingSearchEnter=false; + m_SearchBox.RedrawWindow(); + wchar_t text[256]; + m_SearchBox.GetWindowText(text,_countof(text)); + DoEnvironmentSubst(text,_countof(text)); + unsigned int hash=CalcFNVHash(text); + if (m_SearchHash!=hash && !m_bInSearchUpdate) + SetTimer(TIMER_SEARCH,100); + m_SearchHash=hash; + return 0; +} + +void CMenuContainer::UpdateSearchResults( bool bForceShowAll ) +{ + if (m_bInSearchUpdate) + return; + m_bInSearchUpdate=true; + wchar_t text[256]; + m_SearchBox.GetWindowText(text,_countof(text)); + DoEnvironmentSubst(text,_countof(text)); + wchar_t *pText=text; + while (*pText==' ' || *pText=='\t') + pText++; + TSearchState state=SEARCH_NONE; + if (*pText) + { + int len=Strlen(pText); + while (len>0 && (pText[len-1]==' ' || pText[len-1]=='\t')) + len--; + pText[len]=0; + CharUpper(pText); + s_SearchResults.currentString=pText; + g_SearchManager.BeginSearch(s_SearchResults.currentString); + s_SearchResults.bSearching=true; + s_bPendingSearchEnter=false; + if (s_bWin7Style) + { + MenuItem &item=m_Items[m_SearchIndex-m_SearchItemCount+1]; + item.id=MENU_SEARCH_EMPTY; + item.name=FindTranslation(L"Menu.Searching",L"Searching..."); + item.pItemInfo=g_ItemManager.GetCustomIcon(L"imageres.dll,8",CItemManager::ICON_SIZE_TYPE_SMALL); + } + if (m_Submenu!=m_SearchIndex && s_MenuMode!=MODE_SEARCH) + { + ActivateData data; + data.bNoModifiers=true; + ActivateItem(m_SearchIndex,ACTIVATE_OPEN_SEARCH,NULL,&data); + } + Assert(s_SearchMenu); + RefreshSearch(); + state=SEARCH_TEXT; + } + else if (GetFocus()==m_SearchBox.m_hWnd) + { + state=SEARCH_BLANK; + } + SetSearchState(state); + m_bInSearchUpdate=false; +} + +// Turn on the keyboard cues from now on. This is done when a keyboard action is detected +void CMenuContainer::ShowKeyboardCues( void ) +{ + if (!s_bKeyboardCues) + { + s_bKeyboardCues=true; + for (std::vector::const_iterator it=s_Menus.begin();it!=s_Menus.end();++it) + (*it)->Invalidate(); + } +} + +void CMenuContainer::SetActiveWindow( void ) +{ + HWND active=GetActiveWindow(); + if (active!=m_hWnd && active!=m_SearchBox.m_hWnd) + ::SetActiveWindow(m_hWnd); + if (!m_bSubMenu && s_bBehindTaskbar && s_TaskBar) + SetWindowPos(s_TaskBar,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE); // make sure the top menu stays behind the taskbar +} + +void CMenuContainer::PostRefreshMessage( void ) +{ + if (!m_bDestroyed) + { + if (!InterlockedExchange(&m_RefreshPosted,1)) + PostMessage(MCM_REFRESH); + } +} + +LRESULT CMenuContainer::OnSysCommand( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if ((wParam&0xFFF0)==SC_KEYMENU) + { + // stops Alt from activating the window menu + ShowKeyboardCues(); + s_bOverrideFirstDown=false; + } + else + bHandled=FALSE; + return 0; +} + +LRESULT CMenuContainer::OnSettingChange( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==SPI_SETWORKAREA) + NotifyDisplayChange(); + bHandled=FALSE; + return 0; +} + +void CMenuContainer::NotifyDisplayChange( void ) +{ + if (!m_bSubMenu && !m_bWorkAreaPosted && !s_bLockWorkArea) + { + m_bWorkAreaPosted=true; + PostMessage(MCM_WORKAREACHANGED); + } +} + +LRESULT CMenuContainer::OnDisplayChange( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + NotifyDisplayChange(); + bHandled=FALSE; + return 0; +} + +LRESULT CMenuContainer::OnWorkAreaChanged( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + Assert(!m_bSubMenu); + Assert(!s_bLockWorkArea); + + // resize main menu + RECT taskbarRect; + UINT uEdge=GetTaskbarPosition(s_TaskBar,NULL,NULL,&taskbarRect); + if (uEdge==s_TaskBarEdge) + { + RECT area=CalculateWorkArea(taskbarRect); + if (memcmp(&area,&s_MainMenuLimits,sizeof(RECT))!=0) + { + s_MainMenuLimits=area; + s_MenuHeight=-1; + POINT corner=CalculateCorner(); + RECT menuRect; + InitWindowInternal(false,corner,menuRect); + if (s_MenuMode==MODE_PROGRAMS) + { + // resize programs tree + MenuItem &item=m_Items[m_ProgramTreeIndex]; + item.itemRect=m_rContent; + item.itemRect.bottom=m_Items[m_ProgramTreeIndex+1].itemRect.top; + RECT rc; + m_pProgramsTree->GetWindowRect(&rc); + int dh=rc.bottom-rc.top; + m_pProgramsTree->GetClientRect(&rc); + dh-=rc.bottom; + int itemHeight=TreeView_GetItemHeight(m_pProgramsTree->m_hWnd); + rc=item.itemRect; + int h=rc.bottom-rc.top; + int n=(h-dh)/itemHeight; + rc.bottom=rc.top+n*itemHeight+dh; + m_pProgramsTree->SetWindowPos(NULL,&rc,SWP_NOZORDER|SWP_NOACTIVATE); + } + else if (s_MenuMode==MODE_SEARCH) + { + // HACK: before initializing the search items we need to know the size of the menu, so InitWindow needs to be called twice + InitSearchItems(); + InitWindowInternal(false,corner,menuRect); + } + + if (s_UserPicture.m_hWnd && s_UserPictureRect.top=0) + { + if (m_HoverItem!=m_Submenu && m_HoverItem!=m_SubJumpItem && m_HoverItem==m_HotItem && m_bHoverArrow==m_bHotArrow && !s_bDisableHover && m_SearchState<=SEARCH_BLANK) + { + if (m_HoverItem==m_ProgramTreeIndex) + m_pProgramsTree->SetFocus(); + ActivateItem(m_HoverItem,ACTIVATE_OPEN,NULL); + m_SubShowTime=GetTickCount(); + } + if (m_HoverItem==m_ProgramButtonIndex) + m_bDisableProgHover=true; + m_HoverItem=-1; + KillTimer(TIMER_HOVER); + } + return 0; + } + if (wParam==TIMER_SCROLL_MOUSE || wParam==TIMER_SCROLL_TOUCH) + { + if (wParam==TIMER_SCROLL_MOUSE && s_bHasTouch && GetKeyState(VK_LBUTTON)>=0) + return 0; + int speed=GetSettingInt(m_bSubMenu?L"SubMenuScrollSpeed":L"MainMenuScrollSpeed"); + if (speed<1) speed=1; + if (speed>20) speed=20; + int scroll=m_ScrollOffset; + if (m_bScrollUp && m_bScrollUpHot) + { + scroll-=s_Skin.ItemSettings[m_bSubMenu?MenuSkin::SUBMENU_ITEM:MenuSkin::COLUMN1_ITEM].itemHeight*speed/6; + if (scroll<0) scroll=0; + } + else if (m_bScrollDown && m_bScrollDownHot) + { + scroll+=s_Skin.ItemSettings[m_bSubMenu?MenuSkin::SUBMENU_ITEM:MenuSkin::COLUMN1_ITEM].itemHeight*speed/6; + int total=m_Items[m_ScrollCount-1].itemRect.bottom-m_rContent.top-m_ScrollHeight; + if (scroll>total) scroll=total; + } + if (m_ScrollOffset!=scroll) + { + m_ScrollOffset=scroll; + UpdateScroll(); + if (!m_bScrollUp && !m_bScrollDown) + KillTimer(wParam); + Invalidate(); + } + } + if (wParam==TIMER_TOOLTIP_SHOW) + { + KillTimer(TIMER_TOOLTIP_SHOW); + + if (!s_pHotMenu || s_pHotMenu->m_bDestroyed) + return 0; + if (s_pHotMenu!=s_pTipMenu || s_HotItem!=s_TipItem) + return 0; + + if (std::find(s_Menus.begin(),s_Menus.end(),s_pHotMenu)==s_Menus.end()) + return 0; + + if (s_HotItem>=(int)s_pHotMenu->m_Items.size()) + return 0; + + if (!m_bSubMenu && s_MenuMode==MODE_SEARCH && s_SearchResults.bSearching) + return 0; + + TOOLINFO tool={sizeof(tool),TTF_ABSOLUTE|TTF_TRACK|TTF_TRANSPARENT|(s_bRTL?TTF_RTLREADING:0)}; + tool.uId=1; + + wchar_t text[1024]; + if (!s_pHotMenu->GetDescription(s_HotItem,text,_countof(text))) + return 0; + + RECT rc; + s_pHotMenu->GetItemRect(s_HotItem,rc); + s_pHotMenu->MapWindowPoints(NULL,&rc); + DWORD pos=GetMessagePos(); + POINT pt={(short)LOWORD(pos),(short)HIWORD(pos)}; + if (PtInRect(&rc,pt)) + { + pt.x+=8; + pt.y+=16; + } + else if (!(s_pHotMenu->m_Options&CONTAINER_SEARCH)) + { + pt.x=(rc.left+rc.right)/2; + pt.y=rc.bottom; + } + else + return 0; + + tool.lpszText=text; + s_Tooltip.SendMessage(TTM_UPDATETIPTEXT,0,(LPARAM)&tool); + s_Tooltip.SendMessage(TTM_TRACKPOSITION,0,MAKELONG(pt.x,pt.y)); + s_Tooltip.SendMessage(TTM_TRACKACTIVATE,TRUE,(LPARAM)&tool); + + // make sure the tooltip is inside the monitor + s_Tooltip.GetWindowRect(&rc); + int dx=0, dy=0; + if (rc.lefts_MenuLimits.right) dx-=rc.right-s_MenuLimits.right; + if (rc.tops_MenuLimits.bottom) dy-=rc.bottom-s_MenuLimits.bottom; + if (dx || dy) + s_Tooltip.SendMessage(TTM_TRACKPOSITION,0,MAKELONG(pt.x+dx,pt.y+dy)); + + if (s_pHotMenu->m_Items[s_HotItem].bFolder && s_pHotMenu->m_Items[s_HotItem].id!=MENU_SHUTDOWN_BUTTON) + SetTimer(TIMER_TOOLTIP_HIDE,s_TipHideTimeFolder); + else + SetTimer(TIMER_TOOLTIP_HIDE,s_TipHideTime); + return 0; + } + if (wParam==TIMER_TOOLTIP_HIDE) + { + TOOLINFO tool={sizeof(tool),TTF_ABSOLUTE|TTF_TRACK|TTF_TRANSPARENT}; + tool.uId=1; + s_Tooltip.SendMessage(TTM_TRACKACTIVATE,FALSE,(LPARAM)&tool); + KillTimer(TIMER_TOOLTIP_HIDE); + return 0; + } + if (wParam==TIMER_BALLOON_HIDE) + { + TOOLINFO tool={sizeof(tool)}; + tool.uId=1; + if (s_TooltipBalloon.m_hWnd) + s_TooltipBalloon.SendMessage(TTM_TRACKACTIVATE,FALSE,(LPARAM)&tool); + KillTimer(TIMER_BALLOON_HIDE); + } + if (wParam==TIMER_SEARCH) + { + UpdateSearchResults(false); + KillTimer(TIMER_SEARCH); + } + if (wParam==TIMER_DRAG) + { + if (!s_bDragClosed) + { + // if the mouse is outside of the menu for more than 4 seconds close the menu + DWORD pos=GetMessagePos(); + POINT pt={(short)LOWORD(pos),(short)HIWORD(pos)}; + HWND hWnd=WindowFromPoint(pt); + if (hWnd) hWnd=GetAncestor(hWnd,GA_ROOT); + wchar_t name[256]; + if (hWnd) + GetClassName(hWnd,name,_countof(name)); + else + name[0]=0; + + if (_wcsicmp(name,L"ClassicShell.CMenuContainer")!=0) + { + int dt=GetMessageTime()-m_DragTime; + if (dt>GetSettingInt(L"DragHideDelay")) + { + HideStartMenu(); + KillTimer(TIMER_DRAG); + s_bDragClosed=true; + } + } + else + { + m_DragTime=GetMessageTime(); + } + } + } + return 0; +} + +// Handle right-click and the menu keyboard button +LRESULT CMenuContainer::OnContextMenu( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (s_bNoContextMenu) return 0; + POINT pt={(short)LOWORD(lParam),(short)HIWORD(lParam)}; + int index; + BOOL bPad=FALSE; + if (pt.x!=-1 || pt.y!=-1) + { + POINT pt2=pt; + ScreenToClient(&pt2); + index=HitTest(pt2,NULL); + if (index<0) + bPad=PtInRect(&m_rPadding,pt2); + if (index<0 && !bPad) return 0; + ActivateItem(index,ACTIVATE_MENU,&pt); + } + else + { + index=m_HotItem; + if (index<0 && !bPad) return 0; + ActivateItem(index,ACTIVATE_MENU,NULL); + } + return 0; +} + +LRESULT CMenuContainer::OnVScroll( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + int pos0=m_SearchScrollPos; + int pos=pos0; + switch (LOWORD(wParam)) + { + case SB_TOP: + pos=0; + break; + case SB_BOTTOM: + pos=m_SearchScrollCount; + break; + case SB_LINEUP: + pos--; + break; + case SB_LINEDOWN: + pos++; + break; + case SB_PAGEUP: + pos-=m_SearchScrollHeight; + break; + case SB_PAGEDOWN: + pos+=m_SearchScrollHeight; + break; + case SB_THUMBTRACK: + pos=HIWORD(wParam); + break; + default: + return 0; + } + m_SearchScrollPos=m_Scrollbar.SetScrollPos(SB_CTL,pos); + if (m_SearchScrollPos!=pos0) + InvalidateRect(&m_rContent); + return 0; +} + +bool CMenuContainer::CanSelectItem( int index, bool bKeyboard ) +{ + if (!m_bSubMenu) + { + if (s_MenuMode==MODE_PROGRAMS && indexm_hWnd && m_pProgramsTree->m_hWnd==GetFocus()) + tab=0; + else if (m_HotItem>=0) + { + const MenuItem &item=m_Items[m_HotItem]; + if (item.id==MENU_PROGRAMS) + tab=1; + else if (item.id==MENU_SEARCH_BOX) + tab=2; + else if (item.id==MENU_SHUTDOWN_BUTTON) + tab=4; + else + tab=(item.column==0?0:3); + } + if (GetKeyState(VK_SHIFT)<0) + { + tab=(tab+4)%5; + if (tab==2 && m_SearchIndex==-1) + tab=1; + if (tab==4 && GetSettingInt(L"ShutdownCommand")==SHUTDOWN_TYPE_NONE) + tab=3; + } + else + { + tab=(tab+1)%5; + if (tab==2 && m_SearchIndex==-1) + tab=3; + if (tab==4 && GetSettingInt(L"ShutdownCommand")==SHUTDOWN_TYPE_NONE) + tab=0; + } + int index=-1; + if (tab==0 || tab==3) + { + int column=(tab==0)?0:1; + int miny=32768; + for (int i=0;i<(int)m_Items.size();i++) + if (m_Items[i].column==column && m_Items[i].itemRect.top=0) + { + CloseSubMenus(CLOSE_KEEP_MODE,this); + ActivateItem(index,ACTIVATE_SELECT,NULL); + } + return 0; + } + else if (m_SearchBox.m_hWnd && m_SearchState==SEARCH_NONE) + { + // destroy old submenus + CloseSubMenus(0,this); + ActivateItem(m_SearchIndex,ACTIVATE_SELECT,NULL); + return 0; + } + } + + int index=m_HotItem; + + if (index>=0 && m_SearchState==SEARCH_NONE) + { + if (wParam==VK_F2) + { + if (m_Items[index].id==MENU_NO && m_Items[index].pItem1 && !m_Items[index].pItem2) + { + ActivateItem(index,ACTIVATE_RENAME,NULL); + if (IsWindow()) PostMessage(MCM_SETHOTITEM,index); + } + return 0; + } + if (wParam==VK_DELETE) + { + if ((m_Items[index].id==MENU_NO || m_Items[index].id==MENU_RECENT) && m_Items[index].pItem1 && !m_Items[index].pItem2) + { + ActivateItem(index,ACTIVATE_DELETE,NULL); + if (IsWindow()) PostMessage(MCM_SETHOTITEM,index); + } + return 0; + } + } + if (!m_bSubMenu && m_SearchIndex>=0 && wParam=='F' && GetKeyState(VK_CONTROL)<0) + { + ActivateItem(m_SearchIndex,ACTIVATE_SELECT,NULL); + return 0; + } + + if (wParam==VK_HOME || wParam==VK_END) + { + // select first or last in the given column + int column=-1; + if (s_bWin7Style && m_bTwoColumns && m_HotItem>=0) + column=m_Items[m_HotItem].column; + int index=-1; + for (int i=0;i<(int)m_Items.size();i++) + { + const MenuItem &item=m_Items[i]; + if ((column==-1 || item.column==column) && CanSelectItem(i) && item.id!=MENU_SEARCH_BOX) + { + if (s_bWin7Style && m_bTwoColumns && (item.id==MENU_PROGRAMS || item.id==MENU_MORE_RESULTS || item.id==MENU_SEARCH_INTERNET || item.id==MENU_SEARCH_PROVIDER || item.id==MENU_SHUTDOWN_BUTTON)) + continue; + index=i; + if (wParam==VK_HOME) break; + } + } + if (index>=0) + { + CloseSubMenus(CLOSE_KEEP_MODE,this); + ActivateItem(index,ACTIVATE_SELECT,NULL); + } + return 0; + } + + if (wParam==VK_PRIOR || wParam==VK_NEXT) + { + int index=m_HotItem<0?0:m_HotItem; + if (m_ScrollHeight>0) + { + // scrolling menu + if (index>=m_ScrollCount) return 0; + int count=m_ScrollHeight/s_Skin.ItemSettings[m_bSubMenu?MenuSkin::SUBMENU_ITEM:MenuSkin::COLUMN1_ITEM].itemHeight-1; + int newIndex=index; + for (int i=0;i=m_ScrollCount) break; + } + if (CanSelectItem(newIndex)) + index=newIndex; + } + } + else if (m_SearchScrollCount>m_SearchScrollHeight) + { + int index0=index; + if (wParam==VK_PRIOR) + { + if (indexlast) index=last; + } + } + if (index0==index) return 0; + if (m_Items[index].pItemInfo) + { + CString path; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + path=m_Items[index].pItemInfo->GetPath(); + } + if (!path.IsEmpty()) + UpdateAutoComplete(path); + } + } + else + { + // multiple columns + if (!m_bSubMenu) return 0; + if (wParam==VK_PRIOR) + { + int column=m_Items[index].column; + if (index>0 && m_Items.rbegin()->column>0 && m_Items[index-1].column!=column) + column--; + for (int i=0;icolumn>0 && m_Items[index+1].column!=column) + column++; + for (int i=index;i<(int)m_Items.size();i++) + if (CanSelectItem(i) && m_Items[i].column==column) + index=i; + } + } + if (index>=0) + { + CloseSubMenus(0,this); + ActivateItem(index,ACTIVATE_SELECT,NULL); + } + } + + if (wParam!=VK_UP && wParam!=VK_DOWN && wParam!=VK_LEFT && wParam!=VK_RIGHT && wParam!=VK_ESCAPE && wParam!=VK_RETURN) + return TRUE; + + if (index<0 && m_SearchState!=SEARCH_NONE) + index=m_SearchIndex; + if (index<0) index=-1; + bool bProgramsTree=(!m_bSubMenu && s_MenuMode==MODE_PROGRAMS && GetFocus()==m_pProgramsTree->m_hWnd); + if (bProgramsTree) + index=m_ProgramTreeIndex; + + int n=(int)m_Items.size(); + + if (wParam==VK_UP) + { + // previous item + int best=-1; + if (index<0) + { + // no item is selected - find the first selectable item in the last column then go up + int col=(m_bTwoColumns?1:0); + index=0; + for (int i=0;i0 && index==m_SearchIndex-m_SearchItemCount+1) + { + best=m_OriginalCount+m_SearchScrollCount-1; + } + else if (m_SearchScrollCount>0 && index>m_OriginalCount) + { + best=index-1; + } + else + { + int col=m_Items[index].column; + int x0=m_Items[index].itemRect.left; + int y0=m_Items[index].itemRect.top; + int scrollOffset=0; + if (m_ScrollCount>0) + scrollOffset=m_Items[m_ScrollCount-1].itemRect.bottom-m_rContent.top-m_ScrollHeight; + if (index0 && i>=m_OriginalCount) + continue; + if (item.column==col && bottom<=y0) + { + d=((y0-bottom)<<16)+abs(item.itemRect.left-x0); + } + else if (item.bInline && !item.bInlineFirst) + continue; + else if (s_MenuMode==MODE_SEARCH && item.id==MENU_SHUTDOWN_BUTTON) + continue; + } + if (d=0) + { + ActivateItem(best,ACTIVATE_SELECT,NULL); + if ((m_Items[best].categoryHash&CSearchManager::CATEGORY_MASK)==CSearchManager::CATEGORY_AUTOCOMPLETE && m_Items[best].pItemInfo) + { + CString path; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + path=m_Items[best].pItemInfo->GetPath(); + } + if (!path.IsEmpty()) + { + if (m_Options&CONTAINER_SEARCH) + m_pParent->UpdateAutoComplete(path); + else + UpdateAutoComplete(path); + } + } + if (!m_bSubMenu && s_MenuMode==MODE_PROGRAMS && best==m_ProgramTreeIndex) + m_pProgramsTree->SelectLast(); + } + } + if (wParam==VK_DOWN) + { + // next item + if (bOldOverride) + index=-1; + int best=-1; + if (index<0) + { + // no item is selected - find the last selectable item then go down + index=0; + for (int i=n-1;i>=0;i--) + { + const MenuItem &item=m_Items[i]; + if (CanSelectItem(i) && (!item.bInline || item.bInlineFirst) && (s_MenuMode!=MODE_SEARCH || item.id!=MENU_SHUTDOWN_BUTTON)) + { + index=i; + break; + } + } + best=index; + } + if (m_SearchScrollCount>0 && index==m_SearchIndex) + { + best=m_OriginalCount; + } + else if (m_SearchScrollCount>0 && index>=m_OriginalCount && index0) + scrollOffset=m_Items[m_ScrollCount-1].itemRect.bottom-m_rContent.top-m_ScrollHeight; + if (index0 && i>=m_OriginalCount) + continue; + if (item.column==col && top>=y0) + { + d=((top-y0)<<16)+abs(item.itemRect.left-x0); + } + else if (item.bInline && !item.bInlineFirst) + continue; + else if (s_MenuMode==MODE_SEARCH && item.id==MENU_SHUTDOWN_BUTTON) + continue; + } + if (d=0) + { + ActivateItem(best,ACTIVATE_SELECT,NULL); + if ((m_Items[best].categoryHash&CSearchManager::CATEGORY_MASK)==CSearchManager::CATEGORY_AUTOCOMPLETE && m_Items[best].pItemInfo) + { + CString path; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + path=m_Items[best].pItemInfo->GetPath(); + } + if (!path.IsEmpty()) + { + if (m_Options&CONTAINER_SEARCH) + m_pParent->UpdateAutoComplete(path); + else + UpdateAutoComplete(path); + } + } + if (!m_bSubMenu && s_MenuMode==MODE_PROGRAMS && best==m_ProgramTreeIndex) + m_pProgramsTree->SelectFirst(); + } + } + if (wParam==VK_ESCAPE && s_MenuMode==MODE_JUMPLIST) + { + SetMenuMode(MODE_NORMAL,true); + return 0; + } + bool bBack=((wParam==VK_LEFT && !s_bRTL) || (wParam==VK_RIGHT && s_bRTL)); + if (wParam==VK_ESCAPE || (bBack && GetKeyState(VK_CONTROL)>=0 && (s_Menus.size()>1 || (s_Menus.size()==1 && m_bSubMenu)))) + { + // close top menu + if (!s_Menus[s_Menus.size()-1]->m_bDestroyed) + s_Menus[s_Menus.size()-1]->PostMessage(WM_CLOSE); + if (s_Menus.size()>=2 && !s_Menus[s_Menus.size()-2]->m_bDestroyed) + s_Menus[s_Menus.size()-2]->SetActiveWindow(); + if (s_Menus.size()==1) + { + if (m_bSubMenu) + { + ::SetFocus(g_ProgramsButton); + } + else + { + // HACK: stops the call to SetActiveWindow(NULL). The correct behavior is to not close the taskbar when Esc is pressed + s_TaskbarState&=~ABS_AUTOHIDE; + } + } + } + else if (bBack && index>=0) + { + if (m_Items[index].bInline && !m_Items[index].bInlineFirst) + { + index--; + while (!CanSelectItem(index)) + index--; + if (index>=0) + ActivateItem(index,ACTIVATE_SELECT,NULL); + } + else + { + if (s_MenuMode==MODE_JUMPLIST && m_Items[index].jumpIndex>=0) + { + SetMenuMode(MODE_NORMAL,true); + return 0; + } + int column=(m_Items[index].column+(int)m_ColumnOffsets.size()-1)%(int)m_ColumnOffsets.size(); + int y0=(m_Items[index].itemRect.top+m_Items[index].itemRect.bottom)/2; + if (indexm_hWnd); + RECT rc={0}; + if (hItem) + TreeView_GetItemRect(m_pProgramsTree->m_hWnd,hItem,&rc,TRUE); + m_pProgramsTree->MapWindowPoints(m_hWnd,&rc); + y0=(rc.top+rc.bottom)/2; + } + int dist=INT_MAX; + index=-1; + for (int i=0;id) + { + index=i; + dist=d; + } + } + } + if (index>=0) + { + ActivateItem(index,ACTIVATE_SELECT,NULL); + if (s_MenuMode==MODE_PROGRAMS && index==m_ProgramTreeIndex) + { + POINT pt={0,y0}; + MapWindowPoints(m_pProgramsTree->m_hWnd,&pt,1); + m_pProgramsTree->SelectItem(pt.y); + } + } + } + } + + bool bForward=((wParam==VK_RIGHT && !s_bRTL) || (wParam==VK_LEFT && s_bRTL)); + if (wParam==VK_RETURN || bForward) + { + // open submenu + if (index>=0) + { + if (m_Items[index].bFolder && (bForward || !m_Items[index].bSplit) && (wParam==VK_RETURN || GetKeyState(VK_CONTROL)>=0)) + ActivateItem(index,ACTIVATE_OPEN_KBD,NULL); + else if (wParam==VK_RETURN) + ActivateItem(index,ACTIVATE_EXECUTE,NULL); + else if (bForward) + { + if (m_Items[index].bInline && !m_Items[index].bInlineLast) + { + index++; + while (!CanSelectItem(index)) + index++; + if (index>=0) + ActivateItem(index,ACTIVATE_SELECT,NULL); + } + else + { + int column=(m_Items[index].column+1)%(int)m_ColumnOffsets.size(); + int y0=(m_Items[index].itemRect.top+m_Items[index].itemRect.bottom)/2; + if (indexm_hWnd); + RECT rc={0}; + if (hItem) + TreeView_GetItemRect(m_pProgramsTree->m_hWnd,hItem,&rc,TRUE); + m_pProgramsTree->MapWindowPoints(m_hWnd,&rc); + y0=(rc.top+rc.bottom)/2; + } + int dist=INT_MAX; + index=-1; + for (int i=0;id) + { + index=i; + dist=d; + } + } + } + if (index>=0) + { + ActivateItem(index,ACTIVATE_SELECT,NULL); + if (s_MenuMode==MODE_PROGRAMS && index==m_ProgramTreeIndex) + { + POINT pt={y0,0}; + MapWindowPoints(m_pProgramsTree->m_hWnd,&pt,1); + m_pProgramsTree->SelectItem(pt.y); + } + } + } + } + } + else if (bForward) + { + for (int i=n-1;i>=0;i--) + { + if (CanSelectItem(i) && (!m_Items[i].bInline || m_Items[i].bInlineFirst)) + { + ActivateItem(i,ACTIVATE_SELECT,NULL); + break; + } + } + } + } + return 0; +} + +LRESULT CMenuContainer::OnSysKeyDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==VK_RETURN && m_HotItem>=0) + { + int index=m_HotItem; + if (m_Items[index].pItem1 && !m_Items[index].pItem2) + { + POINT pt={0,0}; + ActivateItem(index,ACTIVATE_PROPERTIES,&pt); + PostMessage(MCM_SETHOTITEM,index); + } + } + else + bHandled=FALSE; + return 0; +} + +LRESULT CMenuContainer::OnChar( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam>=0xD800 && wParam<=0xDBFF) + return TRUE; // don't support supplementary characters + + // find the current menu item + int index=m_HotItem; + if (index<0) index=-1; + + // find the next item with that accelerator + wchar_t buf[2]={(wchar_t)wParam,0}; + CharUpper(buf); + + int n=(int)m_Items.size(); + + int first=-1, count=0, firstCustom=-1, countCustom=0; + for (int i=1;i<=n;i++) + { + int idx=(index+2*n+i)%n; + if (m_Items[idx].accelerator==buf[0] && CanSelectItem(idx)) + { + if (first==-1) + first=idx; + count++; + if (m_Items[idx].bCustomAccelerator) + { + if (firstCustom==-1) + firstCustom=idx; + countCustom++; + } + } + } + + if (count==0) + return TRUE; // no item was found + + if (countCustom>1 || (countCustom==0 && count>1)) + { + // multiple items have the same accelerator. select the next one + ActivateItem(first,ACTIVATE_SELECT,NULL); + return 0; + } + + if (countCustom==1) + first=firstCustom; + + // exactly 1 item has that accelerator + if (m_Items[first].bHasJumpList && GetSettingInt(L"JumplistKeys")==0) + { + ActivateItem(first,ACTIVATE_SELECT,NULL); + return 0; + } + ActivateData data; + data.bNoModifiers=true; + if (!m_Items[first].bFolder || (!m_Items[first].bHasJumpList && m_Items[first].bSplit) || (m_Items[first].bHasJumpList && GetSettingInt(L"JumplistKeys")==1)) + { + ActivateItem(first,ACTIVATE_EXECUTE,NULL,&data); + return 0; + } + + // m_Items[first].bFolder + ActivateItem(first,ACTIVATE_OPEN_KBD,NULL,&data); + + return 0; +} + +LRESULT CMenuContainer::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + LOG_MENU(LOG_OPEN,L"Close Menu, ptr=%p",this); + if (m_pAccessible) + { + NotifyWinEvent(EVENT_SYSTEM_MENUPOPUPEND,m_hWnd,OBJID_CLIENT,CHILDID_SELF); + m_pAccessible->Reset(); + m_pAccessible=NULL; + } + if (m_pDropTargetHelper && m_pDragObject) + { + m_pDropTargetHelper->DragLeave(); + } + m_pDragObject=NULL; + m_pDropTargetHelper=NULL; + m_pDropTargetProxy->Reset(); + m_pDropTargetProxy=NULL; + RevokeDragDrop(m_hWnd); + // remember the scroll position + if (m_ScrollHeight>0 && m_FolderHash[0]) + s_MenuScrolls[m_FolderHash[0]]=m_ScrollOffset; + else + s_MenuScrolls.erase(m_FolderHash[0]); + + if (s_pHotMenu==this) + { + s_pHotMenu=NULL; + s_HotItem=-1; + } + if (s_pTipMenu==this) + { + s_pTipMenu=NULL; + TOOLINFO tool={sizeof(tool),TTF_ABSOLUTE|TTF_TRACK|TTF_TRANSPARENT}; + tool.uId=1; + s_Tooltip.SendMessage(TTM_TRACKACTIVATE,FALSE,(LPARAM)&tool); + } + if ((m_Options&CONTAINER_SEARCH) && !m_pParent->m_bDestroyed && !m_pParent->m_bInSearchUpdate) + { + m_pParent->m_SearchBox.SetWindowText(L""); + } + m_bDestroyed=true; + if (this==s_Menus[0]) + { + // cleanup when the last menu is closed + if (s_Theme) + CloseThemeData(s_Theme); + s_Theme=NULL; + if (s_PagerTheme) + CloseThemeData(s_PagerTheme); + s_PagerTheme=NULL; + if (s_Tooltip.m_hWnd) + s_Tooltip.DestroyWindow(); + s_Tooltip.m_hWnd=NULL; + s_TooltipBalloon.m_hWnd=NULL; // the balloon tooltip is owned, no need to be destroyed + if (s_UserPicture.m_hWnd) + s_UserPicture.DestroyWindow(); + s_UserPicture.m_hWnd=NULL; + s_pHotMenu=NULL; + s_HotItem=-1; + if (!m_bSubMenu) + EnableStartTooltip(true); + BufferedPaintUnInit(); + if (!m_bSubMenu && (s_TaskbarState&ABS_AUTOHIDE)) + { + HWND capture=GetCapture(); + if (!capture || !(capture==s_TaskBar || ::IsChild(s_TaskBar,capture))) + ::SetActiveWindow(NULL); // close the taskbar if it is auto-hide and doesn't have the mouse capture + } + if (s_XMouse) + SystemParametersInfo(SPI_SETACTIVEWINDOWTRACKING,NULL,(PVOID)TRUE,SPIF_SENDCHANGE); + g_SearchManager.CloseMenu(); + if (m_pProgramsTree && m_pProgramsTree->m_hWnd && s_MenuMode==MODE_PROGRAMS) + s_ProgramsScrollPos=m_pProgramsTree->GetScrollPos(SB_VERT); + s_bAllPrograms=false; + if ((m_Options&CONTAINER_ALLPROGRAMS) && g_TopWin7Menu && ::IsWindowVisible(g_TopWin7Menu)) + { + ::ShowWindow(g_UserPic,SW_SHOW); + ::SetFocus(g_ProgramsButton); + CPoint pt(GetMessagePos()); + RECT rc; + ::GetWindowRect(g_TopWin7Menu,&rc); + if (PtInRect(&rc,pt)) + { + ::ScreenToClient(g_TopWin7Menu,&pt); + ::PostMessage(g_TopWin7Menu,WM_MOUSEMOVE,0,MAKELONG(pt.x,pt.y)); + } + } + s_FirstMenu=NULL; + if (!(m_Options&CONTAINER_ALLPROGRAMS)) + { + g_CurrentCSMTaskbar=-1; + PressStartButton(s_TaskBarId,false); + } + s_TaskBar=s_StartButton=NULL; + s_TaskBarId=-1; + g_ItemManager.SaveCacheFile(); + if (s_ArrowsBitmap) DeleteObject(s_ArrowsBitmap); + s_ArrowsBitmap=NULL; + CloseLog(); + } + if (m_Options&CONTAINER_SEARCH) + s_SearchMenu=NULL; + if (m_ScrollTheme) + { + CloseThemeData(m_ScrollTheme); + m_ScrollTheme=NULL; + } + return 0; +} + +LRESULT CMenuContainer::OnShowWindow( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (!wParam && !m_bSubMenu && s_UserPicture) + s_UserPicture.ShowWindow(SW_HIDE); + bHandled=FALSE; + return 0; +} + +LRESULT CMenuContainer::OnRefresh( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + m_RefreshPosted=0; + if ((m_Options&CONTAINER_SEARCH) || (!m_bSubMenu && s_MenuMode==MODE_SEARCH)) + { + // update search results + unsigned int hash=0; + int index=m_ContextItem==-1?m_HotItem:m_ContextItem; + if (index>=0) + { + if (index>=m_OriginalCount && index<(int)m_Items.size()) + hash=m_Items[index].nameHash; + else if (s_bWin7Style && index>m_SearchIndex-m_SearchItemCount && index<=m_SearchIndex && m_Items[index].id!=MENU_SEARCH_EMPTY) + hash=m_SearchIndex-index+1; + } + bool bSearching=InitSearchItems(); + InitWindow(bSearching && s_MenuMode!=MODE_SEARCH); + Invalidate(); + int hotItem=-1; + if (s_bWin7Style && hash==1) + hotItem=m_SearchIndex; + else if (s_bWin7Style && hash==2) + hotItem=m_SearchIndex-1; + else if (s_bWin7Style && hash==3) + hotItem=m_SearchIndex-2; + else + { + for (int i=m_OriginalCount;i<(int)m_Items.size();i++) + { + if (hash && m_Items[i].nameHash==hash) + { + hotItem=i; + break; + } + } + } + if (m_ContextItem!=-1) + SetContextItem(hotItem); + if (hotItem==-1 && m_OriginalCount<(int)m_Items.size()) + { + if (s_SearchResults.autoCompletePath.IsEmpty() && wcsncmp(s_SearchResults.currentString,L"\\\\",2)!=0) + { + if (m_Items[m_OriginalCount].id==MENU_SEARCH_EMPTY) + { + if (!bSearching) + { + for (int i=0;i<(int)m_Items.size();i++) + { + if (m_Items[i].id==MENU_MORE_RESULTS) + { + hotItem=i; + break; + } + else if (m_Items[i].id==MENU_SEARCH_INTERNET || m_Items[i].id==MENU_SEARCH_PROVIDER) + { + hotItem=i; + break; + } + } + } + } + else if (m_Items[m_OriginalCount].id==MENU_SEARCH_CATEGORY) + hotItem=m_OriginalCount+1; + } + else + hotItem=-1; + } + if (hotItem>=0) + { + ActivateItem(hotItem,ACTIVATE_SELECT,NULL); + if (s_bPendingSearchEnter) + { + ActivateItem(hotItem,ACTIVATE_EXECUTE,NULL); + s_bPendingSearchEnter=false; + } + } + else + SetHotItem(-1); + } + else if (s_MenuMode==MODE_JUMPLIST) + { + OpenJumpList(m_SubJumpItem,false); + } + else + { + // updates the menu after drag/drop, delete, or rename operation + for (std::vector::reverse_iterator it=s_Menus.rbegin();*it!=this;++it) + if (!(*it)->m_bDestroyed) + (*it)->PostMessage(WM_CLOSE); + if (m_ScrollHeight>0 && m_FolderHash[0]) + s_MenuScrolls[m_FolderHash[0]]=m_ScrollOffset; + else + s_MenuScrolls.erase(m_FolderHash[0]); + if (!m_bSubMenu && !s_bWin7Style) + s_MenuMaxHeight[0]=-1; + InitItems(); + InitWindow(); + Invalidate(); + SetFocus(); + SetHotItem(-1); + } + return 0; +} + +void CMenuContainer::HideTemp( bool bHide ) +{ + ::PostMessage(g_OwnerWindow,WM_CLEAR,bHide,0); +} + +LRESULT CMenuContainer::OnActivate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (LOWORD(wParam)!=WA_INACTIVE) + { + if (s_Tooltip.m_hWnd) + s_Tooltip.SetWindowPos(HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); + return 0; + } +#ifndef PREVENT_CLOSING + if (lParam) + { + // check if another menu window is being activated + // if not, close all menus + for (std::vector::const_iterator it=s_Menus.begin();it!=s_Menus.end();++it) + if ((*it)->m_hWnd==(HWND)lParam || (*it)->m_SearchBox.m_hWnd==(HWND)lParam) + return 0; + + if ((HWND)lParam==g_OwnerWindow || (HWND)lParam==g_TopWin7Menu) + return 0; + + if (s_bPreventClosing && (::GetWindowLong((HWND)lParam,GWL_EXSTYLE)&WS_EX_TOPMOST)) + return 0; + } + + // a non-top-most window tries to activate while we are still here + if (s_bPreventClosing && (!g_TopWin7Menu || !s_bAllPrograms)) + HideTemp(true); + else + { + for (std::vector::reverse_iterator it=s_Menus.rbegin();it!=s_Menus.rend();++it) + if ((*it)->m_hWnd && !(*it)->m_bDestroyed) + { + (*it)->PostMessage(WM_CLOSE); + (*it)->m_bClosing=true; + } + if (g_TopWin7Menu && s_bAllPrograms) ::PostMessage(g_TopWin7Menu,WM_CLOSE,0,0); + } +#endif + + return 0; +} + +LRESULT CMenuContainer::OnMouseActivate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_Submenu>=0 || (m_Options&CONTAINER_SEARCH)) + return MA_NOACTIVATE; + bHandled=FALSE; + return 0; +} + +LRESULT CMenuContainer::OnMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (!m_bTrackMouse) + { + TRACKMOUSEEVENT track={sizeof(track),TME_LEAVE,m_hWnd,0}; + TrackMouseEvent(&track); + m_bTrackMouse=true; + } + if (!(wParam&MK_LBUTTON) && m_ClickIndex==-2) + SetClickItem(-1); + if (s_HotPos==GetMessagePos()) + return 0; // HACK - ignore the mouse if it hasn't moved since last time. otherwise the mouse can override the keyboard navigation + s_HotPos=GetMessagePos(); + POINT pt={(short)LOWORD(lParam),(short)HIWORD(lParam)}; + bool bArrow=false; + int index=HitTest(pt,&bArrow); + if (index!=m_ProgramButtonIndex) + m_bDisableProgHover=false; + if (GetCapture()==m_hWnd) + { + if (m_ClickIndex!=index) + { + if (!DragOut(m_ClickIndex,(m_Options&CONTAINER_APPS)!=0)) + SetHotItem(-2); + } + else + SetHotItem(index,bArrow,true); + } + else + { + if (index>=0 && m_Items[index].id==MENU_SEPARATOR) + index=m_HotItem; + SetHotItem(index,bArrow,true); + + UpdateScroll(&pt,false); + + if (m_Submenu<0 && !(m_Options&CONTAINER_SEARCH) && m_SearchState==SEARCH_NONE) + SetFocus(); + if (index>=0) + { + if ((m_Submenu>=0 && index!=m_Submenu) || (m_Submenu<0 && m_Items[index].bFolder) || (s_MenuMode==MODE_JUMPLIST && m_SubJumpItem>=0 && index!=m_SubJumpItem && index=0) + SetTimer(TIMER_HOVER,time); + } + LOG_MENU(LOG_MOUSE,L"Start Hover, index=%d",index); + } + } + else + m_HoverItem=-1; + } + else + m_HoverItem=-1; + } + + return 0; +} + +LRESULT CMenuContainer::OnMouseLeave( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_bTrackMouse) // HACK - somehow after a context menu WM_MOUSELEAVE comes even if we are not tracking the mouse + { + UpdateScroll(NULL,false); + SetHotItem(-1); + m_bTrackMouse=false; + m_bDisableProgHover=false; + if (m_HoverItem!=-1) + { + KillTimer(TIMER_HOVER); + m_HoverItem=-1; + } + } + return 0; +} + +LRESULT CMenuContainer::OnMouseWheel( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + POINT pt={(short)LOWORD(lParam),(short)HIWORD(lParam)}; + HWND hwnd=WindowFromPoint(pt); + if (hwnd!=m_hWnd) + { + for (std::vector::iterator it=s_Menus.begin();it!=s_Menus.end();++it) + { + if ((*it)->m_hWnd==hwnd) + { + (*it)->SendMessage(uMsg,wParam,lParam); + return 0; + } + } + } + if (m_ScrollCount<1 && m_SearchScrollCount<1) return 0; // nothing to scroll + UINT lines; + if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES,0,&lines,FALSE)) + lines=3; + if (lines<1) lines=1; + + m_MouseWheel+=lines*(short)HIWORD(wParam); + int n=m_MouseWheel/WHEEL_DELTA; + m_MouseWheel-=n*WHEEL_DELTA; + if (m_SearchScrollCount>0) + { + int pos=m_SearchScrollPos; + m_SearchScrollPos=m_Scrollbar.SetScrollPos(SB_CTL,m_SearchScrollPos-n); + if (m_SearchScrollPos!=pos) + { + Invalidate(); + s_HotPos=-1; + ScreenToClient(&pt); + OnMouseMove(WM_MOUSEMOVE,LOWORD(wParam),MAKELONG(pt.x,pt.y),bHandled); + } + } + else + { + int scroll=m_ScrollOffset; + scroll-=n*s_Skin.ItemSettings[m_bSubMenu?MenuSkin::SUBMENU_ITEM:MenuSkin::COLUMN1_ITEM].itemHeight; + if (scroll<0) scroll=0; + int total=m_Items[m_ScrollCount-1].itemRect.bottom-m_rContent.top-m_ScrollHeight; + if (scroll>total) scroll=total; + if (m_ScrollOffset!=scroll) + { + m_ScrollOffset=scroll; + UpdateScroll(); + Invalidate(); + s_HotPos=-1; + ScreenToClient(&pt); + OnMouseMove(WM_MOUSEMOVE,LOWORD(wParam),MAKELONG(pt.x,pt.y),bHandled); + } + } + return 0; +} + +bool CMenuContainer::GetDescription( int index, wchar_t *text, int size ) +{ + if (index<0 || index>=(int)m_Items.size()) + return false; + const MenuItem &item=m_Items[index]; + bool bLabel=false; + if (item.bStartScreen) + return false; + if (item.bInline) + { + int len=0; + for (const wchar_t *c=item.name;*c && len0; + text+=len; + size-=len; + } + if (item.id==MENU_PROGRAMS && s_MenuMode==MODE_PROGRAMS) + return false; + if (item.pStdItem && item.pStdItem->tip) + { + if (_wcsicmp(item.pStdItem->tip,L"none")==0) + return false; + // get the tip for the standard item + if (bLabel) + Sprintf(text,size,L"\r\n%s",item.pStdItem->tip); + else + Strcpy(text,size,item.pStdItem->tip); + return true; + } + + if (item.id==MENU_SEARCH_CATEGORY && item.categoryHash>=CSearchManager::CATEGORY_FILE && m_bHotArrow) + { + Sprintf(text,size,L"%s (Ctrl+Enter)",FindTranslation(L"Menu.MoreResults",L"See more results")); + return true; + } + if (item.id==MENU_NO && item.categoryHash==CSearchManager::CATEGORY_METROSETTING) + { + // try to get the description from the XML file. looks like it is always the same as the display name though + CComPtr pDoc; + if (SUCCEEDED(pDoc.CoCreateInstance(L"Msxml2.FreeThreadedDOMDocument"))) + { + pDoc->put_async(VARIANT_FALSE); + VARIANT_BOOL loaded; + if (pDoc->load(CComVariant(item.pItemInfo->PATH),&loaded)==S_OK && loaded==VARIANT_TRUE) + { + CComPtr pDescription; + HRESULT res=pDoc->selectSingleNode(CComBSTR(L"PCSettings/SearchableContent/SettingInformation/Description"),&pDescription); + if (res==S_OK) + { + CComBSTR desc; + if (pDescription->get_text(&desc)==S_OK) + { + if (SUCCEEDED(SHLoadIndirectString(desc,text,size,NULL))) + return true; + } + } + } + } + } + if (item.jumpIndex>=0 && item.id!=MENU_SEPARATOR && item.id!=MENU_EMPTY) + { + const CJumpGroup &group=s_JumpList.groups[LOWORD(item.jumpIndex)]; + const CJumpItem &jumpItem=group.items[HIWORD(item.jumpIndex)]; + if (m_bHotArrow) + { + if (group.type==CJumpGroup::TYPE_PINNED) + Strcpy(text,size,FindTranslation(L"Jumplist.UnpinTip",L"Unpin from this list")); + else + Strcpy(text,size,FindTranslation(L"Jumplist.PinTip",L"Pin to this list")); + return true; + } + if (jumpItem.type==CJumpItem::TYPE_ITEM) + { + CComQIPtr pItem=jumpItem.pItem; + if (pItem) + { + { + CComString pName; + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEEDITING,&pName))) + { + Strcpy(text,size,pName); + return true; + } + } + CComPtr pQueryInfo; + if (SUCCEEDED(pItem->BindToHandler(NULL,BHID_SFUIObject,IID_IQueryInfo,(void**)&pQueryInfo))) + { + CComString pTip; + if (FAILED(pQueryInfo->GetInfoTip(QITIPF_LINKNOTARGET,&pTip)) || !pTip) + return false; + + Strcpy(text,size,pTip); + return true; + } + } + } + else if (jumpItem.type==CJumpItem::TYPE_LINK) + { + CComQIPtr pLink=jumpItem.pItem; + if (pLink) + { + if (SUCCEEDED(pLink->GetDescription(text,size)) && text[0]) + return true; + wchar_t args[256]; + if (SUCCEEDED(pLink->GetArguments(args,_countof(args))) && args[0]) + { + // don't use default tip for items with arguments + Strcpy(text,size,item.name); + return true; + } + if (pLink->GetPath(text,size,NULL,0)==S_OK) + return true; + } + } + } + + if ((item.categoryHash&CSearchManager::CATEGORY_MASK)==CSearchManager::CATEGORY_FILE) + { + // for search files show the path + if (item.pItemInfo) + { + bool bShowPath; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + bShowPath=!item.pItemInfo->GetPath().IsEmpty(); + } + if (bShowPath) + { + CComPtr pItem; + if (SUCCEEDED(SHCreateItemFromIDList(item.pItemInfo->GetPidl(),IID_IShellItem,(void**)&pItem))) + { + CComString pName; + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_FILESYSPATH,&pName))) + { + Strcpy(text,size,pName); + return true; + } + } + } + } + } + + if (item.pItem1) + { + if (item.pItemInfo) + { + CString path; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + path=item.pItemInfo->GetPath(); + } + if (!path.IsEmpty() && PathIsNetworkPath(path)) + { + Strcpy(text,size,path); + return true; + } + } + + // get the tip from the shell + CComPtr pItem; + if (FAILED(SHCreateItemFromIDList(item.pItem1,IID_IShellItem,(void**)&pItem))) + return bLabel; + + CComPtr pQueryInfo; + if (FAILED(pItem->BindToHandler(NULL,BHID_SFUIObject,IID_IQueryInfo,(void**)&pQueryInfo))) + return bLabel; + + CComString pTip; + HRESULT hr=pQueryInfo->GetInfoTip(QITIPF_DEFAULT,&pTip); + if (FAILED(hr) || !pTip) + return bLabel; + + if (bLabel) + Sprintf(text,size,L"\r\n%s",pTip); + else + Strcpy(text,size,pTip); + return true; + } + return bLabel; +} + +LRESULT CMenuContainer::OnLButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (!GetCapture()) + { + if (m_Submenu<0 && !(m_Options&CONTAINER_SEARCH) && m_SearchState==SEARCH_NONE) + SetFocus(); + POINT pt={(short)LOWORD(lParam),(short)HIWORD(lParam)}; + SetClickItem(-1); + if (m_rUser1.left=0) + { + SetActiveWindow(); // must be done before the children are destroyed + // close all child menus + CloseSubMenus(0,this); + SetHotItem(-1); // must be done after the children are destroyed + } + return 0; + } + const MenuItem &item=m_Items[index]; + if (item.id==MENU_SEPARATOR) return 0; + if (index==m_ProgramButtonIndex && GetSettingInt(L"ProgramsStyle")==PROGRAMS_INLINE) + { + m_bDisableProgHover=true; + KillTimer(TIMER_HOVER); + } + SetClickItem(index); + m_bClickArrow=bArrow; + SetCapture(); + } + return 0; +} + +LRESULT CMenuContainer::OnLButtonDblClick( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + SetClickItem(-1); + // execute item under the mouse + POINT pt={(short)LOWORD(lParam),(short)HIWORD(lParam)}; + bool bArrow; + int index=HitTest(pt,&bArrow); + if (index<0) return 0; + const MenuItem &item=m_Items[index]; + if (item.id==MENU_SEPARATOR) return 0; + ClientToScreen(&pt); + if (s_bWin7Style && item.id==MENU_PROGRAMS) // only single clicks for All Programs + OnLButtonDown(WM_LBUTTONDOWN,wParam,lParam,bHandled); + else if (!bArrow) // ignore double-click on the split arrow + ActivateItem(index,ACTIVATE_EXECUTE,&pt); + return 0; +} + +LRESULT CMenuContainer::OnLButtonUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (GetCapture()==m_hWnd) + ReleaseCapture(); + else if (m_ClickIndex!=-2) + return 0; + POINT pt={(short)LOWORD(lParam),(short)HIWORD(lParam)}; + bool bArrow=false; + int index=HitTest(pt,&bArrow); + if (m_ClickIndex!=-2 && (index!=m_ClickIndex || bArrow!=m_bClickArrow)) + { + InvalidateItem(m_ClickIndex); + SetHotItem(-1); + return 0; + } + if (index<0) return 0; + const MenuItem &item=m_Items[index]; + POINT pt2=pt; + ClientToScreen(&pt2); + if (!item.bFolder) + { + if (item.jumpIndex>=0 && m_bHotArrow) + { + const CJumpGroup &group=s_JumpList.groups[LOWORD(item.jumpIndex)]; + const CJumpItem &jumpItem=group.items[HIWORD(item.jumpIndex)]; + PinJumpItem(s_JumpAppInfo,s_JumpList,LOWORD(item.jumpIndex),HIWORD(item.jumpIndex),group.type!=CJumpGroup::TYPE_PINNED,-1); + PostRefreshMessage(); + } + else if (item.id==MENU_SEARCH_CATEGORY && item.categoryHash>=CSearchManager::CATEGORY_FILE && m_bHotArrow) + { + ActivateData data; + data.bArrow=true; + ActivateItem(index,ACTIVATE_EXECUTE,&pt2,&data); + } + else + ActivateItem(index,ACTIVATE_EXECUTE,&pt2); + } + else + { + const MenuItem &item=m_Items[index]; + if (item.bSplit) + { + if (!bArrow) + { + ActivateItem(index,ACTIVATE_EXECUTE,&pt2); + return 0; + } + if ((index==m_Submenu || index==m_SubJumpItem) && (!m_SubShowTime || (int)(GetTickCount()-m_SubShowTime)>500)) + { + // second click on the arrow closes the menus + SetActiveWindow(); + // destroy old submenus + CloseSubMenus(0,this); + SetHotItem(index,true,true); + KillTimer(TIMER_HOVER); + return 0; + } + } + else if (s_bWin7Style && item.id==MENU_PROGRAMS && GetSettingInt(L"ProgramsStyle")==PROGRAMS_INLINE && m_SubShowTime && (int)(GetTickCount()-m_SubShowTime)<500) + return 0; // ignore clicks soon after the programs open + if (index!=m_Submenu) + { + ActivateItem(index,ACTIVATE_OPEN,NULL); + } + } + return 0; +} + +LRESULT CMenuContainer::OnRButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (!GetCapture()) + { + POINT pt={(short)LOWORD(lParam),(short)HIWORD(lParam)}; + SetClickItem(-1); + int index=HitTest(pt,NULL); + if (index>=0) + { + if (m_Items[index].id==MENU_SEPARATOR) return 0; + } + else if (!PtInRect(&m_rPadding,pt)) + return 0; + SetClickItem(index); + SetCapture(); + } + return 0; +} + +LRESULT CMenuContainer::OnRButtonUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (GetCapture()!=m_hWnd) + return 0; + ReleaseCapture(); + if (s_bNoContextMenu) return 0; + POINT pt={(short)LOWORD(lParam),(short)HIWORD(lParam)}; + bool bArrow=false; + int index=HitTest(pt,&bArrow); + if (index>=0) + { + if (m_Items[index].id==MENU_SEPARATOR) return 0; + if (m_Items[index].id!=MENU_SEARCH_CATEGORY || m_Items[index].categoryHash &items ) +{ + if ((m_Options&CONTAINER_DROP) && m_FolderHash[0]) + { + // save item names in the registry + CRegKey regOrder; + wchar_t name[100]; + if (regOrder.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu\\Order")!=ERROR_SUCCESS) + regOrder.Create(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu\\Order"); + std::vector hashes[2]; + for (std::vector::const_iterator it=items.begin();it!=items.end();++it) + { + if (m_FolderHash[1] && it->priority==2) + hashes[1].push_back(it->nameHash); + else + hashes[0].push_back(it->nameHash); + } + + Sprintf(name,_countof(name),L"%08X",m_FolderHash[0]); + if (hashes[0].empty()) + regOrder.SetBinaryValue(name,NULL,0); + else + regOrder.SetBinaryValue(name,&hashes[0][0],(int)hashes[0].size()*4); + if (m_FolderHash[1]) + { + Sprintf(name,_countof(name),L"%08X",m_FolderHash[1]); + if (hashes[1].empty()) + regOrder.SetBinaryValue(name,NULL,0); + else + regOrder.SetBinaryValue(name,&hashes[1][0],(int)hashes[1].size()*4); + } + } +} + +void CMenuContainer::LoadItemOrder( void ) +{ + bool bLoaded=false; + if ((m_Options&CONTAINER_DROP) && m_FolderHash[0]) + { + // load item names from the registry + std::vector hashes[2]; + CRegKey regOrder; + if (regOrder.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu\\Order",KEY_READ)==ERROR_SUCCESS) + { + wchar_t name[100]; + { + ULONG size=0; + Sprintf(name,_countof(name),L"%08X",m_FolderHash[0]); + regOrder.QueryBinaryValue(name,NULL,&size); + if (size>0 && !(size&3)) + { + hashes[0].resize(size/4); + regOrder.QueryBinaryValue(name,&hashes[0][0],&size); + bLoaded=true; + } + } + if (m_FolderHash[1]) + { + ULONG size=0; + Sprintf(name,_countof(name),L"%08X",m_FolderHash[1]); + regOrder.QueryBinaryValue(name,NULL,&size); + if (size>0 && !(size&3)) + { + hashes[1].resize(size/4); + regOrder.QueryBinaryValue(name,&hashes[1][0],&size); + bLoaded=true; + } + } + } + if (hashes[0].size()==1 && hashes[0][0]=='AUTO') + { + m_Options|=CONTAINER_AUTOSORT; + for (std::vector::iterator it=m_Items.begin();it!=m_Items.end();++it) + it->row=0; + } + else + { + m_Options&=~CONTAINER_AUTOSORT; + + // assign each m_Item an index based on its position in items. store in row + // unknown items get the index of the blank item, or at the end + for (std::vector::iterator it=m_Items.begin();it!=m_Items.end();++it) + { + unsigned int hash=it->nameHash; + const std::vector &hashRef=(it->priority==0?hashes[0]:hashes[1]); + it->row=(int)hashRef.size(); + for (int i=0;i<(int)hashRef.size();i++) + { + if (hashRef[i]==hash) + { + it->row=i; + break; + } + else if (hashRef[i]==FNV_HASH0) + it->row=i; + } + if (m_Options&CONTAINER_SORTZA) + it->row=-it->row; + } + } + } + else + { + for (std::vector::iterator it=m_Items.begin();it!=m_Items.end();++it) + it->row=0; + } + + if (!(m_Options&CONTAINER_DOCUMENTS) || GetSettingInt(L"SortRecentDocuments")!=2) + { + // sort by row, then by bFolder, then by name + s_bExtensionSort=(m_Options&CONTAINER_DOCUMENTS) && GetSettingInt(L"SortRecentDocuments")==1; + std::sort(m_Items.begin(),m_Items.end()); + s_bExtensionSort=false; + } + if (m_Options&CONTAINER_SORTZA) + std::reverse(m_Items.begin(),m_Items.end()); + + if ((m_Options&CONTAINER_DROP) && (m_Options&CONTAINER_SORTONCE) && !bLoaded) + { + std::vector items; + for (std::vector::const_iterator it=m_Items.begin();it!=m_Items.end();++it) + { + if (it->id==MENU_NO) + { + SortMenuItem item(*it); + items.push_back(item); + } + } + SaveItemOrder(items); + } +} + +void CMenuContainer::AddMRUAppId( const wchar_t *appid ) +{ + wchar_t path[256]; + Sprintf(path,_countof(path),L"APP:%s",appid); + AddMRUShortcut(path); +} + +void CMenuContainer::AddMRUShortcut( const wchar_t *path ) +{ + if (!*path) return; + Assert(s_bMRULoaded); + bool bFound=false; + for (int i=0;i0) + { + CString str=s_MRUShortcuts[i]; + for (;i>0;i--) + s_MRUShortcuts[i]=s_MRUShortcuts[i-1]; + s_MRUShortcuts[0]=str; + } + bFound=true; + break; + } + } + + if (!bFound) + { + for (int i=MRU_PROGRAMS_COUNT-1;i>0;i--) + s_MRUShortcuts[i]=s_MRUShortcuts[i-1]; + s_MRUShortcuts[0]=path; + } + + SaveMRUShortcuts(); +} + +void CMenuContainer::DeleteMRUAppId( const wchar_t *appid ) +{ + wchar_t path[256]; + Sprintf(path,_countof(path),L"APP:%s",appid); + DeleteMRUShortcut(path); +} + +void CMenuContainer::DeleteMRUShortcut( const wchar_t *path ) +{ + Assert(s_bMRULoaded); + if (path) + { + for (int i=0;i::iterator it=s_Menus.begin();it!=s_Menus.end();++it) + if (!(*it)->m_bDestroyed) + (*it)->ShowWindow(SW_HIDE); +} + +bool CMenuContainer::IsMenuWindow( HWND hWnd ) +{ + for (std::vector::iterator it=s_Menus.begin();it!=s_Menus.end();++it) + if (hWnd==(*it)->m_hWnd || (*it)->IsChild(hWnd)) + return true; + return false; +} + +bool CMenuContainer::CloseProgramsMenu( void ) +{ + if (s_Menus.empty()) return false; + + for (std::vector::const_reverse_iterator it=s_Menus.rbegin();it!=s_Menus.rend();++it) + if (!(*it)->m_bDestroyed) + (*it)->PostMessage(WM_CLOSE); + + return true; +} + +static void NewVersionCallback( VersionData &data ) +{ + wchar_t path[_MAX_PATH]; + GetModuleFileName(g_Instance,path,_countof(path)); + PathRemoveFileSpec(path); + PathAppend(path,L"ClassicShellUpdate.exe"); + wchar_t cmdLine[1024]; + Sprintf(cmdLine,_countof(cmdLine),L"\"%s\" -popup",path); + STARTUPINFO startupInfo={sizeof(startupInfo)}; + PROCESS_INFORMATION processInfo; + memset(&processInfo,0,sizeof(processInfo)); + if (CreateProcess(path,cmdLine,NULL,NULL,TRUE,0,NULL,NULL,&startupInfo,&processInfo)) + { + CloseHandle(processInfo.hThread); + CloseHandle(processInfo.hProcess); + } +} + +static bool CheckForUpdates( void ) +{ + bool bHasUpdates=false; + if (GetWinVersion()0; + } + } + } + if (!bHasUpdates) + { + CComPtr pSysInfo; + pSysInfo.CoCreateInstance(CLSID_SystemInformation); + if (pSysInfo) + { + VARIANT_BOOL reboot; + if (SUCCEEDED(pSysInfo->get_RebootRequired(&reboot)) && reboot) + { + LOG_MENU(LOG_OPEN,L"WU: Reboot required"); + bHasUpdates=true; + } + } + } + if (!bHasUpdates && GetWinVersion()>=WIN_VER_WIN8) + { + typedef HRESULT (WINAPI *FGetAutoUpdateNotification)(DWORD,DWORD*,DWORD*,DWORD*); + HMODULE mod=LoadLibrary(L"wuaext.dll"); + if (mod) + { + FGetAutoUpdateNotification fun=(FGetAutoUpdateNotification)GetProcAddress(mod,"GetAutoUpdateNotification"); + if (fun) + { + DWORD a,b,c; + HRESULT hr=fun(0,&a,&b,&c); + bHasUpdates=(a==1 || a==2); + LOG_MENU(LOG_OPEN,L"WU: GetAutoUpdateNotification: %d, %d, %d, %d",hr,a,b,c); + } + FreeLibrary(mod); + } + } + return bHasUpdates; +} + +static void CreateStartScreenFile( const wchar_t *fname ) +{ + wchar_t link[_MAX_PATH]; + GetModuleFileName(g_Instance,link,_countof(link)); + PathRemoveFileSpec(link); + PathAppend(link,L"Start Screen.lnk"); + CopyFile(link,fname,TRUE); +} + +bool CMenuContainer::HasMoreResults( void ) +{ + if (s_HasMoreResults==-1) + s_HasMoreResults=(GetSettingBool(L"SearchFiles") && HasSearchService())?1:0; + return s_HasMoreResults!=0; +} + +RECT CMenuContainer::CalculateWorkArea( const RECT &taskbarRect ) +{ + RECT rc=s_MenuLimits; + if ((s_TaskBarEdge==ABE_LEFT || s_TaskBarEdge==ABE_RIGHT) && GetSettingBool(L"ShowNextToTaskbar")) + { + // when the taskbar is on the side and the menu is not on top of it + // the start button is assumed at the top + if (s_TaskBarEdge==ABE_LEFT) + rc.left=taskbarRect.right; + else + rc.right=taskbarRect.left; + } + else + { + if (s_TaskBarEdge==ABE_BOTTOM) + { + // taskbar is at the bottom + rc.bottom=taskbarRect.top; + } + else if (s_TaskBarEdge==ABE_TOP) + { + // taskbar is at the top + rc.top=taskbarRect.bottom; + } + else + { + // taskbar is on the side, start button must be at the top + rc.top=s_StartRect.bottom; + } + } + + if (!s_bLockWorkArea) + { + // exclude floating keyboard + if (s_pFrameworkInputPane) + { + RECT kbdRect; + if (SUCCEEDED(s_pFrameworkInputPane->Location(&kbdRect))) + { + if (rc.topkbdRect.top && rc.leftkbdRect.left) + { + HMONITOR monitor=MonitorFromWindow(m_hWnd,MONITOR_DEFAULTTONULL); + if (monitor) + { + MONITORINFO info={sizeof(info)}; + GetMonitorInfo(monitor,&info); + if (kbdRect.bottom==info.rcMonitor.bottom && kbdRect.left==info.rcMonitor.left && kbdRect.right==info.rcMonitor.right) + { + // the keyboard is docked at the bottom of the monitor + rc.bottom=kbdRect.top; + } + } + } + } + } + } + return rc; +} + +POINT CMenuContainer::CalculateCorner( void ) +{ + RECT margin={0,0,0,0}; + if (IsAppThemed()) + AdjustWindowRect(&margin,GetWindowLong(GWL_STYLE),FALSE); + + POINT corner; + if (m_Options&CONTAINER_LEFT) + corner.x=s_MainMenuLimits.left+margin.left; + else + corner.x=s_MainMenuLimits.right+margin.right; + + if (m_Options&CONTAINER_TOP) + { + if (s_bBehindTaskbar) + corner.y=s_MainMenuLimits.top+margin.top; + else + corner.y=s_MainMenuLimits.top; + } + else + corner.y=s_MainMenuLimits.bottom+margin.bottom; + + return corner; +} + +// Toggles the start menu +HWND CMenuContainer::ToggleStartMenu( int taskbarId, bool bKeyboard, bool bAllPrograms ) +{ + s_bAllPrograms=false; + if (bAllPrograms) + { + if (CloseProgramsMenu()) + { + return NULL; + } + + ::ShowWindow(g_UserPic,SW_HIDE); + } + else + { + if (!CanShowMenu()) + return NULL; + if (!bKeyboard) s_LastFGWindow=NULL; + bool bSameTaskbar=(s_TaskBarId==taskbarId); + if (CloseStartMenu()) + { + if (bSameTaskbar) + return NULL; + } + + s_LastFGWindow=GetForegroundWindow(); + SetForegroundWindow(GetTaskbarInfo(taskbarId)->startButton); + EnableStartTooltip(false); + } + + { + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,GetSettingsRegPath())!=ERROR_SUCCESS) + regKey.Create(HKEY_CURRENT_USER,GetSettingsRegPath()); + + DWORD val; + if (regKey.QueryDWORDValue(L"ShowedStyle2",val)!=ERROR_SUCCESS) + { + regKey.SetDWORDValue(L"ShowedStyle2",1); + if (GetSettingBool(L"EnableSettings") && !IsSettingLocked(L"MenuStyle") && !IsSettingForcedDefault(L"MenuStyle")) + { + if (regKey.QueryDWORDValue(L"ShowedStyle2",val)==ERROR_SUCCESS && val) + { + EditSettings(false,IDS_STYLE_SETTINGS); + return NULL; + } + } + } + } + + if (GetSettingInt(L"CompatibilityFixes")&COMPATIBILITY_CRASH_TEST) + *(int*)0=0; + g_ItemManager.RefreshInfos(); + s_bWin7Style=GetSettingInt(L"MenuStyle")==MENU_WIN7; + + if (!s_StartMenuMsg) + s_StartMenuMsg=RegisterWindowMessage(L"ClassicStartMenu.StartMenuMsg"); + s_StartMenuParams.uEdge=0xFFFFFFFF; + s_TaskBarId=taskbarId; + TaskbarInfo *taskBar=GetTaskbarInfo(taskbarId); + s_TaskBar=taskBar->taskBar; + s_StartButton=taskBar->startButton; + s_bAllPrograms=bAllPrograms; + s_MenuMode=MODE_NORMAL; + s_PreSearchMenuMode=MODE_NORMAL; + s_MenuHeight=-1; + s_MenuMaxHeight[0]=-1; + s_MenuWidthJump=0; + s_MenuWidthMax=0; + s_MenuWidthNormal=-1; + s_ProgramsWidth=GetSettingInt(L"ProgramsWidth"); + s_JumplistWidth=GetSettingInt(L"JumplistWidth"); + s_BackgroundW1=s_BackgroundW2=s_BackgroundH1=s_BackgroundH2=0; + ClearOldState(); + int categories=0; + { + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu\\Settings",KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + DWORD log; + if (regKey.QueryDWORDValue(L"LogCategories",log)==ERROR_SUCCESS) + categories=log; + } + } +#ifdef BUILD_BETA + categories=LOG_ALL; +#endif + if (categories!=0) + { + wchar_t path[_MAX_PATH]=L"%LOCALAPPDATA%\\ClassicShell"; + DoEnvironmentSubst(path,_MAX_PATH); + SHCreateDirectory(NULL,path); + Strcat(path,_countof(path),L"\\StartMenuLog.txt"); + InitLog(categories,path); + } + + { + CSettingsLockWrite lock; + UpdateDefaultSettings(); + } + + // initialize all settings + bool bErr=false; + HMONITOR initialMonitor=MonitorFromWindow(s_TaskBar,MONITOR_DEFAULTTONEAREST); + int dpi=CItemManager::GetDPI(true); + if (!CItemManager::GetDPIOverride() && GetWinVersion()>=WIN_VER_WIN81) + { + HMODULE shModule=GetModuleHandle(L"Shcore.dll"); + if (shModule) + { + typedef HRESULT (WINAPI *tGetDpiForMonitor)( HMONITOR monitor, UINT dpiType, UINT *dpiX, UINT *dpiY ); + tGetDpiForMonitor GetDpiForMonitor=(tGetDpiForMonitor)GetProcAddress(shModule,"GetDpiForMonitor"); + if (GetDpiForMonitor) + { + UINT dpiX, dpiY; + if (SUCCEEDED(GetDpiForMonitor(initialMonitor,0,&dpiX,&dpiY))) + dpi=dpiY; + } + } + } + if (bAllPrograms) + { + bErr=!s_Skin.LoadMenuSkin(GetSettingString(L"SkinA"),GetSettingString(L"SkinVariationA"),GetSettingString(L"SkinOptionsA"),MenuSkin::SKIN_TYPE_ALL_PROGRAMS,LOADMENU_RESOURCES,dpi); + if (bErr) + s_Skin.LoadDefaultMenuSkin(MenuSkin::SKIN_TYPE_ALL_PROGRAMS,LOADMENU_RESOURCES,dpi); + } + else if (s_bWin7Style) + { + bErr=!s_Skin.LoadMenuSkin(GetSettingString(L"SkinW7"),GetSettingString(L"SkinVariationW7"),GetSettingString(L"SkinOptionsW7"),MenuSkin::SKIN_TYPE_WIN7,LOADMENU_RESOURCES,dpi); + if (bErr) + s_Skin.LoadDefaultMenuSkin(MenuSkin::SKIN_TYPE_WIN7,LOADMENU_RESOURCES,dpi); + } + else if (GetSettingInt(L"MenuStyle")==1) + { + bErr=!s_Skin.LoadMenuSkin(GetSettingString(L"SkinC2"),GetSettingString(L"SkinVariationC2"),GetSettingString(L"SkinOptionsC2"),MenuSkin::SKIN_TYPE_CLASSIC2,LOADMENU_RESOURCES,dpi); + if (bErr) + s_Skin.LoadDefaultMenuSkin(MenuSkin::SKIN_TYPE_CLASSIC2,LOADMENU_RESOURCES,dpi); + } + else + { + bErr=!s_Skin.LoadMenuSkin(GetSettingString(L"SkinC1"),GetSettingString(L"SkinVariationC1"),GetSettingString(L"SkinOptionsC1"),MenuSkin::SKIN_TYPE_CLASSIC1,LOADMENU_RESOURCES,dpi); + if (bErr) + s_Skin.LoadDefaultMenuSkin(MenuSkin::SKIN_TYPE_CLASSIC1,LOADMENU_RESOURCES,dpi); + } + + const MenuSkin &s_Skin=CMenuContainer::s_Skin; // shadow s_Skin with a const reference to catch any modifications to non-mutable members + g_CurrentCSMTaskbar=s_TaskBarId; + PressStartButton(s_TaskBarId,true); + g_ItemManager.ResetTempIcons(); + s_ScrollMenus=GetSettingInt(L"ScrollType"); + s_bExpandLinks=GetSettingBool(L"ExpandFolderLinks"); + s_bLogicalSort=GetSettingBool(L"NumericSort"); + s_MaxRecentDocuments=GetSettingInt(L"MaxRecentDocuments"); + s_ShellFormat=RegisterClipboardFormat(CFSTR_SHELLIDLIST); + s_ShellUrlFormat=RegisterClipboardFormat(CFSTR_INETURL); + s_DescriptorFormat=RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR); + s_ContentsFormat=RegisterClipboardFormat(CFSTR_FILECONTENTS); + s_MetroLinkFormat=RegisterClipboardFormat(L"ClassicShell.MetroLink"); + s_PreferredEffectFormat=RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT); + s_DropDescriptionFormat=RegisterClipboardFormat(CFSTR_DROPDESCRIPTION); + s_bNoCommonFolders=(SHRestricted(REST_NOCOMMONGROUPS)!=0); + s_bNoRun=(SHRestricted(REST_NORUN)!=0); + s_bNoClose=(SHRestricted(REST_NOCLOSE)!=0); + s_bHasTouch=GetWinVersion()>=WIN_VER_WIN8 && GetSettingBool(L"EnableTouch") && (GetSystemMetrics(SM_DIGITIZER)&NID_INTEGRATED_TOUCH)!=0; + s_HasMoreResults=-1; + s_bDisableHover=false; + s_bDragClosed=false; + s_bPendingSearchEnter=false; + InitTouchHelper(); + + bool bRemote=GetSystemMetrics(SM_REMOTESESSION)!=0; + wchar_t wabPath[_MAX_PATH]=L"%ProgramFiles%\\Windows Mail\\wab.exe"; + DoEnvironmentSubst(wabPath,_countof(wabPath)); + HANDLE hWab=CreateFile(wabPath,0,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + bool bPeople=(hWab!=INVALID_HANDLE_VALUE); + if (bPeople) CloseHandle(hWab); + s_bRTL=s_Skin.ForceRTL || IsLanguageRTL(); + + { + APPBARDATA appbar={sizeof(appbar)}; + s_TaskbarState=(DWORD)SHAppBarMessage(ABM_GETSTATE,&appbar); + } + + // the taskbar on Windows 7 (and most likely later versions) is always on top even though it doesn't have the ABS_ALWAYSONTOP flag. + if (GetWinVersion()>=WIN_VER_WIN7) + { + // also check the WS_EX_TOPMOST style - maybe some tool like DisableTaskbarOnTop is messing with it + if (::GetWindowLong(s_TaskBar,GWL_EXSTYLE)&WS_EX_TOPMOST) + s_TaskbarState|=ABS_ALWAYSONTOP; + } + + if (!bAllPrograms && (s_TaskbarState&ABS_AUTOHIDE)) + { + ::SetActiveWindow(s_TaskBar); + } + if (!bAllPrograms) + { + // set the taskbar as the foreground window so all keyboard input is sent to the taskbar thread (and be later captured by the start menu) + SetForegroundWindow(s_TaskBar); + } + + if (s_bActiveDirectory==-1) + { + DOMAIN_CONTROLLER_INFO *info; + DWORD err=DsGetDcName(NULL,NULL,NULL,NULL,DS_RETURN_FLAT_NAME,&info); + if (err==ERROR_SUCCESS) + { + s_bActiveDirectory=1; + NetApiBufferFree(info); + } + else + s_bActiveDirectory=0; + } + + if (GetWinVersion()>=WIN_VER_WIN8 && !s_pFrameworkInputPane && !(GetSettingInt(L"CompatibilityFixes")&COMPATIBILITY_NO_TOUCH_KBD)) + { + s_pFrameworkInputPane.CoCreateInstance(CLSID_FrameworkInputPane); + } + + s_bHasUpdates=(!bRemote || GetSettingBool(L"RemoteShutdown")) && GetSettingBool(L"CheckWinUpdates") && CheckForUpdates(); + + SYSTEM_POWER_CAPABILITIES powerCaps; + GetPwrCapabilities(&powerCaps); + + bool bHibernate=false; + if (powerCaps.HiberFilePresent) + { + bHibernate=true; +/* disabled for now, use group policy to hide Hibernate + // disable hibernate if hybrid sleep (fast s4) is enabled + SYSTEM_POWER_STATUS status; + if (GetSystemPowerStatus(&status) && (status.ACLineStatus==0 || status.ACLineStatus==1)) + { + GUID *pScheme; + if (PowerGetActiveScheme(NULL,&pScheme)==ERROR_SUCCESS) + { + DWORD index; + if ((status.ACLineStatus==1?PowerReadACValueIndex:PowerReadDCValueIndex)(NULL,pScheme,&GUID_SLEEP_SUBGROUP,&GUID_HIBERNATE_FASTS4_POLICY,&index)==ERROR_SUCCESS && index) + bHibernate=false; + LocalFree(pScheme); + } + }*/ + } + + for (int i=0;i<_countof(g_StdOptions);i++) + { + switch (g_StdOptions[i].id) + { + case MENU_COMPUTER: + if (s_bWin7Style) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + else + { + g_StdOptions[i].options=0; + int show=GetSettingInt(L"Computer"); + if (show==1) + g_StdOptions[i].options=MENU_ENABLED; + else if (show==2 || show==3) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + } + break; + case MENU_FAVORITES: + if (s_bWin7Style) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + else + { + g_StdOptions[i].options=0; + int show=GetSettingInt(L"Favorites"); + if (show==1) + g_StdOptions[i].options=MENU_ENABLED; + else if (show==2) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + } + break; + case MENU_DOCUMENTS: + if (s_bWin7Style) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + else + { + g_StdOptions[i].options=0; + int show=GetSettingInt(L"Documents"); + if (show==1) + g_StdOptions[i].options=MENU_ENABLED; + else if (show==2) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + } + break; + case MENU_LOGOFF: + if (s_bWin7Style) + g_StdOptions[i].options=SHRestricted(REST_STARTMENULOGOFF)!=1?MENU_ENABLED|MENU_EXPANDED:0; + else + g_StdOptions[i].options=GetSettingBool(L"LogOff")?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_DISCONNECT: + g_StdOptions[i].options=(bRemote && !SHRestricted(REST_NODISCONNECT))?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_SHUTDOWN: + case MENU_RESTART: + g_StdOptions[i].options=(!s_bNoClose && (!bRemote || GetSettingBool(L"RemoteShutdown")))?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_SHUTDOWN_NOUPDATE: + g_StdOptions[i].options=(s_bHasUpdates && !s_bNoClose && (!bRemote || GetSettingBool(L"RemoteShutdown")))?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_RESTART_NOUPDATE: + g_StdOptions[i].options=(s_bHasUpdates && GetWinVersion()>=WIN_VER_WIN8 && !s_bNoClose && (!bRemote || GetSettingBool(L"RemoteShutdown")))?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_SHUTDOWN_BOX: + g_StdOptions[i].options=0; + if (!bRemote || GetSettingBool(L"RemoteShutdown")) + { + int show=GetSettingInt(L"Shutdown"); + if (show==1) + g_StdOptions[i].options=MENU_ENABLED; + else if (show==2) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + } + break; + case MENU_SHUTDOWN_BUTTON: + g_StdOptions[i].options=GetSettingInt(L"ShutdownCommand")>SHUTDOWN_TYPE_NONE?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_UNDOCK: + { + HW_PROFILE_INFO info; + GetCurrentHwProfile(&info); + if ((info.dwDockInfo&(DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))!=DOCKINFO_DOCKED) + g_StdOptions[i].options=0; + else if (s_bWin7Style) + g_StdOptions[i].options=SHRestricted(REST_NOSMEJECTPC)?0:MENU_ENABLED|MENU_EXPANDED; + else + g_StdOptions[i].options=GetSettingBool(L"Undock")?MENU_ENABLED|MENU_EXPANDED:0; + } + break; + case MENU_CONTROLPANEL: + if (s_bWin7Style) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + else + { + g_StdOptions[i].options=0; + int show=GetSettingInt(L"ControlPanel"); + if (show==1) + g_StdOptions[i].options=MENU_ENABLED; + else if (show==2) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + } + break; + case MENU_SECURITY: + g_StdOptions[i].options=bRemote?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_NETWORK: + if (s_bWin7Style) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + else + { + g_StdOptions[i].options=0; + int show=GetSettingInt(L"Network"); + if (show==1) + g_StdOptions[i].options=MENU_ENABLED; + else if (show==2) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + } + break; + case MENU_PRINTERS: + if (s_bWin7Style) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + else + { + g_StdOptions[i].options=0; + int show=GetSettingInt(L"Printers"); + if (show==1) + g_StdOptions[i].options=MENU_ENABLED; + else if (show==2) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + } + break; + + case MENU_SEARCH_PRINTER: + g_StdOptions[i].options=s_bActiveDirectory==1?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_SEARCH_COMPUTERS: + g_StdOptions[i].options=(s_bActiveDirectory==1 && !SHRestricted(REST_HASFINDCOMPUTERS))?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_SEARCH_PEOPLE: + g_StdOptions[i].options=bPeople?MENU_ENABLED|MENU_EXPANDED:0; + break; + + case MENU_HELP: + if (s_bWin7Style) + g_StdOptions[i].options=SHRestricted(REST_NOSMHELP)?0:MENU_ENABLED|MENU_EXPANDED; + else + g_StdOptions[i].options=GetSettingBool(L"Help")?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_RUN: + if (s_bWin7Style) + g_StdOptions[i].options=s_bNoRun?0:MENU_ENABLED|MENU_EXPANDED; + else + g_StdOptions[i].options=GetSettingBool(L"Run")?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_TASKBAR: + g_StdOptions[i].options=!SHRestricted(REST_NOSETTASKBAR)?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_FEATURES: + g_StdOptions[i].options=(!SHRestricted(REST_NOSETFOLDERS) && !SHRestricted(REST_NOCONTROLPANEL))?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_CLASSIC_SETTINGS: + g_StdOptions[i].options=GetSettingBool(L"EnableSettings")?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_SEARCH: + g_StdOptions[i].options=GetSettingBool(L"Search")?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_SEARCH_BOX: + g_StdOptions[i].options=GetSettingInt(L"SearchBox")!=SEARCHBOX_HIDDEN?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_USERFILES: + if (s_bWin7Style) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + else + { + g_StdOptions[i].options=0; + int show=GetSettingInt(L"UserFiles"); + if (show==1) + g_StdOptions[i].options=MENU_ENABLED; + else if (show==2) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + } + break; + case MENU_USERDOCUMENTS: + if (s_bWin7Style) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + else + { + g_StdOptions[i].options=0; + int show=GetSettingInt(L"UserDocuments"); + if (show==1) + g_StdOptions[i].options=MENU_ENABLED; + else if (show==2) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + } + break; + case MENU_USERPICTURES: + if (s_bWin7Style) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + else + { + g_StdOptions[i].options=0; + int show=GetSettingInt(L"UserPictures"); + if (show==1) + g_StdOptions[i].options=MENU_ENABLED; + else if (show==2) + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + } + break; + case MENU_SLEEP: + g_StdOptions[i].options=(!s_bNoClose && (powerCaps.SystemS1 || powerCaps.SystemS2 || powerCaps.SystemS3))?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_HIBERNATE: + g_StdOptions[i].options=(!s_bNoClose && bHibernate)?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_SWITCHUSER: + { + g_StdOptions[i].options=MENU_ENABLED|MENU_EXPANDED; + CComPtr pShellDisp; + if (SUCCEEDED(CoCreateInstance(CLSID_Shell,NULL,CLSCTX_SERVER,IID_IShellDispatch2,(void**)&pShellDisp))) + { + long val; + if (SUCCEEDED(pShellDisp->IsRestricted(CComBSTR(L"System"),CComBSTR(L"HideFastUserSwitching"),&val)) && val) + g_StdOptions[i].options=0; + } + } + break; + case MENU_APPS: + g_StdOptions[i].options=(s_bWin7Style || (GetWinVersion()>=WIN_VER_WIN8 && GetSettingBool(L"ShowAppsMenu")))?MENU_ENABLED|MENU_EXPANDED:0; + break; + case MENU_PCSETTINGS: + g_StdOptions[i].options=(GetWinVersion()>=WIN_VER_WIN8)?MENU_ENABLED|MENU_EXPANDED:0; + break; + } + LOG_MENU(LOG_OPEN,L"ItemOptions[%d]=%d",i,g_StdOptions[i].options); + } + + s_bNoDragDrop=!GetSettingBool(L"EnableDragDrop"); + s_bNoContextMenu=!GetSettingBool(L"EnableContextMenu"); + s_bKeyboardCues=bKeyboard; + s_RecentPrograms=(TRecentPrograms)GetSettingInt(L"RecentPrograms"); + if (s_RecentPrograms!=RECENT_PROGRAMS_NONE) + LoadMRUShortcuts(); + s_ShutdownCommand=MENU_NO; + + // create the top menu from the Start Menu folders + CAbsolutePidl path1; + CAbsolutePidl path2; + s_PinFolder.Empty(); + if (bAllPrograms || GetSettingInt(L"PinnedPrograms")==PINNED_PROGRAMS_FAST) + { + ShGetKnownFolderIDList(FOLDERID_StartMenu,&path1); + CComString pPath; + ShGetKnownFolderPath(FOLDERID_StartMenu,&pPath); + if (pPath) + s_PinFolder=pPath; + if (!s_bNoCommonFolders) + ShGetKnownFolderIDList(FOLDERID_CommonStartMenu,&path2); + } + else + { + wchar_t path[_MAX_PATH]=START_MENU_PINNED_ROOT; + DoEnvironmentSubst(path,_countof(path)); + SHCreateDirectory(NULL,path); + s_PinFolder=path; + SHParseDisplayName(path,NULL,&path1,0,NULL); + } +#ifndef STARTSCREEN_WIN7 + if (GetWinVersion()>=WIN_VER_WIN8) +#endif + { + bool bPinned=GetSettingInt(L"PinnedPrograms")==PINNED_PROGRAMS_PINNED; + bool bShortcut=GetSettingBool(L"StartScreenShortcut"); + wchar_t path[_MAX_PATH]=START_MENU_PINNED_ROOT L"\\" STARTSCREEN_COMMAND; + DoEnvironmentSubst(path,_countof(path)); + if (bPinned) + { + if (GetFileAttributes(path)==INVALID_FILE_ATTRIBUTES) + { + if (bShortcut) + CreateStartScreenFile(path); + } + else if (!bShortcut) + DeleteFile(path); + } + CComString pPath; + ShGetKnownFolderPath(FOLDERID_StartMenu,&pPath); + Sprintf(path,_countof(path),L"%s\\" STARTSCREEN_COMMAND,pPath); + if (GetFileAttributes(path)==INVALID_FILE_ATTRIBUTES) + { + if (!bPinned && bShortcut) + CreateStartScreenFile(path); + } + else if (bPinned || !bShortcut) + DeleteFile(path); + } + + int options=CONTAINER_PROGRAMS|CONTAINER_DRAG|CONTAINER_DROP; + unsigned int rootSettings=0; + const StdMenuItem *pRoot=NULL; + if (bAllPrograms) + { + options|=CONTAINER_ALLPROGRAMS; + } + else + { + pRoot=ParseCustomMenu(rootSettings); + } + + bool bTopMost=(s_TaskbarState&ABS_ALWAYSONTOP)!=0 || bAllPrograms; + + SystemParametersInfo(SPI_GETACTIVEWINDOWTRACKING,NULL,&s_XMouse,0); + if (s_XMouse) + SystemParametersInfo(SPI_SETACTIVEWINDOWTRACKING,NULL,(PVOID)FALSE,SPIF_SENDCHANGE); + + s_bBehindTaskbar=!bAllPrograms; + s_bShowTopEmpty=false; + DWORD dwStyle=WS_POPUP|WS_CLIPCHILDREN; + s_SubmenuStyle=WS_POPUP; + + bool bTheme=IsAppThemed()!=FALSE; + if (bTheme) + { + if (s_Skin.Main_opacity==MenuSkin::OPACITY_SOLID) + dwStyle|=WS_BORDER; + if (s_Skin.Submenu_opacity==MenuSkin::OPACITY_SOLID) + s_SubmenuStyle|=WS_BORDER; + } + else + { + if (s_Skin.Main_opacity==MenuSkin::OPACITY_SOLID) + dwStyle|=s_Skin.Main_thin_frame?WS_BORDER:WS_DLGFRAME; + if (s_Skin.Submenu_opacity==MenuSkin::OPACITY_SOLID) + s_SubmenuStyle|=s_Skin.Submenu_thin_frame?WS_BORDER:WS_DLGFRAME; + } + + if (s_bWin7Style) + { + for (int i=MenuSkin::SHUTDOWN_BUTTON;i<=MenuSkin::SHUTDOWN_BUTTON_JUMP;i++) + { + const MenuSkin::ItemDrawSettings &settings=s_Skin.ItemSettings[i]; + int textHeight=settings.textMetrics.tmHeight+settings.textPadding.top+settings.textPadding.bottom; + int iconHeight=0; + if (s_bHasUpdates) + iconHeight=s_Skin.Shutdown_bitmap_Size.cy; + iconHeight+=settings.iconPadding.top+settings.iconPadding.bottom; + if (iconHeightCreate(owner,&rc,bAllPrograms?s_SubmenuStyle:dwStyle,WS_EX_TOOLWINDOW|((bTopMost || !s_bBehindTaskbar)?WS_EX_TOPMOST:0)|(s_bRTL?WS_EX_LAYOUTRTL:0))) + { + delete pStartMenu; + return NULL; + } + dummyRc=rc; + } + + if (GetSettingBool(L"MenuShadow") && s_Skin.Main_shadow==MenuSkin::SHADOW_ON) + SetClassLong(pStartMenu->m_hWnd,GCL_STYLE,GetClassLong(pStartMenu->m_hWnd,GCL_STYLE)|CS_DROPSHADOW); + else + SetClassLong(pStartMenu->m_hWnd,GCL_STYLE,GetClassLong(pStartMenu->m_hWnd,GCL_STYLE)&~CS_DROPSHADOW); + + if (s_bWin7Style && !s_bAllPrograms && s_Skin.User_bitmapSize.cx>0) + { + s_UserPicture.Create(pStartMenu->m_hWnd,NULL,NULL,WS_POPUP,WS_EX_TOOLWINDOW|WS_EX_LAYERED); + s_UserPicture.Init(pStartMenu); + } + dummyRc.right++; + pStartMenu->SetWindowPos(NULL,&dummyRc,SWP_NOZORDER); + + memset(&s_StartRect,0,sizeof(s_StartRect)); + + HMONITOR s_MenuMonitor=MonitorFromWindow(bAllPrograms?g_ProgramsButton:pStartMenu->m_hWnd,MONITOR_DEFAULTTONEAREST); + s_bLockWorkArea=true; + RECT taskbarRect; + if (initialMonitor!=s_MenuMonitor && s_StartMenuParams.uEdge==0xFFFFFFFF) + { + // somebody has moved the menu to another monitor. recalculate the working area and the taskbar orientation + MONITORINFO info={sizeof(info)}; + GetMonitorInfo(s_MenuMonitor,&info); + s_MenuLimits=info.rcMonitor; + s_StartButton=s_TaskBar=NULL; + if (bAllPrograms) + { + ::GetWindowRect(g_ProgramsButton,&s_StartRect); + } + else + { + RECT rc; + pStartMenu->GetWindowRect(&rc); + s_StartRect=rc; + taskbarRect=info.rcMonitor; + int dx=(rc.left+rc.right-info.rcMonitor.left-info.rcMonitor.right)/2; + int dy=(rc.top+rc.bottom-info.rcMonitor.top-info.rcMonitor.bottom)/2; + if (dx<0 && dy<0) + { + // top-left corner + s_StartRect.bottom=s_StartRect.top; + s_StartRect.right=s_StartRect.left; + if (rc.top-info.rcMonitor.top>rc.left-info.rcMonitor.left) + { + // top + taskbarRect.bottom=rc.top; + s_TaskBarEdge=ABE_TOP; + } + else + { + // left + taskbarRect.right=rc.left; + s_TaskBarEdge=ABE_LEFT; + } + } + else if (dx<0 && dy>=0) + { + // bottom-left corner + s_StartRect.top=s_StartRect.bottom; + s_StartRect.right=s_StartRect.left; + if (info.rcMonitor.bottom-rc.bottom>rc.left-info.rcMonitor.left) + { + // bottom + taskbarRect.top=rc.bottom; + s_TaskBarEdge=ABE_BOTTOM; + } + else + { + // left + taskbarRect.right=rc.left; + s_TaskBarEdge=ABE_LEFT; + } + } + else if (dx>=0 && dy<0) + { + // top-right corner + s_StartRect.bottom=s_StartRect.top; + s_StartRect.left=s_StartRect.right; + if (rc.top-info.rcMonitor.top>info.rcMonitor.right-rc.right) + { + // top + taskbarRect.bottom=rc.top; + s_TaskBarEdge=ABE_TOP; + } + else + { + // right + taskbarRect.left=rc.right; + s_TaskBarEdge=ABE_RIGHT; + } + } + else + { + // bottom-right corner + s_StartRect.top=s_StartRect.bottom; + s_StartRect.left=s_StartRect.right; + if (info.rcMonitor.bottom-rc.bottom>info.rcMonitor.right-rc.right) + { + // bottom + taskbarRect.top=rc.bottom; + s_TaskBarEdge=ABE_BOTTOM; + } + else + { + // right + taskbarRect.left=rc.right; + s_TaskBarEdge=ABE_RIGHT; + } + } + } + } + else if (s_StartMenuParams.uEdge!=0xFFFFFFFF) + { + s_StartButton=s_StartMenuParams.startButton; + s_TaskBar=s_StartMenuParams.taskbar; + s_TaskBarEdge=s_StartMenuParams.uEdge; + s_MenuLimits=s_StartMenuParams.monitorRect; + s_StartRect=s_StartMenuParams.startButtonRect; + taskbarRect=s_StartMenuParams.taskbarRect; + } + else + { + s_bLockWorkArea=false; + MONITORINFO info={sizeof(info)}; + GetMonitorInfo(s_MenuMonitor,&info); + s_TaskBarEdge=GetTaskbarPosition(s_TaskBar,NULL,NULL,&taskbarRect); + RECT rc=taskbarRect; + LOG_MENU(LOG_OPEN,L"Taskbar Rect: %d, %d, %d, %d",rc.left,rc.top,rc.right,rc.bottom); + { + RECT box; + if (::GetWindowRgnBox(s_TaskBar,&box)) + { + LOG_MENU(LOG_OPEN,L"Taskbar Region: %d, %d, %d, %d",box.left,box.top,box.right,box.bottom); + ::GetWindowRect(s_TaskBar,&rc); + OffsetRect(&box,rc.left,rc.top); + IntersectRect(&rc,&taskbarRect,&box); + } + } + switch (s_TaskBarEdge) + { + case ABE_LEFT: rc.right=info.rcWork.right; break; + case ABE_RIGHT: rc.left=info.rcWork.left; break; + case ABE_TOP: rc.bottom=info.rcWork.bottom; break; + case ABE_BOTTOM: rc.top=info.rcWork.top; break; + } + IntersectRect(&s_MenuLimits,&rc,&info.rcMonitor); + + if (s_StartButton) + { + ::GetWindowRect(s_StartButton,&s_StartRect); + } + else if (s_TaskBar) + { + // no start button. try to guess the rect + if (taskBar->oldButton) + { + ::GetWindowRect(taskBar->oldButton,&s_StartRect); + } + else + { + s_StartRect=taskbarRect; + if (s_TaskBarEdge==ABE_LEFT || s_TaskBarEdge==ABE_RIGHT) + { + ::GetWindowRect(taskBar->rebar,&rc); + s_StartRect.bottom=rc.top; + } + else if (::GetWindowLong(s_TaskBar,GWL_EXSTYLE)&WS_EX_LAYOUTRTL) + s_StartRect.left=s_StartRect.right-(s_StartRect.bottom-s_StartRect.top); + else + s_StartRect.right=s_StartRect.left+(s_StartRect.bottom-s_StartRect.top); + } + } + } + LOG_MENU(LOG_OPEN,L"Main Rect: %d, %d, %d, %d",s_MenuLimits.left,s_MenuLimits.top,s_MenuLimits.right,s_MenuLimits.bottom); + LOG_MENU(LOG_OPEN,L"Start Rect: %d, %d, %d, %d",s_StartRect.left,s_StartRect.top,s_StartRect.right,s_StartRect.bottom); + LOG_MENU(LOG_OPEN,L"Start Button: %08X",s_StartButton); + + s_TipShowTime=400; + s_TipHideTime=4000; + CString delay=GetSettingString(L"InfotipDelay"); + if (!delay.IsEmpty()) + { + wchar_t token[256]; + const wchar_t *str=GetToken(delay,token,_countof(token),L", \t"); + int time=_wtol(token); + if (time>=0) s_TipShowTime=time; + str=GetToken(str,token,_countof(token),L", \t"); + time=_wtol(token); + if (time>=0) s_TipHideTime=time; + } + if (s_TipShowTime>30000) s_TipShowTime=30000; + if (s_TipHideTime>30000) s_TipHideTime=30000; + + s_TipHideTimeFolder=s_TipShowTimeFolder=0; + delay=GetSettingString(L"FolderInfotipDelay"); + if (!delay.IsEmpty()) + { + wchar_t token[256]; + const wchar_t *str=GetToken(delay,token,_countof(token),L", \t"); + int time=_wtol(token); + if (time>=0) s_TipShowTimeFolder=time; + str=GetToken(str,token,_countof(token),L", \t"); + time=_wtol(token); + if (time>=0) s_TipHideTimeFolder=time; + } + if (s_TipShowTimeFolder>30000) s_TipShowTimeFolder=30000; + if (s_TipHideTimeFolder>30000) s_TipHideTimeFolder=30000; + + DWORD animFlags=0; + { + int anim=GetSettingInt(bAllPrograms?L"SubMenuAnimation":L"MainMenuAnimation"); + if (anim==3) animFlags=((rand()m_Options=options; + s_MainMenuLimits=s_MenuLimits; + } + else + { + RECT margin={0,0,0,0}; + AdjustWindowRect(&margin,dwStyle,FALSE); + if (s_Skin.Main_bitmap_slices_X[1]>0) + { + s_Skin.Caption_padding.left+=margin.left; if (s_Skin.Caption_padding.left<0) s_Skin.Caption_padding.left=0; + s_Skin.Caption_padding.top+=margin.top; if (s_Skin.Caption_padding.top<0) s_Skin.Caption_padding.top=0; + s_Skin.Caption_padding.bottom-=margin.bottom; if (s_Skin.Caption_padding.bottom<0) s_Skin.Caption_padding.bottom=0; + } + else + { + // no caption + s_Skin.Main_padding.left+=margin.left; if (s_Skin.Main_padding.left<0) s_Skin.Main_padding.left=0; + if (s_Skin.Main2_padding.left>=0) + { + s_Skin.Main2_padding.left+=margin.left; if (s_Skin.Main2_padding.left<0) s_Skin.Main2_padding.left=0; + } + } + s_Skin.Main_padding.right-=margin.right; if (s_Skin.Main_padding.right<0) s_Skin.Main_padding.right=0; + s_Skin.Main_padding.top+=margin.top; if (s_Skin.Main_padding.top<0) s_Skin.Main_padding.top=0; + s_Skin.Main_padding.bottom-=margin.bottom; if (s_Skin.Main_padding.bottom<0) s_Skin.Main_padding.bottom=0; + if (s_Skin.Main2_padding.left>=0) + { + s_Skin.Main2_padding.right-=margin.right; if (s_Skin.Main2_padding.right<0) s_Skin.Main2_padding.right=0; + s_Skin.Main2_padding.top+=margin.top; if (s_Skin.Main2_padding.top<0) s_Skin.Main2_padding.top=0; + s_Skin.Main2_padding.bottom-=margin.bottom; if (s_Skin.Main2_padding.bottom<0) s_Skin.Main2_padding.bottom=0; + } + if (s_bWin7Style) + { + s_Skin.Main_search_padding.left+=margin.left; if (s_Skin.Main_search_padding.left<0) s_Skin.Main_search_padding.left=0; + s_Skin.Main_search_padding.right-=margin.right; if (s_Skin.Main_search_padding.right<0) s_Skin.Main_search_padding.right=0; + s_Skin.Main_search_padding.top+=margin.top; if (s_Skin.Main_search_padding.top<0) s_Skin.Main_search_padding.top=0; + s_Skin.Main_search_padding.bottom-=margin.bottom; if (s_Skin.Main_search_padding.bottom<0) s_Skin.Main_search_padding.bottom=0; + + s_Skin.Main_jump_padding.right-=margin.right; if (s_Skin.Main_jump_padding.right<0) s_Skin.Main_jump_padding.right=0; + s_Skin.Main_jump_padding.top+=margin.top; if (s_Skin.Main_jump_padding.top<0) s_Skin.Main_jump_padding.top=0; + s_Skin.Main_jump_padding.bottom-=margin.bottom; if (s_Skin.Main_jump_padding.bottom<0) s_Skin.Main_jump_padding.bottom=0; + } + + if (!bTheme) + memset(&margin,0,sizeof(margin)); // in Classic mode don't offset the main menu by the border size + + // determine options + if (s_TaskBarEdge==ABE_LEFT || s_TaskBarEdge==ABE_RIGHT || s_TaskBarEdge==ABE_TOP) + { + options|=CONTAINER_TOP; + animFlags|=AW_VER_POSITIVE; + } + else + { + animFlags|=AW_VER_NEGATIVE; + } + + if (s_StartRect.right+s_StartRect.leftm_Options=options; + + s_MainMenuLimits=pStartMenu->CalculateWorkArea(taskbarRect); + corner=pStartMenu->CalculateCorner(); + } + + // reposition start menu + if (bTopMost || !s_bBehindTaskbar) + animFlags|=AW_TOPMOST; + pStartMenu->SetWindowPos((animFlags&AW_TOPMOST)?HWND_TOPMOST:HWND_TOP,corner.x,corner.y,0,0,(initialMonitor!=s_MenuMonitor && !bAllPrograms)?SWP_NOMOVE|SWP_NOSIZE:0); + + pStartMenu->InitItems(); + pStartMenu->m_MaxWidth=s_MainMenuLimits.right-s_MainMenuLimits.left; + g_ItemManager.UpdateNewPrograms(CPoint((s_StartRect.left+s_StartRect.right)/2,(s_StartRect.top+s_StartRect.bottom)/2)); + + pStartMenu->InitWindow(); + pStartMenu->SetHotItem((bKeyboard && bAllPrograms)?0:-1); + bool bTreeSelected=false; + if (s_bWin7Style && GetSettingInt(L"ProgramsStyle")==PROGRAMS_INLINE && GetSettingBool(L"OpenPrograms")) + { + pStartMenu->SetMenuMode(MODE_PROGRAMS); + if (pStartMenu->m_SearchIndex<0 || GetSettingInt(L"SearchBox")!=SEARCHBOX_NORMAL || !GetSettingBool(L"SearchSelect")) + { + bTreeSelected=true; + pStartMenu->SetHotItem(pStartMenu->m_ProgramTreeIndex,false,false); + } + } + + if (bAllPrograms) + { + ::InvalidateRect(g_ProgramsButton,NULL,TRUE); + ::UpdateWindow(g_ProgramsButton); + } + + BOOL animate; + if ((animFlags&(AW_BLEND|AW_SLIDE))==0) + animate=FALSE; + else + SystemParametersInfo(SPI_GETMENUANIMATION,NULL,&animate,0); + + if (s_TaskBar && s_bBehindTaskbar) + ::SetWindowPos(s_TaskBar,bTopMost?HWND_TOPMOST:HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); // bring the start button on top + + int speed=0; + if (animate) + { + speed=GetSettingInt(bAllPrograms?L"SubMenuAnimationSpeed":L"MainMenuAnimationSpeed"); + if (speed<=0) speed=MENU_ANIM_SPEED; + else if (speed>=10000) speed=10000; + } + { + RECT rc; + pStartMenu->GetWindowRect(&rc); + pStartMenu->AnimateMenu(animFlags,speed,rc); + } + + s_bOverrideFirstDown=false; + if (pStartMenu->m_SearchIndex>=0 && GetSettingInt(L"SearchBox")==SEARCHBOX_NORMAL && GetSettingBool(L"SearchSelect")) + { + pStartMenu->ActivateItem(pStartMenu->m_SearchIndex,ACTIVATE_SELECT,NULL); + if (pStartMenu->m_bTwoColumns && pStartMenu->m_Items[pStartMenu->m_SearchIndex].column==0 && pStartMenu->m_SearchIndex+1<(int)pStartMenu->m_Items.size() && pStartMenu->m_Items[pStartMenu->m_SearchIndex+1].column==1) + s_bOverrideFirstDown=true; + } + else if (!bTreeSelected) + { + pStartMenu->SetFocus(); + if (!bAllPrograms) + pStartMenu->SetHotItem(-1); + } + SetForegroundWindow(pStartMenu->m_hWnd); + SwitchToThisWindow(pStartMenu->m_hWnd,FALSE); // just in case + if (s_TaskBar && s_bBehindTaskbar) + { + // position the start button on top + if (s_StartButton) + ::SetWindowPos(s_StartButton,bTopMost?HWND_TOPMOST:HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); + // position the start menu behind the taskbar + pStartMenu->SetWindowPos(s_TaskBar,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); + } + if (bErr && GetSettingBool(L"ReportSkinErrors") && !*MenuSkin::s_SkinError) + { + Strcpy(MenuSkin::s_SkinError,_countof(MenuSkin::s_SkinError),LoadStringEx(IDS_SKIN_ERR_UNKNOWN)); + } + if (*MenuSkin::s_SkinError && GetSettingBool(L"ReportSkinErrors") && s_StartButton) + { + Strcat(MenuSkin::s_SkinError,_countof(MenuSkin::s_SkinError),LoadStringEx(IDS_SKIN_ERR_DISABLE)); + s_TooltipBalloon=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|(s_bRTL?WS_EX_LAYOUTRTL:0),TOOLTIPS_CLASS,NULL,WS_POPUP|TTS_BALLOON|TTS_CLOSE|TTS_NOPREFIX,0,0,0,0,pStartMenu->m_hWnd,NULL,g_Instance,NULL); + s_TooltipBalloon.SendMessage(TTM_SETMAXTIPWIDTH,0,500); + TOOLINFO tool={sizeof(tool),TTF_TRANSPARENT|TTF_TRACK|(s_bRTL?TTF_RTLREADING:0)}; + tool.uId=1; + tool.lpszText=MenuSkin::s_SkinError; + s_TooltipBalloon.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + if (bErr) + { + s_TooltipBalloon.SendMessage(TTM_SETTITLE,TTI_ERROR,(LPARAM)(const wchar_t*)LoadStringEx(IDS_SKIN_ERR)); + } + else + { + s_TooltipBalloon.SendMessage(TTM_SETTITLE,TTI_WARNING,(LPARAM)(const wchar_t*)LoadStringEx(IDS_SKIN_WARN)); + } + RECT rc; + ::GetWindowRect(s_StartButton,&rc); + s_TooltipBalloon.SendMessage(TTM_TRACKPOSITION,0,MAKELONG((rc.left+rc.right)/2,(rc.top+rc.bottom)/2)); + s_TooltipBalloon.SendMessage(TTM_TRACKACTIVATE,TRUE,(LPARAM)&tool); + pStartMenu->SetTimer(TIMER_BALLOON_HIDE,10000); + } + CheckForNewVersion(NULL,COMPONENT_MENU,CHECK_AUTO,NewVersionCallback); + + return pStartMenu->m_hWnd; +} + +bool CMenuContainer::ProcessMouseMessage( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + if (uMsg==WM_MOUSEMOVE) + { + if (!s_bAllPrograms) + return false; + if (hwnd && hwnd==g_ProgramsButton) + return true; + for (std::vector::const_iterator it=s_Menus.begin();it!=s_Menus.end();++it) + if ((*it)->m_hWnd==hwnd && (*it)->m_ContextItem<0) + { + (*it)->SendMessage(WM_MOUSEMOVE,wParam,lParam); + return true; + } + } + if (uMsg==WM_MOUSEHOVER) + { + if (hwnd && hwnd==g_ProgramsButton && GetSettingBool(L"CascadeAll")) + return true; + if (!s_bAllPrograms) + return false; + for (std::vector::const_iterator it=s_Menus.begin();it!=s_Menus.end();++it) + if ((*it)->m_hWnd==hwnd) + return false; + // if the mouse hovers over some window, close the menus + CloseSubMenus(0,NULL); + ::ShowWindow(g_UserPic,SW_SHOW); + CPoint pt(GetMessagePos()); + RECT rc; + ::GetWindowRect(g_TopWin7Menu,&rc); + if (PtInRect(&rc,pt)) + { + ::ScreenToClient(g_TopWin7Menu,&pt); + ::PostMessage(g_TopWin7Menu,WM_MOUSEMOVE,0,MAKELONG(pt.x,pt.y)); + } + return false; + } + return false; +} + +// Win7 stuff +void CMenuContainer::SetMenuMode( TMenuMode mode, bool bKeyboard ) +{ + if (mode==s_MenuMode) return; + InitializeOldState(); + + if (mode==MODE_SEARCH) + { + // switch to search - delete all additional items + ClearItems(m_Items.begin()+m_OriginalCount,m_Items.end()); + } + if (s_MenuMode==MODE_SEARCH) + { + // switch from search - restore scroll count + m_ScrollCount=m_OriginalScrollCount; + } + + s_MenuMode=mode; + + s_bOverrideFirstDown=false; + if (s_OldMenuState.mode==MODE_PROGRAMS) + { + // hide programs tree + m_pProgramsTree->ShowWindow(SW_HIDE); + s_ProgramsScrollPos=m_pProgramsTree->GetScrollPos(SB_VERT); + } + + if (s_MenuMode==MODE_JUMPLIST) + { + // from any to jumplist + InitWindow(); + if (bKeyboard) + { + for (int i=m_OriginalCount;i<(int)m_Items.size();i++) + { + if (m_Items[i].jumpIndex>=0) + { + SetHotItem(i); + break; + } + } + } + else + SetHotItem(-1); + } + else if (s_MenuMode==MODE_SEARCH) + { + // from any to search + InitWindow(); + s_SearchMenu=m_hWnd; + } + else if (s_OldMenuState.mode==MODE_JUMPLIST || s_OldMenuState.mode==MODE_SEARCH) + { + // from search and jumplist to program or normal + if (m_bRefreshItems) + InitItems(); + else + ClearItems(m_Items.begin()+m_OriginalCount,m_Items.end()); + s_JumpAppInfo=NULL; + int hotItem=m_HotItem; + InitWindow(); + if (s_UserPicture.m_hWnd && s_UserPictureRect.top=m_OriginalCount) + { + s_OldMenuState.hotItem=m_SubJumpItem; + s_OldMenuState.bHotArrow=true; + SetHotItem(m_SubJumpItem); + } + else + SetHotItem(hotItem); + } + m_SubJumpItem=-1; + s_SearchMenu=NULL; + } + else + { + InvalidateRect(&m_rContent); + } + + if (s_MenuMode==MODE_PROGRAMS) + { + for (std::vector::reverse_iterator it=s_Menus.rbegin();*it!=this;++it) + if (!(*it)->m_bDestroyed) + (*it)->PostMessage(WM_CLOSE); + + // initialize programs tree + MenuItem &item=m_Items[m_ProgramTreeIndex]; + item.itemRect=m_rContent; + item.itemRect.bottom=m_Items[m_ProgramTreeIndex+1].itemRect.top; + bool bNewTree=!m_pProgramsTree; + if (bNewTree) + { + m_pProgramsTree=new CProgramsTree(); + m_pProgramsTree->Create(this); + m_pProgramsTree->CreateItems(); + } + SetHotItem(m_ProgramTreeIndex); + RECT rc; + m_pProgramsTree->GetWindowRect(&rc); + int dh=rc.bottom-rc.top; + m_pProgramsTree->GetClientRect(&rc); + dh-=rc.bottom; + int itemHeight=TreeView_GetItemHeight(m_pProgramsTree->m_hWnd); + rc=item.itemRect; + int h=rc.bottom-rc.top; + int n=(h-dh)/itemHeight; + rc.bottom=rc.top+n*itemHeight+dh; + m_pProgramsTree->SetWindowPos(NULL,&rc,SWP_NOZORDER|SWP_NOACTIVATE); + if (bNewTree) + { + for (int i=0;iSendMessage(WM_VSCROLL,SB_LINEDOWN); // using SetSrollPos doesn't quite work because the contents are not scrolled during WM_PRINT + } + + ULONGLONG curTime; + GetSystemTimeAsFileTime((FILETIME*)&curTime); + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu",KEY_WRITE)!=ERROR_SUCCESS) + regKey.Create(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu"); + regKey.SetQWORDValue(L"LastProgramsTime",curTime); + if (s_OldMenuState.mode!=MODE_SEARCH) + m_pProgramsTree->SetFocus(); + TreeView_SelectItem(m_pProgramsTree->m_hWnd,NULL); + } + + if (m_Bitmap) + { + DeleteObject(m_Bitmap); + m_Bitmap=NULL; + } + if (s_UserPicture.m_hWnd && s_MenuMode!=MODE_NORMAL && s_MenuMode!=MODE_PROGRAMS) + s_UserPicture.SetWindowPos(NULL,0,0,0,0,SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_HIDEWINDOW|SWP_NOACTIVATE); + if (!m_bClosing && s_Skin.Main_opacity!=MenuSkin::OPACITY_SOLID && GetSettingBool(L"MainMenuAnimate") && IsWindowVisible()) + AnimateBackground(); + else + { + int tw, th; + CreateBackground(s_BackgroundW1,s_BackgroundW2,s_BackgroundH1,s_BackgroundH2,tw,th,true); + OffsetRect(&m_rContent,m_BitmapOffset,0); + OffsetRect(&m_rContent2,m_BitmapOffset,0); + if (m_Region && !s_bRTL) + OffsetRgn(m_Region,m_BitmapOffset,0); + if (m_SearchBox.m_hWnd && m_SearchIndex>=0) + { + RECT itemRect; + GetItemRect(m_SearchIndex,itemRect); + itemRect.right-=(itemRect.bottom-itemRect.top); + if (!s_Skin.Search_frame) + InflateRect(&itemRect,-1,-3); + m_SearchBox.SetWindowPos(NULL,&itemRect,SWP_NOZORDER); + } + Invalidate(); + ApplyRegion(TRUE); + } + + if (s_MenuMode==MODE_PROGRAMS) + { + // show programs tree + m_pProgramsTree->ShowWindow(SW_SHOW); + if (s_OldMenuState.mode!=MODE_SEARCH) + m_pProgramsTree->SetFocus(); + m_pProgramsTree->RedrawWindow(); + } + if (s_UserPicture.m_hWnd && (s_MenuMode==MODE_NORMAL || s_MenuMode==MODE_PROGRAMS) && !m_bClosing && IsWindowVisible()) + s_UserPicture.SetWindowPos(NULL,0,0,0,0,SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + ClearOldState(); +} + +void CMenuContainer::AnimateBackground( void ) +{ + TMenuMode newMode=s_MenuMode; + int newHotItem=m_HotItem; + bool bNewHotArrow=m_bHotArrow; + int width1=s_OldMenuState.mode==MODE_JUMPLIST?s_MenuWidthJump:s_MenuWidthNormal; + int width2=s_MenuMode==MODE_JUMPLIST?s_MenuWidthJump:s_MenuWidthNormal; + + int totalDW=width2-width1; + int totalDX=m_BitmapOffset-s_OldMenuState.bitmapOffset; + m_BitmapOffset=s_OldMenuState.bitmapOffset; + m_rMenu.left=m_BitmapOffset; + m_rMenu.right=m_rMenu.left+width1; + + for (std::vector::iterator it=m_Items.begin();it!=m_Items.end();++it) + { + if (it->column==1 && it->id!=MENU_SHUTDOWN_BUTTON) + it->itemRect.right-=totalDW; + OffsetRect(&it->itemRect,-totalDX,0); + } + + LARGE_INTEGER time0; + QueryPerformanceCounter(&time0); + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + + unsigned int *bits1=NULL, *bits2=NULL; + HBITMAP bitmap1=NULL, bitmap2=NULL; + + int oldDW=0, oldDX=0; + HDC hDst=CreateCompatibleDC(NULL); + if (s_bRTL) SetLayout(hDst,LAYOUT_RTL); + HGDIOBJ bmp0=GetCurrentObject(hDst,OBJ_BITMAP); + int step=25; + for (s_OldMenuState.blend=step;s_OldMenuState.blend<100;s_OldMenuState.blend+=step) + { + int dx=(totalDX*s_OldMenuState.blend)/100; + int dw=(totalDW*s_OldMenuState.blend)/100; + + int ddw=dw-oldDW; oldDW=dw; + int ddx=dx-oldDX; oldDX=dx; + + for (std::vector::iterator it=m_Items.begin();it!=m_Items.end();++it) + { + if (it->column==1 && it->id!=MENU_SHUTDOWN_BUTTON) + it->itemRect.right+=ddw; + OffsetRect(&it->itemRect,ddx,0); + } + + for (std::vector::iterator it=s_OldMenuState.items.begin();it!=s_OldMenuState.items.end();++it) + { + if (it->column==1 && it->id!=MENU_SHUTDOWN_BUTTON) + it->itemRect.right+=ddw; + OffsetRect(&it->itemRect,ddx,0); + } + + if (ddx && s_MenuMode==MODE_PROGRAMS) + { + RECT rc; + m_pProgramsTree->GetWindowRect(&rc); + ::MapWindowPoints(NULL,m_hWnd,(POINT*)&rc,2); + m_pProgramsTree->SetWindowPos(NULL,rc.left+ddx,rc.top,0,0,SWP_NOZORDER|SWP_NOSIZE); + } + if (m_SearchBox.m_hWnd && m_SearchIndex>=0) + { + RECT itemRect; + GetItemRect(m_SearchIndex,itemRect); + itemRect.right-=(itemRect.bottom-itemRect.top); + if (!s_Skin.Search_frame) + InflateRect(&itemRect,-1,-3); + m_SearchBox.SetWindowPos(NULL,&itemRect,SWP_NOZORDER); + } + + m_BitmapOffset+=ddx; + m_rMenu.left=m_BitmapOffset; + m_rMenu.right=m_rMenu.left+width1+dw; + + BITMAPINFO dib={sizeof(dib)}; + dib.bmiHeader.biWidth=(m_rMenu.right-m_rMenu.left); + dib.bmiHeader.biHeight=-(m_rMenu.bottom-m_rMenu.top); + dib.bmiHeader.biPlanes=1; + dib.bmiHeader.biBitCount=32; + dib.bmiHeader.biCompression=BI_RGB; + + // draw old menu + s_MenuMode=s_OldMenuState.mode; + m_HotItem=s_OldMenuState.hotItem; + m_bHotArrow=s_OldMenuState.bHotArrow; + m_Items.swap(s_OldMenuState.items); + + int tw, th; + HBITMAP bmp1=bitmap1; + RECT rContentA1, rContentB1; + if (!bmp1) + { + Assert(!m_Bitmap); + CreateBackground(s_OldMenuState.w1,s_OldMenuState.w2+dw,s_OldMenuState.h1,s_OldMenuState.h2,tw,th,false); + Assert(tw==m_rMenu.right-m_rMenu.left && th==m_rMenu.bottom-m_rMenu.top); + rContentA1=m_rContent; + rContentB1=m_rContent2; + OffsetRect(&m_rContent,m_BitmapOffset,0); + OffsetRect(&m_rContent2,m_BitmapOffset,0); + + bmp1=CreateDIBSection(hDst,&dib,DIB_RGB_COLORS,(void**)&bits1,NULL,0); + SelectObject(hDst,bmp1); + SetViewportOrgEx(hDst,-m_BitmapOffset,0,NULL); + DrawBackground(hDst,m_rMenu); + if (s_MenuMode==MODE_PROGRAMS) + { + RECT rc; + m_pProgramsTree->GetWindowRect(&rc); + ::MapWindowPoints(NULL,m_hWnd,(POINT*)&rc,2); + SetViewportOrgEx(hDst,rc.left-m_BitmapOffset,rc.top,NULL); + m_pProgramsTree->GetClientRect(&rc); + m_pProgramsTree->DrawTree(hDst,rc); + m_pProgramsTree->Print(hDst,PRF_NONCLIENT); + } + if (m_Bitmap) + DeleteObject(m_Bitmap); + m_Bitmap=NULL; + SetViewportOrgEx(hDst,0,0,NULL); + SelectObject(hDst,bmp0); + if (totalDW==0) + bitmap1=bmp1; + } + else + { + CreateContentRects(s_OldMenuState.w1,s_OldMenuState.w2+dw,s_OldMenuState.h1,s_OldMenuState.h2,tw,th); + rContentA1=m_rContent; + rContentB1=m_rContent2; + OffsetRect(&m_rContent,m_BitmapOffset,0); + OffsetRect(&m_rContent2,m_BitmapOffset,0); + } + bool bOpaqueA1=(s_Skin.Main_opacity==MenuSkin::OPACITY_GLASS || s_Skin.Main_opacity==MenuSkin::OPACITY_ALPHA); + bool bOpaqueB1=(s_Skin.Main2_opacity==MenuSkin::OPACITY_GLASS || s_Skin.Main2_opacity==MenuSkin::OPACITY_ALPHA); + if (s_MenuMode==MODE_JUMPLIST) + bOpaqueB1=(s_Skin.Jumplist_opacity==MenuSkin::OPACITY_GLASS || s_Skin.Jumplist_opacity==MenuSkin::OPACITY_ALPHA); + + // draw new menu + s_MenuMode=newMode; + m_HotItem=newHotItem; + m_bHotArrow=bNewHotArrow; + m_Items.swap(s_OldMenuState.items); + + HBITMAP bmp2=bitmap2; + RECT rContentA2, rContentB2; + if (!bmp2) + { + if (s_BackgroundW2>0) + CreateBackground(s_BackgroundW1,s_BackgroundW2+dw-totalDW,s_BackgroundH1,s_BackgroundH2,tw,th,true); + else + CreateBackground(s_BackgroundW1+dw-totalDW,s_BackgroundW2,s_BackgroundH1,s_BackgroundH2,tw,th,true); + Assert(tw==m_rMenu.right-m_rMenu.left && th==m_rMenu.bottom-m_rMenu.top); + rContentA2=m_rContent; + rContentB2=m_rContent2; + OffsetRect(&m_rContent,m_BitmapOffset,0); + OffsetRect(&m_rContent2,m_BitmapOffset,0); + + bmp2=CreateDIBSection(hDst,&dib,DIB_RGB_COLORS,(void**)&bits2,NULL,0); + SelectObject(hDst,bmp2); + SetViewportOrgEx(hDst,-m_BitmapOffset,0,NULL); + DrawBackground(hDst,m_rMenu); + if (s_MenuMode==MODE_PROGRAMS) + { + RECT rc; + m_pProgramsTree->GetWindowRect(&rc); + ::MapWindowPoints(NULL,m_hWnd,(POINT*)&rc,2); + SetViewportOrgEx(hDst,rc.left-m_BitmapOffset,rc.top,NULL); + m_pProgramsTree->GetClientRect(&rc); + m_pProgramsTree->DrawTree(hDst,rc); + m_pProgramsTree->Print(hDst,PRF_NONCLIENT); + } + if (m_Bitmap) + DeleteObject(m_Bitmap); + m_Bitmap=NULL; + SetViewportOrgEx(hDst,0,0,NULL); + SelectObject(hDst,bmp0); + if (totalDW==0) + bitmap2=bmp2; + + if (m_Region && !s_bRTL) + OffsetRgn(m_Region,m_BitmapOffset,0); + } + else + { + if (s_BackgroundW2>0) + CreateContentRects(s_BackgroundW1,s_BackgroundW2+dw-totalDW,s_BackgroundH1,s_BackgroundH2,tw,th); + else + CreateContentRects(s_BackgroundW1+dw-totalDW,s_BackgroundW2,s_BackgroundH1,s_BackgroundH2,tw,th); + rContentA2=m_rContent; + rContentB2=m_rContent2; + OffsetRect(&m_rContent,m_BitmapOffset,0); + OffsetRect(&m_rContent2,m_BitmapOffset,0); + } + + bool bOpaqueA2=(s_Skin.Main_opacity==MenuSkin::OPACITY_GLASS || s_Skin.Main_opacity==MenuSkin::OPACITY_ALPHA); + bool bOpaqueB2=(s_Skin.Main2_opacity==MenuSkin::OPACITY_GLASS || s_Skin.Main2_opacity==MenuSkin::OPACITY_ALPHA); + if (s_MenuMode==MODE_JUMPLIST) + bOpaqueB2=(s_Skin.Jumplist_opacity==MenuSkin::OPACITY_GLASS || s_Skin.Jumplist_opacity==MenuSkin::OPACITY_ALPHA); + + if (s_bRTL) + { + int q; + q=rContentA1.right; + rContentA1.right=dib.bmiHeader.biWidth-rContentA1.left; + rContentA1.left=dib.bmiHeader.biWidth-q; + q=rContentB1.right; + rContentB1.right=dib.bmiHeader.biWidth-rContentB1.left; + rContentB1.left=dib.bmiHeader.biWidth-q; + q=rContentA2.right; + rContentA2.right=dib.bmiHeader.biWidth-rContentA2.left; + rContentA2.left=dib.bmiHeader.biWidth-q; + q=rContentB2.right; + rContentB2.right=dib.bmiHeader.biWidth-rContentB2.left; + rContentB2.left=dib.bmiHeader.biWidth-q; + } + + Assert(!m_Bitmap); + unsigned int *bits3; + m_Bitmap=CreateDIBSection(hDst,&dib,DIB_RGB_COLORS,(void**)&bits3,NULL,0); + + // blend + int blend2=s_OldMenuState.blend; + int blend1=100-blend2; + for (int y=0,i=0;y<-dib.bmiHeader.biHeight;y++) + { + for (int x=0;x>8)&255; + int b1=(pixel1>>16)&255; + int a1=pixel1>>24; + if ((bOpaqueA1 && x>=rContentA1.left && x=rContentA1.top && y=rContentB1.left && x=rContentB1.top && y>8)&255; + int b2=(pixel2>>16)&255; + int a2=pixel2>>24; + if ((bOpaqueA2 && x>=rContentA2.left && x=rContentA2.top && y=rContentB2.left && x=rContentB2.top && y::iterator it=m_Items.begin();it!=m_Items.end();++it) + { + if (it->column==1 && it->id!=MENU_SHUTDOWN_BUTTON) + it->itemRect.right+=ddw; + OffsetRect(&it->itemRect,ddx,0); + } + if (ddx && s_MenuMode==MODE_PROGRAMS) + { + RECT rc; + m_pProgramsTree->GetWindowRect(&rc); + ::MapWindowPoints(NULL,m_hWnd,(POINT*)&rc,2); + m_pProgramsTree->SetWindowPos(NULL,rc.left+ddx,rc.top,0,0,SWP_NOZORDER|SWP_NOSIZE); + } + if (m_SearchBox.m_hWnd && m_SearchIndex>=0) + { + RECT itemRect; + GetItemRect(m_SearchIndex,itemRect); + itemRect.right-=(itemRect.bottom-itemRect.top); + if (!s_Skin.Search_frame) + InflateRect(&itemRect,-1,-3); + m_SearchBox.SetWindowPos(NULL,&itemRect,SWP_NOZORDER); + } + + m_BitmapOffset+=ddx; + m_rMenu.left=m_BitmapOffset; + m_rMenu.right=m_rMenu.left+width2; + int tw, th; + CreateBackground(s_BackgroundW1,s_BackgroundW2,s_BackgroundH1,s_BackgroundH2,tw,th,true); + OffsetRect(&m_rContent,m_BitmapOffset,0); + OffsetRect(&m_rContent2,m_BitmapOffset,0); + if (m_Region && !s_bRTL) + OffsetRgn(m_Region,m_BitmapOffset,0); + + Invalidate(); + ApplyRegion(TRUE); +} + +void CMenuContainer::InitializeOldState( void ) +{ + s_OldMenuState.mode=s_MenuMode; + s_OldMenuState.w1=s_BackgroundW1; + s_OldMenuState.w2=s_BackgroundW2; + s_OldMenuState.h1=s_BackgroundH1; + s_OldMenuState.h2=s_BackgroundH2; + s_OldMenuState.bitmapOffset=m_BitmapOffset; + s_OldMenuState.hotItem=m_HotItem; + s_OldMenuState.bHotArrow=m_bHotArrow; + s_OldMenuState.items.resize(m_Items.size()); + for (size_t i=0;i=0) + { + SetHotItem(i); + break; + } + } + } + else + SetHotItem(-1); + } + else + SetMenuMode(MODE_JUMPLIST,bKeyboard); +} + +void CMenuContainer::OpenSearchList( void ) +{ + s_PreSearchMenuMode=s_MenuMode==MODE_PROGRAMS?MODE_PROGRAMS:MODE_NORMAL; + SetMenuMode(MODE_SEARCH); +} diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MenuContainer.h b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MenuContainer.h new file mode 100644 index 0000000..9eb4122 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MenuContainer.h @@ -0,0 +1,1132 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#include "SkinManager.h" +#include "JumpLists.h" +#include "ItemManager.h" +#include "SearchManager.h" +#include "DragDrop.h" +#include "TouchHelper.h" +#include +#include + +//#define PREVENT_CLOSING // define this to prevent the menu from closing when it is deactivated (useful for debugging) +//#define REPEAT_ITEMS 10 // define this to repeat each menu item (useful to simulate large menus) +//#define REPEAT_JUMPLIST_ITEMS 2 // define this to repeat jumplist items (useful to simulate large menus) + +#ifdef BUILD_SETUP +#undef PREVENT_CLOSING // make sure it is defined in Setup +#undef REPEAT_ITEMS +#undef REPEAT_JUMPLIST_ITEMS +#endif + +enum TRecentPrograms; + +enum TMenuID +{ + MENU_NO=0, + MENU_LAST=0, + MENU_SEPARATOR, + MENU_EMPTY, + MENU_EMPTY_TOP, + MENU_RECENT, + MENU_JUMPITEM, + MENU_COLUMN_PADDING, + MENU_COLUMN_BREAK, + MENU_PROGRAMS_TREE, + + // standard menu items + MENU_PROGRAMS, + MENU_APPS, + MENU_COMPUTER, + MENU_FAVORITES, + MENU_DOCUMENTS, + MENU_USERFILES, + MENU_USERDOCUMENTS, + MENU_USERPICTURES, + MENU_SETTINGS, + MENU_CONTROLPANEL, + MENU_PCSETTINGS, + MENU_NETWORK, + MENU_SECURITY, + MENU_PRINTERS, + MENU_TASKBAR, + MENU_FEATURES, + MENU_CLASSIC_SETTINGS, + MENU_SEARCH, + MENU_SEARCH_FILES, + MENU_SEARCH_PRINTER, + MENU_SEARCH_COMPUTERS, + MENU_SEARCH_PEOPLE, + MENU_HELP, + MENU_RUN, + MENU_LOGOFF, + MENU_DISCONNECT, + MENU_UNDOCK, + MENU_MONITOROFF, + MENU_SHUTDOWN_BOX, + MENU_SHUTDOWN_BUTTON, + + // additional commands + MENU_CUSTOM, // used for any custom item + MENU_SLEEP, + MENU_HIBERNATE, + MENU_RESTART, + MENU_SHUTDOWN, + MENU_SWITCHUSER, + MENU_LOCK, + MENU_RECENT_PROGRAMS, + MENU_SEARCH_BOX, + MENU_SEARCH_CATEGORY, + MENU_SEARCH_EXECUTE, + MENU_SEARCH_EMPTY, + MENU_MORE_RESULTS, + MENU_SEARCH_INTERNET, + MENU_SEARCH_PROVIDER, + + // internal commands + MENU_SEARCH_FILES_CUSTOM, + MENU_LOGOFF_CONFIRM, + MENU_RESTART_ADVANCED, + MENU_RESTART_UPDATE, + MENU_SHUTDOWN_UPDATE, + MENU_RESTART_NOUPDATE, + MENU_SHUTDOWN_NOUPDATE, + MENU_SHUTDOWN_HYBRID, + + MENU_IGNORE=1024, // ignore this item +}; + +struct StdMenuItem +{ + const wchar_t *command; + TMenuID id; + const KNOWNFOLDERID *folder1; // NULL if not used + const KNOWNFOLDERID *folder2; // NULL if not used + + const wchar_t *label; // localization key + const wchar_t *tip; // default tooltip + const wchar_t *iconPath; + const wchar_t *link; + unsigned int settings; + const StdMenuItem *submenu; + CString labelString, tipString; // additional storage for the strings + + // user settings + enum + { + MENU_OPENUP = 0x000001, // prefer to open up + MENU_OPENUP_REC = 0x000002, // children prefer to open up + MENU_SORTZA = 0x000004, // sort backwards + MENU_SORTZA_REC = 0x000008, // children sort backwards + MENU_SORTONCE = 0x000010, // save the sort order the first time the menu is opened + MENU_ITEMS_FIRST = 0x000020, // place the custom items before the folder items + MENU_TRACK = 0x000040, // track shortcuts from this menu + MENU_NOTRACK = 0x000080, // don't track shortcuts from this menu + MENU_NOEXPAND = 0x000100, // don't expand this link item + MENU_SINGLE_EXPAND = 0x000200, // expand only one level + MENU_MULTICOLUMN = 0x000400, // make this item a multi-column item + MENU_NOEXTENSIONS = 0x000800, // hide extensions + MENU_INLINE = 0x001000, // inline sub-items in the parent menu + MENU_SPLIT_BUTTON = 0x002000, // the item is drawn as a split button + MENU_ITEM_DISABLED = 0x004000, // the item is disabled + MENU_NORECENT = 0x008000, // don't show recent items in the root menu (because a sub-menu uses MENU_RECENT_ITEMS) + + // style + MENU_STYLE_CLASSIC1 = 0x100000, + MENU_STYLE_CLASSIC2 = 0x200000, + MENU_STYLE_MASK = MENU_STYLE_CLASSIC1|MENU_STYLE_CLASSIC2, + }; +}; + +struct SpecialFolder +{ + const KNOWNFOLDERID *folder; + unsigned int settings; + wchar_t PATH[_MAX_PATH]; + + enum + { + FOLDER_NOSUBFOLDERS=1, // don't show the subfolders of this folder + FOLDER_NONEWFOLDER=2, // don't show the "New Folder" command + FOLDER_NODROP=4, // don't allow reordering, don't show "Sort" and "Auto Arrange" (also implies FOLDER_NONEWFOLDER) + FOLDER_NOPATH=8, // don't trust the child parsing names + }; +}; + +extern SpecialFolder g_SpecialFolders[]; +void InitializeSpecialFolders( void ); + +class CMenuAccessible; +class CProgramsTree; +class CMenuContainer; + +#ifndef __IFrameworkInputPane_INTERFACE_DEFINED__ + +MIDL_INTERFACE("226C537B-1E76-4D9E-A760-33DB29922F18") +IFrameworkInputPaneHandler : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE Showing( RECT *prcInputPaneScreenLocation, BOOL fEnsureFocusedElementInView ) = 0; + virtual HRESULT STDMETHODCALLTYPE Hiding( BOOL fEnsureFocusedElementInView ) = 0; +}; + +MIDL_INTERFACE("5752238B-24F0-495A-82F1-2FD593056796") +IFrameworkInputPane: public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE Advise( IUnknown *pWindow, IFrameworkInputPaneHandler *pHandler, DWORD *pdwCookie ) = 0; + virtual HRESULT STDMETHODCALLTYPE AdviseWithHWND( HWND hwnd, IFrameworkInputPaneHandler *pHandler, DWORD *pdwCookie ) = 0; + virtual HRESULT STDMETHODCALLTYPE Unadvise( DWORD dwCookie ) = 0; + virtual HRESULT STDMETHODCALLTYPE Location( RECT *prcInputPaneScreenLocation ) = 0; +}; + +#endif + +// CUserWindow - implementation for the user picture window +class CUserWindow: public CWindowImpl +{ +public: + CUserWindow( void ) { m_pOwner=NULL; m_Bits=NULL; m_bDefaultImage=true; m_Bitmap=m_UserBitmap=m_TimerBitmap=NULL; m_Timer=0; m_Size.cx=m_Size.cy=0; } + DECLARE_WND_CLASS_EX(L"ClassicShell.CUserWindow",0,COLOR_MENU) + + // message handlers + BEGIN_MSG_MAP( CUserWindow ) + MESSAGE_HANDLER( WM_DESTROY, OnDestroy ) + MESSAGE_HANDLER( WM_MOUSEACTIVATE, OnMouseActivate ) + MESSAGE_HANDLER( WM_NCHITTEST, OnNcHitTest ) + MESSAGE_HANDLER( WM_LBUTTONDOWN, OnLButtonDown ) + MESSAGE_HANDLER( WM_SETCURSOR, OnSetCursor ) + MESSAGE_HANDLER( WM_TIMER, OnTimer ) + END_MSG_MAP() + + void Init( CMenuContainer *pOwner ); + void Update( int alpha=255 ); + void UpdatePartial( POINT pos, const RECT *pClipRect ); + void SetImage( HBITMAP bmp, bool bAnimate ); + void StartImageTimer( HBITMAP bmp ); + +protected: + LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnMouseActivate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { return MA_NOACTIVATE; } + LRESULT OnNcHitTest( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { return HTCLIENT; } + LRESULT OnLButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSetCursor( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnEraseBkgnd( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { return 1; } + LRESULT OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + +private: + CMenuContainer *m_pOwner; + std::vector m_Source; + unsigned int *m_Bits; + bool m_bDefaultImage; + HBITMAP m_UserBitmap; + HBITMAP m_Bitmap; + SIZE m_Size; + int m_Timer; + HBITMAP m_TimerBitmap; + bool m_bUserBitmapMask; + + enum + { + TIMER_BLEND=1, + TIMER_SET=2, + }; +}; + +// sound events +enum TMenuSound +{ + SOUND_MAIN, + SOUND_POPUP, + SOUND_COMMAND, + SOUND_DROP, + SOUND_BUTTON_HOVER, +}; + +// CMenuContainer - implementation of a single menu box. +class CMenuContainer: public IDropTarget, public IFrameworkInputPaneHandler, public CWindowImplBaseT +{ +public: + virtual ATL::CWndClassInfo &GetWndClassInfo( void ) + { + static ATL::CWndClassInfo wc = + { + {sizeof(WNDCLASSEX),CS_DROPSHADOW|CS_DBLCLKS,StartWindowProc,0,0,NULL,NULL,NULL,(HBRUSH)(COLOR_MENU+1),NULL,L"ClassicShell.CMenuContainer",NULL}, + NULL,NULL,IDC_ARROW,TRUE,0,_T("") + }; + return wc; + } + + HWND Create( HWND hWndParent, RECT *pRect, DWORD dwStyle, DWORD dwExStyle ) + { + ATOM atom=GetWndClassInfo().Register(&m_pfnSuperWindowProc); + return CWindowImplBaseT::Create(hWndParent,pRect,NULL,dwStyle,dwExStyle,0u,atom,NULL); + } + + // message handlers + BEGIN_MSG_MAP( CMenuContainer ) + // forward all messages to m_pMenu2 and m_pMenu3 to ensure the context menu functions properly + if (m_pMenu3) + { + if (m_pMenu3->HandleMenuMsg2(uMsg,wParam,lParam,&lResult)==S_OK) + return TRUE; + } + else if (m_pMenu2) + { + m_pMenu2->HandleMenuMsg(uMsg,wParam,lParam); + } + MESSAGE_HANDLER( WM_CREATE, OnCreate ) + MESSAGE_HANDLER( WM_DESTROY, OnDestroy ) + MESSAGE_HANDLER( WM_SHOWWINDOW, OnShowWindow ) + MESSAGE_HANDLER( WM_PAINT, OnPaint ) + MESSAGE_HANDLER( WM_PRINTCLIENT, OnPaint ) + MESSAGE_HANDLER( WM_ERASEBKGND, OnEraseBkgnd ) + MESSAGE_HANDLER( WM_ACTIVATE, OnActivate ) + MESSAGE_HANDLER( WM_MOUSEACTIVATE, OnMouseActivate ) + MESSAGE_HANDLER( WM_MOUSEMOVE, OnMouseMove ) + MESSAGE_HANDLER( WM_MOUSELEAVE, OnMouseLeave ) + MESSAGE_HANDLER( WM_MOUSEWHEEL, OnMouseWheel ) + MESSAGE_HANDLER( WM_LBUTTONDOWN, OnLButtonDown ) + MESSAGE_HANDLER( WM_LBUTTONDBLCLK, OnLButtonDblClick ) + MESSAGE_HANDLER( WM_LBUTTONUP, OnLButtonUp ) + MESSAGE_HANDLER( WM_RBUTTONDOWN, OnRButtonDown ) + MESSAGE_HANDLER( WM_RBUTTONUP, OnRButtonUp ) + MESSAGE_HANDLER( WM_SETCURSOR, OnSetCursor ) + MESSAGE_HANDLER( WM_CONTEXTMENU, OnContextMenu ) + MESSAGE_HANDLER( WM_VSCROLL, OnVScroll ) + MESSAGE_HANDLER( WM_KEYDOWN, OnKeyDown ) + MESSAGE_HANDLER( WM_SYSKEYDOWN, OnSysKeyDown ) + MESSAGE_HANDLER( WM_CHAR, OnChar ) + MESSAGE_HANDLER( WM_SYSCHAR, OnChar ) + MESSAGE_HANDLER( WM_TIMER, OnTimer ) + MESSAGE_HANDLER( WM_SYSCOMMAND, OnSysCommand ) + MESSAGE_HANDLER( WM_SETTINGCHANGE, OnSettingChange ) + MESSAGE_HANDLER( WM_DISPLAYCHANGE, OnDisplayChange ) + MESSAGE_HANDLER( WM_GETOBJECT, OnGetAccObject ) + MESSAGE_HANDLER( WM_CTLCOLOREDIT, OnColorEdit ) + MESSAGE_HANDLER( WM_GESTURE, OnGesture ) + MESSAGE_HANDLER( WM_GESTURENOTIFY, OnGestureNotify ) + MESSAGE_HANDLER( MCM_REFRESH, OnRefresh ) + MESSAGE_HANDLER( MCM_SETCONTEXTITEM, OnSetContextItem ) + MESSAGE_HANDLER( MCM_REDRAWEDIT, OnRedrawEdit ) + MESSAGE_HANDLER( MCM_REFRESHICONS, OnRefreshIcons ) + MESSAGE_HANDLER( MCM_SETHOTITEM, OnSetHotItem ) + MESSAGE_HANDLER( MCM_WORKAREACHANGED, OnWorkAreaChanged ) + MESSAGE_HANDLER( s_StartMenuMsg, OnStartMenuMsg ) + MESSAGE_HANDLER( WM_POINTERDOWN, OnPointerDown ) + MESSAGE_HANDLER( WM_POINTERUPDATE, OnPointerUpdate ) + MESSAGE_HANDLER( WM_POINTERUP, OnPointerUp ) + COMMAND_CODE_HANDLER( EN_CHANGE, OnEditChange ) + REFLECT_NOTIFICATIONS() + END_MSG_MAP() + + static bool CloseStartMenu( void ); + static bool IsMenuOpened( void ) { return !s_Menus.empty(); } + static bool HasInputHandler( void ) { return s_pFrameworkInputPane!=NULL; } + static bool CanShowMenu( void ) { return s_Menus.empty() || !s_bPreventClosing; } + static bool IsMenuWindow( HWND hWnd ); + static bool IgnoreTaskbarTimers( void ) { return !s_Menus.empty() && (s_TaskbarState&ABS_AUTOHIDE); } + static HWND ToggleStartMenu( int taskbarId, bool bKeyboard, bool bAllPrograms ); + static bool ProcessMouseMessage( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); + static void RefreshIcons( void ); + static void RefreshSearch( void ); + static void PlayMenuSound( TMenuSound sound ); + +protected: + // IUnknown + virtual STDMETHODIMP QueryInterface( REFIID riid, void **ppvObject ); + + virtual ULONG STDMETHODCALLTYPE AddRef( void ) + { + return InterlockedIncrement(&m_RefCount); + } + + virtual ULONG STDMETHODCALLTYPE Release( void ) + { + long nTemp=InterlockedDecrement(&m_RefCount); + if (!nTemp) delete this; + return nTemp; + } + + // IDropTarget + virtual HRESULT STDMETHODCALLTYPE DragEnter( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ); + virtual HRESULT STDMETHODCALLTYPE DragOver( DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ); + virtual HRESULT STDMETHODCALLTYPE DragLeave( void ); + virtual HRESULT STDMETHODCALLTYPE Drop( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ); + + // IFrameworkInputPaneHandler + virtual HRESULT STDMETHODCALLTYPE Showing( RECT *prcInputPaneScreenLocation, BOOL fEnsureFocusedElementInView ); + virtual HRESULT STDMETHODCALLTYPE Hiding( BOOL fEnsureFocusedElementInView ); + + LRESULT OnCreate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnShowWindow( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnRefresh( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnPaint( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnEraseBkgnd( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { return 1; } + LRESULT OnActivate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnMouseActivate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnMouseLeave( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnMouseWheel( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnLButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnLButtonDblClick( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnLButtonUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnRButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnRButtonUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSetCursor( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnContextMenu( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnVScroll( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnKeyDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSysKeyDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnChar( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSysCommand( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSettingChange( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnDisplayChange( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnWorkAreaChanged( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnGetAccObject( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSetContextItem( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnColorEdit( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnGesture( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnGestureNotify( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnPointerDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnPointerUpdate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnPointerUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnRedrawEdit( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnRefreshIcons( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSetHotItem( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnStartMenuMsg( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnEditChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + virtual void OnFinalMessage( HWND ) { Release(); } + +protected: + CMenuContainer( CMenuContainer *pParent, int index, int options, const StdMenuItem *pStdItem, PIDLIST_ABSOLUTE path1, PIDLIST_ABSOLUTE path2 ); + ~CMenuContainer( void ); + +private: + // options when creating a container + enum + { + CONTAINER_MULTICOLUMN = 0x0000001, // use multiple columns instead of a single scrolling column + CONTAINER_MULTICOL_REC = 0x0000002, // the children will be multi-column + CONTAINER_CONTROLPANEL = 0x0000004, // this is the control panel, don't go into subfolders + CONTAINER_PROGRAMS = 0x0000008, // this is a folder from the Start Menu hierarchy (drop operations prefer link over move) + CONTAINER_DOCUMENTS = 0x0000010, // sort by time, limit the count (for recent documents) + CONTAINER_ALLPROGRAMS = 0x0000020, // this is the main menu of All Programs (combines the Start Menu and Programs folders) + CONTAINER_RECENT = 0x0000040, // insert recent programs (sorted by time) + CONTAINER_LINK = 0x0000080, // this is an expanded link to a folder (always scrolling) + CONTAINER_ITEMS_FIRST = 0x0000100, // put standard items at the top + CONTAINER_DRAG = 0x0000200, // allow items to be dragged out + CONTAINER_DROP = 0x0000400, // allow dropping of items + CONTAINER_LEFT = 0x0000800, // the window is aligned on the left + CONTAINER_TOP = 0x0001000, // the window is aligned on the top + CONTAINER_AUTOSORT = 0x0002000, // the menu is always in alphabetical order + CONTAINER_OPENUP_REC = 0x0004000, // the container's children will prefer to open up instead of down + CONTAINER_SORTZA = 0x0008000, // the container will sort backwards by default + CONTAINER_SORTZA_REC = 0x0010000, // the container's children will sort backwards by default + CONTAINER_SORTONCE = 0x0020000, // the container will save the sort order the first time the menu is opened + CONTAINER_TRACK = 0x0040000, // track shortcuts from this menu + CONTAINER_NOSUBFOLDERS = 0x0080000, // don't go into subfolders + CONTAINER_NONEWFOLDER = 0x0100000, // don't show the "New Folder" command + CONTAINER_NOPATH = 0x0200000, // don't trust the child parsing names + CONTAINER_SEARCH = 0x0400000, // this is he search results submenu + CONTAINER_NOEXTENSIONS = 0x0800000, // hide extensions + CONTAINER_JUMPLIST = 0x1000000, // this is a jumplist menu + CONTAINER_APPS = 0x2000000, // this is the folder for Metro apps + }; + + // description of a menu item + struct MenuItem + { + MenuItem( TMenuID _id=MENU_NO ) + { + id=_id; + pStdItem=NULL; + nameHash=0; + pItemInfo=NULL; + drawType=MenuSkin::COLUMN1_ITEM; + column=row=0; + memset(&itemRect,0,sizeof(itemRect)); + bFolder=bLink=bPrograms=bAlignBottom=bBreak=bInline=bInlineFirst=bInlineLast=bSplit=bHasJumpList=bMetroLink=bMetroApp=bBlankSeparator=bNew=bStartScreen=bCustomAccelerator=false; + priority=0; + pItem1=pItem2=NULL; + mfuHash=0; + categoryHash=0; + jumpIndex=-1; + accelerator=0; + drive=0; + textStart=textEnd=0; + mruOrder=-1; + nameOffset=0; + } + + TMenuID id; // if pStdItem!=NULL, this is pStdItem->id. otherwise it can only be MENU_NO, MENU_SEPARATOR, MENU_EMPTY or MENU_EMPTY_TOP + const StdMenuItem *pStdItem; // NULL if not a standard menu item + CString name; + unsigned int nameHash; + const CItemManager::ItemInfo *pItemInfo; + MenuSkin::TItemDrawType drawType; + int column; + int row; + RECT itemRect; + bool bFolder:1; // this is a folder - draw arrow + bool bLink:1; // this is a link (if a link to a folder is expanded it is always single-column) + bool bPrograms:1; // this item is part of the Start Menu folder hierarchy + bool bAlignBottom:1; // two-column menu: this item is aligned to the bottom + bool bBreak:1; // two-column menu: this item starts the second column + bool bInline:1; // this item is inlined in the parent menu + bool bInlineFirst:1; // this item is the first from the inlined group + bool bInlineLast:1; // this item is the last from the inlined group + bool bSplit:1; // split button item + bool bHasJumpList:1; // this item has a jump list + bool bMetroLink:1; // this is a Windows 8 Metro shortcut + bool bMetroApp:1; // this is a Windows 10 Metro app item + bool bBlankSeparator:1; // this is a blank separator that is the same size as normal items + bool bNew:1; // this is a highlighted new item + bool bStartScreen:1; // this is the start screen shortcut item + bool bCustomAccelerator:1; // the accelerator is specified explicitly + char priority; // used for sorting of the All Programs menu (0 for Start Menu, 1 for the separator, 2 for the Programs) + char drive; + wchar_t accelerator; // accelerator character, 0 if none + + // pair of shell items. 2 items are used to combine a user folder with a common folder (I.E. user programs/common programs) + PIDLIST_ABSOLUTE pItem1; + PIDLIST_ABSOLUTE pItem2; + + unsigned int mfuHash; // MENU_RECENT + short mruOrder; // MENU_RECENT + short nameOffset; // MENU_RECENT + unsigned int categoryHash; // search item (lower 4 bits correspond to category) + short textStart, textEnd; // start and end horizontal offset of the text + int jumpIndex; // MENU_JUMPITEM: MAKELONG(group,item) + + bool operator<( const MenuItem &item ) const + { + if (priorityitem.priority) return false; + if (rowitem.row) return false; + if ((bFolder && !bHasJumpList) && !(item.bFolder && !item.bHasJumpList)) return true; + if (!(bFolder && !bHasJumpList) && (item.bFolder && !item.bHasJumpList)) return false; + if (drive && !item.drive) return true; + if (!drive && item.drive) return false; + if (drive && item.drive) return drivex.priority) return false; + if ((bFolder && !bHasJumpList) && !(x.bFolder && !x.bHasJumpList)) return true; + if (!(bFolder && !bHasJumpList) && (x.bFolder && !x.bHasJumpList)) return false; + if (drive && !x.drive) return true; + if (!drive && x.drive) return false; + if (drive && x.drive) return drive0; } + }; + + LONG m_RefCount; + bool m_bSubMenu; + bool m_bDestroyed; // the menu is destroyed but not yet deleted + bool m_bTrackMouse; + bool m_bRefreshItems; + bool m_bWorkAreaPosted; + volatile DWORD m_RefreshPosted; + int m_Options; + const StdMenuItem *m_pStdItem; // the first item + CMenuContainer *m_pParent; // parent menu + int m_ParentIndex; // the index of this menu in the parent (usually matches m_pParent->m_Submenu) + int m_Submenu; // the item index of the opened submenu + int m_SubShowTime; // the time when the submenu was shown + int m_HotItem; + int m_InsertMark; + bool m_bInsertAfter; + bool m_bHotArrow; + unsigned int m_FolderHash[2]; // hash of the path to use for per-menu settings + CAbsolutePidl m_Path1[2]; + CAbsolutePidl m_Path2[2]; + CComPtr m_pDropFolder[2]; // the primary folder (used only as a drop target) + CComPtr m_pShellView; // keep the view alive because some buggy namespace extensions clean up if there is no view + CComPtr m_pAccessible; + CComPtr m_pDropTargetProxy; + DWORD m_InputCookie; + std::vector m_ColumnOffsets; + + std::vector m_Items; // all items in the menu (including separators) + CComQIPtr m_pMenu2; // additional interfaces used when a context menu is displayed + CComQIPtr m_pMenu3; + + int m_DragHoverTime; + int m_DragHoverItem; + int m_DragIndex; // the index of the item being dragged + CComPtr m_pDropTargetHelper; // to show images while dragging + CComPtr m_pDragSourceHelper; + CComPtr m_pDragObject; + CComPtr m_pDropTarget; + const CItemManager::ItemInfo *m_pDropTargetInfo; + int m_DropTargetIndex; + int m_DragTime; + + int m_ClickIndex; // the index of the last clicked item (-2 until the mouse enters the menu for the first time) + bool m_bClickArrow; + int m_HoverItem; // item under the mouse (used for opening a submenu when the mouse hovers over an item) + bool m_bHoverArrow; + int m_ContextItem; // force this to be the hot item while a context menu is up + HBITMAP m_Bitmap; // the background bitmap + int m_BitmapOffset; // the horizontal offset of the main menu background from the window + HRGN m_Region; // the outline region + POINT m_PaintOffset; + int m_MaxWidth; + bool m_bTwoColumns; + RECT m_rMenu; + RECT m_rContent; + RECT m_rContent2; + RECT m_rUser1; // the user image (0,0,0,0 if the user image is not shown) + RECT m_rUser2; // the user name (0,0,0,0 if the user name is not shown) + RECT m_rPadding; // padding in the menu where right-click is possible + int m_ExtraTop, m_ExtraBottom; // amount of padding that the menu background virtually extends beyond the screen (not actually drawn) + int m_ExtraBorder; // hight of the border by which the menu extends beyond the screen (solid background with window border) + + int m_ScrollCount; // number of items to scroll in the pager + int m_ScrollHeight; // 0 - don't scroll + int m_ScrollOffset; + int m_ScrollButtonSize; + int m_MouseWheel; + bool m_bScrollUp, m_bScrollDown; + bool m_bScrollUpHot, m_bScrollDownHot; + bool m_bScrollTimerMouse; + bool m_bScrollTimerTouch; + bool m_bNoSearchDraw; + bool m_bSearchDrawn; + bool m_bInSearchUpdate; + bool m_bDisableProgHover; + bool m_bClosing; + int m_SearchIndex; + int m_SearchProvidersCount; + int m_SearchItemCount; + CWindow m_SearchBox; + unsigned int m_SearchHash; + HBITMAP m_SearchIcons; + + struct SearchItem + { + SearchItem( const CString &_name, const CItemManager::ItemInfo *_info ) { name=_name; info=_info; } + SearchItem( const CItemManager::ItemInfo *_info ) { info=_info; } + CString name; + const CItemManager::ItemInfo *info; + }; + + int AddSearchItems( const std::vector &items, const CString &categoryName, unsigned int categoryHash, int originalCount ); + void GetRecentPrograms( std::vector &items, int maxCount ); + + // additional commands for the context menu + enum + { + CMD_OPEN=1, + CMD_OPEN_ALL, + CMD_SORT, + CMD_AUTOSORT, + CMD_NEWFOLDER, + CMD_NEWSHORTCUT, + CMD_DELETEMRU, + CMD_DELETEALL, + CMD_EXPLORE, + CMD_PIN, + CMD_PINSETTING, + CMD_TOGGLE, + CMD_DELETE, + CMD_RENAME, + CMD_MARKOLD, + CMD_UNINSTALL, + + CMD_LAST, + CMD_MAX=32767 + }; + + // ways to activate a menu item + enum TActivateType + { + ACTIVATE_SELECT, // just selects the item + ACTIVATE_OPEN, // opens the submenu or selects if not a menu + ACTIVATE_OPEN_KBD, // same as above, but when done with a keyboard + ACTIVATE_OPEN_SEARCH, // opens the search results submenu + ACTIVATE_EXECUTE, // executes the item + ACTIVATE_MENU, // shows context menu + ACTIVATE_MENU_BACKGROUND, // shows context menu for the menu itself + ACTIVATE_RENAME, // renames the item + ACTIVATE_DELETE, // deletes the item + ACTIVATE_PROPERTIES, // shows the properties of the item + }; + + // search state + enum TSearchState + { + SEARCH_NONE, // the search is inactive + SEARCH_BLANK, // the search box has the focus but is blank + SEARCH_TEXT, // the search box has the focus and is not blank + }; + + TSearchState m_SearchState; + unsigned int m_SearchCategoryHash; + + enum + { + // timer ID + TIMER_HOVER=1, + TIMER_SCROLL_MOUSE=2, + TIMER_SCROLL_TOUCH=3, + TIMER_TOOLTIP_SHOW=4, + TIMER_TOOLTIP_HIDE=5, + TIMER_BALLOON_HIDE=6, + TIMER_SEARCH=7, + TIMER_DRAG=8, + + MCM_REFRESH=WM_USER+10, // posted to force the container to refresh its contents + MCM_SETCONTEXTITEM=WM_USER+11, // sets the item for the context menu. wParam is the nameHash of the item + MCM_REDRAWEDIT=WM_USER+12, // redraw the search edit box + MCM_REFRESHICONS=WM_USER+13, // refreshes the icon list and redraws all menus + MCM_SETHOTITEM=WM_USER+14, // sets the hot item + MCM_WORKAREACHANGED=WM_USER+15, // when the working area is changed + + // some constants + MIN_SCROLL_HEIGHT=13, // the scroll buttons are at least this tall + MAX_MENU_ITEMS=2000, + MENU_ANIM_SPEED=200, + MENU_ANIM_SPEED_SUBMENU=100, + MENU_FADE_SPEED=400, + MRU_PROGRAMS_COUNT=40, + }; + + void AddFirstFolder( IShellItem *pFolder, std::vector &items, int options ); + void AddSecondFolder( IShellItem *pFolder, std::vector &items, int options ); + + struct ActivateData + { + ActivateData( void ) { bNoModifiers=bProgramsTree=bExpanded=bArrow=bAutoSort=bApps=false; command=0; pNewItemInfo=NULL; hTreeItem=NULL; } + bool bNoModifiers; + bool bProgramsTree; // this is an item from the tree + bool bExpanded; // for tree items + bool bArrow; // the arrow was clicked + bool bAutoSort; // the programs folder is auto-sort + bool bApps; + HTREEITEM hTreeItem; + CAbsolutePidl parent; // parent folder + int command; // menu command + const CItemManager::ItemInfo *pNewItemInfo; // returns the new item created by a rename or new folder + }; + + void InitItems( void ); + bool InitSearchItems( void ); + void InitWindow( bool bDontShrink=false ); + void InitWindowInternal( bool bDontShrink, const POINT &corner, RECT &menuRect ); + void InitWindowFinalize( const RECT &menuRect ); + + // pPt - optional point in screen space (used only by ACTIVATE_EXECUTE and ACTIVATE_MENU) + void ActivateItem( int index, TActivateType type, const POINT *pPt, ActivateData *pData=NULL ); + void ActivateTreeItem( const void *treeItem, RECT &itemRect, TActivateType type, const POINT *pPt, ActivateData *pData=NULL ); + void DragTreeItem( const void *treeItem, bool bApps ); + void ShowKeyboardCues( void ); + void SetActiveWindow( void ); + void CreateBackground( int width1, int width2, int height1, int height2, int &totalWidth, int &totalHeight, bool bCreateRegion ); // width1/2, height1/2 - the first and second content area + void BlendPatterns( unsigned int *bits, int width, int height ); + void CreateContentRects( int width1, int width2, int height1, int height2, int &totalWidth, int &totalHeight ); + void CreateSubmenuRegion( int width, int height ); // width, height - the content area + void ApplyRegion( BOOL bRedraw ); + void PostRefreshMessage( void ); + void SaveItemOrder( const std::vector &items ); + void LoadItemOrder( void ); + void RemoveMFUShortcut( unsigned int hash, bool bAppId ); + void FadeOutItem( int index ); + bool GetItemRect( int index, RECT &rc ); + int HitTest( const POINT &pt, bool *bArrow, bool bDrop=false ); + bool DragOut( int index, bool bApp ); + bool DragOutApps( const CItemManager::ItemInfo *pInfo ); + CComPtr CreateMetroDataObject( const CItemManager::ItemInfo *pInfo ); + void GetDragEffect( DWORD &grfKeyState, DWORD *pdwEffect ); + void InvalidateItem( int index ); + void SetHotItem( int index, bool bArrow=false, bool bShowTip=false ); + void SetSubmenu( int index ); + void SetContextItem( int index ); + void SetClickItem( int index ); + void UpdateUserPicture( void ); + void SetInsertMark( int index, bool bAfter ); + bool GetInsertRect( RECT &rc ); + void DrawBackground( HDC hdc, const RECT &drawRect ); + bool GetDescription( int index, wchar_t *text, int size ); + void UpdateScroll( void ); + void UpdateScroll( const POINT *pt, bool bTouch ); + bool CanSelectItem( int index, bool bKeyboard=true ); + void SetSearchState( TSearchState state ); + void UpdateSearchResults( bool bForceShowAll ); + void AddInternetSearch( size_t index ); + void AddStandardItems( void ); + void UpdateAccelerators( int first, int last ); + void ExecuteCommand( const wchar_t *command, bool bElevated, bool bEnvSubst ); + void RunUserCommand( bool bPicture ); + void OpenSubMenu( int index, TActivateType type, bool bShift ); + void UpdateAutoComplete( const wchar_t *text ); + bool HasMoreResults( void ); + RECT CalculateWorkArea( const RECT &taskbarRect ); + POINT CalculateCorner( void ); + void NotifyDisplayChange( void ); + +#define AW_TOPMOST 0x00100000 + void AnimateMenu( int flags, int speed, const RECT &rect ); + + enum + { + COLLECT_RECURSIVE = 1, // go into subfolders + COLLECT_PROGRAMS = 2, // only collect programs (.exe, .com, etc) + COLLECT_FOLDERS = 4, // include folder items + COLLECT_METRO = 8, // check for metro links (non-recursive) + COLLECT_KEYWORDS =16, // include the keywords + }; + + static int s_MaxRecentDocuments; // limit for the number of recent documents + static int s_ScrollMenus; // global scroll menus setting + static bool s_bRTL; // RTL layout + static bool s_bKeyboardCues; // show keyboard cues + static bool s_bOverrideFirstDown; // the first down key from the search box will select the top item + static bool s_bExpandRight; // prefer expanding submenus to the right + static bool s_bBehindTaskbar; // the main menu is behind the taskbar (when the taskbar is horizontal) + static bool s_bShowTopEmpty; // shows the empty item on the top menu so the user can drag items there + static bool s_bNoDragDrop; // disables drag/drop + static bool s_bNoContextMenu; // disables the context menu + static bool s_bExpandLinks; // expand links to folders + static bool s_bLogicalSort; // use StrCmpLogical instead of CompareString + static bool s_bExtensionSort; // sort file names by extension + static bool s_bAllPrograms; // this is the All Programs menu of the Windows start menu + static bool s_bNoCommonFolders; // don't show the common folders (start menu and programs) + static bool s_bNoRun; // don't show run, disable autocomplete + static bool s_bNoClose; // don't show shutdown, restart, sleep and hibernate + static bool s_bHasTouch; // the device has integrated touch digitizer + static char s_bActiveDirectory; // the Active Directory services are available (-1 - uninitialized) + static bool s_bPreventClosing; // prevents the menus from closing even if they lose focus + static bool s_bDragClosed; // the menu was closed during a drag operation + static bool s_bTempHidden; // the menu windows are temporarily hidden + static bool s_bDisableHover; // disable hovering while the search box has the focus + static bool s_bHasUpdates; // the OS wants to install updates + static CMenuContainer *s_pDragSource; // the source of the current drag operation + static bool s_bDragFromTree; // the source is the programs tree + static bool s_bDragMovable; // the dragged item is normal original item + static bool s_bRightDrag; // dragging with the right mouse button + static bool s_bLockWorkArea; // changes to the work area are ignored + static bool s_bPendingSearchEnter; // Enter was pressed before the search results were ready + static RECT s_MenuLimits; // area of the main monitor accessible to all menus + static RECT s_MainMenuLimits; // area of the main monitor accessible by the main menu + static DWORD s_TaskbarState; // the state of the taskbar (ABS_AUTOHIDE and ABS_ALWAYSONTOP) + static DWORD s_HoverTime; + static DWORD s_SplitHoverTime; + static DWORD s_ProgramsHoverTime; + static DWORD s_XMouse; + static DWORD s_SubmenuStyle; + static int s_TaskBarId; + static HWND s_TaskBar, s_StartButton; // the current taskbar and start button + static UINT s_TaskBarEdge; + static RECT s_StartRect; // the bounds of the start button + static HWND s_LastFGWindow; // stores the foreground window to restore later when the menu closes + static HMONITOR s_MenuMonitor; + static HTHEME s_Theme; + static HTHEME s_PagerTheme; + static CWindow s_Tooltip; + static CWindow s_TooltipBalloon; + static int s_TipShowTime; + static int s_TipHideTime; + static int s_TipShowTimeFolder; + static int s_TipHideTimeFolder; + static DWORD s_HotPos; // last mouse position over a hot item (used to ignore WM_MOUSEMOVE when the mouse didn't really move) + static int s_HotItem; + static CMenuContainer *s_pHotMenu; // the menu with the hot item + static int s_TipItem; // the item that needs a tooltip + static CMenuContainer *s_pTipMenu; + static HBITMAP s_ArrowsBitmap; + static unsigned int s_LastArrowColor; + static CComPtr s_pFrameworkInputPane; + static CString s_PinFolder; + static CLIPFORMAT s_ShellFormat; // CFSTR_SHELLIDLIST + static CLIPFORMAT s_ShellUrlFormat; // CFSTR_INETURL + static CLIPFORMAT s_DescriptorFormat; // CFSTR_FILEDESCRIPTOR + static CLIPFORMAT s_ContentsFormat; // CFSTR_FILECONTENTS + static CLIPFORMAT s_PreferredEffectFormat; + static CLIPFORMAT s_MetroLinkFormat; + static CLIPFORMAT s_DropDescriptionFormat; + + static TRecentPrograms s_RecentPrograms; // show and track recent items + + static std::vector s_Menus; // all menus, in cascading order + static volatile HWND s_FirstMenu, s_SearchMenu; + static CSearchManager::SearchResults s_SearchResults; + static std::map s_MenuScrolls; // scroll offset for each sub menu + static char s_HasMoreResults; // -1 - uninitialized + static int s_ProgramsWidth, s_JumplistWidth; + + static CString s_MRUShortcuts[MRU_PROGRAMS_COUNT]; + static bool s_bMRULoaded; + + static const CItemManager::ItemInfo *s_JumpAppInfo; + static CJumpList s_JumpList; + + static MenuSkin s_Skin; + + friend class CMetroDataObject; + friend class COwnerWindow; + friend class CMenuAccessible; + friend LRESULT CALLBACK SubclassTopMenuProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + friend HRESULT CreatePinLink( PCIDLIST_ABSOLUTE sourcePidl, const wchar_t *name, const wchar_t *iconPath, int iconIndex ); + + static void HideTemp( bool bHide ); + static void AddMRUShortcut( const wchar_t *path ); + static void AddMRUAppId( const wchar_t *appid ); + static void DeleteMRUShortcut( const wchar_t *path ); + static void DeleteMRUAppId( const wchar_t *appid ); + static void SaveMRUShortcuts( void ); + static void LoadMRUShortcuts( void ); + static HBITMAP LoadUserImage( int size, HBITMAP hMask ); + static int CompareMenuString( const wchar_t *str1, const wchar_t *str2 ); + static LRESULT CALLBACK SubclassSearchBox( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + static LRESULT CALLBACK SubclassScrollbar( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + void ClearItems( const std::vector::iterator &begin, const std::vector::iterator &end ); + void AddJumpListItems( std::vector &items ); + static HBITMAP GetArrowsBitmap( unsigned int color ); + static bool CloseProgramsMenu( void ); + static void HideStartMenu( void ); + static void SetDropTip( IDataObject *pDataObj, bool bPin ); + + enum + { + CLOSE_POST =1, + CLOSE_SKIP_LAST =2, + CLOSE_SKIP_SEARCH =4, + CLOSE_ONLY_SEARCH =8, + CLOSE_KEEP_MODE =16, + }; + static void CloseSubMenus( int flags, CMenuContainer *pAfter ); + + // To control the placement of the start menu, send ClassicStartMenu.StartMenuMsg message right after the start menu is created but before it is displayed + // The lParam must point to StartMenuParams + // monitorRect - the entire area available to the start menu (sub-menus will use it). It is usually the monitor area but can be less if the Desktop app is docked in Win8 + // uEdge - the location of the taskbar - ABE_BOTTOM, ABE_LEFT, etc + // taskbarRect - the bounding box of the taskbar. When the taskbar is at the top or bottom, the main menu will try to not overlap that rect. When the taskbar is on the side the behavior depends on the ShowNextToTaskbar setting + // startButtonRect - the bounding box of the start button. When the taskbar is on the side the main menu will appear below that box if ShowNextToTaskbar is not set + // taskbar - the taskbar window (optional). The main menu will try to stay in front of that window + // startButton - the start button window (optional). The main menu will try to stay behind that window + struct StartMenuParams + { + HWND startButton; + HWND taskbar; + RECT startButtonRect; + RECT taskbarRect; + RECT monitorRect; + DWORD uEdge; + }; + + static StartMenuParams s_StartMenuParams; + static UINT s_StartMenuMsg; + + // Win7 stuff + enum TMenuMode + { + MODE_UNKNOWN=-1, + MODE_NORMAL, + MODE_PROGRAMS, // the programs tree is shown + MODE_SEARCH, // the search results are shown + MODE_JUMPLIST, // a jumplist is shown + }; + + void SetMenuMode( TMenuMode mode, bool bKeyboard=false ); + void OpenJumpList( int index, bool bKeyboard ); + void OpenSearchList( void ); + void AnimateBackground( void ); + + CProgramsTree *m_pProgramsTree; + int m_ProgramButtonIndex; + int m_ProgramTreeIndex; + int m_SubJumpItem; // the currently expanded embedded jumplist + int m_OriginalCount; // the number of orginal items in the main menu + int m_OriginalScrollCount; // the initial number of scrolled items + int m_SearchScrollCount; + int m_SearchScrollHeight; // in items + int m_SearchScrollPos; // in items + CWindow m_Scrollbar; + HTHEME m_ScrollTheme; + + static bool s_bWin7Style; + static TMenuMode s_MenuMode; // always MODE_NORMAL if s_bWin7Style is false + static TMenuMode s_PreSearchMenuMode; + static TMenuID s_ShutdownCommand; + static int s_MenuHeight; // main menu height in normal mode + static int s_MenuMaxHeight[2]; // main menu max height in normal mode + static CUserWindow s_UserPicture; + static RECT s_UserPictureRect; + static int s_ProgramsScrollPos; + + // main menu animation + static int s_MenuWidthNormal; // main menu width in normal modes + static int s_MenuWidthJump; // main menu width in jumplist mode + static int s_MenuWidthMax; // the larger of the two widths + static int s_BackgroundW1, s_BackgroundW2, s_BackgroundH1, s_BackgroundH2; + struct OldMenuState + { + TMenuMode mode; + int w1, w2, h1, h2; + int bitmapOffset; + int hotItem; + bool bHotArrow; + std::vector items; + int blend; // from 0 to 100 + }; + static OldMenuState s_OldMenuState; + + void InitializeOldState( void ); + static void ClearOldState( void ); + + friend class CProgramsTree; + friend class CUserWindow; + friend void CloseSkinManager( bool bCloseIat ); + + // Gestures + int m_PanPosY; + int m_Overpan; + int m_PointerId; +}; + +class CSubMenuContainer: public CMenuContainer +{ +public: + virtual ATL::CWndClassInfo &GetWndClassInfo( void ) + { + static ATL::CWndClassInfo wc = + { + {sizeof(WNDCLASSEX),CS_DROPSHADOW|CS_DBLCLKS,StartWindowProc,0,0,NULL,NULL,NULL,(HBRUSH)(COLOR_MENU+1),NULL,L"ClassicShell.CMenuContainer",NULL}, + NULL,NULL,IDC_ARROW,TRUE,0,_T("") + }; + return wc; + } + + CSubMenuContainer( CMenuContainer *pParent, int index, int options, const StdMenuItem *pStdItem, PIDLIST_ABSOLUTE path1, PIDLIST_ABSOLUTE path2 ) + : CMenuContainer(pParent,index,options,pStdItem,path1,path2) + {} +}; + +class CMenuFader: public CWindowImpl +{ +public: + CMenuFader( HBITMAP bmp, HRGN region, int duration, RECT &rect ); + ~CMenuFader( void ); + DECLARE_WND_CLASS_EX(L"ClassicShell.CMenuFader",0,COLOR_MENU) + + // message handlers + BEGIN_MSG_MAP( CMenuFader ) + MESSAGE_HANDLER( WM_ERASEBKGND, OnEraseBkgnd ) + MESSAGE_HANDLER( WM_TIMER, OnTimer ) + END_MSG_MAP() + + void Create( void ); + + static void ClearAll( void ); + +protected: + LRESULT OnEraseBkgnd( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + virtual void OnFinalMessage( HWND ) { PostQuitMessage(0); delete this; } + +private: + int m_Time0; + int m_Duration; + int m_LastTime; + HBITMAP m_Bitmap; + HRGN m_Region; + RECT m_Rect; + + static std::vector s_Faders; +}; + +struct WINCOMPATTRDATA +{ + DWORD attribute; + PVOID pData; + ULONG dataSize; +}; +typedef BOOL (WINAPI *tSetWindowCompositionAttribute)( HWND hwnd, WINCOMPATTRDATA *pAttrData ); + +void MarginsBlit( HDC hSrc, HDC hDst, const RECT &rSrc, const RECT &rDst, const RECT &rMargins, bool bAlpha ); diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MenuPaint.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MenuPaint.cpp new file mode 100644 index 0000000..9e38a09 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MenuPaint.cpp @@ -0,0 +1,3162 @@ +// ## MenuContainer.h +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// MenuPaint.cpp - handles the painting functionality of CMenuContainer + +#include "stdafx.h" +#include "ItemManager.h" +#include "MenuContainer.h" +#include "ClassicStartMenuDLL.h" +#include "Settings.h" +#include "Translations.h" +#include "ResourceHelper.h" +#include "LogManager.h" +#include "ProgramsTree.h" +#include "SettingsUI.h" +#include +#include +#include +#include + +static BLENDFUNCTION g_AlphaFunc={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + +MIDL_INTERFACE("4BEDE6E0-A125-46A7-A3BF-4187165E09A5") +IUserTileStore8 : public IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE SaveUserTileToStream( IStream*, int ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetUserTileFromStream( int, IStream* ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetLargePath( const wchar_t *userSid, wchar_t **pPath ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetSmallPath( const wchar_t *userSid, wchar_t **pPath ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDynamicPath( const wchar_t *userSid, wchar_t **pPath ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetSmallPicture( const wchar_t *userSid, HBITMAP *pBitmap ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetLargePicture( const wchar_t *userSid, HBITMAP *pBitmap ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetUserTilePathBySize( const wchar_t *userSid, unsigned int size, wchar_t **pPath ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDynamicPathBySize( const wchar_t *userSid, unsigned int size, wchar_t **pPath ) = 0; +}; + +MIDL_INTERFACE("A1BA55E7-0F4E-454D-89A4-2376347D504A") +IUserTileStore81 : public IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE SaveUserTileToStream( IStream*, int ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetUserTileFromStream( int, IStream* ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetLargePath( const wchar_t *userSid, wchar_t **pPath ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetSmallPath( const wchar_t *userSid, wchar_t **pPath ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDynamicPath( const wchar_t *userSid, wchar_t **pPath ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetSmallPicture( const wchar_t *userSid, HBITMAP *pBitmap ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetLargePicture( const wchar_t *userSid, HBITMAP *pBitmap ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetUserTilePathBySize( const wchar_t *userSid, unsigned int size, wchar_t **pPath ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDynamicPathBySize( const wchar_t *userSid, unsigned int size, wchar_t **pPath ) = 0; +}; + +MIDL_INTERFACE("A76E31A3-DED8-4119-ADD8-BF818F05965C") +IUserTileStore10 : public IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE SaveUserTileToStream( IStream*, int ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetUserTileFromStream( int, IStream* ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetLargePath( const wchar_t *userSid, wchar_t **pPath ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetSmallPath( const wchar_t *userSid, wchar_t **pPath ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetExtraSmallPath( const wchar_t *userSid, wchar_t **pPath ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDynamicPath( const wchar_t *userSid, wchar_t **pPath ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetSmallPicture( const wchar_t *userSid, HBITMAP *pBitmap ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetLargePicture( const wchar_t *userSid, HBITMAP *pBitmap ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetUserTilePathBySize( const wchar_t *userSid, unsigned int size, wchar_t **pPath ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDynamicPathBySize( const wchar_t *userSid, unsigned int size, wchar_t **pPath ) = 0; +}; + +static CLSID CLSID_UserTileStore={0x09c5dd34, 0x009d, 0x40fa, {0xbc, 0xb9, 0x01, 0x65, 0xad, 0x0c, 0x15, 0xd4}}; + +static void StretchBlt2( HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc, bool bAlpha ) +{ + if (wDest>0 && hDest>0 && wSrc>0 && hSrc>0) + { + if (bAlpha) + AlphaBlend(hdcDest,xDest,yDest,wDest,hDest,hdcSrc,xSrc,ySrc,wSrc,hSrc,g_AlphaFunc); + else if (wDest==wSrc && hDest==hSrc) + { + // HACK: when blitting RTL image with no stretching, StretchBlt adds 1 pixel offset. use BitBlt instead + BitBlt(hdcDest,xDest,yDest,wDest,hDest,hdcSrc,xSrc,ySrc,SRCCOPY); + } + else + StretchBlt(hdcDest,xDest,yDest,wDest,hDest,hdcSrc,xSrc,ySrc,wSrc,hSrc,SRCCOPY); + } +} + +HBITMAP CMenuContainer::LoadUserImage( int size, HBITMAP hMask ) +{ + wchar_t path[_MAX_PATH]; + path[0]=0; + CString str=GetSettingString(L"UserPicturePath"); + if (str.IsEmpty()) + { + if (GetWinVersion()==WIN_VER_WIN8) + { + CComPtr pStore; + pStore.CoCreateInstance(CLSID_UserTileStore); + if (pStore) + { + CComString pPath; + if (SUCCEEDED(pStore->GetDynamicPathBySize(NULL,size,&pPath)) || SUCCEEDED(pStore->GetUserTilePathBySize(NULL,size,&pPath))) + Strcpy(path,_countof(path),pPath); + } + } + else if (GetWinVersion()==WIN_VER_WIN81) + { + CComPtr pStore; + pStore.CoCreateInstance(CLSID_UserTileStore); + if (pStore) + { + CComString pPath; + if (SUCCEEDED(pStore->GetDynamicPathBySize(NULL,size,&pPath)) || SUCCEEDED(pStore->GetUserTilePathBySize(NULL,size,&pPath))) + Strcpy(path,_countof(path),pPath); + } + } + else if (GetWinVersion()>=WIN_VER_WIN10) + { + CComPtr pStore; + pStore.CoCreateInstance(CLSID_UserTileStore); + if (pStore) + { + CComString pPath; + if (SUCCEEDED(pStore->GetDynamicPathBySize(NULL,size,&pPath)) || SUCCEEDED(pStore->GetUserTilePathBySize(NULL,size,&pPath))) + Strcpy(path,_countof(path),pPath); + } + } + if (!path[0]) + { + HMODULE hShell32=GetModuleHandle(L"shell32.dll"); + typedef HRESULT (__stdcall*tSHGetUserPicturePath)(LPCWSTR, UINT, LPWSTR, ULONG); + tSHGetUserPicturePath SHGetUserPicturePath=(tSHGetUserPicturePath)GetProcAddress(hShell32,MAKEINTRESOURCEA(261)); + if (SHGetUserPicturePath) + SHGetUserPicturePath(NULL,0x80000000,path,_countof(path)); + } + } + else + { + Strcpy(path,_countof(path),str); + DoEnvironmentSubst(path,_countof(path)); + } + HBITMAP hBitmap=NULL; + if (path[0]) + { + LOG_MENU(LOG_OPEN,L"Loading user image: '%s'",path); + SIZE s={size,size}; + if (str.IsEmpty()) + hBitmap=LoadImageFile(path,&s,false,false,NULL); + else + hBitmap=LoadImageFile(path,&s,true,true,NULL); + } + if (hBitmap && hMask) + { + BITMAP info1, info2; + GetObject(hBitmap,sizeof(info1),&info1); + GetObject(hMask,sizeof(info2),&info2); + if (info1.bmBits && info2.bmBits && info1.bmWidth==info2.bmWidth && info1.bmHeight==info2.bmHeight && info1.bmBitsPixel==32 && info2.bmBitsPixel==32) + { + unsigned char *pixels1=(unsigned char*)info1.bmBits; + const unsigned char *pixels2=(const unsigned char*)info2.bmBits; + int n=info1.bmWidth*info1.bmHeight; + bool bHasAlpha=false; + pixels1+=3; + for (int i=0;irDst.right) x1a=rDst.right; + int x2a=rDst.right-rMargins.right; + if (x2ax2a) x1a=x2a=(x1a+x2a)/2; + int x3a=rDst.right; + int x0b=rSrc.left; + int x1b=rSrc.left+rMargins.left; + int x2b=rSrc.right-rMargins.right; + int x3b=rSrc.right; + + int y0a=rDst.top; + int y1a=rDst.top+rMargins.top; + if (y1a>rDst.bottom) y1a=rDst.bottom; + int y2a=rDst.bottom-rMargins.bottom; + if (y2ay2a) y1a=y2a=(y1a+y2a)/2; + int y3a=rDst.bottom; + int y0b=rSrc.top; + int y1b=rSrc.top+rMargins.top; + int y2b=rSrc.bottom-rMargins.bottom; + int y3b=rSrc.bottom; + + SetStretchBltMode(hDst,COLORONCOLOR); + StretchBlt2(hDst,x0a,y0a,x1a-x0a,y1a-y0a,hSrc,x0b,y0b,x1b-x0b,y1b-y0b,bAlpha); + StretchBlt2(hDst,x1a,y0a,x2a-x1a,y1a-y0a,hSrc,x1b,y0b,x2b-x1b,y1b-y0b,bAlpha); + StretchBlt2(hDst,x2a,y0a,x3a-x2a,y1a-y0a,hSrc,x2b,y0b,x3b-x2b,y1b-y0b,bAlpha); + + StretchBlt2(hDst,x0a,y1a,x1a-x0a,y2a-y1a,hSrc,x0b,y1b,x1b-x0b,y2b-y1b,bAlpha); + StretchBlt2(hDst,x1a,y1a,x2a-x1a,y2a-y1a,hSrc,x1b,y1b,x2b-x1b,y2b-y1b,bAlpha); + StretchBlt2(hDst,x2a,y1a,x3a-x2a,y2a-y1a,hSrc,x2b,y1b,x3b-x2b,y2b-y1b,bAlpha); + + StretchBlt2(hDst,x0a,y2a,x1a-x0a,y3a-y2a,hSrc,x0b,y2b,x1b-x0b,y3b-y2b,bAlpha); + StretchBlt2(hDst,x1a,y2a,x2a-x1a,y3a-y2a,hSrc,x1b,y2b,x2b-x1b,y3b-y2b,bAlpha); + StretchBlt2(hDst,x2a,y2a,x3a-x2a,y3a-y2a,hSrc,x2b,y2b,x3b-x2b,y3b-y2b,bAlpha); +} + +struct PatternInfo +{ + int index; + SIZE size; + int offsetX; + int maskShift; + unsigned int otherMask; + const std::vector *bits; + const unsigned int *bitsY; + int stride; +}; + +static HBITMAP CreateMaskedEmblem( HBITMAP bmpEmblem, RECT &rcEmblem, const unsigned int *EMaskBits, int maskWidth, int maskHeight, int channel ) +{ + if (channel<3) channel=2-channel; + int minx=rcEmblem.left<0?0:rcEmblem.left; + int maxx=rcEmblem.right>maskWidth?maskWidth:rcEmblem.right; + int miny=rcEmblem.top<0?0:rcEmblem.top; + int maxy=rcEmblem.bottom>maskHeight?maskHeight:rcEmblem.bottom; + Assert(minx=0 && start+(maxx-minx)*4<=info.bmHeight*info.bmWidthBytes); + for (int x=minx;x=0 && start+(maxx-minx)*3<=info.bmHeight*info.bmWidthBytes); + for (int x=minx;xsize()/pattern.size.cy; + } + } + + for (int y=0;y>pattern.maskShift)&255; + if (mask==0) continue; + + unsigned int pat=pattern.bitsY[x]; + if ((pixel&pattern.otherMask)==0) + { + // fast path if only one channel is set + int pa=pat>>24; + if (pa) + { + if (mask==255) + { + // even faster path for straight copy + pixel=pat; + } + else + { + mask++; // a cheat to make the mask from 1 to 256, so we can use >>8 instead of /255 + a=(pa*mask)>>8; + if (a==0) + { + pixel=0; + } + else + { + r=(((pat>>16)&255)*mask)>>8; + g=(((pat>>8)&255)*mask)>>8; + b=((pat&255)*mask)>>8; + pixel=(a<<24)|(r<<16)|(g<<8)|b; + } + } + } + else + pixel=0; + goto end; + } + int pa=pat>>24; + if (pa) + { + a+=pa*mask; + r+=((pat>>16)&255)*mask; + g+=((pat>>8)&255)*mask; + b+=(pat&255)*mask; + } + } + a/=255; + if (a==0) + { + pixel=0; + } + else + { + if (a>255) a=255; + r/=255; if (r>255) r=255; + g/=255; if (g>255) g=255; + b/=255; if (b>255) b=255; + pixel=(a<<24)|(r<<16)|(g<<8)|b; + } +end:; + } + } + + LARGE_INTEGER time; + QueryPerformanceCounter(&time); + LONGLONG dt=(time.QuadPart-time0.QuadPart)*1000000/freq.QuadPart; +// Trace("BlendPatterns: %.3f ms",(int)dt/1000.f); +} + +// Creates the bitmap for the background +void CMenuContainer::CreateBackground( int width1, int width2, int height1, int height2, int &totalWidth, int &totalHeight, bool bCreateRegion ) +{ + // get the text from the ini file or from the registry + wchar_t caption[256]; + Strcpy(caption,_countof(caption),GetSettingString(L"MenuCaption")); + DoEnvironmentSubst(caption,_countof(caption)); + + MenuBitmap bmpSkin; + MenuBitmap bmpSkinPattern; + MenuBitmap bmpSkinEmblem; + const int *slicesX, *slicesY; + if (s_MenuMode==MODE_SEARCH) + { + bmpSkin=s_Skin.Main_bitmap_search; + slicesX=s_Skin.Main_bitmap_search_slices_X; + slicesY=s_Skin.Main_bitmap_search_slices_Y; + bmpSkinPattern=s_Skin.Main_pattern_search_mask; + bmpSkinEmblem=s_Skin.Main_emblem_search_mask; + } + else if (s_MenuMode==MODE_JUMPLIST) + { + bmpSkin=s_Skin.Main_bitmap_jump; + slicesX=s_Skin.Main_bitmap_jump_slices_X; + slicesY=s_Skin.Main_bitmap_jump_slices_Y; + bmpSkinPattern=s_Skin.Main_pattern_jump_mask; + bmpSkinEmblem=s_Skin.Main_emblem_jump_mask; + } + else + { + bmpSkin=s_Skin.Main_bitmap; + slicesX=s_Skin.Main_bitmap_slices_X; + slicesY=s_Skin.Main_bitmap_slices_Y; + bmpSkinPattern=s_Skin.Main_pattern_mask; + bmpSkinEmblem=s_Skin.Main_emblem_mask; + } + bool bCaption=(slicesX[1]>0); + MenuSkin::TOpacity opacity=s_Skin.Main_opacity; + + HDC hdcTemp=CreateCompatibleDC(NULL); + + HFONT font0=NULL; + if (bCaption) + font0=(HFONT)SelectObject(hdcTemp,s_Skin.Caption_font); + + RECT rc={0,0,0,0}; + DTTOPTS opts={sizeof(opts),DTT_COMPOSITED|DTT_CALCRECT}; + if (bCaption) + { + if (s_Theme) + DrawThemeTextEx(s_Theme,hdcTemp,0,0,caption,-1,DT_NOPREFIX|DT_SINGLELINE|DT_CALCRECT,&rc,&opts); + else + DrawText(hdcTemp,caption,-1,&rc,DT_NOPREFIX|DT_SINGLELINE|DT_CALCRECT); + } + int textWidth=rc.right+s_Skin.Caption_padding.top+s_Skin.Caption_padding.bottom; + int textHeight=rc.bottom+s_Skin.Caption_padding.left+s_Skin.Caption_padding.right; + + int total=slicesX[0]+slicesX[2]; + if (textHeight=0 && s_bWin7Style) + total+=slicesY[3]+slicesY[5]; + if (totalHeighttotalHeight) textWidth=totalHeight; + + m_rContent.left=menuPadding[0].left+textHeight; + m_rContent.right=totalWidth1-menuPadding[0].right; + m_rContent.top=menuPadding[0].top; + m_rContent.bottom=m_rContent.top+height1; + if (totalWidth2>0) + { + m_rContent2.left=m_rContent.right+menuPadding[0].right+menuPadding[1].left; + m_rContent2.right=totalWidth-menuPadding[1].right; + m_rContent2.top=menuPadding[1].top; + m_rContent2.bottom=m_rContent2.top+height2; + } + + MenuBitmap bmpSearch; + MenuBitmap bmpSearchPattern; + MenuBitmap bmpSearchEmblem; + int *searchSlicesX, *searchSlicesY; + RECT searchPadding; + int searchX[4], searchY[4]; + if (m_SearchIndex>=0 && s_bWin7Style) + { + if (s_MenuMode==MODE_SEARCH) + { + bmpSearch=s_Skin.Search_background_search; + bmpSearchPattern=s_Skin.Search_pattern_search_mask; + bmpSearchEmblem=s_Skin.Search_emblem_search_mask; + searchSlicesX=s_Skin.Search_background_search_slices_X; + searchSlicesY=s_Skin.Search_background_search_slices_Y; + searchPadding=s_Skin.Search_background_search_padding; + } + else if (s_MenuMode==MODE_JUMPLIST) + { + bmpSearch=s_Skin.Search_background_jump; + bmpSearchPattern=s_Skin.Search_pattern_jump_mask; + bmpSearchEmblem=s_Skin.Search_emblem_jump_mask; + searchSlicesX=s_Skin.Search_background_jump_slices_X; + searchSlicesY=s_Skin.Search_background_jump_slices_Y; + searchPadding=s_Skin.Search_background_jump_padding; + } + else + { + bmpSearch=s_Skin.Search_background; + bmpSearchPattern=s_Skin.Search_pattern_mask; + bmpSearchEmblem=s_Skin.Search_emblem_mask; + searchSlicesX=s_Skin.Search_background_slices_X; + searchSlicesY=s_Skin.Search_background_slices_Y; + searchPadding=s_Skin.Search_background_padding; + } + + const MenuSkin::ItemDrawSettings &settings=s_Skin.ItemSettings[MenuSkin::COLUMN1_ITEM]; + int searchH=settings.textMetrics.tmHeight*12/8+s_Skin.Search_padding.top+s_Skin.Search_padding.bottom; // 12 DLUs + int searchW=settings.textMetrics.tmAveCharWidth*25; + + RECT searchRect; + searchRect.left=m_rContent.left+s_Skin.Search_padding.left; + searchRect.top=m_rContent.bottom-searchH+s_Skin.Search_padding.top; + searchRect.bottom=m_rContent.bottom-s_Skin.Search_padding.bottom; + searchRect.right=m_rContent.right-s_Skin.Search_padding.right; + + RECT editRect; + if (m_SearchBox.m_hWnd) + { + m_SearchBox.GetWindowRect(&editRect); + ::MapWindowPoints(NULL,m_hWnd,(POINT*)&editRect,2); + OffsetRect(&editRect,-m_BitmapOffset,0); + searchRect.right=editRect.right+(editRect.bottom-editRect.top); + if (!s_Skin.Search_frame) + searchRect.right+=7; + } + else + { + editRect=searchRect; + editRect.right-=(editRect.bottom-editRect.top); + if (!s_Skin.Search_frame) + InflateRect(&editRect,-1,-3); + } + + searchX[0]=m_rContent.left-searchPadding.left; + searchX[1]=editRect.left; + searchX[2]=searchRect.right+s_Skin.Search_padding.right; + searchX[3]=((s_MenuMode==MODE_JUMPLIST)?m_rContent2.right:m_rContent.right)+searchPadding.right; + searchY[0]=searchRect.top-s_Skin.Search_padding.top-searchPadding.top; + searchY[1]=editRect.top-2; + searchY[2]=editRect.bottom+2; + searchY[3]=m_rContent.bottom+searchPadding.bottom; + } + + BITMAPINFO dib={sizeof(dib)}; + dib.bmiHeader.biWidth=totalWidth; + dib.bmiHeader.biHeight=-totalHeight; + dib.bmiHeader.biPlanes=1; + dib.bmiHeader.biBitCount=32; + dib.bmiHeader.biCompression=BI_RGB; + + HDC hdc=CreateCompatibleDC(NULL); + unsigned int *bits; + m_Bitmap=CreateDIBSection(hdc,&dib,DIB_RGB_COLORS,(void**)&bits,NULL,0); + HGDIOBJ bmp0=SelectObject(hdc,m_Bitmap); + + if (opacity==MenuSkin::OPACITY_SOLID) + { + RECT rc={0,0,totalWidth,totalHeight}; + SetDCBrushColor(hdc,s_Skin.Main_background); + FillRect(hdc,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + } + + bool bHasPattern=false; + if (s_Skin.Patterns[0].GetBitmap() || s_Skin.Patterns[1].GetBitmap() || s_Skin.Patterns[2].GetBitmap() || s_Skin.Patterns[3].GetBitmap()) + { + bHasPattern=(bmpSkinPattern.GetBitmap() || bmpSkinPattern.GetColor() || bmpSearchPattern.GetBitmap() || bmpSearchPattern.GetColor()); + } + + bool bHasEmblemMask=false; + if (s_Skin.Main_emblems[0].GetBitmap() || s_Skin.Main_emblems[1].GetBitmap() || s_Skin.Main_emblems[2].GetBitmap() || s_Skin.Main_emblems[3].GetBitmap()) + { + bHasEmblemMask=(bmpSkinEmblem.GetBitmap() || bmpSkinEmblem.GetColor() || bmpSearchEmblem.GetBitmap() || bmpSearchEmblem.GetColor()); + } + + HBITMAP PMaskBmp=NULL, EMaskBmp=NULL; + unsigned int *PMaskBits=NULL, *EMaskBits=NULL; + HGDIOBJ bmp02=GetCurrentObject(hdcTemp,OBJ_BITMAP); + + HDC hdcPMask=NULL, hdcEMask=NULL; + HDC hdcPMaskTemp=NULL, hdcEMaskTemp=NULL; + HGDIOBJ PMaskBmp0=NULL, PMaskBmp02=NULL, EMaskBmp0=NULL, EMaskBmp02=NULL; + if (bHasPattern) + { + hdcPMask=CreateCompatibleDC(NULL); + PMaskBmp=CreateDIBSection(hdcPMask,&dib,DIB_RGB_COLORS,(void**)&PMaskBits,NULL,0); + PMaskBmp0=SelectObject(hdcPMask,PMaskBmp); + hdcPMaskTemp=CreateCompatibleDC(NULL); + PMaskBmp02=GetCurrentObject(hdcPMaskTemp,OBJ_BITMAP); + } + if (bHasEmblemMask) + { + hdcEMask=CreateCompatibleDC(NULL); + EMaskBmp=CreateDIBSection(hdcEMask,&dib,DIB_RGB_COLORS,(void**)&EMaskBits,NULL,0); + EMaskBmp0=SelectObject(hdcEMask,EMaskBmp); + hdcEMaskTemp=CreateCompatibleDC(NULL); + EMaskBmp02=GetCurrentObject(hdcEMaskTemp,OBJ_BITMAP); + } + + if (bmpSkin.GetBitmap()) + { + // draw the skinned background + SelectObject(hdcTemp,bmpSkin.GetBitmap()); + + if (bHasPattern) + { + if (bmpSkinPattern.GetBitmap()) + { + SelectObject(hdcPMaskTemp,bmpSkinPattern.GetBitmap()); + } + else + { + RECT rc={0,0,totalWidth,totalHeight}; + SetDCBrushColor(hdcPMask,bmpSkinPattern.GetColor()); + FillRect(hdcPMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + } + } + + if (bHasEmblemMask) + { + if (bmpSkinEmblem.GetBitmap()) + { + SelectObject(hdcEMaskTemp,bmpSkinEmblem.GetBitmap()); + } + else + { + RECT rc={0,0,totalWidth,totalHeight}; + SetDCBrushColor(hdcEMask,bmpSkinEmblem.GetColor()); + FillRect(hdcEMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + } + } + + int searchHeight=0; + if (m_SearchIndex>=0 && s_bWin7Style && slicesY[3]+slicesY[4]+slicesY[5]>0) + searchHeight=m_Items[m_SearchIndex].itemRect.top-s_Skin.Search_padding.top-searchPadding.top; + + RECT rSrc={0,0,slicesX[0]+slicesX[1]+slicesX[2],slicesY[0]+slicesY[1]+slicesY[2]}; + RECT rDst={0,0,textHeight,searchHeight?searchHeight:totalHeight}; + RECT rMargins={slicesX[0],slicesY[0],slicesX[2],slicesY[2]}; + MarginsBlit(hdcTemp,hdc,rSrc,rDst,rMargins,(opacity==MenuSkin::OPACITY_SOLID && bmpSkin.bIs32)); + if (bmpSkinPattern.GetBitmap()) + MarginsBlit(hdcPMaskTemp,hdcPMask,rSrc,rDst,rMargins,false); + if (bmpSkinEmblem.GetBitmap()) + MarginsBlit(hdcEMaskTemp,hdcEMask,rSrc,rDst,rMargins,false); + + rSrc.left=rSrc.right; + rSrc.right+=slicesX[3]+slicesX[4]+slicesX[5]; + rDst.left=rDst.right; + rDst.right=totalWidth1; + rMargins.left=slicesX[3]; + rMargins.right=slicesX[5]; + MarginsBlit(hdcTemp,hdc,rSrc,rDst,rMargins,(opacity==MenuSkin::OPACITY_SOLID && bmpSkin.bIs32)); + if (bmpSkinPattern.GetBitmap()) + MarginsBlit(hdcPMaskTemp,hdcPMask,rSrc,rDst,rMargins,false); + if (bmpSkinEmblem.GetBitmap()) + MarginsBlit(hdcEMaskTemp,hdcEMask,rSrc,rDst,rMargins,false); + + if (searchHeight>0) + { + RECT rSrc2=rSrc, rDst2=rDst, rMargins2=rMargins; + rSrc2.top=rSrc.bottom; + rSrc2.bottom+=slicesY[3]+slicesY[4]+slicesY[5]; + rDst2.top=rDst.bottom; + rDst2.bottom=totalHeight; + rMargins2.top=slicesY[3]; + rMargins2.bottom=slicesY[5]; + MarginsBlit(hdcTemp,hdc,rSrc2,rDst2,rMargins2,(opacity==MenuSkin::OPACITY_SOLID && bmpSkin.bIs32)); + if (bmpSkinPattern.GetBitmap()) + MarginsBlit(hdcPMaskTemp,hdcPMask,rSrc2,rDst2,rMargins2,false); + if (bmpSkinEmblem.GetBitmap()) + MarginsBlit(hdcEMaskTemp,hdcEMask,rSrc2,rDst2,rMargins2,false); + } + + if (totalWidth2>0) + { + rSrc.left=rSrc.right; + rSrc.right+=slicesX[6]+slicesX[7]+slicesX[8]; + rDst.left=rDst.right; + rDst.right+=totalWidth2; + rMargins.left=slicesX[6]; + rMargins.right=slicesX[8]; + MarginsBlit(hdcTemp,hdc,rSrc,rDst,rMargins,(opacity==MenuSkin::OPACITY_SOLID && bmpSkin.bIs32)); + if (bmpSkinPattern.GetBitmap()) + MarginsBlit(hdcPMaskTemp,hdcPMask,rSrc,rDst,rMargins,false); + if (bmpSkinEmblem.GetBitmap()) + MarginsBlit(hdcEMaskTemp,hdcEMask,rSrc,rDst,rMargins,false); + + if (searchHeight>0) + { + RECT rSrc2=rSrc, rDst2=rDst, rMargins2=rMargins; + rSrc2.top=rSrc.bottom; + rSrc2.bottom+=slicesY[3]+slicesY[4]+slicesY[5]; + rDst2.top=rDst.bottom; + rDst2.bottom=totalHeight; + rMargins2.top=slicesY[3]; + rMargins2.bottom=slicesY[5]; + MarginsBlit(hdcTemp,hdc,rSrc2,rDst2,rMargins2,(opacity==MenuSkin::OPACITY_SOLID && bmpSkin.bIs32)); + if (bmpSkinPattern.GetBitmap()) + MarginsBlit(hdcPMaskTemp,hdcPMask,rSrc2,rDst2,rMargins2,false); + if (bmpSkinEmblem.GetBitmap()) + MarginsBlit(hdcEMaskTemp,hdcEMask,rSrc2,rDst2,rMargins2,false); + } + } + } + else + { + RECT rc={0,0,totalWidth,totalHeight}; + SetDCBrushColor(hdc,s_Skin.Main_background); + FillRect(hdc,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + + if (bHasPattern) + { + SetDCBrushColor(hdcPMask,bmpSkinPattern.GetColor()); + FillRect(hdcPMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + } + if (bHasEmblemMask) + { + SetDCBrushColor(hdcEMask,bmpSkinEmblem.GetColor()); + FillRect(hdcEMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + } + } + + if (m_SearchIndex>=0 && s_bWin7Style) + { + // draw the search background + if (bmpSearch.GetBitmap()) + { + if (bHasPattern) + { + if (bmpSearchPattern.GetBitmap()) + { + SelectObject(hdcPMaskTemp,bmpSearchPattern.GetBitmap()); + } + else if (!bmpSearchPattern.bIsBitmap) + { + RECT rc={searchX[0],searchY[0],searchX[3],searchY[3]}; + SetDCBrushColor(hdcPMask,bmpSearchPattern.GetColor()); + FillRect(hdcPMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + } + } + if (bHasEmblemMask) + { + if (bmpSearchEmblem.GetBitmap()) + { + SelectObject(hdcEMaskTemp,bmpSearchEmblem.GetBitmap()); + } + else if (!bmpSearchEmblem.bIsBitmap) + { + RECT rc={searchX[0],searchY[0],searchX[3],searchY[3]}; + SetDCBrushColor(hdcEMask,bmpSearchEmblem.GetColor()); + FillRect(hdcEMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + } + } + + int u[4], v[4]; + u[0]=0; + u[1]=searchSlicesX[0]+searchSlicesX[1]+searchSlicesX[2]; + u[2]=u[1]+searchSlicesX[3]+searchSlicesX[4]+searchSlicesX[5]; + u[3]=u[2]+searchSlicesX[6]+searchSlicesX[7]+searchSlicesX[8]; + v[0]=0; + v[1]=searchSlicesY[0]+searchSlicesY[1]+searchSlicesY[2]; + v[2]=v[1]+searchSlicesY[3]+searchSlicesY[4]+searchSlicesY[5]; + v[3]=v[2]+searchSlicesY[6]+searchSlicesY[7]+searchSlicesY[8]; + SelectObject(hdcTemp,bmpSearch.GetBitmap()); + for (int y=0;y<3;y++) + { + for (int x=0;x<3;x++) + { + RECT rDst={searchX[x],searchY[y],searchX[x+1],searchY[y+1]}; + RECT rSrc={u[x],v[y],u[x+1],v[y+1]}; + RECT rMargins={searchSlicesX[x*3],searchSlicesY[y*3],searchSlicesX[x*3+2],searchSlicesY[y*3+2]}; + MarginsBlit(hdcTemp,hdc,rSrc,rDst,rMargins,bmpSearch.bIs32); + if (bmpSearchPattern.GetBitmap()) + MarginsBlit(hdcPMaskTemp,hdcPMask,rSrc,rDst,rMargins,bmpSearchPattern.bIs32); + if (bmpSearchEmblem.GetBitmap()) + MarginsBlit(hdcEMaskTemp,hdcEMask,rSrc,rDst,rMargins,bmpSearchPattern.bIs32); + } + } + } + else if (!bmpSearch.bIsBitmap) + { + RECT rDst={searchX[0],searchY[0],searchX[3],searchY[3]}; + SetDCBrushColor(hdc,bmpSearch.GetColor()); + FillRect(hdc,&rDst,(HBRUSH)GetStockObject(DC_BRUSH)); + if (bHasPattern && !bmpSearchPattern.bIsBitmap) + { + SetDCBrushColor(hdcPMask,bmpSkinPattern.GetColor()); + FillRect(hdcPMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + } + if (bHasEmblemMask && !bmpSearchEmblem.bIsBitmap) + { + SetDCBrushColor(hdcEMask,bmpSkinEmblem.GetColor()); + FillRect(hdcEMask,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + } + } + } + + if (bHasPattern) + { + if (PMaskBmp02) + SelectObject(hdcPMaskTemp,PMaskBmp02); + if (PMaskBmp0) + SelectObject(hdcPMask,PMaskBmp0); + if (hdcPMask) + DeleteDC(hdcPMask); + if (hdcPMaskTemp) + DeleteDC(hdcPMaskTemp); + + // apply pattern + BlendPatterns(PMaskBits,totalWidth,totalHeight); + SelectObject(hdcTemp,PMaskBmp); + AlphaBlend(hdc,0,0,totalWidth,totalHeight,hdcTemp,0,0,totalWidth,totalHeight,g_AlphaFunc); + SelectObject(hdcTemp,bmp02); + DeleteObject(PMaskBmp); + } + + // draw vertical separator + if (width2) + { + if (s_Skin.Main_separatorV.GetBitmap()) + { + SelectObject(hdcTemp,s_Skin.Main_separatorV.GetBitmap()); + RECT rSrc2={0,0,s_Skin.Main_separatorWidth,s_Skin.Main_separator_slices_Y[0]+s_Skin.Main_separator_slices_Y[1]+s_Skin.Main_separator_slices_Y[2]}; + RECT rDst2={totalWidth1,menuPadding[0].top,totalWidth1+s_Skin.Main_separatorWidth,totalHeight-menuPadding[0].bottom}; + if (s_bRTL) + { + rDst2.left=totalWidth-rDst2.right; + rDst2.right=totalWidth-totalWidth1; + } + RECT rMargins2={0,s_Skin.Main_separator_slices_Y[0],0,s_Skin.Main_separator_slices_Y[2]}; + MarginsBlit(hdcTemp,hdc,rSrc2,rDst2,rMargins2,s_Skin.Main_separatorV.bIs32); + } + else if (!bmpSkin.GetBitmap()) // only when there is no main bitmap (it may have a built-in separator) + { + rc.left=rc.right=s_bRTL?(totalWidth-totalWidth1-2):totalWidth1; + rc.top=menuPadding[0].top; + rc.bottom=totalHeight-menuPadding[0].bottom; + DrawEdge(hdc,&rc,EDGE_ETCHED,BF_LEFT); + } + } + + SelectObject(hdcTemp,bmp02); + + for (int i=0;i<_countof(s_Skin.Main_emblems);i++) + { + if (s_Skin.Main_emblems[i].GetBitmap()) + { + const SIZE &emblemSize=s_Skin.Main_emblem_sizes[i]; + const RECT &emblemPadding=s_Skin.Main_emblem_paddings[i]; + MenuSkin::THAlign alignH=s_Skin.Main_emblem_alignH1[i]; + if (width2==0 && (alignH==MenuSkin::HALIGN_LEFT2 || alignH==MenuSkin::HALIGN_RIGHT2 || alignH==MenuSkin::HALIGN_CENTER2)) + alignH=s_Skin.Main_emblem_alignH2[i]; + if (alignH==MenuSkin::HALIGN_CORNER) + alignH=(m_Options&CONTAINER_LEFT)?MenuSkin::HALIGN_LEFT:MenuSkin::HALIGN_RIGHT; + MenuSkin::TVAlign alignV=s_Skin.Main_emblem_alignV[i]; + if (alignV==MenuSkin::VALIGN_CORNER) + alignV=(m_Options&CONTAINER_TOP)?MenuSkin::VALIGN_TOP:MenuSkin::VALIGN_BOTTOM; + if (alignH==MenuSkin::HALIGN_NONE || alignV==MenuSkin::VALIGN_NONE) + continue; + + int w=emblemSize.cx+emblemPadding.left+emblemPadding.right; + int h=emblemSize.cy+emblemPadding.top+emblemPadding.bottom; + int x0=0, x1=totalWidth; + int y0=0, y1=totalHeight; + + if (alignH==MenuSkin::HALIGN_CENTER1 || alignH==MenuSkin::HALIGN_LEFT1 || alignH==MenuSkin::HALIGN_RIGHT1) + x1=totalWidth1; + else if (alignH==MenuSkin::HALIGN_CENTER2 || alignH==MenuSkin::HALIGN_LEFT2 || alignH==MenuSkin::HALIGN_RIGHT2) + x0=totalWidth1; + if (alignH==MenuSkin::HALIGN_LEFT || alignH==MenuSkin::HALIGN_LEFT1 || alignH==MenuSkin::HALIGN_LEFT2) + x1=x0+w; + else if (alignH==MenuSkin::HALIGN_RIGHT || alignH==MenuSkin::HALIGN_RIGHT1 || alignH==MenuSkin::HALIGN_RIGHT2) + x0=x1-w; + else if (alignH==MenuSkin::HALIGN_CENTER || alignH==MenuSkin::HALIGN_CENTER1 || alignH==MenuSkin::HALIGN_CENTER2) + x0=(x0+x1-w)/2, x1=x0+w; + + if (alignV==MenuSkin::VALIGN_TOP) + y1=y0+h; + else if (alignV==MenuSkin::VALIGN_BOTTOM) + y0=y1-h; + else if (alignV==MenuSkin::VALIGN_CENTER) + y0=(y0+y1-h)/2, y1=y0+h; + + x0+=emblemPadding.left; + y0+=emblemPadding.top; + + RECT rcEmblem={x0,y0,x0+emblemSize.cx,y0+emblemSize.cy}; + if (rcEmblem.left>=totalWidth || rcEmblem.right<0 || rcEmblem.top>=totalHeight || rcEmblem.bottom<0) + continue; + + HBITMAP maskedEmblem=NULL; + if (bHasEmblemMask && i<4) + maskedEmblem=CreateMaskedEmblem(s_Skin.Main_emblems[i].GetBitmap(),rcEmblem,EMaskBits,totalWidth,totalHeight,i); + + if (maskedEmblem) + SelectObject(hdcTemp,maskedEmblem); + else + SelectObject(hdcTemp,s_Skin.Main_emblems[i].GetBitmap()); + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + w=rcEmblem.right-rcEmblem.left; + h=rcEmblem.bottom-rcEmblem.top; + AlphaBlend(hdc,rcEmblem.left,rcEmblem.top,w,h,hdcTemp,0,0,w,h,func); + SelectObject(hdcTemp,bmp02); + if (maskedEmblem) + DeleteObject(maskedEmblem); + } + } + + if (bHasEmblemMask) + { + if (EMaskBmp02) + SelectObject(hdcEMaskTemp,EMaskBmp02); + if (EMaskBmp0) + SelectObject(hdcEMask,EMaskBmp0); + if (hdcEMask) + DeleteDC(hdcEMask); + if (hdcEMaskTemp) + DeleteDC(hdcEMaskTemp); + DeleteObject(EMaskBmp); + } + + if (s_bRTL) + { + SelectObject(hdc,bmp0); // deselect m_Bitmap so all the GDI operations get flushed + // mirror the background image for RTL windows + for (int y=0;y0) + { + // draw the glow + opts.dwFlags=DTT_COMPOSITED|DTT_TEXTCOLOR|DTT_GLOWSIZE; + opts.crText=0xFFFFFF; + opts.iGlowSize=s_Skin.Caption_glow_size; + DrawThemeTextEx(s_Theme,hdcTemp,0,0,caption,-1,DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE,&rc,&opts); + SelectObject(hdcTemp,bmp02); // deselect bmpText so all the GDI operations get flushed + + // change the glow color + int gr=(s_Skin.Caption_glow_color)&255; + int gg=(s_Skin.Caption_glow_color>>8)&255; + int gb=(s_Skin.Caption_glow_color>>16)&255; + for (int y=0;y>24); + int r1=(pixel>>16)&255; + int g1=(pixel>>8)&255; + int b1=(pixel)&255; + r1=(r1*gr)/255; + g1=(g1*gg)/255; + b1=(b1*gb)/255; + pixel=(a1<<24)|(r1<<16)|(g1<<8)|b1; + } + + SelectObject(hdcTemp,bmpText); + } + + // draw the text + int offset=0; + if (s_bRTL) + offset=totalWidth-textHeight; + + if (s_Theme) + { + opts.dwFlags=DTT_COMPOSITED|DTT_TEXTCOLOR; + opts.crText=s_Skin.Caption_text_color; + DrawThemeTextEx(s_Theme,hdcTemp,0,0,caption,-1,DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE,&rc,&opts); + SelectObject(hdcTemp,bmp02); + + // rotate and copy the text onto the final bitmap. Combine the alpha channels + for (int y=0;y>24); + int r1=(src>>16)&255; + int g1=(src>>8)&255; + int b1=(src)&255; + + unsigned int &dst=bits[(totalHeight-1-x)*totalWidth+y+offset]; + + int a2=(dst>>24); + int r2=(dst>>16)&255; + int g2=(dst>>8)&255; + int b2=(dst)&255; + + r2=(r2*(255-a1))/255+r1; + g2=(g2*(255-a1))/255+g1; + b2=(b2*(255-a1))/255+b1; + a2=a1+a2-(a1*a2)/255; + + dst=(a2<<24)|(r2<<16)|(g2<<8)|b2; + } + } + else + { + // draw white text on black background + SetTextColor(hdcTemp,0xFFFFFF); + SetBkMode(hdcTemp,TRANSPARENT); + DrawText(hdcTemp,caption,-1,&rc,DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE); + SelectObject(hdcTemp,bmp02); + + // rotate and copy the text onto the final bitmap + // change the text color + int tr=(s_Skin.Caption_text_color>>16)&255; + int tg=(s_Skin.Caption_text_color>>8)&255; + int tb=(s_Skin.Caption_text_color)&255; + for (int y=0;y>24); + int r2=(dst>>16)&255; + int g2=(dst>>8)&255; + int b2=(dst)&255; + + r2=(r2*(255-a1)+tr*a1)/255; + g2=(g2*(255-a1)+tg*a1)/255; + b2=(b2*(255-a1)+tb*a1)/255; + a2=a1+a2-(a1*a2)/255; + + dst=(a2<<24)|(r2<<16)|(g2<<8)|b2; + } + } + + DeleteObject(bmpText); + SelectObject(hdcTemp,font0); + } + + if (s_Skin.User_image_size && !s_bWin7Style) + { + // draw user image + HBITMAP userPicture; + bool bMask=(s_Skin.User_mask.bIsBitmap && s_Skin.User_mask.bIs32 && s_Skin.User_maskSize.cx==s_Skin.User_image_size && s_Skin.User_maskSize.cy==s_Skin.User_image_size); + if (bMask) + userPicture=LoadUserImage(s_Skin.User_image_size,s_Skin.User_mask.GetBitmap()); + else + userPicture=LoadUserImage(s_Skin.User_image_size,NULL); + if (userPicture) + { + // draw user picture + SIZE frameSize; + if (s_Skin.User_bitmap.GetBitmap()) + { + BITMAP info; + GetObject(s_Skin.User_bitmap.GetBitmap(),sizeof(info),&info); + frameSize.cx=info.bmWidth; + frameSize.cy=info.bmHeight; + } + else + { + frameSize.cx=s_Skin.User_image_size+s_Skin.User_image_offset.x*2; + frameSize.cy=s_Skin.User_image_size+s_Skin.User_image_offset.y*2; + } + POINT pos=s_Skin.User_frame_position; + if (pos.x==MenuSkin::USER_CENTER) + pos.x=(totalWidth-frameSize.cx)/2; + else if (pos.x==MenuSkin::USER_CENTER1) + pos.x=(totalWidth1+textHeight-frameSize.cx)/2; + else if (pos.x==MenuSkin::USER_CENTER2) + { + if (totalWidth2>0) + pos.x=totalWidth1+(totalWidth2-frameSize.cx)/2; + else + pos.x=(totalWidth-frameSize.cx)/2; + } + + if (pos.x<0) pos.x+=totalWidth-frameSize.cx; + if (pos.y<0) pos.y+=totalHeight-frameSize.cy; + + if (s_bRTL) + pos.x=totalWidth-frameSize.cx-pos.x; + pos.x+=s_Skin.User_image_offset.x; + pos.y+=s_Skin.User_image_offset.y; + HGDIOBJ bmp02=SelectObject(hdcTemp,userPicture); + unsigned int alpha=s_Skin.User_image_alpha; + if (alpha==255 && !bMask) + { + BitBlt(hdc,pos.x,pos.y,s_Skin.User_image_size,s_Skin.User_image_size,hdcTemp,0,0,SRCCOPY); + } + else + { + BLENDFUNCTION func={AC_SRC_OVER,0,bMask?255:alpha,bMask?AC_SRC_ALPHA:0}; + AlphaBlend(hdc,pos.x,pos.y,s_Skin.User_image_size,s_Skin.User_image_size,hdcTemp,0,0,s_Skin.User_image_size,s_Skin.User_image_size,func); + } + + if (s_bRTL) + m_rUser1.left=totalWidth-pos.x-s_Skin.User_image_size; + else + m_rUser1.left=pos.x; + m_rUser1.right=m_rUser1.left+s_Skin.User_image_size; + m_rUser1.top=pos.y; + m_rUser1.bottom=pos.y+s_Skin.User_image_size; + + if (opacity!=MenuSkin::OPACITY_SOLID && !bMask) + { + // set to opaque + SelectObject(hdc,bmp0); // deselect m_Bitmap so all the GDI operations get flushed + unsigned int *bits2=bits+pos.y*totalWidth+pos.x; + alpha<<=24; + for (int y=0;y0) + { + int nameWidth=rc0.right-rc0.left; + int nameHeight=rc0.bottom-rc0.top; + RECT rc={0,0,nameWidth,nameHeight}; + + // draw the title + BITMAPINFO dib={sizeof(dib)}; + dib.bmiHeader.biWidth=nameWidth; + dib.bmiHeader.biHeight=-nameHeight; + dib.bmiHeader.biPlanes=1; + dib.bmiHeader.biBitCount=32; + dib.bmiHeader.biCompression=BI_RGB; + + font0=(HFONT)SelectObject(hdcTemp,s_Skin.User_font); + + unsigned int *bits2; + HBITMAP bmpText=CreateDIBSection(hdcTemp,&dib,DIB_RGB_COLORS,(void**)&bits2,NULL,0); + HGDIOBJ bmp02=SelectObject(hdcTemp,bmpText); + FillRect(hdcTemp,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH)); + + DWORD align=DT_CENTER; + if (s_Skin.User_name_align==MenuSkin::HALIGN_LEFT || s_Skin.User_name_align==MenuSkin::HALIGN_LEFT1 || s_Skin.User_name_align==MenuSkin::HALIGN_LEFT2) + align=s_bRTL?DT_RIGHT:DT_LEFT; + else if (s_Skin.User_name_align==MenuSkin::HALIGN_RIGHT || s_Skin.User_name_align==MenuSkin::HALIGN_RIGHT1 || s_Skin.User_name_align==MenuSkin::HALIGN_RIGHT2) + align=s_bRTL?DT_LEFT:DT_RIGHT; + if (s_Theme && s_Skin.User_glow_size>0) + { + InflateRect(&rc,-s_Skin.User_glow_size,-s_Skin.User_glow_size); + // draw the glow + opts.dwFlags=DTT_COMPOSITED|DTT_TEXTCOLOR|DTT_GLOWSIZE; + opts.crText=0xFFFFFF; + opts.iGlowSize=s_Skin.User_glow_size; + DrawThemeTextEx(s_Theme,hdcTemp,0,0,name,-1,align|DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS|DT_NOCLIP,&rc,&opts); + SelectObject(hdcTemp,bmp02); // deselect bmpText so all the GDI operations get flushed + + // change the glow color + int gr=(s_Skin.User_glow_color)&255; + int gg=(s_Skin.User_glow_color>>8)&255; + int gb=(s_Skin.User_glow_color>>16)&255; + for (int y=0;y>24); + int r1=(pixel>>16)&255; + int g1=(pixel>>8)&255; + int b1=(pixel)&255; + r1=(r1*gr)/255; + g1=(g1*gg)/255; + b1=(b1*gb)/255; + pixel=(a1<<24)|(r1<<16)|(g1<<8)|b1; + } + + SelectObject(hdcTemp,bmpText); + } + + // draw the text + int offset=rc0.top*totalWidth+rc0.left; + if (s_bRTL) + offset=rc0.top*totalWidth+totalWidth-rc0.right; + + if (s_Theme) + { + opts.dwFlags=DTT_COMPOSITED|DTT_TEXTCOLOR; + opts.crText=s_Skin.User_text_color; + DrawThemeTextEx(s_Theme,hdcTemp,0,0,name,-1,align|DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS|DT_NOCLIP,&rc,&opts); + SelectObject(hdcTemp,bmp02); + + // copy the text onto the final bitmap. Combine the alpha channels + for (int y=0;y>24); + int r1=(src>>16)&255; + int g1=(src>>8)&255; + int b1=(src)&255; + + unsigned int &dst=bits[y*totalWidth+x+offset]; + + int a2=(dst>>24); + int r2=(dst>>16)&255; + int g2=(dst>>8)&255; + int b2=(dst)&255; + + r2=(r2*(255-a1))/255+r1; + g2=(g2*(255-a1))/255+g1; + b2=(b2*(255-a1))/255+b1; + a2=a1+a2-(a1*a2)/255; + + dst=(a2<<24)|(r2<<16)|(g2<<8)|b2; + } + } + else + { + // draw white text on black background + SetTextColor(hdcTemp,0xFFFFFF); + SetBkMode(hdcTemp,TRANSPARENT); + DrawText(hdcTemp,name,-1,&rc,align|DT_VCENTER|DT_NOPREFIX|DT_SINGLELINE|DT_END_ELLIPSIS|DT_NOCLIP); + SelectObject(hdcTemp,bmp02); + + // copy the text onto the final bitmap + // change the text color + int tr=(s_Skin.User_text_color>>16)&255; + int tg=(s_Skin.User_text_color>>8)&255; + int tb=(s_Skin.User_text_color)&255; + for (int y=0;y>24); + int r2=(dst>>16)&255; + int g2=(dst>>8)&255; + int b2=(dst)&255; + + r2=(r2*(255-a1)+tr*a1)/255; + g2=(g2*(255-a1)+tg*a1)/255; + b2=(b2*(255-a1)+tb*a1)/255; + a2=a1+a2-(a1*a2)/255; + + dst=(a2<<24)|(r2<<16)|(g2<<8)|b2; + } + } + + DeleteObject(bmpText); + SelectObject(hdcTemp,font0); + } + } + + DeleteDC(hdcTemp); + + SelectObject(hdc,bmp0); + DeleteDC(hdc); + + // calculate the window region + if (bCreateRegion) + { + if (m_Region) DeleteObject(m_Region); + m_Region=NULL; + if (opacity==MenuSkin::OPACITY_REGION || opacity==MenuSkin::OPACITY_GLASS || opacity==MenuSkin::OPACITY_FULLGLASS) + { + for (int y=0;y=0) + { + maxx++; + HRGN r=CreateRectRgn(minx,y,maxx,y+1); + AddTrackedObject(r); + if (!m_Region) + m_Region=r; + else + { + CombineRgn(m_Region,m_Region,r,RGN_OR); + DeleteObject(r); + } + } + } + } + else if (opacity==MenuSkin::OPACITY_ALPHA || opacity==MenuSkin::OPACITY_FULLALPHA) + m_Region=CreateRectRgn(0,0,totalWidth,totalHeight); + } +} + +void CMenuContainer::CreateContentRects( int width1, int width2, int height1, int height2, int &totalWidth, int &totalHeight ) +{ + const int *slicesY; + RECT menuPadding[2]; + if (s_MenuMode==MODE_SEARCH) + { + slicesY=s_Skin.Main_bitmap_search_slices_Y; + menuPadding[0]=s_Skin.Main_search_padding; + memset(&menuPadding[1],0,sizeof(menuPadding[1])); + } + else if (s_MenuMode==MODE_JUMPLIST) + { + slicesY=s_Skin.Main_bitmap_jump_slices_Y; + menuPadding[0]=s_Skin.Main_padding; + menuPadding[1]=s_Skin.Main_jump_padding; + } + else + { + slicesY=s_Skin.Main_bitmap_slices_Y; + menuPadding[0]=s_Skin.Main_padding; + menuPadding[1]=s_Skin.Main2_padding; + } + + int totalWidth1=width1+menuPadding[0].left+menuPadding[0].right; + int totalWidth2=width2+menuPadding[1].left+menuPadding[1].right; + totalWidth=totalWidth1+totalWidth2; + + totalHeight=height1+menuPadding[0].top+menuPadding[0].bottom; + int totalHeight2=height2+menuPadding[1].top+menuPadding[1].bottom; + if (totalHeight0) + { + m_rContent2.left=m_rContent.right+menuPadding[0].right+menuPadding[1].left; + m_rContent2.right=totalWidth-menuPadding[1].right; + m_rContent2.top=menuPadding[1].top; + m_rContent2.bottom=m_rContent2.top+height2; + } +} + +void CMenuContainer::CreateSubmenuRegion( int width, int height ) +{ + int totalWidth=s_Skin.Submenu_padding.left+s_Skin.Submenu_padding.right+width; + int totalHeight=s_Skin.Submenu_padding.top+s_Skin.Submenu_padding.bottom+height; + if (m_Region) DeleteObject(m_Region); + m_Region=NULL; + if (s_Skin.Submenu_opacity==MenuSkin::OPACITY_SOLID) + return; + if (!s_Skin.Submenu_bitmap.GetBitmap() || !s_Skin.Submenu_bitmap.bIs32) + return; + if (s_Skin.Submenu_opacity==MenuSkin::OPACITY_ALPHA || s_Skin.Submenu_opacity==MenuSkin::OPACITY_FULLALPHA) + { + m_Region=CreateRectRgn(0,0,totalWidth,totalHeight-m_ExtraTop-m_ExtraBottom); + return; + } + BITMAP info; + GetObject(s_Skin.Submenu_bitmap.GetBitmap(),sizeof(info),&info); + const int *slicesX=s_Skin.Submenu_bitmap_slices_X+3; + const int *slicesY=s_Skin.Submenu_bitmap_slices_Y; + int slicesX0=slicesX[s_bRTL?2:0]; + int slicesX2=slicesX[s_bRTL?0:2]; + int bmpWidth=slicesX0+slicesX[1]+slicesX2; + int bmpHeight=slicesY[0]+slicesY[1]+slicesY[2]; + unsigned int *bits=(unsigned int*)info.bmBits; + { + for (int y=m_ExtraTop;y=totalHeight-slicesY[2]) + yy=bmpHeight-totalHeight+y; + else + yy=slicesY[0]+((y-slicesY[0])*slicesY[1])/(totalHeight-slicesY[0]-slicesY[2]); + if (info.bmHeight>0) + yy=info.bmHeight-yy-1; + int yw=yy*info.bmWidth; + int minx=-1, maxx=-1; + for (int x=0;x=0) + { + if (minx>=bmpWidth-slicesX2) + minx+=totalWidth-bmpWidth; + else if (minx>slicesX0) + minx=slicesX0+((minx-slicesX0)*(totalWidth-slicesX0-slicesX2))/slicesX[1]; + + if (maxx>=bmpWidth-slicesX2) + maxx+=totalWidth-bmpWidth; + else if (minx>slicesX0) + maxx=slicesX0+((maxx-slicesX0)*(totalWidth-slicesX0-slicesX2))/slicesX[1]; + + maxx++; + HRGN r=CreateRectRgn(minx,y-m_ExtraTop,maxx,y-m_ExtraTop+1); + AddTrackedObject(r); + if (!m_Region) + m_Region=r; + else + { + CombineRgn(m_Region,m_Region,r,RGN_OR); + DeleteObject(r); + } + } + } + } +} + +void CMenuContainer::DrawBackground( HDC hdc, const RECT &drawRect ) +{ + HDC hdc2=CreateCompatibleDC(hdc); + + // draw the background (bitmap or solid color) + HBITMAP bmpMain=NULL; + RECT rMarginsMain, rSrcMain; + bool bAlphaMain; + if (m_Bitmap) + { + HGDIOBJ bmp0=SelectObject(hdc2,m_Bitmap); + BitBlt(hdc,m_BitmapOffset,0,m_rMenu.right,m_rMenu.bottom,hdc2,0,0,SRCCOPY); + SelectObject(hdc2,bmp0); + bmpMain=m_Bitmap; + { RECT rc={m_rMenu.right-m_rMenu.left,m_rMenu.bottom,0,0}; rMarginsMain=rc; } + { RECT rc={0,0,m_rMenu.right-m_rMenu.left,m_rMenu.bottom}; rSrcMain=rc; } + bAlphaMain=false; + } + else if (m_bSubMenu && s_Skin.Submenu_bitmap.GetBitmap()) + { + bAlphaMain=(s_Skin.Submenu_opacity==MenuSkin::OPACITY_SOLID && s_Skin.Submenu_bitmap.bIs32); + if (bAlphaMain) + { + SetDCBrushColor(hdc,s_Skin.Submenu_background); + FillRect(hdc,&drawRect,(HBRUSH)GetStockObject(DC_BRUSH)); + } + HGDIOBJ bmp0=SelectObject(hdc2,s_Skin.Submenu_bitmap.GetBitmap()); + const int *slicesX=s_Skin.Submenu_bitmap_slices_X; + const int *slicesY=s_Skin.Submenu_bitmap_slices_Y; + RECT rSrc={0,0,slicesX[3]+slicesX[4]+slicesX[5],slicesY[0]+slicesY[1]+slicesY[2]}; + RECT rMargins={slicesX[3],slicesY[0],slicesX[5],slicesY[2]}; + RECT rDst=m_rMenu; + rDst.top-=m_ExtraTop; + rDst.bottom+=m_ExtraBottom; + MarginsBlit(hdc2,hdc,rSrc,rDst,rMargins,bAlphaMain); + SelectObject(hdc2,bmp0); + bmpMain=s_Skin.Submenu_bitmap.GetBitmap(); + rMarginsMain=rMargins; + rSrcMain=rSrc; + } + else + { + SetDCBrushColor(hdc,m_bSubMenu?s_Skin.Submenu_background:s_Skin.Main_background); + FillRect(hdc,&m_rMenu,(HBRUSH)GetStockObject(DC_BRUSH)); + } + + MenuBitmap bmpSeparatorV; + int sepWidth=0; + const int *sepSlicesY=NULL; + MenuBitmap bmpPager; + const int *pagSlicesX=NULL; + const int *pagSlicesY=NULL; + MenuBitmap bmpPagerArrows; + SIZE pagArrowSize; + MenuSkin::TOpacity opacity=m_bSubMenu?s_Skin.Submenu_opacity:s_Skin.Main_opacity; + int glow=s_Skin.ItemSettings[m_bSubMenu?MenuSkin::SUBMENU_ITEM:MenuSkin::COLUMN1_ITEM].glowSize; + if (!s_Theme) glow=0; + TRecentKeys recentType=(TRecentKeys)GetSettingInt(L"RecentProgKeys"); + + if (m_bSubMenu) + { + bmpSeparatorV=s_Skin.Submenu_separatorV; + sepWidth=s_Skin.Submenu_separatorWidth; + sepSlicesY=s_Skin.Submenu_separator_slices_Y; + + bmpPager=s_Skin.Submenu_pager; + pagSlicesX=s_Skin.Submenu_pager_slices_X; + pagSlicesY=s_Skin.Submenu_pager_slices_Y; + bmpPagerArrows=s_Skin.Submenu_pager_arrows; + pagArrowSize=s_Skin.Submenu_pager_arrow_Size; + } + else + { + bmpSeparatorV=s_Skin.Main_separatorV; + sepWidth=s_Skin.Main_separatorWidth; + sepSlicesY=s_Skin.Main_separator_slices_Y; + + bmpPager=s_Skin.Main_pager; + pagSlicesX=s_Skin.Main_pager_slices_X; + pagSlicesY=s_Skin.Main_pager_slices_Y; + bmpPagerArrows=s_Skin.Main_pager_arrows; + pagArrowSize=s_Skin.Main_pager_arrow_Size; + } + + HGDIOBJ font0=GetCurrentObject(hdc,OBJ_FONT); + SetBkMode(hdc,TRANSPARENT); + + // set clip rectangle for the scrollable items + int clipTop=m_rContent.top; + int clipBottom=m_rContent.bottom; + if (m_bScrollUp) + clipTop=m_rContent.top+m_ScrollButtonSize; + if (m_bScrollDown) + clipBottom=m_rContent.top+m_ScrollHeight-m_ScrollButtonSize; + if (m_ScrollHeight>0) + IntersectClipRect(hdc,0,clipTop,m_rMenu.right,clipBottom); + + // draw items + for (int index=0;;index++) + { + if (!m_bSubMenu) + { + if (index==m_ProgramTreeIndex) continue; + if (s_MenuMode==MODE_PROGRAMS) + { + if (index0 && index==m_ScrollCount) + { + // clean up after the scrollable items + SelectClipRgn(hdc,NULL); + if (m_bScrollUp) + { + if (glow || opacity==MenuSkin::OPACITY_FULLALPHA || opacity==MenuSkin::OPACITY_FULLGLASS) + { + // fix background behind the up button (DrawThemeTextEx may spill onto the tablecloth) + RECT rc={m_rContent.left,0,m_rContent.right,clipTop}; + if (bAlphaMain || !bmpMain) + { + SetDCBrushColor(hdc,m_bSubMenu?s_Skin.Submenu_background:s_Skin.Main_background); + FillRect(hdc,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + } + if (bmpMain) + { + HGDIOBJ bmp0=SelectObject(hdc2,bmpMain); + IntersectClipRect(hdc,m_rContent.left,0,m_rContent.right,clipTop); + MarginsBlit(hdc2,hdc,rSrcMain,m_rMenu,rMarginsMain,bAlphaMain); + SelectObject(hdc2,bmp0); + SelectClipRgn(hdc,NULL); + } + } + + // draw up button + RECT rc=m_rContent; + rc.bottom=clipTop; + if (bmpPager.GetBitmap() && bmpPagerArrows.GetBitmap()) + { + // background + HGDIOBJ bmp0=SelectObject(hdc2,bmpPager.GetBitmap()); + RECT rSrc={0,0,pagSlicesX[0]+pagSlicesX[1]+pagSlicesX[2],pagSlicesY[0]+pagSlicesY[1]+pagSlicesY[2]}; + if (m_bScrollUpHot) + OffsetRect(&rSrc,0,rSrc.bottom); + RECT rMargins={pagSlicesX[0],pagSlicesY[0],pagSlicesX[2],pagSlicesY[2]}; + MarginsBlit(hdc2,hdc,rSrc,rc,rMargins,bmpPager.bIs32); + + // arrow + SelectObject(hdc2,bmpPagerArrows.GetBitmap()); + int x=(rc.left+rc.right-pagArrowSize.cx)/2; + int y=(rc.top+rc.bottom-pagArrowSize.cy)/2; + if (bmpPagerArrows.bIs32) + { + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + AlphaBlend(hdc,x,y,pagArrowSize.cx,pagArrowSize.cy,hdc2,m_bScrollUpHot?pagArrowSize.cx:0,0,pagArrowSize.cx,pagArrowSize.cy,func); + } + else + BitBlt(hdc,x,y,pagArrowSize.cx,pagArrowSize.cy,hdc2,m_bScrollUpHot?pagArrowSize.cx:0,0,SRCCOPY); + SelectObject(hdc2,bmp0); + } + else + { + if (s_PagerTheme) + DrawThemeBackground(s_PagerTheme,hdc,SBP_ARROWBTN,(m_bScrollUpHot?ABS_UPHOT:ABS_UPHOVER),&rc,NULL); + else + DrawFrameControl(hdc,&rc,DFC_SCROLL,DFCS_SCROLLUP|DFCS_FLAT|(m_bScrollUpHot?DFCS_PUSHED:0)); + } + } + if (m_bScrollDown) + { + int bottom=clipBottom+s_Skin.ItemSettings[m_bSubMenu?MenuSkin::SUBMENU_ITEM:MenuSkin::COLUMN1_ITEM].itemHeight; + if (bottom>=m_rMenu.bottom) bottom=m_rMenu.bottom; + if (bottom>clipBottom && (glow || opacity==MenuSkin::OPACITY_FULLALPHA || opacity==MenuSkin::OPACITY_FULLGLASS)) + { + // fix background behind the up button (DrawThemeTextEx may spill onto the tablecloth) + RECT rc={m_rContent.left,clipBottom,m_rContent.right,bottom}; + if (bAlphaMain || !bmpMain) + { + SetDCBrushColor(hdc,m_bSubMenu?s_Skin.Submenu_background:s_Skin.Main_background); + FillRect(hdc,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + } + if (bmpMain) + { + HGDIOBJ bmp0=SelectObject(hdc2,bmpMain); + IntersectClipRect(hdc,m_rContent.left,clipBottom,m_rContent.right,bottom); + MarginsBlit(hdc2,hdc,rSrcMain,m_rMenu,rMarginsMain,bAlphaMain); + SelectObject(hdc2,bmp0); + SelectClipRgn(hdc,NULL); + } + } + + // draw down button + RECT rc=m_rContent; + rc.bottom=m_rContent.top+m_ScrollHeight; + rc.top=clipBottom; + if (bmpPager.GetBitmap() && bmpPagerArrows.GetBitmap()) + { + // background + HGDIOBJ bmp0=SelectObject(hdc2,bmpPager.GetBitmap()); + RECT rSrc={0,0,pagSlicesX[0]+pagSlicesX[1]+pagSlicesX[2],pagSlicesY[0]+pagSlicesY[1]+pagSlicesY[2]}; + if (m_bScrollDownHot) + OffsetRect(&rSrc,0,rSrc.bottom); + RECT rMargins={pagSlicesX[0],pagSlicesY[0],pagSlicesX[2],pagSlicesY[2]}; + MarginsBlit(hdc2,hdc,rSrc,rc,rMargins,bmpPager.bIs32); + + // arrow + SelectObject(hdc2,bmpPagerArrows.GetBitmap()); + int x=(rc.left+rc.right-pagArrowSize.cx)/2; + int y=(rc.top+rc.bottom-pagArrowSize.cy)/2; + if (bmpPagerArrows.bIs32) + { + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + AlphaBlend(hdc,x,y,pagArrowSize.cx,pagArrowSize.cy,hdc2,m_bScrollDownHot?pagArrowSize.cx:0,pagArrowSize.cy,pagArrowSize.cx,pagArrowSize.cy,func); + } + else + BitBlt(hdc,x,y,pagArrowSize.cx,pagArrowSize.cy,hdc2,m_bScrollDownHot?pagArrowSize.cx:0,pagArrowSize.cy,SRCCOPY); + SelectObject(hdc2,bmp0); + } + else + { + if (s_PagerTheme) + DrawThemeBackground(s_PagerTheme,hdc,SBP_ARROWBTN,(m_bScrollDownHot?ABS_DOWNHOT:ABS_DOWNHOVER),&rc,NULL); + else + DrawFrameControl(hdc,&rc,DFC_SCROLL,DFCS_SCROLLDOWN|DFCS_FLAT|(m_bScrollDownHot?DFCS_PUSHED:0)); + } + } + } + + if (index>=(int)m_Items.size()) break; + const MenuItem &item=m_Items[index]; + + RECT itemRect=item.itemRect; + // ignore offscreen items + if (m_ScrollHeight>0 && index=clipBottom) continue; + } + else if (m_SearchScrollCount>m_SearchScrollHeight && index>=m_OriginalCount) + { + if (index-m_OriginalCount=m_SearchScrollPos+m_SearchScrollHeight) + continue; + OffsetRect(&itemRect,0,-m_SearchScrollPos*(itemRect.bottom-itemRect.top)); + } + { + RECT q; + if (!IntersectRect(&q,&drawRect,&itemRect)) + continue; + } + + bool bHot=(index==m_HotItem || index==m_SubJumpItem || (m_HotItem==-1 && (index==m_Submenu || index==m_ContextItem))); + bool bSplit=false; + int stateLeft=0, stateRight=0; + bool bNew=!bHot && item.bNew && !(s_bWin7Style && item.id==MENU_PROGRAMS && s_MenuMode==MODE_PROGRAMS); + MenuSkin::TItemDrawType drawType=item.drawType; + if (!bNew) + { + if (drawType==MenuSkin::COLUMN1_NEW) + drawType=MenuSkin::COLUMN1_ITEM; + else if (drawType==MenuSkin::COLUMN2_NEW) + drawType=MenuSkin::COLUMN2_ITEM; + else if (drawType==MenuSkin::PROGRAMS_BUTTON_NEW) + drawType=MenuSkin::PROGRAMS_BUTTON; + else if (drawType==MenuSkin::PROGRAMS_CASCADING_NEW) + drawType=MenuSkin::PROGRAMS_CASCADING; + else if (drawType==MenuSkin::SUBMENU_NEW) + drawType=MenuSkin::SUBMENU_ITEM; + + if (!bHot && index==m_DropTargetIndex) + { + if (drawType==MenuSkin::COLUMN1_SPLIT) + drawType=MenuSkin::COLUMN1_ITEM; + if (drawType==MenuSkin::COLUMN2_SPLIT) + drawType=MenuSkin::COLUMN2_ITEM; + } + } + + if (item.id==MENU_SEARCH_BOX) + { + itemRect.left=itemRect.right-(itemRect.bottom-itemRect.top); + bHot=(index==m_HotItem && m_SearchState>=SEARCH_TEXT); + } + if (item.id==MENU_PROGRAMS_TREE) + bHot=false; + int splitX=itemRect.right; + const MenuSkin::ItemDrawSettings &settings=s_Skin.ItemSettings[drawType]; + int glowSize=s_Theme?settings.glowSize:0; + + if (bHot || bNew || item.id==MENU_SHUTDOWN_BUTTON || index==m_DropTargetIndex) + { + if (bHot || item.id==MENU_SHUTDOWN_BUTTON) + { + bSplit=(item.bSplit && (item.bFolder || item.jumpIndex>=0 || item.id==MENU_SEARCH_CATEGORY || item.id==MENU_SHUTDOWN_BUTTON)); + if (item.id==MENU_SHUTDOWN_BUTTON) + { + if (GetCapture()==m_hWnd) + { + if (index==m_ClickIndex && !m_bClickArrow && index==m_HotItem && !m_bHotArrow) + stateLeft=2; + else if (index==m_ClickIndex || index==m_Submenu || index==m_SubJumpItem) + stateLeft=1; + } + else if (index==m_HotItem || index==m_Submenu || index==m_SubJumpItem) + stateLeft=1; + + if (index==m_Submenu || index==m_SubJumpItem) + stateRight=2; + else if (GetCapture()==m_hWnd) + { + if (index==m_ClickIndex && m_bClickArrow && index==m_HotItem && m_bHotArrow) + stateRight=2; + } + else if (index==m_HotItem) + stateRight=1; + } + else + { + if ((index==m_HotItem && !m_bHotArrow) || index==m_ContextItem) + stateLeft=1; + if ((index==m_HotItem && m_bHotArrow) || index==m_Submenu || index==m_SubJumpItem || index==m_ContextItem) + stateRight=1; + } + splitX=itemRect.right-settings.arrPadding.cx-settings.arrPadding.cy-1; + if (item.jumpIndex>=0) + splitX-=s_Skin.Pin_bitmap_Size.cx; + else if (item.id==MENU_SEARCH_CATEGORY) + splitX-=s_Skin.More_bitmap_Size.cx; + else + splitX-=settings.arrSize.cx; + } + // draw selection background + if (bSplit && settings.bmpSelection.GetBitmap()) + { + int srcHeight=settings.selSlicesY[0]+settings.selSlicesY[1]+settings.selSlicesY[2]; + HGDIOBJ bmp0=SelectObject(hdc2,settings.bmpSelection.GetBitmap()); + { + // draw left half + RECT rSrc={0,0,settings.selSlicesX[0]+settings.selSlicesX[1]+settings.selSlicesX[2],srcHeight}; + OffsetRect(&rSrc,0,srcHeight*stateLeft); + RECT rMargins={settings.selSlicesX[0],settings.selSlicesY[0],settings.selSlicesX[2],settings.selSlicesY[2]}; + RECT itemRect2=itemRect; + itemRect2.right=splitX; + int w=itemRect2.right-itemRect2.left; + int h=itemRect2.bottom-itemRect2.top; + if (rMargins.left>w) rMargins.left=w; + if (rMargins.right>w) rMargins.right=w; + if (rMargins.top>h) rMargins.top=h; + if (rMargins.bottom>h) rMargins.bottom=h; + MarginsBlit(hdc2,hdc,rSrc,itemRect2,rMargins,settings.bmpSelection.bIs32); + } + { + // draw right half + RECT rSrc={settings.selSlicesX[0]+settings.selSlicesX[1]+settings.selSlicesX[2],0,0,srcHeight}; + OffsetRect(&rSrc,0,srcHeight*stateRight); + rSrc.right=rSrc.left+settings.selSlicesX[3]+settings.selSlicesX[4]+settings.selSlicesX[5]; + RECT rMargins={settings.selSlicesX[3],settings.selSlicesY[0],settings.selSlicesX[5],settings.selSlicesY[2]}; + RECT itemRect2=itemRect; + itemRect2.left=splitX; + int w=itemRect2.right-itemRect2.left; + int h=itemRect2.bottom-itemRect2.top; + if (rMargins.left>w) rMargins.left=w; + if (rMargins.right>w) rMargins.right=w; + if (rMargins.top>h) rMargins.top=h; + if (rMargins.bottom>h) rMargins.bottom=h; + MarginsBlit(hdc2,hdc,rSrc,itemRect2,rMargins,settings.bmpSelection.bIs32); + } + SelectObject(hdc2,bmp0); + } + else if (settings.bmpSelection.GetBitmap()) + { + HGDIOBJ bmp0=SelectObject(hdc2,settings.bmpSelection.GetBitmap()); + RECT rSrc={0,0,settings.selSlicesX[0]+settings.selSlicesX[1]+settings.selSlicesX[2],settings.selSlicesY[0]+settings.selSlicesY[1]+settings.selSlicesY[2]}; + { + RECT rMargins={settings.selSlicesX[0],settings.selSlicesY[0],settings.selSlicesX[2],settings.selSlicesY[2]}; + RECT itemRect2=itemRect; + if (bSplit) itemRect2.right=splitX; + int w=itemRect2.right-itemRect2.left; + int h=itemRect2.bottom-itemRect2.top; + if (rMargins.left>w) rMargins.left=w; + if (rMargins.right>w) rMargins.right=w; + if (rMargins.top>h) rMargins.top=h; + if (rMargins.bottom>h) rMargins.bottom=h; + MarginsBlit(hdc2,hdc,rSrc,itemRect2,rMargins,settings.bmpSelection.bIs32); + } + if (bSplit) + { + RECT rMargins={settings.selSlicesX[0],settings.selSlicesY[0],settings.selSlicesX[2],settings.selSlicesY[2]}; + RECT itemRect2=itemRect; + itemRect2.left=splitX; + int w=itemRect2.right-itemRect2.left; + int h=itemRect2.bottom-itemRect2.top; + if (rMargins.left>w) rMargins.left=w; + if (rMargins.right>w) rMargins.right=w; + if (rMargins.top>h) rMargins.top=h; + if (rMargins.bottom>h) rMargins.bottom=h; + MarginsBlit(hdc2,hdc,rSrc,itemRect2,rMargins,settings.bmpSelection.bIs32); + } + SelectObject(hdc2,bmp0); + } + else if (item.id==MENU_SHUTDOWN_BUTTON) + { + RECT itemRect2=itemRect; + itemRect2.right=splitX; + DrawEdge(hdc,&itemRect2,stateLeft==2?BDR_SUNKENOUTER:BDR_RAISEDINNER,BF_RECT|BF_MIDDLE); + if (bHot && m_Submenu==-1 && s_bKeyboardCues) + { + RECT focus=itemRect2; + if (s_Skin.Dpi>=144) + InflateRect(&focus,-3,-3); + else + InflateRect(&focus,-2,-2); + SetBkColor(hdc,0); + SetTextColor(hdc,0xFFFFFF); + DrawFocusRect(hdc,&focus); + } + itemRect2.left=itemRect2.right; + itemRect2.right=itemRect.right; + DrawEdge(hdc,&itemRect2,stateRight==2?BDR_SUNKENOUTER:BDR_RAISEDINNER,BF_RECT|BF_MIDDLE); + } + else + { + SetDCBrushColor(hdc,settings.bmpSelection.GetColor()); + SetDCPenColor(hdc,settings.bmpSelection.GetColor()); + if (bSplit) + { + if (stateLeft>0) + { + RECT itemRect2=itemRect; + itemRect2.right=splitX; + FillRect(hdc,&itemRect2,(HBRUSH)GetStockObject(DC_BRUSH)); + } + else + { + SelectObject(hdc,GetStockObject(DC_PEN)); + SelectObject(hdc,GetStockObject(NULL_BRUSH)); + Rectangle(hdc,itemRect.left,itemRect.top,splitX+1,itemRect.bottom); + } + if (stateRight>0) + { + RECT itemRect2=itemRect; + itemRect2.left=splitX+1; + FillRect(hdc,&itemRect2,(HBRUSH)GetStockObject(DC_BRUSH)); + } + else + { + SelectObject(hdc,GetStockObject(DC_PEN)); + SelectObject(hdc,GetStockObject(NULL_BRUSH)); + Rectangle(hdc,splitX-1,itemRect.top,itemRect.right,itemRect.bottom); + } + } + else + { + FillRect(hdc,&itemRect,(HBRUSH)GetStockObject(DC_BRUSH)); + } + } + } + + if (item.id==MENU_SEPARATOR || item.id==MENU_SEARCH_CATEGORY) + { + // draw separator + if (!item.bBlankSeparator && itemRect.bottom>itemRect.top) + { + RECT itemRect2=itemRect; + if (item.id==MENU_SEARCH_CATEGORY) + { + itemRect2.left+=settings.iconPadding.left; + if (item.bSplit) + itemRect2.right=splitX; + if (s_Skin.Search_arrow.GetBitmap()) + { + int x=itemRect2.left; + int y=(itemRect2.top+itemRect2.bottom-s_Skin.Search_arrow_size.cy)/2; + int v=(m_SearchCategoryHash==item.categoryHash?s_Skin.Search_arrow_size.cy:0); + HGDIOBJ bmp0=SelectObject(hdc2,s_Skin.Search_arrow.GetBitmap()); + if (s_Skin.Search_arrow.bIs32) + { + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + AlphaBlend(hdc,x,y,s_Skin.Search_arrow_size.cx,s_Skin.Search_arrow_size.cy,hdc2,0,v,s_Skin.Search_arrow_size.cx,s_Skin.Search_arrow_size.cy,func); + } + else + BitBlt(hdc,x,y,s_Skin.Search_arrow_size.cx,s_Skin.Search_arrow_size.cy,hdc2,0,v,SRCCOPY); + SelectObject(hdc2,bmp0); + itemRect2.left+=settings.iconPadding.right+s_Skin.Search_arrow_size.cx; + } + else + { + const POINT *sizes=s_Skin.GetArrowsBitmapSizes(); + int x=itemRect2.left; + int y=(itemRect2.top+itemRect2.bottom-sizes[6].y)/2; + HGDIOBJ bmp0=SelectObject(hdc2,GetArrowsBitmap(settings.arrColors[((bHot && (!bSplit || stateLeft>0))?1:0)])); + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + if (m_SearchCategoryHash==item.categoryHash) + { + SIZE s={sizes[5].y-sizes[5].x,sizes[6].y}; + AlphaBlend(hdc,x,y,s.cx,s.cy,hdc2,s_bRTL?sizes[6].x-sizes[5].y:sizes[5].x,0,s.cx,s.cy,func); + } + else + { + SIZE s={sizes[3].y-sizes[3].x,sizes[6].y}; + int dx=(sizes[5].y-sizes[5].x-s.cx+1)/2; + AlphaBlend(hdc,x+dx,y,s.cx,s.cy,hdc2,s_bRTL?sizes[6].x-sizes[4].y:sizes[3].x,0,s.cx,s.cy,func); + } + SelectObject(hdc2,bmp0); + itemRect2.left+=settings.iconPadding.right+sizes[5].y-sizes[5].x+1; + } + } + if (!item.name.IsEmpty()) + { + if (item.id==MENU_SEARCH_CATEGORY && !item.bSplit && item.categoryHash>=CSearchManager::CATEGORY_FILE && index==m_HotItem && m_bHotArrow) + SelectObject(hdc,s_Skin.Search_underline_font); + else + SelectObject(hdc,settings.font); + + COLORREF color=settings.textColors[(bHot && (!bSplit || stateLeft>0))?1:0]; + COLORREF shadowColor=settings.textShadowColors[(bHot && (!bSplit || stateLeft>0))?1:0]; + RECT rc={itemRect2.left+settings.textPadding.left,itemRect2.top+settings.textTopOffset+settings.textPadding.top-settings.textPadding.bottom, + itemRect2.right-settings.arrSize.cx-settings.arrPadding.cx-settings.arrPadding.cy-settings.textPadding.right,itemRect2.bottom-settings.textTopOffset}; + DWORD flags=DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS|DT_NOPREFIX; + if (s_Theme) + { + DTTOPTS opts={sizeof(opts),DTT_TEXTCOLOR}; + if (glowSize || settings.opacity==MenuSkin::OPACITY_FULLALPHA || settings.opacity==MenuSkin::OPACITY_FULLGLASS) + opts.dwFlags|=DTT_COMPOSITED; + if (glowSize) + { + opts.dwFlags|=DTT_GLOWSIZE; + opts.iGlowSize=glowSize; + } + if (shadowColor!=0xFFFFFFFF) + { + opts.crText=shadowColor; + RECT rc2=rc; + OffsetRect(&rc2,1,1); + DrawThemeTextEx(s_Theme,hdc,0,0,item.name,item.name.GetLength(),flags,&rc2,&opts); + } + opts.crText=color; + DrawThemeTextEx(s_Theme,hdc,0,0,item.name,item.name.GetLength(),flags,&rc,&opts); + } + else + { + if (shadowColor!=0xFFFFFFFF) + { + RECT rc2=rc; + OffsetRect(&rc2,1,1); + SetTextColor(hdc,shadowColor); + DrawText(hdc,item.name,item.name.GetLength(),&rc,flags); + } + + SetTextColor(hdc,color); + DrawText(hdc,item.name,item.name.GetLength(),&rc,flags); + } + SIZE size; + GetTextExtentPoint32(hdc,item.name,item.name.GetLength(),&size); + itemRect2.left=rc.left+size.cx+settings.textPadding.right; + } + if (itemRect2.left=30) + { + iconSize=20; + iconY=16; + if (s_bRTL) + icon--; + } + HGDIOBJ bmp0=SelectObject(hdc2,searchIcons.GetBitmap()); + RECT rSrc={0,0,iconSize,iconSize}; + RECT rDst=rSrc; + OffsetRect(&rSrc,iconSize*icon,iconY); + OffsetRect(&rDst,(itemRect.right+itemRect.left-iconSize)/2,(itemRect.bottom+itemRect.top-iconSize)/2); + RECT rMargins={0,0,0,0}; + MarginsBlit(hdc2,hdc,rSrc,rDst,rMargins,searchIcons.bIs32); + SelectObject(hdc2,bmp0); + continue; + } + + bool bNoIcon=!item.bInline && settings.iconSize==MenuSkin::ICON_SIZE_NONE; + SIZE iconSize; + if (settings.iconSize==MenuSkin::ICON_SIZE_SMALL) + iconSize.cx=iconSize.cy=g_ItemManager.SMALL_ICON_SIZE; + else if (settings.iconSize==MenuSkin::ICON_SIZE_LARGE) + iconSize.cx=iconSize.cy=g_ItemManager.LARGE_ICON_SIZE; + else if (settings.iconSize==MenuSkin::ICON_SIZE_PROGRAMS) + { + if (s_Skin.Programs_icon.GetBitmap()) + iconSize=s_Skin.Programs_icon_size; + else + { + iconSize.cx=s_Skin.ItemSettings[MenuSkin::COLUMN1_ITEM].iconSize==MenuSkin::ICON_SIZE_SMALL?g_ItemManager.SMALL_ICON_SIZE:g_ItemManager.LARGE_ICON_SIZE; + iconSize.cy=7; + } + } + else + iconSize.cx=iconSize.cy=0; + + // draw icon + if (drawType==MenuSkin::PROGRAMS_BUTTON || drawType==MenuSkin::PROGRAMS_BUTTON_NEW) + { + if (s_Skin.Programs_icon.GetBitmap()) + { + int iconX=itemRect.left+settings.iconPadding.left; + int iconY=itemRect.top+settings.iconPadding.top+settings.iconTopOffset; + const MenuBitmap &icon=bHot?s_Skin.Programs_icon_selected:s_Skin.Programs_icon; + HGDIOBJ bmp0=SelectObject(hdc2,icon.GetBitmap()); + if (icon.bIs32) + { + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + AlphaBlend(hdc,iconX,iconY,s_Skin.Programs_icon_size.cx,s_Skin.Programs_icon_size.cy,hdc2,0,s_MenuMode==MODE_PROGRAMS?s_Skin.Programs_icon_size.cy:0,s_Skin.Programs_icon_size.cx,s_Skin.Programs_icon_size.cy,func); + } + else + BitBlt(hdc,iconX,iconY,s_Skin.Programs_icon_size.cx,s_Skin.Programs_icon_size.cy,hdc2,0,s_MenuMode==MODE_PROGRAMS?s_Skin.Programs_icon_size.cy:0,SRCCOPY); + SelectObject(hdc2,bmp0); + } + else + { + const POINT *sizes=s_Skin.GetArrowsBitmapSizes(); + SIZE s={sizes[4].y-sizes[4].x,sizes[6].y}; + int x=itemRect.left+settings.arrPadding.cx; + int y=(itemRect.top+itemRect.bottom-s.cy)/2; + HGDIOBJ bmp0=SelectObject(hdc2,GetArrowsBitmap(settings.arrColors[bHot?1:0])); + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + if (s_MenuMode==MODE_PROGRAMS) + { + AlphaBlend(hdc,x,y,s.cx,s.cy,hdc2,s_bRTL?sizes[6].x-sizes[3].y:sizes[4].x,0,s.cx,s.cy,func); + } + else + { + AlphaBlend(hdc,x,y,s.cx,s.cy,hdc2,s_bRTL?sizes[6].x-sizes[4].y:sizes[3].x,0,s.cx,s.cy,func); + } + SelectObject(hdc2,bmp0); + } + } + else if (item.pItemInfo && !bNoIcon) + { + int iconX=itemRect.left+settings.iconPadding.left; + int iconY=itemRect.top+settings.iconPadding.top+settings.iconTopOffset; + if (settings.bmpIconFrame.GetBitmap()) + { + HGDIOBJ bmp0=SelectObject(hdc2,settings.bmpIconFrame.GetBitmap()); + RECT rSrc={0,0,settings.frameSlicesX[0]+settings.frameSlicesX[1]+settings.frameSlicesX[2],settings.frameSlicesY[0]+settings.frameSlicesY[1]+settings.frameSlicesY[2]}; + if (bHot) + OffsetRect(&rSrc,rSrc.right,0); + RECT rDst={iconX,iconY,iconX+iconSize.cx,iconY+iconSize.cy}; + InflateRect(&rDst,settings.iconFrameOffset.x,settings.iconFrameOffset.y); + RECT rMargins={settings.frameSlicesX[0],settings.frameSlicesY[0],settings.frameSlicesX[2],settings.frameSlicesY[2]}; + MarginsBlit(hdc2,hdc,rSrc,rDst,rMargins,settings.bmpIconFrame.bIs32); + SelectObject(hdc2,bmp0); + } + const CItemManager::IconInfo *pIcon=(settings.iconSize==MenuSkin::ICON_SIZE_LARGE)?item.pItemInfo->largeIcon:item.pItemInfo->smallIcon; + if (pIcon && pIcon->bitmap) + { + BITMAP info; + GetObject(pIcon->bitmap,sizeof(info),&info); + HGDIOBJ bmp0=SelectObject(hdc2,pIcon->bitmap); + if (bmp0) + { + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + AlphaBlend(hdc,iconX,iconY,iconSize.cx,iconSize.cy,hdc2,0,0,info.bmWidth,info.bmHeight,func); + SelectObject(hdc2,bmp0); + } + } + } + else if (item.id==MENU_SHUTDOWN_BUTTON && s_bHasUpdates && s_Skin.Shutdown_bitmap.GetBitmap()) + { + int iconX=itemRect.left+settings.iconPadding.left; + int iconY=itemRect.top+settings.iconPadding.top+settings.iconTopOffset; + if (stateLeft==2 && !settings.bmpSelection.GetBitmap()) + iconX++, iconY++; + HGDIOBJ bmp0=SelectObject(hdc2,s_Skin.Shutdown_bitmap.GetBitmap()); + if (s_Skin.Shutdown_bitmap.bIs32) + { + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + AlphaBlend(hdc,iconX,iconY,s_Skin.Shutdown_bitmap_Size.cx,s_Skin.Shutdown_bitmap_Size.cy,hdc2,0,0,s_Skin.Shutdown_bitmap_Size.cx,s_Skin.Shutdown_bitmap_Size.cy,func); + } + else + BitBlt(hdc,iconX,iconY,s_Skin.Shutdown_bitmap_Size.cx,s_Skin.Shutdown_bitmap_Size.cy,hdc2,0,0,SRCCOPY); + SelectObject(hdc2,bmp0); + } + + + // draw text + SelectObject(hdc,settings.font); + COLORREF color, shadowColor; + bool bHotColor=(bHot && !bSplit) || stateLeft>0; + if (item.id==MENU_EMPTY || item.id==MENU_EMPTY_TOP) + { + color=settings.textColors[bHotColor?3:2]; + shadowColor=settings.textShadowColors[bHotColor?3:2]; + } + else + { + color=settings.textColors[bHotColor?1:0]; + shadowColor=settings.textShadowColors[bHotColor?1:0]; + } + RECT rc={itemRect.left+settings.iconPadding.left+settings.iconPadding.right+settings.textPadding.left,itemRect.top+settings.textPadding.top, + itemRect.right-settings.arrPadding.cx-settings.arrPadding.cy-settings.textPadding.right,itemRect.bottom-settings.textPadding.bottom}; + if (item.id==MENU_SHUTDOWN_BUTTON) + { + if (s_bHasUpdates && s_Skin.Shutdown_bitmap.GetBitmap()) + rc.left+=s_Skin.Shutdown_bitmap_Size.cx-settings.iconPadding.left-settings.iconPadding.right; + if (stateLeft==2 && !settings.bmpSelection.GetBitmap()) + OffsetRect(&rc,1,1); + } + if (s_MenuMode==MODE_SEARCH && !m_bSubMenu && item.id==MENU_NO && index>=m_OriginalCount) + rc.right+=settings.arrPadding.cx+settings.arrPadding.cy; + else + rc.right-=(item.jumpIndex>=0)?s_Skin.Pin_bitmap_Size.cx:settings.arrSize.cx; + if (!bNoIcon) + rc.left+=iconSize.cx; + + DWORD flags=DT_END_ELLIPSIS; + if (item.id==MENU_NO || (item.id==MENU_RECENT && recentType!=RECENT_KEYS_DIGITS)) + flags|=DT_NOPREFIX; + else if (!s_bKeyboardCues) + flags|=DT_HIDEPREFIX; + + CString name; + if (drawType==MenuSkin::PROGRAMS_BUTTON || drawType==MenuSkin::PROGRAMS_BUTTON_NEW || drawType==MenuSkin::PROGRAMS_CASCADING || drawType==MenuSkin::PROGRAMS_CASCADING_NEW) + name=s_MenuMode==MODE_PROGRAMS?FindTranslation(L"Menu.Back",L"Back"):FindTranslation(L"Menu.AllPrograms",L"All Programs"); + else + name=item.name; + + if (settings.textMetrics.tmHeight*2<=rc.bottom-rc.top) + { + // if the height can fit two lines, see if we can make use of them + RECT rc2={0,0,rc.right-rc.left,0}; + DrawText(hdc,name,name.GetLength(),&rc2,flags|DT_WORDBREAK|DT_CALCRECT); + if (2*rc2.bottom>settings.textMetrics.tmHeight*3) + { + flags|=DT_EDITCONTROL|DT_WORDBREAK; + int d=rc.bottom-rc.top-settings.textMetrics.tmHeight*2; + rc.top+=d/2; + } + } + if (!(flags&DT_WORDBREAK)) + flags|=DT_VCENTER|DT_SINGLELINE; + + if (s_Theme) + { + DTTOPTS opts={sizeof(opts),DTT_TEXTCOLOR}; + if (glowSize || settings.opacity==MenuSkin::OPACITY_FULLALPHA || settings.opacity==MenuSkin::OPACITY_FULLGLASS) + opts.dwFlags|=DTT_COMPOSITED; + if (glowSize) + { + opts.dwFlags|=DTT_GLOWSIZE; + opts.iGlowSize=glowSize; + } + if (shadowColor!=0xFFFFFFFF) + { + opts.crText=shadowColor; + RECT rc2=rc; + OffsetRect(&rc2,1,1); + DrawThemeTextEx(s_Theme,hdc,0,0,name,name.GetLength(),flags,&rc2,&opts); + } + opts.crText=color; + DrawThemeTextEx(s_Theme,hdc,0,0,name,name.GetLength(),flags,&rc,&opts); + } + else + { + if (shadowColor!=0xFFFFFFFF) + { + RECT rc2=rc; + OffsetRect(&rc2,1,1); + SetTextColor(hdc,shadowColor); + DrawText(hdc,item.name,item.name.GetLength(),&rc,flags); + } + + SetTextColor(hdc,color); + DrawText(hdc,name,name.GetLength(),&rc,flags); + } + + if (item.bFolder && drawType!=MenuSkin::PROGRAMS_BUTTON && drawType!=MenuSkin::PROGRAMS_BUTTON_NEW) + { + // draw the sub-menu arrows + bool bHotArrow=(bHot && !bSplit) || stateRight>0; + if (settings.bmpArrow.GetBitmap()) + { + int x=itemRect.right-settings.arrPadding.cy-settings.arrSize.cx; + int y=(itemRect.top+itemRect.bottom-settings.arrSize.cy)/2; + if (stateRight==2 && !settings.bmpSelection.GetBitmap()) + x++, y++; + HGDIOBJ bmp0=SelectObject(hdc2,settings.bmpArrow.GetBitmap()); + if (settings.bmpArrow.bIs32) + { + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + AlphaBlend(hdc,x,y,settings.arrSize.cx,settings.arrSize.cy,hdc2,0,bHotArrow?settings.arrSize.cy:0,settings.arrSize.cx,settings.arrSize.cy,func); + } + else + { + BitBlt(hdc,x,y,settings.arrSize.cx,settings.arrSize.cy,hdc2,0,bHotArrow?settings.arrSize.cy:0,SRCCOPY); + } + SelectObject(hdc2,bmp0); + } + else + { + const POINT *sizes=s_Skin.GetArrowsBitmapSizes(); + SIZE s={sizes[3].y-sizes[3].x,sizes[6].y}; + int x=itemRect.right-settings.arrPadding.cy-s.cx; + int y=(itemRect.top+itemRect.bottom-s.cy)/2; + if (stateRight==2 && !settings.bmpSelection.GetBitmap()) + x++, y++; + HGDIOBJ bmp0=SelectObject(hdc2,GetArrowsBitmap(settings.arrColors[bHotArrow?1:0])); + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + AlphaBlend(hdc,x,y,s.cx,s.cy,hdc2,s_bRTL?sizes[6].x-sizes[4].y:sizes[3].x,0,s.cx,s.cy,func); + SelectObject(hdc2,bmp0); + } + } + else if (bHot && item.bSplit && item.jumpIndex>=0) + { + int x=itemRect.right-settings.arrPadding.cy-s_Skin.Pin_bitmap_Size.cx; + int y=(itemRect.top+itemRect.bottom-s_Skin.Pin_bitmap_Size.cy)/2; + HGDIOBJ bmp0=SelectObject(hdc2,s_Skin.Pin_bitmap.GetBitmap()); + bool bPinned=s_JumpList.groups[LOWORD(item.jumpIndex)].type==CJumpGroup::TYPE_PINNED; + if (s_Skin.Pin_bitmap.bIs32) + { + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + AlphaBlend(hdc,x,y,s_Skin.Pin_bitmap_Size.cx,s_Skin.Pin_bitmap_Size.cy,hdc2,bPinned?s_Skin.Pin_bitmap_Size.cx:0,stateRight==0?s_Skin.Pin_bitmap_Size.cy:0,s_Skin.Pin_bitmap_Size.cx,s_Skin.Pin_bitmap_Size.cy,func); + } + else + { + BitBlt(hdc,x,y,s_Skin.Pin_bitmap_Size.cx,s_Skin.Pin_bitmap_Size.cy,hdc2,bPinned?s_Skin.Pin_bitmap_Size.cx:0,stateRight==0?s_Skin.Pin_bitmap_Size.cy:0,SRCCOPY); + } + SelectObject(hdc2,bmp0); + } + } + + // draw vertical separators + if (m_bSubMenu && m_ColumnOffsets.size()>1) + { + if (bmpSeparatorV.GetBitmap()) + { + HGDIOBJ bmp0=SelectObject(hdc2,bmpSeparatorV.GetBitmap()); + RECT rSrc={0,0,sepWidth,sepSlicesY[0]+sepSlicesY[1]+sepSlicesY[2]}; + RECT rMargins={0,sepSlicesY[0],0,sepSlicesY[2]}; + for (size_t i=1;i>24; + a=remapAlpha[a]; + pixel=(a<<24)|(pixel&0xFFFFFF); + } + } + SelectObject(hdcPaint,bmp); + DeleteObject(bmp0); + } + if (m_SearchBox.m_hWnd && ((uMsg==WM_PRINTCLIENT && (lParam&PRF_CHILDREN)) || (uMsg==WM_PAINT && !m_bSearchDrawn))) + { + RECT rc; + GetWindowRect(&rc); + m_SearchBox.GetWindowRect(&rc); + ::MapWindowPoints(NULL,m_hWnd,(POINT*)&rc,2); + + // print the editbox to a new bitmap, and then blit to hdcPaint. printing directly into hdcPaint doesn't quite work with RTL + HDC hdcSearch=CreateCompatibleDC(hdcPaint); + HBITMAP bmpSearch=CreateCompatibleBitmap(hdcPaint,rc.right-rc.left,rc.bottom-rc.top); + HGDIOBJ bmp0=SelectObject(hdcSearch,bmpSearch); + + if (s_bRTL) SetLayout(hdcSearch,0); + m_SearchBox.SendMessage(WM_PRINTCLIENT,(WPARAM)hdcSearch,PRF_CLIENT); + if (s_bRTL) SetLayout(hdcSearch,LAYOUT_RTL); + BitBlt(hdcPaint,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,hdcSearch,0,0,SRCCOPY); + BufferedPaintSetAlpha(hBufferedPaint,&rc,255); + SelectObject(hdcSearch,bmp0); + DeleteDC(hdcSearch); + DeleteObject(bmpSearch); + } + if (m_pProgramsTree && s_MenuMode==MODE_PROGRAMS) + { + bool bDrawTree=(uMsg==WM_PAINT && (m_PaintOffset.x!=0 || m_PaintOffset.y!=0)) || (uMsg==WM_PRINTCLIENT && (lParam&PRF_CHILDREN)); + if (bDrawTree) + { + RECT rc; + m_pProgramsTree->GetWindowRect(&rc); + ::MapWindowPoints(NULL,m_hWnd,(POINT*)&rc,2); + SetViewportOrgEx(hdcPaint,rc.left,rc.top,NULL); + m_pProgramsTree->GetClientRect(&rc); + m_pProgramsTree->DrawTree(hdcPaint,rc); + m_pProgramsTree->Print(hdcPaint,PRF_NONCLIENT); + SetViewportOrgEx(hdcPaint,0,0,NULL); + } + } + if (opacity==MenuSkin::OPACITY_REGION && uMsg==WM_PRINTCLIENT && m_bSubMenu && s_Skin.Submenu_bitmap.bIsBitmap && !s_Skin.Submenu_bitmap.bIs32) + { + // if the bitmap is 24-bit, the alpha channel may be undefined + BufferedPaintSetAlpha(hBufferedPaint,&ps.rcPaint,255); + } + else + { + if (s_OldMenuState.mode==MODE_UNKNOWN) + { + if (opacity==MenuSkin::OPACITY_GLASS || opacity==MenuSkin::OPACITY_ALPHA || (opacity==MenuSkin::OPACITY_REGION && uMsg==WM_PRINTCLIENT)) + { + RECT rc; + IntersectRect(&rc,&ps.rcPaint,&m_rContent); + BufferedPaintSetAlpha(hBufferedPaint,&rc,255); + } + if (m_bTwoColumns && (opacity2==MenuSkin::OPACITY_GLASS || opacity2==MenuSkin::OPACITY_ALPHA || (opacity2==MenuSkin::OPACITY_REGION && uMsg==WM_PRINTCLIENT))) + { + RECT rc; + IntersectRect(&rc,&ps.rcPaint,&m_rContent2); + BufferedPaintSetAlpha(hBufferedPaint,&rc,255); + } + } + if (m_SearchIndex>=0 && s_bWin7Style && ((s_Skin.Search_background_jump.GetBitmap() && !s_Skin.Search_background_jump.bIs32) || !s_Skin.Search_background_jump.bIsBitmap)) + { + RECT padding; + if (s_MenuMode==MODE_SEARCH) + padding=s_Skin.Search_background_search_padding; + else if (s_MenuMode==MODE_JUMPLIST) + padding=s_Skin.Search_background_jump_padding; + else + padding=s_Skin.Search_background_padding; + RECT rcSearch; + rcSearch.left=m_rContent.right-padding.left; + rcSearch.right=m_rContent2.left+padding.right; + rcSearch.top=m_Items[m_SearchIndex].itemRect.top-s_Skin.Search_padding.top-padding.top; + rcSearch.bottom=m_rContent.bottom+padding.bottom; + RECT rc; + IntersectRect(&rc,&ps.rcPaint,&rcSearch); + BufferedPaintSetAlpha(hBufferedPaint,&rc,255); + } + } + EndBufferedPaint(hBufferedPaint,TRUE); + } + + if (uMsg!=WM_PRINTCLIENT) + EndPaint(&ps); + + return 0; +} + +static void FillSolidGlassRect( HDC hdc, LPCRECT pRect, COLORREF color ) +{ + BP_PAINTPARAMS paintParams={sizeof(paintParams)}; + paintParams.dwFlags=0; + HDC hdcPaint=NULL; + HPAINTBUFFER hBufferedPaint=BeginBufferedPaint(hdc,pRect,BPBF_TOPDOWNDIB,&paintParams,&hdcPaint); + if (hdcPaint) + { + SetDCBrushColor(hdcPaint,color); + FillRect(hdcPaint,pRect,(HBRUSH)GetStockObject(DC_BRUSH)); + BufferedPaintSetAlpha(hBufferedPaint,pRect,255); + EndBufferedPaint(hBufferedPaint,TRUE); + } +} + +void CProgramsTree::DrawTree( HDC hdc, const RECT &drawRect ) +{ + RECT rcClient; + GetClientRect(&rcClient); + { + RECT rc; + TreeView_GetItemRect(m_hWnd,TreeView_GetRoot(m_hWnd),&rc,TRUE); + m_MinX=rc.left-m_RootX; // detect when the tree auto-scrolls + + // find the widest of the visible elements + m_MaxX=rcClient.right; + int maxy=rcClient.bottom; + for (HTREEITEM hItem=TreeView_GetFirstVisible(m_hWnd);hItem;hItem=TreeView_GetNextVisible(m_hWnd,hItem)) + { + TreeView_GetItemRect(m_hWnd,hItem,&rc,TRUE); + if (m_MaxX=maxy) + break; + } + } + + BP_PAINTPARAMS paintParams={sizeof(paintParams)}; + HDC hdcPaint=NULL; + HPAINTBUFFER hBufferedPaint=BeginBufferedPaint(hdc,&drawRect,BPBF_TOPDOWNDIB,&paintParams,&hdcPaint); + if (hdcPaint) + { + HDC hsrc=CreateCompatibleDC(hdcPaint); + const MenuSkin &skin=CMenuContainer::s_Skin; + int alpha; + if (skin.Programs_background==0) + { + RECT bmpRect=drawRect; + ::MapWindowPoints(m_hWnd,m_pOwner->m_hWnd,(POINT*)&bmpRect,2); + HGDIOBJ bmp0=SelectObject(hsrc,m_pOwner->m_Bitmap); + BitBlt(hdcPaint,drawRect.left,drawRect.top,drawRect.right-drawRect.left,drawRect.bottom-drawRect.top,hsrc,bmpRect.left,bmpRect.top,SRCCOPY); + SelectObject(hsrc,bmp0); + alpha=(skin.Main_opacity==MenuSkin::OPACITY_ALPHA || skin.Main_opacity==MenuSkin::OPACITY_GLASS)?255:0; + } + else + { + SetDCBrushColor(hdcPaint,skin.Programs_background&0xFFFFFF); + FillRect(hdcPaint,&drawRect,(HBRUSH)GetStockObject(DC_BRUSH)); + alpha=skin.Programs_background>>24; + if (alpha<255) + { + if (skin.Main_FakeGlass) + alpha=(unsigned char)(255*pow(alpha/255.f,0.2f)); + BufferedPaintSetAlpha(hBufferedPaint,&drawRect,alpha); + } + } + + SelectObject(hdcPaint,GetFont()); + HTREEITEM hSelection=TreeView_GetSelection(m_hWnd); + HTREEITEM hHilight=TreeView_GetDropHilight(m_hWnd); + HWND focus=GetFocus(); + for (HTREEITEM hItem=TreeView_GetFirstVisible(m_hWnd);hItem;hItem=TreeView_GetNextVisible(m_hWnd,hItem)) + { + RECT itemRect; + TreeView_GetItemRect(m_hWnd,hItem,&itemRect,TRUE); + if (itemRect.top>=drawRect.bottom) + break; + bool bHot=((hItem==hSelection && m_DropLocation==DROP_NOWHERE) || hItem==hHilight) && (m_pOwner->m_HotItem==m_pOwner->m_ProgramTreeIndex || focus==m_hWnd); + if (itemRect.bottom>drawRect.top) + DrawTreeItem(hdcPaint,hsrc,hItem,itemRect,bHot); + } + RECT rc; + if (GetInsertRect(rc)) + { + const POINT *sizes=skin.GetArrowsBitmapSizes(); + HGDIOBJ bmp0=SelectObject(hsrc,CMenuContainer::GetArrowsBitmap(CMenuContainer::s_Skin.ItemSettings[MenuSkin::PROGRAMS_TREE_ITEM].textColors[0])); + RECT rSrc={CMenuContainer::s_bRTL?sizes[6].x-sizes[2].y:sizes[0].x,0,CMenuContainer::s_bRTL?sizes[6].x-sizes[0].x:sizes[2].y,sizes[1].y}; + RECT rMargins={sizes[0].y-sizes[0].x,0,sizes[2].y-sizes[2].x,0}; + MarginsBlit(hsrc,hdcPaint,rSrc,rc,rMargins,true); + SelectObject(hsrc,bmp0); + } + DeleteDC(hsrc); + + if (alpha==255) + BufferedPaintSetAlpha(hBufferedPaint,&drawRect,alpha); + EndBufferedPaint(hBufferedPaint,TRUE); + } +} + +void CProgramsTree::DrawTreeItem( HDC hdc, HDC hsrc, HTREEITEM hItem, const RECT &itemRect, bool bHot ) const +{ + TVITEM item={TVIF_PARAM|TVIF_STATE,hItem,0,TVIS_SELECTED}; + TreeView_GetItem(m_hWnd,&item); + + const MenuSkin &skin=CMenuContainer::s_Skin; + const CTreeItem *pItem=(CTreeItem*)item.lParam; + COLORREF textColor; + COLORREF shadowColor; + MenuBitmap bmp; + const int *slicesX, *slicesY; + RECT iconPadding; + int iconTopOffset, textTopOffset; + int glowSize; + if (bHot) + { + // selected + const MenuSkin::ItemDrawSettings &settings=skin.ItemSettings[MenuSkin::PROGRAMS_TREE_ITEM]; + bmp=settings.bmpSelection; + slicesX=settings.selSlicesX; + slicesY=settings.selSlicesY; + iconPadding=settings.iconPadding; + iconTopOffset=settings.iconTopOffset+settings.iconPadding.top; + textTopOffset=settings.textTopOffset+settings.textPadding.top; + textColor=settings.textColors[pItem->bEmpty?3:1]; + shadowColor=settings.textShadowColors[bHot?1:0]; + glowSize=settings.glowSize; + } + else if (pItem->bNew) + { + // highlighted + const MenuSkin::ItemDrawSettings &settings=skin.ItemSettings[MenuSkin::PROGRAMS_TREE_NEW]; + bmp=settings.bmpSelection; + slicesX=settings.selSlicesX; + slicesY=settings.selSlicesY; + iconPadding=settings.iconPadding; + iconTopOffset=settings.iconTopOffset+settings.iconPadding.top; + textTopOffset=settings.textTopOffset+settings.textPadding.top; + textColor=settings.textColors[pItem->bEmpty?2:0]; + shadowColor=settings.textShadowColors[bHot?1:0]; + glowSize=settings.glowSize; + } + else + { + // not selected + bmp=skin.Programs_background; + const MenuSkin::ItemDrawSettings &settings=skin.ItemSettings[MenuSkin::PROGRAMS_TREE_ITEM]; + iconPadding=settings.iconPadding; + iconTopOffset=settings.iconTopOffset+settings.iconPadding.top; + textTopOffset=settings.textTopOffset+settings.textPadding.top; + textColor=settings.textColors[pItem->bEmpty?2:0]; + shadowColor=settings.textShadowColors[bHot?1:0]; + glowSize=settings.glowSize; + } + + RECT rc=itemRect; + int left=rc.left; + rc.left=m_MinX; + rc.right=m_MaxX; + + if (bHot || pItem->bNew) + { + // draw background + if (bmp.bIsBitmap) + { + HGDIOBJ bmp0=SelectObject(hsrc,bmp.GetBitmap()); + RECT rSrc={0,0,slicesX[0]+slicesX[1]+slicesX[2],slicesY[0]+slicesY[1]+slicesY[2]}; + RECT rMargins={slicesX[0],slicesY[0],slicesX[2],slicesY[2]}; + MarginsBlit(hsrc,hdc,rSrc,rc,rMargins,bmp.bIs32); + SelectObject(hsrc,bmp0); + } + else + { + SetDCBrushColor(hdc,bmp.GetColor()); + FillRect(hdc,&rc,(HBRUSH)GetStockObject(DC_BRUSH)); + } + } + + // draw icon + rc.left=left; + int iconSize=CItemManager::SMALL_ICON_SIZE; + int x=rc.left-iconSize-3-iconPadding.right; + int y=rc.top+iconTopOffset; + + if (pItem->pItemInfo1 && pItem->pItemInfo1->smallIcon) + { + HGDIOBJ bmp0=SelectObject(hsrc,pItem->pItemInfo1->smallIcon->bitmap); + BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA}; + AlphaBlend(hdc,x,y,iconSize,iconSize,hsrc,0,0,iconSize,iconSize,func); + SelectObject(hsrc,bmp0); + } + + // draw text + rc.top+=textTopOffset; + + if (m_TreeTheme) + { + DTTOPTS opts={sizeof(opts),DTT_TEXTCOLOR}; + if (glowSize || skin.ItemSettings[MenuSkin::PROGRAMS_TREE_ITEM].opacity==MenuSkin::OPACITY_FULLALPHA || skin.ItemSettings[MenuSkin::PROGRAMS_TREE_ITEM].opacity==MenuSkin::OPACITY_FULLGLASS) + opts.dwFlags|=DTT_COMPOSITED; + if (glowSize) + { + opts.dwFlags|=DTT_GLOWSIZE; + opts.iGlowSize=glowSize; + } + if (shadowColor!=0xFFFFFFFF) + { + opts.crText=shadowColor; + RECT rc2=rc; + OffsetRect(&rc2,1,1); + DrawThemeTextEx(m_TreeTheme,hdc,0,0,pItem->name,pItem->name.GetLength(),DT_SINGLELINE|DT_NOPREFIX,&rc2,&opts); + } + opts.crText=textColor; + DrawThemeTextEx(m_TreeTheme,hdc,0,0,pItem->name,pItem->name.GetLength(),DT_SINGLELINE|DT_NOPREFIX,&rc,&opts); + } + else + { + SetBkMode(hdc,TRANSPARENT); + if (shadowColor!=0xFFFFFFFF) + { + RECT rc2=rc; + OffsetRect(&rc2,1,1); + SetTextColor(hdc,shadowColor); + DrawText(hdc,pItem->name,pItem->name.GetLength(),&rc,DT_SINGLELINE|DT_NOPREFIX); + } + + SetTextColor(hdc,textColor); + DrawText(hdc,pItem->name,pItem->name.GetLength(),&rc,DT_SINGLELINE|DT_NOPREFIX); + } +} + +void CProgramsTree::DrawScrollbarBackground( HDC hdc, int iPartId, int iStateId, LPCRECT pRect ) +{ + const MenuSkin &skin=CMenuContainer::s_Skin; + HDC hSrc=CreateCompatibleDC(hdc); + if (iPartId==SBP_ARROWBTN) + { + // draw arrows + int state=0; + if (iStateId==ABS_UPHOT || iStateId==ABS_DOWNHOT) + state=1; + else if (iStateId==ABS_UPPRESSED || iStateId==ABS_DOWNPRESSED) + state=2; + + HGDIOBJ bmp0=GetCurrentObject(hSrc,OBJ_BITMAP); + if (skin.Scrollbar_button.bIsBitmap) + { + SelectObject(hSrc,skin.Scrollbar_button.GetBitmap()); + int w=skin.Scrollbar_button_slices_X[0]+skin.Scrollbar_button_slices_X[1]+skin.Scrollbar_button_slices_X[2]; + int h=skin.Scrollbar_button_slices_Y[0]+skin.Scrollbar_button_slices_Y[1]+skin.Scrollbar_button_slices_Y[2]; + RECT rSrc={0,h*state,w,h*(state+1)}; + RECT rMargins={skin.Scrollbar_button_slices_X[0],skin.Scrollbar_button_slices_Y[0],skin.Scrollbar_button_slices_X[2],skin.Scrollbar_button_slices_Y[2]}; + MarginsBlit(hSrc,hdc,rSrc,*pRect,rMargins,false); + } + else + { + FillSolidGlassRect(hdc,pRect,skin.Scrollbar_button.GetColor()); + } + + int arrowOffset=0; + if ((iStateId>=ABS_DOWNNORMAL && iStateId<=ABS_DOWNDISABLED) || iStateId==ABS_DOWNHOVER) + arrowOffset=skin.Scrollbar_arrows_size.cx; + + SelectObject(hSrc,skin.Scrollbar_arrows.GetBitmap()); + int x=(pRect->right+pRect->left-skin.Scrollbar_arrows_size.cx)/2; + int y=(pRect->bottom+pRect->top-skin.Scrollbar_arrows_size.cy)/2; + StretchBlt2(hdc,x,y,skin.Scrollbar_arrows_size.cx,skin.Scrollbar_arrows_size.cy,hSrc,arrowOffset,skin.Scrollbar_arrows_size.cy*state,skin.Scrollbar_arrows_size.cx,skin.Scrollbar_arrows_size.cy,true); + SelectObject(hSrc,bmp0); + } + else if (iPartId==SBP_LOWERTRACKVERT || iPartId==SBP_UPPERTRACKVERT) + { + // draw background + if (skin.Scrollbar_background.bIsBitmap) + { + int state=0; + if (iStateId==SCRBS_HOT) + state=1; + else if (iStateId==SCRBS_PRESSED) + state=2; + + HGDIOBJ bmp0=SelectObject(hSrc,skin.Scrollbar_background.GetBitmap()); + int w=skin.Scrollbar_background_slices_X[0]+skin.Scrollbar_background_slices_X[1]+skin.Scrollbar_background_slices_X[2]; + int h=skin.Scrollbar_background_slices_Y[0]+skin.Scrollbar_background_slices_Y[1]+skin.Scrollbar_background_slices_Y[2]; + RECT rSrc={0,h*state,w,h*(state+1)}; + RECT rMargins={skin.Scrollbar_background_slices_X[0],skin.Scrollbar_background_slices_Y[0],skin.Scrollbar_background_slices_X[2],skin.Scrollbar_background_slices_Y[2]}; + MarginsBlit(hSrc,hdc,rSrc,*pRect,rMargins,false); + SelectObject(hSrc,bmp0); + } + else + { + FillSolidGlassRect(hdc,pRect,skin.Scrollbar_background.GetColor()); + } + } + else if (iPartId==SBP_THUMBBTNVERT) + { + // draw thumb + if (skin.Scrollbar_thumb.bIsBitmap) + { + int state=0; + if (iStateId==SCRBS_HOT) + state=1; + else if (iStateId==SCRBS_PRESSED) + state=2; + + HGDIOBJ bmp0=SelectObject(hSrc,skin.Scrollbar_thumb.GetBitmap()); + int w=skin.Scrollbar_thumb_slices_X[0]+skin.Scrollbar_thumb_slices_X[1]+skin.Scrollbar_thumb_slices_X[2]; + int h=skin.Scrollbar_thumb_slices_Y[0]+skin.Scrollbar_thumb_slices_Y[1]+skin.Scrollbar_thumb_slices_Y[2]; + RECT rSrc={0,h*state,w,h*(state+1)}; + RECT rMargins={skin.Scrollbar_thumb_slices_X[0],skin.Scrollbar_thumb_slices_Y[0],skin.Scrollbar_thumb_slices_X[2],skin.Scrollbar_thumb_slices_Y[2]}; + MarginsBlit(hSrc,hdc,rSrc,*pRect,rMargins,false); + } + else + { + FillSolidGlassRect(hdc,pRect,skin.Scrollbar_thumb.GetColor()); + } + } + else if (iPartId==SBP_GRIPPERVERT) + { + // draw gripper + if (skin.Scrollbar_gripper.GetBitmap()) + { + int state=0; + if (iStateId==SCRBS_HOT) + state=1; + else if (iStateId==SCRBS_PRESSED) + state=2; + + HGDIOBJ bmp0=SelectObject(hSrc,skin.Scrollbar_gripper.GetBitmap()); + int x=(pRect->right+pRect->left-skin.Scrollbar_gripper_size.cx)/2; + int y=(pRect->bottom+pRect->top-skin.Scrollbar_gripper_size.cy)/2; + StretchBlt2(hdc,x,y,skin.Scrollbar_gripper_size.cx,skin.Scrollbar_gripper_size.cy,hSrc,0,skin.Scrollbar_gripper_size.cy*state,skin.Scrollbar_gripper_size.cx,skin.Scrollbar_gripper_size.cy,true); + SelectObject(hSrc,bmp0); + } + } + DeleteDC(hSrc); +} + +void CMenuContainer::AnimateMenu( int flags, int speed, const RECT &rect ) +{ + RECT clipRect=m_bSubMenu?s_MenuLimits:s_MainMenuLimits; + + bool bUserPic=(!m_bSubMenu && s_bWin7Style && s_UserPicture.m_hWnd && s_UserPictureRect.top0) + { + // fade in + SetWindowLong(GWL_EXSTYLE,GetWindowLong(GWL_EXSTYLE)|WS_EX_LAYERED); + SetWindowPos((flags&AW_TOPMOST)?HWND_TOPMOST:HWND_TOP,&rect,SWP_SHOWWINDOW|((flags&AW_ACTIVATE)?0:SWP_NOACTIVATE)); + if (!m_bSubMenu && s_TaskBar && s_bBehindTaskbar) + { + // position the start button on top + if (s_StartButton) + ::SetWindowPos(s_StartButton,(flags&AW_TOPMOST)?HWND_TOPMOST:HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); + // position the start menu behind the taskbar + SetWindowPos(s_TaskBar,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); + } + if (bUserPic) + { + s_UserPicture.Update(0); + s_UserPicture.SetWindowPos(NULL,&s_UserPictureRect,SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW); + } + + // animate + int time0=GetTickCount(); + while (true) + { + int dt=GetTickCount()-time0; + if (dt>speed) break; + float f=dt/(float)speed; + int alpha=(int)(f*255); + SetLayeredWindowAttributes(m_hWnd,0,(BYTE)alpha,LWA_ALPHA); + RedrawWindow(); + if (bUserPic) + s_UserPicture.Update(alpha); + } + + SetWindowLong(GWL_EXSTYLE,GetWindowLong(GWL_EXSTYLE)&~WS_EX_LAYERED); + RedrawWindow(); + } + else if ((flags&AW_SLIDE) && speed>0) + { + // slide in + HRGN rgn=CreateRectRgn(0,0,0,0); + if (!SetWindowRgn(rgn,FALSE)) // set empty region + DeleteObject(rgn); + SetWindowPos((flags&AW_TOPMOST)?HWND_TOPMOST:HWND_TOP,&rect,SWP_SHOWWINDOW|((flags&AW_ACTIVATE)?0:SWP_NOACTIVATE)); + if (!m_bSubMenu && s_TaskBar && s_bBehindTaskbar) + { + // position the start button on top + if (s_StartButton) + ::SetWindowPos(s_StartButton,(flags&AW_TOPMOST)?HWND_TOPMOST:HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); + // position the start menu behind the taskbar + SetWindowPos(s_TaskBar,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); + } + if (bUserPic) + { + s_UserPicture.Update(0); + s_UserPicture.SetWindowPos(NULL,&s_UserPictureRect,SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW); + } + if (m_pProgramsTree && s_MenuMode==MODE_PROGRAMS) + m_pProgramsTree->ShowWindow(SW_HIDE); + HRGN rgn0=NULL; + if (m_Region) + { + int rgnSize=GetRegionData(m_Region,0,NULL); + std::vector buf(rgnSize); + GetRegionData(m_Region,rgnSize,(RGNDATA*)&buf[0]); + XFORM xform={1,0,0,1}; + if (s_bRTL) + { + // mirror the region (again) + xform.eM11=-1; + xform.eDx=(float)(m_rMenu.right+m_rMenu.left-m_BitmapOffset); + } + rgn0=ExtCreateRegion(&xform,rgnSize,(RGNDATA*)&buf[0]); + } + + // animate + int time0=GetTickCount(); + int movex=0, movey=0; + if (flags&AW_HOR_POSITIVE) + { + movex=rect.right-rect.left; + clipRect.left=rect.left; + } + else if (flags&AW_HOR_NEGATIVE) + { + movex=rect.left-rect.right; + clipRect.right=rect.right; + } + else if (flags&AW_VER_POSITIVE) + { + movey=rect.bottom-rect.top; + clipRect.top=rect.top; + } + else + { + movey=rect.top-rect.bottom; + clipRect.bottom=rect.bottom; + } + + HRGN clipRgn=CreateRectRgn(clipRect.left-rect.left,clipRect.top-rect.top,clipRect.right-rect.left,clipRect.bottom-rect.top); // clip region in window space + while (true) + { + int dt=GetTickCount()-time0; + if (dt>speed) break; + float f=1-dt/(float)speed; + f=powf(f,5); + int dx=(int)(movex*f); + int dy=(int)(movey*f); + if (dx==0 && dy==0) break; + m_PaintOffset.x=-dx; + m_PaintOffset.y=-dy; + + // calculate region + HRGN wndRgn=CreateRectRgn(0,0,rect.right-rect.left,rect.bottom-rect.top); // window region + if (rgn0) + CombineRgn(wndRgn,rgn0,NULL,RGN_COPY); + OffsetRgn(wndRgn,-dx,-dy); + HRGN rgn=CreateRectRgn(0,0,0,0); + CombineRgn(rgn,clipRgn,wndRgn,RGN_AND); // clipped window region + if (!SetWindowRgn(rgn,FALSE)) + DeleteObject(rgn); + DeleteObject(wndRgn); + RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); + + // move user pic + if (bUserPic) + { + POINT pos={s_UserPictureRect.left-dx,s_UserPictureRect.top-dy}; + s_UserPicture.UpdatePartial(pos,&clipRect); + } + } + DeleteObject(clipRgn); + + m_PaintOffset.x=m_PaintOffset.y=0; + if (!SetWindowRgn(rgn0,FALSE) && rgn0) + DeleteObject(rgn0); + if (m_pProgramsTree && s_MenuMode==MODE_PROGRAMS) + m_pProgramsTree->ShowWindow(SW_SHOW); + RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); + } + else + { + // no animation + SetWindowPos((flags&AW_TOPMOST)?HWND_TOPMOST:HWND_TOP,&rect,SWP_SHOWWINDOW|((flags&AW_ACTIVATE)?0:SWP_NOACTIVATE)); + RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); + if (bUserPic) + { + s_UserPicture.Update(255); + s_UserPicture.SetWindowPos(NULL,&s_UserPictureRect,SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW); + } + } + + if (m_SearchBox.m_hWnd) + m_SearchBox.ShowWindow(SW_SHOW); + + if (bUserPic) + { + POINT pos={s_UserPictureRect.left,s_UserPictureRect.top}; + s_UserPicture.UpdatePartial(pos,NULL); + } +} diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MetroLinkManager.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MetroLinkManager.cpp new file mode 100644 index 0000000..306151b --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/MetroLinkManager.cpp @@ -0,0 +1,383 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "MetroLinkManager.h" +#include "ItemManager.h" +#include "LogManager.h" +#include "FNVHash.h" +#include "ResourceHelper.h" +#include "Translations.h" +#include +#include + +PROPERTYKEY PKEY_MetroAppLink={{0x9F4C2855, 0x9F79, 0x4B39, {0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3}}, 10}; // pidl +PROPERTYKEY PKEY_MetroAppLauncher={{0x9F4C2855, 0x9F79, 0x4B39, {0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3}}, 14}; // =1 for metro apps +PROPERTYKEY PKEY_MetroIconColor={{0x86D40B4D, 0x9069, 0x443C, {0x81, 0x9A, 0x2A, 0x54, 0x09, 0x0D, 0xCC, 0xEC}}, 4}; +PROPERTYKEY PKEY_MetroPackageName={{0x9F4C2855, 0x9F79, 0x4B39, {0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3}}, 21}; +PROPERTYKEY PKEY_MetroPackagePath={{0x9F4C2855, 0x9F79, 0x4B39, {0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3}}, 15}; +PROPERTYKEY PKEY_AppUserModel_ParentID={{0x9F4C2855, 0x9F79, 0x4B39, {0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3}}, 19}; // non-empty for content tiles +PROPERTYKEY PKEY_AppUserModel_InstalledBy={{0x9F4C2855, 0x9F79, 0x4B39, {0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3}}, 18}; +PROPERTYKEY PKEY_AppUserModel_IsDualMode={{0x9F4C2855, 0x9F79, 0x4B39, {0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3}}, 11}; +PROPERTYKEY PKEY_Launcher_AppState={{0x0ded77b3, 0xc614, 0x456c, {0xae, 0x5b, 0x28, 0x5b, 0x38, 0xd7, 0xb0, 0x1b}}, 7}; + +// FOLDERID_AppsFolder is defined in the 8.0 SDK, but we don't want to require it +KNOWNFOLDERID FOLDERID_AppsFolder2={0x1E87508D,0x89C2,0x42F0,{0x8A,0x7E,0x64,0x5A,0x0F,0x50,0xCA,0x58}}; // similar to shell:::{4234d49b-0245-4df3-b780-3893943456e1} +GUID CLSID_PinExt={0x90AA3A4E,0x1CBA,0x4233,{0xB8,0xBB,0x53,0x57,0x73,0xD4,0x84,0x49}}; +const wchar_t *MetroAppClassId=L"Launcher.ImmersiveApplication"; + +// Returns a list of links for all metro apps +void GetMetroLinks( std::vector &links, bool bLog, std::vector *pNonApps10 ) +{ + LOG_MENU(LOG_APPS,L"Collect Metro Links (start)"); + if (bLog && !(g_LogCategories&LOG_APPS)) + bLog=false; + CComPtr pApps; + if (FAILED(ShGetKnownFolderItem(FOLDERID_AppsFolder2,&pApps))) + return; + CComPtr pEnum; + pApps->BindToHandler(NULL,BHID_EnumItems,IID_IEnumShellItems,(void**)&pEnum); + + CComPtr pChild; + while (pEnum && (pChild=NULL,pEnum->Next(1,&pChild,NULL)==S_OK)) + { + if (bLog) + { + CComString pName; + pChild->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName); + LOG_MENU(LOG_APPS,L"App: %s",pName); + } + CComPtr pStore; + if (FAILED(pChild->BindToHandler(NULL,BHID_PropertyStore,IID_IPropertyStore,(void**)&pStore))) + { + LOG_MENU(LOG_APPS,L" No Store"); + continue; + } + PROPVARIANT val; + PropVariantInit(&val); + bool bNonApp=false; + if (FAILED(pStore->GetValue(PKEY_MetroAppLauncher,&val))) + { + LOG_MENU(LOG_APPS,L" No launcher"); + bNonApp=true; + } + else + { + if ((val.vt!=VT_I4 && val.vt!=VT_UI4) || !val.intVal) + { + LOG_MENU(LOG_APPS,L" No launcher: %d",val.vt); + bNonApp=true; + } + PropVariantClear(&val); + } + if (GetWinVersion()>=WIN_VER_WIN10) + { + PIDLIST_ABSOLUTE pidl; + if (!bNonApp && SUCCEEDED(SHGetIDListFromObject(pChild,&pidl))) + { + links.resize(links.size()+1); + MetroLink &link=*links.rbegin(); + link.pidl.Attach(pidl); + link.appid=GetPropertyStoreString(pStore,PKEY_AppUserModel_ID); + link.pItem=pChild; + } + else + bNonApp=true; + if (bNonApp && pNonApps10) + pNonApps10->push_back(GetPropertyStoreString(pStore,PKEY_AppUserModel_ID)); + continue; + } + if (bNonApp) + continue; + if (FAILED(pStore->GetValue(PKEY_MetroAppLink,&val))) + { + LOG_MENU(LOG_APPS,L" No link"); + continue; + } + if (val.vt!=(VT_VECTOR|VT_UI1) || !val.caub.pElems) + { + LOG_MENU(LOG_APPS,L" No link: %d",val.vt); + PropVariantClear(&val); + continue; + } + PIDLIST_ABSOLUTE pidl=ILCloneFull((PIDLIST_ABSOLUTE)val.caub.pElems); + PropVariantClear(&val); + links.resize(links.size()+1); + MetroLink &link=*links.rbegin(); + link.pidl.Attach(pidl); + SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&link.pItem); + if (bLog && link.pItem) + { + CComString pName; + link.pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName); + LOG_MENU(LOG_APPS,L" Link: %s",pName); + } + } + LOG_MENU(LOG_APPS,L"Collect Metro Links (end)"); +} + +void ExecuteMetroLink( const CItemManager::ItemInfo *pInfo ) +{ + SHELLEXECUTEINFO execute={sizeof(execute),SEE_MASK_CLASSNAME|SEE_MASK_INVOKEIDLIST|SEE_MASK_FLAG_LOG_USAGE|SEE_MASK_FLAG_NO_UI}; + wchar_t path[_MAX_PATH]; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + Strcpy(path,_countof(path),pInfo->GetPath()); + } + execute.lpFile=path; + execute.nShow=SW_SHOWNORMAL; + execute.lpClass=MetroAppClassId; + BOOL res=ShellExecuteEx(&execute); + LOG_MENU(LOG_EXECUTE,L"ExecuteMetroLink: 0x%08X 0x%08X",res?0:GetLastError(),(int)execute.hInstApp); + + // create UserAssist entry + { + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced")!=ERROR_SUCCESS) + return; + DWORD val; + if (regKey.QueryDWORDValue(L"Start_TrackProgs",val)==ERROR_SUCCESS && !val) + return; + } + + CRegKey regKeyLink; + if (regKeyLink.Open(HKEY_CURRENT_USER,USERASSIST_LINKS_KEY,KEY_READ|KEY_WRITE)!=ERROR_SUCCESS) + return; + + EncodeUserAssistPath(path); + EncodeRot13(path); + UserAssistData data; + DWORD size=sizeof(data); + if (regKeyLink.QueryBinaryValue(path,&data,&size)!=ERROR_SUCCESS) + memset(&data,0,sizeof(data)); + GetSystemTimeAsFileTime(&data.timestamp); + data.count++; + regKeyLink.SetBinaryValue(path,&data,sizeof(data)); +} + +/* +void ExecutePCSettings( void ) +{ + const wchar_t *appid=L"windows.immersivecontrolpanel_cw5n1h2txyewy!microsoft.windows.immersivecontrolpanel"; + CComPtr pItem; + if (SUCCEEDED(SHCreateItemInKnownFolder(FOLDERID_AppsFolder2,0,appid,IID_IShellItem,(void**)&pItem))) + { + CAbsolutePidl pidl; + if (SUCCEEDED(SHGetIDListFromObject(pItem,&pidl))) + { + SHELLEXECUTEINFO execute={sizeof(execute),SEE_MASK_IDLIST|SEE_MASK_FLAG_LOG_USAGE}; + execute.lpIDList=pidl; + execute.nShow=SW_SHOWNORMAL; + ShellExecuteEx(&execute); + } + } + } +} +*/ + +CComPtr GetMetroPinMenu( const wchar_t *appid ) +{ + if (GetWinVersion() pAppFolder; + { + CAbsolutePidl pidl; + if (SUCCEEDED(SHGetKnownFolderIDList(FOLDERID_AppsFolder2,KF_FLAG_DEFAULT,NULL,&pidl))) + SHBindToObject(NULL,pidl,NULL,IID_IShellFolder,(void **)&pAppFolder); + } + CComPtr pPinMenu; + if (pAppFolder) + { + PIDLIST_RELATIVE child; + if (SUCCEEDED(pAppFolder->ParseDisplayName(NULL,NULL,(LPWSTR)appid,NULL,&child,NULL))) + { + CComPtr pDataObject; + if (SUCCEEDED(pAppFolder->GetUIObjectOf(NULL,1,(PCUITEMID_CHILD*)&child,IID_IDataObject,NULL,(void**)&pDataObject))) + { + CRegKey regKey; + if (regKey.Open(HKEY_CLASSES_ROOT,MetroAppClassId,KEY_READ)==ERROR_SUCCESS) + { + CComPtr pInit; + pInit.CoCreateInstance(CLSID_PinExt); + if (pInit && SUCCEEDED(pInit->Initialize(NULL,pDataObject,regKey))) + pPinMenu=CComQIPtr(pInit); + } + } + ILFree(child); + } + } + return pPinMenu; +} + +static const wchar_t *g_UninstallableApps[]={ + L"windows.immersivecontrolpanel_cw5n1h2txyewy!microsoft.windows.immersivecontrolpanel", + L"Microsoft.WindowsStore_8wekyb3d8bbwe!App", + L"Microsoft.Windows.Cortana_cw5n1h2txyewy!CortanaUI", +}; + +// Returns true if the app should not be uninstalled +bool IsProtectedApp( const wchar_t *appid ) +{ + for (int i=0;i<_countof(g_UninstallableApps);i++) + { + if (_wcsicmp(appid,g_UninstallableApps[i])==0) + return true; + } + return false; +} + +// Returns true if uninstalling is allowed by the policy +bool GetUninstallPolicy( void ) +{ + if (GetWinVersion() pAppItem; + if (FAILED(SHCreateItemInKnownFolder(FOLDERID_AppsFolder2,0,appid,IID_IShellItem2,(void**)&pAppItem))) + return false; + + CComPtr pStore; + PROPERTYKEY keys[]={ + PKEY_MetroPackagePath, + PKEY_AppUserModel_ParentID, + PKEY_AppUserModel_InstalledBy, + PKEY_AppUserModel_IsDualMode, + PKEY_Launcher_AppState, + }; + if (FAILED(pAppItem->GetPropertyStoreForKeys(keys,_countof(keys),GPS_FASTPROPERTIESONLY,IID_IPropertyStore,(void**)&pStore))) + return false; + + CString parentid=GetPropertyStoreString(pStore,PKEY_AppUserModel_ParentID); + if (!parentid.IsEmpty()) + return false; // this is a child tile + CString packagePath=GetPropertyStoreString(pStore,PKEY_MetroPackagePath); + if (packagePath.IsEmpty() || GetFileAttributes(packagePath)==INVALID_FILE_ATTRIBUTES) + return false; + PROPVARIANT val; + PropVariantInit(&val); + bool res=true; + if (SUCCEEDED(pStore->GetValue(PKEY_AppUserModel_InstalledBy,&val))) + { + if (val.vt==VT_UI4 && val.intVal==1) + res=false; // from CAppTileHelper::IsInboxAppTile + } + PropVariantClear(&val); + + if (res && SUCCEEDED(pStore->GetValue(PKEY_AppUserModel_IsDualMode,&val))) + { + if (val.vt==VT_BOOL && val.boolVal) + res=false; + } + PropVariantClear(&val); + + if (!res) return false; + + if (SUCCEEDED(pStore->GetValue(PKEY_Launcher_AppState,&val))) + { + if (val.vt!=VT_UI4 || val.intVal==4 || val.intVal==6) + res=false; + } + else + res=false; + PropVariantClear(&val); + + return res; +} + +// Uninstalls the app with the given id +void UninstallMetroApp( const wchar_t *appid ) +{ + CComPtr pAppItem; + if (SUCCEEDED(SHCreateItemInKnownFolder(FOLDERID_AppsFolder2,0,appid,IID_IShellItem,(void**)&pAppItem))) + { + CComPtr pStore; + pAppItem->BindToHandler(NULL,BHID_PropertyStore,IID_IPropertyStore,(void**)&pStore); + if (pStore) + { + CString packageName=GetPropertyStoreString(pStore,PKEY_MetroPackageName); + if (!packageName.IsEmpty()) + { + wchar_t command[1024]; + Sprintf(command,_countof(command),L"Remove-AppxPackage %s",packageName); + ShellExecute(NULL,L"open",L"powershell.exe",command,NULL,SW_HIDE); + } + } + } +} + +// Asks for confirmation to uninstall the specified app +void UninstallMetroApp( HWND parent, const wchar_t *name, const wchar_t *appid ) +{ + wchar_t text[1024]; + Sprintf(text,_countof(text),FindTranslation(L"Menu.UninstallPrompt",L"Are you sure you want to uninstall %s?"),name); + CString title=FindTranslation(L"Menu.UninstallTitle",L"Uninstall"); + + HICON hIcon=NULL; + CComPtr pAppItem; + if (SUCCEEDED(SHCreateItemInKnownFolder(FOLDERID_AppsFolder2,0,appid,IID_IShellItem,(void**)&pAppItem))) + { + CAbsolutePidl pidl; + SHGetIDListFromObject(pAppItem,&pidl); + const CItemManager::ItemInfo *pItemInfo=g_ItemManager.GetItemInfo(pAppItem,pidl,CItemManager::INFO_LINK|CItemManager::INFO_METRO); + g_ItemManager.UpdateItemInfo(pItemInfo,CItemManager::INFO_LARGE_ICON|CItemManager::INFO_REFRESH_NOW); + HBITMAP hMonoBitmap=CreateBitmap(CItemManager::LARGE_ICON_SIZE,CItemManager::LARGE_ICON_SIZE,1,1,NULL); + ICONINFO info={TRUE,0,0,hMonoBitmap,pItemInfo->largeIcon->bitmap}; + hIcon=CreateIconIndirect(&info); + DeleteObject(hMonoBitmap); + } + + TASKDIALOGCONFIG task={sizeof(task),parent,NULL,TDF_ALLOW_DIALOG_CANCELLATION|TDF_USE_HICON_MAIN,TDCBF_YES_BUTTON|TDCBF_NO_BUTTON}; + task.pszWindowTitle=title; + task.pszContent=text; + task.hMainIcon=hIcon?hIcon:LoadIcon(NULL,IDI_QUESTION); + int res; + if (FAILED(TaskDialogIndirect(&task,&res,NULL,NULL))) + res=0; + if (hIcon) DestroyIcon(hIcon); + + if (res==IDYES) + UninstallMetroApp(appid); +} + +// Determines if Edge is the default browser +bool IsEdgeDefaultBrowser( void ) +{ + if (GetWinVersion() +#include "ItemManager.h" +#include "LogManager.h" + +#define METRO_APP_ROOT L"%LOCALAPPDATA%\\Microsoft\\Windows\\Application Shortcuts" +extern PROPERTYKEY PKEY_MetroAppLink; // pidl +extern PROPERTYKEY PKEY_MetroAppLauncher; // =1 for metro apps +extern PROPERTYKEY PKEY_MetroIconColor; +extern KNOWNFOLDERID FOLDERID_AppsFolder2; + +#define DESKTOP_APP_ID L"Microsoft.Windows.Desktop" +#define SEARCH_APP_ID L"Windows.UI.Search" + +struct MetroLink +{ + CAbsolutePidl pidl; + CString appid; // only for Windows 10 + CComPtr pItem; +}; + +// Returns a list of links for all metro apps +void GetMetroLinks( std::vector &links, bool bLog, std::vector *pNonApps10=NULL ); + +// Executes the metro link of the given item info +void ExecuteMetroLink( const CItemManager::ItemInfo *pInfo ); + +// Returns true if the app is still valid +bool IsValidApp( const wchar_t *appid ); + +// Returns true if the app should not be uninstalled +bool IsProtectedApp( const wchar_t *appid ); + +// Returns true if uninstalling is allowed by the policy +bool GetUninstallPolicy( void ); + +// Checks if the app can be uninstalled +bool CanUninstallMetroApp( const wchar_t *appid ); + +// Uninstalls the app with the given id +void UninstallMetroApp( const wchar_t *appid ); + +// Asks for confirmation to uninstall the specified app +void UninstallMetroApp( HWND parent, const wchar_t *name, const wchar_t *appid ); + +// Creates a context menu to pin/unpin the metro app to the taskbar +CComPtr GetMetroPinMenu( const wchar_t *appid ); + +// Determines if Edge is the default browser +bool IsEdgeDefaultBrowser( void ); diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ProgramsTree.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ProgramsTree.cpp new file mode 100644 index 0000000..82ca10c --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ProgramsTree.cpp @@ -0,0 +1,1770 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +// ProgramsTree.cpp - contains the implementation of the programs tree for the Win7 style + +#include "stdafx.h" +#include "ProgramsTree.h" +#include "MenuContainer.h" +#include "MetroLinkManager.h" +#include "Translations.h" +#include "Settings.h" +#include "ResourceHelper.h" +#include "FNVHash.h" +#include "LogManager.h" +#include "ClassicStartMenuDLL.h" +#include "SettingsUI.h" +#include +#include + +bool CProgramsTree::s_bFoldersFirst; + +const wchar_t *ORDER_PREFIX=L"#"; + +CProgramsTree::CProgramsTree( void ) +{ + m_RefCount=1; + m_pOwner=NULL; + m_ImageList=NULL; + m_bHoverTimer=m_bTrackMouse=m_bRefreshPosted=m_bAutoSort=m_bDragApps=m_bInsertAfter=false; + m_LastMousePos.x=m_LastMousePos.y=0; + m_MinX=m_MaxX=m_RootX=0; + m_DropLocation=DROP_NOWHERE; + m_DragItem=m_DropTarget=m_HoverItem=NULL; + m_TreeTheme=m_ScrollTheme=NULL; + m_InsertMark=NULL; +} + +// Subclass the tooltip to delay the tip when the mouse moves from one tree item to the next +static LRESULT CALLBACK SubclassInfoTipProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==TTM_UPDATE) + { + int time=(int)SendMessage(hWnd,TTM_GETDELAYTIME,TTDT_RESHOW,0); + SetTimer(hWnd,'CLSH',time,NULL); + return 0; + } + if (uMsg==WM_TIMER && wParam=='CLSH') + { + KillTimer(hWnd,wParam); + DefSubclassProc(hWnd,TTM_UPDATE,0,0); + return 0; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +void CProgramsTree::Create( CMenuContainer *pOwner ) +{ + m_pOwner=pOwner; + HWND hWnd=CreateWindowEx(0,WC_TREEVIEW,NULL,WS_CHILD|TVS_EDITLABELS|TVS_FULLROWSELECT|(CMenuContainer::s_TipHideTime?TVS_INFOTIP:0)|TVS_NOHSCROLL|TVS_SHOWSELALWAYS|TVS_NONEVENHEIGHT,0,0,0,0,pOwner->m_hWnd,NULL,g_Instance,NULL); + TreeView_SetExtendedStyle(hWnd,TVS_EX_AUTOHSCROLL,TVS_EX_AUTOHSCROLL); + const MenuSkin &skin=CMenuContainer::s_Skin; + m_TreeTheme=OpenThemeData(m_hWnd,L"treeview"); + if (skin.BHasScrollbar) + m_ScrollTheme=OpenThemeData(m_hWnd,L"scrollbar"); + + const MenuSkin::ItemDrawSettings &settings=skin.ItemSettings[MenuSkin::PROGRAMS_TREE_ITEM]; + + SendMessage(hWnd,WM_SETFONT,(LPARAM)settings.font,FALSE); + + TreeView_SetItemHeight(hWnd,settings.itemHeight); + + SubclassWindow(hWnd); + m_ImageList=ImageList_Create(CItemManager::SMALL_ICON_SIZE+settings.iconPadding.left+settings.iconPadding.right,CItemManager::SMALL_ICON_SIZE,ILC_COLOR32|ILC_MASK|ILC_MIRROR,1,16); + TreeView_SetImageList(hWnd,m_ImageList,TVSIL_NORMAL); + TreeView_SetIndent(hWnd,TreeView_GetIndent(hWnd)+skin.Programs_indent); + m_DragItem=NULL; + m_DropLocation=DROP_NOWHERE; + m_DropTarget=NULL; + m_bRefreshPosted=false; + m_pDropTargetProxy=new CDropTargetProxy(this); + RegisterDragDrop(hWnd,m_pDropTargetProxy); + m_LastMousePos.x=m_LastMousePos.y=-1; + s_bFoldersFirst=GetSettingBool(L"FoldersFirst"); + + HWND tooltip=TreeView_GetToolTips(m_hWnd); + SendMessage(tooltip,TTM_SETDELAYTIME,TTDT_AUTOPOP,CMenuContainer::s_TipHideTime); + SendMessage(tooltip,TTM_SETDELAYTIME,TTDT_INITIAL,CMenuContainer::s_TipShowTime); + SendMessage(tooltip,TTM_SETDELAYTIME,TTDT_RESHOW,CMenuContainer::s_TipShowTime); + SetWindowSubclass(tooltip,SubclassInfoTipProc,'CLSH',0); + + AddRef(); // this will be released in OnFinalMeessage +} + +LRESULT CALLBACK CProgramsTree::CustomWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + CProgramsTree *pThis=static_cast((CWindowImpl*)hWnd); + if (!pThis->m_ScrollTheme) + { + return WindowProc(hWnd,uMsg,wParam,lParam); + } + DWORD oldThread=g_CustomScrollbarThread; + g_CustomScrollbarThread=GetCurrentThreadId(); + g_CustomScrollbarTheme=pThis->m_ScrollTheme; + LRESULT res=WindowProc(hWnd,uMsg,wParam,lParam); + g_CustomScrollbarThread=oldThread; + if (!oldThread) + g_CustomScrollbarTheme=NULL; + return res; +} + +LRESULT CProgramsTree::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + m_pDropTargetProxy->Reset(); + m_pDropTargetProxy=NULL; + RevokeDragDrop(m_hWnd); + ImageList_Destroy(m_ImageList); + m_ImageList=NULL; + if (m_TreeTheme) + { + CloseThemeData(m_TreeTheme); + m_TreeTheme=NULL; + } + if (m_ScrollTheme) + { + CloseThemeData(m_ScrollTheme); + m_ScrollTheme=NULL; + } + return 0; +} + +LRESULT CProgramsTree::OnDeleteItem( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + // free data + NMTREEVIEW *pItem=(NMTREEVIEW*)pnmh; + delete (CTreeItem*)pItem->itemOld.lParam; + return 0; +} + +LRESULT CProgramsTree::OnItemExpanding( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + // generate child items + NMTREEVIEW *pView=(NMTREEVIEW*)pnmh; + if (pView->itemNew.state&TVIS_EXPANDEDONCE) + return 0; + CreateFolderItems(pView->itemNew.hItem); + HTREEITEM hChild=TreeView_GetChild(m_hWnd,pView->itemNew.hItem); + if (hChild && !TreeView_GetNextSibling(m_hWnd,hChild)) + PostMessage(TVM_EXPAND,TVE_EXPAND,(LPARAM)hChild); + return 0; +} + +LRESULT CProgramsTree::OnSingleExpand( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + return TVNRET_SKIPOLD; +} + +LRESULT CProgramsTree::OnBeginDrag( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMTREEVIEW *pDrag=(NMTREEVIEW*)pnmh; + CTreeItem *pItem=(CTreeItem*)pDrag->itemNew.lParam; + if (!pItem) return 0; + m_DragItem=pDrag->itemNew.hItem; + m_bDragApps=pItem->bApps; + if (pItem->bApps) + { + m_pOwner->DragOutApps(pItem->pItemInfo1); + } + else + { + m_pOwner->DragTreeItem(pItem,pItem->bApp); + } + m_DropLocation=DROP_NOWHERE; + m_DragItem=NULL; + return 0; +} + +LRESULT CProgramsTree::OnKeyDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==VK_RETURN) + { + HTREEITEM hItem; + const CTreeItem *pItem=GetSelectedItem(hItem); + if (!pItem) return 0; + if (pItem->bFolder) + TreeView_Expand(m_hWnd,hItem,TVE_TOGGLE); + else if (pItem->pItemInfo1) + { + RECT rc; + TreeView_GetItemRect(m_hWnd,hItem,&rc,FALSE); + MapWindowPoints(m_pOwner->m_hWnd,&rc); + CMenuContainer::ActivateData data; + data.bProgramsTree=true; + m_pOwner->ActivateTreeItem(pItem,rc,CMenuContainer::ACTIVATE_EXECUTE,NULL,&data); + } + return 0; + } + if (wParam==VK_TAB) + { + m_pOwner->SendMessage(WM_KEYDOWN,wParam,lParam); + return 0; + } + + // Del to delete, F2 to rename + if (wParam==VK_DELETE || wParam==VK_F2) + { + HTREEITEM hItem; + const CTreeItem *pItem=GetSelectedItem(hItem); + if (!pItem) return 0; + if (pItem->pItemInfo1) + { + RECT rc; + TreeView_GetItemRect(m_hWnd,hItem,&rc,FALSE); + MapWindowPoints(m_pOwner->m_hWnd,&rc); + CMenuContainer::ActivateData data; + data.bProgramsTree=true; + m_pOwner->ActivateTreeItem(pItem,rc,wParam==VK_F2?CMenuContainer::ACTIVATE_RENAME:CMenuContainer::ACTIVATE_DELETE,NULL,&data); + if (data.command==CMenuContainer::CMD_DELETE) + { + HTREEITEM hParent=TreeView_GetParent(m_hWnd,hItem); + if (hParent) + { + TVITEM item={TVIF_PARAM,hParent}; + TreeView_GetItem(m_hWnd,&item); + const CTreeItem *pParent=(CTreeItem*)item.lParam; + PostRefreshMessage(pParent->pItemInfo1); + } + else + PostRefreshMessage(); + } + else if (data.command==CMenuContainer::CMD_RENAME) + { + if (data.pNewItemInfo) + SaveRenamedOrder(hItem,data.pNewItemInfo); + PostRefreshMessage(data.pNewItemInfo); + } + } + return 0; + } + + if (wParam==VK_ESCAPE) + { + m_pOwner->SetMenuMode(CMenuContainer::MODE_NORMAL); + m_pOwner->SetHotItem(m_pOwner->m_ProgramButtonIndex); + return 0; + } + + HTREEITEM hSelect1=TreeView_GetSelection(m_hWnd); + DWORD state1=hSelect1?TreeView_GetItemState(m_hWnd,hSelect1,TVIS_EXPANDED)&TVIS_EXPANDED:0; + + LRESULT res=DefWindowProc(uMsg,wParam,lParam); + + HTREEITEM hSelect2=TreeView_GetSelection(m_hWnd); + DWORD state2=hSelect2?TreeView_GetItemState(m_hWnd,hSelect2,TVIS_EXPANDED)&TVIS_EXPANDED:0; + + if (hSelect1==hSelect2 && state1==state2) + { + if (wParam==VK_UP || wParam==VK_DOWN || wParam==VK_LEFT || wParam==VK_RIGHT) + { + m_pOwner->SendMessage(uMsg,wParam,lParam); + } + } + return res; +} + +LRESULT CProgramsTree::OnSysKeyDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==VK_RETURN) + { + HTREEITEM hItem; + const CTreeItem *pItem=GetSelectedItem(hItem); + if (!pItem) return 0; + if (pItem->pItemInfo1) + { + RECT rc; + TreeView_GetItemRect(m_hWnd,hItem,&rc,FALSE); + MapWindowPoints(m_pOwner->m_hWnd,&rc); + CMenuContainer::ActivateData data; + data.bProgramsTree=true; + m_pOwner->ActivateTreeItem(pItem,rc,CMenuContainer::ACTIVATE_PROPERTIES,NULL,&data); + } + } + else + bHandled=FALSE; + return 0; +} + +LRESULT CProgramsTree::OnChar( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + bHandled=(wParam==VK_TAB || wParam==VK_RETURN || wParam==VK_ESCAPE); + return 0; +} + +LRESULT CProgramsTree::OnSetFocus( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + for (std::vector::reverse_iterator it=CMenuContainer::s_Menus.rbegin();*it!=m_pOwner;++it) + if (!(*it)->m_bDestroyed) + (*it)->PostMessage(WM_CLOSE); + bHandled=FALSE; + return 0; +} + +LRESULT CProgramsTree::OnMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + TVHITTESTINFO test={{(short)LOWORD(lParam),(short)HIWORD(lParam)}}; + if (m_LastMousePos.x!=-1 && (m_LastMousePos.x!=test.pt.x || m_LastMousePos.y!=test.pt.y) && TreeView_HitTest(m_hWnd,&test)) + { + RECT rc; + TreeView_GetItemRect(m_hWnd,test.hItem,&rc,FALSE); + int bottom=rc.bottom; + GetClientRect(&rc); + if (bottom<=rc.bottom) + TreeView_SelectItem(m_hWnd,test.hItem); + + if (!m_bHoverTimer) + { + SetTimer(TIMER_HOVER,CMenuContainer::s_HoverTime); + m_bHoverTimer=true; + } + if (m_pOwner->m_Submenu<0) + SetFocus(); + m_pOwner->SetHotItem(m_pOwner->m_ProgramTreeIndex); + } + m_LastMousePos=test.pt; + + if (!m_bTrackMouse) + { + TRACKMOUSEEVENT track={sizeof(track),TME_LEAVE,m_hWnd,0}; + TrackMouseEvent(&track); + m_bTrackMouse=true; + } + + bHandled=FALSE; + return 0; +} + +LRESULT CProgramsTree::OnMouseLeave( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + m_pOwner->SetHotItem(-1); + m_bTrackMouse=false; + if (m_bHoverTimer) + { + KillTimer(TIMER_HOVER); + m_bHoverTimer=false; + } + return 0; +} + +LRESULT CProgramsTree::OnNcMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + TreeView_SelectItem(m_hWnd,NULL); + if (!m_bHoverTimer) + { + SetTimer(TIMER_HOVER,CMenuContainer::s_HoverTime); + m_bHoverTimer=true; + } + if (m_pOwner->m_Submenu<0) + SetFocus(); + m_pOwner->SetHotItem(m_pOwner->m_ProgramTreeIndex); + bHandled=FALSE; + return 0; +} + +LRESULT CProgramsTree::OnNcMouseLeave( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + m_bTrackMouse=false; + if (m_bHoverTimer) + { + KillTimer(TIMER_HOVER); + m_bHoverTimer=false; + } + bHandled=FALSE; + return 0; +} + +LRESULT CProgramsTree::OnNcLButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + SetFocus(); + TreeView_SelectItem(m_hWnd,NULL); + bHandled=FALSE; + return 0; +} + +LRESULT CProgramsTree::OnMouseActivate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + SetFocus(); + if (CMenuContainer::s_bBehindTaskbar && CMenuContainer::s_TaskBar) + m_pOwner->SetWindowPos(CMenuContainer::s_TaskBar,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE); + return MA_NOACTIVATE; +} + +LRESULT CProgramsTree::OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==TIMER_HOVER) + { + KillTimer(TIMER_HOVER); + m_bHoverTimer=false; + RECT rc; + GetWindowRect(&rc); + if (PtInRect(&rc,CPoint(GetMessagePos()))) + SetFocus(); + } + else + bHandled=FALSE; + return 0; +} + +LRESULT CProgramsTree::OnContextMenu( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (CMenuContainer::s_bNoContextMenu) return 0; + HTREEITEM hItem; + const CTreeItem *pItem=GetSelectedItem(hItem); + if (pItem) + { + RECT rc; + TreeView_GetItemRect(m_hWnd,hItem,&rc,FALSE); + MapWindowPoints(m_pOwner->m_hWnd,&rc); + CMenuContainer::ActivateData data; + data.bProgramsTree=true; + data.bExpanded=(TreeView_GetItemState(m_hWnd,hItem,TVIS_EXPANDED)&TVIS_EXPANDED)!=0; + HTREEITEM hParent=TreeView_GetParent(m_hWnd,hItem); + const CTreeItem *pParent=NULL; + if (hParent) + { + TVITEM item={TVIF_PARAM,hParent}; + TreeView_GetItem(m_hWnd,&item); + pParent=(CTreeItem*)item.lParam; + data.parent=pParent->pItemInfo1->GetPidl(); + data.bAutoSort=pParent->bAutoSort; + } + else + { + data.parent=m_pOwner->m_Path1[0]; + data.bAutoSort=m_bAutoSort; + } + data.hTreeItem=hItem; + m_pOwner->ActivateTreeItem(pItem,rc,CMenuContainer::ACTIVATE_MENU,NULL,&data); + if (data.command==CMenuContainer::CMD_RENAME && data.pNewItemInfo) + SaveRenamedOrder(hItem,data.pNewItemInfo); + if (data.command==CMenuContainer::CMD_TOGGLE) + TreeView_Expand(m_hWnd,hItem,TVE_TOGGLE); + else if (data.command==CMenuContainer::CMD_DELETE || data.command==CMenuContainer::CMD_MARKOLD) + PostRefreshMessage(pParent?pParent->pItemInfo1:NULL); + else if (data.command==CMenuContainer::CMD_RENAME || data.command==CMenuContainer::CMD_NEWFOLDER) + PostRefreshMessage(data.pNewItemInfo); + } + + return 0; +} + +LRESULT CProgramsTree::OnScroll( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (CMenuContainer::s_Skin.Programs_background==0) + Invalidate(); + bHandled=FALSE; + return 0; +} + +bool CProgramsTree::GetInsertRect( RECT &rc ) const +{ + if (!m_InsertMark) return false; + + RECT itemRect; + TreeView_GetItemRect(m_hWnd,m_InsertMark,&itemRect,TRUE); + + GetClientRect(&rc); + rc.left=itemRect.left-CItemManager::SMALL_ICON_SIZE-3-CMenuContainer::s_Skin.ItemSettings[MenuSkin::PROGRAMS_TREE_ITEM].iconPadding.right; + const POINT *sizes=CMenuContainer::s_Skin.GetArrowsBitmapSizes(); + int h=sizes[1].y; + rc.top=(m_bInsertAfter?itemRect.bottom:itemRect.top)-h/2; + rc.bottom=rc.top+h; + return true; +} + +LRESULT CProgramsTree::OnSetInsertMark( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + RECT rc; + if (GetInsertRect(rc)) + InvalidateRect(&rc); + m_InsertMark=(HTREEITEM)lParam; + m_bInsertAfter=wParam!=0; + if (GetInsertRect(rc)) + InvalidateRect(&rc); + bHandled=FALSE; + return 0; +} + +LRESULT CProgramsTree::OnRefresh( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + m_bRefreshPosted=false; + RefreshTree(NULL,(CItemManager::ItemInfo*)lParam); + return 0; +} + +// Subclass the renaming editbox to handle Esc and Enter +static LRESULT CALLBACK SubclassEditboxProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_GETDLGCODE) + return DLGC_WANTALLKEYS; + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +LRESULT CProgramsTree::OnBeginLabelEdit( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + SetWindowSubclass(TreeView_GetEditControl(m_hWnd),SubclassEditboxProc,'CLSH',0); +/* NMTVDISPINFO *pInfo=(NMTVDISPINFO*)pnmh; + if (!pInfo->item.lParam || ((CTreeItem*)pInfo->item.lParam)->bSeparator) + return TRUE;*/ + return FALSE; +} + +LRESULT CProgramsTree::OnEndLabelEdit( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ +/* NMTVDISPINFO *pInfo=(NMTVDISPINFO*)pnmh; + if (pInfo->item.pszText) + { + if (!*pInfo->item.pszText) + { + ::MessageBox(m_hWnd,LoadStringEx(IDS_ERROR_EMPTY),LoadStringEx(IDS_ERROR_TITLE),MB_OK|MB_ICONERROR); + return FALSE; + } + bool bValid=true; + for (const wchar_t *c=pInfo->item.pszText;*c;c++) + { + if ((*c>='a' && *c<='z') || (*c>='A' && *c<='Z') || (*c>='0' && *c<='9') || *c=='_') + continue; + ::MessageBox(m_hWnd,LoadStringEx(IDS_ERROR_ASCII),LoadStringEx(IDS_ERROR_TITLE),MB_OK|MB_ICONERROR); + return FALSE; + } + wchar_t text[1024]; + if (m_pOwner->IsSeparator(pInfo->item.pszText)) + { + Sprintf(text,_countof(text),LoadStringEx(IDS_ERROR_SEPARATOR),pInfo->item.pszText); + ::MessageBox(m_hWnd,text,LoadStringEx(IDS_ERROR_TITLE),MB_OK|MB_ICONERROR); + return FALSE; + } + if (FindItemByName(NULL,pInfo->item.pszText,pInfo->item.hItem)) + { + Sprintf(text,_countof(text),LoadStringEx(IDS_DUPLICATE_ITEM),pInfo->item.pszText); + ::MessageBox(m_hWnd,text,LoadStringEx(IDS_ERROR_TITLE),MB_OK|MB_ICONERROR); + return FALSE; + } + ((CTreeItem*)pInfo->item.lParam)->name=pInfo->item.pszText; + return TRUE; + }*/ + return FALSE; +} + +LRESULT CProgramsTree::OnGetInfoTip( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMTVGETINFOTIP *pTip=(NMTVGETINFOTIP*)pnmh; + const CTreeItem *pTreeItem=(CTreeItem*)pTip->lParam; + if (pTreeItem && pTreeItem->pItemInfo1 && !pTreeItem->bFolder) + { + // get the tip from the shell + CComPtr pItem; + if (FAILED(SHCreateItemFromIDList(pTreeItem->pItemInfo1->GetPidl(),IID_IShellItem,(void**)&pItem))) + return 0; + + CComPtr pQueryInfo; + if (FAILED(pItem->BindToHandler(NULL,BHID_SFUIObject,IID_IQueryInfo,(void**)&pQueryInfo))) + return 0; + + CComString pText; + if (FAILED(pQueryInfo->GetInfoTip(QITIPF_LINKNOTARGET,&pText)) || !pText) + return 0; + + Strcpy(pTip->pszText,pTip->cchTextMax,pText); + } + return 0; +} + +LRESULT CProgramsTree::OnClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + CPoint pt(GetMessagePos()); + ScreenToClient(&pt); + TVHITTESTINFO test={pt}; + TreeView_HitTest(m_hWnd,&test); + if (test.flags&TVHT_ONITEM|TVHT_ONITEMINDENT) + { + TreeView_SelectItem(m_hWnd,test.hItem); + TVITEM item={TVIF_PARAM,test.hItem}; + TreeView_GetItem(m_hWnd,&item); + const CTreeItem *pItem=(CTreeItem*)item.lParam; + if (!pItem) return TRUE; + if (pItem->bFolder) + TreeView_Expand(m_hWnd,test.hItem,TVE_TOGGLE); + else if (pItem->pItemInfo1) + { + RECT rc; + TreeView_GetItemRect(m_hWnd,test.hItem,&rc,FALSE); + MapWindowPoints(m_pOwner->m_hWnd,&rc); + CMenuContainer::ActivateData data; + data.bProgramsTree=true; + m_pOwner->ActivateTreeItem(pItem,rc,CMenuContainer::ACTIVATE_EXECUTE,NULL,&data); + } + } + return TRUE; +} + +LRESULT CProgramsTree::OnRClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + if (CMenuContainer::s_bNoContextMenu) return 1; + CPoint pt(GetMessagePos()); + TVHITTESTINFO test={pt}; + ScreenToClient(&test.pt); + TreeView_HitTest(m_hWnd,&test); + if (test.flags&TVHT_ONITEM|TVHT_ONITEMINDENT) + { + TreeView_SelectItem(m_hWnd,test.hItem); + TVITEM item={TVIF_PARAM,test.hItem}; + TreeView_GetItem(m_hWnd,&item); + const CTreeItem *pItem=(CTreeItem*)item.lParam; + if (pItem) + { + RECT rc; + TreeView_GetItemRect(m_hWnd,test.hItem,&rc,FALSE); + MapWindowPoints(m_pOwner->m_hWnd,&rc); + CMenuContainer::ActivateData data; + data.bProgramsTree=true; + data.bExpanded=(TreeView_GetItemState(m_hWnd,test.hItem,TVIS_EXPANDED)&TVIS_EXPANDED)!=0; + HTREEITEM hParent=TreeView_GetParent(m_hWnd,test.hItem); + const CTreeItem *pParent=NULL; + if (hParent) + { + TVITEM item={TVIF_PARAM,hParent}; + TreeView_GetItem(m_hWnd,&item); + pParent=(CTreeItem*)item.lParam; + data.parent=pParent->pItemInfo1->GetPidl(); + data.bAutoSort=pParent->bAutoSort; + } + else + { + data.parent=m_pOwner->m_Path1[0]; + data.bAutoSort=m_bAutoSort; + } + data.hTreeItem=test.hItem; + m_pOwner->ActivateTreeItem(pItem,rc,CMenuContainer::ACTIVATE_MENU,&pt,&data); + if (data.command==CMenuContainer::CMD_RENAME && data.pNewItemInfo) + SaveRenamedOrder(test.hItem,data.pNewItemInfo); + if (data.command==CMenuContainer::CMD_TOGGLE) + TreeView_Expand(m_hWnd,test.hItem,TVE_TOGGLE); + else if (data.command==CMenuContainer::CMD_DELETE || data.command==CMenuContainer::CMD_MARKOLD) + PostRefreshMessage(pParent?pParent->pItemInfo1:NULL); + else if (data.command==CMenuContainer::CMD_RENAME || data.command==CMenuContainer::CMD_NEWFOLDER) + PostRefreshMessage(data.pNewItemInfo); + } + } + return 1; +} + +LRESULT CProgramsTree::OnPaint( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + // use buffered paint to allow the tree control to appear on a transparent background + PAINTSTRUCT ps; + HDC hdc=BeginPaint(&ps); + DrawTree(hdc,ps.rcPaint); + EndPaint(&ps); + return 0; +} + +void CProgramsTree::DeleteAllItems( void ) +{ + TreeView_DeleteAllItems(m_hWnd); +} + +void CProgramsTree::ClearAllNewRec( HTREEITEM hParent ) +{ + for (HTREEITEM hItem=hParent?TreeView_GetChild(m_hWnd,hParent):TreeView_GetRoot(m_hWnd);hItem;hItem=TreeView_GetNextSibling(m_hWnd,hItem)) + { + TVITEM item={TVIF_PARAM,hItem}; + TreeView_GetItem(m_hWnd,&item); + CTreeItem *pTreeItem=(CTreeItem*)item.lParam; + pTreeItem->bNew=false; + ClearAllNewRec(hItem); + } +} + +void CProgramsTree::ClearAllNew( void ) +{ + ClearAllNewRec(NULL); +} + +void CProgramsTree::AddFirstFolder( std::vector &items, IShellItem *pParent, bool bPrograms ) +{ + unsigned int hash0Prog=CalcFNVHash(L"\\",FNV_HASH0); + unsigned int hash0=FNV_HASH0; + CShellItemEnumerator enumerator(pParent); + if (!enumerator.IsValid()) return; + + CComPtr pChild; + CAbsolutePidl childPidl; + while (enumerator.GetNext(pChild,childPidl)) + { + SFGAOF itemFlags; + if (SUCCEEDED(pChild->GetAttributes(SFGAO_FOLDER|SFGAO_HIDDEN,&itemFlags))) + { + if (itemFlags&SFGAO_HIDDEN) + continue; + CTreeItem *pItem=new CTreeItem(); + pItem->bFolder=(itemFlags&SFGAO_FOLDER)!=0; + pItem->bEmpty=false; + pItem->pItemInfo1=g_ItemManager.GetItemInfo(pChild,childPidl,CItemManager::INFO_SMALL_ICON|CItemManager::INFO_LINK|CItemManager::INFO_METRO); + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + if (pItem->pItemInfo1->IsMetroLink()) + { + if (GetSettingBool(L"HideProgramsMetro") || _wcsicmp(pItem->pItemInfo1->GetAppid(),DESKTOP_APP_ID)==0) + continue; + CString name=pItem->pItemInfo1->GetMetroName(); + pItem->SetName(name,false); + name.MakeUpper(); + pItem->nameHash=CalcFNVHash(name,hash0); + pItem->nameHashProg=CalcFNVHash(name,hash0Prog); + } + } + if (pItem->name.IsEmpty()) + { + CComString pName; + if (FAILED(pChild->GetDisplayName(SIGDN_NORMALDISPLAY,&pName))) + continue; + pItem->SetName(pName,false); + CComString pName2; + if (SUCCEEDED(pChild->GetDisplayName(SIGDN_PARENTRELATIVEPARSING,&pName2))) + { + pName2.MakeUpper(); + pItem->nameHash=CalcFNVHash(pName2,hash0); + pItem->nameHashProg=CalcFNVHash(pName2,hash0Prog); + } + else + { + pName.MakeUpper(); + pItem->nameHash=CalcFNVHash(pName,hash0); + pItem->nameHashProg=CalcFNVHash(pName2,hash0Prog); + } + } + if (pItem->bFolder) + pItem->folderHash=CalcFNVHash(pItem->pItemInfo1->PATH,CalcFNVHash(ORDER_PREFIX)); + pItem->pItemInfo2=NULL; + pItem->order=-1; + pItem->bPrograms=bPrograms; + pItem->bNew=g_ItemManager.IsNewProgram(pItem->pItemInfo1->GetPidl(),pItem->bFolder,false); + items.push_back(pItem); + } + } +} + +void CProgramsTree::AddSecondFolder( std::vector &items, IShellItem *pParent, bool bPrograms ) +{ + unsigned int hash0Prog=CalcFNVHash(L"\\",FNV_HASH0); + unsigned int hash0=FNV_HASH0; + CShellItemEnumerator enumerator(pParent); + if (!enumerator.IsValid()) return; + + CComPtr pChild; + CAbsolutePidl childPidl; + while (enumerator.GetNext(pChild,childPidl)) + { + SFGAOF itemFlags; + if (SUCCEEDED(pChild->GetAttributes(SFGAO_FOLDER|SFGAO_HIDDEN,&itemFlags))) + { + if (itemFlags&SFGAO_HIDDEN) + continue; + CTreeItem *pItem=new CTreeItem(); + pItem->bFolder=(itemFlags&SFGAO_FOLDER)!=0; + pItem->bEmpty=false; + pItem->pItemInfo1=g_ItemManager.GetItemInfo(pChild,childPidl,CItemManager::INFO_SMALL_ICON|CItemManager::INFO_LINK|CItemManager::INFO_METRO); + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + if (pItem->pItemInfo1->IsMetroLink()) + { + if (GetSettingBool(L"HideProgramsMetro") || _wcsicmp(pItem->pItemInfo1->GetAppid(),DESKTOP_APP_ID)==0) + continue; + CString name=pItem->pItemInfo1->GetMetroName(); + pItem->SetName(name,false); + name.MakeUpper(); + pItem->nameHash=CalcFNVHash(name,hash0); + pItem->nameHashProg=CalcFNVHash(name,hash0Prog); + } + } + if (pItem->name.IsEmpty()) + { + CComString pName; + if (FAILED(pChild->GetDisplayName(SIGDN_NORMALDISPLAY,&pName))) + continue; + pItem->SetName(pName,false); + CComString pName2; + if (SUCCEEDED(pChild->GetDisplayName(SIGDN_PARENTRELATIVEPARSING,&pName2))) + { + pName2.MakeUpper(); + pItem->nameHash=CalcFNVHash(pName2,hash0); + pItem->nameHashProg=CalcFNVHash(pName2,hash0Prog); + } + else + { + pName.MakeUpper(); + pItem->nameHash=CalcFNVHash(pName,hash0); + pItem->nameHashProg=CalcFNVHash(pName2,hash0Prog); + } + } + if (pItem->bFolder) + pItem->folderHash=CalcFNVHash(pItem->pItemInfo1->PATH,CalcFNVHash(ORDER_PREFIX)); + pItem->pItemInfo2=NULL; + pItem->order=-1; + pItem->bPrograms=bPrograms; + pItem->bNew=g_ItemManager.IsNewProgram(pItem->pItemInfo1->GetPidl(),pItem->bFolder,false); + unsigned int nameHash=pItem->GetNameHash(); + for (std::vector::iterator it=items.begin();it!=items.end();++it) + { + if ((*it)->GetNameHash()==nameHash) + { + (*it)->pItemInfo2=pItem->pItemInfo1; + if (pItem->bNew) + (*it)->bNew=true; + delete pItem; + pItem=NULL; + break; + } + } + if (pItem) + items.push_back(pItem); + } + } +} + +void CProgramsTree::AddMetroApps( std::vector &items ) +{ + unsigned int hash0Prog=CalcFNVHash(L"\\",FNV_HASH0); + unsigned int hash0=FNV_HASH0; + std::vector links; + GetMetroLinks(links,true); + for (std::vector::const_iterator it=links.begin();it!=links.end();++it) + { + const CItemManager::ItemInfo *pItemInfo=g_ItemManager.GetItemInfo(it->pItem,it->pidl,CItemManager::INFO_SMALL_ICON|CItemManager::INFO_LINK|CItemManager::INFO_METRO); + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + if (_wcsicmp(pItemInfo->GetAppid(),DESKTOP_APP_ID)==0) + continue; + CString name; + if (pItemInfo->IsMetroLink()) + name=pItemInfo->GetMetroName(); + else + { + CComString pName; + if (FAILED(it->pItem->GetDisplayName(SIGDN_NORMALDISPLAY,&pName)) || wcsncmp(pName,L"@{",2)==0) + continue; + name=pName; + } + CTreeItem *pItem=new CTreeItem(); + pItem->pItemInfo1=pItemInfo; + pItem->SetName(name,false); + name.MakeUpper(); + pItem->nameHash=CalcFNVHash(name,hash0); + pItem->nameHashProg=CalcFNVHash(name,hash0Prog); + pItem->bApp=true; + pItem->order=-1; + pItem->bNew=g_ItemManager.IsNewProgram(pItemInfo->GetPidl(),false,true); + items.push_back(pItem); + } + + ULONGLONG curTime; + GetSystemTimeAsFileTime((FILETIME*)&curTime); + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu",KEY_WRITE)!=ERROR_SUCCESS) + regKey.Create(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu"); + regKey.SetQWORDValue(L"LastAppsTime",curTime); +} + +void CProgramsTree::GetFolderItems( std::vector &items, HTREEITEM hParent ) +{ + CTreeItem *pTreeItem=NULL; + if (hParent) + { + TVITEM item={TVIF_PARAM,hParent}; + TreeView_GetItem(m_hWnd,&item); + pTreeItem=(CTreeItem*)item.lParam; + if (pTreeItem->bApps) + { + AddMetroApps(items); + } + else + { + CComPtr pFolder1, pFolder2; + SHCreateItemFromIDList(pTreeItem->pItemInfo1->GetPidl(),IID_IShellItem,(void**)&pFolder1); + if (!pFolder1) return; + + if (pTreeItem->pItemInfo2) + SHCreateItemFromIDList(pTreeItem->pItemInfo2->GetPidl(),IID_IShellItem,(void**)&pFolder2); + + AddFirstFolder(items,pFolder1,false); + + if (pFolder2) + AddSecondFolder(items,pFolder2,false); + if (items.empty()) + { + CTreeItem *pItem=new CTreeItem(); + pItem->bFolder=false; + pItem->bEmpty=true; + pItem->SetName(FindTranslation(L"Menu.Empty",L"(Empty)"),false); + pItem->nameHash=pItem->nameHashProg=0; + pItem->pItemInfo1=pItem->pItemInfo2=NULL; + items.push_back(pItem); + } + } + } + else + { + CComPtr pRoot; + CAbsolutePidl pidl; + if (GetSettingInt(L"PinnedPrograms")==PINNED_PROGRAMS_PINNED) + { + if (SUCCEEDED(ShGetKnownFolderIDList(FOLDERID_StartMenu,&pidl))) + { + SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pRoot); + if (pRoot) + { + AddFirstFolder(items,pRoot,false); + pRoot=NULL; + } + pidl.Clear(); + } + if (!CMenuContainer::s_bNoCommonFolders && SUCCEEDED(ShGetKnownFolderIDList(FOLDERID_CommonStartMenu,&pidl))) + { + SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pRoot); + if (pRoot) + { + AddSecondFolder(items,pRoot,false); + pRoot=NULL; + } + pidl.Clear(); + } + } + if (SUCCEEDED(ShGetKnownFolderIDList(FOLDERID_Programs,&pidl))) + { + SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pRoot); + if (pRoot) + { + AddFirstFolder(items,pRoot,true); + pRoot=NULL; + for (std::vector::iterator it=items.begin();it!=items.end();++it) + { + if (ILIsEqual((*it)->pItemInfo1->GetPidl(),pidl)) + { + items.erase(it); + break; + } + } + } + pidl.Clear(); + } + if (!CMenuContainer::s_bNoCommonFolders && SUCCEEDED(ShGetKnownFolderIDList(FOLDERID_CommonPrograms,&pidl))) + { + SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pRoot); + if (pRoot) + { + AddSecondFolder(items,pRoot,true); + pRoot=NULL; + for (std::vector::iterator it=items.begin();it!=items.end();++it) + { + if (ILIsEqual((*it)->pItemInfo1->GetPidl(),pidl)) + { + items.erase(it); + break; + } + } + } + pidl.Clear(); + } + if (GetSettingBool(L"AllProgramsMetro")) + { + CTreeItem *pItem=new CTreeItem(); + pItem->bFolder=true; + pItem->bApps=true; + pItem->SetName(FindTranslation(L"Menu.Apps",L"Apps"),false); + pItem->pItemInfo1=g_ItemManager.GetCustomIcon(L",2",CItemManager::ICON_SIZE_TYPE_SMALL); + if (pItem->bFolder) + pItem->folderHash=CalcFNVHash(L"?Apps",CalcFNVHash(ORDER_PREFIX)); + pItem->pItemInfo2=NULL; + pItem->order=-1; + pItem->bNew=g_ItemManager.HasNewApps(false); + items.push_back(pItem); + } + } + unsigned int folderHash=pTreeItem?pTreeItem->folderHash:CalcFNVHash(ORDER_PREFIX); + + // load item names from the registry + std::vector hashes; + CRegKey regOrder; + if (pTreeItem) + pTreeItem->bAutoSort=false; + else + m_bAutoSort=false; + if (regOrder.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu\\Order",KEY_READ)==ERROR_SUCCESS) + { + wchar_t name[100]; + { + ULONG size=0; + Sprintf(name,_countof(name),L"%08X",folderHash); + regOrder.QueryBinaryValue(name,NULL,&size); + if (size>0 && !(size&3)) + { + hashes.resize(size/4); + regOrder.QueryBinaryValue(name,&hashes[0],&size); + } + } + } + if (hashes.size()==1 && hashes[0]=='AUTO') + { + if (pTreeItem) + pTreeItem->bAutoSort=true; + else + m_bAutoSort=true; + } + else + { + // assign each item an index based on its position in items. store in order + for (std::vector::iterator it=items.begin();it!=items.end();++it) + { + unsigned int hash=(*it)->GetNameHash(); + (*it)->order=32768; + for (int i=0;i<(int)hashes.size();i++) + { + if (hashes[i]==hash) + { + (*it)->order=i; + break; + } + } + } + } + + std::sort(items.begin(),items.end(),CmpTreeItems); +} + +void CProgramsTree::CreateFolderItems( HTREEITEM hParent ) +{ + std::vector items; + GetFolderItems(items,hParent); + + HTREEITEM hAfter=NULL; + for (std::vector::const_iterator it=items.begin();it!=items.end();++it) + { + TVINSERTSTRUCT insert={hParent,hAfter?hAfter:TVI_FIRST,{TVIF_CHILDREN|TVIF_PARAM|TVIF_TEXT}}; + insert.itemex.pszText=(LPWSTR)(LPCWSTR)(*it)->name; + insert.itemex.cChildren=(*it)->bFolder?1:0; + insert.itemex.lParam=(LPARAM)*it; + hAfter=TreeView_InsertItem(m_hWnd,&insert); + } +} + +void CProgramsTree::CreateItems( void ) +{ + TreeView_DeleteAllItems(m_hWnd); + CreateFolderItems(NULL); + RECT rc; + TreeView_GetItemRect(m_hWnd,TreeView_GetRoot(m_hWnd),&rc,TRUE); + m_RootX=rc.left; +} + +void CProgramsTree::RefreshTree( HTREEITEM hParent, const CItemManager::ItemInfo *pSelectItem ) +{ + std::vector newItems; + GetFolderItems(newItems,hParent); + int index=0; + HTREEITEM hAfter=NULL; + for (HTREEITEM hItem=hParent?TreeView_GetChild(m_hWnd,hParent):TreeView_GetRoot(m_hWnd);hItem;) + { + TVITEM item={TVIF_PARAM|TVIF_STATE,hItem,0,TVIS_SELECTED}; + TreeView_GetItem(m_hWnd,&item); + CTreeItem *pOldItem=(CTreeItem*)item.lParam; + int nextIndex=-1; + for (int i=index;i<(int)newItems.size();i++) + { + if (*pOldItem==*newItems[i]) + { + pOldItem->bNew=newItems[i]->bNew; + nextIndex=i; + break; + } + } + HTREEITEM hNext=TreeView_GetNextSibling(m_hWnd,hItem); + if (nextIndex>=0) + { + for (int i=index;iname; + insert.itemex.cChildren=newItems[i]->bFolder?1:0; + insert.itemex.lParam=(LPARAM)newItems[i]; + hAfter=TreeView_InsertItem(m_hWnd,&insert); + } + delete newItems[nextIndex]; + index=nextIndex+1; + hAfter=hItem; + } + else + { + if (item.state&TVIS_SELECTED) + TreeView_SelectItem(m_hWnd,NULL); + TreeView_DeleteItem(m_hWnd,hItem); + } + hItem=hNext; + } + for (int i=index;i<(int)newItems.size();i++) + { + TVINSERTSTRUCT insert={hParent,hAfter?hAfter:TVI_FIRST,{TVIF_CHILDREN|TVIF_PARAM|TVIF_TEXT}}; + insert.itemex.pszText=(LPWSTR)(LPCWSTR)newItems[i]->name; + insert.itemex.cChildren=newItems[i]->bFolder?1:0; + insert.itemex.lParam=(LPARAM)newItems[i]; + hAfter=TreeView_InsertItem(m_hWnd,&insert); + } + size_t count=0; + for (HTREEITEM hItem=hParent?TreeView_GetChild(m_hWnd,hParent):TreeView_GetRoot(m_hWnd);hItem;hItem=TreeView_GetNextSibling(m_hWnd,hItem)) + { + TVITEM item={TVIF_STATE|TVIF_PARAM,hItem,0,TVIS_EXPANDEDONCE}; + TreeView_GetItem(m_hWnd,&item); + if (item.state&TVIS_EXPANDEDONCE) + RefreshTree(hItem,pSelectItem); + count++; + if (pSelectItem && ((CTreeItem*)item.lParam)->pItemInfo1==pSelectItem) + TreeView_SelectItem(m_hWnd,hItem); + } + Assert(count==newItems.size()); +} + +const CProgramsTree::CTreeItem *CProgramsTree::GetSelectedItem( HTREEITEM &hItem ) +{ + hItem=TreeView_GetSelection(m_hWnd); + if (!hItem) return NULL; + TVITEM item={TVIF_PARAM,hItem}; + TreeView_GetItem(m_hWnd,&item); + return (CTreeItem*)item.lParam; +} + +bool CProgramsTree::CmpTreeItems( const CTreeItem *item1, const CTreeItem *item2 ) +{ + if (item1->order!=item2->order) return item1->orderorder; + if (!item1->bFolder && item2->bFolder) return !s_bFoldersFirst; + if (item1->bFolder && !item2->bFolder) return s_bFoldersFirst; + if (item1->bApps && !item2->bApps) return false; + if (!item1->bApps && item2->bApps) return true; + return CMenuContainer::CompareMenuString(item1->name,item2->name)<0; +} + +void CProgramsTree::SelectItem( int y ) +{ + SetFocus(); + RECT rcClient; + GetClientRect(&rcClient); + HTREEITEM hSelect=NULL, hLast=NULL; + for (HTREEITEM hItem=TreeView_GetFirstVisible(m_hWnd);hItem;hItem=TreeView_GetNextVisible(m_hWnd,hItem)) + { + RECT rc; + TreeView_GetItemRect(m_hWnd,hItem,&rc,FALSE); + if (rc.toprcClient.bottom) + break; + TVITEM item={TVIF_PARAM,hItem}; + TreeView_GetItem(m_hWnd,&item); + const CTreeItem *pItem=(CTreeItem*)item.lParam; + if (!hSelect) + hSelect=hItem; + else if (rc.top<=y && rc.bottom>y) + { + hSelect=hItem; + break; + } + hLast=hItem; + } + if (!hSelect) hSelect=hLast; + if (hSelect) + TreeView_SelectItem(m_hWnd,hSelect); +} + +void CProgramsTree::SelectFirst( void ) +{ + SetFocus(); + HTREEITEM hSelect=TreeView_GetRoot(m_hWnd); + if (hSelect) + TreeView_SelectItem(m_hWnd,hSelect); +} + +void CProgramsTree::SelectLast( void ) +{ + SetFocus(); + HTREEITEM hSelect=TreeView_GetRoot(m_hWnd); + if (!hSelect) return; + while (1) + { + for (HTREEITEM hItem=hSelect;hItem;hItem=TreeView_GetNextSibling(m_hWnd,hItem)) + hSelect=hItem; + if (!(TreeView_GetItemState(m_hWnd,hSelect,TVIS_EXPANDED)&TVIS_EXPANDED)) + break; + + HTREEITEM hChild=TreeView_GetChild(m_hWnd,hSelect); + if (!hChild) break; + hSelect=hChild; + } + TreeView_SelectItem(m_hWnd,hSelect); +} + +// IDropTarget +HRESULT CProgramsTree::DragEnter( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ) +{ + CMenuContainer::s_bRightDrag=(grfKeyState&MK_RBUTTON)!=0; + if (m_pOwner->m_pDropTargetHelper) + { + POINT p={pt.x,pt.y}; + m_pOwner->m_pDropTargetHelper->DragEnter(m_hWnd,pDataObj,&p,*pdwEffect); + } + m_pOwner->m_DragHoverTime=GetMessageTime()-10000; + m_HoverItem=NULL; + m_pOwner->m_pDragObject=pDataObj; + return S_OK; +} + +void CProgramsTree::GetDragEffect( DWORD &grfKeyState, DWORD *pdwEffect ) +{ + grfKeyState&=MK_SHIFT|MK_CONTROL|MK_ALT; + if (CMenuContainer::s_bNoDragDrop) + { + *pdwEffect=DROPEFFECT_NONE; // can't drop here + return; + } + + if (m_bDragApps) + { + *pdwEffect&=DROPEFFECT_MOVE; + return; + } + + // only accept known data formats + FORMATETC format1={CMenuContainer::s_ShellFormat,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}; + FORMATETC format2={CMenuContainer::s_ShellUrlFormat,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}; + FORMATETC format3={CMenuContainer::s_MetroLinkFormat,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}; + if (m_pOwner->m_pDragObject->QueryGetData(&format1)!=S_OK && m_pOwner->m_pDragObject->QueryGetData(&format2)!=S_OK && m_pOwner->m_pDragObject->QueryGetData(&format3)!=S_OK) + { + *pdwEffect=DROPEFFECT_NONE; + return; + } + + bool bDragApp=m_pOwner->m_pDragObject->QueryGetData(&format3)==S_OK; // dragging a wrapped metro link or the Apps folder + bool bDropApps=false; // dropping in the Apps folder + HTREEITEM hDropFolder=NULL; + if (m_DropTarget && (m_DropLocation==DROP_BEFORE || m_DropLocation==DROP_AFTER || m_DropLocation==DROP_LAST)) + hDropFolder=TreeView_GetParent(m_hWnd,m_DropTarget); + else + hDropFolder=m_DropTarget; + if (hDropFolder) + { + TVITEM item={TVIF_PARAM,hDropFolder}; + TreeView_GetItem(m_hWnd,&item); + const CTreeItem *pTreeItem=(CTreeItem*)item.lParam; + bDropApps=pTreeItem->bApps; + } + + if (CMenuContainer::s_pDragSource) + { + if (CMenuContainer::s_pDragSource->m_Items[CMenuContainer::s_pDragSource->m_DragIndex].id==MENU_RECENT) + *pdwEffect&=DROPEFFECT_LINK; // dragging a recent item (allow only link) + else if (!CMenuContainer::s_bRightDrag && grfKeyState==0 && CMenuContainer::s_bDragMovable) + *pdwEffect&=(bDragApp && !bDropApps)?DROPEFFECT_LINK:DROPEFFECT_MOVE; // dragging normal item - default to move + } + + if (bDragApp) + { + if (bDropApps) + *pdwEffect&=(m_DragItem && hDropFolder && TreeView_GetParent(m_hWnd,m_DragItem)==hDropFolder)?DROPEFFECT_MOVE:DROPEFFECT_NONE; // dragging a metro link to Apps folder + else + *pdwEffect&=DROPEFFECT_LINK; // dragging a metro link to another folder + } + + // handle keys + if (!CMenuContainer::s_bRightDrag) + { + if (grfKeyState==MK_SHIFT) + *pdwEffect&=DROPEFFECT_MOVE; + if (grfKeyState==MK_CONTROL) + *pdwEffect&=DROPEFFECT_COPY; + if (grfKeyState==(MK_CONTROL|MK_SHIFT) || grfKeyState==MK_ALT) + *pdwEffect&=DROPEFFECT_LINK; + } +} + +HRESULT CProgramsTree::DragOver( DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ) +{ + CMenuContainer::s_bRightDrag=(grfKeyState&MK_RBUTTON)!=0; + POINT p={pt.x,pt.y}; + if (m_pOwner->m_pDropTargetHelper) + { + m_pOwner->m_pDropTargetHelper->DragOver(&p,*pdwEffect); + } + ScreenToClient(&p); + + if (m_bDragApps) + { + // scroll tree during dragging Apps + if ((GetMessageTime()-m_pOwner->m_DragHoverTime)>200) + { + m_pOwner->m_DragHoverTime=GetMessageTime(); + RECT rc; + GetClientRect(&rc); + int h=TreeView_GetItemHeight(m_hWnd); + if (p.yrc.bottom-h) + SendMessage(WM_VSCROLL,SB_LINEDOWN); + } + } + + TVHITTESTINFO test={p}; + if (TreeView_HitTest(m_hWnd,&test)) + { + m_DropTarget=test.hItem; + } + else + { + HTREEITEM hLast=TreeView_GetLastVisible(m_hWnd); + if (hLast) + { + RECT rc; + TreeView_GetItemRect(m_hWnd,hLast,&rc,FALSE); + if (test.pt.y>=rc.bottom) + { + // after the last visible item + m_DropTarget=hLast; + } + } + } + + const CTreeItem *pTreeItem=NULL; + bool bAutoSort=false; + if (m_DropTarget) + { + TVITEM item={TVIF_PARAM,m_DropTarget}; + TreeView_GetItem(m_hWnd,&item); + pTreeItem=(CTreeItem*)item.lParam; + if (m_DragItem) + { + // can't drop inside itself + for (HTREEITEM hItem=TreeView_GetParent(m_hWnd,m_DropTarget);hItem;hItem=TreeView_GetParent(m_hWnd,hItem)) + { + if (hItem==m_DragItem) + { + m_DropTarget=NULL; + break; + } + } + if (m_DropTarget) + { + HTREEITEM hParent=TreeView_GetParent(m_hWnd,m_DropTarget); + if (hParent==TreeView_GetParent(m_hWnd,m_DragItem)) + { + if (hParent) + { + TVITEM parent={TVIF_PARAM,hParent}; + TreeView_GetItem(m_hWnd,&parent); + bAutoSort=((CTreeItem*)parent.lParam)->bAutoSort; + } + else + bAutoSort=m_bAutoSort; + } + } + } + } + if (m_DropTarget) + { + RECT rc; + TreeView_GetItemRect(m_hWnd,m_DropTarget,&rc,FALSE); + int dy=test.pt.y-rc.top; + if (bAutoSort) + { + if (pTreeItem->bFolder && !m_bDragApps) + m_DropLocation=DROP_INSIDE; + else + m_DropTarget=NULL; + } + else if (pTreeItem->bFolder && !m_bDragApps) + { + int h1=(rc.bottom-rc.top)/4; + int h2=(rc.bottom-rc.top)-h1; + if (dy=h2) + m_DropLocation=DROP_AFTER; + else + m_DropLocation=DROP_INSIDE; + } + else if (m_bDragApps && TreeView_GetParent(m_hWnd,m_DropTarget)) + m_DropTarget=NULL; + else + { + int h=(rc.bottom-rc.top)/2; + m_DropLocation=(dym_DragHoverTime)>(int)CMenuContainer::s_HoverTime*4) + { + TreeView_Expand(m_hWnd,m_HoverItem,TVE_EXPAND); + } + } + else + { + m_HoverItem=m_DropTarget; + m_pOwner->m_DragHoverTime=GetMessageTime(); + } + } + return S_OK; +} + +HRESULT CProgramsTree::DragLeave( void ) +{ + if (m_pOwner->m_pDropTargetHelper) + m_pOwner->m_pDropTargetHelper->DragLeave(); + m_pOwner->m_pDragObject.Release(); + TreeView_SelectDropTarget(m_hWnd,NULL); + TreeView_SetInsertMark(m_hWnd,NULL,FALSE); + m_DropLocation=DROP_NOWHERE; + return S_OK; +} + +HRESULT CProgramsTree::Drop( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ) +{ + if (CMenuContainer::s_pDragSource) + { + if (!CMenuContainer::s_pDragSource->m_bDestroyed) + CMenuContainer::s_pDragSource->KillTimer(CMenuContainer::TIMER_DRAG); + } + GetDragEffect(grfKeyState,pdwEffect); + m_pOwner->m_pDragObject.Release(); + + if (m_pOwner->m_pDropTargetHelper) + { + POINT p={pt.x,pt.y}; + m_pOwner->m_pDropTargetHelper->Drop(pDataObj,&p,*pdwEffect); + } + + std::vector order; + if (m_DropTarget && (m_DropLocation==DROP_BEFORE || m_DropLocation==DROP_AFTER || m_DropLocation==DROP_LAST)) + { + // calculate new order + HTREEITEM hParent=TreeView_GetParent(m_hWnd,m_DropTarget); + size_t dropIndex=-1; + unsigned int dragHash=0; + if (m_DragItem) + { + TVITEM item={TVIF_PARAM,m_DragItem}; + TreeView_GetItem(m_hWnd,&item); + const CTreeItem *pTreeItem=(CTreeItem*)item.lParam; + dragHash=hParent?pTreeItem->nameHash:pTreeItem->nameHashProg; + } + else + { + // get name from dragged item + CString name; + if (CMenuContainer::s_pDragSource && CMenuContainer::s_pDragSource->m_Items[CMenuContainer::s_pDragSource->m_DragIndex].pItemInfo) + { + const CItemManager::ItemInfo *pInfo=CMenuContainer::s_pDragSource->m_Items[CMenuContainer::s_pDragSource->m_DragIndex].pItemInfo; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + if (pInfo->IsMetroLink()) + name=pInfo->GetMetroName(); + } + if (name.IsEmpty()) + { + CComPtr pItem; + SHCreateItemFromIDList(pInfo->GetPidl(),IID_IShellItem,(void**)&pItem); + CComString pName; + if (pItem && (SUCCEEDED(pItem->GetDisplayName(SIGDN_PARENTRELATIVEPARSING,&pName)) || SUCCEEDED(pItem->GetDisplayName(SIGDN_NORMALDISPLAY,&pName)))) + name=pName; + } + } + else + { + // TODO: get name from data object + } + if (!name.IsEmpty()) + { + name.MakeUpper(); + unsigned int hash0=hParent?FNV_HASH0:CalcFNVHash(L"\\",FNV_HASH0); + dragHash=CalcFNVHash(name,hash0); + } + } + for (HTREEITEM hItem=hParent?TreeView_GetChild(m_hWnd,hParent):TreeView_GetRoot(m_hWnd);hItem;hItem=TreeView_GetNextSibling(m_hWnd,hItem)) + { + TVITEM item={TVIF_PARAM,hItem}; + TreeView_GetItem(m_hWnd,&item); + const CTreeItem *pTreeItem=(CTreeItem*)item.lParam; + if (hItem==m_DropTarget && m_DropLocation==DROP_BEFORE) + dropIndex=order.size(); + if (hItem!=m_DragItem) + order.push_back(pTreeItem->GetNameHash()); + if (hItem==m_DropTarget && m_DropLocation==DROP_AFTER) + dropIndex=order.size(); + } + if (m_DropLocation==DROP_LAST) + dropIndex=order.size(); + order.insert(order.begin()+dropIndex,dragHash); + + if (m_DragItem && hParent==TreeView_GetParent(m_hWnd,m_DragItem)) + { + // dropped in the same folder, just reorder + OrderElements(m_DragItem,hParent,order,false,true); + CMenuContainer::PlayMenuSound(SOUND_DROP); + m_DropTarget=NULL; + } + } + + // clear the insert mark + TreeView_SelectDropTarget(m_hWnd,NULL); + TreeView_SetInsertMark(m_hWnd,NULL,FALSE); + TDropLocation dropLocation=m_DropLocation; + m_DropLocation=DROP_NOWHERE; + if (!m_DropTarget) return 0; + + // simulate dropping the object into the original folder + CMenuContainer::PlayMenuSound(SOUND_DROP); + + if (dropLocation!=DROP_INSIDE) + { + // drop in parent folder + m_DropTarget=TreeView_GetParent(m_hWnd,m_DropTarget); + dropLocation=DROP_INSIDE; + } + + CAbsolutePidl dropFolder; + if (m_DropTarget) + { + // drop inside a folder + TVITEM item={TVIF_PARAM,m_DropTarget}; + TreeView_GetItem(m_hWnd,&item); + const CTreeItem *pTreeItem=(CTreeItem*)item.lParam; + dropFolder=pTreeItem->pItemInfo1->GetPidl(); + } + else + { + // drop at top + ShGetKnownFolderIDList(FOLDERID_Programs,&dropFolder); + } + if (!dropFolder) return E_FAIL; + + // must use IShellFolder to get to the drop target because the BindToHandler doesn't support passing the parent window (easily) + CComPtr pDesktop; + SHGetDesktopFolder(&pDesktop); + CComPtr pFolder; + CComPtr pTarget; + if (!pDesktop || FAILED(pDesktop->BindToObject(dropFolder,NULL,IID_IShellFolder,(void**)&pFolder)) || FAILED(pFolder->CreateViewObject(g_OwnerWindow,IID_IDropTarget,(void**)&pTarget))) + return S_OK; + + DWORD dwEffect=*pdwEffect; + if (CMenuContainer::s_bRightDrag) + { + if (FAILED(pTarget->DragEnter(pDataObj,MK_RBUTTON|grfKeyState,pt,&dwEffect))) + return E_FAIL; + dwEffect=*pdwEffect; + pTarget->DragOver(MK_RBUTTON|grfKeyState,pt,&dwEffect); + } + else + { + if (FAILED(pTarget->DragEnter(pDataObj,MK_LBUTTON|grfKeyState,pt,&dwEffect))) + return E_FAIL; + dwEffect=*pdwEffect; + pTarget->DragOver(MK_LBUTTON|grfKeyState,pt,pdwEffect); + } + CComQIPtr pAsync=pDataObj; + if (pAsync) + pAsync->SetAsyncMode(FALSE); + for (std::vector::iterator it=CMenuContainer::s_Menus.begin();it!=CMenuContainer::s_Menus.end();++it) + if (!(*it)->m_bDestroyed) + (*it)->EnableWindow(FALSE); // disable all menus + bool bOld=CMenuContainer::s_bPreventClosing; + CMenuContainer::s_bPreventClosing=true; + m_pOwner->AddRef(); + pTarget->Drop(pDataObj,grfKeyState,pt,pdwEffect); + if (!bOld) + CMenuContainer::HideTemp(false); + CMenuContainer::s_bPreventClosing=bOld; + for (std::vector::iterator it=CMenuContainer::s_Menus.begin();it!=CMenuContainer::s_Menus.end();++it) + if (!(*it)->m_bDestroyed) + (*it)->EnableWindow(TRUE); // enable all menus + if (!m_pOwner->m_bDestroyed) + { + SetForegroundWindow(m_pOwner->m_hWnd); + m_pOwner->SetActiveWindow(); + m_pOwner->SetHotItem(m_pOwner->m_ProgramTreeIndex); + SetFocus(); + } + if (!order.empty()) + { + OrderElements(NULL,m_DropTarget,order,false,false); + } + PostRefreshMessage(); + m_pOwner->Release(); + + return S_OK; +} + +void CProgramsTree::PostRefreshMessage( const CItemManager::ItemInfo *pSelectItem ) +{ + if (!m_bRefreshPosted && !m_pOwner->m_bDestroyed) + { + m_bRefreshPosted=true; + PostMessage(TVM_REFRESH,0,(LPARAM)pSelectItem); + } +} + +int CALLBACK CProgramsTree::CmpTreeItemsCB( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort ) +{ + const CTreeItem *pTreeItem1=(CTreeItem*)lParam1; + const CTreeItem *pTreeItem2=(CTreeItem*)lParam2; + return pTreeItem1->order-pTreeItem2->order; +} + +// reorders the tree elements and saves the order in registry +// bResort - resort the tree with the given order +void CProgramsTree::OrderElements( HTREEITEM hChild, HTREEITEM hParent, const std::vector &order, bool bAutoSort, bool bResort ) +{ + CTreeItem *pParentItem=NULL; + unsigned int folderHash; + if (hParent) + { + TVITEM item={TVIF_PARAM,hParent}; + TreeView_GetItem(m_hWnd,&item); + pParentItem=(CTreeItem*)item.lParam; + folderHash=pParentItem->folderHash; + } + else + folderHash=CalcFNVHash(ORDER_PREFIX); + + if (order.empty()) + { + if (pParentItem) + pParentItem->bAutoSort=bAutoSort; + else + m_bAutoSort=bAutoSort; + + if (hChild) + { + TVITEM item={TVIF_PARAM,hChild}; + TreeView_GetItem(m_hWnd,&item); + PostMessage(TVM_REFRESH,0,item.lParam); + } + else + PostMessage(TVM_REFRESH); + } + else if (bResort) + { + // set item order + for (HTREEITEM hItem=hParent?TreeView_GetChild(m_hWnd,hParent):TreeView_GetRoot(m_hWnd);hItem;hItem=TreeView_GetNextSibling(m_hWnd,hItem)) + { + TVITEM item={TVIF_PARAM,hItem}; + TreeView_GetItem(m_hWnd,&item); + CTreeItem *pTreeItem=(CTreeItem*)item.lParam; + pTreeItem->order=32768; + unsigned int nameHash=pTreeItem->GetNameHash(); + for (int i=0;i<(int)order.size();i++) + { + if (nameHash==order[i]) + { + pTreeItem->order=i; + break; + } + } + } + // sort by order + TVSORTCB sort={hParent,CmpTreeItemsCB,0}; + TreeView_SortChildrenCB(m_hWnd,&sort,0); + } + + // save order + CRegKey regOrder; + wchar_t name[100]; + if (regOrder.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu\\Order")!=ERROR_SUCCESS) + regOrder.Create(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu\\Order"); + + Sprintf(name,_countof(name),L"%08X",folderHash); + if (bAutoSort) + { + DWORD cAuto='AUTO'; + regOrder.SetBinaryValue(name,&cAuto,4); + } + else if (order.empty()) + regOrder.SetBinaryValue(name,NULL,0); + else + regOrder.SetBinaryValue(name,&order[0],(int)order.size()*4); +} + +// saves the item order by replacing the item with the new info +void CProgramsTree::SaveRenamedOrder( HTREEITEM hItem, const CItemManager::ItemInfo *pNewInfo ) +{ + HTREEITEM hParent=TreeView_GetParent(m_hWnd,hItem); + CTreeItem *pParentItem=NULL; + unsigned int folderHash; + if (hParent) + { + TVITEM item={TVIF_PARAM,hParent}; + TreeView_GetItem(m_hWnd,&item); + pParentItem=(CTreeItem*)item.lParam; + if (pParentItem->bAutoSort) + return; + folderHash=pParentItem->folderHash; + } + else + { + if (m_bAutoSort) + return; + folderHash=CalcFNVHash(ORDER_PREFIX); + } + + std::vector order; + for (HTREEITEM hChild=hParent?TreeView_GetChild(m_hWnd,hParent):TreeView_GetRoot(m_hWnd);hChild;hChild=TreeView_GetNextSibling(m_hWnd,hChild)) + { + TVITEM item={TVIF_PARAM,hChild}; + TreeView_GetItem(m_hWnd,&item); + const CTreeItem *pTreeItem=(CTreeItem*)item.lParam; + if (hChild==hItem) + { + CComPtr pChild; + if (FAILED(SHCreateItemFromIDList(pNewInfo->GetPidl(),IID_IShellItem,(void**)&pChild))) + return; + CComString pName; + if (FAILED(pChild->GetDisplayName(SIGDN_PARENTRELATIVEPARSING,&pName)) && FAILED(pChild->GetDisplayName(SIGDN_NORMALDISPLAY,&pName))) + return; + pName.MakeUpper(); + unsigned int hash0=pTreeItem->bPrograms?CalcFNVHash(L"\\",FNV_HASH0):FNV_HASH0; + order.push_back(CalcFNVHash(pName,hash0)); + } + else + order.push_back(pTreeItem->GetNameHash()); + } + if (order.empty()) + return; + + // save order + CRegKey regOrder; + wchar_t name[100]; + if (regOrder.Open(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu\\Order")!=ERROR_SUCCESS) + regOrder.Create(HKEY_CURRENT_USER,L"Software\\IvoSoft\\ClassicStartMenu\\Order"); + + Sprintf(name,_countof(name),L"%08X",folderHash); + regOrder.SetBinaryValue(name,&order[0],(int)order.size()*4); +} diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ProgramsTree.h b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ProgramsTree.h new file mode 100644 index 0000000..a1ec415 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/ProgramsTree.h @@ -0,0 +1,221 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#include "ItemManager.h" +#include "DragDrop.h" + +class CMenuContainer; + +class CProgramsTree: public IDropTarget, public CWindowImpl +{ +public: + enum { + TVM_REFRESH=WM_APP+1, + TIMER_HOVER=1, + }; + + struct CTreeItem + { + CString name; + unsigned int nameHashProg; // hash if the item is directly in the Programs folder + unsigned int nameHash; // hash if the item is not directly in the Programs folder + const CItemManager::ItemInfo *pItemInfo1; + const CItemManager::ItemInfo *pItemInfo2; + bool bFolder; + bool bEmpty; + bool bApps; // the Apps folder item + bool bApp; // App inside the Apps folder + bool bAutoSort; + bool bPrograms; // this item is directly in the Programs folder + bool bNew; + int order; + unsigned int folderHash; // only if bFolder + + CTreeItem( void ) { nameHash=nameHashProg=0; pItemInfo1=pItemInfo2=NULL; bFolder=bEmpty=bApps=bApp=bAutoSort=bPrograms=bNew=false; order=0; folderHash=0; } + void SetName( const wchar_t *_name, bool bNoExtensions ) + { + if (bNoExtensions) + { + const wchar_t *end=wcsrchr(_name,'.'); + if (end) + { + name=CString(_name,(int)(end-_name)); + return; + } + } + name=_name; + } + + bool operator==( const CTreeItem &item ) const { return pItemInfo1==item.pItemInfo1 && pItemInfo2==item.pItemInfo2 && name==item.name && bFolder==item.bFolder && (bFolder || bNew==item.bNew); } + unsigned int GetNameHash( void ) const { return bPrograms?nameHashProg:nameHash; } + }; + + BEGIN_MSG_MAP( CProgramsTree ) + MESSAGE_HANDLER( WM_DESTROY, OnDestroy ) + MESSAGE_HANDLER( WM_KEYDOWN, OnKeyDown ) + MESSAGE_HANDLER( WM_SYSKEYDOWN, OnSysKeyDown ) + MESSAGE_HANDLER( WM_CHAR, OnChar ) + MESSAGE_HANDLER( WM_SETFOCUS, OnSetFocus ) + MESSAGE_HANDLER( WM_MOUSEMOVE, OnMouseMove ) + MESSAGE_HANDLER( WM_MOUSELEAVE, OnMouseLeave ) + MESSAGE_HANDLER( WM_NCMOUSEMOVE, OnNcMouseMove ) + MESSAGE_HANDLER( WM_NCMOUSELEAVE, OnNcMouseLeave ) + MESSAGE_HANDLER( WM_MOUSEACTIVATE, OnMouseActivate ) + MESSAGE_HANDLER( WM_NCLBUTTONDOWN, OnNcLButtonDown) + MESSAGE_HANDLER( WM_TIMER, OnTimer ) + MESSAGE_HANDLER( WM_ERASEBKGND, OnEraseBkgnd ) + MESSAGE_HANDLER( WM_PAINT, OnPaint ) + MESSAGE_HANDLER( WM_CONTEXTMENU, OnContextMenu ) + MESSAGE_HANDLER( WM_HSCROLL, OnScroll ) + MESSAGE_HANDLER( WM_VSCROLL, OnScroll ) + MESSAGE_HANDLER( WM_MOUSEWHEEL, OnScroll ) + MESSAGE_HANDLER( TVM_SETINSERTMARK, OnSetInsertMark ) + MESSAGE_HANDLER( TVM_REFRESH, OnRefresh ) + REFLECTED_NOTIFY_CODE_HANDLER( TVN_DELETEITEM, OnDeleteItem ) + REFLECTED_NOTIFY_CODE_HANDLER( TVN_ITEMEXPANDING, OnItemExpanding ) + REFLECTED_NOTIFY_CODE_HANDLER( TVN_SINGLEEXPAND, OnSingleExpand ) + REFLECTED_NOTIFY_CODE_HANDLER( TVN_BEGINDRAG, OnBeginDrag ) + REFLECTED_NOTIFY_CODE_HANDLER( TVN_BEGINRDRAG, OnBeginDrag ) + REFLECTED_NOTIFY_CODE_HANDLER( TVN_BEGINLABELEDIT, OnBeginLabelEdit ) + REFLECTED_NOTIFY_CODE_HANDLER( TVN_ENDLABELEDIT, OnEndLabelEdit ) + REFLECTED_NOTIFY_CODE_HANDLER( TVN_GETINFOTIP, OnGetInfoTip ) + REFLECTED_NOTIFY_CODE_HANDLER( NM_CLICK, OnClick ) + REFLECTED_NOTIFY_CODE_HANDLER( NM_RCLICK, OnRClick ) + END_MSG_MAP() + + CProgramsTree( void ); + + ~CProgramsTree( void ) + { + Assert(m_RefCount==0); + } + void Create( CMenuContainer *pOwner ); + + virtual WNDPROC GetWindowProc( void ) { return CustomWindowProc; } + static LRESULT CALLBACK CustomWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + void DeleteAllItems( void ); + void CreateItems( void ); + void SelectItem( int y ); + void SelectFirst( void ); + void SelectLast( void ); + void ClearAllNew( void ); + + // reorders the tree elements and saves the order in registry + void OrderElements( HTREEITEM hChild, HTREEITEM hParent, const std::vector &order, bool bAutoSort, bool bResort ); + // saves the item order by replacing the item with the new info + void SaveRenamedOrder( HTREEITEM hItem, const CItemManager::ItemInfo *pNewInfo ); + + // IUnknown + virtual STDMETHODIMP QueryInterface( REFIID riid, void **ppvObject ) + { + Assert(0); + *ppvObject=NULL; + return E_FAIL; + } + + virtual ULONG STDMETHODCALLTYPE AddRef( void ) + { + return InterlockedIncrement(&m_RefCount); + } + + virtual ULONG STDMETHODCALLTYPE Release( void ) + { + long nTemp=InterlockedDecrement(&m_RefCount); + if (!nTemp) delete this; + return nTemp; + } + + // IDropTarget + virtual HRESULT STDMETHODCALLTYPE DragEnter( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ); + virtual HRESULT STDMETHODCALLTYPE DragOver( DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ); + virtual HRESULT STDMETHODCALLTYPE DragLeave( void ); + virtual HRESULT STDMETHODCALLTYPE Drop( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ); + + static void DrawScrollbarBackground( HDC hdc, int iPartId, int iStateId, LPCRECT pRect ); + + void DrawTree( HDC hdc, const RECT &drawRect ); + +protected: + LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnKeyDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSysKeyDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnChar( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSetFocus( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnMouseLeave( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnNcMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnNcMouseLeave( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnMouseActivate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnNcLButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnPaint( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnEraseBkgnd( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { return 1; } + LRESULT OnContextMenu( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnScroll( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSetInsertMark( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnRefresh( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnDeleteItem( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnItemExpanding( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnSingleExpand( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnBeginDrag( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnBeginLabelEdit( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnEndLabelEdit( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnGetInfoTip( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnRClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + virtual void OnFinalMessage( HWND ) { Release(); } + +private: + DWORD m_RefCount; + CMenuContainer *m_pOwner; + HIMAGELIST m_ImageList; + bool m_bHoverTimer; + bool m_bTrackMouse; + bool m_bRefreshPosted; + bool m_bAutoSort; + bool m_bDragApps; + bool m_bInsertAfter; + POINT m_LastMousePos; + int m_RootX; + int m_MinX; + int m_MaxX; + HTREEITEM m_InsertMark; + HTHEME m_TreeTheme; + HTHEME m_ScrollTheme; + + enum TDropLocation + { + DROP_NOWHERE, + DROP_INSIDE, + DROP_BEFORE, + DROP_AFTER, + DROP_LAST, + }; + + TDropLocation m_DropLocation; + HTREEITEM m_DragItem; + HTREEITEM m_DropTarget; + HTREEITEM m_HoverItem; + CComPtr m_pDropTargetProxy; + + const CTreeItem *GetSelectedItem( HTREEITEM &hItem ); + void AddFirstFolder( std::vector &items, IShellItem *pParent, bool bPrograms ); + void AddSecondFolder( std::vector &items, IShellItem *pParent, bool bPrograms ); + void AddMetroApps( std::vector &items ); + void GetFolderItems( std::vector &items, HTREEITEM hParent ); + void CreateFolderItems( IShellItem *pParent1, IShellItem *pParent2, HTREEITEM hParent ); + void CreateFolderItems( HTREEITEM hParent ); + void PostRefreshMessage( const CItemManager::ItemInfo *pSelectItem=NULL ); + void RefreshTree( HTREEITEM hParent, const CItemManager::ItemInfo *pSelectItem ); + void GetDragEffect( DWORD &grfKeyState, DWORD *pdwEffect ); + void DrawTreeItem( HDC hdc, HDC hsrc, HTREEITEM hItem, const RECT &itemRect, bool bHot ) const; + bool GetInsertRect( RECT &rc ) const; + void ClearAllNewRec( HTREEITEM hParent ); + + static bool s_bFoldersFirst; + static bool CmpTreeItems( const CTreeItem *item1, const CTreeItem *item2 ); + static int CALLBACK CmpTreeItemsCB( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort ); +}; diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SearchManager.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SearchManager.cpp new file mode 100644 index 0000000..3d4ada4 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SearchManager.cpp @@ -0,0 +1,1676 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "SearchManager.h" +#include "MenuContainer.h" +#include "MetroLinkManager.h" +#include "Settings.h" +#include "SettingsUIHelper.h" +#include "SettingsUI.h" +#include "FNVHash.h" +#include "ResourceHelper.h" +#include "LogManager.h" +#include "Translations.h" +#include +#include +#include +#include + +// attempt to get more accurate PIDLs for the search results by laundering them through a search folder. +// this produces better search items for the CSC search connector (better icons and behavior) but is slow. +//#define LAUNDER_SEARCH_RESULTS + +CSearchManager g_SearchManager; +const CLSID CLSID_CSearchManager2={0x7D096C5F,0xAC08,0x4f1f,{0xBE,0xB7,0x5C,0x22,0xC5,0x17,0xCE,0x39}}; + +const int RANK_LIST_VERSION=1; +const int RANK_LIST_SIZE=256; + +CSearchManager::CSearchManager( void ) +{ + m_bInitialized=false; + m_bRanksLoaded=false; + memset(m_CriticalSections,0,sizeof(m_CriticalSections)); + memset(m_CriticalSectionOwners,0,sizeof(m_CriticalSectionOwners)); + m_SearchEvent=NULL; + m_ExitEvent=NULL; + memset(m_SearchThreads,0,sizeof(m_SearchThreads)); + m_MainThreadId=0; + m_LastRequestId=0; + m_LastCompletedId=0; + m_LastProgramsRequestId=0; + m_SearchThreadCount=0; + m_bProgramsFound=m_bSettingsFound=false; + m_ProgramsHash=m_ProgramsHashOld=m_SettingsHash=m_SettingsHashOld=FNV_HASH0; +} + +CSearchManager::~CSearchManager( void ) +{ + Close(); +} + +void CSearchManager::Init( void ) +{ + m_bInitialized=true; + for (int i=0;i='A' && str[0]<='Z' && str[1]==':') + { + const wchar_t *end=wcsrchr(str+2,'\\'); + if (end) + return searchText.Left((int)(end-str)); + return searchText; + } + if (str[0]=='\\' && str[1]=='\\') + { + const wchar_t *end=wcsrchr(str+2,'\\'); + if (end) + return searchText.Left((int)(end-str)); + } + if (str[0]=='%') + { + const wchar_t *end=wcsrchr(str+1,'\\'); + if (end) + return searchText.Left((int)(end-str)); + } + } + return CString(); +} + +void CSearchManager::BeginSearch( const CString &searchText ) +{ + Assert(GetCurrentThreadId()==m_MainThreadId); + + { + Lock lock(this,LOCK_DATA); + m_SearchText=searchText; + + // initialize the request with unique ID + m_SearchRequest.requestId=++m_LastRequestId; + m_SearchRequest.bSearchPrograms=GetSettingBool(L"SearchPrograms"); + m_SearchRequest.bSearchPath=GetSettingBool(L"SearchPath"); + m_SearchRequest.bSearchMetroApps=GetSettingBool(L"SearchMetroApps"); + m_SearchRequest.bSearchMetroSettings=GetSettingBool(L"SearchMetroSettings"); + m_SearchRequest.bSearchSettings=m_SearchRequest.bSearchPrograms; //GetSettingBool(L"SearchSettings"); + m_SearchRequest.bSearchKeywords=GetSettingBool(L"SearchKeywords"); + m_SearchRequest.bSearchFiles=GetSettingBool(L"SearchFiles"); + m_SearchRequest.bSearchMetadata=GetSettingBool(L"SearchContents"); + m_SearchRequest.bSearchTypes=GetSettingBool(L"SearchCategories"); + m_SearchRequest.bSearchSubWord=GetSettingBool(L"SearchSubWord"); + m_SearchRequest.bUseRanks=GetSettingBool(L"SearchTrack"); + m_SearchRequest.bNoCommonFolders=(SHRestricted(REST_NOCOMMONGROUPS)!=0); + m_SearchRequest.bPinnedFolder=(GetSettingInt(L"PinnedPrograms")==PINNED_PROGRAMS_PINNED); + m_SearchRequest.searchText=searchText; + m_SearchRequest.autoCompletePath=ParseAutoCompletePath(searchText); + } + SetEvent(m_SearchEvent); +} + +void CSearchManager::CloseMenu( void ) +{ + Lock lock(this,LOCK_DATA); + m_LastRequestId++; + m_LastProgramsRequestId=m_LastRequestId; + if (g_LogCategories&LOG_SEARCH) + { + for (std::vector::const_iterator it=m_ProgramItems.begin();it!=m_ProgramItems.end();++it) + { + if (it->category==CATEGORY_PROGRAM) + LOG_MENU(LOG_SEARCH,L"Program: '%s', %d",it->name,it->rank); + } + std::sort(m_SettingsItems.begin(),m_SettingsItems.end()); + for (std::vector::const_iterator it=m_SettingsItems.begin();it!=m_SettingsItems.end();++it) + { + if (it->category==CATEGORY_SETTING) + LOG_MENU(LOG_SEARCH,L"Setting: '%s', %d",it->name,it->rank); + } + } + if (m_bProgramsFound) + { + m_ProgramItemsOld.swap(m_ProgramItems); + m_ProgramsHashOld=m_ProgramsHash; + } + m_ProgramItems.clear(); + m_ProgramsHash=FNV_HASH0; + m_bProgramsFound=false; + + if (m_bSettingsFound) + { + m_SettingsItemsOld.swap(m_SettingsItems); + m_SettingsHashOld=m_SettingsHash; + } + m_SettingsItems.clear(); + m_SettingsHash=FNV_HASH0; + m_bSettingsFound=false; + + m_IndexedItems.clear(); + m_AutoCompleteItems.clear(); + m_AutoCompletePath.Empty(); + m_LastAutoCompletePath.Empty(); +} + +bool CSearchManager::CmpRankTime( const CSearchManager::ItemRank &rank1, const CSearchManager::ItemRank &rank2 ) +{ + return rank1.lastTime>rank2.lastTime; +} + +unsigned int CSearchManager::CalcItemsHash( const std::vector &items ) +{ + unsigned int hash=FNV_HASH0; + for (std::vector::const_iterator it=items.begin();it!=items.end();++it) + { + hash=CalcFNVHash(&it->category,sizeof(TItemCategory),hash); + hash=CalcFNVHash(it->name,hash); + hash=CalcFNVHash(it->keywords,hash); + hash=CalcFNVHash(&it->pInfo,sizeof(void*),hash); + hash=CalcFNVHash(&it->rank,sizeof(int),hash); + hash=CalcFNVHash(&it->bMetroLink,sizeof(bool),hash); + } + return hash; +} + +void CSearchManager::LoadItemRanks( void ) +{ + Assert(GetCurrentThreadId()==m_MainThreadId); + Lock lock(this,LOCK_RANKS); + m_ItemRanks.clear(); + if (GetSettingBool(L"SearchTrack")) + { + CRegKey regKey; + if (regKey.Open(HKEY_CURRENT_USER,GetSettingsRegPath(),KEY_READ)==ERROR_SUCCESS) + { + ULONG size=0; + regKey.QueryBinaryValue(L"ItemRanks",NULL,&size); + if (size>0 && (size%sizeof(ItemRank))==0) + { + m_ItemRanks.resize(size/sizeof(ItemRank)); + regKey.QueryBinaryValue(L"ItemRanks",&m_ItemRanks[0],&size); + if (m_ItemRanks[0].hash!='CLSH' || m_ItemRanks[0].rank!=RANK_LIST_VERSION) + m_ItemRanks.clear(); + else if (m_ItemRanks.size()>RANK_LIST_SIZE) + { + std::sort(m_ItemRanks.begin()+1,m_ItemRanks.end(),CmpRankTime); + m_ItemRanks.resize(RANK_LIST_SIZE); + } + } + } + if (m_ItemRanks.empty()) + { + ItemRank rank('CLSH',RANK_LIST_VERSION); + m_ItemRanks.push_back(rank); + } + std::sort(m_ItemRanks.begin()+1,m_ItemRanks.end()); + } + m_bRanksLoaded=true; +} + +void CSearchManager::AddItemRank( unsigned int hash ) +{ + Assert(GetCurrentThreadId()==m_MainThreadId); + Assert(m_bRanksLoaded); + Lock lock(this,LOCK_RANKS); + if (GetSettingBool(L"SearchTrack")) + { + FILETIME curTime; + GetSystemTimeAsFileTime(&curTime); + ItemRank rank(hash,1,curTime.dwHighDateTime); + std::vector::iterator it=std::lower_bound(m_ItemRanks.begin()+1,m_ItemRanks.end(),rank); + if (it!=m_ItemRanks.end() && it->hash==rank.hash) + { + it->rank++; + it->lastTime=curTime.dwHighDateTime; + } + else + { + m_ItemRanks.push_back(rank); + std::sort(m_ItemRanks.begin()+1,m_ItemRanks.end()); + } + } + else + { + m_ItemRanks.clear(); + ItemRank rank('CLSH',RANK_LIST_VERSION); + m_ItemRanks.push_back(rank); + } + CRegKey reg; + if (reg.Open(HKEY_CURRENT_USER,GetSettingsRegPath())!=ERROR_SUCCESS) + reg.Create(HKEY_CURRENT_USER,GetSettingsRegPath()); + + reg.SetBinaryValue(L"ItemRanks",&m_ItemRanks[0],sizeof(ItemRank)*(int)m_ItemRanks.size()); +} + +// Extensions to look for in the PATH directories +static const wchar_t *g_pProgramExtensions[]= +{ + L".EXE", + L".COM", + L".BAT", + L".CMD", + L".MSC", + L".CPL", + L".SCR", +}; + +bool CSearchManager::AddSearchItem( IShellItem *pItem, const wchar_t *name, int flags, TItemCategory category, SearchRequest &searchRequest ) +{ + CAbsolutePidl pidl; + if (FAILED(SHGetIDListFromObject(pItem,&pidl))) + return false; + + SearchItem item; + item.category=CATEGORY_INVALID; + item.pInfo=g_ItemManager.GetItemInfo(pItem,pidl,CItemManager::INFO_LINK|((flags&COLLECT_METRO)?CItemManager::INFO_METRO:0)); + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + item.bMetroLink=item.pInfo->IsMetroLink(); + if ((flags&COLLECT_ONLY_METRO) && !item.bMetroLink) + return false; + if (item.bMetroLink && (!searchRequest.bSearchMetroApps || _wcsicmp(item.pInfo->GetAppid(),DESKTOP_APP_ID)==0)) + return false; + item.category=category; + if (item.bMetroLink) + { + item.name=item.pInfo->GetMetroName(); + StringUpper(item.name); + } + else + item.name=name; + } + if (flags&COLLECT_KEYWORDS) + { + CComQIPtr pItem2=pItem; + PROPVARIANT val; + PropVariantInit(&val); + pItem2->GetProperty(PKEY_Keywords,&val); + wchar_t keywords[1024]; + int len=0; + if (val.vt==VT_BSTR || val.vt==VT_LPWSTR) + { + len+=Strcpy(keywords+len,_countof(keywords)-len,L";"); + len+=Strcpy(keywords+len,_countof(keywords)-len,val.pwszVal); + } + else if (val.vt==(VT_VECTOR|VT_BSTR) || val.vt==(VT_VECTOR|VT_LPWSTR)) + { + for (ULONG i=0;i0) + { + CharUpper(keywords); + item.keywords+=keywords; + } + PropVariantClear(&val); + } + + Lock lock(this,LOCK_DATA); + if (category==CATEGORY_PROGRAM || category==CATEGORY_SETTING) + { + if (searchRequest.requestId &items=(category==CATEGORY_PROGRAM)?m_ProgramItems:m_SettingsItems; + if (category==CATEGORY_SETTING) + { + // remove duplicate settings + for (std::vector::const_iterator it=items.begin();it!=items.end();++it) + { + if (wcscmp(it->name,item.name)==0 && it->bMetroLink==item.bMetroLink) + { + item.category=CATEGORY_INVALID; + break; + } + } + } + + if (searchRequest.bUseRanks) + { + Lock lock(this,LOCK_RANKS); + Assert(m_bRanksLoaded); + unsigned int hash; + CComString pName; + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_PARENTRELATIVEPARSING,&pName))) + { + pName.MakeUpper(); + hash=CalcFNVHash(pName); + } + else + hash=CalcFNVHash(item.name); + ItemRank rank(hash); + std::vector::const_iterator it=std::lower_bound(m_ItemRanks.begin()+1,m_ItemRanks.end(),rank); + if (it!=m_ItemRanks.end() && it->hash==rank.hash) + item.rank=it->rank*2; + } + + items.push_back(item); + } + else if (category==CATEGORY_AUTOCOMPLETE) + { + item.rank=(flags&COLLECT_IS_FOLDER)?1:0; + m_AutoCompleteItems.push_back(item); + } + if (!(flags&COLLECT_NOREFRESH)) + { + DWORD time=GetTickCount(); + int dt=(time-searchRequest.searchTime); + if (dt>1000) + { + CMenuContainer::RefreshSearch(); + searchRequest.searchTime=time; + } + } + return res; +} + +void CSearchManager::CollectSearchItems( IShellItem *pFolder, int flags, TItemCategory category, SearchRequest &searchRequest ) +{ + CComPtr pEnum; + pFolder->BindToHandler(NULL,BHID_EnumItems,IID_IEnumShellItems,(void**)&pEnum); + if (!pEnum) return; + + CComPtr pChild; + while (pChild=NULL,pEnum->Next(1,&pChild,NULL)==S_OK) + { + if (category==CATEGORY_PROGRAM || category==CATEGORY_SETTING) + { + if (searchRequest.requestIdGetAttributes(SFGAO_FOLDER|SFGAO_STREAM|SFGAO_LINK|SFGAO_HIDDEN,&itemFlags))) + { + if (itemFlags&SFGAO_HIDDEN) + continue; + if ((flags&COLLECT_RECURSIVE) && (itemFlags&(SFGAO_FOLDER|SFGAO_STREAM|SFGAO_LINK))==SFGAO_FOLDER) + { + // go into subfolders but not archives or links to folders + CollectSearchItems(pChild,flags,category,searchRequest); + if (category==CATEGORY_PROGRAM || category==CATEGORY_SETTING) + { + if (searchRequest.requestIdGetDisplayName((flags&COLLECT_PROGRAMS)?SIGDN_PARENTRELATIVEPARSING:SIGDN_PARENTRELATIVEEDITING,&pName))) + { + pName.MakeUpper(); + bool bSkip=false; + if (flags&COLLECT_PROGRAMS) + { + bSkip=true; + const wchar_t *ext=PathFindExtension(pName); + for (int i=0;i<_countof(g_pProgramExtensions);i++) + if (wcscmp(ext,g_pProgramExtensions[i])==0) + { + bSkip=false; + break; + } + } + if (!bSkip) + AddSearchItem(pChild,pName,flags|((itemFlags&SFGAO_FOLDER)?COLLECT_IS_FOLDER:0),category,searchRequest); + } + } + } + } +} + +bool CSearchManager::SearchScope::ParseSearchConnector( const wchar_t *fname ) +{ + CComPtr pDoc; + if (FAILED(pDoc.CoCreateInstance(L"Msxml2.FreeThreadedDOMDocument"))) + return false; + pDoc->put_async(VARIANT_FALSE); + VARIANT_BOOL loaded; + if (pDoc->load(CComVariant(fname),&loaded)!=S_OK || loaded!=VARIANT_TRUE) + return false; + + CComPtr pRoot; + HRESULT res=pDoc->selectSingleNode(CComBSTR(L"searchConnectorDescription"),&pRoot); + if (res!=S_OK) return false; + + CComPtr pScope; + res=pRoot->selectSingleNode(CComBSTR(L"scope"),&pScope); + if (res==S_OK) + { + CComPtr pScopeItem; + pScope->get_firstChild(&pScopeItem); + while (pScopeItem) + { + CComBSTR name; + pScopeItem->get_nodeName(&name); + if (_wcsicmp(name,L"scopeItem")==0) + { + CComPtr pUrl; + CComBSTR url; + if (pScopeItem->selectSingleNode(CComBSTR(L"url"),&pUrl)==S_OK && pUrl->get_text(&url)==S_OK) + { + if (_wcsnicmp(url,L"file:",5)==0) + return false; // ignore files + CComPtr pMode, pDepth; + CComBSTR mode, depth; + bool bExclude=(pScopeItem->selectSingleNode(CComBSTR(L"mode"),&pMode)==S_OK && pMode->get_text(&mode)==S_OK && _wcsicmp(mode,L"exclude")==0); + bool bShallow=(pScopeItem->selectSingleNode(CComBSTR(L"depth"),&pDepth)==S_OK && pDepth->get_text(&depth)==S_OK && _wcsicmp(depth,L"shallow")==0); + CString url2; + if (bExclude) + url2.Format(bShallow?L"-=%s":L"-%s",(const wchar_t*)url); + else + url2.Format(bShallow?L"=%s":L"%s",(const wchar_t*)url); + StringUpper(url2); + roots.push_back(url2); + } + } + + CComPtr pNext; + if (pScopeItem->get_nextSibling(&pNext)!=S_OK) + break; + pScopeItem=pNext; + } + return true; + } + + CComPtr pTemplate; + res=pRoot->selectSingleNode(CComBSTR(L"templateInfo"),&pTemplate); + if (res==S_OK) + { + CComPtr pType; + res=pTemplate->selectSingleNode(CComBSTR(L"folderType"),&pType); + if (res==S_OK) + { + CComBSTR type; + bCommunications=(pType->get_text(&type)==S_OK && _wcsicmp(type,L"{91475FE5-586B-4EBA-8D75-D17434B8CDF6}")==0); + } + } + + res=pRoot->selectSingleNode(CComBSTR(L"simpleLocation"),&pScope); + if (res==S_OK) + { + CComPtr pUrl; + res=pScope->selectSingleNode(CComBSTR(L"url"),&pUrl); + if (res!=S_OK) return false; + CComBSTR url; + if (pUrl->get_text(&url)!=S_OK) + return false; + if (_wcsnicmp(url,L"file:",5)==0) + return false; // ignore files + CString url2=url; + StringUpper(url2); + roots.push_back(url2); + return true; + } + return false; +} + +void CSearchManager::SearchThread( void ) +{ + HANDLE events[2]={m_SearchEvent,m_ExitEvent}; + SearchRequest searchRequest; + searchRequest.requestId=-1; + InterlockedIncrement(&m_SearchThreadCount); + while (1) + { + if (searchRequest.requestId==m_LastRequestId) + { + Lock lock(this,LOCK_DATA); + if (searchRequest.requestId==m_LastRequestId) + { + m_LastCompletedId=searchRequest.requestId; + CMenuContainer::RefreshSearch(); + } + } + long count=InterlockedDecrement(&m_SearchThreadCount); +// Trace(L"Search thread count: %d",count); + if (WaitForMultipleObjects(2,events,FALSE,INFINITE)!=WAIT_OBJECT_0) + break; + count=InterlockedIncrement(&m_SearchThreadCount); +// Trace(L"Search thread count: %d",count); + { + Lock lock(this,LOCK_DATA); + if (m_SearchRequest.requestId!=m_LastRequestId) + continue; + searchRequest=m_SearchRequest; + m_SearchRequest.requestId=0; + m_IndexedItems.clear(); + if (!searchRequest.autoCompletePath.IsEmpty() && searchRequest.autoCompletePath==m_LastAutoCompletePath) + continue; + m_AutoCompleteItems.clear(); + m_AutoCompletePath=searchRequest.autoCompletePath; + m_LastAutoCompletePath.Empty(); + } +// Trace(L"Search request: %d",searchRequest.requestId); + + searchRequest.searchTime=GetTickCount(); + + // find programs + if (searchRequest.autoCompletePath.IsEmpty()) + { + if (searchRequest.searchText.IsEmpty() || wcsncmp(searchRequest.searchText,L"\\\\",2)==0) + continue; + Lock lock(this,LOCK_PROGRAMS); + if (searchRequest.requestId pFolder; + if (SUCCEEDED(ShGetKnownFolderItem(FOLDERID_StartMenu,&pFolder))) + CollectSearchItems(pFolder,COLLECT_RECURSIVE|COLLECT_METRO|COLLECT_NOREFRESH,CATEGORY_PROGRAM,searchRequest); + if (searchRequest.requestId pFolder; + if (SUCCEEDED(ShGetKnownFolderItem(FOLDERID_CommonStartMenu,&pFolder))) + CollectSearchItems(pFolder,COLLECT_RECURSIVE|COLLECT_METRO|COLLECT_NOREFRESH,CATEGORY_PROGRAM,searchRequest); + if (searchRequest.requestId pFolder; + if (SUCCEEDED(SHCreateItemFromParsingName(path,NULL,IID_IShellItem,(void**)&pFolder))) + CollectSearchItems(pFolder,COLLECT_METRO|COLLECT_NOREFRESH,CATEGORY_PROGRAM,searchRequest); + if (searchRequest.requestId pFolder; + if (SUCCEEDED(ShGetKnownFolderItem(FOLDERID_Games,&pFolder))) + CollectSearchItems(pFolder,COLLECT_RECURSIVE|COLLECT_METRO|COLLECT_NOREFRESH,CATEGORY_PROGRAM,searchRequest); + if (searchRequest.requestId pFolder; + if (SUCCEEDED(SHCreateItemFromParsingName(token,NULL,IID_IShellItem,(void**)&pFolder))) + CollectSearchItems(pFolder,COLLECT_PROGRAMS|COLLECT_NOREFRESH,CATEGORY_PROGRAM,searchRequest); + if (searchRequest.requestId=WIN_VER_WIN8 && searchRequest.bSearchMetroApps) + { + std::vector links; + GetMetroLinks(links,false); + for (std::vector::const_iterator it=links.begin();it!=links.end();++it) + { + if (GetWinVersion()pItem,L"",COLLECT_PROGRAMS|COLLECT_METRO|COLLECT_ONLY_METRO,CATEGORY_PROGRAM,searchRequest); + else + { + CComString pName; + if (SUCCEEDED(it->pItem->GetDisplayName(SIGDN_NORMALDISPLAY,&pName))) + AddSearchItem(it->pItem,pName,COLLECT_PROGRAMS|COLLECT_METRO,CATEGORY_PROGRAM,searchRequest); + } + if (searchRequest.requestId pFolder; + if (SUCCEEDED(ShGetKnownFolderItem(FOLDERID_ControlPanelFolder,&pFolder))) + CollectSearchItems(pFolder,COLLECT_FOLDERS|COLLECT_NOREFRESH,CATEGORY_SETTING,searchRequest); + if (searchRequest.requestId pFolder; + if (SUCCEEDED(ShGetKnownFolderItem(FOLDERID_AdminTools,&pFolder))) + CollectSearchItems(pFolder,COLLECT_RECURSIVE|COLLECT_NOREFRESH,CATEGORY_SETTING,searchRequest); + if (searchRequest.requestId pFolder; + if (SUCCEEDED(ShGetKnownFolderItem(FOLDERID_CommonAdminTools,&pFolder))) + CollectSearchItems(pFolder,COLLECT_RECURSIVE|COLLECT_NOREFRESH,CATEGORY_SETTING,searchRequest); + if (searchRequest.requestId pFolder; + if (SUCCEEDED(SHCreateItemFromParsingName(L"shell:::{ED7BA470-8E54-465E-825C-99712043E01C}",NULL,IID_IShellItem,(void**)&pFolder))) + CollectSearchItems(pFolder,(searchRequest.bSearchKeywords?COLLECT_KEYWORDS:0)|COLLECT_NOREFRESH,CATEGORY_SETTING,searchRequest); + if (searchRequest.requestId pFolder; + wchar_t path[_MAX_PATH]; + Strcpy(path,_countof(path),searchRequest.autoCompletePath); + DoEnvironmentSubst(path,_countof(path)); + if (SUCCEEDED(SHCreateItemFromParsingName(path,NULL,IID_IShellItem,(void**)&pFolder))) + { + SFGAOF itemFlags; + if (SUCCEEDED(pFolder->GetAttributes(SFGAO_FOLDER|SFGAO_STREAM|SFGAO_LINK,&itemFlags)) && (itemFlags&(SFGAO_FOLDER|SFGAO_STREAM|SFGAO_LINK))==SFGAO_FOLDER) + CollectSearchItems(pFolder,COLLECT_FOLDERS,CATEGORY_AUTOCOMPLETE,searchRequest); + } + { + Lock lock(this,LOCK_DATA); + if (searchRequest.requestId==m_LastRequestId) + m_LastAutoCompletePath=searchRequest.autoCompletePath; + } + continue; + } + + if (searchRequest.requestId!=m_LastRequestId || (!searchRequest.bSearchFiles && !searchRequest.bSearchMetroSettings)) + continue; + CMenuContainer::RefreshSearch(); + searchRequest.searchTime=GetTickCount(); + + CDataSource dataSource; + CSession session; + if (SUCCEEDED(dataSource.OpenFromInitializationString(L"provider=Search.CollatorDSO.1;EXTENDED PROPERTIES=\"Application=Windows\"")) && SUCCEEDED(session.Open(dataSource))) + { + std::list scopeList; + + if (searchRequest.bSearchMetroSettings) + { + scopeList.push_back(SearchScope()); + SearchScope &scope=*scopeList.rbegin(); + scope.bFiles=true; + scope.name=FindTranslation(L"Search.CategoryPCSettings",L"PC settings"); + scope.categoryHash=CATEGORY_METROSETTING; + scope.roots.push_back(L"FILE:"); + } + if (searchRequest.bSearchFiles) + { + // prepare roots + CComPtr pLibrary; + pLibrary.CoCreateInstance(CLSID_ShellLibrary); + if (searchRequest.bSearchTypes && pLibrary) + { + CComPtr pLibraries; + std::vector> libraries; + static KNOWNFOLDERID defaultLibraries[]= + { + FOLDERID_DocumentsLibrary, + FOLDERID_MusicLibrary, + FOLDERID_PicturesLibrary, + FOLDERID_VideosLibrary, + }; + { + for (int i=0;i<_countof(defaultLibraries);i++) + { + CComPtr pItem; + if (SUCCEEDED(ShGetKnownFolderItem(defaultLibraries[i],&pItem))) + libraries.push_back(pItem); + } + } + if (SUCCEEDED(ShGetKnownFolderItem(FOLDERID_Libraries,&pLibraries))) + { + CComPtr pEnum; + pLibraries->BindToHandler(NULL,BHID_EnumItems,IID_IEnumShellItems,(void**)&pEnum); + if (pEnum) + { + CComPtr pItem; + while (pItem=NULL,pEnum->Next(1,&pItem,NULL)==S_OK) + { + bool bFound=false; + for (size_t i=0;iCompare(pItem,SICHINT_CANONICAL,&order)) && order) + { + bFound=true; + break; + } + } + if (!bFound) + libraries.push_back(pItem); + } + } + } + for (std::vector>::const_iterator it=libraries.begin();it!=libraries.end();++it) + { + if (!*it) continue; + CComString pName; + if (SUCCEEDED(pLibrary->LoadLibraryFromItem(*it,STGM_READ)) && SUCCEEDED((*it)->GetDisplayName(SIGDN_NORMALDISPLAY,&pName))) + { + scopeList.push_back(SearchScope()); + SearchScope &scope=*scopeList.rbegin(); + scope.bFiles=true; + scope.name=pName; + LOG_MENU(LOG_SEARCH,L"Category: %s",scope.name); + SHGetIDListFromObject(*it,&scope.search); + scope.categoryHash=CATEGORY_FILE; + CComString pName2; + if (SUCCEEDED((*it)->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName2))) + scope.categoryHash|=(CalcFNVHash(pName)&~CATEGORY_MASK); + CComPtr pArray; + if (SUCCEEDED(pLibrary->GetFolders(LFF_FORCEFILESYSTEM,IID_IShellItemArray,(void**)&pArray)) && pArray) + { + CComPtr pEnum2; + if (SUCCEEDED(pArray->EnumItems(&pEnum2)) && pEnum2) + { + CComPtr pFolder; + while (pFolder=NULL,pEnum2->Next(1,&pFolder,NULL)==S_OK) + { + CComString pPath; + if (SUCCEEDED(pFolder->GetDisplayName(SIGDN_FILESYSPATH,&pPath)) && pPath) + { + pPath.MakeUpper(); + for (wchar_t *str=(wchar_t*)(const wchar_t*)pPath;*str;str++) + if (*str=='\\') + *str='/'; + CString path; + path.Format(L"FILE:%s/",pPath); + path.Replace(L"'",L"''"); + scope.roots.push_back(path); + LOG_MENU(LOG_SEARCH,L" Scope: %s",path); + } + } + } + } + if (scope.roots.empty()) + scopeList.pop_back(); + } + } + } + else + { + // one for files + scopeList.push_back(SearchScope()); + SearchScope &scope=*scopeList.rbegin(); + scope.bFiles=true; + scope.name=FindTranslation(L"Search.CategoryFiles",L"Files"); + scope.categoryHash=CATEGORY_FILE; + scope.categoryHash|=(CalcFNVHash(L"Files")&~CATEGORY_MASK); + scope.roots.push_back(L"FILE:"); + } + { + // search connectors + CComPtr pSearches; + if (SUCCEEDED(ShGetKnownFolderItem(FOLDERID_SavedSearches,&pSearches))) + { + CComPtr pEnum; + pSearches->BindToHandler(NULL,BHID_EnumItems,IID_IEnumShellItems,(void**)&pEnum); + PROPERTYKEY keyStartMenu; + PSGetPropertyKeyFromName(L"System.StartMenu.IncludeInScope",&keyStartMenu); + if (pEnum) + { + CComPtr pItem; + while (pItem=NULL,pEnum->Next(1,&pItem,NULL)==S_OK) + { + CComString pName; + pItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,&pName); + LOG_MENU(LOG_SEARCH,L"Search Root: %s",(const wchar_t*)pName); + if (_wcsicmp(PathFindExtension(pName),L".searchconnector-ms")!=0) + { + LOG_MENU(LOG_SEARCH,L"Ignoring: not a search connector"); + continue; + } + CComPtr pStore; + pItem->BindToHandler(NULL,BHID_PropertyStore,IID_IPropertyStore,(void**)&pStore); + if (!pStore) + { + LOG_MENU(LOG_SEARCH,L"Ignoring: no store"); + continue; + } + PROPVARIANT val; + PropVariantInit(&val); + if (FAILED(pStore->GetValue(keyStartMenu,&val))) + { + LOG_MENU(LOG_SEARCH,L"Ignoring: no start menu1"); + continue; + } + bool bStartMenu=(val.vt==VT_BOOL && val.boolVal); + PropVariantClear(&val); + if (!bStartMenu) + { + LOG_MENU(LOG_SEARCH,L"Ignoring: no start menu2"); + continue; + } + scopeList.push_back(SearchScope()); + SearchScope &scope=*scopeList.rbegin(); + if (!scope.ParseSearchConnector(pName)) + { + scopeList.pop_back(); + LOG_MENU(LOG_SEARCH,L"Ignoring: failed to parse searchconnector-ms"); + continue; + } + if (GetWinVersion()>=WIN_VER_WIN10) + { + // ignore search connector using the WINRT scope - looks like it just duplicates the last search + bool bWinRT=false; + for (std::vector::const_iterator it=scope.roots.begin();it!=scope.roots.end();++it) + { + if (wcsncmp(*it,L"WINRT://",8)==0) + { + bWinRT=true; + break; + } + } + if (bWinRT) + { + scopeList.pop_back(); + LOG_MENU(LOG_SEARCH,L"Ignoring: uses WINRT scope"); + continue; + } + } + scope.bFiles=false; + SHGetIDListFromObject(pItem,&scope.search); + scope.categoryHash=CATEGORY_ITEM; + scope.categoryHash|=(CalcFNVHash(pName)&~CATEGORY_MASK); + pName.Clear(); + pItem->GetDisplayName(SIGDN_NORMALDISPLAY,&pName); + scope.name=pName; + LOG_MENU(LOG_SEARCH,L"Category: %s",scope.name); + if (g_LogCategories&LOG_SEARCH) + { + for (std::vector::const_iterator it=scope.roots.begin();it!=scope.roots.end();++it) + LOG_MENU(LOG_SEARCH,L" Scope: %s",*it); + } + } + } + } + } + if (searchRequest.bSearchTypes && pLibrary) + { + // one for uncategorized files + scopeList.push_back(SearchScope()); + SearchScope &scope=*scopeList.rbegin(); + scope.bFiles=true; + scope.name=FindTranslation(L"Search.CategoryFiles",L"Files"); + scope.categoryHash=CATEGORY_FILE; + scope.roots.push_back(L"FILE:"); + } + } + + const wchar_t *columns=L"System.ItemUrl, System.ItemType, Path, System.ItemPathDisplay, System.ItemNameDisplay"; + const wchar_t *order=L"System.Search.Rank DESC, System.DateModified DESC, System.ItemNameDisplay ASC"; + const wchar_t *orderComm=L"System.Contact.FileAsName ASC, System.Message.DateReceived DESC, System.Search.Rank DESC"; + + CComPtr pStore; + pStore.CoCreateInstance(CLSID_InMemoryPropertyStore); + if (!pStore) continue; + CComPtr pBindCtx0; + CreateBindCtx(0,&pBindCtx0); + if (!pBindCtx0) continue; + pBindCtx0->RegisterObjectParam(STR_PARSE_WITH_PROPERTIES,pStore); + +#ifdef LAUNDER_SEARCH_RESULTS + CComPtr pSearchFactory; + pSearchFactory.CoCreateInstance(CLSID_SearchFolderItemFactory); + if (!pSearchFactory) continue; + CComPtr pConditionFactory; + pConditionFactory.CoCreateInstance(CLSID_ConditionFactory); + if (!pConditionFactory) continue; +#endif + + CCommand,CRowset> command0; + + { + CComPtr pSearchManager; + pSearchManager.CoCreateInstance(CLSID_CSearchManager2); + if (!pSearchManager) continue; + CComPtr pCatalogManager; + pSearchManager->GetCatalog(L"SystemIndex",&pCatalogManager); + if (!pCatalogManager) continue; + CComPtr pQueryHelper; + pCatalogManager->GetQueryHelper(&pQueryHelper); + if (!pQueryHelper) continue; + pQueryHelper->put_QuerySelectColumns(columns); + pQueryHelper->put_QuerySorting(order); + pQueryHelper->put_QueryWhereRestrictions(L"AND NOT System.Shell.SFGAOFlagsStrings = SOME ARRAY['superhidden'] AND System.Shell.OmitFromView!='true'"); + if (!searchRequest.bSearchMetadata) + pQueryHelper->put_QueryContentProperties(L"System.ItemNameDisplay"); + CComString pQuery; + pQueryHelper->GenerateSQLFromUserQuery(searchRequest.searchText,&pQuery); + if (g_LogCategories&LOG_SEARCH_SQL) + { + wchar_t *query=const_cast((const wchar_t*)pQuery); + int len=Strlen(query); + for (int i=0;i pInfo=command0.GetInterface(); + if (pInfo) + { + DBPROPID propids[1]={MSIDXSPROP_WHEREID}; + DBPROPIDSET propset={propids,1,DBPROPSET_MSIDXS_ROWSETEXT}; + ULONG csets; + DBPROPSET *props=NULL; + if (SUCCEEDED(pInfo->GetProperties(1,&propset,&csets,&props)) && props) + { + if (props->rgProperties) + { + if (props->rgProperties[0].vValue.vt==VT_UI4) + whereid=props->rgProperties[0].vValue.uintVal; + VariantClear(&props->rgProperties[0].vValue); + } + if (props->rgProperties) + CoTaskMemFree(props->rgProperties); + CoTaskMemFree(props); + } + } + if (whereid==0xFFFFFFFF) + { + command0.Close(); + continue; + } + for (std::list::iterator it=scopeList.begin();it!=scopeList.end();++it) + { + if (it->roots.empty()) + continue; + wchar_t query[8192]; + int len=Sprintf(query,_countof(query),L"SELECT TOP %d %s FROM SystemIndex WHERE REUSEWHERE(%u)",MAX_SEARCH_RESULTS,columns,whereid); + if (it->roots.size()==1 && it->roots[0]==L"FILE:") + { + if (it->categoryHash==CATEGORY_METROSETTING) + { + len+=Strcpy(query+len,_countof(query)-len,L" AND System.Search.Store='FILE' AND System.FileName NOT LIKE 'Classic_%' AND System.ItemType='.settingcontent-ms'"); + wchar_t userPath[_MAX_PATH]=L"%LOCALAPPDATA%\\Packages\\windows.immersivecontrolpanel_cw5n1h2txyewy\\LocalState\\Indexed\\Settings"; + DoEnvironmentSubst(userPath,_countof(userPath)); + len+=Sprintf(query+len,_countof(query)-len,L" AND SCOPE='%s'",userPath); + } + else + { + len+=Strcpy(query+len,_countof(query)-len,L" AND System.Search.Store='FILE' AND System.ItemType!='.settingcontent-ms'"); + for (std::list::iterator it2=scopeList.begin();it2!=it;++it2) + { + if (it2->categoryHash==CATEGORY_METROSETTING) + continue; + for (std::vector::iterator it3=it2->roots.begin();it3!=it2->roots.end();++it3) + { + if (wcsncmp(*it3,L"FILE:",5)==0) + len+=Sprintf(query+len,_countof(query)-len,L" AND NOT SCOPE='%s'",*it3); + } + } + if (searchRequest.bSearchPrograms) + { + // remove start menu/programs + { + CComString pPath; + if (SUCCEEDED(ShGetKnownFolderPath(FOLDERID_StartMenu,&pPath))) + len+=Sprintf(query+len,_countof(query)-len,L" AND NOT SCOPE='%s'",pPath); + } + { + CComString pPath; + if (SUCCEEDED(ShGetKnownFolderPath(FOLDERID_Programs,&pPath))) + len+=Sprintf(query+len,_countof(query)-len,L" AND NOT SCOPE='%s'",pPath); + } + } + if (searchRequest.bSearchPrograms || searchRequest.bNoCommonFolders) + { + // remove common start menu/programs + { + CComString pPath; + if (SUCCEEDED(ShGetKnownFolderPath(FOLDERID_CommonStartMenu,&pPath))) + len+=Sprintf(query+len,_countof(query)-len,L" AND NOT SCOPE='%s'",pPath); + } + { + CComString pPath; + if (SUCCEEDED(ShGetKnownFolderPath(FOLDERID_CommonPrograms,&pPath))) + len+=Sprintf(query+len,_countof(query)-len,L" AND NOT SCOPE='%s'",pPath); + } + } + } + } + else + { + for (std::vector::iterator it2=it->roots.begin();it2!=it->roots.end();++it2) + { + const wchar_t *scope=*it2; + if (scope[0]=='-') + { + bool bShallow=false; + scope++; + if (scope[0]=='=') + { + bShallow=true; + scope++; + } + if (bShallow) + len+=Sprintf(query+len,_countof(query)-len,L" AND NOT DIRECTORY='%s'",scope); + else + len+=Sprintf(query+len,_countof(query)-len,L" AND NOT SCOPE='%s'",scope); + } + } + len+=Sprintf(query+len,_countof(query)-len,L" AND ("); + bool bFirst=true; + for (std::vector::iterator it2=it->roots.begin();it2!=it->roots.end();++it2) + { + const wchar_t *scope=*it2; + bool bExclude=false, bShallow=false; + if (scope[0]=='-') + { + bExclude=true; + scope++; + } + if (scope[0]=='=') + { + bShallow=true; + scope++; + } + if (!bExclude) + { + if (bShallow) + len+=Sprintf(query+len,_countof(query)-len,bFirst?L"DIRECTORY='%s'":L" OR DIRECTORY='%s'",scope); + else + len+=Sprintf(query+len,_countof(query)-len,bFirst?L"SCOPE='%s'":L" OR SCOPE='%s'",scope); + bFirst=false; + } + } + len+=Strcpy(query+len,_countof(query)-len,L")"); + } + len+=Sprintf(query+len,_countof(query)-len,L" ORDER BY %s",it->bCommunications?orderComm:order); + + if (g_LogCategories&LOG_SEARCH_SQL) + { + for (int i=0;i,CRowset> command; + HRESULT hr=command.Open(session,query); + if (FAILED(hr)) + { + LOG_MENU(LOG_SEARCH_SQL,L"Query failed: 0x%08X",hr); + continue; + } + + CComQIPtr pInfo=command.GetInterface(); + DBPROPID propids[1]={MSIDXSPROP_RESULTS_FOUND}; + DBPROPIDSET propset={propids,1,DBPROPSET_MSIDXS_ROWSETEXT}; + ULONG csets; + DBPROPSET *props=NULL; + if (SUCCEEDED(pInfo->GetProperties(1,&propset,&csets,&props)) && props) + { + if (props->rgProperties) + { + if (props->rgProperties[0].vValue.vt==VT_I4) + it->resultCount=props->rgProperties[0].vValue.intVal; + VariantClear(&props->rgProperties[0].vValue); + } + if (props->rgProperties) + CoTaskMemFree(props->rgProperties); + CoTaskMemFree(props); + } + LOG_MENU(LOG_SEARCH_SQL,L"Query results: %d",it->resultCount); + if (it->resultCount>0) + { + SearchCategory *pCategory=NULL; + { + Lock lock(this,LOCK_DATA); + m_IndexedItems.push_back(SearchCategory()); + pCategory=&*m_IndexedItems.rbegin(); + pCategory->name.Format(L"%s (%d)",it->name,it->resultCount); + pCategory->categoryHash=it->categoryHash; + pCategory->search.Clone(it->search); + } + while (command.MoveNext()==S_OK) + { + LOG_MENU(LOG_SEARCH_SQL,L"Result: %s, %s, %s, %s, %s",command.itemUrl,command.itemType,command.parsingPath,command.displayPath,command.displayName); + SearchCategory::Item item; + if (it->bFiles) + { + const wchar_t *path=wcsrchr(command.itemUrl,'/'); + if (!path || _wcsicmp(path+1,command.displayName)!=0) + item.name=command.displayName; + } + if (command.itemUrl[0]) + { + if (!it->bFiles) + { +#ifdef LAUNDER_SEARCH_RESULTS + CComPtr pCondition; + hr=pConditionFactory->CreateStringLeaf(PKEY_ItemUrl,COP_EQUAL,command.itemUrl,NULL,CONDITION_CREATION_DEFAULT,IID_PPV_ARGS(&pCondition)); + if (pCondition) + { + pSearchFactory->SetCondition(pCondition); + + CAbsolutePidl pidl0; + hr=pSearchFactory->GetIDList(&pidl0); + CComPtr pFolder; + hr=SHBindToObject(NULL,pidl0,NULL,IID_IShellFolder,(void**)&pFolder); + if (SUCCEEDED(hr)) + { + CComPtr pEnum; + pFolder->EnumObjects(NULL,SHCONTF_FOLDERS|SHCONTF_NONFOLDERS,&pEnum); + PITEMID_CHILD child; + if (pEnum && pEnum->Next(1,&child,NULL)==S_OK) + { + item.pidl.Attach(ILCombine(pidl0,child)); + ILFree(child); + } + } + } +#else + PROPVARIANT val; + val.vt=VT_LPWSTR; + val.pwszVal=command.itemType; + pStore->SetValue(PKEY_ItemType,val); + val.pwszVal=command.parsingPath; + pStore->SetValue(PKEY_ParsingPath,val); + val.pwszVal=command.displayPath; + pStore->SetValue(PKEY_ItemPathDisplay,val); + val.pwszVal=command.displayName; + pStore->SetValue(PKEY_ItemNameDisplay,val); + item.name=command.displayName; + hr=SHParseDisplayName(command.itemUrl,pBindCtx0,&item.pidl,0,NULL); +#endif + } + else + { + hr=SHParseDisplayName(command.itemUrl,NULL,&item.pidl,0,NULL); + if (FAILED(hr) && _wcsnicmp(command.itemUrl,L"file:",5)==0) + { + for (wchar_t *str=command.itemUrl;*str;++str) + { + if (*str=='/') + *str='\\'; + } + hr=SHParseDisplayName(command.itemUrl+5,NULL,&item.pidl,0,NULL); + } + } + if (SUCCEEDED(hr)) + { + Lock lock(this,LOCK_DATA); + if (searchRequest.requestId!=m_LastRequestId) + break; + pCategory->items.push_back(item); + DWORD time=GetTickCount(); + int dt=(time-searchRequest.searchTime); + if (dt>1000) + { + CMenuContainer::RefreshSearch(); + searchRequest.searchTime=time; + } + } + } + } + } + command.Close(); + if (searchRequest.requestId!=m_LastRequestId) + break; + } + command0.Close(); + } + } +} + +DWORD CALLBACK CSearchManager::StaticSearchThread( void *param ) +{ +// SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_IDLE); + OleInitialize(NULL); + ((CSearchManager*)param)->SearchThread(); + OleUninitialize(); + return 0; +} + +void CSearchManager::GetSearchResults( SearchResults &results ) +{ + results.programs.clear(); + results.settings.clear(); + results.indexed.clear(); + results.autocomplete.clear(); + results.autoCompletePath.Empty(); + Lock lock(this,LOCK_DATA); + results.autoCompletePath=m_AutoCompletePath; + bool bSearchSubWord=GetSettingBool(L"SearchSubWord"); + if (m_AutoCompletePath.IsEmpty()) + { + { + std::vector &programs=m_bProgramsFound?m_ProgramItems:m_ProgramItemsOld; + std::sort(programs.begin(),programs.end()); + std::vector foundItems; + for (std::vector::const_iterator it=programs.begin();it!=programs.end();++it) + { + if (it->category==CATEGORY_PROGRAM && it->MatchText(m_SearchText,bSearchSubWord)) + { + bool bDuplicate=false; + bool bAppResolved=false; + for (std::vector::const_iterator it2=foundItems.begin();it2!=foundItems.end();++it2) + { + if (wcscmp(it->name,(*it2)->name)==0 && it->bMetroLink==(*it2)->bMetroLink) + { + if (!bAppResolved) + { + bAppResolved=true; + g_ItemManager.UpdateItemInfo(it->pInfo,CItemManager::INFO_LINK_APPID); + } + g_ItemManager.UpdateItemInfo((*it2)->pInfo,CItemManager::INFO_LINK_APPID); + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + if (it->pInfo->GetAppid()==(*it2)->pInfo->GetAppid()) + { + bDuplicate=true; + break; + } + } + } + if (!bDuplicate) + { + results.programs.push_back(it->pInfo); + foundItems.push_back(&*it); + } + } + } + } + + { + std::vector &settings=m_bSettingsFound?m_SettingsItems:m_SettingsItemsOld; + for (std::vector::iterator it=settings.begin();it!=settings.end();++it) + { + int match=(it->category==CATEGORY_SETTING)?it->MatchText(m_SearchText,bSearchSubWord):0; + it->rank=(it->rank&0xFFFFFFFE)|(match>>1); + } + std::sort(settings.begin(),settings.end()); + for (std::vector::const_iterator it=settings.begin();it!=settings.end();++it) + { + if (it->category==CATEGORY_SETTING && it->MatchText(m_SearchText,bSearchSubWord)) + results.settings.push_back(it->pInfo); + } + } + + results.indexed=m_IndexedItems; + } + else + { + std::sort(m_AutoCompleteItems.begin(),m_AutoCompleteItems.end()); + Assert(_wcsnicmp(m_SearchText,m_AutoCompletePath,m_AutoCompletePath.GetLength())==0); + CString filter=m_SearchText.Mid(m_AutoCompletePath.GetLength()+1); + if (!filter.IsEmpty()) + filter+='*'; + for (std::vector::const_iterator it=m_AutoCompleteItems.begin();it!=m_AutoCompleteItems.end();++it) + { + if (filter.IsEmpty() || PathMatchSpec(it->name,filter)) + results.autocomplete.push_back(it->pInfo); + } + } + results.bResults=(!results.programs.empty() || !results.settings.empty() || !results.indexed.empty() || !results.autocomplete.empty()); + results.bSearching=(m_LastCompletedId!=m_LastRequestId); +} + +bool CSearchManager::SearchItem::MatchTextInt( const wchar_t *search, const CString &text, bool bSearchSubWord ) +{ + if (text.IsEmpty()) return false; + if (bSearchSubWord) + { + // split search into tokens and see if all are found + for (const wchar_t *pSearch=search;*pSearch;) + { + wchar_t token[100]; + pSearch=GetToken(pSearch,token,_countof(token),L" "); + if (FindNLSStringEx(LOCALE_NAME_USER_DEFAULT,FIND_FROMSTART|LINGUISTIC_IGNORECASE|LINGUISTIC_IGNOREDIACRITIC,text,-1,token,-1,NULL,NULL,NULL,0)<0) + return false; + } + } + else + { + // split search into tokens, then see if any of the words start with those tokens + for (const wchar_t *pSearch=search;*pSearch;) + { + wchar_t token[100]; + pSearch=GetToken(pSearch,token,_countof(token),L" "); + bool bFound=false; + int len=Strlen(token); + for (const wchar_t *pName=text;*pName;) + { + while (*pName && wcschr(L" \t.,$&[]{}();|",*pName)) + pName++; + if (FindNLSStringEx(LOCALE_NAME_USER_DEFAULT,FIND_STARTSWITH|LINGUISTIC_IGNORECASE|LINGUISTIC_IGNOREDIACRITIC,pName,-1,token,len,NULL,NULL,NULL,0)>=0) + { + bFound=true; + break; + } + while (*pName && !wcschr(L" \t.,$&[]{}();|",*pName)) + pName++; + } + if (!bFound) + return false; + } + } + return true; +} + +void CSearchManager::LaunchExternalSearch( PIDLIST_ABSOLUTE root, unsigned int categoryHash, const CString &searchText ) +{ + Assert(GetCurrentThreadId()==m_MainThreadId); + if (searchText.IsEmpty()) return; + + CComPtr pConditionFactory; + pConditionFactory.CoCreateInstance(CLSID_ConditionFactory); + if (!pConditionFactory) return; + + CComPtr pSearchFactory; + pSearchFactory.CoCreateInstance(CLSID_SearchFolderItemFactory); + if (!pSearchFactory) return; + + std::vector> conditions; + CComPtr pCondition; + + if (!root) + { + if (categoryHash==CATEGORY_FILE) + { + // uncategorized files + PROPERTYKEY keyGroup; + if (FAILED(PSGetPropertyKeyFromName(L"System.StartMenu.Group",&keyGroup))) + return; + if (FAILED(pConditionFactory->CreateStringLeaf(keyGroup,COP_EQUAL,L"files",NULL,CONDITION_CREATION_DEFAULT,IID_PPV_ARGS(&pCondition)))) + return; + conditions.push_back(pCondition); + } + else if ((categoryHash&CATEGORY_MASK)==CATEGORY_FILE) + { + // all files + if (FAILED(pConditionFactory->CreateStringLeaf(PKEY_Search_Store,COP_EQUAL,L"file",NULL,CONDITION_CREATION_DEFAULT,IID_PPV_ARGS(&pCondition)))) + return; + conditions.push_back(pCondition); + } + pCondition=NULL; + } + + PROPERTYKEY keyString; + if (!GetSettingBool(L"SearchContents")) + keyString=PKEY_ItemNameDisplay; + else if (FAILED(PSGetPropertyKeyFromName(L"System.Generic.String",&keyString))) + return; + + // create condition for each word + const wchar_t *str=searchText; + const wchar_t *str0=str; + while (*str) + { + while (*str==' ') + str++; + CONDITION_OPERATION oper=*str=='"'?COP_WORD_EQUAL:COP_WORD_STARTSWITH; + wchar_t token[100]; + str=GetToken(str,token,_countof(token),L" "); + if (SUCCEEDED(pConditionFactory->CreateStringLeaf(keyString,oper,token,NULL,CONDITION_CREATION_DEFAULT,IID_PPV_ARGS(&pCondition)))) + { + conditions.push_back(pCondition); + pCondition=NULL; + } + } + + if (root) + { + PCIDLIST_ABSOLUTE pidls[1]={root}; + CComPtr pArray; + if (SUCCEEDED(SHCreateShellItemArrayFromIDLists(1,pidls,&pArray))) + pSearchFactory->SetScope(pArray); + } + else if (categoryHash==CATEGORY_FILE) + { + CAbsolutePidl root2; + SHParseDisplayName(L"::{DAF95313-E44D-46AF-BE1B-CBACEA2C3065}",NULL,&root2,0,NULL); + PCIDLIST_ABSOLUTE pidls[1]={root2}; + CComPtr pArray; + if (SUCCEEDED(SHCreateShellItemArrayFromIDLists(1,pidls,&pArray))) + pSearchFactory->SetScope(pArray); + } + + if (conditions.size()==1) + pSearchFactory->SetCondition(conditions[0]); + else + { + CComPtr pConditionAnd; + if (SUCCEEDED(pConditionFactory->CreateCompoundFromArray(CT_AND_CONDITION,&conditions[0].p,(ULONG)conditions.size(),CONDITION_CREATION_DEFAULT,IID_PPV_ARGS(&pConditionAnd)))) + pSearchFactory->SetCondition(pConditionAnd); + } + + CComPtr pSearchItem; + if (FAILED(pSearchFactory->GetShellItem(IID_IShellItem,(void**)&pSearchItem))) + return; + + SHELLEXECUTEINFO execute={sizeof(execute)}; + execute.lpVerb=L"open"; + execute.nShow=SW_SHOWNORMAL; + execute.fMask=SEE_MASK_IDLIST; + CAbsolutePidl pidl; + if (SUCCEEDED(SHGetIDListFromObject(pSearchItem,&pidl))) + { +/* + // Unsucessful attempt to use some undocumented APIs to highlight the search term in Explorer. + // The seach box is populated with the text but the items are still not higlighted + + const GUID IID_IFilterCondition={0xFCA2857D,0x1760,0x4AD3,{0x8C,0x63,0xC9,0xB6,0x02,0xFC,0xBA,0xEA}}; + + interface IFilterCondition: public IPersistStream + { + }; + + const GUID IID_IShellFolder3={0x711B2CFD,0x93D1,0x422B,{0xBD,0xF4,0x69,0xBE,0x92,0x3F,0x24,0x49}}; + + typedef DWORD FILTERIDLISTTYPE; + + interface IShellFolder3: public IShellFolder2 + { + STDMETHOD(CreateFilteredIDList)(IFilterCondition *, FILTERIDLISTTYPE, IPropertyStore *, PITEMID_CHILD *)=0; + // STDMETHOD(GetFilteredIDListType)(PCITEMID_CHILD, FILTERIDLISTTYPE *); + // STDMETHOD(ModifyFilteredIDList)(PCITEMID_CHILD, IFilterCondition *, PITEMID_CHILD *); + // STDMETHOD(ReparentFilteredIDList)(PCIDLIST_RELATIVE, PIDLIST_RELATIVE *); + // STDMETHOD(CreateStackedIDList)(PROPERTYKEY const &, PIDLIST_ABSOLUTE *); + // STDMETHOD(GetStackedKey)(PROPERTYKEY *); + // STDMETHOD(EnumObjectsEx)(HWND, IBindCtx *, ULONG, IItemFilter *, IEnumIDList **); + // STDMETHOD(GetConditions)(PROPERTYKEY const &, IQueryUnit *, REFIID, PVOID *); + // STDMETHOD(GetAutoListFlags)(ULONG *); + }; + + typedef HRESULT (WINAPI*tSHCreateFilter)( PCWSTR Name, PCWSTR InFolder, PROPERTYKEY const &PropertyKey, INT Type, ICondition *Condition, REFIID riid, PVOID *ppv ); + + tSHCreateFilter SHCreateFilter=(tSHCreateFilter)GetProcAddress(GetModuleHandle(L"shell32.dll"),MAKEINTRESOURCEA(818)); + if (SHCreateFilter) + { + PROPERTYKEY wordWheel=PKEY_Kind; + wordWheel.pid=5; + CComPtr pFilter; + HRESULT hr=SHCreateFilter(searchText,NULL,wordWheel,7,pCondition,IID_IFilterCondition,(void**)&pFilter); + if (pFilter) + { + CComPtr pShellFolder3; + SHBindToObject(NULL,pidl,NULL,IID_IShellFolder3,(void**)&pShellFolder3); + if (pShellFolder3) + { + PITEMID_CHILD pChild; + hr=pShellFolder3->CreateFilteredIDList(pFilter,2,NULL,&pChild); + if (SUCCEEDED(hr)) + { + pSearchItem=NULL; + if (SUCCEEDED(SHCreateItemWithParent(NULL,pShellFolder3,pChild,IID_IShellItem,(void**)&pSearchItem))) + { + CAbsolutePidl pidl2; + if (SUCCEEDED(SHGetIDListFromObject(pSearchItem,&pidl2))) + pidl.Swap(pidl2); + } + ILFree(pChild); + } + } + } + }*/ + execute.lpIDList=pidl; + ShellExecuteEx(&execute); + } +} + +void CSearchManager::LaunchInternetSearch( const CString &searchText ) +{ + Assert(GetCurrentThreadId()==m_MainThreadId); + if (searchText.IsEmpty()) return; + + if (IsEdgeDefaultBrowser()) + { + wchar_t search[256]; + Sprintf(search,_countof(search),L"? %s",searchText); + ShellExecute(NULL,NULL,L"shell:appsfolder\\Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge",search,NULL,SW_SHOWNORMAL); + } + else + { + wchar_t path[_MAX_PATH]; + DWORD size=_countof(path); + if (SUCCEEDED(AssocQueryString(0,ASSOCSTR_EXECUTABLE,L"http",L"open",path,&size))) + { + wchar_t search[256]; + Sprintf(search,_countof(search),L"\"? %s\"",searchText); + ShellExecute(NULL,NULL,path,search,NULL,SW_SHOWNORMAL); + } + } +} + +bool HasSearchService( void ) +{ + bool bWSearch=false; + SC_HANDLE hManager=OpenSCManager(NULL,NULL,SC_MANAGER_CONNECT); + if (hManager) + { + SC_HANDLE hService=OpenService(hManager,L"WSearch",SERVICE_QUERY_STATUS); + if(hService) + { + // service is installed + SERVICE_STATUS status; + if(QueryServiceStatus(hService,&status)) + { + bWSearch=(status.dwCurrentState==SERVICE_RUNNING); + } + CloseServiceHandle(hService); + } + CloseServiceHandle(hManager); + } + return bWSearch; +} diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SearchManager.h b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SearchManager.h new file mode 100644 index 0000000..ceab6d4 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SearchManager.h @@ -0,0 +1,262 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#include "ItemManager.h" +#include +#include +#include + +const int MAX_SEARCH_RESULTS=100; // per category + +class CSearchManager +{ +public: + CSearchManager( void ); + ~CSearchManager( void ); + void Init( void ); + void Close( void ); + + + enum TItemCategory + { + CATEGORY_INVALID, + CATEGORY_PROGRAM, + CATEGORY_SETTING, + CATEGORY_METROSETTING, + CATEGORY_FILE, + CATEGORY_ITEM, + CATEGORY_INTERNET, + CATEGORY_AUTOCOMPLETE, + + CATEGORY_MASK=15 + }; + + struct SearchCategory + { + SearchCategory( void ) {} + SearchCategory( const SearchCategory &cat ) + { + search.Clone(cat.search); + categoryHash=cat.categoryHash; + name=cat.name; + items=cat.items; + } + CAbsolutePidl search; + unsigned int categoryHash; + CString name; + struct Item + { + CString name; + CAbsolutePidl pidl; + }; + std::vector items; + }; + + struct SearchResults + { + bool bSearching; + bool bResults; + CString currentString; + CString autoCompletePath; + std::vector programs; + std::vector settings; + std::vector autocomplete; + std::list indexed; + }; + + void BeginSearch( const CString &searchText ); + void GetSearchResults( SearchResults &results ); + void AddItemRank( unsigned int hash ); + void CloseMenu( void ); + + void LaunchExternalSearch( PIDLIST_ABSOLUTE root, unsigned int categoryHash, const CString &searchText ); + void LaunchInternetSearch( const CString &searchText ); + +private: + struct ItemRank + { + unsigned int hash; // hash of the item name in caps + int rank; // number of times it was used + int lastTime; // the last time it was updated (hi dword of FILETIME) + + ItemRank( unsigned int _hash=0, int _rank=0, int _lastTime=0 ) { hash=_hash; rank=_rank; lastTime=_lastTime; } + bool operator<( const ItemRank &rank ) const { return hashitem.rank || (rank==item.rank && wcscmp(name,item.name)<0); } + + private: + static bool MatchTextInt( const wchar_t *search, const CString &text, bool bSearchSubWord ); + }; + + bool m_bInitialized; + + CString m_SearchText; + CString m_AutoCompletePath; + + volatile int m_LastRequestId; + volatile int m_LastProgramsRequestId; + volatile int m_LastCompletedId; + + struct SearchRequest + { + int requestId; + bool bSearchPrograms; + bool bSearchPath; + bool bSearchMetroApps; + bool bSearchMetroSettings; + bool bSearchSettings; + bool bSearchKeywords; + bool bSearchFiles; + bool bSearchMetadata; + bool bSearchTypes; + bool bSearchSubWord; + bool bUseRanks; + bool bNoCommonFolders; + bool bPinnedFolder; + DWORD searchTime; + CString searchText; + CString autoCompletePath; + }; + + // LOCK_DATA + SearchRequest m_SearchRequest; + std::vector m_ProgramItems; // also LOCK_PROGRAMS + std::vector m_SettingsItems; // also LOCK_PROGRAMS + std::vector m_ProgramItemsOld; + std::vector m_SettingsItemsOld; + unsigned int m_ProgramsHash; + unsigned int m_ProgramsHashOld; + unsigned int m_SettingsHash; + unsigned int m_SettingsHashOld; + bool m_bProgramsFound; + bool m_bSettingsFound; + std::vector m_AutoCompleteItems; + std::list m_IndexedItems; + std::vector m_ItemRanks; + CString m_LastAutoCompletePath; + + enum + { + COLLECT_RECURSIVE =0x01, // go into subfolders + COLLECT_PROGRAMS =0x02, // only collect programs (.exe, .com, etc) + COLLECT_FOLDERS =0x04, // include folder items + COLLECT_METRO =0x08, // check for metro links (non-recursive) + COLLECT_ONLY_METRO =0x10, // collect only metro links + COLLECT_KEYWORDS =0x20, // include the keywords + COLLECT_LIBRARY =0x40, // the folder is a library + COLLECT_NOREFRESH =0x80, // suppress the refresh message + + COLLECT_IS_FOLDER =0x8000 + }; + + bool AddSearchItem( IShellItem *pItem, const wchar_t *name, int flags, TItemCategory category, SearchRequest &searchRequest ); + void CollectSearchItems( IShellItem *pFolder, int flags, TItemCategory category, SearchRequest &searchRequest ); + void CollectIndexItems( IShellItem *pFolder, int flags, TItemCategory category, const wchar_t *groupName ); + + enum TLock + { + LOCK_DATA, + LOCK_PROGRAMS, + LOCK_RANKS, + LOCK_COUNT, + }; + + CRITICAL_SECTION m_CriticalSections[LOCK_COUNT]; + DWORD m_CriticalSectionOwners[LOCK_COUNT]; + + class Lock + { + public: + Lock( CSearchManager *pThis, TLock index ) + { + m_pSection=&pThis->m_CriticalSections[index]; + EnterCriticalSection(m_pSection); + m_pOwner=&pThis->m_CriticalSectionOwners[index]; + if (!*m_pOwner) + *m_pOwner=GetCurrentThreadId(); + else + m_pOwner=NULL; + } + + ~Lock( void ) + { + if (m_pOwner) *m_pOwner=0; + LeaveCriticalSection(m_pSection); + } + + private: + CRITICAL_SECTION *m_pSection; + DWORD *m_pOwner; + }; + + bool ThreadHasLock( TLock index ) { return m_CriticalSectionOwners[index]==GetCurrentThreadId(); } + + HANDLE m_SearchEvent; + HANDLE m_ExitEvent; + HANDLE m_SearchThreads[8]; + volatile long m_SearchThreadCount; + DWORD m_MainThreadId; + + void LoadItemRanks( void ); + void SearchThread( void ); + static DWORD CALLBACK StaticSearchThread( void *param ); + + static bool CmpRankTime( const CSearchManager::ItemRank &rank1, const CSearchManager::ItemRank &rank2 ); + static unsigned int CalcItemsHash( const std::vector &items ); + + struct SearchScope + { + SearchScope( void ) { resultCount=0; categoryHash=0; bFiles=true; bCommunications=false; } + CAbsolutePidl search; + unsigned int categoryHash; + CString name; + bool bFiles; + bool bCommunications; + + std::vector roots; + int resultCount; + + bool ParseSearchConnector( const wchar_t *fname ); + }; + + class CDataAccessor + { + public: + wchar_t itemUrl[_MAX_PATH]; + wchar_t itemType[_MAX_PATH]; + wchar_t parsingPath[_MAX_PATH]; + wchar_t displayPath[_MAX_PATH]; + wchar_t displayName[_MAX_PATH]; + + //Output Accessor + BEGIN_COLUMN_MAP(CDataAccessor) + COLUMN_ENTRY(1, itemUrl) + COLUMN_ENTRY(2, itemType) + COLUMN_ENTRY(3, parsingPath) + COLUMN_ENTRY(4, displayPath) + COLUMN_ENTRY(5, displayName) + END_COLUMN_MAP() + }; +}; + +extern CSearchManager g_SearchManager; + +bool HasSearchService( void ); diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SettingsUI.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SettingsUI.cpp new file mode 100644 index 0000000..5a7b3e2 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SettingsUI.cpp @@ -0,0 +1,5196 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "resource.h" +#include "ClassicStartMenuDLL.h" +#include "ClassicStartButton.h" +#include "Settings.h" +#include "SkinManager.h" +#include "FNVHash.h" +#include "SettingsUIHelper.h" +#include "LanguageSettingsHelper.h" +#include "SettingsUI.h" +#include "ResourceHelper.h" +#include "MenuContainer.h" +#include "Translations.h" +#include "CustomMenu.h" +#include "dllmain.h" +#include +#include +#include +#define SECURITY_WIN32 +#include + +const int DEFAULT_GLASS_OPACITY=50; // 50% +const int DEFAULT_TASK_OPACITY7=25; // 25% +const int DEFAULT_TASK_OPACITY8=55; // 55% +const int DEFAULT_TASK_OPACITY10=85; // 85% + +/////////////////////////////////////////////////////////////////////////////// + +class CSkinSettingsDlg: public CResizeableDlg +{ +public: + enum { + IDC_EDITBOX=101, + IDC_BROWSEBTN=102, + WM_EDITKEY=WM_APP+11, + }; + + CSkinSettingsDlg( void ); + void Create( MenuSkin::TSkinType skinType, HWND hWndParent, DLGTEMPLATE *pTemplate ); + + BEGIN_MSG_MAP( CSkinSettingsDlg ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + MESSAGE_HANDLER( WM_DESTROY, OnDestroy ) + MESSAGE_HANDLER( WM_SIZE, OnSize ) + MESSAGE_HANDLER( WM_EDITKEY, OnEditKey ) + COMMAND_HANDLER( IDC_EDITBOX, EN_CHANGE, OnEditChange ) + COMMAND_HANDLER( IDC_EDITBOX, EN_KILLFOCUS, OnKillFocus ) + COMMAND_HANDLER( IDC_BROWSEBTN, BN_CLICKED, OnBrowse ) + COMMAND_HANDLER( IDC_BROWSEBTN, BN_KILLFOCUS, OnKillFocus ) + COMMAND_HANDLER( IDC_COMBOSKIN, CBN_SELENDOK, OnSelEndOK ) + COMMAND_HANDLER( IDC_ABOUT, BN_CLICKED, OnAbout ) + COMMAND_HANDLER( IDC_BUTTONRESET, BN_CLICKED, OnReset ) + NOTIFY_HANDLER( IDC_SKINOPTIONS, NM_CUSTOMDRAW, OnCustomDraw ) + NOTIFY_HANDLER( IDC_SKINOPTIONS, TVN_SELCHANGED, OnSelChanged ) + NOTIFY_HANDLER( IDC_SKINOPTIONS, TVN_ITEMEXPANDING, OnExpanding ) + NOTIFY_HANDLER( IDC_SKINOPTIONS, NM_CLICK, OnClick ) + NOTIFY_HANDLER( IDC_SKINOPTIONS, NM_DBLCLK, OnClick ) + NOTIFY_HANDLER( IDC_SKINOPTIONS, TVN_KEYDOWN, OnKeyDown ) + NOTIFY_HANDLER( IDC_SKINOPTIONS, TVN_GETINFOTIP, OnGetInfoTip ) + END_MSG_MAP() + + BEGIN_RESIZE_MAP + RESIZE_CONTROL(IDC_COMBOSKIN,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_ABOUT,MOVE_MOVE_X) + RESIZE_CONTROL(IDC_BUTTONRESET,MOVE_MOVE_X) + RESIZE_CONTROL(IDC_STATICVER,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_SKINOPTIONS,MOVE_SIZE_X|MOVE_SIZE_Y) + RESIZE_CONTROL(IDC_STATICALLPROGS,MOVE_SIZE_X|MOVE_MOVE_Y) + END_RESIZE_MAP + + void SetGroup( CSetting *pGroup ); + +protected: + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSelEndOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnAbout( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnReset( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnSelChanged( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnExpanding( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) { return TRUE; } // prevent collapsing + LRESULT OnClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnKeyDown( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnGetInfoTip( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnEditKey( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnEditChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnKillFocus( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnBrowse( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + +private: + + MenuSkin::TSkinType m_SkinType; + MenuSkin m_CurrentSkin; + CWindow m_Tree; + CWindow m_EditBox; + CWindow m_BrowseButton; + TSkinOptionType m_EditMode; + HTREEITEM m_EditItem; + int m_EditItemIndex; + bool m_bLoadSuccess; + bool m_bIgnoreFocus; + CSetting *m_pSetting; + std::vector m_SkinNames; + int m_SkinIndex; + int m_VariationIndex; + + void InitSkinUI( void ); + void UpdateSkinSettings( void ); + void StoreSkinOptions( void ); + void ToggleItem( HTREEITEM hItem ); + void ItemSelected( HTREEITEM hItem, int index, bool bEnabled ); + void ApplyEditBox( void ); + void UpdateEditPosition( void ); +}; + +CSkinSettingsDlg::CSkinSettingsDlg( void ) +{ + m_SkinType=MenuSkin::SKIN_TYPE_COUNT; + m_pSetting=NULL; + m_SkinIndex=m_VariationIndex=0; + m_EditItem=NULL; + m_EditMode=SKIN_OPTION_NONE; + m_EditItemIndex=-1; + m_bIgnoreFocus=false; + m_bLoadSuccess=false; +} + +void CSkinSettingsDlg::Create( MenuSkin::TSkinType skinType, HWND hWndParent, DLGTEMPLATE *pTemplate ) +{ + m_SkinType=skinType; + CResizeableDlg::Create(hWndParent,pTemplate); +} + +// Subclass the edit control to forward some keyboard messages to the parent and to act as a hotkey control +static LRESULT CALLBACK SubclassEditProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_CHAR && wParam==VK_RETURN) + return 0; + if (uMsg==WM_GETDLGCODE && wParam==VK_RETURN) + return DLGC_WANTALLKEYS; + if (uMsg==WM_KEYDOWN) + { + if (wParam==VK_UP || wParam==VK_DOWN || wParam==VK_PRIOR || wParam==VK_NEXT || (wParam==VK_SPACE && GetKeyState(VK_CONTROL)<0)) + return SendMessage(GetParent(hWnd),uMsg,wParam,lParam); + if (wParam==VK_RETURN || wParam==VK_ESCAPE) + return SendMessage(GetParent(GetParent(hWnd)),CSkinSettingsDlg::WM_EDITKEY,wParam,0); + } + if (uMsg==WM_KILLFOCUS) + { + if (wParam && (HWND)wParam==GetDlgItem(GetParent(hWnd),CSkinSettingsDlg::IDC_BROWSEBTN)) + return 0; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +// Subclass the tooltip to delay the tip when the mouse moves from one tree item to the next +static LRESULT CALLBACK SubclassInfoTipProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==TTM_UPDATE) + { + int time=(int)SendMessage(hWnd,TTM_GETDELAYTIME,TTDT_RESHOW,0); + SetTimer(hWnd,'CLSH',time,NULL); + return 0; + } + if (uMsg==WM_TIMER && wParam=='CLSH') + { + KillTimer(hWnd,wParam); + DefSubclassProc(hWnd,TTM_UPDATE,0,0); + return 0; + } + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +// Subclass the tree control to forward the command messages to the parent +static LRESULT CALLBACK SubclassTreeProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_COMMAND) + return SendMessage(GetParent(hWnd),uMsg,wParam,lParam); + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +LRESULT CSkinSettingsDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + InitResize(); + EnableThemeDialogTexture(m_hWnd,ETDT_ENABLETAB); + + m_Tree=GetDlgItem(IDC_SKINOPTIONS); + SetWindowSubclass(m_Tree,SubclassTreeProc,'CLSH',0); + TreeView_SetImageList(m_Tree,GetSettingsImageList(m_Tree),TVSIL_NORMAL); + m_Tree.SendMessage(TVM_SETEXTENDEDSTYLE,TVS_EX_DOUBLEBUFFER,TVS_EX_DOUBLEBUFFER); + m_Tree.SetWindowLong(GWL_STYLE,m_Tree.GetWindowLong(GWL_STYLE)|TVS_SHOWSELALWAYS); // should be in the dialog template, but I don't want to have to edit all language DLLs + if (IsAppThemed()) + { + m_Tree.SetWindowLong(GWL_STYLE,m_Tree.GetWindowLong(GWL_STYLE)|TVS_TRACKSELECT); + SetWindowTheme(m_Tree,L"Explorer",NULL); + } + + m_SkinNames.clear(); + m_SkinNames.push_back(LoadStringEx(IDS_DEFAULT_SKIN)); + wchar_t find[_MAX_PATH]; + GetSkinsPath(find); + Strcat(find,_countof(find),L"1.txt"); + if (GetFileAttributes(find)!=INVALID_FILE_ATTRIBUTES) + { + m_SkinNames.push_back(L"Custom"); + } + + *PathFindFileName(find)=0; + Strcat(find,_countof(find),m_SkinType==MenuSkin::SKIN_TYPE_WIN7?L"*.skin7":L"*.skin"); + WIN32_FIND_DATA data; + HANDLE h=FindFirstFile(find,&data); + while (h!=INVALID_HANDLE_VALUE) + { + if (!(data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)) + { + *PathFindExtension(data.cFileName)=0; + m_SkinNames.push_back(data.cFileName); + } + if (!FindNextFile(h,&data)) + { + FindClose(h); + break; + } + } + + CWindow skins=GetDlgItem(IDC_COMBOSKIN); + for (std::vector::const_iterator it=m_SkinNames.begin();it!=m_SkinNames.end();++it) + skins.SendMessage(CB_ADDSTRING,0,(LPARAM)(const wchar_t *)*it); + + CWindow tooltip=TreeView_GetToolTips(m_Tree); + tooltip.SendMessage(TTM_SETDELAYTIME,TTDT_AUTOPOP,10000); + tooltip.SendMessage(TTM_SETDELAYTIME,TTDT_INITIAL,1000); + tooltip.SendMessage(TTM_SETDELAYTIME,TTDT_RESHOW,1000); + SetWindowSubclass(tooltip,SubclassInfoTipProc,'CLSH',0); + + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS,m_hWnd,'CLSH'}; + CString str=LoadStringEx(IDS_SETTING_LOCKED); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + skins.GetClientRect(&tool.rect); + skins.MapWindowPoints(m_hWnd,&tool.rect); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + GetDlgItem(IDC_STATICALLPROGS).ShowWindow(m_SkinType==MenuSkin::SKIN_TYPE_ALL_PROGRAMS?SW_SHOW:SW_HIDE); + + HINSTANCE hInstance=_AtlBaseModule.GetResourceInstance(); + HFONT font=m_Tree.GetFont(); + m_EditBox=CreateWindow(L"EDIT",NULL,WS_CHILD|WS_BORDER|ES_AUTOHSCROLL,0,0,0,0,m_Tree,(HMENU)IDC_EDITBOX,hInstance,NULL); + m_EditBox.SetFont(font); + SetWindowSubclass(m_EditBox,SubclassEditProc,'CLSH',0); + m_BrowseButton=CreateWindow(L"BUTTON",L"...",WS_CHILD|BS_PUSHBUTTON,0,0,0,0,m_Tree,(HMENU)IDC_BROWSEBTN,hInstance,NULL); + m_BrowseButton.SetFont(font); + m_EditMode=SKIN_OPTION_NONE; + m_EditItem=NULL; + m_EditItemIndex=-1; + m_bIgnoreFocus=false; + + return TRUE; +} + +LRESULT CSkinSettingsDlg::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + m_EditMode=SKIN_OPTION_NONE; + bHandled=FALSE; + return 0; +} + +// Fills the tree with the options for the current skin +void CSkinSettingsDlg::InitSkinUI( void ) +{ + m_Tree.SetRedraw(FALSE); + TreeView_DeleteAllItems(m_Tree); + m_VariationIndex=-1; + m_EditItemIndex=-1; + m_EditMode=SKIN_OPTION_NONE; + m_BrowseButton.ShowWindow(SW_HIDE); + m_EditBox.ShowWindow(SW_HIDE); + + m_bLoadSuccess=m_CurrentSkin.LoadMenuSkin(m_SkinNames[m_SkinIndex],NULL,L"",m_SkinType,0,96); + if (!m_bLoadSuccess) + m_CurrentSkin.Reset(); + + if (m_CurrentSkin.Version>MAX_SKIN_VERSION) + { + GetDlgItem(IDC_STATICVER).ShowWindow(SW_SHOW); + m_CurrentSkin.Variations.clear(); + m_CurrentSkin.Options.clear(); + } + else + GetDlgItem(IDC_STATICVER).ShowWindow(SW_HIDE); + + CWindow label=GetDlgItem(IDC_STATICOPT); + + if (m_CurrentSkin.Options.empty() && m_CurrentSkin.Variations.empty()) + { + label.ShowWindow(SW_HIDE); + m_Tree.SetRedraw(TRUE); + m_Tree.ShowWindow(SW_HIDE); + } + else + { + // init variations + if (!m_CurrentSkin.Variations.empty()) + { + const wchar_t *variaton=L""; + if (m_pSetting[1].value.vt==VT_BSTR) + variaton=m_pSetting[1].value.bstrVal; + + m_VariationIndex=0; + CString vars=LoadStringEx(IDC_SKINVARIATION); + TVINSERTSTRUCT insert={NULL,TVI_LAST,{TVIF_STATE|TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM,NULL,TVIS_EXPANDED,TVIS_EXPANDED|TVIS_OVERLAYMASK,(LPWSTR)(LPCWSTR)vars,0,SETTING_STATE_SETTING,SETTING_STATE_SETTING}}; + insert.item.lParam=(LPARAM)(m_pSetting+1); + if (m_pSetting[1].IsLocked()) + { + insert.item.state|=INDEXTOOVERLAYMASK(1); + insert.item.iImage=insert.item.iSelectedImage=SETTING_STATE_SETTING|SETTING_STATE_DISABLED; + } + HTREEITEM hVars=TreeView_InsertItem(m_Tree,&insert); + int n=(int)m_CurrentSkin.Variations.size(); + for (int i=0;i=0) + insert.hParent=hLastGroup; + insert.item.lParam=i; + if (m_pSetting[2].IsLocked()) + insert.item.state|=INDEXTOOVERLAYMASK(1); + HTREEITEM hItem=TreeView_InsertItem(m_Tree,&insert); + if (option.type==SKIN_OPTION_GROUP) + hLastGroup=hItem; + } + UpdateSkinSettings(); + label.ShowWindow(SW_SHOW); + m_Tree.SetRedraw(TRUE); + m_Tree.Invalidate(); + m_Tree.ShowWindow(SW_SHOW); + } +} + +void CSkinSettingsDlg::UpdateSkinSettings( void ) +{ + HTREEITEM hItem=TreeView_GetRoot(m_Tree); + if (!hItem) return; + TVITEM item={TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE,hItem}; + TreeView_GetItem(m_Tree,&item); + if (item.lParam==(LPARAM)(m_pSetting+1)) + { + // has variations + for (HTREEITEM hVar=TreeView_GetChild(m_Tree,hItem);hVar;hVar=TreeView_GetNextSibling(m_Tree,hVar)) + { + item.hItem=hVar; + TreeView_GetItem(m_Tree,&item); + int image=SETTING_STATE_RADIO; + if (-1-(int)item.lParam==m_VariationIndex) + image|=SETTING_STATE_CHECKED; + if (m_pSetting[1].IsLocked()) + image|=SETTING_STATE_DISABLED; + if (item.iImage!=image) + { + item.iImage=item.iSelectedImage=image; + TreeView_SetItem(m_Tree,&item); + RECT rc; + TreeView_GetItemRect(m_Tree,hVar,&rc,FALSE); + m_Tree.InvalidateRect(&rc); + } + } + hItem=TreeView_GetNextSibling(m_Tree,hItem); + } + + bool bLocked=m_pSetting[2].IsLocked(); + std::map options; + if (m_pSetting[2].value.vt==VT_BSTR) + m_CurrentSkin.ParseOptionsString(m_pSetting[2].value.bstrVal,options); + { + std::vector values; + m_CurrentSkin.ComputeOptionStates(options,values,false); + } + + HTREEITEM hLastGroup=NULL; + while (hItem) + { + wchar_t text[256]; + item.hItem=hItem; + item.pszText=text; + TreeView_GetItem(m_Tree,&item); + int idx=(int)item.lParam; + const MenuSkin::Option &option=m_CurrentSkin.Options[idx]; + if (option.type==SKIN_OPTION_GROUP) + { + hLastGroup=hItem; + hItem=TreeView_GetChild(m_Tree,hItem); + } + else + { + int image=option.groupId>=0?SETTING_STATE_RADIO:SETTING_STATE_CHECKBOX; + if (option.bValue) + image|=SETTING_STATE_CHECKED; + if (!option.bEnabled || bLocked) + image|=SETTING_STATE_DISABLED; + if (option.bValue && option.type>SKIN_OPTION_BOOL) + Sprintf(text,_countof(text),L"%s: %s",option.label,option.sValue); + else + Sprintf(text,_countof(text),L"%s",option.label); + + item.iImage=item.iSelectedImage=image; + item.mask|=TVIF_TEXT; + TreeView_SetItem(m_Tree,&item); + item.mask&=~TVIF_TEXT; + RECT rc; + TreeView_GetItemRect(m_Tree,hItem,&rc,FALSE); + m_Tree.InvalidateRect(&rc); + + hItem=TreeView_GetNextSibling(m_Tree,hItem); + if (!hItem && hLastGroup) + { + hItem=TreeView_GetNextSibling(m_Tree,hLastGroup); + hLastGroup=NULL; + } + } + } +} + +void CSkinSettingsDlg::StoreSkinOptions( void ) +{ + std::vector buffer; + m_CurrentSkin.SerializeOptionStates(buffer); + + CSettingsLockWrite lock; + const wchar_t *strNew=&buffer[0]; + const wchar_t *strOld=m_pSetting[2].value.vt==VT_BSTR?m_pSetting[2].value.bstrVal:L""; + if (wcscmp(strNew,strOld)!=0) + SetSettingsDirty(); + + m_pSetting[2].value=CComVariant(strNew); +} + +LRESULT CSkinSettingsDlg::OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMTVCUSTOMDRAW *pDraw=(NMTVCUSTOMDRAW*)pnmh; + if (pDraw->nmcd.dwDrawStage==CDDS_PREPAINT) + { + UpdateEditPosition(); + return CDRF_NOTIFYITEMDRAW; + } + else if (pDraw->nmcd.dwDrawStage==CDDS_ITEMPREPAINT) + { + TVITEM item={TVIF_IMAGE|TVIF_STATE,(HTREEITEM)pDraw->nmcd.dwItemSpec,0,TVIS_SELECTED}; + TreeView_GetItem(m_Tree,&item); + if ((item.iImage&SETTING_STATE_DISABLED) && (!(item.state&TVIS_SELECTED) || IsAppThemed())) + pDraw->clrText=GetSysColor(COLOR_GRAYTEXT); + return CDRF_NOTIFYPOSTPAINT; + } + else if (pDraw->nmcd.dwDrawStage==CDDS_ITEMPOSTPAINT) + { + if (IS_INTRESOURCE(pDraw->nmcd.lItemlParam) && m_CurrentSkin.Options[pDraw->nmcd.lItemlParam].bValue && m_CurrentSkin.Options[pDraw->nmcd.lItemlParam].type==SKIN_OPTION_COLOR) + { + RECT rc; + if (TreeView_GetItemRect(m_Tree,(HTREEITEM)pDraw->nmcd.dwItemSpec,&rc,TRUE)) + { + const wchar_t *str=m_CurrentSkin.Options[pDraw->nmcd.lItemlParam].sValue; + wchar_t *end; + COLORREF color=wcstoul(str,&end,16); + SetDCBrushColor(pDraw->nmcd.hdc,color&0xFFFFFF); + SelectObject(pDraw->nmcd.hdc,GetStockObject(DC_BRUSH)); + SelectObject(pDraw->nmcd.hdc,GetStockObject(BLACK_PEN)); + Rectangle(pDraw->nmcd.hdc,rc.right,rc.top,rc.right+rc.bottom-rc.top,rc.bottom-1); + } + } + } + return CDRF_DODEFAULT; +} + +LRESULT CSkinSettingsDlg::OnSelChanged( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + HTREEITEM hItem=TreeView_GetSelection(m_Tree); + if (hItem) + { + TVITEM item={TVIF_PARAM|TVIF_IMAGE,hItem}; + TreeView_GetItem(m_Tree,&item); + if (IS_INTRESOURCE(item.lParam)) + ItemSelected(item.hItem,(int)item.lParam,(item.iImage&SETTING_STATE_CHECKED)!=0); + else + ItemSelected(NULL,-1,false); + } + else + ItemSelected(NULL,-1,false); + return 0; +} + +void CSkinSettingsDlg::ToggleItem( HTREEITEM hItem ) +{ + if (!hItem) return; + TVITEM item={TVIF_PARAM|TVIF_IMAGE,hItem}; + TreeView_GetItem(m_Tree,&item); + if (item.iImage&SETTING_STATE_DISABLED) + return; + if (IS_INTRESOURCE(item.lParam)) + { + const MenuSkin::Option &option=m_CurrentSkin.Options[item.lParam]; + if (option.groupId>=0) + { + // radio button + if (item.iImage&SETTING_STATE_CHECKED) + return; + for (std::vector::const_iterator it=m_CurrentSkin.Options.begin();it!=m_CurrentSkin.Options.end();++it) + { + if (it->type==SKIN_OPTION_GROUP || it->groupId!=option.groupId) + continue; + it->bValue=&option==&*it; + } + } + else + { + option.bValue=!(item.iImage&SETTING_STATE_CHECKED); + } + StoreSkinOptions(); + } + else if (IS_INTRESOURCE(-item.lParam)) + { + // select variation + if (item.iImage&SETTING_STATE_CHECKED) + return; + m_VariationIndex=-1-(int)item.lParam; + CSettingsLockWrite lock; + const wchar_t *strNew=m_CurrentSkin.Variations[m_VariationIndex].second.labelEn; + const wchar_t *strOld=m_pSetting[1].value.vt==VT_BSTR?m_pSetting[1].value.bstrVal:L"???"; + if (wcscmp(strNew,strOld)!=0) + SetSettingsDirty(); + m_pSetting[1].value=CComVariant(strNew); + } + UpdateSkinSettings(); + if (IS_INTRESOURCE(item.lParam)) + ItemSelected(hItem,(int)item.lParam,m_CurrentSkin.Options[item.lParam].bValue); +} + +LRESULT CSkinSettingsDlg::OnClick( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + DWORD pos=GetMessagePos(); + TVHITTESTINFO test={{(short)LOWORD(pos),(short)HIWORD(pos)}}; + m_Tree.ScreenToClient(&test.pt); + if (TreeView_HitTest(m_Tree,&test)) + { + if (test.flags&(TVHT_ONITEMICON|TVHT_ONITEMLABEL)) + { + if (test.flags&TVHT_ONITEMLABEL) + { + TVITEM item={TVIF_STATE|TVIF_PARAM,test.hItem}; + TreeView_GetItem(m_Tree,&item); + if (!(item.state&TVIS_SELECTED) && IS_INTRESOURCE(item.lParam)) + { + const MenuSkin::Option &option=m_CurrentSkin.Options[item.lParam]; + if (option.type>SKIN_OPTION_BOOL && option.bValue && option.groupId==-1) + return 0; + } + } + ToggleItem(test.hItem); + } + if (test.flags&TVHT_ONITEMRIGHT) + { + TVITEM item={TVIF_STATE|TVIF_PARAM,test.hItem}; + TreeView_GetItem(m_Tree,&item); + if (item.lParam!=m_EditItemIndex && IS_INTRESOURCE(item.lParam)) + { + const MenuSkin::Option &option=m_CurrentSkin.Options[item.lParam]; + if (option.type==SKIN_OPTION_COLOR && option.bValue) + { + RECT rc; + if (TreeView_GetItemRect(m_Tree,item.hItem,&rc,TRUE) && test.pt.x>=rc.right && test.pt.xwVKey==VK_SPACE) + { + ToggleItem(TreeView_GetSelection(m_Tree)); + return 1; + } + bHandled=FALSE; + return 0; +} + +LRESULT CSkinSettingsDlg::OnGetInfoTip( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMTVGETINFOTIP *pTip=(NMTVGETINFOTIP*)pnmh; + TVITEM item={TVIF_STATE|TVIF_IMAGE|TVIF_PARAM,pTip->hItem,0,TVIS_OVERLAYMASK}; + TreeView_GetItem(m_Tree,&item); + int len=0; + if (IS_INTRESOURCE(item.lParam)) + { + len=Strcpy(pTip->pszText,pTip->cchTextMax,m_CurrentSkin.Options[item.lParam].tip); + } + else if (IS_INTRESOURCE(-item.lParam)) + { + len=Strcpy(pTip->pszText,pTip->cchTextMax,m_CurrentSkin.Variations[-1-item.lParam].second.tip); + } + if (item.state&TVIS_OVERLAYMASK) + { + Sprintf(pTip->pszText+len,pTip->cchTextMax-len,L"\r\n%s",LoadStringEx(IDS_SETTING_LOCKED)); + } + return 0; +} + +LRESULT CSkinSettingsDlg::OnEditKey( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==VK_RETURN && !(m_EditBox.GetWindowLong(GWL_STYLE)&ES_READONLY)) + ItemSelected(m_EditItem,m_EditItemIndex,true); + return 0; +} + +LRESULT CSkinSettingsDlg::OnEditChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + UpdateEditPosition(); + return 0; +} + +LRESULT CSkinSettingsDlg::OnKillFocus( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (!m_bIgnoreFocus && m_EditItemIndex>=0) + { + ApplyEditBox(); + UpdateEditPosition(); + } + return 0; +} + +LRESULT CSkinSettingsDlg::OnBrowse( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (m_EditMode==SKIN_OPTION_IMAGE) + { + m_bIgnoreFocus=true; + CString str; + m_EditBox.GetWindowText(str); + str.TrimLeft(); str.TrimRight(); + wchar_t text[1024]; + if (_wcsicmp(PathFindExtension(str),L".bmp")==0 || _wcsicmp(PathFindExtension(str),L".png")==0 || _wcsicmp(PathFindExtension(str),L".jpg")==0) + { + Strcpy(text,_countof(text),str); + DoEnvironmentSubst(text,_countof(text)); + } + else + text[0]=0; + if (BrowseForBitmap(m_hWnd,text,true)) + { + m_EditBox.SetWindowText(text); + } + SendMessage(WM_NEXTDLGCTL,(LPARAM)m_EditBox.m_hWnd,TRUE); + m_EditBox.SetFocus(); + m_bIgnoreFocus=false; + } + else if (m_EditMode==SKIN_OPTION_COLOR) + { + m_bIgnoreFocus=true; + CString str; + m_EditBox.GetWindowText(str); + str.TrimLeft(); str.TrimRight(); + wchar_t *end; + int val=wcstol(str,&end,16)&0xFFFFFF; + static COLORREF customColors[16]; + CHOOSECOLOR choose={sizeof(choose),m_hWnd,NULL,val,customColors}; + choose.Flags=CC_ANYCOLOR|CC_FULLOPEN|CC_RGBINIT; + if (ChooseColor(&choose)) + { + wchar_t text[100]; + Sprintf(text,_countof(text),L"%06X",choose.rgbResult); + m_EditBox.SetWindowText(text); + ApplyEditBox(); + m_Tree.Invalidate(); + } + SendMessage(WM_NEXTDLGCTL,(LPARAM)m_EditBox.m_hWnd,TRUE); + m_EditBox.SetFocus(); + m_bIgnoreFocus=false; + } + return 0; +} + +void CSkinSettingsDlg::ApplyEditBox( void ) +{ + if (m_EditItemIndex>=0) + { + CString str; + m_EditBox.GetWindowText(str); + str.TrimLeft(); str.TrimRight(); + m_CurrentSkin.Options[m_EditItemIndex].sValue=str; + StoreSkinOptions(); + } +} + +void CSkinSettingsDlg::ItemSelected( HTREEITEM hItem, int index, bool bEnabled ) +{ + if (m_EditItemIndex>=0) + { + ApplyEditBox(); + const MenuSkin::Option &option=m_CurrentSkin.Options[m_EditItemIndex]; + wchar_t text[256]; + if (option.bValue && option.type>SKIN_OPTION_BOOL) + Sprintf(text,_countof(text),L"%s: %s",option.label,option.sValue); + else + Sprintf(text,_countof(text),L"%s",option.label); + TVITEM item={TVIF_TEXT,m_EditItem,0,0,text}; + TreeView_SetItem(m_Tree,&item); + m_EditItemIndex=-1; + } + m_EditItem=NULL; + TSkinOptionType mode=SKIN_OPTION_NONE; + CString text; + if (index>=0) + { + const MenuSkin::Option &option=m_CurrentSkin.Options[index]; + if (option.type>SKIN_OPTION_BOOL) + mode=option.type; + text=option.sValue; + } + + RECT rc; + m_EditMode=mode; + if (mode!=SKIN_OPTION_NONE) + { + CString str=m_CurrentSkin.Options[index].label; + TVITEM item={TVIF_TEXT,hItem,0,0,(LPWSTR)(LPCWSTR)str}; + TreeView_SetItem(m_Tree,&item); + m_Tree.GetClientRect(&rc); + int w=rc.right; + TreeView_GetItemRect(m_Tree,hItem,&rc,TRUE); + rc.left=rc.right; + rc.right=w; + if (bEnabled && mode>SKIN_OPTION_BOOL) + { + m_EditItem=hItem; + m_EditItemIndex=index; + } + } + + if (bEnabled && (mode==SKIN_OPTION_IMAGE || mode==SKIN_OPTION_COLOR)) + { + RECT rc2=rc; + int width=(rc2.bottom-rc2.top)*3/2; + rc2.left=rc2.right-width; + m_BrowseButton.SetWindowPos(NULL,&rc2,SWP_NOZORDER|SWP_SHOWWINDOW); + m_BrowseButton.EnableWindow(bEnabled); + rc.right=rc2.left; + } + else + m_BrowseButton.ShowWindow(SW_HIDE); + + if (bEnabled && mode>SKIN_OPTION_BOOL) + { + m_EditBox.SetWindowText(text); + m_EditBox.SendMessage(EM_SETREADONLY,!bEnabled,0); + m_EditBox.SetWindowPos(NULL,&rc,SWP_NOZORDER|SWP_SHOWWINDOW); + SendMessage(WM_NEXTDLGCTL,(LPARAM)m_EditBox.m_hWnd,TRUE); + } + else + m_EditBox.ShowWindow(SW_HIDE); +} + +void CSkinSettingsDlg::UpdateEditPosition( void ) +{ + if (m_EditMode==SKIN_OPTION_NONE) return; + + RECT rc; + m_Tree.GetClientRect(&rc); + int w=rc.right; + TreeView_GetItemRect(m_Tree,m_EditItem,&rc,TRUE); + rc.left=rc.right; + rc.right=w; + w-=rc.left; + int width=(rc.bottom-rc.top)*3/2; + + HDC hdc=CreateCompatibleDC(NULL); + HFONT font0=(HFONT)SelectObject(hdc,m_EditBox.GetFont()); + SIZE size; + CString str; + m_EditBox.GetWindowText(str); + GetTextExtentPoint(hdc,str,str.GetLength(),&size); + SelectObject(hdc,font0); + DeleteDC(hdc); + DWORD margins=(DWORD)m_EditBox.SendMessage(EM_GETMARGINS); + size.cx+=HIWORD(margins)+LOWORD(margins)+12; + if (m_EditMode==SKIN_OPTION_IMAGE || m_EditMode==SKIN_OPTION_COLOR) + size.cx+=width; + if (size.cx::OnSize(); + UpdateEditPosition(); + + CWindow skins=GetDlgItem(IDC_COMBOSKIN); + CWindow tooltip=TreeView_GetToolTips(m_Tree); + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS,m_hWnd,'CLSH'}; + skins.GetClientRect(&tool.rect); + skins.MapWindowPoints(m_hWnd,&tool.rect); + tooltip.SendMessage(TTM_NEWTOOLRECT,0,(LPARAM)&tool); + + return 0; +} + +LRESULT CSkinSettingsDlg::OnSelEndOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + m_SkinIndex=(int)SendDlgItemMessage(IDC_COMBOSKIN,CB_GETCURSEL); + { + CSettingsLockWrite lock; + const wchar_t *strNew=m_SkinIndex==0?L"":m_SkinNames[m_SkinIndex]; + const wchar_t *strOld=m_pSetting[0].value.vt==VT_BSTR?m_pSetting[0].value.bstrVal:L"???"; + if (wcscmp(strNew,strOld)!=0) + SetSettingsDirty(); + m_pSetting[0].value=CComBSTR(strNew); + } + InitSkinUI(); + return 0; +} + +static HRESULT CALLBACK TaskDialogCallbackProc( HWND hwnd, UINT uNotification, WPARAM wParam, LPARAM lParam, LONG_PTR dwRefData ) +{ + if (uNotification==TDN_HYPERLINK_CLICKED) + { + ShellExecute(hwnd,L"open",(const wchar_t*)lParam,NULL,NULL,SW_SHOWNORMAL); + } + return S_OK; +} + +LRESULT CSkinSettingsDlg::OnAbout( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + int idx=(int)SendDlgItemMessage(IDC_COMBOSKIN,CB_GETCURSEL,0,0); + const wchar_t *name=m_SkinNames[idx]; + wchar_t caption[256]; + Sprintf(caption,_countof(caption),LoadStringEx(IDS_SKIN_ABOUT),name); + if (!m_bLoadSuccess) + { + MessageBox(LoadStringEx(IDS_SKIN_FAIL),caption,MB_OK|MB_ICONERROR); + return TRUE; + } + TASKDIALOGCONFIG task={sizeof(task),m_hWnd,NULL,TDF_ENABLE_HYPERLINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_USE_HICON_MAIN,TDCBF_OK_BUTTON}; + task.pszWindowTitle=caption; + task.pszContent=m_CurrentSkin.About; + task.hMainIcon=m_CurrentSkin.AboutIcon?m_CurrentSkin.AboutIcon:LoadIcon(NULL,IDI_INFORMATION); + task.pfCallback=TaskDialogCallbackProc; + TaskDialogIndirect(&task,NULL,NULL,NULL); + return TRUE; +} + +LRESULT CSkinSettingsDlg::OnReset( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + { + CSettingsLockWrite lock; + if (!m_pSetting[0].IsLocked()) + m_pSetting[0].value=m_pSetting[0].defValue; + if (!m_pSetting[1].IsLocked()) + m_pSetting[1].value=m_pSetting[1].defValue; + if (!m_pSetting[2].IsLocked()) + m_pSetting[2].value=m_pSetting[2].defValue; + SetSettingsDirty(); + } + SetGroup(m_pSetting-1); + return TRUE; +} + +void CSkinSettingsDlg::SetGroup( CSetting *pGroup ) +{ + m_pSetting=pGroup+1; + // the skin settings are never default + { + CSettingsLockWrite lock; + m_pSetting[0].flags&=~CSetting::FLAG_DEFAULT; + m_pSetting[1].flags&=~CSetting::FLAG_DEFAULT; + m_pSetting[2].flags&=~CSetting::FLAG_DEFAULT; + } + + const wchar_t *skin=L""; + if (m_pSetting[0].value.vt==VT_BSTR) + skin=m_pSetting[0].value.bstrVal; + + m_SkinIndex=-1; + if (!*skin) + SendDlgItemMessage(IDC_COMBOSKIN,CB_SETCURSEL,0); + else + { + int n=(int)m_SkinNames.size(); + for (int i=1;i &modules, int style, int mask ): CEditCustomItemDlg(pItem,modules) { m_Style=style; m_StyleMask=mask; } + + BEGIN_MSG_MAP( CEditMenuDlg ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + COMMAND_ID_HANDLER( IDOK, OnOK ) + COMMAND_ID_HANDLER( IDCANCEL, OnCancel ) + COMMAND_HANDLER( IDC_COMBOCOMMAND, CBN_KILLFOCUS, OnCommandChanged ) + COMMAND_HANDLER( IDC_COMBOCOMMAND, CBN_SELENDOK, OnCommandChanged ) + COMMAND_HANDLER( IDC_BUTTONCOMMAND, BN_CLICKED, OnBrowseCommand ) + COMMAND_HANDLER( IDC_BUTTONLINK, BN_CLICKED, OnBrowseLink ) + COMMAND_HANDLER( IDC_BUTTONICON, BN_CLICKED, OnBrowseIcon ) + COMMAND_HANDLER( IDC_COMBOLINK, CBN_KILLFOCUS, OnLinkChanged ) + COMMAND_HANDLER( IDC_COMBOLINK, CBN_SELENDOK, OnLinkChanged ) + COMMAND_HANDLER( IDC_EDITICON, EN_KILLFOCUS, OnIconChanged ) + COMMAND_HANDLER( IDC_CHECKTRACK, BN_CLICKED, OnCheckTrack ) + COMMAND_HANDLER( IDC_CHECKNOTRACK, BN_CLICKED, OnCheckTrack ) + COMMAND_HANDLER( IDC_CHECKMULTICOLUMN, BN_CLICKED, OnCheckMulti ) + COMMAND_HANDLER( IDC_BUTTONRESET, BN_CLICKED, OnReset ) + CHAIN_MSG_MAP( CEditCustomItemDlg ) + END_MSG_MAP() + + virtual BEGIN_RESIZE_MAP + RESIZE_CONTROL(IDC_COMBOCOMMAND,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_COMBOLINK,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_BUTTONCOMMAND,MOVE_MOVE_X) + RESIZE_CONTROL(IDC_BUTTONLINK,MOVE_MOVE_X) + RESIZE_CONTROL(IDC_EDITLABEL,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_EDITTIP,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_EDITICON,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_BUTTONICON,MOVE_MOVE_X) + RESIZE_CONTROL(IDOK,MOVE_MOVE_X) + RESIZE_CONTROL(IDCANCEL,MOVE_MOVE_X) + END_RESIZE_MAP + +protected: + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCommandChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnLinkChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnIconChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCheckTrack( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCheckMulti( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnBrowseCommand( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnBrowseLink( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnBrowseIcon( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnReset( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + +private: + int m_Style, m_StyleMask; +}; + +LRESULT CEditMenuDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + CWindow commands=GetDlgItem(IDC_COMBOCOMMAND); + CWindow links=GetDlgItem(IDC_COMBOLINK); + InitDialog(commands,g_StdCommands,m_Style,m_StyleMask,links,g_CommonLinks); + SetDlgItemText(IDC_EDITLABEL,m_pItem->label); + SetDlgItemText(IDC_EDITTIP,m_pItem->tip); + SetDlgItemText(IDC_EDITICON,m_pItem->icon); + + BOOL bEnable=!(m_pItem->pStdCommand && m_pItem->pStdCommand->knownFolder); + links.EnableWindow(bEnable); + GetDlgItem(IDC_BUTTONLINK).EnableWindow(bEnable); + GetDlgItem(IDC_BUTTONRESET).EnableWindow(m_pItem->pStdCommand && *m_pItem->pStdCommand->name); + + if (m_pItem->settings&StdMenuItem::MENU_TRACK) + m_pItem->settings&=~StdMenuItem::MENU_NOTRACK; + CheckDlgButton(IDC_CHECKSORTZA,(m_pItem->settings&StdMenuItem::MENU_SORTZA)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKSORTZAREC,(m_pItem->settings&StdMenuItem::MENU_SORTZA_REC)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKSORTONCE,(m_pItem->settings&StdMenuItem::MENU_SORTONCE)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKOPENUP,(m_pItem->settings&StdMenuItem::MENU_OPENUP)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKOPENUPREC,(m_pItem->settings&StdMenuItem::MENU_OPENUP_REC)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKNOEXPAND,(m_pItem->settings&StdMenuItem::MENU_NOEXPAND)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKNOTRACK,(m_pItem->settings&StdMenuItem::MENU_NOTRACK)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKITEMSFIRST,(m_pItem->settings&StdMenuItem::MENU_ITEMS_FIRST)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKINLINE,(m_pItem->settings&StdMenuItem::MENU_INLINE)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKSPLIT,(m_pItem->settings&StdMenuItem::MENU_SPLIT_BUTTON)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKNOEXT,(m_pItem->settings&StdMenuItem::MENU_NOEXTENSIONS)?BST_CHECKED:BST_UNCHECKED); + if (m_pItem->pStdCommand && (wcscmp(m_pItem->pStdCommand->name,L"programs")==0 || wcscmp(m_pItem->pStdCommand->name,L"apps")==0)) + { + CheckDlgButton(IDC_CHECKMULTICOLUMN,BST_CHECKED); + GetDlgItem(IDC_CHECKMULTICOLUMN).EnableWindow(FALSE); + CheckDlgButton(IDC_CHECKTRACK,(m_pItem->settings&StdMenuItem::MENU_NOTRACK)?BST_UNCHECKED:BST_CHECKED); + } + else + { + CheckDlgButton(IDC_CHECKMULTICOLUMN,(m_pItem->settings&StdMenuItem::MENU_MULTICOLUMN)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKTRACK,(m_pItem->settings&StdMenuItem::MENU_TRACK)?BST_CHECKED:BST_UNCHECKED); + } + + UpdateIcons(IDC_ICONN,0); + SendDlgItemMessage(IDC_EDITLABEL,EM_SETCUEBANNER,TRUE,(LPARAM)(const wchar_t*)LoadStringEx(IDS_NO_TEXT)); + + CWindow tooltip=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_TRANSPARENT,TOOLTIPS_CLASS,NULL,WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP,0,0,0,0,m_hWnd,NULL,g_Instance,NULL); + tooltip.SendMessage(TTM_SETMAXTIPWIDTH,0,GetSystemMetrics(SM_CXSCREEN)/2); + + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS|TTF_IDISHWND,m_hWnd,(UINT_PTR)(HWND)commands}; + CString str=LoadStringEx(IDS_COMMAND_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + tool.uId=(UINT_PTR)(HWND)commands.GetWindow(GW_CHILD); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_LINK_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)links; + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + tool.uId=(UINT_PTR)(HWND)links.GetWindow(GW_CHILD); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_TEXT_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_EDITLABEL); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_TIP_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_EDITTIP); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_ICON_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_EDITICON); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_SORTZA_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKSORTZA); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_SORTZAREC_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKSORTZAREC); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_SORTONCE_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKSORTONCE); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_OPENUP_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKOPENUP); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_OPENUPREC_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKOPENUPREC); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_NOEXPAND_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKNOEXPAND); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_MULTICOLUMN_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKMULTICOLUMN); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_TRACK_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKTRACK); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_NOTRACK_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKNOTRACK); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_ITEMSFIRST_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKITEMSFIRST); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_INLINE_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKINLINE); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_SPLIT_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKSPLIT); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_NOEXTENSIONS_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKNOEXT); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_RESTORE_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_BUTTONRESET); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + return TRUE; +} + +LRESULT CEditMenuDlg::OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + GetDlgItemText(IDC_EDITLABEL,m_pItem->label); + m_pItem->label.TrimLeft(); + m_pItem->label.TrimRight(); + GetDlgItemText(IDC_EDITTIP,m_pItem->tip); + m_pItem->tip.TrimLeft(); + m_pItem->tip.TrimRight(); + + m_pItem->settings=0; + bool bForceMultiColumn=(m_pItem->pStdCommand && (wcscmp(m_pItem->pStdCommand->name,L"programs")==0 || wcscmp(m_pItem->pStdCommand->name,L"apps")==0)); + if (IsDlgButtonChecked(IDC_CHECKSORTZA)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_SORTZA; + if (IsDlgButtonChecked(IDC_CHECKSORTZAREC)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_SORTZA_REC; + if (IsDlgButtonChecked(IDC_CHECKSORTONCE)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_SORTONCE; + if (IsDlgButtonChecked(IDC_CHECKOPENUP)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_OPENUP; + if (IsDlgButtonChecked(IDC_CHECKOPENUPREC)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_OPENUP_REC; + if (IsDlgButtonChecked(IDC_CHECKNOEXPAND)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_NOEXPAND; + if (IsDlgButtonChecked(IDC_CHECKTRACK)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_TRACK; + if (IsDlgButtonChecked(IDC_CHECKNOTRACK)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_NOTRACK; + if (IsDlgButtonChecked(IDC_CHECKITEMSFIRST)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_ITEMS_FIRST; + if (IsDlgButtonChecked(IDC_CHECKINLINE)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_INLINE; + if (IsDlgButtonChecked(IDC_CHECKSPLIT)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_SPLIT_BUTTON; + if (IsDlgButtonChecked(IDC_CHECKNOEXT)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_NOEXTENSIONS; + if (bForceMultiColumn) + { + // special handling of the Programs menu + // it is always MULTICOLUMN + // it is always tracking, unless NOTRACK is set + m_pItem->settings&=~StdMenuItem::MENU_TRACK; + } + else + { + if (IsDlgButtonChecked(IDC_CHECKMULTICOLUMN)==BST_CHECKED) + m_pItem->settings|=StdMenuItem::MENU_MULTICOLUMN; + } + + return CEditCustomItemDlg::OnOK(wNotifyCode,wID,hWndCtl,bHandled); +} + +LRESULT CEditMenuDlg::OnCommandChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CString text=GetComboText(wNotifyCode,wID); + if (text==m_pItem->command) return 0; + m_pItem->SetCommand(text,g_StdCommands,m_Style,m_StyleMask); + BOOL bEnable=!(m_pItem->pStdCommand && m_pItem->pStdCommand->knownFolder); + GetDlgItem(IDC_COMBOLINK).EnableWindow(bEnable); + GetDlgItem(IDC_BUTTONLINK).EnableWindow(bEnable); + GetDlgItem(IDC_BUTTONRESET).EnableWindow(m_pItem->pStdCommand && *m_pItem->pStdCommand->name); + if (m_pItem->pStdCommand && (wcscmp(m_pItem->pStdCommand->name,L"programs")==0 || wcscmp(m_pItem->pStdCommand->name,L"apps")==0)) + { + CheckDlgButton(IDC_CHECKMULTICOLUMN,BST_CHECKED); + GetDlgItem(IDC_CHECKMULTICOLUMN).EnableWindow(FALSE); + } + else + { + CheckDlgButton(IDC_CHECKMULTICOLUMN,(m_pItem->settings&StdMenuItem::MENU_MULTICOLUMN)?BST_CHECKED:BST_UNCHECKED); + GetDlgItem(IDC_CHECKMULTICOLUMN).EnableWindow(TRUE); + } + UpdateIcons(IDC_ICONN,0); + return 0; +} + +LRESULT CEditMenuDlg::OnLinkChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CString text=GetComboText(wNotifyCode,wID); + if (text==m_pItem->link) return 0; + m_pItem->link=text; + UpdateIcons(IDC_ICONN,0); + return 0; +} + +LRESULT CEditMenuDlg::OnIconChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CString text; + GetDlgItemText(IDC_EDITICON,text); + text.TrimLeft(); + text.TrimRight(); + if (text==m_pItem->icon) return 0; + m_pItem->icon=text; + UpdateIcons(IDC_ICONN,0); + return 0; +} + +LRESULT CEditMenuDlg::OnCheckTrack( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (IsDlgButtonChecked(wID)==BST_CHECKED) + CheckDlgButton(IDC_CHECKTRACK+IDC_CHECKNOTRACK-wID,BST_UNCHECKED); + return 0; +} + +LRESULT CEditMenuDlg::OnCheckMulti( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (IsDlgButtonChecked(IDC_CHECKMULTICOLUMN)==BST_CHECKED) + m_pItem->settings|=StdMenuItem::MENU_MULTICOLUMN; + else + m_pItem->settings&=~StdMenuItem::MENU_MULTICOLUMN; + return 0; +} + +LRESULT CEditMenuDlg::OnBrowseCommand( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + wchar_t text[_MAX_PATH]; + GetDlgItemText(IDC_COMBOCOMMAND,text,_countof(text)); + if (BrowseCommandHelper(m_hWnd,text)) + { + SetDlgItemText(IDC_COMBOCOMMAND,text); + SendMessage(WM_COMMAND,MAKEWPARAM(IDC_COMBOCOMMAND,CBN_KILLFOCUS)); + } + return 0; +} + +LRESULT CEditMenuDlg::OnBrowseLink( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + wchar_t text[_MAX_PATH]; + GetDlgItemText(IDC_COMBOLINK,text,_countof(text)); + if (BrowseLinkHelper(m_hWnd,text)) + { + SetDlgItemText(IDC_COMBOLINK,text); + SendMessage(WM_COMMAND,MAKEWPARAM(IDC_COMBOLINK,CBN_KILLFOCUS)); + } + return 0; +} + +LRESULT CEditMenuDlg::OnBrowseIcon( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + wchar_t text[_MAX_PATH]; + GetDlgItemText(IDC_EDITICON,text,_countof(text)); + if (BrowseIconHelper(m_hWnd,text)) + { + SetDlgItemText(IDC_EDITICON,text); + SendMessage(WM_COMMAND,MAKEWPARAM(IDC_EDITICON,EN_KILLFOCUS)); + } + return 0; +} + +LRESULT CEditMenuDlg::OnReset( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (!m_pItem->pStdCommand || !*m_pItem->pStdCommand->name) + return 0; + m_pItem->link.Empty(); + m_pItem->label=m_pItem->pStdCommand->label; + m_pItem->tip=m_pItem->pStdCommand->tip; + m_pItem->icon=m_pItem->pStdCommand->icon; + m_pItem->iconD=m_pItem->pStdCommand->iconD; + m_pItem->settings=m_pItem->pStdCommand->settings&~m_StyleMask; + SendDlgItemMessage(IDC_COMBOLINK,CB_SETCURSEL,-1); + SetDlgItemText(IDC_EDITLABEL,m_pItem->label); + SetDlgItemText(IDC_EDITTIP,m_pItem->tip); + SetDlgItemText(IDC_EDITICON,m_pItem->icon); + CheckDlgButton(IDC_CHECKSORTZA,(m_pItem->settings&StdMenuItem::MENU_SORTZA)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKSORTZAREC,(m_pItem->settings&StdMenuItem::MENU_SORTZA_REC)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKSORTONCE,(m_pItem->settings&StdMenuItem::MENU_SORTONCE)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKOPENUP,(m_pItem->settings&StdMenuItem::MENU_OPENUP)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKOPENUPREC,(m_pItem->settings&StdMenuItem::MENU_OPENUP_REC)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKNOEXPAND,(m_pItem->settings&StdMenuItem::MENU_NOEXPAND)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKMULTICOLUMN,(m_pItem->settings&StdMenuItem::MENU_MULTICOLUMN)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKTRACK,(m_pItem->settings&StdMenuItem::MENU_TRACK)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKNOTRACK,(m_pItem->settings&StdMenuItem::MENU_NOTRACK)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKITEMSFIRST,(m_pItem->settings&StdMenuItem::MENU_ITEMS_FIRST)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKINLINE,(m_pItem->settings&StdMenuItem::MENU_INLINE)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKSPLIT,(m_pItem->settings&StdMenuItem::MENU_SPLIT_BUTTON)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKNOEXT,(m_pItem->settings&StdMenuItem::MENU_NOEXTENSIONS)?BST_CHECKED:BST_UNCHECKED); + if (m_pItem->pStdCommand && (wcscmp(m_pItem->pStdCommand->name,L"programs")==0 || wcscmp(m_pItem->pStdCommand->name,L"apps")==0)) + { + CheckDlgButton(IDC_CHECKMULTICOLUMN,BST_CHECKED); + GetDlgItem(IDC_CHECKMULTICOLUMN).EnableWindow(FALSE); + } + else + GetDlgItem(IDC_CHECKMULTICOLUMN).EnableWindow(TRUE); + + UpdateIcons(IDC_ICONN,IDC_ICOND); + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +class CCustomMenuDlg: public CCustomTreeDlg +{ +public: + CCustomMenuDlg( int style, int mask ): CCustomTreeDlg(true,g_StdCommands,style,mask) {} + bool Validate( void ); + + static void UpdateWarnings( TMenuStyle menuStyle ); + +protected: + virtual void ParseTreeItemExtra( CTreeItem *pItem, CSettingsParser &parser ); + virtual void SerializeItemExtra( CTreeItem *pItem, std::vector &stringBuilder ); + virtual bool EditItem( CTreeItem *pItem, HWND tree, HTREEITEM hItem, std::vector &modules ); + virtual void ItemsChanged( void ) { UpdateWarnings(m_Style==StdMenuItem::MENU_STYLE_CLASSIC1?MENU_CLASSIC1:MENU_CLASSIC2); } +}; + +void CCustomMenuDlg::ParseTreeItemExtra( CTreeItem *pItem, CSettingsParser &parser ) +{ + pItem->settings=0; + wchar_t text[256]; + Sprintf(text,_countof(text),L"%s.Settings",pItem->name); + const wchar_t *str=parser.FindSetting(text); + if (!str) return; + + while (*str) + { + wchar_t token[256]; + str=GetToken(str,token,_countof(token),L", \t|;"); + if (_wcsicmp(token,L"OPEN_UP")==0) pItem->settings|=StdMenuItem::MENU_OPENUP; + if (_wcsicmp(token,L"OPEN_UP_CHILDREN")==0) pItem->settings|=StdMenuItem::MENU_OPENUP_REC; + if (_wcsicmp(token,L"SORT_ZA")==0) pItem->settings|=StdMenuItem::MENU_SORTZA; + if (_wcsicmp(token,L"SORT_ZA_CHILDREN")==0) pItem->settings|=StdMenuItem::MENU_SORTZA_REC; + if (_wcsicmp(token,L"SORT_ONCE")==0) pItem->settings|=StdMenuItem::MENU_SORTONCE; + if (_wcsicmp(token,L"ITEMS_FIRST")==0) pItem->settings|=StdMenuItem::MENU_ITEMS_FIRST; + if (_wcsicmp(token,L"TRACK_RECENT")==0) pItem->settings|=StdMenuItem::MENU_TRACK; + if (_wcsicmp(token,L"NOTRACK_RECENT")==0) pItem->settings|=StdMenuItem::MENU_NOTRACK; + if (_wcsicmp(token,L"NOEXPAND")==0) pItem->settings|=StdMenuItem::MENU_NOEXPAND; + if (_wcsicmp(token,L"MULTICOLUMN")==0) pItem->settings|=StdMenuItem::MENU_MULTICOLUMN; + if (_wcsicmp(token,L"INLINE")==0) pItem->settings|=StdMenuItem::MENU_INLINE; + if (_wcsicmp(token,L"SPLIT")==0) pItem->settings|=StdMenuItem::MENU_SPLIT_BUTTON; + if (_wcsicmp(token,L"NOEXTENSIONS")==0) pItem->settings|=StdMenuItem::MENU_NOEXTENSIONS; + } +} + +void CCustomMenuDlg::SerializeItemExtra( CTreeItem *pItem, std::vector &stringBuilder ) +{ + if (!pItem->settings) return; + wchar_t text[256]; + Sprintf(text,_countof(text),L"%s.Settings=",pItem->name); + AppendString(stringBuilder,text); + if (pItem->settings&StdMenuItem::MENU_OPENUP) AppendString(stringBuilder,L"OPEN_UP|"); + if (pItem->settings&StdMenuItem::MENU_OPENUP_REC) AppendString(stringBuilder,L"OPEN_UP_CHILDREN|"); + if (pItem->settings&StdMenuItem::MENU_SORTZA) AppendString(stringBuilder,L"SORT_ZA|"); + if (pItem->settings&StdMenuItem::MENU_SORTZA_REC) AppendString(stringBuilder,L"SORT_ZA_CHILDREN|"); + if (pItem->settings&StdMenuItem::MENU_SORTONCE) AppendString(stringBuilder,L"SORT_ONCE|"); + if (pItem->settings&StdMenuItem::MENU_ITEMS_FIRST) AppendString(stringBuilder,L"ITEMS_FIRST|"); + if (pItem->settings&StdMenuItem::MENU_TRACK) AppendString(stringBuilder,L"TRACK_RECENT|"); + if (pItem->settings&StdMenuItem::MENU_NOTRACK) AppendString(stringBuilder,L"NOTRACK_RECENT|"); + if (pItem->settings&StdMenuItem::MENU_NOEXPAND) AppendString(stringBuilder,L"NOEXPAND|"); + if (pItem->settings&StdMenuItem::MENU_MULTICOLUMN) AppendString(stringBuilder,L"MULTICOLUMN|"); + if (pItem->settings&StdMenuItem::MENU_INLINE) AppendString(stringBuilder,L"INLINE|"); + if (pItem->settings&StdMenuItem::MENU_SPLIT_BUTTON) AppendString(stringBuilder,L"SPLIT|"); + if (pItem->settings&StdMenuItem::MENU_NOEXTENSIONS) AppendString(stringBuilder,L"NOEXTENSIONS|"); + stringBuilder[stringBuilder.size()-1]='\n'; +} + +bool CCustomMenuDlg::EditItem( CTreeItem *pItem, HWND tree, HTREEITEM hItem, std::vector &modules ) +{ + return CEditMenuDlg(pItem,modules,m_Style,m_StyleMask).Run(m_hWnd,IDD_CUSTOMMENU); +} + +void CCustomMenuDlg::UpdateWarnings( TMenuStyle menuStyle ) +{ + const CSetting *pSetting=FindSetting(menuStyle==MENU_CLASSIC1?L"MenuItems1":L"MenuItems2"); + Assert(pSetting->value.vt==VT_BSTR); + CString items=pSetting->value.bstrVal; + + bool bWarning; + items.MakeLower(); + items.Replace('\r','\n'); + bWarning=!wcsstr(items,L".command=favorites\n"); + UpdateSettingText(L"Favorites",-1,bWarning?IDS_SHOW_FAVORITES_TIP2:IDS_SHOW_FAVORITES_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=recent_documents\n"); + UpdateSettingText(L"Documents",-1,bWarning?IDS_SHOW_DOCUMENTS_TIP2:IDS_SHOW_DOCUMENTS_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=computer\n"); + UpdateSettingText(L"Computer",-1,bWarning?IDS_SHOW_COMPUTER_TIP2:IDS_SHOW_COMPUTER_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=user_files\n"); + UpdateSettingText(L"UserFiles",-1,bWarning?IDS_SHOW_USERFILES_TIP2:IDS_SHOW_USERFILES_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=user_documents\n"); + UpdateSettingText(L"UserDocuments",-1,bWarning?IDS_SHOW_USERDOCS_TIP2:IDS_SHOW_USERDOCS_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=user_pictures\n"); + UpdateSettingText(L"UserPictures",-1,bWarning?IDS_SHOW_USERPICS_TIP2:IDS_SHOW_USERPICS_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=control_panel\n"); + UpdateSettingText(L"ControlPanel",-1,bWarning?IDS_SHOW_CP_TIP2:IDS_SHOW_CP_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=network_connections\n"); + UpdateSettingText(L"Network",-1,bWarning?IDS_SHOW_NETWORK_TIP2:IDS_SHOW_NETWORK_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=printers\n"); + UpdateSettingText(L"Printers",-1,bWarning?IDS_SHOW_PRINTERS_TIP2:IDS_SHOW_PRINTERS_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=shutdown_box\n"); + UpdateSettingText(L"Shutdown",-1,bWarning?IDS_SHOW_SHUTDOWN_TIP2:IDS_SHOW_SHUTDOWN_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=search_box\n"); + UpdateSettingText(L"SearchBox",-1,bWarning?IDS_SHOW_SEARCH_BOX_TIP2:IDS_SHOW_SEARCH_BOX_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=search\n"); + UpdateSettingText(L"Search",-1,bWarning?IDS_SHOW_SEARCH_TIP2:IDS_SHOW_SEARCH_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=apps\n"); + UpdateSettingText(L"ShowAppsMenu",-1,bWarning?IDS_SHOW_APPS_MENU_TIP2:IDS_SHOW_APPS_MENU_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=help\n"); + UpdateSettingText(L"Help",-1,bWarning?IDS_SHOW_HELP_TIP2:IDS_SHOW_HELP_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=run\n"); + UpdateSettingText(L"Run",-1,bWarning?IDS_SHOW_RUN_TIP2:IDS_SHOW_RUN_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=logoff\n"); + UpdateSettingText(L"LogOff",-1,bWarning?IDS_SHOW_LOGOFF_TIP2:IDS_SHOW_LOGOFF_TIP,bWarning); + + bWarning=!wcsstr(items,L".command=undock\n"); + UpdateSettingText(L"Undock",-1,bWarning?IDS_SHOW_UNDOCK_TIP2:IDS_SHOW_UNDOCK_TIP,bWarning); +} + +class CCustomMenuPanel: public ISettingsPanel +{ +public: + CCustomMenuPanel( int index ) { m_Index=index; } + virtual HWND Create( HWND parent ); + virtual HWND Activate( CSetting *pGroup, const RECT &rect, bool bReset ); + virtual bool Validate( HWND parent ) { return true; } + +private: + int m_Index; + static CCustomMenuDlg s_Dialogs[2]; +}; + +CCustomMenuDlg CCustomMenuPanel::s_Dialogs[2]={ + CCustomMenuDlg(StdMenuItem::MENU_STYLE_CLASSIC1,StdMenuItem::MENU_STYLE_MASK), + CCustomMenuDlg(StdMenuItem::MENU_STYLE_CLASSIC2,StdMenuItem::MENU_STYLE_MASK), +}; + +HWND CCustomMenuPanel::Create( HWND parent ) +{ + if (!s_Dialogs[m_Index].m_hWnd) + s_Dialogs[m_Index].Create(parent,LoadDialogEx(IDD_CUSTOMTREE)); + return s_Dialogs[m_Index].m_hWnd; +} + +HWND CCustomMenuPanel::Activate( CSetting *pGroup, const RECT &rect, bool bReset ) +{ + s_Dialogs[m_Index].SetGroup(pGroup,bReset); + s_Dialogs[m_Index].SetWindowPos(HWND_TOP,&rect,SWP_SHOWWINDOW); + return s_Dialogs[m_Index].m_hWnd; +} + +static CCustomMenuPanel g_CustomMenuPanel1(0); +static CCustomMenuPanel g_CustomMenuPanel2(1); + +/////////////////////////////////////////////////////////////////////////////// + +class CCustomMenuDlg7: public CResizeableDlg +{ +public: + CCustomMenuDlg7( void ) {} + ~CCustomMenuDlg7( void ) {} + + BEGIN_MSG_MAP( CCustomMenuDlg7 ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + MESSAGE_HANDLER( WM_SIZE, OnSize ) + MESSAGE_HANDLER( WM_CONTEXTMENU, OnContextMenu ) + REFLECT_NOTIFICATIONS() + END_MSG_MAP() + + BEGIN_RESIZE_MAP + RESIZE_CONTROL(IDC_LISTITEMS,MOVE_SIZE_X|MOVE_SIZE_Y) + RESIZE_CONTROL(IDC_STATICHINT,MOVE_SIZE_X|MOVE_MOVE_Y) + END_RESIZE_MAP + + void SetGroup( CSetting *pGroup, bool bReset ); + +protected: + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnContextMenu( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + +private: + + struct MenuItem + { + CString command; + CString link; + CString label; + CString tip; + CString icon; + unsigned int settings; + int stdItemIndex; + }; + + class CItemList: public CWindowImpl + { + public: + CItemList( void ) { m_bDragging=m_bDisabled=false; m_Line=m_Column=-1; } + enum { + WM_RESIZE_COMBO=WM_USER+200, + WM_HANDLE_TAB, + TIMER_SCROLL_UP=1, + TIMER_SCROLL_DOWN=2, + }; + + BEGIN_MSG_MAP( CSettingsTree ) + MESSAGE_HANDLER( WM_DESTROY, OnDestroy ) + MESSAGE_HANDLER( WM_LBUTTONDOWN, OnLButtonDown ) + MESSAGE_HANDLER( WM_LBUTTONDBLCLK, OnLButtonDblClick ) + MESSAGE_HANDLER( WM_LBUTTONUP, OnLButtonUp ) + MESSAGE_HANDLER( WM_MOUSEMOVE, OnMouseMove) + MESSAGE_HANDLER( WM_RBUTTONDOWN, OnRButtonDown ) + MESSAGE_HANDLER( WM_GETDLGCODE, OnGetDlgCode ) + MESSAGE_HANDLER( WM_KEYDOWN, OnKeyDown ) + MESSAGE_HANDLER( WM_CAPTURECHANGED, OnCaptureChanged ) + MESSAGE_HANDLER( WM_HSCROLL, OnScroll ) + MESSAGE_HANDLER( WM_VSCROLL, OnScroll ) + MESSAGE_HANDLER( WM_TIMER, OnTimer ) + MESSAGE_HANDLER( WM_RESIZE_COMBO, OnResizeCombo ) + MESSAGE_HANDLER( WM_HANDLE_TAB, OnHandleTab ) + COMMAND_CODE_HANDLER( CBN_SELENDOK, OnSelEndOk ) + NOTIFY_CODE_HANDLER( HDN_ENDTRACK, OnEndTrack ) + NOTIFY_CODE_HANDLER( HDN_DIVIDERDBLCLICK, OnEndTrack ) + NOTIFY_CODE_HANDLER( HDN_ITEMCLICK, OnEndTrack ) + REFLECTED_NOTIFY_CODE_HANDLER( NM_CUSTOMDRAW, OnCustomDraw ) + END_MSG_MAP() + + void SetDisabled( bool bDisabled ) { m_bDisabled=bDisabled; } + void SubclassWindow( HWND hWnd, CCustomMenuDlg7 *pOwner ); + + void UpdateItem( int index ); + + int LoadIcon( const MenuItem &item ); + unsigned int GetIconKey( const MenuItem &item ) const; + HICON LoadIcon( const MenuItem &item, bool bSmall ) const; + + void EditItem( int index ); + void DeleteItem( int index ); + void InsertItem( int index, int copy ); + void MoveItem( int from, int to ); + + protected: + LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnLButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnLButtonDblClick( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnLButtonUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnRButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { return 0; } + LRESULT OnGetDlgCode( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnKeyDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnCaptureChanged( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnScroll( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnResizeCombo( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnHandleTab( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnEndTrack( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnSelEndOk( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + + private: + CCustomMenuDlg7 *m_pOwner; + CWindow m_Combo; + HIMAGELIST m_ImageList; + int m_Line; + int m_Column; + bool m_bDisabled; + bool m_bThemed; + bool m_bDragging; + int m_ClickedItem; + + mutable std::vector m_Modules; + std::map m_IconCache; + + friend class CCustomMenuDlg7; + + void CreateCombo( int line, int column ); + void DestroyCombo( void ); + static LRESULT CALLBACK SubclassGridCombo( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ); + }; + + CItemList m_List; + CSetting *m_pSetting; + + std::vector m_Items; + + void SerializeData( void ); + + friend class CEditMenuDlg7; +}; + +class CEditMenuDlg7: public CResizeableDlg +{ +public: + CEditMenuDlg7( CCustomMenuDlg7 *pOwner, CCustomMenuDlg7::MenuItem *pItem ) { m_pOwner=pOwner; m_pItem=pItem; } + + BEGIN_MSG_MAP( CEditMenuDlg7 ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + COMMAND_ID_HANDLER( IDOK, OnOK ) + COMMAND_ID_HANDLER( IDCANCEL, OnCancel ) + COMMAND_HANDLER( IDC_COMBOCOMMAND, CBN_KILLFOCUS, OnCommandChanged ) + COMMAND_HANDLER( IDC_COMBOCOMMAND, CBN_SELENDOK, OnCommandChanged ) + COMMAND_HANDLER( IDC_BUTTONCOMMAND, BN_CLICKED, OnBrowseCommand ) + COMMAND_HANDLER( IDC_BUTTONLINK, BN_CLICKED, OnBrowseLink ) + COMMAND_HANDLER( IDC_BUTTONICON, BN_CLICKED, OnBrowseIcon ) + COMMAND_HANDLER( IDC_EDITLINK2, EN_KILLFOCUS, OnLinkChanged ) + COMMAND_HANDLER( IDC_EDITICON, EN_KILLFOCUS, OnIconChanged ) + COMMAND_HANDLER( IDC_BUTTONRESET, BN_CLICKED, OnReset ) + MESSAGE_HANDLER( WM_SIZE, OnSize ) + MESSAGE_HANDLER( WM_GETMINMAXINFO, OnGetMinMaxInfo ) + END_MSG_MAP() + + BEGIN_RESIZE_MAP + RESIZE_CONTROL(IDC_COMBOCOMMAND,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_EDITLINK2,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_BUTTONCOMMAND,MOVE_MOVE_X) + RESIZE_CONTROL(IDC_BUTTONLINK,MOVE_MOVE_X) + RESIZE_CONTROL(IDC_EDITLABEL,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_EDITTIP,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_EDITICON,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_BUTTONICON,MOVE_MOVE_X) + RESIZE_CONTROL(IDOK,MOVE_MOVE_X) + RESIZE_CONTROL(IDCANCEL,MOVE_MOVE_X) + END_RESIZE_MAP + + bool Run( void ); + + enum { SETTINGS_MASK=StdMenuItem::MENU_NOEXPAND|StdMenuItem::MENU_SINGLE_EXPAND|StdMenuItem::MENU_ITEM_DISABLED }; + +protected: + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnCommandChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnLinkChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnIconChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnBrowseCommand( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnBrowseLink( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnBrowseIcon( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnReset( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + +private: + CCustomMenuDlg7 *m_pOwner; + CCustomMenuDlg7::MenuItem *m_pItem; + CCustomMenuDlg7::MenuItem m_StoredItem; + + bool m_bResult; + HICON m_hIcon; + unsigned int m_IconKey; + + CString GetComboText( WORD wNotifyCode, WORD wID ); + void UpdateIcon( void ); + void UpdateControls( void ); + void StorePlacement( void ); +}; + +void CEditMenuDlg7::UpdateControls( void ) +{ + BOOL bEnable=(m_pItem->stdItemIndex>0); + GetDlgItem(IDC_EDITLABEL).EnableWindow(bEnable); + GetDlgItem(IDC_STATICINFOTIP).EnableWindow(bEnable); + GetDlgItem(IDC_EDITTIP).EnableWindow(bEnable); + GetDlgItem(IDC_STATICICON).EnableWindow(bEnable); + GetDlgItem(IDC_EDITICON).EnableWindow(bEnable); + GetDlgItem(IDC_BUTTONICON).EnableWindow(bEnable); + + GetDlgItem(IDC_EDITLINK2).EnableWindow(bEnable && m_pItem->stdItemIndex==g_StdCommands7Count-1); + GetDlgItem(IDC_BUTTONLINK).EnableWindow(bEnable && m_pItem->stdItemIndex==g_StdCommands7Count-1); + GetDlgItem(IDC_BUTTONRESET).EnableWindow(bEnable && m_pItem->stdItemIndexstdItemIndex].flags&CStdCommand7::ITEM_SINGLE); + GetDlgItem(IDC_CHECKSORTZA).EnableWindow(bEnable); + GetDlgItem(IDC_CHECKSORTZAREC).EnableWindow(bEnable); + GetDlgItem(IDC_CHECKSORTONCE).EnableWindow(bEnable); + GetDlgItem(IDC_CHECKOPENUP).EnableWindow(bEnable); + GetDlgItem(IDC_CHECKOPENUPREC).EnableWindow(bEnable); + GetDlgItem(IDC_CHECKNOEXT).EnableWindow(bEnable); + GetDlgItem(IDC_CHECKTRACK).EnableWindow(bEnable); + GetDlgItem(IDC_CHECKMULTICOLUMN).EnableWindow(bEnable); + GetDlgItem(IDC_STATICTEXT).EnableWindow(bEnable); +} + +LRESULT CEditMenuDlg7::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + m_hIcon=NULL; + m_IconKey=0; + m_StoredItem=*m_pItem; + if (m_pItem->stdItemIndexstdItemIndex]; + if (m_pItem->label.IsEmpty()) + m_pItem->label=command.label; + if (m_pItem->tip.IsEmpty()) + m_pItem->tip=command.tip; + if (m_pItem->icon.IsEmpty()) + m_pItem->icon=command.icon; + } + + InitResize(MOVE_HORIZONTAL|MOVE_GRIPPER); + CWindow commands=GetDlgItem(IDC_COMBOCOMMAND); + for (int i=0;istdItemIndex) + { + commands.SendMessage(CB_SETCURSEL,i); + break; + } + } + commands.SetWindowText(m_pItem->command); + + COMBOBOXINFO info={sizeof(info)}; + commands.SendMessage(CB_GETCOMBOBOXINFO,0,(LPARAM)&info); + SHAutoComplete(info.hwndItem,SHACF_FILESYSTEM); + SendDlgItemMessage(IDC_EDITLINK2,CB_GETCOMBOBOXINFO,0,(LPARAM)&info); + SHAutoComplete(info.hwndItem,SHACF_FILESYSTEM); + + SetDlgItemText(IDC_EDITLINK2,m_pItem->link); + SetDlgItemText(IDC_EDITLABEL,m_pItem->label); + SetDlgItemText(IDC_EDITTIP,m_pItem->tip); + SetDlgItemText(IDC_EDITICON,m_pItem->icon); + + CheckDlgButton(IDC_CHECKSORTZA,(m_pItem->settings&StdMenuItem::MENU_SORTZA)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKSORTZAREC,(m_pItem->settings&StdMenuItem::MENU_SORTZA_REC)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKSORTONCE,(m_pItem->settings&StdMenuItem::MENU_SORTONCE)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKOPENUP,(m_pItem->settings&StdMenuItem::MENU_OPENUP)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKOPENUPREC,(m_pItem->settings&StdMenuItem::MENU_OPENUP_REC)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKNOEXT,(m_pItem->settings&StdMenuItem::MENU_NOEXTENSIONS)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKTRACK,(m_pItem->settings&StdMenuItem::MENU_TRACK)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKMULTICOLUMN,(m_pItem->settings&StdMenuItem::MENU_MULTICOLUMN)?BST_CHECKED:BST_UNCHECKED); + + UpdateControls(); + UpdateIcon(); + SendDlgItemMessage(IDC_EDITLABEL,EM_SETCUEBANNER,TRUE,(LPARAM)(const wchar_t*)LoadStringEx(IDS_NO_TEXT)); + + CWindow tooltip=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_TRANSPARENT,TOOLTIPS_CLASS,NULL,WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP,0,0,0,0,m_hWnd,NULL,g_Instance,NULL); + tooltip.SendMessage(TTM_SETMAXTIPWIDTH,0,GetSystemMetrics(SM_CXSCREEN)/2); + + TOOLINFO tool={sizeof(tool),TTF_SUBCLASS|TTF_IDISHWND,m_hWnd,(UINT_PTR)(HWND)commands}; + CString str=LoadStringEx(IDS_COMMAND_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + tool.uId=(UINT_PTR)(HWND)commands.GetWindow(GW_CHILD); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_LINK_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_EDITLINK2); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_TEXT_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_EDITLABEL); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_TIP_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_EDITTIP); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_ICON_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_EDITICON); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_SORTZA_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKSORTZA); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_SORTZAREC_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKSORTZAREC); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_SORTONCE_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKSORTONCE); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_OPENUP_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKOPENUP); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_OPENUPREC_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKOPENUPREC); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_MULTICOLUMN_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKMULTICOLUMN); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_TRACK_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKTRACK); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_NOEXTENSIONS_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_CHECKNOEXT); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + str=LoadStringEx(IDS_RESTORE_TIP); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + tool.uId=(UINT_PTR)(HWND)GetDlgItem(IDC_BUTTONRESET); + tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + RECT rc; + CRegKey regSettings; + if (regSettings.Open(HKEY_CURRENT_USER,GetSettingsRegPath())==ERROR_SUCCESS) + { + ULONG size=sizeof(rc); + if (regSettings.QueryBinaryValue(L"CEditMenuDlg7",&rc,&size)==ERROR_SUCCESS && size==sizeof(rc)) + SetStoreRect(rc); + } + return TRUE; +} + +LRESULT CEditMenuDlg7::OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + SetFocus(); + GetDlgItemText(IDC_EDITLABEL,m_pItem->label); + m_pItem->label.TrimLeft(); + m_pItem->label.TrimRight(); + GetDlgItemText(IDC_EDITTIP,m_pItem->tip); + m_pItem->tip.TrimLeft(); + m_pItem->tip.TrimRight(); + + m_pItem->settings&=SETTINGS_MASK; + if (IsDlgButtonChecked(IDC_CHECKSORTZA)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_SORTZA; + if (IsDlgButtonChecked(IDC_CHECKSORTZAREC)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_SORTZA_REC; + if (IsDlgButtonChecked(IDC_CHECKSORTONCE)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_SORTONCE; + if (IsDlgButtonChecked(IDC_CHECKOPENUP)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_OPENUP; + if (IsDlgButtonChecked(IDC_CHECKOPENUPREC)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_OPENUP_REC; + if (IsDlgButtonChecked(IDC_CHECKTRACK)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_TRACK; + if (IsDlgButtonChecked(IDC_CHECKNOEXT)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_NOEXTENSIONS; + if (IsDlgButtonChecked(IDC_CHECKMULTICOLUMN)==BST_CHECKED) m_pItem->settings|=StdMenuItem::MENU_MULTICOLUMN; + + m_pItem=NULL; + ::EnableWindow(GetAncestor(m_pOwner->m_hWnd,GA_ROOT),TRUE); + m_bResult=true; + StorePlacement(); + DestroyWindow(); + return 0; +} + +LRESULT CEditMenuDlg7::OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + *m_pItem=m_StoredItem; + m_pItem=NULL; + ::EnableWindow(GetAncestor(m_pOwner->m_hWnd,GA_ROOT),TRUE); + m_bResult=false; + StorePlacement(); + DestroyWindow(); + return 0; +} + +LRESULT CEditMenuDlg7::OnCommandChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CString text=GetComboText(wNotifyCode,wID); + if (!m_pItem || text==m_pItem->command) return 0; + m_pItem->command=text; + m_pItem->stdItemIndex=g_StdCommands7Count-1; + for (int i=0;istdItemIndex=i; + break; + } + UpdateControls(); + UpdateIcon(); + return 0; +} + +LRESULT CEditMenuDlg7::OnLinkChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CString text=GetComboText(wNotifyCode,wID); + if (!m_pItem || text==m_pItem->link) return 0; + m_pItem->link=text; + UpdateIcon(); + return 0; +} + +LRESULT CEditMenuDlg7::OnIconChanged( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CString text; + GetDlgItemText(IDC_EDITICON,text); + text.TrimLeft(); + text.TrimRight(); + if (!m_pItem || text==m_pItem->icon) return 0; + m_pItem->icon=text; + UpdateIcon(); + return 0; +} + +LRESULT CEditMenuDlg7::OnBrowseCommand( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + wchar_t text[_MAX_PATH]; + GetDlgItemText(IDC_COMBOCOMMAND,text,_countof(text)); + if (BrowseCommandHelper(m_hWnd,text)) + { + SetDlgItemText(IDC_COMBOCOMMAND,text); + SendMessage(WM_COMMAND,MAKEWPARAM(IDC_COMBOCOMMAND,CBN_KILLFOCUS)); + } + return 0; +} + +LRESULT CEditMenuDlg7::OnBrowseLink( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + wchar_t text[_MAX_PATH]; + GetDlgItemText(IDC_EDITLINK2,text,_countof(text)); + if (BrowseLinkHelper(m_hWnd,text)) + { + SetDlgItemText(IDC_EDITLINK2,text); + SendMessage(WM_COMMAND,MAKEWPARAM(IDC_EDITLINK2,EN_KILLFOCUS)); + } + return 0; +} + +LRESULT CEditMenuDlg7::OnBrowseIcon( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + wchar_t text[_MAX_PATH]; + GetDlgItemText(IDC_EDITICON,text,_countof(text)); + if (BrowseIconHelper(m_hWnd,text)) + { + SetDlgItemText(IDC_EDITICON,text); + SendMessage(WM_COMMAND,MAKEWPARAM(IDC_EDITICON,EN_KILLFOCUS)); + } + return 0; +} + +LRESULT CEditMenuDlg7::OnReset( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (m_pItem->stdItemIndexstdItemIndex]; + m_pItem->link.Empty(); + SetDlgItemText(IDC_EDITLINK2,L""); + m_pItem->label=command.label; + SetDlgItemText(IDC_EDITLABEL,m_pItem->label); + m_pItem->tip=command.tip; + SetDlgItemText(IDC_EDITTIP,m_pItem->tip); + m_pItem->icon=command.icon; + SetDlgItemText(IDC_EDITICON,m_pItem->icon); + + m_pItem->settings=command.settings|(m_pItem->settings&SETTINGS_MASK); + CheckDlgButton(IDC_CHECKSORTZA,(m_pItem->settings&StdMenuItem::MENU_SORTZA)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKSORTZAREC,(m_pItem->settings&StdMenuItem::MENU_SORTZA_REC)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKSORTONCE,(m_pItem->settings&StdMenuItem::MENU_SORTONCE)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKOPENUP,(m_pItem->settings&StdMenuItem::MENU_OPENUP)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKOPENUPREC,(m_pItem->settings&StdMenuItem::MENU_OPENUP_REC)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKNOEXT,(m_pItem->settings&StdMenuItem::MENU_NOEXTENSIONS)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKTRACK,(m_pItem->settings&StdMenuItem::MENU_TRACK)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_CHECKMULTICOLUMN,(m_pItem->settings&StdMenuItem::MENU_MULTICOLUMN)?BST_CHECKED:BST_UNCHECKED); + UpdateIcon(); + } + return 0; +} + +LRESULT CEditMenuDlg7::OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + CResizeableDlg::OnSize(); + return 0; +} + +void CEditMenuDlg7::UpdateIcon( void ) +{ + unsigned int key=m_pOwner->m_List.GetIconKey(*m_pItem); + + if (key!=m_IconKey) + { + m_IconKey=key; + if (m_hIcon) DestroyIcon(m_hIcon); + m_hIcon=m_pOwner->m_List.LoadIcon(*m_pItem,false); + SendDlgItemMessage(IDC_ICONN,STM_SETICON,(WPARAM)m_hIcon); + } +} + +CString CEditMenuDlg7::GetComboText( WORD wNotifyCode, WORD wID ) +{ + CString text; + if (wNotifyCode==CBN_SELENDOK) + { + int idx=(int)SendDlgItemMessage(wID,CB_GETCURSEL); + text.Empty(); + if (idx>=0) + { + int len=(int)SendDlgItemMessage(wID,CB_GETLBTEXTLEN,idx); + SendDlgItemMessage(wID,CB_GETLBTEXT,idx,(LPARAM)text.GetBuffer(len+1)); + text.ReleaseBuffer(len); + } + } + else + GetDlgItemText(wID,text); + text.TrimLeft(); + text.TrimRight(); + return text; +} + +void CEditMenuDlg7::StorePlacement( void ) +{ + RECT rc; + GetStoreRect(rc); + + CRegKey regSettings; + if (regSettings.Open(HKEY_CURRENT_USER,GetSettingsRegPath())!=ERROR_SUCCESS) + regSettings.Create(HKEY_CURRENT_USER,GetSettingsRegPath()); + regSettings.SetBinaryValue(L"CEditMenuDlg7",&rc,sizeof(rc)); +} + +bool CEditMenuDlg7::Run( void ) +{ + HWND parent=GetAncestor(m_pOwner->m_hWnd,GA_ROOT); + DLGTEMPLATE *pTemplate=LoadDialogEx(IDD_CUSTOMMENU7); + Create(parent,pTemplate); + ShowWindow(SW_SHOWNORMAL); + ::EnableWindow(parent,FALSE); + MSG msg; + while (m_hWnd && GetMessage(&msg,0,0,0)) + { + if (IsDialogMessage(&msg)) continue; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return m_bResult; +} + +/////////////////////////////////////////////////////////////////////////////// + +unsigned int CCustomMenuDlg7::CItemList::GetIconKey( const MenuItem &item ) const +{ + if (!item.icon.IsEmpty()) + return CalcFNVHash(item.icon); + else if (item.stdItemIndex>=0 && item.stdItemIndex=0 && item.stdItemIndexbuf) + { + *end=0; + end--; + if (*end!=' ') + break; + } + } + + TNetworkType networkType; + MenuParseDisplayName(buf,&pidl,NULL,&networkType); + // disable for now, to match the tree item icon loading + if (pidl && GetWinVersion()>=WIN_VER_WIN8 && _wcsicmp(PathFindExtension(buf),L".lnk")==0) + { + CComPtr pItem; + if (SUCCEEDED(SHCreateItemFromIDList(pidl,IID_IShellItem,(void**)&pItem))) + { + const CItemManager::ItemInfo *pItemInfo=g_ItemManager.GetItemInfo(pItem,pidl,CItemManager::INFO_LINK|CItemManager::INFO_METRO); + if (pItemInfo) + { + bool bMetroLink; + { + CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); + bMetroLink=pItemInfo->IsMetroLink(); + } + if (bMetroLink) + { + g_ItemManager.UpdateItemInfo(pItemInfo,(bSmall?CItemManager::INFO_SMALL_ICON:CItemManager::INFO_LARGE_ICON)|CItemManager::INFO_REFRESH_NOW); + const CItemManager::IconInfo *pIconInfo=bSmall?pItemInfo->smallIcon:pItemInfo->largeIcon; + if (pIconInfo && pIconInfo->bitmap) + { + int iconSize=GetSystemMetrics(bSmall?SM_CXSMICON:SM_CXICON); + BITMAP bmpInfo; + GetObject(pIconInfo->bitmap,sizeof(bmpInfo),&bmpInfo); + + std::vector buf((iconSize+1)*iconSize,-1); + HBITMAP bmpMask=CreateBitmap(iconSize,iconSize,1,8,&buf[0]); + + HBITMAP bmpColor=pIconInfo->bitmap; + if (bmpInfo.bmWidth!=iconSize || bmpInfo.bmHeight!=iconSize) + { + HDC hSrc=CreateCompatibleDC(NULL); + HDC hDst=CreateCompatibleDC(hSrc); + + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=bi.bmiHeader.biHeight=iconSize; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + bmpColor=CreateDIBSection(hDst,&bi,DIB_RGB_COLORS,NULL,NULL,0); + + HGDIOBJ bmp01=SelectObject(hSrc,pIconInfo->bitmap); + HGDIOBJ bmp02=SelectObject(hDst,bmpColor); + StretchBlt(hDst,0,0,bi.bmiHeader.biWidth,bi.bmiHeader.biHeight,hSrc,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY); + SelectObject(hSrc,bmp01); + SelectObject(hDst,bmp02); + DeleteDC(hSrc); + DeleteDC(hDst); + } + ICONINFO info={TRUE,0,0,bmpMask,bmpColor}; + HICON hIcon=CreateIconIndirect(&info); + DeleteObject(bmpMask); + if (bmpColor!=pIconInfo->bitmap) + DeleteObject(bmpColor); + return hIcon; + } + } + } + } + } + if (networkType!=NETWORK_NONE && networkType!=NETWORK_FILE) + return ::LoadIcon(GetSystemMetrics(bSmall?SM_CXSMICON:SM_CXICON),GetDefaultNetworkIcon(networkType),m_Modules); + } + if (pidl) + return ::LoadIcon(GetSystemMetrics(bSmall?SM_CXSMICON:SM_CXICON),pidl); + } + return NULL; +} + +int CCustomMenuDlg7::CItemList::LoadIcon( const MenuItem &item ) +{ + if (item.stdItemIndex==0) + return -1; + unsigned int key=GetIconKey(item); + std::map::const_iterator it=m_IconCache.find(key); + if (it!=m_IconCache.end()) + return it->second; + + // extract icon + HICON hIcon=LoadIcon(item,true); + if (!hIcon) + { + m_IconCache[key]=0; + return 0; + } + int index=ImageList_AddIcon(m_ImageList,hIcon); + DestroyIcon(hIcon); + m_IconCache[key]=index; + return index; +} + +void CCustomMenuDlg7::CItemList::UpdateItem( int index ) +{ + const MenuItem &menuItem=m_pOwner->m_Items[index]; + const wchar_t *text=g_StdCommands7[menuItem.stdItemIndex].displayName; + if (menuItem.stdItemIndex==g_StdCommands7Count-1) + { + if (!menuItem.label.IsEmpty()) + text=menuItem.label; + else if (!menuItem.command.IsEmpty()) + text=menuItem.command; + } + ListView_SetItemText(m_hWnd,index,1,(wchar_t*)(const wchar_t*)text); + CString str; + if (menuItem.settings&StdMenuItem::MENU_ITEM_DISABLED) + str=LoadStringEx(IDS_ITEM_HIDE); + else if (g_StdCommands7[menuItem.stdItemIndex].flags&CStdCommand7::ITEM_SINGLE) + str=LoadStringEx(IDS_ITEM_SHOW2); + else if ((menuItem.settings&StdMenuItem::MENU_NOEXPAND) && !(g_StdCommands7[menuItem.stdItemIndex].flags&CStdCommand7::ITEM_FOLDER)) + str=LoadStringEx(IDS_ITEM_SHOW); + else if ((menuItem.settings&StdMenuItem::MENU_SINGLE_EXPAND) && (g_StdCommands7[menuItem.stdItemIndex].flags&CStdCommand7::ITEM_COMPUTER)) + str=LoadStringEx(IDS_ITEM_DRIVES); + else + str=LoadStringEx(IDS_ITEM_MENU); + ListView_SetItemText(m_hWnd,index,2,(wchar_t*)(const wchar_t*)str); +} + +void CCustomMenuDlg7::CItemList::SubclassWindow( HWND hWnd, CCustomMenuDlg7 *pOwner ) +{ + m_pOwner=pOwner; + CWindowImpl::SubclassWindow(hWnd); + CString str; + { + str=LoadStringEx(IDS_COLUMN_ICON); + HDC hdc=CreateCompatibleDC(NULL); + HFONT font=GetFont(); + HGDIOBJ font0=SelectObject(hdc,font); + SIZE size; + if (GetTextExtentPoint32(hdc,str,str.GetLength(),&size)) + size.cx+=20; + else + size.cx=0; + if (size.cx<50) size.cx=50; + + SelectObject(hdc,font0); + DeleteDC(hdc); + LVCOLUMN column={LVCF_WIDTH|LVCF_TEXT,0,size.cx,(LPWSTR)(LPCWSTR)str}; + ListView_InsertColumn(m_hWnd,0,&column); + } + { + // TODO: scale the size with DPI + str=LoadStringEx(IDS_COLUMN_COMMAND); + LVCOLUMN column={LVCF_WIDTH|LVCF_TEXT,0,300,(LPWSTR)(LPCWSTR)str}; + ListView_InsertColumn(m_hWnd,1,&column); + } + { + str=LoadStringEx(IDS_COLUMN_DISPLAY); + LVCOLUMN column={LVCF_WIDTH|LVCF_TEXT,0,200,(LPWSTR)(LPCWSTR)str}; + ListView_InsertColumn(m_hWnd,2,&column); + } + ListView_SetExtendedListViewStyle(m_hWnd,LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_DOUBLEBUFFER); + int iconSize=GetSystemMetrics(SM_CXSMICON); + m_ImageList=ImageList_Create(iconSize,iconSize,ILC_COLOR32|ILC_MASK|ILC_MIRROR,1,16); + ListView_SetImageList(m_hWnd,m_ImageList,LVSIL_SMALL); + SHFILEINFO info; + if (SHGetFileInfo(L"file",FILE_ATTRIBUTE_NORMAL,&info,sizeof(info),SHGFI_USEFILEATTRIBUTES|SHGFI_ICON|SHGFI_SMALLICON)) + { + AddTrackedIcon(info.hIcon); + ImageList_AddIcon(m_ImageList,info.hIcon); + DestroyIcon(info.hIcon); + } + m_bThemed=(IsAppThemed()!=0); + if (m_bThemed) + SetWindowTheme(m_hWnd,L"Explorer",NULL); + + m_Combo.Create(WC_COMBOBOX,hWnd,NULL,NULL,WS_CHILD|CBS_DROPDOWNLIST|WS_VSCROLL); + m_Combo.SetFont(GetFont()); + RECT rc; + m_Combo.GetWindowRect(&rc); + HIMAGELIST images=ImageList_Create(2,rc.bottom-rc.top,ILC_COLOR,1,1); + ListView_SetImageList(m_hWnd,images,LVSIL_STATE); + m_Combo.DestroyWindow(); +} + +LRESULT CCustomMenuDlg7::CItemList::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + DestroyCombo(); + for (std::vector::const_iterator it=m_Modules.begin();it!=m_Modules.end();++it) + FreeLibrary(*it); + m_Modules.clear(); + m_IconCache.clear(); + return 0; +} + +LRESULT CCustomMenuDlg7::CItemList::OnLButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + LVHITTESTINFO test={{(short)LOWORD(lParam),(short)HIWORD(lParam)}}; + int index=ListView_HitTest(m_hWnd,&test); + DestroyCombo(); + if (index>=0) + { + ListView_SetItemState(m_hWnd,index,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED); + SetCapture(); + m_ClickedItem=index; + return 0; + } + else + { + m_Line=m_Column=-1; + } + bHandled=FALSE; + return 0; +} + +LRESULT CCustomMenuDlg7::CItemList::OnLButtonDblClick( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + LVHITTESTINFO test={{(short)LOWORD(lParam),(short)HIWORD(lParam)}}; + int index=ListView_HitTest(m_hWnd,&test); + DestroyCombo(); + m_Line=m_Column=-1; + if (index>=0) + EditItem(index); + else if (test.flags&LVHT_NOWHERE) + { + RECT rc; + ListView_GetItemRect(m_hWnd,m_pOwner->m_Items.size()-1,&rc,LVIR_BOUNDS); + if (test.pt.y>rc.bottom) + InsertItem((int)m_pOwner->m_Items.size(),-1); + } + bHandled=FALSE; + return 0; +} + +LRESULT CCustomMenuDlg7::CItemList::OnLButtonUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (GetCapture()==m_hWnd) + { + if (m_bDragging) + { + LVINSERTMARK mark={sizeof(mark),0,-1}; + if (ListView_GetInsertMark(m_hWnd,&mark) && mark.iItem>=0) + { + // move m_ClickedItem to mark.iItem + int index=mark.iItem; + if (mark.dwFlags&LVIM_AFTER) + index++; + MoveItem(m_ClickedItem,index); + } + ReleaseCapture(); + } + else + { + ReleaseCapture(); + LVHITTESTINFO test={{(short)LOWORD(lParam),(short)HIWORD(lParam)}}; + int index=ListView_SubItemHitTest(m_hWnd,&test); + DestroyCombo(); + if (index>=0 && (test.iSubItem==1 || test.iSubItem==2)) + { + CreateCombo(index,test.iSubItem); + ListView_SetItemState(m_hWnd,index,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED); + return 0; + } + else + { + m_Line=m_Column=-1; + } + } + } + return 0; +} + +LRESULT CCustomMenuDlg7::CItemList::OnMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (GetCapture()==m_hWnd) + { + LVHITTESTINFO test={{(short)LOWORD(lParam),(short)HIWORD(lParam)}}; + int index=ListView_HitTest(m_hWnd,&test); + if (index!=m_ClickedItem) + { + m_bDragging=true; + } + if (m_bDragging) + { + if (index==-1) + { + LVINSERTMARK mark={sizeof(mark),0,-1}; + ListView_SetInsertMark(m_hWnd,&mark); + } + else + { + LVINSERTMARK mark={sizeof(mark),0,index}; + RECT rc; + ListView_GetItemRect(m_hWnd,index,&rc,LVIR_BOUNDS); + if (test.pt.y>(rc.top+rc.bottom)/2) + mark.dwFlags=LVIM_AFTER; + ListView_SetInsertMark(m_hWnd,&mark); + if (mark.dwFlags==LVIM_AFTER && index<(int)m_pOwner->m_Items.size()-1) + index++; + } + RECT rc; + ::GetWindowRect(ListView_GetHeader(m_hWnd),&rc); + ::MapWindowPoints(NULL,m_hWnd,(POINT*)&rc,2); + if (test.pt.yrc.bottom) + SetTimer(TIMER_SCROLL_DOWN,100); + else + KillTimer(TIMER_SCROLL_DOWN); + } + } + } + else + bHandled=FALSE; + return 0; +} + +LRESULT CCustomMenuDlg7::CItemList::OnGetDlgCode( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (lParam) + { + MSG *msg=(MSG*)lParam; + if (msg->message==WM_KEYDOWN && msg->wParam==VK_ESCAPE) + { + bHandled=FALSE; + return 0; + } + } + return DLGC_WANTALLKEYS; +} + +LRESULT CCustomMenuDlg7::CItemList::OnKeyDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + int index=ListView_GetNextItem(m_hWnd,-1,LVNI_FOCUSED); + if (wParam==VK_DOWN && GetKeyState(VK_CONTROL)<0) + { + if (index>=0 && index0) + MoveItem(index,index-1); + } + else if (wParam==VK_RETURN) + { + if (index>=0) + EditItem(index); + } + else if (wParam==VK_DELETE) + { + if (index>=0) + DeleteItem(index); + } + else if (wParam==VK_INSERT) + { + InsertItem(index+1,-1); + } + else if (wParam==VK_TAB) + { + SendMessage(WM_HANDLE_TAB,GetKeyState(VK_SHIFT)<0); + } + else + bHandled=FALSE; + return 0; +} + +LRESULT CCustomMenuDlg7::CItemList::OnCaptureChanged( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + LVINSERTMARK mark={sizeof(mark),0,-1}; + ListView_SetInsertMark(m_hWnd,&mark); + KillTimer(TIMER_SCROLL_UP); + KillTimer(TIMER_SCROLL_DOWN); + m_bDragging=false; + return 0; +} + +LRESULT CCustomMenuDlg7::CItemList::OnScroll( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + PostMessage(WM_RESIZE_COMBO); + bHandled=FALSE; + return 0; +} + +LRESULT CCustomMenuDlg7::CItemList::OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (wParam==TIMER_SCROLL_UP) + { + RECT rc; + if (ListView_GetItemRect(m_hWnd,0,&rc,LVIR_BOUNDS)) + ListView_Scroll(m_hWnd,0,rc.top-rc.bottom); + } + if (wParam==TIMER_SCROLL_DOWN) + { + RECT rc; + if (ListView_GetItemRect(m_hWnd,0,&rc,LVIR_BOUNDS)) + ListView_Scroll(m_hWnd,0,rc.bottom-rc.top); + } + return 0; +} + +LRESULT CCustomMenuDlg7::CItemList::OnResizeCombo( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (lParam==1) + { + SetFocus(); + DestroyCombo(); + return 0; + } + if (m_Combo.m_hWnd && m_Line>=0 && m_Column>=1) + { + RECT rc; + ListView_GetSubItemRect(m_hWnd,m_Line,m_Column,LVIR_BOUNDS,&rc); + if (m_Line>=ListView_GetTopIndex(m_hWnd)) + { + m_Combo.SetWindowPos(NULL,&rc,SWP_NOZORDER|SWP_SHOWWINDOW); + m_Combo.SetFocus(); + if (wParam) + m_Combo.SendMessage(CB_SHOWDROPDOWN,TRUE); + } + else + m_Combo.SetWindowPos(NULL,&rc,SWP_NOZORDER|SWP_HIDEWINDOW); + } + return 0; +} + +LRESULT CCustomMenuDlg7::CItemList::OnHandleTab( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + int line=-1, column=-1; + if (m_Combo.m_hWnd && m_Line>=0) + { + line=m_Line; + column=m_Column; + } + else + { + line=ListView_GetNextItem(m_hWnd,-1,LVNI_FOCUSED); + if (line<0) line=0; + column=0; + } + if (wParam) + { + // back + if (column>0) + column--; + else + { + line--; + column=2; + } + if (line<0) return 0; + } + else + { + // forward + if (column<2) + column++; + else + { + line++; + column=0; + } + if (line>=ListView_GetItemCount(m_hWnd)) + return 0; + } + if (m_Combo.m_hWnd) + { + SetFocus(); + DestroyCombo(); + } + ListView_EnsureVisible(m_hWnd,line,FALSE); + ListView_SetItemState(m_hWnd,line,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED); + if (column>0) + { + CreateCombo(line,column); + } + return 0; +} + +LRESULT CCustomMenuDlg7::CItemList::OnEndTrack( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + PostMessage(WM_RESIZE_COMBO); + bHandled=FALSE; + return 0; +} + +LRESULT CCustomMenuDlg7::CItemList::OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + NMLVCUSTOMDRAW *pDraw=(NMLVCUSTOMDRAW*)pnmh; + if (pDraw->nmcd.dwDrawStage==CDDS_PREPAINT) + return CDRF_NOTIFYITEMDRAW; + if (pDraw->nmcd.dwDrawStage==CDDS_ITEMPREPAINT) + { + const CCustomMenuDlg7::MenuItem &menuItem=m_pOwner->m_Items[pDraw->nmcd.dwItemSpec]; + if (menuItem.settings&StdMenuItem::MENU_ITEM_DISABLED) + pDraw->clrText=GetSysColor(COLOR_GRAYTEXT); + if (m_pOwner->m_pSetting->IsLocked()) + pDraw->clrTextBk=GetSysColor(COLOR_BTNFACE); + return CDRF_NOTIFYPOSTPAINT; + } + if (pDraw->nmcd.dwDrawStage==CDDS_ITEMPOSTPAINT) + { + const CCustomMenuDlg7::MenuItem &menuItem=m_pOwner->m_Items[pDraw->nmcd.dwItemSpec]; + int icon=LoadIcon(menuItem); + if (icon>=0) + { + int iconSize=GetSystemMetrics(SM_CXSMICON); + RECT rc; + ListView_GetItemRect(m_hWnd,pDraw->nmcd.dwItemSpec,&rc,LVIR_ICON); + int x=(rc.right-iconSize)/2; + int y=(rc.top+rc.bottom-iconSize)/2; + if (!m_bThemed && (ListView_GetItemState(m_hWnd,pDraw->nmcd.dwItemSpec,LVIS_SELECTED)&LVIS_SELECTED)) + ImageList_DrawEx(m_ImageList,icon,pDraw->nmcd.hdc,x,y,0,0,CLR_NONE,CLR_DEFAULT,ILD_SELECTED); + else if (menuItem.settings&StdMenuItem::MENU_ITEM_DISABLED) + ImageList_DrawEx(m_ImageList,icon,pDraw->nmcd.hdc,x,y,0,0,CLR_NONE,GetSysColor(COLOR_WINDOW),ILD_SELECTED); + else + ImageList_DrawEx(m_ImageList,icon,pDraw->nmcd.hdc,x,y,0,0,CLR_NONE,CLR_DEFAULT,ILD_NORMAL); + } + } + return CDRF_DODEFAULT; +} + +LRESULT CCustomMenuDlg7::CItemList::OnSelEndOk( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + if (m_Line<0) return 0; + CWindow combo=hWndCtl; + int sel=(int)combo.SendMessage(CB_GETCURSEL); + if (sel<0) return 0; + MenuItem &menuItem=m_pOwner->m_Items[m_Line]; + if (m_Column==1) + { + // type + const CStdCommand7 &command=g_StdCommands7[sel]; + menuItem.stdItemIndex=sel; + menuItem.command=command.command; + menuItem.link.Empty(); + menuItem.label=command.label; + menuItem.tip=command.tip; + menuItem.icon=command.icon; + menuItem.settings=command.settings|(menuItem.settings&CEditMenuDlg7::SETTINGS_MASK); + } + if (m_Column==2) + { + // state + CString str; + menuItem.settings&=~CEditMenuDlg7::SETTINGS_MASK; + if (sel==0) + menuItem.settings|=StdMenuItem::MENU_ITEM_DISABLED; + else if (sel==1 && !(g_StdCommands7[menuItem.stdItemIndex].flags&(CStdCommand7::ITEM_SINGLE|CStdCommand7::ITEM_FOLDER))) + menuItem.settings|=StdMenuItem::MENU_NOEXPAND; + else if (sel==3 && (g_StdCommands7[menuItem.stdItemIndex].flags&CStdCommand7::ITEM_COMPUTER)) + menuItem.settings|=StdMenuItem::MENU_SINGLE_EXPAND; + } + UpdateItem(m_Line); + RECT rc; + ListView_GetItemRect(m_hWnd,m_Line,&rc,LVIR_BOUNDS); + InvalidateRect(&rc); + m_pOwner->SerializeData(); + return 0; +} + +void CCustomMenuDlg7::CItemList::EditItem( int index ) +{ + if (m_pOwner->m_pSetting->IsLocked()) + return; + DestroyCombo(); + CEditMenuDlg7 dlg(m_pOwner,&m_pOwner->m_Items[index]); + if (dlg.Run()) + { + UpdateItem(index); + m_pOwner->SerializeData(); + } + else + UpdateItem(index); +} + +void CCustomMenuDlg7::CItemList::DeleteItem( int index ) +{ + if (m_pOwner->m_pSetting->IsLocked()) + return; + DestroyCombo(); + ListView_DeleteItem(m_hWnd,index); + m_pOwner->m_Items.erase(m_pOwner->m_Items.begin()+index); + m_pOwner->SerializeData(); +} + +void CCustomMenuDlg7::CItemList::InsertItem( int index, int copy ) +{ + if (m_pOwner->m_pSetting->IsLocked()) + return; + DestroyCombo(); + MenuItem menuItem; + if (copy>=0) + menuItem=m_pOwner->m_Items[copy]; + else + { + menuItem.stdItemIndex=1; + menuItem.command=g_StdCommands7[1].command; + menuItem.settings=0; + } + m_pOwner->m_Items.insert(m_pOwner->m_Items.begin()+index,menuItem); + LVITEM item={LVIF_IMAGE,index}; + item.iImage=I_IMAGENONE; + ListView_InsertItem(m_hWnd,&item); + ListView_EnsureVisible(m_hWnd,index,FALSE); + UpdateItem(index); + m_pOwner->SerializeData(); + + ListView_SetItemState(m_hWnd,index,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED); + m_Line=index; + if (copy<0) + { + m_Column=1; + CreateCombo(m_Line,1); + } +} + +void CCustomMenuDlg7::CItemList::MoveItem( int from, int to ) +{ + if (m_pOwner->m_pSetting->IsLocked()) + return; + DestroyCombo(); + SetRedraw(FALSE); + MenuItem menuItem=m_pOwner->m_Items[from]; + m_pOwner->m_Items.erase(m_pOwner->m_Items.begin()+from); + ListView_DeleteItem(m_hWnd,from); + if (fromm_Items.insert(m_pOwner->m_Items.begin()+to,menuItem); + + LVITEM item={LVIF_IMAGE,to}; + item.iImage=I_IMAGENONE; + ListView_InsertItem(m_hWnd,&item); + UpdateItem(to); + ListView_SetItemState(m_hWnd,to,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED); + ListView_EnsureVisible(m_hWnd,to,FALSE); + SetRedraw(TRUE); + Invalidate(); + m_pOwner->SerializeData(); +} + +LRESULT CALLBACK CCustomMenuDlg7::CItemList::SubclassGridCombo( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) +{ + if (uMsg==WM_KEYDOWN) + { + if (wParam==VK_ESCAPE || (wParam==VK_RETURN && !::SendMessage(hWnd,CB_GETDROPPEDSTATE,0,0))) + { + ::PostMessage(::GetParent(hWnd),WM_RESIZE_COMBO,0,1); + } + if (wParam==VK_TAB) + { + ::PostMessage(::GetParent(hWnd),WM_HANDLE_TAB,GetKeyState(VK_SHIFT)<0,0); + } + } + if (uMsg==WM_GETDLGCODE) + return DLGC_WANTALLKEYS; + return DefSubclassProc(hWnd,uMsg,wParam,lParam); +} + +void CCustomMenuDlg7::CItemList::CreateCombo( int line, int column ) +{ + if (m_pOwner->m_pSetting->IsLocked()) + return; + m_Combo.Create(WC_COMBOBOX,m_hWnd,NULL,NULL,WS_CHILD|CBS_DROPDOWNLIST|WS_VSCROLL); + m_Combo.SetFont(GetFont()); + m_Combo.SendMessage(CB_SETEXTENDEDUI,TRUE); + SetWindowSubclass(m_Combo,SubclassGridCombo,'CLSH',0); + + m_Line=line; + m_Column=column; + const CCustomMenuDlg7::MenuItem &menuItem=m_pOwner->m_Items[line]; + if (column==1) + { + for (int i=0;iIsLocked()); + const wchar_t *pText=L""; + if (m_pSetting->value.vt==VT_BSTR) + pText=m_pSetting->value.bstrVal; + + CSettingsParser parser; + parser.LoadText(pText,Strlen(pText)); + parser.ParseText(); + + m_Items.clear(); + for (int i=1;;i++) + { + wchar_t item[100]; + Sprintf(item,_countof(item),L"Item%d.Command",i); + const wchar_t *command=parser.FindSetting(item); + Sprintf(item,_countof(item),L"Item%d.Link",i); + const wchar_t *link=parser.FindSetting(item); + if (!command && !link) + break; + + MenuItem menuItem; + menuItem.stdItemIndex=g_StdCommands7Count-1; + menuItem.settings=0; + if (command) + { + menuItem.command=command; + for (int i=0;i::const_iterator it=m_Items.begin();it!=m_Items.end();++it,idx++) + { + LVITEM item={LVIF_IMAGE,idx}; + item.iImage=I_IMAGENONE; + ListView_InsertItem(m_List,&item); + m_List.UpdateItem(idx); + } + + TOOLINFO tool={sizeof(tool),0,m_hWnd,'CLSH'}; + tool.uId=(UINT_PTR)m_List.m_hWnd; + CString str; + if (m_pSetting->IsLocked()) + str=LoadStringEx(IDS_MENU_LOCKED); + tool.lpszText=(LPWSTR)(LPCWSTR)str; + ::SendMessage(ListView_GetToolTips(m_List),TTM_UPDATETIPTEXT,0,(LPARAM)&tool); + + ListView_SetBkColor(m_List,GetSysColor(m_pSetting->IsLocked()?COLOR_BTNFACE:COLOR_WINDOW)); +} + +LRESULT CCustomMenuDlg7::OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + CResizeableDlg::OnSize(); + return 0; +} + +LRESULT CCustomMenuDlg7::OnContextMenu( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + CWindow list=(HWND)wParam; + if (list.m_hWnd!=m_List.m_hWnd) + return 0; + if (m_pSetting->IsLocked()) + return 0; + if (GetCapture()==list) + { + ReleaseCapture(); + return 0; + } + POINT pt; + int index; + if ((DWORD)lParam==0xFFFFFFFF) + { + // keyboard + index=ListView_GetNextItem(list,-1,LVNI_FOCUSED); + if (index>=0) + { + RECT rc; + ListView_GetItemRect(list,m_List.m_Line,&rc,LVIR_BOUNDS); + pt.x=(rc.left+rc.right)/2; + pt.y=(rc.top+rc.bottom)/2; + } + else + pt.x=pt.y=0; + m_List.ClientToScreen(&pt); + } + else + { + DWORD pos=GetMessagePos(); + pt.x=(short)LOWORD(pos); + pt.y=(short)HIWORD(pos); + LVHITTESTINFO test={pt}; + m_List.ScreenToClient(&test.pt); + index=ListView_HitTest(list,&test); + } + + enum { + CMD_EDIT=1, + CMD_DELETE, + CMD_DUPLICATE, + CMD_INSERT, + CMD_RESETALL, + CMD_MOVE_UP, + CMD_MOVE_DOWN, + }; + + m_List.DestroyCombo(); + + HMENU menu=CreatePopupMenu(); + wchar_t text[256]; + if (index>=0) + { + ListView_SetItemState(list,index,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED); + Sprintf(text,_countof(text),L"%s\tEnter",LoadStringEx(IDS_MENU_EDIT)); + AppendMenu(menu,MF_STRING,CMD_EDIT,text); + SetMenuDefaultItem(menu,CMD_EDIT,FALSE); + Sprintf(text,_countof(text),L"%s\tDel",LoadStringEx(IDS_MENU_DELETE)); + AppendMenu(menu,MF_STRING,CMD_DELETE,text); + AppendMenu(menu,MF_STRING,CMD_DUPLICATE,LoadStringEx(IDS_MENU_DUPLICATE)); + Sprintf(text,_countof(text),L"%s\tCtrl+Up",LoadStringEx(IDS_MENU_MOVE_UP)); + AppendMenu(menu,MF_STRING,CMD_MOVE_UP,text); + Sprintf(text,_countof(text),L"%s\tCtrl+Down",LoadStringEx(IDS_MENU_MOVE_DOWN)); + AppendMenu(menu,MF_STRING,CMD_MOVE_DOWN,text); + if (index==0) + EnableMenuItem(menu,CMD_MOVE_UP,MF_BYCOMMAND|MF_GRAYED); + if (index==(int)m_Items.size()-1) + EnableMenuItem(menu,CMD_MOVE_DOWN,MF_BYCOMMAND|MF_GRAYED); + AppendMenu(menu,MF_SEPARATOR,0,0); + } + Sprintf(text,_countof(text),L"%s\tInsert",LoadStringEx(IDS_MENU_INSERT)); + AppendMenu(menu,MF_STRING,CMD_INSERT,text); + if (index<0) + SetMenuDefaultItem(menu,CMD_INSERT,FALSE); + AppendMenu(menu,MF_STRING,CMD_RESETALL,LoadStringEx(IDS_RESET_MENU)); + + int res=TrackPopupMenu(menu,TPM_RIGHTBUTTON|TPM_RETURNCMD,pt.x,pt.y,0,m_hWnd,NULL); + DestroyMenu(menu); + if (res==CMD_EDIT) + m_List.EditItem(index); + if (res==CMD_DELETE) + m_List.DeleteItem(index); + if (res==CMD_INSERT) + m_List.InsertItem(index<0?(int)m_Items.size():(index+1),-1); + if (res==CMD_DUPLICATE) + m_List.InsertItem(index<0?(int)m_Items.size():(index+1),index); + if (res==CMD_MOVE_UP) + m_List.MoveItem(index,index-1); + if (res==CMD_MOVE_DOWN) + m_List.MoveItem(index,index+2); + if (res==CMD_RESETALL) + { + if (::MessageBox(m_hWnd,LoadStringEx(IDS_RESET_MENU_WARN),LoadStringEx(IDS_RESET_MENU),MB_YESNO|MB_ICONWARNING)==IDYES) + { + { + CSettingsLockWrite lock; + m_pSetting->value=m_pSetting->defValue; + m_pSetting->flags|=CSetting::FLAG_DEFAULT; + SetSettingsDirty(); + } + SetGroup(m_pSetting-1,true); + } + } + return 0; +} + +static void AppendString( std::vector &stringBuilder, const wchar_t *format, ... ) +{ + va_list args; + va_start(args,format); + wchar_t buf[1024]; + int len=Vsprintf(buf,_countof(buf),format,args); + va_end(args); + int pos=(int)stringBuilder.size(); + stringBuilder.resize(pos+len); + memcpy(&stringBuilder[pos],buf,len*2); +} + +void CCustomMenuDlg7::SerializeData( void ) +{ + std::vector stringBuilder; + for (int i=0;i<(int)m_Items.size();i++) + { + const MenuItem &menuItem=m_Items[i]; + const CStdCommand7 &command=g_StdCommands7[menuItem.stdItemIndex]; + if (menuItem.stdItemIndex\n",i+1,menuItem.command); + } + if (!menuItem.label.IsEmpty()) + AppendString(stringBuilder,L"Item%d.Label=%s\n",i+1,menuItem.label); + if (!menuItem.tip.IsEmpty()) + AppendString(stringBuilder,L"Item%d.Tip=%s\n",i+1,menuItem.tip); + if (!menuItem.icon.IsEmpty()) + AppendString(stringBuilder,L"Item%d.Icon=%s\n",i+1,menuItem.icon); + if (menuItem.settings) + { + AppendString(stringBuilder,L"Item%d.Settings=",i+1); + if (menuItem.settings&StdMenuItem::MENU_OPENUP) AppendString(stringBuilder,L"OPEN_UP|"); + if (menuItem.settings&StdMenuItem::MENU_OPENUP_REC) AppendString(stringBuilder,L"OPEN_UP_CHILDREN|"); + if (menuItem.settings&StdMenuItem::MENU_SORTZA) AppendString(stringBuilder,L"SORT_ZA|"); + if (menuItem.settings&StdMenuItem::MENU_SORTZA_REC) AppendString(stringBuilder,L"SORT_ZA_CHILDREN|"); + if (menuItem.settings&StdMenuItem::MENU_SORTONCE) AppendString(stringBuilder,L"SORT_ONCE|"); + if (menuItem.settings&StdMenuItem::MENU_TRACK) AppendString(stringBuilder,L"TRACK_RECENT|"); + if (menuItem.settings&StdMenuItem::MENU_NOEXPAND) AppendString(stringBuilder,L"NOEXPAND|"); + else if (menuItem.settings&StdMenuItem::MENU_SINGLE_EXPAND) AppendString(stringBuilder,L"SINGLE_EXPAND|"); + if (menuItem.settings&StdMenuItem::MENU_MULTICOLUMN) AppendString(stringBuilder,L"MULTICOLUMN|"); + if (menuItem.settings&StdMenuItem::MENU_NOEXTENSIONS) AppendString(stringBuilder,L"NOEXTENSIONS|"); + if (menuItem.settings&StdMenuItem::MENU_ITEM_DISABLED) AppendString(stringBuilder,L"ITEM_DISABLED|"); + stringBuilder[stringBuilder.size()-1]='\n'; + } + } + stringBuilder.push_back(0); + CSettingsLockWrite lock; + m_pSetting->value=CComVariant(&stringBuilder[0]); + m_pSetting->flags&=~CSetting::FLAG_DEFAULT; + SetSettingsDirty(); +} + +class CCustomMenuPanel7: public ISettingsPanel +{ +public: + virtual HWND Create( HWND parent ); + virtual HWND Activate( CSetting *pGroup, const RECT &rect, bool bReset ); + virtual bool Validate( HWND parent ) { return true; } + +private: + static CCustomMenuDlg7 s_Dialog; +}; + +CCustomMenuDlg7 CCustomMenuPanel7::s_Dialog; + +HWND CCustomMenuPanel7::Create( HWND parent ) +{ + if (!s_Dialog.m_hWnd) + s_Dialog.Create(parent,LoadDialogEx(IDD_CUSTOMLIST)); + return s_Dialog.m_hWnd; +} + +HWND CCustomMenuPanel7::Activate( CSetting *pGroup, const RECT &rect, bool bReset ) +{ + s_Dialog.SetGroup(pGroup,bReset); + s_Dialog.SetWindowPos(HWND_TOP,&rect,SWP_SHOWWINDOW); + return s_Dialog.m_hWnd; +} + +static CCustomMenuPanel7 g_CustomMenuPanel7; + +/////////////////////////////////////////////////////////////////////////////// + +class CMenuStyleDlg: public CResizeableDlg +{ +public: + BEGIN_MSG_MAP( CMenuStyleDlg ) + MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) + MESSAGE_HANDLER( WM_DESTROY, OnDestroy ) + MESSAGE_HANDLER( WM_SIZE, OnSize ) + + // menu style + MESSAGE_HANDLER( WM_SETCURSOR, OnSetCursor ) + COMMAND_HANDLER( IDC_STATIC_CLASSIC, STN_CLICKED, OnClick ) + COMMAND_HANDLER( IDC_STATIC_TWO_COLUMNS, STN_CLICKED, OnClick ) + COMMAND_HANDLER( IDC_STATIC_WIN7, STN_CLICKED, OnClick ) + COMMAND_HANDLER( IDC_RADIO_CLASSIC, BN_CLICKED, OnClick ) + COMMAND_HANDLER( IDC_RADIO_TWO_COLUMNS, BN_CLICKED, OnClick ) + COMMAND_HANDLER( IDC_RADIO_WIN7, BN_CLICKED, OnClick ) + + // button style + COMMAND_HANDLER( IDC_CHECKENABLED, BN_CLICKED, OnEnabled ) + COMMAND_HANDLER( IDC_STATICAERO, STN_CLICKED, OnButtonStyle ) + COMMAND_HANDLER( IDC_STATICCLASSIC, STN_CLICKED, OnButtonStyle ) + COMMAND_HANDLER( IDC_STATICCUSTOM, STN_CLICKED, OnButtonStyle ) + COMMAND_HANDLER( IDC_RADIOAERO, BN_CLICKED, OnButtonStyle ) + COMMAND_HANDLER( IDC_RADIOCLASSIC, BN_CLICKED, OnButtonStyle ) + COMMAND_HANDLER( IDC_RADIOCUSTOM, BN_CLICKED, OnButtonStyle ) + COMMAND_HANDLER( IDC_BUTTONPICK, BN_CLICKED, OnPick ) + NOTIFY_HANDLER( IDC_LINKADVANCED, NM_CLICK, OnAdvanced ) + NOTIFY_HANDLER( IDC_LINKADVANCED, NM_RETURN, OnAdvanced ) + + NOTIFY_HANDLER( IDC_SKIN_CLASSIC, NM_CLICK, OnSkin ) + NOTIFY_HANDLER( IDC_SKIN_CLASSIC, NM_RETURN, OnSkin ) + NOTIFY_HANDLER( IDC_SKIN_CLASSIC2, NM_CLICK, OnSkin ) + NOTIFY_HANDLER( IDC_SKIN_CLASSIC2, NM_RETURN, OnSkin ) + NOTIFY_HANDLER( IDC_SKIN_WIN7, NM_CLICK, OnSkin ) + NOTIFY_HANDLER( IDC_SKIN_WIN7, NM_RETURN, OnSkin ) + END_MSG_MAP() + + BEGIN_RESIZE_MAP + RESIZE_CONTROL(IDC_STATICTITLE,MOVE_SIZE_X) + RESIZE_CONTROL(IDC_STATICEDGE,MOVE_SIZE_X) + END_RESIZE_MAP + + static void UpdateDefaults( void ); + + void Update( bool bForce ); + +protected: + // Handler prototypes: + // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); + // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); + LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnSetCursor( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); + LRESULT OnClick( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnEnabled( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnButtonStyle( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnPick( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); + LRESULT OnAdvanced( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + LRESULT OnSkin( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ); + +protected: + CWindow m_ImageClassic1, m_ImageClassic2, m_ImageWin7; + CWindow m_Tooltip; + CWindow m_ButtonAero, m_ButtonClassic, m_ButtonCustom; + bool m_bLargeBitmaps; + HICON m_hIcon; + CString m_IconPath; + + void UpdateIcon( bool bForce ); +}; + +static void UpdateButtons( bool bForce ); + +LRESULT CMenuStyleDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + InitResize(); + EnableThemeDialogTexture(m_hWnd,ETDT_ENABLETAB); + m_ImageClassic1=GetDlgItem(IDC_STATIC_CLASSIC); + m_ImageClassic2=GetDlgItem(IDC_STATIC_TWO_COLUMNS); + m_ImageWin7=GetDlgItem(IDC_STATIC_WIN7); + HDC hdc=::GetDC(NULL); + int dpi=GetDeviceCaps(hdc,LOGPIXELSY); + ::ReleaseDC(NULL,hdc); + m_bLargeBitmaps=dpi>=144; + if (m_bLargeBitmaps) + { + HBITMAP bmp=(HBITMAP)LoadImage(g_Instance,MAKEINTRESOURCE(IDB_STYLE_CLASSIC1150),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION); + m_ImageClassic1.SendMessage(STM_SETIMAGE,IMAGE_BITMAP,(LPARAM)bmp); + bmp=(HBITMAP)LoadImage(g_Instance,MAKEINTRESOURCE(IDB_STYLE_CLASSIC2150),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION); + m_ImageClassic2.SendMessage(STM_SETIMAGE,IMAGE_BITMAP,(LPARAM)bmp); + bmp=(HBITMAP)LoadImage(g_Instance,MAKEINTRESOURCE(IDB_STYLE_WIN7150),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION); + m_ImageWin7.SendMessage(STM_SETIMAGE,IMAGE_BITMAP,(LPARAM)bmp); + } + + bool bLocked=IsSettingLocked(L"MenuStyle"); + CString tip1=LoadStringEx(bLocked?IDS_SETTING_LOCKED:IDS_CLASSIC_STYLE_TIP); + CString tip2=LoadStringEx(bLocked?IDS_SETTING_LOCKED:IDS_TWO_COLUMN_STYLE_TIP); + CString tip3=LoadStringEx(bLocked?IDS_SETTING_LOCKED:IDS_WIN7_STYLE_TIP); + bool bRTL=IsLanguageRTL(); + m_Tooltip=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_TRANSPARENT|(bRTL?WS_EX_LAYOUTRTL:0),TOOLTIPS_CLASS,NULL,WS_POPUP|TTS_NOPREFIX,0,0,0,0,m_hWnd,NULL,g_Instance,NULL); + m_Tooltip.SendMessage(TTM_SETMAXTIPWIDTH,0,500); + TOOLINFO tool={sizeof(tool),TTF_IDISHWND|TTF_SUBCLASS|(bRTL?TTF_RTLREADING:0)}; + tool.uId=(UINT_PTR)m_ImageClassic1.m_hWnd; + tool.lpszText=(wchar_t*)(const wchar_t*)tip1; + m_Tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + tool.uId=(UINT_PTR)m_ImageClassic2.m_hWnd; + tool.lpszText=(wchar_t*)(const wchar_t*)tip2; + m_Tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + tool.uId=(UINT_PTR)m_ImageWin7.m_hWnd; + tool.lpszText=(wchar_t*)(const wchar_t*)tip3; + m_Tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool); + + m_hIcon=NULL; + m_IconPath="?"; + SetDlgItemText(IDC_CHECKENABLED,LoadStringEx(GetWinVersion()==WIN_VER_WIN8?IDS_ENABLE_BUTTON:IDS_ENABLE_BUTTON2)); + m_ButtonAero=GetDlgItem(IDC_STATICAERO); + m_ButtonClassic=GetDlgItem(IDC_STATICCLASSIC); + m_ButtonCustom=GetDlgItem(IDC_STATICCUSTOM); + return TRUE; +} + +LRESULT CMenuStyleDlg::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if (m_hIcon) DestroyIcon(m_hIcon); + m_hIcon=NULL; + if (m_bLargeBitmaps) + { + HBITMAP bmp=(HBITMAP)m_ImageClassic1.SendMessage(STM_GETIMAGE,IMAGE_BITMAP); + if (bmp) DeleteObject(bmp); + bmp=(HBITMAP)m_ImageClassic2.SendMessage(STM_GETIMAGE,IMAGE_BITMAP); + if (bmp) DeleteObject(bmp); + bmp=(HBITMAP)m_ImageWin7.SendMessage(STM_GETIMAGE,IMAGE_BITMAP); + if (bmp) DeleteObject(bmp); + } + UpdateButtons(false); + bHandled=FALSE; + return 0; +} + +LRESULT CMenuStyleDlg::OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + CResizeableDlg::OnSize(); + return 0; +} + +LRESULT CMenuStyleDlg::OnSetCursor( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) +{ + if ((HWND)wParam==m_ImageClassic1.m_hWnd || (HWND)wParam==m_ImageClassic2.m_hWnd || (HWND)wParam==m_ImageWin7.m_hWnd || (HWND)wParam==m_ButtonAero.m_hWnd || (HWND)wParam==m_ButtonClassic.m_hWnd || (HWND)wParam==m_ButtonCustom.m_hWnd) + { + SetCursor(LoadCursor(NULL,IDC_HAND)); + return TRUE; + } + bHandled=FALSE; + return 0; +} + +LRESULT CMenuStyleDlg::OnClick( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + static bool bProcessing; + if (bProcessing) return 0; + + if (IsSettingLocked(L"MenuStyle")) + return 0; + bProcessing=true; + bool bReset=false; + { + TMenuStyle style, style0=(TMenuStyle)GetSettingInt(L"MenuStyle"); + int styleFlag; + CSettingsLockWrite lock; + + CSetting *pSetting=FindSetting(L"MenuStyle"); + if (wID==IDC_STATIC_WIN7 || wID==IDC_RADIO_WIN7) + { + style=MENU_WIN7; + styleFlag=CSetting::FLAG_MENU_WIN7; + SendMessage(WM_NEXTDLGCTL,(LPARAM)GetDlgItem(IDC_RADIO_WIN7).m_hWnd,TRUE); + } + else if (wID==IDC_STATIC_TWO_COLUMNS || wID==IDC_RADIO_TWO_COLUMNS) + { + style=MENU_CLASSIC2; + styleFlag=CSetting::FLAG_MENU_CLASSIC2; + SendMessage(WM_NEXTDLGCTL,(LPARAM)GetDlgItem(IDC_RADIO_TWO_COLUMNS).m_hWnd,TRUE); + } + else + { + style=MENU_CLASSIC1; + styleFlag=CSetting::FLAG_MENU_CLASSIC1; + SendMessage(WM_NEXTDLGCTL,(LPARAM)GetDlgItem(IDC_RADIO_CLASSIC).m_hWnd,TRUE); + } + pSetting->value=CComVariant(style); + CheckDlgButton(IDC_RADIO_CLASSIC,pSetting->value.intVal==MENU_CLASSIC1?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_RADIO_TWO_COLUMNS,pSetting->value.intVal==MENU_CLASSIC2?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_RADIO_WIN7,pSetting->value.intVal==MENU_WIN7?BST_CHECKED:BST_UNCHECKED); + pSetting->flags&=~CSetting::FLAG_DEFAULT; + SetSettingsDirty(); + + SetSettingsStyle(styleFlag,CSetting::FLAG_MENU_MASK); + UpdateDefaults(); + CCustomMenuDlg::UpdateWarnings(style); + } + bProcessing=false; + return 0; +} + +LRESULT CMenuStyleDlg::OnEnabled( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + BOOL bEnabled=(IsDlgButtonChecked(IDC_CHECKENABLED)==BST_CHECKED); + { + CSettingsLockWrite lock; + CSetting *pSetting=FindSetting(L"EnableStartButton"); + pSetting->value=CComVariant(bEnabled); + pSetting->flags&=~CSetting::FLAG_DEFAULT; + SetSettingsDirty(); + } + Update(false); + return 0; +} + +LRESULT CMenuStyleDlg::OnButtonStyle( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + int style=START_BUTTON_AERO; + if (IsDlgButtonChecked(IDC_RADIOCLASSIC)==BST_CHECKED) + style=START_BUTTON_CLASSIC; + else if (IsDlgButtonChecked(IDC_RADIOCUSTOM)==BST_CHECKED) + style=START_BUTTON_CUSTOM; + + if (wID==IDC_STATICAERO || wID==IDC_RADIOAERO) + { + style=START_BUTTON_AERO; + SendMessage(WM_NEXTDLGCTL,(LPARAM)GetDlgItem(IDC_RADIOAERO).m_hWnd,TRUE); + } + else if (wID==IDC_STATICCLASSIC || wID==IDC_RADIOCLASSIC) + { + style=START_BUTTON_CLASSIC; + SendMessage(WM_NEXTDLGCTL,(LPARAM)GetDlgItem(IDC_RADIOCLASSIC).m_hWnd,TRUE); + } + else + { + style=START_BUTTON_CUSTOM; + SendMessage(WM_NEXTDLGCTL,(LPARAM)GetDlgItem(IDC_RADIOCUSTOM).m_hWnd,TRUE); + } + + CheckDlgButton(IDC_RADIOAERO,style==START_BUTTON_AERO?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_RADIOCLASSIC,style==START_BUTTON_CLASSIC?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_RADIOCUSTOM,style==START_BUTTON_CUSTOM?BST_CHECKED:BST_UNCHECKED); + + { + CSettingsLockWrite lock; + CSetting *pSetting=FindSetting(L"StartButtonType"); + pSetting->value=CComVariant(style); + pSetting->flags&=~CSetting::FLAG_DEFAULT; + SetSettingsDirty(); + } + Update(false); + return 0; +} + +LRESULT CMenuStyleDlg::OnPick( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) +{ + CString str=GetSettingString(L"StartButtonPath"); + wchar_t path[_MAX_PATH]; + if (_wcsicmp(PathFindExtension(str),L".bmp")==0 || _wcsicmp(PathFindExtension(str),L".png")==0) + { + Strcpy(path,_countof(path),str); + DoEnvironmentSubst(path,_countof(path)); + } + else + path[0]=0; + if (BrowseForBitmap(m_hWnd,path,false)) + { + { + CSettingsLockWrite lock; + CSetting *pSetting=FindSetting(L"StartButtonPath"); + pSetting->value=CComVariant(path); + pSetting->flags&=~CSetting::FLAG_DEFAULT; + SetSettingsDirty(); + } + Update(true); + } + return 0; +} + +LRESULT CMenuStyleDlg::OnAdvanced( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + SelectSettingsTab(IDS_START_BUTTON,true,NULL); + return 0; +} + +LRESULT CMenuStyleDlg::OnSkin( int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) +{ + SelectSettingsTab(IDS_SKIN_SETTINGS,false,NULL); + return 0; +} + +static HICON CreateIconFromButton( HBITMAP bitmap, int frames ) +{ + BITMAP bmpInfo; + GetObject(bitmap,sizeof(bmpInfo),&bmpInfo); + int width=bmpInfo.bmWidth; + int height=bmpInfo.bmHeight/frames; + if (height<1) height=1; + std::vector buf((width+1)*height,-1); + HBITMAP bmpMask=CreateBitmap(width,height,1,8,&buf[0]); + + HDC hSrc=CreateCompatibleDC(NULL); + HDC hDst=CreateCompatibleDC(hSrc); + + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=width; + bi.bmiHeader.biHeight=height; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + HBITMAP bmpColor=CreateDIBSection(hDst,&bi,DIB_RGB_COLORS,NULL,NULL,0); + + HGDIOBJ bmp01=SelectObject(hSrc,bitmap); + HGDIOBJ bmp02=SelectObject(hDst,bmpColor); + BitBlt(hDst,0,0,width,height,hSrc,0,0,SRCCOPY); + SelectObject(hSrc,bmp01); + SelectObject(hDst,bmp02); + DeleteDC(hSrc); + DeleteDC(hDst); + + ICONINFO info={TRUE,0,0,bmpMask,bmpColor}; + HICON hIcon=CreateIconIndirect(&info); + DeleteObject(bmpMask); + DeleteObject(bmpColor); + return hIcon; +} + +void CMenuStyleDlg::UpdateIcon( bool bForce ) +{ + wchar_t path[_MAX_PATH]; + Strcpy(path,_countof(path),GetSettingString(L"StartButtonPath")); + DoEnvironmentSubst(path,_countof(path)); + if (m_IconPath==path && !bForce) + return; + m_IconPath=path; + const int MAX_ICON_SIZE=40; + SIZE size={-MAX_ICON_SIZE,0}; + std::vector buttonAnim; + int frames=3; + HBITMAP bitmap=LoadImageFile(path,&size,true,false,&buttonAnim); + if (bitmap) + { + if (!buttonAnim.empty()) + { + frames=buttonAnim[2]&255; + if (frames<1) frames=1; + } + } + else + { + frames=1; + HDC hdc=CreateCompatibleDC(NULL); + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=MAX_ICON_SIZE; + bi.bmiHeader.biHeight=MAX_ICON_SIZE; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + bitmap=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,NULL,NULL,0); + SelectObject(hdc,GetStockObject(BLACK_PEN)); + SelectObject(hdc,GetStockObject(WHITE_BRUSH)); + HGDIOBJ bmp02=SelectObject(hdc,bitmap); + Rectangle(hdc,0,0,MAX_ICON_SIZE,MAX_ICON_SIZE); + SelectObject(hdc,bmp02); + DeleteDC(hdc); + } + HICON hIcon=CreateIconFromButton(bitmap,frames); + DeleteObject(bitmap); + SendDlgItemMessage(IDC_STATICCUSTOM,STM_SETICON,(WPARAM)hIcon,0); + if (m_hIcon) DestroyIcon(m_hIcon); + m_hIcon=hIcon; +} + +void CMenuStyleDlg::Update( bool bForce ) +{ + int type=GetSettingInt(L"MenuStyle"); + CheckDlgButton(IDC_RADIO_CLASSIC,type==MENU_CLASSIC1?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_RADIO_TWO_COLUMNS,type==MENU_CLASSIC2?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_RADIO_WIN7,type==MENU_WIN7?BST_CHECKED:BST_UNCHECKED); + GetDlgItem(IDC_SKIN_CLASSIC).ShowWindow(type==MENU_CLASSIC1?SW_SHOW:SW_HIDE); + GetDlgItem(IDC_SKIN_CLASSIC2).ShowWindow(type==MENU_CLASSIC2?SW_SHOW:SW_HIDE); + GetDlgItem(IDC_SKIN_WIN7).ShowWindow(type==MENU_WIN7?SW_SHOW:SW_HIDE); + + BOOL bEnabled=!IsSettingLocked(L"MenuStyle"); + GetDlgItem(IDC_RADIO_CLASSIC).EnableWindow(bEnabled); + GetDlgItem(IDC_RADIO_TWO_COLUMNS).EnableWindow(bEnabled); + GetDlgItem(IDC_RADIO_WIN7).EnableWindow(bEnabled); + + bEnabled=GetSettingBool(L"EnableStartButton"); + TStartButtonType buttonType=GetStartButtonType(); + CheckDlgButton(IDC_CHECKENABLED,bEnabled?BST_CHECKED:BST_UNCHECKED); + GetDlgItem(IDC_CHECKENABLED).EnableWindow(!IsSettingLocked(L"EnableStartButton")); + + CheckDlgButton(IDC_RADIOAERO,buttonType==START_BUTTON_AERO?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_RADIOCLASSIC,buttonType==START_BUTTON_CLASSIC?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(IDC_RADIOCUSTOM,buttonType==START_BUTTON_CUSTOM?BST_CHECKED:BST_UNCHECKED); + BOOL bEnabled2=bEnabled && !IsSettingLocked(L"StartButtonType"); + GetDlgItem(IDC_RADIOAERO).EnableWindow(bEnabled2); + GetDlgItem(IDC_RADIOCLASSIC).EnableWindow(bEnabled2); + GetDlgItem(IDC_RADIOCUSTOM).EnableWindow(bEnabled2); + m_ButtonAero.EnableWindow(bEnabled2); + m_ButtonClassic.EnableWindow(bEnabled2); + m_ButtonCustom.EnableWindow(bEnabled2); + + bEnabled2=bEnabled && buttonType==START_BUTTON_CUSTOM && !IsSettingLocked(L"StartButtonPath"); + GetDlgItem(IDC_BUTTONPICK).EnableWindow(bEnabled2); + UpdateIcon(bForce); + UpdateButtons(bForce); +} + +void CMenuStyleDlg::UpdateDefaults( void ) +{ + const CSetting *pSetting=FindSetting(L"MenuStyle"); + Assert(pSetting->value.vt==VT_I4); + TMenuStyle menuStyle=(TMenuStyle)pSetting->value.intVal; + UpdateSetting(L"SearchBox",CComVariant(menuStyle!=MENU_CLASSIC1?SEARCHBOX_NORMAL:SEARCHBOX_TAB),false); + UpdateSetting(L"RecentPrograms",CComVariant(menuStyle!=MENU_CLASSIC1?RECENT_PROGRAMS_FREQUENT:RECENT_PROGRAMS_RECENT),false); + UpdateSetting(L"MaxRecentPrograms",CComVariant(menuStyle!=MENU_CLASSIC1?10:5),false); + UpdateSetting(L"RecentProgsTop",CComVariant(menuStyle!=MENU_CLASSIC1?0:1),false); + UpdateSetting(L"RecentProgKeys",CComVariant(menuStyle!=MENU_CLASSIC1?RECENT_KEYS_HIDDEN_DIGITS:RECENT_KEYS_DIGITS),false); + UpdateSetting(L"PinnedPrograms",CComVariant(menuStyle!=MENU_WIN7?PINNED_PROGRAMS_FAST:PINNED_PROGRAMS_PINNED),false); +} + +class CStyleSettingsPanel: public ISettingsPanel +{ +public: + virtual HWND Create( HWND parent ); + virtual HWND Activate( CSetting *pGroup, const RECT &rect, bool bReset ); + virtual bool Validate( HWND parent ) { return true; } + +private: + static CMenuStyleDlg s_Dialog; +}; + +CMenuStyleDlg CStyleSettingsPanel::s_Dialog; + +HWND CStyleSettingsPanel::Create( HWND parent ) +{ + if (!s_Dialog.m_hWnd) + s_Dialog.Create(parent,LoadDialogEx(IDD_STYLESETTINGS)); + return s_Dialog.m_hWnd; +} + +HWND CStyleSettingsPanel::Activate( CSetting *pGroup, const RECT &rect, bool bReset ) +{ + s_Dialog.SetWindowPos(HWND_TOP,&rect,SWP_SHOWWINDOW); + s_Dialog.Update(false); + return s_Dialog.m_hWnd; +} + +static CStyleSettingsPanel g_StyleSettingsPanel; + +/////////////////////////////////////////////////////////////////////////////// + +CSetting g_Settings[]={ +{L"MenuStyleGroup",CSetting::TYPE_GROUP,IDS_STYLE_SETTINGS,0,0,CSetting::FLAG_BASIC,NULL,NULL,&g_StyleSettingsPanel}, + {L"MenuStyle",CSetting::TYPE_INT,0,0,2,CSetting::FLAG_NORESET}, + {L"Classic1",CSetting::TYPE_RADIO}, + {L"Classic2",CSetting::TYPE_RADIO}, + {L"Win7",CSetting::TYPE_RADIO}, + +{L"Basic",CSetting::TYPE_GROUP,IDS_BASIC_SETTINGS}, + {L"EnableSettings",CSetting::TYPE_BOOL,0,0,1,CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"CrashDump",CSetting::TYPE_INT,0,0,0,CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"OldProgramsAge",CSetting::TYPE_INT,0,0,48,CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"FolderStartMenu",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"FolderCommonStartMenu",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"FolderPrograms",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"FolderCommonPrograms",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"CompatibilityFixes",CSetting::TYPE_INT,0,0,0,CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"AutoStartDelay",CSetting::TYPE_INT,0,0,0,CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + // needed for backwards compatibility + {L"DefaultMenuStyle",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"MenuItems",CSetting::TYPE_MULTISTRING,0,0,L"",CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"Skin1",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"SkinOptions1",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"SkinVariation1",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"Skin2",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"SkinOptions2",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"SkinVariation2",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + +{L"Controls",CSetting::TYPE_GROUP,IDS_CONTROLS_SETTINGS}, + {L"MouseClick",CSetting::TYPE_INT,IDS_LCLICK,IDS_LCLICK_TIP,1,CSetting::FLAG_BASIC}, + {L"Nothing",CSetting::TYPE_RADIO,IDS_OPEN_NOTHING,IDS_OPEN_NOTHING_TIP}, + {L"ClassicMenu",CSetting::TYPE_RADIO,IDS_OPEN_CSM,IDS_OPEN_CSM_TIP}, + {L"WindowsMenu",CSetting::TYPE_RADIO,IDS_OPEN_WSM,IDS_OPEN_WSM_TIP}, + {L"Both",CSetting::TYPE_RADIO,IDS_OPEN_BOTH,IDS_OPEN_BOTH_TIP,0,CSetting::FLAG_HIDDEN}, + {L"ShiftClick",CSetting::TYPE_INT,IDS_SHIFT_LCLICK,IDS_SHIFT_LCLICK_TIP,2,CSetting::FLAG_BASIC}, + {L"Nothing",CSetting::TYPE_RADIO,IDS_OPEN_NOTHING,IDS_OPEN_NOTHING_TIP}, + {L"ClassicMenu",CSetting::TYPE_RADIO,IDS_OPEN_CSM,IDS_OPEN_CSM_TIP}, + {L"WindowsMenu",CSetting::TYPE_RADIO,IDS_OPEN_WSM,IDS_OPEN_WSM_TIP}, + {L"Both",CSetting::TYPE_RADIO,IDS_OPEN_BOTH,IDS_OPEN_BOTH_TIP,0,CSetting::FLAG_HIDDEN}, +/* {L"Desktop",CSetting::TYPE_RADIO,IDS_OPEN_DESKTOP,IDS_OPEN_DESKTOP_TIP,0,CSetting::FLAG_HIDDEN}, + {L"Cortana",CSetting::TYPE_RADIO,IDS_OPEN_CORTANA,IDS_OPEN_CORTANA_TIP},*/ + {L"WinKey",CSetting::TYPE_INT,IDS_WIN_KEY,IDS_WIN_KEY_TIP,1,CSetting::FLAG_BASIC}, + {L"Nothing",CSetting::TYPE_RADIO,IDS_OPEN_NOTHING,IDS_OPEN_NOTHING_TIP}, + {L"ClassicMenu",CSetting::TYPE_RADIO,IDS_OPEN_CSM,IDS_OPEN_CSM_TIP}, + {L"WindowsMenu",CSetting::TYPE_RADIO,IDS_OPEN_WSM,IDS_OPEN_WSM_TIP}, + {L"Both",CSetting::TYPE_RADIO,IDS_OPEN_BOTH,IDS_OPEN_BOTH_TIP}, + {L"Desktop",CSetting::TYPE_RADIO,IDS_OPEN_DESKTOP,IDS_OPEN_DESKTOP_TIP}, + {L"ShiftWin",CSetting::TYPE_INT,IDS_SHIFT_WIN,IDS_SHIFT_WIN_TIP,2,CSetting::FLAG_BASIC}, + {L"Nothing",CSetting::TYPE_RADIO,IDS_OPEN_NOTHING,IDS_OPEN_NOTHING_TIP}, + {L"ClassicMenu",CSetting::TYPE_RADIO,IDS_OPEN_CSM,IDS_OPEN_CSM_TIP}, + {L"WindowsMenu",CSetting::TYPE_RADIO,IDS_OPEN_WSM,IDS_OPEN_WSM_TIP}, + {L"Both",CSetting::TYPE_RADIO,IDS_OPEN_BOTH,IDS_OPEN_BOTH_TIP}, +/* {L"Desktop",CSetting::TYPE_RADIO,IDS_OPEN_DESKTOP,IDS_OPEN_DESKTOP_TIP,0,CSetting::FLAG_HIDDEN}, + {L"Cortana",CSetting::TYPE_RADIO,IDS_OPEN_CORTANA,IDS_OPEN_CORTANA_TIP},*/ + {L"MiddleClick",CSetting::TYPE_INT,IDS_MCLICK,IDS_MCLICK_TIP,0}, + {L"Nothing",CSetting::TYPE_RADIO,IDS_OPEN_NOTHING,IDS_OPEN_NOTHING_TIP}, + {L"ClassicMenu",CSetting::TYPE_RADIO,IDS_OPEN_CSM,IDS_OPEN_CSM_TIP}, + {L"WindowsMenu",CSetting::TYPE_RADIO,IDS_OPEN_WSM,IDS_OPEN_WSM_TIP}, +/* {L"Both",CSetting::TYPE_RADIO,IDS_OPEN_BOTH,IDS_OPEN_BOTH_TIP,0,CSetting::FLAG_HIDDEN}, + {L"Desktop",CSetting::TYPE_RADIO,IDS_OPEN_DESKTOP,IDS_OPEN_DESKTOP_TIP,0,CSetting::FLAG_HIDDEN}, + {L"Cortana",CSetting::TYPE_RADIO,IDS_OPEN_CORTANA,IDS_OPEN_CORTANA_TIP},*/ + {L"Hover",CSetting::TYPE_INT,IDS_HOVER,IDS_HOVER_TIP,0}, + {L"Nothing",CSetting::TYPE_RADIO,IDS_OPEN_NOTHING,IDS_OPEN_NOTHING_TIP}, + {L"ClassicMenu",CSetting::TYPE_RADIO,IDS_OPEN_CSM,IDS_OPEN_CSM_TIP}, + {L"WindowsMenu",CSetting::TYPE_RADIO,IDS_OPEN_WSM,IDS_OPEN_WSM_TIP}, + {L"StartHoverDelay",CSetting::TYPE_INT,IDS_HOVER_DELAY,IDS_HOVER_DELAY_TIP,1000,0,L"Hover",L"Hover"}, + {L"ShiftRight",CSetting::TYPE_BOOL,IDS_RIGHT_SHIFT,IDS_RIGHT_SHIFT_TIP,0}, + {L"CSMHotkey",CSetting::TYPE_HOTKEY,IDS_CSM_HOTKEY,IDS_CSM_HOTKEY_TIP,0}, + {L"WSMHotkey",CSetting::TYPE_HOTKEY,IDS_WSM_HOTKEY,IDS_WSM_HOTKEY_TIP,0}, + +{L"SpecialItems",CSetting::TYPE_GROUP,IDS_SHOW_ITEMS,0,0,CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"Computer",CSetting::TYPE_INT,IDS_SHOW_COMPUTER,IDS_SHOW_COMPUTER_TIP,1,CSetting::FLAG_BASIC|CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"Hide",CSetting::TYPE_RADIO,IDS_ITEM_HIDE,IDS_ITEM_HIDE_TIP}, + {L"Show",CSetting::TYPE_RADIO,IDS_ITEM_SHOW,IDS_ITEM_SHOW_TIP}, + {L"Menu",CSetting::TYPE_RADIO,IDS_ITEM_MENU,IDS_ITEM_MENU_TIP}, + {L"Drives",CSetting::TYPE_RADIO,IDS_ITEM_DRIVES,IDS_ITEM_DRIVES_TIP}, + {L"Favorites",CSetting::TYPE_INT,IDS_SHOW_FAVORITES,IDS_SHOW_FAVORITES_TIP,0,CSetting::FLAG_BASIC|CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"Hide",CSetting::TYPE_RADIO,IDS_ITEM_HIDE,IDS_ITEM_HIDE_TIP}, + {L"Show",CSetting::TYPE_RADIO,IDS_ITEM_SHOW,IDS_ITEM_SHOW_TIP}, + {L"Menu",CSetting::TYPE_RADIO,IDS_ITEM_MENU,IDS_ITEM_MENU_TIP}, + {L"Documents",CSetting::TYPE_INT,IDS_SHOW_DOCUMENTS,IDS_SHOW_DOCUMENTS_TIP,2,CSetting::FLAG_BASIC|CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"Hide",CSetting::TYPE_RADIO,IDS_ITEM_HIDE,IDS_ITEM_HIDE_TIP}, + {L"Show",CSetting::TYPE_RADIO,IDS_ITEM_SHOW,IDS_ITEM_SHOW_TIP}, + {L"Menu",CSetting::TYPE_RADIO,IDS_ITEM_MENU,IDS_ITEM_MENU_TIP}, + {L"MaxRecentDocuments",CSetting::TYPE_INT,IDS_MAX_DOCS,IDS_MAX_DOCS_TIP,15,CSetting::FLAG_MENU_CLASSIC_BOTH,L"Documents=2",L"Documents"}, + {L"SortRecentDocuments",CSetting::TYPE_INT,IDS_SORT_DOCS,IDS_SORT_DOCS_TIP,0,CSetting::FLAG_MENU_CLASSIC_BOTH,L"Documents=2",L"Documents"}, + {L"Name",CSetting::TYPE_RADIO,IDS_SORT_NAME,IDS_SORT_NAME_TIP}, + {L"Extension",CSetting::TYPE_RADIO,IDS_SORT_EXT,IDS_SORT_EXT_TIP}, + {L"Date",CSetting::TYPE_RADIO,IDS_SORT_DATE,IDS_SORT_DATE_TIP}, + {L"UserFiles",CSetting::TYPE_INT,IDS_SHOW_USERFILES,IDS_SHOW_USERFILES_TIP,1,CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"Hide",CSetting::TYPE_RADIO,IDS_ITEM_HIDE,IDS_ITEM_HIDE_TIP}, + {L"Show",CSetting::TYPE_RADIO,IDS_ITEM_SHOW,IDS_ITEM_SHOW_TIP}, + {L"Menu",CSetting::TYPE_RADIO,IDS_ITEM_MENU,IDS_ITEM_MENU_TIP}, + {L"UserDocuments",CSetting::TYPE_INT,IDS_SHOW_USERDOCS,IDS_SHOW_USERDOCS_TIP,1,CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"Hide",CSetting::TYPE_RADIO,IDS_ITEM_HIDE,IDS_ITEM_HIDE_TIP}, + {L"Show",CSetting::TYPE_RADIO,IDS_ITEM_SHOW,IDS_ITEM_SHOW_TIP}, + {L"Menu",CSetting::TYPE_RADIO,IDS_ITEM_MENU,IDS_ITEM_MENU_TIP}, + {L"UserPictures",CSetting::TYPE_INT,IDS_SHOW_USERPICS,IDS_SHOW_USERPICS_TIP,1,CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"Hide",CSetting::TYPE_RADIO,IDS_ITEM_HIDE,IDS_ITEM_HIDE_TIP}, + {L"Show",CSetting::TYPE_RADIO,IDS_ITEM_SHOW,IDS_ITEM_SHOW_TIP}, + {L"Menu",CSetting::TYPE_RADIO,IDS_ITEM_MENU,IDS_ITEM_MENU_TIP}, + {L"ControlPanel",CSetting::TYPE_INT,IDS_SHOW_CP,IDS_SHOW_CP_TIP,2,CSetting::FLAG_BASIC|CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"Hide",CSetting::TYPE_RADIO,IDS_ITEM_HIDE,IDS_ITEM_HIDE_TIP}, + {L"Show",CSetting::TYPE_RADIO,IDS_ITEM_SHOW,IDS_ITEM_SHOW_TIP}, + {L"Menu",CSetting::TYPE_RADIO,IDS_ITEM_MENU,IDS_ITEM_MENU_TIP}, + {L"ControlPanelCategories",CSetting::TYPE_BOOL,IDS_CP_CATEGORIES,IDS_CP_CATEGORIES_TIP,0,CSetting::FLAG_MENU_CLASSIC_BOTH,L"#ControlPanel",L"ControlPanel"}, + {L"Network",CSetting::TYPE_INT,IDS_SHOW_NETWORK,IDS_SHOW_NETWORK_TIP,1,CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"Hide",CSetting::TYPE_RADIO,IDS_ITEM_HIDE,IDS_ITEM_HIDE_TIP}, + {L"Show",CSetting::TYPE_RADIO,IDS_ITEM_SHOW,IDS_ITEM_SHOW_TIP}, + {L"Menu",CSetting::TYPE_RADIO,IDS_ITEM_MENU,IDS_ITEM_MENU_TIP}, + {L"Printers",CSetting::TYPE_INT,IDS_SHOW_PRINTERS,IDS_SHOW_PRINTERS_TIP,1,CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"Hide",CSetting::TYPE_RADIO,IDS_ITEM_HIDE,IDS_ITEM_HIDE_TIP}, + {L"Show",CSetting::TYPE_RADIO,IDS_ITEM_SHOW,IDS_ITEM_SHOW_TIP}, + {L"Menu",CSetting::TYPE_RADIO,IDS_ITEM_MENU,IDS_ITEM_MENU_TIP}, + {L"Shutdown",CSetting::TYPE_INT,IDS_SHOW_SHUTDOWN,IDS_SHOW_SHUTDOWN_TIP,2,CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"Hide",CSetting::TYPE_RADIO,IDS_ITEM_HIDE,IDS_ITEM_HIDE_TIP}, + {L"Show",CSetting::TYPE_RADIO,IDS_ITEM_SHOW,IDS_ITEM_SHOW_TIP}, + {L"Menu",CSetting::TYPE_RADIO,IDS_ITEM_MENU,IDS_ITEM_MENU_TIP}, + {L"LogOff",CSetting::TYPE_BOOL,IDS_SHOW_LOGOFF,IDS_SHOW_LOGOFF_TIP,1,CSetting::FLAG_MENU_CLASSIC_BOTH|CSetting::FLAG_BASIC}, + {L"ConfirmLogOff",CSetting::TYPE_BOOL,IDS_CONFIRM_LOGOFF,IDS_CONFIRM_LOGOFF_TIP,0,CSetting::FLAG_MENU_CLASSIC_BOTH,L"#LogOff",L"LogOff"}, + {L"Undock",CSetting::TYPE_BOOL,IDS_SHOW_UNDOCK,IDS_SHOW_UNDOCK_TIP,1,CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"Search",CSetting::TYPE_BOOL,IDS_SHOW_SEARCH,IDS_SHOW_SEARCH_TIP,1,CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"ShowAppsMenu",CSetting::TYPE_BOOL,IDS_SHOW_APPS_MENU,IDS_SHOW_APPS_MENU_TIP,1,CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"Help",CSetting::TYPE_BOOL,IDS_SHOW_HELP,IDS_SHOW_HELP_TIP,1,CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"Run",CSetting::TYPE_BOOL,IDS_SHOW_RUN,IDS_SHOW_RUN_TIP,1,CSetting::FLAG_MENU_CLASSIC_BOTH}, + +{L"MainMenu",CSetting::TYPE_GROUP,IDS_MAIN_MENU_SETTINGS}, + {L"ProgramsStyle",CSetting::TYPE_INT,IDS_INLINE_PROGS,IDS_INLINE_PROGS_TIP,1,CSetting::FLAG_MENU_WIN7|CSetting::FLAG_BASIC}, + {L"Cascade",CSetting::TYPE_RADIO,IDS_MAIN_CASCADE,IDS_MAIN_CASCADE_TIP}, + {L"Inline",CSetting::TYPE_RADIO,IDS_MAIN_INLINE,IDS_MAIN_INLINE_TIP}, + {L"Hidden",CSetting::TYPE_RADIO,IDS_MAIN_HIDDEN,IDS_MAIN_HIDDEN_TIP}, + {L"AllProgramsMetro",CSetting::TYPE_BOOL,IDS_SHOW_APPS,IDS_SHOW_APPS_TIP,1,CSetting::FLAG_MENU_WIN7,NULL,L"Inline"}, + {L"FoldersFirst",CSetting::TYPE_BOOL,IDS_FOLDERS_FIRST,IDS_FOLDERS_FIRST_TIP,0,CSetting::FLAG_MENU_WIN7,L"ProgramsStyle=1",L"Inline"}, + {L"OpenPrograms",CSetting::TYPE_BOOL,IDS_OPEN_PROGRAMS,IDS_OPEN_PROGRAMS_TIP,0,CSetting::FLAG_MENU_WIN7,L"ProgramsStyle=1",L"Inline"}, + {L"ProgramsMenuDelay",CSetting::TYPE_INT,IDS_PROGRAMS_DELAY,IDS_PROGRAMS_DELAY_TIP,200,CSetting::FLAG_MENU_WIN7,L"ProgramsStyle=1",L"Inline"}, // 2x system delay time + {L"HideProgramsMetro",CSetting::TYPE_BOOL,IDS_HIDE_APPS,IDS_HIDE_APPS_TIP,1}, + {L"PinnedPrograms",CSetting::TYPE_INT,IDS_PINNED_PROGRAMS,IDS_PINNED_PROGRAMS_TIP,PINNED_PROGRAMS_PINNED}, + {L"FastItems",CSetting::TYPE_RADIO,IDS_FAST_ITEMS,IDS_FAST_ITEMS_TIP}, + {L"PinnedItems",CSetting::TYPE_RADIO,IDS_PINNED_ITEMS,IDS_PINNED_ITEMS_TIP}, + {L"RecentPrograms",CSetting::TYPE_INT,IDS_RECENT_PROGRAMS,IDS_RECENT_PROGRAMS_TIP,RECENT_PROGRAMS_RECENT,CSetting::FLAG_BASIC}, + {L"None",CSetting::TYPE_RADIO,IDS_NO_RECENT,IDS_NO_RECENT_TIP}, + {L"Recent",CSetting::TYPE_RADIO,IDS_SHOW_RECENT,IDS_SHOW_RECENT_TIP}, + {L"Frequent",CSetting::TYPE_RADIO,IDS_SHOW_FREQUENT,IDS_SHOW_FREQUENT_TIP}, + {L"RecentMetroApps",CSetting::TYPE_BOOL,IDS_RECENT_METRO,IDS_RECENT_METRO_TIP,1,0,L"RecentPrograms",L"RecentPrograms"}, + {L"MaxRecentPrograms",CSetting::TYPE_INT,IDS_MAX_PROGS,IDS_MAX_PROGS_TIP,5,0,L"RecentPrograms",L"RecentPrograms"}, + {L"RecentProgsTop",CSetting::TYPE_BOOL,IDS_RECENT_TOP,IDS_RECENT_TOP_TIP,1,0,L"RecentPrograms",L"RecentPrograms"}, + {L"RecentSortName",CSetting::TYPE_BOOL,IDS_RECENT_NAME,IDS_RECENT_NAME_TIP,0,0,L"RecentPrograms",L"RecentPrograms"}, + {L"RecentProgKeys",CSetting::TYPE_INT,IDS_RECENT_KEYS,IDS_RECENT_KEYS_TIP,RECENT_KEYS_DIGITS,0,L"RecentPrograms",L"RecentPrograms"}, + {L"NoKey",CSetting::TYPE_RADIO,IDS_KEY_NOTHING,IDS_KEY_NOTHING_TIP,0,0,L"RecentPrograms"}, + {L"Normal",CSetting::TYPE_RADIO,IDS_KEY_NORMAL,IDS_KEY_NORMAL_TIP,0,0,L"RecentPrograms"}, + {L"Digits",CSetting::TYPE_RADIO,IDS_KEY_DIGITS,IDS_KEY_DIGITS_TIP,0,0,L"RecentPrograms"}, + {L"HiddenDigits",CSetting::TYPE_RADIO,IDS_KEY_HIDDEN,IDS_KEY_HIDDEN_TIP,0,0,L"RecentPrograms"}, + {L"EnableJumplists",CSetting::TYPE_BOOL,IDS_JUMPLISTS,IDS_JUMPLISTS_TIP,1}, + {L"MaxJumplists",CSetting::TYPE_INT,IDS_MAX_JUMPLISTS,IDS_MAX_JUMPLISTS_TIP,10,0,L"EnableJumplists",L"EnableJumplists"}, + {L"JumplistKeys",CSetting::TYPE_INT,IDS_JUMPLIST_KEYS,IDS_JUMPLISTS_KEY_TIP,0,0,L"EnableJumplists",L"EnableJumplists"}, + {L"Select",CSetting::TYPE_RADIO,IDS_KEY_SELECT,IDS_KEY_SELECT_TIP,0,0,L"EnableJumplists"}, + {L"Run",CSetting::TYPE_RADIO,IDS_KEY_RUN,IDS_KEY_RUN_TIP,0,0,L"EnableJumplists"}, + {L"Open",CSetting::TYPE_RADIO,IDS_KEY_OPEN,IDS_KEY_OPEN_TIP,0,0,L"EnableJumplists"}, + {L"ShutdownCommand",CSetting::TYPE_INT,IDS_SHUTDOWN_COMMAND,IDS_SHUTDOWN_COMMAND_TIP,1,CSetting::FLAG_MENU_WIN7|CSetting::FLAG_BASIC}, + {L"CommandNone",CSetting::TYPE_RADIO,IDS_SHUTDOWN_NONE,IDS_SHUTDOWN_NONE_TIP}, + {L"CommandShutdown",CSetting::TYPE_RADIO,IDS_SHUTDOWN_SHUTDOWN,IDS_SHUTDOWN_SHUTDOWN_TIP}, + {L"CommandRestart",CSetting::TYPE_RADIO,IDS_SHUTDOWN_RESTART,IDS_SHUTDOWN_RESTART_TIP}, + {L"CommandLogOff",CSetting::TYPE_RADIO,IDS_SHUTDOWN_LOGOFF,IDS_SHUTDOWN_LOGOFF_TIP}, + {L"CommandSleep",CSetting::TYPE_RADIO,IDS_SHUTDOWN_SLEEP,IDS_SHUTDOWN_SLEEP_TIP}, + {L"CommandHibernate",CSetting::TYPE_RADIO,IDS_SHUTDOWN_HIBERNATE,IDS_SHUTDOWN_HIBERNATE_TIP}, + {L"CommandLock",CSetting::TYPE_RADIO,IDS_SHUTDOWN_LOCK,IDS_SHUTDOWN_LOCK_TIP}, + {L"CommandSwitch",CSetting::TYPE_RADIO,IDS_SHUTDOWN_SWITCH,IDS_SHUTDOWN_SWITCH_TIP}, + {L"CommandShutdownBox",CSetting::TYPE_RADIO,IDS_SHUTDOWN_SHUTDOWN_BOX,IDS_SHUTDOWN_SHUTDOWN_BOX_TIP}, + {L"ShutdownW7",CSetting::TYPE_STRING,IDS_SHUTDOWN7,IDS_SHUTDOWN7_TIP,L"",CSetting::FLAG_MENU_WIN7,L"ShutdownCommand",L"ShutdownCommand"}, + {L"RemoteShutdown",CSetting::TYPE_BOOL,IDS_SHOW_RSHUTDOWN,IDS_SHOW_RSHUTDOWN_TIP,0,0,L"ShutdownCommand",L"ShutdownCommand"}, + {L"HybridShutdown",CSetting::TYPE_BOOL,IDS_HYBRID_SHUTDOWN,IDS_HYBRID_SHUTDOWN_TIP,1,0,L"ShutdownCommand",L"ShutdownCommand"}, + {L"ConfirmLogOff2",CSetting::TYPE_BOOL,IDS_CONFIRM_LOGOFF,IDS_CONFIRM_LOGOFF_TIP,0,CSetting::FLAG_MENU_WIN7,NULL,L"ShutdownCommand"}, + {L"SelectLastShutdown",CSetting::TYPE_BOOL,IDS_SELECT_LAST,IDS_SELECT_LAST_TIP,0,CSetting::FLAG_MENU_WIN7,NULL,L"ShutdownCommand"}, + {L"ProgramsWidth",CSetting::TYPE_INT,IDS_PROG_WIDTH,IDS_PROG_WIDTH_TIP,40,CSetting::FLAG_MENU_WIN7}, + {L"JumplistWidth",CSetting::TYPE_INT,IDS_JUMP_WIDTH,IDS_JUMP_WIDTH_TIP,40,CSetting::FLAG_MENU_WIN7}, + {L"MinMainHeight",CSetting::TYPE_INT,IDS_MIN_HEIGHT,IDS_MIN_HEIGHT_TIP,20,CSetting::FLAG_MENU_WIN7}, + {L"MaxRecentDocuments2",CSetting::TYPE_INT,IDS_MAX_DOCS,IDS_MAX_DOCS_TIP,15,CSetting::FLAG_MENU_WIN7}, + {L"SortRecentDocuments2",CSetting::TYPE_INT,IDS_SORT_DOCS,IDS_SORT_DOCS_TIP,0,CSetting::FLAG_MENU_WIN7}, + {L"Name",CSetting::TYPE_RADIO,IDS_SORT_NAME,IDS_SORT_NAME_TIP}, + {L"Extension",CSetting::TYPE_RADIO,IDS_SORT_EXT,IDS_SORT_EXT_TIP}, + {L"Date",CSetting::TYPE_RADIO,IDS_SORT_DATE,IDS_SORT_DATE_TIP}, + {L"StartScreenShortcut",CSetting::TYPE_BOOL,IDS_STARTSCREEN_ITEM,IDS_STARTSCREEN_ITEM_TIP,1}, + {L"ControlPanelCategories2",CSetting::TYPE_BOOL,IDS_CP_CATEGORIES2,IDS_CP_CATEGORIES_TIP,0,CSetting::FLAG_MENU_WIN7}, + {L"MainSortZA",CSetting::TYPE_BOOL,IDS_MAIN_SORTZA,IDS_SORTZA_TIP,0}, + {L"MainSortOnce",CSetting::TYPE_BOOL,IDS_MAIN_SORTONCE,IDS_SORTONCE_TIP,0}, + +{L"GeneralBehavior",CSetting::TYPE_GROUP,IDS_BEHAVIOR_SETTINGS}, + {L"AutoStart",CSetting::TYPE_BOOL,IDS_AUTOSTART,IDS_AUTOSTART_TIP,1,CSetting::FLAG_BASIC}, + {L"HighlightNew",CSetting::TYPE_BOOL,IDS_HIGHLIGHT_NEW,IDS_HIGHLIGHT_NEW_TIP,1}, + {L"HighlightNewApps",CSetting::TYPE_BOOL,IDS_HIGHLIGHT_NEWAPPS,IDS_HIGHLIGHT_NEWAPPS_TIP,1,0,L"#HighlightNew",L"HighlightNew"}, + {L"CheckWinUpdates",CSetting::TYPE_BOOL,IDS_CHECK_UPDATES,IDS_CHECK_UPDATES_TIP,1}, + {L"MenuDelay",CSetting::TYPE_INT,IDS_MENU_DELAY,IDS_MENU_DELAY_TIP,-1}, // system delay time + {L"SplitMenuDelay",CSetting::TYPE_INT,IDS_SPLIT_DELAY,IDS_SPLIT_DELAY_TIP,200}, // 2x system delay time + {L"InfotipDelay",CSetting::TYPE_STRING,IDS_TIP_DELAY,IDS_TIP_DELAY_TIP,L"400,4000"}, + {L"FolderInfotipDelay",CSetting::TYPE_STRING,IDS_FTIP_DELAY,IDS_FTIP_DELAY_TIP,L"0,0"}, + {L"EnableDragDrop",CSetting::TYPE_BOOL,IDS_DRAG_DROP,IDS_DRAG_DROP_TIP,1}, + {L"DragHideDelay",CSetting::TYPE_INT,IDS_DRAG_DELAY,IDS_DRAG_DELAY_TIP,4000}, + {L"ScrollType",CSetting::TYPE_INT,IDS_SCROLL_TYPE,IDS_SCROLL_TYPE_TIP,1}, + {L"Scroll",CSetting::TYPE_RADIO,IDS_SCROLL_YES,IDS_SCROLL_YES_TIP}, + {L"NoScroll",CSetting::TYPE_RADIO,IDS_SCROLL_NO,IDS_SCROLL_NO_TIP}, + {L"Auto",CSetting::TYPE_RADIO,IDS_SCROLL_AUTO,IDS_SCROLL_AUTO_TIP}, + {L"SameSizeColumns",CSetting::TYPE_BOOL,IDS_SAME_COLUMNS,IDS_SAME_COLUMNS_TIP,1,0,L"ScrollType",L"ScrollType"}, + {L"UserPicturePath",CSetting::TYPE_BITMAP,IDS_PIC_PATH,IDS_PIC_PATH_TIP,L""}, + {L"UserPictureCommand",CSetting::TYPE_STRING,IDS_PIC_COMMAND,IDS_PIC_COMMAND_TIP,L"control nusrmgr.cpl"}, + {L"UserNameCommand",CSetting::TYPE_STRING,IDS_NAME_COMMAND,IDS_NAME_COMMAND_TIP,L"control nusrmgr.cpl"}, + {L"SearchFilesCommand",CSetting::TYPE_STRING,IDS_SEARCH_COMMAND,IDS_SEARCH_COMMAND_TIP,L"search-ms:",CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"ExpandFolderLinks",CSetting::TYPE_BOOL,IDS_EXPAND_LINKS,IDS_EXPAND_LINKS_TIP,1}, + {L"EnableTouch",CSetting::TYPE_BOOL,IDS_ENABLE_TOUCH,IDS_ENABLE_TOUCH_TIP,1}, + {L"EnableAccessibility",CSetting::TYPE_BOOL,IDS_ACCESSIBILITY,IDS_ACCESSIBILITY_TIP,1}, + {L"ShowNextToTaskbar",CSetting::TYPE_BOOL,IDS_NEXTTASKBAR,IDS_NEXTTASKBAR_TIP,0}, + {L"PreCacheIcons",CSetting::TYPE_BOOL,IDS_CACHE_ICONS,IDS_CACHE_ICONS_TIP,1,CSetting::FLAG_COLD}, + {L"DelayIcons",CSetting::TYPE_BOOL,IDS_DELAY_ICONS,IDS_DELAY_ICONS_TIP,1,CSetting::FLAG_COLD}, + {L"ReportSkinErrors",CSetting::TYPE_BOOL,IDS_SKIN_ERRORS,IDS_SKIN_ERRORS_TIP,0}, + +{L"SearchBoxSettings",CSetting::TYPE_GROUP,IDS_SEARCH_BOX}, + {L"SearchBox",CSetting::TYPE_INT,IDS_SHOW_SEARCH_BOX,IDS_SHOW_SEARCH_BOX_TIP,SEARCHBOX_TAB,CSetting::FLAG_BASIC}, + {L"Hide",CSetting::TYPE_RADIO,IDS_SEARCH_BOX_HIDE,IDS_SEARCH_BOX_HIDE_TIP}, + {L"Normal",CSetting::TYPE_RADIO,IDS_SEARCH_BOX_SHOW,IDS_SEARCH_BOX_SHOW_TIP}, + {L"Tab",CSetting::TYPE_RADIO,IDS_SEARCH_BOX_TAB,IDS_SEARCH_BOX_TAB_TIP}, + {L"SearchSelect",CSetting::TYPE_BOOL,IDS_SEARCH_BOX_SEL,IDS_SEARCH_BOX_SEL_TIP,1,0,L"SearchBox=1",L"Normal"}, + {L"SearchTrack",CSetting::TYPE_BOOL,IDS_SEARCH_TRACK,IDS_SEARCH_TRACK_TIP,1,0,L"SearchBox"}, + {L"SearchResults",CSetting::TYPE_INT,IDS_SEARCH_MAX2,IDS_SEARCH_MAX_TIP2,5,CSetting::FLAG_MENU_CLASSIC_BOTH,L"SearchBox"}, + {L"SearchResultsMax",CSetting::TYPE_INT,IDS_SEARCH_MAX3,IDS_SEARCH_MAX_TIP3,20,CSetting::FLAG_MENU_CLASSIC_BOTH,L"SearchBox"}, + {L"SearchAutoComplete",CSetting::TYPE_BOOL,IDS_SEARCH_AUTO,IDS_SEARCH_AUTO_TIP,1,0,L"SearchBox"}, + {L"SearchPrograms",CSetting::TYPE_BOOL,IDS_SEARCH_PROGRAMS,IDS_SEARCH_PROGRAMS_TIP,1,0,L"SearchBox"}, + {L"SearchPath",CSetting::TYPE_BOOL,IDS_SEARCH_PATH,IDS_SEARCH_PATH_TIP,1,0,L"#SearchPrograms",L"SearchPrograms"}, + {L"SearchMetroApps",CSetting::TYPE_BOOL,IDS_SEARCH_METRO,IDS_SEARCH_METRO_TIP,1,0,L"#SearchPrograms",L"SearchPrograms"}, + {L"SearchMetroSettings",CSetting::TYPE_BOOL,IDS_SEARCH_METROS,IDS_SEARCH_METROS_TIP,1,0,L"#SearchPrograms",L"SearchPrograms"}, + {L"SearchKeywords",CSetting::TYPE_BOOL,IDS_SEARCH_KEYWORDS,IDS_SEARCH_KEYWORDS_TIP,1,0,L"#SearchPrograms",L"SearchPrograms"}, + {L"SearchSubWord",CSetting::TYPE_BOOL,IDS_SUB_WORD,IDS_SUB_WORD_TIP,1,0,L"#SearchPrograms",L"SearchPrograms"}, + {L"SearchFiles",CSetting::TYPE_BOOL,IDS_SEARCH_FILES,IDS_SEARCH_FILES_TIP,1,0,L"SearchBox"}, + {L"SearchContents",CSetting::TYPE_BOOL,IDS_SEARCH_CONTENTS,IDS_SEARCH_CONTENTS_TIP,1,0,L"#SearchFiles",L"SearchFiles"}, + {L"SearchCategories",CSetting::TYPE_BOOL,IDS_SEARCH_CATEGORIES,IDS_SEARCH_CATEGORIES_TIP,1,0,L"#SearchFiles",L"SearchFiles"}, + {L"SearchInternet",CSetting::TYPE_BOOL,IDS_SEARCH_INTERNET,IDS_SEARCH_INTERNET_TIP,1,0,L"SearchBox"}, + +{L"Look",CSetting::TYPE_GROUP,IDS_LOOK_SETTINGS}, + {L"SmallIconSize",CSetting::TYPE_INT,IDS_SMALL_SIZE_SM,IDS_SMALL_SIZE_SM_TIP,-1,CSetting::FLAG_COLD}, // 16 for DPI<=96, 20 for DPI<=120, 24 otherwise + {L"LargeIconSize",CSetting::TYPE_INT,IDS_LARGE_SIZE_SM,IDS_LARGE_SIZE_SM_TIP,-1,CSetting::FLAG_COLD}, // 32 for DPI<=96, 40 for DPI<=120, 48 otherwise + {L"InvertMetroIcons",CSetting::TYPE_BOOL,IDS_INVERT_ICONS,IDS_INVERT_ICONS_TIP,0}, + {L"MaxMainMenuWidth",CSetting::TYPE_INT,IDS_MENU_WIDTH,IDS_MENU_WIDTH_TIP,60,CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"MaxMenuWidth",CSetting::TYPE_INT,IDS_SUBMENU_WIDTH,IDS_SUBMENU_WIDTH_TIP,60}, + {L"OverrideDPI",CSetting::TYPE_INT,IDS_DPI_OVERRIDE,IDS_DPI_OVERRIDE_TIP,0,CSetting::FLAG_COLD}, + {L"MainMenuAnimate",CSetting::TYPE_BOOL,IDS_ANIMATION7,IDS_ANIMATION7_TIP,1,CSetting::FLAG_MENU_WIN7}, + {L"MainMenuAnimation",CSetting::TYPE_INT,IDS_ANIMATION,IDS_ANIMATION_TIP,-1}, // system animation type + {L"None",CSetting::TYPE_RADIO,IDS_ANIM_NONE,IDS_ANIM_NONE_TIP}, + {L"Fade",CSetting::TYPE_RADIO,IDS_ANIM_FADE,IDS_ANIM_FADE_TIP}, + {L"Slide",CSetting::TYPE_RADIO,IDS_ANIM_SLIDE,IDS_ANIM_SLIDE_TIP}, + {L"Random",CSetting::TYPE_RADIO,IDS_ANIM_RANDOM,IDS_ANIM_RANDOM_TIP}, + {L"MainMenuAnimationSpeed",CSetting::TYPE_INT,IDS_ANIM_SPEED,IDS_ANIM_SPEED_TIP,200,0,L"MainMenuAnimation"}, + {L"SubMenuAnimation",CSetting::TYPE_INT,IDS_SUB_ANIMATION,IDS_SUB_ANIMATION_TIP,-1}, // system animation type + {L"None",CSetting::TYPE_RADIO,IDS_ANIM_NONE,IDS_ANIM_NONE_TIP}, + {L"Fade",CSetting::TYPE_RADIO,IDS_ANIM_FADE,IDS_ANIM_FADE_TIP}, + {L"Slide",CSetting::TYPE_RADIO,IDS_ANIM_SLIDE,IDS_ANIM_SLIDE_TIP}, + {L"Random",CSetting::TYPE_RADIO,IDS_ANIM_RANDOM,IDS_ANIM_RANDOM_TIP}, + {L"SubMenuAnimationSpeed",CSetting::TYPE_INT,IDS_SUB_ANIM_SPEED,IDS_SUB_ANIM_SPEED_TIP,200,0,L"SubMenuAnimation"}, + {L"SubMenuAnimationAlways",CSetting::TYPE_BOOL,IDS_SUB_ANIM_ALWAYS,IDS_SUB_ANIM_ALWAYS_TIP,0,0,L"SubMenuAnimation"}, + {L"MainMenuScrollSpeed",CSetting::TYPE_INT,IDS_SCROLL_SPEED,IDS_SCROLL_SPEED_TIP,3,CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"SubMenuScrollSpeed",CSetting::TYPE_INT,IDS_SUB_SCROLL_SPEED,IDS_SUB_SCROLL_SPEED_TIP,3}, + {L"MenuFadeSpeed",CSetting::TYPE_INT,IDS_FADE_SPEED,IDS_FADE_SPEED_TIP,400}, + {L"MenuCaption",CSetting::TYPE_STRING,IDS_MENU_CAPTION,IDS_MENU_CAPTION_TIP,L"",CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"MenuUsername",CSetting::TYPE_STRING,IDS_MENU_USERNAME,IDS_MENU_USERNAME_TIP,L"",CSetting::FLAG_MENU_CLASSIC_BOTH}, + {L"NumericSort",CSetting::TYPE_BOOL,IDS_NUMERIC_SORT,IDS_NUMERIC_SORT_TIP,1}, + {L"FontSmoothing",CSetting::TYPE_INT,IDS_FONT_SMOOTHING,IDS_FONT_SMOOTHING_TIP,0}, + {L"Default",CSetting::TYPE_RADIO,IDS_SMOOTH_DEFAULT,IDS_SMOOTH_DEFAULT_TIP}, + {L"None",CSetting::TYPE_RADIO,IDS_SMOOTH_NONE,IDS_SMOOTH_NONE_TIP}, + {L"Standard",CSetting::TYPE_RADIO,IDS_SMOOTH_STD,IDS_SMOOTH_STD_TIP}, + {L"ClearType",CSetting::TYPE_RADIO,IDS_SMOOTH_CLEAR,IDS_SMOOTH_CLEAR_TIP}, + {L"MenuShadow",CSetting::TYPE_BOOL,IDS_MENU_SHADOW,IDS_MENU_SHADOW_TIP,1}, + {L"AeroGlass",CSetting::TYPE_BOOL,IDS_MENU_GLASS,IDS_MENU_GLASS_TIP,0,CSetting::FLAG_CALLBACK}, + {L"EnableGlass",CSetting::TYPE_BOOL,IDS_MENU_GLASS2,IDS_MENU_GLASS2_TIP,1}, + {L"GlassOverride",CSetting::TYPE_BOOL,IDS_GLASS_OVERRIDE,IDS_GLASS_OVERRIDE_TIP,0}, + {L"GlassColor",CSetting::TYPE_COLOR,IDS_GLASS_COLOR,IDS_GLASS_COLOR_TIP,0,0,L"GlassOverride",L"GlassOverride"}, + {L"GlassIntensity",CSetting::TYPE_INT,IDS_GLASS_INTENSITY,IDS_GLASS_INTENSITY_TIP,0,0,L"GlassOverride",L"GlassOverride"}, + {L"GlassBlending",CSetting::TYPE_INT,IDS_GLASS_BLENDING,IDS_GLASS_BLENDING_TIP,0,0,L"GlassOverride",L"GlassOverride"}, + {L"GlassOpacity",CSetting::TYPE_INT,IDS_GLASS_OPACITY,IDS_GLASS_OPACITY_TIP,DEFAULT_GLASS_OPACITY,0,L"EnableGlass"}, + +{L"Skin",CSetting::TYPE_GROUP,IDS_SKIN_SETTINGS,0,0,CSetting::FLAG_BASIC|CSetting::FLAG_MENU_CLASSIC1,NULL,NULL,&g_SkinSettingsPanelClassic1}, + {L"SkinC1",CSetting::TYPE_STRING,0,0,L"Windows Aero"}, + {L"SkinVariationC1",CSetting::TYPE_STRING,0,0,L""}, + {L"SkinOptionsC1",CSetting::TYPE_MULTISTRING,0,0,L""}, + +{L"Skin",CSetting::TYPE_GROUP,IDS_SKIN_SETTINGS,0,0,CSetting::FLAG_BASIC|CSetting::FLAG_MENU_CLASSIC2,NULL,NULL,&g_SkinSettingsPanelClassic2}, + {L"SkinC2",CSetting::TYPE_STRING,0,0,L"Windows Aero"}, + {L"SkinVariationC2",CSetting::TYPE_STRING,0,0,L""}, + {L"SkinOptionsC2",CSetting::TYPE_MULTISTRING,0,0,L""}, + +{L"Skin7",CSetting::TYPE_GROUP,IDS_SKIN_SETTINGS,0,0,CSetting::FLAG_BASIC|CSetting::FLAG_MENU_WIN7,NULL,NULL,&g_SkinSettingsPanelWin7}, + {L"SkinW7",CSetting::TYPE_STRING,0,0,L"Windows Aero"}, + {L"SkinVariationW7",CSetting::TYPE_STRING,0,0,L""}, + {L"SkinOptionsW7",CSetting::TYPE_MULTISTRING,0,0,L""}, + +{L"StartButton",CSetting::TYPE_GROUP,IDS_START_BUTTON}, + {L"EnableStartButton",CSetting::TYPE_BOOL,IDS_ENABLE_BUTTON,IDS_ENABLE_BUTTON_TIP,1}, + {L"AllTaskbars",CSetting::TYPE_BOOL,IDS_ENABLE_TASKBARS,IDS_ENABLE_TASKBARS_TIP,1,0,L"EnableStartButton"}, + {L"StartButtonTip",CSetting::TYPE_STRING,IDS_BUTTON_TIP,IDS_BUTTON_TIP_TIP,L"$Menu.Start",0,L"EnableStartButton"}, + {L"StartButtonType",CSetting::TYPE_INT,IDS_BUTTON_TYPE,IDS_BUTTON_TYPE_TIP,0,0,L"EnableStartButton"}, + {L"AeroButton",CSetting::TYPE_RADIO,IDS_AERO_BUTTON,IDS_AERO_BUTTON_TIP}, + {L"ClasicButton",CSetting::TYPE_RADIO,IDS_CLASSIC_BUTTON,IDS_CLASSIC_BUTTON_TIP}, + {L"CustomButton",CSetting::TYPE_RADIO,IDS_CUSTOM_BUTTON,IDS_CUSTOM_BUTTON_TIP}, + {L"StartButtonPath",CSetting::TYPE_BITMAP,IDS_BUTTON_IMAGE,IDS_BUTTON_IMAGE_TIP,L"",0,L"#StartButtonType=2",L"CustomButton"}, + {L"StartButtonSize",CSetting::TYPE_INT,IDS_BUTTON_SIZE,IDS_BUTTON_SIZE_TIP2,0,0,L"#StartButtonType=2",L"CustomButton"}, + {L"StartButtonAlign",CSetting::TYPE_BOOL,IDS_BUTTON_ALIGN,IDS_BUTTON_ALIGN_TIP,0,0,L"#StartButtonType=2",L"CustomButton"}, + {L"StartButtonIcon",CSetting::TYPE_ICON,IDS_BUTTON_ICON,IDS_BUTTON_ICON_TIP,L",1",0,L"#StartButtonType=1",L"ClasicButton"}, + {L"StartButtonIconSize",CSetting::TYPE_INT,IDS_BUTTON_ICON_SIZE,IDS_BUTTON_ICON_SIZE_TIP,0,0,L"#StartButtonType=1",L"ClasicButton"}, + {L"StartButtonText",CSetting::TYPE_STRING,IDS_BUTTON_TEXT,IDS_BUTTON_TEXT_TIP,L"$Menu.Start",0,L"#StartButtonType=1",L"ClasicButton"}, + +{L"Taskbar",CSetting::TYPE_GROUP,IDS_TASKBAR_SETTINGS}, + {L"CustomTaskbar",CSetting::TYPE_BOOL,IDS_TASK_CUSTOM,IDS_TASK_CUSTOM_TIP,0,CSetting::FLAG_CALLBACK}, + {L"TaskbarLook",CSetting::TYPE_INT,IDS_TASK_LOOK,IDS_TASK_LOOK_TIP,1,CSetting::FLAG_CALLBACK,L"CustomTaskbar",L"CustomTaskbar"}, + {L"Opaque",CSetting::TYPE_RADIO,IDS_TASK_OPAQUE,IDS_TASK_OPAQUE_TIP}, + {L"Transparent",CSetting::TYPE_RADIO,IDS_TASK_TRANS,IDS_TASK_TRANS_TIP}, + {L"Glass",CSetting::TYPE_RADIO,IDS_TASK_GLASS,IDS_TASK_GLASS_TIP}, + {L"AeroGlass",CSetting::TYPE_RADIO,IDS_TASK_AEROGLASS,IDS_TASK_AEROGLASS_TIP,0,CSetting::FLAG_HIDDEN}, + {L"TaskbarOpacity",CSetting::TYPE_INT,IDS_TASK_OPACITY,IDS_TASK_OPACITY_TIP,DEFAULT_TASK_OPACITY10,CSetting::FLAG_CALLBACK,L"TaskbarLook",L"CustomTaskbar"}, + {L"TaskbarColor",CSetting::TYPE_COLOR,IDS_TASK_COLOR,IDS_TASK_COLOR_TIP,0,CSetting::FLAG_CALLBACK,L"CustomTaskbar",L"CustomTaskbar"}, + {L"TaskbarTextColor",CSetting::TYPE_COLOR,IDS_TASK_TEXTCOLOR,IDS_TASK_TEXTCOLOR_TIP,0xFFFFFF,CSetting::FLAG_CALLBACK|(1<<24),L"CustomTaskbar",L"CustomTaskbar"}, + {L"TaskbarTexture",CSetting::TYPE_BITMAP_JPG,IDS_TASK_TEXTURE,IDS_TASK_TEXTURE_TIP,L"",CSetting::FLAG_CALLBACK,L"CustomTaskbar",L"CustomTaskbar"}, + {L"TaskbarTileH",CSetting::TYPE_INT,IDS_TASK_STRETCHH,IDS_TASK_STRETCHH_TIP,1,CSetting::FLAG_CALLBACK,L"#TaskbarTexture",L"TaskbarTexture"}, + {L"Tile",CSetting::TYPE_RADIO,IDS_TASK_TILE,IDS_TASK_TILE_TIP}, + {L"Stretch",CSetting::TYPE_RADIO,IDS_TASK_STRETCH,IDS_TASK_STRETCH_TIP}, + {L"TaskbarBordersH",CSetting::TYPE_STRING,IDS_TASK_BORDERS,IDS_TASK_BORDERS_TIP,L"0,0",CSetting::FLAG_CALLBACK,L"#TaskbarTileH=1",L"TaskbarTileH"}, + {L"TaskbarTileV",CSetting::TYPE_INT,IDS_TASK_STRETCHV,IDS_TASK_STRETCHV_TIP,1,CSetting::FLAG_CALLBACK,L"#TaskbarTexture",L"TaskbarTexture"}, + {L"Tile",CSetting::TYPE_RADIO,IDS_TASK_TILE,IDS_TASK_TILE_TIP}, + {L"Stretch",CSetting::TYPE_RADIO,IDS_TASK_STRETCH,IDS_TASK_STRETCH_TIP}, + {L"TaskbarBordersV",CSetting::TYPE_STRING,IDS_TASK_BORDERS,IDS_TASK_BORDERS_TIP,L"0,0",CSetting::FLAG_CALLBACK,L"#TaskbarTileV=1",L"TaskbarTileV"}, + +{L"Metro",CSetting::TYPE_GROUP,IDS_METRO_SETTINGS}, + {L"SkipMetro",CSetting::TYPE_BOOL,IDS_SKIP_METRO,IDS_SKIP_METRO_TIP,1,CSetting::FLAG_BASIC}, + {L"SkipMetroCount",CSetting::TYPE_INT,0,0,10,CSetting::FLAG_HIDDEN|CSetting::FLAG_NOSAVE}, + {L"DisableHotCorner",CSetting::TYPE_INT,IDS_HOT_CORNERS,IDS_HOT_CORNERS_TIP,1}, + {L"DisableNone",CSetting::TYPE_RADIO,IDS_DISABLE_NONE,IDS_DISABLE_NONE_TIP}, + {L"DisableStart",CSetting::TYPE_RADIO,IDS_DISABLE_START,IDS_DISABLE_START_TIP}, + {L"DisableAll",CSetting::TYPE_RADIO,IDS_DISABLE_ALL,IDS_DISABLE_ALL_TIP}, + {L"OpenMouseMonitor",CSetting::TYPE_BOOL,IDS_MOUSE_MONITOR,IDS_MOUSE_MONITOR_TIP,0}, + +{L"CustomMenu1",CSetting::TYPE_GROUP,IDS_CUSTOM_SETTINGS,0,0,CSetting::FLAG_MENU_CLASSIC1,NULL,NULL,&g_CustomMenuPanel1}, + {L"MenuItems1",CSetting::TYPE_MULTISTRING,0,0,L""}, + +{L"CustomMenu2",CSetting::TYPE_GROUP,IDS_CUSTOM_SETTINGS,0,0,CSetting::FLAG_MENU_CLASSIC2,NULL,NULL,&g_CustomMenuPanel2}, + {L"MenuItems2",CSetting::TYPE_MULTISTRING,0,0,L""}, + +{L"CustomMenu7",CSetting::TYPE_GROUP,IDS_CUSTOM_SETTINGS,0,0,CSetting::FLAG_BASIC|CSetting::FLAG_MENU_WIN7,NULL,NULL,&g_CustomMenuPanel7}, + {L"MenuItems7",CSetting::TYPE_MULTISTRING,0,0,L""}, + +{L"WindowsMenu",CSetting::TYPE_GROUP,IDS_WSM_SETTINGS}, + {L"CascadeAll",CSetting::TYPE_BOOL,IDS_CASCADE_ALL,IDS_CASCADE_ALL_TIP,0}, + {L"AllProgramsDelay",CSetting::TYPE_INT,IDS_ALL_DELAY,IDS_ALL_DELAY_TIP,-1,0,L"CascadeAll",L"CascadeAll"}, // system hover time + {L"InitiallySelect",CSetting::TYPE_INT,IDS_ALL_SELECT,IDS_ALL_SELECT_TIP,0,0,L"CascadeAll",L"CascadeAll"}, + {L"SelectSearch",CSetting::TYPE_RADIO,IDS_SELECT_SEARCH,IDS_SELECT_SEARCH_TIP}, + {L"SelectButton",CSetting::TYPE_RADIO,IDS_SELECT_BUTTON,IDS_SELECT_BUTTON_TIP}, + {L"HideUserPic",CSetting::TYPE_BOOL,IDS_HIDE_PIC,IDS_HIDE_PIC_TIP,0}, + +{L"AllProgramsSkin",CSetting::TYPE_GROUP,IDS_ALL_SKIN_SETTINGS,0,0,0,NULL,NULL,&g_SkinSettingsPanelAll}, + {L"SkinA",CSetting::TYPE_STRING,0,0,L""}, + {L"SkinVariationA",CSetting::TYPE_STRING,0,0,L""}, + {L"SkinOptionsA",CSetting::TYPE_MULTISTRING,0,0,L""}, + +{L"ContextMenu",CSetting::TYPE_GROUP,IDS_CONTEXT_MENU_SETTINGS}, + {L"EnableContextMenu",CSetting::TYPE_BOOL,IDS_CONTEXT_MENU,IDS_CONTEXT_MENU_TIP,1}, + {L"CascadingMenu",CSetting::TYPE_BOOL,IDS_CASCADE_MENU,IDS_CASCADE_MENU_TIP,0,0,L"EnableContextMenu",L"EnableContextMenu"}, + {L"ShowNewFolder",CSetting::TYPE_BOOL,IDS_NEW_FOLDER,IDS_NEW_FOLDER_TIP,1,0,L"EnableContextMenu",L"EnableContextMenu"}, + {L"EnableExit",CSetting::TYPE_BOOL,IDS_EXIT,IDS_EXIT_TIP,1}, + {L"EnableExplorer",CSetting::TYPE_BOOL,IDS_EXPLORER,IDS_EXPLORER_TIP,1}, + {L"ExplorerPath",CSetting::TYPE_STRING,IDS_EXPLORER_PATH,IDS_EXPLORER_PATH_TIP,L"computer",0,L"EnableExplorer",L"EnableExplorer"}, + {L"DisablePinExt",CSetting::TYPE_BOOL,IDS_NOPIN,IDS_NOPIN_TIP,0}, + +{L"Sounds",CSetting::TYPE_GROUP,IDS_SOUND_SETTINGS}, + {L"SoundMain",CSetting::TYPE_SOUND,IDS_SOUND_MAIN,IDS_SOUND_MAIN_TIP,L"MenuPopup"}, + {L"SoundPopup",CSetting::TYPE_SOUND,IDS_SOUND_POPUP,IDS_SOUND_POPUP_TIP,L"MenuPopup"}, + {L"SoundCommand",CSetting::TYPE_SOUND,IDS_SOUND_COMMAND,IDS_SOUND_COMMAND_TIP,L"MenuCommand"}, + {L"SoundDrop",CSetting::TYPE_SOUND,IDS_SOUND_DROP,IDS_SOUND_DROP_TIP,L"MoveMenuItem"}, + {L"SoundButtonHover",CSetting::TYPE_SOUND,IDS_SOUND_HOVER,IDS_SOUND_HOVER_TIP,L""}, + +{L"Language",CSetting::TYPE_GROUP,IDS_LANGUAGE_SETTINGS_SM,0,0,0,NULL,NULL,GetLanguageSettings(COMPONENT_MENU)}, + {L"Language",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_COLD|CSetting::FLAG_SHARED}, + {L"Update",CSetting::TYPE_BOOL,0,0,1,CSetting::FLAG_SHARED}, // this is here only to generate the ADMX entry + +{NULL} +}; + +void UpgradeSettings( bool bShared ) +{ + if (bShared) return; + + // determine if we are upgrading + if (FindSetting(L"DefaultMenuStyle")->IsDefault() && + FindSetting(L"MenuItems")->IsDefault() && + FindSetting(L"Skin1")->IsDefault() && + FindSetting(L"SkinOptions1")->IsDefault() && + FindSetting(L"SkinVariation1")->IsDefault() && + FindSetting(L"Skin2")->IsDefault() && + FindSetting(L"SkinOptions2")->IsDefault() && + FindSetting(L"SkinVariation2")->IsDefault()) + return; + + // determine if the old menu was using two columns + bool bTwoColumns=false; + const wchar_t *oldStyle=L"Classic"; + const CSetting *pSetting=FindSetting(L"DefaultMenuStyle"); + if (pSetting->value.vt==VT_BSTR) + oldStyle=pSetting->value.bstrVal; + + // XP skin is always two columns + pSetting=FindSetting(L"Skin1"); + if (pSetting->IsDefault()) + { + if (_wcsicmp(oldStyle,L"XP")==0) + bTwoColumns=true; + } + else if (pSetting->value.vt==VT_BSTR && _wcsicmp(pSetting->value.bstrVal,L"Windows XP Luna")==0) + bTwoColumns=true; + + if (!bTwoColumns) + { + pSetting=FindSetting(L"SkinOptions1"); + if (pSetting->IsDefault()) + { + // default setting for XP and Vista uses two columns + if (_wcsicmp(oldStyle,L"Classic")!=0) + bTwoColumns=true; + } + else if (pSetting->value.vt==VT_BSTR && wcswcs(pSetting->value.bstrVal,L"DA60029B")) + bTwoColumns=true; + } + + // preserve menu items + const CSetting *pSettingItems0=FindSetting(L"MenuItems"); + CSetting *pSettingItems=FindSetting(bTwoColumns?L"MenuItems2":L"MenuItems1"); + if (!pSettingItems->IsLocked() && !pSettingItems0->IsDefault()) + { + CString items=pSettingItems0->value; + items.Replace(L"Command=documents\n",L"Command=recent_documents\n"); + items.Replace(L"Command=recent_items\n",L"Command=recent_programs\n"); + items.Replace(L"Command=control_panel_categories\n",L"Command=control_panel\n"); + pSettingItems->value=items; + pSettingItems->flags&=~CSetting::FLAG_DEFAULT; + } + + // set initial menu style + CSetting *pSettingStyle=FindSetting(L"MenuStyle"); + if (!pSettingStyle->IsLocked()) + { + pSettingStyle->value=(bTwoColumns?1:0); + pSettingStyle->flags&=~CSetting::FLAG_DEFAULT; + SetSettingsStyle(bTwoColumns?CSetting::FLAG_MENU_CLASSIC2:CSetting::FLAG_MENU_CLASSIC1,CSetting::FLAG_MENU_MASK); + } + + // set skin + CSetting *pSettingSkin=FindSetting(bTwoColumns?L"SkinC2":L"SkinC1"); + if (!pSettingSkin->IsLocked()) + { + pSetting=FindSetting(L"Skin1"); + if (!pSetting->IsDefault()) + { + pSettingSkin->value=pSetting->value; + pSettingSkin->flags&=~CSetting::FLAG_DEFAULT; + } + } + CSetting *pSettingOpt=FindSetting(bTwoColumns?L"SkinOptionsC2":L"SkinOptionsC1"); + if (!pSettingOpt->IsLocked()) + { + pSetting=FindSetting(L"SkinOptions1"); + if (!pSetting->IsDefault()) + { + pSettingOpt->value=pSetting->value; + pSettingOpt->flags&=~CSetting::FLAG_DEFAULT; + } + } + CSetting *pSettingVar=FindSetting(bTwoColumns?L"SkinVariationC2":L"SkinVariationC1"); + if (!pSettingVar->IsLocked()) + { + pSetting=FindSetting(L"SkinVariation1"); + if (!pSetting->IsDefault()) + { + pSettingVar->value=pSetting->value; + pSettingVar->flags&=~CSetting::FLAG_DEFAULT; + } + } + + // set skin2 + pSettingSkin=FindSetting(L"SkinA"); + if (!pSettingSkin->IsLocked()) + { + pSetting=FindSetting(L"Skin2"); + if (!pSetting->IsDefault()) + { + pSettingSkin->value=pSetting->value; + pSettingSkin->flags&=~CSetting::FLAG_DEFAULT; + } + } + pSettingOpt=FindSetting(L"SkinOptionsA"); + if (!pSettingOpt->IsLocked()) + { + pSetting=FindSetting(L"SkinOptions2"); + if (!pSetting->IsDefault()) + { + pSettingOpt->value=pSetting->value; + pSettingOpt->flags&=~CSetting::FLAG_DEFAULT; + } + } + pSettingVar=FindSetting(L"SkinVariationA"); + if (!pSettingVar->IsLocked()) + { + pSetting=FindSetting(L"SkinVariation2"); + if (!pSetting->IsDefault()) + { + pSettingVar->value=pSetting->value; + pSettingVar->flags&=~CSetting::FLAG_DEFAULT; + } + } +} + +void UpdateSettings( void ) +{ + { + CRegKey regKey; + wchar_t language[100]=L""; + if (regKey.Open(HKEY_LOCAL_MACHINE,L"Software\\IvoSoft\\ClassicShell",KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS) + { + ULONG size=_countof(language); + if (regKey.QueryStringValue(L"DefaultLanguage",language,&size)!=ERROR_SUCCESS) + language[0]=0; + } + UpdateSetting(L"Language",language,false); + } + + TMenuStyle menuStyle=MENU_CLASSIC1; + { + const CSetting *pSetting=FindSetting(L"MenuStyle"); + if (pSetting && pSetting->value.vt==VT_I4) + menuStyle=(TMenuStyle)pSetting->value.intVal; + } + FindSetting(L"MaxRecentDocuments2")->pLinkTo=FindSetting(L"MaxRecentDocuments"); + FindSetting(L"SortRecentDocuments2")->pLinkTo=FindSetting(L"SortRecentDocuments"); + FindSetting(L"ControlPanelCategories2")->pLinkTo=FindSetting(L"ControlPanelCategories"); + FindSetting(L"ConfirmLogOff2")->pLinkTo=FindSetting(L"ConfirmLogOff"); + CMenuStyleDlg::UpdateDefaults(); + CCustomMenuDlg::UpdateWarnings(menuStyle); + + int dpi=FindSetting(L"OverrideDPI")->value.intVal; + if (dpi==0) + { + HDC hdc=GetDC(NULL); + dpi=GetDeviceCaps(hdc,LOGPIXELSY); + ReleaseDC(NULL,hdc); + } + else if (dpi<96) dpi=96; + else if (dpi>480) dpi=480; + + int iconSize=24; + if (dpi<=96) + iconSize=16; + else if (dpi<=120) + iconSize=20; + UpdateSetting(L"SmallIconSize",CComVariant(iconSize),false); + UpdateSetting(L"LargeIconSize",CComVariant(iconSize*2),false); + + DWORD time; + SystemParametersInfo(SPI_GETMENUSHOWDELAY,NULL,&time,0); + UpdateSetting(L"MenuDelay",CComVariant((int)time),false); + SystemParametersInfo(SPI_GETMOUSEHOVERTIME,NULL,&time,0); + UpdateSetting(L"AllProgramsDelay",CComVariant((int)time),false); + + int animation=0; + BOOL animate; + SystemParametersInfo(SPI_GETMENUANIMATION,NULL,&animate,0); + if (animate) + { + DWORD fade; + SystemParametersInfo(SPI_GETMENUFADE,NULL,&fade,0); + animation=fade?1:2; + } + UpdateSetting(L"MainMenuAnimation",CComVariant((int)animation),false); + UpdateSetting(L"SubMenuAnimation",CComVariant((int)animation),false); + + DWORD fade; + SystemParametersInfo(SPI_GETSELECTIONFADE,NULL,&fade,0); + UpdateSetting(L"MenuFadeSpeed",CComVariant(fade?400:0),false); + + UpdateSetting(L"Favorites",CComVariant(0),SHRestricted(REST_NOFAVORITESMENU)!=0); + if (SHRestricted(REST_NORECENTDOCSMENU)) + UpdateSetting(L"Documents",CComVariant(0),true); + else + UpdateSetting(L"Documents",CComVariant(2),false); + + DWORD logoff1=SHRestricted(REST_STARTMENULOGOFF); + DWORD logoff2=SHRestricted(REST_FORCESTARTMENULOGOFF); + UpdateSetting(L"LogOff",CComVariant((logoff1!=1)?1:0),logoff1 || logoff2); + + bool bNoClose=SHRestricted(REST_NOCLOSE)!=0; + UpdateSetting(L"Shutdown",CComVariant(bNoClose?0:2),bNoClose); + UpdateSetting(L"RemoteShutdown",CComVariant(0),bNoClose); + + bool bNoUndock=SHRestricted(REST_NOSMEJECTPC)!=0; + UpdateSetting(L"Undock",CComVariant(bNoUndock?0:1),bNoUndock); + + bool bNoSetFolders=SHRestricted(REST_NOSETFOLDERS)!=0; // hide control panel, printers, network + bool bNoControlPanel=bNoSetFolders || SHRestricted(REST_NOCONTROLPANEL); + UpdateSetting(L"ControlPanel",CComVariant(bNoControlPanel?0:1),bNoControlPanel); + + bool bNoNetwork=bNoSetFolders || SHRestricted(REST_NONETWORKCONNECTIONS); + UpdateSetting(L"Network",CComVariant(bNoNetwork?0:1),bNoNetwork); + + UpdateSetting(L"Printers",CComVariant(bNoSetFolders?0:1),bNoSetFolders); + + bool bNoHelp=SHRestricted(REST_NOSMHELP)!=0; + UpdateSetting(L"Help",CComVariant(bNoHelp?0:1),bNoHelp); + + bool bNoRun=SHRestricted(REST_NORUN)!=0; + UpdateSetting(L"Run",CComVariant(bNoRun?0:1),bNoRun); + UpdateSetting(L"SearchAutoComplete",CComVariant(bNoRun?0:1),bNoRun); + + bool bNoSearch=SHRestricted(REST_NOFIND)!=0; + UpdateSetting(L"Search",CComVariant(bNoSearch?0:1),bNoSearch); + + bool bNoDocs=SHRestricted(REST_NOSMMYDOCS)!=0; + UpdateSetting(L"UserFiles",CComVariant(bNoDocs?0:1),bNoDocs); + UpdateSetting(L"UserDocuments",CComVariant(bNoDocs?0:1),bNoDocs); + UpdateSetting(L"UserPictures",CComVariant(bNoDocs?0:1),bNoDocs); + + bool bNoEdit=SHRestricted(REST_NOCHANGESTARMENU)!=0; + UpdateSetting(L"EnableDragDrop",CComVariant(bNoEdit?0:1),bNoEdit); + UpdateSetting(L"EnableContextMenu",CComVariant(bNoEdit?0:1),bNoEdit); + + UpdateSetting(L"NumericSort",CComVariant(SHRestricted(REST_NOSTRCMPLOGICAL)?0:1),false); + + wchar_t title[256]=L"Windows"; + ULONG size=_countof(title); + { + CRegKey regTitle; + if (regTitle.Open(HKEY_LOCAL_MACHINE,L"Software\\Microsoft\\Windows NT\\CurrentVersion",KEY_READ)==ERROR_SUCCESS) + regTitle.QueryStringValue(L"ProductName",title,&size); + } + UpdateSetting(L"MenuCaption",CComVariant(title),false); + + size=_countof(title); + if (!GetUserNameEx(NameDisplay,title,&size)) + { + // GetUserNameEx may fail (for example on Home editions). use the login name + size=_countof(title); + GetUserName(title,&size); + } + UpdateSetting(L"MenuUsername",CComVariant(title),false); + + if (GetWinVersion()>=WIN_VER_WIN8) + { + HideSettingGroup(L"WindowsMenu",true); + HideSettingGroup(L"AllProgramsSkin",true); + UpdateSetting(L"CascadeAll",CComVariant(0),false); HideSetting(L"CascadeAll",true); + HIGHCONTRAST contrast={sizeof(contrast)}; + if (SystemParametersInfo(SPI_GETHIGHCONTRAST,sizeof(contrast),&contrast,0) && (contrast.dwFlags&HCF_HIGHCONTRASTON)) + UpdateSetting(L"StartButtonType",CComVariant(START_BUTTON_CLASSIC),false); + else + UpdateSetting(L"StartButtonType",CComVariant(START_BUTTON_AERO),false); + + HideSetting(L"EnableTouch",!(GetSystemMetrics(SM_DIGITIZER)&NID_INTEGRATED_TOUCH)); + + bool bStartScreen=GetWinVersion()nameID=bStartScreen?IDS_OPEN_WSS:IDS_OPEN_WSM; + pSetting->tipID=bStartScreen?IDS_OPEN_WSS_TIP:IDS_OPEN_WSM_TIP; + + pSetting=FindSetting(L"ShiftClick")+3; + pSetting->nameID=bStartScreen?IDS_OPEN_WSS:IDS_OPEN_WSM; + pSetting->tipID=bStartScreen?IDS_OPEN_WSS_TIP:IDS_OPEN_WSM_TIP; + + pSetting=FindSetting(L"WinKey")+3; + pSetting->nameID=bStartScreen?IDS_OPEN_WSS:IDS_OPEN_WSM; + pSetting->tipID=bStartScreen?IDS_OPEN_WSS_TIP:IDS_OPEN_WSM_TIP; + + pSetting=FindSetting(L"ShiftWin")+3; + pSetting->nameID=bStartScreen?IDS_OPEN_WSS:IDS_OPEN_WSM; + pSetting->tipID=bStartScreen?IDS_OPEN_WSS_TIP:IDS_OPEN_WSM_TIP; + + pSetting=FindSetting(L"MiddleClick")+3; + pSetting->nameID=bStartScreen?IDS_OPEN_WSS:IDS_OPEN_WSM; + pSetting->tipID=bStartScreen?IDS_OPEN_WSS_TIP:IDS_OPEN_WSM_TIP; + + pSetting=FindSetting(L"Hover")+3; + pSetting->nameID=bStartScreen?IDS_OPEN_WSS:IDS_OPEN_WSM; + pSetting->tipID=bStartScreen?IDS_OPEN_WSS_TIP:IDS_OPEN_WSM_TIP; + + if (bStartScreen) + UpdateSettingText(L"WSMHotkey",IDS_WSS_HOTKEY,IDS_WSS_HOTKEY_TIP,false); + else + UpdateSettingText(L"OpenMouseMonitor",IDS_MOUSE_MONITOR2,IDS_MOUSE_MONITOR_TIP2,false); + UpdateSettingText(L"ShiftRight",IDS_RIGHT_SHIFTX,IDS_RIGHT_SHIFTX_TIP,false); + + if (GetWinVersion()>=WIN_VER_WIN81) + { + if (GetWinVersion()>=WIN_VER_WIN10) + { + UpdateGroupText(L"Metro",IDS_METRO_SETTINGS10); + UpdateSetting(L"SkipMetro",CComVariant(0),false); HideSetting(L"SkipMetro",true); + UpdateSetting(L"DisableHotCorner",CComVariant(0),false); HideSetting(L"DisableHotCorner",true); + } + else + { + UpdateGroupText(L"Metro",IDS_METRO_SETTINGS81); + } + UpdateSettingText(L"EnableStartButton",IDS_ENABLE_BUTTON2,IDS_ENABLE_BUTTON_TIP2,false); + UpdateSetting(L"EnableStartButton",CComVariant(0),false); + pSetting=FindSetting(L"SkipMetro"); + CRegKey regSkip; + DWORD skip=0; + if (regSkip.Open(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage",KEY_READ)==ERROR_SUCCESS) + if (regSkip.QueryDWORDValue(L"OpenAtLogon",skip)!=ERROR_SUCCESS) + skip=0; + pSetting->value=CComVariant(skip==0?1:0); + } + else + { + UpdateSetting(L"SearchMetroSettings",CComVariant(0),false); HideSetting(L"SearchMetroSettings",true); + } + } + else + { + // Windows 7 + HideSettingGroup(L"Metro",true); + UpdateSetting(L"SkipMetro",CComVariant(0),false); HideSetting(L"SkipMetro",true); + UpdateSetting(L"EnableStartButton",CComVariant(0),false); + UpdateSetting(L"AllTaskbars",CComVariant(0),false); HideSetting(L"AllTaskbars",true); + UpdateSetting(L"AllProgramsMetro",CComVariant(0),false); HideSetting(L"AllProgramsMetro",true); + UpdateSetting(L"HideProgramsMetro",CComVariant(0),false); HideSetting(L"HideProgramsMetro",true); + UpdateSetting(L"ShowAppsMenu",CComVariant(0),false); HideSetting(L"ShowAppsMenu",true); + UpdateSetting(L"InvertMetroIcons",CComVariant(0),false); HideSetting(L"InvertMetroIcons",true); + UpdateSetting(L"AeroGlass",CComVariant(0),false); HideSetting(L"AeroGlass",true); + UpdateSettingText(L"EnableStartButton",IDS_ENABLE_BUTTON2,IDS_ENABLE_BUTTON_TIP2,false); + UpdateSetting(L"StartButtonType",CComVariant(IsAppThemed()?START_BUTTON_AERO:START_BUTTON_CLASSIC),false); + + FindSetting(L"WinKey")[4].flags|=CSetting::FLAG_HIDDEN; + FindSetting(L"WinKey")[5].flags|=CSetting::FLAG_HIDDEN; + FindSetting(L"ShiftWin")[4].flags|=CSetting::FLAG_HIDDEN; + UpdateSetting(L"RecentMetroApps",CComVariant(0),false); HideSetting(L"RecentMetroApps",true); + UpdateSetting(L"SearchMetroApps",CComVariant(0),false); HideSetting(L"SearchMetroApps",true); + UpdateSetting(L"SearchMetroSettings",CComVariant(0),false); HideSetting(L"SearchMetroSettings",true); + UpdateSetting(L"HybridShutdown",CComVariant(0),false); HideSetting(L"HybridShutdown",true); + UpdateSetting(L"EnableTouch",CComVariant(0),false); HideSetting(L"EnableTouch",true); +#ifndef STARTSCREEN_WIN7 + UpdateSetting(L"StartScreenShortcut",CComVariant(0),false); HideSetting(L"StartScreenShortcut",true); +#endif + UpdateSetting(L"HighlightNewApps",CComVariant(0),false); HideSetting(L"HighlightNewApps",true); + } + if (GetWinVersion()0) + { + dr/=dc; + dg/=dc; + db/=dc; + } + if (dr<0) dr=0; if (dr>255) dr=255; + if (dg<0) dg=0; if (dg>255) dg=255; + if (db<0) db=0; if (db>255) db=255; + if (da<0) da=0; if (da>255) da=255; + UpdateSetting(L"GlassColor",CComVariant(dr|(dg<<8)|(db<<16)),false); + UpdateSetting(L"GlassIntensity",CComVariant(dc*100/255),false); + UpdateSetting(L"GlassBlending",CComVariant(100-da*100/255),false); + HideSetting(L"GlassOpacity",true); + UpdateSetting(L"EnableGlass",CComVariant(1),false); HideSetting(L"EnableGlass",true); + UpdateSetting(L"TaskbarOpacity",CComVariant(GetWinVersion()<=WIN_VER_WIN7?DEFAULT_TASK_OPACITY7:DEFAULT_TASK_OPACITY8),false); + if (GetWinVersion()>WIN_VER_WIN7) + { + int color=GetSystemGlassColor8(); + UpdateSetting(L"TaskbarColor",CComVariant(((color&0xFF)<<16)|(color&0xFF00)|((color>>16)&0xFF)),false); + } + + if (GetWinVersion()<=WIN_VER_WIN7) + { + UpdateSetting(L"TaskbarLook",CComVariant(TASKBAR_GLASS),false); + } + else + { + FindSetting(L"TaskbarLook")[3].flags|=CSetting::FLAG_HIDDEN; + UpdateSetting(L"TaskbarLook",CComVariant(TASKBAR_TRANSPARENT),false); + } +/* + FindSetting(L"ShiftClick")[6].flags|=CSetting::FLAG_HIDDEN; + FindSetting(L"ShiftWin")[6].flags|=CSetting::FLAG_HIDDEN; + FindSetting(L"MiddleClick")[6].flags|=CSetting::FLAG_HIDDEN;*/ + } + else + { + // Windows 10 + int dr, dg, db; + GetMetroGlassColor(dr,dg,db); + if (dr<0) dr=0; if (dr>255) dr=255; + if (dg<0) dg=0; if (dg>255) dg=255; + if (db<0) db=0; if (db>255) db=255; + UpdateSetting(L"GlassColor",CComVariant(dr|(dg<<8)|(db<<16)),false); + HideSetting(L"GlassIntensity",true); + HideSetting(L"GlassBlending",true); + UpdateSetting(L"AeroGlass",CComVariant(0),false); HideSetting(L"AeroGlass",true); + + bool bTransparent; + int color=GetMetroTaskbarColor(bTransparent)&0xFFFFFF; + UpdateSetting(L"TaskbarLook",CComVariant(bTransparent?TASKBAR_TRANSPARENT:TASKBAR_OPAQUE),false); + UpdateSetting(L"TaskbarColor",CComVariant(color),false); + + FindSetting(L"MouseClick")[4].flags&=~CSetting::FLAG_HIDDEN; + FindSetting(L"ShiftClick")[4].flags&=~CSetting::FLAG_HIDDEN; + FindSetting(L"WinKey")[5].flags|=CSetting::FLAG_HIDDEN; + } + + bool bWSearch=HasSearchService(); + UpdateSettingText(L"SearchFiles",-1,bWSearch?IDS_SEARCH_FILES_TIP:IDS_SEARCH_FILES_TIP2,!bWSearch); + + UpdateSetting(L"MenuItems1",CComVariant(g_DefaultStartMenu1),false); + UpdateSetting(L"MenuItems2",CComVariant(g_DefaultStartMenu2),false); + { + // make games disabled by default if the folder doesn't exist (like on a server) + + const wchar_t *defaultMenu, *gameSettings0, *gameSettings1, *gameSettings2; + if (GetWinVersion() buf(Strlen(defaultMenu)+1); + wchar_t *str=&buf[0]; + Strcpy(str,(int)buf.size(),defaultMenu); + memcpy(wcswcs(str,gameSettings1),gameSettings2,Strlen(gameSettings2)*2); + UpdateSetting(L"MenuItems7",CComVariant(str),false); + } + else + { + UpdateSetting(L"MenuItems7",CComVariant(defaultMenu),false); + } + } + InitStdCommands7(); + + { + const wchar_t *skin12, *skin3; + const wchar_t *options1=L"", *options2=L"", *options3=L""; + bool bClassic; + if (GetWinVersion()WIN_VER_WIN8) + { + for (CSetting *pSetting=g_Settings;pSetting->name;pSetting++) + if (wcscmp(pSetting->name,L"SkipMetro")==0) + { + pSetting->flags|=CSetting::FLAG_NODEFAULT; + break; + } + } + InitSettings(g_Settings,COMPONENT_MENU,&g_CustomSettings); +} + +static int g_ButtonPath, g_ButtonSize, g_ButtonIcon, g_ButtonIconSize, g_ButtonText, g_ButtonTip; +static bool g_bButtonEnable, g_bTaskbarsChanged, g_bTaskbarsUpdated; + +static void StoreButtonSettings( void ) +{ + g_bButtonEnable=GetSettingBool(L"EnableStartButton"); + g_ButtonTip=CalcFNVHash(GetSettingString(L"StartButtonTip")); + g_ButtonPath=GetSettingInt(L"StartButtonType"); + g_ButtonIcon=0; + g_ButtonText=0; + if (g_ButtonPath==START_BUTTON_CLASSIC) + { + g_ButtonIcon=CalcFNVHash(GetSettingString(L"StartButtonIcon")); + g_ButtonText=CalcFNVHash(GetSettingString(L"StartButtonText")); + } + if (g_ButtonPath==START_BUTTON_CUSTOM) + g_ButtonPath=CalcFNVHash(GetSettingString(L"StartButtonPath")); + g_ButtonSize=GetSettingInt(L"StartButtonSize"); + g_ButtonIconSize=GetSettingInt(L"StartButtonIconSize"); +} + +static void UpdateButtons( bool bForce ) +{ + int tip=CalcFNVHash(GetSettingString(L"StartButtonTip")); + int path=GetSettingInt(L"StartButtonType"); + int icon=0; + int text=0; + if (path==START_BUTTON_CLASSIC) + { + icon=CalcFNVHash(GetSettingString(L"StartButtonIcon")); + text=CalcFNVHash(GetSettingString(L"StartButtonText")); + } + if (path==START_BUTTON_CUSTOM) + path=CalcFNVHash(GetSettingString(L"StartButtonPath")); + bool bRecreate=(g_bButtonEnable!=GetSettingBool(L"EnableStartButton") || path!=g_ButtonPath || g_ButtonSize!=GetSettingInt(L"StartButtonSize") + || g_ButtonIcon!=icon || g_ButtonIconSize!=GetSettingInt(L"StartButtonIconSize") || g_ButtonText!=text || g_ButtonTip!=tip); + if ((g_bTaskbarsChanged && !g_bTaskbarsUpdated) || bForce || bRecreate) + { + UpdateTaskBars(bRecreate?TASKBAR_RECREATE_BUTTONS:TASKBAR_UPDATE); + UpdateTaskBars(TASKBAR_UPDATE_TEXTURE); + g_bTaskbarsUpdated=true; + } + StoreButtonSettings(); +} + +void ClosingSettings( HWND hWnd, int flags, int command ) +{ + EnableHotkeys(HOTKEYS_NORMAL); + bool bRecreate=false; + if (command==IDOK) + { + if (flags&CSetting::FLAG_COLD) + MessageBox(hWnd,LoadStringEx(IDS_NEW_SETTINGS),LoadStringEx(IDS_APP_TITLE),MB_OK|MB_ICONWARNING); + if (GetWinVersion()>WIN_VER_WIN8) + { + CRegKey regSkip; + if (regSkip.Open(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage",KEY_WRITE)==ERROR_SUCCESS) + regSkip.SetDWORDValue(L"OpenAtLogon",GetSettingBool(L"SkipMetro")?0:1); + } + } + else if (command==IDCANCEL && g_bTaskbarsChanged) + { + g_bTaskbarsUpdated=false; + } + UpdateButtons(false); + ResetHotCorners(); + RedrawTaskbars(); +} + +void SettingChangedCallback( const CSetting *pSetting ) +{ + if (wcscmp(pSetting->name,L"CustomTaskbar")==0 || wcscmp(pSetting->name,L"TaskbarLook")==0 || wcscmp(pSetting->name,L"TaskbarOpacity")==0 || wcscmp(pSetting->name,L"TaskbarColor")==0 || wcscmp(pSetting->name,L"TaskbarTextColor")==0) + { + UpdateTaskBars(TASKBAR_UPDATE); + UpdateTaskBars(TASKBAR_UPDATE_TEXTURE); + g_bTaskbarsChanged=true; + g_bTaskbarsUpdated=true; + } + else if (wcscmp(pSetting->name,L"TaskbarTexture")==0 || wcscmp(pSetting->name,L"TaskbarTileH")==0 || wcscmp(pSetting->name,L"TaskbarTileV")==0 || wcscmp(pSetting->name,L"TaskbarBordersH")==0 || wcscmp(pSetting->name,L"TaskbarBordersV")==0) + { + UpdateTaskBars(TASKBAR_UPDATE_TEXTURE); + g_bTaskbarsChanged=true; + g_bTaskbarsUpdated=true; + } +/* not sure if I want to ever show the AeroGlass option + if (wcscmp(pSetting->name,L"AeroGlass")==0) + { + CSettingsLockWrite lock; + Assert(pSetting->value.vt==VT_I4); + if (pSetting->value.intVal) + FindSetting(L"TaskbarLook")[4].flags&=~CSetting::FLAG_HIDDEN; + else + FindSetting(L"TaskbarLook")[4].flags|=CSetting::FLAG_HIDDEN; + }*/ +} + +void EditSettings( bool bModal, int tab ) +{ +#ifndef BUILD_SETUP + wchar_t path[_MAX_PATH]; + GetModuleFileName(NULL,path,_countof(path)); + if (_wcsicmp(PathFindFileName(path),L"ClassicStartMenu.exe")==0) + bModal=true; +#endif + EnableHotkeys(HOTKEYS_SETTINGS); + StoreButtonSettings(); + g_bTaskbarsChanged=false; + g_bTaskbarsUpdated=true; + + wchar_t title[100]; + DWORD ver=GetVersionEx(g_Instance); + if (ver) + Sprintf(title,_countof(title),LoadStringEx(IDS_SETTINGS_TITLE_VER),ver>>24,(ver>>16)&0xFF,ver&0xFFFF); + else + Sprintf(title,_countof(title),LoadStringEx(IDS_SETTINGS_TITLE)); + EditSettings(title,bModal,tab); +} + +bool DllImportSettingsXml( const wchar_t *fname ) +{ + return ImportSettingsXml(fname); +} + +bool DllExportSettingsXml( const wchar_t *fname ) +{ + return ExportSettingsXml(fname); +} diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SettingsUI.h b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SettingsUI.h new file mode 100644 index 0000000..924b3f0 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SettingsUI.h @@ -0,0 +1,94 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#pragma once + +#include "ClassicStartMenuDLL.h" + +enum TMenuStyle +{ + MENU_CLASSIC1, + MENU_CLASSIC2, + MENU_WIN7, +}; + +enum TProgramsStyle +{ + PROGRAMS_CASCADING, + PROGRAMS_INLINE, + PROGRAMS_HIDDEN, +}; + +enum TRecentPrograms +{ + RECENT_PROGRAMS_NONE, + RECENT_PROGRAMS_RECENT, + RECENT_PROGRAMS_FREQUENT, +}; + +enum TPinnedPrograms +{ + PINNED_PROGRAMS_FAST, + PINNED_PROGRAMS_PINNED, +}; + +enum TRecentKeys +{ + RECENT_KEYS_NONE, + RECENT_KEYS_NORMAL, + RECENT_KEYS_DIGITS, + RECENT_KEYS_HIDDEN_DIGITS, +}; + +enum TShutdownType +{ + SHUTDOWN_TYPE_NONE, + SHUTDOWN_TYPE_SHUTDOWN, + SHUTDOWN_TYPE_RESTART, + SHUTDOWN_TYPE_LOGOFF, + SHUTDOWN_TYPE_SLEEP, + SHUTDOWN_TYPE_HIBERNATE, + SHUTDOWN_TYPE_LOCK, + SHUTDOWN_TYPE_SWITCHUSER, + SHUTDOWN_TYPE_SHUTDOWN_BOX, + + SHUTDOWN_TYPE_COUNT +}; + +enum TSearchBoxType +{ + SEARCHBOX_HIDDEN, + SEARCHBOX_NORMAL, + SEARCHBOX_TAB, +}; + +enum TTaskbarLook +{ + TASKBAR_OPAQUE, + TASKBAR_TRANSPARENT, + TASKBAR_GLASS, + TASKBAR_AEROGLASS, +}; + +enum TTaskbarTile +{ + TILE_TILE, + TILE_STRETCH, +}; + +enum +{ + COMPATIBILITY_ENUM_SHELLITEM= 1, // use IEnumShellItems to enumerate items + COMPATIBILITY_ENUM_FIX_PIDLS= 2, // regenerate child pidls when enumerating folders (requres COMPATIBILITY_ENUM_SHELLITEM) + COMPATIBILITY_SKIP_DESKTOP= 4, // don't collect items from desktop + COMPATIBILITY_TRIM_HOOKS= 8, // less hooking for Win7 + COMPATIBILITY_UPDATE_ITEMS= 16, // update the shell items for all search results + COMPATIBILITY_NO_TOUCH_KBD= 32, // disable the touch keyboard support + + COMPATIBILITY_CRASH_TEST= 0x80000000 +}; + +void InitSettings( void ); +STARTMENUAPI void EditSettings( bool bModal, int tab ); +STARTMENUAPI bool DllImportSettingsXml( const wchar_t *fname ); +STARTMENUAPI bool DllExportSettingsXml( const wchar_t *fname ); diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SkinDescription.txt b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SkinDescription.txt new file mode 100644 index 0000000..5f8d130 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SkinDescription.txt @@ -0,0 +1,23 @@ +; Empty skin - all properties are defaults, except: + +About=#7100 +AboutIcon=103 +Main_padding=2,2,2,2 +Main_no_icons2=1 +Main_new_selection=#FFBB00 +Main_new_text_color=#000000 +Main_new_arrow_color=#000000 +Submenu_padding=2,2,2,2 +Submenu_separator_text_padding=3,4,4,4,100% +Submenu_separator_icon_padding=6,3,3,3,100% +Submenu_separator_split_text_padding=3,4,4,4,100% +Submenu_separator_split_icon_padding=6,3,3,3,100% +Submenu_new_selection=#FFBB00 +Submenu_new_text_color=#000000 +Submenu_new_arrow_color=#000000 +Main2_padding=4,2,2,2 +Main2_text_padding=3,4,4,4,100% +Main2_new_selection=#FFBB00 +Main2_new_text_color=#000000 +Main2_new_arrow_color=#000000 +More_bitmap=none diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SkinDescription7.txt b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SkinDescription7.txt new file mode 100644 index 0000000..145d665 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SkinDescription7.txt @@ -0,0 +1,32 @@ +; Empty skin - all properties are defaults, except: + +About=#7100 +AboutIcon=103 +Main_padding=2,2,4,2 +Main_new_selection=#FFBB00 +Main_new_text_color=#000000 +Main_new_arrow_color=#000000 +Submenu_new_selection=#FFBB00 +Submenu_new_text_color=#000000 +Submenu_new_arrow_color=#000000 +Programs_new_selection=#FFBB00 +Programs_new_text_color=#000000 +Main2_new_selection=#FFBB00 +Main2_new_text_color=#000000 +Main2_new_arrow_color=#000000 +Main2_padding=2,2,2,2 +Main_search_padding=2,2,2,2 +Main_jump_padding=2,2,2,2 +Main_text_padding=1,3,8,4 +Main_no_icons2=1 +Shutdown_padding=5,5,5,5 +Shutdown_text_padding=5,4,8,5 +Shutdown_icon_padding=4,3,-2,3 +Submenu_padding=2,2,2,2 +Submenu_separator_text_padding=3,4,4,4 +List_separator_text_padding=3,0,0,0 +List_separator_icon_padding=4,3,4,3 +List_separator_split_text_padding=3,0,0,0 +List_separator_split_icon_padding=4,3,4,3 +Main_search_indent=8 +More_bitmap=none diff --git a/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SkinManager.cpp b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SkinManager.cpp new file mode 100644 index 0000000..f6977a5 --- /dev/null +++ b/ClassicShellSrc/ClassicStartMenu/ClassicStartMenuDLL/SkinManager.cpp @@ -0,0 +1,3298 @@ +// Classic Shell (c) 2009-2016, Ivo Beltchev +// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author + +#include "stdafx.h" +#include "resource.h" +#include "SkinManager.h" +#include "ItemManager.h" +#include "LogManager.h" +#include "SettingsParser.h" +#include "Settings.h" +#include "SettingsUI.h" +#include "Translations.h" +#include "ResourceHelper.h" +#include "FNVHash.h" +#include "dllmain.h" +#include "IatHookHelper.h" +#include "MenuContainer.h" +#include "ProgramsTree.h" +#include +#include + +//#define SIMULATE_METRO_COLORS "win8_blue" + +#ifdef BUILD_SETUP +#undef SIMULATE_METRO_COLORS +#endif + +static struct +{ + const wchar_t *name; + int code; +} g_SystemColors[]= +{ + {L"SystemScrollbar",COLOR_SCROLLBAR}, + {L"SystemBackground",COLOR_BACKGROUND}, + {L"SystemActiveCaption",COLOR_ACTIVECAPTION}, + {L"SystemInactiveCaption",COLOR_INACTIVECAPTION}, + {L"SystemMenu",COLOR_MENU}, + {L"SystemWindow",COLOR_WINDOW}, + {L"SystemWindowFrame",COLOR_WINDOWFRAME}, + {L"SystemMenuText",COLOR_MENUTEXT}, + {L"SystemWindowText",COLOR_WINDOWTEXT}, + {L"SystemCaptionText",COLOR_CAPTIONTEXT}, + {L"SystemActiveBorder",COLOR_ACTIVEBORDER}, + {L"SystemInactiveBorder",COLOR_INACTIVEBORDER}, + {L"SystemAppWorkspace",COLOR_APPWORKSPACE}, + {L"SystemHighlight",COLOR_HIGHLIGHT}, + {L"SystemHighlightText",COLOR_HIGHLIGHTTEXT}, + {L"SystemBtnFace",COLOR_BTNFACE}, + {L"SystemBtnShadow",COLOR_BTNSHADOW}, + {L"SystemGrayText",COLOR_GRAYTEXT}, + {L"SystemBtnText",COLOR_BTNTEXT}, + {L"SystemInactiveCaptionText",COLOR_INACTIVECAPTIONTEXT}, + {L"SystemBtnHighlight",COLOR_BTNHIGHLIGHT}, + {L"System3DDKShadow",COLOR_3DDKSHADOW}, + {L"System3DLight",COLOR_3DLIGHT}, + {L"SystemInfoText",COLOR_INFOTEXT}, + {L"SystemInfoBK",COLOR_INFOBK}, + {L"SystemHotLight",COLOR_HOTLIGHT}, + {L"SystemGradientActiveCaption",COLOR_GRADIENTACTIVECAPTION}, + {L"SystemGradientInactiveCaption",COLOR_GRADIENTINACTIVECAPTION}, + {L"SystemMenuHilight",COLOR_MENUHILIGHT}, + {L"SystemMenuBar",COLOR_MENUBAR}, +}; + +wchar_t MenuSkin::s_SkinError[1024]; + +const RECT DEFAULT_ICON_PADDING={3,3,3,3}; +const RECT DEFAULT_TEXT_PADDING={1,2,8,2}; +const SIZE DEFAULT_ARROW_PADDING={5,7}; +const int DEFAULT_SEPARATOR_WIDTH=4; +const int DEFAULT_SEPARATOR_HEIGHT=8; +const POINT DEFAULT_USER_IMAGE_PADDING={-4,8}; +const RECT DEFAULT_SEARCH_PADDING={4,4,4,4}; + +static int g_GlassColorR, g_GlassColorG, g_GlassColorB, g_GlassColorA; + +#ifdef SIMULATE_METRO_COLORS +struct SimMetroColor +{ + unsigned int nameHash; + COLORREF color; +}; +static std::vector g_MetroColors; + +static int GetImmersiveUserColorSetPreference( bool bForceCheckRegistry, bool bSkipCheckOnFail ) +{ + return 0; +} + +static COLORREF GetImmersiveColorFromColorSetEx( UINT dwImmersiveColorSet, UINT dwImmersiveColorType, bool bIgnoreHighContrast, UINT dwHighContrastCacheMode ) +{ + return g_MetroColors[dwImmersiveColorType].color; +} + +static int GetImmersiveColorTypeFromName( const wchar_t *name ) +{ + if (wcsncmp(name,L"Immersive",9)==0) + { + unsigned int crc=CalcFNVHash(name+9); + for (int i=0;i<(int)g_MetroColors.size();i++) + if (g_MetroColors[i].nameHash==crc) + return i; + } + return -1; +} + +#else +typedef int (WINAPI *TGetImmersiveUserColorSetPreference)(bool bForceCheckRegistry, bool bSkipCheckOnFail); +typedef COLORREF (WINAPI *TGetImmersiveColorFromColorSetEx)(UINT dwImmersiveColorSet, UINT dwImmersiveColorType, bool bIgnoreHighContrast, UINT dwHighContrastCacheMode); +typedef int (WINAPI *TGetImmersiveColorTypeFromName)(const wchar_t *name); + +static TGetImmersiveUserColorSetPreference GetImmersiveUserColorSetPreference; +static TGetImmersiveColorFromColorSetEx GetImmersiveColorFromColorSetEx; +static TGetImmersiveColorTypeFromName GetImmersiveColorTypeFromName; +#endif +static int g_CurrentMetroColorSet; + +void MenuBitmap::Init( bool bIsColor ) +{ + bIsBitmap=!bIsColor; + bIsOwned=false; + bitmap=NULL; +} + +void MenuBitmap::Reset( bool bIsColor ) +{ + if (bIsOwned && GetBitmap()) + { + BOOL res=DeleteObject(bitmap); + Assert(res); + } + Init(bIsColor); +} + +MenuSkin::MenuSkin( void ) +{ + Hash=0; + AboutIcon=NULL; + BOwnHintFont=false; + BHasScrollbar=false; + BHasMetroColors=false; + Main_bitmap.Init(); + Main_bitmap_search.Init(); + Main_bitmap_jump.Init(); + Caption_font=NULL; + User_font=NULL; + Main_separatorV.Init(); + Main_pager.Init(); + Main_pager_arrows.Init(); + User_bitmap.Init(); + User_mask.Init(); + Programs_icon.Init(); + Programs_icon_selected.Init(); + Scrollbar_button.Init(); + Scrollbar_arrows.Init(); + Scrollbar_background.Init(); + Scrollbar_thumb.Init(); + Scrollbar_gripper.Init(); + Submenu_bitmap.Init(); + Submenu_separatorV.Init(); + Submenu_pager.Init(); + Submenu_pager_arrows.Init(); + Pin_bitmap.Init(); + More_bitmap.Init(); + Shutdown_bitmap.Init(); + Search_bitmap.Init(); + Search_arrow.Init(); + Search_background.Init(); + Search_background_search.Init(); + Search_background_jump.Init(); + for (int i=0;i<_countof(Main_emblems);i++) + Main_emblems[i].Init(); + Main_emblem_mask.Init(); + Main_emblem_search_mask.Init(); + Main_emblem_jump_mask.Init(); + Search_emblem_mask.Init(); + Search_emblem_search_mask.Init(); + Search_emblem_jump_mask.Init(); + for (int i=0;i<_countof(Patterns);i++) + Patterns[i].Init(); + Main_pattern_mask.Init(); + Main_pattern_search_mask.Init(); + Main_pattern_jump_mask.Init(); + Search_pattern_mask.Init(); + Search_pattern_search_mask.Init(); + Search_pattern_jump_mask.Init(); + Search_hint_font=NULL; + Search_underline_font=NULL; + for (int i=0;i<_countof(ItemSettings);i++) + ItemSettings[i].Init(); +} + +void MenuSkin::ItemDrawSettings::Init( void ) +{ + font=NULL; + bOwnFont=true; + glowSize=0; + memset(textColors,0,sizeof(textColors)); + memset(textShadowColors,-1,sizeof(textShadowColors)); + memset(&textPadding,0,sizeof(textPadding)); + memset(selSlicesX,0,sizeof(selSlicesX)); + memset(selSlicesY,0,sizeof(selSlicesY)); + arrSize.cx=arrSize.cy=0; + memset(arrColors,0,sizeof(arrColors)); + arrPadding.cx=arrPadding.cy=0; + memset(frameSlicesX,0,sizeof(frameSlicesX)); + memset(frameSlicesY,0,sizeof(frameSlicesY)); + iconFrameOffset.x=iconFrameOffset.y=0; + memset(&iconPadding,0,sizeof(iconPadding)); + memset(sepSlicesX,0,sizeof(sepSlicesX)); + sepHeight=0; + opacity=MenuSkin::OPACITY_SOLID; + textTopOffset=iconTopOffset=0; + + bmpSelection.Init(); + bmpArrow.Init(); + bmpIconFrame.Init(); + bmpSeparator.Init(); +} + +void MenuSkin::ItemDrawSettings::Reset( void ) +{ + if (font && bOwnFont) + { + DeleteObject(font); + font=NULL; + bOwnFont=true; + } + bmpSelection.Reset(); + bmpArrow.Reset(); + bmpIconFrame.Reset(); + bmpSeparator.Reset(); +} + +MenuSkin::~MenuSkin( void ) +{ + Reset(); +} + +void MenuSkin::Reset( void ) +{ + if (AboutIcon) DestroyIcon(AboutIcon); + AboutIcon=NULL; + Main_bitmap.Reset(); + Main_bitmap_search.Reset(); + Main_bitmap_jump.Reset(); + if (Caption_font) DeleteObject(Caption_font); + Caption_font=NULL; + if (User_font) DeleteObject(User_font); + User_font=NULL; + Main_separatorV.Reset(); + User_bitmap.Reset(); + User_mask.Reset(); + Programs_icon.Reset(); + Programs_icon_selected.Reset(); + Scrollbar_button.Reset(); + Scrollbar_arrows.Reset(); + Scrollbar_background.Reset(); + Scrollbar_thumb.Reset(); + Scrollbar_gripper.Reset(); + Submenu_bitmap.Reset(); + Submenu_separatorV.Reset(); + Main_pager.Reset(); + Main_pager_arrows.Reset(); + Submenu_pager.Reset(); + Submenu_pager_arrows.Reset(); + Pin_bitmap.Reset(); + More_bitmap.Reset(); + Shutdown_bitmap.Reset(); + Search_bitmap.Reset(); + Search_arrow.Reset(); + Search_background.Reset(); + Search_background_search.Reset(); + Search_background_jump.Reset(); + for (int i=0;i<_countof(Main_emblems);i++) + Main_emblems[i].Reset(); + Main_emblem_mask.Reset(); + Main_emblem_search_mask.Reset(); + Main_emblem_jump_mask.Reset(); + Search_emblem_mask.Reset(); + Search_emblem_search_mask.Reset(); + Search_emblem_jump_mask.Reset(); + for (int i=0;i<_countof(Patterns);i++) + { + Patterns[i].Reset(); + PatternBits[i].clear(); + } + Main_pattern_mask.Reset(); + Main_pattern_search_mask.Reset(); + Main_pattern_jump_mask.Reset(); + Search_pattern_mask.Reset(); + Search_pattern_search_mask.Reset(); + Search_pattern_jump_mask.Reset(); + PatternPretileWidth=0; + if (Search_hint_font && BOwnHintFont) DeleteObject(Search_hint_font); + BOwnHintFont=false; + BHasScrollbar=false; + BHasMetroColors=false; + Search_hint_font=NULL; + if (Search_underline_font) DeleteObject(Search_underline_font); + Search_underline_font=NULL; + for (int i=0;i<_countof(ItemSettings);i++) + ItemSettings[i].Reset(); + + for (std::vector::const_iterator it=CustomBitmaps.begin();it!=CustomBitmaps.end();++it) + DeleteObject(it->bitmap); + CustomBitmaps.clear(); + + Options.clear(); + Variations.clear(); + Hash=0; + MetroColorHash=0; + MetroColors.clear(); +} + +static void GetErrorMessage( wchar_t *err, int size, DWORD code ) +{ + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,NULL,code,0,err,size,NULL); +} + +int MenuSkin::ScaleSkinElement( int num, int scale ) const +{ + int ddpi=Dpi-96; + if (ddpi<=0) + return num; + if (num<0) + return (num*(9600+ddpi*scale)-4800)/9600; + else + return (num*(9600+ddpi*scale)+4800)/9600; +} + +COLORREF MenuSkin::GetMetroColor( const wchar_t *names ) const +{ + unsigned int crc=CalcFNVHash(names); + std::map::const_iterator it=MetroColors.find(crc); + if (it!=MetroColors.end()) + return it->second.color; + + MetroColor data={0}; + + wchar_t name[100]; + while (*names) + { + if (names[0]=='#') + { + wchar_t *end; + data.color=wcstoul(names+1,&end,16); + break; + } + if (names[0]=='$') + names++; + names=GetToken(names,name,_countof(name),L"|"); + + bool bFound=false; + if (wcsncmp(name,L"System",6)==0) + { + for (int i=0;i<_countof(g_SystemColors);i++) + { + if (wcscmp(name,g_SystemColors[i].name)==0) + { + data.colorType=-2-g_SystemColors[i].code; + COLORREF color=GetSysColor(g_SystemColors[i].code); + data.color=((color&0xFF)<<16)|(color&0xFF00)|((color>>16)&0xFF); + bFound=true; + break; + } + } + } + + if (!bFound) + { + BHasMetroColors=true; + if (GetImmersiveUserColorSetPreference!=NULL) + { + wchar_t text[256]; + Sprintf(text,_countof(text),L"Immersive%s",name); + int type=GetImmersiveColorTypeFromName(text); + data.colorType=type<0?-1:type; + if (type>=0) + { + DWORD color=GetImmersiveColorFromColorSetEx(g_CurrentMetroColorSet,type,true,0); + data.color=((color&0xFF)<<16)|(color&0xFF00)|((color>>16)&0xFF); + bFound=true; + } + } + } + if (bFound) + break; + } + + data.color|=0xFF000000; + MetroColors[crc]=data; + return data.color; +} + +unsigned int MenuSkin::CalcMetroColorHash( int set ) const +{ + // if set is -1 returns the currently cached colors + unsigned int hash=FNV_HASH0; + for (std::map::const_iterator it=MetroColors.begin();it!=MetroColors.end();++it) + { + COLORREF color=0; + if (set==-1) + color=it->second.color; + else if (it->second.colorType<-1) + { + color=GetSysColor(-2-it->second.colorType); + color=((color&0xFF)<<16)|(color&0xFF00)|((color>>16)&0xFF); + } + else if (it->second.colorType>=0) + { + color=GetImmersiveColorFromColorSetEx(set,it->second.colorType,true,0); + color=((color&0xFF)<<16)|(color&0xFF00)|((color>>16)&0xFF); + } + color|=0xFF000000; + hash=CalcFNVHash(&color,sizeof(color),hash); + } + return hash; +} + +int MenuSkin::LoadSkinNumbers( const wchar_t *str, int *numbers, int count, TSkinNumberType type ) const +{ + memset(numbers,0,count*4); + for (int i=0;i>16)&0xFF); + else if (type==NUMBERS_COLORS_ABGR) + { + if (Strlen(token+1)==6) + num|=0xFF000000; + numbers[i]=((num&0xFF)<<16)|(num&0xFF00FF00)|((num>>16)&0xFF); + } + else + numbers[i]=num; + } + + if (type==NUMBERS_PADDING || type==NUMBERS_SIZE) + { + int scale=0; + for (int i=0;i100) scale=100; + } + numbers[i]=ScaleSkinElement(numbers[i],scale); + } + } + return count; +} + +RECT MenuSkin::ScaleSkinElement( const RECT &rect ) const +{ + RECT res; + res.left=ScaleSkinElement(rect.left); + res.right=ScaleSkinElement(rect.right); + res.top=ScaleSkinElement(rect.top); + res.bottom=ScaleSkinElement(rect.bottom); + return res; +} + +POINT MenuSkin::ScaleSkinElement( const POINT &point ) const +{ + POINT res; + res.x=ScaleSkinElement(point.x); + res.y=ScaleSkinElement(point.y); + return res; +} + +SIZE MenuSkin::ScaleSkinElement( const SIZE &size ) const +{ + SIZE res; + res.cx=ScaleSkinElement(size.cx); + res.cy=ScaleSkinElement(size.cy); + return res; +} + +HFONT MenuSkin::LoadSkinFont( const wchar_t *str, const wchar_t *name, int weight, float size, bool bScale ) const +{ + DWORD quality=DEFAULT_QUALITY; + int smoothing=GetSettingInt(L"FontSmoothing"); + if (smoothing==1) + quality=NONANTIALIASED_QUALITY; + else if (smoothing==2) + quality=ANTIALIASED_QUALITY; + if (smoothing==3) + quality=CLEARTYPE_QUALITY; + wchar_t token[256]; + bool bItalic=false; + int scale=bScale?100:0; + if (str) + { + if (_wcsicmp(str,L"none")==0) + return NULL; + str=GetToken(str,token,_countof(token),L", \t"); + name=token; + wchar_t token2[256]; + str=GetToken(str,token2,_countof(token2),L", \t"); + weight=FW_NORMAL; + if (_wcsicmp(token2,L"bold")==0) + weight=FW_BOLD; + else if (_wcsicmp(token2,L"italic")==0) + bItalic=true; + else if (_wcsicmp(token2,L"bold_italic")==0) + weight=FW_BOLD, bItalic=true; + str=GetToken(str,token2,_countof(token2),L", \t"); + size=(float)_wtof(token2); + str=GetToken(str,token2,_countof(token2),L", \t"); + if (token2[0] && token2[Strlen(token2)-1]=='%') + { + scale=_wtol(token2); + if (scale<0) scale=0; + if (scale>100) scale=100; + } + } + else if (!name) + { + // get the default menu font + NONCLIENTMETRICS metrics={sizeof(metrics)}; + SystemParametersInfo(SPI_GETNONCLIENTMETRICS,NULL,&metrics,0); + metrics.lfMenuFont.lfQuality=(BYTE)quality; + return CreateFontIndirect(&metrics.lfMenuFont); + } + size=ScaleSkinElement((int)(size*96),scale)/72.f; + return CreateFont((int)size,0,0,0,weight,bItalic?1:0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,quality,DEFAULT_PITCH,name); +} + +static HICON LoadSkinIcon( HMODULE hMod, int index ) +{ + if (hMod) + { + return (HICON)LoadImage(hMod,MAKEINTRESOURCE(index),IMAGE_ICON,0,0,LR_DEFAULTSIZE); + } + else + { + wchar_t path[_MAX_PATH]; + GetSkinsPath(path); + wchar_t fname[_MAX_PATH]; + Sprintf(fname,_countof(fname),L"%s%d.ico",path,index); + return (HICON)LoadImage(NULL,fname,IMAGE_ICON,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE); + } +} + +struct DWMCOLORIZATIONPARAMS +{ + DWORD ColorizationColor; + DWORD ColorizationAfterglow; + DWORD ColorizationColorBalance; + DWORD ColorizationAfterglowBalance; + DWORD ColorizationBlurBalance; + DWORD ColorizationGlassReflectionIntensity; + DWORD ColorizationOpaqueBlend; + DWORD extra; // Win8 has extra parameter +}; + +static bool GetSkinColorizationParameters( DWMCOLORIZATIONPARAMS *params ) +{ + typedef HRESULT (WINAPI *tGetColorizationParameters)(DWMCOLORIZATIONPARAMS *params); + + // HACK: the system function DwmGetColorizationColor is buggy on Win 7. its calculations can overflow and return a totally wrong value + // (try orange color with full intensity and no transparency - you'll get alpha=0 and green color). so here we use the undocumented + // function GetColorizationParameters exported by dwmapi.dll, ordinal 127 and then compute the colors manually using integer math + HMODULE hMod=GetModuleHandle(L"dwmapi.dll"); + if (!hMod) return false; + tGetColorizationParameters GetColorizationParameters=(tGetColorizationParameters)GetProcAddress(hMod,MAKEINTRESOURCEA(127)); + if (!GetColorizationParameters || FAILED(GetColorizationParameters(params))) + return false; + if (GetWinVersion()>=WIN_VER_WIN8) + params->ColorizationOpaqueBlend=0; // Win8 has no transparency + return true; +} + +COLORREF GetSystemGlassColor8( void ) +{ + COLORREF color=0; + DWMCOLORIZATIONPARAMS params; + if (GetSkinColorizationParameters(¶ms)) + { + int r=(params.ColorizationColor>>16)&255; + int g=(params.ColorizationColor>>8)&255; + int b=(params.ColorizationColor)&255; + int gray=217*(100-params.ColorizationColorBalance)+50; + r=(r*params.ColorizationColorBalance+gray)/100; + g=(g*params.ColorizationColorBalance+gray)/100; + b=(b*params.ColorizationColorBalance+gray)/100; + r=(r*200+127)/255; + g=(g*200+127)/255; + b=(b*200+127)/255; + color=(r<<16)|(g<<8)|b|(params.ColorizationColor&0xFF000000); + } + return color; +} + +void GetSystemGlassColor( int &dr, int &dg, int &db, int &da, int &dc ) +{ + dr=dg=db=da=dc=0; + DWMCOLORIZATIONPARAMS params; + if (GetSkinColorizationParameters(¶ms)) + { + // boost the color balance to better match the Windows 7 menu + params.ColorizationColorBalance=(int)(100.f*powf(params.ColorizationColorBalance/100.f,0.5f)); + int ir=(params.ColorizationColor>>16)&255; + int ig=(params.ColorizationColor>>8)&255; + int ib=(params.ColorizationColor)&255; + + int ir2=(params.ColorizationAfterglow>>16)&255; + int ig2=(params.ColorizationAfterglow>>8)&255; + int ib2=(params.ColorizationAfterglow)&255; + + int brightness=(ir*21+ig*72+ib*7)/255; // [0..100] + int glowBalance=(brightness*params.ColorizationAfterglowBalance)/100; // [0..100] + + dr=MulDiv(ir2*glowBalance+ir*100,params.ColorizationColorBalance*255,10000); + dg=MulDiv(ig2*glowBalance+ig*100,params.ColorizationColorBalance*255,10000); + db=MulDiv(ib2*glowBalance+ib*100,params.ColorizationColorBalance*255,10000); + dc=(glowBalance+100)*params.ColorizationColorBalance*255/10000; + + da=(100-params.ColorizationAfterglowBalance-params.ColorizationBlurBalance)*255/100; + if (params.ColorizationOpaqueBlend || da>=255) + da=255; + else if (da<=0) + dr=dg=db=da=0; + } +} + +void GetMetroGlassColor( int &dr, int &dg, int &db ) +{ + if (GetImmersiveUserColorSetPreference!=NULL) + { + int type=GetImmersiveColorTypeFromName(L"ImmersiveStartBackground"); + if (type>=0) + { + int set=GetImmersiveUserColorSetPreference(false,false); + DWORD color=GetImmersiveColorFromColorSetEx(set,type,true,0); + db=((color>>16)&255); + dg=((color>>8)&255); + dr=((color)&255); + return; + } + } + dr=dg=db=0; +} + +COLORREF GetMetroTaskbarColor( bool &bTransparent ) +{ + bTransparent=true; + if (GetImmersiveUserColorSetPreference!=NULL) + { + CRegKey regTheme; + if (regTheme.Open(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",KEY_READ)==ERROR_SUCCESS) + { + DWORD trans=1; + bTransparent=regTheme.QueryDWORDValue(L"EnableTransparency",trans)!=ERROR_SUCCESS || trans; + } + int type=GetImmersiveColorTypeFromName(bTransparent?L"ImmersiveSystemAccentDark3":L"ImmersiveSystemAccentDark2"); + if (type>=0) + { + int set=GetImmersiveUserColorSetPreference(false,false); + return GetImmersiveColorFromColorSetEx(set,type,true,0); + } + } + return 0; +} + +COLORREF GetSystemAccentColor( void ) +{ + if (GetImmersiveUserColorSetPreference!=NULL && GetWinVersion()>=WIN_VER_WIN10) + { + int type=GetImmersiveColorTypeFromName(L"ImmersiveSystemAccent"); + if (type>=0) + { + int set=GetImmersiveUserColorSetPreference(false,false); + return GetImmersiveColorFromColorSetEx(set,type,true,0); + } + } + return 0; +} + +static void GetMenuGlassColor( int &dr, int &dg, int &db, int &da ) +{ + if (GetWinVersion()>=WIN_VER_WIN10) + { + bool bDef=true; + if (GetSettingBool(L"GlassOverride")) + { + COLORREF color=GetSettingInt(L"GlassColor",bDef); + db=((color>>16)&255); + dg=((color>>8)&255); + dr=((color)&255); + } + if (bDef) + GetMetroGlassColor(dr,dg,db); + dr*=255; + dg*=255; + db*=255; + da=255; + } + else + { + bool bDef=true; + if (GetSettingBool(L"GlassOverride")) + { + bool bDef1, bDef2, bDef3; + COLORREF color=GetSettingInt(L"GlassColor",bDef1); + int intensity=GetSettingInt(L"GlassIntensity",bDef2); + da=GetSettingInt(L"GlassBlending",bDef3); + bDef=bDef1 && bDef2 && bDef3; + if (!bDef) + { + db=((color>>16)&255); + dg=((color>>8)&255); + dr=((color)&255); + + if (intensity<0) intensity=0; + if (intensity>100) intensity=100; + intensity=(intensity*255)/100; + dr*=intensity; + dg*=intensity; + db*=intensity; + + if (da<0) da=0; + if (da>100) da=100; + da=((100-da)*255)/100; + } + } + + if (bDef) + { + int dc; + GetSystemGlassColor(dr,dg,db,da,dc); + } + } +} + +const COLORREF DEFAULT_GLASS_COLOR=0x00000000; +const COLORREF DEFAULT_GLASS_CONFLICT=0x00000001; + +static void BlendColor( int &r, int &g, int &b, int a1, int a2, int a3, COLORREF tintColor1, COLORREF tintColor2, COLORREF tintColor3 ) +{ + int tr1, tg1, tb1; + int ta2=tintColor2>>24, tr2=(tintColor2)&255, tg2=(tintColor2>>8)&255, tb2=(tintColor2>>16)&255; + int ta3=tintColor3>>24, tr3=(tintColor3)&255, tg3=(tintColor3>>8)&255, tb3=(tintColor3>>16)&255; + int a1m=1; + if (tintColor1==DEFAULT_GLASS_COLOR) + { + a1m=g_GlassColorA; + tr1=g_GlassColorR; + tg1=g_GlassColorG; + tb1=g_GlassColorB; + } + else + { + a1*=tintColor1>>24; + tr1=(tintColor1)&255; + tg1=(tintColor1>>8)&255; + tb1=(tintColor1>>16)&255; + } + a2*=ta2; + a3*=ta3; + int a4=255*255-a1*a1m-a2-a3; if (a4<0) a4=0; + r=(tr1*a1+tr2*a2+tr3*a3+r*a4)/(255*255); + g=(tg1*a1+tg2*a2+tg3*a3+g*a4)/(255*255); + b=(tb1*a1+tb2*a2+tb3*a3+b*a4)/(255*255); + if (r>255) r=255; + if (g>255) g=255; + if (b>255) b=255; +} + +static void BlendColor( COLORREF &color, COLORREF mask, COLORREF tintColor1, COLORREF tintColor2, COLORREF tintColor3 ) +{ + int r=(color)&255, g=(color>>8)&255, b=(color>>16)&255; + int a1=(mask)&255, a2=(mask>>8)&255, a3=(mask>>16)&255; + BlendColor(r,g,b,a1,a2,a3,tintColor1,tintColor2,tintColor3); + color=(b<<16)|(g<<8)|r; +} + +static HBITMAP DuplicateBitmap( HBITMAP src ) +{ + BITMAP info; + GetObject(src,sizeof(info),&info); + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=info.bmWidth; + bi.bmiHeader.biHeight=info.bmHeight; + bi.bmiHeader.biPlanes=info.bmPlanes; + bi.bmiHeader.biBitCount=info.bmBitsPixel; + HDC hdc=CreateCompatibleDC(NULL); + void *bits; + HBITMAP dst=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,&bits,NULL,0); + DeleteDC(hdc); + memcpy(bits,info.bmBits,info.bmHeight*info.bmWidthBytes); + return dst; +} + +void MenuSkin::LoadSkinTintColors( CSkinParser &parser, const wchar_t *name, COLORREF &tintColor1, COLORREF &tintColor2, COLORREF &tintColor3, COLORREF backgroundColor ) const +{ + wchar_t name2[256]; + Sprintf(name2,_countof(name2),L"%s_tint1",name); + const wchar_t *str=parser.FindSetting(name2); + if (str && _wcsicmp(str,L"$Default")!=0 && LoadSkinNumbers(str,(int*)&tintColor1,1,NUMBERS_COLORS_ABGR)) + { + if (tintColor1==DEFAULT_GLASS_COLOR) + tintColor1=DEFAULT_GLASS_CONFLICT; + } + else + tintColor1=DEFAULT_GLASS_COLOR; + + Sprintf(name2,_countof(name2),L"%s_tint2",name); + str=parser.FindSetting(name2); + if (!str || _wcsicmp(str,L"$Default")==0 || !LoadSkinNumbers(str,(int*)&tintColor2,1,NUMBERS_COLORS_ABGR)) + tintColor2=backgroundColor|0xFF000000; + + Sprintf(name2,_countof(name2),L"%s_tint3",name); + str=parser.FindSetting(name2); + if (!str || _wcsicmp(str,L"$Default")==0 || !LoadSkinNumbers(str,(int*)&tintColor3,1,NUMBERS_COLORS_ABGR)) + tintColor3=0; +} + +bool MenuSkin::LoadSkinColors( CSkinParser &parser, const wchar_t *name, COLORREF *colors, int count, COLORREF backgroundColor, TSkinNumberType type ) const +{ + const wchar_t *str=parser.FindSetting(name); + if (!str || !LoadSkinNumbers(str,(int*)colors,count,type)) + return false; + + if (count>10) return false; + wchar_t name2[256]; + Sprintf(name2,_countof(name2),L"%s_mask",name); + str=parser.FindSetting(name2); + if (str) + { + COLORREF masks[10], tintColor1, tintColor2, tintColor3; + if (LoadSkinNumbers(str,(int*)masks,count,NUMBERS_COLORS)) + { + LoadSkinTintColors(parser,name,tintColor1,tintColor2,tintColor3,backgroundColor); + for (int i=0;i0 - bitmap ID + // if maskIndex<0 - color RGB + MenuBitmap res; + res.Init(); + wchar_t err[1024]; + HBITMAP bmp=NULL; + if (index>0) + { + if ((index&0xFF000000)==0x0F000000) + { + bmp=DuplicateBitmap(CustomBitmaps[index&0xFFFFFF].bitmap); + } + else if (hMod) + { + bmp=(HBITMAP)LoadImage(hMod,MAKEINTRESOURCE(index),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION); + if (!bmp) + bmp=LoadImageResource(hMod,MAKEINTRESOURCE(index),false,false); + if (!bmp) + { + GetErrorMessage(err,_countof(err),GetLastError()); + Sprintf(MenuSkin::s_SkinError,_countof(MenuSkin::s_SkinError),LoadStringEx(IDS_SKIN_ERR_BMPRES),index,err); + return res; + } + } + else + { + wchar_t path[_MAX_PATH]; + GetSkinsPath(path); + wchar_t fname[_MAX_PATH]; + Sprintf(fname,_countof(fname),L"%s%d.bmp",path,index); + bmp=(HBITMAP)LoadImage(NULL,fname,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_LOADFROMFILE); + if (!bmp) + { + GetErrorMessage(err,_countof(err),GetLastError()); + Sprintf(MenuSkin::s_SkinError,_countof(MenuSkin::s_SkinError),LoadStringEx(IDS_SKIN_ERR_BMPFILE),fname,err); + return res; + } + } + } + + HBITMAP bmpMask=NULL; + BITMAP infoMask={0}; + if (maskIndex>0) + { + if ((maskIndex&0xFF000000)==0x0F000000) + { + bmpMask=DuplicateBitmap(CustomBitmaps[maskIndex&0xFFFFFF].bitmap); + } + else if (hMod) + { + bmpMask=(HBITMAP)LoadImage(hMod,MAKEINTRESOURCE(maskIndex),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION); + if (!bmpMask) + bmpMask=LoadImageResource(hMod,MAKEINTRESOURCE(maskIndex),false,false); + if (!bmpMask) + { + GetErrorMessage(err,_countof(err),GetLastError()); + Sprintf(MenuSkin::s_SkinError,_countof(MenuSkin::s_SkinError),LoadStringEx(IDS_SKIN_ERR_MASKRES),maskIndex,err); + } + } + else + { + wchar_t path[_MAX_PATH]; + GetSkinsPath(path); + wchar_t fname[_MAX_PATH]; + Sprintf(fname,_countof(fname),L"%s%d.bmp",path,maskIndex); + bmpMask=(HBITMAP)LoadImage(NULL,fname,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_LOADFROMFILE); + if (!bmpMask) + { + GetErrorMessage(err,_countof(err),GetLastError()); + Sprintf(MenuSkin::s_SkinError,_countof(MenuSkin::s_SkinError),LoadStringEx(IDS_SKIN_ERR_MASKFILE),fname,err); + } + } + if (!bmpMask) + { + res=bmpMask; + return res; + } + GetObject(bmpMask,sizeof(infoMask),&infoMask); + if (index<0) + { + unsigned int colorRGB=index&0xFFFFFF; + BITMAPINFO bi={0}; + bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth=infoMask.bmWidth; + bi.bmiHeader.biHeight=infoMask.bmHeight; + bi.bmiHeader.biPlanes=1; + bi.bmiHeader.biBitCount=32; + HDC hdc=CreateCompatibleDC(NULL); + unsigned int *bits; + bmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&bits,NULL,0); + if (infoMask.bmBitsPixel==32) + { + unsigned int *ptrMask=(unsigned int*)infoMask.bmBits; + for (int i=infoMask.bmWidth*infoMask.bmHeight-1;i>=0;i--) + bits[i]=colorRGB|(ptrMask[i]&0xFF000000); + } + else + { + for (int i=infoMask.bmWidth*infoMask.bmHeight-1;i>=0;i--) + bits[i]=colorRGB|0xFF000000; + } + DeleteDC(hdc); + } + } + else if (maskIndex<0) + { + infoMask.bmBits=&maskIndex; + } + + BITMAP info; + GetObject(bmp,sizeof(info),&info); + + if (bmpMask && index>0 && (info.bmWidth!=infoMask.bmWidth || info.bmHeight!=infoMask.bmHeight)) + { + Sprintf(MenuSkin::s_SkinError,_countof(MenuSkin::s_SkinError),LoadStringEx(IDS_SKIN_ERR_MASKSIZE),index,maskIndex); + } + + if (maskIndex<0 || (bmpMask && info.bmWidth==infoMask.bmWidth && info.bmHeight==infoMask.bmHeight)) + { + // apply color mask + unsigned char *ptr=(unsigned char*)info.bmBits; + int stride=info.bmBitsPixel/8; + int pad=stride*info.bmWidth; + pad=((pad+3)&~3)-pad; + unsigned char *ptrMask=(unsigned char*)infoMask.bmBits; + int strideMask=infoMask.bmBitsPixel/8; + int padMask=strideMask*info.bmWidth; + padMask=((padMask+3)&~3)-padMask; + + for (int y=0;y>24); + int r=(pixel>>16)&255; + int g=(pixel>>8)&255; + int b=(pixel)&255; + r=(r*a)/255; + g=(g*a)/255; + b=(b*a)/255; + pixel=(a<<24)|(r<<16)|(g<<8)|b; + } + } + return res; +} + +static void MirrorBitmap( HBITMAP bmp ) +{ + BITMAP info; + GetObject(bmp,sizeof(info),&info); + + unsigned char *ptr=(unsigned char*)info.bmBits; + if (!ptr) return; + int stride=info.bmBitsPixel/8; + int pitch=(stride*info.bmWidth+3)&~3; + for (int y=0;y=(int)CustomBitmaps.size()) return true; + id|=0x0F000000; + } + else + { + id=_wtol(str); + if (id<=0) return true; + } + + int id2; + wchar_t name2[256]; + Sprintf(name2,_countof(name2),L"%s_mask",name); + str=parser.FindSetting(name2); + if (!str) + id2=0; + else if (str[0]=='#' || str[0]=='$') + { + LoadSkinNumbers(str,&id2,1,NUMBERS_COLORS_RGB); + id2|=0xFF000000; + } + else if (str[0]=='@') + { + id2=_wtol(str+1); + if (id2<0 || id2>=(int)CustomBitmaps.size()) return true; + id2|=0x0F000000; + } + else + { + id2=_wtol(str); + if (id2<0) id2=0; + } + + if (id2) + { + COLORREF tintColor1, tintColor2, tintColor3; + LoadSkinTintColors(parser,name,tintColor1,tintColor2,tintColor3,backgroundColor); + if (id>0 || id2>0) + { + bitmap=LoadSkinBitmap(hMod,id,id2,tintColor1,tintColor2,tintColor3,bPremultiply); + } + else + { + COLORREF color=((id>>16)&0xFF)|(id&0xFF00)|((id&0xFF)<<16); + COLORREF mask=((id2>>16)&0xFF)|(id2&0xFF00)|((id2&0xFF)<<16); + BlendColor(color,mask,tintColor1,tintColor2,tintColor3); + bitmap=color; + } + } + else if (id>0) + { + bitmap=LoadSkinBitmap(hMod,id,0,0,0,0,bPremultiply); + } + else + { + COLORREF color=((id>>16)&0xFF)|(id&0xFF00)|((id&0xFF)<<16); + bitmap=color; + } + + if (!bitmap.bIsBitmap) + { + if (!bAllowColor) + Sprintf(MenuSkin::s_SkinError,_countof(MenuSkin::s_SkinError),LoadStringEx(IDS_SKIN_ERR_RECBITMAP),name); + return bAllowColor; + } + + if (!bitmap.GetBitmap()) + return false; + if (bMirror) + MirrorBitmap(bitmap.GetBitmap()); + + BITMAP info; + if ((!countX && slicesX) || (!countY && slicesY)) + GetObject(bitmap.GetBitmap(),sizeof(info),&info); + if (countX) + { + Sprintf(name2,_countof(name2),L"%s_slices_X",name); + str=parser.FindSetting(name2); + if (str) + LoadSkinNumbers(str,slicesX,countX,NUMBERS_SLICES); + else + memset(slicesX,0,countX*4); + } + else if (slicesX) + *slicesX=info.bmWidth; + if (countY) + { + Sprintf(name2,_countof(name2),L"%s_slices_Y",name); + str=parser.FindSetting(name2); + if (str) + LoadSkinNumbers(str,slicesY,countY,NUMBERS_SLICES); + else + memset(slicesY,0,countY*4); + } + else if (slicesY) + *slicesY=info.bmHeight; + return true; +} + +bool MenuSkin::LoadSkinBitmap( HMODULE hMod, CSkinParser &parser, const wchar_t *name, MenuBitmap &bitmap, SIZE *size, bool bMirror, bool bPremultiply ) const +{ + int cx, cy; + if (!LoadSkinBackground(hMod,parser,name,bitmap,0,&cx,0,&cy,0,bMirror,false,bPremultiply)) + return false; + if (size) + { + size->cx=cx; + size->cy=cy; + } + return true; +} + +MenuSkin::THAlign MenuSkin::ParseHAlign( const wchar_t *str ) +{ + if (str) + { + if (_wcsicmp(str,L"center1")==0) + return HALIGN_CENTER1; + else if (_wcsicmp(str,L"center2")==0) + return HALIGN_CENTER2; + else if (_wcsicmp(str,L"left")==0) + return HALIGN_LEFT; + else if (_wcsicmp(str,L"left1")==0) + return HALIGN_LEFT1; + else if (_wcsicmp(str,L"left2")==0) + return HALIGN_LEFT2; + else if (_wcsicmp(str,L"right")==0) + return HALIGN_RIGHT; + else if (_wcsicmp(str,L"right1")==0) + return HALIGN_RIGHT1; + else if (_wcsicmp(str,L"right2")==0) + return HALIGN_RIGHT2; + else if (_wcsicmp(str,L"corner")==0) + return HALIGN_CORNER; + else if (_wcsicmp(str,L"none")==0) + return HALIGN_NONE; + } + return HALIGN_CENTER; +} + +MenuSkin::TIconSize MenuSkin::ParseIconSize( const wchar_t *str ) +{ + if (str) + { + if (_wcsicmp(str,L"small")==0) + return ICON_SIZE_SMALL; + else if (_wcsicmp(str,L"large")==0) + return ICON_SIZE_LARGE; + else if (_wcsicmp(str,L"none")==0) + return ICON_SIZE_NONE; + } + return ICON_SIZE_UNDEFINED; +} + +MenuSkin::TVAlign MenuSkin::ParseVAlign( const wchar_t *str ) +{ + if (str) + { + if (_wcsicmp(str,L"top")==0) + return VALIGN_TOP; + else if (_wcsicmp(str,L"bottom")==0) + return VALIGN_BOTTOM; + else if (_wcsicmp(str,L"corner")==0) + return VALIGN_CORNER; + else if (_wcsicmp(str,L"none")==0) + return VALIGN_NONE; + } + return VALIGN_CENTER; +} + +bool MenuSkin::LoadSkinItem( HMODULE hMod, CSkinParser &parser, const wchar_t *name, MenuSkin::ItemDrawSettings &settings, MenuSkin::ItemDrawSettings *pDefaults, COLORREF backgroundColor, bool bRTL ) const +{ + wchar_t name2[256]; + const wchar_t *str; + Sprintf(name2,_countof(name2),L"%s_font",name); + str=parser.FindSetting(name2); + if (str) + { + settings.font=LoadSkinFont(str,NULL,0,0,true); + settings.bOwnFont=true; + } + else if (pDefaults) + { + settings.font=pDefaults->font; + settings.bOwnFont=false; + } + else + { + settings.font=LoadSkinFont(NULL,NULL,0,0,true); + settings.bOwnFont=true; + } + + Sprintf(name2,_countof(name2),L"%s_glow_size",name); + str=parser.FindSetting(name2); + if (str) + settings.glowSize=_wtol(str); + else if (pDefaults) + settings.glowSize=pDefaults->glowSize; + else + settings.glowSize=0; + + Sprintf(name2,_countof(name2),L"%s_text_color",name); + if (LoadSkinColors(parser,name2,settings.textColors,_countof(settings.textColors),backgroundColor)) + {} + else if (pDefaults) + memcpy(settings.textColors,pDefaults->textColors,sizeof(settings.textColors)); + else + { + settings.textColors[0]=GetSysColor(COLOR_MENUTEXT); + settings.textColors[1]=GetSysColor(COLOR_HIGHLIGHTTEXT); + settings.textColors[2]=GetSysColor(COLOR_GRAYTEXT); + settings.textColors[3]=GetSysColor(COLOR_HIGHLIGHTTEXT); + } + Sprintf(name2,_countof(name2),L"%s_text_shadow_color",name); + str=parser.FindSetting(name2); + if (str && wcscmp(str,L"none")==0) + memset(settings.textShadowColors,-1,sizeof(settings.textShadowColors)); + else if (LoadSkinColors(parser,name2,settings.textShadowColors,_countof(settings.textShadowColors),backgroundColor)) + {} + else if (pDefaults) + memcpy(settings.textShadowColors,pDefaults->textShadowColors,sizeof(settings.textShadowColors)); + else + memset(settings.textShadowColors,-1,sizeof(settings.textShadowColors)); + + Sprintf(name2,_countof(name2),L"%s_text_padding",name); + str=parser.FindSetting(name2); + if (str) + LoadSkinNumbers(str,(int*)&settings.textPadding,4,NUMBERS_PADDING); + else if (pDefaults) + settings.textPadding=pDefaults->textPadding; + else + settings.textPadding=ScaleSkinElement(DEFAULT_TEXT_PADDING); + + Sprintf(name2,_countof(name2),L"%s_icon_padding",name); + str=parser.FindSetting(name2); + if (str) + LoadSkinNumbers(str,(int*)&settings.iconPadding,4,NUMBERS_PADDING); + else if (pDefaults) + settings.iconPadding=pDefaults->iconPadding; + else + settings.iconPadding=ScaleSkinElement(DEFAULT_ICON_PADDING); + + Sprintf(name2,_countof(name2),L"%s_arrow_color",name); + if (LoadSkinColors(parser,name2,settings.arrColors,_countof(settings.arrColors),backgroundColor)) + {} + else if (pDefaults) + memcpy(settings.arrColors,pDefaults->arrColors,sizeof(settings.arrColors)); + else + { + settings.arrColors[0]=settings.textColors[0]; + settings.arrColors[1]=settings.textColors[1]; + } + + Sprintf(name2,_countof(name2),L"%s_selection",name); + str=parser.FindSetting(name2); + if (str) + { + if (!LoadSkinBackground(hMod,parser,name2,settings.bmpSelection,backgroundColor,settings.selSlicesX,_countof(settings.selSlicesX),settings.selSlicesY,_countof(settings.selSlicesY),bRTL,true)) + return false; + } + else if (pDefaults) + { + settings.bmpSelection=pDefaults->bmpSelection; + settings.bmpSelection.bIsOwned=false; + memcpy(settings.selSlicesX,pDefaults->selSlicesX,sizeof(settings.selSlicesX)); + memcpy(settings.selSlicesY,pDefaults->selSlicesY,sizeof(settings.selSlicesY)); + } + else + { + settings.bmpSelection=GetSysColor(COLOR_HIGHLIGHT); + } + + { + const POINT *sizes=GetArrowsBitmapSizes(); + settings.arrSize.cx=sizes[3].y-sizes[3].x; + settings.arrSize.cy=sizes[6].y; + } + Sprintf(name2,_countof(name2),L"%s_arrow",name); + str=parser.FindSetting(name2); + if (str && wcscmp(str,L"0")==0) + {} + else if (str) + { + if (!LoadSkinBitmap(hMod,parser,name2,settings.bmpArrow,&settings.arrSize,bRTL)) + return false; + settings.arrSize.cy/=2; + } + else if (pDefaults) + { + settings.bmpArrow=pDefaults->bmpArrow; + settings.bmpArrow.bIsOwned=false; + settings.arrSize=pDefaults->arrSize; + } + + Sprintf(name2,_countof(name2),L"%s_arrow_padding",name); + str=parser.FindSetting(name2); + if (str) + LoadSkinNumbers(str,(int*)&settings.arrPadding,2,NUMBERS_PADDING); + else if (pDefaults) + settings.arrPadding=pDefaults->arrPadding; + else + settings.arrPadding=ScaleSkinElement(DEFAULT_ARROW_PADDING); + + Sprintf(name2,_countof(name2),L"%s_icon_frame",name); + str=parser.FindSetting(name2); + if (str) + { + if (!LoadSkinBackground(hMod,parser,name2,settings.bmpIconFrame,backgroundColor,settings.frameSlicesX,_countof(settings.frameSlicesX),settings.frameSlicesY,_countof(settings.frameSlicesY),bRTL)) + return false; + + if (settings.bmpIconFrame.GetBitmap()) + { + Sprintf(name2,_countof(name2),L"%s_icon_frame_offset",name); + str=parser.FindSetting(name2); + if (str) + LoadSkinNumbers(str,(int*)&settings.iconFrameOffset,2,NUMBERS_PADDING); + else + memset(&settings.iconFrameOffset,0,sizeof(settings.iconFrameOffset)); + } + } + else if (pDefaults) + { + settings.bmpIconFrame=pDefaults->bmpIconFrame; + settings.bmpIconFrame.bIsOwned=false; + memcpy(settings.frameSlicesX,pDefaults->frameSlicesX,sizeof(settings.frameSlicesX)); + memcpy(settings.frameSlicesY,pDefaults->frameSlicesY,sizeof(settings.frameSlicesY)); + settings.iconFrameOffset=pDefaults->iconFrameOffset; + } + + return true; +} + +void MenuSkin::ParseOptionsString( const wchar_t *optionsStr, std::map &options ) const +{ + options.clear(); + wchar_t text[1024]; + const wchar_t *str=optionsStr; + while (*str) + { + str=GetToken(str,text,_countof(text),L"\n"); + wchar_t token[256]; + const wchar_t *val=GetToken(text,token,_countof(token),L"="); + if (*token) + options[token]=val; + } + + if (wcschr(optionsStr,'|')) + { + // backwards compatibility for old-style settings + const wchar_t *end=wcschr(optionsStr,'\n'); + if (end && wcschr(end+1,'\n')) + return; // multiple lines + for (std::vector