Intercept mouse click from other program - c#

I’m trying to intercept mouse clicks from another program. I’m making a plugin for the program, that overlays a transparent form on the program and displays additional information. When I click on the transparent part of the form I can click on things in the main program. I don’t want this to happen (at least not every time - there are some parts where you are allowed to click and some parts where you aren’t but this isn’t the problem).
The way I’m doing this now is by using WH_MOUSE_LL, this is working fine and I can keep the mouse click from getting to the program by returning a non zero value (http://msdn.microsoft.com/en-gb/library/windows/desktop/ms644988(v=vs.85).aspx).
The problem is, this makes my main program lag, I don’t need to get notifications for all mouse movements, I only want to get a notification if the user actually clicked something. Is there any way I can limit the WH_MOUSE_LL so it only fires on mouse clicks? (The lag isn’t because of calculations in the MouseHookProc method - it’s currently doing nothing except for calling: CallNextHookEx(hHook, nCode, wParam, lParam).)
I’ve tried to fix this by using a global hook (http://www.codeproject.com/Articles/18638/Using-Window-Messages-to-Implement-Global-System-H) that hooks the WM_MOUSEACTIVATE message. The idea was to only hook up the WH_MOUSE_LL when I received a WM_MOUSEACTIVATE notification. Unfortunately WH_MOUSE_LL click notification gets sent before WM_MOUSEACTIVATE so this doesn't work.
EDIT:
#Nanda here’s the proc code:
public int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
return WindowUtility.CallNextHookEx(hHook, nCode, wParam, lParam);
}
As you can see I’m not doing very much with it atm, but it already lags...
#Cody Gray I’ve made a very small test for the Form handling the messages:
public class Form1 : Form
{
private TrackBar m_Trackbar;
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
public Form1()
{
m_Trackbar = new System.Windows.Forms.TrackBar();
m_Trackbar.LargeChange = 1;
m_Trackbar.Location = new System.Drawing.Point(5, 10);
m_Trackbar.Maximum = 100;
m_Trackbar.Size = new System.Drawing.Size(280, 40);
m_Trackbar.Value = 100;
this.Controls.Add(m_Trackbar);
m_Trackbar.Scroll += new System.EventHandler(this.m_TrackbarScroll);
}
private void m_TrackbarScroll(object sender, System.EventArgs e)
{
this.Opacity = ((Convert.ToDouble(m_Trackbar.Value)) / 100);
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0x201: //WM_LBUTTONDOWN
Console.WriteLine("MouseButton Down!");
//I could copy the Message over to the MainProgram with this right?
//SendMessage(MainProgramHwnd, m.Msg, m.WParam, m.LParam);
//This will also only work on an opacity higher than 0.
break;
}
base.WndProc(ref m);
}
}
When you said: “return that it's transparent and let it be routed to the window underneath it?” Can I do this by using SendMessage and basically copying the message I receive in my WndProc method?
To make things more complicated I’m also using this form http://www.codeproject.com/Articles/1822/Per-Pixel-Alpha-Blend-in-C. To my understanding this enables me to draw bitmaps on the form who are Anti Aliasing against the background. With this form there seems to be no way to set the opacity, as it’s just transparent all the time. Is there a better way to draw bitmaps on a Form?

You may want to look into Easyhook (http://easyhook.codeplex.com/) which will allow you to hook Windows API calls from a single process rather than for all processes.

Related

How to always show underline character? (C# Windows Form)

I'm making a dialog that look like Notepad's Find Dialog. I notice that the underline character of Notepad's Find dialog always show all the time (I have to press ALT key to see this with my dialog). How to always show underline character like that?
I try to use SendKeys.Send("%") on Form_Load event but nothing happens.
There is another problem, when I press ALT key on child Form, it show underline charater of parent Form too. How to avoid that?
This is sreenshot of Notepad's find dialog:
I pretty sure this is not about Ease of Acess Center, because the main Form of Notepad doesn't always show this.
Seeing the n in "Find" underlined in the Notepad dialog is an intentional bug. The dialog isn't actually part of Notepad, it built into Windows. Underlying winapi call is FindText(). The feature is in general a pile 'o bugs, one core problem is that creating a new window after the UI is put in the "show underlines" state doesn't work correctly, that new window isn't also in that state. Presumably the intentional bug was based on the assumption that the user would be somewhat likely to use the Alt key to get the dialog displayed. Yuck if he pressed Ctrl+F.
The Windows dialog probably does it by simply drawing the "Find" string with DrawText() with the DT_NOPREFIX option omitted. You could do the same with TextRenderer.DrawText(), omit the TextFormatFlags.HidePrefix option.
Not exactly WinFormsy, you'd favor a Label control instead of code. It is hackable, you'd have to intentionally send the message that puts the UI in the "show underlines" state for your own dialog. Do so in an override for the OnHandleCreated() method:
protected override void OnHandleCreated(EventArgs e) {
const int WM_UPDATEUISTATE = 0x0128;
base.OnHandleCreated(e);
SendMessage(this.label1.Handle, WM_UPDATEUISTATE, new IntPtr(0x30002), IntPtr.Zero);
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
Where "label1" is the control you want to show underlines. Repeat for other controls, if any. It is supposed to work by sending the message to the form, that this doesn't work is part of the pile 'o bugs. Yuck.
Fwiw: do not fix this by changing the system option as recommended in the duplicate. That's very unreasonable.
You can use RichTextBox control and extension method for that:
public static class FontHelper
{
public static void Underline(this RichTextBox txtBox, int underlineStart, int length)
{
if (underlineStart > 0)
{
txtBox.SelectionStart = underlineStart;
txtBox.SelectionLength = length;
txtBox.SelectionFont = new Font(txtBox.SelectionFont, FontStyle.Underline);
txtBox.SelectionLength = 0;
}
}
}
richTextBox1.Text = "Search for";
richTextBox1.Underline(7, 1); // index and length of underlying text

Mouse cursor flickers over selected text - how to prevent this?

I'm encountering strange behaviour while moving the mouse over selected text in a RichTextBox (C#, .NET 4.0, WinForms): as I move the mouse cursor, it flickers between Cursors.Arrow and Cursors.IBeam.
I found code that disables the flickering:
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg == WM_SETCURSOR) //WM_SETCURSOR is set to 0x20
return;
}
but then the mouse cursor is stuck as Cursors.Arrow, even when I manually set it to something else, ex:
void RTFBox_MouseMove(object sender, MouseEventArgs e)
{
Cursor = Cursors.IBeam;
}
(I also had logic in the MouseMove function to set Cursor to other types of non-Arrow cursors, depending on what the mouse was over.)
I also tried:
public override Cursor Cursor
{
get
{
//(I have other logic here to determine the desired cursor type I want; in all cases it was a non-Arrow cursor)
return Cursors.Cross; //'Cross' instead of 'IBeam' just to prove whether this works
}
set
{
return;
}
}
which successfully made the cursor a cross (but only when I commented out the WndProc code), but the flickering remained when I moused over selected text (with the mouse cursor changing between Arrow and Cross).
In trying to find a solution, I came across this post, but calling
SendMessage(Handle, LVM_SETHOTCURSOR, IntPtr.Zero, Cursors.IBeam.Handle);
from a class inheriting from RichTextBox did not fix the flickering problem.
My problem seems identical to the one desribed in this post, but the problem was described to exist on .NET 3.0 and fixed in .NET 3.5.
When I created a new project and inserted a RichTextBox into the form, the flickering is still there.
Thus, my question is: How do I prevent this flickering? Or does anyone know if this problem is resolved in later versions of .NET/visual studio?
[Update: I downloaded Visual Studio 2013, but the "flicker" effect is still present. I downloaded .Net 4.5.1 installer and told it to repair, but the "flickering" remained. Under "Properties" > "References", it says that "System.Windows.Forms" is version 4.0.0.0; I suppose this means that updating past 4.0 was unnecessary?]
Flickering is mostly because of Graphics objects or surface redrawing. If you put codes to an event of a control that continuosly updates itself (f.i. MouseMove), and the code modificates somehow the surface or the contents of it, flickering occurs.
I used to use DoubleBuffering to fix flickering problems. Just add this code to your form's constructor (above or below the InitializeComponent() method):
DoubleBuffered = true;
If this doesn't fix the problem, the issue is probably not because of a graphical trouble.
Cursor could also flicker when two events codes want to change the cursor at the same time.
It could be your code or a default code as well (f.i. the IBeam automatically appears when you move cursor above the Control).
Check your code, whether it contains codes that modify the Cursor or the selected text during you use it. Then change the cursor from a nother event every time to the type you want. I mean:
//MouseMove is the best choice in this case
private void RichTextBox1_MouseMove(object sender, MouseEventArgs e)
{
Cursor = Cursors.Arrow;
}
But I use .Net 4.0, and I don't have any problems with it. I think it has been fixed in the latest version.
Hope it helps a bit. :)
The documentation for WndProc's WM_SETCURSOR is found here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648382(v=vs.85).aspx
You can use this code to manually set the cursor to a specific type:
[DllImport("user32.dll")]
public static extern int SetCursor(IntPtr cursor);
private const int WM_SETCURSOR = 0x20;
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg == WM_SETCURSOR)
{
SetCursor(Cursors.IBeam.Handle);
m.Result = new IntPtr(1); //Signify that we dealt with the message. We should be returning "true", but I can't figure out how to do that.
return;
}
base.WndProc(ref m);
}
However, this code results in the text-caret flickering every time SetCursor is called (which happens every time the mouse is moved in the control).
I added onto chess123mate's answer to get it to show the arrow cursor over the vertical scrollbar:
[DllImport("user32.dll")]
public static extern int SetCursor(IntPtr cursor);
private const int WM_SETCURSOR = 0x20;
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg == WM_SETCURSOR)
{
var scrollbarWidth = System.Windows.Forms.SystemInformation.VerticalScrollBarWidth;
var x = PointToClient(Control.MousePosition).X;
var inScrollbar = x > this.Width - scrollbarWidth;
var cursor = inScrollbar ? Cursors.Arrow : Cursors.IBeam;
SetCursor(cursor.Handle);
m.Result = new IntPtr(1); //Signify that we dealt with the message. We should be returning "true", but I can't figure out how to do that.
return;
}
base.WndProc(ref m);
}
I can't really speak to the flickering issue... it sounds like something that you need to speak with the vendor about.
As to why your code "fixed" the issue, but doesn't let you change the cursor, it helps to understand more about how the windows message pump works.
Basically, at a low level, you are intercepting requests to change the cursor and then blocking them. If you look at the documentation for this function, you'll see this comment:
Notes to Inheritors
Inheriting controls should call the base class's WndProc method to process any messages that they do not handle.
You are overriding this function, essentially becoming an "inheritor", and then "handling" messages requesting the cursor to change by ignoring it.

Get the active color of Windows 8 automatic color theme

In Windows 8, I have set the color scheme to automatic and configured my wallpaper to change after x minutes. The color scheme changes according to the active wallpaper.
I'm developing a WPF application and would like to have my gradients change when Windows changes the color scheme to match the current wallpaper.
Is there a way get the current/actual color scheme and be notified of the change in C#?
Yes, it's possible. However be warned: this encompasses quite a bit of Win32 interop (this means P/Invokes into native DLLs from managed code), and is only doable with certain undocumented APIs. Although, the only undocumented features involved are for obtaining the window color scheme (or as the DWM calls it, the window colorization color), which is covered in this other question:
Vista/7: How to get glass color?
In my own project, I make use of a call to DwmGetColorizationParameters():
internal static class NativeMethods
{
[DllImport("dwmapi.dll", EntryPoint="#127")]
internal static extern void DwmGetColorizationParameters(ref DWMCOLORIZATIONPARAMS params);
}
public struct DWMCOLORIZATIONPARAMS
{
public uint ColorizationColor,
ColorizationAfterglow,
ColorizationColorBalance,
ColorizationAfterglowBalance,
ColorizationBlurBalance,
ColorizationGlassReflectionIntensity,
ColorizationOpaqueBlend;
}
I've tested it and it works great with Windows 8 and its automatic window colorization feature. As suggested in the link above, you can look in the registry for the color values as an alternative to a P/Invoke, but I haven't tested that method, and as stated these are undocumented and not guaranteed to be stable.
Once you obtain the color for drawing your gradient brushes, the brushes won't update when the window color scheme changes, whether manually or automatically by Windows. Thankfully, Windows broadcasts the WM_DWMCOLORIZATIONCOLORCHANGED window message whenever that happens, so you simply need to listen for that message and update your colors whenever it's sent. You do this by hooking onto the window procedure (WndProc()).
The value of WM_DWMCOLORIZATIONCOLORCHANGED is 0x320; you'll want to define that as a constant somewhere so you can use it in code.
Also, unlike WinForms, WPF windows don't have a virtual WndProc() method to override, so you have to create and hook one in as a delegate to their associated window handles (HWNDs).
Taking some example code from these answers of mine:
How do I make a WPF window movable by dragging the extended window frame?
Detect system theme change in WPF
We have:
const int WM_DWMCOLORIZATIONCOLORCHANGED = 0x320;
private IntPtr hwnd;
private HwndSource hsource;
private void Window_SourceInitialized(object sender, EventArgs e)
{
if ((hwnd = new WindowInteropHelper(this).Handle) == IntPtr.Zero)
{
throw new InvalidOperationException("Could not get window handle.");
}
hsource = HwndSource.FromHwnd(hwnd);
hsource.AddHook(WndProc);
}
private static Color GetWindowColorizationColor(bool opaque)
{
var params = NativeMethods.DwmGetColorizationParameters();
return Color.FromArgb(
(byte)(opaque ? 255 : params.ColorizationColor >> 24),
(byte)(params.ColorizationColor >> 16),
(byte)(params.ColorizationColor >> 8),
(byte) params.ColorizationColor
);
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case WM_DWMCOLORIZATIONCOLORCHANGED:
/*
* Update gradient brushes with new color information from
* NativeMethods.DwmGetColorizationParams() or the registry.
*/
return IntPtr.Zero;
default:
return IntPtr.Zero;
}
}
When Windows transitions the color change, WM_DWMCOLORIZATIONCOLORCHANGED is dispatched at every keyframe in the transition, so you'll receive numerous messages at a short burst during the color change. This is normal; just update your gradient brushes as usual and you'll notice that when Windows transitions the window color scheme, your gradients will transition smoothly along with the rest of the window frames as well.
Remember that you may need to account for situations where the DWM isn't available, such as when running on Windows XP, or when running on Windows Vista or later with desktop composition disabled. You'll also want to ensure you don't overuse this, or you may incur a significant performance hit and slow down your app.
This can be done in .NET 4.5 and later without P/Invokes. The SystemParameters class now has static WindowGlassBrush and WindowGlassColor properties along with a StaticPropertyChanged event.
From XAML, you can bind to the WindowGlassBrush property like:
<Grid Background="{x:Static SystemParameters.WindowGlassBrush}">
However, with this assignment the Background color won't get updated automatically when Windows changes its colors. Unfortunately, SystemParameters does not provide WindowGlassBrushKey or WindowGlassColorKey properties to use as ResourceKeys with DynamicResource, so getting change notifications requires code behind to handle the StaticPropertyChanged event.
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
SystemParameters.StaticPropertyChanged += this.SystemParameters_StaticPropertyChanged;
// Call this if you haven't set Background in XAML.
this.SetBackgroundColor();
}
protected override void OnClosed(EventArgs e)
{
SystemParameters.StaticPropertyChanged -= this.SystemParameters_StaticPropertyChanged;
base.OnClosed(e);
}
private void SetBackgroundColor()
{
this.Background = SystemParameters.WindowGlassBrush;
}
private void SystemParameters_StaticPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "WindowGlassBrush")
{
this.SetBackgroundColor();
}
}
}

In C#, how to activate the previously focused window?

I work eg. in Firefox, and my C#.NET app brings its window to the front. That's ok, but when I use SendToBack() to hide the form, it doesn't activate Firefox's window, so altough Firefox is in the foreground, I have to click into the window to be able to scroll, etc. How can I activate the previously focused window in C#?
i have tried these:
[DllImport("User32")]
private static extern int SetForegroundWindow(IntPtr hwnd);
[DllImport("user32.dll")]
static extern bool AllowSetForegroundWindow(int dwProcessId);
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[...]
AllowSetForegroundWindow(System.Diagnostics.Process.GetCurrentProcess().Id);
SendToBack();
SetForegroundWindow(GetForegroundWindow());
I hoped that after sending my window back, the previous one will be returned by GetForegroundWindow, but it doesn't work.
Secondly, I've tried to override WndProc, and handle the WM_ACTIVATE message to get the previous window from lParam, but it doesn't work either if I use SetForegroundWindow() with this handle.
protected override void WndProc(ref Message msg) {
if (msg.Msg == 0x0006) {
prevWindow = msg.LParam;
}
base.WndProc(ref msg);
}
[...]
SetForegroundWindow(prevWindow);
did you try the SetActiveWindow function? Its separate from the SetForgroundWindow function, although it seems that you may need to use them both.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646311%28v=vs.85%29.aspx
There is also a SetFocus function which sounds like it could work.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646312%28v=vs.85%29.aspx
Update
To get the current Active Window, I would fire off the GetActiveWindow function before moving your application to the front of the stack, that way you have the handle for the window that was active before hand.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646292%28v=vs.85%29.aspx
Another Update
I did a bit more digging around on the site and came up with the following three links, which might work better. The keyboard input functions seem to be dependent on the Window you are trying to set being part of the calling threads message queue, which since we are dealing with two separate application threads, is likely to not be the case.
GetGUIThreadInfo Get the threads information, including active window
GUITHREADINFO The GUITHREADINFO structure
SwitchToThisWindow Another method of window changing
All of these are in the same method stack as the SetForegroundWindow method, which seems to make them more likely to do what you are attempting.
When you call SetFocus() to move your app forward, it returns the handle of the window that had focus before you.

Start Bar Shows Up Over Maximized Form (Pocket PC 2003)

Environment
Windows XP SP3 x32
Visual Studio 2005 Standard
Windows Mobile/Pocket PC 2003
.NET Compact Framework 1.0 SP3 and .NET Framework 1.1
Honeywell Dolphin 9500 Handheld Barcode Scanner
Goal
I have a three form application and an external class (Program.cs) that has the application entry point, Main(). The main form loads first and then, from within MainForm_Load(...), instantiates/shows a new form kind of like a splash screen. I want all three forms to be maximized. All three forms have the following properties set:
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
this.ControlBox = false;
Problem
The "splash screen" form shows up full screen without any issue. I then dispose of it and show the main screen (first to load and the param for Application.Run();. From the main screen, once a list box SelectedIndexChanged event is detected, a third form is shown (leaving the main form behind said third form). That third form shows the task bar over the top portion of my form:
Upon closing this form, the main form now has the task bar overlayed as well.
Code
Friend paste links. Let me know if I should just post the code here. WorkOrderView is over a thousand lines so I figured this would be easier.
"Main" Form (WorkOrders.cs)
"Third" Form (WorkOrderView.cs) - Pictured above
Unrelated Suggestions
I am quite a green programmer and I especially lack experience in this environment. So, if you have any suggestions/criticisms on the way I'm doing some things, don't hesitate to hit me with them. Probably best to just comment on the post instead of posting an answer for those types of replies.
Thanks!
First off, I only run Windows Mobile 5 (WM5) these days. (I got to move up from PocketPC 2003 a couple of years ago. LOL)
I've found that defining a Form's Window Size does not work well on mobile devices, and that showing/hiding multiple forms is awkward and never behaves the way you want.
Still, make sure your Main Form has it's WindowState set to Maximized.
I also set ControlBox and MinimizeBox to False, if that helps.
Instead of using multiple forms, it will look much nicer if you simply use Panels as your forms with the Main Form as some kind of MDI container (bad choice of words, but that is what I'm doing).
In my Designer View, each panel is just a small box full of controls.
To work with each panel, select it in the Visual Studio designer, and you will see a position box (arrows up & down and left & right).
Right-Click the position box and click Bring to Front.
Now go over to the panel control's Properties and set Dock to Fill.
While this panel is full screen, add all of your buttons, textboxes, etc. with appropriate names. Names like pnl1_button1 and pnl2_button1 are easier to understand in your code than the VS default button1 and button2.
When you are through with your design view of this panel, go back to the Dock properties and set it back to None.
Go on to the next panel control.
I have found it also helps to maintain a small sketch of your panels with their names and the names of their controls.
In the Load event of your main form, set every Panel's Dock property to DockStyle.Fill. Then, as you want to show one form, simply call Panel1.BringToFront() instead of dialog.Show().
Mobile development isn't hard, but it is different. :)
EDIT:
In the project's Program.cs file, I keep the following static tools that I can use to turn ON and OFF the Start Menu (doesn't work so well in WM5, but I've still got it in my code from my PocketPC version).
I have not had to open this project in a year or so, but it should all be valid. Give them a try. If I've left something out, just let me know.
Once this is pasted into your project's Program.cs file, just call Program.ShowWindowsMenu(false); when your program starts and Program.ShowWindowsMenu(true); when your program exits.
static IntPtr _taskBar;
static IntPtr _sipButton;
public enum Notify_Events {
NOTIFICATION_EVENT_NONE = 0,
NOTIFICATION_EVENT_TIME_CHANGE = 1,
NOTIFICATION_EVENT_SYNC_END = 2,
NOTIFICATION_EVENT_DEVICE_CHANGE = 7,
NOTIFICATION_EVENT_RS232_DETECTED = 9,
NOTIFICATION_EVENT_RESTORE_END = 10,
NOTIFICATION_EVENT_WAKEUP = 11,
NOTIFICATION_EVENT_TZ_CHANGE = 12,
NOTIFICATION_EVENT_OFF_AC_POWER,
NOTIFICATION_EVENT_ON_AC_POWER
}
public enum WindowPosition {
SWP_HIDEWINDOW = 0x0080,
SWP_SHOWWINDOW = 0x0040
}
[DllImport("coredll.dll", EntryPoint = "FindWindowW", SetLastError = true)]
public static extern IntPtr FindWindowCE(string lpClassName, string lpWindowName);
[DllImport("coredll.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
static void ShowWindowsMenu(bool enable) {
try {
if (enable) {
if (_taskBar != IntPtr.Zero) {
SetWindowPos(_taskBar, IntPtr.Zero, 0, 0, 240, 26, (int)WindowPosition.SWP_SHOWWINDOW); // display the start bar
}
} else {
_taskBar = FindWindowCE("HHTaskBar", null); // Find the handle to the Start Bar
if (_taskBar != IntPtr.Zero) { // If the handle is found then hide the start bar
SetWindowPos(_taskBar, IntPtr.Zero, 0, 0, 0, 0, (int)WindowPosition.SWP_HIDEWINDOW); // Hide the start bar
}
}
} catch (Exception err) {
ErrorWrapper(enable ? "Show Start" : "Hide Start", err);
}
try {
if (enable) {
if (_sipButton != IntPtr.Zero) { // If the handle is found then hide the start bar
SetWindowPos(_sipButton, IntPtr.Zero, 0, 0, 240, 26, (int)WindowPosition.SWP_SHOWWINDOW); // display the start bar
}
} else {
_sipButton = FindWindowCE("MS_SIPBUTTON", "MS_SIPBUTTON");
if (_sipButton != IntPtr.Zero) { // If the handle is found then hide the start bar
SetWindowPos(_sipButton, IntPtr.Zero, 0, 0, 0, 0, (int)WindowPosition.SWP_HIDEWINDOW); // Hide the start bar
}
}
} catch (Exception err) {
ErrorWrapper(enable ? "Show SIP" : "Hide SIP", err);
}
}
static void ErrorWrapper(string routine, Exception e) {
if (!String.IsNullOrEmpty(e.Message)) {
MessageBox.Show(e.Message, routine, MessageBoxButtons.OKCancel, MessageBoxIcon.None, 0);
}
}
EDIT2:
Declare a private static instance of your main form, then wrap that in a try....catch routine inside your project's Program.cs file like so:
static Form1 ppcForm = null;
static void Main() {
ShowWindowsMenu(false);
try {
ppcForm = new Form1();
Application.Run(ppcForm );
} catch (Exception err) {
if (!String.IsNullOrEmpty(err.Message)) {
ErrorWrapper("Mobile Form (Program)", err);
}
} finally {
ShowWindowsMenu(true);
}
}
What you're after is usually referred to as "kiosk mode" (which may help your search engine results).
The underlying issue is that the start bar is not part of your app - it's part of the Shell app and you're competing with it for desired behavior. What you want is something the Platform is trying to prevent you from doing, so you have to be prepared to put your developer boot on the platform's neck to get it to behave.
This blog entry is a really good starting point for this issue and will probably give you what you need, but feel free to use a search engine to find more/aternate proposals. There's actually a lot of material on the web for this - more than would belong in this answer.

Categories