【问题标题】:windows desktop new folder c++windows桌面新文件夹c++
【发布时间】:2020-09-08 04:56:26
【问题描述】:

目的: Windows 资源管理器(桌面)中的新文件夹创建功能 (图标坐标设置+标签校正)

我想知道如何创建一个新文件夹,如 Windows Explorer(桌面)。

想知道和“桌面右键→新建→文件夹”一样的功能。

我想要的是让它到特定的坐标。

++ 如果你也能修改标签就更好了。

我就是这样做的。

CreateDirectory → FindWindow (桌面列表视图) → SendMessage (LVM_SETITEMPOSITION)

但是当我执行CreateDirectory 时,它在桌面上显得太慢了。 (默认 1000 毫秒或更长)

所以我尝试了SHChangeNotify,但它看起来很慢。

该源代码的功能是将鼠标移动到桌面上的特定位置并按下快捷方式以创建具有该坐标的文件夹。 但是,我可以看到该文件夹​​显示缓慢且移动 (SendMessage (LVM_SETITEMPOSITION))。

// this is Console Application
HWND hDesk = FindWindow(NULL, L"Program Manager");
HWND hDesk2 = FindWindowEx(hDesk, NULL, L"SHELLDLL_DefView", NULL);
HWND hListView = FindWindowEx(hDesk2, NULL, L"SysListView32", NULL);

int iconCount = (int)SendMessage(hListView, LVM_GETITEMCOUNT, NULL, NULL);

printf("컨트롤(Control) + F2\n");
RegisterHotKey(NULL, 1, MOD_CONTROL, VK_F2);

MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
    PeekMessage(&msg, 0, 0, 0, 0x0001);
    switch (msg.message)
    {
    case WM_HOTKEY:
        if (msg.wParam == 1)
        {
            printf("ㅇㅋ 누름 (Hotkey Event)\n");
            int a = SendMessage(hListView, LVM_GETITEMCOUNT, 0, 0);
            int b;
            int ms = GetTickCount();
            CreateDirectory(L"C:\\Users\\root\\Desktop\\new Folder", NULL);
            //SendMessage(hListView, LVM_REDRAWITEMS, 0, a+5);
            //SendMessage(hListView, LVM_UPDATE, a, 0);
            //SHChangeNotify(SHCNE_MKDIR, SHCNF_IDLIST| SHCNF_PATHW, L"C:\\Users\\root\\Desktop", NULL);
            while (true)
            {
                b = SendMessage(hListView, LVM_GETITEMCOUNT, 0, 0);
                if (a != b) {
                    ms = GetTickCount() - ms;
                    break;
                }
            }
            Sleep(1);
            POINT mouse;
            GetCursorPos(&mouse);
            SendMessage(hListView, LVM_SETITEMPOSITION, b - 1, MAKEWPARAM(mouse.x, mouse.y));
            SendMessage(hListView, LVM_EDITLABEL, b - 1, 0);

        }

    }
}

我认为CreateDirectory 是问题所在,并尝试使用NtCreateFile(用户空间/Ring3)创建一个目录,但它仍然很慢。 图标在桌面上仍然显示缓慢。

有 WinAPI / DesktopAPI / COM / ATL 吗?

【问题讨论】:

  • 不确定您到底想做什么。您希望“新建...”菜单出现吗?或者您想在给定的 Shell 视图中创建一个文件夹?跟坐标有什么关系?您可以使用“Scriptable Shell Objects”(又名“Shell Objects for Scripting”)使用 shell 方法创建文件夹:docs.microsoft.com/en-us/windows/win32/shell/folder-newfolder
  • 我英语说得不好。对不起。我想要做的是在 C++ 代码中创建一个“桌面右键单击-> 新建-> 文件夹”。我有一个 CreateDirectory WinAPI,但它没有设置桌面的位置。您可以使用 SendMessage LVM_SETITEMPOSITION 设置坐标。但是,由于 CreateDirectory 存在延迟。有什么办法可以加快速度吗?还是有别的办法?
  • @Simon Mourier 我也尝试过使用 Shell Object,但它在桌面上仍然显得很慢。
  • 嗨@mp662002,答案是否解决了您的问题?如果有帮助,请随时accept

标签: winapi com icons desktop windows-shell


【解决方案1】:

这是一个模拟什么是新...文件夹菜单在控制台应用程序中的作用的代码。

它打开某个文件夹的视图并在其中创建一个子文件夹,然后进入名称编辑模式。它使用 Shell 的 IFileOperation interfaceATL's smart pointers 只是为了简单。

int main()
{
  CoInitialize(NULL);
  {
    CComHeapPtr<ITEMIDLIST> pidl;
    CComHeapPtr<ITEMIDLIST> newFolderPidl;
    CComPtr<IFileOperationProgressSink> sink;
    CComPtr<IFileOperation> fo;
    CComPtr<IShellItem> folder;
    LPCITEMIDLIST pidls = { nullptr };
    CFileOperationProgressSink csink;

    // get some folder's PIDL
    HRESULT hr = SHParseDisplayName(L"c:\\temp", NULL, &pidl, 0, NULL);
    if (SUCCEEDED(hr))
    {
      // open it and, for demo purposes here, selects nothing (pass a terminator PIDL)
      ITEMIDLIST idl = { 0 };
      pidls = { &idl };
      hr = SHOpenFolderAndSelectItems(pidl, 1, &pidls, 0);
      if (SUCCEEDED(hr))
      {
        // get a Shell Item from this PIDL
        hr = SHCreateItemFromIDList(pidl, IID_PPV_ARGS(&folder));
      }
    }

    if (SUCCEEDED(hr))
    {
      // we want to operate on files and directory using Shell's API
      hr = fo.CoCreateInstance(CLSID_FileOperation);
      if (SUCCEEDED(hr))
      {
        csink.QueryInterface(IID_PPV_ARGS(&sink));

        // create the new folder "New Folder", using the sink
        // we need a sink to be advised of what really is the new folder
        // we can't use the name we've passed
        // because it could have been changed like 'New Folder (2)' if there's already a 'New Folder', etc.
        hr = fo->NewItem(folder, FILE_ATTRIBUTE_DIRECTORY, L"New Folder", NULL, sink);
        if (SUCCEEDED(hr))
        {
          // commit
          hr = fo->PerformOperations();
        }
      }
    }

    if (SUCCEEDED(hr))
    {
      // we want the new child's relative-to-the-parent PIDL
      CComPtr<IParentAndItem> pai;
      hr = csink.m_newItem->QueryInterface(&pai);
      if (SUCCEEDED(hr))
      {
        hr = pai->GetParentAndItem(NULL, NULL, &newFolderPidl);
      }
    }

    if (SUCCEEDED(hr))
    {
      // now, select the new child and get into name-edit mode (from the parent again)
      pidls = { newFolderPidl };
      hr = SHOpenFolderAndSelectItems(pidl, 1, &pidls, OFASI_EDIT);
    }
  }

  CoUninitialize();
  return 0;
}

// the sink. this implementation's only interested by PostNewItem
class CFileOperationProgressSink : public IFileOperationProgressSink
{
  LONG m_cRef;

public:
  CComPtr<IShellItem> m_newItem;

  CFileOperationProgressSink() : m_cRef(1)
  {
  }

  STDMETHOD(QueryInterface)(REFIID riid, void** ppv)
  {
    static const QITAB qit[] =
    {
      QITABENT(CFileOperationProgressSink, IFileOperationProgressSink),
      { 0 },
    };
    return QISearch(this, qit, riid, ppv);
  }

  STDMETHOD_(ULONG, AddRef)() { return InterlockedIncrement(&m_cRef); }
  STDMETHOD_(ULONG, Release)()
  {
    if (InterlockedDecrement(&m_cRef))
      return m_cRef;

    delete this;
    return 0;
  }

  STDMETHOD(StartOperations)() { return S_OK; };
  STDMETHOD(FinishOperations)(HRESULT hrResult) { return S_OK; };
  STDMETHOD(PreRenameItem)(DWORD dwFlags, IShellItem* psiItem, LPCWSTR pszNewName) { return S_OK; };
  STDMETHOD(PostRenameItem)(DWORD dwFlags, IShellItem* psiItem, LPCWSTR pszNewName, HRESULT hrRename, IShellItem* psiNewlyCreated) { return S_OK; };
  STDMETHOD(PreMoveItem)(DWORD dwFlags, IShellItem* psiItem, IShellItem* psiDestinationFolder, LPCWSTR pszNewName) { return S_OK; };
  STDMETHOD(PostMoveItem)(DWORD dwFlags, IShellItem* psiItem, IShellItem* psiDestinationFolder, LPCWSTR pszNewName, HRESULT hrMove, IShellItem* psiNewlyCreated) { return S_OK; };
  STDMETHOD(PreCopyItem)(DWORD dwFlags, IShellItem* psiItem, IShellItem* psiDestinationFolder, LPCWSTR pszNewName) { return S_OK; };
  STDMETHOD(PostCopyItem)(DWORD dwFlags, IShellItem* psiItem, IShellItem* psiDestinationFolder, LPCWSTR pszNewName, HRESULT hrCopy, IShellItem* psiNewlyCreated) { return S_OK; };
  STDMETHOD(PreDeleteItem)(DWORD dwFlags, IShellItem* psiItem) { return S_OK; };
  STDMETHOD(PostDeleteItem)(DWORD dwFlags, IShellItem* psiItem, HRESULT hrDelete, IShellItem* psiNewlyCreated) { return S_OK; };
  STDMETHOD(PreNewItem)(DWORD dwFlags, IShellItem* psiDestinationFolder, LPCWSTR pszNewName) { return S_OK; };
  STDMETHOD(PostNewItem)(DWORD dwFlags, IShellItem* psiDestinationFolder, LPCWSTR pszNewName, LPCWSTR pszTemplateName, DWORD dwFileAttributes, HRESULT hrNew, IShellItem* psiNewItem)
  {
    if (SUCCEEDED(hrNew))
    {
      psiNewItem->QueryInterface(&m_newItem);
    }
    return S_OK;
  }
  STDMETHOD(UpdateProgress)(UINT iWorkTotal, UINT iWorkSoFar) { return S_OK; };
  STDMETHOD(ResetTimer)() { return S_OK; };
  STDMETHOD(PauseTimer)() { return S_OK; };
  STDMETHOD(ResumeTimer)() { return S_OK; };
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-18
    • 1970-01-01
    • 2016-01-30
    • 2015-01-09
    • 1970-01-01
    • 2021-12-14
    相关资源
    最近更新 更多