How to stop flashing title bar?

I was using the KnowledgeBase article (Q176085) to put a program in the system tray when it is minimized. Everything works fine, but when you maximize the program's form by clicking or double-clicking on its tray icon, the form's title bar flashes on and off (enabled/disabled) a few times. I'm pretty sure this is by design in order to cause attention to the form, but it's kind of annoying.

Is there any way to stop the flashing title bar?
RoboRobAsked:
Who is Participating?
 
ArkConnect With a Mentor Commented:
Hi
This is Microsoft's sample design :-)
Try this
Option Explicit

' SYSTRAY Sample by Matt Hart - vbhelp@matthart.com
' http://matthart.com
'
' The uCallbackMessage parameter is usually a user-defined
' message.  However, we can also use a message that VB
' automatically handles as an Event - the MouseMove message.
' The X parameter of this event contains the action.
'
' This method came from a Tip in VBPJ. http://www.windx.com
'
' Updated to show how to forcefully activate a window.
' Win98 doesn't automatically set the focus to the new
' window, but has an annoying tendancy to "blink" the
' task bar caption and window. The hProcess returned by
' GetWindowThreadProcessID (not the thread ID) can be
' used with AppActivate. Note that you can also use the
' Caption of the form you want to activate, but if you
' have more than one window with the same caption, you
' cannot be guaranteed of activating the correct one.

Private Type NOTIFYICONDATA
    cbSize As Long
    hwnd As Long
    uID As Long
    uFlags As Long
    uCallbackMessage As Long
    hIcon As Long
    szTip As String * 64
End Type
   
Const NIM_ADD = 0
Const NIM_MODIFY = 1
Const NIM_DELETE = 2
Const NIF_MESSAGE = 1
Const NIF_ICON = 2
Const NIF_TIP = 4

Const WM_MOUSEMOVE = &H200
   
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Declare Function Shell_NotifyIconA Lib "SHELL32" (ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Integer

' SetWindowPos Flags
Private Const SWP_NOSIZE = &H1
Private Const SWP_NOMOVE = &H2
Private Const SWP_NOZORDER = &H4
Private Const SWP_NOREDRAW = &H8
Private Const SWP_NOACTIVATE = &H10
Private Const SWP_FRAMECHANGED = &H20        '  The frame changed: send WM_NCCALCSIZE
Private Const SWP_SHOWWINDOW = &H40
Private Const SWP_HIDEWINDOW = &H80
Private Const SWP_NOCOPYBITS = &H100
Private Const SWP_NOOWNERZORDER = &H200      '  Don't do owner Z ordering

Private Const SWP_DRAWFRAME = SWP_FRAMECHANGED
Private Const SWP_NOREPOSITION = SWP_NOOWNERZORDER

' SetWindowPos() hwndInsertAfter values
Private Const HWND_TOP = 0
Private Const HWND_BOTTOM = 1
Private Const HWND_TOPMOST = -1
Private Const HWND_NOTOPMOST = -2

Private Function setNOTIFYICONDATA(hwnd As Long, ID As Long, Flags As Long, CallbackMessage As Long, Icon As Long, Tip As String) As NOTIFYICONDATA
    Dim nidTemp As NOTIFYICONDATA

    nidTemp.cbSize = Len(nidTemp)
    nidTemp.hwnd = hwnd
    nidTemp.uID = ID
    nidTemp.uFlags = Flags
    nidTemp.uCallbackMessage = CallbackMessage
    nidTemp.hIcon = Icon
    nidTemp.szTip = Tip & Chr$(0)

    setNOTIFYICONDATA = nidTemp
End Function

Private Sub Command1_Click()
    'Add an icon.  This procedure uses the icon specified in
    'the Icon property of Form1. This can be modified as desired.

    Dim i As Integer
    Dim s As String
    Dim nid As NOTIFYICONDATA

    s = "ToolTipText Here!"
    nid = setNOTIFYICONDATA(Form1.hwnd, vbNull, NIF_MESSAGE Or NIF_ICON Or NIF_TIP, WM_MOUSEMOVE, Form1.Icon, s)
    i = Shell_NotifyIconA(NIM_ADD, nid)
   
    WindowState = vbMinimized
    Visible = False
End Sub
   
Private Sub Command3_Click()
    'Delete an existing icon.

    Dim i As Integer
    Dim nid As NOTIFYICONDATA

    nid = setNOTIFYICONDATA(Form1.hwnd, vbNull, NIF_MESSAGE Or NIF_ICON Or NIF_TIP, vbNull, Form1.Icon, "")

    i = Shell_NotifyIconA(NIM_DELETE, nid)
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
    If Not Visible Then
        Select Case x
            Case 7680
                'List1.AddItem "MouseMove!"
            Case 7695
                List1.AddItem "Left MouseDown"
            Case 7710
                List1.AddItem "Left MouseUp"
            Case 7725
                List1.AddItem "Left DoubleClick"
                Visible = True
                WindowState = vbNormal
                Dim hProcess As Long
                GetWindowThreadProcessId hwnd, hProcess
                AppActivate hProcess
            Case 7740
                List1.AddItem "Right MouseDown"
            Case 7755
                List1.AddItem "Right MouseUp"
            Case 7770
                List1.AddItem "Right DoubleClick"
        End Select
    End If
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Command3_Click
End Sub
Cheers
0
 
hkshijunCommented:
I'm pretty sure this is by design in order to cause attention to the form?
Really by design? :-)
0
 
RoboRobAuthor Commented:
Not my design, Microsoft's!
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
korkyCommented:
try using FlashWindow with bInvert = false

here is the declaration for this function:


Public Declare Function FlashWindow Lib "user32" Alias "FlashWindow" (ByVal hwnd As Long, ByVal bInvert As Long) As Long
0
 
RoboRobAuthor Commented:
While korky's solution was simple and did get rid of the flashing title bar, it left the app without the focus (or at least appearing as if it didn't have the focus).

Ark's solution worked perfectly. To simplify things for anyone else accessing this question, here's the code needed to restore the app:

Dim lonResult As Long
Dim lonProcessId As Long

Me.WindowState = vbNormal
lonResult = SetForegroundWindow(Me.hWnd)
Me.Show
lonResult = GetWindowThreadProcessId _
    (Me.hWnd, lonProcessID)
AppActivate lonProcessID

Of course, you also have to declare the SetForegroundWindow and GetWindowThreadProcessId API functions:

Declare Function SetForegroundWindow _
    Lib "user32" (ByVal hWnd As Long) As Long
Declare Function GetWindowThreadProcessId Lib "user32" _
    (ByVal hWnd As Long, lpdwProcessId As Long) As Long

That's it!

Rob
0
 
ArkCommented:
Hi
Rob: Thank you for points. I posted all code just to show another way (not shown at MS sample) how to get notification from SysTray without subclassing
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.