1313using Windows . Win32 . System . Com ;
1414using Windows . Win32 . UI . Accessibility ;
1515using Windows . Win32 . UI . Shell ;
16+ using Windows . Win32 . UI . WindowsAndMessaging ;
1617
1718namespace Flow . Launcher . Infrastructure . QuickSwitch
1819{
@@ -604,19 +605,19 @@ public static void JumpToPath(nint dialog, string path, Action action = null)
604605 switch ( _settings . QuickSwitchFileResultBehaviour )
605606 {
606607 case QuickSwitchFileResultBehaviours . FullPath :
607- result = Win32Helper . FileJump ( path , dialogHandle , forceFileName : true ) ;
608+ result = FileJump ( path , dialogHandle , forceFileName : true ) ;
608609 Log . Debug ( ClassName , $ "File Jump FullPath: { path } ") ;
609610 break ;
610611 case QuickSwitchFileResultBehaviours . FullPathOpen :
611- result = Win32Helper . FileJump ( path , dialogHandle , forceFileName : true , openFile : true ) ;
612+ result = FileJump ( path , dialogHandle , forceFileName : true , openFile : true ) ;
612613 Log . Debug ( ClassName , $ "File Jump FullPathOpen: { path } ") ;
613614 break ;
614615 case QuickSwitchFileResultBehaviours . Directory :
615- result = Win32Helper . DirJump ( Path . GetDirectoryName ( path ) , dialogHandle ) ;
616+ result = DirJump ( Path . GetDirectoryName ( path ) , dialogHandle ) ;
616617 Log . Debug ( ClassName , $ "File Jump Directory: { path } ") ;
617618 break ;
618619 case QuickSwitchFileResultBehaviours . DirectoryAndFileName :
619- result = Win32Helper . FileJump ( path , dialogHandle ) ;
620+ result = FileJump ( path , dialogHandle ) ;
620621 Log . Debug ( ClassName , $ "File Jump DirectoryAndFileName: { path } ") ;
621622 break ;
622623 default :
@@ -629,7 +630,7 @@ public static void JumpToPath(nint dialog, string path, Action action = null)
629630 }
630631 else
631632 {
632- result = Win32Helper . DirJump ( path , dialogHandle ) ;
633+ result = DirJump ( path , dialogHandle ) ;
633634 Log . Debug ( ClassName , $ "Dir Jump: { path } ") ;
634635 }
635636
@@ -676,6 +677,110 @@ static bool CheckPath(string path, out bool file)
676677 }
677678 }
678679
680+ // Edited from: https://github.com/idkidknow/Flow.Launcher.Plugin.DirQuickJump
681+
682+ internal static bool FileJump ( string filePath , HWND dialogHandle , bool forceFileName = false , bool openFile = false )
683+ {
684+ if ( forceFileName )
685+ {
686+ return DirFileJumpForFileName ( filePath , dialogHandle , openFile ) ;
687+ }
688+ else
689+ {
690+ return DirFileJump ( Path . GetDirectoryName ( filePath ) , filePath , dialogHandle ) ;
691+ }
692+ }
693+
694+ internal static bool DirJump ( string dirPath , HWND dialogHandle )
695+ {
696+ return DirFileJump ( dirPath , null , dialogHandle ) ;
697+ }
698+
699+ private static unsafe bool DirFileJump ( string dirPath , string filePath , HWND dialogHandle )
700+ {
701+ // Get the handle of the path input box and then set the text.
702+ var controlHandle = PInvoke . GetDlgItem ( dialogHandle , 0x0000 ) ; // WorkerW
703+ controlHandle = PInvoke . GetDlgItem ( controlHandle , 0xA005 ) ; // ReBarWindow32
704+ controlHandle = PInvoke . GetDlgItem ( controlHandle , 0xA205 ) ; // Address Band Root
705+ controlHandle = PInvoke . GetDlgItem ( controlHandle , 0x0000 ) ; // msctls_progress32
706+ controlHandle = PInvoke . GetDlgItem ( controlHandle , 0xA205 ) ; // ComboBoxEx32
707+ if ( controlHandle == HWND . Null )
708+ {
709+ // https://github.com/idkidknow/Flow.Launcher.Plugin.DirQuickJump/issues/1
710+ // The dialog is a legacy one, so we edit file name text box directly.
711+ return DirFileJumpForFileName ( string . IsNullOrEmpty ( filePath ) ? dirPath : filePath , dialogHandle , true ) ;
712+ }
713+
714+ var timeOut = ! SpinWait . SpinUntil ( ( ) =>
715+ {
716+ var style = PInvoke . GetWindowLong ( controlHandle , WINDOW_LONG_PTR_INDEX . GWL_STYLE ) ;
717+ return ( style & ( int ) WINDOW_STYLE . WS_VISIBLE ) != 0 ;
718+ } , 1000 ) ;
719+ if ( timeOut )
720+ {
721+ return false ;
722+ }
723+
724+ var editHandle = PInvoke . GetDlgItem ( controlHandle , 0xA205 ) ; // ComboBox
725+ editHandle = PInvoke . GetDlgItem ( editHandle , 0xA205 ) ; // Edit
726+ if ( editHandle == HWND . Null )
727+ {
728+ return false ;
729+ }
730+
731+ SetWindowText ( editHandle , dirPath ) ;
732+
733+ if ( ! string . IsNullOrEmpty ( filePath ) )
734+ {
735+ // Note: I don't know why even openFile is set to false, the dialog still opens the file.
736+ return DirFileJumpForFileName ( Path . GetFileName ( filePath ) , dialogHandle , false ) ;
737+ }
738+
739+ return true ;
740+ }
741+
742+ /// <summary>
743+ /// Edit file name text box in the file open dialog.
744+ /// </summary>
745+ private static bool DirFileJumpForFileName ( string fileName , HWND dialogHandle , bool openFile )
746+ {
747+ var controlHandle = PInvoke . GetDlgItem ( dialogHandle , 0x047C ) ; // ComboBoxEx32
748+ controlHandle = PInvoke . GetDlgItem ( controlHandle , 0x047C ) ; // ComboBox
749+ controlHandle = PInvoke . GetDlgItem ( controlHandle , 0x047C ) ; // Edit
750+ if ( controlHandle == HWND . Null )
751+ {
752+ return false ;
753+ }
754+
755+ SetWindowText ( controlHandle , fileName ) ;
756+
757+ if ( openFile )
758+ {
759+ var openHandle = PInvoke . GetDlgItem ( dialogHandle , 0x0001 ) ; // "&Open" Button
760+ if ( openHandle == HWND . Null )
761+ {
762+ return false ;
763+ }
764+
765+ ClickButton ( openHandle ) ;
766+ }
767+
768+ return true ;
769+ }
770+
771+ private static unsafe nint SetWindowText ( HWND handle , string text )
772+ {
773+ fixed ( char * textPtr = text + '\0 ' )
774+ {
775+ return PInvoke . SendMessage ( handle , PInvoke . WM_SETTEXT , 0 , ( nint ) textPtr ) . Value ;
776+ }
777+ }
778+
779+ private static unsafe nint ClickButton ( HWND handle )
780+ {
781+ return PInvoke . PostMessage ( handle , PInvoke . BM_CLICK , 0 , 0 ) . Value ;
782+ }
783+
679784 #endregion
680785
681786 #region Class Name
0 commit comments