|
-
June 21st, 2002, 12:59 PM
#1
Open docs in single instance of another application
Hey all,
Im trying to open a document in a 3rd party program that supports multiple documents. Using the shell approach (i.e. "program.exe file_to_open.ext") opens a new instance of the application every time I want a new document opened. Is there a way that I can get all the files to open as documents in the same application instance?
I was thinking that maybe I can sent an open document message to the application, although im not sure if this is possible.
Thanks in advance to any replies!
Andy
-
June 22nd, 2002, 03:33 AM
#2
-
June 22nd, 2002, 12:40 PM
#3
First of all you need to decide whether there's an instance of
your program already running. Look in the samples in MFC
under 'how do I make sure only one instance of the application
can be run', or something like that.
My preferred method is to go through all the windows on the desktop testing their windows classes.
Right, now you can do this, on startup of your application find out if there's any other instances running and find out its
window handles (its HWND).
What we're going to do is send a known message to this window, with a file name in its WPARAM so that it knows to open this file. Your new instance of your application can then shut down.
Now, in your application try code like this :
[ccode]
CMyMainFrm : public CMDIFrameWnd
{
public:
.....
static const UINT m_nOpenFileMessage;
protected:
afx_msg LRESULT OnMyOpenFileMessage(WPARAM wParam, LPARAM lParam);
} ;
// in the .cpp
const UINT CMyMainFrm::m_nOpenFileMessage = RegisterWindowMessage("OpenMessage");
// in the message map
ON_REGISTERED_MESSAGE(m_nDropMessage, OnMyOpenFileMessage)
// implementation
LRESULT CMyMainFrm::OnMyOpenFileMessage(WPARAM wParam, LPARAM lParam)
{
// open the file
HGLOBAL hGlobal = (HGLOBAL)wParam;
CString sFileName = (LPCSTR)GlobalLock(hGlobal);
GlobalUnlock(hGlobal);
AfxGetApp()->m_pDocManager->OpenDocumentFile(sFileName);
return S_OK;
}
[/ccode]
Note the use of global memory to do the passing. This is because both the apps will have their own memory spaces, and therefore you can't just pass pointers about.
In your app's InitInstance you should have something like this :
[ccode]
// assume that sFileName is the required filename
CString sFileName = <filename>
// after you've created but not shown your mainfrm
// should really use something much better than this, but it'll suffice
char cWindowClass[512];
::GetClassName(m_pMainFrm->m_hWnd, cWindowClass, 512);
HWND hWndOther = ::FindWindow(cWindowClass, NULL);
if (hWndOther != NULL)
{
// prepare the file name
HGLOBAL hGlobal = ::GlobalAlloc(GHND|GMEM_SHARE, sFileName.GetLength() + 1);
LPSTR lpStr = ::GlobalLock(hGlobal);
::strcpy(lpStr, sFileName);
::GlobalUnlock(hGlobal);
::SendMessage(hWndOther, CMyMainFrame::m_nOpenFileMessage,
(WPARAM)hGlobal, NULL);
return FALSE;
}
.. continue
[/ccode]
Hope this helps. I've not tried it so it's going to need a bit of
playing around with but I'm pretty sure that the basics are all there to get it working.
Have fun !
Darwen.
-
June 22nd, 2002, 12:41 PM
#4
Oopsy ! There should be a ::GlobalFree(hGlobal) in
the end part of that.
Can't have messy memory & resource leaks, can we ?
Darwen.
-
June 23rd, 2002, 06:24 AM
#5
Darwen,
Thanks for the reply. Only problem is, and perhaps I should have made this clearer in my post, im trying to open the document in a 3rd party program i.e. one written by somebody else and not under my control - its a pre-existing program. So I can edit the 3rd part program code so it knows to open all the files in the same instance.
I thought I could emulate a drag and drop, but I discovered that the program doesnt support dropfiles either!! So at the moment im rather defeated!
Thanks,
Andy
-
July 22nd, 2002, 02:44 PM
#6
Hi
Hi i want to open many doc files from explorer in a singleton application. i tried the code that is mentioned by darwen. But when i get the message to mainframe the file name is not there. it is lost!! i.e
does GlobalAlloc really is a method to allocate global memory or its jus tfunction for backward 16bit compatibility??
LRESULT CMyMainFrm::OnMyOpenFileMessage(WPARAM wParam, LPARAM lParam)
{
// open the file
HGLOBAL hGlobal = (HGLOBAL)wParam;
CString sFileName = (LPCSTR)GlobalLock(hGlobal);
GlobalUnlock(hGlobal);
AfxGetApp()->m_pDocManager->OpenDocumentFile(sFileName);
return S_OK;
}
in this function the sFileName contains no file name.
Any help is appreciated.
Thanks
Shashi
-
July 22nd, 2002, 05:29 PM
#7
The only other thing which I can suggest is if you set up
your own clipboard format and use that to transfer the file name.
Have a look at MSDN about using the clipboard.
Oh, and yes GlobalAlloc IS the way to allocate global memory - after all the clipboard uses it !
The other alternative is to have a COM LOCAL_SERVER interface to your application which will enable you to pass the file name directly. I've personally never been able to get local server com objects to work, but I'm sure there's plenty of stuff on this site and on Developer.com to point you in the right direction.
Darwen.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|