Qt - Opening a custom file via double-click - windows

I have a program and a .l2p file with some lines of info.
I have run a registry file:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\.l2p\DefaultIcon]
#="\"C:\\Program Files\\ToriLori\\L2P.exe\",0"
[HKEY_CLASSES_ROOT\.l2p\shell\Open\command]
#="\"C:\\Program Files\\ToriLori\\L2P.exe\" \"%1\""
When I double-click the .l2p file the program starts but doesn't load the file. What do I have to do to make it load properly? Example code would be very appreciated.

When you double click on a file the file name is passed as a command line argument to the associated program. You have to parse the command line, get the file name and open it (how to do that depends on how your program works).
#include <iostream>
int main(int argc, char *argv[])
{
for (int i = 1; i < argc; ++i) {
std::cout << "The " << i << "th argument is " << argv[i] << std::endl;
}
}
If you run this program from command line:
>test.exe "path/to/file" "/path/to/second/file"
The 1th argument is path/to/file
The 2th argument is /path/to/second/file
In Qt if you create a QApplication you can also access the command line arguments via QCoreApplications::arguments().
You might want to load the file after having created your main window. You may do something like this:
#include <QApplication>
#include <QTimer>
#include "MainWindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
QTimer::singleShot(0, & window, SLOT(initialize()));
window.show();
return app.exec();
}
This way the slot MainWindow::initialize() (which you have to define) gets called as soon as the event loop has started.
void MainWindow::initialize()
{
QStringList arguments = QCoreApplication::arguments();
// Now you can parse the arguments *after* the main window has been created.
}

If I'm understanding your question correctly, L2P.exe is a Qt program you created and you want to handle a passed argument as specifying a file to open. If that's the case, you just need to read that argument in your main() method and handle it. (This isn't something that happens automatically.) Something like the following, although you obviously want to add a bit of error checking:
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
const QStringList arguments = a.arguments();
// The final argument is assumed to be the file to open.
if (arguments.size() > 1 && QFile::exists(arguments.last())) {
your_app_open(arguments.last());
}
// ... etc.
}

Related

stdio redirect "fails" when calling waveInOpen, why?

Here's my basic program, it should compile fairly easily with VisualStudio (even express).
// ConsoleApplication1.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <mmsystem.h>
#include <stdint.h>
#pragma comment(lib, "winmm.lib")
HWAVEIN hWaveIn;
WAVEFORMATEX WaveFormat;
WAVEHDR WaveHeader;
typedef union
{
uint32_t u32;
struct
{
int16_t iLeft;
int16_t iRight;
};
} audiosample16_t;
#define AUDIORATE (44100*4)
#define SECONDS (13)
audiosample16_t MyBuffer[AUDIORATE*SECONDS];
int _tmain(int argc, _TCHAR* argv[])
{
std::cout << "Hello World!\n";
UINT WaveId = 0;
WaveFormat.wFormatTag = WAVE_FORMAT_PCM; // simple, uncompressed format
WaveFormat.nChannels = 2; // 1=mono, 2=stereo
WaveFormat.nSamplesPerSec = 44100;
WaveFormat.wBitsPerSample = 16; // 16 for high quality, 8 for telephone-grade
WaveFormat.nBlockAlign = WaveFormat.nChannels*WaveFormat.wBitsPerSample/8;
WaveFormat.nAvgBytesPerSec = (WaveFormat.nSamplesPerSec)*(WaveFormat.nChannels)*(WaveFormat.wBitsPerSample)/8;
WaveFormat.cbSize=0;
WaveHeader.lpData = (LPSTR)MyBuffer;
WaveHeader.dwBufferLength = sizeof(MyBuffer);
WaveHeader.dwFlags = 0;
std::cout << "Hello World!\n";
//std::cout << std::flush;
HRESULT hr;
if(argc>1)
hr= waveInOpen(&hWaveIn,WaveId,&WaveFormat,0,0,CALLBACK_NULL);
std::cout << "Hello World!\n";
std::cout << "Hello World!\n";
//std::cout << std::flush;
return 0;
}
If you call it from the command line with no arguments, everything prints out fine(several 'Hello World!'s). If you redirect this to a file (myprog.exe > blah.txt) , again, everything works fine and several lines of 'Hello World!' end up in the file as expected.
HOWEVER, if you have an argument (so that waveInOpen is called), it will not redirect anything to the file. The file is empty. If you don't redirect the output, it'll print out to the command prompt just fine.
UNLESS you uncomment the std::flush lines, then the file isn't empty and everything works fine.
What the heck is going on under the hood that's causing that? Shouldn't stdout be flushed on exit and piped to the file no matter what? What is the waveInOpen() call doing that screws up the stdio buffering like that?
FWIW, this came to light because we're calling this program from TCL and Python to do audio quality measurements on an attached product and nothing was being read back, even though it would print out fine when run from the command line (and not redirected).

How do you run code up until a certain line on Xcode?

#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char *argv[])
{
cout << argv[0]; //ONLY WANT TO RUN TILL HERE
for(int x = 1; x < argc; x++)
{
string s(argv[x]);
if(
}
return 0;
}
I added and enabled a breakpoint on that line, but it still runs the whole program.
Screenshot of code:
You need to fix the errors in your code. The line with the red dot next to it has a syntax error that needs to be solved. Once you fix the error the program will run as desired.

How do I handle errors in Lua when executing arbitrary strings?

I'm going for absolute minimalism here. (It's been a while since I've worked with the Lua C API.)
#include <lua.hpp>
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char** argv)
{
lua_State* state = luaL_newstate();
luaL_openlibs(state);
string input;
while (getline(cin, input))
{
auto error = luaL_dostring(state, input.c_str());
if (error)
{
cerr << "Lua Error: " << lua_tostring(state, -1) << '\n';
lua_pop(state, 1);
}
}
lua_close(state);
return 0;
}
This program works fine as long as I feed it perfect Lua. However, if I enter something bad (such as asdf()), the program crashes! Why is it not handling my error gracefully?
I've tried breaking out the calls before. It crashes on the call to lua_pcall itself. I never make it past that line.
The binary download (5.2.1 I believe) has a bug that was corrected in 5.2.3. I rebuilt the library from source, and now my program works fine.

Command-Line arguments not working (char, TCHAR) VS2010

I have following code:
int _tmain(int argc, char** argv) {
bool g_graphics = true;
palPhysics * pp = 0;
#ifndef PAL_STATIC
PF -> LoadPALfromDLL();
#endif
char a[] = "Bullet";
std::string aa;
aa = std::string(argv[1]);
//PF->SelectEngine("Bullet");
DebugBreak();
PF -> SelectEngine(argv[1]);
//PF->SelectEngine(aa);
//debug
// assert(false);
pp = PF -> CreatePhysics();
}
I am trying to read in the command line argument no. 1 in this line:
PF->SelectEngine(argv[1]);
However, I only get the first letter of the argument. I have also tried changing
int _tmain(int argc, char** argv)
to
int _tmain(int argc, TCHAR** argv), but then I get
error:
error C2664: 'palFactory::SelectEngine' : cannot convert parameter 1 from 'TCHAR *' to 'const PAL_STRING &'
PAL_STRING is just a std::string.
This might be a simple one, but I am not sure how to convert TCHAR to std::string, especially since TCHAR is something else depending on compiler /environment settings. Is anyone aware of an easy way to get the command-line arguments to work, such that I don't need to convert anything myself, i..e maybe by changing the tmain function?
Thanks!
C
Update: example of invoking on command line:
Yep. so the way I invoke this on command line is:
progname.exe arg1 arg2,
where arg1 is a physics engine I am trying to load, and arg2 is a dae(physics file with physics info), so I go, specifically:
progname.exe Bullet E:/a.dae
Stepping into the line "PF->SelectEngine(argv[1]);" gives the following code:
bool palFactory::SelectEngine(const PAL_STRING& name) {
#ifdef INTERNAL_DEBUG
printf("palFactory::SelectEngine: this = %p\n", this);
#endif
SetActiveGroup(name); // also calls RebuildRegistry
return isClassRegistered("palPhysics");
}
, in this case, when debugging, I can see that const PAL_STRING& name, i.e. the string, is just "B", instead of what I would expect it to be, which is "Bullet", my command line argument I have passed in the command line.
I've been plauged by this problem for years. The only solution I've been able to find is to NOT USE Visual Studio. I've had to fall back to using other compilers when I must be able to process command-line args. Specifically, I've been using the Digital Mars compiler successfully. It handles the command-line args correctly. I use the VS environment for intellisense and debugging, then compile with DMC to deploy.
---edit below---
Turns out, I just wasn't asking the right question. I finally asked the right question, and got the right answer! See link below.
What is the difference between _tmain() and main() in C++?

Outputting UTF-8 with qInstallMsgHandler

I would like to make my debug handler (installed with qInstallMsgHandler) handles UTF-8, however it seems it can only be defined as void myMessageOutput(QtMsgType type, const char *msg) and const char* doesn't handle UTF-8 (once displayed, it's just random characters).
Is there some way to define this function as void myMessageOutput(QtMsgType type, QString msg), or maybe some other way to make it work?
This is my current code:
void myMessageOutput(QtMsgType type, const char *msg) {
QString message = "";
QString test = QString::fromUtf8(msg);
// If I break into the debugger here. both "test" and "msg" contain a question mark.
switch (type) {
case QtDebugMsg:
message = QString("[Debug] %1").arg(msg);
break;
case QtWarningMsg:
message = QString("[Warning] %1").arg(msg);
break;
case QtCriticalMsg:
message = QString("[Critical] %1").arg(msg);
break;
case QtFatalMsg:
message = QString("[Fatal] %1").arg(msg);
abort();
}
Application::instance()->debugDialog()->displayMessage(message);
}
Application::Application(int argc, char *argv[]) : QApplication(argc, argv) {
debugDialog_ = new DebugDialog();
debugDialog_->show();
qInstallMsgHandler(myMessageOutput);
qDebug() << QString::fromUtf8("我");
}
If you step through the code in the debugger you will find out that QDebug and qt_message first construct a QString from the const char* and then use toLocal8Bit on this string.
The only way I can think of to circumvent this: Use your own coding (something like "[E68891]") or some other coding like uu-encode or base64-encoding that uses only ASCII characters and decode the string in your message handler.
You should also consider to use the version qDebug("%s", "string") to avoid quotes and additional whitespace (see this question).
Edit: the toLocal8Bit happens in the destructor of QDebug that is call at the end of a qDebug statement (qdebug.h line 85). At least on the Windows platform this calls toLatin1 thus misinterpreting the string. You can prevent this by calling the following lines at the start of your program:
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(codec);
On some platforms UTF-8 seems to be the default text codec.
try to pass data in UTF8 and extract it in your function with something like
QString::fromUTF8
it takes const char* on input.
The problem is that the operator<<(const char *) method expects a Latin1-encoded string, so you should pass a proper UTF-8 QString to QDebug like this:
qDebug() << QString::fromUtf8("我");
... and from inside the message handler expect a UTF-8 string:
QString message = QString::fromUtf8(msg);
And that should work like a charm. ;)
For more information please read the QDebug reference manual.
You could also do the wrong thing: keep passing UTF-8 encoded strings via << and convert the strings with the horrible QString::fromUtf8(QString::fromUtf8(msg).toAscii().constData()) call.
Edit: This is the final example that works:
#include <QString>
#include <QDebug>
#include <QMessageBox>
#include <QApplication>
void
myMessageOutput(QtMsgType type, const char *msg)
{
QMessageBox::information(NULL, NULL, QString::fromUtf8(msg), QMessageBox::Ok);
}
int
main(int argc, char *argv[])
{
QApplication app(argc, argv);
qInstallMsgHandler(myMessageOutput);
qDebug() << QString::fromUtf8("我");
return 0;
}
Please note that QDebug doesn't do any charset conversion if you don't instantiate QApplication. This way you wouldn't need to do anything special to msg from inside the message handler, but I STRONGLY recommend you to instantiate it.
One thing you must be sure is that your source code file is being encoded in UTF-8. To do that you might use a proper tool to check it (file in case you use Linux, for example) or just call QMessageBox::information(NULL, NULL, QString::fromUtf8("我"), QMessageBox::Ok) and see if a proper message appears.
#include <QtCore/QCoreApplication>
#include <stdio.h>
#include <QDebug>
void myMessageOutput(QtMsgType type, const char *msg)
{
fprintf(stderr, "Msg: %s\n", msg);
}
int main(int argc, char *argv[])
{
qInstallMsgHandler(myMessageOutput);
QCoreApplication a(argc, argv);
qDebug() << QString::fromUtf8("我");
}
The code above works here perfectly, but I must stress that my console does support UTF-8, because if it would not it would show another char at that location.

Resources