Bon alors la solution comme je l'ai dis c'est de vérifier (au démarrage et donc avant création des fenêtres, c'est mieux, sinon ça complique la vie ^^) si une autre instance de ton application existe, puis de lui transmettre un message.
Sous Windows: (Linux je sais pas

)
Pour regarder si une autre instance de ton application existe, tu peux comme le suggère la documentation de Windows, créer un Mutex (et me demande pas ce que c'est même après lecture de la doc je comprends toujours pas...). Mais sans aller si loin, tu peux te reposer sur la simple présence d'une fenêtre dans le système.
Sous Windows les fenêtres sont identifiés par leur handle (HWND), par leur titre, et par leur classe de fenêtre. Ce qui est intéressant ce n'est certainement pas le titre, puisque ça ne donne absolument aucune information fiable sur la fenêtre... La classe de fenêtre par contre est bien plus intéressante, et assez fiable (si on prend un nom de fenêtre relativement peu courant et qu'aucun rigolo ne s'amuse à utiliser le même dans son application).
Pour trouver le handle d'une fenêtre en fonction de la classe, on utilise FindWindow[Ex] (la version sans le Ex devrait suffire), et si ça retourne NULL on en déduit qu'aucune fenêtre de cette classe n'a été créée donc l'appli n'a pas encore été lancée. Si ça retourne un handle, alors on suppose que c'est une fenêtre ouverte par notre application et on lui transmet le message en utilisant PostMessage ou SendMessage (SendMessage attend l'autre processus, donc "plante" si l'autre a planté, mais pas PostMessage), avec pour un numéro de message défini par quelque chose du type WM_USER, WM_USER + 1, WM_USER + 2, etc... (Puisque ce n'est pas un message windows standard)
Par contre dans le cas de comunnication inter-processus, tu ne peux pas transmettre de pointeurs puisqu'il n'y a pas partage de mémoire.
Mais dans le cas de l'ouverture d'un fichier tu n'a qu'une chaîne de caractère à transmettre, donc le plus simple est d'utiliser un Atom global, qui va partager ta chaîne à travers tout le système. (cf MSDN pour la documentation des 2-3 fonctions associées)
Bon par contre la taille est limitée à 255 caractères, donc tu devra peut-être avoir recours à la mémoire partagée (cherche GlobalAlloc sur MSDN ça devrait aller) mais le principe est le même.
Bref le seul truc à faire ensuite c'est dans ta procédure de fenêtre (je sais pas avec quoi tu code, mais normalement c'est accessible pour Delphi, C/C++ et Windows Forms) de gérer le message avec le numéro que tu aura choisi (c'est mieux d'en faire une constante) et c'est fini. (Bon bien sûr la mémoire globale il faut pas oublier de la libérer sinon ça fait une jolie fuite

)
En C ça donne ça =>
http://goldencrystal.free.fr/vrac/UniqueInstanceDemo.7z (c'est juste une dizaine de lignes commentées éparpillées dans le fichier principal)