|
-
Jul 31st, 2001, 07:58 AM
#1
Opening documents from Windows Explorer
Hi all,
I have a bit of a problem with the following scenario:
I'm trying to get my MDI application to open documents from Windows Explorer.
This isn't actually any problems but when ever I double click on a document a new instance of the application is started.
So what I'm trying to do is to let the old instance (if any) open the new document.
This is how I'm trying to do this:
The start-up object is set to Sub Main().
The first thing the Main sub does is to check if App.PrevInstance is True.
If not it loads the frmMDI form that saves its hWnd to the registry (and other startup stuff in the Load event).
If there is a previous instance loaded Sub Main reads the hWnd value from the registry.
Then it calls the Command function to get the file name (if any).
The file name is saved to a string called sFile.
After that it sends a user defined message (WM_USER + &HFC) to the previous instance with wParam set to the length of the string (sFile) and lParam to the actual string value.
I've subclassed the frmMDI form and it gets the message allright.
But when I try to retrieve the original string it fails.
I use CopyMemory in my WinProc to copy wParam back into a string but I only get garbage.
Here's the code I use:
Code:
'In module1:
Private Declare Function SendMessageString _
Lib "user32" Alias "SendMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As String) As Long
Public Const = UM_OPENFILE = &H4FC&
Public Sub Main()
Dim sFile As String
Dim hWnd As Long
If App.PrevInstance Then
sFile = Command
If Len(sFile) Then
hWnd = CLng(GetSetting(App.EXEName, "Instance", "hWnd", "0")
If hWnd Then
SendMessageString hWnd, UM_OPENFILE, LenB(sFile), sFile
End
End If
End If
End If
frmMDI.Show
End Sub
'**********************************
'in frmMDI
Private Sub MDIForm_Load()
SaveSetting App.EXEName, "Instance", "hWnd", Me.hwnd
HookForm Me.hwnd 'set up the sub-classing
'other init stuff goes here
End Sub
'**********************************
'in Module2 (sub-classing module)
Private Declare Sub CopyMemory _
Lib "kernel32" Alias "RtlMoveMemory" ( _
Destination As Any, _
Source As Any, _
ByVal Length As Long)
Private Declare Function SetWindowLong _
Lib "user32" Alias "SetWindowLongA" ( _
ByVal hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Private Declare Function CallWindowProc _
Lib "user32" Alias "CallWindowProcA" ( _
ByVal lpPrevWndFunc As Long, _
ByVal hwnd As Long, _
ByVal Msg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
Private Const GWL_WNDPROC = (-4)
Private Const WM_DESTROY = &H2&
Private lngHwnd As Long
Private lngPrevWndProc As Long
Public Sub HookForm(frmHandle As Long)
lngHwnd = frmHandle
lngPrevWndProc = SetWindowLong(lngHwnd, GWL_WNDPROC, AddressOf WinProc)
End Sub
Public Sub UnhookForm()
SetWindowLong lngHwnd, GWL_WNDPROC, lngPrevWndProc
End Sub
Public Function WinProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim sFile As String
Select Case uMsg
Case UM_OPENFILE
If wParam > 0 Then
sFile = String$(wParam, vbNullChar)
CopyMemory ByVal sFile, ByVal lParam, wParam
End If
Case WM_DESTROY
'the window has been closed
UnhookForm
End Select
WinProc = CallWindowProc(lngPrevWndProc, hw, uMsg, wParam, lParam)
If Len(sFile) Then
MsgBox sFile 'here I actually want to call my open file procedure
End If
End Function
Why doesn't the above work??????
The message is sent and retrieved by my WinProc above but I just can't get the string out correctly.
Best regards
-
Jul 31st, 2001, 04:46 PM
#2
I've seen this before in another guise.
You are getting StringA and StringW (Ansi vs Unicode) garbling.
sfile is being sent as a string which the compiler thinks is a wide string(two bytes per char), but in fact it is an Ansi (one byte per char) string.
For a start try:
Code:
If hWnd Then
SendMessageString hWnd, UM_OPENFILE, LenB(sFile), StrConv(sFile,vbUnicode)
End
-
Aug 1st, 2001, 05:35 AM
#3
Fanatic Member
Joacim,
Just to let you know I've been bashing the hell out of this all morning, I've tried enough combos of pushing and pulling Unicode and ANSI strings to make your hair turn blue, and I still can't get the string back either, ByVal, ByRef, by lstrLenW, by lStrLenA, and various other slimy memory hacks... 
sorry it's not better news....
I don't get it.....
Crispin
VB6 ENT SP5
VB.NET
W2K ADV SVR SP3
WWW.BLOCKSOFT.CO.UK
[Microsoft Basic: 1976-2001, RIP]
-
Aug 1st, 2001, 08:43 AM
#4
You could also pass an atom via the GlobalAddAtom(), GlobalGetAtomName() and GlobalDeleteAtom() functions.
For example, to send it you could use:
VB Code:
Dim nAtom As Integer
nAtom = GlobalAddAtom("MyString")
SendMessage hwnd, WM_MYMESSAGE, nAtom, 0
Now in your WinProc, add the following code:
VB Code:
If wMsg = WM_MYMESSAGE Then
Dim iLength As String
Dim sText As String
sText = Space$(255)
iLength = GlobalGetAtomName(wParam, sText, 255)
GlobalDeleteAtom (wParam)
sText = Left$(sText, iLength)
Debug.Print sText
Exit Function
End If
-
Aug 1st, 2001, 10:00 AM
#5
Thanks a lot Megatron!
I never thought about using atoms, it's so easy.
Just one thing for anyone else that want to try this out:
Change the declaration in the functions from Integer into Long because they are unsigned and it just didn't work until I changed the declarations.
Thanks again Megatron!!!!
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
|