Button caption from a Windows dll? How?

Hi all!

How can i read a control text from a Windows dll? For example i'd like to get the caption of a dialog button. Windows\System32\msgina.dll (under XP)

Dialog\1800\

CONTROL "&Change Password...", 1803, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 7, 98, 84, 14 (with ResourceHacker, in DIALOGEX)

I want to read this button's caption into an Edit.

Thanks!

(Please show me some source code)
rogerrrAsked:
Who is Participating?
 
moduloConnect With a Mentor Commented:
PAQed with points refunded (110)

modulo
Community Support Moderator
0
 
Ivanov_GCommented:
procedure TForm1.Button1Click(Sender: TObject);
var
  buffer: array[0..255] of Char;
  DLL_HANDLE : THandle;
begin
  DLL_HANDLE := LoadLibrary('msgina.dll');
  Loadstring(DLL_HANDLE, 1, @buffer, 255);  //1 = first string
  label1.Caption := StrPas(buffer);
end;
0
 
rogerrrAuthor Commented:
Thanks, but this code works only with Stringtable resources...
0
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

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.

 
TyrsisCommented:
I would suggest looking at the source code for the Resource Explorer and the Resource Utility components that are on the following page:

http://www.wilsonc.demon.co.uk/delphi.htm

All source code is included from that web page on how to find and read resources from DLL/EXEs in Delphi.  And it is all free.

I hope this helps put you on the right track.

Tyrsis
0
 
LRHGuyCommented:
Try this...you'll have to fill in a few items...

const
  Flags=format_message_from_hmodule or format_message_allocate_buffer;
  dllname='netmsg.dll';  //name of DLL to get message from
  msgno=12; //message number
var
  DLL:HModule;
  Msg:pChar;
begin
  dll:=loadlibraryex(dllname,0,load_library_as_datafile);
  if dll<>0 then begin
    if formatmessage(flags,pointer(dll),msgno,0,@msg,0,nil)>0 then begin
      showmessage(msg);
      localfree(cardinal(msg));
    end;
    freelibrary(dll);
  end;
0
 
rogerrrAuthor Commented:
Hi all!

It as good as done!:-)

I found a code but this doesn't works if the dialog type is DIALOGEX.

Code:

unit Unit1;

interface

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

  type
  TDialogItem = record
    ControlID: dWord;
    Title: WideString;
  end;


type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    FDlgItems: array of TDialogItem;
    procedure ReadDialogItems(Stream: TStream);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

function ReadChar(Stream: TStream; var Ch: WideChar): Boolean;
begin
  Stream.ReadBuffer(Ch, SizeOf(Ch));
  Result := Word(Ch) <> $0000;
end;

function ReadString(Stream: TStream; var StrBuf: WideString): Boolean;
var
  Ch: WideChar;
begin
  Result := True;
  StrBuf := '';
  if ReadChar(Stream, Ch) then begin
    Result := Word(Ch) <> $FFFF;
    if Result then begin
      StrBuf := StrBuf + Ch;
      while (Stream.Position <> Stream.Size) and ReadChar(Stream, Ch) do
        StrBuf := StrBuf + Ch;
    end
    else begin
      SetLength(StrBuf, 1);
      ReadChar(Stream, StrBuf[1]);
    end;
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
  msgina: HModule;
  Stream: TStream;
begin
  msgina := LoadLibrary('msgina.dll');
  try
    Stream := TResourceStream.CreateFromID(msgina, 1800, RT_DIALOG);
    try
      ReadDialogItems(Stream);
    finally
      Stream.Free;
    end;
  finally
    FreeLibrary(msgina);
  end;
  for I := 0 to Length(FDlgItems) - 1 do
    if FDlgItems[I].ControlID = 1803 then begin
      label1.caption:=FDlgItems[0].Title;
      Break;
    end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
Finalize(FDlgItems);
end;

procedure TForm1.ReadDialogItems(Stream: TStream);
var
  DataSize: Word;
  DlgItem: TDlgItemTemplate;
  DlgTemplate: TDlgTemplate;
  I: Integer;
  StrBuf: WideString;
begin
  Stream.ReadBuffer(DlgTemplate, SizeOf(DlgTemplate));
  ReadString(Stream, StrBuf);
  ReadString(Stream, StrBuf);
  ReadString(Stream, StrBuf);
  if (DlgTemplate.style and DS_SETFONT) <> 0 then begin
  Stream.Seek(SizeOf(SmallInt), soFromCurrent);
    ReadString(Stream, StrBuf);
  end;
  Finalize(FDlgItems);
  for I := 0 to DlgTemplate.cdit - 1 do begin
    SetLength(FDlgItems, I + 1);
    Stream.Seek(Stream.Position mod SizeOf(DWORD), soFromCurrent);
    Stream.ReadBuffer(DlgItem, SizeOf(DlgItem));
    FDlgItems[I].ControlID:= DlgItem.id;
   ReadString(Stream, StrBuf);
    ReadString(Stream, FDlgItems[I].Title);
   Stream.ReadBuffer(DataSize, SizeOf(DataSize));
    Stream.Seek(DataSize, soFromCurrent);
  end;
end;

end.



2500 is a simple DIALOG. I changed 1800 to 2500 and 1803 to 2501. Label1.Caption will be -->OK (Under XP)



What's the problem if i read a DIALOGEX type????????
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.