Открыть файл с родной программой Windows в коде C ++ - PullRequest
3 голосов
/ 26 февраля 2011

Моя программа на C ++ создает файл .png, и мне нужно открыть (просмотреть) этот файл сразу после создания - есть ли способ открыть его так, как он был открыт в Проводник Windows - так что файл будет открыт с предпочтительной программой пользователя, и если нет связанных программ с форматом файла - Windows покажет диалоговое окно, в котором пользователь сможет выбрать любую программу, чтобы открыть этот файл.

Кроссплатформенное решение (+ Linux, + MacOS, + BSD) будет идеальным.

Спасибо.

Ответы [ 3 ]

7 голосов
/ 26 февраля 2011

В Windows вы можете использовать функцию ShellExecute .

4 голосов
/ 26 февраля 2011

Если вы использовали Qt для разработки своего кроссплатформенного приложения, тогда метод QDesktopServices :: openUrl () сделает эту работу. Это, конечно, кроссплатформенный, как и все в Qt.

Поскольку вы уже используете wxWidgets, использование Qt просто для открытия файла, очевидно, является излишним. А поскольку wxWidgets - это, в основном, GUI, у него, вероятно, нет ничего подобного, хотя я не уверен, поскольку сам никогда не использовал его.

Тем не менее, если вы хотите сделать это кроссплатформенным способом, вот что Qt делает для Windows:

quintptr returnValue = (quintptr)ShellExecute(0, 0,
  (wchar_t*)filePath.utf16(), 0, 0, SW_SHOWNORMAL);
// ShellExecute returns a value greater than 32 if successful
return (returnValue > 32);

Здесь filePath.utf16 () - это путь к файлу в формате Юникод с нулем в конце.

Вот соответствующая часть для X11 / Unix:

if (launch(url, QLatin1String("xdg-open")))
    return true;
if (X11->desktopEnvironment == DE_GNOME 
    && launch(url, QLatin1String("gnome-open"))) {
    return true;
} else {
    if (X11->desktopEnvironment == DE_KDE 
        && launch(url, QLatin1String("kfmclient exec")))
        return true;
}
if (launch(url, QLatin1String("firefox")))
    return true;
if (launch(url, QLatin1String("mozilla")))
    return true;
if (launch(url, QLatin1String("netscape")))
    return true;
if (launch(url, QLatin1String("opera")))
    return true;
return false;

Здесь функция launch () в основном запускает указанное приложение, передавая ему URL для открытия. Не только путь к файлу, как в Windows, но и полный URL-адрес, такой как file:///home/user/tmp/file.doc. Не уверен, что это имеет значение, хотя. Он также кодирует в процентах все не-ASCII-символы в URL-адресе перед передачей его в программу. Не уверен, имеет ли это значение для всех программ, которые пытается openDocument (). Я протестировал его с xdg-open, и мне все равно, закодировано оно в процентах или нет.

Вот часть, которая определяет среду рабочего стола и устанавливает X11->desktopEnvironment соответственно:

    X11->desktopEnvironment = DE_UNKNOWN;
    Atom type;
    int format;
    unsigned long length, after;
    uchar *data = 0;
    int rc;
    do {
        if (!qgetenv("KDE_FULL_SESSION").isEmpty()) {
            X11->desktopEnvironment = DE_KDE;
            break;
        }
        if (qgetenv("DESKTOP_SESSION") == "gnome") {
            X11->desktopEnvironment = DE_GNOME;
            break;
        }
        // GNOME_DESKTOP_SESSION_ID is deprecated for some reason, but still check it
        if (!qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty()) {
            X11->desktopEnvironment = DE_GNOME;
            break;
        }
        rc = XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(_DT_SAVE_MODE),
                                0, 2, False, XA_STRING, &type, &format, &length,
                                &after, &data);
        if (rc == Success && length) {
            if (!strcmp(reinterpret_cast<char *>(data), "xfce4")) {
                // Pretend that xfce4 is gnome, as it uses the same libraries.
                // The detection above is stolen from xdg-open.
                X11->desktopEnvironment = DE_GNOME;
                break;
            }
            // We got the property but it wasn't xfce4. Free data before it gets overwritten.
            XFree(data);
            data = 0;
        }
    } while(0);

Ух ты, это было что-то. И я удалил части, которые обнаруживают другие среды, потому что они не используются в openDocument ().

И, наконец, вот великолепная версия openDocument () для Mac:

// LSOpen does not work in this case, use QProcess open instead.
return QProcess::startDetached(QLatin1String("open"), QStringList() << file.toLocalFile());

В самом деле? Это оно? Вау, должно быть что-то на платформе Mac в конце концов. Здесь QProcess :: startDetached () просто запускает новый процесс, передавая путь к файлу в качестве аргумента. Это в значительной степени эквивалентно вызову system (), но не ожидает завершения процесса. Не уверен, что это имеет значение, и я понятия не имею, как сделать это на Mac без использования QProcess, поскольку я никогда не видел Mac.

1 голос
/ 26 февраля 2011

Вот пример открытия растрового изображения из приложения:

ShellExecute(   GetSafeHwnd(),
                      _T("open"),
                      "Test.bmp",
                      NULL,
                      NULL,
                      SW_SHOW);

Для кросс-платформенной версии, если вы отправите запрос в Google, вы найдете много информации.Пока

...