This may be of limited use to you since I'm effectively saying "write your own test execution engine", but it's perfectly achievable. Just start small and build up the features piece by piece, and you'll have something cool that meets your own unique needs in no time.
Whilst it's perhaps useful to have the error that stopped a test quickly called out (maybe to do a quick failure diagnosis without viewing the detailed steps), please don't neglect having reports containing the detailed steps. When a test fails you need to know what went wrong and why, and have a record of what actions led to that failure.
Nonetheless, here's one way to go about fulfilling your requirement:
Write a test driver using a supported language of your choice using the QTP API, and trigger a separate run in QTP for each test. When calling Test.Run you can control where the results are saved using the RunResultsOptions structure. In your tests just leave "When error occurs during run session" as "pop-up message box" so it stops when an error occurs. If you want different behaviour then handle it on a case-by-case basis with "on error resume next / on error goto 0 / check Err.Number and Err.Description"-blocks. Don't ever switch it to "proceed to next step".
Check the LastRunResults structure returned by Test.LastRunResults after the run is complete. LastRunResults.Status will tell you the status of the run, and therefore let you decide whether you want to proceed to step #3 to extract failure details.
Parse results.xml from the results folder after each run. It will be located at {results folder}\Report\results.xml. It's trivial to scan the XML for all the failed steps or just the last failed step, whereupon you can grab the step details and save them to another file in the format of your choosing. You'll be looking for NodeArgs elements with attribute eType=User. You can then find the status of the step and the step details nearby. If you need more info on the errors besides the logging auto-generated by QTP then you need to be trapping errors as they happen and adding some Reporter.ReportEvent statements of your own with more salient info.
Do something fun with your result summary file...
If you are hoping to use QTP itself as the driver for a batch of tests (i.e. press play once and run all your tests) and therefore catch the error messages from sub-tests or something then I would just say this: don't do that unless you're just running multiple iterations of the same test. Using QTP itself to run all your tests mashed together in a single epic test run is a poor way to do things for a multitude of reasons, but I don't intend to write an essay here about it!