This is one that I have been fooling around with for sometime and just can’t get it to work so I’m asking for help from the hardcore Delphi coderz.
I have been writing a player for sometime and the very last feature I want to add is being able to add a file to a playlist by just double clicking on it (My associations are setup correctly). If my application is not running I can easily do this by using cmdline and ParamStr.
The problem arises when I already have my player running and double click on a song to be added to the playlist, the ParamStr doesn’t change from the initial loading. So I need to find a way to do it and I have tried everything I can think of.
MS Media Player has this function, as do most media players, and I think it could be a good topic and of use to all of us as well.
Any ideas? I appreciate your help.
- NiteBeast asked 14 years ago
Ok here goes, applogies for the lenght but theres alot of code involved please read through the entire comments on this before you go abouts using it. By the way, look at the [b:30sfusbq]Form1.ComShell Cmd[/b:30sfusbq] Within the function [b:30sfusbq]WindowProc[/b:30sfusbq] This is what function to exectue when it recives a new command arg from the new application. You may change this to your liking.
First, add a module and paste the following subs and and declares.
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) 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 SetForegroundWindow Lib "user32" (ByVal hwnd 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 Declare Function lstrlenW Lib "kernel32" (ByVal psString As Long) As Long
Private Declare Function lstrlenA Lib "kernel32" (ByVal psString 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 Declare Function SetProp Lib "user32" Alias "SetPropA" (ByVal hwnd As Long, ByVal lpString As String, ByVal hData As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal wNewWord As Long) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long)
Private Const GWL_WNDPROC = (-4)
Private Const SW_RESTORE = 9
Private Const WM_COPYDATA = &H4A
Private Type COPYDATASTRUCT
dwData As Long
cbData As Long
lpData As Long
Private m_hWnd As Long
Private m_lpPrev As Long
Public Sub PassCommand(ByVal sWindowText As String)
Dim hwnd As Long
Dim sSend As String
Dim cds As COPYDATASTRUCT
hwnd = FindWindow(vbNullString, sWindowText)
If hwnd Then
If IsIconic(hwnd) Then
Call ShowWindow(hwnd, SW_RESTORE)
If Len(Command$) Then cds.cbData = LenB(Command$) cds.lpData = StrPtr(Command$) Call SendMessage(hwnd, WM_COPYDATA, hwnd, cds) End If
Public Sub Hook(ByVal hwnd As Long)
If hwnd = 0 Then ‘ unhook
Call SetWindowLong(m_hWnd, GWL_WNDPROC, m_lpPrev)
Else ‘ hook into message stream
m_hWnd = hwnd
m_lpPrev = SetWindowLong(m_hWnd, GWL_WNDPROC, AddressOf WindowProc)
Private Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim cds As COPYDATASTRUCT
Dim Cmd As String
If uMsg = WM_COPYDATA Then
CopyMem cds, ByVal lParam, Len(cds)
Cmd = Space$(cds.cbData \ 2)
CopyMem ByVal StrPtr(Cmd), ByVal cds.lpData, cds.cbData
WindowProc = True
WindowProc = CallWindowProc(m_lpPrev, hwnd, uMsg, wParam, lParam)
Next in your forms load load sub add the following bit of code at the start
of the sub so that it is the first bit of code executed.
Dim CaptionSearch As String
If App.PrevInstance Then CaptionSearch = Me.Caption Me.Caption = "" Call PassCommand(CaptionSearch) Unload Me Exit Sub Else Call Hook(Me.hwnd) End If
Finally you need to unhook when you unload, thus within the unload function of the form, simply add the following line of code.
Thats it, hope it helps. Oh btw, this won’t work correctly with MDI applications however I can post the code for MDI apps if so needed.
Best of luck.
How I would do it is for your application to detect whether another instace of that application is already running. There are various ways to do this, such as mutex, FindWindow, etc. If another instance is found, then it sends the filename to the instance that is already running (look up inter-process communication in the Win32 help file) and exits. In Delphi, this would all be done in the DPR file prior to the first call to CreateForm.
Here you go [url:121qtbqf]http://www.undu.com/Articles/991221b.html[/url:121qtbqf]
This is a good introduction. Sendmessage IPC is useful as long as your windows all have handles and you want to handle data synchronously with events (useless for service applications), and the messages are not huge datastructures.
Mapped memory is good for async data storage and sharing.
You could also use an atom, or named pipe, but I wouldn’t suggest it under winblows. Since atoms are not really ‘suggested use’ anymore, and named pipes can give you threading nightmares
Umm I know how to do this via VB, I could post the code here, perhaps someone could port it to Delphi for you, its mainly setting up a message hook and listening for messages from another instanance of the app.
I am going to assume that you mean so that, if your application is already running, and you douple click say an mp3, rather then run a new instance of your application it would simply pass the mp3 file to your already running application?
Anyhow if your looking for this let me know and I’ll post, as I’am not entirely sure what your looking for.
Please login first to submit.