VBcoders Guest



Don't have an account yet? Register
 


Forgot Password?



Inter process communication using Sendmessage

by Duncan Jones (19 Submissions)
Category: Windows API Call/Explanation
Compatability: Visual Basic 3.0
Difficulty: Intermediate
Date Added: Wed 3rd February 2021
Rating: (15 Votes)

This articles shows how you can use windows messages to communicate between two (or more) applications.

Rate Inter process communication using Sendmessage


  
  Inter process communication using registered messages from Visual Basic
  


   One of the simplest ways to implement multi-tasking in Visual Basic is to create a seperate 
  executable program to do each task and simply use the Shell command to run them as neccessary. The only problem with this is
  that once a program is running you need to communicate with it in order to control its operation.
 
   One way of doing this is using the RegisterWindowMessage and SendMessage API calls to create your own particluar
  windows messages and to send them between windows thus allowing you to create two or more programs that communicate with each 
  other.

   In this example the server has the job of watching a printer queue and sending a message to every interested client whenever an event (job 
  added, driver changed, job printed etc.) occurs.
  


   1. Specifying your own unique messages


    Windows communicate with each other by sending each other standard
   windows messages such as WM_CLOSE to close and terminate the window.

    There are a large number of standard messages which cover most of the standard operations that can be performed by and to different windows. However if you want to implement your
   own custom communication you need to create your own custom messages. This is done with the RegisterWindowMessage API call:
  


  
  '\\ Declaration to register custom messages

  Private Declare Function RegisterWindowMessage Lib "user32" Alias 

      "RegisterWindowMessageA" (ByVal lpString As String) As Long
  
  


   This API call takes an unique string and registers it as a defined windows message, returning a system wide unique identifier for that message
  as a result. Thereafter any call to RegisterWindowMessage in any application that specifies the same string will return the same unique message id.

  Because this value is constant during each session it is safe to store it in a global variable to speed up execution thus:
   


  
  Public Const MSG_CHANGENOTIFY = "MCL_PRINT_NOTIFY" 

  

  Public Function WM_MCL_CHANGENOTIFY() As Long 

  Static msg As Long 

  

  If msg = 0 Then 

     msg = RegisterWindowMessage(MSG_CHANGENOTIFY)

  End If

  

  WM_MCL_CHANGENOTIFY = msg

  

  End Function

  


   Since this message needs to be known to every application that is using it to communicate, it is a good idea to put this into a shared 
  code module common to all projects.

  


   2. Creating windows to listen for these messages


   To create a window in Visual Basic you usually use the form designer and add a new form to your project. However, since our communications 
  window has no visible component nor interaction with the user, this is a bit excessive.

   Instead we can use the CreateWindowEx API call to create a window solely for our communication:
  


  
  Private Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" 

     (ByVal dwExStyle As Long, 

     ByVal lpClassName As String, '\\ The window class, e.g. "STATIC","BUTTON" etc.

     ByVal lpWindowName As String, '\\ The window's name (and caption if it has one)

     ByVal dwStyle As Long, 

     ByVal x As Long, 

     ByVal y As Long, 

     ByVal nWidth As Long, 

     ByVal nHeight As Long, 

     ByVal hWndParent As Long, 

     ByVal hMenu As Long, 

     ByVal hInstance As Long, 

     lpParam As Any) As Long 

  


   If this call is successful, it returns an unique window handle which can be used to refer to that window. This can be used in SendMessage 
  calls to send a message to it.
  


   In a typical client/server communication you need to create one window for the client(s) and one window for the server. Again this can be done with a bit of code common to each application:
  


  
  Public Const WINDOWTITLE_CLIENT = "Merrion Computing IPC - Client" 

  Public Const WINDOWTITLE_SERVER = "Merrion Computing IPC - Server"

  

  Public Function CreateCommunicationWindow(ByVal client As Boolean) As Long 

 

 Dim hwndThis As Long 

 Dim sWindowTitle As String 

 

 If client Then 

    sWindowTitle = WINDOWTITLE_CLIENT 

 Else

    sWindowTitle = WINDOWTITLE_SERVER 

 End If 

 

 hwndThis = CreateWindowEx(0, "STATIC", sWindowTitle, 0, 0, 0, 0, 0, 0, 0, App.hInstance, ByVal 0&)

 

 CreateCommunicationWindow = hwndThis

 

  End Function 

  


   Obviously for your own applications you should use different text for the WINDOWTITLE_CLIENT and WINDOWTITLE_SERVER than above to ensure that your window names are unique.
  


   3. Processing the custom messages


   As it stands you have a custom message and have created a window to which you can send that message. However, as this message is entirely new to windows it does not do anything when it recieves it. To actually process the message you need to subclass the window to intercept and react to the message yourself.

   To subclass the window you create a procedure that processes windows messages and substitute this for the default message handling procedure of that window. Your procedure must have
 the same parameters and return type as the default window procedure:
  


 
 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


 

 
 '\\ --[VB_WindowProc]-----------------------

 '\\ 'typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM); 

 '\\ Parameters: 

 '\\ hwnd - window handle receiving message 

 '\\ wMsg - The window message (WM_..etc.) 

 '\\ wParam - First message parameter 

 '\\ lParam - Second message parameter 


 Public Function VB_WindowProc(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long 

  

  If wMsg = WM_MCL_CHANGENOTIFY Then 

     '\\Respond to the custom message here

  

  Else

     '\\Pass the message to the previous window procedure to handle it

     VB_WindowProc = CallWindowProc(hOldProc, hwnd, wMsg, wParam, lParam)

  End If

  

  End Function 

 


 You then need to inform Windows to substitute this procedure for the existing window procedure. To do this you call SetWindowLong to change the address 
 of the procedure as stored in the GWL_WINDPROC index.
 


 
  Public Const GWL_WNDPROC = (-4) 

  Public Declare Function SetWindowLongApi Lib "user32" Alias "SetWindowLongA" 
 (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long 

 

 '\\ Use (after creating the window...) 

 hOldProc = SetWindowLongApi(hwndThis, GWL_WNDPROC, AddressOf VB_WindowProc) 

 


  You keep the address of the previous window procedure address in hOldProc in order to pass on all the messages that you don't deal with for 
 default processing. It is a good idea to set the window procedure back to this address before closing the window.
 


  4. Sending the custom messages


  There are two steps to sending the custom message to your server window: First you need to find the window handle of that window using the FindWindowEx API call then you need to send the message using the SendMessage API call.
 


 
 '\\ Declarations 

 Public Declare Function SendMessageLong Lib "user32" Alias "SendMessageA" 
 (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam 
 As Long, ByVal lParam As Long) As Long 

 Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (
 ByVal lpClassName As String, ByVal lpWindowName As String) As Long 

 

 '\\ use.... 

 Dim hwndTarget As Long

 

 hwndTarget = FindWindow(vbNullString, WINDOWTITLE_SERVER)

 

 If hwndTarget <> 0 Then 

    Call SendMessageLong(hwnd_Server, WM_MCL_CHANGENOTIFY, 0,0) 

 End If

 


  This will send the WM_MCL_CHANGENOTIFY message to the server window and return when it has been processed.
 


 
  Source Code
  
  The complete source code for these examples is available for download ">here

  You will be asked to register with Yahoo!Groups in order to access it.
  
  

Download this snippet    Add to My Saved Code

Inter process communication using Sendmessage Comments

No comments have been posted about Inter process communication using Sendmessage. Why not be the first to post a comment about Inter process communication using Sendmessage.

Post your comment

Subject:
Message:
0/1000 characters