Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Associating a file type to my program?



  • I have a multi tab text editor program and I want to associate a file type to it, so when we double click on the file, my program will open it in a new tab.

    From my understanding, I'll need to first register the file type and shell command in registry to:

    HKEY_CURRENT_USER\SOFTWARE\Classes\.myextension
    HKEY_CURRENT_USER\SOFTWARE\Classes\.myextension\Shell\Open\Command = "C:\my_program.exe" "%1".

    And then I can retrieve the file path in main(int argc, char *argv[]) in my c++ file with argv[0].

    But how do I keep my program at only one instance? Right now if I double click the file type, it will open a new instance of my program.


  • Lifetime Qt Champion

    @lansing said in Associating a file type to my program?:

    But how do I keep my program at only one instance?

    See this thread: https://forum.qt.io/topic/98417/how-to-create-singleinstance-application/13



  • @jsulm

    Is there another alternative with less hassle? That's a lot of files to add for this feature.


  • Lifetime Qt Champion

    @lansing I don't know about any simpler solution


  • Moderators

    @lansing
    clone into your project source [https://github.com/KDAB/KDSingleApplication] and include the .pri file in your .pro file



  • I have implemented the SingleApplication from here, and now double clicking on the text file will not open a second instance of the program. But it wouldn't open my file in a new tab.



  • @lansing
    Glancing through that link, you will have to implement what is in the Secondary Instances sub-section. Have you done so?

    Here is an example of how you would start a Secondary Instance send a message with the command line arguments to the primary instance and then shut down.

    That is what you want, isn't it?



  • @JonB

    Yes, so I got the secondary instance sending message to the first instance now. But it was sending a joined QByteArray and I don't know how to split it back in the slot.

        if( app.isSecondary() ) {
            app.sendMessage( app.arguments().join(' ').toUtf8() );        
            return 0;
        } else {
            QObject::connect(
                &app,
                &SingleApplication::receivedMessage,
                mainwindow,
                MainWindow::slotReceivedMessage
            );
        }
    

    The QByteArray I received is "my_program.exe D:\myfile.txt", how do I get the myfile.txt string?


  • Lifetime Qt Champion

    Hi,

    You can split your string however why to just send the relevant arguments rather than just all of them ?



  • @lansing
    Well QString::split() will be the simplest to handle "my_program.exe D:\myfile.txt". Though you might want to test with a space in the filename passed in, that might be more tricky, don't know if you can use the QString::split(const QRegularExpression &re) overload for that.



  • @SGaist said in Associating a file type to my program?:

    Hi,

    You can split your string however why to just send the relevant arguments rather than just all of them ?

    Oh yes you're right, I can just send app.sendMessage( argv[1] ). A new problem I see is that my file path that was sent will get shrink if it's too long. Like this
    C:\Users\Me\Desktop\MYFILE~1.TXT. Is this normal?



  • @lansing
    That's just a short (8.3) filename. Nothing you can do about it if that's what you receive. Should work.



  • @JonB

    How do I get the original name back? I tried QFileInfo(filePath).absoluteFilePath() but it still couldn't convert it.



  • @lansing
    I believe this will need a Windows-specific function call, and will not be available as a native Qt call. See GetLongPathNameA function (fileapi.h).



  • @JonB

    I've been trying for 2 days but I couldn't get it to work:

    main.cpp

    int main(int argc, char *argv[])
    {    
        SingleApplication application( argc, argv, true);
        mainWindow = new MainWindow();
    
        if (application.isSecondary()) {
            if (application.arguments().count() == 2) {
                application.sendMessage( argv[1] );
            }
            return 0;
        } else { 
            QObject::connect(&application, &SingleApplication::receivedMessage,
                        mainWindow , &MainWindow::slotReceivedMessage);
        }
    

    mainwindow.cpp

    namespace Win32 {
    #include "Windows.h"
    }
    
    #define BUFSIZE 4096
    void MainWindow::slotReceivedMessage(int instanceId, QByteArray message)
    {
        Win32::DWORD  retval=0;
        Win32::BOOL   success;
        Win32::TCHAR  buffer[BUFSIZE];
        Win32::TCHAR  buf[BUFSIZE];
        Win32::TCHAR** lppPart={NULL};
    
        // convert char * to wchar_t *
        const size_t WCHARBUF = 100;
        wchar_t message_t[WCHARBUF];
        Win32::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, message, -1, message_t, WCHARBUF);
    
        // get full filename from short filename
        retval = Win32::GetFullPathName(message_t, BUFSIZE, buffer, lppPart);
        QString filePath = QString::fromWCharArray(buffer);
    
        qDebug() << message;
        qDebug() << filePath;    
    }
    

    Since GetFullPathName needs a wchar_t as input, I have to first convert the char to wchar_t, then convert it to full path name.

    But when printing out with debug, both the input(message) and output(filePath) are still the same. The GetFullPathName wasn't doing anything. What am I doing wrong?


Log in to reply