Search code examples
windowsdelphiwinapistartmenu

How to detect if Windows Start (Orb) button is clicked?


In Delphi, is it possible to detect when the user clicks on Windows' Start button (the button on the bottom left that brings up the menu)?

I try to create my own Start menu, so when the Start button is clicked, it will show my menu rather then Windows' menu.

My concept is my app will run automatically in the systray when Windows starts, and detect when the user clicks on the Start button then shown my menu.

I see a similar question, but in C#: How to detect when the Windows start menu / start screen opens?, but how to do that in Delphi?


Solution

  • found solution use mousehook .. 1st get the start button size and position

    _handle := FindWindow('Shell_TrayWnd', nil);
    _Start.Handle := FindWindowEx(_handle, 0, 'Start', nil);
    GetWindowRect(_Start.Handle, _Start.Rect);
    

    then use mousehook to check mouse pointer clicked on start button or not :

    if (ms.X >= Start.Rect.Left)
    and (ms.X <= Start.Rect.Right)
    and (ms.Y >= Start.Rect.Top)
    and (ms.Y <= Start.Rect.Bottom) then dowhatiwant ......
    

    no matter where is TASKBAR POSITION in left bottom right or top it will always found the start button position ..

    UPDATE : i found another solutions from github .. thanks to Remy for the clue answer and vhanla for the powerfull taskbar component which has a code to implement remy answer,, i share it here if someone need it .. :

    type
    // *********************************************************************//
    // Interface: IAppVisibilityEvents
    // Flags:     (0)
    // GUID:      {6584CE6B-7D82-49C2-89C9-C6BC02BA8C38}
    // *********************************************************************//
      IAppVisibilityEvents = interface(IUnknown)
        ['{6584CE6B-7D82-49C2-89C9-C6BC02BA8C38}']
        function AppVisibilityOnMonitorChanged(hMonitor: HMONITOR;
                  previousMode: MONITOR_APP_VISIBILITY;
                  currentMode: MONITOR_APP_VISIBILITY):HRESULT; stdcall;
        function LauncherVisibilityChange(currentVisibleState: BOOL): HRESULT; stdcall;
      end;
    // *********************************************************************//
    // Interface: IAppVisibility
    // Flags:     (0)
    // GUID:      {2246EA2D-CAEA-4444-A3C4-6DE827E44313}
    // *********************************************************************//
      IAppVisibility = interface(IUnknown)
        ['{2246EA2D-CAEA-4444-A3C4-6DE827E44313}']
        function GetAppVisibilityOnMonitor(monitor: HMONITOR; out pMode: MONITOR_APP_VISIBILITY): HRESULT; stdcall;
        function IsLauncherVisible(out pfVisible: BOOL): HRESULT; stdcall;
        function Advise(pCallBack: IAppVisibilityEvents; out pdwCookie: DWORD): HRESULT; stdcall;
        function Unadvise(dwCookie: DWORD): HRESULT; stdcall;
      end;
    
    
    
    function IsStartMenuVisible: Boolean;
    var
      acc: IAppVisibility;
      res: HRESULT;
      isLauncherVisible: BOOL;
    begin
      Result := False;
      // Initialization of COM is required to use the AppVisibility (CLSID_AppVisibility) object
      res := CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
      if Succeeded(res) then
      begin
        // Create the App Visibility component
        res := CoCreateInstance(CLSID_AppVisibility, nil, CLSCTX_ALL, IID_AppVisibility, acc);
        if Succeeded(res) then
        begin
          res := acc.IsLauncherVisible(isLauncherVisible);
          if Succeeded(res) then
            Result := Boolean(isLauncherVisible);
        end;
    
      end;
      CoUninitialize;
    end;
    

    and call the function to detect start menu is opened or not .