Using Hidden Security Icons in Taskdialog - c#

I am trying to display a Security Success Icon (with the blue background) in TaskDialog message box. This is not one of the enum values of TaskDialogStandardIcon. Reference: http://dotnet.dzone.com/articles/using-new-taskdialog-winapi.
How do I assign these non standard values to ((TaskDialog)sender).Icon ? Is it even possible in C#? C#
Any pointers would be really helpful.
Regards,
Ashwin

I think you will need to import TaskDialog function from comctl32.dll yourself:
static class TaskDialogWrapper
{
[DllImport("comctl32.dll", CharSet = CharSet.Unicode, EntryPoint = "TaskDialog")]
static extern int TaskDialog(IntPtr hWnd, IntPtr hInstance, string pszWindowTitle, string pszMainInstruction, string pszContent, TaskDialogCommonButton dwCommonButtons, IntPtr pszIcon, out IntPtr pnButton);
public static TaskDialogCommonButton Show(IntPtr handle, IntPtr instance, string title, string instructionText, string content, TaskDialogCommonButton commonButtons, TaskDialogCommonIcon commonIcon)
{
IntPtr resultButton;
if (TaskDialog(handle, instance, title, instructionText, content, commonButtons, new IntPtr((int)commonIcon), out resultButton) != 0)
throw new InvalidOperationException();
return (TaskDialogCommonButton)resultButton;
}
}
[Flags()]
enum TaskDialogCommonButton
{
Ok = 0x1,
Yes = 0x2,
No = 0x4,
Cancel = 0x8,
Retry = 0x10,
Close = 0x20
}
enum TaskDialogCommonIcon
{
ShieldGrey = 65527,
ShieldOk = 65528,
ShieldError = 65529,
ShieldWarning = 65530,
ShieldBlue = 65531,
Shield = 65532,
Information = 65533,
Error = 65534,
Warning = 65535,
}
To use your own icon from a file, you will need to import TaskDialogIndirect.
(Btw., I found many other interesting icon styles for TaskDialogCommonIcon. You could add e.g.:
enum TaskDialogCommonIcon
{
None = 0,
Sheet = 2,
ExplorerFolderOpen = 3,
ExplorerFolderFlat = 5,
ExplorerFolderLeft = 6,
Search = 8,
ExplorerFolderClosed = 10,
ExplorerGames = 14,
Application = 15,
TransparentSpace = 17,
ExplorerSearch = 18,
TextFile = 19,
Letter = 20,
Picture = 21,
Diashow = 103,
// ...
}

I know that this is an old question, but I was looking for something similar, so I thought I'd pass along what I've found. Using the information posted by #KnorxThieus, I found a way to use the "hidden" security icons in the TaskDialog without going through the DLLImport process outlined above. Using the actual values he provided for the TaskDialogCommonIcon enumeration, I found that you can simply cast them to the appropriate type (i.e., the TaskDialogCommonIcon), and your application should display them properly.
Please note, I'm using the WindowsAPICodePack version 1.1.2 from Nuget (nuget.org/packages/WindowsAPICodePack-Core), and the code below has been converted from Visual Basic using the Telerik Code Converter (http://converter.telerik.com/), so it's possible that you may have to do some fine-tuning in C#:
if (TaskDialog.IsPlatformSupported) {
using (TaskDialog dialog = new TaskDialog()) {
dialog.Caption = "TESTING";
dialog.InstructionText = "THIS IS A TEST";
dialog.Text = "This is a test of casting a value to the desired Icon type for a TaskDialog.";
// Produces the green shield with green background
dialog.Icon = (TaskDialogStandardIcon)65528;
dialog.OwnerWindowHandle = this.Handle;
dialog.Show();
}
}
In my testing, this seems to work for all of the enumerations #KnorxThieus listed, as well as several others. I'm trying to figure out if there's a similar method for setting the Icon property to another (non-standard) image file, but I've been unsuccessful with that so far. I hope this helps anyone that stumbles across this in the future.

Take a look at the Ookii.Dialogs. It implements the TaskDialog and others dialogs as well, and have versions targeting WPF and Windows Forms.

Related

InsertMenuItem cutting off the string to first char

I am trying to modify window's system menu using InsertMenuItem (instead of InsertMenu - the reason is that I want to insert submenus eventually). Language is C#.
Tried inserting a new item, tried getting existing item and reinserting it, it inserts, but the item string is shown in the menu only as the first character. Anyone have a clue about what I am missing?
// try creating one from scratch
MENUITEMINFO it = new MENUITEMINFO();
it.cbSize = (uint)Marshal.SizeOf(it);
it.fMask = 64;// MIIM_STRING
it.wID = 12345;
it.dwTypeData = "Now is the time";
it.fType = 0;
it.cch = 0;
InsertMenuItem(hSysMenu, 7, true, ref it);
//try copying one
GetMenuItemInfo(hSysMenu, (uint)0, true, ref it);
it.cch += 10;
it.dwTypeData = new string(' ', (int)(menuItemInfo.cch+10));
GetMenuItemInfo(hSysMenu, (uint)0, true, ref it);
it.wID = 123456;
var err = InsertMenuItem(hSysMenu, 1, true, ref it);
The result of the above code
Ok I finally figured it out. I will leave this here so maybe someone else later will find it when they are baffled by this.
The reason was that the InsertMenuItem p/invoke was defined with
[DllImport("user32.dll")] in the pinvoke.net site - see https://www.pinvoke.net/default.aspx/user32/insertmenu.html?diff=y
and it needs to be
[DllImport("user32.dll", CharSet = CharSet.Auto) ]
I changed the pinvoke.net page to reflect it.

Can anyone explain the major features of a VDPROJ file?

I'm sure there must be some documentation on MSDN somewhere, but I couldn't find it. It looks like some subset/variation of JSON. Really, this question grew out of something that has always bugged me: what do all the 8:s and 3:s mean? Is this some a version number of some kind? Maybe a typing scheme? Every VDPROJ excerpt I've ever seen is filled with these "eight-colon" and "three-colon" prefixes, but this is not the sort of question search engines are really good for.
"DeployProject"
{
"VSVersion" = "3:800"
"ProjectType" = "8:{978C614F-708E-4E1A-B201-565925725DBA}"
"IsWebType" = "8:FALSE"
"ProjectName" = "8:ProjectNameRedacted"
"LanguageId" = "3:1033"
"CodePage" = "3:1252"
"UILanguageId" = "3:1033"
"SccProjectName" = "8:"
"SccLocalPath" = "8:"
"SccAuxPath" = "8:"
"SccProvider" = "8:"
"Hierarchy"
{
"Entry"
{
"MsmKey" = "8:_02F97BB7BD104F1AAA1C97C854D5DC99"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
...
If anyone just wants to berate my pitiful Google-fu, that's fine too.
As #R. Matveev pointed out, the prefix numbers likely indicate the type of data stored in the property. This would be useful when deserializing the file into an object structure.
I doubt the source code which Visual Studio used to read/write the files was ever made open source, so it's no wonder that web searches returned nothing.
The best I could find was this page on OLE Automation data types, which may not have been the actual constants, but the data types seem to match the values in the *.vdproj file.
2.2.7 VARIANT Type Constants
typedef enum tagVARENUM
{
VT_EMPTY = 0x0000,
VT_NULL = 0x0001,
VT_I2 = 0x0002,
VT_I4 = 0x0003, // 4-byte signed integer
VT_R4 = 0x0004,
VT_R8 = 0x0005,
VT_CY = 0x0006,
VT_DATE = 0x0007,
VT_BSTR = 0x0008, // BSTR (string data)
VT_DISPATCH = 0x0009,
VT_ERROR = 0x000A,
VT_BOOL = 0x000B, // Boolean value
VT_VARIANT = 0x000C,
VT_UNKNOWN = 0x000D
...
} VARENUM;

How to use Shell32 within a C# application?

What should I include within a C# application in order to make Shell32 work?
Edit:
My application can't recognize shell32. What references or lib should I include? What I'm trying to do is:
Shell32.Shell shell = new Shell32.Shell();
What I'm getting as an error:
Error 1 The type or namespace name 'Shell32' could not be found (are you missing a using directive or an assembly reference?)
Just add a reference to Shell32.dll from the Windows\System32 folder and use it:
Shell32.Shell shell = new Shell32.Shell();
shell.MinimizeAll();
maybe this can help:
Right click project
Click Add reference
Click .COM tab in Add reference dialogue
Select Microsoft Shell Controls and Automation
Click OK
your shell32 is ready to use...
I know this thread is old, but I post this for anyone having the same problem as I did. The solution above does not compile under windows 8
Shell32.Shell shell = new Shell32.Shell(); <= this doesn't work with windows 8
Use the work around below if you want your apps to run under windows 8.
using Shell32;
private Shell32.Folder GetShell32Folder(string folderPath)
{
Type shellAppType = Type.GetTypeFromProgID("Shell.Application");
Object shell = Activator.CreateInstance(shellAppType);
return (Shell32.Folder)shellAppType.InvokeMember("NameSpace",
System.Reflection.BindingFlags.InvokeMethod, null, shell, new object[] { folderPath });
}
Right click your project in the solution explorer.
Choose "Add Reference..." from the drop-down menu.
Click the "Browse" tab.
Navigate to the C:\Windows\System32 directory.
Choose the shell32.dll file. and press the "OK" button.
You now have the appropriate reference for using Shell32.Shell.
Add to your project a reference to the COM library Microsoft Shell Controls and Automation. Additionally, ensure that the code using Shell32.Shell is running in a single threaded apartment, e.g. by adding the [STAThread] attribute to Main.
I'm guessing that you're having trouble getting any calls recognized, so I'd refer you to this general article: http://www.codeproject.com/KB/shell/csdoesshell1.aspx
Beyond that, you'll need to provide specifics of what isn't working for you.
The class shown below should help with some of the methods of shell32 in C# .
you should add the reference of "Microsoft Shell command and automation" with the reference window by righting clicking the project .
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MusicMuttPrototype
{
public class clsShellFileInfo
{
public Exception errorException;
public enum FileDetailInfo
{
Name = 0,
Year = 15,
Size = 1,
Track_Number = 19,
Type = 2,
Genre = 20,
Date_Modified = 3,
Duration = 27,
Date_Created = 4,
Bit_Rate = 28,
Date_Accessed = 5,
Protected = 23,
Attributes = 6,
Camera_Model = 24,
Status = 7,
Date_Picture_Taken = 25,
Owner = 8,
Dimensions = 26,
Author = 9,
Not_used = 27,
Title = 10,
Not_used_file = 28,
Subject = 11,
//Not_used = 29,
Category = 12,
Company = 30,
Pages = 13,
Description = 31,
Comments = 14,
File_Version = 32,
Copyright = 15,
Product_Name_Chapter = 33,
//Scripting Quicktest Profess11ional Page 63
Artist = 16,
Product_Version = 34,
Album_Title = 17,
Retrieves_the_info_tip_inf = -1
}
public string getFileDetails(string fileFolder, string filePath, FileDetailInfo infotype)
{
string strReturnval = "";
try
{
Shell32.Shell fileshell = new Shell32.Shell();
Shell32.Folder fileshellfolder = fileshell.NameSpace(fileFolder);
Shell32.FolderItem Item = fileshellfolder.ParseName(filePath);
strReturnval = fileshellfolder.GetDetailsOf(Item, (int)infotype);
}
catch (Exception ex)
{
errorException = ex;
}
return strReturnval;
}
}
}
If you don't need the full set of API calls, you maybe better off creating a COM import stub class. See how Mike Ward who wrote Desk Drive did it.
Link 1
Link 2
C# .Net
I do not understand the full question but this is working for me.
[DllImport("Shell32.dll")]
public static extern int ShellExecuteA(int hwnd, string lpOperation, string lpFile, int lpParameters, int lpDirecotry, int nShowCmd);
private void pictureBox1_Click(object sender, EventArgs e)
{
int open;
open = ShellExecuteA(0, "open", "https://google.com", 0, 0, 1);
}
Using a picturebox to open a link.

System.Windows.MessageBox vs System.Windows.Forms.MessageBox

I am having trouble finding out what the key differences are between the two message boxes. What is the difference between System.Windows.MessageBox and System.Windows.Forms.MessageBox?
System.Windows.MessageBox was added with WPF, and exists within the WPF assemblies (PresentationFramework.dll).
System.Windows.Forms.MessageBox was added with Windows Forms, and exists within the Windows Forms assemblies.
If your program is a Windows Forms program, I would use the latter (System.Windows.Forms.MessageBox), as it won't pull in a dependency on WPF. On the other hand, if you are developing for WPF, I'd use System.Windows.MessageBox.
One additional point should be noted:
If you want to display a message box in an application that is neither a windows forms application or a forms application (such as a .NET console application), you should not drag in assembly references for either as seems to be the common mantra all over the internet.
Instead, you should use pinvoke and call into User32 as follows:
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern MessageBoxResult MessageBox(IntPtr hWnd, String text, String caption, int options);
/// <summary>
/// Flags that define appearance and behaviour of a standard message box displayed by a call to the MessageBox function.
/// </summary>
[Flags]
public enum MessageBoxOptions : uint
{
Ok = 0x000000,
OkCancel = 0x000001,
AbortRetryIgnore = 0x000002,
YesNoCancel = 0x000003,
YesNo = 0x000004,
RetryCancel = 0x000005,
CancelTryContinue = 0x000006,
IconHand = 0x000010,
IconQuestion = 0x000020,
IconExclamation = 0x000030,
IconAsterisk = 0x000040,
UserIcon = 0x000080,
IconWarning = IconExclamation,
IconError = IconHand,
IconInformation = IconAsterisk,
IconStop = IconHand,
DefButton1 = 0x000000,
DefButton2 = 0x000100,
DefButton3 = 0x000200,
DefButton4 = 0x000300,
ApplicationModal = 0x000000,
SystemModal = 0x001000,
TaskModal = 0x002000,
Help = 0x004000, //Help Button
NoFocus = 0x008000,
SetForeground = 0x010000,
DefaultDesktopOnly = 0x020000,
Topmost = 0x040000,
Right = 0x080000,
RTLReading = 0x100000,
}
/// <summary>
/// Represents possible values returned by the MessageBox function.
/// </summary>
public enum MessageBoxResult : uint
{
Ok = 1,
Cancel,
Abort,
Retry,
Ignore,
Yes,
No,
Close,
Help,
TryAgain,
Continue,
Timeout = 32000
}
var result = User32.MessageBox(IntPtr.Zero, "Debugging Break", "Your Console Application", (int)User32.MessageBoxOptions.Ok);
Both eventually call the same low level windows API as far as I know...
The both basically do the same thing, except system.windows.messagebox is WPF and system.windows.forms.messagebox is Windows Forms. If you're using WPF use the former, for WinForms use the latter.

How to get current Windows theme name?

I am trying to get the current Windows theme name in C# but it has turned out to be a little tougher than expected. I have a code sample from MSDN:
public void Test()
{
StringBuilder themeFileName = new StringBuilder(0x200);
GetCurrentThemeName(themeFileName, themeFileName.Capacity, null, 0, null, 0);
string fileName = Path.GetFileName(VisualStyleInformation.ThemeFilename);
if (string.Equals("aero.msstyles", fileName, StringComparison.OrdinalIgnoreCase))
{
// user is using aero theme
}
}
[DllImport("uxtheme.dll", CharSet = CharSet.Auto)]
public static extern int GetCurrentThemeName(StringBuilder pszThemeFileName, int
dwMaxNameChars, StringBuilder pszColorBuff, int dwMaxColorChars,
StringBuilder pszSizeBuff, int cchMaxSizeChars);
GetCurrentTheme() does not modify the StringBuilder. I also tried looking at the
System.Windows.Forms.VisualStyles.VisualStyleInformation class, but it is full of empty values. Anyone know how to do this? I must be missing something easy, but I haven't found anything yet that works.
That article on CodeProject describes how to get "the current visual style information" (search for that string in the article).
It contains sample code how to do that.
You are not passing the string builder by reference.

Categories