First you need to determine if it is windows message box or not.
What kind of message is in the message box (custom/standard win32/compilation of system strings)? Also an screen-shot would be nice if possible (so we can see more...) If you can make it work on some test machine then check also the CLASS_ID of the message box it can reveal if it is windows message box or custom VCL Form that just looks like it... You can obtain the Class_ID with
but its deleted and you do not have enough rep on SO to see it so here the copied source (VCL C++ so you need just port to Pascal if you do not have Borland C++) from it:
//---------------------------------------------------------------------------
//--- Windows ver: 1.1 ------------------------------------------------------
//---------------------------------------------------------------------------
HWND getwindow(HWND hnd0,AnsiString nam,AnsiString cls="")
{
int i,l,ln=nam.Length(),lc=cls.Length(),e;
char txt[256];
HWND hnd1;
if (hnd0==NULL) hnd1=GetTopWindow(hnd0);
else hnd1=GetWindow(hnd0,GW_HWNDNEXT);
for (;;)
{
e=1;
if (hnd1==hnd0) break;
if (hnd1==NULL) break;
l=GetWindowText(hnd1,txt,256);
if (e) { if (l>ln) l=ln; if (l<ln) e=0; else for (i=0;i<l;i++) if (txt[i]!=nam[i+1]) { e=0; break; } }
l=RealGetWindowClass(hnd1,txt,256);
if (e) { if (l>lc) l=lc; if (l<lc) e=0; else for (i=0;i<l;i++) if (txt[i]!=cls[i+1]) { e=0; break; } }
if (e) return hnd1;
hnd0=hnd1;
hnd1=GetWindow(hnd0,GW_HWNDNEXT);
}
return NULL;
};
//---------------------------------------------------------------------------
HWND getsubwindow(HWND hndp,HWND hnd0,AnsiString nam,AnsiString cls="")
{
int i,l,ln=nam.Length(),lc=cls.Length(),e;
char txt[256];
HWND hnd1;
if (hnd0==NULL) hnd1=GetTopWindow(hnd0);
else hnd1=GetWindow(hnd0,GW_HWNDNEXT);
for (;;)
{
e=1;
if (hnd1==hnd0) break;
if (hnd1==NULL) break;
if (GetParent(hnd1)!=hndp) e=0;
l=GetWindowText(hnd1,txt,256);
if (e) { if (l>ln) l=ln; if (l<ln) e=0; else for (i=0;i<l;i++) if (txt[i]!=nam[i+1]) { e=0; break; } }
l=RealGetWindowClass(hnd1,txt,256);
if (e) { if (l>lc) l=lc; if (l<lc) e=0; else for (i=0;i<l;i++) if (txt[i]!=cls[i+1]) { e=0; break; } }
if (e) return hnd1;
hnd0=hnd1;
hnd1=GetWindow(hnd0,GW_HWNDNEXT);
}
return NULL;
};
//---------------------------------------------------------------------------
bool getwindows(HWND &hnd,AnsiString &nam,AnsiString &cls)
{
int i,l;
char txt[256];
HWND hnd0=hnd;
nam=""; cls="";
if (hnd0==NULL) hnd=GetTopWindow(hnd0);
else hnd=GetWindow(hnd0,GW_HWNDNEXT);
if (hnd==hnd0) { hnd=NULL; return false; }
if (hnd==NULL) { hnd=NULL; return false; }
l=GetWindowText(hnd,txt,256); for (i=0;i<l;i++) nam+=txt[i];
l=RealGetWindowClass(hnd,txt,256); for (i=0;i<l;i++) cls+=txt[i];
return true;
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
It is written in BDS2006 Turbo C++ and use VCL so you need to convert it to your Language. Actually it uses only AnsiString
from VCL so just change it to any string you have. It is WinAPI based so include "Windows.h"
Here is some example of usage:
HANDLE hnd,hnd0;
AnsiString nam,cls;
AnsiString s,t="";
for (hnd=NULL;;)
{
if (!getwindows(hnd,nam,cls)) break; // get hnd,name and class
hnd0=GetParent(hnd); // get parent hnd
if (hnd0!=Application->Handle) continue;// filter out unwanted windows
// here process found window or add it to list or what ever
// for example add to memo->Lines->Add(...) so you obtain a list of all windows ...
s=AnsiString().sprintf("%X",hnd); while (s.Length()< 8) s="0"+s; t+=s+"h ";
s=cls; while (s.Length()<32) s=s+" "; t+=s+" ";
s=nam; while (s.Length()<32) s=s+" "; t+=s+"\r\n";
}
mm_log->Text=t; // just my memo
Here few lines of the unfiltered output:
Handle: Class_ID: Name
0003060Ch TTokenWindow CodeParamWindow
00030374h ComboLBox
000100F8h tooltips_class32
000100FAh TaskListThumbnailWnd
000100E6h tooltips_class32
000100E8h tooltips_class32
000100ECh tooltips_class32
000100EEh tooltips_class32
000100D0h tooltips_class32
000100E4h tooltips_class32
000100C8h Button Start
00030118h tooltips_class32
0003013Eh tooltips_class32
00040122h tooltips_class32
00090102h tooltips_class32
000100C2h Shell_TrayWnd
000303ECh TaskSwitcherOverlayWnd
00010240h IME Default IME
0001023Eh TaskSwitcherWnd Task Switching
00030376h ComboLBox
000403A0h Auto-Suggest Dropdown
00010108h CiceroUIWndFrame CiceroUIWndFrame
000100C6h MSCTFIME UI MSCTFIME UI
000100C0h IME Default IME
00010158h tooltips_class32
00010246h ATL:000007FEF0EF52C0 Network Flyout
00010180h CDA Server Class Administrator : CDA Server
00010182h IME Default IME
0001008Ch CiceroUIWndFrame CiceroUIWndFrame
0001008Ah CiceroUIWndFrame TF_FloatingLangBar_WndTitle
000303CEh tooltips_class32
0003061Eh TForm1 Project Euler
00090566h TApplication Project1
0003061Ah TPUtilWindow
00050610h IME Default IME
00090386h MSCTFIME UI MSCTFIME UI
00210408h IME Default IME
000B0416h TEditWindow Unit1.cpp
0007057Ch TWatchWindow Watch List
000105B2h TTabDockHostForm Project1.bdsproj - Project Manager
As you can see there will be many handles (all the visual components are like window so you need to filter out many things ... for example find the hnd
of your Message box App. and then show only handles which have the same parrent hnd0
.
For example I just created a message box to get the Class_ID:
int ret=MessageDlg("Test message",mtCustom,TMsgDlgButtons(mrOk),-1); // cls = "TMessageForm"
To get the parent handle you need to search the unfiltered list for class TApplication
. I used Application->Handle
instead as I test this directly in the same App.
if the message box is native win32
Then that does not necessarily mean the App calls winapi directly. Most likely it uses some VCL encapsulation of it instead. So browns the Delphi IDE help for any message box function names ... test them and look if the Class_ID matches with your app ...
if the message box is not native win32
Then it is most likely normal VCL window. The class name is then the name of the Delphi window class like TForm1
. Name of window is usually its Caption
and for App the exe filename. In this case showing dialog is different:
- set position
Left,Top,Width,Height
or call SetBounds()
- set the message can be a
TLabel,TEdit
,... Text
or Caption
property or directly rendered on Canvas
.
- set
Visible=true
or use ShowWindow,ShowModal
...
So you know what to look for ...
Text
For multilingual App the text is usually in some *.ini
or *.dll
file. In case of DLL the DLL can be compressed or encrypted so it is not easily visible. Try to search for files with Languages in filenames.
Hope it helps a bit if you got more info let me know.