Results 1 to 23 of 23

Thread: Non-Activating Form

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2014
    Posts
    553

    Non-Activating Form

    Is it possible for a project to have 2 Forms, a main primary Form and a second Form that never takes the focus.

    Sorry I didn't word that very well. The main Form is used for most all of the user interaction and the second form is optional and displays progress and status information. The second Form also provides configuration options, so it will be 'clicked' on from time to time.

    If possible, I'd like to have the main Form to always keep the focus as the active window. Placing code in the second Form to relinquish focus once it clicked upon, and returning it to the main Form, is problematic causing flashing titlebars.

    Thanks.

  2. #2
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,910

    Re: Non-Activating Form


  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2014
    Posts
    553

    Re: Non-Activating Form

    Hey Arnoutdv, thanks for the links, and showing a Form with the SW_SHOWNOACTIVATE flag is a good start, but if possible, I'd like to keep the secondary Form from ever taking the focus away from the primary Form.

    It would be like how a MDI child Form behaves, but allowing it to reside outside the bounds of the MDI parent.

    When working with a MDI parent form, it keeps the focus even when one interacts with one of it's child Forms. The TitleBars on all of the Forms, parent and children, all show as if they are 'Active'. Clicking on a child form does not cause the main MDI form to pass off the focus to the child. This is the functionality I'd like to copy.

    Thanks.

  4. #4
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,942

    Re: Non-Activating Form

    Hi Stuck,

    You want more than the following?

    Form1 code:

    Code:
    
    Option Explicit
    
    Private Sub Form_Load()
        Form2.Show
    End Sub
    
    Form2 code:
    Code:
    
    Option Explicit
    
    Private Sub Form_Activate()
        Form1.SetFocus
    End Sub
    
    Do you want the user to be able to drag the "status form" around by its titlebar? Would you want the "status form" to be sizable?

    Good Luck,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  5. #5
    PowerPoster
    Join Date
    Feb 2017
    Posts
    5,067

    Re: Non-Activating Form

    Quote Originally Posted by stuck-n-past View Post
    If possible, I'd like to have the main Form to always keep the focus as the active window. Placing code in the second Form to relinquish focus once it clicked upon, and returning it to the main Form, is problematic causing flashing titlebars.

    Thanks.
    You'll need to use subclassing.

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2014
    Posts
    553

    Re: Non-Activating Form

    Elroy - you sort of nailed it with your last remark - In a perfect solution, Yes I'd love to be able to have the status Form act and behave as any other normal Form. Move, Size, Min - Max, all in the normal fashion so that the user will automatically understand how to interact with it. And it would seem the best way to accomplish that is to have it behave as any other window would, supporting all of the standard commands / interface.

    Microsoft Word's Assistant comes really close to what I'm looking for, it allows one to drag the 'child' window outside of the bounds of the main window, and while doing so, Word does not loose focus.

    I just want to change the Word Assistant Window to a Program Status Window.


    Edit: I'm referring to the old style of Word's assistant when it appeared as a normal Form complete with TitleBar.
    Last edited by stuck-n-past; Dec 13th, 2017 at 10:56 AM.

  7. #7
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,942

    Re: Non-Activating Form

    Hi Stuck,

    Did you try the little demo (Form1 & Form2) I outlined? Maybe if you were to specify what that's not doing that you'd like to do.

    Take Care,
    Elroy

    EDIT1: And yeah, to suppress the bit of an activation flash that Form2 occasionally gets, it would take sub-classing.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2014
    Posts
    553

    Re: Non-Activating Form

    Sorry Eduardo, I just missed your post as I wrote mine. While I'm not always ready to invest the time needed to subclass things, this time around it seems the trade offs will be worth the effort if I can get the results I'm looking for.

  9. #9
    PowerPoster
    Join Date
    Feb 2017
    Posts
    5,067

    Re: Non-Activating Form

    Quote Originally Posted by stuck-n-past View Post
    Sorry Eduardo, I just missed your post as I wrote mine. While I'm not always ready to invest the time needed to subclass things, this time around it seems the trade offs will be worth the effort if I can get the results I'm looking for.
    Subclassing the WM_NCACTIVATE message and setting the wParam to 1 will prevent the title bar from showing the inactive state. But the focus will still change. Perhaps you can use this with a combination of Elroy's suggestion.

  10. #10
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,910

    Re: Non-Activating Form

    Ugly solution, sample with 2 Forms:
    Code:
    '---------------------------------------------------------------------------------------
    ' Module    : Form1
    '---------------------------------------------------------------------------------------
    Option Explicit
    
    Private Sub Command1_Click()
      Dim fForm2 As Form2
      
      Set fForm2 = New Form2
      Set fForm2.Parent = Me
      fForm2.Move Me.Left + Me.Width, Me.Top
      fForm2.Show
    End Sub
    Code:
    '---------------------------------------------------------------------------------------
    ' Module    : Form2
    '---------------------------------------------------------------------------------------
    Option Explicit
    
    Private m_fParent As Form
    
    Public Property Set Parent(fValue As Form)
      Set m_fParent = fValue
    End Property
    
    Private Sub Form_Activate()
      SetCaption "Activate"
      Timer1.Enabled = True
    End Sub
    
    Private Sub Form_Deactivate()
      Timer1.Enabled = False
      SetCaption "De_Activate"
    End Sub
    
    Private Sub Form_Load()
      Timer1.Interval = 100
      Timer1.Enabled = True
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
      Timer1.Enabled = False
      Set m_fParent = Nothing
    End Sub
    
    Private Sub Timer1_Timer()
      Timer1.Enabled = False
      'On Error Resume Next
      SetCaption "Timer event: set focus parent"
      m_fParent.SetFocus
    End Sub
    
    Private Sub SetCaption(ByVal sValue As String)
      Label1.Caption = sValue
      Debug.Print Timer, sValue
    End Sub

  11. #11
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,942

    Re: Non-Activating Form

    Hi Stuck,

    I'm probably willing to throw together a bit of subclassing, but I've got some more questions.

    Will you want to type on this "status-slave form" such as in a TextBox?

    Will you want to click buttons on this "status-slave form"?

    Will you want to check checkboxes and/or select option buttons on the "status-slave form"?


    The typing one is the one that's most difficult for me to get my head around. I mean, that's sort of the whole idea of focus/activation. Why would you want one form showing active but keyboard input goes to another. Is that what we're talking about? Splitting mouse and keyboard input between two forms?: Mouse going wherever it is, but keyboard staying with some "master" form?
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  12. #12

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2014
    Posts
    553

    Re: Non-Activating Form

    Thanks Eduardo, I had started looking through some of the Window messages wondering about how to prevent the Titlebar from flashing.

    I have code squirreled away somewhere that makes a functioning window created solely through API calls. Since the Status Form / Window has minimal functionality compared to the main form, I was curious if I could make use of it. Perhaps having that much control over the message processing loop, could there be a way of preventing the API created form gaining focus?

  13. #13

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2014
    Posts
    553

    Re: Non-Activating Form

    That's pretty cool Elroy, thanks.

    The Status Form is fairly sparse, containing only two types of controls, Option Buttons and a FlexGrid. There is nothing for the user to ever type when it comes to the status form. Depending on the data displayed on the FlexGrid, the need to size the form comes into play, and the few Option Buttons present are there to toggle between which columns are displayed.

    I've tried searching for information on Office97 assistant to see if I could make use of the same functionality, but it looks to be tied to Word.

    Arnoutdv - thanks for the code, I'll check it out.
    Last edited by stuck-n-past; Dec 13th, 2017 at 11:55 AM.

  14. #14
    PowerPoster ChrisE's Avatar
    Join Date
    Jun 2017
    Location
    Frankfurt
    Posts
    3,048

    Re: Non-Activating Form

    Hi Stuck,

    I use a Frame as a Form, I need sometimes to display additional Information.
    You just place a Frame on your Form and add the Controls you need.

    here the Class: clsFrameForm
    Code:
    '        Optionen: Moveable, Exitbutton, Area on Form
    '        Events:   QueryUnload, isMoved, LostFocus
    
    Option Explicit
    
    Private Type RECT
       Left As Long
       Top As Long
       Right As Long
       Bottom As Long
    End Type
    
    Private Declare Function DrawCaption Lib "user32" (ByVal hwnd As Long, _
                             ByVal hdc As Long, pcRect As RECT, _
                             ByVal un As Long) As Long
    
    Private Declare Function SetRect Lib "user32" (lpRect As RECT, _
                             ByVal X1 As Long, ByVal Y1 As Long, _
                             ByVal X2 As Long, ByVal Y2 As Long) As Long
    
    
    
    Private Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
    Private Const SM_CYSIZE = 31
    
    Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
    Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    
    Private Const tbarWidth = 20
    Private Const tbarColor = &H29
    
    Private Const BS_RIGHT& = &H200&
    Private Const BS_LEFT& = &H100&
    Private Const BS_BOTTOM& = &H800&
    Private Const BS_TOP& = &H400&
    Private Const BS_VCENTER& = &HC00&
    Private Const BS_CENTER& = &H300&
    
    Private Const GWL_STYLE& = -16
    
    
    '---------------------------------------------------------
    
    Private WithEvents Parentform As Form        'Parentform des Frames
    Private WithEvents myFrame As Frame          'Frame selbst
    Private ShapeA(1) As Shape                   'Border Frame Left/Top Right/Bottom
    Private WithEvents PicTitleBar As PictureBox 'die Titlebar
    Private WithEvents LabelBasic As Label       'zum Abdecken der PicBox
    Private WithEvents cmdExit As CommandButton  'Exitbutton
    Private WithEvents mTimer As Timer           'zur Überprüfung des Focus
    
    Public Event QueryUnload(Cancel As Boolean)    'Event Click Exitbutton
    Public Event FrameMoved()                    'Event Frame was moved
    Public Event LostFocus()                     'Event Frame(Controls) LostFocus
    Public Event GotFocus()                      'Event GotFocus
    
    Private MeFormX As Single                    'Variable moving Frame
    Private MeFormY As Single
    Private MeMouseDown As Boolean
    Private PicTitleBarGotFocus As Boolean       'Titlebar hat gerade den Focus erhalten
    
    Private mvarMoveable As Boolean              'Frame is moveable
    Private mvarExitButton As Boolean            'Exitbutton or not
    Private mvarCaption As String
    
    Private mvarOnFormTopMax As Single           'Area moving Frame
    Private mvarOnFormLeftMax As Single
    Private mvarOnFormRightMax As Single
    Private mvarOnFormBottomMax As Single
    
    Private mvarVisible As Boolean               'Frame visible schalten
    
    Public Property Let Visible(ByVal vData As Boolean)
          mvarVisible = vData
          myFrame.Visible = vData
          If myFrame.Visible Then
             PicTitleBar.SetFocus
             mTimer.Enabled = True
          Else
             mTimer.Enabled = False
          End If
    
          ZOrder 0
    End Property
    
    Public Property Get Visible() As Boolean
        Visible = mvarVisible
    End Property
    
    Public Property Let Caption(ByVal vData As String)
          mvarCaption = vData
          Refresh
    End Property
    
    Public Property Get Caption() As String
          Caption = mvarCaption
    End Property
    
    Public Property Let OnFormBottomMax(ByVal vData As Single)
        mvarOnFormBottomMax = vData
    End Property
    
    Public Property Get OnFormBottomMax() As Single
        OnFormBottomMax = mvarOnFormBottomMax
    End Property
    
    Public Property Let OnFormRightMax(ByVal vData As Single)
        mvarOnFormRightMax = vData
    End Property
    
    Public Property Get OnFormRightMax() As Single
        OnFormRightMax = mvarOnFormRightMax
    End Property
    
    Public Property Let OnFormLeftMax(ByVal vData As Single)
        mvarOnFormLeftMax = vData
    End Property
    
    Public Property Get OnFormLeftMax() As Single
        OnFormLeftMax = mvarOnFormLeftMax
    End Property
    
    Public Property Let OnFormTopMax(ByVal vData As Single)
        mvarOnFormTopMax = vData
    End Property
    
    Public Property Get OnFormTopMax() As Single
        OnFormTopMax = mvarOnFormTopMax
    End Property
    
    Public Property Let ExitButton(ByVal vData As Boolean)
    'Exitbutton zugelassen oder nicht
    
          mvarExitButton = vData
          If mvarExitButton Then
             cmdExit.Visible = True
          Else
             cmdExit.Visible = False
          End If
    End Property
    
    Public Property Get ExitButton() As Boolean
          ExitButton = mvarExitButton
    End Property
    
    Public Property Let Moveable(ByVal vData As Boolean)
          mvarMoveable = vData
    End Property
    
    Public Property Get Moveable() As Boolean
          Moveable = mvarMoveable
    End Property
    
    
    'Initialisieren Frame und sonstige Controls
    Public Sub Init(mFrame As Frame, Optional IsVisible As Boolean = True)
    
       Static Initdone As Boolean
       Dim i As Long
       Dim s As String
    
          If Initdone Then
             'nicht 2 x aufrufen
             Exit Sub
          End If
          Initdone = True
          
          'zuweisen Frame
          Set myFrame = mFrame
          'zuweisen der Parentform (aufrufende Form)
          Set Parentform = mFrame.Parent
          
          'Caption Ãœberschrift
          mvarCaption = myFrame.Caption
          
          'Grenzen für das Frame auf der Form
          mvarOnFormTopMax = 0
          mvarOnFormLeftMax = 0
          mvarOnFormRightMax = 0
          mvarOnFormBottomMax = 0
    
          'Controls aufnehmen in Parentform Collection
          Set LabelBasic = LoadControl("VB.Label", "FaF_LabelBasic")
          Set PicTitleBar = LoadControl("VB.Picturebox", "FAF_PicTitleBar")
          Set ShapeA(0) = LoadControl("VB.Shape", "FaF_ShapeA")
          Set ShapeA(1) = LoadControl("VB.Shape", "FaF_ShapeB")
          Set cmdExit = LoadControl("VB.CommandButton", "FaF_CmdExit")
          Set mTimer = LoadControl("VB.Timer", "FaF_mTimer")
          
          'Controls einrichten
          SetControls
          
          'anzeigen
          Visible = IsVisible
    End Sub
    
    'ein Control auf die Parentform beamen
    Private Function LoadControl(LibraryName As String, _
                                 objCtlName As String) As Control
    
       Dim i As Long
       Dim s As String
       Dim objCtl As Control
       
          i = 1
          Do
             On Error Resume Next
             'durch Anhängen einer Laufnummer eindeutige Bezeichner bilden
             s = objCtlName & i
             'Control in Parentform Collection aufnehmen
             Set objCtl = Parentform.Controls.Add(LibraryName, s, Parentform)
             If Err.Number = 0 Then
                'kein Fehler
                Exit Do
             ElseIf Err.Number = 727 Then
                'Control mit Bezeichner schon vorhanden, Laufnummer + 1
                i = i + 1
                Err.Clear
             Else
                'sonstiger Fehler
                FehlerAnzeige Err.Number, Err.Description, "clsFrameAsForm.LoadControl"
                Exit Do
             End If
          Loop
          
          'Control zuweisen
          Set LoadControl = objCtl
          Set objCtl = Nothing
    End Function
    
    'Controls endgültig einrichten
    Private Sub SetControls()
    
       Dim R As RECT
    
          'Frame ohne Border setzen
          myFrame.BorderStyle = 0
    
          'Border Right & Bottom
          With ShapeA(0)
             Set .Container = myFrame
             .BorderWidth = 2
             .BorderColor = vb3DDKShadow
             .Top = -60
             .Left = -60
             .Width = myFrame.Width + 60
             .Height = myFrame.Height + 60
             .Visible = True
          End With
          
          'Border Left & Top
          With ShapeA(1)
             Set .Container = myFrame
             .BorderWidth = 3
             .BorderColor = vb3DHighlight
             .Top = 0
             .Left = 0
             .Width = myFrame.Width + 60
             .Height = myFrame.Height + 60
             .Visible = True
          End With
    
          'Titlebar
          With PicTitleBar
             Set .Container = myFrame
             .TabStop = False
             .Left = 60
             .Top = 60
             .Width = myFrame.Width - 120
             .BorderStyle = 0
             .ScaleMode = vbPixels
             .Height = GetSystemMetrics(SM_CYSIZE) * Screen.TwipsPerPixelY
             .AutoRedraw = True
             .Cls
             .Visible = True
             'Fill Rect
             SetRect R, 0, 0, PicTitleBar.ScaleWidth, tbarWidth
             'Draw Titlebar
             DrawCaption PicTitleBar.hwnd, PicTitleBar.hdc, R, tbarColor
             
             .CurrentY = (.ScaleHeight - .TextHeight("W")) / 2
             .CurrentX = 5
             .ForeColor = vbTitleBarText
             .FontBold = True
             PicTitleBar.Print mvarCaption
             .AutoRedraw = False
          End With
          
          'Titlebar Abdeckung
          With LabelBasic
             Set .Container = PicTitleBar
             .Caption = ""
             .BorderStyle = 0
             .BackStyle = 0
             .Move 0, 0, PicTitleBar.Width, PicTitleBar.Height
             .Visible = True
          End With
          
          'Exitbutton
          With cmdExit
             Set .Container = PicTitleBar
             .Caption = "r"
             .FontName = "Marlett"
             .FontSize = 7
             .FontBold = False
             .FontItalic = False
             .Width = 17
             .Height = 14
             .Top = 2
             .Left = PicTitleBar.ScaleWidth - .Width - 2
             .TabStop = False
             .Visible = True
          End With
          
          'anpassen Höhe für X
          ButtonTextAlign 1&
          
          'der Timer
          mTimer.Interval = 500
          mTimer.Enabled = True
    End Sub
    
    'anpassen Beschriftung für Exitbutton
    Private Sub ButtonTextAlign(ByVal pos As Long)
    
       Dim oldStyle As Long
       Dim align As Long
       Dim ret As Long
       
          Select Case pos
          Case 0 ' Center
             align = BS_CENTER
             oldStyle = GetWindowLong(cmdExit.hwnd, GWL_STYLE) And Not (BS_TOP Or BS_BOTTOM)
          Case 1 ' Top
             align = BS_TOP
             oldStyle = GetWindowLong(cmdExit.hwnd, GWL_STYLE) And Not BS_BOTTOM
          Case 2 'Bottom
             align = BS_BOTTOM
             oldStyle = GetWindowLong(cmdExit.hwnd, GWL_STYLE) And Not BS_TOP
          End Select
          
          ret = SetWindowLong(cmdExit.hwnd, GWL_STYLE, oldStyle Or align)
          cmdExit.Refresh
    End Sub
    
    
    'ist der Focus bei einem Steuerelement des Frames
    Private Function IsActiveControlOnFrame() As Boolean
    
          If Parentform.ActiveControl.Container = myFrame Then
             IsActiveControlOnFrame = True
          End If
    End Function
    
    'Grundeinstellungen (Default)
    Private Sub Class_Initialize()
          
          mvarExitButton = True
          mvarMoveable = True
    End Sub
    
    'Objecte aus Parentform entfernen und terminieren
    Private Sub Class_Terminate()
          
          Parentform.Controls.Remove LabelBasic
          Parentform.Controls.Remove ShapeA(0)
          Parentform.Controls.Remove ShapeA(1)
          Parentform.Controls.Remove cmdExit
          Parentform.Controls.Remove mTimer
          Parentform.Controls.Remove PicTitleBar
          
          Set mTimer = Nothing
          Set LabelBasic = Nothing
          Set ShapeA(0) = Nothing
          Set ShapeA(1) = Nothing
          Set cmdExit = Nothing
          Set PicTitleBar = Nothing
          Set Parentform = Nothing
    End Sub
    
    'Abbruch, Frame schliessen
    Private Sub CmdExit_Click()
          
       Dim Cancel As Boolean
          
          'Event für Parentform auslösen
          PicTitleBar.SetFocus
          RaiseEvent QueryUnload(Cancel)
          If Not Cancel Then
             'Frame unvisible
             myFrame.Visible = False
          Else
             PicTitleBar.SetFocus
          End If
    End Sub
    
    'Frame verschieben
    Private Sub MoveFrame(X As Single, Y As Single)
    
       Dim X1 As Single
       Dim Y1 As Single
    
          'beachten des vorgegebenen Areas beim Verschieben
          With myFrame
             X1 = .Left + X - MeFormX
             Y1 = .Top + Y - MeFormY
             If X1 > (Parentform.ScaleWidth - OnFormRightMax - .Width) Then
                X1 = Parentform.ScaleWidth - OnFormRightMax - .Width
             End If
             If X1 < OnFormLeftMax Then
                X1 = OnFormLeftMax
             End If
             If Y1 > (Parentform.ScaleHeight - OnFormBottomMax - .Height) Then
                Y1 = Parentform.ScaleHeight - OnFormBottomMax - .Height
             End If
             If Y1 < OnFormTopMax Then
                Y1 = OnFormTopMax
             End If
             .Left = X1
             .Top = Y1
          End With
    End Sub
    
    'allgemeine Routine
    Private Sub FehlerAnzeige(ErrNumber As Long, ErrDescription As String, _
                             Optional Titel As String = "")
    
       Dim Msg As String
       
          Msg = "Fehler " & ErrNumber & vbCrLf & vbCrLf & _
                ErrDescription
          MsgBox Msg, vbCritical, Titel
    End Sub
    
    'überprüfen, ob das Focus haltende Steuerelement
    'zum Frame gehört
    Private Sub mTimer_Timer()
          
          If Not myFrame.Visible Then
             mTimer.Enabled = False
             Exit Sub
          End If
          
          If Not Parentform.ActiveControl.Container Is myFrame Then
             'nein, Event LostFocus feuern
             RaiseEvent LostFocus
          End If
    End Sub
    
    'beim Click auf das Frame
    Private Sub myFrame_Click()
    
          'in den Vordergrund
          myFrame.ZOrder 0
          
          'wenn der Focus nicht bei einem Steuerelement
          'des Frames liegt
          If Not IsActiveControlOnFrame Then
             PicTitleBar.SetFocus
             RaiseEvent GotFocus
          End If
    End Sub
    
    Public Sub Refresh()
    'Refreshen
    
          SetControls
    End Sub
    
    'reagieren auf vbMaximize, vbNormal, FormResize
    Private Sub Parentform_Resize()
    
          MeFormX = myFrame.Left
          MeFormY = myFrame.Top
          MoveFrame MeFormX, MeFormY
    End Sub
    
    
    Private Sub PicTitleBar_LostFocus()
    
          PicTitleBarGotFocus = False
    End Sub
    
    'Beginn Moven
    Private Sub LabelBasic_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    
          'in den Vordergrund
          myFrame.ZOrder 0
    
          'verschiebbar ?  Start Move
          If Moveable Then
             MeMouseDown = True
             MeFormX = X
             MeFormY = Y
          End If
          
          'der Focus liegt hier
          If Not PicTitleBarGotFocus Then
             PicTitleBarGotFocus = True
             RaiseEvent GotFocus
          End If
          
          'Timer abschalten
          mTimer.Enabled = False
    End Sub
    
    'Frame moven
    Private Sub LabelBasic_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    
       Static IsLocked As Boolean
       Static Lasttimer As Single
       Static LastCheck As Long
    
          If IsLocked Then
             Exit Sub
          End If
    
          If MeMouseDown Then
             IsLocked = True
             MoveFrame X, Y
             'Event auslösen
             RaiseEvent FrameMoved
             IsLocked = False
          End If
    End Sub
    
    'Ende Frame moven
    Private Sub LabelBasic_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    
          MeMouseDown = False
          mTimer.Enabled = True
    End Sub
    
    'ZOrder setzen
    Public Sub ZOrder(Position As Long)
    
          myFrame.ZOrder Position
    End Sub
    and here the Form , add a Frame and a Commandbutton
    Code:
    Option Explicit
    Private cFrameF As clsFrameForm 'Class
    
    Private Sub Command1_Click()
                cFrameF.Visible = True
                cFrameF.ZOrder 0
                Text1.SetFocus
                'add the Controls you need
    'EDIT:
    'I mean add the Controls to your Frame, and adjust the Frame Height/Width
    
    End Sub
    
    
    Private Sub Form_Load()
      
      With Frame1
             .Width = 3615
             .Height = 2775
             .Caption = "this is my Frame as Form"
    End With
       
    'set the Frame Visible to False
        Set cFrameF = New clsFrameForm
        cFrameF.Init Frame1, False
       
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        Set cFrameF = Nothing
    End Sub
    regards
    Chris
    Last edited by ChrisE; Dec 14th, 2017 at 02:04 AM.
    to hunt a species to extinction is not logical !
    since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.

  15. #15
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,259

    Re: Non-Activating Form

    To prevent unwanted Focus-Switching, Subclassing is not needed at all, when certain Style-Flags get set
    (in the following Demo on a normal Private-UserControl, which then acts as such a "PopOut").

    Add a Private UserControl to an empty Project and name it: ucPopOut
    On that UserControl - add a VB-Button named: Command1
    Set the BackGround-Color of the UserControl to a "contrasting color" of your choice (to see its area better).

    Now put the following Demo-Code into the UserControl:
    Code:
    Option Explicit
    
    Event CommandClick()
    
    Private Const GWL_STYLE = -16, GWL_EXSTYLE = -20, WS_EX_TOOLWINDOW = &H80, WS_EX_NOACTIVATE = &H8000000
    
    Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
    Private Declare Function GetWindowLongW Lib "user32" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
    Private Declare Function SetWindowLongW Lib "user32" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
     
    Private Declare Function ReleaseCapture Lib "user32" () As Long
    Private Declare Function SendMessageW Lib "user32" (ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, lParam As Any) As Long
    
    Private mX!, mY!
    
    Public Sub PopOut(X, Y)
      SetWindowLongW hWnd, GWL_EXSTYLE, GetWindowLongW(hWnd, GWL_EXSTYLE) Or WS_EX_TOOLWINDOW Or WS_EX_NOACTIVATE
      SetParent hWnd, 0
      mX = UserControl.Extender.Left: mY = UserControl.Extender.Top
      UserControl.Extender.Move X, Y
    End Sub
    
    Public Sub PopIn(hWndParent As Long)
      SetParent hWnd, hWndParent
      UserControl.Extender.Move mX, mY
    End Sub
     
    Private Sub Command1_Click()
      RaiseEvent CommandClick
    End Sub
    
    Private Sub UserControl_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
      Call ReleaseCapture: SendMessageW hWnd, &H112, &HF012&, 0& 'just to allow dragging on the UC
    End Sub
    Now close all UserControl-Windows in your IDE and add the new Control to your Form, named: ucPopOut1
    Add a normal VB-TextBox to your Form as well, named: Text1

    FormCode:
    Code:
    Option Explicit
    
    Private Sub Form_Load()
      Caption = "Click Me"
    End Sub
    
    Private Sub Form_Click()
    Static InOut As Boolean: InOut = Not InOut
      If InOut Then
        ucPopOut1.PopOut Left + Width, Top
      Else
        ucPopOut1.PopIn hWnd
      End If
    End Sub
    
    Private Sub ucPopOut1_CommandClick() 'just to show that the Event-Transport works
      Text1.Text = Text1.Text & " " & Time
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
      ucPopOut1.PopIn hWnd 'just to make sure, that the uc is back within the Parent it started from (before cleanup)
    End Sub
    Clicking the Form repeatedly will Pop the ucPopup1 "out or back in"
    (the Control will be draggable as well).

    Here some ScreenShots:



    HTH

    Olaf

  16. #16
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,942

    Re: Non-Activating Form

    Hmmm, well, I've been playing around with it, and I can't quite get the correct combination. Here ... I'll post my "play" code:

    For a BAS module:

    Code:
    
    Option Explicit
    '
    Public gbAllowSubclassing As Boolean
    '
    Private Const WM_DESTROY As Long = &H2&
    '
    Private Declare Function SetWindowSubclass Lib "comctl32.dll" Alias "#410" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, Optional ByVal dwRefData As Long) As Long
    Private Declare Function GetWindowSubclass Lib "comctl32.dll" Alias "#411" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, pdwRefData As Long) As Long
    Private Declare Function RemoveWindowSubclass Lib "comctl32.dll" Alias "#412" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long) As Long
    Private Declare Function NextSubclassProcOnChain Lib "comctl32.dll" Alias "#413" (ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    'Private Declare Function DefSubclassProc Lib "comctl32.dll" Alias "#413" (ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    '
    Private Declare Sub PutMem4 Lib "msvbvm60.dll" (ByRef Ptr As Any, ByRef Value As Any)
    Private Declare Function GetWindow Lib "user32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
    Private Declare Function SetActiveWindow Lib "user32.dll" (ByVal hWnd As Long) As Long
    '
    Dim bSetWhenSubclassing_UsedByIdeStop As Boolean ' Never goes false once set by first subclassing, unless IDE Stop button is clicked.
    '
    
    '**************************************************************************************
    '**************************************************************************************
    '**************************************************************************************
    
    Private Sub SubclassSomeWindow(hWnd As Long, AddressOf_ProcToHook As Long, Optional dwRefData As Long)
        ' This just always uses hWnd for uIdSubclass, as we never have a need to subclass the same window to the same proc.
        ' The uniqueness is pfnSubclass and uIdSubclass (second and third argument below).
        '
        ' This can be called AFTER the initial subclassing to update dwRefData.
        '
        If Not gbAllowSubclassing Then Exit Sub
        '
        bSetWhenSubclassing_UsedByIdeStop = True
        Call SetWindowSubclass(hWnd, AddressOf_ProcToHook, hWnd, dwRefData)
    End Sub
    
    Private Sub UnSubclassSomeWindow(hWnd As Long, AddressOf_ProcToHook As Long)
        ' Only needed if we specifically want to un-subclass before we're closing the form (or control),
        ' otherwise, it's automatically taken care of when the window closes.
        '
        ' Be careful, some subclassing may require additional cleanup that's not done here.
        Call RemoveWindowSubclass(hWnd, AddressOf_ProcToHook, hWnd)
    End Sub
    
    Private Function ProcedureAddress(AddressOf_TheProc As Long)
        ' A private "helper" function for writing the AddressOf_... functions (see above notes).
        ProcedureAddress = AddressOf_TheProc
    End Function
    
    Private Function IdeStopButtonClicked() As Boolean
        ' The following works because all variables are cleared when the STOP button is clicked,
        ' even though other code may still execute such as Windows calling some of the subclassing procedures below.
        IdeStopButtonClicked = Not bSetWhenSubclassing_UsedByIdeStop
    End Function
    
    '**************************************************************************************
    '**************************************************************************************
    '**************************************************************************************
    
    Public Sub SubclassFormNeverFocus(frmChild As VB.Form, frmParent As VB.Form)
        SubclassSomeWindow frmChild.hWnd, AddressOf NeverFocus_Proc, frmParent.hWnd
    End Sub
    
    Private Function NeverFocus_Proc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal uIdSubclass As Long, ByVal dwRefData As Long) As Long
        If uMsg = WM_DESTROY Then
            UnSubclassSomeWindow hWnd, AddressOf_NeverFocus_Proc
            NeverFocus_Proc = NextSubclassProcOnChain(hWnd, uMsg, wParam, lParam)
            Exit Function
        End If
        If IdeStopButtonClicked Then ' Protect the IDE.  Don't execute any specific stuff if we're stopping.  We may run into COM objects or other variables that no longer exist.
            NeverFocus_Proc = NextSubclassProcOnChain(hWnd, uMsg, wParam, lParam)
            Exit Function
        End If
        '
    
    
    
        Const WM_NCACTIVATE = 134&
        Const WM_ACTIVATE = 6&
        Const WM_PAINT = 15&
    
        Const GW_OWNER = 4&
    
        Dim hOwner As Long
    
    
            'If uMsg = WM_NCACTIVATE Or uMsg = WM_ACTIVATE Then
            If uMsg = WM_ACTIVATE Then
    
    
                SetActiveWindow dwRefData
                Exit Function
    
    
            End If
        '
        NeverFocus_Proc = NextSubclassProcOnChain(hWnd, uMsg, wParam, lParam)
    End Function
    
    Private Function AddressOf_NeverFocus_Proc() As Long
        AddressOf_NeverFocus_Proc = ProcedureAddress(AddressOf NeverFocus_Proc)
    End Function
    
    

    For Form1 (the "parent"):
    Code:
    
    Option Explicit
    
    Private Sub Form_Activate()
        Load Form2
        gbAllowSubclassing = True
        SubclassFormNeverFocus Form2, Me
        Form2.Show
    End Sub
    
    For Form2 (the child/status form):
    Code:
    
    Option Explicit
    
    Private Sub Command1_Click()
        MsgBox "Command1 clicked"
    End Sub
    
    
    I also tried with assigning an official "parent" on the Form2.Show line, but that didn't help matters. When done the way above, you lose all ability to click the Form2.

    I'll let others play with it, but the non-subclass approach might be the best way to do it. That way, you still get resize, close, etc.

    Good Luck,
    Elroy

    EDIT1: The NeverFocus_Proc was where I was doing most of the playing. If you want a list of windows messages, a long list of them can be found here.

    EDIT2: The "assumed" task I was shooting for: 1) slave/child window's title bar never shows active, 2) slave/child window never receives keyboard input, 3) slave/child window's resize, close, drag still work as expected, 4) slave/child window processes mouse clicks, 5) slave/child window auto-gives focus to its parent.

    That reminds me of something else. Notice that NeverFocus_Proc has access to both hwndChild and hwndParent (even if/when it's not the official parent.

    EDIT3: And truth be told, I like some of the other ideas. And this isn't something I'd probably ever do. It just sounded a bit fun.
    Last edited by Elroy; Dec 13th, 2017 at 02:06 PM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  17. #17
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Non-Activating Form

    What about something like this:


    Name:  sshot1.png
Views: 609
Size:  3.6 KB


    Click the arrow to pop up the "settings" panel:

    Name:  sshot2.png
Views: 592
Size:  5.0 KB


    The "Popper" UserControl is a container. Once you place one on your Form you can size it and add controls to it like a Frame or PictureBox.
    Attached Files Attached Files

  18. #18

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2014
    Posts
    553

    Re: Non-Activating Form

    Dang everyone, it must be the Holiday Season, I can't thank all of you enough for so much support and example code that you have provided. I'm busy over here typing away learning from all of your generous posts.

    I'll post an update shortly.

    Don't know if it's OK to say this or not.

    With all of the craziness in the news these days, I've got to say how cool it is that complete strangers from around the world come together and help others on this Forum. Too bad not everybody takes after the kindness found here.

    Thanks to all and here's wishing everyone a wonderful holiday season.

  19. #19
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,942

    Re: Non-Activating Form

    Stuck, IMHO, it's absolutely wonderful that you've said that.

    And the absolute best wishes to you and yours as well, and that goes for everyone here.

    Happy Holidays,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  20. #20
    PowerPoster ChrisE's Avatar
    Join Date
    Jun 2017
    Location
    Frankfurt
    Posts
    3,048

    Re: Non-Activating Form

    Quote Originally Posted by stuck-n-past View Post
    With all of the craziness in the news these days, I've got to say how cool it is that complete strangers from around the world come together and help others on this Forum. Too bad not everybody takes after the kindness found here.

    Thanks to all and here's wishing everyone a wonderful holiday season.
    true words

    have a great holiday season

    regards from Germany
    Chris
    to hunt a species to extinction is not logical !
    since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.

  21. #21

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2014
    Posts
    553

    Re: Non-Activating Form

    Hey all, sorry I haven't gotten back here sooner, been spending a great deal of time with AutoCad woes.

    I don't always pay attention to where people come from on this Forum, except for when I had first joined. That's when I started noticing that people from around the world were posting here. Sitting in front of a computer screen in a hazy-eyed stare 8 hours a day, you sort of loose track and forget about the fact that messages fly around the globe in mere seconds bringing everybody closer together. Something growing up I never could of imagined, yea OK so I'm a dinosaur.

    Chris - I just went Doh! realizing the location of Frankfurt being in Germany, probably slept through that lesson at school.

    Anyhow, while born and raised here in the US, both of my parent are of German descent, and have always been jealous of my older Sister who spent close to a month of a vacation touring Germany. I don't know if it was the particular tour she was on or what, but there were many old castles in which they were able to visit and explore. I love historic sites especially castles. Maybe someday somehow.

  22. #22
    Hyperactive Member
    Join Date
    Aug 2017
    Posts
    380

    Re: Non-Activating Form

    Here's yet another subclassing solution. This one processes the WM_ACTIVATE and WM_ACTIVATEAPP messages instead of WM_NCACTIVATE.

    Code:
    Private Function SubclassProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal uIdSubclass As Long, ByVal dwRefData As Long) As Long
        Select Case uMsg
            #If Debugging Then
            Case WM_NCACTIVATE
                OnNCActivate wParam, lParam
            #End If
    
            Case WM_ACTIVATE
                #If Debugging Then
                OnActivate wParam, lParam
                #End If
    
                If (wParam And &HFFFF&) = WA_INACTIVE Then                              'If main form is being deactivated
                    If GetWindowThreadProcessId(lParam) = App.ThreadID Then             'If the window being activated belongs to the same thread as the main form
                        If IsWindowEnabled(hWnd) Then                                   'If main form isn't disabled (e.g. by a modal dialog)
                            dwRefData = SendMessageW(hWnd, WM_NCACTIVATE, TRUE_, 0&)    'Tell the OS to render the main form's nonclient area as if it still is active
                        End If
                    End If
                End If
    
            Case WM_ACTIVATEAPP
                #If Debugging Then
                OnActivateApp wParam, lParam
                #End If
    
                If wParam Then                                                          'If the main form (or another window in the same thread) is being activated
                    If IsWindowEnabled(hWnd) Then                                       'If main form isn't disabled (e.g. by a modal dialog)
                        dwRefData = SendMessageW(hWnd, WM_NCACTIVATE, TRUE_, 0&)        'Ensure the main form's nonclient area still appears active
                    End If                                                              'even when the focus is actually on a secondary form
                Else
                    dwRefData = SendMessageW(hWnd, WM_NCACTIVATE, FALSE_, 0&)           'If this thread is losing the keyboard focus, deactivate the main
                End If                                                                  'form's nonclient area just in case it still appears active
        End Select
    
        SubclassProc = DefSubclassProc(hWnd, uMsg, wParam, lParam)
    End Function



    The main form appears active (red X button and drop shadow) even though the tool window actually has the focus.


    Attached Files Attached Files

  23. #23

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2014
    Posts
    553

    Re: Non-Activating Form

    Wow - I have to admit I've really enjoyed all of the code posted here and done a bit of mixing. In one way or another, I think I've used pieces from every example.

    While grabbing pieces from all, the bulk of my current Frankenstein code uses ChrisE's "Frame/Form" Class overlaid on Olaf's UserControl. The results have the UserControl appearing just like a child form. But hey I'm nothing if not greedy so I also took advantage of dilettante's code in addition to the now new Status UserControl. It allowed me to un-clutter the main form, hiding some of the less frequently used controls.

    OK - so I actually wrote this offline as my internet computer happen to be on life support after the nastiest AutoCAD install ever seen by humanity. So I hadn't seen the latest post by Victor which looks really interesting, so it's quite possible Frankenstein is up for still more pieces / parts.

    I'll be uploading the combined project here soon, till then - Thanks to all.


    Edit: Sorry I forgot to ask something about this newest project which involves Signal-Processing. Its by far the largest I've worked on and the IDE takes a good deal of time just to load, unload and or save and its only getting larger.

    My background has been to create libraries of object modules of reusable code. The libraries grew over the years to be extremely large but only the referenced modules were pulled into the final Exe.

    With this large of a project, I'm contemplating breaking things down into Class Modules to make things easier to manage. Is that the best way to handle large VB projects or is there a better way?

    Thanks.
    Last edited by stuck-n-past; Dec 14th, 2017 at 10:16 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width