hidrau
asked on
Only to improve a function
Hello guys, I have this function and I would also like to get the name of my windows.
like: form1 , form2
procedure TForm1.Timer1Timer(Sender: TObject);
var
pt : TPoint;
wnd : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
begin
// if you use 'controls' unit, then you may use Mouse.CursorPos instead of variable 'pt'
// in that case GetCursorPos() is not necessary
GetCursorPos(pt);
wnd := WindowFromPoint(pt);
GetClassName(wnd, @txt1[0], sizeof(txt1));
GetWindowText(wnd, @txt2[0], sizeof(txt2));
if txt2 = '' then begin // sometimes wm_gettext works when GetWindowText() does not work
SendMessage(wnd, wm_gettext, sizeof(txt2), integer(@txt2[0]));
end;
label1.Caption := format('handle: %.8x'#13#10'class: %s'#13#10'text: %s', [wnd, txt1, txt2]);
end;
like: form1 , form2
procedure TForm1.Timer1Timer(Sender:
var
pt : TPoint;
wnd : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
begin
// if you use 'controls' unit, then you may use Mouse.CursorPos instead of variable 'pt'
// in that case GetCursorPos() is not necessary
GetCursorPos(pt);
wnd := WindowFromPoint(pt);
GetClassName(wnd, @txt1[0], sizeof(txt1));
GetWindowText(wnd, @txt2[0], sizeof(txt2));
if txt2 = '' then begin // sometimes wm_gettext works when GetWindowText() does not work
SendMessage(wnd, wm_gettext, sizeof(txt2), integer(@txt2[0]));
end;
label1.Caption := format('handle: %.8x'#13#10'class: %s'#13#10'text: %s', [wnd, txt1, txt2]);
end;
When I do this with a new application and I hold the mouse over the main form area (not over a component) I get the result you are expecting.
ASKER
I know, but my form is a skin and it doesn't give me the name of my form, you see.
It gives me the component name that is all on the form
It gives me the component name that is all on the form
Try this:
procedure TForm1.Timer1Timer(Sender: TObject);
var
pt : TPoint;
wnd : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
begin
GetCursorPos(pt);
wnd := WindowFromPoint(pt);
if wnd<>0 then begin
GetClassName(wnd, @txt1[0], sizeof(txt1));
if txt1<>'TForm' then begin //if the found window isn't a TForm, let's look for it's parent
wnd:=GetParent(wnd);
GetClassName(wnd, @txt1[0], sizeof(txt1));
end;
GetWindowText(wnd, @txt2[0], sizeof(txt2));
if txt2 = '' then begin // sometimes wm_gettext works when GetWindowText() does not work
SendMessage(wnd, wm_gettext, sizeof(txt2), integer(@txt2[0]));
end;
label1.Caption := format('handle: %.8x'#13#10'class: %s'#13#10'text: %s', [wnd, txt1, txt2]);
end;
end;
procedure TForm1.Timer1Timer(Sender:
var
pt : TPoint;
wnd : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
begin
GetCursorPos(pt);
wnd := WindowFromPoint(pt);
if wnd<>0 then begin
GetClassName(wnd, @txt1[0], sizeof(txt1));
if txt1<>'TForm' then begin //if the found window isn't a TForm, let's look for it's parent
wnd:=GetParent(wnd);
GetClassName(wnd, @txt1[0], sizeof(txt1));
end;
GetWindowText(wnd, @txt2[0], sizeof(txt2));
if txt2 = '' then begin // sometimes wm_gettext works when GetWindowText() does not work
SendMessage(wnd, wm_gettext, sizeof(txt2), integer(@txt2[0]));
end;
label1.Caption := format('handle: %.8x'#13#10'class: %s'#13#10'text: %s', [wnd, txt1, txt2]);
end;
end;
Correction, should be
if txt1<>'TForm1' then begin //or whatever the expected class name (of the form) is.
Or better try (to get through several layers if necessary):
procedure TForm1.Timer1Timer(Sender: TObject);
var
pt : TPoint;
i:Integer;
wnd, backup : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
begin
GetCursorPos(pt);
i:=0;
backup:=0;
wnd := WindowFromPoint(pt);
if wnd<>0 then begin
backup:=wnd;
GetClassName(wnd, @txt1[0], sizeof(txt1));
while txt1<>'TForm1' do begin
wnd:=GetParent(wnd);
GetClassName(wnd, @txt1[0], sizeof(txt1));
if i>100 then
break;
inc(i);
end;
if wnd=0 then begin
wnd:=backup;
GetClassName(wnd, @txt1[0], sizeof(txt1));
end;
GetWindowText(wnd, @txt2[0], sizeof(txt2));
if txt2 = '' then begin // sometimes wm_gettext works when GetWindowText() does not work
SendMessage(wnd, wm_gettext, sizeof(txt2), integer(@txt2[0]));
end;
label1.Caption := format('handle: %.8x'#13#10'class: %s'#13#10'text: %s', [wnd, txt1, txt2]);
end;
end;
if txt1<>'TForm1' then begin //or whatever the expected class name (of the form) is.
Or better try (to get through several layers if necessary):
procedure TForm1.Timer1Timer(Sender:
var
pt : TPoint;
i:Integer;
wnd, backup : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
begin
GetCursorPos(pt);
i:=0;
backup:=0;
wnd := WindowFromPoint(pt);
if wnd<>0 then begin
backup:=wnd;
GetClassName(wnd, @txt1[0], sizeof(txt1));
while txt1<>'TForm1' do begin
wnd:=GetParent(wnd);
GetClassName(wnd, @txt1[0], sizeof(txt1));
if i>100 then
break;
inc(i);
end;
if wnd=0 then begin
wnd:=backup;
GetClassName(wnd, @txt1[0], sizeof(txt1));
end;
GetWindowText(wnd, @txt2[0], sizeof(txt2));
if txt2 = '' then begin // sometimes wm_gettext works when GetWindowText() does not work
SendMessage(wnd, wm_gettext, sizeof(txt2), integer(@txt2[0]));
end;
label1.Caption := format('handle: %.8x'#13#10'class: %s'#13#10'text: %s', [wnd, txt1, txt2]);
end;
end;
Or even better try (a more generic solution, that doesn't rely on the class name):
procedure TForm1.Timer1Timer(Sender: TObject);
var
pt : TPoint;
i:Integer;
wnd, parentWnd, backup : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
begin
GetCursorPos(pt);
i:=0;
backup:=0;
wnd := WindowFromPoint(pt);
if wnd<>0 then begin
backup:=wnd;
parentWnd:=GetParent(wnd);
while parentWnd<>0 do begin
wnd:=GetParent(wnd);
parentWnd:=GetParent(wnd);
if i>1000 then
break;
inc(i);
end;
if wnd=0 then begin
wnd:=backup;
end;
GetClassName(wnd, @txt1[0], sizeof(txt1));
GetWindowText(wnd, @txt2[0], sizeof(txt2));
if txt2 = '' then begin
SendMessage(wnd, wm_gettext, sizeof(txt2), integer(@txt2[0]));
end;
label1.Caption :=format('handle: %.8x'#13#10'class: %s'#13#10'text: %s', [wnd, txt1, txt2]);
end;
end;
procedure TForm1.Timer1Timer(Sender:
var
pt : TPoint;
i:Integer;
wnd, parentWnd, backup : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
begin
GetCursorPos(pt);
i:=0;
backup:=0;
wnd := WindowFromPoint(pt);
if wnd<>0 then begin
backup:=wnd;
parentWnd:=GetParent(wnd);
while parentWnd<>0 do begin
wnd:=GetParent(wnd);
parentWnd:=GetParent(wnd);
if i>1000 then
break;
inc(i);
end;
if wnd=0 then begin
wnd:=backup;
end;
GetClassName(wnd, @txt1[0], sizeof(txt1));
GetWindowText(wnd, @txt2[0], sizeof(txt2));
if txt2 = '' then begin
SendMessage(wnd, wm_gettext, sizeof(txt2), integer(@txt2[0]));
end;
label1.Caption :=format('handle: %.8x'#13#10'class: %s'#13#10'text: %s', [wnd, txt1, txt2]);
end;
end;
ASKER
ok Tname, I am gonna test it.
There are two built in safeguards (backup and brake if i>x) that are probably not needed (at least not both and especially backup). You could try a simplified version (it also shows the level of parentage):
procedure TForm1.Timer1Timer(Sender: TObject);
var
pt : TPoint;
wnd, parentWnd : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
level:Integer;
begin
level:=0;
GetCursorPos(pt);
wnd := WindowFromPoint(pt);
if wnd<>0 then begin
parentWnd:=GetParent(wnd);
while parentWnd<>0 do begin
wnd:=GetParent(wnd);
parentWnd:=GetParent(wnd);
inc(level);
end;
GetClassName(wnd, @txt1[0], sizeof(txt1));
GetWindowText(wnd, @txt2[0], sizeof(txt2));
if txt2 = '' then begin
SendMessage(wnd, wm_gettext, sizeof(txt2), integer(@txt2[0]));
end;
Label1.Caption:='Level: '+IntToStr(level)+#13#10; //Just to test the level depth
Label1.Caption:=Label1.Cap tion+forma t('handle: %.8x'#13#10'class: %s'#13#10'text: %s', [wnd, txt1, txt2]);
end;
end;
procedure TForm1.Timer1Timer(Sender:
var
pt : TPoint;
wnd, parentWnd : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
level:Integer;
begin
level:=0;
GetCursorPos(pt);
wnd := WindowFromPoint(pt);
if wnd<>0 then begin
parentWnd:=GetParent(wnd);
while parentWnd<>0 do begin
wnd:=GetParent(wnd);
parentWnd:=GetParent(wnd);
inc(level);
end;
GetClassName(wnd, @txt1[0], sizeof(txt1));
GetWindowText(wnd, @txt2[0], sizeof(txt2));
if txt2 = '' then begin
SendMessage(wnd, wm_gettext, sizeof(txt2), integer(@txt2[0]));
end;
Label1.Caption:='Level: '+IntToStr(level)+#13#10; //Just to test the level depth
Label1.Caption:=Label1.Cap
end;
end;
ASKER
I tested the last version and I got the name only of my form,
I need to get this information:
Component name : Tbutton
Form where the component is present : form2
This is only to work on my system, I need to map my system in run time, for this reason, I need this.
You see,
I need to get this information:
Component name : Tbutton
Form where the component is present : form2
This is only to work on my system, I need to map my system in run time, for this reason, I need this.
You see,
>brake
I meant break of course :)
I meant break of course :)
ASKER
Sorry, I didn't understand
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
The comment should be:
GetClassName(wnd, @txt3[0], sizeof(txt3)); // <---- if you want the type, e.g TButton
GetClassName(wnd, @txt3[0], sizeof(txt3)); // <---- if you want the type, e.g TButton
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
TName , I could see that some components name I can't get the name, example:
Tlabel - Timage - TSpeedButton
Maybe there are others :((
Why?
Tlabel - Timage - TSpeedButton
Maybe there are others :((
Why?
Tlabel - Timage - TSpeedButton
These components (and all other derived from TGraphicControl) don't have window handles, so: no luck...
These components (and all other derived from TGraphicControl) don't have window handles, so: no luck...
That is because they are not window controls
>and all other derived from TGraphicControl...
Just have a look at a VCL hierarchy map. It's basically
TWinControl - yes
TGraphicControl - no (and none of the non-visual components of course...)
http://bdn.borland.com/article/images/20569/3112b.gif (not complete)
http://magicpotato.com/bbs/data/p_tip/vcl.jpg (this is quite big)
Just have a look at a VCL hierarchy map. It's basically
TWinControl - yes
TGraphicControl - no (and none of the non-visual components of course...)
http://bdn.borland.com/article/images/20569/3112b.gif (not complete)
http://magicpotato.com/bbs/data/p_tip/vcl.jpg (this is quite big)
ASKER
I see, ok Tname. I thank you very much for your help
and for the participation of mikelittlewood
and for the participation of mikelittlewood
No problem Hidrau
You're welcome and thanks.
@ mikelittlewood
Just tried your version. Nice one, thanks.
@ mikelittlewood
Just tried your version. Nice one, thanks.
ASKER
TName, I could see that your function is returning me the name of my caption form, I need to get the name of my form.
Where I need to change? Here GetWindowText(wnd, @txt2[0], sizeof(txt2));?
Where I need to change? Here GetWindowText(wnd, @txt2[0], sizeof(txt2));?
ASKER
My application works with a component named TsuiForm from SUIPack, this component is a couple of components to work with skin. When I place this component, it covers my form. When I start your procedure the name retrieved is only
from my suiForm and not the name of my windows. I need to retrieve only the name of my window when it is from Tform.
Thanks Very much
from my suiForm and not the name of my windows. I need to retrieve only the name of my window when it is from Tform.
Thanks Very much
> your function is returning me the name of my caption form, I need to get the name of my form.
The *name* of the form is an internal variable in your application, and I don't think there is an easy (via API) way of retrieving it.
Main question is: do you want to do all this from outside your application (one application trying to find out properties of another application)? This is what I presumed...
If you want to do it from within your application (regardless of how many forms are involved), then there are many more things you can do.
And if it's two different applications we're talking about - do you control (can you change the source for) both of them?
The *name* of the form is an internal variable in your application, and I don't think there is an easy (via API) way of retrieving it.
Main question is: do you want to do all this from outside your application (one application trying to find out properties of another application)? This is what I presumed...
If you want to do it from within your application (regardless of how many forms are involved), then there are many more things you can do.
And if it's two different applications we're talking about - do you control (can you change the source for) both of them?
ASKER
>>Main question is: do you want to do all this from outside your application (one application trying to find out properties of another application)? This is what I presumed...
I need this only in my application.
I need this only in my application.
Ok, this will show you
Class of the component
Class of the form
Name of the form (real name, not caption)
for normal Delphi applications.
Now regarding TsuiForm - as I've never used them, it's pretty hard to guess what they are doing.
Tell me what you see now if your mouse hovers over a component on a form with Tsui skin.
procedure TForm1.Timer1Timer(Sender: TObject);
var
pt : TPoint;
wnd, parentWnd : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
i:Integer;
FormName, FormClass:String;
begin
FormName:='';
GetCursorPos(pt);
wnd := WindowFromPoint(pt);
if wnd<>0 then begin
GetClassName(wnd, @txt1[0], sizeof(txt1));
parentWnd:=GetParent(wnd);
while parentWnd<>0 do begin
wnd:=GetParent(wnd);
parentWnd:=GetParent(wnd);
end;
GetClassName(wnd, @txt2[0], sizeof(txt2));
for i:=0 to Application.ComponentCount -1 do begin
if Application.Components[i] is TForm then
if TForm(Application.Componen ts[i]).Han dle = Wnd then
FormName:=TForm(Applicatio n.Componen ts[i]).Nam e;
end;
Label1.Caption:='Component class: '+txt1+#13#10;
Label1.Caption:=Label1.Cap tion+'Form class: '+txt2+#13#10;
Label1.Caption:=Label1.Cap tion+'Form name: '+FormName;
end;
end;
Class of the component
Class of the form
Name of the form (real name, not caption)
for normal Delphi applications.
Now regarding TsuiForm - as I've never used them, it's pretty hard to guess what they are doing.
Tell me what you see now if your mouse hovers over a component on a form with Tsui skin.
procedure TForm1.Timer1Timer(Sender:
var
pt : TPoint;
wnd, parentWnd : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
i:Integer;
FormName, FormClass:String;
begin
FormName:='';
GetCursorPos(pt);
wnd := WindowFromPoint(pt);
if wnd<>0 then begin
GetClassName(wnd, @txt1[0], sizeof(txt1));
parentWnd:=GetParent(wnd);
while parentWnd<>0 do begin
wnd:=GetParent(wnd);
parentWnd:=GetParent(wnd);
end;
GetClassName(wnd, @txt2[0], sizeof(txt2));
for i:=0 to Application.ComponentCount
if Application.Components[i] is TForm then
if TForm(Application.Componen
FormName:=TForm(Applicatio
end;
Label1.Caption:='Component
Label1.Caption:=Label1.Cap
Label1.Caption:=Label1.Cap
end;
end;
ASKER
Yeah, that's right!
now, give more one thing, can you give me the component name?
Like this:
Component Class : Tbutton
Component name : BT_open
Form class: Tform1
Form Name: Form1
now, give more one thing, can you give me the component name?
Like this:
Component Class : Tbutton
Component name : BT_open
Form class: Tform1
Form Name: Form1
Ok, try this:
procedure TMyForm1.Timer1Timer(Sende r: TObject);
var
pt : TPoint;
wnd, parentWnd, compWnd : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
i,j:Integer;
ComponentName, ComponentClass,FormName,Fo rmClass:St ring;
begin
FormName:='';
GetCursorPos(pt);
wnd := WindowFromPoint(pt);
if wnd<>0 then begin
compWnd:=wnd;
GetClassName(wnd, @txt1[0], sizeof(txt1));
parentWnd:=GetParent(wnd);
while parentWnd<>0 do begin
wnd:=GetParent(wnd);
parentWnd:=GetParent(wnd);
end;
GetClassName(wnd, @txt2[0], sizeof(txt2));
for i:= 0 to Screen.FormCount-1 do begin
if Screen.Forms[i].Handle=wnd then begin
FormName:=Screen.Forms[i]. Name;
ComponentName:=FormName;
for j:=0 to Screen.Forms[i].ComponentC ount-1 do begin
if Screen.Forms[i].Components [j] is TWinControl then
if TWinControl(Screen.Forms[i ].Componen ts[j]).Han dle = compWnd then
ComponentName:=Screen.Form s[i].Compo nents[j].N ame;
end;
end;
end;
Label1.Caption:='Component class: '+txt1+#13#10;
Label1.Caption:=Label1.Cap tion+'Comp onent Name: '+ComponentName+#13#10;
Label1.Caption:=Label1.Cap tion+'Form class: '+txt2+#13#10;
Label1.Caption:=Label1.Cap tion+'Form name: '+FormName;
end;
end;
procedure TMyForm1.Timer1Timer(Sende
var
pt : TPoint;
wnd, parentWnd, compWnd : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
i,j:Integer;
ComponentName, ComponentClass,FormName,Fo
begin
FormName:='';
GetCursorPos(pt);
wnd := WindowFromPoint(pt);
if wnd<>0 then begin
compWnd:=wnd;
GetClassName(wnd, @txt1[0], sizeof(txt1));
parentWnd:=GetParent(wnd);
while parentWnd<>0 do begin
wnd:=GetParent(wnd);
parentWnd:=GetParent(wnd);
end;
GetClassName(wnd, @txt2[0], sizeof(txt2));
for i:= 0 to Screen.FormCount-1 do begin
if Screen.Forms[i].Handle=wnd
FormName:=Screen.Forms[i].
ComponentName:=FormName;
for j:=0 to Screen.Forms[i].ComponentC
if Screen.Forms[i].Components
if TWinControl(Screen.Forms[i
ComponentName:=Screen.Form
end;
end;
end;
Label1.Caption:='Component
Label1.Caption:=Label1.Cap
Label1.Caption:=Label1.Cap
Label1.Caption:=Label1.Cap
end;
end;
ASKER
Tname, thanks very much.
It was all that I needed. :))))
It was all that I needed. :))))
You're welcome :)
One more version ;)
This will work for TGraphicControl descendants (TLabel, TSpeedButton etc) also.
It is possible because we are within one application.
procedure TMyForm1.Timer1Timer(Sende r: TObject);
var
pt : TPoint;
wnd, parentWnd, compWnd : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
i,j:Integer;
ComponentName, ComponentClass,FormName,Fo rmClass:St ring;
begin
FormName:='';
GetCursorPos(pt);
wnd := WindowFromPoint(pt);
if wnd<>0 then begin
compWnd:=wnd;
GetClassName(wnd, @txt1[0], sizeof(txt1));
ComponentClass:=txt1;
parentWnd:=GetParent(wnd);
while parentWnd<>0 do begin
wnd:=GetParent(wnd);
parentWnd:=GetParent(wnd);
end;
GetClassName(wnd, @txt2[0], sizeof(txt2));
for i:= 0 to Screen.FormCount-1 do begin
if Screen.Forms[i].Handle=wnd then begin
FormName:=Screen.Forms[i]. Name;
ComponentName:=FormName;
pt:=Screen.Forms[i].Screen ToClient(p t);
for j:=0 to Screen.Forms[i].ComponentC ount-1 do begin
if Screen.Forms[i].Components [j] is TWinControl then begin
if TWinControl(Screen.Forms[i ].Componen ts[j]).Han dle = compWnd then
ComponentName:=Screen.Form s[i].Compo nents[j].N ame;
end
else begin
if PtInRect(TControl(Screen.F orms[i].Co mponents[j ]).BoundsR ect, pt) then
if Screen.Forms[i].Components [j] is TControl then begin
ComponentName:=Screen.Form s[i].Compo nents[j].N ame;
ComponentClass:=Screen.For ms[i].Comp onents[j]. ClassName;
end;
end;
end;
end;
end;
Label1.Caption:='Component class: '+ComponentClass+#13#10;
Label1.Caption:=Label1.Cap tion+'Comp onent Name: '+ComponentName+#13#10;
Label1.Caption:=Label1.Cap tion+'Form class: '+txt2+#13#10;
Label1.Caption:=Label1.Cap tion+'Form name: '+FormName;
end;
end;
This will work for TGraphicControl descendants (TLabel, TSpeedButton etc) also.
It is possible because we are within one application.
procedure TMyForm1.Timer1Timer(Sende
var
pt : TPoint;
wnd, parentWnd, compWnd : cardinal;
txt1 : array [0..255] of char;
txt2 : array [0..255] of char;
i,j:Integer;
ComponentName, ComponentClass,FormName,Fo
begin
FormName:='';
GetCursorPos(pt);
wnd := WindowFromPoint(pt);
if wnd<>0 then begin
compWnd:=wnd;
GetClassName(wnd, @txt1[0], sizeof(txt1));
ComponentClass:=txt1;
parentWnd:=GetParent(wnd);
while parentWnd<>0 do begin
wnd:=GetParent(wnd);
parentWnd:=GetParent(wnd);
end;
GetClassName(wnd, @txt2[0], sizeof(txt2));
for i:= 0 to Screen.FormCount-1 do begin
if Screen.Forms[i].Handle=wnd
FormName:=Screen.Forms[i].
ComponentName:=FormName;
pt:=Screen.Forms[i].Screen
for j:=0 to Screen.Forms[i].ComponentC
if Screen.Forms[i].Components
if TWinControl(Screen.Forms[i
ComponentName:=Screen.Form
end
else begin
if PtInRect(TControl(Screen.F
if Screen.Forms[i].Components
ComponentName:=Screen.Form
ComponentClass:=Screen.For
end;
end;
end;
end;
end;
Label1.Caption:='Component
Label1.Caption:=Label1.Cap
Label1.Caption:=Label1.Cap
Label1.Caption:=Label1.Cap
end;
end;