 |
 |

10-08-2002, 05:19 PM
|
|
Regular
|
|
Join Date: Jun 2002
Location: Homewood, IL
Posts: 89
|
|
Help with multiple instances of program running.
|
Hi,
I am writing a simple image viewer, and when I open a JPG or other image it will be opened with my program image.exe.
Now the question is: if I open another image then another instance on the program opens with the new image.
What I want to do is have the image open in the first instance of the program, and only allow one copy of the program to run.
I found a way to restrict other instances of the program to open, I just don't know how to have the image open with the first instance of the program.
Hmm...I'm bad at explaining things.
Thanks for any help.
|
|

10-08-2002, 06:09 PM
|
|
|
|
You could create your application as an ActiveX EXE and use the
GetObject() function to use an already opened instance of your application.
|
|

10-08-2002, 06:43 PM
|
 |
Junior Contributor
|
|
Join Date: Sep 2002
Location: Toronto, Canada
Posts: 278
|
|
|
My first question is if you created an SDI or MDI (single document and multiple document interface) program. MDI would have to be used if more than one JPG is to be used else each previous jpg will have to be closed before opening the new one.
|
__________________
Win Win Situation: Swapping my salary with my golf score
|

10-08-2002, 07:13 PM
|
|
Regular
|
|
Join Date: Jun 2002
Location: Homewood, IL
Posts: 89
|
|
|
It's a SDI. I created an array that will hold filenames so I can just load a new picture on top of the old picture. Then I can go forward and backward quite easily.
I think I will have to use a Sendmessage procedure. Correct me if I am wrong though.
|
|

10-08-2002, 07:51 PM
|
 |
Senior Contributor
|
|
Join Date: Jul 2002
Posts: 1,021
|
|
This is what I did and it works fine for me.
Code:
If App.PrevInstance Then
Unload Me
End If
|
__________________
Jayceepoo
"I recently went to a new doctor and noticed he was located in something called the Professional Building. I felt better right away." - George Carlin
|

10-08-2002, 08:05 PM
|
|
Regular
|
|
Join Date: Jun 2002
Location: Homewood, IL
Posts: 89
|
|
Ya, I have that part already.
The part that is screwing with me is that I don't know if I am sending the message the right was using sendmessage and I don't know how to receive the message after I send it.
Here is the code I am using.
Code:
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
(ByVal hwnd As Long, ByVal wMsg As Long,
ByVal wParam As Long, lParam As Any) As Long
ret = SendMessage(Main.hwnd, wMsg, wParam, ByVal CStr(Command))
The name of the form I want to pass the info to is called 'Main'.
I don't know what to put for 'wMsg' or 'wParam'. And I have no clue how to receive the message.
Any help with this would be great...I'm pretty stuck here. Thanks.
|
Last edited by timwhit; 10-08-2002 at 08:24 PM.
|

10-08-2002, 08:11 PM
|
 |
Obsessive OPtimizer
Administrator * Guru *
|
|
Join Date: Jun 2002
Location: Debug Window
Posts: 13,686
|
|
When the new instance opens it will have to send information to the existing instance. This is called IPC or Inter-Process Communication. One way is to subclass for WM_COPYDATA and use SendMessage with WM_COPYDATA from newly opened instances which search for and send to previous instances. Another possibility is Memory Mapped files, which can share memory across processes. And as was already mentioned an AX EXE server.
If I use App.PrevInstance its usually in a Sub Main. Then no form is ever loaded.
Add to a BAS module (which is setup as the startup object):
Code:
If App.PrevInstance Then
' FindWindow on the other instance
' SendMessage with WM_COPYDATA the filename
End
Else
Dim frm As New Form1
Set frm = New Form1
frm.Show
End If
End Sub
|
Last edited by OnErr0r; 05-24-2004 at 07:58 PM.
Reason: Added vb tags.
|

10-08-2002, 09:05 PM
|
|
Regular
|
|
Join Date: Jun 2002
Location: Homewood, IL
Posts: 89
|
|
Maybe I am just slow today, or is it everyday?
Anyways, I have tried to do what you said, I think. Here is what my Sub Main() looks like. It doesn't crash or anything, but I am still confused about how the first instance of the program receives the message that I am sending it.
Code:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA"
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Public Sub Main()
Dim m_hWnd As Long
m_hWnd = FindWindow(vbNullString, "Image Viewer")
If App.PrevInstance = True Then
ret = SendMessage(m_hWnd, WM_COPYDATA, -1, ByVal CStr(Command))
MsgBox ret & " " & WM_COPYDATA
End
Else
Load MainW
MainW.Show
End If
End Sub
Thanks for the help though...I really do appreciate it.
|
|

10-08-2002, 10:22 PM
|
 |
Obsessive OPtimizer
Administrator * Guru *
|
|
Join Date: Jun 2002
Location: Debug Window
Posts: 13,686
|
|
You have a WindowProc which subclasses your form, its always listening for WM_COPYDATA, when its recieved you get the filename, once the filename is sent the instance commits harikari.
http://support.microsoft.com/default...;EN-US;Q170570
Make sure you save often, and no breakpoints nor stepping in the IDE.
|
__________________
Quis custodiet ipsos custodues.
|

10-08-2002, 10:31 PM
|
 |
Obsessive OPtimizer
Administrator * Guru *
|
|
Join Date: Jun 2002
Location: Debug Window
Posts: 13,686
|
|
Code:
Dim cData As COPYDATASTRUCT
Dim Buffer(MAX_PATH) As Byte ' buffer large enough to handle the max path plus null terminator
RtlMoveMemory Buffer(0), ByVal Command$, MAX_PATH
cData.dwData = 0 ' this long variable could be used for security
cData.cbData = Len(Command$) + 1
cData.lpData = VarPtr(Buffer(0))
SendMessage PreviousInstancehWnd, WM_COPYDATA, Me.hWnd, cData
|
__________________
Quis custodiet ipsos custodues.
|

10-09-2002, 12:40 AM
|
|
Regular
|
|
Join Date: Jun 2002
Location: Homewood, IL
Posts: 89
|
|
OK...this is really driving me nuts now. Maybe if I post my code someone who is not as tired and dumb as me can tell me what I am doing wrong.
Here is Sub Main() and the stuff that happens to be around it:
Code:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function IsIconic Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function ShowWindow Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Const WM_COPYDATA = &H4A
Private Const SW_RESTORE = 9
Private Type COPYDATASTRUCT
dwData As Long
cbData As Long
lpData As Long
End Type
Public Sub Main()
If App.PrevInstance = True Then
'MsgBox "previnst=true"
Dim hWnd As Long
Dim cds As COPYDATASTRUCT
hWnd = FindWindow(vbNullString, "Image Viewer")
If hWnd Then
'MsgBox "found window"
If IsIconic(hWnd) Then
MsgBox "X"
Call ShowWindow(hWnd, SW_RESTORE)
End If
Call SetForegroundWindow(hWnd)
Else
Exit Sub
End If
cds.cbData = LenB(Command)
cds.lpData = StrPtr(Command)
Call SendMessage(hWnd, WM_COPYDATA, hWnd, cds)
End
Else
Load MainW
MainW.Show
End If
End Sub
Now here is the rest of the program, I am using a freeware message handler that I found a little while ago called MsgHook. It is supposed to do the same thing as writing your own message handler but easier of course. (If you want to check it out just search on google.)
ok...here is the Main code from the main window on the program:
Code:
Private Type COPYDATASTRUCT
dwData As Long
cbData As Long
lpData As Long
End Type
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Const LB_FINDSTRING = &H18F
Private Const WM_COPYDATA = &H4A
Dim pic(100) As String
Dim num As Integer
Private Sub About_Click()
frmAbout.Show
End Sub
Private Sub Exit_Click()
End
End Sub
Private Sub Form_Load()
Dim NewHeight As Double, NewWidth As Double
Img.Stretch = False
Img.Visible = False
pic(num) = Command
Img.Picture = LoadPicture(pic(num))
NewWidth = Me.ScaleWidth / Img.Width
NewHeight = (Me.ScaleHeight - 24.981) / Img.Height
ratio = Img.Width / Img.Height
If NewWidth < 1 Or NewHeight < 1 Then
Img.Stretch = True
If NewWidth < NewHeight Then
Img.Width = Img.Width * NewWidth
Img.Height = Img.Height * NewWidth
Else
Img.Width = Img.Width * NewHeight
Img.Height = Img.Height * NewHeight
End If
End If
Img.Move (Me.ScaleWidth - Img.Width) / 2, ((Me.ScaleHeight - Img.Height) / 2) + 24.981
Img.Visible = True
num = num + 1
End Sub
Private Sub Msghook_Message(ByVal Msg As Long, ByVal wp As Long, ByVal lp As Long, result As Long)
Dim cds As COPYDATASTRUCT
Dim Send As String
If Msg = WM_COPYDATA Then
'copymem cds, ByVal lp, Len(cds)
Send = Space$(cds.cbData \ 2)
'copymem ByVal StrPtr(Send), ByVal cds.lpData, cds.cbData
result = True
End If
End Sub
The bottom subroutine is supposed to catch the message but it never does. I know this because I put a message box in there and it never comes up, the message gets sent fine, it just never gets caught.
Lemme know if you see anything in there that looks like it is causing the problem. Thanks!
(The funny thing about this is that this isn't for work or school...I just want to get it to work, I think I would have given up long ago if it were for work or school.)
|
|

10-09-2002, 02:16 AM
|
|
Regular
|
|
Join Date: Jun 2002
Location: Homewood, IL
Posts: 89
|
|
I finally figured this out after so so many hours. This problem turned out to be that the LinkTopic property of the main form was set incorrectly. It needs to be set to the same thing as the name of the main form.
Thanks for the help OnErr0r you definately steered me in the right direction.
The biggest help of all though was this sample program I found on the web, if you ever need help with this then this is the program to use.
http://www.vbdiamond.com/Sources/Vie...ticle=1&ID=120
|
|

10-09-2002, 09:36 AM
|
 |
Obsessive OPtimizer
Administrator * Guru *
|
|
Join Date: Jun 2002
Location: Debug Window
Posts: 13,686
|
|
|
I'm glad you got it working. One quick point about FindWindow. You should probably include the classname of your compiled EXE to narrow down the search. Also, make the form caption of your app initially vbNullString, that way FindWindow won't find itself. Change the caption to whatever after the FindWindow call.
|
__________________
Quis custodiet ipsos custodues.
|
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
|
|
|
| Thread Tools |
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|
|
|
|
 |
|