From: Steve Gerrard on

"Andy" <andrewjellis(a)hotmailnospam.com> wrote in message
news:D15CE7C3-B647-4333-9AEC-EECA00F61C67(a)microsoft.com...
> "Steve Gerrard" wrote:
>
>> I will poke around for a way to just load the menu at runtime...
>
> I'd be very grateful for that, thanks. Don't know where you are, but here
> (in UK) it's 4:27am, and I can't keep myself going any longer, so there's no
> rush!
>


Good news, I think.

The issue is the difference between Constituent controls and Contained controls.
If you put a PictureBox on a form, and then put a CheckBox inside the
picturebox, you can determine that the container of the checkbox is the
picturebox, but the parent of the checkbox is the form:

Private Sub Command1_Click()
Debug.Print "Checkbox parent is " & Check1.Parent.Name
Debug.Print "Checkbox container is " & Check1.Container.Name
End Sub

'result:
Checkbox parent is Form1
Checkbox container is Picture1

For a UserControl, there are two ways to go. If you make a UserControl a
ControlContainer, you can place one on a form, then put a checkbox inside of it,
just like with a picturebox:

'result:
Checkbox parent is Form1
Checkbox container is UserControl11

If, on the other hand, you went to the UserControl designer, and put a check box
on it directly, it would not be contained by the user control, it would be a
constituent. The code above wouldn't work, because the checkbox was not a
control on the form, but just a part of the usercontrol. With slightly different
code, you would find this result:
Checkbox parent is UserControl1
Checkbox container is UserControl1

The same applies to controls added dynamically at run-time. If they are added to
the Controls collection of the UserControl, they become constituent controls;
but if they are added to the Controls collection of the form, and their
container is set to the UserControl, they become contained controls. Clear as
mud?

- - - - - - -

So, here is how to make it work. I will call the "sizeable container"
usercontrol you mentioned UCHost, and the usercontrol of interest UCTest.

If you add an instance of UCTest at runtime, and add it to the form's Controls,
while making its container UCHost, then the menu defined in UCTest will be
merged with the form's menu, which is the goal. (If you added it directly to the
controls of UCHost, it would become a constituent control instead, and not
work).

So, UCHost has ControlContainer = True, and an instance is placed on Form1.
Form1 has a File menu, negotiate left, and a Window and Help menu, negotiate
right. UCTest has a menu, with each top level item set as negotiate middle.

In Project Properties, Make tab, uncheck the box "Remove information about
unused ActiveX Controls", so that UCTest can be added at runtime.

Then put this code in the Form:

Private Sub Command1_Click()
Dim Test As VBControlExtender

' add it to the form, but make UCHost1 the container

Set Test = Me.Controls.Add("Project1.UCTest", "UCTest1", Me.UCHost1)

With Test
.Visible = True
.Top = 100
.Left = 100
.SetFocus
Debug.Print .Parent.Name
Debug.Print .Container.Name
End With

End Sub

You should see that the parent is Form1, and the container is UCHost1. When
UCTest1 has focus, its menu will be inserted between the File and Window menus.

Very cool, in fact. I like this, now I want to find a place to use it...



From: Steve Gerrard on

"Andy" <andrewjellis(a)hotmailnospam.com> wrote in message
news:D15CE7C3-B647-4333-9AEC-EECA00F61C67(a)microsoft.com...
> "Steve Gerrard" wrote:
>
>
> BTW - I need to do Popup menus as well. I did find this, which I could use
> if necessary...
> http://www.developerfusion.co.uk/show/5475/
>

You don't really need that for pop up menus. They can be added to forms and
usercontrols fairly easily. Just define another top level menu item, say
mnuPopup, and set Visible = False. It won't show in the regular menu bar. To
display it as a popup, just do this (for a usercontrol):

Private Sub UserControl_MouseDown _
(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = vbRightButton Then
PopupMenu mnuPopup, , X, Y
End If
End Sub

You can then add code to the click event of each sub menu item in mnuPopup.

You could also create different popups for different constituent controls of the
user control as needed, using their respective MouseDown events.


From: Andy on
"Steve Gerrard" wrote:

<all snipped - you know what you wrote>

I played around with the code you sent, and I can get that to work OK.
However, I still can't get it to work in the app I'm developing. The reason
for that is... - remember, the whole point of my ucSizeableContainer UC is to
host other controls, but it contains a number of constituent controls, and I
need to site my hosted controls on one of them (picHostWindow, which is a
PictureBox). So, I thought my code should look something like this (with all
the stuff I don't need for this exercise stripped out to make it look a bit
more readable):

(In ucSizeableContainer)
Private mfrmHostForm As HostForm

Public Sub CreateHostedControl _
(ByVal ProgID As String, _
(ByVal ControlName As String)

Dim ctlExtender As VBControlExtender

Set ctlExtender = mfrmHostForm.Controls.Add _
("MyProject." & ProgID, ControlName, picHostWindow)

End Sub

But VB doesn't like that. It gives me
'Error 721 picHostWindow is not a valid control container'.

When I had it written as
Set ctlExtender = UserControl.Controls.Add -
("MyProject." & ProgID, ControlName, picHostWindow)
it was all fine - except, of course that the menus didn't appear.
From: Steve Gerrard on

"Andy" <andrewjellis(a)hotmailnospam.com> wrote in message
news:594B89CD-E2E3-4B4F-8F5B-8017C6B0E28E(a)microsoft.com...
> "Steve Gerrard" wrote:
>
> <all snipped - you know what you wrote>
>
> I played around with the code you sent, and I can get that to work OK.
> However, I still can't get it to work in the app I'm developing. The reason
> for that is... - remember, the whole point of my ucSizeableContainer UC is to
> host other controls, but it contains a number of constituent controls, and I
> need to site my hosted controls on one of them (picHostWindow, which is a
> PictureBox). So, I thought my code should look something like this (with all
> the stuff I don't need for this exercise stripped out to make it look a bit
> more readable):
>
> (In ucSizeableContainer)
> Private mfrmHostForm As HostForm
>
> Public Sub CreateHostedControl _
> (ByVal ProgID As String, _
> (ByVal ControlName As String)
>
> Dim ctlExtender As VBControlExtender
>
> Set ctlExtender = mfrmHostForm.Controls.Add _
> ("MyProject." & ProgID, ControlName, picHostWindow)
>
> End Sub
>
> But VB doesn't like that. It gives me
> 'Error 721 picHostWindow is not a valid control container'.
>
> When I had it written as
> Set ctlExtender = UserControl.Controls.Add -
> ("MyProject." & ProgID, ControlName, picHostWindow)
> it was all fine - except, of course that the menus didn't appear.

Ouch! When VB tells you a picturebox is not a container, that can't be good...

I suspect the problem is that the form doesn't know about picHostWindow, so it
won't accept it as the container.

I'm pretty sure that what you would have to do is make picHostWindow also be a
control that has mfrmHostForm as its Parent, with the ucSizeableContainer as its
container.

With the names changed, it could look something like this, which seemed to work
as a sub in the host user control:

Public Sub SetMeUp(Frm As Form)

Dim PicBox As PictureBox

' add a picture box to form, but make this UC its container
Set PicBox = Frm.Controls.Add("VB.PictureBox", "picHost", Me)
With PicBox
.Left = 500
.Top = 200
.Width = 3000
.Height = 2000
.BorderStyle = 1
.Visible = True
End With

' add the test UC to the form, and make the PicBox its container
Dim Ext As VBControlExtender
Set Ext = Frm.Controls.Add("Project1.UCTest", "UCTest1", PicBox)
With Ext
.Left = 100
.Top = 100
.Visible = True
.SetFocus
End With

End Sub

Hopefully that's enough layers of containers for you :)


From: Andy on
"Steve Gerrard" wrote:


> I'm pretty sure that what you would have to do is make picHostWindow also be a
> control that has mfrmHostForm as its Parent, with the ucSizeableContainer as its
> container.
>
> With the names changed, it could look something like this, which seemed to work
> as a sub in the host user control:
>
> Public Sub SetMeUp(Frm As Form)
>
> Dim PicBox As PictureBox
>
> ' add a picture box to form, but make this UC its container
> Set PicBox = Frm.Controls.Add("VB.PictureBox", "picHost", Me)
> With PicBox
> .Left = 500
> .Top = 200
> .Width = 3000
> .Height = 2000
> .BorderStyle = 1
> .Visible = True
> End With
>
> ' add the test UC to the form, and make the PicBox its container
> Dim Ext As VBControlExtender
> Set Ext = Frm.Controls.Add("Project1.UCTest", "UCTest1", PicBox)
> With Ext
> .Left = 100
> .Top = 100
> .Visible = True
> .SetFocus
> End With
>
> End Sub

This looks pretty much workable. Unfortunately, I'm not able to try this
out until late tonight because I'm dealing with other commitments today, but
I'll have a go.

Actually, it has occurred to me that one way I could go now is to abandon
ucSizeableContainer altogether. The original motivation for producing it was
to avoid having all the code for resizing hosted UCs repeated across multiple
forms, and perhaps that's no longer an issue for me. If I have one frmHost,
which itself manages hosted UCs, I still get to see this code in a single
place, which is what I was after. It then means that my picHostWindow is
known about by the form, and I should end up with something like this in
frmHost...

Dim Ext As VBControlExtender
Set Ext = Me.Controls.Add("MyProject." & ProgID, ControlName,
picHostWindow)

Which way I go with this, I'm undecided. I can see that ucSizeableContainer
could be useful for other applications, so perhaps I'll persist with it. But
if I still have trouble, it does look like I have a fallback position.

First  |  Prev  |  Next  |  Last
Pages: 1 2 3
Prev: COM-RPCServer - New Version
Next: Debug VB OCX and DLL