How to 'Refresh' the Vista start menu programmatically - c#

I am working on a piece of code that removes an extra folder we have in the user's start menu. I start by removing all of the shortcuts it contains, and then remove the folder itself.
After this is done, I can confirm that the shortcuts have been removed from the start menu, but their containing folder remains listed in the start menu. So, I checked the file system for such a folder and found none. Suspecting that this is some sort of refresh problem, I logged my user out and back into Vista and found that the folder was now removed from the start menu list.
How utterly annoying... Does anyone know how to programmatically force a 'refresh' of the Vista start menu, so that the user doesn't see this empty folder before they log out?
Thanks,
-Ben

I tried to implement this myself but it did not work as expected using SendMessageTimeout.
Instead, it worked when I used
SHGetSpecialFolderLocation(CSIDL_STARTMENU)
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidl, NULL);
See this article for sample c++ code:
http://support.microsoft.com/kb/q193293/
Tested on Windows Server 2008 Enterprise (x86) with SP1.

This article seems to have the answer you're looking for:
http://social.msdn.microsoft.com/forums/en-US/winforms/thread/ce540c7d-a113-4f39-956e-0af6bc91abd3/
The answer given is:
class Program
{
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SendMessageTimeout ( IntPtr hWnd, int Msg, IntPtr wParam, string lParam, uint fuFlags, uint uTimeout, IntPtr lpdwResult );
private static readonly IntPtr HWND_BROADCAST = new IntPtr(0xffff);
private const int WM_SETTINGCHANGE = 0x1a;
private const int SMTO_ABORTIFHUNG = 0x0002;
static void Main ( string[] args )
{
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, null, SMTO_ABORTIFHUNG, 100, IntPtr.Zero);
}
}

Related

Use fixed version of Internet Explorer in the webbrowser despite FEATURE_BROWSER_EMULATION

C#. Can I say to the webbrowser in my winform application - use only IE7 (IE8-IE11, Edge) version regardless of the property FEATURE_BROWSER_EMULATION value in the registry?
I try to find any information about this, but find only manipulation with FEATURE_BROWSER_EMULATION value in the registry.
I think, that I must to use this function:
[DllImport("wininet.dll", SetLastError = true)]
private static extern bool InternetSetOption(
IntPtr hInternet,
int dwOption,
IntPtr lpBuffer,
int lpdwBufferLength);
but don't find any info.
Thanks!

Change system default language programmatically with c#

We have a virtual keyboard (for touch screen) which its language layout is configured via the windows default language.
I have seen numerous answers which involves InputLanguageManager and CultureInfo.
They're not useful to me, didn't do the job.
There is this one method - SystemParametersInfo function with the SPI_SETDEFAULTINPUTLANG flag that i'm trying to check.
So far, didn't find any useful usage examples besides this one here, but it changes the keyboard layout from Dvorak to Marshal.
Can you give me an example (hopefully with the SystemParametersInfo) that converts the default system language to en-US?
Edit
A brief clarification.
This program replaces the explorer as windows shell, hence all keyboard settings such as setting default keyboard layout should be handled from my program.
Moreover, my wish is to replace between different installed languages such as English, Swedish, Portuguese and so on..
I don't want to change between Dvorak and Qwerty layout of the keyboard.
The purpose of this post is to ask for examples for changing between different languages and not for layout of English symbols on keyboard.
Thanks!
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref uint pvParam, uint fWinIni);
public void Foo()
{
uint localeUS = 0x00000409;
uint localeNL = 0x00000403;
SetSystemDefaultInputLanguage(localeUS);
}
public bool SetSystemDefaultInputLanguage(uint locale)
{
return SystemParametersInfo(SPI_SETDEFAULTINPUTLANG, 0, ref locale, 0);
}
public uint GetSystemDefaultInputLanguage()
{
uint result = uint.MinValue;
bool retVal = SystemParametersInfo(SPI_GETDEFAULTINPUTLANG, 0, ref result, 0);
return result;
}
This seems to work fine for me.
Sources:
SystemParametersInfo API
SystemParametersInfo Parameter Definition
Input Locales List MSDN

Changing windows settings with a script

I have a problem that every once in a while the amount of lines or w\e that moves when I turn the mouse wheel goes from 3 to 30 and my brother sometimes sees it changes to 100.
What I'm talking about is when you go to "Control Panel" -> "Mouse" -> and then the mouse-wheel tab, it has 2 number-scrollers, and I need to change the value of the first one with a script or .exe or whatever way you know how to change it with.
For whoever might encounter that problem and wants the solution, here's the code:
[DllImport("user32.dll", SetLastError = true)]
static extern bool SystemParametersInfo(int uiAction, int uiParam, IntPtr pvParam, int fWinIni);
static void Main(string[] args)
{
const int SPI_SETWHEELSCROLLLINES = 0x0069;
const int SPIF_UPDATEINIFILE = 0x01;
const int SPIF_SENDCHANGE = 0x02;
SystemParametersInfo(SPI_SETWHEELSCROLLLINES, 3, IntPtr.Zero,
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
}
Thanks for helping!
System parameters are not to be changed via registry keys, because (1) that's an implementation detail, that may change in future versions of Windows or even depending on other user profile settings and (2) because you are updating just the saved value, not the one that is currently active.
The correct way to go is to use the SystemParametersInfo API specifying the correct parameter constant (in your case, SPI_SETWHEELSCROLLLINES) and SPIF_UPDATEINIFILE | SPIF_SENDCHANGE as last parameter to both activate it right now and save it for the next sessions.
With regedit you can setup a script that sets the mouse wheeel scrolling speed, property is here:
HKEY_CURRENT_USER\Control Panel\Desktop\WheelScrollLines
just browse regedit (win+R regedit) look at the WeelScrollLines value, then create a reg file as specified by microsoft : https://support.microsoft.com/en-us/kb/310516#bookmark-syntax

code to open windows explorer (or focus if exists) with file selected

My goal is to write a C# code that will open a Windows Explorer window, with a particular file selected. If such window is already open, I want to bring it to front. I have tried two options.
First, I start by explicitly calling explorer.exe:
arg = "/select, " + pathToFile;
Process.Start("explorer.exe", arg);
This opens and selects a window fine, but the problem is that it will always open a new window, even if one exists. So I tried this:
Process.Start(pathToDir);
This either opens a new window or focuses an old one, but gives me no option to select a file.
What can I do? I looked at explorer's arguments and I don't see anything I can use. A last-resort option I can come up with is to get the list of already open windows and use some WINAPI-level code to handle it, but that seems like an overkill.
I don't know if it's possible using process start, but the following code opens the Windows explorer on the containing folder only if needed (if the folder is already open, or selected on another file, it's reused) and selects the desired file.
It's using p/invoke interop code on the SHOpenFolderAndSelectItems function:
public static void OpenFolderAndSelectFile(string filePath)
{
if (filePath == null)
throw new ArgumentNullException("filePath");
IntPtr pidl = ILCreateFromPathW(filePath);
SHOpenFolderAndSelectItems(pidl, 0, IntPtr.Zero, 0);
ILFree(pidl);
}
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr ILCreateFromPathW(string pszPath);
[DllImport("shell32.dll")]
private static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, int cild, IntPtr apidl, int dwFlags);
[DllImport("shell32.dll")]
private static extern void ILFree(IntPtr pidl);

How to get the total number of items on the (logical) desktop (C#)

Let me elaborate. By "items" I mean all the items you see one the desktop (Windows) which includes "My Computer", "Recycle Bin", all the shortcuts etc. If I select all the items on the desktop I get the count in the properties displayed. It is this count I want, programmatically.
The problem I face:
The desktop as we see has items from my account, also the All Users's desktop items and also other shortcuts like "My Computer", "Recycle Bin". In total, 3 things. So I can't just get the item count from the physical path to Desktop directory. So this fails:
int count =
Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder
.DesktopDirectory)
).Length;
I know SpecialFolder.Desktop stands for the logical desktop as we see. But this fails again since GetFolderPath() again gets the physical path of user's desktop:
int count =
Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder
.Desktop)
).Length;
What is the right way to get total count on the user's desktop?
The Windows shell has full and comprehensive support for this.
Call SHGetDesktopFolder() to get an IShellFolder for the desktop.
Call IShellFolder::EnumObjects() to get the contents.
This Code Project article gives some usage examples from a C# perspective.
This is just not possible in a way you want it.
You probably forgot that there are elements on any desktop, which is not file-related (files, or links) but rather a registry-based, and you will miss them definetely.
I'm answering for myself the answer I finally found out with the help of tips and links posted here.
private const uint GET_ITEM_COUNT = 0x1000 + 4;
[DllImport("user32.DLL")]
private static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
[DllImport("user32.DLL")]
private static extern IntPtr FindWindow(string lpszClass, string lpszWindow);
[DllImport("user32.DLL")]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter,
string lpszClass, string lpszWindow);
public static int GetDesktopCount()
{
//Get the handle of the desktop listview
IntPtr vHandle = FindWindow("Progman", "Program Manager");
vHandle = FindWindowEx(vHandle, IntPtr.Zero, "SHELLDLL_DefView", null);
vHandle = FindWindowEx(vHandle, IntPtr.Zero, "SysListView32", "FolderView");
//Get total count of the icons on the desktop
int vItemCount = SendMessage(vHandle, GET_ITEM_COUNT, 0, 0);
return vItemCount;
}
There's an interesting (rather annoying!) thing I came to learn meanwhile. The desktop you see on your screen is different from the desktop's folder view. Even if you uncheck My Computer and MyDocument from being on desktop (the desktop you see on monitor), these icons can be still there in the folder view of the desktop. I tried the solution given in this link, but it gives the count of items present in the folder view. The solution I posted above would yield the perfect result I want. The solution was got from here, by Zhi-Xin Ye. Thanks #C.Evenhuis for the tip.

Categories

Resources