Затваряне на лентата с препратки на Windows 8

Имам Surface Pro, който трябва да „заключя“ като тип павилионен режим. Наясно съм, че предстои актуализация за „Киоск режим“. Въпреки това трябва да направя това преди това.

Търсих из целия интернет, но изглежда, че не можете да деактивирате Charm bar чрез плъзгане по екрана. Намерих начини да деактивирам тракпадовете.. но за съжаление, тъй като този таблет ще се използва без клавиатура, трябва да деактивирам лентата Charm.

Новата ми мисъл е да преместя цялата лента Charm HWND хиляди пиксели извън екрана или може би да задам стил на Windows върху нея, така че да не се показва. Опитах се да използвам Spy++ и персонализирано конзолно приложение, базирано на EnumWindows, за да ми дадат някои манипулатори на Window.. обаче не мога да държа лентата Charm отворена достатъчно дълго, за да влязат в сила.

Въпросът ми е: Как мога да намеря манипулатора на прозореца (HWND) за лентата с препратки в Windows 8? Или как мога да получа препратка към лентата Charm по някакъв друг начин, за да хвърля SetWindowLong или SetWindowPos към нея?


person Simon Whitehead    schedule 04.07.2013    source източник


Отговори (5)


Всъщност намерих начин да направя това (очевидно никой друг не е :/).

За тези, които се чудят, софтуер като "Start8" и "SkipMetroSuite" натиска клавиш за анкета, за да спре Charm Bar. Те буквално симулират натискането на клавиши, за да го затворят в стегнат цикъл.

Намерих (това, което мисля, че е) по-добър начин.

Първо... някои 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. Заглавието на прозореца за това се оказва 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
    }
});

Това работи добре и дава допълнителна полза от това, че Charm Bar продължава да работи, когато приложението е затворено. Thread.Sleep е там, за да спре нишката, която разбива процесора - но закъснението също така позволява лентата Charm да се появи за част от секундата. Предстои да отворя успешно Charm Bar и да натисна бутон достатъчно бързо, преди нишката да го скрие отново, така че това е добре. Намаляването на времето за сън очевидно прави това по-бързо.

Другият проблем с Windows 8 е, че ако имате някакъв плъзгач (в моето приложение имам ListBox, съдържащ изображения за галерия), тогава всъщност можете да плъзнете отстрани на екрана... задръжте пръста си там и достъп до лентата на задачите...

И така.. следващата част е затварянето на лентата със задачи:

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

..след това го показвам отново при затваряне на приложението:

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

Функционално, това е всичко, което ми трябваше за моето приложение. Надявам се това да помогне на някого.

person Simon Whitehead    schedule 06.07.2013
comment
Вашият цикъл while ще изяде процесора. Надяваме се, че не работите на батерия :-) Освен това NativeHWNDHost е често срещано име на клас, което не е специфично за лентата с препратки. Трябва да добавите други проверки, за да сте сигурни, че това наистина е прозорецът, който искате. - person Simon Mourier; 06.07.2013
comment
Прав си. Всъщност бях толкова развълнуван, че горният метод проработи, че прескочих малко. Скоро ще го актуализирам с новата си версия! - person Simon Whitehead; 06.07.2013
comment
@SimonMourier Благодаря за коментарите ви. Актуализирах с новата си версия :) - person Simon Whitehead; 07.07.2013
comment
Трябва трябва да има някакъв базиран на събития начин за откриване кога се отварят прозорци (и след това можете да проверите дали това е лентата с препратки или не) - person Mooing Duck; 27.08.2013
comment
Благодаря! Това беше единственото решение, което е работило досега, но как мога да намеря заглавието или името на класа на други прозорци като „горещия ъгъл“, „лявата странична лента“ и „бутона за стартиране“, които изскачат, когато задържите курсора близо до краищата . Защото трябва да се отърва и от тях!! - person Shayan RC; 26.06.2014
comment
Написах малко конзолно приложение, което изброява всички прозорци и отпечатва техните заглавия на секундата, за да намери Charm Bar. За съжаление обаче вече нямам кода. - person Simon Whitehead; 27.06.2014
comment
WindowShowStyle не е наличен в приложение winrt. Как мога да затворя прозореца? - person GermanSniper; 18.12.2014

Бих искал също да отбележа, че часовникът се съдържа в прозорец с надпис „Часовник и дата“.

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

Направих малко приложение за превключване на лентата с препратки: https://bitbucket.org/darkwingduck/charmsbartoggle/overview

person user2718558    schedule 26.08.2013

Ето как да деактивирате лентата с препратки, когато приложението е разширено с помощта на взаимодействие 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
person Ron Schuler    schedule 05.11.2014

По-добрият и лесен начин е да промените 2 ключа на системния регистър, когато стартирате приложението си и да ги възстановите обратно, когато го затворите?

Всичко, от което се нуждаете, е да създадете (ако не съществува) ключ EdgeUI под:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ImmersiveShell

и добавете нови DWORD ключове: DisableTLcorner & DisableCharmsHint

За деактивиране:

DisableTLcorner = 1 DisableCharmsHint = 1

За промяна на Активиране на нула или изтриване:

DisableTLcorner = 0 DisableCharmsHint = 0

Всичко това може лесно да се направи в programmatic с помощта на всеки език!!!!

person Joseph    schedule 03.10.2015
comment
Страхотен! Тази информация не беше налична по времето, когато първоначално зададох въпроса. Радвам се, че е много по-просто, отколкото си мислех! - person Simon Whitehead; 05.10.2015
comment
Здравейте, тук това абсолютно не помогна. Ръчно и програмно добавих тези reg ключове и все още мога да дръпна лентата с препратки и да използвам горещи ъгли в Windows 8.1. Странно нещо обаче: ключът ImmersiveShell нямаше никаква стойност, а само подключове. това нормално ли е - person Ninj; 05.11.2015

Просто решение, не е перфектно, всеки път, когато лентата с препратки се активира, вашето приложение се деактивира, така че го активирайте отново незабавно и лентата с препратки изчезва. добавете това във вашия 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();
    }
person Emmanuel    schedule 25.11.2015