WM_APPCOMMAND to control Volume & Mute using C# - c#

I have the below code working in my C# program to control system VOLUME _UP _DOWN _MUTE, etc.
I do this using WM_APPCOMMAND messages; however, (and this is a BIG however) I am wondering if it ONLY works because I use a Keyboard with HOTKEYS, i.e.(browser, power, media player, email, etc.) the buttons at the top of the keyboard above the Function Keys.
I would like to know if my code will work on Laptops and PCs whose keyboards are not equipped with HOTKEYS?
From researching I see that this WM_APPCOMMAND stuff goes all the way back to 2001 in some message threads, so I suspect it is pretty stable on XP, Vista and now Windows 7 & 8. And it does not appear to be deprecated as companies like Logitech and other keyboard/media console manufacturers still use it for new products.
I just need to if it works for keyboards without HOTKEYS.
Thanks!
Anthony
private const uint APPCOMMAND_VOLUME_MUTE = 8;
private const uint APPCOMMAND_VOLUME_DOWN = 9;
private const uint APPCOMMAND_VOLUME_UP = 10;
[DllImport("user32.dll")]
public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
//APPCOMMAND_VOLUME_DOWN
SendMessageW(this.Handle, WmAppcommand, this.Handle, (IntPtr)APPCOMMAND_VOLUME_DOWN);
//APPCOMMAND_VOLUME_UP
SendMessageW(this.Handle, WmAppcommand, this.Handle, (IntPtr)APPCOMMAND_VOLUME_UP);

Related

Send Mouse Clicks to a Minimized C# Application using The Same App

There're a lot of ways to simulate a mouse click in an inactive window. I want my program to make clicks even when it's minimized and of course without capturing the main mouse.
Specifically, my C# program will contain a Web Control displaying some flash content and this is where I want the clicks to occur.
here's the techniques I tried:
1.[DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
2.[DllImport("user32.dll", SetLastError = true)]
public static extern bool SendMessage(int hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
Both of them did not do any good in my case. Surprisingly, I was able to use the SendMessage() function to send mouse clicks in a minimized chrome displaying some flash content. but, it doesn't seem to do that in my C# program. Is there a possibility that my program not receiving the message for some reason?
Any Hints on how can I do this?

How do I use these PostMessage Lparam and Wparam's?

I'm really struggling to understand how PostMessage works. I'm from a web dev background so its all very foreign to me. I'm trying to send a single "a" charcter to a third party application. I've used spy++ to get the PostMessage (params below) required but I cant make sense of how to use the Lparam and Wparam.
This is what I have so far. I'm assuming 00000041 (and the others from spy++) is actually hexadecimal and I'm correct in putting 0x in font of it?
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const Int32 WM_CHAR = 0x0102;
PostMessage(WindowHandle, WM_KEYDOWN, (IntPtr)(0x00000041), (IntPtr)(0x001E0001));
PostMessage(WindowHandle, WM_CHAR, (IntPtr)(0x00000061), (IntPtr)(0x001E0001));
PostMessage(WindowHandle, WM_KEYUP, (IntPtr)(0x00000041), (IntPtr)(0xC01E0001));
That gives me an algorithmic overflow...
And before anyone tells me to use sendinput this is for a window not in focus :-p
You don't send WM_CHAR, WM_CHAR is synthesized by the application in TranslateMessage - i.e. the application posts it to itself. Either send only the WM_CHAR, or send only WM_KEYDOWN and WM_KEYUP. If sending KEYUP you need to have a delay to allow the application to synthesize the WM_CHAR before you send the KEYDOWN, or they will be processed out of order. Even then you will have a problem with the async key state. However the long and short of it is: You can't synthesize keyboard input using PostMessage.
Here's some background reading:
https://blogs.msdn.microsoft.com/oldnewthing/20130531-00/?p=4203/
https://blogs.msdn.microsoft.com/oldnewthing/20130530-00/?p=4213/
https://msdn.microsoft.com/en-us/library/windows/desktop/ms646276(v=vs.85).aspx
Your best bet is probably to put the application to the foreground and use SendInput.

Are there any dangers of using Windows API calls in C#

I want to watermark a textbox, and found several different ways of doing it, but one that I liked uses SendMessage and an external DLL. However, I think I heard somewhere that doing it this way can cause BSOD since it isn't managed. Is this true, or is it just hear-say.
http://vidmar.net/weblog/archive/2008/11/05/watermarked-textbox-in-windows-forms-on-.net.aspx
private const uint ECM_FIRST = 0x1500;
private const uint EM_SETCUEBANNER = ECM_FIRST + 1;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, uint wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);
The short answer is no. It won't cause a BSOD, although it could crash your program.
WinForms is basically built on top of Windows API calls, so when done right, custom API calls should work good as well.
One other thing to keep in mind is that if you do call the Windows API, it may create portability issues, such as when porting to Mono, as those DLLs will most likely not be available.

c# What are these volume changing codes/messages

I found this script to change the System sound volume and it works. But what are these constant volume codes called and where can I find a full list of these codes that do more things.
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
//Volume codes, or messages, or whatever they are called
const int VOLUME_MUTE = 0x80000;
const int VOLUME_DOWN = 0x90000;
const int VOLUME_UP = 0xA0000;
SendMessage(this.Handle, 0x319, IntPtr.Zero, (IntPtr)VOLUME_UP);
These are AppCommand messages.
0x319 is the Win32 Windows MSG for WM_APPCOMMAND, and the messages are more accurately APPCOMMAND_VOLUME_UP, etc...
AppCommand messages are messages sent to windows, which are handled at a global level and perform certain application functions. These tend to be linked to Keyboard hotkeys and mouse button functions.
Your app gets first crack at processing any such messages, and if you do not handle them then your apps parent does. If that doesn't handle them, then eventually it gets sent to a global message hook to process them. The key point here is that other windows can trap these messages, so it's not a guarantee that sending these messages will accomplish the task. Just like you might have seen where pressing the volume up or down on your keyboard might not always work when certain windows have focus.
You can find the details for all the messages in the Win32 API reference:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx

Registry settings immediate effect using C#

I have used the following code to disable the control panel:
RegistryKey RegKey = Registry.CurrentUser.CreateSubKey(
#"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer");
RegKey.SetValue("NoControlPanel", false, RegistryValueKind.DWord);
RegKey.Close();
The above code disables control panel only after restarting, I would like to apply the setting immediately without restarting. Please help me.
Try this...
private const int HWND_BROADCAST = 0xffff;
private const int WM_WININICHANGE = 0x001a, WM_SETTINGCHANGE = WM_WININICHANGE, INI_INTL = 1;
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, INI_INTL);
[DllImport("user32.dll")]
private static extern int SendMessage(int hWnd, uint wMsg, uint wParam, uint lParam);
This will notify all applications that changes have been made to the registry, and those programs that accept the notification shuould reload their settings.
Note that not all applications may do this, but things like control panel should.
I haven't tested this, but I suspect you only have to close all your explorer.exe processes for this to take effect.
Note that the desktop and taskbar are provided by explorer.exe, so you'll need to start a new one after closing them all.
It's a bit hostile, because the user might have Explorer windows that they don't want to lose, so do it only if it's not going to annoy people. 8-)

Categories