The 'click sound' in question is actually a system wide preference, so I only want it to be disabled when my application has focus and then re-enable when the application closes/loses focus.
Originally, I wanted to ask this question here on stackoverflow, but I was not yet in the beta. So, after googling for the answer and finding only a little bit of information on it I came up with the following and decided to post it here now that I'm in the beta.
using System;
using Microsoft.Win32;
namespace HowTo
{
class WebClickSound
{
/// <summary>
/// Enables or disables the web browser navigating click sound.
/// </summary>
public static bool Enabled
{
get
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(#"AppEvents\Schemes\Apps\Explorer\Navigating\.Current");
string keyValue = (string)key.GetValue(null);
return String.IsNullOrEmpty(keyValue) == false && keyValue != "\"\"";
}
set
{
string keyValue;
if (value)
{
keyValue = "%SystemRoot%\\Media\\";
if (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor > 0)
{
// XP
keyValue += "Windows XP Start.wav";
}
else if (Environment.OSVersion.Version.Major == 6)
{
// Vista
keyValue += "Windows Navigation Start.wav";
}
else
{
// Don't know the file name so I won't be able to re-enable it
return;
}
}
else
{
keyValue = "\"\"";
}
// Open and set the key that points to the file
RegistryKey key = Registry.CurrentUser.OpenSubKey(#"AppEvents\Schemes\Apps\Explorer\Navigating\.Current", true);
key.SetValue(null, keyValue, RegistryValueKind.ExpandString);
isEnabled = value;
}
}
}
}
Then in the main form we use the above code in these 3 events:
Activated
Deactivated
FormClosing
private void Form1_Activated(object sender, EventArgs e)
{
// Disable the sound when the program has focus
WebClickSound.Enabled = false;
}
private void Form1_Deactivate(object sender, EventArgs e)
{
// Enable the sound when the program is out of focus
WebClickSound.Enabled = true;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// Enable the sound on app exit
WebClickSound.Enabled = true;
}
The one problem I see currently is if the program crashes they won't have the click sound until they re-launch my application, but they wouldn't know to do that.
What do you guys think? Is this a good solution? What improvements can be made?
const int FEATURE_DISABLE_NAVIGATION_SOUNDS = 21;
const int SET_FEATURE_ON_PROCESS = 0x00000002;
[DllImport("urlmon.dll")]
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
static extern int CoInternetSetFeatureEnabled(int FeatureEntry,
[MarshalAs(UnmanagedType.U4)] int dwFlags,
bool fEnable);
static void DisableClickSounds()
{
CoInternetSetFeatureEnabled(FEATURE_DISABLE_NAVIGATION_SOUNDS,
SET_FEATURE_ON_PROCESS,
true);
}
I've noticed that if you use WebBrowser.Document.Write rather than WebBrowser.DocumentText then the click sound doesn't happen.
So instead of this:
webBrowser1.DocumentText = "<h1>Hello, world!</h1>";
try this:
webBrowser1.Document.OpenNew(true);
webBrowser1.Document.Write("<h1>Hello, world!</h1>");
You disable it by changing Internet Explorer registry value of navigating sound to "NULL":
Registry.SetValue("HKEY_CURRENT_USER\\AppEvents\\Schemes\\Apps\\Explorer\\Navigating\\.Current","","NULL");
And enable it by changing Internet Explorer registry value of navigating sound to "C:\Windows\Media\Cityscape\Windows Navigation Start.wav":
Registry.SetValue("HKEY_CURRENT_USER\\AppEvents\\Schemes\\Apps\\Explorer\\Navigating\\.Current","","C:\Windows\Media\Cityscape\Windows Navigation Start.wav");
Definitely feels like a hack, but having done some research on this a long time ago and not finding any other solutions, probably your best bet.
Better yet would be designing your application so it doesn't require many annoying page reloads.. for example, if you're refreshing an iframe to check for updates on the server, use XMLHttpRequest instead. (Can you tell that I was dealing with this problem back in the days before the term "AJAX" was coined?)
If you want to use replacing Windows Registry, use this:
// backup value
RegistryKey key = Registry.CurrentUser.OpenSubKey(#"AppEvents\Schemes\Apps\Explorer\Navigating\.Current");
string BACKUP_keyValue = (string)key.GetValue(null);
// write nothing
key = Registry.CurrentUser.OpenSubKey(#"AppEvents\Schemes\Apps\Explorer\Navigating\.Current", true);
key.SetValue(null, "", RegistryValueKind.ExpandString);
// do navigation ...
// write backup key
RegistryKey key = Registry.CurrentUser.OpenSubKey(#"AppEvents\Schemes\Apps\Explorer\Navigating\.Current", true);
key.SetValue(null, BACKUP_keyValue, RegistryValueKind.ExpandString);
Related
The title might not make sense so I'll explain it more.
if (checkbox1.Checked && (RobloxPlayerBeta.exe is open)
{
api.Launch;
}
I want to make it so that the api launches if the checkbox is checked and the process is open.
Making a function to see if a process is active, is pretty straight forward. I have made a small example to show you.
Dont forget to use the following import:
using System.Diagnostics;
This is the function i'm using:
public bool IsProcessOpen(string name)
{
Process[] p = Process.GetProcessesByName(name); ///Get the process by a name
if(p.Length == 0) /// if the length of the array is 0, then it means its not running.
{
return false;
}
else /// if its other then 0 it means its its running.
{
return true;
}
}
I'm checking the answer with a simple button click on a Windows Forms application. I'm using the following:
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(IsProcessOpen(textBox1.Text).ToString());
///To test this function, you can try this by changing "textBox1.Text" to "cmd"
///If cmd is not opened, it will return false,
///If cmd is running, it will return True. You can also do this with other processes. For example Chrome
}
If you decide to copy this function, you're if statement should look something like this:
if (checkbox1.Checked == true && IsProcessOpen(RobloxPlayerBeta) == true)
{
api.Launch;
}
Hope this helps you out.
Twan
I finally figured out how to print transformed XML without prompting the user or showing an IE window, but now I need to specify a number of copies and possibly other printer settings.
Is there a way to programmatically change printer settings on a WebBrowser control?
The code in question:
private static void PrintReport(string reportFilename)
{
WebBrowser browser = new WebBrowser();
browser.DocumentCompleted += browser_DocumentCompleted;
browser.Navigate(reportFilename);
}
private static void browser_DocumentCompleted
(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser browser = sender as WebBrowser;
if (null == browser)
{
return;
}
browser.Print();
browser.Dispose();
}
The only method I've had success with is modifying the registry on the fly (and changing them back to not affect anything else).
You can find the settings you need at "Software\Microsoft\Internet Explorer\PageSetup" under CurrentUser.
To change the printer, you can use this:
using System.Management
public static bool SetDefaultPrinter(string defaultPrinter)
{
using (ManagementObjectSearcher objectSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_Printer"))
{
using (ManagementObjectCollection objectCollection = objectSearcher.Get())
{
foreach (ManagementObject mo in objectCollection)
{
if (string.Compare(mo["Name"].ToString(), defaultPrinter, true) == 0)
{
mo.InvokeMethod("SetDefaultPrinter", null, null);
return true;
}
}
}
}
return false;
}
As for the number of copies, you can always put the WebBrowser.Print in a while loop.
string strKey = "Software\\Microsoft\\Internet Explorer\\PageSetup";
bool bolWritable = true;
RegistryKey oKey = Registry.CurrentUser.OpenSubKey(strKey, bolWritable);
Console.Write(strKey);
if (stringToPrint.Contains("Nalog%20za%20sluzbeno%20putovanje_files"))
{
oKey.SetValue("margin_bottom", 15);
oKey.SetValue("margin_top", 0.19);
}
else
{
//Return onld walue
oKey.SetValue("margin_bottom", 0.75);
oKey.SetValue("margin_top", 0.75);
}
you need to change registry settings via code to change settings for internet explorer or the web browser control. check out the link below, it describes how to do so, also if there's more options you need to alter using the registry, then use regedit.exe to find what other keys internet explorer has.
http://support.microsoft.com/kb/236777
ps: you should note that any changes you make via your code to internet explorer's registry settings will persist on your system/user account.
This worked well for me, however I am on .NET 3.5
this.webBrowser1.ShowPrintDialog();
I have an applications that install two other application which has a "Help" option. Each of these application has a common help file but the contents should be displayed based on the index selected for the application in the "Table of Contents". If i open one application, the help of that particular application should be displayed.
My code looks like this for Appl1.
private void Help_Click(Core.CommandBarButton Ctrl, ref bool CancelDefault)
{
if (System.IO.File.Exists(new PlugInConstants().HELP_FILE_Path))
{
System.Windows.Forms.Help.ShowHelp(new System.Windows.Forms.Control(),
new PlugInConstants().HELP_FILE_Path,
System.Windows.Forms.HelpNavigator.TableOfContents, "Appl1");
}
else
{
System.Windows.Forms.MessageBox.Show(m_objLanguage.ERR_HELP_NOT_FOUND.Replace
("%1", m_objGlobalConfig.HelpFilename));
}
CancelDefault = false;
}
and looks like this for Appl2
private void HelpToolStripMenuItem_Click(object sender, EventArgs e)
{
helpToolStripMenuItem.Enabled = false;
string helpFilePath;
helpFilePath = new TrayConstants().HELP_FILE_Path;
if (System.IO.File.Exists(helpFilePath))
{
System.Windows.Forms.Help.ShowHelp(new System.Windows.Forms.Control(),
helpFilePath, System.Windows.Forms.HelpNavigator.TableOfContents, "Appl2") ;
}
else
{
if (m_helpPage == null)
m_helpPage = new HelpPage();
m_helpPage.ShowDialog();
}
helpToolStripMenuItem.Enabled = true;
}
from this i can only see the Content page of common helpfile, but not the particular application help that is selected.
Now i did run Appl1 but still i can see the main MyAppbut not Appl1that is automatically selected and the contents that is displayed to right.
I am using VS 2010,C#, win forms
thanks in advance
I believe that your issue is that you are accessing the wrong value in the HelpNavigator enum. Looks like it should be Topic, not TableOfContents.
System.Windows.Forms.Help.ShowHelp(new System.Windows.Forms.Control(),
helpFilePath, System.Windows.Forms.HelpNavigator.Topic, "Appl2") ;
http://msdn.microsoft.com/en-us/library/system.windows.forms.helpnavigator.aspx
I'm trying to write an application that senses when someone taps and holds something. I am using windows forms. I tried using the mouse down even but it doesn't appear to fire all the time. This is also going to be a multi touch application. I'm going to have two buttons , and the user can tap and hold one button, while they press on the other button. Or Just press one button. I'm not even sure how a windows form app can handle that.
All the examples inhave seen for a windows touch app use xaml. Is this really the only way to capture tap and hold ??
I'm essentially making an onscreen keyboard here, and I don't think that isnpossible WITHOUT windows forms. Correct me if I am wrong here.
Any help or guidance in this is greatly appreciated. Thanks.
If your program is running on Windows 8, you can use the WM_POINTER API to get the input you need. Override WndProc to capture the messages. You will have to do some P/Invoke to get it working, but it's not terribly hard. Here's some incomplete code to get you started, you'll need to add cases for up, down, and update events for each type of pointer you want to track. Keep track of the pointer IDs to process multi touch. To handle the press-and-hold you'll need to track the time yourself from WM_POINTERDOWN to WM_POINTERUP and act accordingly. Hope this helps.
public const int WM_POINTERDOWN = 0x0246;
public const int WM_POINTERUP = 0x0247;
public const int WM_POINTERUPDATE = 0x0245;
public enum POINTER_INPUT_TYPE : int
{
PT_POINTER = 0x00000001,
PT_TOUCH = 0x00000002,
PT_PEN = 0x00000003,
PT_MOUSE = 0x00000004
}
public static uint GET_POINTERID_WPARAM(uint wParam) { return wParam & 0xFFFF; }
[DllImport("User32.dll")]
public static extern bool GetPointerType(uint pPointerID, out POINTER_INPUT_TYPE pPointerType);
protected override void WndProc(ref Message m)
{
bool handled = false;
uint pointerID;
POINTER_INPUT_TYPE pointerType;
switch(m.Message)
{
case WM_POINTERDOWN:
pointerID = User32.GET_POINTERID_WPARAM((uint)m.WParam);
if (User32.GetPointerType(pointerID, out pointerType))
{
switch (pointerType)
{
case POINTER_INPUT_TYPE.PT_PEN:
// Stylus Down
handled = true;
break;
case POINTER_INPUT_TYPE.PT_TOUCH:
// Touch down
handled = true;
break;
}
}
break;
}
if (handled)
m.Result = (IntPtr)1;
base.WndProc(ref m);
}
This question has been around for a while and might benefit from a simple approach. You can simulate the "tap and hold" (or click and hold) by measuring the time between the MouseDown event and the Click event (which fires before MouseUp). If the time is greater than some value then you cancel the Click and (perhaps) fire your own TapAndHold event. I have created a test control that anyone can use to try this approach out. Just add a UserControl to your test app (I called mine TestTapAndHold) and then paste in the following:
public partial class TestTapAndHold : UserControl
{
private string showText = "Tap Me";
private DateTime mouseDown;
private const int holdTime = 500;
public TestTapAndHold()
{
InitializeComponent();
this.Paint += drawText;
}
public delegate void OnTapAndHold(EventArgs e);
public event OnTapAndHold TapAndHold;
private void drawText(object sender, PaintEventArgs e)
{
using (var drawBrush = new SolidBrush(Color.Black))
{
e.Graphics.DrawString(showText, Font, drawBrush, new Point(5,3));
}
}
protected override void OnClick(EventArgs e)
{
if (DateTime.Now.Subtract(mouseDown).Milliseconds >= holdTime)
{
showText = "Tap Hold";
TapAndHold?.Invoke(e);
} else
{
base.OnClick(e);
showText = "Tapped";
}
Invalidate();
}
private void TestTapAndHold_MouseDown(object sender, MouseEventArgs e)
{
mouseDown = DateTime.Now;
}
}
Build the app and then pop one of the test controls onto a form. You can then add an event handler to your form like:
private void testTapAndHold1_TapAndHold(EventArgs e)
{
MessageBox.Show("You tapped and Held");
}
This general approach enabled me to add "Tap and Hold" functionality to a Windows Forms app running on a Microsoft Surface 4
How to detect the ctrl key is pressed twice if the program is minimized or in system tray
I am trying to develop a c# program where the main form will be shown to the user when the control key is pressed twice. I found samples for hotkey combinations but this is not hotkey with combination, like control+ some other key. This is like google desktop app where the search box is displayed when control key is pressed twice.
Keyboard hooking as suggested. It's been nicely wrapped for you at CodePlex, where you get a .NET API simply raising Key and Mouse events, regardless of the state your app is in.
This seems like a case of keyboard hooking (WH_KEYBOARD).
What you could do is capture each time the key is pressed, and perhaps in a background worker compare the difference in time.
Set yourself a threshold and if it is less than that, you would consider it a double press and do what you need to.
Untested the components could look something like:
private readonly DateTime _originDateTime = new DateTime(0);
private DateTime _lastKeyPress;
Hook up worker:
_backgroundWorker = new BackgroundWorker { WorkerSupportsCancellation = false };
_backgroundWorker.DoWork += DoBackgroundWork;
_backgroundWorker.RunWorkerAsync();
Implement DoBackgroundWork method:
private void DoBackgroundWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
do
{
if (_lastKeyPress != _originDateTime)
{
Thread.Sleep(DelayInMilliseconds);
DateTime now = DateTime.Now;
TimeSpan delta = now - _lastKeyPress;
if (delta < new TimeSpan(0, 0, 0, 0, DelayInMilliseconds))
{
continue;
}
}
//do stuff
} while (true);
}
And don't forget to capture the key:
private void SomeEvent_KeyDown(object sender, KeyEventArgs e)
{
_lastKeyPress = DateTime.Now;
}
This is based on XPath Visualizer
Use keyboard hooks like foxx1337 suggested, then do something like this:
int triggerThreshold = 500; //This would be equivalent to .5 seconds
int lastCtrlTick = 0;
private void OnCtrlPress()
{
int thisCtrlTick = Environment.TickCount;
int elapsed = thisCtrlTick - lastCtrlTick;
if (elapsed <= triggerThreshold)
{
LaunchYourAppOrWhatever();
}
lastCtrlTick = thisCtrlTick;
}
UPDATE:
The managed wrapper .NET library library mentioned in an accepted answer has moved here. Now there is also a nuget package MouseKeyHook available.
Recently support for detecting shortcuts, key combinations and sequences was added. Here is a usage example:
void DoSomething()
{
Console.WriteLine("You pressed UNDO");
}
Hook.GlobalEvents().OnCombination(new Dictionary<Combination, Action>
{
{Combination.FromString("Control+Z"), DoSomething},
{Combination.FromString("Shift+Alt+Enter"), () => { Console.WriteLine("You Pressed FULL SCREEN"); }}
});
For more information see: Detecting Key Combinations and Seuqnces