Home All Groups Group Topic Archive Search About

Help using SendMessage() function

Author
6 May 2009 5:42 PM
GS
Hello,

Can anyone tell me how I could get a browser app to display a specific page
(by name or by indexID), using the API SendMessage function?

Thanks in advance..
Garry

Author
8 May 2009 12:25 AM
Karl E. Peterson
GS wrote:
> Can anyone tell me how I could get a browser app to display a specific page
> (by name or by indexID), using the API SendMessage function?

Why do you want to use SendMessage, and what the heck is an IndexID wrt a webpage?

At any rate, to fire off a web page in the default browser, it's as simple as:

   Private Sub HyperJump(ByVal URL As String)
      Call ShellExecute(0&, vbNullString, URL, vbNullString, _
                        vbNullString, vbNormalFocus)
   End Sub

More info: http://vb.mvps.org/samples/HyperJmp
--
..NET: It's About Trust!
http://vfred.mvps.org
Author
8 May 2009 3:19 AM
GS
Hi Karl,

Thanks for your reply. I need to use SendMessage because it's not a standard
web browser, it's a browser app that displays html pages (ie: ebook). It
doesn't respond to the standard browser (like IE) keystrokes and so SendKey
is not an option.

An IndexID is similar to the context ID for a CHM topic page. This wouldn't
be used so much as the page name (ie: "somepage.htm") but it can be if
desired.

Basically, it's a stand-alone EXE that I have managed to get to behave like
a CHM in that it is controlled much in the same way as far as opening,
closing, and taking focus when minimized or not the top window. This is done
entirely using SendMessage. All I need to finish it off is to be able to
specify which page (topic) to display.

I know this is possible because the author of the software that creates the
EXEs uses SendMessage to display context sensitive help in one of these apps.
The problem is he uses Delphi, which is jibberish to me, and didn't provide
all the source code that performs this. He has a SDK API that's not
registerable (regsrver32 doesn't like it) and so I can't use it with VBA
projects.

I believe it uses pointers to pass the lParam arg, which I suspect is
similar to using AddressOf in VB but not sure because I'm relatively new to
programming. Any help here would be greatly appreciated.

Kind regards,
Garry

Show quoteHide quote
"Karl E. Peterson" wrote:

> GS wrote:
> > Can anyone tell me how I could get a browser app to display a specific page
> > (by name or by indexID), using the API SendMessage function?
>
> Why do you want to use SendMessage, and what the heck is an IndexID wrt a webpage?
>
> At any rate, to fire off a web page in the default browser, it's as simple as:
>
>    Private Sub HyperJump(ByVal URL As String)
>       Call ShellExecute(0&, vbNullString, URL, vbNullString, _
>                         vbNullString, vbNormalFocus)
>    End Sub
>
> More info: http://vb.mvps.org/samples/HyperJmp
> --
> ..NET: It's About Trust!
http://vfred.mvps.org
>
>
>
Author
12 May 2009 7:55 PM
Nobody
"GS" <G*@discussions.microsoft.com> wrote in message
news:55409C09-132B-454D-9A23-0D186E2F431B@microsoft.com...
> He has a SDK API that's not
> registerable (regsrver32 doesn't like it) and so I can't use it with VBA
> projects.

You might be able to use the SDK with Declare statement. Just post some of
the declaration here.
Author
12 May 2009 10:43 PM
GS
Thanks! This would require shipping the DLL with VB6 apps, but will it work
with VBA apps? Using SendMessage seems easier to me!

Here's the DLL constants:
// API public commands
const
HEC_EXITPUB = 0; // Exit program
HEC_LOADPAGE = 1; // Load page with name
HEC_BRINGTOFRONT = 2; // Bring to front
HEC_LOADID = 3; // Load page with ID
HEC_ISHEPUB = 4; // Internal use
DLLname = 'HEAPI.DLL';


Here's the DLL functions:
// * DLL import functions *
function StartPublication(PathToPublication, Params:PChar): LongInt; cdecl;
external DLLName;
// Execute the command of the pub specified by ID.
function ExecuteCommand(PubId: LongInt; Command: LongInt; Params1: PChar):
LongInt;cdecl; external DLLName;
// Launch a pub & execute a command immediately. Always starts a new session.
function StartExecuteCommand(PathToPublication:PChar; Command: LongInt;
Params1: PChar): LongInt;cdecl; external DLLName;

Here's the procedures that call them:
procedure HEDisplayPage(pagename: String);
begin
EnsurePubIsRunning;
ExecuteCommand(CurrentAppID, HEC_LOADPAGE, PChar(pagename));
ExecuteCommand(CurrentAppID, HEC_BRINGTOFRONT, '');
end;

procedure HEDisplayID(pageID: Integer);
begin
EnsurePubIsRunning;
ExecuteCommand(CurrentAppID, HEC_LOADID, PChar(inttostr(pageID)));
ExecuteCommand(CurrentAppID, HEC_BRINGTOFRONT, '');
end;


Garry
--
Author
13 May 2009 12:27 AM
Nobody
"GS" <G*@discussions.microsoft.com> wrote in message
news:ED9DE7FF-0919-4871-A560-FC65EEDBDD21@microsoft.com...
> Thanks! This would require shipping the DLL with VB6 apps, but will it
> work
> with VBA apps? Using SendMessage seems easier to me!

Unfortunately, the functions were exported with "cdecl", so you can't use
them in VB6/VBA. You can tell the author to just edit "cdecl" to "stdcall"
in the function declaration and recompile. See this article:

INFO: Visual Basic Requirements for Exported DLL Functions
http://support.microsoft.com/kb/142840

Another option is to make a light weight C or Delphi wrapper DLL, which
translates the calls. Here is an air code:

// Original function
function StartPublication(PathToPublication, Params:PChar): LongInt; cdecl;
external DLLName;

// This one is callable from VB
function StartPublicationVB(PathToPublication, Params:PChar):LongInt;
stdcall;
begin
  // Call the original function
  Result := StartPublication(PathToPublication, Params);
end;

You can download Turbo C++ or Delphi 2006 freely from here:

http://www.turboexplorer.com
Author
13 May 2009 1:06 AM
GS
Thanks again!
I'll pass this on to the author to see if he'll respond.

Here's what he sent me regarding the DLL:

About the wMsg: it’s more complicated: below is the code used by the DLL to
send data to the publication.



function SendHEMessage(Window: THandle; Envoi: THEVCommand): LongInt;

var

CopyDataStruct: TCopyDataStruct;

begin

with CopyDataStruct do

begin

  dwData := 1;

  cbData := sizeof(Envoi);

  lpData := @Envoi;

end;

Result := SendMessage(Window, WM_COPYDATA, HInstance,
LONGINT(@CopyDataStruct));

end;



// Echange données.

PCopyDataStruct = ^TCopyDataStruct;

TCopyDataStruct = record

  dwData: LongInt;

  cbData: LongInt;

  lpData: Pointer;

end;



Here are the two structures I mentioned:



PHEVCommand = ^THEVCommand;

THEVCommand = packed record

  Param1: string[255];

  Param2: string[255];

  Param3: LongInt;

  Command: integer;

  Sender: THandle;

end;



it works with pointers. AFAIR, VB doesn’t handle pointers (or maybe they
changed this…)?

Maybe you could make some VB sense of it. If you could I will be most
appreciative!

Garry
--
Author
13 May 2009 1:37 AM
Nobody
"GS" <G*@discussions.microsoft.com> wrote in message
news:8D0AF688-66D9-44C4-9168-E4D5B82AE096@microsoft.com...
> Thanks again!
> I'll pass this on to the author to see if he'll respond.
>
> Here's what he sent me regarding the DLL:

See this article:

How To Pass String Data Between Applications Using SendMessage
http://support.microsoft.com/kb/176058

Show quoteHide quote
> function SendHEMessage(Window: THandle; Envoi: THEVCommand): LongInt;
>
> var
>
> CopyDataStruct: TCopyDataStruct;
>
> begin
>
> with CopyDataStruct do
>
> begin
>
>  dwData := 1;
>
>  cbData := sizeof(Envoi);
>
>  lpData := @Envoi;
>
> end;
>
> Result := SendMessage(Window, WM_COPYDATA, HInstance,
> LONGINT(@CopyDataStruct));
>
> end;

Translation(air code):

Function SendHEMessage(ByVal Window As Long,  ByRef Envoi As THEVCommand) As
Long
    Dim cds As TCopyDataStruct;

    cds.dwData = 1
    cds.cbData = Len(Envoi)
    cds.lpData = VarPtr(Envoi)
    SendHEMessage = SendMessage(Window, WM_COPYDATA, App.hInstance, ByVal
VarPtr(cds))
End Function


> PCopyDataStruct = ^TCopyDataStruct;
>
> TCopyDataStruct = record
>
>  dwData: LongInt;
>
>  cbData: LongInt;
>
>  lpData: Pointer;
>
> end;


This is declared in the article.


Show quoteHide quote
> PHEVCommand = ^THEVCommand;
>
> THEVCommand = packed record
>
>  Param1: string[255];
>
>  Param2: string[255];
>
>  Param3: LongInt;
>
>  Command: integer;
>
>  Sender: THandle;
>
> end;

Translation(air code):

Type  THEVCommand
    Param1(1 To 255) As String
    Param2(1 To 255) As String
    Param3 As Long
    Command As Long
    Sender As Long
End Type

The 255 above could be 256, I am not sure. You will need to use CopyMemory()
to copy from a VB String to the byte array. Example:

CopyMemory ByVal VarPtr(Envoi.Param1(0), ByVal s, Len(s) + 1

Save your project often because you are likly to crash the IDE.

> it works with pointers. AFAIR, VB doesn't handle pointers (or maybe they
> changed this.)?

WM_COPYDATA can copy data between processes if needed.
Author
14 May 2009 2:53 PM
GS
More thanks!
I guess what I need to do is try to follow the flow path of the values being
passed, starting with the entry point from the software procedure making the
call to the DLL, and from there to the DLL making the call to SendMessage.
Therein is where I will find a solution.

Unfortunately, my programming skills are only 'entry level' and so this is
way over my head. However, I have an appetite for learning and so I will
persist.

I really appreciate your assistance! Thanks so much...

Kind regards,
Garry
--

Show quoteHide quote
"Nobody" wrote:

> "GS" <G*@discussions.microsoft.com> wrote in message
> news:8D0AF688-66D9-44C4-9168-E4D5B82AE096@microsoft.com...
> > Thanks again!
> > I'll pass this on to the author to see if he'll respond.
> >
> > Here's what he sent me regarding the DLL:
>
> See this article:
>
> How To Pass String Data Between Applications Using SendMessage
> http://support.microsoft.com/kb/176058
>
> > function SendHEMessage(Window: THandle; Envoi: THEVCommand): LongInt;
> >
> > var
> >
> > CopyDataStruct: TCopyDataStruct;
> >
> > begin
> >
> > with CopyDataStruct do
> >
> > begin
> >
> >  dwData := 1;
> >
> >  cbData := sizeof(Envoi);
> >
> >  lpData := @Envoi;
> >
> > end;
> >
> > Result := SendMessage(Window, WM_COPYDATA, HInstance,
> > LONGINT(@CopyDataStruct));
> >
> > end;
>
> Translation(air code):
>
> Function SendHEMessage(ByVal Window As Long,  ByRef Envoi As THEVCommand) As
> Long
>     Dim cds As TCopyDataStruct;
>
>     cds.dwData = 1
>     cds.cbData = Len(Envoi)
>     cds.lpData = VarPtr(Envoi)
>     SendHEMessage = SendMessage(Window, WM_COPYDATA, App.hInstance, ByVal
> VarPtr(cds))
> End Function
>
>
> > PCopyDataStruct = ^TCopyDataStruct;
> >
> > TCopyDataStruct = record
> >
> >  dwData: LongInt;
> >
> >  cbData: LongInt;
> >
> >  lpData: Pointer;
> >
> > end;
>
>
> This is declared in the article.
>
>
> > PHEVCommand = ^THEVCommand;
> >
> > THEVCommand = packed record
> >
> >  Param1: string[255];
> >
> >  Param2: string[255];
> >
> >  Param3: LongInt;
> >
> >  Command: integer;
> >
> >  Sender: THandle;
> >
> > end;
>
> Translation(air code):
>
> Type  THEVCommand
>     Param1(1 To 255) As String
>     Param2(1 To 255) As String
>     Param3 As Long
>     Command As Long
>     Sender As Long
> End Type
>
> The 255 above could be 256, I am not sure. You will need to use CopyMemory()
> to copy from a VB String to the byte array. Example:
>
> CopyMemory ByVal VarPtr(Envoi.Param1(0), ByVal s, Len(s) + 1
>
> Save your project often because you are likly to crash the IDE.
>
> > it works with pointers. AFAIR, VB doesn't handle pointers (or maybe they
> > changed this.)?
>
> WM_COPYDATA can copy data between processes if needed.
>
>
>
>
>
Author
14 May 2009 4:59 PM
Nobody
Show quote Hide quote
"GS" <G*@discussions.microsoft.com> wrote in message
news:CDEFE9C3-37D1-4E40-8E0D-76BCB93B500E@microsoft.com...
> More thanks!
> I guess what I need to do is try to follow the flow path of the values
> being
> passed, starting with the entry point from the software procedure making
> the
> call to the DLL, and from there to the DLL making the call to SendMessage.
> Therein is where I will find a solution.
>
> Unfortunately, my programming skills are only 'entry level' and so this is
> way over my head. However, I have an appetite for learning and so I will
> persist.
>
> I really appreciate your assistance! Thanks so much...

Try using Spy++, which is part of VS6, in the VS6 Tools menu. If you don't
have it, use the following software:

http://www.windows-spy.com

Monitor the target application for WM_COPYDATA activity, and you will see
what it's being sent to.
Author
13 May 2009 1:28 AM
Jeremiah D. Seitz
On Tue, 12 May 2009 20:27:31 -0400, "Nobody" <nob***@nobody.com>
wrote:

>Unfortunately, the functions were exported with "cdecl", so you can't use
>them in VB6/VBA. You can tell the author to just edit "cdecl" to "stdcall"
>in the function declaration and recompile. See this article:

Paul Caton (@PSC) has written some code to call *any* (or almost any)
export from a DLL, no matter its export method. If the OP has trouble
getting the author to create a stdcall version, there's always the
other option.

http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=70195&lngWId=1

    J.
    Jeremiah D. Seitz
    Omega Techware
    http://www.omegatechware.net
Author
14 May 2009 2:36 PM
GS
Hello Jeremiah,

Thanks for your input. I can tell you for sure that the author has no
intention of recompiling the DLL, not even to make it registerable.<??>

I will look at this whether I get SendMessage working or not.

Kind regards,
Garry
--

Show quoteHide quote
"Jeremiah D. Seitz" wrote:

> On Tue, 12 May 2009 20:27:31 -0400, "Nobody" <nob***@nobody.com>
> wrote:
>
> >Unfortunately, the functions were exported with "cdecl", so you can't use
> >them in VB6/VBA. You can tell the author to just edit "cdecl" to "stdcall"
> >in the function declaration and recompile. See this article:
>
> Paul Caton (@PSC) has written some code to call *any* (or almost any)
> export from a DLL, no matter its export method. If the OP has trouble
> getting the author to create a stdcall version, there's always the
> other option.
>
> http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=70195&lngWId=1
>
>     J.
>     Jeremiah D. Seitz
>     Omega Techware
>     http://www.omegatechware.net
>