AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 78500989
Accepted
jtxkopt - Stand With Palestine
jtxkopt - Stand With Palestine
Asked: 2024-05-19 05:01:52 +0800 CST2024-05-19 05:01:52 +0800 CST 2024-05-19 05:01:52 +0800 CST

Abrindo pasta em uma nova guia da janela Shell existente

  • 772

Nota : Esta questão se aplica apenas ao Windows 11.

Quero abrir uma pasta em uma nova guia de uma janela de shell existente. Parece que não existe uma API oficial.

Eu tentei dois métodos:

A primeira, mais óbvia, foi a ShellExecutefunção com o verbo opennewtab(Este verbo vem de dentro da chave Shell da pasta ProgID no registro - [HKEY_CLASSES_ROOT\Folder\shell\opennewtab]). Mas não funcionou. A função apenas abre uma nova janela para a pasta.

Para uma segunda chance, examinei o opennewtabverbo no registro. É implementado como um IExecuteCommand(através de DelegateExecute). Portanto, minha segunda tentativa foi recuperar as interfaces de seu servidor COM , definir os parâmetros necessários por meio dos métodos que eles fornecem (a SetXXXfamília de funções para IExecuteCommand, o Initializemétodo de IInitializeCommandetc.) e, finalmente, chamar o Executemétodo.

Para saber o que o Windows Shell passa para esses métodos e em que ordem ele os chama, implementei minha implementação de verbo personalizada e seu servidor COM , e substituí o antigo servidor COM registrado pelo opennewtabmeu servidor.

Aqui você pode ver a saída exibida pelo DebugView (minha implementação de verbo gera saídas usando OutputDebugString).

insira a descrição da imagem aqui

Como você pode ver, ele não chama todos os métodos das interfaces. Então, pensei que deveria ter sido bem fácil definir os mesmos parâmetros. Mas, sim, há algumas coisas que não levei em consideração. Essa abordagem gerou uma Nullexceção de desreferenciação sem sucesso.

Nota : Estou ciente de que o segundo é "hacky" .

Nota : O CLSIDque implementa o manipulador de verbos padrão é CLSID_ExecuteFolder.

Como podemos abrir uma pasta em uma nova aba?

windows
  • 1 1 respostas
  • 36 Views

1 respostas

  • Voted
  1. Best Answer
    Simon Mourier
    2024-05-19T22:45:37+08:002024-05-19T22:45:37+08:00

    A primeira solução é usar a UI Automation API oficial .

    Microsoft UI Automation é uma estrutura de acessibilidade que permite que aplicativos Windows forneçam e consumam informações programáticas sobre interfaces de usuário (UIs). Ele fornece acesso programático à maioria dos elementos da interface do usuário na área de trabalho. Ele permite que produtos de tecnologia assistiva, como leitores de tela, forneçam informações sobre a UI aos usuários finais e manipulem a UI por outros meios que não a entrada padrão. A UI Automation também permite que scripts de teste automatizados interajam com a UI.

    Este código abre uma c:\temppasta (ou seleciona uma já aberta) e adiciona uma nova aba à janela do Explorer:

    int main()
    {
      CoInitialize(nullptr);
    
      // get a pidl for a given folder
      LPITEMIDLIST pidl;
      if (SUCCEEDED(SHParseDisplayName(L"c:\\temp", nullptr, &pidl, 0, nullptr)))
      {
        // open the folder (or activate an already matching opened one)
        SHOpenFolderAndSelectItems(pidl, 1, (LPCITEMIDLIST*)&pidl, 0);
    
        // find window that displays this pidl
        IShellWindows* windows;
        if (SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&windows))))
        {
          // build buffer from pidl
          VARIANT url;
          VariantInit(&url);
          if (SUCCEEDED(InitVariantFromBuffer(pidl, ILGetSize(pidl), &url))) // propvarutil.h
          {
            long hwnd = 0;
            IDispatch* disp;
            VARIANT empty;
            VariantInit(&empty);
            windows->FindWindowSW(&url, &empty, SWC_BROWSER, &hwnd, 0, &disp);
            VariantClear(&url);
            VariantClear(&empty); // useless but we always pair calls
    
            if (disp) // should be null but we never know...
            {
              disp->Release();
            }
    
            if (hwnd)
            {
              //needs UIAutomationCore.h & UIAutomationClient.h
              IUIAutomation* automation;
              if (SUCCEEDED(CoCreateInstance(CLSID_CUIAutomation8, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&automation)))) // or CLSID_CUIAutomation
              {
                // get UIA element from handle
                IUIAutomationElement* window;
                automation->ElementFromHandle((UIA_HWND)(INT_PTR)hwnd, &window);
                if (window)
                {
                  // window's class should be 'ShellTabWindowClass'
                  // create inconditional "true" condition
                  IUIAutomationCondition* trueCondition;
                  automation->CreateTrueCondition(&trueCondition);
                  if (trueCondition)
                  {
                    // create a tree walker to determine window's parent
                    IUIAutomationTreeWalker* walker;
                    automation->CreateTreeWalker(trueCondition, &walker);
                    if (walker)
                    {
                      IUIAutomationElement* parent;
                      walker->GetParentElement(window, &parent);
                      if (parent)
                      {
                        // create a condition to find the first button with AutomationId property set to AddButton
                        VARIANT v;
                        V_VT(&v) = VT_BSTR;
                        V_BSTR(&v) = SysAllocString(L"AddButton");
                        IUIAutomationCondition* condition;
                        automation->CreatePropertyCondition(UIA_AutomationIdPropertyId, v, &condition);
                        VariantClear(&v);
                        if (condition)
                        {
                          IUIAutomationElement* button;
                          // search button
                          parent->FindFirst(TreeScope_Subtree, condition, &button);
                          if (button)
                          {
                            // a button implements the "Invoke" pattern
                            IUnknown* unk;
                            button->GetCurrentPattern(UIA_InvokePatternId, &unk);
                            if (unk)
                            {
                              IUIAutomationInvokePattern* pattern;
                              unk->QueryInterface(&pattern);
                              if (pattern)
                              {
                                // press the button
                                pattern->Invoke();
                                pattern->Release();
                              }
                              unk->Release();
                            }
                            button->Release();
                          }
                          condition->Release();
                        }
                        parent->Release();
                      }
                      walker->Release();
                    }
                    trueCondition->Release();
                  }
                }
                automation->Release();
              }
              CoUninitialize();
            }
          }
          windows->Release();
        }
        CoTaskMemFree(pidl);
      }
      CoUninitialize();
      return 0;
    }
    

    Para poder programar o UIA, você geralmente primeiro analisa a estrutura da janela, por exemplo, usando a ferramenta Inspect do Windows SDK ou o mais recente Accessibility Insights para entender quais ações você deve executar. Aqui está uma captura de tela de inspeção no botão "Adicionar nova guia" do Explorer em destaque que nos informa que este botão tem uma propriedade Automation Id definida como "AddButton":

    insira a descrição da imagem aqui

    PS: Às vezes, é menos óbvio porque o Automation Id nem sempre está definido.

    Outra solução é usar o WM_COMMAND0xA21B (41499) do Explorer não documentado, que solicita diretamente ao Explorer para abrir uma nova guia. Portanto, com o código de exemplo anterior, você pode simplesmente substituir todo o código UIA por este, depois de acessar a ShellTabWindowClassjanela:

    ...
    if (hwnd)
    {
      // window's class should be 'ShellTabWindowClass'
      // ask to open a new tab
      SendMessage((HWND)(INT_PTR)hwnd, WM_COMMAND, 0xA21B, 0);
    }
    ...
    

    Depois de abrir uma nova aba, ela é vista como uma nova janela (visualização), então você pode (re)começar a usar CLSID_ShellWindowsnovamente e navegar nesta nova visualização para qualquer pasta usando algo parecido com o que fiz aqui https://stackoverflow.com /a/78272475/403671 com Navigate2ligação.

    • 1

relate perguntas

  • C++ ReadFile inteiramente, onde tamanho> 2 GB (Win64)

  • BSOD do Windows Palo Alto Cortex XDR com verificação de bug 0x139

  • Não consigo importar pacotes locais no meu projeto go

  • O KERNEL32.DLL é sempre o terceiro módulo carregado em um processo do Windows?

  • Qual é o problema neste código Rust inseguro para que funcione no Windows, mas não no Ubuntu?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve