Go Back  Xtreme Visual Basic Talk > Legacy Visual Basic (VB 4/5/6) > VBA / Office Integration > Excel > Screen.ActiveForm in VBA - Is there an API or Workaround?


Reply
 
Thread Tools Display Modes
  #1  
Old 08-18-2009, 02:31 PM
Khaelor Khaelor is offline
Newcomer
 
Join Date: Aug 2009
Posts: 3
Default Screen.ActiveForm in VBA - Is there an API or Workaround?


Hi,

I am trying to determine which UserForm is currently Active (has Focus) during script execution...

I have a public function in a module that prints out data from a ListView (named PrintMe). I designed this function to be as portable as possible, meaning it can accept any listview from any form as an argument; However the only thing I have left to do is Hide the form that calls PrintMe Function.

I did many searches and the only relevant piece of info I came up with was Screen.ActiveForm, but this doesn't seem to work in VBA. So my questions:

Is there an Import API that will give me access to Screen.[whatever]?

Is there a workaround that would have the same results as the following (assuming the visible property existed for forms):

Dim frm as UserForm
For Each frm in UserForms
If frm.Visible = True Then frm.hide
next frm

Obviously the .Visible property doesn't exist for UserForms, but the idea is there.

I have a workaround for this problem, which would be to just pass the form name in the function arguments: Function PrintMe(frm as UserForm), etc.

That is Plan B at the moment, as I already have 3 arguments required for my PrintMe function, and I'd rather not have to have a 4th in there.

The ideal situation is that the module script itself can find out which userform called the function.

Thanks in advance.

EDIT:
Ok so apparently my workaround won't actually work. When passing a UserForm as an argument, you cannot access the .Hide method on it. For Example (much abridged):

Assume:
Function PrintMe(frm as UserForm)
frm.hide
end function

Called With:
PrintMe(frmSearch)

This errors out in runtime:

"Run-time error '438':
Object doesn't support this property or method"

and frm.Hide is highlighted.

So I guess I need help with my workaround too, if the main problem can't be solved...

Last edited by Khaelor; 08-18-2009 at 03:02 PM.
Reply With Quote
  #2  
Old 08-18-2009, 09:15 PM
kassyopeia kassyopeia is offline
Junior Contributor
 
Join Date: Mar 2009
Posts: 301
Default

Quote:
Originally Posted by Khaelor View Post
Is there an Import API that will give me access to Screen.[whatever]?
Pretty much, there is an API that gives you the hWnd (window handle) of the active window, which you can then compare with the UserForms' hWnds, which in turn can also be obtained using API. If you insist on doing it this way, I'll post links to the relevant MSDN pages.
Quote:
That is Plan B at the moment, as I already have 3 arguments required for my PrintMe function, and I'd rather not have to have a 4th in there.
If you don't mind me saying so, that isn't much of a reason for resorting to API. It's your call, of course, but it seems disproportionate...

Anyway, I don't think you even need to do that. If you are passing the ListView control, you can easily navigate to the form, using .Parent I think. Additionally, your work-around code sample suggests that simply hiding all forms would do the trick.
Quote:
When passing a UserForm as an argument, you cannot access the .Hide method on it.
This is extremely weird. Somehow, VBA magically adds .Hide, .Show and .Visible to the UserForm interface to create the UserForm1 (etc.) interface. If you search for .Hide in the Object Browser, even including hidden members, nothing related shows up, so I have no idea what's going on.

Nevertheless, this can be compensated for. If your ListView forms are all instances of the same UserForm class, let's call it ListViewContainer, you can do it like
Code:
For Each frm in UserForms
    If TypeOf frm Is ListViewContainer Then
        Set lvc = frm
        lvc.Hide
    End If
Next frm
where lvc is declared as ListViewContainer. If they are instances of different UserForm classes, you can create a common interface which exposes the required functionality. You add a class module to your project and name it say IListViewContainer (the leading "I" is not needed but good practice, it marks it as an interface class). Then, you "Implement" this interface in each userform for which it is needed. The code looks like this:

class IListViewContainer
Code:
Public Sub lvcHide()
End Sub
Public Sub lvcShow(fsc As FormShowConstants)
End Sub
Public Property Get lvcVisible() As Boolean
End Property
Public Property Let lvcVisible(RHS As Boolean)
End Property
each UserForm
Code:
Implements IListViewContainer

Private Sub IListViewContainer_lvcHide()
    Call Me.Hide
End Sub
Private Sub IListViewContainer_lvcShow(fsc As FormShowConstants)
    Call Me.Show(fsc)
End Sub
Private Property Get IListViewContainer_lvcVisible() As Boolean
    IListViewContainer_lvcVisible = Me.Visible
End Property
Private Property Let IListViewContainer_lvcVisible(RHS As Boolean)
    Me.Visible = RHS
End Property
usage example
Code:
Private Function AsListViewContainer(frm As UserForm) As IListViewContainer
    Set AsListViewContainer = frm
End Function

For Each frm in UserForms
    If TypeOf frm Is IListViewContainer Then
        Call AsListViewContainer(frm).lvcHide
    End If
Next frm
So, the loop checks for each form if it is of a type which has the added interface functionality, and if so, uses the function to access that interface and call its lvcHide method. That method, in turn, calls the specific form classes Me.Hide method.

If you haven't used classes before, this may seem a lot of new stuff at once, but if you take it step by step, each one should be quite straightforward to follow, I hope.
Reply With Quote
  #3  
Old 08-19-2009, 03:25 PM
Khaelor Khaelor is offline
Newcomer
 
Join Date: Aug 2009
Posts: 3
Default

Quote:
Originally Posted by kassyopeia View Post
Pretty much, there is an API that gives you the hWnd (window handle) of the active window, which you can then compare with the UserForms' hWnds, which in turn can also be obtained using API. If you insist on doing it this way, I'll post links to the relevant MSDN pages.
Thanks - I'll look into the hWnd API.

Quote:
If you don't mind me saying so, that isn't much of a reason for resorting to API. It's your call, of course, but it seems disproportionate...
I agree - It was more along the lines of my intended design and then running into a roadblock... Then just wanting to figure out how to do what I originally wanted out of curiosity's sake

Quote:
Anyway, I don't think you even need to do that. If you are passing the ListView control, you can easily navigate to the form, using .Parent I think. Additionally, your work-around code sample suggests that simply hiding all forms would do the trick.
This one made me facepalm a bit, totally forgot about using the .Parent method. I'll give this one a try, I have a feeling it will do exactly what I want.

Quote:
If you haven't used classes before, this may seem a lot of new stuff at once, but if you take it step by step, each one should be quite straightforward to follow, I hope.
I haven't used classes before, but I have a rough understanding of them. I'll look into the code you supplied and mess around with it a bit.

Thanks
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
 
 
-->