【问题标题】:How Open a user-defined extension file in Program?如何在程序中打开用户定义的扩展文件?
【发布时间】:2016-01-20 01:11:51
【问题描述】:

我正在使用 Borland C++Builder 2006 编写数据记录器 GUI 软件。这是我公司想要的平台。

在我定义的扩展名为 ".evp" 的特定文件中进行一些分析后,我正在保存收到的数据。我在我的程序中定义了保存和打开功能,效果很好。

现在我遇到了如何不使用我的软件直接打开我保存的文件的问题。我的意思是当我双击一个保存的文件时,它会用我的软件自动打开并显示数据。然后有两个问题:

  1. 我如何告诉 Windows 用我的软件打开这个“.evp”文件。
  2. 我如何在我的软件中处理打开的文件并使用我定义的 Open 函数。

【问题讨论】:

    标签: c++ windows file-association c++builder-2006


    【解决方案1】:

    Borland C2006 你的意思是Embarcadero BDS2006 Turbo(explorer) C++

    1. 文件关联存储在注册表中的某处

      Create registry entry to associate file extension with application in C++。因此,您可以通过 WinAPI 以编程方式创建 reg 文件或添加注册表项。

      我从未在我的应用程序中更新注册表,但这是您如何读取注册表(获取 CPU 频率)的示例:

      double getregfcpu()
      {
      DWORD keyhnd;
      HKEY  hKey=NULL;
      DWORD dwSize;
      DWORD dwFrequency;
      double f=0.0;
      for(;;)
          {
          keyhnd=RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Hardware\\Description\\System\\CentralProcessor\\0",0,KEY_QUERY_VALUE,&hKey);
          if (keyhnd!=ERROR_SUCCESS) break;
          dwSize = sizeof(dwFrequency);
          keyhnd = RegQueryValueEx (hKey,"~MHz",NULL,NULL,(LPBYTE)&dwFrequency,&dwSize );
          if (keyhnd!=ERROR_SUCCESS) break;
          f=dwFrequency; f*=1e6;
          break;
          }
      if (hKey!=NULL) RegCloseKey(hKey);
      return f;
      }
      

      所以实验/使用RegCreateKeyEx 而不是RegOpenKeyEx。强烈建议先在一些自己的与 Windows 无关的注册表项上进行试验,这样你就不会搞砸了。并且只有在工作时才应将条目名称更改为所需的位置。

    2. 应用端

      转到您的应用程序源文件(在 IDE 中打开项目时打开的文件)。找到 WinMain 函数并像这样更改它:

      WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR cmdl, int)
      {
          try
          {
              Application->Initialize();
              Application->Tag=(int)cmdl; // *** ADD THIS LINE ***
              Application->CreateForm(__classid(TMain), &Main);
              Application->Run();
          }
          catch (Exception &exception)
          {
              Application->ShowException(&exception);
          }
          catch (...)
          {
              try
              {
                  throw Exception("");
              }
              catch (Exception &exception)
              {
                  Application->ShowException(&exception);
              }
          }
          return 0;
      }
      

      cmdl 保存指向调用应用程序的命令行的指针。因此,将其复制到您的Application->Tag,它适用于任何用户定义的行为。通过这种方式,可以从整个项目(在任何窗口/表单中)访问 cmdl。现在要提取文件以打开您只需在 Form 构造函数中执行如下操作:

      AnsiString cmdl=(LPSTR)Application->Tag;    // access the command line parameters
      if (cmdl.Length()>2) // file is encapsulated with ""
       if (cmdl[1]=='"')
        if (cmdl[cmdl.Length()]=='"')
          {
          AnsiString s="";
          for (int i=2;i<cmdl.Length();i++) s+=cmdl[i]; // cut of the ""
          // here load file: s
          }
      

      如果您想拥有更多命令行选项,则需要先搜索“”并处理所有命令行开关来升级它...有时使用应用程序 exe 本地路径很有用。你可以像这样得到它:

      AnsiString exepath=ExtractFilePath(Application-&gt;ExeName);

    【讨论】:

    • 很好的答案,tnx。在您的表单构造函数代码中,我认为它必须更正为:cmdl[0] 而不是 cmdl[1] 和 int i=1 而不是 int i=2。因为第一个索引是 [0] 而不是 [1]。我说的对吗?
    • @HOPE AnsiString 是从1 索引的!!!如果你访问cmdl[0]你它会抛出异常!!!
    • @HOPE 那是因为它是从 TurboPascal 移植的,并且字符串从 1 开始。 ...如果您需要原始char*,那么您可以随时使用char *p=cmdl.c_str();,现在您可以使用p[0] ...
    • @HOPE 很高兴能为您提供帮助......因为您正在使用 BDS2006(我的最爱),我建议您阅读以下内容:stackoverflow.com/a/18016392/2521214
    • 天哪,这太神奇了,因为我已经为这个问题苦苦挣扎了几天,而正是因为 delete[] 和 new[] 表达式,我才意识到这个问题。但是你的解决方案很棒,干得好......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-28
    相关资源
    最近更新 更多