Prev: ndp20-kb916002-x86.exe supperceded by .net 2 sp1?
Next: Dynamically creating an ActiveX on a WPF/Windows .Net app
From: Jozsef Bekes on 20 Aug 2008 12:23 Hello All, I have a tester appliaction that tests our MFC application by pushing buttons and filling editboxes, etc. automatically. It identifies the control windows by the control id, that can be retrieved by GetWindowLongPtr(hwnd, GWL_ID); Our application also has a complicated .net dialog written in vb.net. When I tried to implement some testcases for this dialog, I found out (to my amazement) that the control id for any control becomes different when the dialog gets destroyed and created again. Now my question is: Is there a reliable way how I could find the HWND of a .NET control using win32 calls? For buttons it is ok, they have unique windownames (that is the label on them), so I do not strictly need the ctrl id. But the windowname of an editbox is its content, that is not unique on this complicated dialog. I do have access to the vb.net code, so I can do modifications if that can help my situation, but I do not want a COM interface that returns the HWND for the requested control, I hope there is a solution more elegant than that. Do you have any sugestions other than to find a control by its position? Thank you!! Best regards, Jozsi
From: Peter Duniho on 20 Aug 2008 12:59 On Wed, 20 Aug 2008 09:23:25 -0700, Jozsef Bekes <bjdodo(a)hotmail.com> wrote: > [...] > Our application also has a complicated .net dialog written in vb.net. > When I > tried to implement some testcases for this dialog, I found out (to my > amazement) that the control id for any control becomes different when the > dialog gets destroyed and created again. I don't find that too surprising. .NET Forms are created programmatically instead of using a dialog template from a resource, and assuming an ID is assigned at all, the Forms Designer code doesn't do that so it wouldn't be persistent across instances. > Now my question is: > > Is there a reliable way how I could find the HWND of a .NET control using > win32 calls? I'm confused. The first part of your question said that you can retrieve the ID, but it's changing from instance to instance. To do that you'd need the HWND so that you can use that in the call to GetWindowLongPtr(). Given that the first part of your question implies that you already have the HWND, why are you now asking how to get the HWND? Also, a minor point: if you're calling GetWindowLongPtr(), you should be passing GWLP_ID as the index. GWL_ID is for GetWindowLong(). Of course, given that you're just getting the control index and not an actual pointer, maybe it's better to just go back to using GetWindowLong(). > For buttons it is ok, they have unique windownames (that is the label on > them), so I do not strictly need the ctrl id. But the windowname of an > editbox is its content, that is not unique on this complicated dialog. > > I do have access to the vb.net code, so I can do modifications if that > can > help my situation, but I do not want a COM interface that returns the > HWND > for the requested control, I hope there is a solution more elegant than > that. > > Do you have any sugestions other than to find a control by its position? Well, it seems to me that you could in fact add some code to the dialog Form's constructor that explicitly sets the GWL_ID for each control. Just use p/invoke to get at the SetWindowLong() function, and call that for each control with whatever ID you want to set. Pete
From: Jozsef Bekes on 20 Aug 2008 13:17 Hi Peter, Thanks for the answer! > the Forms Designer code doesn't do that so it wouldn't be persistent > across instances. Ok, it makes sense :-) > I'm confused. The first part of your question said that you can retrieve > the ID, but it's changing from instance to instance. To do that you'd > need the HWND so that you can use that in the call to GetWindowLongPtr(). I can enumerate the child windows (=controls) of the form. In theory, if one of them has the control id I am looking for, that is the HWND I want. This is what does not work. > Also, a minor point: if you're calling GetWindowLongPtr(), you should be > passing GWLP_ID as the index. Good point :-) Thanks! > Well, it seems to me that you could in fact add some code to the dialog > Form's constructor that explicitly sets the GWL_ID for each control. Just > use p/invoke to get at the SetWindowLong() function, and call that for > each control with whatever ID you want to set. Ok, this sounds like a solution, I am not too glad about it though. All in all there is no easy way to find a control from a different process unless I prepare my control so. I wonder if there is an automated tester software, that can push buttons for you on a .net application. If there is I guess there must be a way to achieve what I want. Well anyway, it's better than nothing :-)) Thanks!! Jozsi "Peter Duniho" <NpOeStPeAdM(a)nnowslpianmk.com> wrote in message news:op.uf62tato8jd0ej(a)petes-computer.local... > On Wed, 20 Aug 2008 09:23:25 -0700, Jozsef Bekes <bjdodo(a)hotmail.com> > wrote: > >> [...] >> Our application also has a complicated .net dialog written in vb.net. >> When I >> tried to implement some testcases for this dialog, I found out (to my >> amazement) that the control id for any control becomes different when the >> dialog gets destroyed and created again. > > I don't find that too surprising. .NET Forms are created programmatically > instead of using a dialog template from a resource, and assuming an ID is > assigned at all, the Forms Designer code doesn't do that so it wouldn't be > persistent across instances. > >> Now my question is: >> >> Is there a reliable way how I could find the HWND of a .NET control using >> win32 calls? > > I'm confused. The first part of your question said that you can retrieve > the ID, but it's changing from instance to instance. To do that you'd > need the HWND so that you can use that in the call to GetWindowLongPtr(). > Given that the first part of your question implies that you already have > the HWND, why are you now asking how to get the HWND? > > Also, a minor point: if you're calling GetWindowLongPtr(), you should be > passing GWLP_ID as the index. GWL_ID is for GetWindowLong(). Of course, > given that you're just getting the control index and not an actual > pointer, maybe it's better to just go back to using GetWindowLong(). > >> For buttons it is ok, they have unique windownames (that is the label on >> them), so I do not strictly need the ctrl id. But the windowname of an >> editbox is its content, that is not unique on this complicated dialog. >> >> I do have access to the vb.net code, so I can do modifications if that >> can >> help my situation, but I do not want a COM interface that returns the >> HWND >> for the requested control, I hope there is a solution more elegant than >> that. >> >> Do you have any sugestions other than to find a control by its position? > > Well, it seems to me that you could in fact add some code to the dialog > Form's constructor that explicitly sets the GWL_ID for each control. Just > use p/invoke to get at the SetWindowLong() function, and call that for > each control with whatever ID you want to set. > > Pete
From: Jozsef Bekes on 21 Aug 2008 09:27 Hi Peter, I have got a response in another forum. This looks better, although not perfect: "You can fill "AccessibleName" property with unique ID string for a given control. Then, from the tester application call `AccessibleObjectFromWindow' in order to obtain `IAccessible' interface for the control. Use the `IAccessible::get_accName' method to identify your control." BR, Jozsi "Jozsef Bekes" <bjdodo(a)hotmail.com> wrote in message news:%23LgwyiuAJHA.1184(a)TK2MSFTNGP04.phx.gbl... > Hi Peter, > > Thanks for the answer! > >> the Forms Designer code doesn't do that so it wouldn't be persistent >> across instances. > Ok, it makes sense :-) > >> I'm confused. The first part of your question said that you can retrieve >> the ID, but it's changing from instance to instance. To do that you'd >> need the HWND so that you can use that in the call to GetWindowLongPtr(). > > I can enumerate the child windows (=controls) of the form. In theory, if > one of them has the control id I am looking for, that is the HWND I want. > This is what does not work. > >> Also, a minor point: if you're calling GetWindowLongPtr(), you should be >> passing GWLP_ID as the index. > > Good point :-) Thanks! > >> Well, it seems to me that you could in fact add some code to the dialog >> Form's constructor that explicitly sets the GWL_ID for each control. >> Just use p/invoke to get at the SetWindowLong() function, and call that >> for each control with whatever ID you want to set. > > Ok, this sounds like a solution, I am not too glad about it though. All in > all there is no easy way to find a control from a different process unless > I prepare my control so. I wonder if there is an automated tester > software, that can push buttons for you on a .net application. If there is > I guess there must be a way to achieve what I want. > > Well anyway, it's better than nothing :-)) > > Thanks!! > Jozsi > > > > > > > "Peter Duniho" <NpOeStPeAdM(a)nnowslpianmk.com> wrote in message > news:op.uf62tato8jd0ej(a)petes-computer.local... >> On Wed, 20 Aug 2008 09:23:25 -0700, Jozsef Bekes <bjdodo(a)hotmail.com> >> wrote: >> >>> [...] >>> Our application also has a complicated .net dialog written in vb.net. >>> When I >>> tried to implement some testcases for this dialog, I found out (to my >>> amazement) that the control id for any control becomes different when >>> the >>> dialog gets destroyed and created again. >> >> I don't find that too surprising. .NET Forms are created >> programmatically instead of using a dialog template from a resource, and >> assuming an ID is assigned at all, the Forms Designer code doesn't do >> that so it wouldn't be persistent across instances. >> >>> Now my question is: >>> >>> Is there a reliable way how I could find the HWND of a .NET control >>> using >>> win32 calls? >> >> I'm confused. The first part of your question said that you can retrieve >> the ID, but it's changing from instance to instance. To do that you'd >> need the HWND so that you can use that in the call to GetWindowLongPtr(). >> Given that the first part of your question implies that you already have >> the HWND, why are you now asking how to get the HWND? >> >> Also, a minor point: if you're calling GetWindowLongPtr(), you should be >> passing GWLP_ID as the index. GWL_ID is for GetWindowLong(). Of course, >> given that you're just getting the control index and not an actual >> pointer, maybe it's better to just go back to using GetWindowLong(). >> >>> For buttons it is ok, they have unique windownames (that is the label on >>> them), so I do not strictly need the ctrl id. But the windowname of an >>> editbox is its content, that is not unique on this complicated dialog. >>> >>> I do have access to the vb.net code, so I can do modifications if that >>> can >>> help my situation, but I do not want a COM interface that returns the >>> HWND >>> for the requested control, I hope there is a solution more elegant than >>> that. >>> >>> Do you have any sugestions other than to find a control by its position? >> >> Well, it seems to me that you could in fact add some code to the dialog >> Form's constructor that explicitly sets the GWL_ID for each control. >> Just use p/invoke to get at the SetWindowLong() function, and call that >> for each control with whatever ID you want to set. >> >> Pete > >
From: Peter Duniho on 21 Aug 2008 11:38
On Thu, 21 Aug 2008 06:27:52 -0700, Jozsef Bekes <bjdodo(a)hotmail.com> wrote: > Hi Peter, > > I have got a response in another forum. This looks better, although not > perfect: > > "You can fill "AccessibleName" property with unique ID string for a given > control. Then, from the tester application call > `AccessibleObjectFromWindow' > in order to obtain `IAccessible' interface for the control. Use the > `IAccessible::get_accName' method to identify your control." The IAccessible interface is part of the larger accessibility support in Windows. I would not personally use it to accomplish some other unrelated task. YMMV. I also don't see how using that is significantly better than setting the GWL_ID value explicitly in code. The only significant difference between the two is in how the ID information is entered. Maybe it's marginally easier to enter that ID in the VS Designer, but it's not that hard to just write the code to assign it either. Pete |