我有一台Surface Pro需要“锁定”作为一种Kiosk模式。我知道有一个更新正在为“Kiosk模式”...但是我需要在此之前这样做。
我在互联网上搜索过,但您似乎无法通过屏幕上的滑动来禁用超级按钮栏。我已经找到了禁用触控板的方法..但不幸的是,由于这款平板电脑将在没有键盘的情况下使用,我需要禁用魅力吧。
我的新想法是将整个Charm条HWND移出屏幕数千个像素,或者,可能在其上设置一个窗口样式,以便它不会出现。我试图使用Spy ++和一个基于自定义EnumWindows
的控制台应用程序给我一些Window句柄..但是我不能让Charm栏保持足够长的时间让它们生效。
所以我的问题是:如何在Windows 8中找到Charm Bar的窗口句柄(HWND
)?或者,我如何以其他方式获取对Charm栏的引用,以便向其投掷SetWindowLong
或SetWindowPos
?
答案 0 :(得分:7)
事实上,我已经找到了一种方法(显然,其他人没有:/)。
对于那些想知道的人来说,像“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
可以阻止线程粉碎CPU - 但延迟也允许Charm Bar一瞬间出现。我还没有成功打开Charm Bar并按下一个按钮,然后线程再次隐藏它,所以这很好。降低睡眠时间显然会使这更快。
Windows 8的另一个问题是,如果您有某种滑块(在我的应用中,我有一个ListBox
包含图库的图像),那么您实际上可以滑到屏幕的一侧。把手指放在那里,然后进入任务栏......
所以..下一部分是关闭任务栏:
IntPtr hWndTray = FindWindow("Shell_TrayWnd", null);
ShowWindow(hWndTray, 0);
..然后我在app close上再次显示它:
IntPtr hWndTray = FindWindow("Shell_TrayWnd", null);
ShowWindow(hWndTray, 1);
从功能上讲,这就是我的应用所需的全部内容。希望能帮助别人。
答案 1 :(得分:1)
我还要注意,时钟包含在一个标题为“时钟和日期”的窗口中。
IntPtr hWndCharmClock = FindWindowByCaption(IntPtr.Zero, "Clock and Date");
我做了一个小应用程序来切换魅力栏:https://bitbucket.org/darkwingduck/charmsbartoggle/overview
答案 2 :(得分:1)
这是在使用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
答案 3 :(得分:1)
更好,最简单的方法是在启动应用程序时更改2个注册表项,并在关闭时将其还原?
您只需要创建(如果不存在) EdgeUI 键:
HKEY_CURRENT_USER \软件\微软\的Windows \ CurrentVersion \ ImmersiveShell
并添加新的DWORD键: DisableTLcorner &amp; DisableCharmsHint
禁用:
DisableTLcorner = 1 DisableCharmsHint = 1
对于启用更改为零或删除它们:
DisableTLcorner = 0 DisableCharmsHint = 0
所有这些都可以使用任何语言在程序化中轻松完成!!!!
答案 4 :(得分:0)
简单的解决方案,并非完美,每次激活魅力栏时,您的应用程序都会停用,因此请立即重新激活它,并且魅力栏会消失。将其添加到App.xaml.cs
中WHERE col1 is MISSING