• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 250
  • Last Modified:

Send message from my dll to mine unfocused form

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
ginsonic
Asked:
ginsonic
  • 8
  • 7
  • 2
1 Solution
 
robert_marquardtCommented:
Maybe a RecreateWnd has happened and your Window handle is now invalid.
0
 
ginsonicAuthor Commented:
Not from my codes :(
0
 
robert_marquardtCommented:
A RecreateWnd may happen because the Style of the Window has to be changed which may happen when your app loses focus.
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
Lee_NoverCommented:
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
 
ginsonicAuthor Commented:
Hey guys,
Can you give me more details ? Maybe some codes ?

Regards,
Nick
0
 
Lee_NoverCommented:
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
 
ginsonicAuthor Commented:
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
 
ginsonicAuthor Commented:
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
 
Lee_NoverCommented:
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
 
ginsonicAuthor Commented:
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
 
Lee_NoverCommented:
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
 
ginsonicAuthor Commented:
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
 
Lee_NoverCommented:
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
 
ginsonicAuthor Commented:
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
 
Lee_NoverCommented:
it's implemented in the unit DllDemoU

it's bellow the dll source
I named it DllHandler
0
 
ginsonicAuthor Commented:
Sorry , I forgot this procedure :)

Thanks for support,
Nick
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 8
  • 7
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now