Показать сенсорную клавиатуру (TabTip.exe) в Windows 10 Anniversary Edition

В Windows 8 и Windows 10 до обновления Anniversary можно было показывать сенсорную клавиатуру, запустив

C:\Program Files\Common Files\microsoft shared\ink\TabTip.exe

Это больше не работает в Windows 10 Anniversary Update; TabTip.exe процесс запущен, но клавиатура не отображается.

Есть ли способ показать это программно?

ОБНОВИТЬ

Я нашел обходной путь - фальшивый щелчок мышью по иконке сенсорной клавиатуры в системном трее. Вот код в Delphi

// Find tray icon window
function FindTrayButtonWindow: THandle;
var
  ShellTrayWnd: THandle;
  TrayNotifyWnd: THandle;
begin
  Result := 0;
  ShellTrayWnd := FindWindow('Shell_TrayWnd', nil);
  if ShellTrayWnd > 0 then
  begin
    TrayNotifyWnd := FindWindowEx(ShellTrayWnd, 0, 'TrayNotifyWnd', nil);
    if TrayNotifyWnd > 0 then
    begin
      Result := FindWindowEx(TrayNotifyWnd, 0, 'TIPBand', nil);
    end;
  end;
end;

// Post mouse click messages to it
TrayButtonWindow := FindTrayButtonWindow;
if TrayButtonWindow > 0 then
begin
  PostMessage(TrayButtonWindow, WM_LBUTTONDOWN, MK_LBUTTON, $00010001);
  PostMessage(TrayButtonWindow, WM_LBUTTONUP, 0, $00010001);
end;

ОБНОВЛЕНИЕ 2

Еще одна вещь, которую я обнаружил, заключается в том, что установка этого раздела реестра восстанавливает старую функциональность при запуске TabTip.exe показывает сенсорную клавиатуру

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\TabletTip\1.7\EnableDesktopModeAutoInvoke=1

15 ответов

Хорошо, я изменил то, что делает проводник, когда пользователь нажимает эту кнопку в системном трее.

В основном это создает экземпляр недокументированного интерфейса ITipInvocation и называет его Toggle(HWND) метод, передавая окно рабочего стола в качестве аргумента. Как следует из названия, метод отображает или скрывает клавиатуру в зависимости от ее текущего состояния.

Обратите внимание, что проводник создает экземпляр ITipInvocation при каждом нажатии кнопки. Поэтому я считаю, что экземпляр не следует кэшировать. Я также заметил, что исследователь никогда не звонит Release() на полученном экземпляре. Я не слишком знаком с COM, но это похоже на ошибку.

Я проверил это в Windows 8.1, Windows 10 и Windows 10 Anniversary Edition, и он отлично работает. Вот минимальный пример на C, в котором явно отсутствуют некоторые проверки ошибок.

#include <initguid.h>
#include <Objbase.h>
#pragma hdrstop

// 4ce576fa-83dc-4F88-951c-9d0782b4e376
DEFINE_GUID(CLSID_UIHostNoLaunch,
    0x4CE576FA, 0x83DC, 0x4f88, 0x95, 0x1C, 0x9D, 0x07, 0x82, 0xB4, 0xE3, 0x76);

// 37c994e7_432b_4834_a2f7_dce1f13b834b
DEFINE_GUID(IID_ITipInvocation,
    0x37c994e7, 0x432b, 0x4834, 0xa2, 0xf7, 0xdc, 0xe1, 0xf1, 0x3b, 0x83, 0x4b);

struct ITipInvocation : IUnknown
{
    virtual HRESULT STDMETHODCALLTYPE Toggle(HWND wnd) = 0;
};

int WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HRESULT hr;
    hr = CoInitialize(0);

    ITipInvocation* tip;
    hr = CoCreateInstance(CLSID_UIHostNoLaunch, 0, CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER, IID_ITipInvocation, (void**)&tip);
    tip->Toggle(GetDesktopWindow());
    tip->Release();
    return 0;
}

Вот также версия C#:

class Program
{
    static void Main(string[] args)
    {
        var uiHostNoLaunch = new UIHostNoLaunch();
        var tipInvocation = (ITipInvocation)uiHostNoLaunch;
        tipInvocation.Toggle(GetDesktopWindow());
        Marshal.ReleaseComObject(uiHostNoLaunch);
    }

    [ComImport, Guid("4ce576fa-83dc-4F88-951c-9d0782b4e376")]
    class UIHostNoLaunch
    {
    }

    [ComImport, Guid("37c994e7-432b-4834-a2f7-dce1f13b834b")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface ITipInvocation
    {
        void Toggle(IntPtr hwnd);
    }

    [DllImport("user32.dll", SetLastError = false)]
    static extern IntPtr GetDesktopWindow();
}

Обновление: согласно комментариям @EugeneK, я считаю, что tabtip.exe является COM-сервером для рассматриваемого COM-компонента, поэтому, если ваш код получает REGDB_E_CLASSNOTREGдолжно быть tabtip.exe и попробуй еще раз.

У меня тоже была такая же проблема. Мне потребовалось много времени и головной боли, но благодаря Алексею и Торвину я наконец-то заработал на Win 10 1709. Проверка видимости была трудностью. Возможно, OSKlib Nuget может быть обновлен. Позвольте мне подвести итоги полного sulotion (наверняка мой код теперь имеет несколько ненужных строк):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;

using Osklib.Interop;
using System.Runtime.InteropServices;
using System.Threading;

namespace OSK
{
    public static class OnScreenKeyboard
    {
        static OnScreenKeyboard()
        {
            var version = Environment.OSVersion.Version;
            switch (version.Major)
            {
                case 6:
                    switch (version.Minor)
                    {
                        case 2:
                            // Windows 10 (ok)
                            break;
                    }
                    break;
                default:
                    break;
            }
        }

        private static void StartTabTip()
        {
            var p = Process.Start(@"C:\Program Files\Common Files\Microsoft Shared\ink\TabTip.exe");
            int handle = 0;
            while ((handle = NativeMethods.FindWindow("IPTIP_Main_Window", "")) <= 0)
            {
                Thread.Sleep(100);
            }
        }

        public static void ToggleVisibility()
        {
            var type = Type.GetTypeFromCLSID(Guid.Parse("4ce576fa-83dc-4F88-951c-9d0782b4e376"));
            var instance = (ITipInvocation)Activator.CreateInstance(type);
            instance.Toggle(NativeMethods.GetDesktopWindow());
            Marshal.ReleaseComObject(instance);
        }

        public static void Show()
        {
            int handle = NativeMethods.FindWindow("IPTIP_Main_Window", "");
            if (handle <= 0) // nothing found
            {
                StartTabTip();                
                Thread.Sleep(100);                
            }
            // on some devices starting TabTip don't show keyboard, on some does  ¯\_(ツ)_/¯
            if (!IsOpen())
            {
                ToggleVisibility();
            }
        }

        public static void Hide()
        {
            if (IsOpen())
            {
                ToggleVisibility();
            }
        }        


        public static bool Close()
        {
            // find it
            int handle = NativeMethods.FindWindow("IPTIP_Main_Window", "");
            bool active = handle > 0;
            if (active)
            {
                // don't check style - just close
                NativeMethods.SendMessage(handle, NativeMethods.WM_SYSCOMMAND, NativeMethods.SC_CLOSE, 0);
            }
            return active;
        }

        public static bool IsOpen()
        {
            return GetIsOpen1709() ?? GetIsOpenLegacy();
        }


        [DllImport("user32.dll", SetLastError = false)]
        private static extern IntPtr FindWindowEx(IntPtr parent, IntPtr after, string className, string title = null);

        [DllImport("user32.dll", SetLastError = false)]
        private static extern uint GetWindowLong(IntPtr wnd, int index);

        private static bool? GetIsOpen1709()
        {
            // if there is a top-level window - the keyboard is closed
            var wnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, WindowClass1709, WindowCaption1709);
            if (wnd != IntPtr.Zero)
                return false;

            var parent = IntPtr.Zero;
            for (;;)
            {
                parent = FindWindowEx(IntPtr.Zero, parent, WindowParentClass1709);
                if (parent == IntPtr.Zero)
                    return null; // no more windows, keyboard state is unknown

                // if it's a child of a WindowParentClass1709 window - the keyboard is open
                wnd = FindWindowEx(parent, IntPtr.Zero, WindowClass1709, WindowCaption1709);
                if (wnd != IntPtr.Zero)
                    return true;
            }
        }

        private static bool GetIsOpenLegacy()
        {
            var wnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, WindowClass);
            if (wnd == IntPtr.Zero)
                return false;

            var style = GetWindowStyle(wnd);
            return style.HasFlag(WindowStyle.Visible)
                && !style.HasFlag(WindowStyle.Disabled);
        }

        private const string WindowClass = "IPTip_Main_Window";
        private const string WindowParentClass1709 = "ApplicationFrameWindow";
        private const string WindowClass1709 = "Windows.UI.Core.CoreWindow";
        private const string WindowCaption1709 = "Microsoft Text Input Application";

        private enum WindowStyle : uint
        {
            Disabled = 0x08000000,
            Visible = 0x10000000,
        }

        private static WindowStyle GetWindowStyle(IntPtr wnd)
        {
            return (WindowStyle)GetWindowLong(wnd, -16);
        }

    }


    [ComImport]
    [Guid("37c994e7-432b-4834-a2f7-dce1f13b834b")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface ITipInvocation
    {
        void Toggle(IntPtr hwnd);
    }

    internal static class NativeMethods
    {
        [DllImport("user32.dll", EntryPoint = "FindWindow")]
        internal static extern int FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", EntryPoint = "SendMessage")]
        internal static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);

        [DllImport("user32.dll", EntryPoint = "GetDesktopWindow", SetLastError = false)]
        internal static extern IntPtr GetDesktopWindow();

        [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
        internal static extern int GetWindowLong(int hWnd, int nIndex);

        internal const int GWL_STYLE = -16;
        internal const int GWL_EXSTYLE = -20;        
        internal const int WM_SYSCOMMAND = 0x0112;
        internal const int SC_CLOSE = 0xF060;

        internal const int WS_DISABLED = 0x08000000;

        internal const int WS_VISIBLE = 0x10000000;

    }
}

Я обнаружил 4 ситуации при попытке открыть сенсорную клавиатуру в Windows 10 Anniversary Update

  1. Клавиатура видна - когда присутствует "IPTIP_Main_Window", НЕ отключена и не видна
  2. Клавиатура не видна - когда IPTIP_Main_Window присутствует, но отключен
  3. Клавиатура не видна - когда "IPTIP_Main_Window" присутствует, но НЕ отключен и НЕ виден
  4. Клавиатура не видна - когда "IPTIP_Main_Window" НЕ присутствует

1 - ничего не делать

2+3 - активация через COM

4 - самый интересный сценарий. На некоторых устройствах запуск TabTip открывает сенсорную клавиатуру, на некоторых - нет. Поэтому мы должны запустить процесс TabTip, дождаться появления окна "IPTIP_Main_Window", проверить его на видимость и активировать через COM, если это необходимо.

Я делаю небольшую библиотеку для своего проекта, вы можете использовать ее - osklib

Единственное решение, которое я нашел для работы, - это отправка PostMessage, как вы упомянули в ответе 1. Вот его версия на C# на тот случай, если кому-то это понадобится.

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
    private static extern IntPtr FindWindow(string sClassName, string sAppName);

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
    static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle); 

[DllImport("User32.Dll", EntryPoint = "PostMessageA")]
    static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);

var trayWnd = FindWindow("Shell_TrayWnd", null);
var nullIntPtr = new IntPtr(0);

if (trayWnd != nullIntPtr)
{
    var trayNotifyWnd = FindWindowEx(trayWnd, nullIntPtr, "TrayNotifyWnd", null);
    if (trayNotifyWnd != nullIntPtr)
    {
        var tIPBandWnd = FindWindowEx(trayNotifyWnd, nullIntPtr, "TIPBand", null);

        if (tIPBandWnd != nullIntPtr)
        {
            PostMessage(tIPBandWnd, (UInt32)WMessages.WM_LBUTTONDOWN, 1, 65537);
            PostMessage(tIPBandWnd, (UInt32)WMessages.WM_LBUTTONUP, 1, 65537);
        }
    }
}


public enum WMessages : int
{
    WM_LBUTTONDOWN = 0x201,
    WM_LBUTTONUP = 0x202,
    WM_KEYDOWN = 0x100,
    WM_KEYUP = 0x101,
    WH_KEYBOARD_LL = 13,
    WH_MOUSE_LL = 14,
}

Следующий код всегда будет работать, так как он использует последнюю версию MS Api
Я положил его в DLL (необходимо для проекта Delphi), но это простой C
Также полезно для получения размера клавиатуры и настройки раскладки приложения

//*******************************************************************
//
// RETURNS KEYBOARD RECTANGLE OR EMPTY ONE IF KEYBOARD IS NOT VISIBLE
//
//*******************************************************************
RECT __stdcall  GetKeyboardRect()
{
    IFrameworkInputPane *inputPane = NULL;
    RECT prcInputPaneScreenLocation = { 0,0,0,0 };
    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);    
    if (SUCCEEDED(hr))
    {
        hr = CoCreateInstance(CLSID_FrameworkInputPane, NULL, CLSCTX_INPROC_SERVER, IID_IFrameworkInputPane, (LPVOID*)&inputPane);
        if (SUCCEEDED(hr))
        {
            hr=inputPane->Location(&prcInputPaneScreenLocation);
            if (!SUCCEEDED(hr))
            {                   
            }
            inputPane->Release();
        }
    }       
    CoUninitialize();   
    return prcInputPaneScreenLocation;
}

До сих пор остается загадкой, как сенсорная клавиатура отображается в Windows 10 Anniversary Update. На самом деле у меня точно такая же проблема, и вот последние сведения, которые я нашел:

  • Windows 10 1607 работает в двух режимах: рабочий стол и планшет. В режиме рабочего стола TabTip.exe может вызываться, но не отображается. В режиме планшета все работает нормально: TabTip.exe показывает себя при вызове. Таким образом, 100% работающий обходной путь - установить компьютер в режиме планшета, но кто хочет, чтобы его настольный компьютер / ноутбук работал в режиме планшета? Во всяком случае, не я!

  • Вы можете использоватьEnableDesktopModeAutoInvoke"Клавиша (HKCU, DWORD установлена ​​в 1) и на некоторых компьютерах под управлением 1607 она отлично работала в режиме рабочего стола. Но по неизвестным причинам она не работает на моей сенсорной панели HP.

Обратите внимание, что этот параметр реестра является параметром "Показывать сенсорную клавиатуру в режиме рабочего стола, если нет подключенной клавиатуры" в параметрах Windows> сенсорный

  • Вы можете использовать код Торвина, чтобы показать TabTip.exe (как уже упоминалось, TabTip.exe должен быть запущен, когда вы выполняете работу с COM), он отлично работает на некоторых компьютерах под управлением 1607 (включая мой тачпад HP! Уя!), Но он ничего не будет делать на некоторых других comps с теми же окнами Build.

Пока что протестировано на 4 разных компьютерах, и я не могу заставить что-то работать на всех...

Проблема, кажется, с настройкой ОС Windows. Я столкнулся с той же проблемой с приложением, которое я разрабатывал. В Windows 8 и 10 (до обновления) код, который вызывал клавиатуру, работал нормально, но после обновления работать не удалось. Прочитав эту статью, я сделал следующее:

  1. Нажмите Win+I, чтобы открыть приложение Настройки

  2. Нажмите на Устройства> Набор текста

  3. Включено "Автоматически показывать сенсорную клавиатуру в оконных приложениях, когда к вашему устройству не подключена клавиатура".

    Сразу после этого клавиатура начинает появляться и в Windows 10.

Реализация IValueProvider/ITextProvider в вашем контроле является правильным способом достижения этого, как описано здесь: /questions/31726237/kak-ispolzovat-windows-na-ekrannoj-klaviature-v-c-winforms/31726259#31726259

Я пробовал несколько вещей, которые не помогли. Но я обнаружил, что могу использовать сочетания клавиш Windows/Ctrl/O, чтобы открыть экранную клавиатуру.
Также существует пакет Nuget: Input Simulator от Майкла Нунана.

Если вы устанавливаете NuGet-пакет InputSimulator в свой проект Winforms, добавьте к событию такой код, как кнопку:

private void button1_Click(object sender, EventArgs e)
{
    var simu = new InputSimulator();
    simu.Keyboard.ModifiedKeyStroke(new[] { VirtualKeyCode.LWIN, VirtualKeyCode.CONTROL }, VirtualKeyCode.VK_O);
}

Вам также нужно будет добавить эти операторы using:

using WindowsInput;
using WindowsInput.Native;

Запустите ваше приложение, и кнопка отобразит клавиатуру, а также нажмите ее еще раз, и она удалит ее.

Я использую Windows 10 и против 2019.

      Set oShell = CreateObject("WScript.Shell")
oShell.AppActivate "Program Manager"
oShell.Run "tabtip.exe", 0, true
oShell.SendKeys "%{TAB}"

[HKEY_CURRENT_USER\SOFTWARE\Microsoft\TabletTip\1.7] "EnableDesktopModeAutoInvoke"=dword:00000001

Следующий код хорошо работает на планшете и ноутбуке версии 21h1, спасибо за метод @torvin

      #include <dwmapi.h>
#include <windows.h>

#pragma comment(lib,"dwmapi.lib")

void toggleKeyboardShowState()
{
    if(FindWindowEx(nullptr,nullptr,L"IPTip_Main_Window",nullptr)!=nullptr)
    {
        ITipInvocation *tip_invocation_;
        if(CoCreateInstance(CLSID_UIHostNoLaunch,nullptr,CLSCTX_INPROC_HANDLER|CLSCTX_LOCAL_SERVER,IID_ITipInvocation,(void **)&tip_invocation_)==S_OK)
            tip_invocation_->Toggle(GetDesktopWindow());
        return;
    }
    PVOID OldValue=nullptr;
    BOOL bRet=Wow64DisableWow64FsRedirection(&OldValue);
    ShellExecute(nullptr,L"open",L"C:\\Program Files\\Common Files\\microsoft shared\\ink\\TabTip.exe",nullptr,nullptr,SW_SHOWNORMAL);
    if(bRet)
        Wow64RevertWow64FsRedirection(OldValue);
}

bool keyboardIsShow()
{
    int cloaked=0;
    return DwmGetWindowAttribute(FindWindowExW(FindWindowExW(nullptr,nullptr,L"ApplicationFrameWindow",nullptr),nullptr,L"Windows.UI.Core.CoreWindow",L"Microsoft Text Input Application"),DWMWA_CLOAKED,&cloaked,DWM_CLOAKED_INHERITED)==S_OK?0==cloaked:false;
}

Он запустится и покажет taptip и покажет его по умолчанию, если он не находится в фоновом режиме при вызове toggleKeyboardShowState(), в противном случае измените состояние отображения taptip.

запустить процесс табуляции или скрыть-> показать

      if(!keyboardIsShow())
    toggleKeyboardShowState();

показать-> скрыть

      if(keyboardIsShow())
    toggleKeyboardShowState();

Состояние отображения клавиатуры можно переключать даже без суждения.

Инновационная сенсорная клавиатура с помощью TabTip.exe требует добавления нескольких значений в реестр.

Прежде чем мы вызовем TapTip через CMD

«C:\Program Files\Common Files\microsoft Shared\ink\TabTip.exe»

Убедитесь, что приведенные ниже значения присутствуют в реестре Windows и имеют значение 1:

  1. ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ\Microsoft\TabletTip\1.7 - EnableDesktopModeAutoInvoke
  2. ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ\Microsoft\TabletTip\1.7 - DisableNewKeyboardExperience
  3. HKCU\Software\Microsoft\windows\CurrentVersion\ImmersiveShell — TabletMode

Реализация в JAVA, см. OnScreenTabletKeyboardInvoction .

Используйте этот метод:

  1. Создайте файл osk.bat и сохраните его в папке вашей программы, т.е. C:\My Software\osk.bat

  2. Введите этот osk.bat следующий cmd:

    "C:\Program Files\Common Files\Microsoft Shared\Ink\Tabtip.exe"

  3. Используйте Windows Script для запуска этого bat-файла.

    oWSH = CREATEOBJECT("wscript.shell")

    oWSH.Run("osk.bat", 0, .T.)

Чтобы избежать REGDB_E_CLASSNOTREG, я нашел это решение С#:

      Class MyClass
{
      bool tabtipon=false;

      private void RunTabtip()
      {
         if(!tabtipon)
         {
           System.Diagnostics.Process.Start("tabtip.exe");
           tabtipon=true;
         }
         else
         {
           var uiHostNoLaunch = new UIHostNoLaunch();
           var tipInvocation = (ITipInvocation)uiHostNoLaunch;
           tipInvocation.Toggle(GetDesktopWindow());
           Marshal.ReleaseComObject(uiHostNoLaunch);
         }
       }
       [ComImport, Guid("4ce576fa-83dc-4F88-951c-9d0782b4e376")]
       class UIHostNoLaunch
       {
       }

       [ComImport, Guid("37c994e7-432b-4834-a2f7-dce1f13b834b")]
       [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
       interface ITipInvocation
       {
         void Toggle(IntPtr hwnd);
       }

       [DllImport("user32.dll", SetLastError = false)]
       static extern IntPtr GetDesktopWindow();


   }

В Win10 Ver 1803, DesktopMode, нет надежного способа
включить / выключить сенсорную клавиатуру [ ITipInvocation.Toggle() ];
и при этом вы не можете надежно обнаружить, если это "вверх" (на экране)
[IFrameworkInputPane.Location ()]; Обе процедуры терпят неудачу случайно.

Вместо этого убедитесь, что "TabTIP.EXE" и "....InputApp.EXE"
запускается только когда клавиатура "вверх" (на экране).

Чтобы включить или выключить клавиатуру (из X.CPP в Jeff-Relf.Me/X.ZIP):

if ( WM == WM_HOTKEY && C == 'K' ) {

  //  A mouse button takes me here.  Jeff-Relf.Me/g600.PNG

  if ( KillProc = 1, Running( L"TabTIP.EXE" ), KillProc = 1, Running( 
      L"WindowsInternal.ComposableShell.Experiences.TextInput.InputApp.EXE"
  ) )  

    //  The keyboard was _On_ ( i.e. its processes were running ), 
    //  so it was "turned _Off_" (killed); and we're done.

    goto Done ;

  //  The keyboard was _Off_ ( i.e. no running processes ). 
  //  Turn it _On_: 

  Launch( L"%CommonProgramFiles%/microsoft shared/ink/TabTIP.EXE" );
  Sleep(99);

  static const GUID CLSID_UIHostNoLaunch = {  0x4CE576FA, 0x83DC,
    0x4f88,  0x95, 0x1C, 0x9D, 0x07, 0x82, 0xB4, 0xE3, 0x76 };
  static const GUID IID_ITipInvocation = {  0x37c994e7, 0x432b,
    0x4834, 0xa2, 0xf7, 0xdc, 0xe1, 0xf1, 0x3b, 0x83, 0x4b };
  static struct ITipInvocation : IUnknown {  virtual HRESULT 
    STDMETHODCALLTYPE  Toggle( HWND wnd ) = 0 ;  }  * Tog ;

  Tog = 0, CoCreateInstance( CLSID_UIHostNoLaunch, 0, CLSCTX_INPROC_HANDLER
    | CLSCTX_LOCAL_SERVER, IID_ITipInvocation, (void**) & Tog );

  //  Firefox and Chrome need this: 

  Tog ? Tog->Toggle( GetDesktopWindow() ), Tog->Release() : 0 ;    }
- - - - - - - - - - - - -
//  To get the process list, and kill stuff: 
#include <tlhelp32.H>

      int  KillProc ;
int Running( wchar * EXE ) {  int  Found ;  HANDLE  PIDs, aProc ;
  PROCESSENTRY32  aPID = { sizeof aPID };
  PIDs = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
  Process32First( PIDs, &aPID );
  while ( Found = !strCmpI( aPID.szExeFile, EXE ),
    KillProc && Found && ( 
      aProc = OpenProcess( PROCESS_TERMINATE, 0, aPID.th32ProcessID ),
      aProc ? TerminateProcess( aProc, 9 ), CloseHandle( aProc ) : 0 ),
    !Found && Process32Next( PIDs, &aPID ) );

  KillProc = 0, CloseHandle( PIDs );  return  Found ;   }


Launch( wchar * Cmd ) {  wchar _Cmd[333];  static PROCESS_INFORMATION Stat ;
  static STARTUPINFO SU = { sizeof SU };
  SetEnvironmentVariable( L"__compat_layer", L"RunAsInvoker" );
  ExpandEnvironmentStrings( Cmd, _Cmd, 333 ), Cmd = _Cmd ;
  if ( CreateProcess( 0, Cmd, 0,0,1,0,0,0, &SU , &Stat ) )
    CloseHandle( Stat.hProcess ), CloseHandle( Stat.hThread );  }

//  CoInitialize(0);
Другие вопросы по тегам