Go Back  Xtreme Visual Basic Talk > Legacy Visual Basic (VB 4/5/6) > General > Help with multiple instances of program running.


Reply
 
Thread Tools Display Modes
  #1  
Old 10-08-2002, 06:19 PM
timwhit timwhit is offline
Regular
 
Join Date: Jun 2002
Location: Homewood, IL
Posts: 89
Default 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.
Reply With Quote
  #2  
Old 10-08-2002, 07:09 PM
Mark Diesel
Guest
 
Posts: n/a
Default

You could create your application as an ActiveX EXE and use the
GetObject() function to use an already opened instance of your application.
Reply With Quote
  #3  
Old 10-08-2002, 07:43 PM
VisuallyImpared's Avatar
VisuallyImpared VisuallyImpared is offline
Junior Contributor
 
Join Date: Sep 2002
Location: Toronto, Canada
Posts: 278
Default

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
Reply With Quote
  #4  
Old 10-08-2002, 08:13 PM
timwhit timwhit is offline
Regular
 
Join Date: Jun 2002
Location: Homewood, IL
Posts: 89
Default

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.
Reply With Quote
  #5  
Old 10-08-2002, 08:51 PM
jayceepoo's Avatar
jayceepoo jayceepoo is offline
Senior Contributor
 
Join Date: Jul 2002
Posts: 1,021
Default

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
Reply With Quote
  #6  
Old 10-08-2002, 09:05 PM
timwhit timwhit is offline
Regular
 
Join Date: Jun 2002
Location: Homewood, IL
Posts: 89
Default

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 09:24 PM.
Reply With Quote
  #7  
Old 10-08-2002, 09:11 PM
OnErr0r's Avatar
OnErr0r OnErr0r is offline
Obsessive OPtimizer

Administrator
* Guru *
 
Join Date: Jun 2002
Location: Debug Window
Posts: 13,734
Default

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 08:58 PM. Reason: Added vb tags.
Reply With Quote
  #8  
Old 10-08-2002, 10:05 PM
timwhit timwhit is offline
Regular
 
Join Date: Jun 2002
Location: Homewood, IL
Posts: 89
Default

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.
Reply With Quote
  #9  
Old 10-08-2002, 11:22 PM
OnErr0r's Avatar
OnErr0r OnErr0r is offline
Obsessive OPtimizer

Administrator
* Guru *
 
Join Date: Jun 2002
Location: Debug Window
Posts: 13,734
Default

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.
Reply With Quote
  #10  
Old 10-08-2002, 11:31 PM
OnErr0r's Avatar
OnErr0r OnErr0r is offline
Obsessive OPtimizer

Administrator
* Guru *
 
Join Date: Jun 2002
Location: Debug Window
Posts: 13,734
Default

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.
Reply With Quote
  #11  
Old 10-09-2002, 01:40 AM
timwhit timwhit is offline
Regular
 
Join Date: Jun 2002
Location: Homewood, IL
Posts: 89
Default

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.)
Reply With Quote
  #12  
Old 10-09-2002, 03:16 AM
timwhit timwhit is offline
Regular
 
Join Date: Jun 2002
Location: Homewood, IL
Posts: 89
Default

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
Reply With Quote
  #13  
Old 10-09-2002, 10:36 AM
OnErr0r's Avatar
OnErr0r OnErr0r is offline
Obsessive OPtimizer

Administrator
* Guru *
 
Join Date: Jun 2002
Location: Debug Window
Posts: 13,734
Default

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.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
 
 
-->