Solved

Send message from my dll to mine unfocused form

Posted on 2002-05-29
17
237 Views
Last Modified: 2010-04-04
I need to send a message from my dll to main form . All work perfect untill I focus another application. Then the communication stop . The dll work OK because I can hear the messagebeep .

   Case MyCondition of
      SpecialCase: begin
      MessageBeep(1);
      PostMessage(Receiver,MyMessage,wParam,lParam);
      end;
    end;

where MyMessage is WM_USER+1000 and Receiver is the handler of my MainForm ( in CreateForm ... Receiver:=Handle ) .
0
Comment
Question by:ginsonic
  • 8
  • 7
  • 2
17 Comments
 
LVL 11

Expert Comment

by:robert_marquardt
ID: 7041727
Maybe a RecreateWnd has happened and your Window handle is now invalid.
0
 
LVL 9

Author Comment

by:ginsonic
ID: 7041744
Not from my codes :(
0
 
LVL 11

Expert Comment

by:robert_marquardt
ID: 7041981
A RecreateWnd may happen because the Style of the Window has to be changed which may happen when your app loses focus.
0
 
LVL 12

Expert Comment

by:Lee_Nover
ID: 7042427
one option is to create a new dummy window with AllocateHWnd
another would be to post a thread message to the thread owning the window with PostThreadMessage
0
 
LVL 9

Author Comment

by:ginsonic
ID: 7042639
Hey guys,
Can you give me more details ? Maybe some codes ?

Regards,
Nick
0
 
LVL 12

Expert Comment

by:Lee_Nover
ID: 7042964
sure

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, CoolTrayIcon;

type
  TForm1 = class(TForm)
    CoolTrayIcon1: TCoolTrayIcon;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    hDllHandler: Cardinal;
    procedure DllHandler(var Msg: TMessage);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.DllHandler(var Msg: TMessage);
begin
     // handle the message and return a result
     Msg.Result:=0;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
     {$IFDEF VER140}
     hDllHandler:=Classes.AllocateHWnd(DllHandler);
     {$ELSE}
     hDllHandler:=AllocateHWnd(DllHandler);
     {$ENDIF}
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
     {$IFDEF VER140}
     Classes.DeallocateHWnd(hDllHandler);
     {$ELSE}
     DeallocateHWnd(hDllHandler);
     {$ENDIF}
end;

end.

the compiler directives are for D6 and above
the AllocateHWnd has been moved from Forms to Classes
it still exists in Forms but it's been deprecated

send the message to that hDllHandler

this is the most common and most simple way of creating a new window for handling messages

if you want I can write an example on posting thread messages
gotta run now :)
0
 
LVL 9

Author Comment

by:ginsonic
ID: 7043675
Thanks Lee for support, but now the connection don't work at all ( for any cases ).
Look like I send to dll a wrong handle( hear the beep but no message received ).
0
 
LVL 9

Author Comment

by:ginsonic
ID: 7044222
I found a way , but not a profesional one . Now I can get the corect handler detecting it from title name of main form.

But if exist another way , I will appreciate .

Nick
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 12

Expert Comment

by:Lee_Nover
ID: 7044500
did you send hDllHandler to the dll as the handle to receive messages ?
and also if this dll is mapped into other processes and you want to receive notifications to your app then you should store the receivers window hande in a memory mapped file

here's a part from one of my dlls (a system hook)

// we store our window in this structure
type
  PHookRec = ^THookRec;
  THookRec = packed record
    MainWindow: HWND;
    HookID: HHOOK;
  end;


var
   HookRec: PHookRec = nil;
   hMapObject: THandle = 0;

----

// set the receiver window
// so whenever you want to notify your app use SendMessage(HookRec^.MainWindow, SomEMEssage, 1, 2); ..
function SetMainWindow(const hWin: hWND): hWND;stdcall;
begin
     HookRec^.MainWindow:=hWin;
     Result:=hWin;
end;

procedure EntryPointProc(Reason: Integer);
begin
  case Reason of
    DLL_PROCESS_ATTACH:
      begin
        hMapObject:=CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(THookRec), 'JustSomeNameForTheMemorySpace');
        HookRec:=MapViewOfFile(hMapObject, FILE_MAP_WRITE, 0, 0, 0);
      end;

    DLL_PROCESS_DETACH:
      begin
        try
          UnMapViewOfFile(rHookRec);
          CloseHandle(hMapObject);
        except
        end;
      end;
  end;
end;

// ---------- export funkcije
exports
   SetMainWindow,
   HookWindoze,
   UnhookWindoze;


begin
     DllProc := @EntryPointProc;
     EntryPointProc(DLL_PROCESS_ATTACH);
end.


that should do it
0
 
LVL 9

Author Comment

by:ginsonic
ID: 7044624
Got an error in dll.

Can you write a sample project how to send from my dll to my form my own message ?

Alike MyMsg = WM_USER + $300;

I will increase to 100 points for a good answer .
0
 
LVL 12

Accepted Solution

by:
Lee_Nover earned 100 total points
ID: 7049206
sorry it took me this long
I'm just a very busy guy :)

here's the dll source and the calling units


-------------------------------------------

library lnDll;

uses
  Windows;

{$R *.RES}


type
  PMsgInfo = ^TMsgInfo;
  TMsgInfo = packed record
    RcvWnd: HWND;
    Tag: Integer;
  end;


var
   lpMsgInfo: PMsgInfo = nil;
   hMapObject: THandle = 0;
   WM_WOOWOO: Cardinal = 0;


function SetMainWindow(const hWin: hWND): hWND;stdcall;
begin
     lpMsgInfo^.RcvWnd:=hWin;
     Result:=hWin;
end;

function WooWoo(Range: Integer): Integer; stdcall;
begin
     Randomize;
     Result:=Random(Range);
     PostMessage(lpMsgInfo^.RcvWnd, WM_WOOWOO, Result, 0);
end;

procedure EntryPointProc(Reason: Integer);
begin
  case Reason of
    DLL_PROCESS_ATTACH:
    begin
      hMapObject:=CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(TMsgInfo), 'lnWooWoo');
      lpMsgInfo:=MapViewOfFile(hMapObject, FILE_MAP_WRITE, 0, 0, 0);
      WM_WOOWOO:=RegisterWindowMessage('WM_WOOWOO'); // create a unique message
    end;

    DLL_PROCESS_DETACH:
    begin
      UnMapViewOfFile(lpMsgInfo);
      CloseHandle(hMapObject);
    end;
  end;
end;

exports
   SetMainWindow,
   WooWoo;


begin
     DllProc := @EntryPointProc;
     EntryPointProc(DLL_PROCESS_ATTACH);
end.

------------------------------------------


unit DllDemoU;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    WM_WOOWOO: Cardinal;
    wndDll: Cardinal;
    procedure DllHandler(var Msg: TMessage);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

const
  lnDll = 'lnDll.dll';

implementation

{$R *.dfm}


function SetMainWindow(hWin: HWND): Integer; stdcall; external lnDll name 'SetMainWindow';
function WooWoo(Range: Integer): Integer; stdcall; external lnDll name 'WooWoo';


procedure TForm1.FormCreate(Sender: TObject);
begin
     WM_WOOWOO:=RegisterWindowMessage('WM_WOOWOO');
     wndDll:=AllocateHWnd(DllHandler);
     SetMainWindow(wndDll);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
     SetMainWindow(0);
     DeallocateHWnd(wndDll);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
     WooWoo(Random(1000));
end;

procedure TForm1.DllHandler(var Msg: TMessage);
begin
     if Msg.Msg = WM_WOOWOO then
        Caption:=IntToStr(Msg.WParam);
end;

end.

--------------------------------------------------


also read about the RegisterWindowMessage function :)
0
 
LVL 12

Expert Comment

by:Lee_Nover
ID: 7049213
0
 
LVL 9

Author Comment

by:ginsonic
ID: 7049305
Look alike what I need with an exception . I don't need to call from my application the WooWoo function. I hook my mouse movement and I need to send the position to a label from main form.

How can I send the WM_WOOWOO to main form procedure HOOK, for example ?

Something alike
procedure Hook(var message: TMessage); message  WM_WOOWOO;
0
 
LVL 12

Expert Comment

by:Lee_Nover
ID: 7049474
well that woowoo was just a simple proc
replace that with your mouse hook proc
whenever you want to notify your app simply PostMessage the same way as in the woowoo func
I gave that woowoo just as an example :)

so you probably have something like :

function MouseProc(nCode: integer; wParam: WPARAM; lParam: LPARAM): LRESULT;stdcall;
begin
     try
        if nCode = HC_ACTION then begin

           if lpMsgInfo^.RcvWnd > 0 then
              PostMessage(lpMsgInfo^.RcvWnd, WM_WOOWOO, wParam, lParam);
        end;
     finally
        Result:=CallNextHookEx(HookID, nCode, wParam, lParam);
     end;
end;


also you could use gpsysHooks :)
http://gp.17slon.com/gp/gpsyshook.htm
0
 
LVL 9

Author Comment

by:ginsonic
ID: 7051075
I know already this . The problem is how I use the WM_WooWoo in my application ? How I redirect it in my procedure Hook ?

This
procedure Hook(var message: TMessage); message  WM_WOOWOO;
don't work.
0
 
LVL 12

Expert Comment

by:Lee_Nover
ID: 7051087
it's implemented in the unit DllDemoU

it's bellow the dll source
I named it DllHandler
0
 
LVL 9

Author Comment

by:ginsonic
ID: 7051263
Sorry , I forgot this procedure :)

Thanks for support,
Nick
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now