关闭Windows 8魅力栏

本文关键字:Windows 关闭 | 更新日期: 2023-09-27 18:21:13

我有一个Surface Pro,我需要将其"锁定"为一种Kiosk模式。我知道"Kiosk模式"的更新正在进行中。。但是在此之前我需要做这件事。

我已经在互联网上搜索过了,但似乎无法通过在屏幕上滑动禁用魅力栏。我找到了禁用触控板的方法。。但不幸的是,由于这款平板电脑将在没有键盘的情况下使用,我需要禁用Charm栏。

我的新想法是将整个魅力栏HWND从屏幕上移开数千像素,或者,也许在上面设置一个窗口样式,这样它就不会出现。我曾尝试使用Spy++和一个自定义的基于EnumWindows的控制台应用程序来给我一些窗口句柄。。然而,我无法让魅力酒吧保持足够长的时间让这些生效。

所以我的问题是:如何在Windows8中找到魅力栏的窗口句柄(HWND)?或者,我如何以其他方式获得对Charm栏的引用,以便向其抛出SetWindowLongSetWindowPos

关闭Windows 8魅力栏

事实上,我已经找到了一种方法来做到这一点(显然,其他人都没有:/)。

对于那些想知道的人,像"Start8"answers"SkipMetroSuite"这样的软件可以按下投票键来停止魅力栏。他们从字面上模拟按键,将其闭合在一个紧密的循环中。

我找到了(我认为是)更好的方法。

首先。。。一些WinAPI函数:

using System.Runtime.InteropServices;
....
private enum WindowShowStyle : uint
{  // find more info at http://stackoverflow.com/a/8210120/1245420
   Hide = 0, ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3,
   ShowNormalNoActvate = 4, Show = 5, Minimize = 6, ShowNoActivate = 8,
   Restore = 9, ShowDefault = 10, ForceMinimized = 11
}
[DllImport("user32.dll", SetLastError = true)]
static extern System.IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern System.IntPtr FindWindowByCaption(System.IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.dll")]
static extern bool ShowWindow(System.IntPtr hWnd, WindowShowStyle nCmdShow);

所以首先的问题是魅力酒吧。这个窗口的标题原来是Charm Bar。生成一条不断寻找并隐藏窗口的线程效果很好。所以我产生了一个线程,并不断地轮询它:

System.Threading.Tasks.Task.Factory.StartNew(() => {
    while (true) {
        System.IntPtr hWndCharmBar = FindWindowByCaption(System.IntPtr.Zero, "Charm Bar");
        ShowWindow(hWndCharmBar, 0);
        System.Threading.Thread.Sleep(100); // sleep for a bit
    }
});

这样做效果很好,并在应用程序关闭时使魅力栏继续工作。Thread.Sleep可以阻止线程破坏CPU,但延迟也允许Charm Bar出现一瞬间。不过,在线程再次隐藏它之前,我还没有成功打开魅力栏并足够快地按下按钮,所以这很好。降低睡眠时间显然会使睡眠更快。

Windows 8的另一个问题是,如果你有某种滑块(在我的应用程序中,我有一个包含图库图像的ListBox),那么你实际上可以滑动到屏幕的一侧。。。把你的手指放在那里,然后访问任务栏。。。

所以。。下一部分是关闭任务栏:

IntPtr hWndTray = FindWindow("Shell_TrayWnd", null);
ShowWindow(hWndTray, 0);

然后我在应用程序关闭时再次显示:

IntPtr hWndTray = FindWindow("Shell_TrayWnd", null);
ShowWindow(hWndTray, 1);

从功能上讲,这就是我的应用程序所需要的全部。希望这能帮助到别人。

我还想注意的是,时钟包含在一个标题为"clock and Date"的窗口中。

IntPtr hWndCharmClock = FindWindowByCaption(IntPtr.Zero, "Clock and Date");

我制作了一个小应用程序来切换魅力栏:https://bitbucket.org/darkwingduck/charmsbartoggle/overview

这是如何在使用SHGetPropertyStoreForWindow互操作最大化应用程序时禁用魅力栏。应该很容易转换为C#:

Imports System.Runtime.InteropServices
Imports System.Runtime.CompilerServices
Public Class EdgeGestureUtil
    Private Shared DISABLE_TOUCH_SCREEN As Guid = New Guid("32CE38B2-2C9A-41B1-9BC5-B3784394AA44")
    Private Shared IID_PROPERTY_STORE As Guid = New Guid("886d8eeb-8cf2-4446-8d02-cdba1dbdcf99")
    Private Shared VT_BOOL As Short = 11
#Region "Structures"
    <StructLayout(LayoutKind.Sequential, Pack:=4)> _
    Public Structure PropertyKey
        Public Sub New(guid As Guid, pid As UInt32)
            fmtid = guid
            Me.pid = pid
        End Sub
        <MarshalAs(UnmanagedType.Struct)> _
        Public fmtid As Guid
        Public pid As UInteger
    End Structure
    <StructLayout(LayoutKind.Explicit)> _
    Public Structure PropVariant
        <FieldOffset(0)> _
        Public vt As Short
        <FieldOffset(2)> _
        Private wReserved1 As Short
        <FieldOffset(4)> _
        Private wReserved2 As Short
        <FieldOffset(6)> _
        Private wReserved3 As Short
        <FieldOffset(8)> _
        Private cVal As SByte
        <FieldOffset(8)> _
        Private bVal As Byte
        <FieldOffset(8)> _
        Private iVal As Short
        <FieldOffset(8)> _
        Public uiVal As UShort
        <FieldOffset(8)> _
        Private lVal As Integer
        <FieldOffset(8)> _
        Private ulVal As UInteger
        <FieldOffset(8)> _
        Private intVal As Integer
        <FieldOffset(8)> _
        Private uintVal As UInteger
        <FieldOffset(8)> _
        Private hVal As Long
        <FieldOffset(8)> _
        Private uhVal As Long
        <FieldOffset(8)> _
        Private fltVal As Single
        <FieldOffset(8)> _
        Private dblVal As Double
        <FieldOffset(8)> _
        Public boolVal As Boolean
        <FieldOffset(8)> _
        Private scode As Integer
        'CY cyVal;
        <FieldOffset(8)> _
        Private [date] As DateTime
        <FieldOffset(8)> _
        Private filetime As System.Runtime.InteropServices.ComTypes.FILETIME
        'CLSID* puuid;
        'CLIPDATA* pclipdata;
        'BSTR bstrVal;
        'BSTRBLOB bstrblobVal;
        <FieldOffset(8)> _
        Private blobVal As Blob
        'LPSTR pszVal;
        <FieldOffset(8)> _
        Private pwszVal As IntPtr
        'LPWSTR 
        'IUnknown* punkVal;
        'IDispatch* pdispVal;
        '        IStream* pStream;
        '        IStorage* pStorage;
        '        LPVERSIONEDSTREAM pVersionedStream;
        '        LPSAFEARRAY parray;
        '        CAC cac;
        '        CAUB caub;
        '        CAI cai;
        '        CAUI caui;
        '        CAL cal;
        '        CAUL caul;
        '        CAH cah;
        '        CAUH cauh;
        '        CAFLT caflt;
        '        CADBL cadbl;
        '        CABOOL cabool;
        '        CASCODE cascode;
        '        CACY cacy;
        '        CADATE cadate;
        '        CAFILETIME cafiletime;
        '        CACLSID cauuid;
        '        CACLIPDATA caclipdata;
        '        CABSTR cabstr;
        '        CABSTRBLOB cabstrblob;
        '        CALPSTR calpstr;
        '        CALPWSTR calpwstr;
        '        CAPROPVARIANT capropvar;
        '        CHAR* pcVal;
        '        UCHAR* pbVal;
        '        SHORT* piVal;
        '        USHORT* puiVal;
        '        LONG* plVal;
        '        ULONG* pulVal;
        '        INT* pintVal;
        '        UINT* puintVal;
        '        FLOAT* pfltVal;
        '        DOUBLE* pdblVal;
        '        VARIANT_BOOL* pboolVal;
        '        DECIMAL* pdecVal;
        '        SCODE* pscode;
        '        CY* pcyVal;
        '        DATE* pdate;
        '        BSTR* pbstrVal;
        '        IUnknown** ppunkVal;
        '        IDispatch** ppdispVal;
        '        LPSAFEARRAY* pparray;
        '        PROPVARIANT* pvarVal;
        '        
        ''' <summary>
        ''' Helper method to gets blob data
        ''' </summary>
        Private Function GetBlob() As Byte()
            Dim Result As Byte() = New Byte(blobVal.Length - 1) {}
            Marshal.Copy(blobVal.Data, Result, 0, Result.Length)
            Return Result
        End Function
        ''' <summary>
        ''' Property value
        ''' </summary>
        Public ReadOnly Property Value() As Object
            Get
                Dim ve As VarEnum = vt
                Select Case ve
                    Case VarEnum.VT_I1
                        Return bVal
                    Case VarEnum.VT_I2
                        Return iVal
                    Case VarEnum.VT_I4
                        Return lVal
                    Case VarEnum.VT_I8
                        Return hVal
                    Case VarEnum.VT_INT
                        Return iVal
                    Case VarEnum.VT_UI4
                        Return ulVal
                    Case VarEnum.VT_LPWSTR
                        Return Marshal.PtrToStringUni(pwszVal)
                    Case VarEnum.VT_BLOB
                        Return GetBlob()
                End Select
                Throw New NotImplementedException("PropVariant " + ve.ToString())
            End Get
        End Property
    End Structure
    Friend Structure Blob
        Public Length As Integer
        Public Data As IntPtr
        'Code Should Compile at warning level4 without any warnings, 
        'However this struct will give us Warning CS0649: Field [Fieldname] 
        'is never assigned to, and will always have its default value
        'You can disable CS0649 in the project options but that will disable
        'the warning for the whole project, it's a nice warning and we do want 
        'it in other places so we make a nice dummy function to keep the compiler
        'happy.
        Private Sub FixCS0649()
            Length = 0
            Data = IntPtr.Zero
        End Sub
    End Structure
#End Region
#Region "Interfaces"
    <ComImport, Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
    Interface IPropertyStore
        <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
        Sub GetCount(<Out> ByRef cProps As UInteger)
        <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
        Sub GetAt(<[In]> iProp As UInteger, ByRef pkey As PropertyKey)
        <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
        Sub GetValue(<[In]> ByRef key As PropertyKey, ByRef pv As PropVariant)
        <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
        Sub SetValue(<[In]> ByRef key As PropertyKey, <[In]> ByRef pv As PropVariant)
        <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
        Sub Commit()
        <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
        Sub Release()
    End Interface
#End Region
#Region "Methods"
    <DllImport("shell32.dll", SetLastError:=True)> _
    Private Shared Function SHGetPropertyStoreForWindow(handle As IntPtr, ByRef riid As Guid, ByRef propertyStore As IPropertyStore) As Integer
    End Function
    Public Shared Sub EnableEdgeGestures(ByVal hwnd As IntPtr, ByVal enable As Boolean)
        Dim pPropStore As IPropertyStore = Nothing
        Dim hr As Integer
        hr = SHGetPropertyStoreForWindow(hwnd, IID_PROPERTY_STORE, pPropStore)
        If hr = 0 Then
            Dim propKey As New PropertyKey
            propKey.fmtid = DISABLE_TOUCH_SCREEN
            propKey.pid = 2
            Dim var As New PropVariant
            var.vt = VT_BOOL
            var.boolVal = enable
            pPropStore.SetValue(propKey, var)
            Marshal.FinalReleaseComObject(pPropStore)
        End If
    End Sub
#End Region
End Class

更好、最简单的方法是在启动应用程序时更改2个注册表项,并在关闭应用程序时将其恢复?

您只需要在以下位置创建(如果不存在)EdgeUI密钥:

HKEY_CURRENT_USER''Software''Microsoft''Windows''CurrentVersion''ImmersiveShell

并添加新的DWORD键:DisableTLcorner&禁用字符提示

禁用:

DisableTLcorner=1 DisableCharmsHint=1

对于启用更改为零或删除它们:

DisableTLcorner=0 DisableCharmsHint=0

所有这些都可以使用任何语言在编程中轻松完成!!!!

简单的解决方案,并不完美,每次激活魅力栏时,您的应用程序都会被停用,因此立即重新激活它,魅力栏就会消失。将其添加到您的App.xaml.cs 中

 private enum WindowShowStyle : uint
    {  // find more info at http://stackoverflow.com/a/8210120/1245420
        Hide = 0, ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3,
        ShowNormalNoActvate = 4, Show = 5, Minimize = 6, ShowNoActivate = 8,
        Restore = 9, ShowDefault = 10, ForceMinimized = 11
    }
    [DllImport("user32.dll", SetLastError = true)]
    static extern System.IntPtr FindWindow(string lpClassName, string lpWindowName);
    [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
    static extern System.IntPtr FindWindowByCaption(System.IntPtr ZeroOnly, string lpWindowName);
    [DllImport("user32.dll")]
    static extern bool ShowWindow(System.IntPtr hWnd, WindowShowStyle nCmdShow);
    DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
    public App()
    {
        this.Deactivated += App_Deactivated;
        this.Activated += App_Activated;
        timer.Tick += delegate
        {
            Application.Current.MainWindow.Activate();
            System.IntPtr hWndCharmBar = FindWindowByCaption(System.IntPtr.Zero, "Charm Bar");
                            ShowWindow(hWndCharmBar, 0);
        };
        timer.Interval = new TimeSpan(0, 0, 0, 0, 10);
    }
    void App_Activated(object sender, EventArgs e)
    {
        timer.Stop();
    }
    void App_Deactivated(object sender, EventArgs e)
    {
        timer.Start();
    }