在Win7上,GetOpenFileName函数忽略lpstr InitialDir参数

时间:2010-11-07 09:48:12

标签: windows-7

我正在使用GetOpenFileName并将lpstrInitialDir结构的OPENFILENAME成员设置为我想要的目录作为初始目录。但是在Win7上我的应用程序似乎记得用户上次打开的目录,它忽略lpstrInitialDir设置并转到最后一个目录。

Apparently this is by design

  

lpstrInitialDir
  LPCTSTR
  初始目录。   选择初始目录的算法在不同平台上有所不同。

     

Windows 7:

     

1.如果lpstrInitialDir具有与第一次传递的值相同的值   应用程序使用Open或Save As   对话框,最近的路径   由用户选择用作   初始目录。
  2.否则,如果lpstrFile包含路径,则该路径是初始路径   目录。
  3.否则,如果lpstrInitialDir不为NULL,则指定初始值   。目录

有谁知道如何阻止这种情况发生?

我希望我指定的目录是初始目录,而不管用户上次打开的文件是什么,即我希望上面的条件3适用。我做了显而易见的事情并通过注册表进行了搜索,但我找不到任何与此问题相关的内容。

2 个答案:

答案 0 :(得分:1)

如果将lpstrFile设置为所需的初始目录路径(即lpstrInitialDir),会发生什么。如果使用lpstrFile指定文件名,则可能需要在文件名前添加初始目录路径。

答案 1 :(得分:1)

我知道这个帖子很旧,但我最近遇到了这个问题,我找到了解决方案。 GetOpenFileName() 将上次使用的路径保存在注册表中。路径是: HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\

有两个键,我不确定实际使用哪个以及在什么情况下使用,但我从两个键中删除了我的应用程序条目。两个键是: “LastVisitedPidlMRU”和“LastVisitedPidlMRULegacy”。

应用程序名称保存为具有 16 位字符编码的 RegBinary 值(这就是它不会出现在注册表搜索中的原因...)。 我想出了以下函数来删除注册表项,从而迫使 Windows 相信我的应用程序以前从未调用过 GetOpenFileName():

void clear_path_in_registry ()
{
  char keypath[PATH_MAX];
  char *keys[] = { "LastVisitedPidlMRU", "LastVisitedPidlMRULegacy" };
#define NO_OF_KEYS (sizeof(keys)/sizeof(*keys))
  int keynr;
  HKEY hkey;
  int res;
  char val_data[BUFLEN];
  DWORD val_len, data_len;
  int i;
  char val_name[VALUELEN];
  char progname[PATH_MAX];
  char *p, *q;
  char exename[PATH_MAX];
  int index;
  int *pi , *pj;

  do_debug (1, "clear_path_in_registry()\n");

  GetModuleFileName (NULL, progname, sizeof(progname));
  p = strrchr (progname, '\\');
  if (p)
    p ++;
  strncpy (exename, p, sizeof(exename)-1);
  keynr = 0;
  do
  {
    snprintf (keypath, sizeof(keypath),
     "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\%s",
     keys[keynr]);

    res = RegOpenKeyEx (HKEY_CURRENT_USER,keypath,0,KEY_ALL_ACCESS,&hkey);
    if (res == ERROR_SUCCESS)
    {
      i = 0;
      val_len = sizeof (val_name);
      data_len = sizeof (val_data);
      while (RegEnumValue(
              hkey,i,val_name,&val_len,NULL,NULL,(BYTE *)val_data,&data_len)
        == ERROR_SUCCESS)
      {
        if (stricmp(val_name, "MRUListEx"))
        {
          /* is not the "MRUListEx" value -> extract program name
           *
           * for some (unknown) reason the program names are not stored as
           * RegSZ but rather as RegBinary values. They are encoded in some
           * dual-byte encoding. In my experiments the high bytes are
           * always 0x00; so the transcoding is simple, just skip the high
           * bytes. Probably there is a WIN32 API call for this but I did
           * dig into that for now ...
           */
          p = progname;
          q = val_data;
          while (*q)
          {
            *p++ = *q++;
            q ++;
          }
          *p = '\0';
          /* the index in the MRUList is the value name */
          index = atoi (val_name);
          if (stricmp (progname, exename) == 0)
          {
            /* found the value with current executable name -> delete it */
            res = RegDeleteValue (hkey, val_name);
            if (res == ERROR_SUCCESS)
            {
              /* delete the entry from the MRUList
               *
               * The MRUListEx value is a of the type RegBinary as well.
               * The data structure is fairly simple: just 4-byte integers
               * one after the other; -1 marks the end of the list
               */
              data_len = sizeof (val_data);
              res = RegQueryValueEx (hkey, "MRUListEx", NULL, NULL,
                                               (BYTE*)val_data, &data_len);
              if (res == ERROR_SUCCESS)
              {
                pi = (int *)val_data;
                pj = (int *)val_data;
                while (*pj != -1)
                {
                  if (*pj == index)
                  {
                    pj ++;
                    data_len -= sizeof(int);
                  }
                  *pi++ = *pj++;
                }
                *pi = *pj;
                res = RegSetValueEx (hkey, "MRUListEx", 0, REG_BINARY,
                                              (BYTE *)val_data, data_len);
                if (res != ERROR_SUCCESS)
                {
                  do_debug (1,"ERROR writing registry value 'MRUListEx'\n");
                }
              } else
              {
                do_debug (1, "ERROR reading registry value 'MRUListEx'\n");
              }
            } else
            {
              do_debug (1,"ERROR deleting registry value '%s'\n",val_name);
            }
          }
        }
        val_len = sizeof (val_name);
        data_len = sizeof (val_data);
        i ++;
      } /* iterate through registry values */
    }
    res = RegCloseKey (hkey);
    if (res != ERROR_SUCCESS)
    {
      do_debug (1, "Error closing registry key '%s'\n", keys[keynr]);
    }
    keynr ++;
  } while (keynr < NO_OF_KEYS);
}

只需在调用 GetOpenFileName() 之前调用此函数即可。

我在 Windows 10 版本 19042.1052,64 位上进行了测试。

约翰内斯