Author Topic: Cannot Refresh Controls on Palette!!  (Read 4199 times)

0 Members and 1 Guest are viewing this topic.

bncceo

  • Guest
Cannot Refresh Controls on Palette!!
« on: August 23, 2006, 10:36:37 AM »
VS 2005 & AC 2006

I have a problem: I have a palette in my project that contains controls such as multiple textboxes, combobox, buttons, etc. These controls are there to supply the user with calculated data as the user draws figures graphically on the drawing.

However, the only time I can get the controls to refresh on the palette is when the refreshcontrols subroutine is run by an event fired by a control on my palette. The following is the routine in the palette control code that is used to refresh the controls: (You can see everything I have tried in the commented fields)
Code: [Select]
Public Sub RefreshControls()
        'Dim docLock As DocumentLock = AcadApp.DocumentManager.MdiActiveDocument.LockDocument _
        '        (Autodesk.AutoCAD.ApplicationServices.DocumentLockMode.Write, "NB", "NB", True)
        'NativeMethods.SetFocus(Me.Handle)
        'ResetUCSButton.Enabled = True
        'AddNewBeamButton.Enabled = True
        'DistLoadButton.Enabled = True
        'PointLoadButton.Enabled = True
        LengthBox.Text = AppStart.CurrentBeam.Length.ToString
        BeamNameText.Text = AppStart.CurrentBeam.Name
        DeflectionBox.Text = AppStart.CurrentBeam.DeflectionFactorLL & "/" & AppStart.CurrentBeam.DeflectionFactor
        'MomentBox.Text = AppStart.CurrentBeam.CalcMoment.ToString
        'ShearBox.Text = AppStart.CurrentBeam.CalcShear.ToString
        'DeflBox.Text = AppStart.CurrentBeam.DistributedLoads.Count

        'LengthBox.Invalidate()
        'LengthBox.Refresh()
        'BeamNameText.Refresh()
        'DeflectionBox.Refresh()
        'MomentBox.Refresh()
        'ShearBox.Refresh()
        'DeflBox.Refresh()
        'ComboBox1.Refresh()
        'ComboBox1.Items.Clear()
        'Dim beams(AppStart.CurrentBeam.PassingBeams.Count) As String
        'Dim count As Integer = 1
        'For Each beam As BeamType In AppStart.CurrentBeam.PassingBeams
        '    beams.SetValue(beam, count)
        '    count += 1
        'Next
        ComboBox1.DataSource = Nothing
        ComboBox1.DataSource = AppStart.CurrentBeam.PassingBeams
        If ComboBox1.Items.Count > 0 Then
            ComboBox1.SelectedIndex = 0
        End If
        Me.Refresh()
        MyBase.Refresh()
        'AppStart.mPaletteSet.Visible = False
        'AppStart.mPaletteSet.Visible = True
        'ComboBox1.DisplayMember = "FullName"
        'docLock.Dispose()
        'Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor.UpdateScreen()
        'Autodesk.AutoCAD.ApplicationServices.Application.UpdateScreen()
    End Sub

The following is an examble of a handled button click event. When this is fired from a real "click" on a button on my palette, everything works fine as long as I run the NewBeamCommand subroutine directly. However, if I sendstringtoexecute then i have the same problem of the controls never refreshing. It seems that whenever I pass control to the Autocad Editor my palette stops repainting.

Code: [Select]
    Private Sub AddNewBeamButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AddNewBeamButton.Click
        AddNewBeamButton.Enabled = False
        DistLoadButton.Enabled = False
        PointLoadButton.Enabled = False
        ResetUCSButton.Enabled = False
        NativeMethods.SetFocus(AcadApp.DocumentManager.MdiActiveDocument.Window.Handle)
        Dim docLock As DocumentLock = AcadApp.DocumentManager.MdiActiveDocument.LockDocument _
                (Autodesk.AutoCAD.ApplicationServices.DocumentLockMode.Write, "NB", "NB", True)
        Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        'Commands.Command("NB")
        NewBeamCommand() '<- This sub marked with command attribute NB
        'Application.DocumentManager.MdiActiveDocument.SendStringToExecute("_NB ", True, False, True)
        RefreshControls() 'WHY WONT THIS WORK ARGGGHHHH!!!
        Dim db As Database = HostApplicationServices.WorkingDatabase()
        If Not XDataHelper.HasActiveTag(db) Then
            XDataHelper.TagAcadDoc(db)
        End If
        ResetUCSButton.Enabled = True
        AddNewBeamButton.Enabled = True
        DistLoadButton.Enabled = True
        PointLoadButton.Enabled = True
        AcadUi.SetUCS(Matrix3d.AlignCoordinateSystem(Ge.kOrigin, Ge.kXAxis, Ge.kYAxis, Ge.kZAxis, Ge.kOrigin, Ge.kXAxis, Ge.kYAxis, Ge.kZAxis))
        docLock.Dispose()
    End Sub

It is important to note that during debugging, I have identified that the controls properties are updated with the correct data every time. However, the controls are never repainted.

This is very frustrating because the data the controls hold is the whole reason for this program. Unless I figure this out, I will have to force the user to click a button every time they want to use a feature of my program, instead of being able to use commands and the command buffer!

I truly appreciate any help you can give me. I have been lurking here for a while and you guys seem to know your stuff. If you need more info or code, I will be happy to supply as much as I can.

Thanks!

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: Cannot Refresh Controls on Palette!!
« Reply #1 on: August 23, 2006, 06:36:24 PM »
Are you using the AutoCAD version of ShowDialog()? (sorry, I haven't got a sample to hand but it is in the windows section of the managed lib's)

AutoCAD always wants to take focus away from other resources so while your controls may be getting updated they may be missing out on the paint message as acad has taken back control. Using the acad version of show dialog enables your resources to be managed by acad a lot better and helps you to keep focus on your palatte.
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

bncceo

  • Guest
Re: Cannot Refresh Controls on Palette!!
« Reply #2 on: August 24, 2006, 09:51:30 AM »
Currently I am using the following code to show the palette (Borrowed from other samples, note that there are two tabbed pages in the palette):

Code: [Select]
    Public Shared Sub StartInterface()
        'check for instance of the toolpaletteset
        If mPaletteSet Is Nothing Then
            'not yet created so create it
            mPaletteSet = New Autodesk.AutoCAD.Windows.PaletteSet("", New Guid("6DDC1ED1-071E-4d33-A3B7-8602821EEDE8"))
            'add the events
            AddHandler mPaletteSet.StateChanged, AddressOf ps_change
            AddHandler mPaletteSet.Load, AddressOf ps_Load
            AddHandler mPaletteSet.Save, AddressOf ps_Save
            mPaletteSet.Name = "AcadTools for Structural D " & My.Application.Info.Version.Major & "." & My.Application.Info.Version.Minor
            'set how it will look/act
            mPaletteSet.Style = Autodesk.AutoCAD.Windows.PaletteSetStyles.ShowPropertiesMenu Or _
            Autodesk.AutoCAD.Windows.PaletteSetStyles.ShowAutoHideButton Or _
            Autodesk.AutoCAD.Windows.PaletteSetStyles.ShowCloseButton
            'set the minimum size
            mPaletteSet.MinimumSize = New System.Drawing.Size(146, 251)
            'create generic UserControl object
            Dim control As System.Windows.Forms.UserControl
            'create reference to our user control
            control = New LayerPalette
            'set the control's name - appears on tab in the paletteset
            control.Name = String.Format("Layers") '"AcadTools for Structural D " & My.Application.Info.Version.Major & "." & My.Application.Info.Version.Minor
            'store in global var for toolpalette interop
            mUC1 = control
            'add the user control [a.k.a. toolpalette] to the toolpaletteset
            mPaletteSet.Add(control.Name, control)
            'redirect object to second control
            '- comments for here are the same as above
            control = New BeamPalette
            control.Name = String.Format("Beams")
            mUC2 = control

            mPaletteSet.Add(control.Name, control)
            mPaletteSet.Location = New System.Drawing.Point(20, 20)
            mPaletteSet.Visible = True
            'These lines solve some problems with how the palette starts (docked or not)
            mPaletteSet.Dock = Autodesk.AutoCAD.Windows.DockSides.None
            mPaletteSet.Visible = False
            mPaletteSet.Visible = True

        End If
        'turn ON the toolpaletteset
        mPaletteSet.Visible = True
        mPaletteSet.KeepFocus = True
    End Sub

I don't think I understand how to implement ShowDialog() for a palette. Will it sit on top of autocad like the tabbed options page or will it still function like a native ACAD palette? At what point in the above code do I call ShowDialog()? Maybe I've got the whole thing wrong!! Thanks again for your help.

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: Cannot Refresh Controls on Palette!!
« Reply #3 on: August 24, 2006, 06:04:46 PM »
Whoops! you're right, when you create your own forms you need to use the acad ShowDialog method so they play nice with acad. It seems you don't have to call showdialog() as the palette object must look after that itself(?)

Here's my code for setting up a palette that may be of some help -
Code: [Select]
private Autodesk.AutoCAD.Windows.PaletteSet ps;
[CommandMethod("DCS3D")]
public void CreateDCSPalette()
{
if(ps == null)
{
// use constructor with Guid so that we can save/load user data
ps = new Autodesk.AutoCAD.Windows.PaletteSet("DCS3D Tools");
ps.Style = Autodesk.AutoCAD.Windows.PaletteSetStyles.ShowPropertiesMenu
| Autodesk.AutoCAD.Windows.PaletteSetStyles.ShowAutoHideButton
| Autodesk.AutoCAD.Windows.PaletteSetStyles.ShowCloseButton;
ps.Opacity = 90;
ps.Size = new System.Drawing.Size(250,400);
ps.MinimumSize = new System.Drawing.Size(225, 400);
ps.Add("Modelling Tools", new Dcs3dModify());
ps.Add("3D to 2D Tools", new DCS3dto2d());
ps.Add("Detailing Tools", new DCS3dDetailing());
ps.Add("Creation Database Utils", new Dcs3dUtils());
ps.Dock = Autodesk.AutoCAD.Windows.DockSides.None;
ps.KeepFocus = true;
ps.Visible = true;
}
else
{
ps.Visible = true;
}
}


"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

TonyT

  • Guest
Re: Cannot Refresh Controls on Palette!!
« Reply #4 on: August 25, 2006, 12:09:26 PM »
Currently I am using the following code to show the palette (Borrowed from other samples, note that there are two tabbed pages in the palette):

...

I don't think I understand how to implement ShowDialog() for a palette. Will it sit on top of autocad like the tabbed options page or will it still function like a native ACAD palette? At what point in the above code do I call ShowDialog()? Maybe I've got the whole thing wrong!! Thanks again for your help.

Is the handler for the command you are sending to the command line via SendStringToExecute() a method of the control on the palette?

If so, then the problem is that the handler is executing in the document execution context. To get the palette controls to update, you would need to post a message to the contol's message queue (using the PostMessage API).  You can try overriding the WndProc() of the control and watching for the message, and calling your control's Refresh() or Update() methods to make it happen.

bncceo

  • Guest
Re: Cannot Refresh Controls on Palette!!
« Reply #5 on: August 28, 2006, 11:44:28 AM »
Well guys I got it working the way it should and I couldn't have done it without your help!

After hearing your questions, it gave me some ideas and I started moving things around. Now, the palette's code only holds event handlers and the RefreshControls() method, and I have moved all of my other methods to a seperate class as Shared methods. In these shared methods I am referencing the variable I created in my StartInterface() method; mUC2 (which is the variable for the palette control I want to update). So now, I run my code as usual and when I want to update the information on the palette, I call mUC2.RefreshControls() and it works great!

I could have implemented the PostMessage() API and kept my methods in the control's class, but this is much cleaner in my opinion and there was no reason to keep the methods in the Palette's class.

Thanks a ton guys, you have saved my butt!